|
/
Zope
/
Apsis
/
Pound Mailing List
/
Archive
/
2005
/
2005-04
/
remote buffer overflow in pound 1.8.2 + question abotu Host header
[
Spam / Robert Segall <roseg(at)apsis.ch> ]
[
ANNOUNCE: Pound - reverse proxy and load balancer ... ]
remote buffer overflow in pound 1.8.2 + question abotu Host header
Steven Van Acker <deepstar(at)ulyssis.org> |
2005-04-26 13:48:32 |
[ SNIP ]
|
Hi,
more information on the buffer overflow later in this mail ;)
let me first ask the question that got me into digging into the code:
At our site, we use a weird failover setup on our webproxies (which are
running pound of course)
for each IP-address defined on the webproxy, a REDIRECT is done in
netfilter to a specific port from port 443.
For example connections to 192.168.0.2:443 are redirected to
192.168.0.1:444 and 192.168.0.3:443 to 192.168.0.1:445
We then have a number of pounds running, each on a different port ( 444
and 445 in this case), handling the requests
This allows us to have a hot standby webproxy listening on the same
ports, but without the IP's bound to interfaces. When the main webproxy
goes down, the backup detects it (keepalived), and takes over the IP's.
Because the pounds are listening to 1 specific port, and not IP's, the
socket on the backup webproxy does not have to be rebound to the IP of
the main webproxy (or a separate pound started on that IP), but it can
just start processing requests right away.
OK, right. and now for the problem.
Connecting to the webproxy on 192.168.0.2:443 redirects to
192.168.0.1:444. This connection is accepted by pound, which connects to
the backend and passes the host header: Host: 192.168.0.2:444
This is obviously not what was intended, because clients receiving URL's
with port 444 in it, won't be able to connect.
What I need is a way to manipulate the Host header sent to the backend.
Is there a way to do this ?
now the buffer overflow:
while going through the sourcecode to see where the portnumber is added
to a Host: header, I found this function in svc.c:
char *
add_port(char *host, struct sockaddr_in *to_host)
{
char res[MAXBUF];
if(strchr(host, ':') != NULL)
/* the host already contains a port */
return NULL;
sprintf(res, "Host: %s:%hd", host, ntohs(to_host->sin_port));
return strdup(res);
}
MAXBUF is 2048
when a hostname of 2047 bytes is passed to pound, pound crashes because
the res buffer is only 2048 bytes, and at least 2047+8 bytes are required.
At this point I haven't looked whether this could be exploited, but it is not
clean.
I tested it with this line:
(echo "GET / HTTP/1.0"; echo -n "Host: "; perl -e 'print "A"x2040'; echo; echo)
| nc 0.0.0.0 8080
followed by
(echo "GET / HTTP/1.0"; echo -n "Host: "; perl -e 'print "A"x2048'; echo; echo)
| nc 0.0.0.0 8080
(for some reason, I first need to send 2040 bytes...)
and this config:
ListenHTTP *,8080
UrlGroup ".*"
BackEnd 127.0.0.1,1234,1
EndGroup
On port 1234, there is just a netcat listening that allows pound to connect
This is what I get in the logs:
Apr 26 13:42:12 localhost pound: MONITOR: worker exited on signal 11,
restarting...
Apr 26 13:42:20 localhost pound: received signal 2 - exiting...
Apr 26 13:42:20 localhost pound: received signal 2 - exiting...
A quick and dirty patch would be to replace the line:
sprintf(res, "Host: %s:%hd", host, ntohs(to_host->sin_port));
with:
snprintf(res,sizeof(res) - 1,"Host: %s:%hd", host,
ntohs(to_host->sin_port));
greets,
-- Steven Van Acker
|
|
|
Re: remote buffer overflow in pound 1.8.2 + question abotu Host
header
Robert Segall <roseg(at)apsis.ch> |
2005-04-26 15:48:04 |
[ SNIP ]
|
On Tue, 26 Apr 2005 13:48:32 +0200 Steven Van Acker
<deepstar(at)ulyssis.org> wrote:
> Hi,
>
> more information on the buffer overflow later in this mail ;)
>
> let me first ask the question that got me into digging into the code:
>
> At our site, we use a weird failover setup on our webproxies (which
> are
> running pound of course)
>
> for each IP-address defined on the webproxy, a REDIRECT is done in
> netfilter to a specific port from port 443.
>
> For example connections to 192.168.0.2:443 are redirected to
> 192.168.0.1:444 and 192.168.0.3:443 to 192.168.0.1:445
> We then have a number of pounds running, each on a different port (
> 444
> and 445 in this case), handling the requests
>
> This allows us to have a hot standby webproxy listening on the same
> ports, but without the IP's bound to interfaces. When the main
> webproxy
> goes down, the backup detects it (keepalived), and takes over the
> IP's.
>
> Because the pounds are listening to 1 specific port, and not IP's, the
> socket on the backup webproxy does not have to be rebound to the IP of
> the main webproxy (or a separate pound started on that IP), but it can
> just start processing requests right away.
>
> OK, right. and now for the problem.
>
> Connecting to the webproxy on 192.168.0.2:443 redirects to
> 192.168.0.1:444. This connection is accepted by pound, which connects
> to
> the backend and passes the host header: Host: 192.168.0.2:444
> This is obviously not what was intended, because clients receiving
> URL's
> with port 444 in it, won't be able to connect.
>
> What I need is a way to manipulate the Host header sent to the
> backend.
> Is there a way to do this ?
No. Pound passes to the back-end the Host header exactly as generated by
the client browser. Your only option is to remove it altogether, but
most web servers would not like that (it's required in HTTP/1.1).
> now the buffer overflow:
>
> while going through the sourcecode to see where the portnumber is
> added
> to a Host: header, I found this function in svc.c:
>
> char *
> add_port(char *host, struct sockaddr_in *to_host)
> {
> char res[MAXBUF];
>
> if(strchr(host, ':') != NULL)
> /* the host already contains a port */
> return NULL;
> sprintf(res, "Host: %s:%hd", host, ntohs(to_host->sin_port));
> return strdup(res);
> }
>
> MAXBUF is 2048
>
> when a hostname of 2047 bytes is passed to pound, pound crashes
> because
> the res buffer is only 2048 bytes, and at least 2047+8 bytes are
> required.
> At this point I haven't looked whether this could be exploited, but it
> is not clean.
>
> I tested it with this line:
>
> (echo "GET / HTTP/1.0"; echo -n "Host: "; perl -e 'print "A"x2040';
> echo; echo) | nc 0.0.0.0 8080
> followed by
> (echo "GET / HTTP/1.0"; echo -n "Host: "; perl -e 'print "A"x2048';
> echo; echo) | nc 0.0.0.0 8080
>
> (for some reason, I first need to send 2040 bytes...)
>
> and this config:
>
> ListenHTTP *,8080
>
> UrlGroup ".*"
> BackEnd 127.0.0.1,1234,1
> EndGroup
>
> On port 1234, there is just a netcat listening that allows pound to
> connect
>
> This is what I get in the logs:
>
> Apr 26 13:42:12 localhost pound: MONITOR: worker exited on signal 11,
> restarting...
> Apr 26 13:42:20 localhost pound: received signal 2 - exiting...
> Apr 26 13:42:20 localhost pound: received signal 2 - exiting...
>
> A quick and dirty patch would be to replace the line:
> sprintf(res, "Host: %s:%hd", host, ntohs(to_host->sin_port));
> with:
> snprintf(res,sizeof(res) - 1,"Host: %s:%hd", host,
> ntohs(to_host->sin_port));
>
> greets,
> -- Steven Van Acker
>
Thanks for the heads up - see 1.8.3.
--
Robert Segall
Apsis GmbH
Postfach, Uetikon am See, CH-8707
Tel: +41-44-920 4904
|
|
|
Re: remote buffer overflow in pound 1.8.2 + question abotu Host header
Steven Van Acker <deepstar(at)ulyssis.org> |
2005-04-27 09:26:29 |
[ SNIP ]
|
On Tue, Apr 26, 2005 at 03:48:04PM +0200, Robert Segall wrote:
> On Tue, 26 Apr 2005 13:48:32 +0200 Steven Van Acker
> > What I need is a way to manipulate the Host header sent to the
> > backend.
> > Is there a way to do this ?
>
> No. Pound passes to the back-end the Host header exactly as generated by
> the client browser. Your only option is to remove it altogether, but
> most web servers would not like that (it's required in HTTP/1.1).
>
I'm sure it should be possible to provide an obscure configuration
option for it :)
I'll have a look and try to make a patch for it.
> Thanks for the heads up - see 1.8.3.
no problem!
greets,
-- Steven
|
|
|
Re: remote buffer overflow in pound 1.8.2 + question abotu Host header
Peter van Dijk <peter(at)nextgear.nl> |
2005-04-27 17:33:55 |
[ SNIP ]
|
On Tue, Apr 26, 2005 at 03:48:04PM +0200, Robert Segall wrote:
> No. Pound passes to the back-end the Host header exactly as generated by
> the client browser. Your only option is to remove it altogether, but
> most web servers would not like that (it's required in HTTP/1.1).
Hmm, in my experience it adds a :80 to the Host header. This prompted
us to fix some PHP code which wasn't expecting a trailing port number
or a trailing dot :)
Cheers,
Peter.
[repost; it seems the mailinglist checks sender addresses; if you get this
multiple times, my apologies]
|
|
|
|