Swagger stumbles: Flaw enables remote code execution

Swagger's code generators and parsers forgot the core tenet of software development, which is never to trust user input

The popular open source API framework Swagger lets developers describe, produce, and consume RESTful web services using a human-friendly authoring format. But a vulnerability that could result in code execution because of unexpected user input is a sobering reminder to developers to never, ever, trust user input.

Swagger defines a standard, language-agnostic interface to REST APIs by allowing people and computers to discover and understand what a web service can do without having to dig through the original source code, documentation, or network traffic packets. Swagger's code generators let developers easily access APIs and produce client-server code, but a problem arises when the generators are fed malicious input. Because Swagger's generators and parsers don't verify input when generating code, a maliciously-crafted Swagger document can result in remote code execution, Rapid7 said in a blog post disclosing the vulnerability.

"On the client side, a vulnerability exists in trusting a malicious Swagger document to create any generated code base locally, most often in the form of a dynamically generated API client," Rapid7 said. "On the server side, a vulnerability exists in a service that consumes Swagger to dynamically generate and serve API clients, server mocks and testing specs."

Attackers can inject parameters in Swagger JSON or YAML files to dynamically build HTTP API clients or servers in Node.js, PHP, Ruby, and Java with embedded arbitrary code. The potential attack scenario works similarly to specially-crafted Word or PDF documents booby-trapped with malicious executable code. In this case, an application parsing the malicious Swagger document could result in a script being executed on the web server. An attacker could potentially steal keys or certificates, or change application functionality.

Rapid7 recommended developers inspect Swagger documents for "language-specific escape sequences" until a patch is available. The blog post has examples of injectable parameters. Strings within keys inside the 'paths' object of a Swagger document can be written to generate executable Node.js or Java. Strings within the 'description' object in the definitions section of a swagger document can inject comments and inline PHP code, and strings in 'description' and 'title' of a swagger document can be used in unison to terminate block comments and inject inline ruby code.

Rapid7 disclosed the vulnerability to the Swagger API team in April, and to the Computer Emergency Response Team in May. Even after Rapid7 shared a proposed patch addressing the flaw with CERT, which is now available on GitHub, there was no response from the maintainers. Rapid7 researchers publicly disclosed details of the flaw, along with a Metasploit module, this week.

In the absence of fixes to the Swagger specification, which the Linux Foundation's Open API Initiative is built on, developers have to make sure they are sanitizing all input. Mitigations include properly escaping parameters before injecting, and having sanitization efforts in place to ensure the context of trust for an API specification. "For example, using double brackets {{ instead of {{{ for handlebar templates will usually prevent many types of injection attacks that involve single or double quote termination," the blog post said.

There are other examples, such as enforcing single-line for commented variables and sanitizing ' & " in variables before unescaped insertion. Developers are encouraged to use sanitization tools like the OWASP ESAPI.

"Our disclosure on the issues with generated Swagger code is an ultimately positive wake up call to the developers behind it, and I'm sure that they'll be producing some decent documentation on how to avoid getting caught out by unexpected user input going forward," Tod Beardsley, principal research manager at Rapid7.

In the patch discussion on GitHub, swagger-codgen has used a "security" tag for the first time on their issue tracker, "a significant milestone of security maturity for the project," Beardsley said. "There's a lot of engagement on Scott Davis's proposed patches now, and I'm sure the other maintainers will be taking note."

Secure programming is hard, as it runs counter to the normal development mantra of build and ship first, fix later. If developers had to wait till the code was perfect, the product would never ship, but developers need to incorporate basic tenets to protect the application. In this case, it's always sanitize user input.

"'Thou shalt not trust user input' is a basic secure programming commandment, and it's probably the one most violated," Beardsley said.

It's understandable that developers don't have a breaker mindset when working with the specification. Swagger, designed to make API documentation and adoption easier, is targeted squarely at professional developers. It's a tool "for, and by, makers, and generally, it's used by trustworthy parties who are behaving themselves and not trying to poison each other," Beardsley said.

That said, someone can be malicious on the internet, and being smart and secure is the best defense. There have been a number of vulnerabilities related to not sanitizing user inputs, such as the deserialization flaw affecting Apache commons library. While individual commercial products have fixed the issue in their code, the actual library remains vulnerable. The more formats these applications support, the more chances there are slipping in some unchecked user input.

"A toolset like this which consumes and produces code in an array of languages is going to have a much higher attack surface, and more chances for security bugs than most projects," Beardsley said. 

Waiting for the fix can be a long wait, and developers shouldn't count on libraries and APIs to be sanitizing input. Assume input can be bad, and make the appropriate checks accordingly.

Copyright © 2016 IDG Communications, Inc.