SECURITY SANDBOXING FOR PC Vikram Chidanand Adithya

advertisement
SECURITY SANDBOXING FOR PC2
Vikram Chidanand Adithya
B.E., Visvesvaraya Technological University, India, 2006
PROJECT
Submitted in partial satisfaction of
the requirements for the degree of
MASTER OF SCIENCE
in
COMPUTER SCIENCE
at
CALIFORNIA STATE UNIVERSITY, SACRAMENTO
FALL
2011
SECURITY SANDBOXING FOR PC2
A Project
by
Vikram Chidanand Adithya
Approved by:
__________________________________, Committee Chair
John Clevenger, Ph.D.
__________________________________, Second Reader
V. Scott Gordon, Ph.D.
____________________________
Date
ii
Student: Vikram Chidanand Adithya
I certify that this student has met the requirements for format contained in the University format
manual, and that this project is suitable for shelving in the Library and credit is to be awarded for
the Project.
__________________________, Graduate Coordinator
Nikrouz Faroughi, Ph.D.
Department of Computer Science
iii
________________
Date
Abstract
of
SECURITY SANDBOXING FOR PC2
by
Vikram Chidanand Adithya
This project involves developing a Security Sandbox, which is a computer security tool that
prohibits an application from making unauthorized system calls. This tool is used in PC2 which is
Programming Contest Control System, pronounced “P-C-squared” or sometimes just “P-C-Two”
for short. The Security Sandbox limits user submitted programs from accessing restricted system
resources in a programming contest.
Every semester, the Association of Computing Machinery (ACM) at California State University,
Sacramento (CSUS) conducts a Programming Contest, which allows students from all majors to
participate. Every participating student or a team of students have to solve certain questions and
come up with a C, C++ or Java program as a solution for each problem. The judges verify the
solution, give points accordingly, and choose the winner at the end of contest.
iv
PC2 is a software system developed at CSUS. It is used to support smooth flow of programming
contests. Every participating team submits their programs to judges. PC2 takes submitted
programs and runs them as a separate thread, reporting the execution results to the judges.
This project provides a Security Sandbox that can hold and run the team submitted code. The
judges give information regarding all system calls that are permitted for each problem of the
contest. If the participant’s code tries to access unauthorized resources then the Sandbox will stop
the code from execution and further reports it to the judges.
The result of this project is a Linux based working prototype, a report on migrating it to other
platforms such as Windows and Mac OS and finally deploy the Sandbox for Programming
Contests.
_______________________, Committee Chair
John Clevenger, Ph.D.
_______________________
Date
v
DEDICATION
Dedicated to my loving parents, Chidanand Murthy & Usha Devi
vi
ACKNOWLEDGEMENTS
I would like to take this excellent opportunity to thank Dr. Cui Zhang, Department Chair,
Department of Computer Science, for her support and guidance throughout my MS program. I
would also like to thank Dr. Nikrouz Faroughi, Graduate Coordinator, Department of Computer
Science for his timely advice and support.
I thank Dr. John Clevenger for offering me this project and advising me at every level, towards its
completion. He provided new ideas and helped me in planning and executing the entire project.
His Operating System Pragmatics course inspired me to take up this project.
I take this opportunity to thank Dr. Scott Gordon for his willingness to become my second reader
and in conducting the ACM coding contests, which sharpens the student’s skills and ability to
think out of the box.
I also thank the entire PC2 team who helped me in understanding PC2, resolving implementation
issues, and in giving valuable suggestions.
I take this opportunity to thank my loving parents Chidanand Murthy and Usha Devi who had the
dream of making their son an engineer and wished him to become a MS graduate.
I thank Eric Merchant and Tracey Culbertson from Office of Global Education for assisting me
whenever I was in need of advice, from day one of my Master’s program until graduation and
beyond.
To all my friends who came across my life, supported me, motivated me and helped in being a
successful person. To my hometown Tumkur, to her beautiful state of Karnataka and to her
people.
vii
TABLE OF CONTENTS
Page
Dedication ....................................................................................................................................... vi
Acknowledgements ........................................................................................................................ vii
List of Figures ................................................................................................................................. xi
Chapter
1. INTRODUCTION ....................................................................................................................... 1
1.1 Purpose of the Project ................................................................................................... 1
1.2 About PC2 ..................................................................................................................... 1
1.3 Problem Description ..................................................................................................... 2
1.4 Proposed solution.......................................................................................................... 3
2. EXISTING COMPUTER SECURITY TOOLS .......................................................................... 5
2.1 Ptrace ............................................................................................................................ 5
2.2 Systrace ......................................................................................................................... 6
2.3 Strace ............................................................................................................................ 6
2.4 Ktrace............................................................................................................................ 7
2.5 Conclusion .................................................................................................................... 7
3. WORKING WITH SECURITY TOOLS .................................................................................... 9
3.1 Ptrace ............................................................................................................................ 9
3.2 Systrace ....................................................................................................................... 12
4. SECURITY APPROACH FOR PROGRAMMING LANGUAGES ........................................ 15
4.1 With C/C++ ................................................................................................................ 15
4.2 With Java .................................................................................................................... 16
4.2.1 Using C/C++ with JNI....................................................................................... 16
viii
4.2.2 Using Java Security Manager ............................................................................ 18
5. SOFTWARE DESIGN AND APPROACH .............................................................................. 22
5.1 Design Flow ................................................................................................................ 22
5.1.1 Judge or Administrator ...................................................................................... 23
5.1.2 Problem # .......................................................................................................... 23
5.1.3 Problem Specific Judge Policy .......................................................................... 23
5.1.4 Base Policy ........................................................................................................ 23
5.1.5 The Generate Module ........................................................................................ 23
5.1.6 Problem Specific Executable File ..................................................................... 24
5.1.7 Problem Specific C/C++ Policy File ................................................................. 24
5.1.8 Problem Specific Output Log File Name .......................................................... 24
5.1.9 Indicator for C/C++ and Java ............................................................................ 24
5.1.10 The Execute Module ....................................................................................... 24
5.1.11 Security Violation............................................................................................ 24
5.1.12 Print: No Security Violation ............................................................................ 25
5.1.13 Print: Security Violation with reason .............................................................. 25
5.1.14 Output Log file ................................................................................................ 25
5.1.15 PC2 ................................................................................................................... 25
5.2 The Generate Module ................................................................................................. 25
5.3 The Execute Module ................................................................................................... 26
6. EXAMPLES OF SECURITY VIOLATION ATTEMPTS ....................................................... 31
6.1 Execution of system calls by Java using exec method ............................................... 31
6.2 Execution of System calls by Java using JNI ............................................................. 32
6.3 Java socket connection................................................................................................ 34
ix
6.4 C/C++ socket connection ............................................................................................ 36
6.5 Forking child process in C/C++ .................................................................................. 39
6.6 Assumptions and Limitations ..................................................................................... 40
7. DEPLOYMENT AND TESTING OF THE SANDBOX IN PC2 .............................................. 43
7.1 Executing team runs with no Sandbox ....................................................................... 43
7.2 Setting Up Sandbox Environment and Executing with Sandbox ............................... 44
7.2.1 Generating a C/C++ Base Policy File for Systrace ........................................... 44
7.2.2 Modifying Judge Policy File ............................................................................. 45
7.2.3 Generating C/C++ and Java policy files............................................................ 50
7.2.4 Modifying PC2 ................................................................................................... 52
7.3 Executing Team Runs With Sandbox ......................................................................... 52
8. CONCLUSION .......................................................................................................................... 54
8.1 Migration to other major Operating Systems.............................................................. 54
8.1.1 Mac OS .............................................................................................................. 55
8.1.2 Solaris ................................................................................................................ 55
8.1.3 Windows............................................................................................................ 55
8.2 Future Development ................................................................................................... 56
References ...................................................................................................................................... 58
x
LIST OF FIGURES
Figure 1 Complete Flow ................................................................................................................ 22
Figure 2 C/C++ Execution Flow.................................................................................................... 28
Figure 3 Java Execution Flow ....................................................................................................... 29
xi
1
Chapter 1
INTRODUCTION
Computer security is one of the major factors that contribute to the successful execution of any
software application. These software applications have to be completely secured; otherwise, they
will be more vulnerable to attacks and can invite hackers. Providing security is based on factors
such as the importance of the application to be secured, how distributed it is, intensity of potential
loses and consequences if the application is hacked, cost for the security and several others.
1.1 Purpose of the Project
This project aims at providing system level security in the form of a Security Sandbox, to an
application called PC2, which is used for conducting programming contests. The participants of
the contest submit their code to the judges through PC2. The Security Sandbox monitors the
execution of submitted programs and checks if there are any unauthorized accesses to system
resources or presence of any malicious content in the code, during execution. At the end, the
Security Sandbox generates a log file, which states if there was any security violation or not. If
the execution was successful and the code had no malicious content then the generated file
contains “No Security Violation” string. Integration of the Security Sandbox into PC2 enhances
the security features during programming contests.
1.2 About PC2
PC2 is an acronym for Programming Contest Control software system. This application was
developed at California State University at Sacramento by the PC2 team. This system software
supports programming contests conducted throughout the world, including the ACM (Association
2
of Computing Machinery) International Collegiate Programming Contest (ICPC) along with its
Regional contests in six continents [1].
PC2 is designed to work in a variety of computing environments. The contest participants have to
submit their code to the judges over a network. The judges preprogram PC2 to accept the
participants code, compile it and execute. The result of the execution will be compared with the
judge’s own output copy and the response will be sent back to the participants. PC2 has an option
of making the entire receive-compile-execute-feedback process automated, which is called
“automated judging”.
This system also displays the current status of a participant which includes number of programs
submitted, penalties encountered for wrong submission, current total points and where the
participant stands in the contest.
The contest administrator can tailor this system depending on specific contest operations like the
number of teams, different set of problems ranging from lowest to the highest in difficulty levels,
languages used in the contest, scoring methods and other important aspects.
The system is designed to compile and run programs written in different languages. Therefore,
the participants write their code in C/C++, Java, Perl etc., and can submit it to the judges.
1.3 Problem Description
In a programming contest, the participants can submit their code to the judges who simply
compile and run the code with required input data file. The result of this process gets saved in an
output file, which is compared with the judge’s output file. If there are any differences then an
appropriate message is sent to the participants.
3
If the participant has a bad intention, then he can write a malicious code that can harm the entire
system and pose a threat to the integrity of the programming contest. For example, the participant
may try to:
1. Establish a socket connection.
2. Delete some important files in the system.
3. Alter the scoring system.
4. Block submissions of other participants.
Therefore, PC2 system is vulnerable to malicious code submitted by the participants. These have
to be taken care for conducting a successful programming contest and to prohibit participants
from taking actions based on their bad intentions of hacking [2].
1.4 Proposed solution
System calls in programming languages like file read/write operations and socket connections,
have to go through kernel of the underlying operating system. If a program wants to execute some
system command, it has to get itself trapped first by invoking a kernel service routine of the
operating system. Once trapped, the kernel of the operating system checks the trap number and
then executes the request. Therefore, monitoring of system calls is important in order to enforce
limitations on the participant submitted program’s access. The program or application must have
limited types of system calls to achieve a secured environment. An application can intelligently
make system calls to change or access certain information from the system. There should be a
monitoring tool to prevent applications from making unwanted and prohibited system calls.
The role of this project comes in the form of monitoring the system calls made by the team
submitted programs by implementing a system that provides a Security Sandbox, which can hold
and run the participants’ code. The judges would have already given information regarding all the
4
system calls which are permitted for that particular contest and for that particular problem. If the
participant’s code violates the protocol and tries to access unauthorized resources then the
Sandbox would stop the code from execution and further report it to the judges.
The Security Sandbox would be deployed only on the Judge or Administrator’s machine. Hence,
the participants can run their code on their own machine with no Sandbox. Even if the
participants succeed to execute any malicious code on their computer and submit it to the judges,
the Sandbox on the Judge’s machine would stop the code from doing any such malicious
activities that violates the protocol.
Since the Security Sandbox will be deployed only on Judge or Administrator’s machine, a
participant can attempt to run any malicious code and might succeed. The test run performed by
the participant may try to change the submission time stamp of his or her code, may submit as a
different participant, or perform any malicious activity that might disobey the rules of the contest.
However, the Security Sandbox will not monitor these malicious activities at the participant’s
side. It only sandboxes the code at the Judge’s side. Hence, if required, a different approach needs
to be taken to monitor the test runs at the participant’s side.
5
Chapter 2
EXISTING COMPUTER SECURITY TOOLS
Security Sandboxing isolates the participant submitted code by enclosing it inside a box, which
has rules and policies. These policies force the code to adhere to the rules defined by the contest
administrator. There are several ideas that can come up to one’s mind in order to implement the
Sandbox. Before that, it is important to understand existing security tools that exhibit familiar
behavior of a Sandbox. Some of the existing tools are discussed in this chapter along with their
importance to this project.
2.1 Ptrace
Ptrace stands for “Process Trace” and is one of the system calls available in UNIX and other
UNIX related operating systems. It provides control over the execution of some other process to
be traced. Most sophisticated tracing tools use ptrace underneath. Ptrace can be configured to get
control for every system call made by the process to be traced. Once it gets control, it can read or
modify the register contents and decide on the further action. Several security tools use ptrace for
systematic execution and debugging of a process to be traced.
There are two ways of tracing a process using ptrace. One, the parent process can fork to spawn a
new child and later the child can do a PTRACE_TRACEME followed by exec [3][4]. The other
way is the parent process can trace an existing process using PTRACE_ATTACH. The child
process being traced stops at every signal even if the signal is set to be ignored. There is an
exception for this due to SIGKILL. The parent process gets control at its next “wait” and can read
or modify the register contents. Further, it can continue the execution of the child process by
optionally ignoring the delivered signal or can terminate the child using PTRACE_KILL, if
6
required. Once tracing is completed, the parent process can release the control over the child
using PTRACE_DETACH.
2.2 Systrace
Systrace is one of the computer security tools for controlling the execution of a child process. It
enforces certain policy for the process under trace. For every system call made by the process,
systrace checks if it is permitted in the policy or not. If denied, the execution of the system call
will be rejected, further any remaining unexecuted system calls will also be automatically
rejected, and behavior of the code becomes unpredictable due to these rejects.
A user can configure systrace to generate a policy for a particular binary. Once generated, the
user can edit it to allow and deny certain system calls based on the requirement. Later, systrace
can use the modified policy to run the binaries and can check for any violation. The system calls
not covered in this policy are denied.
In a distributed environment, an arbitrary process can be monitored remotely from central
location using systrace. If an intrusion occurs into any remote machine, systrace catches it and
prevents the intrusion from making further damage to the system. Systrace also provides support
for interactive policy generation, where every system call and their parameters that are not
covered in the current policy will be displayed in a GUI. The user can edit them, which in turn
updates the current policy to either allow or deny the new system call [5][6].
2.3 Strace
Strace is a powerful debugging utility tool available for linux and other unix related operating
systems. It intercepts and records all the system calls made by a particular process along with the
7
signals the system calls receive. Strace logs all the necessary information regarding the system
call, the parameters and return values, on to the standard error by default or into a specified file.
As a debugging tool, strace can be used to analyze any process that frequently crashes. Strace will
print every system call made by the process, which can be used for debugging. For example, a
process may try to access a file that is not present. This error checking might not have been taken
care in the program. Therefore, the compiled binary will crash every time when it tries to open
the file. Such scenarios can be debugged using strace, which prints the information about the
file’s read system call along with the arguments used [7] [4].
2.4 Ktrace
Ktrace, which means kernel trace, is a utility available with Mac OS X and some Unix related
operating systems. It is used to document the interaction of the kernel with a particular process.
Therefore, it can log the system calls, signal processing and I/O of a particular process.
The working of ktrace is similar to strace of Linux but much faster because strace has to deal with
context switching every time it traces a system call. While in ktrace, there are no additional
context switches as the kernel itself logs the required information [4].
2.5 Conclusion
This project requires a security tool that can monitor every system call and log them in a file that
can be viewed and edited by a human. Once required information regarding permitted and denied
system calls is entered, the security tool should work independent of the human aid. The entire
application must be automated with no human interaction.
8
Strace, Ktrace and other security tools are very helpful while debugging a process. However, they
will not be able to control the execution of the process based on a list of allowable and denied
system calls.
Ptrace can get control every time the child process makes a system call. However, requires a lot
of coding to check and compare every system call. It also requires repeated ptrace calls to
communicate between parent and child process. It only provides basic controlling features and
requires some OS specific knowledge to work on it.
Systrace suits the current requirement of this project. It accomplishes the task of monitoring
system calls using a policy mechanism. First, the policy will be generated by systrace itself. Once
generated, the user can read the policy, edit it to permit and deny certain system calls as per
requirement, and hand it over back to systrace. Now systrace will only allow those system calls
that are permitted in policy and the rest will be denied. If any system call is denied, it will log the
details in a file, which can be referred by the user. So, I will be using the systrace tool to
implement a Security Sandbox PC2 in this project [5][6].
9
Chapter 3
WORKING WITH SECURITY TOOLS
Before implementing a Security Sandbox using systrace to monitor C/C++ programs, it is
necessary to get a good hands-on experience with systrace. Systrace uses underlying ptrace for
tracing system calls. Therefore, a better understanding of how ptrace works is equally important.
This will give a good knowledge about how ptrace and systrace monitor system calls, their
required environment, input parameters, result of their implementation, ways to utilize the
features of these tools, and several others so that they can be successfully integrated into this
project.
3.1 Ptrace
Implementing ptrace involves a parent process and a child process. Child process needs to request
its parent to trace it by using PTRACE_TRACEME. Below is a simple program to describe the
working of basic ptrace commands. In this example, the parent spawns a child process. The child
process can be any program, which has a PTRACE_TRACEME instruction in the beginning.
ptrace.cpp
#include
#include
#include
#include
#include
#include
<sys/ptrace.h>
<sys/types.h>
<sys/wait.h>
<stdio.h>
<unistd.h>
<sys/reg.h>
struct user_regs_struct{
unsigned long
ebx;
unsigned long
ecx;
unsigned long
edx;
unsigned long
esi;
unsigned long
edi;
10
unsigned
unsigned
unsigned
unsigned
unsigned
unsigned
unsigned
unsigned
unsigned
unsigned
unsigned
unsigned
}uregs;
long
long
long
long
long
long
long
long
long
long
long
long
ebp;
eax;
ds;
es;
fs;
gs;
orig_eax;
eip;
cs;
flags;
esp;
ss;
int main() {
pid_t child;
long orig_eax;
child = fork();
if(child == 0) {
ptrace(PTRACE_TRACEME, 0, NULL, NULL);
execl("/bin/ls", "ls", NULL);
}
else {
wait(NULL);
orig_eax = ptrace(PTRACE_PEEKUSER, child, 4*ORIG_EAX, NULL);
printf("The child made a system call %ld\n", orig_eax);
ptrace(PTRACE_GETREGS, child, 0, &uregs);
printf("Register contents: \n");
printf("EAX = %ld\n", uregs.eax);
printf("EBX = %ld\n", uregs.ebx);
printf("ECX = %ld\n", uregs.ecx);
printf("EDX = %ld\n", uregs.edx);
printf("ESI = %ld\n", uregs.esi);
printf("EDI = %ld\n", uregs.edi);
printf("EBP = %ld\n", uregs.ebp);
printf("DS = %ld\n", uregs.ds);
printf("ES = %ld\n", uregs.es);
printf("FS = %ld\n", uregs.fs);
printf("GS = %ld\n", uregs.gs);
printf("ORIG_EAX = %ld\n", uregs.orig_eax);
printf("EIP = %ld\n", uregs.eip);
printf("CS = %ld\n", uregs.cs);
printf("FLAGS = %ld\n", uregs.flags);
11
printf("ESP = %ld\n", uregs.esp);
printf("SS = %ld\n", uregs.ss);
ptrace(PTRACE_CONT, child, NULL, NULL);
}
return 0;
}
Output:
The child made a system call 11
Register contents:
EAX = 0
EBX = 0
ECX = 0
EDX = 0
ESI = 0
EDI = 0
EBP = 0
DS = 123
ES = 123
FS = 0
GS = 0
ORIG_EAX = 11
EIP = 12613712
CS = 115
FLAGS = 2097682
ESP = -1080493648
SS = 123
Debug src
In this program, the structure “user_regs_struct” is defined to accumulate the register information
and other required details from the system call. The ordering of the registers in the structure
“uregs” is based on i386 architecture.
The parent process forks the child, which executes a “execl” system call. Before calling this
system call, the child requests the parent to trace it by using PTRACE_TRACEME. This informs
the kernel that its parent process is tracing the child process. Therefore, whenever the child
executes a system call, the kernel hands over the control to parent process. The parent waits for a
signal from kernel by issuing a wait() command. Once the parent gets control, it can check the
12
system call information and can read the register contents. Further, the parent process can even
edit the register contents.
The first line in the output of the above program indicates the system call number 11, which is
same as the system call number of “execv”. The rest of the output shows the content of the child’s
registers for that particular system call. Since the child tried to execute “ls” command, the last
line in the output displays the content of the child’s current directory [8].
3.2 Systrace
Working with systrace can be categorized into two parts. In the first part, an executable binary is
handed over to systrace to run and generate a policy file [5][6][9]. To demonstrate this, consider a
simple C++ program as below [10].
testsystrace.cpp
#include <stdio.h>
#include <stdlib.h>
#include <sys/reg.h>
#include <unistd.h>
#include<sys/socket.h>
int main() {
int listenFd;
getppid();
listenFd = socket(AF_INET, SOCK_STREAM, 0);
getpid();
return 0;
}
The above program contains mainly three system calls: getppid, socket and getpid. Once
compiled the binary file is given to systrace as one of its input parameters.
13
systrace –A home/site1/workspace/testsystrace/Debug/testsystrace
The input parameter “-A” indicates to systrace to generate the policy for the binary file named
“testsystrace”. Now, systrace executes the binary and generates the policy file as shown below.
linux-getppid: permit
linux-socket: sockdom eq "AF_INET" and socktype eq "SOCK_STREAM" then
permit
linux-getpid: permit
The generated policy will be present in the .systrace directory. The naming convention for the
generated policy file is equal to the path name of the binary file with “/” replaced by “_”. In this
example,
the
resulting
policy
file
name
looks
like
“home_site1_workspace_testsystrace_Debug_testsystrace”.
In the next run, the generated policy can be given as input to systrace as shown below.
systrace –a home/site1/workspace/testsystrace/Debug/testsystrace
The input parameter “-a” indicates systrace to consider the policy which is already present. If the
location is not specified in the command (as shown in the above example), then by default
systrace searches in .systrace directory.
When executed, systrace will not generate any logs as no system call is being denied by the
permissions in the specified policy file. The user can edit the policy file and change the
permissions as per the requirements. In this example, the user can deny the execution of “getpid”
by removing “getpid” permission from the policy file. The new policy file is as shown below.
14
linux-getppid: permit
linux-socket: sockdom eq "AF_INET" and socktype eq "SOCK_STREAM" then
permit
Now, systrace is executed with the new updated policy file. The new systrace command is as
shown below.
systrace –a home/site1/workspace/testsystrace/Debug/testsystrace –D
home/site1/workspace/testsystrace/Debug –E
home/site1/workspace/testsystrace/Debug/systrace.txt
\
\
The “-D” option mentions the place where the systrace has to look for the policy file. The “-E”
informs systrace regarding where to create the log file generated if there are any denied system
calls.
Execution of above systrace command results in a log file by name “systrace.txt” in
“home/site1/workspace/testsystrace/Debug” folder with contents as shown below:
systrace: deny user: root, prog:
home/site1/workspace/testsystrace/Debug/testsystrace, pid:
10657(0)[0], policy:
home/site1/workspace/testsystrace/Debug/testsystrace, filters: 364,
syscall: linux-getpid(20), args: 68
\
\
\
\
Using the log file, the user can check the reason for denying the execution of the binary file and
can take appropriate action. The above commands will be used in this project to monitor system
calls by sandboxing the execution of C/C++ binary files using systrace. The Java Security tools
that will be used in the Sandbox to monitor Java programs are explained in the later chapters.
15
Chapter 4
SECURITY APPROACH FOR PROGRAMMING LANGUAGES
4.1 With C/C++
Linking required directories and libraries, and compiling C/C++ file results in a binary
executable, which can be used in systrace. Therefore, it is necessary to have a C/C++ binary
executable file that invokes every known system call. Systrace takes this binary file and generates
a C/C++ base policy file that consists of a list of permitted system calls used in that C/C+
program. Since the C/C++ program contained call to every system call, the systrace generated
base policy file would cover access to most libraries and permissions to execute every system
call. However, the judge would come up with a policy file that specifies a list of permitted system
calls for that contest or for a particular problem. Only these system calls are need to be present in
the systrace policy file. Hence, the generated systrace base policy file needs to be edited to
include only judge’s permitted system calls.
The contest administrator can edit the base policy as per the requirements of the contest and the
current programming problem. By referring to the judge’s given policy file, the administrator can
retain only the required system call permissions and remove the rest. The updated policy file now
contains a list of permitted system calls, which can be directly used on the participant submitted
C/C++ program. Systrace only permits the system calls that are present in the input policy. If the
submitted program tries anything illegal then systrace will deny the execution of that particular
system call and will terminate the execution of the program. The denied system calls will be
logged and a judge or an administrator can look into them to take necessary actions.
By using a base C/C++ policy file common to all the contest’s C/C++ problems, the path to
achieve the security sandboxing of the C/C++ programs can be made easier.
16
4.2 With Java
Systrace can be used to achieve security sandboxing for only binary executables. In the case of
Java, the program is compiled to a .class file, which can be executed only through use of a Java
Virtual Machine (JVM). This means that systrace cannot be directly used on Java programs.
There are different ways to sandbox a Java program. By creating a C/C++ program that invokes a
Java program through Java Native Interface (JNI), Java programs can be monitored using
systrace. One more approach would be using Java security manager class. These two approaches
are explained in the following sections.
4.2.1 Using C/C++ with JNI
To implement security sandboxing for Java, one of the approaches to tackle the problem between
binary executables and JVM is by calling a Java program from a C++ program. This C++
program would create a JVM and call the main method inside the Java class. Now the binary
executable of the C++ program can be used in systrace to achieve the Security Sandbox
environment.
The C/C++ program that creates a JVM and invokes a Java program is as shown below [11].
C2java.cpp:
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/socket.h>
#include <sys/ptrace.h>
#include <sys/wait.h>
#include <unistd.h>
#include <sys/reg.h>
#include <iostream>
#include "jni.h"
#include "jni_md.h"
17
#include <jvmti.h>
#include <iostream>
using namespace std;
int main() {
JNIEnv *env;
JavaVM *jvm;
JavaVMInitArgs vm_args;
jint res;
jclass cls;
JavaVMOption options;
options.optionString = "Djava.class.path=/home/site1/workspace/myjava";
vm_args.version = JNI_VERSION_1_6; //JDK version. This indicates
version 1.6
vm_args.nOptions = 1;
vm_args.options = &options;
vm_args.ignoreUnrecognized = 0;
JNI_GetDefaultJavaVMInitArgs(&vm_args);
/* Create JVM */
res = JNI_CreateJavaVM(&jvm, (void **)&env, &vm_args);
/* Get Class ID */
cls = env->FindClass("myjava");
if (cls == 0) printf("Sorry, Not able to find the class\n");
/* Get Static Main method ID */
jmethodID get_main_id =
env>GetStaticMethodID(cls,"main","([Ljava/lang/String;)V");
if (get_main_id == NULL)
printf("Sorry, Not able to find the main\n");
env->CallStaticVoidMethod(cls, get_main_id);
/* Destroy JVM */
jvm->DestroyJavaVM();
return 0;
}
18
Before creating a JVM, the required information including JDK version and Java class name to be
called must be entered. The JVM is created by executing the command JNI_CreateJavaVM.
“FindClass” is used to get the class ID. Using Class ID, “GetStaticMethodID” is used to obtain
the main method’s ID, by sending the signature information including the arguments and return
value. Once the method ID is received, “CallStaticVoidMethod” is used to invoke the Java
program’s main method.
Now, the compiled binary of this C++ program can be used in systrace. If the Java program
makes any system call, systrace can catch that and verify it against the policy file. However, the
above approach has some disadvantages. The systrace policy file generates a huge number of file
reads into JVM libraries. This becomes difficult to differentiate between file reads by JVM and
the ones made by the actual Java program. Therefore, this method is not suitable for
implementing in a programming contest.
4.2.2 Using Java Security Manager
Java has a built-in security manager which can restrict access control such as reading from or
writing into files, accessing system properties, socket programming, networking, AWT,
serializable, reflective operations, runtime commands, SQL and SSL methods, and etc., [12][13].
The SecurityManager class is used to implement the security restrictions. An instance of this class
can be accessed through System.getSecurityManager() method. If no security manager were
registered, then instance would return a null. Moreover, a policy file can be created which
contains all the necessary security permissions. The security manager can use this policy to
restrict permissions on a particular Java program. The Security manager by default denies
permissions to all those operations that are not mentioned in the given input Java policy file.
Hence, an empty block as shown below will simply deny everything.
19
grant{
};
Before utilizing this feature, the program needs to the inform JVM about its intentions of using
Security Manager. This can be achieved by a command line argument, which also mentions the
policy file “test.policy” to be used. The compiled .class file is kept inside a jar file and executed
as shown below.
java -Djava.security.manager -Djava.security.policy=test.policy –jar
asimplejava
A simple file operation using Java with security manger enabled is explained below. The program
tries to write into a file called “filename.txt”. The scenario is explained with and without a grant
permission set in the policy file.
asimplejava.java:
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
public class asimplejava {
public static void main(String[] args) throws IOException {
FileWriter outFile = new FileWriter("filename.txt");
PrintWriter out = new PrintWriter(outFile);
out.println("Testing Java Security Manager");
out.close();
System.out.println(“File written successfully”);
}
}
Output:
File written successfully
20
The above program successfully executes since there is no security manager enabled. Now,
enable the security manager and use the “test.policy” policy file as shown below. Since there are
no permissions mentioned in the grant block, by default it will deny all the permissions.
grant{
};
Now, when the program is executed using the policy file, the output can be observed as follows.
Exception in thread "main" java.security.AccessControlException:
access denied (java.io.FilePermission filename.txt write)
at
java.security.AccessControlContext.checkPermission(AccessControlContex
t.java:323)
at
java.security.AccessController.checkPermission(AccessController.java:5
46)
at
java.lang.SecurityManager.checkPermission(SecurityManager.java:532)
at
java.lang.SecurityManager.checkWrite(SecurityManager.java:962)
at java.io.FileOutputStream.<init>(FileOutputStream.java:169)
at java.io.FileOutputStream.<init>(FileOutputStream.java:70)
at java.io.FileWriter.<init>(FileWriter.java:46)
at asimplejava.main(asimplejava.java:10)
The security manager throws an access denied exception for the file write to “filename.txt”. This
is because, once the policy is specified, the security manager checks the policy file to see which
permissions are allowed. In the above scenario, there is no permission for writing into
“filename.txt”. Hence, it throws an AccessControlException with denied file write permission for
“filename.txt”. The permission can be granted as follows.
21
grant{
permission java.io.FilePermission "filename.txt", "write";
};
The permission to write into “filename.txt” is granted to the Java program. The outcome of the
execution is as follows.
File written successfully
Choosing the appropriate permissions for running a Java program is necessary for controlled
sandboxing. Therefore, for this project, security sandboxing will be different for C/C++ and Java
programs. Systrace will be used for sandboxing C/C++ programs and Java security manager for
Java programs.
22
Chapter 5
SOFTWARE DESIGN AND APPROACH
5.1 Design Flow
The design of the project centers around two primary modules: Generate and Execute. The
Generate module takes problem number, judge’s policy file and base policy file to generate
C/C++ and Java policy files. These files would be used in the Execute module for running C/C++
and Java programs.
Invoke
Judge or Administrator
PC^2
Problem Specific
Judge Policy
Problem
#
C/C++ Base
Policy
Generate
Problem
Specific
Executable File
Problem
Specific
Output Log
File Name
Indicator
for C/C++
and Java
Invoke
Execute
No
Yes
Security
Violation
Print:
Security
Violation:
Reason
Print: No
Security
Violation
Read Output Log File
Problem
Specific C/C++
or Java Policy
File
Problem
Specific
Output Log
File
Figure 1 Complete Flow
23
This section explains the flow of the project with detailed information about every block and
module, input and output files, which are used during the execution of Generate and Execute
module.
5.1.1 Judge or Administrator
This represents a judge or an administrator who takes care of setting up the Sandbox
environment. They supply problem number, contest or problem specific judge policy file and a
C/C++ base policy file to the Generate module. Now, a judge or an administrator invokes the
Generate module to generate a C/C++ and Java policy files specific to the contest or to the
problem.
5.1.2 Problem #
The specific problem number of the programming contest. Generally, it would be A, B, C …
5.1.3 Problem Specific Judge Policy
Judge or Administrator’s policy file that contains information regarding allowable system calls.
This policy can be used as a common policy for every problem or for a particular one.
5.1.4 Base Policy
Policy file generated by running C/C++ code that contained every possible system calls. This
policy will be used to catch libraries that will be accessed while running a C/C++ binary.
5.1.5 The Generate Module
This module generates C/C++ and Java policy files for every contest problem.
24
5.1.6 Problem Specific Executable File
The compiled binary file of participant’s C/C++ code or a .class file of participant’s Java code.
5.1.7 Problem Specific C/C++ Policy File
The policy file relative to a particular contest’s problem. This will be generated as the output of
the Generate module and later used by the Execute module for running the participant’s code.
5.1.8 Problem Specific Output Log File Name
This represents the file name to be used for creating an output log file. This log file will be
created by the Execute module as a result of its execution. PC2 will refer to this problem specific
output log file by its name, to check for any security violation.
5.1.9 Indicator for C/C++ and Java
A string input for the Execute module for indicating whether the incoming executable is a C/C++
binary or a .class file.
5.1.10 The Execute Module
Executes the binary file or .class file using a policy file and generates the output log file.
5.1.11 Security Violation
Checks if there was any violation and logs the message into output log file accordingly.
25
5.1.12 Print: No Security Violation
Stores “No Security Violation” data inside the output log file.
5.1.13 Print: Security Violation with reason
Stores the information regarding security violation in output log file, which occurred during the
execution of the participant’s code.
5.1.14 Output Log file
This file is generated after the execution of participant’s code. This file contains the information
about any security violation that might have occurred during the execution. Else, it contains a
“No Security Violation” tag.
5.1.15 PC2
The main PC2 tool that invokes the Execute module by providing the necessary input files and
information. This also reads the output log file generated by the Execute module for any security
violation and takes corresponding action.
5.2 The Generate Module
The Generate module will be executed only once at the beginning of the contest, to generate the
policies. This module goes through the judge’s policy files corresponding to the contest or a
particular problem and translates it to C/C++ and Java policy files. The generated policy files are
problem specific. There will be a C/C++ policy and a Java policy for every problem in the
contest.
26
For C/C++, the Generate module also refers to the base policy file that contains every system call
information and required library paths, in a systrace friendly format. Information on all available
libraries is taken from the base policy and written into C/C++ policy file. Later, the Generate
module uses judge’s policy file, maps it to systrace format and writes into C/C++ policy file.
For Java, the Generate module maps the judge’s policy file into a Java policy file. Here, extra
care has to be taken to translate into Java friendly policy format. A good understanding of Java
policies and Security Manager is required for successful implementation. Java has limited
features to perform system calls. So, not all Judges’ policies can be mapped. Certain system calls
require some work around to be done before they can be mapped into Java. For example, to
execute “ls” command in Linux, C/C++ can accomplish by simply forking a child process and
running “execve”. By providing permissions for “fork” in the judge’s policy file, the C/C++ can
easily execute “ls” command. However, Java needs to go through “Runtime” class and “exec”
method and has a different approach for executing the “ls” command. It needs to invoke “/bin/ls”
file to run “ls” command. Hence, permission to execute the file “/bin/ls” needs to be provided.
Since, there is only one Judge Policy file used to generate both C/C++ and Java policy, the
Generate module needs to do the above-mentioned workaround to provide permissions in both
C/C++ and Java. The final output of this module consists of a C/C++ and a Java policy file.
5.3 The Execute Module
PC2 uses the generated policies as input to run the Execute module. In the case of C/C++, PC2
supplies either a binary executable or a Java .class file to the Execute module, an indicator to
differentiate between C/C++ and Java, the policy file to be used, and the output log file name.
After providing the necessary inputs, PC2 invokes the Execute module.
27
To simplify the execution flow, a simple shell script called “run_execute.sh” is used which is
wrapped around the Execute module. This shell script accepts the exact input parameters required
by the Execute module and passes them to it.
The “run_execute.sh” script also serves the purpose of finding whether the participant’s code
should run using the Sandbox or not. The Security Sandbox will only be present on Judge’s
machines and not on participant’s machines. Since the participant’s test run would happen on his
or her own machines that does not require the Sandbox, the “run_execute.sh” script would simply
run their program without checking for any security violations. However, the “run_execute.sh”
script uses the Security Sandbox to run participant’s code on a Judge’s machine.
The “run_execute.sh” script decides whether to run the Sandbox by checking if the Execute
module is present in the executable path or not. If it is present then the “run_execute.sh” script
uses the Sandbox. Otherwise, it runs the participant’s code directly with no security checks.
Hence, to accomplish the above purpose, the Security Sandbox including the Execute module,
would be deployed only on the Judge or Administrator’s machine and not on the participant’s
machine.
28
Problem specific
binary image
Indicator
for C/C++
Problem specific
systrace Policy
File
Problem
specific
OutPut Log
File Name
Invoke
Execute
Problem specific
systrace Policy
File
Problem
specific binary
file
Temporary
Output Log File
Systrace
Yes
No
Security
Violation
Run
C/C++ Binary
Print:
Security
Violation:
Reason
Print: No
Security
Violation
Output Log File
Figure 2 C/C++ Execution Flow
For C/C++ programs (See Figure 2), the Execute module uses the input policy file and executable
binary, and invokes systrace with this information. Systrace runs the binary executable against the
given policy and logs information about violation if any occurred, in a temporary output log file.
The Execute module reads the temporary output log file to check if there was any security
29
violation. If there was no violation, the Execute module simply says “No Security Violation” and
logs it in Judge’s output log file. PC2 refers into the log file and takes appropriate action.
Problem specific
.class file
Problem
specific
OutPut Log
File Name
Problem specific
Java Policy File
Indicator
for Java
Problem
specific .class
file
Problem
specific Java
Policy File
Temperary
Output Log File
Create
Invoke
Execute
Invoke
Java Wrapper
JVM
(With Java Security Manager)
No
Security Violation
(Access Control
Exception)
Print:
Security
Violation:
Reason
Print: No
Security
Violation
Problem specific
Output Log File
Figure 3 Java Execution Flow
Yes
30
In the case of Java (See Figure 3), the Execute module uses input Java policy file and creates a
Java wrapper module. This wrapper creates a JVM to invoke the given .class file. It also informs
JVM to enable Security Manager and use the given input policy file to check for security
violation. If there was any security violation, security manager terminates the execution of the
.class file and throws an access denied exception. Java wrapper catches the exception and logs an
appropriate message into the output log file that will be later referred by the Judges. If there was
no access denied exception, “No Security Violation” message will be logged.
31
Chapter 6
EXAMPLES OF SECURITY VIOLATION ATTEMPTS
There are several ways a hacker can attempt to breach through the security of PC2. They can try
to execute system calls that can bring down the entire PC2 system, or try to establish a socket
connection to send across some important files related to the PC2 or to the programming contest.
Most of the system calls attempted through a C/C++ code can be easily caught by systrace. When
it comes to Java, it lacks many features regarding system calls that a C/C++ program enjoys.
Hence, it is not easy to perform system calls in Java. However, a Java program can execute
system calls using the “exec” method and JNI, and care has to be taken when such attempts are
made.
This section explains some of the anticipated attempts that a hacker can try to execute. It also
demonstrates the results of such attempts when the Security Sandboxing is used.
6.1 Execution of system calls by Java using exec method
The Java “exec” method can call any executable file present on the system. The following
example illustrates a Java class that attempts to execute the “ls” command through the “exec”
method with the Security Manager enabled and along with a Java policy file. The Java Security
Manager catches the access denied exception for trying to execute the “ls” command.
javaexec with policy file enabled:
public class javaexec {
public static void main(String[] args) {
try{
String str = null;
Runtime runtime = Runtime.getRuntime();
Process process = runtime.exec("/bin/ls");
InputStream is = process.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
32
BufferedReader br = new BufferedReader(isr);
while((str = br.readLine()) != null){
System.out.println(str);
}
}
catch(Exception e){
e.printStackTrace();
}
}
}
Output:
java.security.AccessControlException: access denied
(java.io.FilePermission /bin/ls execute)
at
java.security.AccessControlContext.checkPermission(AccessControlContex
t.java:323)
at
java.security.AccessController.checkPermission(AccessController.java:5
46)
at
java.lang.SecurityManager.checkPermission(SecurityManager.java:532)
at java.lang.SecurityManager.checkExec(SecurityManager.java:779)
at java.lang.ProcessBuilder.start(ProcessBuilder.java:448)
at java.lang.Runtime.exec(Runtime.java:593)
at java.lang.Runtime.exec(Runtime.java:431)
at java.lang.Runtime.exec(Runtime.java:328)
at javaexec.main(javaexec.java:11)
6.2 Execution of System calls by Java using JNI
A participant can submit Java code along with a C/C++ binary file. The submitted Java code can
try calling the binary file through JNI. However, such JNI calls also get caught by the security
manager. An access denied exception is thrown for attempting to load a JNI library during run
time. The following example shows how Java code can try to call a binary file and gets caught by
the security manager [14].
33
Java Code with policy file enabled:
public class HelloWorld{
private native void print();
public static void main(String[] args)
{
new HelloWorld().print();
}
static{
System.loadLibrary("HelloWorld");
}
}
C Code:
#include "jni.h"
#include <stdio.h>
#include "HelloWorld.h"
JNIEXPORT void JNICALL
Java_HelloWorld_print(JNIEnv *env, jobject obj)
{
printf("Hello World!\n");
printf("PID: %d\n",getpid());
return;
}
Output:
java -Djava.security.manager -Djava.security.policy=java.policy -jar
HelloWorld.jar
Exception in thread "main" java.lang.ExceptionInInitializerError
Caused by: java.security.AccessControlException: access denied
(java.lang.RuntimePermission loadLibrary.HelloWorld)
at
java.security.AccessControlContext.checkPermission(AccessControlContex
t.java:323)
at
java.security.AccessController.checkPermission(AccessController.java:5
46)
at java.lang.SecurityManager.checkPermission(SecurityManager.java:532)
at java.lang.SecurityManager.checkLink(SecurityManager.java:818)
at java.lang.Runtime.loadLibrary0(Runtime.java:817)
at java.lang.System.loadLibrary(System.java:1028)
at HelloWorld.<clinit>(HelloWorld.java:8)
Could not find the main class: HelloWorld. Program will exit.
34
6.3 Java socket connection
One of the important aspects that need to be considered during security is socket connection. The
Java code can try to establish a client socket connection that may simply transfer files to a host or
target computer. Security manager can curb such attempts and throw access denied exception for
socket permissions. The following code illustrates a simple client-server Java application
[15][16]. When client code is executed, the security manager throws an exception for using
“connect and resolve”. In addition, for the server code, it throws an exception for using “accept
and resolve”.
VerySimpleServer.java:
import
import
import
import
import
java.net.Socket;
java.net.ServerSocket;
java.io.InputStream;
java.io.OutputStream;
java.io.IOException;
public class VerySimpleServer {
private static int serverPort = 8085;
private static ServerSocket serverSock = null;
static Socket sock = null;
static InputStream sockInput = null;
static OutputStream sockOutput = null;
static byte[] buf=new byte[1024];
static int bytes_read = 0;
public static void main(String argv[]) {
try {
serverSock = new ServerSocket(serverPort);
sock = serverSock.accept();
sockInput = sock.getInputStream();
sockOutput = sock.getOutputStream();
bytes_read = sockInput.read(buf, 0, buf.length);
System.out.println("Received: "+buf);
sockOutput.flush();
sock.close();
}
catch (IOException e){
35
e.printStackTrace(System.err);
}
}
}
VerySimpleClient.java:
import
import
import
import
import
java.net.Socket;
java.net.ServerSocket;
java.io.InputStream;
java.io.OutputStream;
java.io.IOException;
public class VerySimpleClient {
private static byte[] data = "Hello World".getBytes();
private static Socket sock = null;
private static InputStream sockInput = null;
private static OutputStream sockOutput = null;
static byte[] buf = null;
static int bytes_read = 0;
public static void main(String argv[]) {
try {
printf(“Opening connection to localhost port 8085\n”);
sock = new Socket("localhost", 8085);
sockInput = sock.getInputStream();
sockOutput = sock.getOutputStream();
System.out.println("Sending: "+data);
sockOutput.write(data, 0, data.length);
sock.close();
}
catch (IOException e){
e.printStackTrace(System.err);
}
}
}
Policy Applied on Client code:
Opening connection to localhost port 8085
Exception in thread "main" java.security.AccessControlException:
access denied (java.net.SocketPermission 127.0.0.1:8085
connect,resolve)
at
java.security.AccessControlContext.checkPermission(AccessControlContex
36
t.java:323)
at
java.security.AccessController.checkPermission(AccessController.java:5
46)
at
java.lang.SecurityManager.checkPermission(SecurityManager.java:532)
at
java.lang.SecurityManager.checkConnect(SecurityManager.java:1034)
at java.net.Socket.connect(Socket.java:524)
at java.net.Socket.connect(Socket.java:478)
at java.net.Socket.<init>(Socket.java:375)
at java.net.Socket.<init>(Socket.java:189)
at VerySimpleClient.sendSomeMessages(VerySimpleClient.java:24)
at VerySimpleClient.main(VerySimpleClient.java:73)
Policy Applied on Server Code:
Exception in thread "main" java.security.AccessControlException:
access denied (java.net.SocketPermission 127.0.0.1:46200
accept,resolve)
at
java.security.AccessControlContext.checkPermission(AccessControlContex
t.java:323)
at
java.security.AccessController.checkPermission(AccessController.java:5
46)
at
java.lang.SecurityManager.checkPermission(SecurityManager.java:532)
at
java.lang.SecurityManager.checkAccept(SecurityManager.java:1157)
at java.net.ServerSocket.implAccept(ServerSocket.java:457)
at java.net.ServerSocket.accept(ServerSocket.java:421)
at VerySimpleServer.waitForConnections(VerySimpleServer.java:72)
at VerySimpleServer.main(VerySimpleServer.java:107)
6.4 C/C++ socket connection
When a program attempts to establish client-server connection, the systrace policy file can easily
prohibit such actions. The following examples contain a simple client code, a simple server code
and the results of executing each code using systrace policy [17].
37
During execution of client and server code, systrace restricts the use of socket related system
calls, as the permissions to execute them are not present in the C/C++ policy file. To enable this,
the administrator or the judge has to permit the use of such system calls in the policy file.
asimpleclient.cpp:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
<iostream>
<stdio.h>
<stdlib.h>
<unistd.h>
<sys/types.h>
<sys/socket.h>
<netinet/in.h>
<error.h>
<string.h>
<netdb.h>
#define PORT 0x8093
#define DIRSIZE 8192
#define HOST 127.0.0.1
using namespace std;
int main(int argc, char *argv[]) {
char dir[8192];
int sd, sd_current, cc, fromlen, tolen;
int addrlen;
struct sockaddr_in sin;
struct sockaddr_in pin;
struct hostent *hp;
char hostname[100];
strcpy(hostname, "127.0.0.1");
hp = gethostbyname(hostname);
memset(&pin, 0, sizeof(pin));
pin.sin_family = AF_INET;
pin.sin_addr.s_addr = ((struct in_addr *)(hp->h_addr))->s_addr;
pin.sin_port = htons(PORT);
sd = socket(AF_INET, SOCK_STREAM, 0);
connect(sd, (struct sockaddr *) &pin, sizeof(pin));
38
send(sd, "Sandbox",strlen("Sandbox"), 0);
printf("Sending: %s\n","Sandbox");
return 0;
}
asimpleserver.cpp:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
<iostream>
<stdio.h>
<stdlib.h>
<unistd.h>
<sys/types.h>
<sys/socket.h>
<netinet/in.h>
<error.h>
<string.h>
<netdb.h>
#define PORT 0x8093
#define DIRSIZE 8192
using namespace std;
int main(int argc, char *argv[]) {
char dir[8192];
int sd, sd_current, cc, fromlen, tolen;
int addrlen;
struct sockaddr_in sin;
struct sockaddr_in pin;
sd = socket(AF_INET, SOCK_STREAM, 0);
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = INADDR_ANY;
sin.sin_port = htons(PORT);
bind(sd, (struct sockaddr *) &sin, sizeof(sin));
listen(sd, 5);
addrlen = sizeof(pin);
sd_current = accept(sd, (struct sockaddr *) &pin,
(socklen_t*)&addrlen);
recv(sd_current, dir, sizeof(dir), 0);
printf("Receiving: %s\n",dir);
39
close(sd_current); close(sd); return 0;
}
Policy Applied on Server Code:
syscall: linux-socket(102), sockdom: AF_INET, socktype: SOCK_STREAM
Policy Applied on Client Code:
syscall: linux-socket(102), sockdom: AF_INET, socktype: SOCK_STREAM
6.5 Forking child process in C/C++
Another example of a system call which might be attempted in a programming contest is “fork”.
However, if the permissions to “clone” or “fork” is process is not allowed in the C/C++ policy
file, systrace will reject the creation of a child process. The following example demonstrates a
program trying to fork a child process. Assuming that input C/C++ policy file does not permit
“clone” or “fork” system calls, systrace denies the creation of a child process.
fork.cpp:
#include
#include
#include
#include
#include
#include
<iostream>
<stdio.h>
<stdlib.h>
<string.h>
<unistd.h>
<sys/wait.h>
using namespace std;
int main() {
40
pid_t pid_child;
int status;
printf("Before Cloning\n");
pid_child = fork();
if(pid_child == 0){
printf("Inside Child process\n");
exit(0);
}
else{
wait(&status);
}
printf("After Cloning\n");
return 0;
}
Since there was no permission specified to allow “clone” system call, systrace rejects the
execution and the resulting output is shown below.
Policy Applied on fork.cpp Code:
Security Violation: syscall: linux-clone(120), args: 68
6.6 Assumptions and Limitations
The Security Sandbox entirely depends on systrace for controlling the execution of C/C++ binary
and Java Security Manager for execution of Java code. Both systrace and security manager have
some limitations and they are also applicable for the Sandbox. Most anticipated malicious
attempts have been tested and the Sandbox has shown good results by restricting them. However,
new unknown attempts can be made to breach through the system. The Sandbox needs to be
periodically updated to restrict such attempts.
41
For executing a Java code, the required .class files will be kept inside jar file, along with a
manifest file. Java security manager is applicable on jar file and not Java. However, when tried
directly on Java .class file, certain permissions were ignored and the security manager allowed
access to some files. There is no proper explanation for using a jar file and not directly Java. In
this project, the Execute module creates a jar file and keeps the required .class files in it. Once a
jar file is created, security manager is invoked on jar file.
For C/C++, systrace can use the user-defined policy to execute and monitor on the binary file.
This can be achieved by using “-d” to mention systrace about the location of the policy file.
However, while using systrace, certain naming convention needs to be followed. When using “d” option, the complete path name of the directory which contains policy file must be given. This
path name should not contain the name of the policy file. Systrace searches for the policy file in
the specified directory. Hence, the policy file must also follow certain naming convention. For an
executable file, the policy name is equal to the directory path of the executable binary including
the name of the binary at the end. All “/” should be replaced with “_”. For example, if the binary
file “cbinary” is present in “home/username/workspace/workingdir” directory, then the policy file
name must be named as “home_username_workspace_workingdir_cbinary”. This has to be
followed if systrace is used.
Therefore, in this project, the Generate module simply generates the required policy file. The
user, while invoking the Execute module to run C/C++ binary, needs to mention the problem
letter or number, in order to access that particular policy file. The Execute module will take the
given policy file name, search for it in the sandbox directory and create its own copy in the
current working directory. While creating the copy in the current working directory, the Execute
module makes necessary changes inside the policy file to reflect current working directory and
42
executable binary. The naming convention will be taken care of by the Execute module. It reads
the current working directory name and appends the binary file name at the end. Once the input
policy file is created in a required format, the Execute module takes care of applying it on the
participant’s program.
43
Chapter 7
DEPLOYMENT AND TESTING OF THE SANDBOX IN PC2
The previous chapters discussed the development and testing of the Sandbox outside PC2. Testing
provided good results for most anticipated sorts of malicious code. Considering these test results,
the Sandbox needs to be deployed inside PC2 and has to be tested as one system. This chapter
discusses the best way to deploy Sandbox inside PC2 and the changes required for making team
runs.
7.1 Executing team runs with no Sandbox
For Java, PC2 compiles the code into a .class file and executes it by creating and running a JVM.
The following illustrates a list of commands for running Java program in PC2.
1. Compile Cmd Line:
javac {:mainfile}
2. Executable Filename:
{:basename}.class
3. Program Execution Command Line:
java {:basename}
PC2 substitutes the variables for {:mainfile} and {:basename}. Once compiled, the
{:basename}.class file will be created. Finally, PC2 executes the .class file and either displays the
results on a small window or stores it in a file. The judges or an administrator verify these results
and make decisions accordingly.
For C/C++, PC2 compiles the submitted programs to an executable .exe binary file and later
executes it to get the results. The series of commands used for compiling and running C/C++ files
are as follows.
1. Compile Cmd Line (for C):
Compile Cmd Line (for C++):
gcc –lm –o {:basename}.exe {:mainfile}
g++ –lm –o {:basename}.exe :mainfile}
44
2. Executable Filename:
{:basename}.exe
3. Program Execution Command Line:
./{:basename}.exe
The resulting output is compared and verified against the judge’s own copy and the decisions are
made accordingly.
7.2 Setting Up Sandbox Environment and Executing with Sandbox
Before executing the team runs, the Sandbox folder has to be kept in /usr/local/pc2v9/. Two
executable files need to be present in an executable path so that they can be invoked from any
location. The two executables include “execute” and “run_execute.sh”. “execute” is the binary
executable of the Execute module and “run_execute.sh” is a shell program built over “execute”
binary. Before invoking these executables, it is necessary to setup the Sandbox environment
which includes generating a C/C++ base policy file, editing judge policy files and later generating
problem specific Java and C/C++ policy files.
7.2.1 Generating a C/C++ Base Policy File for Systrace
The
Sandbox
folder
contains
“generate.cpp”
and
“mysystemcalls.cpp”
files.
The
“mysystemcalls.cpp” file contains code to invoke every available system call and the
“generate.cpp” file is the source code for the Generate module. These two files can be compiled
by running the “run_compile.sh” script. Now a C/C++ base policy file needs to be generated.
This base policy file must contain permits to every system call and provide information about
libraries referred for making these system calls. Since, the “mysystemcalls.cpp” program invokes
every system call; by using systrace, this program can be used for generating a base policy file
that contains permission to execute every system call. Therefore, a C/C++ base policy file can be
created by issuing the command shown below.
45
sh run_compile.sh mysystemcalls base.policy
Once a C/C++ base policy file is generated, the judge or contest administrator needs to set rules
on making system calls. It can be done by specifying allowable system calls inside “judge.policy”
file. This policy file will be in a XML format.
7.2.2 Modifying Judge Policy File
Judge policy file is defined in a XML format to ease the editing process for an administrator or a
judge. There is only one judge policy file for both C/C++ and Java. This helps a judge or an
administrator to edit one policy for C/C++ and Java. The judge policy can be problem or contest
dependent. There can be different policy files for different problems in the contest or just one for
the whole contest. The Generate module will take a problem specific judge policy file and a
C/C++ base policy file and generates a C/C++ systrace policy file and a Java policy file. The
generated C/C++ policy will be used later by systrace to monitor a C/C++ binary executable and
the generated Java policy file will be used later by Java security manager for monitoring a Java
program. A typical judge policy file looks as shown below.
<PERMIT>
<FILE>
fsread fileread.txt
fswrite filewrite.txt
</FILE>
<TIME>
</TIME>
<SOCKET>
</SOCKET>
<SYSTEM>
</SYSTEM>
<JAVA-ONLY>
</JAVA-ONLY>
46
</PERMIT>
<!-- The following lists the names of the Linux system calls,
together with the required parameters for each call, which the Judge
can add to the <PERMIT> section shown above:
Reference:
Command + 3 Parameters:
fchown fd uid gid
Command + 2 Parameters:
chmod filename mode
fchmod fd mode
kill pidname signame
link filename1 filename2
mknod filename mode
rename filename1 filename2
socket AF_INET<sockdom> SOCK_STREAM<socktype>
Command + 1 Parameter:
bind inet-[0.0.0.0]:32898
chdir directoryname
chroot directoryname
connect inet-[127.0.0.1]:32898<sockaddr>
execve filename
fsread filename
fswrite filename
mmap2 prot
mprotect PROT_READ
Command + no Parameter:
accept
acct
adjtimex
alarm
bdflush
brk
chroot
clone
close
creat
dup
47
dup2
execve
exit_group
fchdir
fchmod
fchown
fcnt164
fdatasync
flock
fstat64
fstatfs
fsync
ftruncate
getcwd
getdents
getegid
geteuid
getgid
getgroups
getitimer
getpigid
getpgrp
getpid
getppid
getpriority
getresgid
getresuid
getrlimit
getrusage
getsid
gettimeofday
getuid
ioctl
ioperm
iopl
lchown
listen
llseek
lseek
mlock
mlockall
mremap
mount
msync
munlock
munlockall
48
munmap
nanosleep
newuname
oldmount
personality
pipe
poll
prctl
pread
ptrace
pwrite
quotactl
readv
recv
rt_sigaction
rt_sigpending
rt_sigprocmask
rt_sigtimedwait
sched_getparam
sched_getscheduler
sched_get_priority_max
sched_get_priority_min
sched_rr_get_interval
sched_setparam
sched_setscheduler
sched_yield
select
send
sendfile
setdomainname
setgid
setfsuid
setfsgid
setgroups
sethostname
setitimer
setpgid
setpriority
setregid
setresgid
setresuid
setreuid
setrlimit
setsid
set_thread_area
setuid
49
sigaltstack
statfs
stime
sync
sysctl
sysinfo
time
times
truncate
umask
umount
utime
utimes
vhangup
vm86
waitpid
write
writev
-->
The policy file contains two main sections called PERMIT and Reference. Both Java Security
Manager and Systrace are concerned with the system call that needs to be permitted and they both
deny the rest. Therefore, the judge policy file consists of only those system calls that are
permitted for the contest or for a specific problem and not those that are denied. Hence, the
permitted system calls need to be mentioned within the <PERMIT> and </PERMIT> tags.
For editing the Judge Policy file, a proper syntax needs to be followed. Hence, the judge policy
file also contains information for the judges or administrators regarding how to edit. The section
called “Reference” just after the </PERMIT> tag explains how to write the system call
permissions in the judge policy file. For example, if a judge wants to give a file read permission
on “fileread.txt” file, the phrase “fsread fileread.txt” needs to be added in between <FILE> and
</FILE> section. Similarly, the time, socket and system related permissions could be added
within their respective tags. The Reference section is divided further based on the number of
50
parameters required for making a system call. For example, the phrase “chmod filename mode”
represents the “chmod” system call that changes the mode of a given file. To execute this system
call, two parameters namely the “filename” and the “mode” are required. Hence, this belongs to
“Command + 2 parameters” sub-section. Similarly the rest of the system calls phrases are
categorized into their respective sub-sections. The further information regarding these system
calls are available in the Linux Man Pages [4]. The “Reference” section and its sub-sections are
only for the judges. The code will not read anything after the </PERMIT> tag.
In the above judge policy file, permissions are given to “fsread” and “fswrite”. These two system
call phrases indicate to the Generate module to create C/C++ and Java policy files that contain
permissions to the above-mentioned system calls.
The “fsread” system call corresponds to a file read and informs the Generate module to permit
file read operation on “fileread.txt” file, in the yet to be generated C/C++ and Java policy files.
Similarly, “fswrite” corresponds to file write system call and the Generate module will permit
write operation on “filewrite.txt”. In addition, Java can perform certain operations that C/C++
does not support, such as Abstract Window Toolkit (AWT). Hence, permissions to such Java
specific operations can be written within <JAVA-ONLY> and </JAVA-ONLY> tags. These tags
inform the Generate module that they are Java specific and not to bother for C/C++. The
information for the Java specific operations is available in the “Class Security Manager” section
of the Oracle’s website [12].
7.2.3 Generating C/C++ and Java policy files
After coming up with contest or problem specific judge policy file, the corresponding C/C++ and
Java policy files needs to be created. This is done using the Generate module. “generate” is the
51
binary executable of the Generate module. The following command is used for generating
problem specific C/C++ and Java policy files:
./generate judge.policy base.policy <problemletter>.c.policy
<problemletter>.java.policy
The Generate module takes in contest or problem specific “judge.policy” as the judge policy file
and “base.policy” as C/C++ base policy file, as input and produces problem specific C/C++ and
Java policy files. The naming conventions are followed while generating these policy files. The
word “problemletter” specifies the problem in the contest. Generally it would be A,B,C….
Therefore, for the problem letter ‘A’, the output policy files would be “A.c.policy” and
“A.java.policy”. The C/C++ and Java policy files corresponding to the above-mentioned Judge
policy file would look like as shown below.
C/C++ Systrace Policy File Snippet:
linux-fsread: filename eq "fileread.txt" then permit
linux-fswrite: filename eq "filewrite.txt" then permit
Java Policy File Snippet:
grant{
permission java.io.FilePermission "fileread.txt", "read";
permission java.io.FilePermission "filewrite.txt", "write";
};
This completes the necessary changes required to be made on the Sandbox side. Further, PC2 has
to be modified to accommodate a command that can invoke the Execute module.
52
7.2.4 Modifying PC2
After generating the output policy files, the way PC2 compiles and executes binary and .class files
needs to be edited.
For running a Java program, the following changes needs to be made:
Program Execution Command Line:
run_execute.sh
{:basename}
java
{:problemletter}.java.policy jout.log
The “run_execute.sh” script takes .class name, an indicator for Java, input policy file to be used
and the output log file name. Subsequently, when a team submission is received by PC2, it
executes the submission by invoking the “Program Execution Command Line” which in turn
invokes the Execute module. The Execute module generates an output log file which can be
referred by judges and administrators to check if there was any security violation.
Similar changes are made on the C/C++ compilation and execution side.
Program Execution Command Line:
run_execute.sh
{:basename}.exe
c
{:problemletter}.c.policy cout.logs
7.3 Executing Team Runs With Sandbox
Once the required changes are made in the Sandbox and PC2, the team runs on the Judge’s
machine can be made using the Security Sandbox. The judges can opt to execute the participant’s
code manually or can go for Auto-Judge option. In both cases, when the execute procedure is
invoked, PC2 calls the Execute module through the shell and sends all required inputs. The
Execute module runs the C/C++ or Java program based on the input indicator, and generates an
output log file that contains information about the security.
53
If there were any security violation, the output of the execution would be incomplete. Further, the
corresponding violation would be written into the output log file. If there was no violation then
the execution would result in proper output and the output log file contains “No Security
Violation” tag.
54
Chapter 8
CONCLUSION
This project is implemented on a Linux platform. The Security Sandbox will secure PC2 from
those system calls which are prohibited by the policy. The new PC2 tool with Security Sandbox
implemented will enhance the current security features. The Security Sandbox is easy to
implement and use. It can be easily invoked from PC2 and requires minimal changes in current
PC2 system.
8.1 Migration to other major Operating Systems
PC2 is implemented using Java and will run on any Java platform including Linux, Windows and
Mac Operating systems. However, the Security Sandbox is implemented with Linux in mind and
is written mainly using C/C++. This Security Sandbox needs to work on all the platforms where
PC2 is present. Therefore, it is necessary to make some fundamental research on how to migrate
the Security Sandbox to other operating systems.
The Security Sandbox is implemented with two different approaches considering C/C++ and
Java. For C/C++, the Security Sandbox uses systrace and for Java, it uses the JVM security
manager. Both these features are implemented in the Security Sandbox and it invokes the
execution of participant’s code based on a simple indicator supplied by PC2.
For Java programs, the JVM takes care of the underlying platform and hence running a Java
program will be same for all operating systems. Once a corresponding JVM is installed on the
current platform, Java programs can run with no dependencies. Therefore, to run participant’s
Java code, no changes are required in the Security Sandbox.
55
For C/C++, the Security Sandbox calls systrace to execute the binary. Currently systrace is
available only on UNIX based Operating Systems. Hence for other operating systems, research is
needed on what features they provide to implement a Security Sandbox.
8.1.1 Mac OS
A version of Systrace is available for Mac OS. Therefore, a small amount of change is required in
the current code for the Security Sandbox to work on Mac OS. The Generate module might need
to create policy keeping Mac OS in mind. The Execute module simply executes the binary against
the policy given by the Generate module. Further, everything runs in a folder. Therefore, the
Execute module might not require any changes.
8.1.2 Solaris
Since Solaris falls into UNIX OS family, similar changes of Mac OS are required for Solaris too.
Therefore, the Security Sandbox can be migrated to Solaris platform with minimal changes.
8.1.3 Windows
Windows does not have any such security features that Linux enjoys. There is no systrace or
ptrace. Therefore, the entire approach has to be changed when it comes to Windows. However,
there is one tool called StraceNT, which is similar to Strace in Linux. Both Strace and StraceNT
are passive tracing tools. They simply log information about system calls and other information
after executing the binary. By that time, binary executable might caused damage to the system.
Therefore, what is needed is an active tracing tool to monitor every system call made by the
binary executable at run time.
56
Windows Operating Systems provides a tracing facility called Event Tracing for Windows
(ETW). ETW can be used to trace events raised by applications running in user mode and by
device drivers running in Kernel mode [18]. Windows also presents a software tracing technology
called Windows preprocessor (WPP) which uses ETW. The WPP is used in tracing the operation
of a software component [19]. Further research needs to be done on ETW and WPP technologies
to see how much they can help in the Security Sandbox.
Once Windows develops and incorporates a tool similar to the systrace, then the Security
Sandbox can be configured accordingly. The Security Sandbox might need a very new approach
to work on Windows. Therefore, current implementation might have to be changed completely.
Hence, the Security Sandbox for Windows platform would allow an opportunity for future
development.
8.2 Future Development
The Security Sandbox is aimed at running C/C++ and Java programs because these are the most
commonly used programming languages in the programming contests. In future, the organizers
might design a contest that allows other programming and scripting languages such as C#, Perl
and Python. Therefore, the current Security Sandbox might need further enhancements to
accommodate these languages.
Since the Security Sandbox is applied only on the Judge or Administrator’s machine, the
participants might take advantage and run malicious code on their machine that may disobey the
rules of the contest. During the test run, a participant may try to hack into PC2 software on his or
her machine. The Security Sandbox will not monitor these malicious activities. In order to
provide security against these types of activities, PC2 system needs to completely encapsulate
57
contest participants so that they would not have access to any machine resources outside the
encapsulating system. The new system would provide all the necessary tools including editor,
compiler, debugger etc, which are required for the contest. Therefore, the Operating System must
start PC2 as soon as it boots. This method might help to reduce or eliminate any malicious
activities attempted by the participants on their machine during the contest.
Eventually, the Security Sandbox might become one complete security tool for providing a
foolproof security and protection for PC2.
58
REFERENCES
[1] PC2 Home Page [Online]
Available: http://www.ecs.csus.edu/pc2/
[2] ai-contest [Online]
Available: http://code.google.com/p/ai-contest/wiki/Sandboxing
[3] Marshall Kirk McKusick, Keith Bostic, Michael J. Karels, John Quarterman, “The Design and
Implementation of the 4.4 BSD Operating System”, April 1996
[4] Linux Man Pages [Online]
Available: http://linuxmanpages.com/
[5] Systrace - Interactive Policy Generation for System Calls [Online]
Available: http://www.citi.umich.edu/u/provos/systrace/
[6] Systrace by Neils Provos [Online]
Available: http://www.provos.org/index.php?/categories/2-Systrace
[7] Hendrik Weimer, “strace Dissecting Programs”, September 19, 2006 [Online]
Available: http://www.osreviews.net/reviews/admin/strace
[8] Playing with ptrace, Part I [Online]
Available: http://www.linuxjournal.com/article/6100
[9] Ray Lai, “Systrace for Slackers”, NYCBUG, March 2006 [Online]
Available: http://www.cyth.net/~ray/systrace-talk/
[10] Michael W. Lucas, “Creating Systrace Policies”, February 27, 2003 [Online]
Available: http://onlamp.com/pub/a/bsd/2003/02/27/Big_Scary_Daemons.html
[11] Ahmad Jalil Qarshi, “How to Call Java Functions from C Using JNI”, January 13, 2008
[Online]
Available: http://www.codeproject.com/KB/cpp/CJniJava.aspx
59
[12] Class Security Manager [Online]
Available: http://download.oracle.com/javase/6/docs/api/java/lang/SecurityManager.html
[13] Miron Sadziak, “Using Java SecurityManager to grant/deny access to system functions”,
November 16, 2009 [Online]
Available: http://www.javablogging.com/using-java-securitymanager-to-grantdenyaccess-to-system-functions/
[14] JNI Part1: Java Native Interface Introduction and “Hello World” application [Online]
Available: http://electrofriends.com/articles/jni/jni-part1-java-native-interface/
[15] Sean R. Owens, “VerySimpleClient.java” [Online]
Available: http://darksleep.com/player/SocketExample/VerySimpleClient.java.html
[16] Sean R. Owens, “VerySimpleServer.java” [Online]
Available:
http://www.darksleep.com/player/SocketExample/VerySimpleServer.java.html
[17] Sockets Tutorial [Online]
Available: http://www.linuxhowtos.org/C_C++/socket.htm
[18] Dr. Insung Park and Ricky Buch, “Improve Debugging And Performance Tuning With
ETW” [Online]
Available: http://msdn.microsoft.com/en-us/magazine/cc163437.aspx
[19] WPP Software Tracing, September 07, 2011 [Online]
Available: http://msdn.microsoft.com/en-us/library/ff556204.aspx
Download