Friday, December 15. 2006
Within a shared hosting environment it is
sometimes quite often possible to bind yourself to some high TCP port and accept incoming connections. Sometimes this is possible because you also get a shell account on the box and sometimes because dangerous PHP functions like stream_socket_server() are not disabled in the configuration. Unfortunately the ability to bind yourself to a port and receive connections is a threat to webapplications installed on different virtual hosts on the same IP, even if other security measures in place, like tight filesystem permissions or executing PHP script with the permission of the owner.
Consider the following PHP script, that will accept incoming connections on port 7778 and print out the connecting user's IP and the content he sends until an empty line.
<?php
$socket = stream_socket_server("tcp://0.0.0.0:7778",
$errno, $errstr);
if (!$socket) {
echo "$errstr ($errno)<br />\n";
} else {
while ($conn = stream_socket_accept($socket)) {
echo "<h3>".stream_socket_get_name($conn, true)
."</h3><br />\n";
do {
$line = fgets($conn);
echo $line . "<br />\n";
ob_flush(); flush();
} while (!feof($conn) && strlen(trim($line))>0);
fclose($conn);
}
fclose($socket);
}?>
Now guess what happens when you connect with your browser to http://my.bookshop.shop:7778/ which happens to share the same IP with your script. The browser will connect to the port under your control and send it's HTTP headers to your script. Unfortunately this HTTP headers will also contain the cookie stored for http://my.bookshop.shop/ because browsers do not save the port number of the HTTP server that orginally set the cookie. This enables anyone on the same IP with the ability to accept connections to steal cookies from other people's webapplications.
A trivial but annoying trick. And considering how many people are vulnerable to URL Include vulnerabilities you can be pretty sure that the majority of PHP5 hosting servers will allow stream_socket_server().