
Security-aware coding in C and C++ ● Generic notes ● C language related issues ● Operating system related issues ● Programming patterns ● C++ language related issues Zoltán Porkoláb Security Aware C/C++ Coding 1 C language related issues ● Null terminated strings ● Buffer overflow ● Insecure i/o ● Tainted scalars ● Uninitialized values ● Race conditions ● Function parameters ● Syntactical considerations Zoltán Porkoláb Security Aware C/C++ Coding 2 Buffer/Stack overflow Zoltán Porkoláb Security Aware C/C++ Coding 3 Buffer/Stack overflow Zoltán Porkoláb Security Aware C/C++ Coding 4 Null terminated strings char *strcpy(char *tgt, const char *src); ● Issues? Zoltán Porkoláb Security Aware C/C++ Coding 5 Null terminated strings char *strcpy(char *tgt, const char *src); ● Undefined behavior if – the target array is not large enough – the strings overlap – target is not pointer to char array – the source is not null terminated – any of tgt or src is null pointer Zoltán Porkoláb Security Aware C/C++ Coding 6 Null terminated strings char *strcpy(char *tgt, const char *src); char *strncpy(char *tgt, const char *src, size_t n); ● Undefined behavior if the strings overlap ● Copies at most n characters (chars after '\0' not copied) ● Fill the rest of the tgt buffer with null characters ● If there is no null character in the first n character of src, then the array tgt will not be null terminated Zoltán Porkoláb Security Aware C/C++ Coding 7 Null terminated strings char *strcpy(char *tgt, const char *src); char *strncpy(char *tgt, const char *src, size_t n); strncpy( tgt, src, sizeof(tgt)); tgt[sizeof(tgt)-1] = '\0'; ● Strncpy, strncat better to avoid ● Strncmp, … ok Zoltán Porkoláb Security Aware C/C++ Coding 8 Null terminated strings char *strcpy(char *tgt, const char *src); size_t strlcpy(char *tgt, const char *src, size_t tsize); size_t strlcat(char *tgt, const char *src, size_t tsize); ● BSD defines strlcpy, strlcat – Truncates the source string (security risk) – Do not perform all run-time checks – Return value is not explicit about error ● The total length of the string attempted to create Zoltán Porkoláb Security Aware C/C++ Coding 9 Null terminated strings char *strcpy(char *tgt, const char *src); size_t strlcpy(char *tgt, const char *src, size_t tsize); size_t strlcat(char *tgt, const char *src, size_t tsize); ● BSD defines strlcpy, strlcat – Truncates the source string (security risk) – Do not perform all run-time checks – Return value is not explicit about error ● The total length of the string attempted to create Unix man page: Note, however, that if strlcat() traverses size characters without finding a NUL, the length of the string is considered to be size and the destination string will not be NUL-terminated (since there was no space for the NUL). Zoltán Porkoláb Security Aware C/C++ Coding 10 Null terminated strings size_t strlcpy(char *tgt, const char *src, size_t tsize); size_t strlcat(char *tgt, const char *src, size_t tsize); char pname[MAXPATHLEN]; char *dir = ...; char *file = ...; if ( strlcpy( pname, dir, sizeof(pname)) >= sizeof(pname) ) { fprintf( stderr, “truncated!”); return -1; } if ( strlcat( pname, file, sizeof(pname)) >= sizeof(pname) ) { fprintf( stderr, “truncated!”); return -1; } /* ... */ Zoltán Porkoláb Security Aware C/C++ Coding 11 Do not do this! size_t strlcpy(char *tgt, const char *src, size_t tsize); size_t strlcat(char *tgt, const char *src, size_t tsize); char pname[MAXPATHLEN]; char *dir = ...; char *file = ...; size_t n = strlcpy( pname, dir, sizeof(pname)); if ( n >= sizeof(pname) ) { fprintf( stderr, “truncated!”); return -1; } if ( strlcpy( pname+n,file,sizeof(pname)-n) >= sizeof(pname)-n ) { fprintf( stderr, “truncated!”); return -1; } /* ... */ Zoltán Porkoláb Security Aware C/C++ Coding 12 Do not do this! size_t strlcpy(char *tgt, const char *src, size_t tsize); size_t strlcat(char *tgt, const char *src, size_t tsize); char pname[MAXPATHLEN]; char *dir = ...; char *file = ...; size_t n = strlcpy( pname, dir, sizeof(pname)); if ( n >= sizeof(pname) ) { fprintf( stderr, “truncated!”); return -1; } if ( strlcpy( pname+n,file,sizeof(pname)-n) >= sizeof(pname)-n ) { fprintf( stderr, “truncated!”); return -1; } However, one may question the /* ... */ validity of such optimizations, as they defeat the whole purpose of strlcpy() and strlcat(). As a matter of fact, the first version of this Zoltán Porkoláb manualSecurity Aware page C/C++ Codinggot it wrong. 13 Safe functions char *strcpy(char *tgt, const char *src); size_t strlcpy(char *tgt, const char *src, size_t tsize); errno_t strcpy_s(char *tgt, rsize_t tsize, const char *src); ● Calls the constraint handler function if – any of tgt or src is null pointer – tsize is zero or greater RSIZE_MAX – tsize <= strnlen_s(src, tsize) – tgt and src strings overlap ● Undefined if size of tgt array <= strlen_s(src,tsize) < tsize Zoltán Porkoláb Security Aware C/C++ Coding 14 Safe functions #define __STDC_WANT_LIB_EXT1__ 1 #include <string.h> constraint_handler_t set_constraint_handler_s( constraint_handler_t handler ) ● Safe functions are guaranteed to available if – __STDC_LIB_EXT1__ is defined by the implementation – User defines __STDC_WANT_LIB_EXT1__ before including <string.h> ● Defined in <stdlib.h>: typedef void (*constraint_handler_t) ( const char *msg, void *ptr, errno_t error); ● If constraint_handler is not set, default is implementation defined Zoltán Porkoláb Security Aware C/C++ Coding 15 Safe functions strcpy_s( char *dest, rsize_t destsz, const char *src) strncpy_s(char *dest, rsize_t destsz, const char *src, rsize_t n) strcat_s( char *dest, rsize_t destsz, const char *src) strncat_s(char *dest, rsize_t destsz, const char *src, rsize_t n) strnlen_s( char *str, rsize_t strsz) strtok_s(char *str, rsize_t *strmax, const char *delim, char **p) memset_s( void *dest, rsize_t destsz, int ch, rsize_t n) memcpy_s( void *dest, rsize_t destsz, const void *src, rsize_t n) memmove_s(void *dest, rsize_t destsz, const void *src, rsize_t n) strerrorlen_s( errno_t errnum) strerror_s( char *buf, rsize_t bufsz, errno_t errnum) Zoltán Porkoláb Security Aware C/C++ Coding 16 Safe functions strtok_s(char *str, rsize_t *strmax, const char *delim, char **p) char str[] = "A bird came down the walk"; rsize_t strmax = sizeof(str); const char *delim = " "; char *next_token; printf("Parsing the input string '%s'\n", str); char *token = strtok_s(str, &strmax, delim, &next_token); while(token) { puts(token); token = strtok_s(NULL, &strmax, delim, &next_token); } Zoltán Porkoláb Security Aware C/C++ Coding 17 Safe functions strerrorlen_s( errno_t errnum); strerror_s( char *buf, rsize_t bufsz, errno_t errnum); setlocale(LC_ALL, "ja_JP.utf8"); size_t errmsglen = strerrorlen_s(errno) + 1; char errmsg[errmsglen]; strerror_s(errmsg, errmsglen, errno); fprintf(stderr, “Might be truncated: %s”, errmsg); Zoltán Porkoláb Security Aware C/C++ Coding 18 Safe functions strerrorlen_s( errno_t errnum); strerror_s( char *buf, rsize_t bufsz, errno_t errnum); setlocale(LC_ALL, "ja_JP.utf8"); size_t errmsglen = strerrorlen_s(errno) + 1; char errmsg[errmsglen]; strerror_s(errmsg, errmsglen, errno); fprintf(stderr, “Might be truncated: %s”, errmsg); strerror_s() is the only safe function that allows truncation Zoltán Porkoláb Security Aware C/C++ Coding 19 Buffer overflow #include <stdio.h> #define BUFSIZE 80 char *answer(const char *question); int main() { printf(“answer is %s\n”, answer(“How are you?”)); return 0; } char *answer(const char *question) { char buffer[BUFSIZE]; printf(“%s\n”, question); gets(buffer); return buffer; } Zoltán Porkoláb Security Aware C/C++ Coding 20 Buffer overflow #include <stdio.h> #define BUFSIZE 80 char *answer(const char *question); int main() { printf(“answer is %s\n”, answer(“How are you?”)); return 0; } char *answer(const char question) { char buffer[BUFSIZE]; printf(“%s\n”, question); gets(buffer); /* Possible buffer overflow! */ return buffer; } Zoltán Porkoláb Security Aware C/C++ Coding 21 Buffer overflow #include <stdio.h> #define BUFSIZE 80 char *answer(const char *question); int main() { printf(“answer is %s\n”, answer(“How are you?”)); return 0; } char *answer(const char question) { char buffer[BUFSIZE]; printf(“%s\n”, question); fgets(buffer, BUFSIZE, stdin); /* Safe! */ return buffer; } Zoltán Porkoláb Security Aware C/C++ Coding 22 Buffer overflow #include <stdio.h> #define BUFSIZE 80 char *answer(const char *question); int main() { printf(“answer is %s\n”, answer(“How are you?”)); return 0; } char *answer(const char question) { char buffer[BUFSIZE]; printf(“%s\n”, question); fgets(buffer, BUFSIZE, stdin); /* Safe! / return buffer; /* Life of buffer is about to end */ } Zoltán Porkoláb Security Aware C/C++ Coding 23 Buffer overflow #include <stdio.h> #define BUFSIZE 80 char *answer(const char *question); int main() { printf(“answer is %s\n”, answer(“How are you?”)); return 0; } char *answer(const char question) { static char buffer[BUFSIZE]; /* Better, but not perfect */ printf(“%s\n”, question); fgets(buffer, BUFSIZE, stdin); /* Safe! */ return buffer; } Zoltán Porkoláb Security Aware C/C++ Coding 24 Buffer overflow #include <stdio.h> #define BUFSIZE 80 char *answer(const char *question); int main() { char buffer[BUFSIZE]; /* Who owns buffer? */ printf(“answer is %s\n”, answer(“How are you?”, buffer, BUFSIZE)); return 0; } char *answer(const char *question, char *buf, int len) { printf(“%s\n”, question); fgets(buf, len, stdin); /* Safe! */ return buf; } Zoltán Porkoláb Security Aware C/C++ Coding 25 C++ must be better #include <iostream>
Details
-
File Typepdf
-
Upload Time-
-
Content LanguagesEnglish
-
Upload UserAnonymous/Not logged-in
-
File Pages65 Page
-
File Size-