WebVulnerabilities

オープンリダイレクト攻撃について

概要

オープンリダイレクト攻撃は、Webアプリケーションがユーザーのリクエストに基づいてリダイレクトを行う際に、不適切な検証や制限が行われていない場合に発生する脆弱性です。この攻撃により、攻撃者はユーザーを悪意のあるサイトに誘導し、フィッシングやマルウェアの配布などの攻撃を行うことができます。オープンリダイレクトは、信頼されたドメインからリダイレクトが行われるため、ユーザーが騙されやすいという特徴があります。


脆弱性を持つコードの例と攻撃手法

PHP

脆弱なコード:

<?php
$url = $_GET['url'];
header("Location: $url");
exit();
?>

攻撃手法: 攻撃者は、urlパラメータに悪意のあるURLを指定することで、ユーザーをフィッシングサイトやマルウェアサイトにリダイレクトできます。

http://example.com/redirect.php?url=http://malicious-site.com

Python(Flask)

脆弱なコード:

from flask import Flask, request, redirect

app = Flask(__name__)

@app.route('/redirect')
def open_redirect():
    url = request.args.get('url')
    return redirect(url)

攻撃手法: 攻撃者が以下のようなURLを使用して、ユーザーを悪意のあるサイトにリダイレクトすることが可能です。

http://example.com/redirect?url=http://malicious-site.com

Node.js(Express)

脆弱なコード:

const express = require('express');
const app = express();

app.get('/redirect', (req, res) => {
    const url = req.query.url;
    res.redirect(url);
});

app.listen(3000);

攻撃手法: 攻撃者がurlパラメータに悪意のあるURLを指定して、ユーザーをフィッシングサイトにリダイレクトすることが可能です。

http://example.com/redirect?url=http://malicious-site.com

Java(Spring)

脆弱なコード:

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.view.RedirectView;

@Controller
public class RedirectController {

    @GetMapping("/redirect")
    public RedirectView redirect(@RequestParam("url") String url) {
        return new RedirectView(url);
    }
}

攻撃手法: 攻撃者が以下のようなURLを使用して、ユーザーを悪意のあるサイトにリダイレクトできます。

http://example.com/redirect?url=http://malicious-site.com

防止策

  1. ホワイトリスト方式の導入:
    • リダイレクト先のURLをホワイトリストに登録し、許可されたURLにのみリダイレクトできるようにします。これにより、悪意のあるURLへのリダイレクトを防ぐことができます。

    PHPの例:

    <?php
    $url = $_GET['url'];
    $allowed_urls = ['http://trusted-site.com', 'http://example.com'];
       
    if (in_array($url, $allowed_urls)) {
        header("Location: $url");
        exit();
    } else {
        echo "Invalid URL";
    }
    ?>
    
  2. 相対パスの使用:
    • リダイレクトを行う際に、フルURLではなく相対パスを使用し、ドメイン外へのリダイレクトを防ぎます。

    Pythonの例(Flask):

    from flask import Flask, request, redirect
    
    app = Flask(__name__)
    
    @app.route('/redirect')
    def safe_redirect():
        url = request.args.get('url')
        if url.startswith('/'):
            return redirect(url)
        else:
            return "Invalid URL"
    
  3. リダイレクト先の検証とサニタイズ:
    • リダイレクト先のURLを検証し、ユーザーが不正なサイトにリダイレクトされることを防ぐために、サニタイズを行います。特に、外部URLへのリダイレクトを制限します。

    Node.jsの例(Express):

    app.get('/redirect', (req, res) => {
        const url = req.query.url;
        const allowedBaseUrl = 'http://example.com';
    
        if (url.startsWith(allowedBaseUrl)) {
            res.redirect(url);
        } else {
            res.send('Invalid URL');
        }
    });
    
  4. ユーザーにリダイレクトの確認を求める:
    • リダイレクトを行う前に、ユーザーにリダイレクト先を確認させる画面を表示し、同意を得ることで不正なリダイレクトを防ぎます。
  5. HTTPリファラーヘッダーの利用:
    • リダイレクトを行う前に、HTTPリファラーヘッダーを確認し、信頼できるリファラーからのリクエストであることを確認します。

まとめ: オープンリダイレクト攻撃は、ユーザーを悪意のあるサイトに誘導するための攻撃です。ホワイトリスト方式の導入、相対パスの使用、リダイレクト先の検証とサニタイズなどの防止策を実施することで、この脆弱性を効果的に防ぐことが可能です。各プラットフォームや言語に共通する問題であるため、これらの対策を適用することが推奨されます。