We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
English Version Report
通过发送一个请求到服务器,就能实现持续的Loop request攻击,导致拒绝服务/服务缓慢
Loop request
通过精心构造的请求头,绕过Loop request防御,配合HTTP重定向(301/302),实现Loop request攻击。
该程序存在一个公开访问的外部API:
http://127.0.0.1:25500/sub?target=%TARGET%&url=%URL%&config=%CONFIG%
其中的一个名为url参数可以是一个任意的外部url。收到该请求后,服务器会发起一个对该url的GET请求。
url
GET
构造Loop request
我们可以构造这样的一个url,我们叫它BAD_URL_ONE:
BAD_URL_ONE
http://127.0.0.1:25500/sub?target=clash&insert=false&url=BAD_URL_TWO
其中BAD_URL_TWO也是一个url,在任何时候它都返回一个301/302响应,将请求重定向到BAD_URL_ONE(重定向可以用一个简单的nginx做到,或者一个带编辑功能的短链接服务做到)
BAD_URL_TWO
301/302
向该服务器发送一个GET请求,url是BAD_URL_ONE,服务器会请求BAD_URL_TWO。由于重定向,服务器会访问BAD_URL_ONE(自己访问自己),造成Loop request
不幸的是,这种攻击已经被得到防御,但是我们发现了新的方法来绕过。
绕过服务端Loop request防御
该程序通过检查请求头来实施对Loop request攻击的防御:
在向外部发送请求时,会带上一个自定义的请求头SubConverter-Request: 1:
SubConverter-Request: 1
subconverter/src/webget.cpp
Line 199 in ab4d754
通过检查请求头中是否包含SubConverter-Request,且它的值是否为"1"来拒绝Loop request:
SubConverter-Request
"1"
subconverter/src/webserver_libevent.cpp
Line 166 in ab4d754
Line 174 in ab4d754
但是该检测方式存在漏洞。
在服务器发出请求BAD_URL_TWO时,会顺带将攻击者请求BAD_URL_ONE时发送的所有HTTP请求头也带上,像下面这样:
因此,我们可以用curl请求BAD_URL_ONE,并且包含一个叫做SubConverter-Request的请求头,但是值不是"1",而是"2",我们就可以得到,两个SubConverter-Request💥💥
"2"
程序使用libev的evhttp_find_header函数获取请求中的header,这个函数在处理请求中多个相同的header时,只会返回第一个的结果,因此SubConverter-Request的值被我们覆盖成了"2",从而绕过了Loop request防御。
从release页面下载发布的二进制文件,在本地启动一个服务程序:
chmod +x ./subconverter ./subconverter
构造BAD_URL_ONE:http://127.0.0.1:25500/sub?target=clash&insert=false&url=https://t.xice.wang/v
其中BAD_URL_TWO是一个短链接服务:https://t.xice.wang/v,它会重定向(301)到`BAD_URL_ONE`:
curl -v https://t.xice.wang/v < HTTP/2 301 < server: nginx/1.19.0 < content-type: text/html; charset=UTF-8 < location: http://127.0.0.1:25500/sub?target=clash&insert=false&url=https://t.xice.wang/v < cache-control: no-cache
发出BAD_URL_ONE请求:
curl -H 'SubConverter-Request: 2' 'http://127.0.0.1:25500/sub?target=clash&insert=false&url=https://t.xice.wang/v'
该请求发出后,程序开始进入无限的Loop Request
Loop Request
此后新的请求到来时表现为请求缓慢,或者拒绝服务
去掉strcmp()函数,将检测逻辑改成检测SubConverter-Request头是否存在
strcmp()
The text was updated successfully, but these errors were encountered:
感谢提醒。该请求头原意是防止用户将已经过 SubConverter 处理的订阅链接再次送入而做的简单处理,还未考虑过是否能防御真正的攻击。
Sorry, something went wrong.
Fix detection of loop request (#284)
a57906c
还有一问题,测试过程中通过观察日志,发现在两轮loop之后会停顿几秒钟(可能是timeout),然后再是两轮loop,停顿的期间所有的外部请求都会挂起(包括因为loop request而产生的请求),所以我猜测这里是否意味着程序同时最多只能处理两个外部请求,多余的会丢到队列里?这里是否是libevent的使用问题?(没有用过libevent,只是猜测哈)
Merge pull request #1 from tindy2013/master
3dbfbd7
Fix detection of loop request (tindy2013#284)
6ebd989
No branches or pull requests
English Version Report
漏洞危害
通过发送一个请求到服务器,就能实现持续的
Loop request
攻击,导致拒绝服务/服务缓慢漏洞原理
通过精心构造的请求头,绕过
Loop request
防御,配合HTTP重定向(301/302),实现Loop request
攻击。该程序存在一个公开访问的外部API:
其中的一个名为
url
参数可以是一个任意的外部url。收到该请求后,服务器会发起一个对该url
的GET
请求。构造
Loop request
我们可以构造这样的一个url,我们叫它
BAD_URL_ONE
:其中
BAD_URL_TWO
也是一个url,在任何时候它都返回一个301/302
响应,将请求重定向到BAD_URL_ONE
(重定向可以用一个简单的nginx做到,或者一个带编辑功能的短链接服务做到)向该服务器发送一个GET请求,url是
BAD_URL_ONE
,服务器会请求BAD_URL_TWO
。由于重定向,服务器会访问BAD_URL_ONE
(自己访问自己),造成Loop request
不幸的是,这种攻击已经被得到防御,但是我们发现了新的方法来绕过。
绕过服务端
Loop request
防御该程序通过检查请求头来实施对
Loop request
攻击的防御:在向外部发送请求时,会带上一个自定义的请求头
SubConverter-Request: 1
:subconverter/src/webget.cpp
Line 199 in ab4d754
通过检查请求头中是否包含
SubConverter-Request
,且它的值是否为"1"
来拒绝Loop request
:subconverter/src/webserver_libevent.cpp
Line 166 in ab4d754
subconverter/src/webserver_libevent.cpp
Line 174 in ab4d754
但是该检测方式存在漏洞。
在服务器发出请求
BAD_URL_TWO
时,会顺带将攻击者请求BAD_URL_ONE
时发送的所有HTTP请求头也带上,像下面这样:因此,我们可以用curl请求
BAD_URL_ONE
,并且包含一个叫做SubConverter-Request
的请求头,但是值不是"1"
,而是"2"
,我们就可以得到,两个SubConverter-Request
💥💥程序使用libev的evhttp_find_header函数获取请求中的header,这个函数在处理请求中多个相同的header时,只会返回第一个的结果,因此
SubConverter-Request
的值被我们覆盖成了"2"
,从而绕过了Loop request
防御。复现过程
从release页面下载发布的二进制文件,在本地启动一个服务程序:
构造
BAD_URL_ONE
:http://127.0.0.1:25500/sub?target=clash&insert=false&url=https://t.xice.wang/v其中
BAD_URL_TWO
是一个短链接服务:https://t.xice.wang/v,它会重定向(301)到`BAD_URL_ONE`:发出
BAD_URL_ONE
请求:该请求发出后,程序开始进入无限的
Loop Request
此后新的请求到来时表现为请求缓慢,或者拒绝服务
修复建议
去掉
strcmp()
函数,将检测逻辑改成检测SubConverter-Request
头是否存在subconverter/src/webserver_libevent.cpp
Line 174 in ab4d754
The text was updated successfully, but these errors were encountered: