Attack on decryption protocol layer — HTTP request smuggling

Time:2021-7-21

Recently, I have been studying some interesting attack methods and ideas. When I look up local documents (yes, local, I often save some interesting articles, but if I don’t have time to read them, they will be saved locally). An issue of black hat in 2019, HTTP request smuggling, came into my view, At the same time, I also found that the attack technique was analyzed again in blackhat 2020. I have a strong interest in learning this, so I have this article.

HTTP request smuggling is an attack method of HTTP protocol. The reason of the attack is that the implementation of HTTP server in HTTP proxy chain is inconsistent.

Timeline

  • In 2004,[email protected] Amit Klein proposed_HTTP Response SplittingIt is the rudiment of HTTP smuggling attack;
  • In 2005,It was first proposed by @ Watchfire and introduced in detail;
  • In 2016,On Defcon 24, @ regilero is on his agenda——Hiding Wookiees in HTTPIn this paper, we enrich and expand the previous reports;
  • In 2019,On blackhat USA, @ James kettle of portswigger is on the agenda——HTTP DESYNC ATTACKS SMASHING INTO THE CELL NEXT DOORIn this paper, the current network environment is analyzed, and the existing attack surface is expanded by adding chunked technology;
  • In 2020,On blackhat USA, @ Amit Klein’s topic –_HTTP Request Smuggling in 2020_ At the same time, it analyzes various environmental scenarios.

Analysis of vulnerability exploitation scenarios

HTTP request smuggling is not as intuitive as other web attacks, but a security risk in a more complex network environment due to the different processing methods of HTTP packets implemented by different servers based on different RFC standards.

Before analyzing its vulnerabilities, we need to understand the widely used HTTP 1.1 protocol features – keep alive, pipeline technology.

In short, in HTTP 1.0 and its previous versions, the C / s both sides need to carry out three handshake links of TCP in each interaction. Today’s web pages are mainly composed of a large number of static resources. If it is still designed according to HTTP 1.0 and its previous versions, a lot of server load will be wasted. Therefore, in HTTP 1.1, keep alive and pipeline technologies are added.

KEEP-ALIVE

According to rfc7230section-6.3As you can see, persistent connections is used by default in HTTP 1.1. The implementation method is to add the connection: keep alive flag in the HTTP communication packet: the TCP connection will not be closed after an HTTP communication, but the idle TCP channel will be reused in the subsequent request of the same target server, so as to avoid the delay and server resource consumption caused by the new TCP connection, and improve the user resource access speed.

PIPELINE

In keep alive, there is a pipeline mechanism, so that the client can continue to send packets to the server like a pipeline without waiting for the response of a packet. The server will also follow the principle of first in first out to respond to client requests.

Attack on decryption protocol layer -- HTTP request smuggling

As shown in the figure, we can see that compared with no pipelining mode, the response time of the server in pipelining mode has been greatly improved.

Nowadays, in order to improve the user browsing speed, enhance service stability, improve the user experience and reduce the network burden. Most manufacturers will use CDN acceleration service or load balancing lb to deploy services. When users access the static resources of the server, they will get the details directly from the CDN. When there is real server interaction, they will interact with the back-end server. As shown in the figure:

Attack on decryption protocol layer -- HTTP request smuggling

However, in this mode, the reverse proxy part will communicate with the back end part for a long time. Generally, this part of the connection will reuse the TCP channel. Generally speaking, user traffic comes from all directions. Multiple TCP channels will be established for communication from the user end to the reverse proxy end, while the communication ip between the reverse proxy end and the back end end end end is fixed. It is natural for the two sides to reuse the TCP connection channel for communication.

In this scenario, when the RFC standards referenced by different server implementations are different, when we send a fuzzy HTTP request to the reverse proxy, because the reverse proxy and the back end are parsed based on different standards, the reverse proxy may think that the HTTP request is legal and forward it to the back end, while the back end only thinks that part of the HTTP request is legal and the rest is redundant, It’s a smuggled HTTP request. When this part affects the requests of normal users, the HTTP smuggling attack is implemented. As shown in the figure: dark color is normal request, orange is smuggling request, and green is normal user request. In the case of a contract, the smuggled request content is spliced into the normal request.

Attack on decryption protocol layer -- HTTP request smuggling

Chunked packet format

Chunked transfer encodingIt is a data transmission mechanism in hypertext transfer protocol (HTTP), which allowsHTTPThe data can be divided into several parts.

As shown in the figure below, jdcloud.com does not chunk packets.

Attack on decryption protocol layer -- HTTP request smuggling

When partitioning jdcloud.com, as shown in the figure below.

Attack on decryption protocol layer -- HTTP request smuggling

Common attacks

Note: CL = content length and TE = transfer encoding are mentioned in the following articles. If you need to use burpsuite for packet debugging, you need to remove the update content length option in repeater.

Scenario 1: CL not 0 in get request

It mainly refers to setting the content length length in get and using body to send data. Of course, it’s not only limited to get requests, but the understanding of get is typical, so we use it as an example.

stayRFC7230 Content-LengthSome of them mentioned:

For example, a Content-Length header field is normally sent in a POST request even when the value is 0 (indicating an empty payload body). A user agent SHOULD NOT send a Content-Length header field when the request message does not contain a payload body and the method semantics do not anticipate such a body.

In the latestRFC7231 4.3.1 GETThere is only one sentence mentioned in the article:

A payload within a GET request message has no defined semantics; sending a payload body on a GET request might cause some existing implementations to reject the request.

From the official specification documents, we can know that RFC specification does not strictly regulate the server-side processing mode, and the specification of this kind of request is also relaxed, but it is also part of the situation. Because these middleware do not have a strict standard basis, there will also be parsing differences, leading to HTTP smuggling attacks.

  • Construct packet
GET / HTTP/1.1rn
Host: example.comrn
Content-Length: 44rn

GET /secret HTTP/1.1rn
Host: example.comrn
rn

Because of the get request, the server will not process the content length. At the same time, because of the existence of pipeline, the back-end server will treat the packet as two get requests. They are as follows:

Request – 1

GET / HTTP/1.1rn
Host: example.comrn

Request – 2

GET /secret HTTP/1.1rn
Host: example.comrn

This led to requests for smuggling.

Scene 2: cl-cl

In the second part of rfc7230_3.3.3_ Section 4 stipulates that when the server receives a request that contains two content length values, and the values of the two are different, it needs to return 400 errors.

If a message is received without Transfer-Encoding and with either multiple Content-Length header fields having differing field-values or a single Content-Length header field having an invalid value, then the message framing is invalid and the recipient MUST treat it as an unrecoverable error. If this is a request message, the server MUST respond with a 400 (Bad Request) status code and then close the connection. If this is a response message received by a proxy, the proxy MUST close the connection to the server, discard the received response, and send a 502 (Bad Fielding & Reschke Standards Track [Page 32] RFC 7230 HTTP/1.1 Message Syntax and Routing June 2014 Gateway) response to the client. If this is a response message received by a user agent, the user agent MUST close the connection to the server and discard the received response.

But some servers do not follow the specification. When the server does not follow the specification, the front and back servers will not respond. It may cause the proxy server to use the first content length to get the length, while the back end gets the length according to the second content length.

  • Construct packet
POST / HTTP/1.1rn
Host: example.comrn
Content-Length: 8rn
Content-Length: 7rn

12345rn
a

At this time, when the back-end server receives the packet, the content length is 7. In fact, the received body is 12345rn. As we mentioned earlier, the proxy server will reuse the TCP channel with the back-end server. At this time, a will splice to the next request. At this time, if a user initiates a get request. The actual get request of the user is:

aGET / HTTP/1.1rn
Host: example.comrn

At the same time, the user will also receive an error response similar to a get request method not found. In fact, this has realized an HTTP protocol smuggling attack, which has affected normal users, and can be extended to a CSRF like attack mode.

However, the two content length request packets are too idealistic. Most servers will not accept the request packets with two request headers. However, in the second part of rfc2616_4.4_ Section, provides that:

The transfer-length of a message is the length of the message-body as it appears in the message; that is, after any transfer-codings have been applied. When a message-body is included with a message, the transfer-length of that body is determined by one of the following (in order of precedence):

If a Transfer-Encoding header field (section 14.41) is present and has any value other than “identity”, then the transfer-length is defined by use of the “chunked” transfer-coding (section 3.6), unless the message is terminated by closing the connection.

In other words, when content length and transfer encoding are defined and used at the same time, content length can be ignored. In other words, when transfer encoding is added, the two content lengths do not affect the response of the proxy server and the back-end server.

Scenario 3: cl-te

In this case, the proxy server processes content length, and the back-end server processes transfer encoding in accordance with rfc2616 (this is also the case mentioned at the end of scenario 2).

  • Construct packet
POST / HTTP/1.1rn
 Host: example.comrn
 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:56.0) Gecko/20100101 Firefox/56.0rn
 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8rn
 Accept-Language: en-US,en;q=0.5rn
 Connection: keep-alivern
 Content-Length: 6rn
 Transfer-Encoding: chunkedrn
 rn
0rn
rn
G
  • Due to different server specifications, the resolution is as follows:

Request — 1 (resolution of proxy server)

POST / HTTP/1.1rn
 Host: example.comrn
 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:56.0) Gecko/20100101 Firefox/56.0rn
 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8rn
 Accept-Language: en-US,en;q=0.5rn
 Connection: keep-alivern
 Content-Length: 6rn
 Transfer-Encoding: chunkedrn
 rn
0rn
rn
G

Request — 2 (resolution of proxy server)

G

If G is left in the buffer, when there is no other user’s request, will the packet have parsing problems, but when a normal request comes over, TCP reuse will not happen. The following will happen:

GPOST / HTTP/1.1rn
Host: example.comrn
....

At this time, HTTP packets are smuggled through the TCP channel again.

Scene 4: te-cl

That is, the proxy server processes the transfer encoding request, and the back-end server processes the content length request.

  • Construct packet
POST / HTTP/1.1rn
 Host: example.comrn
 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:56.0) Gecko/20100101 Firefox/56.0rn
 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8rn
 Accept-Language: en-US,en;q=0.5rn
 Content-Length: 4rn
 Transfer-Encoding: chunkedrn
 rn
 12rn
GPOST / HTTP/1.1rn
rn
0rn
rn

Because transfer encoding encounters 0rnrn, the parsing ends. At this time, the back end will parse the content length, and the real data arriving at the back end will be:

POST / HTTP/1.1rn
2Host: example.comrn
3User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:56.0) Gecko/20100101 Firefox/56.0rn
4Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8rn
5Accept-Language: en-US,en;q=0.5rn
6Content-Length: 4rn
7rn
812rn

At the same time, a second packet will appear:

GPOST / HTTP/1.1rn
rn
0rn
rn

When a request packet with two request headers is received, both the front and back servers process the transfer encoding request header, which really implements the RFC standard. However, the front-end and back-end servers are not the same after all, so there is a method. We can confuse the transfer encoding in the sent request packet (here mainly refers to content length), so that one of the servers does not process the transfer encoding request header. In a sense, it’s cl-te or te-cl.

  • Construct packet
POST / HTTP/1.1rn
Host: example.comrn
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:56.0) Gecko/20100101 Firefox/56.0rn
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8rn
Content-length: 4rn
Transfer-Encoding: chunkedrn
Transfer-encoding: cowrn
rn
5crn
GPOST / HTTP/1.1rn
Content-Type: application/x-www-form-urlencodedrn
Content-Length: 15rn
rn
x=1rn
0rn
rn

Attack scenario analysis

The experimental environment of portswigger is used to demonstrate the actual attack.

Reuse TCP for administrator operation

*Range link:

https://portswigger.net/web-s…

This lab involves a front-end and back-end server, and the front-end server doesn’t support chunked encoding. There’s an admin panel at /admin, but the front-end server blocks access to it.

To solve the lab, smuggle a request to the back-end server that accesses the admin panel and deletes the user carlos.

Experiment purpose: visit the admin page, and use authentication to delete Carlos users.

  • Setp 1. Due to direct access to the / Admin directory, it is prompted to intercept, and the title prompts cl.te. Here, by constructing cl.te format packets, try to access/ Admin route.

Attack on decryption protocol layer -- HTTP request smuggling

Attack on decryption protocol layer -- HTTP request smuggling

  • Setp 2. The access prompt administrator interface only allows local users to access. Try to directly access localhost and get the route address of the deleted user.

Attack on decryption protocol layer -- HTTP request smuggling

  • Setp 3. You can access it by constructing a request. Finally, you can visit the / Admin display page again without deleting the Carlos user option.

Attack on decryption protocol layer -- HTTP request smuggling

Attack on decryption protocol layer -- HTTP request smuggling

Obtain user request package-1 in combination with service

*Link:

https://portswigger.net/web-s…

This lab involves a front-end and back-end server, and the front-end server doesn’t support chunked encoding.

There’s an admin panel at /admin, but it’s only accessible to people with the IP address 127.0.0.1. The front-end server adds an HTTP header to incoming requests containing their IP address. It’s similar to the X-Forwarded-For header but has a different name.

To solve the lab, smuggle a request to the back-end server that reveals the header that is added by the front-end server. Then smuggle a request to the back-end server that includes the added header, accesses the admin panel, and deletes the user carlos.

The purpose of the experiment is the same as above, but there are restrictions on the front-end server. Chunked is not supported. At the same time, the front-end to back-end checks are done, and a header similar to x-forward-for is defined in the headers.

  • Setp1. Construct smuggling packets directly through the page search, and return the contents of packets from the intermediate server to the back-end server on the page (the length of smuggling packets is currently 200, if it is not fully displayed in the actual scene, it can be solved by increasing the length of CL), and obtain the x-uniqsg-ip header. At the same time, the reason why search is selected here is that there is output on the page.

Attack on decryption protocol layer -- HTTP request smuggling

  • Setp2. The same request can be sent through forgery.

Attack on decryption protocol layer -- HTTP request smuggling

Attack on decryption protocol layer -- HTTP request smuggling

Get user request package with service-

*Link:

https://portswigger.net/web-s…

This lab involves a front-end and back-end server, and the front-end server doesn’t support chunked encoding.

To solve the lab, smuggle a request to the back-end server that causes the next user’s request to be stored in the application. Then retrieve the next user’s request and use the victim user’s cookies to access their account.

Experimental purpose: to get the cookie data in the next request packet by writing the page.

  • Setp1. It is found that there is a page writing operation under post? Postid = route.

Attack on decryption protocol layer -- HTTP request smuggling

  • Setp2, visit the current page and view the website to get the data of the next request package( You can also control the data of the next request packet in the comment area. Just put the last comment parameter comment to the end.)

Attack on decryption protocol layer -- HTTP request smuggling

Reflection XSS

*Link:

https://portswigger.net/web-s…

This lab involves a front-end and back-end server, and the front-end server doesn’t support chunked encoding.

The application is also vulnerable to _reflected XSS_ via the User-Agent header.

To solve the lab, smuggle a request to the back-end server that causes the next user’s request to receive a response containing an XSS exploit that executes alert(1).

Application scenario: when there is reflective XSS in the service, dirty data can be written to other user pages through cache poisoning.

Setp1. Enter any comment area and find that there is a user agent echo on the page. Modify the user agent through the smuggling protocol.

Attack on decryption protocol layer -- HTTP request smuggling

Attack on decryption protocol layer -- HTTP request smuggling

Cache poisoning

*Link:

https://portswigger.net/web-s…

This lab involves a front-end and back-end server, and the front-end server doesn’t support chunked encoding. The front-end server is configured to cache certain responses.

To solve the lab, perform a request smuggling attack that causes the cache to be poisoned, such that a subsequent request for a JavaScript file receives a redirection to the exploit server. The poisoned cache should alert document.cookie.

Application scenario: hijack the next user request page( In the actual scene, you can hijack and jump to the fishing page, etc.)

  • Setp1 and cache injection modify the host as a malicious request.

Attack on decryption protocol layer -- HTTP request smuggling

About defense

From the previous case, we can see the harm of HTTP request smuggling, so how to prevent it?

  • Disable TCP connection reuse between proxy server and back-end server.
  • Use HTTP / 2 protocol.
  • The front and back end use the same server.

However, there are some practical difficulties in these methods

  • The implementation of HTTP / 2 is too difficult, although http / 2 is compatible with HTTP / 1.1.
  • Canceling TCP reuse will increase the server load, and the server resources will not be able to bear it.
  • Using the same server is difficult to implement in some manufacturers. The main reason is the inconsistency of the front and back implementation standards.

So there’s no solution?

In fact, it is not. Cloud is a good solution. Virtual machine, CDN and WAF all implement the coding standard, which can avoid this kind of problem.

Reference link

*https://media.defcon.org/DEF%…
*https://portswigger.net/resea…
*https://regilero.github.io/en…
*https://paper.seebug.org/1048
*https://tools.ietf.org/html/r…
*http://blog.zeddyu.info/2019/…
*https://tools.ietf.org/html/r…
*https://tools.ietf.org/html/r…

Recommended reading

Welcome to click【Jingdong Technology】, learn about the developer community

More wonderful technical practice and exclusive dry goods analysis

Welcome to official account of Jingdong technology developer.

Attack on decryption protocol layer -- HTTP request smuggling