王保勝, 楊新鋒
(南陽(yáng)理工學(xué)院, 南陽(yáng) 473000)
隨著研究用腳本語(yǔ)言攻擊站點(diǎn)的人數(shù)的增加,SQL Injection攻擊也倍受關(guān)注,攻擊者利用SQL Injection漏洞可以在幾分鐘內(nèi),甚至幾十秒時(shí)間內(nèi),入侵至目標(biāo)服務(wù)器,獲取未授權(quán)權(quán)限,竊取不公開信息,修改相關(guān)信息,甚至刪除數(shù)據(jù),幾十秒鐘的時(shí)間足夠在數(shù)據(jù)庫(kù)里面注入數(shù)以萬(wàn)計(jì)的非法數(shù)據(jù)[1-2]。造成這些后果的主要原因就是程序員在編程的失誤或者粗心,然而這些問題完全是可以避免的。國(guó)外對(duì)于SQL Injection的研究已經(jīng)相當(dāng)靠前,由于計(jì)算機(jī)在中國(guó)國(guó)內(nèi)的發(fā)展時(shí)間比較短,國(guó)內(nèi)對(duì)SQL Injection攻擊這方面的研究比較少[3-4]。
SQL Injection是攻擊者把影響程序正常反應(yīng)的SQL命令添加到Web表單的輸入?yún)^(qū)域,或者是頁(yè)面請(qǐng)求執(zhí)行的字符命令中,而達(dá)到對(duì)服務(wù)器的欺騙,從而執(zhí)行這個(gè)影響程序正常反應(yīng)的SQL字符命令的攻擊方式[5-6]。
SQL Injection攻擊網(wǎng)站一般都是通過80端口,通過欺騙等手段提交惡意代碼[7]。通過人眼根本無法分辨,甚至通過軟件也無法測(cè)試出來,因?yàn)镾QL Injection訪問網(wǎng)站的方法與正常訪問者的訪問方式并無不同之處,只有管理員查看web日志的時(shí)候,才能捕捉一些攻擊信息。
如果軟件或者網(wǎng)站存在SQL Injection漏洞,攻擊者就能夠?qū)?shù)據(jù)庫(kù)里面的數(shù)據(jù)進(jìn)行非法操作,在非法得到一定的服務(wù)器權(quán)限后,攻擊者甚至可以在服務(wù)器中通過欺騙的手段添加木馬,安全性較低的數(shù)據(jù)庫(kù)甚至可能被得到服務(wù)器的管理員權(quán)限,這就說明一個(gè)數(shù)據(jù)庫(kù)的不安全,有可能導(dǎo)致整個(gè)站點(diǎn)的內(nèi)容都受到攻擊的威脅。
SQL Injection的本質(zhì)是攻擊者把影響程序正常反應(yīng)的SQL命令添加到Web表單的輸入?yún)^(qū)域,或者是頁(yè)面請(qǐng)求執(zhí)行的字符命令中,而達(dá)到對(duì)服務(wù)器的欺騙,從而執(zhí)行這個(gè)影響程序正常反應(yīng)的SQL字符命令,并最終將執(zhí)行結(jié)果返回給攻擊者[8-9]。
SQL Injection流程,如圖1所示。
圖1 SQL Injection流程
(1)判斷Web系統(tǒng)腳本語(yǔ)言是使用了哪種計(jì)算機(jī)語(yǔ)言,找到注入點(diǎn),確定是否含有SQL Injection漏洞。
(2)判斷Web系統(tǒng)的數(shù)據(jù)庫(kù)類型。
(3)判斷一個(gè)數(shù)據(jù)庫(kù)中表和相應(yīng)字段的結(jié)構(gòu)。
(4)構(gòu)造sql Injection語(yǔ)句,從而得到表中數(shù)據(jù)內(nèi)容。
(5)查找網(wǎng)站管理的后臺(tái),使用得到的管理員賬號(hào)及密碼登錄后臺(tái)。
(6)結(jié)合站點(diǎn)其他漏洞,上傳一個(gè)Webshell。
(7)對(duì)用戶進(jìn)一步提權(quán),從而得到服務(wù)器的系統(tǒng)權(quán)限,隊(duì)整個(gè)站點(diǎn)進(jìn)行非法操作。
(8)刪除侵入痕跡,本地保留侵入方法,以待下一次侵入使用。
下面以管理者和程序員的身份,從防御的角度來談一下如何防止SQL Injection。
在編寫PHP代碼的時(shí)候,要充分考慮用戶輸入信息的安全性。
2.1.1 初始化變量
編寫程序的時(shí)候一定要初始化函數(shù)里面的變量,代碼如下:
if ($admin){
echo‘恭喜你,登陸成功!’;
include(‘a(chǎn)dmin.php’);
}else{
echo‘你不是管理員,請(qǐng)停止你的非法操作!’;
}
?>
假設(shè)后臺(tái)登錄的這個(gè)頁(yè)面的地址是http://127.0.0.1/login.php,那么在瀏覽器的地址欄里面提交:http://127.0.0.1/login.php?admin =1,顯而易見,問題現(xiàn)了,每個(gè)人都是管理員了,只要是進(jìn)行這個(gè)操作的瀏覽者,都可以使用管理員權(quán)限了。
或者將配置文件里面設(shè)置register_global =off這樣就能巧妙地那么就能避免了。重新設(shè)計(jì)代碼:
設(shè)計(jì)代碼實(shí)現(xiàn)后,再重新在地址欄中輸入提交原來的地址:http://127.0.0.1/login.php?admin=1,就會(huì)發(fā)現(xiàn),已經(jīng)不能進(jìn)去了。原因就是在代碼中對(duì)變量“$admin”進(jìn)行了初始化了,令$admin = 0,現(xiàn)在訪問者就無法通過這個(gè)漏洞獲取管理員權(quán)限,也沒有辦法進(jìn)入系統(tǒng)了。由此可以看到,變量的初始化是多么的重要了,變量的初始化,能夠減少漏洞的產(chǎn)生。
$admin=0; //初始化變量
if ($_POST[‘a(chǎn)dmin_user’]&& $_POST[‘a(chǎn)dmin_pass’]){
//假如用戶名和密碼沒有進(jìn)過處理則不運(yùn)行代碼
//……
$admin=1;
}else{
$admin=0;
}
if($admin){
echo‘恭喜你,登陸成功!’;
include(‘a(chǎn)dmin.php’);
}else{
echo‘你不是管理員,請(qǐng)停止你的非法操作!’;
}
?>
2.1.2 過濾變量
提交數(shù)據(jù)的方式有兩種,一種是用get,另一種是用post提交。而很多種SQL Injection都是從get提交方式上面著手,尋找利用這方面的漏洞。這些傳值一定會(huì)利用SQL語(yǔ)句,打破原來的SQL語(yǔ)句,構(gòu)造新的SQL語(yǔ)句。SQL語(yǔ)句的四大句無外乎select、update、delete和insert,SQL Injection就是利用這4種語(yǔ)句構(gòu)造輸入語(yǔ)句的。可以利用如下代碼發(fā)現(xiàn)和避免這些問題:
fuction inject_($sql_str){
return eregi(‘select|insert|update|delete’||
function verify_id($id=null){
//是否為空判斷
if($id){exit(‘沒有提交參數(shù)!’):}
//注入判斷
else if(inject_check($id)){exit(‘提交的參數(shù)非法!’);}
//數(shù)字判斷
else if(!is_numeric($id)){exit(‘提交的參數(shù)非法!’);}
$id=intval($id);//整型化
Returm $id;
}
?>
這樣就能夠進(jìn)行校驗(yàn)了,上面的程序代碼可以進(jìn)一步改寫成:
if (inject_check($_GET[‘id’])){ exit(‘你提交的信息不是正常信息,請(qǐng)檢重新提交合法信息!’);
}else{
//這里調(diào)用了一個(gè)過濾的函數(shù);對(duì)$id的值進(jìn)行過濾防止非法數(shù)值的傳入
$id=verifty_id($_GET[‘id’]));
echo‘你提交的信息不是正常信息,進(jìn)行下一步操作!’;
}
?>
如此設(shè)計(jì)代碼,問題似乎都已經(jīng)被解決了。Get傳值的類型解決了,就要考慮與它不同的post傳值的類型了,當(dāng)然少不了要考慮大批量一起傳輸數(shù)據(jù)。
用戶在提交的數(shù)據(jù)中可能會(huì)有對(duì)數(shù)據(jù)庫(kù)造成影響的字符,比如'_','%'這些字符都具有特殊的意義,那就應(yīng)該對(duì)這些字符進(jìn)行處理。
在PHP配置文件里面設(shè)置magic_quotes_gpc = off,用戶提交的不符合數(shù)據(jù)庫(kù)規(guī)則的數(shù)據(jù),都不會(huì)自動(dòng)的在前面加' '的,這樣就避免了被注入的可能,代碼實(shí)現(xiàn)如下:
function str_check($str){
//判斷magic_quotes_gpc是否打開
if(!get_magic_quotes_gpc()){
$str=addslashes($str);//進(jìn)行過濾
}
$str=str_replace("_","\_",$str);//把‘_’過濾掉
$str=str_replace("%","\%",$str);//把‘%’過濾掉
return $str;
}
?>
然而,在大批量的數(shù)據(jù)面前應(yīng)該怎么考慮呢?只需要將數(shù)據(jù)進(jìn)行HTML標(biāo)記轉(zhuǎn)換,代碼實(shí)現(xiàn):
2.2.1 登錄注冊(cè)頁(yè)面的安全防范
通注冊(cè)頁(yè)面采用短信驗(yàn)證或者郵箱驗(yàn)證,防止水軍注水,緩解服務(wù)器壓力,注冊(cè)者使用驗(yàn)證碼,或者使用郵件里面的鏈接完成對(duì)賬號(hào)的注冊(cè)功能。
注冊(cè)的時(shí)候,對(duì)輸入的賬號(hào)進(jìn)行正則判斷,調(diào)用的正則方程式,而且跟數(shù)據(jù)里的已有賬號(hào)作對(duì)比,已存在的賬號(hào),不能繼續(xù)注冊(cè)。注冊(cè)的時(shí)候前臺(tái)用js代碼進(jìn)行判斷,目的是減輕服務(wù)器的壓力,同時(shí),PHP代碼也是需要判斷,后臺(tái)代碼進(jìn)行判斷的目的是防止攻擊者屏蔽js腳本,非法傳入數(shù)據(jù)對(duì)
function post_check($post){
//判斷magic_quotes_gpc是否為打開
if(!get_magic_quotes_gpc()){
//進(jìn)行magic_quotes_gpc沒有打開的情況對(duì)提交數(shù)據(jù)的過濾
$post=addslashes($post);
}
$post=str_replace("_","\_",$post);//把‘_’過濾掉
$post=str_replace("%","\%",$post);//把‘%’過濾掉
$post=htmlspecialchars($post);//html標(biāo)記轉(zhuǎn)換
return $post;
}
?>
服務(wù)器的安全產(chǎn)生威脅。注冊(cè)和登錄的時(shí)候,對(duì)輸入的密碼進(jìn)行HTML標(biāo)記轉(zhuǎn)換,然后把它的MD5值寫入數(shù)據(jù)庫(kù),或者和數(shù)據(jù)庫(kù)里面的值作對(duì)比。代碼如下:
$data['username']= $wget['username'];
$wget['password']=htmlspecialchars ($wget['password']);
$data['password']= md5($wget['password']);
郵箱注冊(cè)注冊(cè)完了,需要驗(yàn)證,數(shù)據(jù)庫(kù)對(duì)郵箱注冊(cè)的賬號(hào)有一個(gè)拍段,沒有進(jìn)過驗(yàn)證的賬號(hào),是不能夠登錄的。
2.2.2 連接數(shù)據(jù)庫(kù)
很過PHP程序員使用@來抑制程序的報(bào)錯(cuò),代碼如下所示:
$con=@mysql_connect("localhost","peter","abc123";
if(!$con){
die('Could not connect:'.mysql_error()};
}
這種做法不科學(xué),不能真正意義上解決安全問題,登錄數(shù)據(jù)庫(kù)可以采用thinkPHP框架的連接數(shù)據(jù)庫(kù)的方式,其核心代碼如下:
'DB_TYPE'?'mysql',//數(shù)據(jù)庫(kù)數(shù)據(jù)
'DB_HOST'?'127.0.0.1',//服務(wù)器地址
'DB_NAME'?'lagou',//數(shù)據(jù)庫(kù)名
'DB_USER'?'root',//用戶名
'DB_PWD'?'',//密碼
'DB_PORT'?'3306',//端口
'DB_PREFIX'?'lg_',//數(shù)據(jù)庫(kù)表前綴
'DB_CHARSET'?'utf8',//字符集
'DB_DEBUG'?TRUE,//數(shù)據(jù)庫(kù)調(diào)試模式開啟后可以記錄SQL日志3.2.3新增
2.2.3 變量及危險(xiǎn)函數(shù)的處理
對(duì)于每一個(gè)變量,尤其是危險(xiǎn)函數(shù)的變量,都可以用“‘’”引起來,然后對(duì)變量進(jìn)行HTML標(biāo)記轉(zhuǎn)換,這樣就限制住了攻擊者的非法輸入,將用戶輸入的“”,“’”等轉(zhuǎn)換成字符,這樣就避免了SQL漏洞的產(chǎn)生。使用htmlspecialchars()函數(shù)將這些危險(xiǎn)符號(hào)轉(zhuǎn)換成為字符,不再具有其符號(hào)意義。例如登錄時(shí)過濾的代碼:
$data['username']= $wget['username'];
$wget['password']=htmlspecialchars ($wget['password']);
$data['password']= md5($wget['password']);
每一個(gè)函數(shù)的變量都進(jìn)行初始化,并且傳值時(shí)都進(jìn)過過濾,保證傳進(jìn)來的都是安全的數(shù)據(jù)。
正確配置php.ini文件,才能夠確保腳本運(yùn)行環(huán)境和資源的安全性。
可以使用任何有編輯功能的工具打開“php.ini”文件,對(duì)這個(gè)文件里面的代碼進(jìn)行更改,但是要注意的是有些東西更改后會(huì)造成數(shù)據(jù)庫(kù)的不安全的,不要對(duì)這個(gè)文件修改的太多,只修改有助于提高數(shù)據(jù)庫(kù)安全性的地方就可以了,如圖2所示。
(1)打開PHP配置中的安全模式:
safe_mode = on
(2)用戶組的安全:safe_mode_gid = off
(3)安全模式下執(zhí)行程序主目錄:safe_mode_exec_dir推薦不要去執(zhí)行任何一個(gè)程序。
(4)安全模式下的包含文件:
safe_mode_include_dir
(5)控制php腳本能訪問的目錄,使用open_basedir選項(xiàng),這樣就能夠控制PHP腳本,讓訪問者使其只能訪問它所指定的目錄。
(6)關(guān)閉危險(xiǎn)函數(shù):disable_functions = system,passthru,exec,shell_exec,popen,phpinfo
(7)關(guān)閉PHP版本信息:
expose_php = Off
(8)關(guān)閉注冊(cè)全局變量選項(xiàng):
register_globals = Off
(9)打開“magic_quotes_gpc”:
magic_quotes_gpc = On
(10)錯(cuò)誤信息的控制:
display_errors = Off
(11)錯(cuò)誤日志:log_errors = On
本文對(duì)基于PHP的SQL Injection進(jìn)行了一定程度上的研究和總結(jié),對(duì)于整個(gè)數(shù)據(jù)庫(kù)安全問題的研究,在各個(gè)方面都有所討論。但是,SQL Injection不僅僅出現(xiàn)在PHP中,計(jì)算機(jī)技術(shù)的迅速發(fā)展,難保系統(tǒng)不會(huì)受到更嚴(yán)峻的挑戰(zhàn)。本文提出thinkPHP框架的使用可以避免很多出現(xiàn)SQL漏洞的可能性,只需要考慮少量的問題就能夠避免SQL Injection的問題,但是不是所有的PHP開發(fā)人員都會(huì)使用框架開發(fā),那些面向過程開發(fā)的程序員面臨的問題更加多,他們需要處理的問題也更加多,這方面還需要繼續(xù)研究。另外一個(gè)問題就是對(duì)于系統(tǒng)的復(fù)雜度是否也對(duì)這些解決辦法有所影響,也有待去完善和繼續(xù)探究。
[1] 方自遠(yuǎn).SQL注入攻擊及其檢測(cè)防御技術(shù)研究[J].智能計(jì)算機(jī)與應(yīng)用,2016,6(6):87-89.
[2] 張志超,王丹,趙文兵,等.一種基于神經(jīng)網(wǎng)絡(luò)的SQL注入漏洞的檢測(cè)模型[J].計(jì)算機(jī)與現(xiàn)代化,2016(10):67-71.
[3] 李虎軍,林學(xué)華,張遼寧.SQL注入攻擊與防護(hù)探析[J].安徽電子信息職業(yè)技術(shù)學(xué)院學(xué)報(bào),2016,15(2):58-63.
[4] 李俊鋒.基于Apache+PHP+Mysql網(wǎng)站SQL注入防護(hù)探討[J].網(wǎng)絡(luò)空間安全,2016(11):93-95.
[5] 韓宸望,林暉,黃川.基于SQL語(yǔ)法樹的SQL注入過濾方法研究[J].網(wǎng)絡(luò)與信息安全學(xué)報(bào),2016,2(11):00113.1-8.
[6] 張慧琳,丁羽,張利華,等.基于敏感字符的SQL注入攻擊防御方法[J].計(jì)算機(jī)研究與發(fā)展,2016,53(10):2262-2276.
[7] 王苗苗,錢步仁,許瑩瑩,等.基于通用規(guī)則的SQL注入攻擊檢測(cè)與防御系統(tǒng)的研究[J].電子設(shè)計(jì)工程,2017,25(5):24-29.
[8] 仇善梁.開發(fā)者視角下網(wǎng)站SQL注入漏洞及防范[J].河北軟件職業(yè)技術(shù)學(xué)院學(xué)報(bào),2016,18(4):52-55.
[9] 趙陽(yáng),郭玉翠.新型SQL注入攻擊的研究與防范[J].計(jì)算機(jī)系統(tǒng)應(yīng)用,2016,25(6):52-55.