How Common Python Coding Mistakes Can Cause Vulnerabilities
In this blog post we will talk about writing secure code. Am I pretending to always write secure code?… Heck no! I am lazy just like the rest of us :-). That being said, there are a few things that one should be aware of when writing code (even when it is sample code). I believe that you can still write your simple samples. However, if you know at least what vulnerabilities your code might have then you can write that down in your README. Even the famous Chinese philosopher Confucius knew this back around 530 BC:
“To know what you know and what you do not know, that is true knowledge.” – Confucius
Should I be worried about my hello_world.py script?
No. Again, I am not preaching that you should always go the full mile for some code you have written to test out an API. However, I have listed 5 common Python mistakes that can cause serious vulnerabilities in production applications. Please be mindful of these and try to avoid them as much as you can! Also, these coding mistakes can obviously also happen in other programming languages as well, so this does not just apply to Python.
py_vuln00: Arbitrary Code Execution
What is it?
Arbitrary Code Execution is an attacker’s ability to run any commands or code on a target machine or in a target process. This is most common in Python and occurs in many types such as command injection, SQL injection, and more. It arises from user inputs that are being directly passed in a standard Python function. The lack of input sanitization is usually the reason.
Example code snippet:
compute_user_input = input('nType something here to compute: ') if not compute_user_input: print ("No input") else: print ("Result: ", eval(compute_user_input))
Run in terminal as input:
> __import__("os").system("ls") [playing nice] > __import__(‘os’).system(‘rm –rf /’) [less nice…]
How can you solve it?
Always sanitize and validate user inputs first before passing them to the system commands. Using the `ast` Python module can also be a good solution. The Python module `shlex` can also help to automatically escape user input.
py_vuln01: Directory Traversal Attack
What is it?
A Directory Traversal Attack is also caused by improper user input validation. This can lead to sensitive files to be exposed and even to remote code execution. It arises if the path of file access by Python script is not properly checked. An attacker can manipulate the file path for example to something like /etc/passwd…
Example
As example Python library, the Requests package (who doesn’t use this one?) before 2.20.0 for Python sends an HTTP Authorization header to an http URI upon receiving a same-hostname https-to-http redirect, which makes it easier for remote attackers to discover credentials by sniffing the network.
How can you solve it?
This vulnerability can be fixed by updating (and testing!) all the packages for which updates are available. (DUH!)
You can also use tools to help with this after the fact:
- Static application security testing (SAST)
- Dynamic application security testing (DAST)
- Interactive application security testing (IAST)
- Runtime application self-protection (RASP) (e.g. Cisco AppDynamics with Secure Application, please see the last section of this blog post for more details)
py_vuln03: Incomplete Assertions
What is it?
This vulnerability happens when Python assertions are used to evaluate a condition, such as Boolean expressions. If the condition is true, the execution moves to the following line. Otherwise, it will show an error. The `assert` keyword should normally be used when debugging code.
Example snippet
x = "hello" # if condition returns True, then nothing happens: assert x == "hello" # if condition returns False, AssertionError is raised: assert x == "goodbye” # if condition returns False, custom AssertionError is raised: assert x == "goodbye", "x should be 'hello'"
How can you solve it?
Do NOT use Python assertions for logic, use if-else logic for Boolean conditions. In production, assertions might be disabled, so only use assertions in testing environments. Python assertions are not an error-handling tool, they are a debugging tool, please use them as such.
py_vuln04: Broken Access Control
What is it?
Broken access control describes the exploitation of access control management by attackers and bad actors. This vulnerability was actually moved to OWASP10 spot #1 from #5. A stunning 94% of apps were tested for some form of broken access control.
Some examples:
- Manual app state modification: These modifications could be URL modification, browser cookies and sessions, or the use of custom API attack tools.
- Key identifier change: This allows the alteration of key identifiers, like the user’s primary key, in such a way that gives unwanted access to another user to perform actions otherwise unauthorized.
- Privilege escalation: This is a known method of attack where an attacker logs into a business database as an administrator. This attack can take the form of acting as an authenticated user without authentication.
Example snippet
If we look at the following authentication URL we can see the parameters that are being passed:
https://example.com/accounts/details?id=123&access_key=abcdefg&access_secret=opensecret
An attacker may change the URL parameters such as the ID, ACCESS_KEY, and ACCESS_SECRET to anything malicious, giving them access to account information. Via this attack sensitive information might be leaked or altered.
How can you solve it?
Validation and verification of requests should always be in place. Role-based permissions and object-level permissions should also be implemented, so that authorization can be verified between the authorized user and the requested object resource. Below is a simple example of such validation and verification:
def update_details(request, acc_id): user = Account.objects.get(acc=acc_id) if request.user.id == user.id: # ALLOW ACTION # VALIDATE REQUEST DATA form = AccountForm(instance=user,request=request) ... else: # DENY ACTION
Developers vs. Security: Friends or foes?
Sometimes developers and the security team do not really vibe. This might result from the fact that they have somewhat of conflicting interests. Developers might be focused on creating useful features (a.s.a.p.) and only collaborates with security teams during investigations, remediations, and changes to vulnerable code. Security teams (e.g. SecOps and/or AppSec) might be focused more on ensuring developers write secure software and use secure dependencies. They might also create security guardrails through training, testing, tooling, and pipeline integration. They will also investigate events that could be security incidents or breaches.
To sum this up a developer wants to create new lines of code to create features as fast as possible, where the security teams want them to be diligent and secure. How can we make these teams collaborate better?
Cisco AppDynamics with Secure Application
Cisco might be able to help out with this conflict of interest. Unfortunately, it cannot solve it completely, however it can help to relieve some of the friction.
This tool can detect application code dependency and configuration-level security vulnerabilities in production with automatic runtime protection. It will continuously monitor vulnerabilities to find and even block exploits automatically, maximizing speed and uptime while minimizing risk. As earlier mentioned, Cisco Secure Application is a Runtime Application Self-Protection (RASP) solution for modern applications by defending against attacks to prevent breaches. Most importantly, it simplifies the life cycle of vulnerability fixes by giving both developers and security teams a common interface to work with. A small note: at the time of writing this blog post, Cisco Secure Application only works for Java AppDynamics agent, however the support is being built out to the rest of the agents as we speak.
You made it to the end of this blog post! Thanks! As a reward, I have some more info for you to check out:
We’d love to hear what you think. Ask a question or leave a comment below.
And stay connected with Cisco DevNet on social!
LinkedIn | Twitter @CiscoDevNet | Facebook | Developer Video Channel
Share: