在Apache / PHP

时间:2015-10-05 20:08:24

标签: php apache .htaccess mod-rewrite get

所以我有一个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发布一个新的更新,我会尝试并主动修复一些漏洞。

3 个答案:

答案 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 securitycross 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();
    }
}

此外,我打算按照您的建议阅读会话安全性,以便更好地熟悉会话如何用于此目的。再次感谢! :)