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]>

Reply via email to