# Presentation: 169619

## Neither a Borrower nor a Lender Be:The Dangers of Mobile Code

- Barton P. Miller
- bart@cs.wisc.eduComputer Sciences Department
- University of Wisconsin
- Madison, Wisconsin 53705
- USA

## 1. Subverting running programs
It’s easy; we have a nice toolkit.
2. Safety checking of binary programs
Given and interface spec and the machine code, verify safety conditions.
3. Safe remote execution of my job
The Condor or Java applet scenario.
4. An infrastructure for safe mobile computing.
Make mobility easier, while allowing the sysadmin to retain control.

- It’s easy; we have a nice toolkit.
- 2. Safety checking of binary programs
- Given and interface spec and the machine code, verify safety conditions.
- 3. Safe remote execution of my job
- The Condor or Java applet scenario.
- 4. An infrastructure for safe mobile computing.
- Make mobility easier, while allowing the sysadmin to retain control.

- Four Security Topics

## Dynamic Instrumentation

- Does not require recompiling or relinking
- Saves time: compile and link times are significant in real systems.
- Can instrument without the source code (e.g., proprietary libraries).
- Can instrument without linking (relinking is not always possible.
- Instrument optimized code.

## Dynamic Instrumentation (con’d)

- Only instrument what you need, when you need
- No hidden cost of latent instrumentation.
- Enables “one pass” tools.
- Can instrument running programs (such as Web or database servers)
- Production systems.
- Embedded systems.
- Systems with complex start-up procedures.

## The Basic Mechanism

- ApplicationProgram

- Function foo

- Trampoline

## The DynInst Interface

- Machine independent representation
- Object-based interface to build Abstract Syntax Trees (AST’s)
- Write-once, instrument-many (portable)
- Hides most of the complexity in the API
- Process Hijacker: only 700 lines of user code!
- MPI tracer: 250 lines

## Basic DynInst Operations

- Process control:
- Attach/create process
- Monitor process status changes
- Callbacks for fork/exec/exit
- Image (executable program) routines:
- Find procedures/modules/variables
- Call graph (parent/child) queries

## Basic DynInst Operations

- Inferior (application processor) operations:
- Malloc/free
- Allocate heap space in application process
- Inferior RPC
- Asynchronously execute a function in the application.
- Load module
- Cause a new .so/.dll to be loaded into the application.

## Basic DynInst Operations

- Inferior operations (continued):
- Remove Function Call
- Disable an existing function call in the application
- Replace Function Call
- Redirect a function call to a new function
- Replace Function
- Redirect all calls (current and future) to a function to a new function.

## Basic DynInst Operations

- Building AST code sequences:
- Control structures: if and goto
- Arithmetic and Boolean expressions
- Get PID/TID operations
- Read/write registers and global variables
- Read/write parameters and return value
- Function call

## Applications of DynInst

- Process Hijacking (Vic Zandy)
- Submitting already-running jobs to Condor
- MPI Tracer (Chris Chambreau)
- Insert Vampir or Pablo trace calls on the fly.
- Function Call Tracer (Roland Wismüller)
- Generate dynamic call graph
- Image Mentor (Brian Wylie)
- Query module/function/memory structure
- Re-Tee (Jeff Hollingsworth)
- Redirect program output on-the-fly
- License server bypassing
- Condor security attacks

## License Server Attack: The Bypass

**Program**

**License Data**

**Network**

**License**
**Server**

_**Normal**_**: licensed program runs after communicates with license server.**

## Example: Adobe FrameMaker

- Two-step license verification:
- retrieve license data from server [once]
- check license data for correctness [often]
- In practice:
- allow FM to time-out waiting for server
- allow FM to attempt to go into “demo” mode
- switch FM back to normal mode
- insure that future license checks always succeed

## Strategies

- Complete reverse engineering:
- not an option
- legal problems
- complexity (FrameMaker is a 7 MB binary!)
- Focus on certain characteristics:
- I/O (network sockets) traffic
- execution trace

## Tools

- High-level language translators:
- Dyner: interactive, interpreted C subset
- Jdyninst: Java to DynInst compiler
- Bypasser: an interactive call graph browser
- Search and walk application call graph
- Resolves function pointers at runtime
- Call follow caller or callee paths
- Can generate call trace

## Use

- Determining where to apply changes:
- get trace for a successful run
- get trace for a (forced-)failure run
- compare to find differences
- repeat as needed

## Details

- FM calls NlOpenlicenses on start up
- Contacts license server and caches credential  if successful
- At end of main, and calls NluiCheckLicense
- If credential is not present, call ChangeProductToDemo (cannot save files)
- Frequently, during operation, FM will check for cached credentials.

## Details

- FM calls NlOpenlicenses on start up
- Contacts license server and caches credential  if successful
- Allow this to fail.
- At end of main, and calls NluiCheckLicense
- If credential is not present, call ChangeProductToDemo (cannot save files)
- Frequently, during operation, FM will check for cached credentials.

## Details

- FM calls NlOpenlicenses on start up
- Contacts license server and caches credential  if successful
- Allow this to fail.
- At end of main, and calls NluiCheckLicense
- If credential is not present, call ChangeProductToDemo (cannot save files)
- Delete the call to ChangeProductToDemo.
- Frequently, during operation, FM will check for cached credentials.

## Details

- FM calls NlOpenlicenses on start up
- Contacts license server and caches credential  if successful
- Allow this to fail.
- At end of main, and calls NluiCheckLicense
- If credential is not present, call ChangeProductToDemo (cannot save files)
- Delete the call to ChangeProductToDemo.
- Frequently, during operation, FM will check for cached credentials.
- Change this call to always return “true”.

## Condor Attack: Lurking Jobs

- Condor schedules jobs on idle workstations
- In a normal mode, jobs run as a common, low-privilege  user ID: “nobody”.
- This common user ID provides an opportunity for an evil lurking process to ambush subsequent jobs (from other users):

## Condor Job Structure

- Submitting Host

- Shadow Process

- Execution Host

- User Job

## Condor Job Structure

- Submitting Host

- Shadow Process

- Execution Host

- Evil
- User Job

- system calls

## Condor Job Structure

- Submitting Host

- Execution Host

- Lurker
- Process

## Condor Job Structure

- Submitting Host

- Shadow Process

- Execution Host

- Innocent
- User Job

- Lurker
- Process

## Condor Job Structure

- Submitting Host

- Shadow Process

- Execution Host

- Innocent
- User Job

- Lurker
- Process

- attach

## Condor Job Structure

- Submitting Host

- Shadow Process

- Execution Host

- Innocent
- User Job

- Control remote
- system calls

- Lurker
- Process

**rm -rf ***

## Slide 28

## 2. Safety Checking of Binary Code

- Is it safe for untrusted foreign code to be loaded into a trusted host* *system?

- Host

- Untrusted
- Code

- Code producer

- Code consumer

## Safety Properties We Enforce

- Default collection of safety conditions
- No type violations
- No out-of-bounds array accesses,
- No misaligned loads/stores,
- No uses of uninitialized variables,
- No invalid pointer dereferences,
- No unsafe interaction with the host
- Precise and flexible host access policy
- Customizable

- Type safety

## Motivation

- Dynamic extensibility
- Operating systems: custom policies, general functionality, performance
- Extensible OS:  exokernel, VINO, SPIN, synthetix...
- Commodity OS: SLIC, kerninst, ...
- Databases: type-based extensions
- Illustra, informix, paradise, ...
- Web browsers: plug-ins
- Performance tools: measurement code
- Kerninst, paradyn, ...
- Active network components

## Motivation

- Component-based software (Java, COM)
- Software components from different vendors are combined to construct a complete application
- Code from several sources with no mutual trust

## High-Level  Characteristics

- Perform safety checking on ordinary binary, mechanically synthesize (and verify) a safety proof
- Extend the host at a very fine-grained level (allow the untrusted code to manipulate the internal data structures of the host directly)
- Enforce host-specified access policy + type safety

## Host-Specified Access Policy

- As big as the entire address space, as small as a variable
- [Region : Category : Access]
- Category: Types, fields
- Access:
- 	readable (r),
- 	writable (w),
- 	followable (f),
- 	executable (e),
- 	operable (o)
- (e.g., to “copy”, to “examine”)

- Locations

- Values

## Protections Provided by Access Policy

- Initial inputs to the untrusted code

## Kernel page-replacement extension
Pick a cold page from global LRU list.
typedef struct _page_list {
	int page;				
	...
	struct _page_list * next;

} page_list;

	[Host : page_list.page : ro]

	[Host : page_list.next, page_list ptr : rfo]

- Pick a cold page from global LRU list.
- typedef struct _page_list {
- 	int page;
- 	...
- 	struct _page_list * next;
- } page_list;
- 	[Host : page_list.page : ro]
- 	[Host : page_list.next, page_list ptr : rfo]

- Principle of “Least Privilege”

- // read access

- // follow access

## 3. Safe Remote Execution of My Job

- My job is executing on a remote host of unknown pedigree.
- Threats:
- Can I trust the requests that are being made from the remote job to my home host?
- Can I trust the results that are being calculated by the remote job?

## Condor Job Structure

- Submitting Host

- Shadow Process

- Execution Host

- User Job

## Three Approaches

- 1. Filtering: screen out dangerous requests
- Sandboxing: restrict particular syscalls, do a chroot, restrict host access.
- Behavioral profiling, ala intrusion detection: use past behavior to screen future requests.
- This technique addresses the threat to the home host, but not the data integrity problem.

## Three Approaches

- 2. Replication
- Byzantine-like replication to detect and tolerate malicious modifications.
- Similar techniques to detect and tolerate malicious remote requests.
- Addresses both threats, but at a high cost.

## Three Approaches

- 3. “Slippery” jobs and “Crystal” jobs
- Design the program/process so that it is hard to get a handle:
- System defensive techniques from worm technology.
- Code transformations to keep the code unrecognizable.
- Slippery: cannot get a meaningful hold on the job.
- Crystal: is doesn’t bend, but it shatters
- Any modification is likely to destroy, rather than subvert the job.
- This area is in the crazy-idea stage. Stay tuned!

## 4. Ubiquitous Mobility

- Ordinary applications, in execution, that move as:
- User moves to a new computer
- Computer moves to a new location
- No modifications to apps, OS, or network
-  Built on common existing infrastructure
- Security policy set by administrator, not user
- Everything is mobile
- Network connections, GUIs, I/O

## At my desk

**Office Network**

- Laptop

- TCP

## Onto my laptop (802.11b)

**Office Network**

- Compressed TCP

- Laptop

- Office Desktop

## Onto my laptop (low speed wireless)

**Office Network**

- Laptop

- Encrypted Low-Power Compressed TCP

- Office Desktop

## At home (802.11b)

- Laptop

**Office Network**

**Home Network**

- Encrypted Compressed TCP

- Office Desktop

- Home Desktop

## Onto my home desktop (DSL/cable)

- Laptop

**Office Network**

**Home Network**

- Encrypted TCP

- Office Desktop

## Components for Ubiquitous Mobility

- Reliable Sockets
- Mobile, fault-tolerant network connections
- Network Proxy
- Secure and mobile network connections with unmodified correspondents
- GUI Proxy
- Mobile user interfaces
- I/O Proxy
- Remote file access, based on Condor shadow

## Follow-Ups:

- Dyninst Release 1.3:
- Runs on Solaris (SPARC & x86), Windows NT, *AIX/SP2*, Linux (x86), Irix (MIPS),Tru64 Unix.
**http://www.cs.wisc.edu/paradyn**
- Papers on dyninst, process hijacking, static safety checking:
-  **http://www.cs.wisc.edu/paradyn/papers**

## Back-Up Slides

- Static safety checking of binary code

## Experimental Evaluation

- Test cases
- Array sum, start/stop timer, b-tree, kernel paging policy, hash, bubble sort, heap sort, stack-smashing, MD5, jPVM, /dev/kerninst (symbol, loggedWrites)
- Summary of Results
- Found safety violations in kernel policy, stack-smashing, /dev/kerninst
- Verified all conditions, except for some calls in MD5, jPVM (precision lost due to inability to detect that a loop  ‘kills’ all elements of an array)
- Checking times vary from 0.1 to 30 seconds

## Characteristics of Test Cases

## Timing (Seconds)

## Limitations

- Can only ensure safety properties that can be expressed using typestates + linear constraints
- e.g., cannot handle nonlinear array subscripts
- Induction iteration method is incomplete
- e.g., generalization capability is limited
- Limitations in handling of arrays
- Lost precision
- Inherited limitations of static techniques
- Must reject code that cannot be checked statically
- Otherwise, there is the recovery problem

## Safety Checking: Related Work

- Dynamic Techniques:
- Hardware enforced address spaces, SFI, interpretation, etc.
- Hybrid Techniques
- Safe languages:  Java, ML, Modula 3, etc.
- 	Runtime cost
- 	Potential recovery problem

- Static Techniques
- Proof-Carrying Code
- 	[Necula, Lee]
- Certifying Compiler, Typed-Assembly Language
- 	[Necula, Lee]
- 	[Morrisett, Walker, Crary,  Glew, ...]
- 	[Colby, Lee, Necula, Blau]

## Safety Checking: Related Work

- Yes/No

- Safety Policy,
- Initial inputs

## Safety Checking: Related Work

- Certifying
- Compiler

- Safe C,

- Java,

- ML

- Machine Code

- Proof

- Proof
- Checker

- Yes/No

- Yes/No

- C, C++, Assembly, ...

- Ordinary
- Binary

- Proof
- generator

- Off-the-Shelf
- cc, gcc, as

- Safety Policy,
- Initial inputs

- Ordinary
- Binary

- Proof

- Proof
- Checker