Скачать презентацию Software without Security Holes Prabhaker Mateti 1 Скачать презентацию Software without Security Holes Prabhaker Mateti 1

7b5f8c48809254b11a11c5ffdbfbd329.ppt

  • Количество слайдов: 50

Software without Security Holes Prabhaker Mateti 1 Software without Security Holes Prabhaker Mateti 1

Top Ten Security Holes In June 2000, GSA Federal Chief Information Officers Council listed Top Ten Security Holes In June 2000, GSA Federal Chief Information Officers Council listed the "The Ten Most Critical Internet Security Threats" 1. BIND weaknesses: nxt, qinv and in. named allow immediate root compromise. 2. Vulnerable CGI programs and application extensions (e. g. , Cold. Fusion) installed on web servers. 3. Remote Procedure Call (RPC) weaknesses in rpc. ttdbserverd (Tool. Talk), rpc. cmsd (Calendar Manager), and rpc. statd that allow immediate root compromise 4. Remote Data Services (RDS) security hole in the Microsoft's web server named IIS. 5. Sendmail buffer overflow weaknesses, pipe attacks and MIMEbo, that allow immediate root compromise. 6. Buffer overflows in sadmind (remote administration access to Solaris systems) and mountd (controls and arbitrates access to NFS mounts on UNIX hosts) permit root compromise. 7. Global file sharing and inappropriate information sharing via NFS and Windows NT ports 135 ->139 (445 in Windows 2000) or UNIX NFS exports on port 2049. Also Appletalk over IP with Macintosh file sharing enabled. 8. User IDs, especially root/administrator with no passwords or weak passwords. 9. IMAP and POP buffer overflow vulnerabilities or incorrect configuration. 10. Default SNMP community strings set to ‘public’ and ‘private. ’ 2

Robust Programs l l Crash proof, and hang-proof no matter what the inputs are. Robust Programs l l Crash proof, and hang-proof no matter what the inputs are. Crash is unexpected termination. A hang is unexpected non-termination. Two classes of being hung are: infinite looping, and waiting for an event that will not occur. Infinite looping consumes heavily the CPU time. Waiting for a non-occurring event consumes almost no resources. Note that infinite recursion will lead to a crash via resource exhaustion. 3

Correct Programs Specifications, expressed in a language as formal as the programming languages l Correct Programs Specifications, expressed in a language as formal as the programming languages l Implementation “satisfies” the specification. l “Satisfies” is verified not by testing, but by design and proof. l Practical: pre- and post-conditions l 4

Secure Programs Correct and Robust l Importance of the program l l Costs of Secure Programs Correct and Robust l Importance of the program l l Costs of failure 5

Design Principles for Secure Programs l l l l l Laws of Large Programs Design Principles for Secure Programs l l l l l Laws of Large Programs Correctness and Robustness Economy of Mechanism Fail-open or -closed? Security compartments Trusting untrustworthy channels Proper defaults Error Handling and Reporting Assertions and Exit Points 6

Construction Principles for Secure Programs [Not listed in order of importance. ] Do not Construction Principles for Secure Programs [Not listed in order of importance. ] Do not assume that inputs are valid. E. g. , 1. a. b. c. d. 2. if an argument should be a positive integer in the range of 2 to 7, verify that. If an argument should be a non-empty string of letters not exceeding 13 characters in length, verify that. Check interactive input to be sure it contains only "good" characters. Consider how such input will be parsed when substituted. Check arguments passed in environment variables. Check return code of all system call parameters and system calls. System calls should verify their arguments, but unfortunately most OS calls do not for fear of becoming inefficient, so you must. Fortunately, all system calls return a success or failure code. Unfortunately, only a few programs verify these result codes. 7

Construction Principles for Secure Programs Buffer Overflow. 3. a. b. Do bounds checking on Construction Principles for Secure Programs Buffer Overflow. 3. a. b. Do bounds checking on every variable before the contents are copied to a local buffer. Avoid routines that fail to check buffer boundaries when manipulating strings, particularly: sprintf(), fscanf(), vsprintf(), realpath(), getopt(), getpass(), streadd(), strecpy(), strtrns(), gets(), strcpy(), and strcat() Always use full pathnames for any files and directories. The current directory assumed by your program may not be where it is at. 4. a. b. c. d. e. f. Explicitly change directories (chdir()) to an appropriate directory at program start. If creating a new file, use O_EXCL and O_CREAT flags to assure that the file does not already exist. Do not create files in world-writable directories. Use lstat() to make sure a file is not a link, if appropriate. Set limit values to disable creation of a core file if the program fails. If using temporary files, consider using tmpfile() or mktemp() system calls to create them (although most mktemp() library calls have race conditions). 8

Construction Principles for Secure Programs 5. 6. 7. 8. Logging Events. Do log relevant Construction Principles for Secure Programs 5. 6. 7. 8. Logging Events. Do log relevant information, including date, time, uid and effective uid, gid and effective gid, terminal information, pid, command-line arguments, errors, and originating host. Make sure that the log files themselves remain bounded in size. Make the program's critical portion as short and simple as possible. Be aware of race conditions, deadlock conditions and sequencing conditions. Do not require clear-text authentication information. 9

Construction Principles for Secure Programs 9. 10. 11. 12. 13. Use session encryption to Construction Principles for Secure Programs 9. 10. 11. 12. 13. Use session encryption to avoid session hijacking and hide authentication information. Never use system() and popen() system calls Avoid creating setuid or setgid shell scripts Do not make assumptions about port numbers, use getservbyname() instead. Do not assume connections from well-known ports are legitimate or trustworthy. Do not assume the source IP address is legitimate. Place timeouts and load level limits on incoming network-oriented read request. Place timeouts on outgoing network-oriented write requests. Robust Compilation and Libraries. Use tools such as lint, and splint. Have internal consistency-checking code. Use your compiler wisely. With gcc, use -Wall -ansi -pedantic flags. Use safe libraries. 10

Construction Principles for Secure Programs 14. 15. 16. Have code reviewed by other people. Construction Principles for Secure Programs 14. 15. 16. Have code reviewed by other people. E. g. , commercial products such as 3 Com's Core. Builder and Super. Stack II hubs were revealed to have "secret" backdoor passwords. Test thoroughly. Test the software using the same methods that crackers do: Try to overflow every buffer in the package, Try to abuse command line options, Try to create every race condition conceivable. Have others besides the designers and implementers test the code. Be aware of test coverage; gcc -pg a causes the program to produce a bb. out file that is helpful in determining how effective your tests are at covering all branches of the code. Use formal specifications. At a minimum, develop pre- and post -conditions in carefully written English. 11

Programs that Must be Secure The OS kernel. l All setuid and setgid programs. Programs that Must be Secure The OS kernel. l All setuid and setgid programs. l All daemons that accept network connections. l 12

Writing Safe setuid Programs l Simson Garfinkel, Gene Spafford Practical Unix and Internet Security, Writing Safe setuid Programs l Simson Garfinkel, Gene Spafford Practical Unix and Internet Security, 2 nd edition (April 1996), O'Reilly & Associates; ISBN: 1565921488. Errata: http: //www. oreilly. com/catalog/puis/errata/ Chapter 23: Writing Secure SUID and Network Programs. 13

Practical Advice on Writing Pre- Post-Conditions Signatures l Procedures and Functions that Alter Globals Practical Advice on Writing Pre- Post-Conditions Signatures l Procedures and Functions that Alter Globals l Robustness Tests l Some Useful Predicates l 14

Buffer Overflow Over the Years l l l 1988: Morris worm exploits buffer overflows Buffer Overflow Over the Years l l l 1988: Morris worm exploits buffer overflows in fingerd to infect 6, 000 servers 2001: Code Red exploits buffer overflows in Microsoft IIS to infect 250, 000 servers 2002: CERT® Advisory CA-2002 -04 Buffer Overflow in Microsoft Internet Explorer (Last revised: April 2, 2002) 2002: Open UNIX 8. 0. 0 Unix. Ware 7. 1. 1 : Buffer overflow in lib. X 11 with -xrm (2002 April 11) 2002: M-019: Multiple Vendor CDE dtspcd Process Buffer Overflow (17 April 2002) 15

Buffer Overflow Single largest cause of vulnerabilities in CERT advisories l Buffer overflow threatens Buffer Overflow Single largest cause of vulnerabilities in CERT advisories l Buffer overflow threatens Internet --WSJ(1/30/01) l 16

Why aren’t we better off than we were 13 years ago? Ignorance l C Why aren’t we better off than we were 13 years ago? Ignorance l C is difficult to use securely l l Unsafe functions l Confusing APIs Even security aware programmers make mistakes. l Security Knowledge has not been codified into the development process l 17

Automated Tools for Secure Programs l Run-time solutions l l l #include <assert. h> Automated Tools for Secure Programs l Run-time solutions l l l #include Stack. Guard[USENIX 1997], gcc bounds-checking, libsafe[USENIX 2000] Performance penalty Turns buffer overflow into a Do. S attack Compile-time solutions - static analysis l l l No run-time performance penalty Checks properties of all possible executions www. splint. org 18

<assert. h> l The <assert. h> header defines the assert() macro: void assert(int expression); l The header defines the assert() macro: void assert(int expression); l The assert() macro inserts diagnostics into programs. When it is executed, if expression is false (that is, equals to 0), assert() writes information about the particular call that failed (including the text of the argument, the name of the source file and the source file line number - the latter are respectively the values of the preprocessing macros __FILE__ and __LINE__) on stderr and calls abort(). l assert() refers to the macro NDEBUG which is not defined in the header. If NDEBUG is defined as a macro name before the inclusion of this header, the assert() macro is defined simply as: #define assert(ignore)((void) 0) otherwise the macro behaves as described in assert(). 19

Compilers v. Verifiers all Bugs Detected Formal Verifiers int L sp Compilers none Low Compilers v. Verifiers all Bugs Detected Formal Verifiers int L sp Compilers none Low Unfathomable Effort Required 20

SPLINT l Tool that can be used by typical programmers as part of the SPLINT l Tool that can be used by typical programmers as part of the development process l l Tool that can be used to check legacy code l l Handles typical C programs Encourage a proactive security methodology l l Fast, Easy to Use Document key assumptions www. splint. org 21

sp. Lint l l l Lightweight static analysis tool [FSE’ 94, PLDI’ 96] – sp. Lint l l l Lightweight static analysis tool [FSE’ 94, PLDI’ 96] – “quick and dirty” Simple dataflow analyses Mathematically “Unsound and Incomplete” Several thousand users…perhaps ¼ adding annotations to code: gradual learning curve Detects inconsistencies between code and specifications Examples: memory management (leaks, dead references), null dereferences, information hiding, undocumented modifications, etc. 22

SPLINT l Document assumptions about buffer sizes l l l Semantic comments Provide annotated SPLINT l Document assumptions about buffer sizes l l l Semantic comments Provide annotated standard library Allow user's to annotate their code Find inconsistencies between code and assumptions Make compromises to get useful checking l l l Use simplifying assumptions to improve efficiency Use heuristics to analyze common loop idioms Accept some false positives and false negatives (unsound and incomplete analysis) 23

Approach l Programmers add “annotations” l Simple and precise. l Describe programmers intent: l Approach l Programmers add “annotations” l Simple and precise. l Describe programmers intent: l Types, memory management, data hiding, aliasing, modification, null-ity, buffer sizes, security, etc. l SPLINT detects inconsistencies between annotations and code. l Fast dataflow analyses. 24

Overview of checking l Intraprocedural l l Expressions generate constraints l l l But Overview of checking l Intraprocedural l l Expressions generate constraints l l l But use annotations on called procedures and global variables to check calls, entry, exit points C semantics, annotations Axiomatic semantics propagates constraints Simplifying rules, e. g. , max. Read(str + i) ==> max. Read(str) - i l Produce warnings for unresolved constraints 25

Loop Heuristics Recognize common loop idioms l Use heuristics to guess number of iterations Loop Heuristics Recognize common loop idioms l Use heuristics to guess number of iterations l Analyze first and last iterations l Example: for (init; *buf; buf++) l l Assume max. Read(buf) iterations l Model first and last iterations 26

SPLINT Annotations l l l requires are known as pre-conditions ensures are known as SPLINT Annotations l l l requires are known as pre-conditions ensures are known as post-conditions max. Set() highest index that can be safely written to max. Read() highest index that can be safely read A declaration such as char buffer[100]; yields ensures max. Set(buffer) == 99 27

SPLINT Annotation Example char *strncat (char *d, char *s, size_t n) /*@ requires max. SPLINT Annotation Example char *strncat (char *d, char *s, size_t n) /*@ requires max. Set(d) >= max. Read(s) + n @*/ 28

SPLINT Annotation Example char *strcpy (char *s 1, const char *s 2) /*@requires max. SPLINT Annotation Example char *strcpy (char *s 1, const char *s 2) /*@requires max. Set(s 1) >= max. Read(s 2)@*/ /*@ensures max. Read(s 1) == max. Read(s 2) / result == s 1 @*/; 29

SPLINT generates preconditions l strcpy(ls_short, entry->arg[0]); strcpy requires max. Set(s 1) >= max. Read(s SPLINT generates preconditions l strcpy(ls_short, entry->arg[0]); strcpy requires max. Set(s 1) >= max. Read(s 2) l substituting the actual parameters: max. Set (ls_short @ ftpd. c: 1112: 14) >= l max. Read (entry->arg[0] @ ftpd. c: 1112: 23) 30

SPLINT constraints l l 1 t++; 2 *t = ‘x’; 3 t++; leads to SPLINT constraints l l 1 t++; 2 *t = ‘x’; 3 t++; leads to the constraints: l l l requires max. Set(t @ 1: 1) >= 1, ensures max. Read(t @ 3: 4) >= -1 and ensures (t @ 3: 4) = (t @ 1: 1) + 2. 31

Detecting Buffer Overflows l More expressive annotations l l l e. g. , max. Detecting Buffer Overflows l More expressive annotations l l l e. g. , max. Set is the highest index that can safely be written to Checking uses axiomatic semantics with simplification rules Heuristics for analyzing common loop idioms Detected known and unknown vulnerabilities in wu-ftpd and BIND Paper (with David Larochelle) in USENIX Security 2001 32

Security. Focus. com Example char *strncat(char *s 1, char *s 2, size_t n) /*@ Security. Focus. com Example char *strncat(char *s 1, char *s 2, size_t n) /*@ requires max. Set(s 1) >= max. Read(s 1) + n @*/ void func(char *str){ char buffer[256]; strncat(buffer, str, sizeof(buffer) - 1); return; } uninitialized array Source: Secure Programming working document, Security. Focus. com 33

Warning Reported by SPLINT char * strncat (char *s 1, char *s 2, size_t Warning Reported by SPLINT char * strncat (char *s 1, char *s 2, size_t n) /*@ requires max. Set(s 1) >= max. Read(s 1) + n @*/ char buffer[256]; strncat(buffer, str, sizeof(buffer) - 1); strncat. c: 4: 21: Possible out-of-bounds store: strncat(buffer, str, sizeof((buffer)) - 1); Unable to resolve constraint: requires max. Read (buffer @ strncat. c: 4: 29) <= 0 needed to satisfy precondition: requires max. Set (buffer @ strncat. c: 4: 29) >= max. Read (buffer @ strncat. c: 4: 29) + 255 derived from strncat precondition: requires max. Set () >= max. Read () + 34

I/O Streams Challenge Many properties can be described in terms of state attributes l I/O Streams Challenge Many properties can be described in terms of state attributes l A file is open or closed l fopen: returns an open file l fclose: open closed l fgets, etc. require open files l Reading/writing – must reset between certain operations 35

Defining Openness attribute openness context reference FILE * oneof closed, open annotations open ==> Defining Openness attribute openness context reference FILE * oneof closed, open annotations open ==> open closed ==> closed transfers open as closed ==> error Object cannot be open closed as open ==> error on one path, closed on merge open + closed ==> error another losereference open ==> error "file not closed" defaults Cannot abandon FILE reference ==> open in open state end 36

Specifying I/O Functions /*@ open @*/ FILE *fopen (const char *filename, const char *mode); Specifying I/O Functions /*@ open @*/ FILE *fopen (const char *filename, const char *mode); int fclose (/*@[email protected]*/ FILE *stream) /*@ ensures closed stream @*/ ; char *fgets (char *s, int n, /*@ open @*/ FILE *stream); 37

Reading, ‘Rithmetic attribute rwness context reference FILE * oneof rwnone, rwread, rwwrite, rweither annotations Reading, ‘Rithmetic attribute rwness context reference FILE * oneof rwnone, rwread, rwwrite, rweither annotations read ==> rwread write ==> rwwrite rweither ==> rweither rwnone ==> rwnone merge rwread + rwwrite ==> rwnone + * ==> rwnone rweither + rwread ==> rwread rweither + rwwrite ==> rwwrite transfers rwread as rwwrite ==> error "Must reset file between read and write. " rwwrite as rwread ==> error "Must reset file between write and read. " rwnone as rwread ==> error "File in unreadable state. " rwnone as rwwrite ==> error "File in unwritable state. " rweither as rwwrite ==> rwwrite rweither as rwread ==> rwread defaults reference ==> rweither end 38

Reading, ‘Righting /*@rweither@*/ FILE *fopen (const char *filename, const char *mode) ; int fgetc Reading, ‘Righting /*@[email protected]*/ FILE *fopen (const char *filename, const char *mode) ; int fgetc (/*@[email protected]*/ FILE *f) ; int fputc (int, /*@[email protected]*/ FILE *f) ; /* fseek resets the rw state of a stream */ int fseek (/*@[email protected]*/ FILE *stream, long int offset, int whence) /*@ensures rweither [email protected]*/ ; 39

Example f: openness = open f: rwness = rweither FILE *f = fopen (fname, Example f: openness = open f: rwness = rweither FILE *f = fopen (fname, “rw”); Possibly null reference f passed int i = fgetc (f); where non-null expected if (i != EOF) { f: openness = open, f: rwness = rwread fputc (i, f); Attribute mismatch – passed read fclose (f); where write FILE * expected. } f: openness = closed, f: rwness = rwnone Branches join in incompatible states: f is closed on true branch, open on false branch 40

Taintedness attribute taintedness context reference char * oneof untainted, tainted annotations tainted reference ==> Taintedness attribute taintedness context reference char * oneof untainted, tainted annotations tainted reference ==> tainted untainted reference ==> untainted anytainted parameter ==> tainted transfers tainted as untainted ==> error merge tainted + untainted ==> tainted defaults reference ==> tainted literal ==> untainted null ==> untainted end 41

tainted. xh int fprintf (FILE *stream, /*@untainted@*/ char *format, . . . ) ; tainted. xh int fprintf (FILE *stream, /*@[email protected]*/ char *format, . . . ) ; /*@[email protected]*/ char *fgets (char *s, int n, FILE *) /*@ensures tainted [email protected]*/ ; char *strcpy (/*@[email protected]*/ /*@[email protected]*/ char *s 1, /*@[email protected]*/ char *s 2) /*@ensures s 1: taintedness = s 2: [email protected]*/ ; char *strcat (/*@[email protected]*/ /*@[email protected]*/ char *s 1, /*@[email protected]*/ char *s 2) /*@ensures s 1: taintedness = s 1: taintedness | s 2: [email protected]*/ ; 42

SPLINT Case studies l wu-ftpd 2. 5 and BIND 8. 2. 2 p 7 SPLINT Case studies l wu-ftpd 2. 5 and BIND 8. 2. 2 p 7 l Detected known buffer overflows l Unknown buffer overflows exploitable with write access to config files l Performance l wu-ftpd: 7 seconds/ 20, 000 lines of code l BIND: 33 seconds / 40, 000 lines l Athlon 1200 MHz 43

Results – “Real” Code l l l wu-ftpd 2. 6. 1 (20 K lines, Results – “Real” Code l l l wu-ftpd 2. 6. 1 (20 K lines, ~4 seconds) No annotations: 7 warnings After adding ensures clause for ftpd_pclose l 4 spurious warnings 1 used function pointer to close FILE l 1 reference table l 2 convoluted logic involving function static variables l l 2 real bugs (failure to close ftpservers file on two paths) 44

SPLINT analysis of wu-ftp-2. 5. 0 ftpd. c: 1112: 2: Possible out-of-bounds store. Unable SPLINT analysis of wu-ftp-2. 5. 0 ftpd. c: 1112: 2: Possible out-of-bounds store. Unable to resolve constraint: max. Read ((entry->arg[0] @ ftpd. c: 1112: 23)) <= (1023) needed to satisfy precondition: requires max. Set ((ls_short @ ftpd. c: 1112: 14)) >= max. Read ((entry->arg[0] @ ftpd. c: 1112: 23)) derived from strcpy precondition: requires max. Set () >= max. Read () 45

wu-ftpd vulnerablity int acl_getlimit(char *class, char *msgpathbuf) { struct aclmember *entry = NULL; while wu-ftpd vulnerablity int acl_getlimit(char *class, char *msgpathbuf) { struct aclmember *entry = NULL; while (getaclentry("limit", &entry)) { … strcpy(msgpathbuf, entry->arg[3]); } } 46

Results Instances in wu-ftpd (grep) sp. Lint warnings with warning with no annotations added Results Instances in wu-ftpd (grep) sp. Lint warnings with warning with no annotations added strcat 27 19 12 strcpy 97 40 21 strncpy 55 4 4 Other Warnings - 132 writes 220 reads 95 writes 166 reads 47

Will Programmers Add Annotations? l l l C in 1974: char *strcpy (); C Will Programmers Add Annotations? l l l C in 1974: char *strcpy (); C in 1978: char *strcpy (char *s 1, char *s 2); C in 1989: char *strcpy (char *s 1, const char *s 2); C in 1999: char *strcpy (char * restrict s 1, const char *restrict s 2); *strcpy C in 20 xx: nullterminated char *strcpy (returned char *restrict s 1, nullterminated const char *restrict s 2) requires max. Set(s 1) >= max. Read (s 2) ensures s 1: taintedness = s 2: taintedness ensures max. Read(s 1) = max. Read (s 2); 48

In the Year 2012. . . Will buffer overflows still be common? l Will In the Year 2012. . . Will buffer overflows still be common? l Will software be free of design and coding errors? l Will we formally verify software? l Will we spend 90% effort in GUI and 10% in design/ code quality? l 49

References 1. 2. 3. 4. 5. 6. 7. Matt Bishop, Robust Programming, October 1998. References 1. 2. 3. 4. 5. 6. 7. Matt Bishop, Robust Programming, October 1998. seclab. cs. ucdavis. edu/ ~bishop/ classes/ ecs 153 -1998 -winter/ robust. html Required Reading. Simson Garfinkel, Gene Spafford Practical Unix and Internet Security, 2 nd edition (April 1996), O'Reilly & Associates; ISBN: 1565921488. Errata: http: //www. oreilly. com/catalog/puis/errata/ Chapter 23: Writing Secure SUID and Network Programs. Recommended Reading. Prabhaker Mateti, "Practical Advice on Writing Pre- Post-Conditions for Real Programs, " Lecture Notes, May 1998. [local copy] Required Reading. Prabhaker Mateti, "Buffer Overflow", Lectures on Internet Security, www. cs. wright. edu /~pmateti/ Courses/ 499/ Top/ lectures. html. Adam Shostack, "Security Code Review Guidelines, " July 2000, www. homeport. org/ ~adam/ review. html Reference. David A. Wheeler, "Secure Programming for Linux and Unix HOWTO, " April 2000, www. linuxdoc. org/ HOWTO/Secure-Programs-HOWTO. html Reference. SPLINT, www. splint. org, David Evans, University of Virginia. Reference 50