5 min read

Pwning the portal: from database dump to session hijacking

Introduction

I find that doing bug hunting and responsible disclosure is a nice practical way to “learn by doing” for beginners and for practicing your recon and exploit skills while helping companies stay secure. This is a responsible disclosure write-up about a series of vulnerabilities that lead to information disclosure, database dump, and account takeover, among others.

Disclaimer:
Due to the confidentiality of the findings and associated targets, we will not mention the target details and will redact any identifiable information. The company in question had authorized public bug hunting against its systems. Any steps mentioned herein are for educational purposes and should not be used to attack systems you have not been given permission to perform such attacks on.  Bitcrack Cyber Security has already responsibly disclosed the vulnerabilities to the target company through their responsible disclosure policy.

Reconnaissance

Gathering as many subdomains of the target as possible is an important step to broaden your attack surface. The more surface one has to look for bugs, the more probable it is to find some.

The bug bounty community has focused a lot on reconnaissance over the last years with tools and services such as Projectdiscovery.io | Chaos, Security Trails. For this phase, I decided to not spend too much time and use tools and services that are already part of my automation, i.e.

  • Query certificates based on the target organization’s name on crt.sh
  • Do a reverse WHOIS lookup using reversewhois.io
  • Use Project Discovery’s subfinder

After gathering the subdomains and filtering the ones responsive to the HTTP protocol, the next step was to fuzz all of the hosts for “quick wins” using a custom wordlist of known vulnerability identifiers, and leaks and exposures developers might have misconfigured. One host caught my eye when I discovered that an SVN repository was publicly available:

SVN repository detection

A closer look…

The host was a portal for the target company employees. It has a login page with additional functionalities such as password change and a “forgot password” functionality. One can also register for the portal but, since it’s a corporate portal, one has to “request” for an account by providing company data.

An SVN repository has no different purpose than a Git repository. Both SVN and Git are version control systems, with the difference that SVN is a centralized solution, unlike the distributed system Git. It can contain source code, sensitive information, or anything the developers have used for building the web application, without constraining any public access.

Extracting an SVN repository can be easily done with the help of tools such as svn-extractor. By downloading and exploring the repository I came to the conclusion that it contained the source code for the portal, both for authenticated and unauthenticated parts of the application. Before anything, I used grep to catch any sensitive words such as password, admin, apiKey etc. Here I had the first “win”, with some database credentials

Database credentials

Blackbox approach

Although I was in the advantageous position of having the source code of the application, I decided to first test my skills of approaching a target with zero knowledge of the source code.

The blackbox testing approach resulted in multiple issues:

  1. Two endpoints vulnerable to blind SQLi. One GET request and one POST request.
  2. Two reflected XSS’, all in POST requests.
SQLi detection

Showing SQLi impact

The blind SQLi on the GET request endpoint could be exploited with a time-based blind SQLi payload. The end result of the payload was:

https://vulnerable-site.tld/portal/index.php=a'+AND+(SELECT+111+FROM+(+SELECT+(SLEEP(5)))aaa)--+bbb

With the help of the great and well-known  tool sqlmap, I was able to extract database information such as database names, users and their privileges, table and column names, their entries, as well as a sample of the users’ entries with the following columns:

userId,userType,userEmail,userGroup,userPhone,userActive,userClosed,userDelete,userAddress,userCompany,userLastname,userPassword,userUsername,userCloseDate,userCloseUser,userFirstname,userLastLogin,userCreateDate,userCreateUser,userDeleteDate,userDeleteUser,userDepartment,userPrivileges,userDomainLogin,userPasswordOrg,userTransFactor,userLoginAttempts,userPrivilegesHSO,userActivationHash,userClosedBySystem,userHsoPubForAuthor,userPasswordHistory,userPrivilegesHSOPrio,userPasswordLastChange,userPasswordOrgUnCrypt

Note that the last column contains plaintext passwords of users. It is important to note that this is no legacy application and it is still used by employees, as observed by the recent date entries of the column userLastLogin.

Showing XSS’ impact

Unfortunately, both XSS are POST-based XSS’, meaning that they can only be triggered by a POST method, so we’d have to trick the victim into making that request.

This issue can be bypassed by combining the XSS with a CSRF issue, as the application lack CSRF protection. That way, by sending a link from a malicious host we control, we can force the victim into making a POST request with our malicious payload:

<html>
  <body>
  <script>history.pushState('', '', '/')</script>
    <form action="http://vulnerable-site/portal/index.php" method="POST">
      <input type="hidden" name="loginParameter" value="&quot;&gt;&lt;script&gt;alert&#40;1&#41;&lt;&#47;script&gt;&quot;" />
      <input type="hidden" name="languageParameter" value="en" />
      <input type="hidden" name="passwordParameter" value="password" />
      <input type="hidden" name="redirectParameter" value="" />
      <input type="hidden" name="actionParameter" value="checkLogin" />
      <input type="submit" value="Submit request" />
    </form>
    <script>
      document.forms[0].submit();
    </script>
  </body>
</html>

Code reviewing and uncovering more issues

After spending some time on the blackbox approach, I decided to take a look at the source code. I had the feeling that, since there were such issues on the unauthenticated side of the application, there should be more of them on the authenticated side as well.

After analyzing some code, I found the pattern which the developers used to make SQL statements and reflect user input in the source code. A quick way to find possible SQLi and XSS issues is, again, by using grep. The queries

grep -iorE "^.*SELECT.*WHERE.*" ./* 

and

grep -nrE ".* echo \( isset \( .+_(POST|GET)" ./* 

returned strings in the code that match the regex pattern.

Results of grep -iorE "^.*SELECT.*WHERE.*" ./*:

Possible SQLis

We see in multiple lines that the user input is being passed into the query without any filtering, which can later be confirmed by analyzing which variable is being assigned based on user input in the code.

Results of grep -nrE ".* echo \( isset \( .+_(POST|GET)" ./*:

Possible XSS’

Here we also see that the values of the HTTP parameters are being reflected un-sanitized, leading to XSS’.

Through that way, I was able to uncover authenticated SQLi’s as well as authenticated POST-/GET-based reflected XSS’, which could make session hijacking possible, since the victim can have a valid session.

Additionally, through code reviewing, it was also discovered that through the “Forgot Password” functionality, a user would get the username and password received in an email in plaintext, which violates best practices as this can also indicate that the password is being stored in plaintext in the database instead of with a secure hashing algorithm.