作者: h0we777
免责声明:本文仅供学习研究,严禁从事非法活动,任何后果由使用者本人负责。
命令执行漏洞是指攻击者可以随意执行系统命令。它属于高危漏洞之一,也属于代码执行的范畴。命令执行漏洞不仅仅存在于B/S架构中,在C/S架构中也常常遇到。
简单的说,用户通过浏览器提交执行命令,由于服务器端没有针对执行函数做过滤,导致在没有指定绝对路径的情况下就执行命令,可能会允许使用者通过改变$PATH或程序执行环境的其他方面来执行一个恶意构造的代码。
命令执行漏洞是指应用有时需要调用一些执行系统命令的函数,如:system()、exec()、shell_exec()、eval()、passthru(),代码未对用户可控参数做过滤,当用户能控制这些函数中的参数时,就可以将恶意系统命令拼接到正常命令中,从而造成命令执行攻击。
没有对用户输入进行过滤或过滤不严
例如:没有过滤&、&&、| 、||等连接符号。
系统漏洞造成的命令执行
bash破壳漏洞(CVE-2014-6271),该漏洞可以构造环境变量的值来执行具有攻击力的脚本代码,会影响到bash交互的多种应用,如http、ssh和dhcp等。
调用的第三方组件存在代码执行漏洞
例如:
php (system() 、 shell_exec() 、 exec() 、 eval())
JAVA中的命令执行漏洞(struts2/ElasticsearchGroovy等)
ThinkPHP命令执行
windows系统支持的连接符:
Linux系统支持的连接符
命令执行漏洞原理:在操作系统中,"&、| 、||"都可以作为命令连接符使用,用户通过浏览器提交执行命令,由于服务器端没有针对执行函数做过滤,导致在没有指定绝对路径的情况下就执行命令。
应用有时需要调用一些执行系统命令的函数,如PHP中的system、exec、assert、shell_exec、passthru、popen、poc_popen、escapeshellcmd、pcntl_exec等,当用户能控制这些函数中的参数时,就可以将恶意系统命令拼接到正常命令中,从而造成命令执行漏洞,这就是命令执行漏洞。以上函数主要也在webshell中用的多,实际上在正常应用中差别不太大,用得最多的还是前三个。
应用调用执行系统命令的函数;
将用户输入作为系统命令的参数拼接到了命令行中;
没有对用户输入过滤或过滤不严。
用户可以控制输入的内容
用户输入的内容被当作命令执行
应用程序直接使用了危险的可执行系统命令的函数,比如php的system、exec函数等,并且这些函数的运行参数是用户可控的,若过滤不严格,就会增大命令执行漏洞的概率。命令本地包含执行漏洞。(注:(CGI)系统命令注入执行漏洞示例,就比如Bash漏洞,就属于这类漏洞,用户可以直接更改HTTP头user-agent的值,就可引发命令注入。)
命令本地/远程包含漏洞:应用程序直接包含或执行了用户可控的上传脚本文件或远程文件(URL引用文件),就会触发此漏洞。
有些动态脚本语言,如php支持实例对象的序列化传输,然后服务端将实例对象反序列化出来并执行解析后实例的构造函数、析构函数或_wakeup()函数,若这些函数利用了用户可控的参数,则会触发命令/代码注入执行漏洞,原理和之前直接注入一样。
有些动态脚本语言,如php,支持变量或函数的动态定义,即运行时可通过参数名来动态组装变量、变量值或函数。若代码中包含有类似代码,就会存在动态变量/函数的执行漏洞。
语法:eval(phpcode) phpcode必需。规定要计算的php代码。
例子:
<?php $a=$_GET['a'];eval($a);?>
http://127.0.0.1/oscommand/1.php?a=phpinfo();
语法:
PHP 5 : bool assert(mixed assertion [, stringdescription])
PHP 7 : bool assert(mixed assertion [, Throwableexception])
assert() 会检查指定的 assertion 并在结果为false时采取适当的行动。
例子:
<?php $a = $_GET['a'];assert($a); ?>
http://127.0.0.1/oscommand/1.php?a=phpinfo(); http://127.0.0.1/oscommand/1.php?a=phpinfo()
语法:
mixed preg_replace(mixed pattern,mixed replacement,mixed subject \[,int limit=-1 [,int &$count]])
搜索subject 中匹配pattern的部分,以replacement进行替换。
参数说明:
pattern:要搜索的模式,可以是字符串或一个字符串数组。当pattern处存在一个"/e"修饰符时,$replacement的值会被当成php代码来执行。
$replacement:用于替换的字符串或字符串数组。
$subject:要搜索替换的目标字符串或字符串数组。
$limit:可选,对于每个模式用于每个subject字符串的最大可替换次数。默认是-1(无限制)。
$count:可选,为替换执行的次数。
例子:
<?php $a = $_GET['a']; echo preg_replace("/test/e", $a, "just test!") ?>
http://127.0.0.1/oscommand/1.php?a=phpinfo()
注:在php5.4及以下版本中,preg_replace()可正常执行代码,而在php5.5及后续版本中提醒"/e"修饰符已被弃用,要求用preg_replace_callback()函数来代替。
语法:
mixed call_user_func(callable callback \[,mixed paremeter [,mixed $...]])
第一个参数callback 是被调用的回调函数,其余参数是回调函数的参数。
例子:
<?php call_user_func($_GET['a'],$_GET['b']); ?>
http://127.0.0.1/oscommand/1.php?a=assert&b=phpinfo()
语法:
system(string $command [,int $return_var])
函数执行command参数所指定的命令,并输出结果。
string和int是参数的数据类型,分别是字符串和整数。
command:要执行的命令。
return_var:如果提供return_var参数,则外部命令执行后的返回状态会被设置到此变量中。如果成功执行则状态码为0;如果执行失败状态码为1.
语法:
exec ( string KaTeX parse error: Expected 'EOF', got '&' at position 18: …mmand [, array &̲output [, int &$return_var ]] )
函数执行command参数所指定的命令。
string、array、int是参数的数据类型,分别是字符串、数组和整数/
中括号的意思是如果前一个参数存在,那么中括号中的参数可以不写。例如:如果存在$command参数,则$output参数可有可无;如果不存在ouput参数,则$return_var也不能出现。
command:要执行的命令。
output:如果提供了output参数,那么会用命令执行的输出填充此数组,每行输出填充数组中的一个元素。数组中的数据不包括行位的空白字符,例如\n字符。如果数组中自己包含了部分元素,exec()函数会在数组末尾追加内容。如果不想在数组末尾追加,输入exec()函数前使用unset()函数进行重置。
return_var:如果同时提供output和return_var参数,命令执行后的返回状态会被写入到此变量。如果命令成功执行,则状态码为0;如果命令执行失败,则状态码为1。
语法:
shell_exec(string $cmd)
cmd是要执行的命令。
string是参数的数据类型,也就是字符串。
shell_exec函数的用法和反引号相同。
语法:
passthru ( string KaTeX parse error: Expected 'EOF', got '&' at position 16: command [, int &̲return_var ] )
string和int是参数的数据类型,分别为字符串和整型。
passthru()函数也是用来执行command的。当所执行的系统命令输出二进制数据,并且需要直接传送到浏览器的时候,需要此函数来代替exec()或system()函数。
command:要执行的命令。
return_var:如果提供return_var参数,Unix命令返回状态会被记录到此参数。
pcntl_exec
popen
proc_open
ob_start()
unserialize()
usort()
uasort()
ukaort()
array_reduce()
escapeshellarg
该函数过滤一个字符串参数,原理是给字符串添加单引号,而shell不会解释单引号中的特殊字符。如果字符串中已经有单引号了,那么该函数会分段处理这个字符串,对字符串中的单引号做转义,并以之分段,也就是这种形式’…’"…’。也可以说,单引号是就近匹配的。这个函数应该用来过滤单个的shell函数的参数。
escapeshellcmd
该函数应该被用来过滤整个命令字符串(而不是单个参数),转义shell元字符。
反引号() php支持一个执行运算符:反引号
。php将尝试将反引号中的内容作为外壳命令执行,并将输出信息作为返回值返回(即可以赋给一个变量而不是简单的丢弃到标准输出)。使用反引号运算符到效果与函数shell_exec()相同。反引号运算符在激活了安全模式或者关闭了shell_exec()时是无效的。
sys=ctypes.cdll.LoadLibrary('/lib64/libc.so.6')
sys.system(cmd)
如果能直接控制$arg,那么就能执行任意命令了。
能够控制的点是程序的整个参数,可以直接用&& 、|| 或 |等等,利用与、或、管道命令来执行其他命令(可以涉及到很多linux命令行技巧)。还有一个偏门,当$arg被escapeshellcmd处理之后,不能越出这个外部程序的范围,可以看看这个程序自身是否有"执行外部命令"的参数或功能,比如linux下的sendmail命令自带读写文件功能,可以用来写webshell。
控制的点是一个参数,也同样可以利用与、或、管道来执行其他命令,情景与二无异。
这种情况压力大一点,有双引号包囊。如果引号没有被转义,可以先闭合引号,称为第三种情况后按照第三种情况来利用,如果引号被转义(addslashes),也不必着急。linux shell环境下双引号中间点变量也是可以被解析点,可以在双引号内利用反引号执行任意命令id
这是最难受的一种情况了,因为单引号内只是一个字符串,要先闭合单引号才可以执行命令。如:system("/bin/prog -p=‘aaa’ | id")。危害自然不言而喻,执行命令可以读写文件、反弹shell、获得系统权限、内网渗透等。
在漏洞检测中,除了有回显的命令注入(比如执行dir命令或者cat读取系统文件);还可以使用盲打的方式,比如curl远程机器的某个目录(看access.log),或者通过dns解析的方式获取到漏洞机器发出的请求。
windows使用phpstudy集成环境,在网站根目录下建立php文件(自定义)。
<?php
echo "please input get args cmd!";
echo ""
; //格式化页面
if(isset($_GET["cmd"])){
system($_GET["cmd"]);
}
echo "
"; //是页面更加直观,起换行作用。去掉的话,显示信息不会换行。下面做对比。
?>
输入命令:?cmd=ipconfig
现在修改一下代码,看看
的作用是什么。在URL前面加个view-source:也是可以的
对指定目录执行ping命令
<?php
echo ""
; //格式化输出
$arg = $_GET['cmd']; //GET方式执行命令
if($arg){
system("ping $arg");
}
echo "
";
打开cmd ,执行以下命令
ping www.baidu.com
ping 111 & ipconfig
ping 127.0.0.1 && ipconfig
ping 127.0.0.1 | ipconfig
ping 111 || ipconfig
如有不对之处请各位师傅指正!
欢迎关注我们的安全公众号,学习更多安全知识!!!
欢迎关注我们的安全公众号,学习更多安全知识!!!
欢迎关注我们的安全公众号,学习更多安全知识!!!