|
|
Log in / Subscribe / Register

Development

Scanning Python programs with Bandit

By Jake Edge
February 18, 2015

Using a program written in a particular language to search for problems in another program written in that same language has a certain amount of charm. High-level languages, such as Python, can actually give programmers easy access to the data structures built by the parser, so that these analysis programs can see the program exactly as the interpreter does. An OpenStack sub-project called Bandit does exactly that. It uses the Python abstract syntax tree (ast) module to seek out potential security problems in Python code.

OpenStack is a free-software cloud platform that is written in Python—over a million lines of it—so it makes sense for the project to have tools to look for problems in its code. Bandit comes from the OpenStack Security Group and is specifically targeted at finding security flaws in the OpenStack—or any other Python—code base. It is structured as a framework that reads in and parses the source code, then runs through a battery of tests, implemented as plugins, to seek out the use of dubious Python modules and functions, potentially dangerous code constructs, and more.

The README file outlines how to clone and install Bandit into a Python virtual environment, though it can also be installed without the virtual environment in the usual fashion:

    $ python setup.py install
From there it is simple to run; just pass a bunch of Python files to the Bandit program:
    $ bandit examples/*.py
The examples directory contains a full set of programs that demonstrate each of the rules that Bandit is enforcing. In fact, new tests proposed for merging must be accompanied with an example file to demonstrate the dubious code that Bandit will be detecting.

Running Bandit on a moderately sized body of Python code—one that runs a nearby web site—produced an 800-line report that mostly contained false positives. That is not really a surprise for a couple of reasons. For one, the tool and tests are geared toward OpenStack and how it uses Python and its modules. For example, any strings that looked like SQL were flagged as SQL injection warnings—unless the SQLAlchemy module is imported (in which case the severity is reduced to informational). That may make sense for OpenStack, but other projects may have their own mechanisms to avoid SQL injection.

In addition, one totally unrelated string that happened to contain both "select" and "from" triggered the warning. The tests would need to be much more sophisticated to avoid that kind of false positive.

Beyond that, though, a tool of this nature needs to be pretty conservative about skipping over potential problems. That means it will alert on lots of things that aren't actually vulnerabilities, but require a human to determine that. Thus, false positives.

But the list of warnings definitely had some things to look into. For example, there are complaints about network services that may be binding to all interfaces on the system, which may be unexpected. Use of the os.popen() function is generally frowned upon and its use requires some investigation. Use of the random module "is not suitable for security/cryptographic purposes", which is probably not how it is being used, but it should be looked into. And so on.

Beyond the SQL injection complaints, the most common warning was for the use of the pickle module, which can have security (and maintenance) implications. Its use in this code base should be safe (though it is something we plan to replace for other reasons at some point). Disabling those top two warning types resulted in a much shorter report, with only 14 warnings to investigate.

While disabling the pickle test was easy to do, by commenting out some lines in the bandit.yaml configuration file, turning off the SQL injection tests was not quite as straightforward. Since many of the tests are plugins, moving the injection_sql.py file aside in the install plugins directory worked well enough to disable it, but was rather inelegant. A more proper solution was to set up a profile in the configuration file that excluded the hardcoded_sql_expressions test.

Another option is to go through the source and annotate any line that causes a false positive with a "# nosec" comment. One could also filter the results based on the level of the complaint (i.e. information, warning, or error) though, in this case, that would likely mask some problems. Those with an aversion to colored output will want to use the -o file option to send the output to a file (thankfully without the color escape sequences).

Taking a spin through the examples directory will give a good overview of the kinds of things Bandit is looking for. As noted earlier, much of it is advisory in nature, like complaints about calling eval() (which is a warning, though calling exec() is considered an error), use of os.exec() and os.spawn(), use of the MD5 hash function, or any strings from a list of often-used default passwords. Beyond that, there are warnings about urllib.urlopen() ("Audit url open for permitted schemes. Allowing use of file:/ or custom schemes is often unexpected."), yaml.load() (recommending yaml.safe_load() in its place), mark_safe() (a potential cross-site scripting vector), and so on. Any of those could be security problems or completely innocuous, but someone needs to look to be sure.

OpenStack plans to add Bandit into its continuous integration system, and eventually may have it actually reject patches that don't pass. That is still probably a ways off based on the kinds of warnings it is producing now. Those classified as errors might be suitable, however. As with most projects, though, there is a pretty long to-do list on the web page.

For other projects, Bandit will likely take some tweaking to reduce the false positive rate based on the project's coding style and typical Python usage. That should be pretty easy to do, as the framework provides much of what is needed to write these types of tests. Adding new tests (or modifying existing ones) is straightforward, with plenty of code to look at for ideas. Bandit is well worth a look for Python-based projects.

Comments (none posted)

Brief items

Quotes of the week

...and while I was playing with GNOME’s new Bugzilla instance trying to get rid of some upstream feature bloat, I looked at upstream’s Bugzilla front page and spend the next hours wondering where to add eight more Search buttons/links/forms so it’ll become a full dozen.
André Klapper

future CS grads, your destiny is to build a world where your only respite from its bleakness is moments of levity about how poorly it's made
Colin Bayer

Comments (2 posted)

Wayland 1.7.0

Bryce Harrington has announced the release of Wayland 1.7.0. "The Wayland protocol may be considered "done" but that doesn't mean there's not work to be done. This release focused on major improvements to Wayland's documentation, minor improvements to the testsuite, and some scattered bugfixes to the code itself."

Comments (34 posted)

PulseAudio 6.0 available

Version 6.0 of the PulseAudio framework has been released. New is support for several Bluetooth audio profiles under BlueZ 5, socket activation using systemd, and improved support for multi-channel audio profiles.

Full Story (comments: none)

cmocka 1.0 available

Version 1.0 of the cmocka unit-testing framework has been released. Notably, the 1.0 release features a new test runner that allows tests to be grouped, although there are many other updates and improvements to be found.

Full Story (comments: none)

SystemTap 2.7 available

Version 2.7 of the SystemTap instrumentation system has been released. New in this release are several changes to the tracepoint probe behavior, speed-ups when passing string data to and from functions, and a great many changed tapsets and scripts. The new release also happens to coincide with SystemTap's 10th anniversary as a project.

Full Story (comments: none)

Newsletters and articles

Development newsletters from the past week

Comments (none posted)

Routing on OpenStreetMap.org

The OpenStreetMap blog announced the roll-out of point-to-point direction routing on the main OSM site. Historically, OSM has encouraged other developers to build this sort of functionality on top of the OSM data set, but has presented a limited interface on its own site. "But we have a saying: “what gets rendered, gets mapped” – meaning that often you don’t notice a bit of data that needs tweaking unless it actually shows up on the map image. Lots of things aren’t shown on our default rendering, so the feedback loop offers less incentive for people to get them correct. And that goes doubly for things that you never “see” on the map – subtle things like “no left turn” at a particular junction, or “busses only” access on a tiny bit of road, or tricky data issues like when a footpath doesn’t quite join a road that it should join on to. Now that people can see a recommended route directly on the OSM homepage, they have an incentive to quickly pop in and fix little issues like that. The end effect will be OSM’s data going up one more level in terms of its quality for routing."

Comments (none posted)

Page editor: Nathan Willis
Next page: Announcements>>


Copyright © 2015, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds