One of the most valuable weapons you can have in your arsenal as an offensive security engineer or API security tester is tooling that can help with code analysis, especially for attack surface detection.
I’ve talked about this before when covering how to trace API exploitability through code review and taint analysis. I introduced you to tools like graudit, semgrep, and CodeQL specifically for this.
Today I am going to explore a new tool I recently heard about called noir. The author claims it’s an attack surface detector for source code, and I’m always interested in trying out new tools to see if they can help improve my workflow.
In this article, I am going to take you along as I give it a try. We can learn together if Noir can help with the dark art of API attack surface detection.
So the Github repo includes installation instructions. As I am sitting on a deck in the shade writing this on my Macbook Air, let’s take advantage of the homebrew tap that the author has kinda published:
brew tap hahwul/noir
Painless enough. Let’s pour this tap and install it:
brew install noir
Alright. Looks like we are good to go.
Let’s throw noir at some code!
Running Noir against some API source code
We need a code repository to turn Noir onto. Let’s use OWASP’s Open Source completely ridiculous API (crAPI) for that. As I already have the crAPI code locally, we can point Noir right to the repo and let it do the code analysis.
Before we do that, I guess we need to figure out how to use this thing.
OK, let’s check the help docs.
Looks easy enough. The only thing mandatory is the
-b flag to point to the path. Guess we point that to the source code repo and go.
I think later we may need to check out
--send-proxy flag. Might be able to direct this tool right into the Burp proxy for use later.
We will see. But for now, let’s just use the
-b flag and go, go, go!
Running Noir for the first time
Cross your fingers. Let’s see what happens.
cd ~/api/crAPI noir -b .
Not a bad start. Let’s explore the results.
How did Noir do out of the box?
Noir is fast. I couldn’t even time it as it came back so quickly. But how were the results as an attack surface detection tool?
Noir detected that there is code written in Python and Java almost instantly. But it looks like it missed the endpoints written in Go in the community module where coupons are handled.
Checking the Noir repo docs, it says it can detect Go, but I am going to assume the detection logic is looking for a specific pattern only related to Labstack’s Echo framework, which is too bad… since most Go APIs don’t use Echo.
OWASP’s implementation of the community module is a pretty standard codebase for Go, and Noir couldn’t see it.
Beyond the tech stack detection, it looks like Noir found endpoint routes in the identity module that was written in Java. But it didn’t catch any of the Django URL routes in the workshop module written in Python.
I’m not sure why. Quickly looking at the detection and analyzer code in Noir, it looks like it should have been able to find it. But it didn’t.
API docs detection
Now this was disappointing. Even though OWASP publishes the OpenAPI specification doc in the repo, Noir didn’t detect it. The Noir repo docs say they can detect OAS3 spec docs, but it’s not catching the
openapi-spec.json right there in the source code repo.
After some investigation, I found that the compiled code in the Homebrew tap matches the release info for 0.4.0, but that the GitHub repo where the OAS3 code lives haven’t been pushed to the brew tap.
So the code in Brew doesn’t match what’s in GitHub, even though they are versioned the same. OK, let’s check out the Noir code and build it ourselves.
Taking a second stab at Noir
So following the build guidance in the repo, I checked out the source code for Noir, ensured Crystal was installed, and built the shard. All looks good.
I now have the latest code. Let’s see how we do.
Attempting to detect OAS3 API spec docs
Using the latest build of Noir I run it against the crAPI code again.
It still didn’t detect it. WTF?
After some analysis of the code for Noir I found that the detector only looks for OpenAPI 3.0.0 spec docs. Anything newer is ignored.
That sucks. What happens if we downgrade the version of the spec doc? v3.0.1 is only a patch release and shouldn’t have any material impact on the form and function of an OAS spec parser. I’ll just change the version in the file and see what happens.
Ouch. Guess the analyzer isn’t resilient enough to handle that.
OK, I want to see this tool work against API documentation. Let’s point it to a known good OAS3 file. The PETS API seems like a logical choice since the Swagger Editor uses that by default when demoing APi spec docs.
That works. Decent output. So if they fix the versioning issue, it looks like it can do a good job extracting endpoints from the spec docs.
Let’s move on. That whole delivery option in Noir looked interesting. Let’s see if we can fire this tool’s output over to Burp Suite.
Noir + Burp = #winning?
When we first looked at the Noir help, it mentioned the
--send-proxy flag, which is supposed to send discovered endpoints to a proxy. Well, Burp Suite is a proxy. Let’s set that up and see if we can get Noir to work with Burp.
Verify Burp proxy is working
Before testing Noir with Burp, we need to ensure the Burp proxy is working. Easy enough to do. Just send a request to a detected endpoint using curl. Let’s use the health check endpoint Noir detected in the identity module:
curl -x http://localhost:8080 http://crapi.apisec.ai/identity/health_check
That worked. Let’s verify in Burp Suite:
All good. Let’s throw Noir into the mix.
Sending requests via Noir to Burp
So according to the Noir docs, it should just be a matter of using the correct flags. We will use the
-u flag to set the live endpoint URL, and then the
--send-proxy flag to tell it to connect to the Burp Suite proxy.
noir -b . -u http://crapi.apisec.ai --send-proxy http://localhost:8080
Looks like Noir took in the flags and constructed the proper URLs. But we see nothing hit Burp’s proxy.
Not sure what is going on.
I turned on packet capturing on the loopback interface and generated a pcap to explore the traffic with Wireshark. Following the HTTP stream for one of the requests, it appears that Burp Suite doesn’t like this how Noir is sending in the HTTP requests.
The error is straightforward enough. Noir isn’t actually proxy-aware. So to get Noir to work with Burp, we need to edit our proxy listener and enable support for invisible proxy mode, which allows non-proxy-aware clients to connect directly to the listener.
OK, let’s see how that goes…
Success! Wh00t! Wh00t! 🎉
The Power of Open-Source security tools
It was at this point that I decided to report my findings in the GitHub repo for all the issues I found, namely:
- The release in Homebrew did not match what was in GitHub, even though the versions were the same. I recommended the maintainers consider using a GitHub action to publish their Brew taps on any merge to the main branch.
- That the API documentation parser for OpenAPI docs was too strict and that they should be able to parse more than just v3.0.0.
- That the –send-proxy flag does not work right out of the box for Burp Suite users.
And the result of submitting my issues?
As of v0.5.0, Noir now syncs its code with Homebrew using GitHub actions, and the API docs detector and analyzer now properly parse OpenAPI spec docs!
Let’s see those changes in action…
That is a huge improvement, with Noir now going from detecting 27 API endpoints to detecting 71 and capturing all the endpoints from the API documentation. 🎉
While I had a bit of a bumpy road trying out Noir, it shows some real potential for attack surface detection. Open-source security tools are only as good as the development work put into them, and Noir is well on its way to becoming an indispensable tool.
The ease of installation via Homebrew makes it a quick addition to your workflow, and support for injecting detected API endpoints into Burp Suite helps you get started assessing the attack surface of API applications in no time.
Many thanks to Hahwul for being so receptive to my feedback and pushing out fixes so quickly. It made the experience of using Noir that much better.
Want to quickly discover the attack surface of the APIs you are testing? Then give Noir a try. You might find it helpful during your code analysis phase of a project.
One last thing…
The API Hacker Inner Circle is growing. It’s my FREE weekly newsletter where I share articles like this, along with pro tips, industry insights, and community news that I don’t tend to share publicly. If you haven’t yet, join us by subscribing at https://apihacker.blog.