Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Local File Inclusion Vulnerability #293

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
package org.sasanlabs.service.vulnerability.lfi;

import static org.sasanlabs.vulnerability.utils.Constants.NULL_BYTE_CHARACTER;

import java.io.File;
import java.io.IOException;
import java.util.*;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.sasanlabs.internal.utility.LevelConstants;
import org.sasanlabs.internal.utility.Variant;
import org.sasanlabs.internal.utility.annotations.AttackVector;
import org.sasanlabs.internal.utility.annotations.VulnerableAppRequestMapping;
import org.sasanlabs.internal.utility.annotations.VulnerableAppRestController;
import org.sasanlabs.service.vulnerability.pathTraversal.PathTraversalVulnerability;
import org.sasanlabs.vulnerability.types.VulnerabilitySubType;
import org.sasanlabs.vulnerability.types.VulnerabilityType;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestParam;

@VulnerableAppRestController(
descriptionLabel = "URL_BASED_LFI_INJECTION",
value = "LocalFileInclusion",
type = {VulnerabilityType.LFI})
public class LFIVulnerability {

private static final transient Logger LOGGER =
LogManager.getLogger(PathTraversalVulnerability.class);

private static final String URL_PARAM_KEY = "file";

@AttackVector(
vulnerabilityExposed = VulnerabilitySubType.LFI,
description = "LFI_URL_DIRECT_INJECTION")
@VulnerableAppRequestMapping(
value = LevelConstants.LEVEL_1,
descriptionLabel = "LFI_URL_PARAM_BASED_DIRECT_INJECTION",
htmlTemplate = "LEVEL_1/LFI")
public ResponseEntity<String> getVulnerablePayloadLevelUnsecure(
@RequestParam Map<String, String> queryParams) {
StringBuilder payload = new StringBuilder();
String queryParameterURL = queryParams.get(URL_PARAM_KEY);
if (queryParameterURL != null) {
try {
File file =
new File(
"src/main/java/org/sasanlabs/service/vulnerability/lfi/"
+ queryParameterURL);
Scanner reader = new Scanner(file);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is scanner the best way to read file?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure, do you have a suggestion?

Copy link
Member

@preetkaran20 preetkaran20 Jul 8, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

May be buffered reader but not sure if there are any new libraries which can be more better. Please check.

String data = "";
while (reader.hasNextLine()) {
data = data + reader.nextLine();
}
payload.append(data);
reader.close();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please close the reader in finally block or better use try with resourcr

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alright!

} catch (IOException e) {
LOGGER.error("Following error occurred:", e);
}
}

return new ResponseEntity<String>(payload.toString(), HttpStatus.OK);
}

@AttackVector(
vulnerabilityExposed = VulnerabilitySubType.LFI,
description = "LFI_URL_DIRECT_INJECTION_WITH_VALIDATION_ON_FILE")
@VulnerableAppRequestMapping(
value = LevelConstants.LEVEL_2,
descriptionLabel = "LFI_URL_PARAM_BASED_INJECTION_WITH_VALIDATION_ON_FILE",
htmlTemplate = "LEVEL_1/LFI")
public ResponseEntity<String> getVulnerablePayloadLevelUnsecureLevel2(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please try queryparam by name injection instead of map.

@RequestParam Map<String, String> queryParams) {
StringBuilder payload = new StringBuilder();
String queryParameterURL = queryParams.get(URL_PARAM_KEY);
if (queryParameterURL != null && queryParameterURL.contains(NULL_BYTE_CHARACTER)) {
try {
queryParameterURL = queryParameterURL.replace(NULL_BYTE_CHARACTER, "");
File file =
new File(
"src/main/java/org/"
+ "sasanlabs/service/vulnerability/lfi/"
+ queryParameterURL);
Scanner reader = new Scanner(file);
String data = "";
while (reader.hasNextLine()) {
data = data + reader.nextLine();
}
payload.append(data);
reader.close();
} catch (IOException e) {
LOGGER.error("Following error occurred:", e);
}
}

return new ResponseEntity<String>(payload.toString(), HttpStatus.OK);
}

@AttackVector(
vulnerabilityExposed = VulnerabilitySubType.LFI,
description = "LFI_URL_DIRECT_INJECTION_DOT_DOT_SLASH")
@VulnerableAppRequestMapping(
value = LevelConstants.LEVEL_3,
descriptionLabel = "LFI_URL_PARAM_BASED_INJECTION_WITH_DOT_DOT_SLASH",
htmlTemplate = "LEVEL_1/LFI")
public ResponseEntity<String> getVulnerablePayloadLevelUnsecureLevel3(
@RequestParam Map<String, String> queryParams) {
StringBuilder payload = new StringBuilder();
String queryParameterURL = queryParams.get(URL_PARAM_KEY);
if (queryParameterURL != null && queryParameterURL.equals("../passwords.txt")) {
try {
queryParameterURL = queryParameterURL.replace("..", "secretFiles");
File file =
new File(
"src/main/java/org/"
+ "sasanlabs/service/vulnerability/lfi/"
+ queryParameterURL);
Scanner reader = new Scanner(file);
String data = "";
while (reader.hasNextLine()) {
data = data + reader.nextLine();
}
payload.append(data);
reader.close();
} catch (IOException e) {
LOGGER.error("Following error occurred:", e);
}
}

return new ResponseEntity<String>(payload.toString(), HttpStatus.OK);
}

@AttackVector(
vulnerabilityExposed = VulnerabilitySubType.LFI,
description = "LFI_URL_DIRECT_INJECTION_WHITELISTING")
@VulnerableAppRequestMapping(
value = LevelConstants.LEVEL_4,
variant = Variant.SECURE,
descriptionLabel = "LFI_URL_PARAM_BASED_DIRECT_INJECTION",
htmlTemplate = "LEVEL_1/LFI")
public ResponseEntity<String> getVulnerablePayloadLevelUnsecureLevel4(
@RequestParam Map<String, String> queryParams) {
StringBuilder payload = new StringBuilder();
String queryParameterURL = queryParams.get(URL_PARAM_KEY);
String[] files = new String[] {"secretFiles/passwords.txt"};
List<String> protectedFiles = new ArrayList<>(Arrays.asList(files));
if (queryParameterURL != null && protectedFiles.contains(queryParameterURL) == false) {
try {
File file =
new File(
"src/main/java/org/"
+ "sasanlabs/service/vulnerability/lfi/"
+ queryParameterURL);
Scanner reader = new Scanner(file);
String data = "";
while (reader.hasNextLine()) {
data = data + reader.nextLine();
}
payload.append(data);
reader.close();
} catch (IOException e) {
LOGGER.error("Following error occurred:", e);
}
} else {
payload.append("You don't have access to this data");
}

return new ResponseEntity<String>(payload.toString(), HttpStatus.OK);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<h2>TOP SECRET PASSWORDS</h2>

Copy link
Member

@preetkaran20 preetkaran20 Jul 4, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we don't need a special file, use /etc/passwd and equivalent for windows.

<p>USER1:PQOAJ231</p>
<p>USER2:DKAO1020</p>
<p>USER3:CMVNP325</p>

Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,10 @@ public enum VulnerabilitySubType {
NULL_BYTE(VulnerabilityType.NULL_BYTE),

// XXE Vulnerability
XXE(VulnerabilityType.XXE);
XXE(VulnerabilityType.XXE),

// LFI Vulnerability
LFI(VulnerabilityType.LFI);

private VulnerabilityType vulnerabilityType;

Expand Down
31 changes: 28 additions & 3 deletions src/main/resources/i18n/messages.properties
Original file line number Diff line number Diff line change
Expand Up @@ -203,9 +203,34 @@ COMMAND_INJECTION_URL_PARAM_DIRECTLY_EXECUTED_IF_SEMICOLON_SPACE_LOGICAL_AND_%26


# Local File Injection
#URL_BASED_LFI_INJECTION=Url based Local File Injection attack.
#LFI_URL_PARAM_BASED_DIRECT_INJECTION=Url Parameter \"fileName\" is directly passed to the include file.
#LFI_URL_PARAM_BASED_INJECTION_WITH_VALIDATION_ON_FILE=Url Parameter \"fileName\" is validated and passed to include file.
URL_BASED_LFI_INJECTION=LFI vulnerabilities allow an attacker to read (and sometimes execute) files on the victim machine.\
An attacker can use Local File Inclusion (LFI) to trick the web application into exposing or running files on the web server. \
An LFI attack may lead to information disclosure, remote code execution, or even Cross-site Scripting (XSS). \
Typically, LFI occurs when an application uses the path to a file as input. If the application treats this input \ \
as trusted, a local file may be used in the include statement. \
<br/><br/> Important Links on LFI : \
<ol> \ <li><a href="https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/07-Input_Validation_Testing/11.1-Testing_for_Local_File_Inclusion" target="_blank">\
Testing for Local File Inclusion \</a> \
<li><a \
href="https://www.netsparker.com/web-vulnerability-scanner/vulnerabilities/local-file-inclusion/" target="_blank"> \
Local File Inclusion by netsparker </a> \
</ol>
LFI_URL_PARAM_BASED_DIRECT_INJECTION=Url Parameter \"fileName\" is directly passed to the include file.
LFI_URL_PARAM_BASED_INJECTION_WITH_VALIDATION_ON_FILE=Url Parameter \"fileName\" is validated and passed to include file.
LFI_URL_PARAM_BASED_INJECTION_WITH_DOT_DOT_SLASH=Url Parameter \"fileName\" is validated and passed to include file.
#### AttackVector description
LFI_URL_DIRECT_INJECTION=If the developer fails to implement sufficient filtering an attacker could exploit the local file \
inclusion vulnerability by replacing the path with another path of a sensitive file such as a password file, allowing \
the attacker to see its content.
LFI_URL_DIRECT_INJECTION_WITH_VALIDATION_ON_FILE=The null character is a control character with the value zero present in \
many character sets that is being used as a reserved character to mark the end of a string. Once used, any character after \
this special byte will be ignored. Commonly the way to inject this character would be with the URL encoded string %00 by \
appending it to the requested path, this would ignore the file's extension being added to the input filename, \
returning to an attacker the file information as a result of a successful exploitation.
LFI_URL_DIRECT_INJECTION_DOT_DOT_SLASH=The attacker can see a file content by appending the sequence: dot-dot-slash (../) \
and the file's name in the url.
LFI_URL_DIRECT_INJECTION_WHITELISTING=A way to prevent LFI attacks is with a whitelisting: use verified and secured whitelist \
files and ignore everything else

# Local File Injection with Null Byte
#URL_WITH_NULL_BYTE_BASED_LFI_INJECTION=Url with Null Byte Injection based Local File Injection attack.
Expand Down
31 changes: 28 additions & 3 deletions src/main/resources/i18n/messages_en_US.properties
Original file line number Diff line number Diff line change
Expand Up @@ -203,9 +203,34 @@ COMMAND_INJECTION_URL_PARAM_DIRECTLY_EXECUTED_IF_SEMICOLON_SPACE_LOGICAL_AND_%26


# Local File Injection
#URL_BASED_LFI_INJECTION=Url based Local File Injection attack.
#LFI_URL_PARAM_BASED_DIRECT_INJECTION=Url Parameter \"fileName\" is directly passed to the include file.
#LFI_URL_PARAM_BASED_INJECTION_WITH_VALIDATION_ON_FILE=Url Parameter \"fileName\" is validated and passed to include file.
URL_BASED_LFI_INJECTION=LFI vulnerabilities allow an attacker to read (and sometimes execute) files on the victim machine.\
An attacker can use Local File Inclusion (LFI) to trick the web application into exposing or running files on the web server. \
An LFI attack may lead to information disclosure, remote code execution, or even Cross-site Scripting (XSS). \
Typically, LFI occurs when an application uses the path to a file as input. If the application treats this input \ \
as trusted, a local file may be used in the include statement. \
<br/><br/> Important Links on LFI : \
<ol> \ <li><a href="https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/07-Input_Validation_Testing/11.1-Testing_for_Local_File_Inclusion" target="_blank">\
Testing for Local File Inclusion \</a> \
<li><a \
href="https://www.netsparker.com/web-vulnerability-scanner/vulnerabilities/local-file-inclusion/" target="_blank"> \
Local File Inclusion by netsparker </a> \
</ol>
LFI_URL_PARAM_BASED_DIRECT_INJECTION=Url Parameter \"fileName\" is directly passed to the include file.
LFI_URL_PARAM_BASED_INJECTION_WITH_VALIDATION_ON_FILE=Url Parameter \"fileName\" is validated and passed to include file.
LFI_URL_PARAM_BASED_INJECTION_WITH_DOT_DOT_SLASH=Url Parameter \"fileName\" is validated and passed to include file.
#### AttackVector description
LFI_URL_DIRECT_INJECTION=If the developer fails to implement sufficient filtering an attacker could exploit the local file \
inclusion vulnerability by replacing the path with another path of a sensitive file such as a password file, allowing \
the attacker to see its content.
LFI_URL_DIRECT_INJECTION_WITH_VALIDATION_ON_FILE=The null character is a control character with the value zero present in \
many character sets that is being used as a reserved character to mark the end of a string. Once used, any character after \
this special byte will be ignored. Commonly the way to inject this character would be with the URL encoded string %00 by \
appending it to the requested path, this would ignore the file's extension being added to the input filename, \
returning to an attacker the file information as a result of a successful exploitation.
LFI_URL_DIRECT_INJECTION_DOT_DOT_SLASH=The attacker can see a file content by appending the sequence: dot-dot-slash (../) \
and the file's name in the url.
LFI_URL_DIRECT_INJECTION_WHITELISTING=A way to prevent LFI attacks is with a whitelisting: use verified and secured whitelist \
files and ignore everything else

# Local File Injection with Null Byte
#URL_WITH_NULL_BYTE_BASED_LFI_INJECTION=Url with Null Byte Injection based Local File Injection attack.
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 4 additions & 4 deletions src/main/resources/static/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
<!-- TODO Add active to mode when clicked-->
<div class="navbar navbar-item">
<div class="navbar-item-menu active" id="home">
<a href="/">Home</a>
<a href="/VulnerableApp">Home</a>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks a lot for the fix.

</div>
<div class="navbar-item-menu" id="about">
<a href="#about">About Us</a>
Expand All @@ -31,7 +31,7 @@
Mode
</div>
<div class="navbar-item-menu">
<a href="https://github.com/SasanLabs/VulnerableApp" target="_blank"><img src="/images/GitHub-Mark-32px.png" /></a>
<a href="https://github.com/SasanLabs/VulnerableApp" target="_blank"><img src="images/GitHub-Mark-32px.png" /></a>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Amazing

</div>
</div>
</div>
Expand Down Expand Up @@ -86,8 +86,8 @@ <h2>How can Vulnerability Scanning Tools use VulnerableApp?</h2>
<br/>
<b>Following are the endpoints exposed: </b>
<ol>
<li><a href="/scanner">Scanner Endpoint</a></li>
<li><a href="/sitemap.xml">SiteMap Endpoint</a></li>
<li><a href="/VulnerableApp/scanner">Scanner Endpoint</a></li>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks a lot this fix.

<li><a href="/VulnerableApp/sitemap.xml">SiteMap Endpoint</a></li>
</ol>

<b>Scanner Endpoint</b><br/>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#LFI_level_1 {
color: black;
text-align: left;
font-size: 18px;
font-weight: normal;
}

#verifyUrl {
background: blueviolet;
display: inline-block;
padding: 4px 4px;
margin: 10px;
border: 1px solid transparent;
border-radius: 2px;
transition: 0.2s opacity;
color: #FFF;
font-size: 12px;
}

#url {
width: 500px
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<div id="LFI_level_1">
<div>
Local file inclusion (also known as LFI) is the process of including files,
that are already locally present on the server, through the exploiting of
vulnerable inclusion procedures implemented in the application.
This vulnerability occurs, for example, when a page receives, as input,
the path to the file that has to be included and this input is not properly
sanitized, allowing directory traversal characters (such as dot-dot-slash)
to be injected.
<br /> <br />
Try to find the password file inside the secretFiles folder using the URL param: <i>file</i>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line sounds like a challenge, which doesn't align with our vulnerable applications mission. Consider this application as a general application which has flaws and let scanners explore and find them.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I will change it.

</div>
<br /> <br />
<div>
<b>please enter a URL:</b>
<input type="text" id="url"/>
<button id="verifyUrl">Verify URL</button>
<div id="verificationResponse"></div>
</div>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
function addingEventListenerToVerifyUrl() {
document.getElementById("verifyUrl").addEventListener("click", function () {
let urlInput = document.getElementById("url").value;
let params = "?file=" + getParameterByName("file", urlInput);
let urlLevel = getUrlForVulnerabilityLevel() + params;
doGetAjaxCall(updateUIWithVerifyResponse, urlLevel, false);
});
}
addingEventListenerToVerifyUrl();

function updateUIWithVerifyResponse(data) {
if (data) {
document.getElementById("verificationResponse").innerHTML = data;
} else {
document.getElementById("verificationResponse").innerHTML = "Try again.";
}
}

function getParameterByName(name, url) {
name = name.replace(/[\[\]]/g, "\\$&");
var regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"),
results = regex.exec(url);
if (!results) return null;
if (!results[2]) return "";
return results[2];
}