摘要:
這份文檔是詳細討論SQL注入技術,它適應於比較流行的IIS+ASP+SQLSERVER平臺。它討論了哪些SQL語句能經過各類各樣的方法注入到應用程序中,而且記錄與攻擊相關的數據確認和數據庫鎖定。html
這份文檔的預期讀者爲與數據庫通訊的WEB程序的開發者和那些扮演審覈WEB應用程序的安全專家。sql
介紹:
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引擎中,數據能夠被使用'#'限定。第二,避免單引號儘管看上去能夠,可是是不必的,緣由咱們稍後再講。post
咱們更進一步地使用一個簡單的ASP登錄頁面來指出哪些能進入SQLSERVER數據庫而且嘗試鑑別進入一些虛構的應用程序的權限。
這是一個提交表單頁的代碼,讓用戶輸入用戶名和密碼:spa
<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的代碼,它是用來控制登錄的:
debug
<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字段中是必須的,它爲了使這個特殊的查詢終止,而且不返回錯誤。code
攻擊者能夠只需提供他們知道的用戶名,就能夠以任何用戶登錄,使用以下輸入:
Username:admin'—
攻擊者能夠使用users表中第一個用戶,輸入以下:
Username:' or 1=1—
更特別地,攻擊者能夠使用徹底虛構的用戶登錄,輸入以下:
Username:' union select 1,'fictional_user','some_password',1—
這種結果的緣由是應用程序相信攻擊者指定的是從數據庫中返回結果的一部分。orm