安全なWebサイトを作ろう④
ごあいさつ
こんにちは!
オアシステクノロジーズの古本です。
本記事では、IPAの資料をもとにWebアプリケーションにおける代表的なセキュリティ失敗例とその対策について、Next.jsやSpring Bootを活用した実装パターンと共に解説します!
この記事の続きです
1. クリックジャッキング(Clickjacking)
攻撃の概要
クリックジャッキングは、攻撃者が透明なフレームなどを用いて、ユーザーに意図しないクリック操作をさせる攻撃です。これにより、ユーザーの同意なしにボタン操作や設定変更を強制される恐れがあります。
発生する問題・具体例
- SNSの「いいね」ボタンを隠してクリックさせる
- 設定変更や購入ボタンを偽のUIの裏に隠す
攻撃手法の例
以下のようなHTMLを悪意あるサイトに仕込むことで、正規サイトの操作をユーザーに強制できます:
<iframe src="https://trusted-site.com/settings" style="opacity:0;position:absolute;top:0;left:0;width:100%;height:100%;z-index:100;"></iframe>
<button style="position:relative;z-index:200;">ここをクリック!</button>
ユーザーは自サイトのボタンを押しているつもりでも、実際には埋め込まれた iframe
上の操作をしています。
対策
1. Spring Boot でのクリックジャッキング対策
Spring Securityでは、デフォルトでX-Frame-Options
を設定することでクリックジャッキングを防止します。
@Override
protected void configure(HttpSecurity http) throws Exception {
http.headers().frameOptions().deny(); // または sameOrigin
}
2. Next.js でのHTTPヘッダ設定
ミドルウェアを使ってX-Frame-Options
ヘッダを付与します。
import { NextRequest, NextResponse } from 'next/server';
export function middleware(req: NextRequest) {
const res = NextResponse.next();
res.headers.set('X-Frame-Options', 'DENY');
return res;
}
または、Content-Security-Policy: frame-ancestors 'none'
でも対応可能です。
2. バッファオーバーフロー
攻撃の概要
バッファオーバーフローは、プログラムに対して意図的に過剰なデータを入力し、隣接するメモリ領域を書き換える攻撃です。特にC言語などで問題となりますが、JavaやNode.jsでもリソース枯渇などの形で影響を受けることがあります。
発生する問題・具体例
- DoS(サービス拒否攻撃): 異常な長さの入力によりアプリがクラッシュ
- リソース枯渇: メモリ不足による応答不能
攻撃手法の例
大きすぎるリクエストボディを送り、サーバーのメモリを逼迫させてダウンさせる:
curl -X POST -d "$(python3 -c 'print("A"*10000000)')" http://example.com/api/upload
対策
1. Spring Boot における入力サイズの制限
@PostMapping("/upload")
public ResponseEntity<?> upload(@RequestParam MultipartFile file) {
if (file.getSize() > 5000000) { // 5MB 制限
return ResponseEntity.badRequest().body("ファイルサイズが大きすぎます");
}
// 処理続行
return ResponseEntity.ok("アップロード成功");
}
2. Next.js におけるリクエストサイズの制限
APIルートでボディサイズを制限する例:
export const config = {
api: {
bodyParser: {
sizeLimit: '1mb',
},
},
};
3. アクセス制御や認可制御の欠落
攻撃の概要
認可制御の欠如とは、ユーザーの権限に関係なく重要な操作が実行可能になっている状態を指します。これにより、一般ユーザーが管理者用の操作を行えたり、他人のデータにアクセス可能になるリスクがあります。
発生する問題・具体例
- 管理者ページにログインなしでアクセス可能
- 他ユーザーの注文履歴が閲覧可能
攻撃手法の例
以下のように、クライアント側でURLを直接変更してアクセスする:
curl -H "Cookie: session=xxx" http://example.com/admin
あるいは、IDを改ざんして他人のリソースにアクセス:
curl http://example.com/api/order/1001 # 本人の注文IDは1000
対策
1. Spring Boot における認可制御
@PreAuthorize("hasRole('ADMIN')")
@GetMapping("/admin")
public String adminPage() {
return "admin";
}
2. Next.js での認可チェック(APIルート)
import { getSession } from 'next-auth/react';
export default async function handler(req, res) {
const session = await getSession({ req });
if (!session || session.user.role !== 'admin') {
return res.status(403).json({ error: 'Forbidden' });
}
res.status(200).json({ message: 'Admin content' });
}
まとめ
- クリックジャッキングにはフレーム制御用ヘッダの設定が有効
- バッファオーバーフローは入力サイズや型の制限を徹底
- 認可制御の欠如は必ずユーザー権限に応じた制御ロジックを導入
セキュリティ対策は「実装しないと意味がない」領域です。日々の開発でも小さな油断が重大な事故に繋がることを意識して、安全なアプリケーション設計を心がけましょう!
Discussion