Directory listing - Python

Directory listing - Python

Need

Prevention of unauthorized access to directory listings

Context

  • Usage of Python 3 for building and running Python applications
  • Usage of Django for building web applications in Python

Description

Non compliant code

        from django.views.static import serve
from django.conf.urls import url

urlpatterns = [
    url(r'^(?P.*)$', serve, {'document_root': '/path/to/your/static/files'}),
]
        
        

This code is a Django URL configuration that serves static files directly from a specified path. This is a security vulnerability because it allows directory listing.

The serve view from django.views.static is used to serve static files. In the URL configuration, any URL ( r'^(?P.*)$') is mapped to the serve view, which serves files directly from the directory specified by 'document_root'.

An attacker can access any file in this directory by specifying its path in the URL. For example, if there is a file at /path/to/your/static/files/secret.txt, an attacker could access it by visiting http://yourwebsite.com/secret.txt.

Furthermore, if the attacker specifies a directory path instead of a file path, the server will return a listing of all files in that directory. For example, visiting http://yourwebsite.com/ would return a list of all files in /path/to/your/static/files.

This reveals the structure and content of your server's file system to potential attackers, which is a significant security risk.

Steps

  • Disable directory listing in your web server configuration. This will prevent the server from listing the contents of directories.
  • Use Django's built-in static files serving in development only. In production, use a more secure and efficient server like Nginx or Apache to serve static files.
  • Ensure that sensitive files are not stored in publicly accessible directories. They should be stored outside the web root or in a directory protected by access controls.
  • Use Django's 'WhiteNoise' middleware for serving static files in a secure manner.
  • Regularly update and patch your server software to protect against known vulnerabilities.

Compliant code

        from django.conf import settings
from django.conf.urls.static import static
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
from django.urls import path

urlpatterns = [
    # ... the rest of your URLconf goes here ...
] 

if settings.DEBUG:
    urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
    urlpatterns += staticfiles_urlpatterns()
        
        

The above code is a secure way to serve static files in Django. It uses Django's built-in static files serving in development only. In production, you should use a more secure and efficient server like Nginx or Apache to serve static files.

The settings.DEBUG condition ensures that the static files are only served by Django when in development mode. This is because Django is not designed to be efficient or secure at serving static files, and so this should only be done in development.

The static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) function adds a URL pattern for serving static files during development. The staticfiles_urlpatterns() function returns a URL pattern for serving static files using the django.contrib.staticfiles app.

Remember, sensitive files should not be stored in publicly accessible directories. They should be stored outside the web root or in a directory protected by access controls.

For serving static files in a secure manner in production, consider using Django's 'WhiteNoise' middleware. Regularly update and patch your server software to protect against known vulnerabilities.

References