我想防止人们使用cURL对我的php文件,不仅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']的请求,然后向form.php发送一个已经设置好的$_SESSION ['UID']的请求?(不仅是cURL)
我使用两个cURL请求进行了测试:
test.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。
你觉得呢?
谢谢!
2条答案
按热度按时间pqwbnv8z1#
你问的
客户端是否会向createUID.php发送一个设置$_SESSION ['UID']的请求,然后向form.php发送一个已经设置好的$_SESSION ['UID']的请求?
答案是:是的
这一点都不难。
在表单中使用CSRF token将是阻止这种事情的好方法。或者您可以使用captcha来完成类似的工作。
CSRF并不是完全不可战胜的,但它使攻击者更加困难。对于非人类/非浏览器客户端来说,验证码应该是无与伦比的,但它也有一个缺点,那就是它经常会对真实的用户造成干扰。
P.S.你的两个请求cURL测试看起来有效的原因是它可能创建了两个单独的会话。浏览器将会话cookie(由服务器发送)存储在其缓存中。当他们下一次向同一个网站发出请求时(当然,除非你先关闭浏览器),他们会将会话cookie发送回服务器。这样,服务器就知道是哪个用户发出了请求,并将其与服务器内存中的正确会话数据相关联。
您的cURL代码没有这样做,所以它可能在服务器上创建了2个会话。但是,完全可以使用cURL或任何其他HTTP客户端实现它,这就是为什么您的想法只会阻止最天真的调用脚本的尝试。
cgyqldqp2#
要阻止表单提交的curl请求,可以实现各种技术来区分人类用户和自动化脚本。以下是几种常见的方法:
1.用户代理过滤:分析传入请求的用户代理标头。大多数自动化脚本(包括curl)可能不会发送用户代理或使用通用用户代理字符串。您可以将服务器配置为阻止不包含有效用户代理或不匹配特定模式的请求。
1.速率限制:实施速率限制,以限制给定时间段内来自单个IP地址的请求数量。这有助于防止自动脚本在短时间内提交大量请求。考虑使用nginx或Apache模块等工具来配置速率限制规则。
1.隐藏字段或令牌:向表单中添加在服务器端动态生成和验证的隐藏字段或令牌。这可以确保表单是从您的网站提交的,而不是通过自动脚本提交的。在接受表单提交之前,验证服务器上此字段/令牌的存在性和正确性。
请记住,这些方法并非万无一失,坚定的攻击者可能会绕过它们。结合使用这些技术可以提高阻止curl请求的有效性,但必须定期检查和更新安全措施,以领先于不断变化的威胁。