Compass Security Blog

Offensive Defense

Bug Bounty: Insights from Our First-hand Experience

At Compass Security, we recently launched our managed bug bounty service. We openly invite hunters to probe our publicly exposed services for vulnerabilities. In return for their valuable feedback, we offer monetary bounties up to CHF 5000. This service complements our well-established penetration testing expertise, renowned for nearly 25 years.

Out-hack the Hackers

Recently, a bug bounty hunter alerted us to a minor vulnerability in a publicly exposed WordPress instance at our subsidiary, Hacking-Lab. An API designed for administrative purposes was accessible over the Internet, allowing attackers to manipulate the web server into sending arbitrary requests to both external and internal servers.

Although we had implemented IP restrictions on the regular management interface of WordPress (a recommended practice to reduce the attack surface), we decided to expand those restrictions to cover the exposed API. We assumed the issue was resolved after patching, retesting, and notifying the hunter.

The Bypass

Surprisingly, the hunter contacted us again, claiming continued access to the API despite our IP restrictions. Puzzled by how he had bypassed our security measures, we invited him to file another bug report, treating it as an IP restriction bypass and making him eligible for an additional bounty if he could substantiate his claim. He succeeded.

The bypass was straightforward: we had implemented the IP restriction on the Traefik reverse proxy in front of the WordPress instance, blocking all paths starting with /xmlrpc.php. However, the hunter utilized a double slash in front of the path (//xmlrpc.php), evading our filter.

Further investigation revealed that RFC2396 allows empty path segments, which are handled differently by different reverse proxies. Unlike nginx, which normalizes and removes empty paths, Traefik does not. To address this, we decided to globally ban the term xmlrpc.php in any path, accepting potential false positives but ultimately securing access to the API.

Good things come in pairs

But that was not the end of the story. The Hacking Lab decided to create a challenge for this bug to train interested customers. In the process, a new bypass possibility was discovered. In the regex used, the dot token (.) was used to match any preceding path segments. As this token does not match newline characters the restriction could be bypassed using a URL-encoded newline (%0A) in the path.

The restriction has been improved again to cover these scenarios as well.

Conclusion

In the end, the hunter received two bounties for discovering the bug as well as the first bypass, and we gained valuable knowledge from this incident:

  1. Sustained Vigilance: The incident highlighted the need for a constant review of security measures. Regularly revisiting and reassessing the status quo ensures adaptability to emerging threats, contributing to continuous knowledge enhancement within the team.
  2. Transparent Communication: Maintaining open channels with the bug bounty community is important. Encouraging researchers to share additional findings fosters collaboration and facilitates swift resolution of potential security issues.
  3. Efficency of Incentives: The successful resolution and bounty payout act as positive reinforcement for the bug bounty program. Monetary incentives motivate security researchers to actively engage, expediting the identification and resolution of vulnerabilities.

If you are interested in receiving valuable inputs from bug bounty hunters all over the world, read more about our managed bug bounty at https://www.compass-security.com/en/services/bug-bounty.

If you want to find the third bypass in this series, go ahead and participate in our bug bounty program: https://bugbounty.compass-security.com/bug-bounties/hacking-lab-bug-bounty

1 Comment

  1. Stefan

    I recently had a similar behaviour with haproxy.
    We defined an acl with a check for path begins with “acl letmein path_beg /test/publicsite.php”
    But it was possible to bypass this check with the URL https://blabla.com/test/publicsite.php/../secretsite.php
    I added then “http-request deny if { path -m sub /. }” to mitigate this.

Leave a Reply

Your email address will not be published. Required fields are marked *