所以我有一个PHP脚本,我自己没有设计,但有一个已知的安全漏洞。管理员可以在其中更改每个用户的各种配置文件设置,包括他们的电子邮件地址。安全漏洞是这样的,任何知道正确URL的人都可以通过简单地计算他们想要的新电子邮件地址的MD5哈希来更改任何注册用户(包括管理员)的电子邮件地址,只要他们知道相应用户的ID即可。更改并发出GET请求,无需以管理员身份登录。例如,在浏览器中输入以下URL:
?admin.php的用户id = 1&安培; md5hash = c59152a77c0bc073fe6f2a3141b99010&安培; email=blah@blah.com
将成功将ID为“1”的用户的电子邮件地址更新为blah@blah.com。
现在,根据我迄今为止所做的研究,似乎放弃MD5哈希以获得更加专有/安全的加密形式将是实现这一目标的最佳/最安全的方式。虽然我觉得我对PHP有相当好的理解并且自己编写了一些基本脚本,但由于我没有设计有问题的特定脚本,我不确定这是否真的可行和/或合理。此外,人们仍然在实践中使用MD5哈希,因此必须存在另一种同样可行的方法来保护aganist这样的漏洞利用,这导致我查看Apache的mod_rewrite模块来阻止特定类型的GET请求:
[由于新用户的最大链接限制为2而无关紧要]
所以我的问题是:
1)忽略它是否真的可行,将PHP脚本改为使用除MD5哈希之外的其他形式的加密是最好的方法吗?或者是否有一些简单的函数可以添加到PHP脚本本身以防止这种漏洞利用?
2)如果我按照上面的URL描述使用Apache的mod_rewrite的路线,那么最好的方法是什么(在THE_REQUEST,HTTP_REFERER,HTTP_COOKIE,REQUEST_URI,HTTP_USER_AGENT,QUERY_STRING和/或REMOTE_ADDR之外,其中REQUEST_METHOD是“得到”)?或者甚至可以做我想做的事情?
3)有人还建议我可以通过.htaccess文件做我想做的事情吗?这是否可能,并且这种方法是否会比提到的其他方法更安全或更不安全?唯一需要考虑的是,通过我最终使用的任何方法,显然服务器仍然必须能够发出请求,以便管理员想要合法地更改用户的电子邮件地址。我只需要更新它,以便普通公众无法通过在浏览器中输入正确的URL来更改用户的电子邮件地址,因为他们知道正确的用户ID。提前谢谢。
--->编辑:对不起,我忽略了特定脚本的名称,因为它是一个公开可用的脚本,我不确定这个特定的漏洞是否是已知的,但事实证明它是,所以我想在这里发布它没有害处。该脚本是TorrentTrade(v2.08) - 您可以在SourceForge(https://sourceforge.net/projects/torrenttrader/)下载整个脚本。
我还复制并粘贴了整个account-ce.php:
<?php
//
// TorrentTrader v2.x
// $LastChangedDate: 2012-09-28 20:35:06 +0100 (Fri, 28 Sep 2012) $
// $LastChangedBy: torrenttrader $
//
// http://www.torrenttrader.org
//
require_once("backend/functions.php");
dbconn();
$id = (int) $_GET["id"];
$md5 = $_GET["secret"];
$email = $_GET["email"];
if (!$id || !$md5 || !$email)
show_error_msg(T_("ERROR"), T_("MISSING_FORM_DATA"), 1);
$res = SQL_Query_exec("SELECT `editsecret` FROM `users` WHERE `enabled` = 'yes' AND `status` = 'confirmed' AND `editsecret` != '' AND `id` = '$id'");
$row = mysql_fetch_assoc($res);
if (!$row)
show_error_msg(T_("ERROR"), T_("NOTHING_FOUND"), 1);
$sec = $row["editsecret"];
if ($md5 != md5($sec . $email . $sec))
show_error_msg(T_("ERROR"), T_("NOTHING_FOUND"), 1);
SQL_Query_exec("UPDATE `users` SET `editsecret` = '', `email` = ".sqlesc($email)." WHERE `id` = '$id' AND `editsecret` = " . sqlesc($row["editsecret"]));
header("Refresh: 0; url=account.php");
header("Location: account.php");
?>
account-ce.php 是以下几个已知漏洞列表中引用的.php文件(第一个漏洞是我现在唯一看到的漏洞):
https://www.exploit-db.com/exploits/21396/
我想而不是坐在那里等待TorrentTrader发布一个新的更新,我会尝试并主动修复一些漏洞。
答案 0 :(得分:0)
您需要包含在会话处理程序中。我想假设用户在被允许访问任何管理页面之前需要登录,并且某种登录凭证或用户ID被保存到会话变量中。要实现这一点,您需要在每个页面上都包含这样的脚本:
<?php
session_start();
if(!isset($_SESSION['uid'])){
$redirect_url='login.php';
if(isset($_SERVER['HTTP_REFERER'])){
$redirect_url.='?target='.urlencode($_SERVER['HTTP_REFERER']);
}
header('Location: '.$redirect_url);
}
?>
$ _ SESSION ['uid']有点武断,可能是您认为足以保证应用程序安全的任何会话变量。注意:会话变量连接到用户并在页面之间保存,直到通过调用session_destroy()销毁会话。
如果在每个页面加载之前执行上述脚本,那么当一些邪恶的黑客试图在没有登录的情况下触发脚本时,在执行/加载脚本/页面的其余部分之前,它们将被重定向到login.php
答案 1 :(得分:0)
当前脚本非常不安全,但使用md5 哈希不会产生不安全性。使用Apache配置将安全性锁定在这样的系统上真的很困难。
您可能需要先阅读session security和cross site request forgery.
您需要编写一些代码。既然你没有发布任何代码也没有提出具体的解决方案,那么你的问题就不在此了。
答案 2 :(得分:0)
好的家伙我现在觉得自己有点愚蠢,但是感谢您使用会话处理程序的提示,因为这最终指向了我正确的方向并且在正确的位置查找。在挖掘之后,似乎特定的管理文件(account-ce.php),无论出于何种原因,只是错过了这个:
loggedinonly();
在backend / functions.php中定义为:
function loggedinonly() {
global $CURUSER;
if (!$CURUSER) {
header("Refresh: 0; url=account-login.php?returnto=" . urlencode($_SERVER["REQUEST_URI"]));
exit();
}
}
此外,我打算按照您的建议阅读会话安全性,以便更好地熟悉会话如何用于此目的。再次感谢! :)