1

私は他の誰かによって開発されたいくつかのページを維持することに取り組んでいます。フォームは、ユーザーがページに入るたびに生成されるある種の画像CAPTCHAによって保護されていることに気づきました。CAPTCHAは、という名前の非表示の入力に保存されcheck、ユーザーが入力した値は、フォームの送信後に非表示の入力からの値と比較されます。

私はcURLを使用してページを読み取り、その非表示の入力からCAPTHAを解析しようとしました。

$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, "http://example.com/form/");
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);

$result = curl_exec($curl);

$html = str_get_html($result);
$captcha = $html->find('input[name=check]');
var_dump($captcha[0]->value);

curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, array(
    "name"      => "Joe",
    "telephone" => "1423456789",
    "message"   => "Lorem ipsum",
    "auth"      => $captcha[0]->value,
    "check"     => $captcha[0]->value,
    "submit_f1" => "Send"
));

$result = curl_exec($curl);
curl_close ($curl);

上記のスクリプトを実行すると、フォームが正しく送信されます。authさらに、post配列のcheck値を単純に上書きできることに気づきました。

    "auth"      => 123,
    "check"     => 123,

フォームも正しく送信されています。

フォームを保護するための100%安全な方法はないことを認識していますが、フォームをもう少し保護し、自動送信を少し難しくするにはどうすればよいですか。

4

2 に答える 2

1

The idea behind any challenge-response system is that you keep the response (the code) hidden and only show the challenge (the image).

You would typically use session to accomplish this; you store the response in the session and show the challenge. Once the correct response is entered you can clear the response session variable to prepare the system for the next challenge.

The following code only serves to illustrate the idea.

Showing CAPTCHA

session_start();

// generate the string you wish to show as captcha
$str = generate_captcha();
// and store inside session
$_SESSION['captcha'] = $str;

// show_captcha() would generate the image
echo show_captcha($str);

Validating CAPTCHA

session_start();

if ($_POST['captcha'] === $_SESSION['captcha']) {
    unset($_SESSION['captcha']);
    // continue with form submission
} else {
    // yikes, it doesn't match
}
于 2012-09-25T09:58:50.353 に答える
1

他の人が言っているように、$_SESSIONこれを達成するための最も一般的な方法はの使用です。

  1. ランダムな文字列を生成し、に保存し$_SESSIONます。
  2. そのランダムな文字列をjpgに描画し、tmpフォルダーに保存します。
  3. フォームと一緒にユーザーにjpgを表示します。
  4. 入力をセッション値と比較します。

ただし、セッションを使用できない場合は、他の(少し一般的ではない)方法はハッシュを使用することです。

  1. ランダムな文字列を生成します$ranstr
  2. 時々変更する必要がある長いサーバー側の秘密の値がSHA256($ranstr . $SECRET)どこにあるかを計算します。$SECRET
  3. jpgに描画$ranstrし、tmpフォルダに保存します。
  4. フォームと一緒にユーザーにjpgを表示します。フォームには、非表示フィールドにハッシュの結果も含まれます。
  5. 再計算SHA256($POST['human_test'] . $SECRET)して、非表示フィールドの値と比較します。

どちらの場合も、cronを追加して、1時間程度より古いjpgを削除することをお勧めします。

于 2012-09-25T10:34:23.757 に答える