HPP の攻撃原理#
HPP、すなわち HTTP Parameter Pollution、HTTP パラメータの汚染です。HTTP プロトコルでは、同じ名前のパラメータが複数回実行されることがあります。攻撃者は、パラメータを伝播する際に、キーは同じで値が異なるパラメータを転送することで、一部の保護とパラメータの検証を回避することができます。これは注入型の脆弱性であり、攻撃者は特定のパラメータを HTTP リクエストに挿入することで攻撃を開始します。
例を挙げましょう:
2015 年、HackerOne のソーシャル共有ボタンの HPP 脆弱性が発見されました。
脆弱性レポートでは、URL を次のように変更しました:
https://hackerone.com/blog/introducing-signal
次のように変更されます:
https://hackerone.com/blog/introducing-signal?&u=https://me.ursb.me
ソーシャルメディアのリンクを分析する際、このリンクは次のようになります:
https://www.facebook.com/sharer.php?u=https://hackerone.com/blog/introducing-signal?&u=https://me.ursb.me
ここで、最後のパラメータ u は最初のものよりも優先度が高くなります。Facebook の共有時には、Facebook はhackeroneではなく、https://me.ursb.meにリダイレクトします。
ここで、この問題をより具体的に再現するための小さなデモを行います:
const express = require('express')
const bodyParser = require('body-parser')
const app = express()
app.use(bodyParser.json())
app.post('/login', (req, res, next) => {
const { account } = req.body
return res.json({ message: `login sccessful: ${account}` });
})
app.listen(3000)
このシミュレートされたログイン API にリクエストを送信しましょう。ここでは、ユーザーがフロントエンドで "airing" と入力し、"airing" アカウントでログインすることを想定しています。しかし、リクエストが改ざんされ、"account" パラメータが 2 つ含まれており、1 つは "airing"、もう 1 つは "ursb" です。バリデーションが行われない場合、最終的には "airing" ではなく "ursb" でログインされます。
POST /login HTTP/1.1
Host: localhost:3000
Content-Type: application/json
{
"account": "airing",
"account": "ursb"
}
HTTP/1.1 200 OK
X-Powered-By: Express
Content-Type: application/json; charset=utf-8
Content-Length: 35
ETag: W/"23-/iZ+yuhJ7IhuWOkYuK395opzCZI"
Date: Thu, 11 Apr 2019 13:09:53 GMT
Connection: close
{
"message": "login sccessful: ursb"
}
HPP の防止策#
HPP の動作は、バックエンドが複数の同じ名前のパラメータを受け取った場合にどのように処理するかによって異なります。異なるサーバーは異なる方法で処理します。
HTTP プロトコルが同じ名前のパラメータを許可していることに注意する必要があります。アプリケーション全体の処理の過程で、この点に注意し、ビジネスの特性に基づいてこのような状況に適切に対応する必要があります。HPP の脆弱性を防ぐためには、最も重要なのはバックエンドが入力パラメータを適切に検証することです。