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 进行限制即可。由于功底很差,这里就不误导师傅们了。
- 本文作者: JOHNSON
- 本文来源: 奇安信攻防社区
- 原文链接: https://forum.butian.net/share/1358
- 版权声明: 除特别声明外,本文各项权利归原文作者和发表平台所有。转载请注明出处!