<<

Vulnerability Assessment and Secure Coding Practices

Secure Coding Practices for we are Grid and Cloud Middleware and Services Barton P. Miller Elisa Heymann Bart Miller Elisa Heymann Jim Kupsch Eduardo Cesar James A. Kupsch Computer Architecture and Computer Sciences Department Operating Systems Department Vamshi Basupalli Manuel Brugnoli University of Wisconsin Universitat Autònoma de Barcelona Salini Kowsalya Max Frydman

[email protected] [email protected]

XSEDE13 San Diego July 2013 http://www.cs.wisc.edu/mist/

This research funded in part by Department of Homeland Security grant FA8750-10-2-0030 (funded through AFRL). 2 Past funding has been provided by NATO grant CLG 983049, National Science Foundation grant OCI-0844219, the National Science Foundation under contract with San Diego Supercomputing Center, and National Science Foundation grants1 CNS-0627501 and CNS-0716460.

What do we do Our experience Condor, University of Wisconsin Batch queuing workload management system • Assess Middleware: cloud/grid 15 vulnerabilities 600 KLOC of C and C++ SRB, SDSC software secure Storage Resource Broker - data grid 5 vulnerabilities 280 KLOC of C •Train:We teach tutorials for users, MyProxy, NCSA Credential Management System developers, admins, and managers 5 vulnerabilities 25 KLOC of C glExec, Nikhef • Research: Make in-depth assessments Identity mapping service more automated and improve quality of 5 vulnerabilities 48 KLOC of C Gratia Condor Probe, FNAL and Open Science Grid automated code analysis Feeds Condor Usage into Gratia Accounting System 3 vulnerabilities 1.7 KLOC of Perl and Bash Condor Quill, University of Wisconsin http://www.cs.wisc.edu/mist/papers/VAshort.pdf DBMS Storage of Condor Operational and Historical Data 6 vulnerabilities 7.9 KLOC of C and C++

3 4

Our experience Our experience

VOMS Core INFN Wireshark, wireshark.org Virtual Organization Management System Network Protocol Analyzer 1 vulnerability 161 KLOC of Bourne Shell, C++ and C 2 vulnerabilities 2400 KLOC of C iRODS, DICE Condor Privilege Separation, Univ. of Wisconsin Data-management System Restricted Identity Switching Module 9 vulnerabilities (and counting) 285 KLOC of C and C++ 2 vulnerabilities 21 KLOC of C and C++ , Google VOMS Admin, INFN Web browser Web management interface to VOMS data 1 vulnerability 2396 KLOC of C and C++ 4 vulnerabilities 35 KLOC of Java and PHP

CrossBroker, Universitat Autònoma de Barcelona WMS, INFN Resource Mgr for Parallel & Interactive Applications Workload Management System 4 vulnerabilities 97 KLOC of C++ in progress 728 KLOC of Bourne Shell, C++, C, Python, Java, and Perl ARGUS 1.2, HIP, INFN, NIKHEF, SWITCH gLite Authorization Service CREAM, INFN 0 vulnerabilities 42 KLOC of Java and C Computing Resource Execution And Management 5 vulnerabilities (and counting) 216 KLOC of Bourne Shell, Java, and C++ 5 6

1 Vulnerability Assessment and Secure Coding Practices

Who funds us Roadmap • United States – Introduction –DHS – Handling errors –NSF – Pointers and – Numeric Errors • European Commission – Race Conditions – EGI – Exceptions –EMI – Privilege, Sandboxing and Environment • Spanish Government – Injection Attacks – Web Attacks •NATO –Bad things

7 8

Discussion of the Practices Roadmap – Introduction • Description of vulnerability – Handling errors • Signs of presence in the code – Pointers and Strings • Mitigations – Numeric Errors – Race Conditions • Safer alternatives – Exceptions – Privilege, Sandboxing and Environment – Injection Attacks – Web Attacks –Bad things

26 27

Buffer Overflows http://cwe.mitre.org/top25/archive/2011/2011_cwe_sans_top25.html#Listing

1. Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection') 2. Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection') 3. Buffer without Checking Size of Input ('Classic Buffer Pointers and Strings Overflow') 4. Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting') 5. Missing Authentication for Critical Function 6. Missing Authorization 7. Use of Hard-coded Credentials 8. Missing Encryption of Sensitive Data 9. Unrestricted Upload of with Dangerous Type 10. Reliance on Untrusted Inputs in a Security Decision

29 30

2 Vulnerability Assessment and Secure Coding Practices

Why Buffer Overflows Buffer Overflows are Dangerous • Description • An overflow overwrites memory adjacent – Accessing locations of a buffer outside the boundaries to a buffer of the buffer • Common causes • This memory could be –C-style strings – Unused – Array access and pointer arithmetic in languages –Code without bounds checking – Program data that can affect operations – Off by one errors – Internal data used by the runtime system – Fixed large buffer sizes (make it big and hope) – Decoupled buffer pointer and its size • Common result is a crash • If size unknown overflows are impossible to detect • Specially crafted values can be used for an • Require synchronization between the two attack • Ok if size is implicitly known and every use knows it (hard)

31 32

Buffer Overflow of User Data Buffer Overflow Danger Signs: Affecting Flow of Control Missing Buffer Size char id[8]; int validId = 0; /* not valid */ • gets, getpass, getwd, and scanf family %s %[ ] id validId (with or … specifiers without width) \0 \0 \0 \0 – Impossible to use correctly: size comes solely from user input gets(id); /* reads "evillogin"*/ – Source of the first (1987) stack smash attack. id validId – Alternatives: evillogi110 \0 \0 \0 ‘n’ Unsafe Safer /* validId is now 110 decimal */ gets(s) fgets(s, sLen, stdin) if (IsValid(id)) validId = 1; /* not true */ if (validId) /* is true */ getcwd(s) getwd(s, sLen) {DoPrivilegedOp();} /* gets executed */ scanf("%s", s) scanf("%100s", s)

33 34

strcat, strcpy, sprintf, Buffer Overflow Danger Signs: vsprintf Difficult to Use and Truncation – Impossible for function to detect overflow • strncat(dst, src, n) • Destination buffer size not passed – n is the maximum number of chars of src to append – Difficult to use safely w/o pre-checks (trailing null also appended) – can overflow if n >=(dstSize-strlen(dst)) • Checks require destination buffer size • Length of data formatted by • strncpy(dst, src, n) • Difficult & error prone –Writes n chars into dst, if strlen(src)=n, dst is not null terminated Proper usage: concat s1, s2 into dst If (dstSize < strlen(s1) + strlen(s2) + 1) • Truncation detection not provided {ERROR("buffer overflow");} • Deceptively insecure strcpy(dst, s1); – Feels safer but requires same careful use as strcat strcat(dst, s2);

35 36

3 Vulnerability Assessment and Secure Coding Practices

Safer String Handling: C11 and ISO/IEC 24731 C-library functions • snprintf(buf, bufSize, fmt, …) and Extensions for the C library: vsnprintf Part 1, Bounds Checking Interface – Returns number of bytes, not including \0 that • Functions to make the C library safer would’ve been written. • Meant to easily existing library – Truncation detection possible calls with little or no other changes (result >= bufSize implies truncation) – Use as safer version of strcpy and strcat • Aborts on error or optionally reports error Proper usage: concat s1, s2 into dst • Very few unspecified behaviors r = snprintf(dst, dstSize, "%s%s",s1, s2); • All updated buffers require a size param If (r >= dstSize) {ERROR("truncation");} • http://www.open-std.org/jtc1/sc22/wg14

37 38

ISO/IEC 24731: string and memory functions Attacks on Code Pointers • strcpy_s strncpy_s memcpy_s • Stack Smashing is an example strcat_s strncat_s memmove_s • There are many more pointers to functions or • Like standard counterpart, except all addresses in code include an additional parameter for the – Dispatch tables for libraries length of the destination buffer – Return addresses • Run- constraint failure if destination – Function pointers in code • If error – C++ vtables – jmp_buf – Null-terminates destination buffer, null fills – atexit buffer for mem functions – Exception handling run-time – Internal heap run-time data structures

39 42

Buffer Overflow of a User Pointer { char id[8]; int (*logFunc)(char*) = MyLogger; id logFunc Ptr to MyLogger Numeric Errors gets(id); /* reads "evilguyxPtr to system “ */ id logFunc

evi l guyx Ptr to system

/* equivalent to system(userMsg) */ logFunc(userMsg);

43 44

4 Vulnerability Assessment and Secure Coding Practices

Integer Vulnerabilities

• Description – Many programming languages allow silent loss of integer data without warning due to •Overflow • Truncation • Signed vs. unsigned representations – Code may be secure on one platform, but silently vulnerable on another, due to different underlying integer types. • General causes – Not checking for overflow – Mixing integer types of different ranges – Mixing unsigned and signed integers

45 46

Integer Danger Signs Numeric Parsing Unreported Errors • Mixing signed and unsigned integers • atoi, atol, atof, scanf family (with %u, • Converting to a smaller integer %i, %d, %x and %o specifiers) • Using a built-in instead of the API’s – Out of range values results in unspecified typedef type behavior • However built-ins can be problematic too: – Non-numeric input returns 0 size_t is unsigned, ptrdiff_t is signed –Use strtol, strtoul, strtoll, strtoull, strtof, strtod, strtold which allow error • Assigning values to a variable of the detection correct type before data validation (range/size check)

47 48

Integer Mitigations The Cost of Not Checking… • Use correct types, before validation 4 Jun 1996: An unchecked 64 bit floating point • Validate range of data number assigned to a 16 bit integer • Add code to check for overflow, or use safe integer libraries or large integer libraries • Not mixing signed and unsigned integers in a computation • Compiler options for signed integer run-time exceptions, and integer warnings •Use strtol, strtoul, strtoll, strtoull, Ariane 5 mission 501 strtof, strtod, strtold, which allow error Cost: Development cost: $7 billion detection Lost rocket and payload $500 million

49 50

5 Vulnerability Assessment and Secure Coding Practices

Race Conditions

• Description – A race condition occurs when multiple threads of control try to perform a non-atomic operation on a shared object, such as • Multithreaded applications accessing shared data Race Conditions • Accessing external shared resources such as the file system • General causes – Threads or signal handlers without proper synchronization – Non-reentrant functions (may have shared variables) – Performing non-atomic sequences of operations on shared resources (file system, shared memory) and assuming they are atomic

51 52

Successful Race Condition Attack Race Condition on Data void TransFunds(srcAcct, dstAcct, xfrAmt) { if (xfrAmt < 0) FatalError(); • A program contains a data race if two threads int srcAmt = srcAcct.GetBal(); if (srcAmt - xfrAmt < 0) simultaneously access the same variable, where FatalError(); srcAcct.SetBal(srcAmt - xfrAmt); least one of these accesses is a . dstAcct.SetBal(dstAcct.getBal() + xfrAmt); • Programs need to be race free to be safe. } Balances time Thread 1 Thread 2 Bob Ian XfrFunds(Bob, Ian, 100) XfrFunds(Bob, Ian, 100) 100 0 srcAmt = 100 srcAmt = 100 srcAmt – 100 < 0 ? srcAmt – 100 < 0 ? srcAcct.SetBal(100 – 100) 0 srcAcct.SetBal(100 – 100) 0 dst.SetBal(0 + 100) 100 dst.SetBal(0 + 100) 200

53 54

Mitigated Race Condition Attack Spot the Race Condition void synchronized TransFunds(srcAcct, dstAcct, xfrAmt) { if (xfrAmt < 0) FatalError(); int srcAmt = srcAcct.GetBal(); public class SimpleServlet extends HttpServlet { if (srcAmt - xfrAmt < 0) FatalError(); private String query; srcAcct.SetBal(srcAmt - xfrAmt); public void doGet(HttpServletRequest request, dstAcct.SetBal(dstAcct.getBal() + xfrAmt); HttpServletResponse response) } throws ServletException, IOException { try { Connection conn = DriverManager.getConnection(...); Balances time query = "INSERT INTO roles" + "(userId, userRole)" + Thread 1 Thread 2 Bob Ian XfrFunds(Bob, Ian, 100) XfrFunds(Bob, Ian, 100) 100 0 "VALUES " + "('" + request.getParameter("userId") + In use? No, proceed "'," + "'standard')"; In use? Yes, . Statement stmt = conn.createStatement(); srcAmt = 100 stmt.executeUpdate(query); srcAmt – 100 < 0 ? } catch ... srcAcct.SetBal(100 – 100) 0 dst.SetBal(0 + 100) 100 } srcAmt = 0 srcAmt – 100 < 0? Yes, fail

55 56

6 Vulnerability Assessment and Secure Coding Practices

Spot the Race Condition File System Race Conditions

public class SimpleServlet extends HttpServlet { • A file system maps a name of a file or other private String query; object in the file system, to the internal identifier public void doGet(HttpServletRequest request, HttpServletResponse response) (device and inode) throws ServletException, IOException { • If an attacker can control any component of the private String query; path, multiple uses of a path can result in different file system objects try { Connection conn = DriverManager.getConnection(...); query = "INSERT INTO roles" + "(userId, userRole)" + • Safe use of path "VALUES " + "('" + request.getParameter("userId") + "'," + "'standard')"; – eliminate race condition Statement stmt = conn.createStatement(); • use only once stmt.executeUpdate(query); • use file descriptor for all other uses } catch ... } – verify multiple uses are consistent

57 58

File System Race Examples Race Condition File Attributes

• Check properties of a file then open • Using the path to create or open a file and Bad: access or stat Î open then using the same path to change the Safe: open Î fstat ownership or mode of the file – Best to create the file with the correct owner • Create file if it doesn’t exist group and mode at creation Bad: if stat fails Î creat(fn, mode) – Otherwise the file should be created with Safe: open(fn, O_CREAT|O_EXCL, mode) restricted permissions and then changed to – Never use O_CREAT without O_EXCL less restrictive using fchown and fchmod – Better still use safefile library – If created with lax permissions there is a race • http://www.cs.wisc.edu/mist/safefile condition between the attacker opening the file James A. Kupsch and Barton P. Miller, “How to Open a File and Not Get and permissions being changed Hacked,” 2008 Third International Conference on Availability, Reliability and Security (ARES), Barcelona, Spain, March 2008.

59 60

Race Condition Saving Directory Race Condition Creating a File and Returning • Want to atomically check if file exists and • There is a need to save the current working create if not, or fail if it exists directory, chdir somewhere else, and chdir back to original directory • Common solution is to check if file exists stat open • Insecure pattern is to use getwd, and chdir to with , then if it doesn't value returned • Open a file or create it if does not exist – getwd could fail – creat(fname, mode) – Path not guaranteed to be the same directory open(fname, O_CREAT|O_WRONLY|O_TRUNC, mode) • Safe method is get a file descriptor to the • Must use O_CREATE|O_EXCL to get desired directory and to use fchdir to go back property savedDir = open(".", O_RDONLY); chdir(newDir); • Never use O_CREATE without O_EXCL … Do work … fchdir(savedDir);

61 64

7 Vulnerability Assessment and Secure Coding Practices

Race Condition Temporary Files Race Condition Examples

• mktemp, tmpnam, or tempnam, then open • Your Actionstime Attackers Action – Return filename that does not exist s=strdup("/tmp/zXXXXXX") – a race condition exists if O_EXCL is not used tempnam(s) // s now "/tmp/zRANDOM" link = "/etc/passwd" •Use mkstemp which returns the filename and a file = "/tmp/zRANDOM" file descriptor to the opened file (use to symlink(link, file) restrict privileges) f = fopen(s, "w+") // writes now update • To create a directory use mkdtemp if available or // /etc/passwd the following: for (int j = 0; j < 10; ++j) { strcpy(path, template); Safe Version if (mktemp(path) == NULL) {ERROR("mktemp failed");} if ((path) != -1 || errno != EEXIST) { fd = mkstemp(s) break; f = fdopen(fd, "w+") } }

66 67

Exception Vulnerabilities

• Exception are a nonlocal control flow mechanism, usually used to propagate error conditions in languages such as Java and C++. try { // code that generates exception Exceptions } catch (Exception e) { // perform cleanup and error recovery } • Common Vulnerabilities include: – Ignoring (program terminates) – Suppression (catch, but do not handled) – Information leaks (sensitive information in error messages)

78 79

Proper Use of Exceptions Exception Suppression

• Add proper exception handling – Handle expected exceptions (i.e. check for errors) – Don’t suppress: 1. User sends malicious data user=“admin”,=null • Do not catch just to make them go away • from the error or rethrow exception boolean Login(String user, String pwd){ – Include top level exception handler to avoid exiting: boolean loggedIn = true; String realPwd = GetPwdFromDb(user); catch, log, and restart try { • Do not disclose sensitive information in messages if (!GetMd5(pwd).equals(realPwd)) { – Only report non-sensitive data loggedIn = false; – Log sensitive data to secure store, return id of data } – Don't report unnecessary sensitive internal state } catch (Exception e) { //this can not happen, ignore • Stack traces } • Variable values return loggedIn; • Configuration data } 2. System grants access Login() returns true

80 81

8 Vulnerability Assessment and Secure Coding Practices

Unusual or Exceptional WTMI (Way Too Much Info) Conditions Mitigation Login(… user, … pwd) { void ValidatePwd(… user, … pwd) try { throws BadUser, BadPwd { ValidatePwd(user, pwd); realPwd = GetPwdFromDb(user); } catch (Exception e) { if (realPwd == null) ("Login failed.\n"); throw BadUser("user=" + user); 1. User sends malicious data user=“admin”,pwd=null print(e + "\n"); if (!pwd.equals(realPwd)) e.printStackTrace(); throw BadPwd("user=" + user boolean Login(String user, String pwd){ return; + " pwd=" + pwd boolean loggedIn = true; } + " expected=" + realPwd); String realPwd = GetPwdFromDb(user); } … try { User exists Entered pwd if (!GetMd5(pwd).equals(realPwd)) User's actual password ?!? Login failed. { (passwords aren't hashed) loggedIn = false; BadPwd: user=bob pwd=x expected=password } BadPwd: } catch (Exception e) { at Auth.ValidatePwd (Auth.java:92) loggedIn = false; } at Auth.Login (Auth.java:197) Reveals internal structure return loggedIn; … (libraries used, call structure, } com.foo.BadFramework(BadFramework.java:71) version information) 2. System does not grant access Login() returns false ...

82 83

The Right Amount of Information WTMI (Way Too Much Info) Login { #!/usr/bin/ruby try { Log sensitive information ValidatePwd(user, pwd); def ValidatePwd(user, password) } catch (Exception e) { if wrong password logId = LogError(e); // write exception and return log ID. raise “Bad passwd for user #{user} expected #{password}” print("Login failed, username or password is invalid.\n"); end print("Contact support referencing problem id " + logId end + " if the problem persists"); return; def Login(user, password) } Generic error message ValidatePwd(user, password); } (id links sensitive information) rescue Exception => e puts “Login failed” void ValidatePwd(… user, … pwd) throws BadUser, BadPwd { puts e.message realPwdHash = GetPwdHashFromDb(user) puts e.backtrace.inspect if (realPwdHash == null) end throw BadUser("user=" + HashUser(user)); User exists if (!HashPwd(user, pwd).equals(realPwdHash)) User's actual password ?!? throw BadPwdExcept("user=" + HashUser(user)); Login failed. … Reveals internal structure User and password are hashed Bad password for user Elisa expected pwd } ["./test3:4:in `ValidatePwd'", "./test3:8:in `Login'", "./test3:15"] (minimizes damage if breached)

84 85

Not Dropping Privilege

• Description – When a program running with a privileged status (running as root for instance), creates a process or tries to access resources as another user Privilege, Sandboxing, • General causes – Running with elevated privilege and Environment – Not dropping all inheritable process attributes such as uid, gid, euid, egid, supplementary groups, open file descriptors, root directory, working directory – not setting close-on-exec on sensitive file descriptors

86 87

9 Vulnerability Assessment and Secure Coding Practices

Not Dropping Privilege: chroot Insecure Permissions

• chroot changes the root directory for the •Set umask when using mkstemp or fopen process, files outside cannot be accessed – File permissions need to be secure from • Only root can use chroot creation to destruction • chdir needs to follow chroot, otherwise • Don’t write sensitive information into relative pathnames are not restricted insecure locations (directories need to • Need to recreate all support files used by have restricted permission to prevent program in new root: /etc, libraries, … replacing files) Makes chroot difficult to use. • Executables, libraries, configuration, data and log files need to be write protected

88 89

Insecure Permissions Trusted Directory • A trusted directory is one where only trusted • If a file controls what can be run as a users can update the contents of anything in the privileged, users that can update the file directory or any of its ancestors all the way to the root are equivalent to the privileged user • A trusted path needs to check all components of File should be: the path including symbolic links referents for – Owned by privileged user, or trust – Owned by administrative account • A trusted path is immune to TOCTOU attacks from untrusted users •No login •This is extremely tricky to get right! • Never executes anything, just owns files • safefile library • DBMS accounts should be granted minimal – http://www.cs.wisc.edu/mist/safefile privileges for their task – Determines trust based on trusted users & groups

90 91

Directory Traversal Directory Traversal Mitigation

• Description •Use realpath or something similar to – When user data is used to create a pathname to a file create canonical pathnames system object that is supposed to be restricted to a particular set of paths or path prefixes, but which the • Use the canonical pathname when user can circumvent comparing filenames or prefixes • General causes • If using prefix matching to check if a path is – Not checking for path components that are empty, "." or ".." within directory , also check that the – Not creating the canonical form of the pathname (there next character in the path is the directory is an infinite number of distinct strings for the same separator or '\0' object) – Not accounting for symbolic links

92 93

10 Vulnerability Assessment and Secure Coding Practices

Directory Traversal Successful Directory (Path Injection) Traversal Attack • User supplied data is used to create a path, and program security requires but does not verify that the path is in a particular subtree of 1. Users requests File="....//etc/passwd" the directory structure, allowing unintended access to files and directories that can compromise the security of the system. – Usually + "/" + Directory Movement ../ up String path = request.getParameter("file"); path = "/safedir/" + path; ./ or empty string none // remove ../'s to prevent escaping out of /safedir

/ down Replace(path, "../", ""); • Mitigations File f = new File(path); – Validate final path is in required directory using canonical paths f.delete(); (realpath) 2. Server deletes /etc/passwd – Do not allow above patterns to appear in user supplied part (if symbolic links exists in the safe directory tree, they can be used to Before Replace path = "/safedir/….//etc/passwd" escape) After Replace path = "/safedir/../etc/passwd" – Use chroot or other OS mechanisms Moral: Don't try to fix user input, verify and reject instead

94 95

Mitigated Directory Traversal Command Line

1. Users requests file=“../etc/passwd” • Description – Convention is that argv[0] is the path to the executable

String file = request.getParameter(“file”); – Shells enforce this behavior, but it can be set if (file.length() == 0) { throw new PathTraversalException(file + " is null"); to anything if you control the parent process } File prefix = new File(new File("/safedir").getCanonicalPath()); • General causes File path = new File(prefix, file); if(!path.getAbsolutePath().equals(path.getCanonicalPath())){ –Using argv[0] as a path to other files throw new PathTraversalException(path + " is invalid"); } such as configuration data path.getAbsolutePath().delete(); – Process needs to be setuid or setgid to be a 2. Throws error /safedir/../etc/passwd is invalid useful attack

96 97

Command Line Environment

Want to run: –l foo • List of (name, value) string pairs • Available to program to read execlp(ʺ/bin/lsʺ, executable name • Used by programs, libraries and runtime ʺ/bin/ls/bin/evilʺ, ʺ, argv[0]:argv[0]: but usually could the be file anything name environment to affect program behavior ʺ-lʺ, argv[1] • Mitigations: ʺfooʺ, argv[2] – Clean environment to just safe names & values NULL); end of arguments – Don’t assume the length of strings – Avoid PATH, LD_LIBRARY_PATH, and other So,Some now, programs we are usinguse this the to config find filetheir from config the files:attacker: variables that are directory lists used to look /bin/evil.config/bin/ls.config for execs and libs

98 99

11 Vulnerability Assessment and Secure Coding Practices

Injection Attacks

• Description – A string constructed with user input, that is then interpreted by another function, where the string is not parsed as expected • Command injection (in a shell) Injection Attacks • string attacks (in printf/scanf) • SQL injection • Cross-site scripting or XSS (in HTML) • General causes – Allowing metacharacters – Not properly neutralizing user data if metacharacters are allowed

100 101

SQL Injections SQL Injections: attacks and mitigations • User supplied values used in SQL • Dynamically generated SQL without command must be validated, quoted, or validation or quoting is vulnerable prepared statements must be used $u = " '; drop table t --"; • Signs of vulnerability $sth = $dbh->do("select * from t where u = '$u'"); – Uses a database mgmt system (DBMS) Database sees two statements: – Creates SQL statements at run-time select * from t where u = ' '; drop table t --' – Inserts user supplied data directly into •Use prepared statements to mitigate statement without validation $sth = $dbh->do("select * from t where u = ?", $u); – SQL statement template and value sent to database – No mismatch between intention and use

102 103

Successful SQL Injection Attack Mitigated SQL Injection Attack

2. DB Queried SELECT * FROM members SELECT * FROM members WHERE u = ?1 AND p = ?2 WHERE u='admin' AND p='' OR 'x'='x' ?1 = "admin" ?2 = "' OR 'x'='x" 3. Returns all row of table members 2. DB Queried 3. Returns null set

user="admin"; pwd="' OR 'x'='x" 1. User sends malicious data user="admin"; pwd="'OR 'x'='x" 1. User sends malicious data boolean Login(String user, String pwd) { boolean Login(String user, String pwd) { boolean loggedIn = false; boolean loggedIn = false; conn = pool.getConnection( ); conn = pool.getConnection( ); PreparedStatement pstmt = conn.prepareStatement( stmt = conn.createStatement(); "SELECT * FROM members WHERE u = ? AND p = ?"); rs = stmt.executeQuery("SELECT * FROM members" pstmt.setString( 1, user); + "WHERE u='" + user pstmt.setString( 2, pwd); + "' AND p='" + pwd + "'"); ResultSet results = pstmt.executeQuery( ); if (rs.next()) if (rs.next()) loggedIn = true; loggedIn = true; } } 4. System grants access Login() returns true 4. System does not grant access Login() returns false 104 105

12 Vulnerability Assessment and Secure Coding Practices

Command Injections

• User supplied data used to create a string that is the interpreted by command shell such as /bin/sh • Signs of vulnerability – Use of popen, or system – exec of a shell such as sh, or csh – Argument injections, allowing arguments to begin with "-" can be dangerous http://xkcd.com/327 • Usually done to another program – That has no C API – Out of laziness

106 107

Command Injection Mitigations Command Argument Injections • Check user input for metacharacters • A string formed from user supplied input • Neutralize those that can’t be eliminated or that is used as a command line argument rejected to another executable – replace single quotes with the four characters, '\'', • Does not attack shell, attacks command line of and enclose each argument in single quotes program started by shell •Usefork, drop privileges and exec for more control • Need to fully understand command line • Avoid if at all possible interface • Use C API if possible • If value should not be an option – Make sure it doesn't start with a - – Place after an argument of -- if supported

108 109

Command Argument Perl Command Injection Injection Example Danger Signs • Example • open(F, $filename) snprintf(userMsg, sSize, "/bin/mail -s hi %s", email); M = popen(userMsg, "w"); – Filename is a tiny language besides opening fputs(userMsg, M); • Open files in various modes pclose(M); • Can start programs • If email is -I , turns on interactive mode … • dup file descriptors • … so can run arbitrary code by if userMsg –If $filename is " -rf /|", you probably includes: ~!cmd won’t like the result – Use separate mode version of open to eliminate vulnerability

110 111

13 Vulnerability Assessment and Secure Coding Practices

Perl Command Injection Perl Command Injection Danger Signs Examples • Vulnerable to shell interpretation • open(CMD, "|/bin/mail -s $sub $to"); open(C, "$cmd|") open(C, "-|", $cmd) –Bad if $to is "[email protected]; rm -rf /" open(C, "|$cmd") open(C, "|-", $cmd) • open(CMD, “|/bin/mail -s '$sub''$to'"); `$cmd` qx/$cmd/ –Bad if $to is "[email protected]'; rm -rf /'" system($cmd) • ($qSub = $sub) =~ s/'/'\\''/g; • Safe from shell interpretation ($qTo = $to) =~ s/'/'\\''/g; open(C, "-|", @argList) open(CMD, "|/bin/mail -s '$qSub' '$qTo'"); open(C, "|-", @cmdList) – Safe from command injection system(@argList) • open(cmd, "|-", "/bin/mail", "-s", $sub, $to); – Safe and simpler: use this whenever possible.

112 113

Eval Injections Rubi Command Injection Danger Signs • A string formed from user supplied input that is used as an argument that is interpreted by the language running the code – Functions prone to injection attacks: • Usually allowed in scripting languages such as •Kernel.system(os command) Perl, sh and SQL •Kernel.exec(os command) •In Perl eval($s) and s/$pat/$replace/ee •`os command` # back tick operator – $s and $replace are evaluated as perl code •%x[os command] •eval(ruby code)

114 115

Python Command Injection Successful OS Injection Attack

Danger Signs 1. User sends malicious data ="x.com;rm –rf /*" • Functions prone to injection attacks: – exec() # dynamic execution of Python code – eval() # returns the value of an expression or 2. Application uses to get DNS records # code object String rDomainName(String hostname) { … – os.system() # execute a command in a subshell String cmd = "/usr/bin/nslookup " + hostname; os.popen() Process p = Runtime.getRuntime().exec(cmd); – # open a pipe to/from a command … – execfile() # reads & executes Python script from # a file. 3. System executes nslookup x.com;rm –rf /* – input() # equivalent to eval(raw_input()) – compile() # compile the source string into a code 4. All files possible are deleted # object that can be executed

116 117

14 Vulnerability Assessment and Secure Coding Practices

Mitigated OS Injection Attack Format String Injections

1. User sends malicious data • User supplied data used to create format strings hostname="x.com;rm –rf /*" in scanf or printf • printf(userData) is insecure – %n can be used to write memory 2. Application uses nslookup only if input validates String rDomainName(String hostname) { – large field width values can be used to create a denial … of service attack if (hostname.matches("[A-Za-z][A-Za-z0-9.-]*")) { printf("%s", userData) String cmd = "/usr/bin/nslookup " + hostname); – Safe to use or Process p = Runtime.getRuntime().exec(cmd); fputs(userData, stdout) } else { System.out.println(“Invalid name”); • scanf(userData, …) allows arbitrary writes to … memory pointed to by stack values • ISO/IEC 24731 does not allow %n 3. System returns error "Invalid host name"

118 121

Code Injection Code Injection Vulnerability 1. logfile – name's value is user controlled name = John Smith •Cause name = ');import os;os.system('evilprog');#

– Program generates source code from template Read logfile 2. Perl log processing code – uses Python to do real work – User supplied data is injected in template %data = ReadLogFile('logfile'); PH = open("|/usr/bin/python"); – Failure to neutralized user supplied data print PH "import LogIt\n";w • Proper quoting or escaping while (($k, $v) = (each %data)) { if ($k eq 'name') { • Only allowing expected data Start Python, print PH "LogIt.Name('$v')"; } program sent – Source code compiled and executed on stdin

• Very dangerous – high consequences for 3. Python source executed – 2nd LogIt executes arbitrary code getting it wrong: arbitrary code execution import LogIt; LogIt.Name('John Smith') LogIt.Name('');import os;os.system('evilprog');#')

122 123

Code Injection Mitigated 1. logfile – name's value is user controlled name = John Smith name = ');import os;os.system('evilprog');#

2. Perl log processing code – use QuotePyString to safely create string literal %data = ReadLogFile('logfile'); sub QuotePyString { PH = open("|/usr/bin/python"); my $s = shift; print PH "import LogIt\n";w $s =~ s/\\/\\\\/g; # \ Î \\ Safe DNS while (($k, $v) = (each %data)) { if ($k eq 'name') { $s =~ s/\n/\\n/g; # Î \n $q = QuotePyString($v); return "'$s'"; # add quotes print PH "LogIt.Name($q)"; } }

3. Python source executed – 2nd LogIt is now safe import LogIt; LogIt.Name('John Smith') LogIt.Name('\');import os;os.system(\'evilprog\');#')

124 125

15 Vulnerability Assessment and Secure Coding Practices

char *safe_reverse_lookup(struct in_addr *ip) Reverse DNS Lookup { struct hostent *hp; do reverse lookup Problem: A server trying to determine of the client is from an appropriate domain. if ((hp=gethostbyaddr(ip,sizeof *ip AF_INET)) == NULL) return NULL; save name Common solution: Look at the IP address for the other end of the socket, then do a reverse DNS lookup char *name = strdup(hp->h_name); do forward lookup (RARP) on that address. if ((hp = gethostbyname(name)) == NULL) { Risk: The RARP query goes to the server run by the free(name); return NULL; owner of the IP address, and they can respond with } anything they want. check if IP address matches original char **p = hp->h_addr_list; Solution: After doing the RARP lookup, a DNS lookup while (*p) { (ARP) on the name returned and see if it matches the if (!memcmp(ip, *p, hp->h_length)) return name; original IP address. ++p; } (All this assumes that you trust DNS in the first place!) free(name); return NULL; } 126 127

Cross Site Scripting (XSS)

• Injection into an HTML page – HTML tags – JavaScript code • Reflected (from URL) or persistent (stored from prior attacker visit) Web Attacks • Web application fails to neutralize special characters in user supplied data • Mitigate by preventing or encoding/escaping special characters • Special characters and encoding depends on context –HTML text – HTML tag attribute –HTML URL

128 129

Reflected Cross Site Scripting Reflected Cross Site Scripting (XSS) (XSS)3 . Generated HTML displayed by browser 3. Generated HTML displayed by browser ••• ••• You searched for: You searched for: widget ••• ••• 1. Browser sends request to web server 1. Browser sends request to web server http://example.com?q=widget http://example.com?q=

2. Web server code handles request 2. Web server code handles request ••• ••• String query = request.getParameter("q"); String query = request.getParameter("q"); if (query != null) { if (query != null) { out.writeln("You searched for:\n" + query); out.writeln("You searched for:\n" + query); } } ••• •••

130 131

16 Vulnerability Assessment and Secure Coding Practices

XSS Mitigation Cross Site Request Forgery (CSRF) 3. Generated HTML displayed by browser • CSRF is when loading a web pages causes a malicious ••• request to another server Invalid query ••• • Requests made using or forms (also transmits any cookies for the site, such as session or auth cookies) 1. Browser sends request to web server – http://bank.com/xfer?amt=1000&toAcct=joe HTTP GET method http://example.com?q=

HTTP POST method 2. Web server code correctly handles request •••
String query = request.getParameter("q"); if (query != null) { • Web application fails to distinguish between a user if (query.matches("^\\w*$")) { initiated request and an attack out.writeln("You searched for:\n" + query); } else { • Mitigate by using a large random nonce out.writeln("Invalid query"); } } ••• 132 133

Cross Site Request Forgery (CSRF) Successful CSRF Attack 1. User visits evil.com 1. User loads bad page from web server http://evil.com – XSS – Fake server 2. evil.com returns HTML – Bad guy’s server – Compromised server ••• 2. Web browser makes a request to the victim web server directed by bad page ••• – Tags such as 3. Browser sends attack http://bank.com/xfer?amt=1000&toAcct=evil37 – JavaScript 3. Victim web server processes request and assumes 4. bank.com server code handles request ••• request from browser is valid String id = response.getCookie(“user”); – Session IDs in cookies are automatically sent along userAcct = GetAcct(id); If (userAcct != null) { SSL does not – channel security is not an issue here deposits.xfer(userAcct, toAcct, amount); }

134 135

CSRF Mitigation Session Hijacking 1. User visits evil.com Very unlikely attacker will 2. evil.com returns HTML • Session IDs identify a user’s session in provide correct web applications. nonce 3. Browser sends attack • Obtaining the session ID allows 4. bank.com server code correctly handles request ••• impersonation String nonce = (String)session.getAttribute(“nonce”); String id = response.getCookie(“user”); • Attack vectors: if (Utils.isEmpty(nonce) – Intercept the traffic that contains the ID value || !nonce.equals(getParameter(“nonce”) { Login(); // no nonce or bad nonce, force login – Guess a valid ID value (weak randomness) return; // do NOT perform request } // nonce added to all URLs and forms – Discover other logic flaws in the sessions userAcct = GetAcct(id); handling process if (userAcct != null) { deposits.xfer(userAcct, toAcct, amount);

} 136 137

17 Vulnerability Assessment and Secure Coding Practices

Good Session ID Properties Session Hijacking Mitigation

• Create new session id after – Authentication – switching encryption on – other attributes indicate a host change (IP address change) • Encrypt to prevent obtaining session ID through http://xkcd.com/221 eavesdropping • Hard to guess •Expire IDs after short inactivity to limit exposure of – Large entropy (big random number) guessing or reuse of illicitly obtained IDs • Entropy should be large to prevent guessing – No patterns in IDs issued • Invalidate session IDs on logout and provide logout • No reuse functionality

138 139

Session Hijacking Example Successful Hijacking Attack

1. An insecure web application accepts and 1. Tricks user to visit reuses a session ID supplied to a login page. http://bank.com/login;JSESSIONID=123 2. Attacker tricked user visits the web site using attacker chosen session ID 2. User Logs In http://bank.com/login;JSESSIONID=123 3. User logs in to the application 4. Application creates a session using attacker 4. Impersonates the user http://bank.com/home supplied session ID to identify the user Cookie: JSESSIONID=123 3. Creates the 5. The attacker uses session ID to impersonate session if(HttpServletRequest.getRequestedSessionId() == null) HTTP/1.1 200 OK the user { Set-Cookie: HttpServletRequest.getSession(true); JSESSIONID=123 } ...

140 141

Mitigated Hijacking Attack Open Redirect (AKA: URL Redirection to Untrusted Site, and Unsafe URL Redirection) • Description 1. Tricks user to visit – Web app redirects user to malicious site chosen http://bank.com/login;JSESSIONID=123 by attacker • URL parameter (reflected) 2. User Logs In http://bank.com/redir?url=http://evil.com http://bank.com/login;JSESSIONID=123 • Previously stored in a database (persistent) – User may think they are still at safe site

4. Impersonates the user – Web app uses user supplied data in redirect URL http://bank.com/home • Mitigations Cookie: JSESSIONID=123 3. Creates the – Use white list of tokens that map to acceptable session redirect URLs HTTP/1.1 200 OK HttpServletRequest.invalidate(); – Present URL and require explicit click to navigate Set-Cookie: HttpServletRequest.getSession(true); to user supplied URLs JSESSIONID=XXX ...

142 143

18 Vulnerability Assessment and Secure Coding Practices

Open Redirect Example Successful Open Redirect Attack 1. User receives phishing e-mail 1. User receives phishing e-mail with URL Dear bank.com costumer, http://www.bank.com/redir?url=http://evil.com Because of unusual number of invalid login attempts... 2. User inspects URL, finds hostname valid for their bank Sign in to verify

3. User clicks on URL 2. Opens http://bank.com/redir?url=http://evil.com 4. Bank’s web server returns a HTTP redirect String url = request.getParameter("url"); if (url != null) { response to malicious site response.sendRedirect( url ); 5. User’s web browser loads the malicious site } that looks identical to the legitimate one 3. Web server redirects Location: http://evil.com 6. Attacker harvests user’s credentials or other information 4. Browser requests http://evil.com

Welcome to bank.com

5. Browser displays forgery Please enter your PIN ID:

144 •••145

Open Redirect Mitigation

1. User receives phishing e-mail Dear bank.com costumer, •••

2. Opens http://bank.com/redir?url=http://evil.com boolean isValidRedirect(String url) { List validUrls = new ArrayList(); validUrls.add("index"); Generally Bad Things validUrls.add("login"); return (url != null && validUrls.contains(url)); } ••• if (!isValidRedirect(url)){ response.sendError(response.SC_NOT_FOUND, "Invalid URL"); •••

3. bank.com server code correctly handles request 404 Invalid URL

146 147

General Software Engineering Denial of Service

• Don’t trust user data • Description – You don’t know where that data has been – Programs becoming unresponsive due to over • Don’t trust your own client software either consumption of a limited resource or unexpected – It may have been modified, so always revalidate data at the termination. server. • General causes • Don’t trust your operational configuration either – If your program can for unsafe conditions, do so and quit – Not releasing resources • Don’t trust your own code either – Crash causing bugs –Program defensively with checks in high and low level functions – Infinite loops or data causing algorithmic complexity to • KISS - Keep it simple, stupid consume excessive resources – Complexity kills security, its hard enough assessing simple code – Failure to limit data sizes – Failure to limit wait times – Leaks of scarce resources (memory, file descriptors)

148 149

19 Vulnerability Assessment and Secure Coding Practices

Information Leaks Information Leaks

• Description • General causes (cont.) – Inadvertent divulgence of sensitive information – Timing attacks where the duration of the • General causes operation depends on secret information – Reusing buffers without completely erasing – Lack of encryption when using observable – Providing extraneous information that an channels adversary may not be able to otherwise obtain – Allowing secrets on devices where they can't • Generally occurs in error messages be erased such as swap space (mlock • Give as few details as possible prevents this) or backups • Log full details to a database and return id to user, so admin can look up details if needed

150 151

General Software Engineering Let the Compiler Help

• Don’t trust user data • Turn on compiler warnings and fix problems – You don’t know where that data has been • Easy to do on new code • Don’t trust your own client software either • Time consuming, but useful on old code – It may have been modified, so always revalidate data at the server. • Use lint, multiple compilers • Don’t trust your own code either • -Wall is not enough! – Program defensively with checks in high and low level gcc: -Wall, -W, -O2, -Werror, -Wshadow, functions -Wpointer-arith, -Wconversion, -Wcast-qual, • KISS - Keep it simple, stupid -Wwrite-strings, -Wunreachable-code and many – Complexity kills security, its hard enough assessing more simple code – Many useful warning including security related warnings such as format strings and integers

152 153

Let the Perl Compiler Help Perl Taint Mode

• -w - produce warning about suspect code • Taint mode (-T) prevents data from untrusted and runtime events sources from being used in dangerous ways • Untrusted sources • use strict - fail if compile time – Data read from a file descriptor • use Fatal - cause built-in function to raise – Command line arguments an exception on error instead of returning – Environment – User controlled fields in password file an error code – Directory entries • use diagnostics - better diagnostic – Link referents messages – Shared memory – Network messages • Environment sanitizing required for exec – IFS PATH CDPATH ENV BASH_ENV 154 155

20 Vulnerability Assessment and Secure Coding Practices

Secure Coding Practices for Middleware

Elisa Heymann Barton P. Miller James A. Kupsch Questions? [email protected] [email protected]

http://www.cs.wisc.edu/mist/ http://www.cs.wisc.edu/mist http://www.cs.wisc.edu/mist/papers/VAshort.pdf

156 157

21