以php語言為例,概述編碼過程中的sql注入過程,注入可能涉及 存儲(chǔ)過程 、sql語句、關(guān)鍵字等方式,本篇只介紹sql相關(guān)。
注入基本原理
- (正常情況)假設(shè)我們可以通過 http://localhost/test/userinfo.php?username=plhwin 這個(gè)URL來訪問到具體某個(gè)會(huì)員的詳情,正常情況下,如果瀏覽器里傳入的username是合法的,那么SQL語句會(huì)執(zhí)行:
SELECT uid,username FROM user WHERE username='plhwin'
- (注入情況)但是,如果用戶在瀏覽器里把傳入的username參數(shù)變?yōu)?plhwin';SHOW TABLES-- hack,也就是當(dāng)URL變?yōu)?http://localhost/test/userinfo.php?username=plhwin';SHOW TABLES-- hack 的時(shí)候,此時(shí)我們程序?qū)嶋H執(zhí)行的SQL語句變成了:
SELECT uid,username FROM user WHERE username='plhwin';SHOW TABLES-- hack'
解決辦法
先說一個(gè)線上服務(wù)器的配置.
比如用PHP,php.ini文件中的錯(cuò)誤提示開關(guān)等一定要在生產(chǎn)環(huán)境關(guān)掉,可百度下,此處不講。(一般云服務(wù)器已經(jīng)做好了這個(gè))普通用戶與系統(tǒng)管理員用戶的權(quán)限要有嚴(yán)格的區(qū)分。
即對(duì)普通訪問用戶只有查詢等最低使用權(quán)限,并對(duì)不同管理人員進(jìn)行區(qū)分,比如root用戶、啟停用戶、管理用戶、應(yīng)用用戶等強(qiáng)迫使用參數(shù)化語句。如下面的寫法
$sql = "SELECT * FROM table WHERE username = ? AND pwd = ?";
bindParam($sql, 1, $username, 'STRING');
//以字符串的形式.在第一個(gè)問號(hào)的地方綁定$username這個(gè)變量
bindParam($sql, 2, $pwd, 'STRING');
//以字符串的形式.在第二個(gè)問號(hào)的地方綁定$pwd這個(gè)變量
- 過濾特殊符號(hào)以及檢查變量數(shù)據(jù)類型等
$uid = isset($_GET['uid']) ? $_GET['uid'] : 0;
$uid = addslashes(uid);
$sql = "SELECT uid,username FROM user WHERE uid='{$uid}'";
$uid = isset($_GET['uid']) ? $_GET['uid'] : 0;
$uid = addslashes(uid);
$sql = "SELECT uid,username FROM user WHERE uid={$uid}";
上面兩個(gè)查詢語句都經(jīng)過了php的addslashes函數(shù)過濾轉(zhuǎn)義,但在安全性上卻大不相同,在MySQL中,對(duì)于int類型字段的條件查詢,上面?zhèn)€語句的查詢效果完全一樣,由于第一句SQL的變量被單引號(hào)包含起來,SQL注入的時(shí)候,黑客面臨的首要問題是必須要先閉合前面的單引號(hào),這樣才能使后面的語句作為SQL執(zhí)行,并且還要注釋掉原SQL語句中的后面的單引號(hào),這樣才可以成功注入,由于代碼里使用了addslashes函數(shù),黑客的攻擊會(huì)無從下手,但第二句沒有用引號(hào)包含變量,那黑客也不用考慮去閉合、注釋,所以即便同樣采用addslashes轉(zhuǎn)義,也還是存在SQL攻擊漏洞。