Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Date: Tue, 14 Aug 2012 00:03:18 -0600
From: Kurt Seifried <kseifried@...hat.com>
To: oss-security@...ts.openwall.com
CC: "Jason A. Donenfeld" <Jason@...c4.com>
Subject: Re: Tunnel Blick: Multiple Vulnerabilities to Local
 Root and DoS (OS X)

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On 08/13/2012 06:34 AM, Jason A. Donenfeld wrote:
> Hi Kurt,
> 
> Sure, I'll trace each one, and include line numbers with the code. 
> This code comes from: 
> http://code.google.com/p/tunnelblick/source/browse/trunk/tunnelblick/openvpnstart.m?r=2095

Thanks,
> 
without the details this would have been impossible, as it is
I'm going to break one CVE editorial rule, but I think it's for a good
reason (but I could also be wrong). So in summary:

==================
1. A race condition in file permissions checking can lead to local
root. - TOCTOU

Please use CVE-2012-3483 for this issue

==================
2. Insufficient checking of merely 0:0 744 can lead to local root on
systems with particular configurations.

Please use CVE-2012-3484 for this issue

==================
3. Insufficient validation of path names can allow for arbitrary
kernel module loading, which can lead to local root.
4. Insufficient validation of path names can allow execution of
arbitrary scripts as root, leading to local root.
5. Insufficient path validation in errorExitIfAttackViaString can lead
to deletion of files as root, leading to DoS.

Please use CVE-2012-3485 for these issues

==================
6. Allowing OpenVPN to run with user given configurations can lead to
local root.

Please use CVE-2012-3486 for this issue

==================
7. Race condition in process killing. - TOCTOU

Please use CVE-2012-3487 for this issue



although #1 and #7 are both TOCTOU race conditions (and thus should be
merged) one is a classic file perms check/use, the other is quite
different, process listing/killing, so I split the CVE (they are
sufficiently different to warrant it I think).


> 
> 1. A race condition in file permissions checking can lead to local
> root. PoC:
> http://git.zx2c4.com/Pwnnel-Blicker/tree/pwnnel-blicker.c
> 
> 927	int runScript(NSString * scriptName, 928	               int
> argc, 929	               char     * cfgName, 930
> char     * cfgLoc) 931	{ * 964	                if (
> checkOwnerAndPermissions(scriptPath, 0, 0, @"744")  ) { 965 966
> fprintf(stderr, "'%s' executing...\n", [scriptName UTF8String]); *
> 967	                    returnValue = runAsRoot(scriptPath,
> [NSArray array]); 968	                    fprintf(stderr, "'%s'
> returned with status %d\n", [scriptName UTF8String], returnValue); 
> 969	                }
> 
> Here, there's a race condition between the two stared lines.
> 
> 
> 2. Insufficient checking of merely 0:0 744 can lead to local root
> on systems with particular configurations.
> 
> 964	                if (  checkOwnerAndPermissions(scriptPath, 0, 
> 0, @"744")  ) { and 801	            if (  !
> checkOwnerAndPermissions(preConnectPath, 0, 0, @"744")  ) { and 847
> if (  ! checkOwnerAndPermissions(postTunTapPath, 0, 0, @"744")  )
> { and 1675	                if (  !
> checkOwnerAndPermissions(filePath, 0, 0, @"744")  ) {       //
> shell scripts are 744
> 
> Testing a file for whether or not it's 744 and owned by root:root
> is not sufficient for deciding whether a unprivileged should be
> able to run it as root. This not only makes every 744 root:root
> file on the file system a potential vector, but destroys the nosuid
> mount flag OS X uses for all user mountable images and network
> shares.
> 
> 
> 3. Insufficient validation of path names can allow for arbitrary 
> kernel module loading, which can lead to local root.
> 
> 86	    execPath = [[NSString stringWithUTF8String:argv[0]] 
> stringByDeletingLastPathComponent]; 1355	void loadKexts(unsigned
> int bitMask) 1356	{ 1357	    if (  ( bitMask &
> (OPENVPNSTART_OUR_TAP_KEXT | OPENVPNSTART_OUR_TUN_KEXT) ) == 0  )
> { 1358	        return; 1359	    } 1360 1361	    NSMutableArray*
> arguments = [NSMutableArray arrayWithCapacity: 2]; 1362	    if (
> (bitMask & OPENVPNSTART_OUR_TAP_KEXT) != 0  ) { 1363
> NSString * tapkext = [@"tap" stringByAppendingString: 
> TunTapSuffixToUse([execPath stringByAppendingPathComponent:
> @"tap"])]; 1364	        [arguments addObject: [execPath 
> stringByAppendingPathComponent: tapkext]]; 1365
> fprintf(stderr, "Loading %s\n", [tapkext UTF8String]); 1366	    } 
> 1367	    if (  (bitMask & OPENVPNSTART_OUR_TUN_KEXT) != 0  ) { 1368
> NSString * tunkext = [@"tun" stringByAppendingString: 
> TunTapSuffixToUse([execPath stringByAppendingPathComponent:
> @"tun"])]; 1369	        [arguments addObject: [execPath 
> stringByAppendingPathComponent: tunkext]]; 1370
> fprintf(stderr, "Loading %s\n", [tunkext UTF8String]); 1371	    } 
> 1372 1373	    becomeRoot();
> 
> 1374	    int status; 1375	    int i; 1376	    for (i=0; i < 5; i++)
> { 1377	        NSTask * task = [[[NSTask alloc] init]
> autorelease]; 1378 1379	        [task
> setLaunchPath:@"/sbin/kextload"]; 1380 1381	        [task
> setArguments:arguments]; 1382 1383	        [task launch];
> 
> As you can see, the file name of the kernel extension being loaded
> is derived from argv[0], which can be trivially bypassed (
> execl(..., "/attacker/controlled/argv/zero", ...) ).
> 
> 
> 4. Insufficient validation of path names can allow execution of 
> arbitrary scripts as root, leading to local root. PoC:
> http://git.zx2c4.com/Pwnnel-Blicker/tree/pwnnel-blicker-for-kids.sh
>
>  86	    execPath = [[NSString stringWithUTF8String:argv[0]] 
> stringByDeletingLastPathComponent]; 919	void
> runOpenVpnToGetVersion(NSString * openvpnVersion) 920	{ 921
> NSString * openvpnPath = openvpnToUsePath([execPath 
> stringByAppendingPathComponent: @"openvpn"], openvpnVersion); 922
> runAsRoot(openvpnPath, [NSArray arrayWithObject: @"--version"]); 
> 923	}
> 
> This basically amounts to this being run as root:  $(dirname 
> argv[0])/openvpn --version.
> 
> 
> 
> 5. Insufficient path validation in errorExitIfAttackViaString can
> lead to deletion of files as root, leading to DoS. 164	        }
> else if( strcmp(command, "deleteLogs") == 0 ) { 165				if (argc ==
> 4) { 166					NSString* configFile = [NSString
> stringWithUTF8String:argv[2]]; 167
> errorExitIfAttackViaString(configFile); 168
> unsigned cfgLocCode = atoi(argv[3]); 169
> deleteLogFiles(configFile, cfgLocCode); 170
> syntaxError = FALSE; 171	            } 1735	void
> errorExitIfAttackViaString(NSString * string) 1736	{ 1737	    BOOL
> startsWithDot = [string hasPrefix: @"."]; 1738	    NSRange r =
> [string rangeOfString: @"/.."]; 1739	    if (   startsWithDot 1740
> || (r.length != 0)  ) { 1741	        fprintf(stderr, "Tunnelblick
> openvpnstart: Apparent attack detected; string being tested is
> %s\n", [string UTF8String]); 1742	        [pool drain]; 1743
> exit(EXIT_FAILURE); 1744	    } 1745	}
> 
> The "exit if attack string" function doesn't check for links of
> any kind, symbolic or hard, so this validation is not sufficient.
> 
> 
> 6. Allowing OpenVPN to run with user given configurations can lead
> to local root. 939	        if (  [configFile hasSuffix: @"tblk"]  )
> { 940	            unsigned  cfgLocCode = atoi(cfgLoc); 941
> switch (cfgLocCode) { 942	                case 0: 943
> configPrefix = [NSHomeDirectory() 
> stringByAppendingPathComponent:@"/Library/Application 
> Support/Tunnelblick/Configurations"]; 944
> break; 945	                case 1: 946
> configPrefix = [NSString stringWithFormat:@"/Library/Application
> Support/Tunnelblick/Users/%@", NSUserName()]; 947
> break; 948	                case 2: 949
> configPrefix = [execPath stringByAppendingPathComponent:
> @"Deploy"]; 950	                    break; 951	                case
> 3: 952	                    configPrefix = [NSString
> stringWithString: @"/Library/Application
> Support/Tunnelblick/Shared"]; 953	                    break; 954
> default: 955	                    break; 956	            } 957
> } The purpose of this SUID helper is so that users can run OpenVPN
> with their own provided configuration files as root. OpenVPN
> configuration files can run scripts based on various OpenVPN
> events.
> 
> 
> 7. Race condition in process killing. 1496	BOOL isOpenvpn(pid_t
> pid) 1497	{ 1498		BOOL				is_openvpn	= FALSE; 1499		int					count
> = 0, 1500		i			= 0; 1501		struct kinfo_proc*	info		= NULL; 1502 
> 1503		getProcesses(&info, &count); 1504	    for (i = 0; i < count;
> i++) { 1505	        char* process_name = info[i].kp_proc.p_comm; 
> 1506	        pid_t thisPid = info[i].kp_proc.p_pid; 1507	        if
> (pid == thisPid) { 1508				if (strcmp(process_name, "openvpn")==0)
> { 1509					is_openvpn = TRUE; 1510				} else { 1511					is_openvpn
> = FALSE; 1512				} 1513				break; 1514			} 1515	    } 1516
> free(info); 1517		return is_openvpn; 1518	}
> 
> 991		if(isOpenvpn(pid)) { 992			becomeRoot(); 993			didnotKill =
> kill(pid, SIGTERM); and 1022			if(strcmp(process_name, "openvpn")
> == 0) { 1023				becomeRoot(); 1024				didnotKill = kill(pid,
> SIGTERM);
> 
> There's a race between checking the name of the process and
> killing that PID. Since PIDs are cycled, eventually that PID could
> point to a different process the user shouldn't have permission to
> kill.
> 
> 
> Hope this clarifies things. Let me know if you have more
> questions.
> 
> Jason
> 


- -- 
Kurt Seifried Red Hat Security Response Team (SRT)
PGP: 0x5E267993 A90B F995 7350 148F 66BF 7554 160D 4553 5E26 7993

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.12 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iQIcBAEBAgAGBQJQKeomAAoJEBYNRVNeJnmTLMwQALPTVxjFKEb4qtnsB5h0GGV+
LkgubkWO5RuaedLvQsWNqqxDDgDWRDMP+PRwicTLq1bqHJ4ifa54eJnm8q/yyinX
tXCsQrDE0O6f5jXrdEsoOwdeWRn82zD4diFAWEeOI7U166TRTYyFIAmIa0MDgZaw
PHNsS8RccDXOc/Rraz3iV/7sWzU6e6KpmW1vhpbXjxUz6zuSGHATTdPPFAC/sTwf
HycD1wMP1FmSbeBfoliLpb+Ibj+AZUCqsn4efwr0LgsZCmoKvpnEsbfRaNEaeARo
1LzGhCBFWgCSePmebmqWsYP9oPfWlRCwRWrCzX7j/Y272MytkYXbLeUfVQvPc0TW
okyfwtHvNpSHU5AqSMt2DmE62U/275feJgfRTmP4xDGOFE9UTiVKjFz2Jy//KRnY
KvLvoIC7SqPIQvy9bb8QE8IqMyKGq/oF1SP28iOsCSFDes+CRwkr6xXSILiDCzd9
5J4qNi0vSdp1EabQEHtOqwE9kITbO/pSCswd9KQDp8KHV5GeLV76XpBNVY1vDjH6
WWDC0715JQa+TrArCeOIJBI684sdvPPQcWB+P45j/OC4DKHOn4koRa0+LYingq5a
ntpw+fkdhhaf+3StaBlROOEHHkbhdxg8gZgGrRH8r5pQ0A8+bZXuZsJC1ezpp4BM
zN+hCjbnDxxU+5/2jZUr
=amtN
-----END PGP SIGNATURE-----

Powered by blists - more mailing lists

Please check out the Open Source Software Security Wiki, which is counterpart to this mailing list.

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.