Dear OpenBSD devs,
As part of our ongoing information security research into software vulnerabilities Sense of Security has identified a security vulnerability in OpenBSD’s lpr daemon. Sense of Security is an advocate of full disclosure and intends to publish a security advisory for this vulnerability in accordance with our vulnerability disclosure policy found here: http://www.senseofsecurity.com.au/research/vulnerability-disclosure-policy. This security advisory will be posted to all major security vulnerability mailing lists and on our web site. Some previous examples can be viewed here: http://www.senseofsecurity.com.au/research/it-security-advisories.php The vulnerability is a variant of a previously known race-condition, in which the attacker proceeded as follows: 1. Disable a printer (by unplugging it, sending a lenghty print job etc.) 2. Request the printing of a file through a symbolic link (lpr -s) 3. Replace the file to print with a symbolic to another file, which the attacker is not allowed to read (e.g. /etc/shadow) 4. Once the printer becomes available, the target file is printed. The mechanism to prevent this attack currently involves storing the printed file’s inode number in the CF file and ensuring that it has not changed before the actual printing starts. However this remains vulnerable. The bug occurs in usr.sbin/lpr/lpd/printjob.c, line 428: fino = i; where “fino” is the inode number extracted from the print job’s CF file, with which the actual file’s inode number is compared. As of revision 1.58 available in the OpenBSD CVS, the variable “i” is declared “int” (line 337), so it remains a 32-bit integer even on amd64 systems (among other 64 bit architectures). Consequently the inode number comparison for symlink print jobs is effectively truncated to 32 bits. On a 64-bit filesystem with dynamic inode allocation, it is thus possible for an attacker to find or create a file whose inode number’s lower 32 bits will match the inode number of another file, in particular a file the attacker is not allowed to access. If the latter file’s inode number is lower than 2^32, the check will pass and the attacker will be able to print the file. We tested this scenario on a Linux kernel using the BTRFS filesystem. In BTRFS inodes are created dynamically and 64-bit inode numbers are assigned in sequence. Using a proof-of-concept program we created and deleted files repeatedly until we obtained a 32-bit inode number match against /etc/shadow. In our test environment, this process took approx. 4 days (in a virtual machine hosted on a HP Elitebook laptop). The race-condition as described above then succeeds and it is possible to “print” /etc/shadow or, as in this case, effectively send it to a simulated network printer. One of the possible solutions is to parse the inode number from the CF file using a 64-bit accumulator variable instead of “i”, or to declare “i” as unsigned long long. If you have any further questions please feel free to contact us directly, we are happy to assist with demonstrating the bug or testing your resolution. Kind Regards, Jacob Zimmermann -- Jacob Zimmermann – Security Consultant [cid:[email protected]] Level 8, 66 King Street, Sydney NSW 2000, AUSTRALIA T: +61 2 9290 4481 | M : +61 (0)423 973 297 [email protected]<mailto:[email protected]>
