Directory listing
Need
Prevention of unauthorized directory listing
Context
• Usage of Scala for building scalable and high-performance applications
• Usage of play.api.mvc for handling HTTP requests and responses in Play Framework
• Usage of play.api.libs.Files for file handling in Play Framework
Description
1. Non compliant code
import play.api.mvc._
import play.api.libs.Files
class HomeController @Inject()(cc: ControllerComponents) extends AbstractController(cc) {
def index = Action {
Ok.sendFile(Files.get("/public/"))
}
}The code above is a Scala Play Framework controller that serves the files in the "/public/" directory when the index route is hit. The `Ok.sendFile` method sends the file (in this case, a directory) as a response. This code is vulnerable because it exposes the directory listing of the "/public/" directory to the client. An attacker can potentially see all the files and subdirectories in the "/public/" directory. This can provide valuable information to an attacker, such as the structure of the files on the server, the types of files stored, etc. The vulnerability lies in the `Ok.sendFile(Files.get("/public/"))` line, where the server is instructed to send the entire directory as a response without any checks or restrictions. This vulnerability is known as "Directory Listing" vulnerability. It is a type of information disclosure vulnerability where an attacker can gain information about the application that can be used for further attacks.
2. Steps
• Disable directory listing in the web server configuration.
• Remove the code that sends the directory listing response.
• Implement proper access control to restrict access to sensitive directories.
• Use a file server or a web server to serve static files instead of directly accessing the file system.
• Implement input validation and sanitization to prevent path traversal attacks.
3. Secure code example
import play.api.mvc._
import play.api.libs.Files
import java.io.File
class HomeController @Inject()(cc: ControllerComponents) extends AbstractController(cc) {
def index(fileName: String) = Action {
val file = new File("/public/" + fileName)
Ok.sendFile(file)...The updated code now takes a `fileName` parameter in the `index` function. This parameter is used to construct the path to the file that should be sent in response to the client's request. The `if` condition checks if the file exists and if it is not a directory. If both conditions are true, the file is sent as a response. If either condition is false, a "File not found" message is sent as a response. This way, we prevent directory listing as the server will only send a file if it exists and is not a directory. Please note that this is a basic solution and does not include input validation and sanitization to prevent path traversal attacks. For a production-grade solution, you should also implement proper access control to restrict access to sensitive directories and use a file server or a web server to serve static files instead of directly accessing the file system.
References
• 125. Directory listing