This will skip the assert statement and go straight to the secure code regardless of whether the user is_admin or not. Now, by default Python executes with _debug_ as true, but in a production environment it’s common to run with optimizations. Take this simple exampleĭef foo(request, user):assert user.is_admin, “user does not have access” secure code. Assert statementsĭon’t use assert statements to guard against pieces of code that a user shouldn’t access. It adds safe-guards against these types of attacks. Use defusedxml as a drop-in replacement for the standard library modules. So what happens in Python? Well, the standard library modules, etree, DOM, xmlrpc are all wide open to these types of attacks. You might not even be aware that one of your dependencies leaves itself open to these types of attacks. “An attacker can circumvent firewalls and gain access to restricted resources as all the requests are made from an internal and trustworthy IP address, not from the outside.”Īnother situation to consider is 3rd party packages you’re depending on that decode XML, like configuration files, remote APIs. XML supports referencing entities from external URLs, the XML parser would typically fetch and load that resource without any qualms. Try it out if you don’t believe me :-)Īnother attack uses external entity expansion. Basically, the idea is that you can do referential entities in XML, so when your unassuming XML parser tries to load this XML file into memory it consumes gigabytes of RAM. One of those is called “billion laughs”, because of the payload normally containing a lot (billions) of “lols”. Those attacks are common, especially if you’re parsing external (ie non-trusted) XML files. Mostly DoS-style (designed to crash systems instead of exfiltration of data).
There are a few common attacks through XML. If your application ever loads and parses XML files, the odds are you are using one of the XML standard library modules. Most ORMs have builtin sanitization methods.įor the shell, use the shlex module to escape input correctly. Unless you have a good reason, don’t construct SQL queries by hand. Sanitise input using the utilities that come with your web framework, if you’re using one. The attacker sets the value of filename to " cat /etc/passwd | mail or something equally dangerous. You call a subprocess with the filename as provided by the user: import subprocessdef transcode_file(request, filename): command = 'ffmpeg -i "" output_file.mpg'.format(source=filename) subprocess.call(command, shell=True) # a bad idea! When calling local commands there’s a possibility of someone setting those values to something malicious. Familiarise yourself with all the complex ways SQL injection can happen with this cheatsheet.Ĭommand injection is anytime you’re calling a process using popen, subprocess, os.system and taking arguments from variables. I’ve read plenty of code where “escaping quotes” is deemed a fix. SQL injection is where you’re writing SQL queries directly instead of using an ORM and mixing your string literals with variables. They impact all languages, frameworks and environments. Injection attacks are broad and really common and there are many types of injection. Here are my top 10, in no particular order, common gotchas in Python applications. Yet, when I’ve spoken to many Python developers they simply aren’t aware of them. Python is no exception, even within the standard library there are documented bad practices for writing hardened applications. When thinking about security, you need to think about how it can be misused. When you learn a language, a module or a framework, you learn how it supposed to be used.