Unmasking Security Flaws: A Deep Dive into System Vulnerabilities and Misconfigurations

For some of my clients, I look at the software that they have had custom built and look at if it is “Fit for purpose”. One of my clients have very high security requirements, where they need to have the systems that they use be hardened and secured. This means that their internal systems are mature, everyone has individual accounts, networks are vlanned, systems are logged centrally, and they manage their exposure appropriately. They have a bespoke application that is hosted on their internal servers, and internet accessible.

While the system is not critical, it is hosted within the internal network and a breach of that server would have the potential to have lateral movement within their systems. I was poking about at it using tools such as OWASP ZAP and found a few small issues that needed to be addressed, but nothing to cause alarm.

Knowing the context of the client, and what they expect of their systems, I decided to do some manual probing and look at flows of the user accounts to ensure that their expectations are meet.

I do not have access to the code, so I had to interact as though I was an attacker. I quickly determined (from the OWASP ZAP results) what the likely OS, server, and framework it was written in. And from there, I looked at the obvious URLs that are for user and account creation. Whilst the home page did not have any links to register an account, I knew what the default URL should be.

I quickly found that the /Identity/Account/Register page had three elements removed, the submit button, the password input field, and the confirm password input field. Given that the page rendered, I had an inkling that the controller was still active. Hitting F12, I located the form in the DOM and created two new fields to fill in the password and the confirm password.

HTML
<div class="form-group">
    <label for="Input_Password">Password</label>
    <input class="form-control" type="password" data-val="true" data-val-required="The Password field is required." id="Input_Password" name="Input.Password" value="A.Rand0m-Pa33w0rd">
    <span class="text-danger field-validation-valid" data-valmsg-for="Input.Password" data-valmsg-replace="true"></span>
</div>
<div class="form-group">
    <label for="Input_ConfirmPassword">Confirm Password</label>
    <input class="form-control" type="password" data-val="true" data-val-required="The Confirm Password field is required." id="Input_ConfirmPassword" name="Input.ConfirmPassword" value="A.Rand0m-Pa33w0rd">
    <span class="text-danger field-validation-valid" data-valmsg-for="Input.ConfirmPassword" data-valmsg-replace="true"></span>
</div>
HTML

I then went to the console and used the following:

JavaScript
document.querySelector("form").submit();
JavaScript

Amazingly this allowed me to create an account, sign in, and then start accessing the systems behind the login. By just removing the UI elements, the system did not meet the requirement to prevent the public from creating an account. Further, there was not an email address validation system that may have prevented the account based on the domain name or putting it into a quarantine until approved. The email address I used also did not receive any form of address confirmation to validate that the user requesting the account actually controlled that email address.

I quickly contacted the stakeholder responsible for this system and explain in detail what I had found. A little back and forth about the system, and the background into the Important Technical Decision that had been to select the Identity management system. They exclaimed that they had selected a specific Identity management system because it would work with the tech stack and was the “most secure” system available at the time. They then followed on with: “I guess it had not aged well with what you just found”.

The system was using the Microsoft provided ASP.NET core identity system. It was setup to be a simple system, with very simple authentication and authorisation scenario, but the key here was, the requirements (both explicit, and implicit with the clients context of high levels of security) were not well understood by the developer; further the system was not appropriately reviewed, or tested to ensure that it met the requirements and the removal of the user account sign up process worked as required. Critical parts of the software development lifecycle are missing, and it highlighted that a Secure Software Development Lifecycle was not implemented.

In response to the stakeholder, I provided the context that the identification system was fine and was not compromised nor vulnerable. This was a misconfiguration of the system, and a poor implementation of the requirement to prevent external users from signing up to the service. i.e. the risks were not managed during the software development lifecycle.

Additional risks that were not mitigated here after a successful account creation included:

  • A new user could upload files.
    • Whilst file extension limited, no real validation done server side that an image was an image.
    • The files that were uploaded were stored on the C drive, and could be abused by someone wanting to cause a reduction in service by uploading a lot of larger files.
      • A deeper look into the permissions of the folder was not investigated, but if not setup correctly, the directory could have execution rights.
  • Any email could be used to sign up.
    • The email address was not validated during the sign-up flow meaning that any value could be used including email addresses of the legitimate domain.
    • The email address domain was not limited to only specified domains.
  • The removal of UI elements of a form did not prevent the submission of the form.
    • The server side did not do validation, preventing the additional fields from being submitted.
    • The controller was not locked behind an [Authorized] tag.