# httpOnly Cookie の誤解 ― 「読めない」は「悪用できない」ではない
## よくある誤解
> 「Cookie を httpOnly にすれば JavaScript から読めないので安全」
半分正しく、半分間違い。httpOnly 属性は `document.cookie` 経由での読み取りを防ぐが、**Cookie を読めなくても悪用できる**という点が見落とされがち。
---
## 何が起きるのか ― CSRF(Cross-Site Request Forgery)
ブラウザには「リクエスト送信時に、対象ドメインの Cookie を自動的に付与する」という仕様がある。`credentials: "include"` を指定した fetch API も例外ではない。
攻撃者はこの仕様を利用して、**Cookie の中身を一切知らないまま**、被害者のブラウザに正規リクエストを送信させることができる。
### 攻撃の流れ
```
1. 被害者が target-site.com にログイン済み
→ セッション Cookie がブラウザに保存されてい# スクレイピング検知のためのログ分析手法と対策
## 1. 分析対象のログ種別
| ログ種別 | 主な記録内容 | 取得元の例 |
|---|---|---|
| Webサーバーアクセスログ | IP、タイムスタンプ、リクエストURI、ステータスコード、User-Agent、Referer | Apache `access.log`、Nginx `access.log` |
| WAF / CDNログ | リクエストヘッダ全体、レート情報、ブロック履歴 | Cloudflare、AWS WAF、Akamai |
| アプリケーションログ | セッションID、認証状態、API呼び出し回数 | 各アプリケーションフレームワーク |
---
## 2. スクレイピングを示唆するログパターン
### 2.1 リクエスト頻度の異常
**確認方法:** 同一IPアドレスからの単位時間あたりのリクエスト数を集計する。
```bash
# 1分間あたりのIPごとのリクエスト数を集計(Apacheの combined 形式)
awk '{print $1, substr($4,2,17)# ログアウト処理を GET で構築してはいけない理由(PHP)
## 結論
ログアウトは `session_destroy()` によるセッション破棄、すなわちサーバー側の状態変更操作である。HTTP の仕様上、状態変更操作には **POST**(または DELETE)を使用する。GET で実装した場合、以下の具体的な問題が発生する。
---
## 1. CSRF(クロスサイトリクエストフォージェリ)攻撃が成立する
GET リクエストは `<img>` タグの `src` 属性に URL を指定するだけで発火する。
```html
<!-- 攻撃者のサイトに設置されたコード -->
<img src="https://example.com/logout.php" style="display:none" />
```
ブラウザはこの `<img>` タグを解釈した時点で `https://example.com/logout.php` に GET リクエストを送信し、`PHPSESSID` を含む Cookie も自動的に付与する。結果として `session_desimport OpenAI from 'openai';
const openai = new OpenAI({
apiKey: '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',
baseURL: 'https://integrate.api.nvidia.com/v1',
});
async function main() {
const response = await openai.responses.create({
model: "openai/gpt-oss-120b",
input: "",
max_output_tokens: 4096,
top_p: 1,
temperature: 1,
stream: true
});
let reasoningDone = false;
for await (const chunk of response) {
import OpenAI from 'openai';
const openai = new OpenAI({
apiKey: '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',
baseURL: 'https://integrate.api.nvidia.com/v1',
})
async function main() {
const completion = await openai.chat.completions.create({
model: "openai/gpt-oss-120b",
messages: [{"role":"user","content":""}],
temperature: 1,
top_p: 1,
max_tokens: 4096,
stream: true
})
for await (const chunk of completion) from openai import OpenAI
client = OpenAI(
base_url = "https://integrate.api.nvidia.com/v1",
api_key = "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"
)
completion = client.chat.completions.create(
model="openai/gpt-oss-120b",
messages=[{"role":"user","content":""}],
temperature=1,
top_p=1,
max_tokens=4096,
stream=True
)
for chunk in completion:
if not getattr(chunk, "choices", None):
continue
reasoning = getattr(chunk.choiceimport axios from 'axios';
import { readFile } from 'node:fs/promises';
const invokeUrl = "https://integrate.api.nvidia.com/v1/chat/completions";
const stream = true;
const headers = {
"Authorization": "Bearer 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",
"Accept": stream ? "text/event-stream" : "application/json"
};
const payload = {
"model": "moonshotai/kimi-k2.5",
"messages": [{"role":"user","content":""}],
"max_tokens": 16384,
"tempeimport OpenAI from 'openai';
const openai = new OpenAI({
apiKey: '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',
baseURL: 'https://integrate.api.nvidia.com/v1',
})
async function main() {
const completion = await openai.chat.completions.create({
model: "z-ai/glm5",
messages: [{"role":"user","content":""}],
temperature: 1,
top_p: 1,
max_tokens: 16384,
chat_template_kwargs: {"enable_thinking":true,"clear_thinking":false},
from openai import OpenAI
import os
import sys
_USE_COLOR = sys.stdout.isatty() and os.getenv("NO_COLOR") is None
_REASONING_COLOR = "\033[90m" if _USE_COLOR else ""
_RESET_COLOR = "\033[0m" if _USE_COLOR else ""
client = OpenAI(
base_url = "https://integrate.api.nvidia.com/v1",
api_key = "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"
)
completion = client.chat.completions.create(
model="z-ai/glm5",
messages=[{"role":"user","content":""}],
SELECT
-- pst.name AS segment_type,
MAX(CASE WHEN psi.lang_id = 1 THEN psi.name END) AS name_lang_1,
MAX(CASE WHEN psi.lang_id = 2 THEN psi.name END) AS name_lang_2,
MAX(CASE WHEN psi.lang_id = 1 THEN psi.slug END) AS slug_lang_1,
MAX(CASE WHEN psi.lang_id = 2 THEN psi.slug END) AS slug_lang_2
FROM products_segments ps
JOIN products_segments_type pst ON pst.id = ps.type
JOIN products_segments_i18n psi ON psi.product_category_id = ps.id
WHERE pst.name IN ('category', 'subcategSELECT
-- pst.name AS segment_type,
MAX(CASE WHEN psi.lang_id = 1 THEN psi.name END) AS name_lang_1,
MAX(CASE WHEN psi.lang_id = 2 THEN psi.name END) AS name_lang_2,
MAX(CASE WHEN psi.lang_id = 1 THEN psi.slug END) AS slug_lang_1,
MAX(CASE WHEN psi.lang_id = 2 THEN psi.slug END) AS slug_lang_2
FROM products_segments ps
JOIN products_segments_type pst ON pst.id = ps.type
JOIN products_segments_i18n psi ON psi.product_category_id = ps.id
WHERE pst.name IN ('category', 'subcategSELECT psi.name, ps.cat_id, ps.parent_category_id, pst.name, ps.is_active
FROM products_segments ps
JOIN products_segments_type pst ON pst.id = ps.type
JOIN products_segments_i18n psi ON psi.product_category_id = ps.id
WHERE pst.name IN ('category', 'subcategory')
AND psi.lang_id = 1
ORDER BY ps.cat_id/**
* @param {number} left
* @param {number} right
* @return {number}
*/
var countPrimeSetBits = function(left, right) {
// Precompute the only primes we care about.
// No integer in this range will have more than ~20 set bits.
const primes = new Set([2, 3, 5, 7, 11, 13, 17, 19]);
let count = 0;
// Iterate through every number in the inclusive range
for (let n = left; n <= right; n++) {
// Convert to binary and count the number of '1' bits
// Example/**
* @param {string} s
* @return {string}
*/
var makeLargestSpecial = function(s) {
// This array will hold all top-level special substrings
let subs = [];
// We'll scan the string and find balanced segments
let count = 0;
let start = 0;
for (let i = 0; i < s.length; i++) {
// '1' increases balance, '0' decreases it
if (s[i] === '1') count++;
else count--;
// When count returns to 0, we found a complete special substring
if (