secure coding james walden northern kentucky university

30
Secure Coding James Walden Northern Kentucky University

Upload: julia-barton

Post on 31-Dec-2015

217 views

Category:

Documents


0 download

TRANSCRIPT

Secure Coding

James Walden

Northern Kentucky University

Topics

1. Error Handling

2. Return Codes

3. Exceptions

4. Logging

5. Memory Allocation

6. Using and Storing Passwords

7. Protecting Secrets in Memory

CSC 666: Secure Software Engineering

Security Impact of Error Handling

Information leakage Stack traces Database errors

Resource leakage Return on error without de-allocation Exceptions bypass de-allocation

CSC 666: Secure Software Engineering

Error Handling TechniquesReturn a neutral value: return a value that’s known to be

harmless, i.e. a negative number, zero, or “”.Substitute the next piece of data: continue reading from

hardware or file until a valid record is found.Return same answer as last time: don’t keep reading;

instead return the last valid answer.Substitute closest legal value: if velocity has a range of

0..100, show a 0 when backing up.Log a warning message: Write a warning to a log, then

continue on, perhaps using one of the other techniques.Terminate program: Terminate program execution.Return an error code: Report error by

Setting the value of a status variable (errno) Return status as the function’s return value Throw an exception

CSC 666: Secure Software Engineering

Return Codes

Use function return code to indicate error. Easy to ignore. Simply ignore return code. Error handling logic is mixed with logic

processing normal return codes. No universal convention for error codes.

Common return code patterns. Negative values when nonnegative expected. NULL values for pointer return codes.

Example: character get functions

fgetc(), getc(), getchar() read char, return intUse int to represent EOF error code.

Incorrect example: return value is declared as a charchar buf[BUFSIZ]; char c; int i = 0; while ( (c = getchar()) != '\n' && c != EOF )

if (i < BUFSIZ-1) { buf[i++] = c; }buf[i] = '\0'; /* terminate NTBS */

Correct examplechar buf[BUFSIZ]; int c; int i = 0; while (((c = getchar()) != '\n') && !feof(stdin) && !

ferror(stdin))if (i < BUFSIZ-1) { buf[i++] = c; }

buf[i] = '\0'; /* terminate NTBS */

CSC 666: Secure Software Engineering

Resource Leaks

Resources leak due to early returns Memory Filehandles

Examplechar *getblock(int fd) {char *buf = (char *)malloc(1024);if (!buf) { return NULL; }if (read(fd, buf, 1024) != 1024) {

return NULL;}return buf

}

CSC 666: Secure Software Engineering

Using goto for error handling

Problem: need to de-allocate resources on return. Each return is different since Different resources allocated at each point.

Solution: single de-allocation point Check if resource is allocated, then De-allocate if it is, and Return with appropriate error code.

Why goto? Avoids deep nesting. Improves code readability. Commonly used technique in kernel.

CSC 666: Secure Software Engineering

Fixed version with gotochar *getblock(int fd) {char *buf = (char *)malloc(1024);if (!buf) { goto ERROR; }if (read(fd, buf, 1024) != 1024) {

goto ERROR;}return buf;

ERROR:if (buf) { free(buf); }return NULL;

}

CSC 666: Secure Software Engineering

Exceptions

Advantages of exceptions Cannot be ignored by not checking for errors. Separate main code from error code.

Disadvantages of exceptions Difficult to avoid resource leaks, as exceptions create

many implicit control flow paths. Can still ignore exceptions

try {

// code that can throw an exception

} catch (AnException e) {

// empty catch block

}

CSC 666: Secure Software Engineering

Checked Exceptions

Checked exceptions: Exceptions that the language requires client code to handle.

C++, C#: no checked exceptions Java: exceptions that inherit from Exception

Unchecked exceptions: Exceptions that can be ignored by client code.

C++, C#: all exceptions are unchecked Java: exceptions that inherit from

RuntimeException.

CSC 666: Secure Software Engineering

Exception GuaranteesLevels of exception safety for a class.

Basic Guarantee No resources are leaked.

Strong Guarantee Exceptions leave state exactly as it was before the

operation started.

No Throw Guarantee Component will handle all exceptions itself.

No Exception Safety Component may leak resources and leave object

in an inconsistent unusable state.

CSC 666: Secure Software Engineering

Exception Safety Examplevoid stack::push(int element) {top++; if( top == size-1 ){ int* buf = new int[size+=32]; if( buf == 0 ) throw “Out of memory”; for(int i = 0; i < top; i++) buf[i] = data[i]; delete [] data; data = buf; } data[top] = element;

}

CSC 666: Secure Software Engineering

Catch-all Exception HandlersEnsure no information leakage at top level functions.

doGet(), doPost(), web service entry points

protected void doPost(HttpServletRequest req, HttpServlet

Response res) {try {

/* function body */}catch (Throwable t) {

logger.error(“Top-level exception caught”, t);}

}

Do not do this in low level code. Need to deal with individual error types separately, instead of

ignoring them or handling generically.

CSC 666: Secure Software Engineering

Destructor De-Allocation

Resource Acquisition Is Initialization design pattern Resources acquired during initialization of object,

before it can be used. Resources are de-allocated by the object’s destructor,

which occurs even via exceptions.

Examplefile (const char* filename) { file_ = fopen(filename, “w+”);

if (!file_) throw std::runtime_error("file open failure");

}~file() { if (f) { fclose(file_); } }

CSC 666: Secure Software Engineering

Finally

Finally block executed regardless of whether an exception is caught or not.

ExampleStatement stmt = conn.createStatement();

try {

stmt.execute(sqlString);

} finally {

if (stmt != null ) { stmt.close(); }

}

CSC 666: Secure Software Engineering

Logging Frameworks

Use a standard logging framework. Provide single consistent view of system. Facilitate changes, such as logging to a new

system or to a database.

Examples syslog() log4j java.util.logging

CSC 666: Secure Software Engineering

Memory Allocation Strategies

Static Buffer Allocation Advantages: simple, easy to know bounds. Disadvantages: inflexible, wastes memory.

Dynamic Buffer Allocation Advantages: flexible. Disadvantages: must check for DoS attacks.

Track Buffer Sizestypedef struct {

char* ptr;

size_t bufsize;

} buffer;

Common Allocation Errors

Assuming that memory is zeroed. Allocated memory contains junk, not zeros.

Failure to check that allocation succeeded. Most C functions return a NULL pointer on failure. new will throw std::bad_alloc exception on

failure. Unless specify T* p = new(std::nothrow) T;

Use of invalid pointers. Dereference NULLs, use after free, double free.

Failure to deallocate memory. Memory leaks.

Zero-length allocations are implementation defined in C.

CSC 666: Secure Software Engineering

Inbound and Outbound Passwords

Inbound Passwords Used to authenticate users to application. In cleartext only at point of user data entry. Risks: online and offline password guessing.

Outbound Passwords Used to authenticate application to other

systems, such as databases or CC processors.

Must be in cleartext to use. Risks: information leakage.

Securing Inbound Passwords

Slide #21

Offline Password Cracking

Password dictionary

Usernames + Hashed Passwords

word = Next dictionary word

wordhash = Hash(word)

for each (username, hash)

wordhash == hash False

True

Store(usernames, word)

CSC 666: Secure Software Engineering

Hashing and Salting

MD4 (Windows) Unlimited password length. Slow MD4 hash, no salt.

SHA512crypt (Linux, Mac OS X) Unlimited password length. 5000 iterations of SHA-512 hash function. 16 character salt.

PBKDF2 (Password-Based Key Derivation Function 2) Framework with configurable hash, iterations, salt. In .NET.

Scrypt Sequential, memory-hard hashing algorithm. Defense against specialized hardware (GPUs, ASICs, FPGAs)

CSC 666: Secure Software Engineering

Outbound Passwords

Used by app to auth to db, other systems. Must be accessible in cleartext at some point.

Solutions Store in source code.

- Easy to view in source or binary form. Store cleartext in a configuration file. Store encrypted in a configuration file.

- Use a good, known algorithm like AES.- Limit ACLs so only app can access.

Require admin enter password on restart.- PCI 3.6.6 requires key be split among admins.

CSC 666: Secure Software Engineering

Secrets in Memory

Attackers can obtain secrets from memory Remote exploit: buffer overflow or fmt string Physical attack: direct media access Accidental leakage: core dumps or page files

CSC 666: Secure Software Engineering

Securing Secrets in Memory

Minimize time spent holding secrets. Decrypt data just before use. Overwrite data after use.

Share secrets sparingly. Do not store secrets on the client.

Erase secrets securely. Explicitly overwrite memory.

Prevent unnecessary duplication.

CSC 666: Secure Software Engineering

Locking Pages in Memory

Prevent secrets from paging to disk.Does not prevent suspend or hibernate saving pages.

Linux page lockingmlock(const void *addr, size_t len)

munlock(const void *addr, size_t len)

Windows page lockingVirtualLock(LPVOID lpAddress, SIZE_T dwSize);

VirtualUnlock(LPVOID lpAddress, SIZE_T dwSize);

CSC 666: Secure Software Engineering

Erasing Secrets Securely

Garbage collecting languages Essentially impossible to ensure secrets are erased

immediately.

Low level languages Compiler can optimize away code that overwrites a

buffer if buffer contents are not used later. Use memset_s() if compiler supports C11. Use SecureZeroMemory() in Windows. If neither function is available, use volatile pointers to

prevent compiler from optimizing away memory overwrites. Some compilers may still cause problems.

CSC 666: Secure Software Engineering

Erasing Secrets Securely in C99

void auth_function() {

char pass[32];

if (getpass(pass)) {

// Do something with password

}

memset(pass, 0, sizeof(pass));

// Prevent memset from being optimized

// away by using volatile pointers.

*(volatile char *)pass =

*(volatile char *)pass;

}

References

1. David Abrahams, Exception-Safety in Generic Components. Lecture Notes In Computer Science: 69-79, 2000.

2. Tom Cargill, Exception Handling: A False Sense of Security, C++ Report, Volume 6, Number 9, November-December 1994.

3. CERT, Error Handling, https://www.securecoding.cert.org/confluence/download/attachments/3524/error-handling.pdf, 2006.

4. Brian Chess and Jacob West, Secure Programming with Static Analysis, Addison-Wesley, 2007.

5. Robert J. Ellison et. al., Survivability: Protecting Your Critical Systems, IEEE Computer, 1999.

6. Fred Long, CERT Secure Coding Standards: Error Handling, https://www.securecoding.cert.org/confluence/display/cplusplus/12.+Error+Handling+(ERR), 2009.

7. Steve McConnell, Code Complete, 2nd edition, Microsoft Press, 2004.