Client-side desync とは
Client-side desyncは、攻撃者がHTTP/1.1リクエストを悪用し、クライアント(ユーザーのブラウザなど)に誤ったリクエスト処理を強制する攻撃手法です。
サーバーがリクエストを分割する際、クライアントが不正に構造化されたリクエストを解釈することで、別のリクエストに影響を与え、XSSやセッション乗っ取りなどの攻撃が可能になります。
当脆弱性の解説は BurpSuite解説 Client-side desync attacks を参照ください。
今回はDockerで検証環境を作成し、BurpSuite Repeaterで確認する所まで行います。
各システムのバージョン
HAProxy: 1.7.11
Python: 3.9-slim
Flask: 2.0.1
Gunicorn: 19.9.0
フォルダ構造
Client-side desyncの脆弱性が存在する HAProxy 1.7.11のバージョンを使って構成を作成します。
/
├── docker-compose.yml
├── haproxy/
│ ├── Dockerfile
│ └── haproxy.cfg
│
└── web1
├── Dockerfile
└── server.py
各ファイル
docker-compose.yml
version: '3'
services:
haproxy:
build:
context: ./haproxy
ports:
- "80:80"
networks:
- webnet
depends_on:
- web1
web1:
build:
context: ./web1
networks:
- webnet
expose:
- "8080"
networks:
webnet:
haproxy/Dockerfile
# HAProxyの公式イメージを使用
FROM haproxy:1.7.11
# 設定ファイルをコピー
COPY haproxy.cfg /usr/local/etc/haproxy/haproxy.cfg
haproxy/haproxy.cfg
defaults
mode http
timeout http-keep-alive 10s
timeout connect 5s
timeout server 60s
timeout client 30s
timeout http-request 30s
backend servers
http-reuse always
server server1 web1:8080
frontend http-in
bind *:80
timeout client 5s
timeout http-request 10s
default_backend servers
web1/Dockerfile
FROM python:3.9-slim
WORKDIR /usr/src/app
# 依存関係でエラーとなるパッケージも追記
RUN pip install flask==1.1.2 gunicorn==20.0.4 Jinja2==2.11.3 MarkupSafe==1.1.1 itsdangerous==1.1.0 Werkzeug==1.0.1 gevent==21.1.2
COPY server.py .
CMD ["gunicorn", "--keep-alive", "10", "-k", "gevent", "-b", "0.0.0.0:8080", "-w", "4", "server:app"]
gunicorn起動時にパラメータが必要です。(1敗)
web1/server.py
from flask import Flask, request, jsonify
app = Flask(__name__)
@app.route('/', methods=['GET', 'POST'])
def index():
# the next line is required for Transfer-Encoding support in the request
request.environ['wsgi.input_terminated'] = True
headers = {}
for header in request.headers:
headers[header[0]] = header[1]
# ヘッダーとボディを返す
return jsonify({
'Method': request.method,
'headers': headers,
'params': request.args,
'body': request.get_data(as_text=True),
})
if __name__ == '__main__':
app.run(host='0.0.0.0', port=8080)
リクエストメソッド・ヘッダーなど全てJSONで出力します。
Docker 起動
docker-compose up --build
BurpSuiteで検証する
1. Burp Suiteを起動し、Repeaterにリクエストを2つ作成します。
2. POSTメソッドに変更後、Transfer-Encodingヘッダ・ボディ を追記し、パラメータが反映されている事を確認します。
Pages: 1 2