iT邦幫忙

2025 iThome 鐵人賽

DAY 5
0
Security

規組駭了了::你無定落勾去的鑠奅 Web Hacking 步數系列 第 5

0x05 / SQL Injection.著,伊閣有咧喘氣.Protocol Smuggling

  • 分享至 

  • xImage
  •  

https://ithelp.ithome.com.tw/upload/images/20250918/201201872G9nVwoTHW.png

TL;DR
共 query 先櫼甲痟長,若 SQL client 無處理予好勢,按呢就有法度予 protocol 內底囥長度彼个欄位 overflow 規个磅去,長度的數字就會tsua̋n變毋著去,按呢就有機會予咱囥歹資料入去矣。


佇前幾工已經講誠濟 HTTP smuggling 的物件矣,咱來換一个仔口味,來看 SQL Injection Isn't Dead: Smuggling Queries at the Protocol Level

講著 Web Security,凡勢誠濟人拄開始學做「駭客」的時,頭一个耍的物件就是 SQL injection,古早時(?)有啥物阿D注入、明小子,後來閣有像 SQLMap 遮的物件。

是講逐家敢知影世界頭一个 SQL injection 是啥物時陣出現的?是佇 1998 年,踮 Phrack 這个全世界上有名聲的 hacking 雜誌頂懸,予 rain.forest.puppy 發表的,伊是咧研究 Windows 頂的 web 漏縫的時發現的 (ref. https://phrack.org/issues/54/8#article)

彼到這馬攏已經過欲三十年矣,SQL injection 敢閣有啥物新齣頭通好耍?當然嘛是有!佇舊年(2024)的 DEFCON,SonarSource 的 Paul Gerste 就有發表一个新招。

毋過,這擺趣味的是,伊佮傳統的耍法無啥仝,嘛是對 query 落手無毋著,毋過是對 query 來舞 SQL protocol,來共 protocol 舞歹去。

是講,其實遮嘛是咧耍長度無一致的問題,佮 HTTP smuggling 有淡薄仔相𫝛的所在。

基礎概念

咱先愛知影講 SQL client 是按怎參 SQL server 溝通的。

像講佇 PHP,咱若是欲連入去 MySQL 咱可能是按呢寫:

<?php
$pdo = new PDO("mysql:host=sql.server.tld;dbname=testdb","user","pass");
foreach($pdo->query("SELECT * FROM users WHERE id=".$_GET["id"]) as $row){
    print_r($row);
}

這就代表講,佇這个頁面咧走的時,是有三个角色佇咧:

  • 使用者:Browser,會使傳 /?id=1337 按呢的資料予 server
  • PHP:伊是 Web server,毋過伊嘛是 SQL 的 client,愛連入去 SQL server 佮伊講話
  • SQL server:伊愛接著對 PHP 傳入來的 query

咱知影講 Browser <-> PHP / Web server 是透過「HTTP」這个 protocol 來講話的,阿 PHP <-> SQL server 咧?無毋著,in 有 in 家己的 protocol!

所以,伊規个 flow 的差不多生做按呢:

┌───────────────────────────┐
│ /?id=13337           [GO] │
└───────────────────────────┘
|
V
GET /?id=1337 HTTP/1.1
Host: example.tld
|
V
SOME_SQL_PROTOCOL...SELECT * FROM users WHERE id=1337...END
|
V
SQL server

若有這款概念,咱就會使來看覓真實的 protocol 是生啥款,會有啥物問題佇咧!

PostgreSQL

先來看一个仔伊的 protocol:

Type Length Value…
'Q' 00 00 00 17 "SELECT …"

type = 1-byte 標示
length = 4 bytes integer
value = query 本身

欸,彼个 length 干焦 4 bytes aka 2147483647 爾!咱若是予後壁彼个 query value 超過這个數字,length 遐會發生啥物代誌咧?

佇 Golang 內底的 pgx 這个 client 咧處理這種數字的時就有發生這款的問題:

func (src *Bind) Encode(dst []byte) []byte {
    dst = append(dst, 'B')
    sp := len(dst)
    // …
    pgio.SetInt32(dst[sp:], int32(len(dst[sp:])))
                            ^^^^^ 共數字硬去剉斷做 int32 矣
    return dst
}

正常來講,若是有一个 AAAA (len=4) 的資料,length 遐就會是 8(4 bytes length + 4 bytes data)

Type Length Value
'Q' 00 00 00 08 "AAAA"

猶毋過咱的資料若是傷過長,偌長咧?像 2147483647 遮爾仔長,彼个 protocol 資料就會夆變做下跤按呢:

Type Length Value…
'Q' 00 00 00 04 "AAAAAAAA..."

是按怎是 4? 彼是因為 2^32 + 4 = 0x100000004,毋過頭前彼 0x1 遐夆剉斷矣,tsua̋nn 干焦賰 0x00000004 按呢。

咱若送一个親像按呢的資料去入 SQL server,伊遐會按怎解讀咧?

Type Length Value Type Length Value
'Q' 00 00 00 04 "" A AAAA AAA...

著啦,遐後壁捅出去的資料自然就會夆變做後一組資料,按呢就予咱一个注入別个 query 的機會矣。咱共後壁遐的一 thoo-lá-khuh A... 改做一个合法的 query protocol,按呢毋著會當 query 攏隨咱走矣!

MongoDB

messageLength requestID responseTo opCode value
17 00 00 00 00 00 00 00 00 00 00 00 DD 07 00 00

MongoDB 的格式是較小可複雜,毋過道理嘛是攏仝款,自然 in 佇 MongoDB 嘛是有揣著誠成的問題,佇 Rust 的 mongodb 有按呢的 khóo:

async fn write_to<T: AsyncWrite + Send + Unpin>(&self, mut writer: T) -> Result<()> {
    let sections = self.get_sections_bytes();
    let total_length = Header::LENGTH
        + std::mem::size_of::<u32>()
        + sections.len()
        + /* ... */;
    let header = Header {
        length: total_length as i32, //  嘛是共數字硬去剉斷做 int32
        // ...
    };
    header.write_to(&mut writer).await?;
    writer.write_u32_le(self.flags.bits()).await?;
    writer.write_all(&sections).await?;
    // ...
}

欲利用嘛是仝款照起工去共伊 overflow 就好矣:

https://ithelp.ithome.com.tw/upload/images/20250919/20120187hEGJhGkKtN.png

Redis

Type Length Delimiter Value… Delimiter
'+' "17" \r\n "GET …" \r\n

Redis 是純文字的 protocol,彼个 length 干焦是普通的字串無 overflow 的風險,所以其實伊無問題啦 :P

基本上,純文字彼款的就較袂有咱討論的這種 overflow 的問題佇咧。


伊後壁閣有講著一寡若是佇 real world 欲利用會拄著的穩定性問題,佮斟酌看一寡 exploitable 的議題,若是有興趣會當去看覓。

紲落來拜六禮拜,咱會來簡單講一寡佇 CTF 內底捌出現的趣味新招 👀


上一篇
0x04 / HTTP/1.1.啊你好死矣啦.R.I.P \|/
系列文
規組駭了了::你無定落勾去的鑠奅 Web Hacking 步數5
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言