滲透攻防Web篇-SQL注入攻擊初級(jí)

來源;http://bbs.ichunqiu.com/thread-9518-1-1.html?from=ch

作者:zusheng

時(shí)間:2016年8月3日 12:11:50

社區(qū):i春秋

前言

不管用什么語言編寫的Web應(yīng)用,它們都用一個(gè)共同點(diǎn),具有交互性并且多數(shù)是數(shù)據(jù)庫(kù)驅(qū)動(dòng)。在網(wǎng)絡(luò)中,數(shù)據(jù)庫(kù)驅(qū)動(dòng)的Web應(yīng)用隨處可見,由此而存在的SQL注入是影響企業(yè)運(yùn)營(yíng)且最具破壞性的漏洞之一,這里我想問,我們真的了解SQL注入嗎?看完本篇文章希望能讓你更加深刻的認(rèn)識(shí)SQL注入。

目錄

第一節(jié) 注入攻擊原理及自己編寫注入點(diǎn)

1.1、什么是SQL?

1.2、什么是SQL注入?

1.3、SQL注入是怎么樣產(chǎn)生的?

1.4、編寫注入點(diǎn)

第二節(jié) 尋找及確認(rèn)SQL注入

2.1、推理測(cè)試法

2.2、and大法和or大法

2.3、加法和減法

正文

第一節(jié) 注入攻擊原理及自己編寫注入點(diǎn)

1.1、什么是SQL?

SQL 是一門 ANSI 的標(biāo)準(zhǔn)計(jì)算機(jī)語言,用來訪問和操作數(shù)據(jù)庫(kù)系統(tǒng)。SQL 語句用于取回和更新數(shù)據(jù)庫(kù)中的數(shù)據(jù)。SQL 可與數(shù)據(jù)庫(kù)程序協(xié)同工作,比如 MS Access、DB2、Informix、MS SQL Server、Oracle、Sybase 以及其他數(shù)據(jù)庫(kù)系統(tǒng)。

1.2、什么是SQL注入?

看起來很復(fù)雜,其實(shí)很簡(jiǎn)單就能解釋,SQL注入就是一種通過操作輸入來修改后臺(tái)SQL語句達(dá)到代碼執(zhí)行進(jìn)行攻擊目的的技術(shù)。

1.3、SQL注入是怎么樣產(chǎn)生的?

構(gòu)造動(dòng)態(tài)字符串是一種編程技術(shù),它允許開發(fā)人員在運(yùn)行過程中動(dòng)態(tài)構(gòu)造SQL語句。開發(fā)人員可以使用動(dòng)態(tài)SQL來創(chuàng)建通用、靈活的應(yīng)用。動(dòng)態(tài)SQL語句是在執(zhí)行過程中構(gòu)造的,它根據(jù)不同的條件產(chǎn)生不同的SQL語句。當(dāng)開發(fā)人員在運(yùn)行過程中需要根據(jù)不同的查詢標(biāo)準(zhǔn)來決定提取什么字段(如SELECT語句),或者根據(jù)不同的條件來選擇不同的查詢表時(shí),動(dòng)態(tài)構(gòu)造SQL語句會(huì)非常有用。

在PHP中動(dòng)態(tài)構(gòu)造SQL語句字符串:

[PHP]純文本查看復(fù)制代碼

?

1

$query="SELECT * FROM users WHERE username = ".$_GET["ichunqiu"];

看上面代碼我們可以控制輸入?yún)?shù)ichunqiu,修改所要執(zhí)行SQL語句,達(dá)到攻擊的目的。

1.4、編寫注入點(diǎn)

為了照顧一下新人,這里先介紹一下涉及到的基礎(chǔ)知識(shí):

[SQL]純文本查看復(fù)制代碼

?

1

2

3SQLSELECT語法

SELECT列名稱FROM表名稱

符號(hào) * 取代列的名稱是選取所有列

[SQL]純文本查看復(fù)制代碼

?

1

2

3

4WHERE子句

如需有條件地從表中選取數(shù)據(jù),可將WHERE子句添加到SELECT語句。

語法

SELECT列名稱FROM表名稱WHERE列 運(yùn)算符 值

下面的運(yùn)算符可在 WHERE 子句中使用:

了解了以上基礎(chǔ)知識(shí)就讓我們來自己編寫注入點(diǎn)把。

第一步:我們使用if語句來先判斷一下變量是否初始化

[PHP]純文本查看復(fù)制代碼

?

1

2

3

4

5

if(isset($_GET["ichunqiu"])){

}

?>

第二步:在if語句里面,我們連接數(shù)據(jù)庫(kù)。在PHP中,這個(gè)任務(wù)通過 mysql_connect() 函數(shù)完成。

[PHP]純文本查看復(fù)制代碼

?

1

2

3

4mysql_connect(servername,username,password);

servername??????? 可選。規(guī)定要連接的服務(wù)器。默認(rèn)是"localhost:3306"。

username??????? 可選。規(guī)定登錄所使用的用戶名。默認(rèn)值是擁有服務(wù)器進(jìn)程的用戶的名稱。

password??????? 可選。規(guī)定登錄所用的密碼。默認(rèn)是""。

第三步:連接成功后,我們需要選擇一個(gè)數(shù)據(jù)庫(kù)。

[PHP]純文本查看復(fù)制代碼

?

1

2

3mysql_select_db(database,connection)

database??????? 必需。規(guī)定要選擇的數(shù)據(jù)庫(kù)。

connection??????? 可選。規(guī)定 MySQL 連接。如果未指定,則使用上一個(gè)連接。

第四步:選擇完數(shù)據(jù)庫(kù),我們需要執(zhí)行一條 MySQL 查詢。

[PHP]純文本查看復(fù)制代碼

?

1

2

3mysql_query(query,connection)

query??????? 必需。規(guī)定要發(fā)送的 SQL 查詢。注釋:查詢字符串不應(yīng)以分號(hào)結(jié)束。

connection??????? 可選。規(guī)定 SQL 連接標(biāo)識(shí)符。如果未規(guī)定,則使用上一個(gè)打開的連接。

第五步:執(zhí)行完查詢,我們?cè)賹?duì)結(jié)果進(jìn)行處理

[AppleScript]純文本查看復(fù)制代碼

?

1

2

3

4

5

6

7mysql_fetch_array(data,array_type)

data可選。規(guī)定要使用的數(shù)據(jù)指針。該數(shù)據(jù)指針是 mysql_query()函數(shù)產(chǎn)生的結(jié)果。

array_type

可選。規(guī)定返回哪種結(jié)果。可能的值:

MYSQL_ASSOC-關(guān)聯(lián)數(shù)組

MYSQL_NUM-數(shù)字?jǐn)?shù)組

MYSQL_BOTH-默認(rèn)。同時(shí)產(chǎn)生關(guān)聯(lián)和數(shù)字?jǐn)?shù)組

題外話:我們使用echo將執(zhí)行的SQL語句輸出,方便我們查看后臺(tái)執(zhí)行了什么語句。

[PHP]純文本查看復(fù)制代碼

?

1

echo$querry

最終代碼如下:

[PHP]純文本查看復(fù)制代碼

?

01

02

03

04

05

06

07

08

09

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26if(isset($_GET["id"])){

$con= mysql_connect("127.0.0.1:3306","root","root");

if(!$con)

{

die('Could not connect: '. mysql_error());

}

mysql_select_db("ichunqiu",$con);

$querry="select * from users where id = ".$_GET['id'];

$sql= mysql_query($querry,$con);

$result= mysql_fetch_array($sql);

echo"";

id

username

echo"";

".$result['id']."

".$result['username']."

echo"";

echo"";

mysql_close($con);

echo$querry;

}

?>

MySQL數(shù)據(jù)庫(kù)實(shí)驗(yàn)環(huán)境配置:

代碼層工作已經(jīng)做好,但是在數(shù)據(jù)庫(kù)里面,我們還沒有ichunqiu這個(gè)數(shù)據(jù)庫(kù)啊,接下來我就帶大家一步步創(chuàng)建數(shù)據(jù)庫(kù),創(chuàng)建表,創(chuàng)建列,插入數(shù)據(jù)。

第一步:創(chuàng)建數(shù)據(jù)庫(kù)

第二步:創(chuàng)建表users和列id,username,password

第三步:我們插入幾條數(shù)據(jù)

同樣的道理,大家多插幾條數(shù)據(jù)。到此我們整個(gè)任務(wù)就完成了。

最終成果如下:

第二節(jié) 尋找及確認(rèn)SQL注入

2.1、推理測(cè)試法

尋找SQL注入漏洞有一種很簡(jiǎn)單的方法,就是通過發(fā)送特殊的數(shù)據(jù)來觸發(fā)異常。

首先我們需要了解數(shù)據(jù)是通過什么方式進(jìn)行輸入,這里我總結(jié)了三個(gè):

GET請(qǐng)求:該請(qǐng)求在URL中發(fā)送參數(shù)。

POST請(qǐng)求:數(shù)據(jù)被包含在請(qǐng)求體中。

其他注入型數(shù)據(jù):HTTP請(qǐng)求的其他內(nèi)容也可能會(huì)觸發(fā)SQL注入漏洞。

了解完數(shù)據(jù)的輸入方式,我們接下來再學(xué)習(xí)數(shù)據(jù)庫(kù)錯(cuò)誤。這里我們以MySQL為例,其它的請(qǐng)大家自行學(xué)習(xí)咯。

我們現(xiàn)在參數(shù)后面加個(gè)單引號(hào),如下圖:

sql語句最終變?yōu)?/p>

[SQL]純文本查看復(fù)制代碼

?

1

select*fromuserswhereid = 1'

執(zhí)行失敗,所以mysql_query()函數(shù)會(huì)返回一個(gè)布爾值,在下行代碼中mysql_fetch_array($sql)將執(zhí)行失敗,并且PHP會(huì)顯示一條警告信息,告訴我們mysql_fetch_array()的第一個(gè)參數(shù)必須是個(gè)資源,而代碼在實(shí)際運(yùn)行中,給出的參數(shù)值卻是一個(gè)布爾值。

我們修改代碼在

[PHP]純文本查看復(fù)制代碼

?

1

2$sql= mysql_query($querry,$con);下一行加上

var_dump($sql);

可以發(fā)現(xiàn):

為了更好的了解MySQL錯(cuò)誤,我們?cè)?/p>

[PHP]純文本查看復(fù)制代碼

?

1

$sql= mysql_query($querry,$con);

加上

[PHP]純文本查看復(fù)制代碼

?

1

2

3

4if(!$sql)

{

die('

error:'.mysql_error().'

');

}

這樣當(dāng)應(yīng)用捕獲到數(shù)據(jù)庫(kù)錯(cuò)誤且SQL查詢失敗時(shí),就會(huì)返回錯(cuò)誤信息:(我們?cè)趨?shù)中添加單引號(hào)返回的錯(cuò)誤信息)

[SQL]純文本查看復(fù)制代碼

?

1

error:You have an errorinyour SQL syntax;checkthe manual that correspondstoyour MySQL server versionfortherightsyntaxtouse near'''atline 1

然后借助這些錯(cuò)誤,我們這可以推斷應(yīng)該存在SQL注入。還有其他數(shù)據(jù)庫(kù)錯(cuò)誤信息,以及MySQL其他錯(cuò)誤信息,由于篇幅問題就不一一講解了。

2.2、and大法和or大法

頁(yè)面不返回任何錯(cuò)誤信息,我們就可以借助本方法來推斷了,首先我們?cè)趨?shù)后面加上 and 1=1和and 1=2看看有什么不同

可以發(fā)現(xiàn)and 1=1 返回了數(shù)據(jù),而and 1=2沒有,這是由于1=1是一個(gè)為真的條件,前面的結(jié)果是true,true and true 所以沒有任何問題,第二個(gè) 1=2 是個(gè)假條件, true and false還是false,所以并沒有數(shù)據(jù)返回。

好,講完and,我們自來看看 or ,or就是或者,兩個(gè)都為假,才會(huì)為假。我們先把id改為5,可以發(fā)現(xiàn)id=5是沒有數(shù)據(jù)的。

可以發(fā)現(xiàn)我們加上or 1=1就成功返回了數(shù)據(jù),這是因?yàn)?=1為真,不管前面是不是假,數(shù)據(jù)都會(huì)返回,這樣就把表里面數(shù)據(jù)全部返回,我們沒看見,是因?yàn)榇a中并沒有迭代輸出。這樣,我們來修改一下代碼。

[PHP]純文本查看復(fù)制代碼

?

01

02

03

04

05

06

07

08

09

10

11

12echo"";

id

username

echo"";

//遍歷查詢結(jié)果

while($result= mysql_fetch_array($sql)) {

".$result[0] ."

".$result[1] ."

echo"";

}

然后你就可以發(fā)現(xiàn):

2.3、加法和減法

這里我們需要區(qū)分一下數(shù)字型和字符串型:

數(shù)字型:不需要使用單引號(hào)來表示

其他類型:使用單引號(hào)來表示

綜合上述,我們可以發(fā)現(xiàn)我們的例子是數(shù)字型的,這樣我們就可以使用加法和減法來判斷了。

加法,我們?cè)趨?shù)輸入1+1,看看返回的數(shù)據(jù)是不是id等于2的結(jié)果,這里注意一下+號(hào)在SQL語句是有特效含義的,所以我們要對(duì)其進(jìn)行url編碼,最后也就是%2b。

減法是同樣的道理,不過我們不需要對(duì)-號(hào)進(jìn)行url編碼了。

結(jié)束語

感謝大家的支持吧,在此我也總結(jié)一下前面自己的不足,由于篇幅很長(zhǎng),寬度是到位了,但是并沒有深入,也不算詳細(xì),所以本篇教程分為了三級(jí)即初級(jí)、中級(jí)、高級(jí)。六節(jié)來寫,既要深度也要寬度,當(dāng)然我也不是技術(shù)大牛,如文中有錯(cuò)誤請(qǐng)指出,我會(huì)加以改正,謝謝。

系列文章預(yù)告及導(dǎo)航

滲透攻防Web篇-SQL注入攻擊中級(jí)(狀態(tài):更新中)

第三節(jié) 利用SQL注入

第四節(jié) SQL盲注利用

滲透攻防Web篇-SQL注入攻擊高級(jí)(狀態(tài):更新中)

第五節(jié) 避開過濾方法總結(jié)

第六節(jié) 探討SQL注入防御技巧

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容