セッション固定攻撃について
セッション固定攻撃(Session Fixation)は、攻撃者がユーザーに特定のセッションIDを強制的に使用させ、そのセッションIDを用いて攻撃者がユーザーのアカウントに不正にアクセスする攻撃手法です。この攻撃は、WebアプリケーションがセッションIDをユーザーの認証後に再生成しない場合に発生します。攻撃者は、ユーザーがログインする前に固定したセッションIDを取得し、その後ユーザーが認証した後にそのセッションを乗っ取ることができます。
脆弱なコード例:
<?php
// PHPの設定でURLパラメータからセッションIDを受け取る設定が有効な場合
ini_set('session.use_cookies', 0); // クッキーを無効にする
ini_set('session.use_only_cookies', 0); // セッションIDをURLパラメータから受け取る設定を有効にする
ini_set('session.use_trans_sid', 1); // セッションIDをURLからも受け取る設定を有効にする
session_start(); // セッションを開始または既存のセッションを使用
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// ユーザー認証が成功した場合
$_SESSION['username'] = $_POST['username'];
echo "Logged in as " . $_SESSION['username'];
} else {
echo "Please log in.";
}
?>
攻撃手法:
http://example.com/login.php?PHPSESSID=123456789
123456789
)が使用されます。脆弱なコード例:
from flask import Flask, session, request
app = Flask(__name__)
app.secret_key = 'supersecretkey'
@app.route('/login', methods=['POST'])
def login():
if request.form['username'] == 'admin' and request.form['password'] == 'password':
session['username'] = request.form['username']
return f"Logged in as {session['username']}"
return 'Invalid credentials'
if __name__ == '__main__':
app.run()
攻撃手法:
http://example.com/login?sessionid=abcd1234
abcd1234
)が使用されます。脆弱なコード例:
const express = require('express');
const session = require('express-session');
const app = express();
app.use(session({ secret: 'supersecretkey', resave: false, saveUninitialized: true }));
app.post('/login', (req, res) => {
if (req.body.username === 'admin' && req.body.password === 'password') {
req.session.username = req.body.username;
res.send(`Logged in as ${req.session.username}`);
} else {
res.send('Invalid credentials');
}
});
app.listen(3000);
攻撃手法:
http://localhost:3000/login?sessionid=xyz789
xyz789
)が使用されます。脆弱なコード例:
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import javax.servlet.http.HttpSession;
@Controller
public class LoginController {
@PostMapping("/login")
public String login(@RequestParam String username, @RequestParam String password, HttpSession session) {
if ("admin".equals(username) && "password".equals(password)) {
session.setAttribute("username", username);
return "Logged in as " + username;
}
return "Invalid credentials";
}
}
攻撃手法:
http://localhost:8080/login;jsessionid=abc123
abc123
)が使用されます。PHPの例:
session_regenerate_id(true); // セッションIDの再生成
Pythonの例(Flask):
Flaskのセッションは標準でsession.regenerate_id()
に相当する操作がサポートされていないため、セッション再生成のためのカスタムロジックを追加する必要があります。
Node.jsの例(Express):
req.session.regenerate((err) => {
// セッションIDが再生成されました
});
Javaの例(Spring):
session.invalidate(); // セッションを無効化
session = request.getSession(true); // 新しいセッションを作成
HttpOnly
およびSecure
属性を設定し、クッキーがJavaScriptからアクセスされることや、非HTTPS経由で送信されることを防ぎます。PHPの例:
ini_set('session.cookie_httponly', 1);
ini_set('session.cookie_secure', 1);
Node.jsの例(Express):
app.use(session({
secret: 'supersecretkey',
cookie: { httpOnly: true, secure: true }
}));
まとめ: セッション固定攻撃は、攻撃者がユーザーに特定のセッションIDを使用させることで、そのセッションを乗っ取る攻撃です。認証後のセッションIDの再生成、セッション固定防止設定の使用、セッションIDのクッキー管理などの防止策を実施することで、この脆弱性を効果的に防ぐことが可能です。各言語やフレームワークでの適切な対策を講じることが推奨されます。