haproxy
global
daemon
log 127.0.0.1 local0 debug
defaults
log global
retries 3
maxconn 2000
timeout connect 5s
timeout client 50s
timeout server 50s
resolvers docker_resolver
nameserver dns 127.0.0.11:53
frontend internal_access
bind 127.0.0.1:8080
mode http
use_backend test
frontend internet_access
bind *:80
errorfile 403 /etc/haproxy/errorfiles/403custom.http
http-response set-header Server Server
http-request deny if METH_POST
http-request deny if { path_beg /admin }
http-request deny if { cook(IMPERSONATE) -m found }
http-request deny if { hdr_len(Cookie) gt 69 }
mode http
use_backend test
backend test
balance roundrobin
mode http
server flaskapp app:8282 resolvers docker_resolver resolve-prefer ipv4
题目给出了haproxy的设置具体语义去文档看看就懂了,我们可以收获以下信息
- http method不可以是
POST
- url路径不能以
/admin
开头 - cookie中必须包含
IMPERSONATE
项 - cookie长度不能大于69
同时我们可以看到这是个flask的应用
bypass
- 第一步method好解决,用
head
访问//admin
方法可以获取Set-Cookie: IMPERSONATE=admin; Path=/ Set-Cookie: KEY=0be40039bcd8286eab237f481641b16e5e3ab442e0bc1135f08c143b22dc1efc; Path=/
- 第二步这个cookie的长度已经大于69了,但是HTTP 1.1支持分行传递cookie,所以可以
Cookie: KEY=0be40039bcd8286eab237f481641b16e5e3ab442e0bc1135f08c143b22dc1efc; Cookie: IMPERSONATE=admin
flask
cookie
解析问题
其实也不是flask的问题,只是haproxy和flask解析cookie结果不一样导致的bypass。正好最近在学nodejs,我就先拿express试了一下,发现这样解析是没有问题的
然后再拿flask试一下发现本来应该错误的cookie被正确解析了
看一下源码,找到flask中request
类的cookies
方法,往下调可以找到解析cookie的正则
_cookie_re = re.compile(
br"""
(?P<key>[^=;]+)
(?:s*=s*
(?P<val>
"(?:[^\"]|\.)*" |
(?:.*?)
)
)?
s*;
""",
flags=re.VERBOSE,
)
key
中是不可以有=
或者;
的,所以传入这样的cookie时,=
不会被匹配,然后后边的IMPERSONATE=admin;
被正常解析