Local File Inclusion (LFI) is a web application vulnerability in which we have some parameter and the parameter has a value from which the data is read. For example, http://target.site/index.php?location=IT
reads the location of the user, now if proper validation is not applied the attacker can insert his malicious payload and can traverse to the web application root directory and read sensitive data.
Local File Inclusion in severe cases can further lead to cross site scripting (XSS) and remote code execution attacks. For detailed description of Local File Inclusion, you can refer to this article on OWASP.
Aim of the challenge was to find and include local file that has flag content and display it on the page.
In provided application we can clearly see that there is an input field for user and the user must enter the URL in the input field and the response will be shown or loaded in the <iframe/>
on same page.
If any URL is not provided in following format http://something.something
, the application will generate error saying 404 not found
shown below:
Invalid URL
URL: localhost/lfi/?proxy=google.com
This makes it clear that http
is necessary for a URL
to be accepted. If proxy or input is provided in proper format, the response will be
Valid URL
URL: localhost/lfi/?proxy=http://google.com
From above behavior it’s clear that some input validation is performed on the input field which is to be bypassed in order to perform the attack.
So, in same direction we will craft our payload. Since http
is allowed, we will check whether https
is supported or not.
Valid URL With https
URL: localhost/lfi/proxy=https://google.com
From above screen shot it is clear that https is also supported.
Step 1: Bypass the valid URL
Now to bypass the valid URL pattern after http we insert a character i.e., httpa://
and we observe that it is accepted. As we can see the regex in the source code
Regex Pattern
if(preg_match("/^http?.[:]\/\//", no_traversal($proxy))){
$response = file_get_contents(no_traversal($proxy), false);
}
where (.) in regex
means to accept any character without line breaks which is a catch here.
Step 2: Bypass the pattern.
Further we observe that ../ pattern that we use for traversal to the file is filtered. So to bypass the filter we use the nested traversal sequences such as
….// which reverts the simple traversal sequences.
Note: Here we can also use the URL encoded characters.
As we know that we use /etc/passwd
to get information of registered users in Linux, by appending to our previously created payload i.e., http1://a....//....//....//....//....//....//....//etc/passwd we observe that
we are able to read the information.
Payload Output
Step 3: Find The Hidden Flag
Now that we have successfully bypassed the filter the only thing remaining is to find the hidden flag. As we know that the hidden flag is mostly stored is home directory. So in the home directory in the flag.txt file we find our flag.
Your final payload will be similar to
proxy=http1://a....//....//....//....//....//....//....//home/flag.txt
Hidden Flag
In order to mitigate the vulnerability in the above challenge we should compare the validation against a whitelist of permitted values.
But in some cases it is not possible for the required functionality, so in that cases we should verify that input does not contain any malicious characters or patterns.
We should allow regex with only http and https i.e. ^https?://
and also we just filtered the sequences such as ( ../
), but the nested traversal sequences such as (....//
), should have also been filtered.
We are always posting such challenges. We also give rewards and shoutouts to winners of challenges. To participate in such challenges follow us on Twitter, Linkedin, and Instagram.
To increase the arsenal of your knowledge you can also check our latest blogs.