├── README.md
├── apis
└── api.ini
├── common
├── __pycache__
│ ├── logger.cpython-37.pyc
│ └── login.cpython-37.pyc
├── logger.py
└── login.py
├── fuzzers
├── chromedriver.exe
├── fuzzer.py
├── geckodriver.exe
├── geckodriver.log
├── rtsp_fuzzer.py
└── snmp_fuzzer.py
├── logs
└── nvr_2019-06-03.log
└── payloads
├── format_string.txt
├── overflow.txt
├── random_num.txt
├── special_char.txt
└── unicode.txt
/README.md:
--------------------------------------------------------------------------------
1 |
2 | https://www.cnblogs.com/lsdb/p/10958933.html
--------------------------------------------------------------------------------
/apis/api.ini:
--------------------------------------------------------------------------------
1 | ; 目标主机信息配置节区
2 | [server_info]
3 | ; 要探测的IP地址
4 | ;server_ip = 10.10.15.236
5 | server_ip = 10.10.6.93
6 | ; 要探测的端口
7 | server_port = 443
8 | ; 数据包使用的协议,可以是http或https
9 | server_type = https
10 | ; 发送数据包时是否使用用户名和密码进行认证,可以是True或False
11 | use_user = True
12 | ; 发送数据包使用的用户名
13 | username = admin
14 | ; 发送数据包使用的密码
15 | password = ABcd1234
16 | ; 是否使用代理,可以是True或False
17 | use_proxy = True
18 | ; 代理协议及地址,不要使用单引号
19 | proxies = {
20 | "http":"127.0.0.1:8080",
21 | "https":"127.0.0.1:8080"
22 | }
23 | ; 日志输出位置,可以是console或file
24 | log_type = file
25 | ; 当log_type为file时用作日志文件的前辍,当log_type为console时不起作用
26 | log_file_prefix = nvr
27 | ; 要进行模糊测试的类型,及模糊测试类型对应的payload文件
28 | fuzz_payload_dict = {
29 | "overflow":"overflow.txt",
30 | "format_string": "format_string.txt",
31 | "random_num": "random_num.txt",
32 | "special_char": "special_char.txt",
33 | "unicode": "unicode.txt"
34 | }
35 |
36 | ; 协议api节区
37 | [protocol]
38 | ; 都要使用"api_name = api_format"格式,api_name是故URL用的不能随便乱写
39 | ; api_format有多行,在ini文件中后续行要以开头
40 | ; 要模糊测试的位置使用fuzz_var()包含起来即可
41 | testLogin =
42 |
43 |
44 | fuzzer_var(admin)
45 | fuzzer_var(admin)
46 |
47 |
48 |
49 | ; 第二个请求一样写
50 | editParam =
51 |
52 |
53 |
54 | fuzzer_var(manual)
55 | fuzzer_var(60)
56 | fuzzer_var(5,10,30,60,120,0)
57 | fuzzer_var(true)
58 |
59 |
60 |
61 |
62 | ; 后续请求类似前面一样继续点在后边即可
63 |
--------------------------------------------------------------------------------
/common/__pycache__/logger.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PrettyUp/Fuzzer/9a40d4634c08a73d39837ec684c717b398d042c5/common/__pycache__/logger.cpython-37.pyc
--------------------------------------------------------------------------------
/common/__pycache__/login.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PrettyUp/Fuzzer/9a40d4634c08a73d39837ec684c717b398d042c5/common/__pycache__/login.cpython-37.pyc
--------------------------------------------------------------------------------
/common/logger.py:
--------------------------------------------------------------------------------
1 | import os
2 | import datetime
3 | import logging
4 |
5 | class LogConfig:
6 | def __init__(self, log_type="console", log_file_prefix="nvr"):
7 | # 指定日志输出到控制台时的初始化
8 | if log_type == "console":
9 | logging.basicConfig(level=logging.INFO,
10 | format='%(asctime)s %(levelname)s %(message)s',
11 | datefmt='%Y-%m-%d %H:%M:%S',
12 | )
13 | # 指定日志输出到文件的初始化
14 | elif log_type == "file":
15 | # 创建存放日志的目录
16 | if not os.path.exists('../logs'):
17 | os.mkdir('../logs')
18 |
19 | # 操作系统本身不允许文件名包含:等特殊字符,所以这里也不要用,不然赋给filename时会报错
20 | nowTime = datetime.datetime.now().strftime('%Y-%m-%d')
21 |
22 | file_name = f'../logs/{log_file_prefix}_{nowTime}.log'
23 | file_handler = logging.FileHandler(filename=file_name,encoding = 'utf-8', mode = 'w+')
24 | # level----指定打印的日志等级;默认为WARNING;可为NOTSET、DEBUG、INFO、WARNING、ERROR、CRITICAL
25 | # format----指定整条日志的格式;这里设置为“时间-等级-日志内容”
26 | # datefmt----format中时间的格式;
27 | # filename----日志输出到的文件;默认打印到控制台
28 | # filemode----日志文件读写形式;默认为“a”;配合filename使用,如果不用filename该参数也可不用
29 | # 本来输出到文件使用filename和filemode两个参数就可以了,不需要handlers
30 | # 但是logging将日志输出到文件时中文会乱码,而logging.basicConfig又没有提供指定编码的参数,要指定编码只能使用handlers
31 | logging.basicConfig(level=logging.INFO,
32 | format='%(asctime)s %(levelname)s %(message)s',
33 | datefmt='%Y-%m-%d %H:%M:%S',
34 | # filename=file_name,
35 | # filemode='a',
36 | handlers=[file_handler],
37 | )
38 |
39 | # self.logger = logging.getLogger()
40 |
41 | def getLogger(self):
42 | logger = logging.getLogger()
43 | return logger
44 |
45 | if __name__ == "__main__":
46 | # log_type = "console"
47 | log_type = "file"
48 | logger = LogConfig(log_type).getLogger()
49 | logger.debug('print by debug')
50 | logger.info('print by info')
51 | logger.warning('prit by warning')
--------------------------------------------------------------------------------
/common/login.py:
--------------------------------------------------------------------------------
1 | import json
2 | import time
3 | from selenium import webdriver
4 | from selenium.webdriver.support.wait import WebDriverWait
5 | from selenium.webdriver.support import expected_conditions as EC
6 | from selenium.webdriver.common.by import By
7 |
8 | class GetSessionAndToken():
9 | def __init__(self,url,username,password):
10 | # 启用无头模式,可选
11 | browser_options = webdriver.FirefoxOptions()
12 | browser_options.add_argument('--headless')
13 | browser_options.add_argument('--disable-gpu')
14 | self.browser = webdriver.Firefox(firefox_options=browser_options)
15 | # self.browser = webdriver.Chrome()
16 | self.login_system(url,username,password)
17 |
18 | # 登录系统,具体到自己系统时需要自行修改
19 | def login_system(self,url,username,password):
20 | # 登录用户名密码,改成目标系统用户名密码
21 | # username = "admin"
22 | # password = "123456"
23 | # 登录页面url,改成目标系统登录页面
24 | # url = "https://10.10.6.93/#login"
25 | self.browser.get(url)
26 | # 显性等待,直到用户名控件加载出来才进行下一步
27 | WebDriverWait(self.browser,20,0.5).until(EC.presence_of_element_located((By.ID,"txtUserName")))
28 | # 填写用户名
29 | self.browser.find_element_by_id("txtUserName").send_keys(username)
30 | # 填写密码
31 | self.browser.find_element_by_id("txtPassword").send_keys(password)
32 | # 点击登录
33 | self.browser.find_element_by_id("btnLogin").click()
34 | # 强制等待5秒,待session和token都成功返回并存到浏览器中
35 | # restful隐性等待不太好用?self.browser.implicitly_wait(5)
36 | time.sleep(5)
37 |
38 | # 获取sessionid
39 | def get_sessionid(self):
40 | # 是要从localStorage中获取还是要从sessionStorage中获取,具体看目标系统存到哪个中
41 | # window.sessionStorage和直接写sessionStorage是等效的
42 | # 一定要使用return,不然获取到的一直是None
43 | # get的Item不一定就叫sessionId,得具体看目标系统把sessionid存到哪个变量中
44 | sessionid = self.browser.execute_script('return sessionStorage.getItem("sessionId");')
45 |
46 | # 另外sessionid一般都直接通过返回Set-Cookies头设置到Cookie中,所以也可以从Cookie读取
47 | # 获取浏览器所有Set-Cookie,返回对象是字典列表
48 | # cookies = self.browser.get_cookies()
49 | # 获取单项Cookie,是不是叫sessionId取决于系统存成什么变量,单项Cookie是字典
50 | # cookie = self.browser.get_cookie("sessionId")
51 | # cookie = cookie["value"]
52 | # print(f"{cookies}")
53 | return sessionid
54 |
55 | # 获取token
56 | def get_token(self):
57 | # 是要从localStorage中获取还是要从sessionStorage中获取,具体看目标系统存到哪个中
58 | # window.sessionStorage和直接写sessionStorage是等效的
59 | # 一定要使用return,不然获取到的一直是None
60 | # get的Item不一定就叫token,得具体看目标系统把token存到哪个变量中
61 | token = self.browser.execute_script('return sessionStorage.getItem("token");')
62 | # print(f"{token}")
63 | return token
64 |
65 | def __del__(self):
66 | # 退出程序时关闭浏览器
67 | self.browser.close()
68 |
69 | if __name__ == "__main__":
70 | obj = GetSessionAndToken()
71 | obj.login_system()
72 | sessionid = obj.get_sessionid()
73 | token = obj.get_token()
74 | print(f"sessionid为: {sessionid}\n"
75 | f"token为: {token}")
--------------------------------------------------------------------------------
/fuzzers/chromedriver.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PrettyUp/Fuzzer/9a40d4634c08a73d39837ec684c717b398d042c5/fuzzers/chromedriver.exe
--------------------------------------------------------------------------------
/fuzzers/fuzzer.py:
--------------------------------------------------------------------------------
1 | import configparser
2 | import logging
3 | import re
4 | import requests
5 | import json
6 | from common.logger import LogConfig
7 | from common.login import GetSessionAndToken
8 |
9 | # configparser.ConfigParser的optionxform方法返回的是名称的小写,但我们这是的名称是区分大小写的
10 | # 所以我们需要重写其optionxform方法,直接保持名称原大小写返回
11 | class MyConfigParser(configparser.ConfigParser):
12 | # python不会自己调用父类init方法,所以需要手动调用一下
13 | def __init__(self, defaults=None):
14 | configparser.ConfigParser.__init__(self, defaults=defaults)
15 |
16 | def optionxform(self, optionstr):
17 | # return optionstr.lower()
18 | return optionstr
19 |
20 | class Fuzzer:
21 | def __init__(self, fuzz_config_file ="api.ini"):
22 | # 读取配置文件
23 | self.config = MyConfigParser()
24 | self.config.read(f'../apis/{fuzz_config_file}', encoding="utf-8-sig")
25 | self.fuzz_payload_dict = json.loads(self.config["server_info"]["fuzz_payload_dict"])
26 | self.proxies = json.loads(self.config["server_info"]["proxies"])
27 |
28 | # 设置日志格式
29 | log_type = self.config["server_info"]["log_type"]
30 | log_file_prefix = self.config["server_info"]["log_file_prefix"]
31 | LogConfig(log_type=log_type, log_file_prefix=log_file_prefix)
32 |
33 | # 设置登录URL、用户名、密码,并获取session和cookie
34 | # 需要根据自己系统修改登录逻辑,session和token的获取可能也要修复
35 | url = f'{self.config["server_info"]["server_type"]}://{self.config["server_info"]["server_ip"]}:{self.config["server_info"]["server_port"]}/#login'
36 | username = self.config["server_info"]["username"]
37 | password = self.config["server_info"]["password"]
38 | obj = GetSessionAndToken(url,username,password)
39 | sessionid = obj.get_sessionid()
40 | self.token = obj.get_token()
41 | self.fuzz_headers = {
42 | 'Host': f'{self.config["server_info"]["server_ip"]}',
43 | 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:60.0) Gecko/20100101 Firefox/60.0',
44 | 'Accept': 'application/xml, text/xml, */*; q=0.01',
45 | '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',
46 | 'Accept-Encoding': 'gzip, deflate',
47 | 'Referer': f'{self.config["server_info"]["server_type"]}://{self.config["server_info"]["server_ip"]}',
48 | 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
49 | 'X-Requested-With': 'XMLHttpRequest',
50 | 'Cookie': f'Secure; sessionId={sessionid}',
51 | 'Connection': 'close',
52 | }
53 |
54 |
55 | # 主要的遍历逻辑
56 | def exec_fuzz(self):
57 | url_pre = f'{self.config["server_info"]["server_type"]}://{self.config["server_info"]["server_ip"]}:{self.config["server_info"]["server_port"]}/'
58 | regexp = "fuzzer_var\([^\)]*\)"
59 | # 循环所有api
60 | for api in self.config["protocol"]:
61 | url = url_pre + api
62 | org_api_data = self.config["protocol"][f"{api}"]
63 | # 在开头插入token,如果自己系统token不是这么插入的则根据自己系统进行修改
64 | org_api_data = org_api_data.replace("""clientType="WEB">""",f"""clientType="WEB">{self.token}""")
65 | # 循环模糊测试类型
66 | for payload_type,payload_file in self.fuzz_payload_dict.items():
67 | logging.info(f"start to test {payload_type}")
68 | # 找出所有fuzz_var()
69 | fuzz_vars = re.findall(regexp, org_api_data)
70 | # 使用set去重使用list变回列表
71 |
72 | fuzz_vars = list(set(fuzz_vars))
73 | # 遍历所有fuzz_var()
74 | for fuzz_var in fuzz_vars:
75 |
76 | # 对该变量循环具体测试类型的载荷
77 | for fuzz_payload in open(f"../payloads/{payload_file}","r",encoding="utf-8"):
78 | fuzz_payload = fuzz_payload.strip("\n")
79 | # 排除空载荷情况,因为payload文件中为了方例使用了很多空行,不排除的话空载荷会反复多次进行测试
80 | if fuzz_payload.strip() != "":
81 | # 如果是缓冲区溢出,由于我这里payload使用"A"*10等形式,所以需要先使用eval动态执行转成最终的字符串
82 | if payload_type == "overflow":
83 | fuzz_payload = eval(fuzz_payload)
84 | # 为了后边的空载荷不再把发送代码写一遍,所以这里独立出了一个参数复杂的发送函数,但自己一般不用修改所以还行吧
85 | self.send_payload(url, org_api_data, regexp, fuzz_payload,api,payload_type,fuzz_var)
86 | # 最后单独对空载荷进行测试
87 | fuzz_payload = ""
88 | self.send_payload(url,org_api_data, regexp, fuzz_payload,api,payload_type,fuzz_var)
89 |
90 | # 最终的发送函数
91 | def send_payload(self,url,org_api_data,regexp,fuzz_payload,api,payload_type,fuzz_var):
92 | # 将前遍历到的fuzz_var()修改成fuzz_var\(\),因为括号在正则中是特殊字符需要先转义才能是本身
93 | fuzz_var_fix = fuzz_var.replace("(", "\(").replace(")", "\)")
94 | # 获取当前遍历项的匹配个数
95 | count = re.findall(fuzz_var_fix,org_api_data).__len__()
96 | # 获取当前遍历项的原始值
97 | start_pos = re.search("\(", fuzz_var).end()
98 | end_pos = re.search("\)", fuzz_var).start()
99 | org_value = fuzz_var[start_pos:end_pos]
100 | # 如果匹配处不只一处
101 | for i in range(count):
102 | # 将目标位置前的匹配项都还原成原始值
103 | if i != 0:
104 | tt = re.sub(fuzz_var_fix, org_value, org_api_data,i)
105 | # 将目标位置替换成payload,最后的1表示只替换一次,这是关键
106 | tt = re.sub(fuzz_var_fix, fuzz_payload, tt,1)
107 | else:
108 | try:
109 | # 如果目标项是第一个匹配,那么tt来自于org_api_data
110 | tt = re.sub(fuzz_var_fix, fuzz_payload, org_api_data, 1)
111 | except:
112 | logging.warning(f"exception occur-{api}-{payload_type}-{fuzz_var}-{fuzz_payload}")
113 | continue
114 | # 对于剩下的所有fuzz_var\(\),进行直接删除处理
115 | tt = re.sub(regexp, self.delete_var_sign, tt)
116 | logging.info(f"{api}-{payload_type}-{fuzz_var}-{fuzz_payload}")
117 | # 检测是否使用代理
118 | if self.config["server_info"]["use_proxy"] == "True":
119 | response = requests.post(url=url, headers=self.fuzz_headers, data=tt.encode('utf-8'), verify=False, proxies=self.proxies)
120 | else:
121 | response = requests.post(url=url, headers=self.fuzz_headers, data=tt.encode('utf-8'), verify=False)
122 | logging.info(f"{api}-{payload_type}-{fuzz_var}-{fuzz_payload}-{response.status_code}")
123 |
124 | # 用于删除fuzz_var\(\),这里的\是正则中的转义
125 | def delete_var_sign(self,matched):
126 | value_org = matched.group()
127 | start_pos = re.search("\(",value_org).end()
128 | end_pos = re.search("\)",value_org).start()
129 | value = value_org[start_pos:end_pos]
130 | return value
131 |
132 |
133 | if __name__ == "__main__":
134 | fuzzer = Fuzzer()
135 | fuzzer.exec_fuzz()
136 |
--------------------------------------------------------------------------------
/fuzzers/geckodriver.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PrettyUp/Fuzzer/9a40d4634c08a73d39837ec684c717b398d042c5/fuzzers/geckodriver.exe
--------------------------------------------------------------------------------
/fuzzers/geckodriver.log:
--------------------------------------------------------------------------------
1 | 1559526810576 mozrunner::runner INFO Running command: "d:\\Mozilla Firefox\\firefox.exe" "-marionette" "--headless" "--disable-gpu" "-foreground" "-no-remote" "-profile" "C:\\Users\\ls\\AppData\\Local\\Temp\\rust_mozprofile.MztK3mhDDrk5"
2 | *** You are running in headless mode.
3 | 1559526815908 Marionette INFO Listening on port 30252
4 | 1559526816220 Marionette WARN TLS certificate errors will be ignored for this session
5 | [Parent 12436, Gecko_IOThread] WARNING: pipe error: 109: file z:/build/build/src/ipc/chromium/src/chrome/common/ipc_channel_win.cc, line 346
6 | [Child 6748, Chrome_ChildThread] WARNING: pipe error: 109: file z:/build/build/src/ipc/chromium/src/chrome/common/ipc_channel_win.cc, line 346
7 | [Parent 12436, Gecko_IOThread] WARNING: pipe error: 109: file z:/build/build/src/ipc/chromium/src/chrome/common/ipc_channel_win.cc, line 346
8 | [Child 548, Chrome_ChildThread] WARNING: pipe error: 109: file z:/build/build/src/ipc/chromium/src/chrome/common/ipc_channel_win.cc, line 346
9 | [Child 548, Chrome_ChildThread] WARNING: pipe error: 109: file z:/build/build/src/ipc/chromium/src/chrome/common/ipc_channel_win.cc, line 346
10 | [Child 9904, Chrome_ChildThread] WARNING: pipe error: 109: file z:/build/build/src/ipc/chromium/src/chrome/common/ipc_channel_win.cc, line 346
11 | [Child 9904, Chrome_ChildThread] WARNING: pipe error: 109: file z:/build/build/src/ipc/chromium/src/chrome/common/ipc_channel_win.cc, line 346
12 | *** UTM:SVC TimerManager:registerTimer called after profile-before-change notification. Ignoring timer registration for id: telemetry_modules_ping
13 | 1559527049046 mozrunner::runner INFO Running command: "d:\\Mozilla Firefox\\firefox.exe" "-marionette" "--headless" "--disable-gpu" "-foreground" "-no-remote" "-profile" "C:\\Users\\ls\\AppData\\Local\\Temp\\rust_mozprofile.PYXo9qS7gQhe"
14 | *** You are running in headless mode.
15 | 1559527052660 Marionette INFO Listening on port 30392
16 | 1559527052995 Marionette WARN TLS certificate errors will be ignored for this session
17 | [Child 13032, Chrome_ChildThread] WARNING: pipe error: 109: file z:/build/build/src/ipc/chromium/src/chrome/common/ipc_channel_win.cc, line 346
18 | [Child 13872, Chrome_ChildThread] WARNING: pipe error: 109: file z:/build/build/src/ipc/chromium/src/chrome/common/ipc_channel_win.cc, line 346
19 | *** UTM:SVC TimerManager:registerTimer called after profile-before-change notification. Ignoring timer registration for id: telemetry_modules_ping
20 | 1559527207435 mozrunner::runner INFO Running command: "d:\\Mozilla Firefox\\firefox.exe" "-marionette" "--headless" "--disable-gpu" "-foreground" "-no-remote" "-profile" "C:\\Users\\ls\\AppData\\Local\\Temp\\rust_mozprofile.BLu99lLtZajc"
21 | *** You are running in headless mode.
22 | 1559527211166 Marionette INFO Listening on port 30530
23 | 1559527211302 Marionette WARN TLS certificate errors will be ignored for this session
24 | [Parent 14048, Gecko_IOThread] WARNING: pipe error: 109: file z:/build/build/src/ipc/chromium/src/chrome/common/ipc_channel_win.cc, line 346
25 | [Child 14180, Chrome_ChildThread] WARNING: pipe error: 109: file z:/build/build/src/ipc/chromium/src/chrome/common/ipc_channel_win.cc, line 346
26 | [Child 13532, Chrome_ChildThread] WARNING: pipe error: 109: file z:/build/build/src/ipc/chromium/src/chrome/common/ipc_channel_win.cc, line 346
27 | [Parent 14048, Gecko_IOThread] WARNING: pipe error: 109: file z:/build/build/src/ipc/chromium/src/chrome/common/ipc_channel_win.cc, line 346
28 | *** UTM:SVC TimerManager:registerTimer called after profile-before-change notification. Ignoring timer registration for id: telemetry_modules_ping
29 | 1559530581921 mozrunner::runner INFO Running command: "d:\\Mozilla Firefox\\firefox.exe" "-marionette" "--headless" "--disable-gpu" "-foreground" "-no-remote" "-profile" "C:\\Users\\ls\\AppData\\Local\\Temp\\rust_mozprofile.DaXkfpf6gsXV"
30 | *** You are running in headless mode.
31 | 1559530585691 Marionette INFO Listening on port 31189
32 | 1559530585835 Marionette WARN TLS certificate errors will be ignored for this session
33 | [Parent 12504, Gecko_IOThread] WARNING: pipe error: 109: file z:/build/build/src/ipc/chromium/src/chrome/common/ipc_channel_win.cc, line 346
34 | [Parent 12504, Gecko_IOThread] WARNING: file z:/build/build/src/ipc/chromium/src/base/process_util_win.cc, line 188
35 | [Child 9804, Chrome_ChildThread] WARNING: pipe error: 109: file z:/build/build/src/ipc/chromium/src/chrome/common/ipc_channel_win.cc, line 346
36 | [Parent 12504, Gecko_IOThread] WARNING: pipe error: 109: file z:/build/build/src/ipc/chromium/src/chrome/common/ipc_channel_win.cc, line 346
37 | [Child 14024, Chrome_ChildThread] WARNING: pipe error: 109: file z:/build/build/src/ipc/chromium/src/chrome/common/ipc_channel_win.cc, line 346
38 | *** UTM:SVC TimerManager:registerTimer called after profile-before-change notification. Ignoring timer registration for id: telemetry_modules_ping
39 | 1559531545335 mozrunner::runner INFO Running command: "d:\\Mozilla Firefox\\firefox.exe" "-marionette" "--headless" "--disable-gpu" "-foreground" "-no-remote" "-profile" "C:\\Users\\ls\\AppData\\Local\\Temp\\rust_mozprofile.6K8lDrTAF6a0"
40 | *** You are running in headless mode.
41 | 1559531549501 Marionette INFO Listening on port 31498
42 | 1559531549731 Marionette WARN TLS certificate errors will be ignored for this session
43 | JavaScript error: https://10.10.6.93/js/lib/require.js, line 168: Error: Script error for "PtzCtrl", needed by: app/Live/live
44 | http://requirejs.org/docs/errors.html#scripterror
45 | JavaScript error: https://10.10.6.93/js/lib/require.js, line 168: Error: Script error for "app/ChlCfg/editChlGroup", needed by: app/Live/live
46 | http://requirejs.org/docs/errors.html#scripterror
47 | JavaScript error: https://10.10.6.93/js/lib/require.js, line 168: Error: Script error for "grid", needed by: app/Live/live
48 | http://requirejs.org/docs/errors.html#scripterror
49 | JavaScript error: https://10.10.6.93/js/lib/require.js, line 168: Error: Script error for "app/ChlCfg/addPreset", needed by: app/Live/live
50 | http://requirejs.org/docs/errors.html#scripterror
51 | JavaScript error: https://10.10.6.93/js/lib/require.js, line 168: Error: Script error for "slider", needed by: app/Live/live
52 | http://requirejs.org/docs/errors.html#scripterror
53 |
54 | ###!!! [Child][MessageChannel] Error: (msgtype=0x48000E,name=PHttpChannel::Msg_DeletingChannel) Channel closing: too late to send/recv, messages will be lost
55 |
56 | JavaScript error: https://10.10.6.93/js/lib/require.js, line 168: Error: Script error for "listbox", needed by: app/Live/live
57 | http://requirejs.org/docs/errors.html#scripterror
58 |
59 | ###!!! [Child][MessageChannel] Error: (msgtype=0x48000E,name=PHttpChannel::Msg_DeletingChannel) Channel closing: too late to send/recv, messages will be lost
60 |
61 | JavaScript error: https://10.10.6.93/js/lib/require.js, line 168: Error: Script error for "app/ChlCfg/addChlGroup", needed by: app/Live/live
62 | http://requirejs.org/docs/errors.html#scripterror
63 |
64 | ###!!! [Child][MessageChannel] Error: (msgtype=0x48000E,name=PHttpChannel::Msg_DeletingChannel) Channel closing: too late to send/recv, messages will be lost
65 |
66 | JavaScript error: https://10.10.6.93/js/lib/require.js, line 168: Error: Script error for "spliter", needed by: app/Live/live
67 | http://requirejs.org/docs/errors.html#scripterror
68 |
69 | ###!!! [Child][MessageChannel] Error: (msgtype=0x48000E,name=PHttpChannel::Msg_DeletingChannel) Channel closing: too late to send/recv, messages will be lost
70 |
71 | JavaScript error: https://10.10.6.93/js/lib/require.js, line 168: Error: Script error for "tab", needed by: app/Live/live
72 | http://requirejs.org/docs/errors.html#scripterror
73 |
74 | ###!!! [Child][MessageChannel] Error: (msgtype=0x48000E,name=PHttpChannel::Msg_DeletingChannel) Channel closing: too late to send/recv, messages will be lost
75 |
76 |
77 | ###!!! [Child][MessageChannel] Error: (msgtype=0x2C00AF,name=PContent::Msg_ScriptError) Channel closing: too late to send/recv, messages will be lost
78 |
79 |
80 | ###!!! [Child][MessageChannel] Error: (msgtype=0x2C00AF,name=PContent::Msg_ScriptError) Channel closing: too late to send/recv, messages will be lost
81 |
82 |
83 | ###!!! [Child][MessageChannel] Error: (msgtype=0x2C00AF,name=PContent::Msg_ScriptError) Channel closing: too late to send/recv, messages will be lost
84 |
85 |
86 | ###!!! [Child][MessageChannel] Error: (msgtype=0x2C00AF,name=PContent::Msg_ScriptError) Channel closing: too late to send/recv, messages will be lost
87 |
88 |
89 | ###!!! [Child][RunMessage] Error: Channel closing: too late to send/recv, messages will be lost
90 |
91 |
92 | ###!!! [Child][MessageChannel] Error: (msgtype=0x2C00AF,name=PContent::Msg_ScriptError) Channel closing: too late to send/recv, messages will be lost
93 |
94 |
95 | ###!!! [Child][RunMessage] Error: Channel closing: too late to send/recv, messages will be lost
96 |
97 |
98 | ###!!! [Child][MessageChannel] Error: (msgtype=0x2C00AF,name=PContent::Msg_ScriptError) Channel closing: too late to send/recv, messages will be lost
99 |
100 |
101 | ###!!! [Child][MessageChannel] Error: (msgtype=0x2C00AF,name=PContent::Msg_ScriptError) Channel closing: too late to send/recv, messages will be lost
102 |
103 |
104 | ###!!! [Child][MessageChannel] Error: (msgtype=0x2C00AF,name=PContent::Msg_ScriptError) Channel closing: too late to send/recv, messages will be lost
105 |
106 |
107 | ###!!! [Child][MessageChannel] Error: (msgtype=0x2C00AF,name=PContent::Msg_ScriptError) Channel closing: too late to send/recv, messages will be lost
108 |
109 | [Parent 12436, Gecko_IOThread] WARNING: pipe error: 109: file z:/build/build/src/ipc/chromium/src/chrome/common/ipc_channel_win.cc, line 346
110 | [Child 14184, Chrome_ChildThread] WARNING: pipe error: 109: file z:/build/build/src/ipc/chromium/src/chrome/common/ipc_channel_win.cc, line 346
111 | *** UTM:SVC TimerManager:registerTimer called after profile-before-change notification. Ignoring timer registration for id: telemetry_modules_ping
112 | 1559531605356 mozrunner::runner INFO Running command: "d:\\Mozilla Firefox\\firefox.exe" "-marionette" "--headless" "--disable-gpu" "-foreground" "-no-remote" "-profile" "C:\\Users\\ls\\AppData\\Local\\Temp\\rust_mozprofile.wCANx5AZX3C8"
113 | *** You are running in headless mode.
114 | 1559531609721 Marionette INFO Listening on port 31612
115 | 1559531609850 Marionette WARN TLS certificate errors will be ignored for this session
116 |
117 | ###!!! [Parent][MessageChannel] Error: (msgtype=0x1000B,name=PAPZ::Msg_Destroy) Channel error: cannot send/recv
118 |
119 |
120 | ###!!! [Parent][MessageChannel] Error: (msgtype=0x15008C,name=PBrowser::Msg_UpdateNativeWindowHandle) Channel error: cannot send/recv
121 |
122 |
123 | ###!!! [Parent][MessageChannel] Error: (msgtype=0x15007F,name=PBrowser::Msg_Destroy) Channel error: cannot send/recv
124 |
125 | A content process crashed and MOZ_CRASHREPORTER_SHUTDOWN is set, shutting down
126 |
127 | ###!!! [Parent][MessageChannel] Error: (msgtype=0x15008C,name=PBrowser::Msg_UpdateNativeWindowHandle) Channel error: cannot send/recv
128 |
129 |
130 | ###!!! [Parent][MessageChannel] Error: (msgtype=0x15007F,name=PBrowser::Msg_Destroy) Channel error: cannot send/recv
131 |
132 | 1559531630065 mozrunner::runner INFO Running command: "d:\\Mozilla Firefox\\firefox.exe" "-marionette" "--headless" "--disable-gpu" "-foreground" "-no-remote" "-profile" "C:\\Users\\ls\\AppData\\Local\\Temp\\rust_mozprofile.UwRY4McjclZ4"
133 | *** You are running in headless mode.
134 | 1559531634067 Marionette INFO Listening on port 31716
135 | 1559531634494 Marionette WARN TLS certificate errors will be ignored for this session
136 | [Parent 13816, Gecko_IOThread] WARNING: pipe error: 109: file z:/build/build/src/ipc/chromium/src/chrome/common/ipc_channel_win.cc, line 346
137 | [Parent 13816, Gecko_IOThread] WARNING: pipe error: 109: file z:/build/build/src/ipc/chromium/src/chrome/common/ipc_channel_win.cc, line 346
138 | [Child 9416, Chrome_ChildThread] WARNING: pipe error: 109: file z:/build/build/src/ipc/chromium/src/chrome/common/ipc_channel_win.cc, line 346
139 | *** UTM:SVC TimerManager:registerTimer called after profile-before-change notification. Ignoring timer registration for id: telemetry_modules_ping
140 | 1559531753215 mozrunner::runner INFO Running command: "d:\\Mozilla Firefox\\firefox.exe" "-marionette" "--headless" "--disable-gpu" "-foreground" "-no-remote" "-profile" "C:\\Users\\ls\\AppData\\Local\\Temp\\rust_mozprofile.xkhOVJsUAGBt"
141 | *** You are running in headless mode.
142 | 1559531757471 Marionette INFO Listening on port 32058
143 | 1559531757622 Marionette WARN TLS certificate errors will be ignored for this session
144 | [Child 13112, Chrome_ChildThread] WARNING: pipe error: 109: file z:/build/build/src/ipc/chromium/src/chrome/common/ipc_channel_win.cc, line 346
145 | [Child 13112, Chrome_ChildThread] WARNING: pipe error: 109: file z:/build/build/src/ipc/chromium/src/chrome/common/ipc_channel_win.cc, line 346
146 | [Child 13364, Chrome_ChildThread] WARNING: pipe error: 109: file z:/build/build/src/ipc/chromium/src/chrome/common/ipc_channel_win.cc, line 346
147 | [Parent 10808, Gecko_IOThread] WARNING: pipe error: 109: file z:/build/build/src/ipc/chromium/src/chrome/common/ipc_channel_win.cc, line 346
148 | [Child 12864, Chrome_ChildThread] WARNING: pipe error: 109: file z:/build/build/src/ipc/chromium/src/chrome/common/ipc_channel_win.cc, line 346
149 | *** UTM:SVC TimerManager:registerTimer called after profile-before-change notification. Ignoring timer registration for id: telemetry_modules_ping
150 | 1559532007854 mozrunner::runner INFO Running command: "d:\\Mozilla Firefox\\firefox.exe" "-marionette" "--headless" "--disable-gpu" "-foreground" "-no-remote" "-profile" "C:\\Users\\ls\\AppData\\Local\\Temp\\rust_mozprofile.5k9wHAGp9Mim"
151 | *** You are running in headless mode.
152 | 1559532011835 Marionette INFO Listening on port 34226
153 | 1559532012341 Marionette WARN TLS certificate errors will be ignored for this session
154 | [Parent 11076, Gecko_IOThread] WARNING: pipe error: 109: file z:/build/build/src/ipc/chromium/src/chrome/common/ipc_channel_win.cc, line 346
155 | [Child 12436, Chrome_ChildThread] WARNING: pipe error: 109: file z:/build/build/src/ipc/chromium/src/chrome/common/ipc_channel_win.cc, line 346
156 | [Child 12436, Chrome_ChildThread] WARNING: pipe error: 109: file z:/build/build/src/ipc/chromium/src/chrome/common/ipc_channel_win.cc, line 346
157 | [Parent 11076, Gecko_IOThread] WARNING: pipe error: 109: file z:/build/build/src/ipc/chromium/src/chrome/common/ipc_channel_win.cc, line 346
158 | [Child 14104, Chrome_ChildThread] WARNING: pipe error: 109: file z:/build/build/src/ipc/chromium/src/chrome/common/ipc_channel_win.cc, line 346
159 | [Child 14104, Chrome_ChildThread] WARNING: pipe error: 109: file z:/build/build/src/ipc/chromium/src/chrome/common/ipc_channel_win.cc, line 346
160 | *** UTM:SVC TimerManager:registerTimer called after profile-before-change notification. Ignoring timer registration for id: telemetry_modules_ping
161 |
--------------------------------------------------------------------------------
/fuzzers/rtsp_fuzzer.py:
--------------------------------------------------------------------------------
1 | import logging
2 | import re
3 | import socket
4 | import hashlib
5 | import base64
6 | import time
7 | from common.logger import LogConfig
8 |
9 | config_dict = {
10 | 'server_username': 'admin', # RTSP用户名
11 | 'server_password': '123456', # RTSP用户名对应密码
12 | 'server_ip': '10.10.6.93', # RTSP服务器IP地址
13 | 'server_port': 554, # RTSP服务器使用端口
14 | 'server_path': '/chIP=1/', # URL中端口之后的部份,测试发现不同服务器对这部份接受的值是不一样的,也就是说自己使用时很可能得自己修改这部份的值
15 | 'cseq': 2, # RTSP使用的请求起始序列码,不需要改动
16 | 'user_agent': 'LibVLC/3.0.2 (LIVE555 Streaming Media v2016.11.28)', # 自定义请求头部
17 | 'buffer_len': 1024, # 用于接收服务器返回数据的缓冲区的大小
18 | 'auth_method': 'Digest', # RTSP使用的认证方法,Basic/Digest
19 | # OPTIONS/FIRST_DESCRIBE/SECOND_DESCRIBE/FIRST_SETUP/SECOND_SETUP/PLAY/GET_PARAMETER/TEARDOWN/ALL
20 | # 如果不是以上任何一个值那么就会一路正常请求
21 | 'fuzz_step': 'SECOND_DESCRIBE',
22 | 'fuzz_extern_header': False, # 是否对每个请求模糊测试额外的头部
23 | # 'header_normal_modify_allow': False, # 是否允许拼接其他协议规定的请求头的总开关,请些请求头的值为正常值(大多是RFC给出的示例)
24 | # 'header_overload_modify_allow': False, # 是否允许拼接其他协议规定的请求头的总开关,请些请求头的值为超长字符串
25 | # 'options_header_modify': True, # OPTIONS请求中,是否允许拼接其他协议规定的请求头的开关
26 | # 'describe_header_modify': True, # 第一次DESCRIBE请求中,是否允许拼接其他协议规定的请求头的开关
27 | # 'describe_auth_header_modify': True, # 第二次DESCRIBE请求中,是否允许拼接其他协议规定的请求头的开关
28 | # 'setup_header_modify': True, # 第一次SETUP请求中,是否允许拼接其他协议规定的请求头的开关
29 | # 'setup_session_header_modify': True, # 第二次SETUP请求中,是否允许拼接其他协议规定的请求头的开关
30 | # 'play_header_modify': True, # PLAY请求中,是否允许拼接其他协议规定的请求头的开关
31 | # 'get_parameter_header_modify': True, # GET PARAMETER请求中,是否允许拼接其他协议规定的请求头的开关
32 | # 'teardown_header_modify': True # TEARDOWN请求中,是否允许拼接其他协议规定的请求头的开关
33 | 'log_type': 'console',
34 | 'log_file_prefix': 'rtsp'
35 | }
36 |
37 |
38 | class RtspFuzzer():
39 | def __init__(self):
40 | global config_dict
41 | # self.socket_send = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
42 | # self.socket_send.settimeout(5)
43 | # self.socket_send.connect((config_dict['server_ip'], config_dict['server_port']))
44 | # self.config_dict = config_dict
45 | self.socket_send = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
46 | self.socket_send.settimeout(5)
47 | self.socket_send.connect((config_dict['server_ip'], config_dict['server_port']))
48 | log_type = config_dict["log_type"]
49 | log_file_prefix = config_dict["log_file_prefix"]
50 | # LogConfig(log_type="file",test_protocol="tvt")
51 | LogConfig(log_type=log_type, log_file_prefix=log_file_prefix)
52 | self.regexp = "fuzzer_var\([^\)]*\)"
53 | self.fuzz_payload_dict = {
54 | "overflow": "overflow.txt",
55 | "format_string": "format_string.txt",
56 | "random_num": "random_num.txt",
57 | "special_char": "special_char.txt",
58 | "unicode": "unicode.txt",
59 | }
60 | self.uri = f"rtsp://{config_dict['server_ip']}:{config_dict['server_port']}{config_dict['server_path']}"
61 | pass
62 |
63 | # 用于Digest认证方式时生成response的值
64 | def gen_digest_response_value(self, uri, method, realm, nonce):
65 | HA1 = hashlib.md5((f"{config_dict['server_username']}:{realm }:{config_dict['server_password']}").encode()).hexdigest()
66 | HA2 = hashlib.md5((f"{method}:{uri}").encode()).hexdigest()
67 | response_value = hashlib.md5((f"{HA1}:{nonce}:{HA2}").encode()).hexdigest()
68 | return response_value
69 |
70 | # 生成options请求头部
71 | def gen_options_header(self):
72 | global config_dict
73 | str_options_header = (f"""OPTIONS fuzzer_var(rtsp):fuzzer_var(//)fuzzer_var({config_dict['server_ip']})fuzzer_var(:)fuzzer_var({config_dict['server_port']}){config_dict['server_path']}fuzzer_var() fuzzer_var(RTSP)/fuzzer_var(1.0)\r\n"""
74 | f"""CSeq: fuzzer_var({config_dict['cseq']})\r\n"""
75 | f"""User-Agent: fuzzer_var({config_dict['user_agent']})\r\n"""
76 | f"""\r\n"""
77 | )
78 | return str_options_header
79 |
80 | # 生成first describe请求头部
81 | def gen_first_describe_header(self):
82 | global config_dict
83 | str_describe_header = (f"""DESCRIBE fuzzer_var(rtsp):fuzzer_var(//)fuzzer_var({config_dict['server_ip']})fuzzer_var(:)fuzzer_var({config_dict['server_port']}){config_dict['server_path']}fuzzer_var() fuzzer_var(RTSP)/fuzzer_var(1.0)\r\n"""
84 | f"""CSeq: fuzzer_var({config_dict['cseq'] + 1})\r\n"""
85 | f"""User-Agent: fuzzer_var({config_dict['user_agent']})\r\n"""
86 | f"""Accept: fuzzer_var(application/sdp)\r\n"""
87 | f"""\r\n"""
88 | )
89 | return str_describe_header
90 |
91 | # 生成second describe请求头部
92 | def gen_second_describe_header(self, realm, nonce):
93 | global config_dict
94 | method = 'DESCRIBE'
95 | str_describe_auth_header = (f"""{method} rtsp://{config_dict['server_ip']}:{config_dict['server_port']}{config_dict['server_path']} RTSP/1.0\r\n"""
96 | f"""CSeq: fuzzer_var({config_dict['cseq'] + 2})\r\n""")
97 | if config_dict['auth_method'] == 'Basic':
98 | auth_64 = base64.b64encode((f"{config_dict['server_username']}:{config_dict['server_password']}").encode("utf-8")).decode()
99 | str_describe_auth_header += f"""Authorization: fuzzer_var(Basic) fuzzer_var({auth_64})\r\n"""
100 | else:
101 | response_value = self.gen_digest_response_value(self.uri, method, realm, nonce)
102 | str_describe_auth_header += f"""Authorization: Digest username="{config_dict['server_username']}", realm="{realm}", nonce="{nonce}", uri="{self.uri}", response="{response_value}"\r\n"""
103 | str_describe_auth_header += (f"""User-Agent: fuzzer_var({config_dict['user_agent']})\r\n"""
104 | f"""Accept: fuzzer_var(application/sdp)\r\n"""
105 | f"""\r\n"""
106 | )
107 | return str_describe_auth_header
108 |
109 | # 生成first setup请求头部
110 | def gen_first_setup_header(self,realm, nonce):
111 | global config_dict
112 | method = 'SETUP'
113 | str_setup_header = (f"""{method} fuzzer_var(rtsp):fuzzer_var(//)fuzzer_var({config_dict['server_ip']}):fuzzer_var({config_dict['server_port']}){config_dict['server_path']}trackID=fuzzer_var(0) trackID=fuzzer_var(0) fuzzer_var(RTSP)/fuzzer_var(1.0)\r\n"""
114 | f"""CSeq: {config_dict['cseq'] + 3}\r\n""")
115 | if config_dict['auth_method'] == 'Basic':
116 | auth_64 = base64.b64encode((f"{config_dict['server_username']}:{config_dict['server_password']}").encode("utf-8")).decode()
117 | str_setup_header += f"""Authorization: Basic fuzzer_var({auth_64})\r\n"""
118 | else:
119 | response_value = self.gen_digest_response_value(self.uri, method, realm, nonce)
120 | str_setup_header += f"""Authorization: Digest username="fuzzer_var({config_dict['server_username']})", realm="fuzzer_var({realm})", nonce="fuzzer_var({nonce})", uri="fuzzer_var({self.uri})", response="fuzzer_var({response_value})"\r\n"""
121 | str_setup_header += (f"""User-Agent: fuzzer_var({config_dict['user_agent']})\r\n"""
122 | f"""Transport: fuzzer_var(RTP/AVP);fuzzer_var(unicast);client_port=fuzzer_var(50166)-50167\r\n"""
123 | f"""\r\n"""
124 | )
125 | return str_setup_header
126 |
127 | # 生成second setup请求头部
128 | def gen_second_setup_header(self, realm, nonce, session):
129 | global config_dict
130 | method = 'SETUP'
131 | str_setup_session_header = (f"""{method} fuzzer_var(rtsp)://fuzzer_var({config_dict['server_ip']}):fuzzer_var({config_dict['server_port']}){config_dict['server_path']}trackID=fuzzer_var(1) trackID=fuzzer_var(1) fuzzer_var(RTSP)/fuzzer_var(1.0)\r\n"""
132 | f"""CSeq: fuzzer_var({config_dict['cseq'] + 4})\r\n""")
133 | if config_dict['auth_method'] == 'Basic':
134 | auth_64 = base64.b64encode((f"{config_dict['server_username']}:{config_dict['server_password']}").encode("utf-8")).decode()
135 | str_setup_session_header += f"Authorization: Basic fuzzer_var({auth_64})\r\n"
136 | else:
137 | response_value = self.gen_digest_response_value(self.uri, method, realm, nonce)
138 | str_setup_session_header += f"""Authorization: Digest username="fuzzer_var({config_dict['server_username']})", realm="fuzzer_var({realm})", nonce="fuzzer_var({nonce})", uri="fuzzer_var({self.uri})", response="fuzzer_var({response_value})"\r\n"""
139 | str_setup_session_header += (f"""User-Agent: fuzzer_var({config_dict['user_agent']})\r\n"""
140 | f"""Transport: fuzzer_var(RTP/AVP);unicast;client_port=fuzzer_var(50168)-fuzzer_var(50169)\r\n"""
141 | f"""Session: fuzzer_var({session})\r\n"""
142 | f"""\r\n"""
143 | )
144 | return str_setup_session_header
145 |
146 | # 生成play请求头部
147 | def gen_play_header(self, realm, nonce, session):
148 | global config_dict
149 | method = 'PLAY'
150 | str_play_header = (f"""{method} fuzzer_var(rtsp)://fuzzer_var({config_dict['server_ip']}):fuzzer_var({config_dict['server_port']}){config_dict['server_path']} fuzzer_var(RTSP)/fuzzer_var(1.0)\r\n"""
151 | f"""CSeq: fuzzer_var({config_dict['cseq'] + 5})\r\n""")
152 | if config_dict['auth_method'] == 'Basic':
153 | auth_64 = base64.b64encode((f"{config_dict['server_username']}:{config_dict['server_password']}").encode("utf-8")).decode()
154 | str_play_header += f"Authorization: Basic fuzzer_var({auth_64})\r\n"
155 | else:
156 | response_value = self.gen_digest_response_value(self.uri, method, realm, nonce)
157 | str_play_header += f"""Authorization: fuzzer_var(Digest) username="fuzzer_var({config_dict['server_username']})", realm="fuzzer_var({realm})", nonce="fuzzer_var({nonce})", uri="fuzzer_var({self.uri})", response="fuzzer_var({response_value})"\r\n"""
158 | str_play_header += (f"""User-Agent: fuzzer_var({config_dict['user_agent']})\r\n"""
159 | f"""Session: fuzzer_var({session})\r\n"""
160 | f"""Range: npt=fuzzer_var(0.000-)\r\n"""
161 | f"""\r\n"""
162 | )
163 | return str_play_header
164 |
165 | # 生成GET_PARAMETER请求头部
166 | def gen_get_parameter_header(self, realm, nonce, session):
167 | global config_dict
168 | method = 'GET_PARAMETER'
169 | str_get_parameter_header = (f"""{method} fuzzer_var(rtsp)://fuzzer_var({config_dict['server_ip']}):fuzzer_var({config_dict['server_port']}){config_dict['server_path']} fuzzer_var(RTSP)/fuzzer_var(1.0)\r\n"""
170 | f"""CSeq: fuzzer_var({config_dict['cseq'] + 6})\r\n""")
171 | if config_dict['auth_method'] == 'Basic':
172 | auth_64 = base64.b64encode((f"{config_dict['server_username']}:{config_dict['server_password']}").encode("utf-8")).decode()
173 | str_get_parameter_header += f"Authorization: Basic fuzzer_var({auth_64})\r\n"
174 | else:
175 | response_value = self.gen_digest_response_value(self.uri, method, realm, nonce)
176 | str_get_parameter_header += f"""Authorization: Digest username="fuzzer_var({config_dict['server_username']})", realm="fuzzer_var({realm})", nonce="fuzzer_var({nonce})", uri="fuzzer_var({self.uri})", response="fuzzer_var({response_value})"\r\n"""
177 | str_get_parameter_header += (f"""User-Agent: fuzzer_var({config_dict['user_agent']})\r\n"""
178 | f"""Session: fuzzer_var({session})\r\n"""
179 | f"""\r\n"""
180 | )
181 | return str_get_parameter_header
182 |
183 | # 生成teardown请求头部
184 | def gen_teardown_header(self, realm, nonce, session):
185 | global config_dict
186 | method = 'TEARDOWN'
187 | str_teardown_header = (f"""{method} fuzzer_var(rtsp)://fuzzer_var({config_dict['server_ip']}):fuzzer_var({config_dict['server_port']}){config_dict['server_path']} fuzzer_var(RTSP)/fuzzer_var(1.0)\r\n"""
188 | f"""CSeq: fuzzer_var({config_dict['cseq'] + 11})\r\n""")
189 | if config_dict['auth_method'] == 'Basic':
190 | auth_64 = base64.b64encode((f"{config_dict['server_username']}:{config_dict['server_password']}").encode("utf-8")).decode()
191 | str_teardown_header += f"Authorization: Basic fuzzer_var({auth_64})\r\n"
192 | else:
193 | response_value = self.gen_digest_response_value(self.uri, method, realm, nonce)
194 | str_teardown_header += f"""Authorization: Digest username="fuzzer_var({config_dict['server_username']})", realm="fuzzer_var({realm})", nonce="fuzzer_var({nonce})", uri="fuzzer_var({self.uri})", response="fuzzer_var({response_value})"\r\n"""
195 | str_teardown_header += (f"""User-Agent: fuzzer_var({config_dict['user_agent']})\r\n"""
196 | f"""Session: fuzzer_var({session})\r\n"""
197 | f"""\r\n"""
198 | )
199 | return str_teardown_header
200 |
201 | # 拼接rtsp协议的其他请求头,以测试程序对这些请求头部的处理是否有问题;这个方法与add_overload_header_according_to_protocol是互斥的
202 | def add_extern_protocol(self, str_header):
203 | str_header = str_header[0:len(str_header) - 2]
204 | str_header += ('Accept: fuzz_var(application/rtsl), fuzz_var(application/sdp);level=fuzz_var(-2)'
205 | 'Accept-Encoding: fuzz_var(gzip);q=fuzz_var(1.0), identity; q=fuzz_var(0.5), fuzz_var(*);q=fuzz_var(0)\r\n'
206 | 'Accept-Language: fuzz_var(da), en-gb;q=fuzz_var(0.8), en;q=fuzz_var(0.7)\r\n'
207 | 'Bandwidth: fuzz_var(4000) \r\n'
208 | 'Blocksize: fuzz_var(4000) \r\n'
209 | 'Cache-Control: fuzz_var(no-cache);fuzz_var(max-stale) \r\n'
210 | 'Conference: fuzz_var(199702170042.SAA08642@obiwan.arl.wustl.edu%20Starr) \r\n'
211 | 'Connection: fuzz_var(close)\r\n'
212 | 'Content-Base: fuzz_var(gzip)\r\n'
213 | 'Content-Encoding: fuzz_var(gzip)\r\n'
214 | 'Content-Language: fuzz_var(mi),fuzz_var(en)\r\n'
215 | 'Content-Length: fuzz_var(2034953454546565) \r\n'
216 | 'Content-Location: fuzz_var(/etc/passwd)\r\n'
217 | 'Content-Type: fuzz_var(text/html); charset=fuzz_var(ISO-8859-4gg)\r\n'
218 | 'Date: fuzz_var(Tue, 15 Nov 1995x 08:12:31 GMT)\r\n'
219 | 'Expires: fuzz_var(Thu, 01 Dec 1994 16:00:00 GMT) \r\n'
220 | 'From: fuzz_var(webmaster@w3.org)\r\n'
221 | 'If-Modified-Since: fuzz_var(Sat, 29 Oct 1994 19:43:31 GMT) \r\n'
222 | 'Last-Modified: fuzz_var(Tue, 15 Nov 1994 12:45:26 GMT)\r\n'
223 | 'Proxy-Require: fuzz_var(funky-feature)\r\n'
224 | 'Referer: fuzz_var(http://www.w3.org/hypertext/DataSources/Overview.html)\r\n'
225 | 'Require: fuzz_var(funky-feature) \r\n'
226 | 'Scale: fuzz_var(-3.5) \r\n'
227 | 'Speed: fuzz_var(2.5) \r\n'
228 | 'Transport: fuzz_var(RTP/AVP);fuzz_var(unicast);fuzz_var(client_port=3456-3457);mode="fuzz_var(PLAY)" \r\n'
229 | 'Via: fuzz_var(1.0 fred), fuzz_var(1.1 nowhere.com) (Apache/1.1)\r\n'
230 | 'Range: npt=fuzz_var(2)\r\n'
231 | '\r\n'
232 | )
233 | return str_header
234 |
235 | def delete_var_sign(self,matched):
236 | value_org = matched.group()
237 | start_pos = re.search("\(",value_org).end()
238 | end_pos = re.search("\)",value_org).start()
239 | value = value_org[start_pos:end_pos]
240 | return value
241 |
242 | # 从服务器返回结果中提取出realm值
243 | def extract_realm_value(self,msg_recv):
244 | realm_pos = msg_recv.find('realm')
245 | realm_value_begin_pos = msg_recv.find('"', realm_pos) + 1
246 | realm_value_end_pos = msg_recv.find('"', realm_pos + 8)
247 | realm_value = msg_recv[realm_value_begin_pos:realm_value_end_pos]
248 | return realm_value
249 |
250 | # 从服务器返回结果中提取出nonce值
251 | def extract_nonce_value(self,msg_recv):
252 | nonce_pos = msg_recv.find('nonce')
253 | nonce_value_begin_pos = msg_recv.find('"', nonce_pos) + 1
254 | nonce_value_end_pos = msg_recv.find('"', nonce_pos + 8)
255 | nonce_value = msg_recv[nonce_value_begin_pos:nonce_value_end_pos]
256 | return nonce_value
257 |
258 | # 从服务器返回结果中提取出session值
259 | def extract_session_value(self,msg_recv):
260 | session_pos = msg_recv.find('Session')
261 | session_value_begin_pos = msg_recv.find(' ', session_pos + 8) + 1
262 | session_value_end_pos = msg_recv.find(';', session_pos + 8)
263 | session_value = msg_recv[session_value_begin_pos:session_value_end_pos]
264 | return session_value
265 |
266 | # fuzz的真正发包函数,被traverse_fuzz_var()调用
267 | def send_payload(self, org_step_header, fuzz_payload, step, payload_type, fuzz_var):
268 | # 将当前被遍历的fuzz_var()改为fuzz_var\(\)以和其他未遍历的fuzz_var()区分
269 | fuzz_var_fix = fuzz_var.replace("(", "\(").replace(")", "\)")
270 | count = re.findall(fuzz_var_fix, org_step_header).__len__()
271 | # 获取当前遍历项的原始值
272 | start_pos = re.search("\(", fuzz_var).end()
273 | end_pos = re.search("\)", fuzz_var).start()
274 | org_value = fuzz_var[start_pos:end_pos]
275 |
276 | # 先将当前遍历的fuzz_var()替换成测试载荷
277 | for i in range(count):
278 | # 将目标位置前的匹配项都还原成原始值
279 | if i != 0:
280 | tt = re.sub(fuzz_var_fix, org_value, org_step_header,i)
281 | # 将目标位置替换成payload,最后的1表示只替换一次,这是关键
282 | tt = re.sub(fuzz_var_fix, fuzz_payload, tt,1)
283 | else:
284 | try:
285 | # 如果目标项是第一个匹配,那么tt来自于org_step_header
286 | tt = re.sub(fuzz_var_fix, fuzz_payload, org_step_header, 1)
287 | except:
288 | logging.warning(f"exception occur-{step}-{payload_type}-{fuzz_var}-{fuzz_payload}")
289 | continue
290 | # 对于剩下的所有fuzz_var\(\),进行直接删除处理
291 | tt = re.sub(self.regexp, self.delete_var_sign, tt)
292 | logging.info(f"{step}-{payload_type}-{fuzz_var}-{fuzz_payload}")
293 |
294 | # try:
295 | # self.socket_send.send(tt.encode('utf-8'))
296 | # except:
297 | # logging.info(f"{step}-{payload_type}-{fuzz_var}-{fuzz_payload}-{tt}")
298 | # self.socket_send.connect((config_dict['server_ip'], config_dict['server_port']))
299 | # self.socket_send.send(tt.encode('utf-8'))
300 | # 需要暂停一下,因为发现一直发送时服务端会返回continues一直让客户端发送数据不返回,最后就直接fin把连接给关了
301 | # 但似乎也只能延缓一下?
302 | time.sleep(1)
303 | self.socket_send.send(tt.encode('utf-8'))
304 | try:
305 | msg_recv = self.socket_send.recv(config_dict['buffer_len']).decode()
306 | except:
307 | msg_recv = "recv time out"
308 | msg_recv_dict = msg_recv.split('\r\n')
309 | logging.info(f"{step}-{payload_type}-{fuzz_var}-{fuzz_payload}-{msg_recv_dict[0]}")
310 |
311 | # 遍历所有要模糊测试的变量
312 | def traverse_fuzz_var(self, step, org_step_header):
313 | # 如果要模糊测试额外头部,则给传过来的头部先加上
314 | if config_dict["fuzz_extern_header"]:
315 | org_step_header = self.add_extern_protocol(org_step_header)
316 | for payload_type, payload_file in self.fuzz_payload_dict.items():
317 | logging.info(f"start to test {payload_type}")
318 | # payload_file_obj = open(f"{payload_file}","a",encoding="utf-8")
319 | # org_step_header = self.gen_options_header()
320 | # 全部被fuzz_var()包含的位置
321 | fuzz_vars = re.findall(self.regexp, org_step_header)
322 | # 遍历所有被fuzz_var()包含的位置
323 | for fuzz_var in fuzz_vars:
324 |
325 | # 对该变量循环具体测试类型的载荷
326 | for fuzz_payload in open(f"../payloads/{payload_file}", "r", encoding="utf-8"):
327 | fuzz_payload = fuzz_payload.strip("\n")
328 | # 排除空载荷情况
329 | if fuzz_payload.strip() != "":
330 | # 如果是缓冲区溢出,由于我这里payload使用"A"*10等形式,所以需要先使用eval动态执行转成最终的字符串
331 | if payload_type == "overflow":
332 | fuzz_payload = eval(fuzz_payload)
333 | self.send_payload( org_step_header, fuzz_payload, step, payload_type, fuzz_var)
334 | # 最后单独对空载荷进行测试
335 | # 前面排除这里进行是因为载荷中为了方便使用了很多空行
336 | fuzz_payload = ""
337 | self.send_payload( org_step_header, fuzz_payload, step, payload_type, fuzz_var)
338 |
339 | # 正确执行OPTIONS请求
340 | def exec_options_step(self):
341 | # logging.info('now start to check options operation')
342 | str_options_header = self.gen_options_header()
343 | # 删除所有fuzz_var()标志
344 | str_options_header = re.sub(self.regexp, self.delete_var_sign, str_options_header)
345 | self.socket_send.send(str_options_header.encode())
346 | msg_recv = self.socket_send.recv(config_dict['buffer_len']).decode()
347 | if '200 OK' in msg_recv:
348 | logging.info('OPTIONS is ok, next first DESCRIBE')
349 | return msg_recv,2000
350 | else:
351 | logging.info('OPTIONS request is BAD')
352 | return msg_recv,4000
353 |
354 | # 模糊测试OPTIONS请求
355 | def fuzz_options_step(self):
356 | step = "OPTIONS"
357 | org_options_header = self.gen_options_header()
358 | self.traverse_fuzz_var(step,org_options_header)
359 |
360 | # 正确执行first describe请求
361 | def exec_first_describe_step(self):
362 | str_describe_header = self.gen_first_describe_header()
363 | str_describe_header = re.sub(self.regexp, self.delete_var_sign, str_describe_header)
364 | self.socket_send.send(str_describe_header.encode())
365 | msg_recv = self.socket_send.recv(config_dict['buffer_len']).decode()
366 | if msg_recv.find('401 Unauthorized') != -1:
367 | logging.info('first DESCRIBE is ok, next second DESCRIBE')
368 | return msg_recv,2000
369 | else:
370 | msg_recv_dict = msg_recv.split('\r\n')
371 | logging.info('first DESCRIBE occur error: ')
372 | logging.info(msg_recv_dict[0])
373 | return msg_recv,4000
374 |
375 | # 模糊测试first describe请求
376 | def fuzz_first_describe_step(self):
377 | step = "FIRST DESCRIBE"
378 | org_first_describe_header = self.gen_first_describe_header()
379 | self.traverse_fuzz_var(step,org_first_describe_header)
380 |
381 | # 正确执行second describe请求
382 | def exec_second_describe_step(self,realm, nonce):
383 | str_describe_auth_header = self.gen_second_describe_header(realm, nonce)
384 | str_describe_auth_header = re.sub(self.regexp, self.delete_var_sign, str_describe_auth_header)
385 | self.socket_send.send(str_describe_auth_header.encode())
386 | msg_recv = self.socket_send.recv(config_dict['buffer_len']).decode()
387 | if msg_recv.find('200 OK') != -1:
388 | logging.info('second DESCRIBE is ok, next first SETUP')
389 | return msg_recv,2000
390 | else:
391 | msg_recv_dict = msg_recv.split('\r\n')
392 | logging.info('second DESCRIBE request occur error: ')
393 | logging.info(msg_recv_dict[0])
394 | return msg_recv, 4000
395 |
396 | # 模糊测试second describe请求
397 | def fuzz_second_describe_step(self, realm, nonce):
398 | step = "SECOND DESCRIBE"
399 | org_second_describe_header = self.gen_second_describe_header(realm, nonce)
400 | self.traverse_fuzz_var(step,org_second_describe_header)
401 |
402 |
403 | # 正确执行first setup请求
404 | def exec_first_setup_step(self, realm, nonce):
405 | # logging.info('second DESCRIBE is ok, next first SETUP')
406 | str_setup_header = self.gen_first_setup_header(realm, nonce)
407 | str_setup_header = re.sub(self.regexp, self.delete_var_sign, str_setup_header)
408 | self.socket_send.send(str_setup_header.encode())
409 | msg_recv = self.socket_send.recv(config_dict['buffer_len']).decode()
410 | if msg_recv.find('200 OK') != -1:
411 | logging.info('first SETUP is ok, next second SETUP')
412 | return msg_recv, 2000
413 | else:
414 | msg_recv_dict = msg_recv.split('\r\n')
415 | logging.info('first SETUP request occur error: ')
416 | logging.info(msg_recv_dict[0])
417 | return msg_recv, 4000
418 |
419 | # 模糊测试first setup请求
420 | def fuzz_first_setup_step(self, realm, nonce):
421 | step = "FIRST_SETUP"
422 | org_first_setup_header = self.gen_first_setup_header(realm, nonce)
423 | self.traverse_fuzz_var(step, org_first_setup_header)
424 |
425 | # 正确执行second setup请求
426 | def exec_second_setup_step(self, realm, nonce, session):
427 | str_setup_session_header = self.gen_second_setup_header(realm, nonce, session)
428 | str_setup_session_header = re.sub(self.regexp, self.delete_var_sign, str_setup_session_header)
429 | self.socket_send.send(str_setup_session_header.encode())
430 | msg_recv = self.socket_send.recv(config_dict['buffer_len']).decode()
431 | if msg_recv.find('200 OK') != -1:
432 | logging.info('second SETUP is ok, next PLAY')
433 | return msg_recv, 2000
434 | else:
435 | msg_recv_dict = msg_recv.split('\r\n')
436 | logging.info('second SETUP request occur error: ')
437 | logging.info(msg_recv_dict[0])
438 | return msg_recv, 4000
439 |
440 | # 模糊测试second setup请求
441 | def fuzz_second_setup_step(self, realm, nonce, session):
442 | step = "SECOND_SETUP"
443 | org_second_setup_header = self.gen_second_setup_header(realm, nonce, session)
444 | self.traverse_fuzz_var(step, org_second_setup_header)
445 |
446 | # 正确执行play请求
447 | def exec_play_step(self, realm, nonce, session):
448 | str_play_header = self.gen_play_header(realm, nonce, session)
449 | str_play_header = re.sub(self.regexp, self.delete_var_sign, str_play_header)
450 | self.socket_send.send(str_play_header.encode())
451 | msg_recv = self.socket_send.recv(config_dict['buffer_len']).decode()
452 | if msg_recv.find('200 OK') != -1:
453 | logging.info('PLAY is ok, next GET_PARAMETER')
454 | return msg_recv, 2000
455 | else:
456 | msg_recv_dict = msg_recv.split('\r\n')
457 | logging.info('PLAY request occur error: ')
458 | logging.info(msg_recv_dict[0])
459 | return msg_recv, 4000
460 |
461 | # 模糊测试play请求
462 | def fuzz_play_step(self, realm, nonce, session):
463 | step = "PLAY"
464 | org_play_header = self.gen_play_header(realm, nonce, session)
465 | self.traverse_fuzz_var(step, org_play_header)
466 |
467 | # 正确执行get parameter请求
468 | def exec_get_parameter_step(self,realm, nonce, session):
469 | str_get_parameter_header = self.gen_get_parameter_header(realm, nonce, session)
470 | str_get_parameter_header = re.sub(self.regexp, self.delete_var_sign, str_get_parameter_header)
471 | self.socket_send.send(str_get_parameter_header.encode())
472 | msg_recv = self.socket_send.recv(config_dict['buffer_len']).decode()
473 | if msg_recv.find('200 OK') != -1:
474 | logging.info('GET_PARAMETER is ok, next TEARDOWN')
475 | return msg_recv, 2000
476 | else:
477 | msg_recv_dict = msg_recv.split('\r\n')
478 | logging.info('GET_PARAMETER error: ')
479 | logging.info(msg_recv_dict[0])
480 | return msg_recv, 4000
481 |
482 | # 模糊测试get parameter请求
483 | def fuzz_get_parameter_step(self,realm, nonce, session):
484 | step = "GET_PARAMETER"
485 | org_get_parameter_header = self.gen_get_parameter_header(realm, nonce, session)
486 | self.traverse_fuzz_var(step, org_get_parameter_header)
487 |
488 | # 正确执行teardown请求
489 | def exec_teardown_step(self,realm, nonce, session):
490 | str_teardown_header = self.gen_teardown_header(realm, nonce, session)
491 | str_teardown_header = re.sub(self.regexp, self.delete_var_sign, str_teardown_header)
492 | self.socket_send.send(str_teardown_header.encode())
493 | msg_recv = self.socket_send.recv(config_dict['buffer_len']).decode()
494 | if msg_recv.find('200 OK') != -1:
495 | logging.info('TEARDOWN is ok, next finish')
496 | return msg_recv, 2000
497 | else:
498 | msg_recv_dict = msg_recv.split('\r\n')
499 | logging.info('TEARDOWN occur error: ')
500 | logging.info(msg_recv_dict[0])
501 | return msg_recv, 4000
502 |
503 | # 模糊测试teardown请求
504 | def fuzz_teardown_step(self,realm, nonce, session):
505 | step = "TEARDOWN"
506 | org_teardown_header = self.gen_teardown_header(realm, nonce, session)
507 | self.traverse_fuzz_var(step, org_teardown_header)
508 |
509 | # 当为ALL时组织所有步骤进行模糊测试
510 | def exec_fuzz_rtsp(self):
511 | if config_dict["fuzz_step"] == "ALL":
512 | fuzz_steps = ["OPTIONS", "FIRST_DESCRIBE", "SECOND_DESCRIBE", "FIRST_SETUP", "SECOND_SETUP", "PLAY", "GET_PARAMETER", "TEARDOWN"]
513 | for fuzz_step in fuzz_steps:
514 | self.exec_fuzz_rtsp_flow(fuzz_step)
515 | else:
516 | fuzz_step = config_dict["fuzz_step"]
517 | self.exec_fuzz_rtsp_flow(fuzz_step)
518 |
519 | # 主要的模糊测试流程
520 | def exec_fuzz_rtsp_flow(self, fuzz_step):
521 |
522 | # 这些if是顺序性的,如果不是对该步进行模糊测试则该步要正确执行,以便服务器允许进入下一步
523 | # 如果要模糊测试OPTIONS请求,则模糊测试后直接退出
524 | if fuzz_step == "OPTIONS":
525 | self.fuzz_options_step()
526 | return True
527 | else:
528 | msg_recv,result_flag = self.exec_options_step()
529 | # 如果要模糊测试FIRST DESCRIBE请求,则模糊测试后直接退出
530 | if fuzz_step == "FIRST_DESCRIBE":
531 | self.fuzz_first_describe_step()
532 | return True
533 | else:
534 | msg_recv, result_flag = self.exec_first_describe_step()
535 | # 从FIRST_DESCRIBE返回结果中提取realm和nonce
536 | # 在RTSP中后续的请求这两个值都是不变的
537 | realm = self.extract_realm_value(msg_recv)
538 | nonce = self.extract_nonce_value(msg_recv)
539 |
540 | # 如果要模糊测试SECOND DESCRIBE请求,则模糊测试后直接退出
541 | if fuzz_step == "SECOND_DESCRIBE":
542 | self.fuzz_second_describe_step(realm,nonce)
543 | return True
544 | else:
545 | msg_recv, result_flag = self.exec_second_describe_step(realm,nonce)
546 |
547 | # 如果要模糊测试FIRST_SETUP请求,则模糊测试后直接退出
548 | if fuzz_step == "FIRST_SETUP":
549 | self.fuzz_first_setup_step(realm, nonce)
550 | return True
551 | else:
552 | msg_recv, result_flag = self.exec_first_setup_step(realm,nonce)
553 | # 从FIRST_SETUP返回结果中提取session
554 | session = self.extract_session_value(msg_recv)
555 |
556 | # 如果要模糊测试SECOND_SETUP请求,则模糊测试后直接退出
557 | if fuzz_step == "SECOND_SETUP":
558 | self.fuzz_second_setup_step(realm, nonce, session)
559 | return True
560 | else:
561 | msg_recv, result_flag = self.exec_second_setup_step(realm, nonce, session)
562 |
563 | # 如果要模糊测试PLAY请求,则模糊测试后直接退出
564 | if fuzz_step == "PLAY":
565 | self.fuzz_play_step(realm, nonce, session)
566 | return True
567 | else:
568 | self.exec_play_step(realm, nonce, session)
569 |
570 | # 如果要模糊测试GET_PARAMETER请求,则模糊测试后直接退出
571 | if fuzz_step == "GET_PARAMETER":
572 | self.fuzz_get_parameter_step(realm, nonce, session)
573 | return True
574 | else:
575 | msg_recv, result_flag = self.exec_get_parameter_step(realm, nonce, session)
576 |
577 | # 如果要模糊测试TEARDOWN请求,则模糊测试后直接退出
578 | if fuzz_step == "TEARDOWN":
579 | self.fuzz_teardown_step(realm, nonce, session)
580 | return True
581 | else:
582 | self.exec_teardown_step(realm, nonce, session)
583 | return True
584 |
585 | def __del__(self):
586 | self.socket_send.close()
587 | pass
588 |
589 |
590 | if __name__ == '__main__':
591 | rtsp_client = RtspFuzzer()
592 | # OPTIONS/FIRST_DESCRIBE/SECOND_DESCRIBE/FIRST_SETUP/SECOND_SETUP/PLAY/GET_PARAMETER/TEARDOWN
593 | # step = "OPTIONS"
594 | rtsp_client.exec_fuzz_rtsp()
595 | # rtsp_client.exec_full_request()
596 | # rtsp_client.exec_force_request()
597 | # uri = "rtsp://10.10.6.93:554/chIP=1/"
598 | # nonce = "3a260a0da860c9b55b8dbde939962287"
599 | # realm = "RTSP SERVER"
600 | # method = "DESCRIBE"
601 | # result = rtsp_client.gen_digest_response_value(uri, method, realm, nonce)
602 | # pass
--------------------------------------------------------------------------------
/fuzzers/snmp_fuzzer.py:
--------------------------------------------------------------------------------
1 | import binascii
2 | import logging
3 | from scapy.all import *
4 | from common.logger import LogConfig
5 |
6 | class SnmpFuzzer():
7 | def __init__(self):
8 | # snmp模糊测试的主要配置项
9 | # target_ip--snmp服务主机ip地址
10 | # target_port--snmp服务端口
11 | # snmp_hex_string--snmp应用层数据的十六进制字符串,我随便从一个snmp数据包截这来的
12 | # log_type--日志类型,console将日志打印到控制台,file将日志写入到文件
13 | # log_file_prefix--日志文件前辍,console时不生效
14 | self.config = {
15 | "target_ip":"10.10.6.98",
16 | "target_port":161,
17 | "snmp_hex_string":"302202010104067075626c6963a01502047c07ac6c0201000201003007300506012b0500",
18 | 'log_type': 'console',
19 | 'log_file_prefix': 'snmp'
20 | }
21 | # 设置日志格式
22 | LogConfig(log_type=self.config["log_type"], log_file_prefix=self.config["log_file_prefix"])
23 |
24 | def fuzzSnmp(self):
25 | snmp_hex_string_lenght = self.config["snmp_hex_string"].__len__()
26 | # 遍历每个字节
27 | for index in range(int(snmp_hex_string_lenght/2)):
28 | # 每个字节遍历0-255
29 | for value in range(0xff):
30 | # 遍历字节之前的部分
31 | snmp_hex_string_payload_pre = binascii.a2b_hex(self.config["snmp_hex_string"][0:index*2])
32 | # 当前遍历到的字节
33 | value_hex = value.to_bytes(1,"big")
34 | # 遍历字节之后的部分
35 | snmp_hex_string_payload_post = binascii.a2b_hex(self.config["snmp_hex_string"][index*2+2:])
36 | # 构造snmp应用层数据
37 | snmp_hex_string_payload = snmp_hex_string_payload_pre + value_hex + snmp_hex_string_payload_post
38 | # 构造最终要发送的snmp数据包
39 | udp_packet = IP(dst=self.config["target_ip"])/UDP(sport=9876,dport=self.config["target_port"])/snmp_hex_string_payload
40 | # 发送数据包并接收响应
41 | response_packet = sr1(udp_packet)
42 | logging.info(f"{index *2}-{value_hex}-{response_packet.show()}")
43 |
44 |
45 | if __name__ == "__main__":
46 | snmp_fuzzer = SnmpFuzzer()
47 | snmp_fuzzer.fuzzSnmp()
48 |
--------------------------------------------------------------------------------
/payloads/format_string.txt:
--------------------------------------------------------------------------------
1 | %d
2 | %s
3 | %c
4 | %o
5 | %x
6 | %X
7 | %e
8 | %E
9 | %f
10 | %g
11 | %G
12 | %0xa
13 | %-
14 | %d%d
15 | %s%s
16 | %c%c
17 | %o%o
18 | %x%x
19 | %X%X
20 | %e%e
21 | %E%E
22 | %f%f
23 | %g%g
24 | %G%G
25 | %0xa%0xa
26 | %-%-
27 |
28 | %d%d%d%d%d
29 | %s%s%s%s%s
30 | %c%c%c%c%c
31 | %o%o%o%o%o
32 | %x%x%x%x%x
33 | %X%X%X%X%X
34 | %e%e%e%e%e
35 | %E%E%E%E%E
36 | %f%f%f%f%f
37 | %g%g%g%g%g
38 | %G%G%G%G%G
39 | %0xa%0xa%0xa%0xa
40 | %-%-%-%-%-
41 |
42 | %1024d
43 | %2048d
44 | %4096d
45 | %.1024d
46 | %.2048d
47 | %.4096d
48 | %1024c
49 | %2048c
50 | %4096c
51 | %.1024c
52 | %.2048c
53 | %.4096c
54 |
55 | %1024f
56 | %2048f
57 | %4096f
58 | %.1024f
59 | %.2048f
60 | %.4096f
61 | %s%c%d%f
62 |
63 | %s%p%x%d
64 | %p%p%p%p
65 | %x%x%x%x
66 | %d%d%d%d
67 | %s%s%s%s
68 | %99999999999s
69 | %08x
70 | %20d
71 | %20n
72 | %20x
73 | %20s
74 | %d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d
75 | %i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i
76 | %o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o
77 | %u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u
78 | %x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x
79 | %X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X
80 | %a%a%a%a%a%a%a%a%a%a%a%a%a%a%a%a%a%a%a%a%a%a%a%a%a%a%a%a%a%a%a%a%a%a%a%a%a%a%a%a%a%a%a%a%a%a%a%a%a%a%a%a%a%a
81 | %A%A%A%A%A%A%A%A%A%A%A%A%A%A%A%A%A%A%A%A%A%A%A%A%A%A%A%A%A%A%A%A%A%A%A%A%A%A%A%A%A%A%A%A%A%A%A%A%A%A%A%A%A%A
82 | %e%e%e%e%e%e%e%e%e%e%e%e%e%e%e%e%e%e%e%e%e%e%e%e%e%e%e%e%e%e%e%e%e%e%e%e%e%e%e%e%e%e%e%e%e%e%e%e%e%e%e%e%e%e
83 | %E%E%E%E%E%E%E%E%E%E%E%E%E%E%E%E%E%E%E%E%E%E%E%E%E%E%E%E%E%E%E%E%E%E%E%E%E%E%E%E%E%E%E%E%E%E%E%E%E%E%E%E%E%E
84 | %f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f
85 | %F%F%F%F%F%F%F%F%F%F%F%F%F%F%F%F%F%F%F%F%F%F%F%F%F%F%F%F%F%F%F%F%F%F%F%F%F%F%F%F%F%F%F%F%F%F%F%F%F%F%F%F%F%F
86 | %g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g
87 | %G%G%G%G%G%G%G%G%G%G%G%G%G%G%G%G%G%G%G%G%G%G%G%G%G%G%G%G%G%G%G%G%G%G%G%G%G%G%G%G%G%G%G%G%G%G%G%G%G%G%G%G%G%G
88 | %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s
89 | %p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p
90 | %#0123456x%08x%x%s%p%d%n%o%u%c%h%l%q%j%z%Z%t%i%e%g%f%a%C%S%08x%%
91 | XXXXX.%p
92 | XXXXX`perl -e 'print ".%p" x 80'`
93 | `perl -e 'print ".%p" x 80'`%n
94 | %08x.%08x.%08x.%08x.%08x\n
95 | XXX0_%08x.%08x.%08x.%08x.%08x\n
96 | %.16705u%2\$hn
97 | \x10\x01\x48\x08_%08x.%08x.%08x.%08x.%08x|%s|
98 | AAAAA%c
99 | AAAAA%d
100 | AAAAA%e
101 | AAAAA%f
102 | AAAAA%I
103 | AAAAA%o
104 | AAAAA%p
105 | AAAAA%s
106 | AAAAA%x
107 | AAAAA%n
108 | ppppp%c
109 | ppppp%d
110 | ppppp%e
111 | ppppp%f
112 | ppppp%I
113 | ppppp%o
114 | ppppp%p
115 | ppppp%s
116 | ppppp%x
117 | ppppp%n
118 | %@
119 | %@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%
--------------------------------------------------------------------------------
/payloads/overflow.txt:
--------------------------------------------------------------------------------
1 |
2 | "A"*10
3 | "A"*30
4 | "A"*50
5 | "A"*100
6 | "A"*257
7 |
--------------------------------------------------------------------------------
/payloads/random_num.txt:
--------------------------------------------------------------------------------
1 | -1
2 | -20
3 | -268435455
4 | 1
5 | 255
6 | 256
7 | 257
8 | 65536
9 | 65537
10 | 16777215
11 | 16777216
12 | 16777217
13 | 0xfffffff
14 | 1111111111
15 | 11111111111111111111111111111111111111111111111111
16 | 11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
17 | 1.1
18 | 1.1.1.1
19 | 1.111111111111111111111111111111111111111111
20 | 111111 1111
21 | 111111-1111
22 | 111111+1111
23 | 111111*1111
24 | 111111/1111
--------------------------------------------------------------------------------
/payloads/special_char.txt:
--------------------------------------------------------------------------------
1 | `
2 | ~
3 | !
4 | @
5 | #
6 | $
7 | %
8 | ^
9 | &
10 | *
11 | (
12 | )
13 | -
14 | _
15 | =
16 | +
17 | ``
18 | ~~
19 | !!
20 | @@
21 | ##
22 | $$
23 | %%
24 | ^^
25 | &&
26 | **
27 | ((
28 | ))
29 | --
30 | __
31 | ==
32 | ++
33 | `````
34 | ~~~~~
35 | !!!!!
36 | @@@@@
37 | #####
38 | $$$$$
39 | %%%%%
40 | ^^^^^
41 | &&&&&
42 | *****
43 | (((((
44 | )))))
45 | -----
46 | _____
47 | =====
48 | +++++
49 | ``````````
50 | ~~~~~~~~~~
51 | !!!!!~~~~~
52 | @@@@@@@@@@
53 | ##########
54 | $$$$$$$$$$
55 | %%%%%%%%%%
56 | ^^^^^^^^^^
57 | &&&&&&&&&&
58 | **********
59 | ((((((((((
60 | ))))))))))
61 | ----------
62 | __________
63 | ==========
64 | ++++++++++
65 | [
66 | {
67 | ]
68 | }
69 | \\
70 | |"
71 | ";
72 | :
73 | '
74 | \"
75 | ,
76 | <
77 | .
78 | >
79 | /
80 | ?
81 | [[
82 | {{
83 | ]]
84 | }}
85 | \\\\
86 | ||
87 | ;;
88 | ::
89 | ''
90 | ""
91 | ,,
92 | <<
93 | ..
94 | >>
95 | //
96 | ??
97 | [[[[[
98 | {{{{{
99 | ]]]]]
100 | }}}}}
101 | \\\\\\\\\\\\\\
102 | |||||
103 | ;;;;;
104 | :::::
105 | '''''
106 | """""
107 | ,,,,,
108 | <<<<<
109 | .....
110 | >>>>>
111 | /////
112 | ?????
113 | [[[[[[[[[[
114 | {{{{{{{{{{
115 | ]]]]]]]]]]
116 | }}}}}}}}}}
117 | \\\\\\\\\\\\\\\\\\\\\\\\\\\\
118 | ||||||||||
119 | ;;;;;;;;;;
120 | ::::::::::
121 | ''''''''''
122 | """"""""""
123 | ,,,,,,,,,,
124 | <<<<<<<<<<
125 | ..........
126 | >>>>>>>>>>
127 | //////////
128 | ??????????
129 |
130 | ·
131 | ~
132 | !
133 | @
134 | #
135 | ¥
136 | %
137 | ……
138 | &
139 | *
140 | (
141 | )
142 | -
143 | ——
144 | =
145 | +
146 | ··
147 | ~~
148 | !!
149 | @@
150 | ##
151 | ¥¥
152 | %%
153 | …………
154 | &&
155 | **
156 | ((
157 | ))
158 | --
159 | ————
160 | ==
161 | ++
162 | ·····
163 | ~~~~~
164 | !!!!!
165 | @@@@@
166 | #####
167 | ¥¥¥¥¥
168 | %%%%%
169 | …………………………
170 | &&&&&
171 | *****
172 | (((((
173 | )))))
174 | -----
175 | ——————————
176 | =====
177 | +++++
178 | ··········
179 | ~~~~~~~~~~
180 | !!!!!!!!!!
181 | @@@@@@@@@@
182 | ##########
183 | ¥¥¥¥¥¥¥¥¥¥
184 | %%%%%%%%%%
185 | ……………………………………………………
186 | &&&&&&&&&&
187 | **********
188 | ((((((((((
189 | ))))))))))
190 | ----------
191 | ————————————————————
192 | ==========
193 | ++++++++++
194 | 【
195 | {
196 | 】
197 | }
198 | 、
199 | |
200 | ;
201 | :
202 | ’
203 | ”
204 | ,
205 | 《
206 | 。
207 | 》
208 | 、
209 | ?
210 | 【【
211 | {{
212 | 】】
213 | }}
214 | 、、
215 | ||
216 | ;;
217 | ::
218 | ‘’
219 | ”“
220 | ,,
221 | 《《
222 | 。。
223 | 》》
224 | 、、
225 | ??
226 | 【【【【【
227 | {{{{{
228 | 】】】】】
229 | }}}}}
230 | 、、、、、
231 | |||||
232 | ;;;;;
233 | :::::
234 | ‘’‘’‘
235 | ”“”“”
236 | ,,,,,
237 | 《《《《《
238 | 。。。。。
239 | 》》》》》
240 | 、、、、、
241 | ?????
242 | 【【【【【【【【【【
243 | {{{{{{{{{{
244 | 】】】】】】】】】】
245 | }}}}}}}}}}
246 | 、、、、、、、、、、
247 | ||||||||||
248 | ;;;;;;;;;;
249 | ::::::::::
250 | ‘’‘’‘‘’‘’‘
251 | ”“”“””“”“”
252 | ,,,,,,,,,,
253 | 《《《《《《《《《《
254 | 。。。。。。。。。。
255 | 》》》》》》》》》》
256 | 、、、、、、、、、、
257 | ??????????
258 |
259 | `
260 | ~
261 | !
262 | @
263 | #
264 | $
265 | %
266 | ^
267 | &
268 | *
269 | (
270 | )
271 | -
272 | _
273 | =
274 | +
275 | ``
276 | ~~
277 | !!
278 | @@
279 | ##
280 | $$
281 | %%
282 | ^^
283 | &&
284 | **
285 | ((
286 | ))
287 | --
288 | __
289 | ==
290 | ++
291 | `````
292 | ~~~~~
293 | !!!!!
294 | @@@@@
295 | #####
296 | $$$$$
297 | %%%%%
298 | ^^^^^
299 | &&&&&
300 | *****
301 | (((((
302 | )))))
303 | -----
304 | _____
305 | =====
306 | +++++
307 | ``````````
308 | ~~~~~~~~~~
309 | !!!!!!!!!!
310 | @@@@@@@@@@
311 | ##########
312 | $$$$$$$$$$
313 | %%%%%%%%%%
314 | ^^^^^^^^^^
315 | &&&&&&&&&&
316 | **********
317 | ((((((((((
318 | ))))))))))
319 | ----------
320 | __________
321 | ==========
322 | ++++++++++
323 | [
324 | {
325 | ]
326 | }
327 | \
328 | |
329 | ;
330 | :
331 | '
332 | "
333 | ,
334 | <
335 | .
336 | >
337 | /
338 | ?
339 | [[
340 | {{
341 | ]]
342 | }}
343 | \\
344 | ||
345 | ;;
346 | ::
347 | ''
348 | ""
349 | ,,
350 | <<
351 | ..
352 | >>
353 | //
354 | ??
355 | [[[[[
356 | {{{{{
357 | ]]]]]
358 | }}}}}
359 | \\\\\
360 | |||||
361 | ;;;;;
362 | :::::
363 | '''''
364 | """""
365 | ,,,,,
366 | <<<<<
367 | .....
368 | >>>>>
369 | /////
370 | ?????
371 | [[[[[[[[[[
372 | {{{{{{{{{{
373 | ]]]]]]]]]]
374 | }}}}}}}}}}
375 | \\\\\\\\\\
376 | ||||||||||
377 | ;;;;;;;;;;
378 | ::::::::::
379 | ''''''''''
380 | """"""""""
381 | ,,,,,,,,,,
382 | <<<<<<<<<<
383 | ..........
384 | >>>>>>>>>>
385 | //////////
386 | ??????????
--------------------------------------------------------------------------------
/payloads/unicode.txt:
--------------------------------------------------------------------------------
1 | \000x99\000x99\000x99\000x99\000x99\000x99\000x99\000x99\000x99
2 | \000xCB\000xCB\000xCB\000xCB\000xCB\000xCB\000xCB\000xCB\000xCB
3 | \000xCD\000xCD\000xCD\000xCD\000xCD\000xCD\000xCD\000xCD\000xCD
4 | %u00
5 | %u000
6 | %u00%u00
7 | %u000%u000
--------------------------------------------------------------------------------