关于文件包含为ip地址

关于文件包含为ip地址

背景

文件包含是ctf中代码审计经常遇见的,而且会有如下情况。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php
//error_reporting(0);

$id=$_GET['id'];

$data = @file_get_contents($id,'r');
echo $data;
echo "<br />";
if($data=="1112 is a nice lab!")
{
print "win win win win";
}
else
{
print "work harder!harder!harder!";
}

?>

要我们提交的是文件名,而内容却要符合条件,这时最好的办法是用php://input伪协议来解决。然而我再看wp时遇到了另外一种解决方法,就是在自己的服务器上传含有相应内容的文件,然后通过包含该文件来解决。

大致如下:?id=http://192.168.232.134:8889/1.txt192.168.232.134为自己服务器的ip地址,1.txt的内容为1112 is a nice lab!,这样就可以实现绕过了。

测试

然而其实原题的条件更为苛刻一点

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?php
error_reporting(0);
echo "<!--index.phps-->";

$id=$_GET['id'];

if(stripos($a,'.'))
{
echo 'Hahahahahaha';
return ;
}

$data = @file_get_contents($a,'r');

if($data=="1112 is a nice lab!")
{
require("flag.txt");
}
else
{
print "work harder!harder!harder!";
}
?>

stripos()函数导致我们输入的内容里不能出现.,那我们就没法用ip来解决了,而且文件名也是不行的,然后我就看见一个说法,即使用十进制ip来绕过。

下面的结论我是在以下实验条件(php5.5.12,Apache2.4.9)中得到的,不知道是否和版本有关系。

1
2
3
4
例如以下的ip变化:192.168.232.134
十六进制 = C0A8E886
十进制 = 3232295046
二进制 = 11000000101010001110100010000110

我们可以通过直接输入http://3232295046:8889/1.txthttp://0xC0A8E886:8889/1.txt来进行访问。

然而,却无法通过?id=http://3232295046:8889/1.txt?id=http://0xC0A8E886:8889/1.txt来进行文件包含,也不知道是不是版本问题。

虽然ip地址无法绕过,但文件名是可以绕过的:

众所周知,直接访问一个ip地址是默认访问index,然后在文件包含中只输入ip地址,而加上文件名,那么也是会默认访问index的,例如?id=http://3232295046:8889/,就会自动去读取index.phpindex.html,而且,我们也可以不给文件名加上后缀来进行读取,也一样可以成功的,就像?id=http://3232295046:8889/flag,也会成功读取flag的内容的。

结论

综上,结论是:在(php5.5.12,Apache2.4.9)版本下,函数file_get_contents()用来读取别人的服务器上的文件时,不能用十进制ip和十六进制ip来读取。在不指定文件的情况下回默认读取index,也可以访问没有后缀名的文件。