[2019 SSTF OpenCTF] BlackHackerService
[2019 SSTF OpenCTF] BlackHackerService
와 이건 생각도 못했다... 아니 시도를 끈질기게 못했다;;
쿠키값으로 login된 정보를 관리하는데, 이 쿠키값을 변조되면 Not found라는 페이지로 원래는 넘어간다.
그런데 완전 메인 페이지로 돌아가면 TypeError가 뜨면서 500 Internal Server Error 가 나오면서 서버에 올라간 flask의 어떤 부분에서 오류가 났는지 볼 수 있따... 와....
이제 여기서 대부분의 정보를 얻을수 있는데, 하나하나 살펴보면 아래 부분들이 중요하다.
File "/run/task/main.py", line 106, in index
def index():
admin=False
error=""
cook = request.headers.get("Cookie")
if cook != None:
c = check_cookie(cook)
dbSession = init_db()
user = dbSession.query(User).filter(User.username == c['username']).first()
dbSession.close()
if user is not None:
if c['sessionId'] == user.sessionId:
File "/run/task/main.py", line 24, in check_cookie
def check_cookie(cookie):
cookie = cookie.replace("testcookie=","")
#cookie format
#{ "username": "", "email": "", "isAdmin" : 1/0, "sessionId" : "" }
#check /cookietest endpoint if you want to decode your cookie
js = cipher.decrypt(cookie)
js = remNonAscii(js)
j = json.loads(js,object_pairs_hook=OrderedDict)
return j
File "/run/task/AESCipher.py", line 18, in decrypt
plaintext = self._pad(plaintext)
cipher = AES.new(self.key,AES.MODE_CBC,self.iv)
return base64.b64encode(cipher.encrypt(plaintext))
def decrypt(self,ciphertext):
ciphertext = base64.b64decode(ciphertext)
cipher = AES.new(self.key,AES.MODE_CBC,self.iv)
return self._unpad(cipher.decrypt(ciphertext))
def _pad(self,s):
l = len(s)
AES-CBC를 사용한다는 것을 알 수 있고, (물론 이건 login 계정을 여러번 만들면서 추측가능했다.)
쿠키 포맷까지 얻을 수 있다.
#cookie format
#{ "username": "", "email": "", "isAdmin" : 1/0, "sessionId" : "" }
#check /cookietest endpoint if you want to decode your cookie
처음에는 저 부분이 주어지지않는다고 생각하여서, 여러 계정을 만들며 테스트해가며 BLOCKSIZE가 16이고, CBC모드라고 판단할 수 있엇다.
그래서 처음에는 username을 admin으로 만드는 문제인줄 알고 열심히 고생했었다...ㅠㅠ (그런데 사실 저 포맷을 믿을만한게 못되는게... 테스트해본 결과 첫번째블록에는 username의 두번째까지 들어간다.)
그래서 정상적인 포맷은 아래와 같이 되야한다.
{"username": "test", "email": "test@test.test123", "isAdmin": 0, "sessionId": "779ea873a8bc896e89f66f"}
그러므로 블럭단위로 나뉘어 encrypt되는 것은 아래와 같다.
{"username": "te
st", "email": "t
est@test.test123
", "isAdmin": 0,
"sessionId": "7
79ea873a8bc896e89f66f..."}
CBC모드에서는 decrypt 후 이전 Ciphertext와 XOR한 값이 Plaintext가 되므로, 이전 Ciphertext를 수정하여 다음 plaintext에 영향을 줄 수가 있다.
{"username": "br
e4k", "email": "
test@test.test12
3", "isAdmin": 0
"sessionId": "e
fddcaf9eba85ab66aa9ec5649a7b5b4"}
쿠키값에서 3번째 블럭인 email부분은 어짜피 쓸모가 없으니, 3번째 블록의 Ciphertext를 수정하여 다음 블럭의 평문에 영향을 줄 수 있다. 이렇게되면 3번째 블럭은 복호화가 제대로 되지않으나(복호화는 되지만 이상한값이 나온다.) 4번째 블럭의 값을 변경할 수 있다.
이게 BitFlip의 차례이다. 3번째블럭의 16번째 bytes를 flip시켜서 다음 블럭과 xor할때 "isAdmin": 1
이 되게 만들어 주면 된다.
와 근데 이거도 운이 따른다 ㅡㅡ;;
정말 운이 안좋게도 "isAdmin": 1이 안나오는경우가 있다. 2~9까지는 나오는데;;
(그런 경우는 어쩔수없이 새로 계정을 파야한다 ㅁㄴㅇㄹ)
break → br3ak → bre4k 로 해서 bre4k에서 성공했다.
from base64 import b64decode, b64encode
import requests
def requestAdminSecret(cookie):
cookies = {'Cookie': 'testcookie='+cookie}
r = requests.get("http://blackhackerservice.sstf.site/hive/secret/",headers=cookies)
result = r.content
if "Not found" in result or "url(/static/ad.png)" in result:
return (False, result)
return (True, result)
"""
username : bre4k
email : test@test.test123
passwd : test
{"username": "br
e4k", "email": "
test@test.test12
3", "isAdmin": 0
"sessionId": "e
fddcaf9eba85ab66aa9ec5649a7b5b4"}
"""
cookie = "i4KQHe3skBiL2cNgZtz0m8bpdnbe2hFNK+71TIRV9wyKCNhOt+4R4ZQu+cwKkTQ7RK110r8P8csh3GWJAduUqGz5xqkBaG93HBeyoMBOUygPbsXo/q+8gifpRh/FhvOw+GK82TuvGfLU0XB8WjBZDJV5oCSHZUu9Iz7rzwP8LY0="
cookie = b64decode(cookie)
sta = cookie[:32]
mid = cookie[32:48]
end = cookie[48:]
for x in range(0, 256):
middle = mid[:15] + chr(x)
corrupt_cookie = b64encode(sta + middle + end)
access, result = requestAdminSecret(corrupt_cookie)
if access:
print("new cookie("+str(x)+") : "+corrupt_cookie)
'Write-up > Crypto' 카테고리의 다른 글
HITCON2020 another secret note / AES-CBC / JSON (0) | 2020.11.30 |
---|---|
[SEC-T CTF 2019] Trivial RSA (0) | 2019.09.22 |
[2019 SSTF OpenCTF] Roughlt Secure Algorithm (0) | 2019.08.28 |
[2019 SSTF OpenCTF] Certain_parts_are_as_hard_as_the_whole (RSA LSB Oracle) (0) | 2019.08.28 |
[RedpwnCTF] Binary (RSA LSB Oracle Attack) (0) | 2019.08.17 |