WEB安全之SQL注入php
引言:html
在開發網站的時候,出於安全考慮,須要過濾從頁面傳遞過來的字符。一般,用戶能夠經過如下接口調用數據庫的內容:URL地址欄、登錄界面、留言板、搜索框等。這每每給駭客留下了可乘之機。輕則數據遭到泄露,重則服務器被拿下。mysql
一、SQL注入步驟sql
a)尋找注入點,構造特殊的語句數據庫
傳入SQL語句可控參數分爲兩類
1. 數字類型,參數不用被引號括起來,如?id=1
2. 其餘類型,參數要被引號擴起來,如?name="phone"
安全
b)用戶構造SQL語句(如:'or 1=1#;admin'#(這個注入又稱PHP的萬能密碼,是已知用戶名的狀況下,可繞過輸入密碼)之後再作解釋)服務器
c)將SQL語句發送給DBMS數據庫post
d)DBMS收到返回的結果,並將該請求解釋成機器代碼指令,執行必要獲得操做測試
e)DBMS接受返回結果,處理後,返回給用戶fetch
由於用戶構造了特殊的SQL語句,一定返回特殊的結果(只要你的SQL語句夠靈活)
下面,我經過一個實例具體來演示下SQL注入
2、SQL注入實例詳解(以上測試均假設服務器未開啓magic_quote_gpc)
1) 前期準備工做
先來演示經過SQL注入漏洞,登入後臺管理員界面
首先,建立一張試驗用的數據表:
CREATE TABLE `users` ( `id` int(11) NOT NULL AUTO_INCREMENT, `username` varchar(64) NOT NULL, `password` varchar(64) NOT NULL, `email` varchar(64) NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `username` (`username`) ) ENGINE=MyISAM AUTO_INCREMENT=3 DEFAULT CHARSET=latin1;
添加一條記錄用於測試:
INSERT INTO users (username,password,email) VALUES('MarcoFly',md5('test'),'marcofly@test.com');
接下來,貼上登入界面的源代碼
<html>
<head>
<title>Sql注入演示</title>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
</head>
<body >
<form action="validate.php" method="post">
<fieldset >
<legend>Sql注入演示</legend>
<table>
<tr>
<td>用戶名:</td><td><input type="text" name="username"></td>
</tr>
<tr>
<td>密 碼:</td><td><input type="text" name="password"></td>
</tr>
<tr>
<td><input type="submit" value="提交"></td><td><input type="reset" value="重置"></td>
</tr>
</table>
</fieldset>
</form>
</body>
</html>
附上效果圖:
當用戶點擊提交按鈕的時候,將會把表單數據提交給validate.php頁面,validate.php頁面用來判斷用戶輸入的用戶名和密碼有沒有都符合要求(這一步相當重要,也每每是SQL漏洞所在)
! <!--前臺和後臺對接-->
<html>
<head>
<title>登陸驗證</title>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
</head>
<body>
<?php $conn=@mysql_connect("localhost",'root','') or die("數據庫鏈接失敗!");; mysql_select_db("injection",$conn) or die("您要選擇的數據庫不存在"); $name=$_POST['username']; $pwd=$_POST['password']; $sql="select * from users where username='$name' and password='$pwd'"; $query=mysql_query($sql); $arr=mysql_fetch_array($query); if(is_array($arr)){ header("Location:manager.php"); }else{ echo "您的用戶名或密碼輸入有誤,<a href=\"Login.php\">請從新登陸!</a>"; } ?>
</body>
</html>
注意到了沒有,咱們直接將用戶提交過來的數據(用戶名和密碼)直接拿去執行,並無實現進行特殊字符過濾,待會大家將明白,這是致命的。
代碼分析:若是,用戶名和密碼都匹配成功的話,將跳轉到管理員操做界面(manager.php),不成功,則給出友好提示信息。
登陸成功的界面:
登陸失敗的提示:
到這裏,前期工做已經作好了,接下來將展開咱們的重頭戲:SQL注入
2) 構造SQL語句
填好正確的用戶名(marcofly)和密碼(test)後,點擊提交,將會返回給咱們「歡迎管理員」的界面。
由於根據咱們提交的用戶名和密碼被合成到SQL查詢語句當中以後是這樣的:
select * from users where username='marcofly' and password=md5('test')
很明顯,用戶名和密碼都和咱們以前給出的同樣,確定可以成功登錄。可是,若是咱們輸入一個錯誤的用戶名或密碼呢?很明顯,確定登入不了吧。恩,正常狀況下是如此,可是對於有SQL注入漏洞的網站來講,只要構造個特殊的「字符串」,照樣可以成功登陸。
好比:在用戶名輸入框中輸入:' or 1=1#,密碼隨便輸入,這時候的合成後的SQL查詢語句爲:
select * from users where username='' or 1=1#' and password=md5('')
語義分析:「#」在mysql中是註釋符,這樣井號後面的內容將被mysql視爲註釋內容,這樣就不會去執行了,換句話說,如下的兩句sql語句等價:
select * from users where username='' or 1=1#' and password=md5('')
等價於
select* from users where usrername='' or 1=1
由於1=1永遠是都是成立的,即where子句老是爲真,將該sql進一步簡化以後,等價於以下select語句:
select * from users
沒錯,該sql語句的做用是檢索users表中的全部字段
上面是一種輸入方法,這裏再介紹一種注入的方法,這個方法又稱PHP的萬能密碼
咱們再已知用戶名的條件下,能夠不能密碼便可登入,假設用戶名:admin
構造語句:
select * from users where username='admin'#' and password=md5('')
等價於
select * from users where username='admin'
這樣便可不能輸入密碼登入上去的。
數據庫就會錯認爲不用用戶名既能夠登入,繞事後臺的驗證,已到達注入的目的。
一樣利用了SQL語法的漏洞。
看到了吧,一個經構造後的sql語句竟有如此可怕的破壞力,相信你看到這後,開始對sql注入有了一個理性的認識了吧~
沒錯,SQL注入就是這麼容易。可是,要根據實際狀況構造靈活的sql語句卻不是那麼容易的。有了基礎以後,本身再去慢慢摸索吧。
有沒有想過,若是經由後臺登陸窗口提交的數據都被管理員過濾掉特殊字符以後呢?這樣的話,咱們的萬能用戶名' or 1=1#就沒法使用了。但這並非說咱們就毫無對策,要知道用戶和數據庫打交道的途徑不止這一條。
剛開始學這SQL注入比較迷糊,由於本身數據庫沒學好,看了大佬的解釋https://www.jb51.net/article/29444.htm
本身再加了一些本身的見解,纔對SQL注入有了一個比較直觀地認識。