Django 中的 XFF 问题

# Django 中的 XFF 问题 最近在用 Django 开发限制访问只能通过 127.0.0.1 或者内网地址访问后台的功能,关注到 Django 中存在的 XFF 问题。 文中 [1. 后台访问地址/域名功能] 主要说的是...

0x00 Django 中的 XFF 问题

最近在用 Django 开发限制访问只能通过 127.0.0.1 或者内网地址访问后台的功能,关注到 Django 中存在的 XFF 问题。

文中 [1. 后台访问地址/域名功能] 主要说的是从开发到发现问题的过程。

如果想直接看 Django 的 XXF 问题可以直接跳转至文中的 [2. Django Bypass 访问地址限制]

0x01后台访问地址/域名功能

最近在开发一个 Django 限制访问后台的功能,只有通过IP 127.0.0.1 (可设置,多个)才能访问后台,功能已经写完了。代码如下,通过正则匹配只要访问 URL 以 /admin/ 开头的就会校验访问的地址,当地址错误时,会抛出 DisallowedHost 异常,

这个功能代码有问题吗?毫无疑问他有,在哪里?

class AdminHostMiddleware(MiddlewareMixin):
    """
    校验后台访问地址/域名
    """
    def process_request(self, request):
        full_path = request.get_full_path()

        if re.match(r'^/' + settings.ADMIN_URL + '/.*', full_path, flags=0):
            host = request._get_raw_host()
            # 如果 ALLOWED_HOSTS 为空且 DEBUG=True ,啧允许通过本地主机的方法访问。
            admin_allowed_hosts = settings.ADMIN_ALLOWED_HOSTS
            if settings.DEBUG and not admin_allowed_hosts:
                admin_allowed_hosts = ['.localhost', '127.0.0.1', '[::1]']

            domain, port = split_domain_port(host)
            if not (domain and validate_host(domain, admin_allowed_hosts)):
                msg = "Invalid HTTP_HOST header: %r." % host
                if domain:
                    msg += " You may need to add %r to ADMIN_ALLOWED_HOSTS." % domain
                else:
                    msg += " The domain name provided is not valid according to RFC 1034/1035."
                raise DisallowedHost(msg)

1.1 环境准备

settings.py 同目录下,创建 middlewares.py 并新建中间件。

common.middlewares.AdminHostMiddleware

注册组件,设置后台URL,允许访问的地址,同时关闭 DEBUG,并设置 ALLOWED_HOSTS 为 ***** ,允许通过所有可访问地址访问站点。

common.settings

没有通过 127.0.0.1 访问后台,响应状态码 400

通过 127.0.0.1 访问站点,正常可访问。静态文件丢失是因为静态文件路径的配置问题

1.2 Bypass 限制

拦截数据包后,发送到 Repeater 重发中,可以看到确实成功限制住了访问

修改请求头中的 Host 为:127.0.0.1:8000 成功绕过限制,

1.3 代码分析

回到 middlewares 中,肯定是获取 host 的地方出问题了,跟进 **request.\_get\_raw\_host()**

common.middlewares.AdminHostMiddleware.process_request

host 既然来自于请求头中的信息

django.http.request.HttpRequest._get_raw_host

第一次判断中的 settings.USE_X_FORWARDED_HOST 默认为 Flase 所以默认不会从 X-Forwarded-For 中获取

django.http.request.HttpRequest._get_raw_host

我们进入的是第二次判断 'HTTP_HOST' in self.META 这是大多情况,请求头中一般情况下默认会带上 Host 请求头。

django.http.request.HttpRequest._get_raw_host

0x02 Django Bypass 访问地址限制

Django 中其实也是通过同样的方法进行限制的

2.1 环境准备

随机准备一个视图

common.urls

修改 ALLOWED_HOSTS 限制只能通过 127.0.0.1 进行访问

common.settings

通过 127.0.0.1 访问正常

通过别的地址访问被拦截

2.2 Bypass ALLOWED_HOSTS 限制

拦截数据包后,发送到 Repeater 重发中,可以看到确实成功限制住了访问

修改请求头中的 Host 为:127.0.0.1:8000 成功绕过限制

2.1代码分析

限制访问是在 CommonMiddleware 中间件中,跟进

common.settings

CommonMiddleware.process_request 方法中调用了 request.get_host() 方法

django.middleware.common.CommonMiddleware.process_request

进入到 HttpRequest.get_host 方法中,看到了熟悉的方法调用 self._get_raw_host()

django.http.request.HttpRequest.get_host

进入到 _get_raw_host() 方法就是存在问题的地方了

0x03修复建议

最简单粗暴直接通过 Nginx 进行限制即可。由于功底很差,这里就不误导师傅们了。

  • 发表于 2022-03-03 09:34:30
  • 阅读 ( 6982 )
  • 分类:漏洞分析

0 条评论

请先 登录 后评论
JOHNSON
JOHNSON

12 篇文章

站长统计