Prevention of unauthorized access to sensitive files on the server
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class VulnerableServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String fileName = request.getParameter("file");
ServletContext context = getServletContext();
InputStream is = context.getResourceAsStream("/" + fileName);
if (is != null) {
InputStreamReader isr = new InputStreamReader(is);
BufferedReader reader = new BufferedReader(isr);
PrintWriter writer = response.getWriter();
String text = "";
while ((text = reader.readLine()) != null) {
writer.println(text);
}
}
}
}
In the code above, the
doGet
method of the servlet takes a request parameter named
file
and uses it to read a file from the application's context. The
fileName
is directly concatenated to the base path
"/"
without any validation or sanitization. This means an attacker can manipulate the
file
parameter to read any file that the application has access to, such as configuration files, source code, or any other sensitive information stored on the server.
For instance, an attacker can send a request like
http://example.com/VulnerableServlet?file=../../etc/passwd
to read the
/etc/passwd
file which contains user account information on Unix-like systems.
This vulnerability is known as Local File Inclusion (LFI) and can lead to information disclosure, denial of service, or even remote code execution if the attacker can include a file that contains malicious code.
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.util.Arrays;
import java.util.List;
public class SecureServlet extends HttpServlet {
private static final List ALLOWED_FILES = Arrays.asList("file1.txt", "file2.txt", "file3.txt");
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String fileName = request.getParameter("file");
// Validate user input
if (fileName == null || fileName.contains("..") || !ALLOWED_FILES.contains(fileName)) {
response.sendError(HttpServletResponse.SC_BAD_REQUEST);
return;
}
ServletContext context = getServletContext();
InputStream is = context.getResourceAsStream("/" + fileName);
if (is != null) {
InputStreamReader isr = new InputStreamReader(is);
BufferedReader reader = new BufferedReader(isr);
PrintWriter writer = response.getWriter();
String text = "";
while ((text = reader.readLine()) != null) {
writer.println(text);
}
}
}
}
The above code fixes the Local File Inclusion vulnerability in the following ways:
1. Validate user input: The code checks if the 'file' parameter is null, contains path traversal sequences (..), or is not present in the whitelist of allowed files. If any of these conditions are met, it sends a bad request error (400) and returns.
2. Whitelist allowed files: A list of allowed files is maintained. The requested file is checked against this list before it is accessed.
3. Use absolute paths: Although not explicitly shown in the code, it is recommended to use absolute paths when accessing files on the server. This can be done by configuring the server or application settings.
4. Implement access controls: Access to sensitive files should be restricted by implementing proper access controls. This can be done at the server or operating system level.
5. Sanitize user input: The code checks for path traversal sequences and removes them if found. This is a form of input sanitization.
6. Implement file permissions: File permissions should be set on the server to restrict access to sensitive files. This can be done at the server or operating system level.
7. Regularly update and patch dependencies: Although not shown in the code, it is important to keep all libraries and frameworks used by the application up to date.
8. Perform security testing: Regular security testing should be conducted to identify and fix any vulnerabilities. This includes penetration testing and code reviews.