Insecure Processing of Data
This category covers the following issues:
Fixing Insecure Deserialization
About Deserialization
What is a Deserialization vulnerability?
Serialization converts complex data structures into a stream of bytes that can be sent or received over a network. Deserialization restores the byte stream to a copy of the previously serialized object. The receiving application can then interact with this deserialized object.
Deserializing attacker-controlled data allows attackers to manipulate serialized objects and pass malicious data to the receiving application.
Alternative terms for Serialization/Deserialization are:
- Marshaling, Unmarshaling
- Pickling, Unpickling
Check out this video for a high-level explanation:
What is the impact of Deserialization vulnerabilities?
Attackers can reuse existing application code in malicious ways which results in a wide range of vulnerabilities such as:
- Code execution: An attacker can exploit deserialization vulnerabilities to execute arbitrary code on a target system, giving them control over the system and access to sensitive data.
- Unauthorized access: An attacker can use deserialization vulnerabilities to access and manipulate data or functionality that they are not authorized to access, such as administrative functions or sensitive data.
- Denial-of-service (DoS) attacks: An attacker can exploit deserialization vulnerabilities to cause DoS attacks, by overloading the system with large amounts of data or by manipulating the data in a way that causes the system to crash or become unresponsive.
How to prevent Deserialization vulnerabilities?
To prevent deserialization vulnerabilities, it is important to follow security best practices and implement appropriate security measures, such as:
- Avoid deserialization of untrusted data: Do not deserialize data from untrusted sources or unvalidated user input.
- Use type checking and input validation: Verify the type and content of serialized data to ensure that it is valid and expected.
- Use secure deserialization libraries and frameworks: Use secure deserialization libraries and frameworks that can help prevent deserialization vulnerabilities and provide additional security features, such as input validation and type checking.
- Apply access controls: Apply access controls to limit the privileges and actions that deserialized data can perform, such as preventing it from executing arbitrary code or accessing sensitive resources.
- Keep software up to date: Keep software and security protocols up to date, as new vulnerabilities and security patches are regularly released.
References
Taxonomies
- OWASP Top 10 - A08 Software and Data Integrity Failures
- SANS TOP 25 - #12
- CWE-502: Improper Restriction of XML External Entity Reference
Explanation & Prevention
Related CVEs
Training
Insecure Deserialization (pickle)
Rule-specific references:
Option A: Use JSON as a secure alternative
Go through the issues that GuardRails identified in the PR/MR
Identify the code that has one of these patterns, for example:
pickle.loads
pickle.loadAnd replace the functionality with what is offered by the JSON module:
Test it, ship it 🚢 and relax 🌴
Option B: Ensure that only safe user input is serialized
Go through the issues that GuardRails identified in the PR/MR
Identify the code that has one of these patterns, for example:
pickle.loads
pickle.loadEnsure that no user input is processed by the dangerous methods, or sanitize the user input to conform with the expected data formats
Test it, ship it 🚢 and relax 🌴
Insecure Deserialization (PyYAML)
This rule detects insecure usages of PyYAML
loaders.
Insecure examples are:
yaml.unsafe_load(input)
yaml.load(input, Loader=yaml.CLoader)
yaml.load(input, Loader=yaml.Loader)
yaml.load(input, Loader=yaml.UnsafeLoader)
yaml.unsafe_load_all(input)
yaml.load_all(input, Loader=yaml.CLoader)
yaml.load_all(input, Loader=yaml.Loader)
yaml.load_all(input, Loader=yaml.UnsafeLoader)
Secure examples are:
yaml.safe_load(input)
yaml.load(input, Loader=yaml.BaseLoader)
yaml.load(input, Loader=yaml.CSafeLoader)
yaml.load(input, Loader=yaml.SafeLoader)
yaml.load_all(input, Loader=yaml.BaseLoader)
yaml.load_all(input, Loader=yaml.CSafeLoader)
yaml.load_all(input, Loader=yaml.SafeLoader)
Option A: Use a secure PyYAML Loader
Go through the issues that GuardRails identified in the PR/MR.
Replace insecure loader functions with a secure alternative.
import yaml
@app.route('/', methods=['GET'])
def index():
user = request.cookies.get('username')
# Insecure example
return "Hey there, {}!".format(yaml.unsafe_load(user))import yaml
@app.route('/', methods=['GET'])
def index():
user = request.cookies.get('username')
# Secure example
return "Hey there, {}!".format(yaml.safe_load(user))Test it
Ship it 🚢 and relax 🌴
Fixing Cross-Site Scripting
About XSS
What is Cross-Site Scripting?
Cross-site scripting (XSS) is a type of security vulnerability that allows attackers to inject malicious code into web pages viewed by other users. This occurs when an application fails to properly sanitize user input and injects untrusted data into a web page without validating or encoding it.
XSS attacks can occur in different forms, such as reflected, stored, or DOM-based, and can affect various types of web applications, including social media, e-commerce, and online banking sites.
Attackers can use various techniques, such as phishing emails, web forms, or malicious links, to trick users into visiting or interacting with web pages that contain malicious code.
Check out this video for a high-level explanation:
What is the impact of Cross-Site Scripting?
Cross-site scripting (XSS) can lead to various security threats and risks, such as:
- Information theft: XSS attacks can steal sensitive information, such as login credentials, credit card details, or other personally identifiable information, by injecting malicious code that collects and transmits user data to attackers.
- Account hijacking: XSS attacks can hijack user sessions by injecting malicious code that takes over user sessions, allowing attackers to perform unauthorized actions on the website or gain access to user accounts.
- Data tampering: XSS attacks can modify or delete data on a website by injecting malicious code that alters the content of web pages, leading to data tampering, data corruption, or other types of malicious activities.
- Malware distribution: XSS attacks can distribute malware by injecting malicious code that downloads and installs malicious software on the user's computer, leading to malware infections or other types of cyber attacks.
Overall, XSS attacks can compromise the confidentiality, integrity, and availability of data, leading to a range of security threats and risks.
How to prevent Cross-Site Scripting?
To prevent XSS vulnerabilities, you can take the following steps:
- Input validation and sanitization: Ensure that all user input is validated and sanitized before being used to generate web pages or manipulate other data. Input validation should include validating the data type, length, and format, and filtering out any special characters that could be used to inject malicious code.
- Output encoding: Encode all output to protect against XSS attacks. Use output encoding techniques such as HTML entity encoding, URL encoding, and JavaScript encoding to encode user input and output to the browser.
- Use security headers: Implement security headers to protect against XSS attacks, such as Content-Security-Policy (CSP) and X-XSS-Protection. CSP can help prevent XSS attacks by allowing only trusted sources of content to be loaded on a page, while X-XSS-Protection can help prevent the browser from rendering pages that contain malicious scripts.
- Session management: Implement secure session management mechanisms, such as session cookies, to protect against session hijacking and other attacks.
- Secure coding practices: Use secure coding practices to prevent XSS vulnerabilities. This includes using libraries and frameworks that are designed to prevent XSS attacks, testing code for vulnerabilities, and using secure coding practices such as input validation and output encoding.
- Regular security audits: Regularly audit your system for security vulnerabilities, including XSS vulnerabilities. Use automated tools and manual testing to identify potential issues and fix them before they can be exploited.
References
Taxonomies
- OWASP Top 10 - A03 Injection
- CWE-79: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
Explanation & Prevention
Related CVEs
Training
Tainted user input marked as safe (Django)
Django has solid HTML escaping defaults. However, it is possible to disable these protection mechanisms.
This rule detects user input flowing into the django.utils.safestring.mark_safe()
function, which results in a cross-site scripting (XSS) vulnerability. Currently, the following functions are considered sanitizers and won't flag the use of mark_safe():
- Django Utils HTML - escape()
- Django Utils HTML - conditional_escape()
- Django Utils HTML - format_html()
- Django Utils HTML - format_html_join()
Rule-specific references:
Option A: Escape user input with format_html()
By using format_html the user input will be properly escaped and thus prevents XSS vulnerabilities.
Go through the issues that GuardRails identified in the PR/MR.
Look for usages of safestring.mark_safe() calls with user input, and replace them with the secure usage shown below.
from django.utils.safestring import mark_safe
from django.http import HttpResponse
from django.template import loader
# Insecure example:
# User input is passed into mark_safe()
def insecure(request):
template = loader.get_template('contents.html')
insecure = mark_safe(
"""
<div>
<p>Contents! %s</p>
</div>
""" % request.POST.get("contents")
)
return HttpResponse(template.render({"html_example": insecure}, request)from django.utils.html import format_html
from django.http import HttpResponse
from django.template import loader
# Secure example:
# User input is escaped by format_html()
def insecure(request):
template = loader.get_template('contents.html')
secure = format_html(
"""
<div>
<p>Contents! {}</p>
</div>
""",
request.POST.get("contents")
)
return HttpResponse(template.render({"html_example": secure}, request)Test it
Ship it 🚢 and relax 🌴
Fixing Insecure XML Processing
About XML External Entities
What is XML External Entities (XXE) injection?
XML External Entities (XXE) injection is a type of security vulnerability that allows attackers to exploit the processing of XML data by an application.
This occurs when an application accepts XML data from an untrusted source and processes it without proper validation, allowing the inclusion of external entities that can be malicious or contain sensitive information.
As a result, attackers can perform various malicious activities, such as stealing user data, executing arbitrary code, or performing denial-of-service attacks.
Check out this video for a high-level explanation:
What is the impact of XXE injection?
XML External Entities (XXE) injection can lead to various security threats and risks, such as:
- Information theft: XXE attacks can steal sensitive information, such as login credentials, credit card details, or other personally identifiable information, by injecting malicious code or entities that collect and transmit user data to attackers.
- Server-side request forgery: XXE attacks can initiate requests to systems that are accessible from the affected web server.
- Denial of service: XXE attacks can cause denial-of-service (DoS) attacks by injecting malicious code or entities that consume system resources, such as CPU or memory, leading to system crashes or slowdowns.
- Arbitrary code execution: XXE attacks can execute arbitrary code on the server by injecting malicious code or entities that exploit vulnerabilities in the application or the underlying operating system.
How to prevent XXE injection?
To prevent XML External Entities (XXE) injection, it is important to follow security best practices and implement appropriate security measures, such as:
- Disable external entity processing: Disable the processing of external entities in XML parsers and libraries to prevent XXE vulnerabilities.
- Use secure parsers and libraries: Use secure parsers and libraries that support secure XML processing.
- Use input validation: Validate user input to ensure that it is safe and does not contain malicious code or entities.
- Keep software up to date: Keep software and security protocols up to date, as new vulnerabilities and security patches are regularly released.
References
Taxonomies
- OWASP Top 10 - A05 Security Misconfiguration
- SANS TOP 25 - #24
- CWE-611: Improper Restriction of XML External Entity Reference
Explanation & Prevention
- OWASP: XXE Processing
- OWASP: XXE Prevention Cheat Sheet
- MSDN Security Briefs - XML Denial of Service Attacks and Defenses
- Identifying XML External Entity vulnerability (XXE)
- WS-Attacks.org: XML Entity Expansion
- WS-Attacks.org: XML External Entity DOS
- WS-Attacks.org: XML Entity Reference Attack
Related CVEs
Training
Tainted input passed to Python XML Processing Modules
The Python XML modules are not secure against erroneous or maliciously constructed data, and depending on the Python version, the impact can be severe.
Rule-specific references:
Option A: Use the defusedxml package
defusedxml
is a pure Python package with modified subclasses of all standard library XML parsers that prevent any potentially malicious operation. Use of this package is recommended for any server code that parses untrusted XML data. The package also ships with example exploits and extended documentation on more XML exploits such as XPath injection.
The defusedxml
package contains workarounds and fixes for DOS and other vulnerabilities in Python's XML libraries.
Go through the issues that GuardRails identified in the PR/MR.
Replace native Python XML libraries with the drop-in replacements of
defusexml
.from xml.etree import ElementTree
import requests
taintedInput = requests.get('https://example.com/evil.xml')
#Insecure example
node = ElementTree.parse(taintedInput)import defusedxml.ElementTree
import requests
taintedInput = requests.get('https://example.com/evil.xml')
#Secure example
node = defusedxml.ElementTree.parse(taintedInput)Test it
Ship it 🚢 and relax 🌴
Fixing server-side request forgery (SSRF)
About SSRF
What is Server-Side Request Forgery (SSRF)?
Server-Side Request Forgery (SSRF) is a type of web application vulnerability that occurs when an attacker can manipulate the server-side code to make it perform unauthorized HTTP requests to other web applications. SSRF attacks can allow an attacker to send requests from the vulnerable server to internal or external network resources, which can result in data leaks, access to sensitive data or even compromise the entire network.
An SSRF attack typically involves an attacker tricking a server into making a request to a specific URL that the attacker controls. The attacker may do this by manipulating the parameters of a URL or by using other techniques to inject malicious code into the server-side code.
What is the impact of Server-Side Request Forgery (SSRF)?
Attackers can use this vulnerability to perform a variety of attacks, such as:
- Information disclosure: The attacker can use an SSRF attack to access sensitive data, such as configuration files, internal documentation or even credentials, which can be used to compromise the entire network.
- Port scanning: The attacker can use an SSRF attack to scan the network for open ports, which can be used to identify potential vulnerabilities in the system.
- Bypassing authentication and authorization: An SSRF attack can be used to bypass authentication and authorization controls by sending requests to internal services that do not enforce these controls.
- Exploiting internal APIs: An SSRF attack can be used to exploit unprotected internal APIs, which can result in unauthorized access to sensitive information or actions that the user is not authorized to perform.
- Denial-of-service (DoS): The attacker can use an SSRF attack to flood the targeted web application with requests or to perform a request to a resource that is not available, causing the application to crash or slow down.
How to prevent Server-Side Request Forgery (SSRF)?
Here are some best practices to prevent SSRF attacks:
- Use secure APIs: Use secure APIs that do not allow arbitrary URLs to be passed as parameters. This can prevent attackers from manipulating the server-side code to perform unauthorized HTTP requests.
- Input validation and sanitization: Validate and sanitize all user input, especially for URLs, to ensure that they are valid and safe. This can prevent attackers from injecting malicious URLs into the server-side code.
- Access controls: Implement access controls to limit access to only authorized users. This can prevent attackers from exploiting unprotected internal APIs or cloud infrastructure.
- Server hardening: Harden servers by removing unnecessary software and services, and limiting access to administrative interfaces. This can prevent attackers from exploiting vulnerabilities in the server-side code or gaining access to sensitive information.
- Network segmentation: Use network segmentation to prevent web applications from accessing internal resources or those that they do not need to access. This can limit the impact of an SSRF attack by preventing the attacker from accessing sensitive resources.
References
Taxonomies
Explanation & Prevention
Related CVEs
Training
This rule detects server-side request forgery (SSRF) vulnerabilities in Python code using the Flask and Requests libraries. It looks for user-supplied data being passed to the Requests library's HTTP methods, which could lead to SSRF if not properly validated or sanitized.
Rule-specific references:
Option A: Restrict allowed domains
Go through the issues that GuardRails has identified
Locate the vulnerable pattern (example below):
@authentication_decorator
def ssrf_lab2(request):
if request.method == "GET":
return render(request, "Lab/ssrf/ssrf_lab2.html")
elif request.method == "POST":
url = request.POST["url"]
try:
response = requests.get(url)
return render(request, "Lab/ssrf/ssrf_lab2.html", {"response": response.content.decode()})
except:
return render(request, "Lab/ssrf/ssrf_lab2.html", {"error": "Invalid URL"})Implement an allow list for domains:
from urllib.parse import urlparse
# Function to validate the URL based on allowed domains
def is_valid_url(url, allowed_domains):
parsed_url = urlparse(url)
return parsed_url.scheme in ['http', 'https'] and parsed_url.netloc in allowed_domains
@authentication_decorator
def ssrf_lab2(request):
if request.method == "GET":
return render(request, "Lab/ssrf/ssrf_lab2.html")
elif request.method == "POST":
url = request.POST["url"]
# Define allowed domains for your application
allowed_domains = ['example.com', 'example.org']
# Validate the user-supplied URL and check if it is in the allowed domains
if not is_valid_url(url, allowed_domains):
return render(request, "Lab/ssrf/ssrf_lab2.html", {"error": "Invalid URL"})
try:
response = requests.get(url)
return render(request, "Lab/ssrf/ssrf_lab2.html", {"response": response.content.decode()})
except:
return render(request, "Lab/ssrf/ssrf_lab2.html", {"error": "Invalid URL"})Test it
Ship it 🚢 and relax 🌴