By sending a request to the server, a denial of service/slow service can be achieved
With a carefully constructed request header, we can bypass the Loop request defense. With HTTP redirection (301/302), Loop request attack can be realized.
The program has a publicly accessible external API:
http://127.0.0.1:25500/sub?target=%TARGET%&url=%URL%&config=%CONFIG%
One of the parameters named url can be an arbitrary external url. After receiving the request, the server will initiate a GET request for the url.
-
Construct
Loop requestWe can construct such a url, and we call it
BAD_URL_ONE:http://127.0.0.1:25500/sub?target=clash&insert=false&url=BAD_URL_TWOAmong them,
BAD_URL_TWOis also a url. At any time it returns a301/302response, redirecting the request toBAD_URL_ONE(redirection can be done with a simple nginx server, or a short link Service with editing function)First, Send a GET
BAD_URL_ONErequest to the server. Then, the server will requestBAD_URL_TWO. Due to the redirection, the server will requestBAD_URL_ONE(request itself), causingLoop requestUnfortunately, this attack has been defended, but we have discovered new ways to bypass it.
-
Bypass server-side
Loop requestdefenseThis server program implements defense against
Loop requestattacks by checking a request header:When the server sending a request, it will append a custom request header
SubConverter-Request: 1:And it detects
Loop requestby checking whether the request header containsSubConverter-Requestand whether its value is"1":But this detection method has loopholes.
When the server sends a request
BAD_URL_TWO, it will incidentally bring all the HTTP request headers sent when the attacker requestsBAD_URL_ONE, like the following:Therefore, we can use
curlto requestBAD_URL_ONE, and include a request header calledSubConverter-Request, but the value is not"1", but"2". We can get twoSubConverter -RequestonBAD_URL_TWOrequest. 💥💥The program uses libev's evhttp_find_header function to get the header in the HTTP request. This function will only return the first one when processing multiple identical headers in the request. As a result, the value of
SubConverter-Requestwas overwritten by us to"2", thus bypassing theLoop requestdefense.
-
Download the released binary file from the release page, and start a service program locally:
chmod +x ./subconverter ./subconverter
-
Construct
BAD_URL_ONE: http://127.0.0.1:25500/sub?target=clash&insert=false&url=https://t.xice.wang/vAmong them,
BAD_URL_TWOis a short link service: https://t.xice.wang/v, it will redirect (301) toBAD_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 -
Issue a request for
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'After the request is sent, the program starts to enter an infinite
Loop RequestAfter that, new incoming requests will appear to be slow. Multiple attacks can lead to denial of service
Remove the strcmp() function and change the detection logic to detect the existence of the SubConverter-Request header.
https://github.com/tindy2013/subconverter/blob/ab4d7543cec46cd9e45680f3b43d82de16f38a3d/src/webserver_libevent.cpp#L174




