Making /tmp non-executable
Posted by Steve on Wed 15 Dec 2004 at 13:08
Many simple exploits that are used against machines, (via vulnerable PHP applications or local users, etc), rely upon being able to execute commands in /tmp. If this is a seperate partition or file system you can gain some protection by marking it non-executable. The common problem with this is that apt-get fails to work with such a setup.
When you mount a partition there are many flags that can be used, two interesting ones are:
noexec nosetuid
(A full list can be read as part of man mount).
The two flags are explained fully in the man page for mount, but briefly:
- noexec
- Do not allow execution of any binaries on the mounted file system.
- nosuid
- Do not allow set-user-identifier or set-group-identifier bits to take effect.
Mounting filesystems with these flags set raises the bar a little, but it doesn't stop files from being executed. The Linux linker and loader will permit binaries to be run:
# Make /tmp non-executable root@earth:~# mount -o remount,noexec /tmp # Copy an executable into it root@earth:~# cp /bin/ls /tmp root@earth:~# chmod 755 /tmp/ls # Test it - the execution should fail. root@earth:~# /tmp/ls bash: /tmp/ls: Permission denied # But .. what's this? It still runs? root@earth:~# /lib/ld-linux.so.2 /tmp/ls Mail public_html # cleanup root@earth:~# rm /tmp/ls root@earth:~# mount -o remount,exec /tmp
With that in mind you might wonder what the point is? Well it foils any simplistic attack that relies upon putting a script in /tmp and running it. If they've got shell access they can probably figure it out, but an automated tool would be foiled - for the moment.
To make your system have a non-executable /tmp partition you must edit the way that it is mounted in the file /etc/fstab. Find the line that contains /tmp and change the defaults to read nosuid,noexec instead.
For example this is my updated /etc/fstab file:
/dev/sda3 /tmp ext3 noexec,nosuid 0 2
This will take effect the next time you mount the filesystem, you can do this now with:
mount -o remount /tmp
Very if it by running:
root@earth:/tmp# mount |grep /tmp /dev/sda3 on /tmp type ext3 (rw,noexec,nosuid)
The output line should contain the two words 'noexec,nosuid' in it. If this is in place then you're covered.
The only problem now is that when apt-get upgrades your system it will sometimes place scripts inside the temp directory which will now not be executable.
The fix for this is to temporarily make the temporary directory executable before running apt-get and then remove the execution bits afterwards. This would be a troublesome thing to remember doing ourselves - but thankfully we can set it up to be automatic.
Add the following to the file /etc/apt/apt.conf:
DPkg::Pre-Invoke{"mount -o remount,exec /tmp";};
DPkg::Post-Invoke {"mount -o remount /tmp";};
This contains two lines, one running before any packing installation and one afterwards. They merely execute the commands required to add and remove the execute permissions on the /tmp
[ Parent | Reply to this comment ]
[ Parent | Reply to this comment ]
It doesn't really gain you very much as normal users cannot write to this directory - unlike /tmp.
Steve
-- Steve.org.uk
[ Parent | Reply to this comment ]
[ Parent | Reply to this comment ]
[ Parent | Reply to this comment ]
[ Parent | Reply to this comment ]
[ Parent | Reply to this comment ]
Or another suitable directory, probably better than remounting.
[ Parent | Reply to this comment ]
I suppose it's just a matter of time until the typical exploit tries /var/tmp as well, if they don't do that already. So either remount, or use some completely other directory.
Of course if you're afraid of an script hitting /tmp while you install packages, you might use a combination of both. Even setting up a semi-random tmpfs mount at install time would do, but I guess that's a level of paranoia that I don't want to think about. ;) --
Debian GNU/Linux on an IBM Thinkpad T43p
[ Parent | Reply to this comment ]
--
Ubuntu 12.04 x64 GNU/Linux on EeePC 1201N - still gathering the strength for documenting the install experience
[ Parent | Reply to this comment ]
DPkg::Pre-Invoke{"mount -t tmpfs -o size=512m tmpfs /apt-tmp";};
DPkg::Post-Invoke{"umount /apt-tmp";};
APT
{
ExtractTemplates
{
TempDir "/apt-tmp";
};
};
[ Parent | Reply to this comment ]
you would need to change the following:
DPkg::Pre-Install-Pkgs
should be
DPkg::Pre-Invoke
otherwise it is too late in the process for pre-configuring packages (using Perl for example)
#man apt.conf
for more info.
[ Parent | Reply to this comment ]
mrvn@storage:~% ls -lh /tmp/sh
-rwxr-xr-x 1 mrvn mrvn 713K Feb 20 12:05 /tmp/sh*
mrvn@storage:~% /lib/ld-2.3.2.so /tmp/sh
/tmp/sh: error while loading shared libraries: /tmp/sh: failed to map segment from shared object: Operation not permitted
MfG
Goswin
[ Parent | Reply to this comment ]
[ Parent | Reply to this comment ]
[ View Steve's Scratchpad | View Weblogs ]
Nothing.
[ Parent | Reply to this comment ]
[ Parent | Reply to this comment ]
[ Parent | Reply to this comment ]
Make a file-based partition. Mount that as noexec /tmp. Done. All the below needs to be done as root, or with magic word ("sudo", not "please") in the right place.
- Make 100MB /tmp file-based partition
dd if=/dev/zero of=/TMPFILE bs=1024 count=100000
mkfs.ext3 /TMPFILE - Add to /etc/fstab
/TMPFILE /tmp ext3 loop,noexec,nosuid,rw 0 0 - Mount /tmp (you may need to restart services which keep socket files in /tmp after this!)
mount /tmp - If the final command fails, you may need to create your /dev/loop# entries. (Check if /dev/loop0 exists, for example.) If so, then:
for ii in 0 1 2 3 4 5 6 7 8 ; do mknod -m660 /dev/loop$ii b 7 $ii ; done
[ Parent | Reply to this comment ]
mount -o bind /tmp /tmp;
mount -o remount,noexec,nosuid /tmp;
[ Parent | Reply to this comment ]
/dev/shm /tmp tmpfs rw,bind,nosuid,noexec 0 0
Note that this will limit the size of /tmp to one half of your available RAM (by default) and that it will be cleared on reboot (usually the case anyway).
[ Parent | Reply to this comment ]
[ Parent | Reply to this comment ]