问答
发起
提问
文章
攻防
活动
Toggle navigation
首页
(current)
问答
商城
实战攻防技术
漏洞分析与复现
NEW
活动
摸鱼办
搜索
登录
注册
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`** 异常, 这个功能代码有问题吗?毫无疑问他有,在哪里? ```python 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
阅读 ( 6268 )
分类:
漏洞分析
2 推荐
收藏
0 条评论
请先
登录
后评论
JOHNSON
12 篇文章
×
发送私信
请先
登录
后发送私信
×
举报此文章
垃圾广告信息:
广告、推广、测试等内容
违规内容:
色情、暴力、血腥、敏感信息等内容
不友善内容:
人身攻击、挑衅辱骂、恶意行为
其他原因:
请补充说明
举报原因:
×
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!