It's Bugs All the Way Down

Security Research by Dan Rosenberg

Exploiting nano

A number of standard Linux utilities have been documented as being unsafe to run as root on untrusted input, from a security standpoint. For example, the ldd utility, designed to enumerate the dynamic library dependencies of executables, has documented behavior that may result in execution of arbitrary code when run on untrusted binaries [1]. The popular text editor, nano, is another example of a program that is unsafe to run as root on untrusted input. I hope to demonstrate that many of the assumptions users make in regards to security no longer apply in the scenario of running as root in a hostile environment.

The issues presented here have been reported responsibly to both downstream distribution security teams and the developers of nano, and have not been prioritized as issues requiring a security update. They may or may not be addressed in subsequent releases of nano, but I agree with the assessment of the security teams I have spoken with: these issues do not constitute a significant risk to users in most cases. I want to be clear about what this post is – it is not my intent to disclose bugs that I think could be easily exploited in real life scenarios, but rather examine how certain programs are not designed to be run in certain circumstances, and hopefully encourage users to seriously consider which tools to use in these circumstances.

File Swapping

Unlike some text editors, such as vi, nano provides no warning when the file a user is editing has been modified outside of the context of that editing session. In addition, nano does not maintain an open file descriptor to the file being edited during the process of editing. Instead, the file is newly opened and written to upon being saved, without checking to confirm that the file being saved to is the same as what was opened by the user.

A malicious user could exploit this property by convincing the root user to edit an attacker-controlled file, and during the editing session, replacing this file with a symbolic link to a target file. On saving changes, the target file will be overwritten with the attacker’s document. This would most likely be used to create denial-of-service scenarios, but one could dream up situations in which this could possibly lead to privilege escalation.

Backup File Race Conditions

nano allows users to specify an option to create backup files on saving a document. This option can be enabled by inserting the “set backup” directive in a nano configuration file, such as the global settings provided by /etc/nanorc. On saving a file that is being edited, a backup file is created at the same location by appending a tilde (~) to the original file name.

When a file is edited by root with backup files enabled, any backup files are originally created by root and must be chmod’d and chown’d to properly set permissions and ownership. The way in which these actions are performed is vulnerable to exploitation due to race conditions. The following steps are taken:

  • 1. The backup file is opened using fopen(), without checking whether or not the file exists or has been replaced by a symbolic link.
  • 2. nano calls chmod() to change the permissions of the backup file to that of the original file being edited.
  • 3. The backup is written to the backup file using the file descriptor obtained by the previousfopen() call.
  • 4. nano calls chown() to change the ownership of the backup file to that of the original file being edited.

This series of steps can be exploited in a number of ways. First, since no checking is performed upon opening the file, an attacker can simply place a symbolic link at the backup file location (for example, “myfile~”). If root edits and saves “myfile”, the target pointed to by this symbolic link will be overwritten with the attacker’s file and chown’d to the attacker, allowing full privilege escalation.

It is also possible for the attacker to change the permissions or ownership of a target file without overwriting it. If the attacker-controlled file resides in a directory without the sticky bit set, the attacker can exploit the window between the calls to fopen() and chmod()/chown(). After the backup file is opened or created by fopen(), the attacker can delete this file and replace it with a symbolic link, and the target of this link will be chown’d and chmod’d. Alternately, in cases where the attacker can not delete a root-owned file in the working directory, the attacker can create a symbolic link to a target to be overwritten, and switch this symbolic link to point to a separate target before the calls to chmod() or chown(). All of these circumstances can easily lead to privilege escalation by changing permissions or ownership of sensitive system files. With knowledge of these race conditions, an attacker can run an automated script that booby-traps a file, such that whenever it is edited by root, privilege escalation is achieved. I have created a proof-of-concept exploit that accomplishes exactly this.

Fixing the Problems

The resolution of these issues is simple, but may require some restructuring of nano’s source code. To resolve the first issue, nano should maintain an open file descriptor to the file that is being edited throughout the duration of the editing process. On saving, this file descriptor should be rewound and written to, preventing a window of vulnerability in which the file may be replaced by an attacker.

A similar strategy can be used to resolve the race conditions in the creation of backup files. If a previous backup file already exists, it should be opened with open() or fopen(), and fstat() should be called to confirm that the owner of the existing backup file is the same as the owner of the file that is being edited – otherwise, an attack may take place. If a backup file does not exist, a new backup file should be created using open() with O_EXCL and O_CREAT (mileage may vary when working with NFS, but a good effort should be made). Finally, fchown() and fchmod() should be called on the file descriptor returned by the open() call, to prevent a window of vulnerability in between the creation of the file and calls to chmod() and chown() on the filename.

Conclusion

It appears that nano was not designed with these attack scenarios in mind. Administrators should be careful in their choices of text editors when editing the files of potentially malicious users – while such scenarios are unlikely, there are many avenues of attack that can result in privilege escalation.

This entry was posted on Saturday, March 27th, 2010 at 2:52 pm and is filed under Exploitation, Linux. You can follow any responses to this entry through the RSS 2.0 feed. Both comments and pings are currently closed.