PHP - 阻止客户端使用 cURL 向我的网站发送 POST 请求

问题描述 投票:0回答:2

我想阻止人们在我的 php 文件上使用 cURL, 不仅是 cURL,而且每个 POST 请求都不是来自我的网站
我在想办法,如果那个过程错了请告诉我。

我有一个简单的 POST 表单,它根据 $_POST 详细信息执行操作:
form.php:

<?PHP
session_start();
session_regenerate_id();

if( isset($_POST['username']) && isset($_SESSION['pass']) )
{
    // start mysqli query to check the details
}
?>

这样,客户端可以使用 cURL 并向 form.php 发送大量 POST 请求,
并且 if 语句将始终返回 true。

现在,我是这样想的:
当客户在我的域中时,我将创建一个唯一的令牌并将其保存在会话中,
例如:$_SESSION['UID'] = getRandomToken();
此代码将仅在名为:createUID.php 的单独文件上运行:

<?PHP
session_start();
session_regenerate_id();
$_SESSION['UID'] = getRandomToken();
?>

此代码在我网站的每个请求上运行。

现在,这是更新的 form.php:

<?PHP
session_start();
session_regenerate_id();

if( ! isset($_SESSION['UID']) )
{
    die('You are trying to use cURL.');
}

if( isset($_POST['username']) && isset($_SESSION['pass']) )
{
    // start mysqli query to check the details
}
?>

这样,当客户端尝试在 form.php 上使用 cURL 时,他将需要 $_SESSION['UID'] 要设置以继续代码。 当用户通过 cURL 向 form.php 发送请求时,$_SESSION['UID'] 永远不会被设置, 因此,代码将会消亡。

为了知道该技术是否安全,我有一个问题: 无论如何,客户端是否会向 createUID.php 发送请求以设置 $_SESSION['UID'], 然后使用已设置的 $_SESSION['UID'] 向 form.php 发送请求? (不仅限于 cURL)

我测试了使用 2 个 cURL 请求:
测试.php:

<?php
session_start();
session_regenerate_id();

$url = "http://localhost/createUID.php";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_exec($ch);

$url = "http://localhost/form.php";
$data = array('username' => 'admin', 'pass' => '123456');
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_exec($ch);

?>

createUID.php:

<?php

session_start();
session_regenerate_id();
$_SESSION['UID'] = '456a4sd56a4s65d4as'; //example of a random token

echo 'session of createUID.php: ';
print_r( $_SESSION ); //will print 456a4sd56a4s65d4as
echo '<br /><br />';

?>

form.php:

<?php

session_start();
session_regenerate_id();

echo 'session of form.php: ';
print_r( $_SESSION ); //will print nothing
echo '<br /><br />';

if ( ! isset($_SESSION['UID']) )
{
    die('Not allowed');
}
?>

结果是 if ( !isset($_SESSION['UID']) ) 将始终返回 true。
你怎么看?
谢谢!

php http session curl client
2个回答
0
投票

你问了

无论如何,客户端是否会向 createUID.php 发送请求以设置 $_SESSION['UID'],然后向 form.php 发送请求 $_SESSION['UID'] 已经设置好了吗?

答案是:是的

那一点都不难。

在您的表单中使用 CSRF 令牌 将是阻止此类事情的好方法。或者你可以使用 captcha 来做类似的工作。

CSRF 并非完全不可战胜,但它使攻击者更加困难。对于非人类/非浏览器客户端来说,验证码应该是无与伦比的,但它也有一个缺点,即它通常也会对真实用户造成干扰。


附言您的两个请求 cURL 测试似乎有效的原因是它可能创建了两个单独的会话。浏览器在其缓存中存储会话 cookie(由服务器发送)。当他们下次向同一站点发出请求时(当然,除非您先关闭浏览器),他们会将会话 cookie 发送回服务器。这样服务器就知道哪个用户正在发出请求,并将其与服务器内存中正确的会话数据相关联。

您的 cURL 代码没有这样做,因此它可能在服务器上创建了 2 个会话。但是,完全有可能使用 cURL 或任何其他 HTTP 客户端来实现它,这就是为什么你的想法除了最天真的尝试调用你的脚本之外什么都不会阻止。


0
投票

要阻止表单提交的 curl 请求,您可以实施各种技术来区分人类用户和自动脚本。以下是几种常用的方法:

  1. CAPTCHA:向您的表单添加 CAPTCHA 挑战。 CAPTCHA 测试旨在让人类轻松解决,但对自动化脚本来说具有挑战性。您可以将多个验证码库和服务集成到您的表单中。

  2. 用户代理过滤:分析传入请求的用户代理标头。大多数自动化脚本(包括 curl)可能不会发送用户代理或使用通用用户代理字符串。您可以将服务器配置为阻止不包含有效用户代理或不匹配特定模式的请求。

  3. 速率限制:实施速率限制以限制给定时间段内来自单个IP地址的请求数量。这有助于防止自动化脚本在短时间内提交大量请求。考虑使用 nginx 或 Apache 模块等工具来配置速率限制规则。

  4. JavaScript 验证:在您的表单中使用 JavaScript 验证以确保某些操作(例如按钮单击或表单提交)仅由用户交互触发。自动化脚本通常不执行 JavaScript,因此这有助于过滤掉 curl 请求。

  5. 隐藏字段或令牌:将隐藏字段或令牌添加到在服务器端动态生成和验证的表单。这确保表单是从您的网站提交的,而不是通过自动脚本提交的。在接受表单提交之前验证服务器上此字段/令牌的存在性和正确性。

请记住,这些方法并非万无一失,坚定的攻击者有可能绕过它们。实施这些技术的组合可以提高阻止 curl 请求的有效性,但必须定期审查和更新您的安全措施以保持领先于不断变化的威胁。

© www.soinside.com 2019 - 2024. All rights reserved.