はまやんはまやんはまやん

hamayanhamayan's blog

Webセキュリティにおけるレースコンディション問題への傾向と対策

本まとめはセキュリティコンテスト(CTF)で使えるまとめを目指すのが主です。
悪用しないこと。勝手に普通のサーバで試行すると犯罪っぽいです。

レースコンディション Race Condition

概要

どういう問題を発生させられるか

例えば、クーポンを使用する処理があって以下のようなフローになっているとする。

  1. クーポンがあるか確認
  2. クーポンを使用して、クーポンを消す

2つのプロセスで同一クーポンに対してリクエストをほぼ同時に投げたとする。
プロセスAとプロセスBにおいて、「A1 → B1 → A2 → B2」のような順番で処理が行われてしまうと、
クーポンは1つなんだけれど、クーポン使用が2回行われてしまう可能性がある。
このように、排他処理を適切に行わないことで、競合状態を発生させて、攻撃を行う。

攻撃シナリオ

  • ファイルをアップロードして何かを行うサービス
    • サーバ側処理
        1. ファイルをtmpフォルダにアップロード
        1. アップロードファイルに対してサーバ側が処理を行う
        1. アップロードしたファイルを削除する
    • 攻撃
      • 1でファイルをアップロードするときにphpファイルをアップロードしておく。その直後、3で削除される前に参照して、任意コード実行を達成する
  • 購入サイト
    • サーバ側処理「お金があるか確認→購入処理→お金を減らす」
    • 同時に購入することでお金の消費は1回で複数個数買える場合がある
      • これはお金を減らす処理が「最初にお金があるか確認したものから金額を減らして更新する」場合に特に有効
  • 送金システム
    • サーバ側処理「送金→記録」
    • これも同時に行えば、お金の減りは1回だけど複数回送れたりする

並列リクエストコード

python

from requests
from multiprocessing import *
import time
def f():
    requests.post("[url]")
for i in range(20):
    p = Process(target=f)
    p.start()
time.sleep(2)

js

<html><script>
    async function postreq() {
        var xhr = new XMLHttpRequest()
        xhr.open("POST","[url]", true);
        xhr.withCredentials = true;
        xhr.setRequestHeader("Content-Type","[Content-Type]");
        xhr.send("[POST DATA]"); // ex. JSON.stringify({"price":"300"})
    }
    for (var i = 0; i < 1000; i++) {
        postreq();
    }
</script></html>

レースコンディション 問題 CTF Writeups

いろいろあったけど、メモるのを忘れてました。

Practicalな話

実装時に気を付けること

競合状態のテストは負荷試験の一環で行えるので、試験しよう。

(CTFじゃ使えないけど)テストツール

概念的な感じなので、テストツールは無さそう。