一、原理
二、概念
三、分類
四、SQL Server數據庫注入
五、Mysql數據庫注入
六、Oracle數據庫注入
七、SQLMap注入工具的使用
八、穿山甲和Havij的使用
九、防止SQL注入
接之前的:
繼續記錄。
五、Mysql數據庫注入
之前記錄了sqlserver的漏洞,數據庫注入思路類似,只不過其使用的函數或語句有不同,像查數據庫版本,sqlserver是@@version,mysql則是version()。
1,mysql中的註釋
①:#:行註釋。
②:--:行註釋,不同的是這個註釋後要跟一個或多個空格,或者tag。
③:/**/:塊註釋,也是多行註釋。
/**/塊註釋有一個特點,如下sql語句:
執行結果正常顯示,/**/是沒有起作用的,因為其!有特殊意義,像圖中的/*!55555,username*/則表示如果版本號高於或等於5.55.55,則會被執行。如果!後不加版本號,mysql則會直接執行sql語句。
2,獲取元數據
mysql5.0版本及以上提供了information_schema一個信息數據庫,提供了訪問元數據的方式。
查詢用戶數據庫名稱sql如下:
意思為從information_schema.schema表中查出第一個數據庫的名稱。information_schema.schemata表提供了關於數據庫的信息。
查詢當前數據庫表的sql如下:
意思為從information_schema.tables中查出第一條數據。information_schema.tables表提供了關於數據庫中表的信息。
查詢指定表的所有字段sql如下:
意思為從information_schema.columns表中查users的字段名。information_schema.columns表提供了表中的列信息。
3,union查詢
union查詢在sqlserver中說過,這裡只記錄他們之間的差異。將以下sql語句分別在sqlserver,mysql,oracle中分別運行,結果卻不同:
sqlserver中提示錯誤:數據類型不匹配,無法正常執行。mysql中正常執行。oracle中提示錯誤:數據類型不匹配,無法正常執行。所以,如果在sqlserver和oracle中,數據類型不確定的情況下,建議使用null關鍵字去匹配。
4,mysql函數利用
每個數據庫都有許多系統函數,來看一下mysql中對滲透有幫助的函數。
①:load_file()函數讀文件操作
load_file()讀文件條件為,文件位置要在服務器,路徑為絕對路徑,用戶要有file權限,容量要小於max_allowed_packet字節(默認16M,最大1GB)。sql語句如下:
一般sql注入中都會對單引號有所防禦,所以轉換為十六進制後的sql如下:
ps:我圖中的十六進制前沒有加ox,實際sql注入中開頭要加0x,表名值是十六進制的。
②:into outfile寫文件操作
into outfile和load_file()一樣,要有file權限,文件要為全路徑名稱。舉個例子:
第一條語句是往c盤下寫了一個1.php的文件,內容是<?php phpinfo();?>,能獲取的信息都懂。
第二條語句是往c盤下寫了一個2.php的文件,內容是c://2.txt。char()這個函數是將ASCII碼轉換成字符的。所以事先將字符串轉換為ASCII碼,ASCII碼中間的空格用逗號代替。工具的話推薦用(ASCII碼及進制轉換工具)。像注入過濾單引號的,除了十六進制,此方法也可以。
③:連接字符串
concat()函數,如下:
第一條語句是往c盤下寫了一個1.php的文件,內容是<?php phpinfo();?>,能獲取的信息都懂。
第二條語句是往c盤下寫了一個2.php的文件,內容是c://2.txt。char()這個函數是將ASCII碼轉換成字符的。所以事先將字符串轉換為ASCII碼,ASCII碼中間的空格用逗號代替。工具的話推薦用(ASCII碼及進制轉換工具)。像注入過濾單引號的,除了十六進制,此方法也可以。
③:連接字符串
concat()函數,如下:
聯合查詢第二語句的內容,mysql自身函數執行的結果是作為一個輸出的,concat()函數將其連接了起來。相似的還有個concat_ws()函數,有興趣可以看下。
mysql常用的函數如下表:
老規矩,這些函數也需要相應的權限,mysql中權限如下表:
5,mysql顯錯式注入
sqlserver中通過將字符串轉為int類型時的報錯來提取一些信息,但mysql中卻會正常執行。這塊將利用mysql的一些特性來提取錯誤消息,下面舉幾個例子:
①:updatexml是修改xml文檔的,利用它來相似mysql的版本號,sql和報錯如下:
②:extractvalue是查看xml文檔的,利用它來獲取當前用戶的名稱,sql和報錯如下:
③:floor函數返回小數的整數部分,利用它來獲取當前用戶名和表名類信息,sql和報錯如下:
通過這類的函數,可以達到與sqlserver數據庫顯錯類似的效果。
6,寬字節注入
寬字節注入是由於編碼不統一造成的,這種注入一般是php+mysql的程序。當打開php.ini中的magic_quotes_gpc選項時,使用get,post接受的單引號雙引號反斜線和null之類的數據,都會在前加上反斜線轉義。如下圖的接受程序和運行實例:
單引號被轉義,隨便輸入一個寬字符,例如%dd,如下圖:
這次的單引號沒有被轉義,這樣可以突破php的轉義,繼續閉合sql語句進行sql注入。不過一般不建議開啟magic_quotes_gpc這項,因為單引號屬於字符串中的正常字符,如果進行轉義,則相當於不是原來的變量值了。
7,mysql長字符截斷
先看一下mysql長字符截斷的原理,假設有如下一張表:
插入以下sql語句,添加幾個用戶,sql如下:
第一個成功插入。第二個成功插入只是有警告。第三個成功插入只是有警告。有了警告,那到底是否插入成功呢?查詢表數據如下:
可見插入成功了,此時分別查看這三條數據的username字段長度,分別為5,7,7。有沒有發現,第二條和第三條是規定的長度,由此可以直到,如果超過默認長度,mysql會將其截斷。
那麼,攻擊點在哪裡?當你運行select username from users where username='admin';這條語句時,查出來的是三條數據。假設,後臺管理員登錄的sql是這樣的:
那註冊一個“admin ”的賬戶也可以進行登錄了。著名的wordpress曾經就被這種方式攻擊過。
8,延時注入
一般我們在url後輸入單引號之類的字符,根據頁面是否正常顯示來判斷是否存在sql注入。到現在,網站這方面比以前強了很多,不論輸入什麼,頁面都不會有變化,這可能就需要盲目的判斷,即無差異的注入,延時注入是無差異注入的一種。
mysql有一個sleep(duration)函數,意思是在duration參數給定的秒數後運行sql語句,如下sql:
這個sql會在3秒後執行。判斷url是否存在sql注入的步驟如下:
這樣便可以確定這個url是存在注入的。既然存在注入,就可以讀取數據,思路如下:
①:查詢當前用戶,並取得字符串長度。
②:截取字符串第一個字符,並轉為ASCII碼。
③:將第一個字符的ASCII碼與ASCII碼錶對比,如果成功將延遲3秒。
④:繼續步驟②、③,直至字符串截取完畢。
對應sql如下:
sql中的L是字符串的第幾個字符。N是ASCII碼。
通過延時注入不僅可以讀取數據庫當前用戶,也可以讀取表,列,文件。
當然sqlserver的waitfor delay函數,oracle的DBMS_LOCK.SLEEP函數,都是類似的功能。
ok,後續內容,這幾天會不間斷續補。
-----------------------------------------------------------------------------------------------------------------------------
tips:棗樹荒頭條號不定期分享關於網站滲透,信息安全,網絡安全,網絡運維等方面的知識。喜歡的請點一波關注。