LFI Reality
- by Vince
-
in Blog
-
Hits: 1577
My original intention was to provide an example of automating Local File Inclusion (LFI) which I'd done previously somewhere on this site using Python. But the point of that post was LFI with Python, not to answer a question someone posed to me in a discussion. Now that I think about it, I wonder if the problems I encountered with this exercise would have also been encountered with a Python script. Hold that thought, I'll work that out in a moment.
Before I digress too much, this post is about automating LFI with Bash but then things got sideways and I thought I'd write about it.
If there's one big takeaway from hacking, I'd say it's this -- what we do is not the intended method for interacting with the application (or interacting with whatever) and we should expect inconsistent results. That was my mistake here.
We have a simple web app:
When we click on one of the links, we notice something in the url:
Pretty standard looking LFI injection point -- if we change the page to a local file:
We can read into the file system. Hence the name, Local File Inclusion (LFI). I hate typing into the address bar and it could make sense to automate this process with a script:
If by chance when you run this script, you encounter a ^? for a backspace, add: stty sane
to the top of the script and that should your problem.
The printf "\033c" is what clears the screen when we run it.
That's our simple script which gives us the ability to read files in the file system.
If you search for Local File Inclusion, you will come across a number of articles that talk about log poisoning but unless we're playing CTF, the reality is that log poisoning won't work in modern Linux systems because the permissions won't match. We're typically acting on behalf of www-data and the permissions are not set for www-data to read the log files. This system is Ubuntu 14.04 and it won't get any better with the more recent releases.
If by chance we could poison the logs, we might want access to /var/log/apache2/access.log and / or error.log but as you can see below:
When we attempt to read the log files, nothing renders back for us to read. If we peer into the logs on the local system, we can see:
We are being denied access to those files.
Ok, so let's say we're playing CTF or someone has managed to set incorrect permissions, we could poison the auth.log file. I've adjusted the permissions:
Basically, we want to inject some PHP into the log and then we'll attempt to read the log through LFI. In order to taint the log file, we can do the following:
This is a pretty basic PHP script for command execution.
<?php echo shell_exec($_GET['e']); ?>
If we saved this into the webroot directory with the name: cmd.php
We could hit this file from a browser and run commands with: /cmd.php?e=id
While reading the logs, we'll use: &e=id
Because we've attempted to login through SSH using this simple statement, we've added an entry into the auth.log file. Looking at the logs, we see:
It strips the single quotes from around the e but that makes no difference.
Now when we hit the log file through the LFI vulnerability, we execute the "id" command:
And as you can see, we have command execution. Issuing the command: "lsb_release -a":
We see that we're running Ubuntu 14.04
Moving back to our script, we execute "ifconfig":
Truncating the additional information and getting to the meat:
We have successfully run an ifconfig. Now the question is -- can we reach out:
With an Netcat listener setup:
We could potentially have Remote File Inclusion capability.
If we try to include a shell with a .php extension, we will pop our own box. We need to include the file with a .txt extension. In some cases, this is enough to catch the shell but not in this scenario.
When we run an "ls", we see our file:
Now here's where my script fails me. I attempt to rename the file using my script but it doesn't work:
I move back to the browser and I attempt the same task:
This time when we run an "ls", we see that it was successful:
When we hit our shell:
With our handler setup:
We catch our shell and we're on the box.
Now back to my tangent, will this work better with Python vs Bash?
We setup our script:
We move our shell in .txt format:
We copy our .txt shell to .php :
We take a look in the file system:
And we see that we are not experiencing the same kind of issues as we did with Bash. I also switched back and forth between Curl and Wget in the Bash script. I had issues with both. The lesson here is that we learn multiple methods and we use whichever method works best for us.