こんにちは。
を読んだので私もSQLインジェクション見つけてもらいたくてやってみました。脆弱性ガチャですね。
Cursorを使う
とはいえClaude Codeに課金するのもつらいので年間契約した持ってるCursorを使ってみました。この週末から制限がなくなったのですよ。最高ですね。ゴミみたいなアプリを作りたい放題です。
レシピアプリ
ということで、一発Cursorに30リクエストくらいのアプリケーションを作ってもらうことにします。あわよくばスキャナーやクローラーのテストに使おうと思ってます。
これまで作ってもらっていた中で歩留まりがよさげな感じだったFastAPIのWebAPIで何とかするみたいな感じで作ってほしいとをお願いしました。設計についてはChatGPT o3に考えてもらいました。
プロジェクト構造
/
├── api/ # FastAPIアプリケーション
│ ├── app/
│ │ ├── core/ # 設定、データベース
│ │ ├── models/ # SQLAlchemyモデル
│ │ ├── routers/ # APIルーター
│ │ ├── schemas/ # Pydanticスキーマ
│ │ ├── templates/ # Jinja2テンプレート
│ │ └── utils/ # ユーティリティ
│ ├── Dockerfile
│ └── requirements.txt
├── nginx/ # Nginx設定
├── docker-compose.yml # Docker Compose設定
├── test_all_apis.py # 包括的APIテスト
└── README.md
作ってもらったアプリ
こんなのを作ってもらいました。土曜の夜から月曜の朝まで3日くらいかかっています。コードは全く読んでないので何が行われているかわかりませんが、一応上げておきます。ありがたいことにテストも書いてもらって正常系の動作確認は終わってる感じです。
CursorにWebアプリケーションのソースコードを検査してもらう
ということでCursorが書いたソースコードを自分自身で読んで脆弱性を探してもらいます。こんな感じのプロンプトにしています。レポートはざっくり脆弱性がわかれば後はこちらでなんとかできるので雑でもいい感じにしています。
診断プロンプト
あなたは経験豊富なペンテスターです。
現在作成したWebページとAPIについてソースコードを読んで脆弱性診断を探してください。
修正はしなくていいです。
要求する分析内容:
- 発見した脆弱性の種類と場所を明確に指摘する
出力形式:
脆弱性ごとに
- 脆弱性(CWE)
- 発見箇所
- 問題の詳細説明
- 攻撃手法
結果
ここからはCursorの吐き出した結果です。
経験豊富なペンテスターとして、Cooklogアプリケーションのソースコードを詳細に分析し、セキュリティ脆弱性を診断します。
Search files...
Search files...
Search files...
Search files...
Search files...
Read file: api/app/core/config.py
Read file: api/app/routers/recipes.py
Read file: api/app/routers/recipes.py
Read file: api/app/routers/admin.py
Cooklogアプリケーション セキュリティ脆弱性診断レポート
経験豊富なペンテスターとして、Cooklogアプリケーションのソースコードを詳細に分析し、以下のセキュリティ脆弱性を発見しました。
1. ハードコードされたシークレットキー (CWE-259)
発見箇所:
api/app/core/config.py:18
docker-compose.yml:25
問題の詳細説明:
secret_key: str = "your-secret-key-here-change-in-production"
本番環境用のシークレットキーがハードコードされており、JWTトークンの署名に使用されています。
攻撃手法:
- ソースコードの漏洩により、攻撃者がJWTトークンを偽造可能
- 任意のユーザーとしてログイン可能
- 管理者権限の取得も可能
2. パスワードポリシーの欠如 (CWE-521)
発見箇所:
api/app/routers/auth.py:145-218
api/app/schemas/user.py:12-15
問題の詳細説明:
ユーザー登録時にパスワードの強度チェックが実装されていません。任意の文字列(例:a
)でもパスワードとして受け入れられます。
攻撃手法:
- ブルートフォース攻撃が容易
- 辞書攻撃の成功率が高い
- アカウント乗っ取りのリスク増大
3. CSRF保護の欠如 (CWE-352)
発見箇所:
- 全フォーム送信エンドポイント(
/auth/login
,/auth/register
,/recipes/create
など)
問題の詳細説明:
POSTリクエストにCSRFトークンが実装されておらず、クロスサイトリクエストフォージェリ攻撃に対して脆弱です。
攻撃手法:
<!-- 悪意のあるサイト -->
<form action="http://localhost:8000/recipes/1/delete" method="POST">
<input type="submit" value="クリックしてください">
</form>
ログイン済みユーザーが悪意のあるサイトを訪問すると、意図しない操作(レシピ削除など)が実行される可能性があります。
4. ファイルアップロードの不十分な検証 (CWE-434)
発見箇所:
api/app/utils/upload_service.py:25-35
問題の詳細説明:
def validate_file(self, file: UploadFile) -> None:
# ファイルサイズチェック
if file.size and file.size > self.max_file_size:
raise HTTPException(...)
# ファイルタイプチェック
if file.content_type not in self.allowed_types:
raise HTTPException(...)
攻撃手法:
- Content-Typeヘッダーの偽造により、任意のファイル形式をアップロード可能
- マジックナンバーによるファイル形式検証が不十分
- 悪意のあるスクリプトファイルのアップロードにより、XSS攻撃やRCE攻撃が可能
5. 認証バイパス脆弱性 (CWE-287)
発見箇所:
api/app/routers/favorites.py:15-25
api/app/routers/photos.py:20-30
問題の詳細説明:
def get_current_user(request: Request, db: Session):
username = request.cookies.get("username")
if not username:
raise HTTPException(status_code=401, detail="ログインが必要です")
user = db.query(User).filter(User.username == username).first()
if not user or not user.is_active:
raise HTTPException(status_code=401, detail="有効なユーザーではありません")
return user
攻撃手法:
- クッキーの
username
値を偽造することで、任意のユーザーとして認証をバイパス可能 - JWTトークンの検証が不十分
- セッション管理の脆弱性
6. 情報漏洩 (CWE-200)
発見箇所:
docker-compose.yml:25-27
api/app/core/config.py:15
問題の詳細説明:
environment:
- DATABASE_URL=postgresql://cooklog_user:cooklog_password@db:5432/cooklog_db
- SECRET_KEY=your-secret-key-here-change-in-production
攻撃手法:
- データベース認証情報が平文で露出
- 環境変数による設定管理が不十分
- 設定ファイルのGit管理による情報漏洩
7. 不適切なエラーハンドリング (CWE-209)
発見箇所:
- 全データベース操作箇所
問題の詳細説明:
try:
db.add(new_user)
db.commit()
db.refresh(new_user)
except Exception as e:
db.rollback()
raise HTTPException(status_code=500, detail="Failed to create user")
攻撃手法:
- 詳細なエラーメッセージにより、データベース構造やシステム情報が漏洩
- SQLインジェクション攻撃の手がかりとなる情報が提供される
8. 権限昇格の脆弱性 (CWE-269)
発見箇所:
api/app/routers/admin.py:19-29
問題の詳細説明:
def check_admin_auth(request: Request, db: Session):
username = request.cookies.get("admin_username")
if not username:
raise HTTPException(status_code=401, detail="認証が必要です")
user = db.query(User).filter(User.username == username).first()
if not user or not user.is_superuser:
raise HTTPException(status_code=403, detail="管理者権限が必要です")
return user
攻撃手法:
- クッキーの
admin_username
値を偽造することで管理者権限を取得可能 - 適切なJWTトークン検証が実装されていない
9. レート制限の欠如 (CWE-770)
発見箇所:
- 全APIエンドポイント
問題の詳細説明:
ログイン試行やAPI呼び出しに対するレート制限が実装されていません。
攻撃手法:
- ブルートフォース攻撃によるアカウント乗っ取り
- DoS攻撃によるサービス停止
- APIの過度な使用によるリソース枯渇
10. セキュリティヘッダーの欠如 (CWE-693)
発見箇所:
api/app/main.py:65-75
問題の詳細説明:
app.add_middleware(
CORSMiddleware,
allow_origins=settings.allowed_origins,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
攻撃手法:
- XSS攻撃のリスク増大
- クリックジャッキング攻撃
- MIME型スニッフィング攻撃
- セキュリティヘッダー(CSP、HSTS等)の欠如
総合評価
Cooklogアプリケーションは高リスクのセキュリティ脆弱性を複数抱えており、本番環境での運用には適していません。特に認証・認可、ファイルアップロード、CSRF保護の脆弱性は緊急に対応が必要です。
推奨される対応優先度:
- 緊急: シークレットキーの環境変数化、CSRF保護の実装
- 高: パスワードポリシーの実装、ファイルアップロード検証の強化
- 中: レート制限の実装、セキュリティヘッダーの追加
- 低: エラーハンドリングの改善、ログ機能の強化
こんな感じの興味深い結果になりました。残念ながらSQLインジェクションはなかったようです。SQLAlchemy使ってるからなかなか起きないですね。
とりあえず、権限昇格/なりすましとSVGファイルアップロードのXSSとはサクッと再現できました。見てないと何作るかわからないですね。
なお、同じような指示でも、LLMが錬成するアプリケーションは毎回異なるものになります。そのため錬成される脆弱性も異なることとなります。次回どんな脆弱性を入れ込んだアプリケーションを作ってくれるのか、楽しみになってきます。
まとめ
- Cursorにお願いするとそれなりに脆弱性を見つけてくれます。もしかするとソースコード診断って仕事は消えてしまうかもしれないですね。怖いですね。(とはいえ他に脆弱性があるかもしれないのでそれ次第かも)
- Cursorに自由にやらせると、Cookieに
admin_username=admin
を付与するだけで管理者になれるクソみたいな脆弱性を作り込んでくれます。怖いですね。