Or press ESC to close.

Part 2: Automating Tests for OWASP Top 10 Vulnerabilities - A QA Engineer's Guide

Jun 2nd 2024 12 min read
medium
security
web
python3.12.1

In the first part of this series, we explored the importance of web application security and delved into automated testing strategies for the initial five vulnerabilities in the OWASP Top 10. By understanding and implementing the discussed testing methods, QA engineers can significantly enhance the security of their web applications, ensuring that common vulnerabilities are identified and mitigated early in the development process.

Building on the foundation laid in Part 1, this post will focus on automated testing methods for the remaining five vulnerabilities in the OWASP Top 10. As web applications grow in complexity, it is crucial to adopt comprehensive testing strategies that cover all potential security risks. This post aims to equip QA engineers with practical tools and techniques to identify and address these additional vulnerabilities, further strengthening the overall security posture of their applications.

In this part, we will cover the following five vulnerabilities:

By the end of this post, we will have a comprehensive understanding of how to automate tests for these vulnerabilities, ensuring a more secure web application environment.

A06:2021-Vulnerable and Outdated Components

Vulnerable and outdated components refer to the use of software libraries, frameworks, and other dependencies that have known security vulnerabilities or are no longer maintained. These components can introduce significant security risks to an application if they are not regularly updated to their latest versions.

Common Risks and Impacts:

Testing Strategy:

General Approach to Identifying Outdated or Vulnerable Components:

Code Example:

Here's an example of a Python script that runs npm audit to check for vulnerabilities in a Node.js project.

                                     
import subprocess


def check_npm_audit(project_dir):
    command = ["npm", "audit"]
    process = subprocess.Popen(command, cwd=project_dir, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    output, error = process.communicate()
    output = output.decode()
    error = error.decode()
                        
    if "found 0 vulnerabilities" in output:
        print(f"No vulnerabilities found in {project_dir}")
        return False
    else:
        print(f"Vulnerabilities found in {project_dir}:\n {error}")
        return True
                        
                        
project_dir = "/path/to/your/node/project"
has_vulnerabilities = check_npm_audit(project_dir)
                        
if has_vulnerabilities:
    print("It is recommended to address the identified vulnerabilities.")
else:
    print("Your project appears to be free of vulnerabilities based on npm audit.")
                    

The script defines a function check_npm_audit that sets the path to a Node.js project directory and executes npm audit to check for vulnerabilities. It uses the subprocess module to run the command within the specified directory. The output of the audit is captured and decoded. If no vulnerabilities are found, the script prints a confirmation message. If vulnerabilities are detected, it prints the error details.

A07:2021-Identification and Authentication Failures

Identification and Authentication Failures occur when an application incorrectly implements authentication mechanisms, allowing attackers to gain unauthorized access. These failures can arise from poor password policies, lack of multi-factor authentication (MFA), or inadequate session management.

Common Scenarios and Their Effects:

Testing Strategy:

General Approach to Testing for Identification and Authentication Issues:

Code Example:

Here's an example using pyotp to automate the testing of multi-factor authentication (MFA) in a web application.

                                     
import requests
import pyotp
                        
# URL of the login endpoint
login_url = 'http://example.com/login'
                        
# URL of the MFA endpoint
mfa_url = 'http://example.com/mfa'
                        
# Login credentials
username = 'testuser'
password = 'testpassword'
                        
# Secret key for TOTP (this should be securely stored and managed)
totp_secret = 'JBSWY3DPEHPK3PXP'
                        
                        
def login_with_mfa():
    try:
        # Step 1: Perform the initial login to get a session token
        login_data = {
            'username': username,
            'password': password
        }
        session = requests.Session()
        login_response = session.post(login_url, data=login_data)
                        
        # Check if login was successful
        if login_response.status_code != 200:
            print("Initial login failed.")
            return
                        
        # Step 2: Generate TOTP code
        totp = pyotp.TOTP(totp_secret)
        mfa_code = totp.now()
                        
        # Step 3: Submit the MFA code
        mfa_data = {
            'mfa_code': mfa_code
        }
        mfa_response = session.post(mfa_url, data=mfa_data)
                        
        # Check if MFA was successful
        if mfa_response.status_code == 200:
            print("MFA login successful.")
        else:
            print("MFA login failed.")
    except Exception as e:
        print(f"An error occurred during MFA testing: {e}")
                        
                        
# Run the MFA test
login_with_mfa()
                    

This script automates the testing of multi-factor authentication (MFA) using requests and pyotp. It first performs the initial login by sending a POST request with the username and password to the login endpoint. If the login is successful, it generates a time-based one-time password (TOTP) using the pyotp library and the secret key associated with the user. The script then submits the TOTP code to the MFA endpoint. Finally, it checks the response to determine if the MFA login was successful.

A08:2021-Software and Data Integrity Failures

Software and Data Integrity Failures occur when an application relies on untrusted sources for software updates, critical data, or CI/CD pipelines without verifying their integrity. This can lead to unauthorized access, data corruption, or execution of malicious code.

Common Scenarios and Impacts:

Testing Strategy:

General Approach to Testing for Integrity Issues:

Code Example:

Here's an example using Python to verify the integrity of a downloaded file using a checksum:

                                     
import hashlib
import requests
                        
# URL of the file to download
file_url = 'http://example.com/software/update.zip'
# Expected SHA-256 checksum of the file
expected_checksum = '5d41402abc4b2a76b9719d911017c592'
                        
                        
def download_file(url, local_filename):
    with requests.get(url, stream=True) as r:
        r.raise_for_status()
        with open(local_filename, 'wb') as f:
            for chunk in r.iter_content(chunk_size=8192):
                f.write(chunk)
    return local_filename
                        
                        
def calculate_checksum(file_path):
    sha256_hash = hashlib.sha256()
    with open(file_path, 'rb') as f:
        for byte_block in iter(lambda: f.read(4096), b''):
            sha256_hash.update(byte_block)
    return sha256_hash.hexdigest()
                        
                        
def verify_file_integrity(url, expected_checksum):
    local_filename = 'update.zip'
    download_file(url, local_filename)
    actual_checksum = calculate_checksum(local_filename)
    assert actual_checksum == expected_checksum, "File integrity verification failed. Checksums do not match."
    print("File integrity verified. Checksums match.")
                        
                        
verify_file_integrity(file_url, expected_checksum)
                    

This script automates the verification of a file's integrity using a checksum. It first downloads the file from the specified URL and saves it locally. The script then calculates the SHA-256 checksum of the downloaded file and compares it with the expected checksum using an assertion. If the checksums do not match, the assertion raises an error with a message indicating that the file integrity verification failed. If the checksums match, it prints a message indicating that the file integrity is verified.

A09:2021-Security Logging and Monitoring Failures

Security Logging and Monitoring Failures occur when an application does not properly log security-relevant events or fails to monitor these logs effectively. This can lead to undetected security breaches, inadequate forensic analysis, and delayed incident response.

Importance of Proper Logging and Monitoring:

Testing Strategy:

General Approach to Testing Logging and Monitoring Mechanisms:

Code Example:

Here's an example using Python to check if specific security events are being logged properly.

                                     
import os

# Path to the log file
log_file_path = '/var/log/application/security.log'
                        
# List of events to check in the log file
security_events = [
    'User login',
    'Failed login attempt',
    'User logout',
    'Data access',
    'Configuration change'
]
                        
                        
def check_log_file(log_file_path, security_events):
    if not os.path.exists(log_file_path):
        raise FileNotFoundError(f"Log file not found: {log_file_path}")
                        
    with open(log_file_path, 'r') as log_file:
        log_contents = log_file.read()
                        
    for event in security_events:
        assert event in log_contents, f"Security event '{event}' not found in log file."
                        
    print("All specified security events are properly logged.")
                        
                        
check_log_file(log_file_path, security_events)
                    

This script checks whether specific security events are being logged properly. It first verifies that the log file exists. It then reads the contents of the log file and checks for the presence of each specified security event using assertions. If any event is not found in the log file, an assertion error is raised with a message indicating the missing event. If all events are found, it prints a message confirming that all specified security events are properly logged.

A10:2021-Server-Side Request Forgery (SSRF)

Server-Side Request Forgery (SSRF) occurs when an attacker can manipulate a server to make unintended requests to internal or external resources. This can lead to unauthorized access to internal systems, data leakage, and even remote code execution.

Common Scenarios and Their Effects:

Testing Strategy:

General Approach to Testing for SSRF Vulnerabilities:

Code Example:

Here's an example using Python to automate the detection of SSRF vulnerabilities:

                                     
import requests

# URL of the web application endpoint to test
url = 'http://example.com/fetch-resource'
                        
# List of SSRF payloads to test
payloads = [
    'http://localhost:80',
    'http://127.0.0.1:80',
    'http://169.254.169.254/latest/meta-data/',  # AWS metadata service
    'http://internal-service:8080'
]
                        
                        
def test_ssrf(url, payloads):
    for payload in payloads:
        response = requests.get(url, params={'url': payload})
        # Check for signs of SSRF in the response
        if response.status_code == 200 and 'internal' in response.text:
            print(f"Potential SSRF vulnerability detected with payload: {payload}")
        else:
            print(f"Payload {payload} did not succeed.")
                        
                        
test_ssrf(url, payloads)
                    

This script tests for SSRF vulnerabilities by sending various payloads to a web application's endpoint that fetches remote resources. It iterates through a list of payloads, making GET requests with each payload as a parameter. The script checks the response for signs of SSRF, such as specific keywords or status codes indicating access to internal resources. If a potential SSRF vulnerability is detected, it prints a message with the problematic payload.

Conclusion

In this post, we covered the importance of testing for the remaining five critical web application vulnerabilities from the OWASP Top 10. We discussed their impacts, provided testing strategies, and shared practical code examples to help you detect and mitigate these risks.

All the code examples provided in this blog post are available on our GitHub page.

Please exercise caution and ensure you have the necessary permissions when executing these tests on resources that do not belong to you.