キャッシュの問題 01 - yujitounai/helloworld GitHub Wiki

キャッシュの問題

  • キャッシュポイズニング

動的なWebサーバーの結果がキャッシュされる

docker-compose.yml

version: '3'

## キャッシュサーバーの単純な例
services:
## originサーバー
  web:
    build:
      context: ./web

## キャッシュサーバー
  cache:
    build:
      context: ./cache_nginx
    ports:
      - "18888:80"


普通にmessageを返すだけのプログラム

from flask import Flask, request

app = Flask(__name__)

@app.route("/",methods=['post','get'])
def index():
    if request.method == 'POST':
        message = request.form['message']
    if request.method == 'GET':
        message = request.args.get("message")

    return f"<h1>{message}</h1>"

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=80)

originサーバーのDockerfile (python)

FROM python:3.8-slim-buster

WORKDIR /app

COPY ./app/app.py ./
COPY ./app/requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt

COPY . .

EXPOSE 80

CMD ["python", "app.py"]

バグのあるnginxの設定ファイル

proxy_cache_path /var/lib/nginx/cache/nginx levels=1 keys_zone=cache:4M inactive=1d max_size=100M;
proxy_temp_path /var/lib/nginx/cache/nginx_temp;
server {
    server_name localhost;
    listen 80;
    root /var/www/html;
    access_log /var/log/nginx/access_test.log;

    # すべてのリクエストをキャッシュする
    location / {
        proxy_set_header Host                   $host;
        proxy_set_header X-Forwarded-Host       $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_pass http://web;
        proxy_cache cache;
        proxy_cache_key "$scheme://$host$request_uri$is_args$args";
        #proxy_cache_key "$scheme://$host$request_uri";
        proxy_cache_methods GET HEAD POST; #POSTをキャッシュさせる
        proxy_cache_valid 200 301 302 1d;
        proxy_cache_valid 404 1m;
        proxy_cache_valid 500 5s;
        add_header X-Cache-Status $upstream_cache_status;
    }
}

キャッシュサーバーのDockerfile

FROM nginx:latest
RUN mkdir -p /var/lib/nginx/cache
COPY ./default.conf /etc/nginx/conf.d/default.conf

攻撃コード

docker compose build docker compose up

攻撃

XSSのあるコードで、POSTリクエストでもGETリクエストでmessageに入力された文字をそのまま返す。 GETだとクエリストリングが違うためキャッシュされないが

POST /

message=<script>alert(3)</script>

のようなPOSTリクエストを送信することで XSSの結果がキャッシュされる

他の人が http://localhost:18888/ にアクセスするとキャッシュを踏んで自分が出していないアラートが出る

⚠️ **GitHub.com Fallback** ⚠️