109
86

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【体験談】「うちは大丈夫」と思っていた個人開発サービスが攻撃された話 ─ 対策と教訓5つ

109
Posted at

個人で運用していたタスク管理ツール(月間アクティブユーザー約300人)が、ある日突然攻撃を受けた。「こんな小さなサービス、誰が狙うんだ」と思っていた。結論から言えば、攻撃者は規模を選ばない。自動スキャンツールで脆弱なサーバーを片っ端から探しているだけだ。

異変の発見 ─ レスポンスタイムの異常

月曜の朝、ユーザーから「画面が重い」という問い合わせが2件入った。CloudWatch Metricsを確認すると、APIのp99レスポンスタイムが通常200msのところ4,800msまで悪化していた。CPU使用率は92%。t3.microの1台構成なので、アクセス増にはすぐ限界が来る。

最初は「バズったのか?」と思ったが、Google Analyticsのリアルタイムユーザーは普段通り8人。トラフィックの増加はユーザー起因ではなかった。

調査 ─ ログが語る攻撃の実態

ALBのアクセスログを確認した。

# 直近1時間のリクエスト数をIPごとに集計
zcat alb-access-log-*.gz | awk '{print $4}' | sort | uniq -c | sort -rn | head -20

結果、上位3つのIPから合計で秒間40リクエスト以上が来ていた。通常のユーザー行動では秒間0.5リクエスト程度なので、80倍の異常値だ。

リクエストの中身を見ると、SQLインジェクションの定番パターンがずらりと並んでいた。' OR 1=1 --UNION SELECTSLEEP(5) ─ 自動スキャンツールの典型的な挙動だ。

# SQLインジェクションパターンを含むリクエストを抽出
zcat alb-access-log-*.gz | grep -iE "(union|select|sleep|or\+1)" | wc -l
# 結果: 14,832件(直近6時間で)

対応 ─ 3時間の応急処置

ステップ1: 攻撃元IPの即時ブロック(所要10分)

# Security Groupで攻撃元IPをブロック
aws ec2 authorize-security-group-ingress \
  --group-id sg-xxxxxxxx \
  --protocol tcp --port 443 \
  --cidr 0.0.0.0/0  # 既存ルール

# 攻撃元IPを拒否するNACLを作成
aws ec2 create-network-acl-entry \
  --network-acl-id acl-xxxxxxxx \
  --rule-number 50 \
  --protocol tcp --port-range From=443,To=443 \
  --cidr-block 203.0.113.0/24 \
  --rule-action deny --ingress

ステップ2: WAFの導入(所要1時間)

それまでWAFを使っていなかった。「個人開発だしコストが…」と後回しにしていた。AWS WAFのマネージドルール(AWSManagedRulesCommonRuleSet)を適用し、SQLインジェクションとXSSの基本パターンをブロック。月額5ドル程度の追加コストで済んだ。

ステップ3: データベースの無事確認(所要30分)

最も恐れていたのはデータ漏洩だ。SQLインジェクションが成功していれば全ユーザーのデータが抜かれている可能性がある。

幸い、ORMを使っていたため直接的なSQL実行はされていなかった。スロークエリログを確認しても異常なクエリの実行履歴はなかった。ただし、これは運が良かっただけだ。

教訓 ─ 個人開発者が最低限やるべき5つのこと

教訓1: WAFは最初から入れる

AWS WAFのマネージドルールは月額数ドルで導入できる。「まだ小さいから」は理由にならない。攻撃者は規模を見ていない。

教訓2: レート制限を設定する

1つのIPからのリクエスト数に上限を設ける。ALBレベルでもアプリケーションレベルでもいい。秒間10リクエスト以上を許可する必要がある個人開発サービスはほぼない。

教訓3: ログは必ず保存する

攻撃に気づいた時、ログがなければ何が起きたのか分からない。ALBのアクセスログはS3への出力をONにしておく。デフォルトではOFFだ。

教訓4: 本番DBへの直接接続を禁止する

DBのセキュリティグループは、ALBやアプリケーションサーバーからの接続のみを許可する。自分のIPからの直接接続を開けっ放しにしている個人開発者は多い。

教訓5: アラートを設定する

CloudWatchでCPU使用率80%超過のアラートを設定する。今回、ユーザーからの問い合わせで気づいたが、アラートがあれば2時間早く対応できた。

aws cloudwatch put-metric-alarm \
  --alarm-name "HighCPU" \
  --metric-name CPUUtilization \
  --namespace AWS/EC2 \
  --statistic Average \
  --period 300 \
  --threshold 80 \
  --comparison-operator GreaterThanThreshold \
  --evaluation-periods 2 \
  --alarm-actions "arn:aws:sns:ap-northeast-1:123456789:alerts"

まとめ

個人開発でも攻撃は来る。規模は関係ない。自動スキャンツールはインターネット上の全サーバーを無差別にスキャンしている。WAF、レート制限、ログ保存。この3つは個人開発でも初日から設定するべきだ。「うちは大丈夫」は、攻撃を受けるまで全員が思っていることだ。

109
86
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
109
86

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?