zer0pts CTF 2022
Writeup for the zer0pts CTF 2022
Updated:
Web
GitFile Explorer
77 points
181 solves
Read
/flag.txt
on the server.
The source code revealed that in order to trigger the file_get_contents
function, the input must match the defined expression.
First, github
or gitlab
or bitbucket
must exist in the service
parameter to get a crafted URL, which for github
it will concatenate with the other parameters with a /
in between.
Then, the crafted URL has to begin with http
, followed by any characters then //
, any characters then either github
or gitlab
or bitbucket
. The regex applies for multiline input.
<?php
function h($s) { return htmlspecialchars($s); }
function craft_url($service, $owner, $repo, $branch, $file) {
if (strpos($service, "github") !== false) {
/* GitHub URL */
return $service."/".$owner."/".$repo."/".$branch."/".$file;
} else if (strpos($service, "gitlab") !== false) {
/* GitLab URL */
return $service."/".$owner."/".$repo."/-/raw/".$branch."/".$file;
} else if (strpos($service, "bitbucket") !== false) {
/* BitBucket URL */
return $service."/".$owner."/".$repo."/raw/".$branch."/".$file;
}
return null;
}
$service = empty($_GET['service']) ? "" : $_GET['service'];
$owner = empty($_GET['owner']) ? "ptr-yudai" : $_GET['owner'];
$repo = empty($_GET['repo']) ? "ptrlib" : $_GET['repo'];
$branch = empty($_GET['branch']) ? "master" : $_GET['branch'];
$file = empty($_GET['file']) ? "README.md" : $_GET['file'];
if ($service) {
$url = craft_url($service, $owner, $repo, $branch, $file);
if (preg_match("/^http.+\/\/.*(github|gitlab|bitbucket)/m", $url) === 1) {
$result = file_get_contents($url);
}
}
?>
The function file_get_contents
can also read local files when the protocol is not recognised, which https//
, without the colon :
, is used to match the regex but an invalid protocol.
The remaining was pretty straightforward, by using github
to match the regex but will be ignored as not found.
The flag is located at /flag.txt
which should be able to access by ../../../../../flag.txt
. The other parameters were given ..
as it will be concatenated as ../
, and the last parameter was given ../../flag.txt
to finish the path.
The full request was service=https//github&owner=..&repo=..&branch=..&file=../../flag.txt
and the flag was read successfully.
Flag: zer0pts{foo/bar/../../../../../directory/traversal}
Comments