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
$