miércoles, febrero 27, 2008

How to make a sandbox

A real sandbox should be a loadable kernel module, but we can easilly make one at user space by coding a lib in order to be preloaded after every execution.

gcc -fPIC sandwich.c -o sandwich.so -shared
export LD_PRELOAD=`pwd`/sandwich.so

now connect() and sento() are hooked, then we can exec our "unsafe" programs,
if they try to connect will be intercepted.

Well, this can be bypassed by calling directly the syscall or using not implemented functions.

// $ gcc -fPIC sandwich.c -o sandwich.so -shared
#define RTLD_NEXT ((void *) -1l)
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <dlfcn.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <strings.h>
#include <netdb.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <errno.h>
#include <fcntl.h>
//Real Calls
static int (*realConnect)(int sockfd,
const struct sockaddr *serv_addr,
socklen_t addrlen);
ssize_t (*realSendto)(int s,
const void *msg,
size_t len,
int flags,
const struct sockaddr *to,
socklen_t tolen);
//Hooked Calls
int connect(int sockfd,
const struct sockaddr *serv_addr,
socklen_t addrlen);
ssize_t sendto(int s,
const void *msg,
size_t len,
int flags,
const struct sockaddr *to,
socklen_t tolen);

int connect(int sockfd,
const struct sockaddr *serv_addr,
socklen_t addrlen) {
int opt;
struct sockaddr_in *s = (struct sockaddr_in *)serv_addr;

printf("Can I connect to %s:%d (Y/N)?",
inet_ntoa(s->sin_addr),s->sin_port);
opt = getchar();
if (opt=='S' || opt=='s' || opt=='y' || opt=='Y') {
realConnect = dlsym(RTLD_NEXT, "connect");
return realConnect(sockfd,serv_addr,addrlen);

} else {
printf("Cancelled ;)\n");
return -1;
}
}

ssize_t sendto(int s,
const void *msg,
size_t len,
int flags,
const struct sockaddr *to,
socklen_t tolen) {
int opt;
struct sockaddr_in *ss = (struct sockaddr_in *)to;

printf("Can I connect to %s:%d (Y/N)?",inet_ntoa(ss->sin_addr),ss->sin_port);
opt = getchar();
if (opt=='S' || opt=='s' || opt=='y' || opt=='Y') {
realSendto = dlsym(RTLD_NEXT, "sendto");
return realSendto(s,msg,len,flags,to,tolen);

} else {
printf("Cancelled ;)\n");
return -1;
}
}

No hay comentarios: