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
- 版权声明: 除特别声明外,本文各项权利归原文作者和发表平台所有。转载请注明出处!