If you have a CGI script that produces multiple headers in separate writes,
then they may be delivered to httpd as separate FastCGI records, depending on
a race between the CGI script writing more headers and slowcgi framing them
and passing them on to httpd.

The fcgi code erroneously believes all headers will appear in the first chunk.

>From server_fcgi.c v1.58:
    545                         case FCGI_STDOUT:
    546                                 if (++clt->clt_chunk == 1) {
    547                                         if (server_fcgi_header(clt,

The The net effect is subsequent headers being leaked into the body of the
http reply.


To reproduce the issue:

$ sysctl kern.version
kern.version=OpenBSD 5.8-beta (GENERIC) #1117: Wed Jul 22 00:53:46 MDT 2015
    [email protected]:/usr/src/sys/arch/amd64/compile/GENERIC

$ cat /var/www/cgi-bin/foo
#!/bin/ksh

if [ -z "$QUERY_STRING" ]; then
        print 'Status: 200 OK\nContent-Type: text/plain\n\ngood'
else
        print 'Status: 200 OK'
        # add a sleep here if you have trouble triggering the race
        print 'Content-Type: text/plain'
        print ''
        print 'bad'
fi
$ cat /etc/httpd.conf
server "default" {
        listen on "*" port 80
        location "/cgi-bin/*" {
                fastcgi
                root "/"
        }
        root "/htdocs"
}
$ doas cp /bin/ksh /var/www/bin
$ doas rcctl -f start slowcgi
slowcgi(ok)
$ doas rcctl -f start httpd
httpd(ok)
$ ftp -Vo- 'http://127.0.0.1/cgi-bin/foo'
good
$ ftp -Vo- 'http://127.0.0.1/cgi-bin/foo?wat'
Content-Type: text/plain

bad
$

Reply via email to