レッスン 2-7
信じられない
読み終えたらなぜ
この頁の流れ
デシリアライズ (保存や
出典を確かめた日 2026年10月27日
なぜ通るのか
ログイン中の
動きは
戻す途中で処理が動く
デシリアライズの
| 形式 | 戻せる物 | 外からの |
|---|---|---|
| JSON | 文字、 | 使える。 |
| pickle、 | 型と、 | 使わない。 |
後者は、
Java のように、
署名を付けても足りない理由
「Cookie に
ただし、
| 崩れる所 | 何が |
|---|---|
| 鍵が漏れる | 設定ファイルや |
| サーバーが | 利用者が |
| 鍵を | 入れ替えの |
だから
脆いコードと直したコード
ラボの
pickle で戻すか、JSON で戻して形を確かめるか
Python
def load_session(cookie):
raw = base64.b64decode(cookie)
return pickle.loads(raw)Python
FIELDS = {"user_id": int, "cart": list}
def load_session(cookie):
data = json.loads(
base64.b64decode(cookie))
if not isinstance(data, dict):
raise ValueError("bad session")
if data.keys() != FIELDS.keys():
raise ValueError("bad session")
for k, t in FIELDS.items():
if not isinstance(data[k], t):
raise ValueError("bad")
return data直したpickle.loads を
印を確かめて pickle で戻すか、印を確かめて JSON で戻すか
Python
def load_session(cookie, key):
body, sig = split(cookie)
if not hmac.compare_digest(
sign(key, body), sig):
raise ValueError("bad sig")
return pickle.loads(body)Python
def load_session(cookie, key):
body, sig = split(cookie)
if not hmac.compare_digest(
sign(key, body), sig):
raise ValueError("bad sig")
return parse_session(body)parse_session は、user_id を
ログでの見え方と検知
直した
記録
ValueError: bad session
path=/cart cookie_len=88ふだんの
| 見る物 | なぜ効くか |
|---|---|
コードの中の pickle.loads、yaml.load、ObjectInputStream | 外からの |
| 形や | ふだんは |
| Web の | 戻す途中で |
| 署名の | 手本からの |
記録には
直し方と、直ったことの確かめ方
自分の
- 作業用の
フォルダに、脆い load_sessionと、辞書を Cookie の 文字に する 小さな 関数を置く - 脆い方に、
辞書ではない 型 (たとえば datetime) をpickle で 包んだ Cookie を 渡し、 その 型が そのまま 組み立てられて 返る ことを 確かめる (型の 作り方まで 戻せる、と いう 性質を、 害の 無い型で 見るだけにする) - 関数を
直した コードに 置き換える - 同じ
Cookie と、 余計な 項目の 付いた Cookie が、 どちらも ValueErrorで止まる ことを 確かめる - 下の
試験を 足し、 pickle で 戻すコードに 戻すと 試験が 落ちる ことも 確かめる - 終わったら、
作業用の フォルダごと消す
Python
def enc(obj):
return base64.b64encode(
json.dumps(obj).encode())
def test_rejects_pickle():
raw = base64.b64encode(pickle.dumps(
{"user_id": 1, "cart": []}))
with pytest.raises(ValueError):
load_session(raw)
def test_rejects_extra_field():
raw = enc({"user_id": 1, "cart": [],
"admin": True})
with pytest.raises(ValueError):
load_session(raw)試験は
あわせて、
関わる事例
Microsoft は
ViewState には
確認クイズ
1 問目
利用者の
答えだと思う選択肢を押すと、その場で正誤と理由が開きます。
答え イ
pickle は、
2 問目
pickle で
答えだと思う選択肢を押すと、その場で正誤と理由が開きます。
答え イ
印が
説明課題
次の
- なぜ
署名だけでは 足りないのか
模範解答を見る
署名が
一次資料
どれも
- pickle Python object serialization (Python の
説明書、英語) 。pickle は 安全ではなく、 戻す途中で 任意の コードを 動かす データを 作れる こと、 信じられない 出どころの データを 戻さないこと - Deserialization Cheat Sheet (OWASP、英語)。
pickle.loadsを信じられない 入力に 使っていないかの 点検、 利用者に データを 渡すなら JSON のような 形式を 使う こと (PHP の 節)、 Java の 直列化の フィルターで 戻して よい 型を 絞ること - CWE-502 Deserialization of Untrusted Data (MITRE、英語)。
ガジェットチェーンで シェルを 起動する 例、 HMAC などで 書き 換えられていない ことを 確かめる手当て - Code injection attacks using publicly disclosed ASP.NET machine keys (Microsoft Threat Intelligence、
英語、 。2025年2月6日) 2024年12月の 活動、 公開された 鍵が 3,000 以上 あった こと、 鍵を 写さず 定期的に 入れ替える勧め
次へ
次の
