1 / 130

SE611 – 2018/2019 2 nd Term Secure Software Development Lectures 6 & 7 Defensive Programming

Cairo University, Faculty of Computers and Information. SE611 – 2018/2019 2 nd Term Secure Software Development Lectures 6 & 7 Defensive Programming. By Dr. Mohamed El-Ramly http://www.acadox.com/class/56820. Requirement. Requirement. Analysis. Analysis. Design. Design. Implement.

gwallace
Télécharger la présentation

SE611 – 2018/2019 2 nd Term Secure Software Development Lectures 6 & 7 Defensive Programming

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Cairo University, Faculty of Computers and Information SE611 – 2018/2019 2nd TermSecure Software DevelopmentLectures 6 & 7Defensive Programming By Dr. Mohamed El-Ramly http://www.acadox.com/class/56820

  2. Requirement Requirement Analysis Analysis Design Design Implement Implement Testing Testing Integrating Security with SDLC • There are two approaches.  Software Security Software Security

  3. Secure Software SDLC • Requirements • Define Security Requirements (what the system should not do) • Develop abuse cases • Architecture • Perform architectural risk analysis • What types of risks, the proposed architecture poses • Threat Modeling

  4. Threat Modeling Questions • What are you building? • What can go wrong? • What should you do about those things that can go wrong? • Did you do a decent job of analysis?

  5. Q2. What can go wrong?STRIDE Spoofing S Attacker pretend to be someone he is not Tampering T Attacker modify something he is not supposed to modify Repudiation R Attacker denies he did something that he actually did Information disclosure I Attacker exposes info he is not authorized to see it Denial of service D Attacker prevents a system from providing its services Elevation of privilege E A program or user is able to do things he is not supposed to do.

  6. Secure Software SDLC • Design • Security-oriented design of the system • Implementation • Applying principles and rules for secure coding (Defensive Programming) • Secure code reviews & automated scanning • Testing • Plan tests to address the risk of attacks. • Penetration testing, looking at the system as an adversary would do.

  7. Best Practices for Secure Design • Try to eliminate security hazards from the design • Identify causes of security hazards and try to reduce their likelihood of occurring through design • Control security hazards once they occur • Design to reduce damage if it occurs

  8. Principles • Least Privilege • Fail-Safe Defaults • Complete Mediation • Economy of Mechanism • Open Design • Separation of Duty • Least Common Mechanism • Psychological Acceptability • Defense in depth • Question assumptions

  9. Lecture Outline • General Practices • C / C++ Language • Java • Specific Tasks Reading • Fedora Security Team Defensive Coding A Guide to Improving Software Security Edition 1 https://docs.fedoraproject.org/en-US/Fedora_Security_Team/1/pdf/Defensive_Coding/Fedora_Security_Team-1-Defensive_Coding-en-US.pdf

  10. Defensive Programming • Is a set of programming techniques intended to ensure the continuing function of a piece of software under unforeseen circumstances. • Defensive programming practices are used to ensure correctness, availability, or security. • Defensive programming improves software quality and reduces bugs. • It makes software behave in a predictable manner despite unexpected inputs or user actions. • It reduces runtime and maintenance costs.

  11. Defensive Driving • Defensive programming can be related to something called Defensive Driving. • In Defensive Driving we assume that everyone around us can potentially and possibly make mistakes. So we have to be careful even to others’ behavior. • The same concept applies to Defensive Programming where us, as developers shouldn’t trust others developers’ code. We shouldn’t trust our code neither. We should not trust user behavior.

  12. Secure Programming • Secure programming is the subset of defensive programming concerned with computer security. • As with defensive programming, avoidingbugs is a primary objective, however the motivation to reduce the attack surface. • The assumption is that the software might be misused actively to reveal bugs, and that bugs could be exploited maliciously. • The goals is to reduce exploitable bugs.

  13. Risky Programming intrisky_programming(char*input){ char str[1000+1]; // +1 for the null // ... strcpy(str, input); // Copy input // no boundary check // ... }

  14. Secure Defensive Programming intsecure_programming(char*input){ char str[1000+1]; // +1 for the null // ... strncpy(str, input, sizeof(str))); // Copy within boundary str[sizeof(str) -1] ='\0'; // Terminate string with null // ... }

  15. Fedora Security Team: Defensive Coding A Guide to Improving Software Security • This document provides guidelines for improving software security through secure coding. • It covers common programming languages and libraries, and focuses on concrete recommendations.

  16. I. General Practices • Input Validation • Encoding & Canonicalization • Sanitization • Error Handling • …

  17. 1. Input Validation • Verification of the data provided and ensuring it is safe and free of hazards. • Validate input from all untrustedsources. • Proper input validation can remove the vast majority of software vulnerabilities. • Be suspicious of external data sources • command line arguments, • network interfaces, • environmental variables, and • user controlled files.

  18. Input Validation • To ensure input datameets assumptions. • e.g. is printable, HTML, email, userid etc • Compare to what is known acceptable. • Use regular expressions • To reject or alter bad input

  19. Input Validation • Validate numeric data. • Internally stored in fixed sized value, e.g. 8, 16, 32, 64-bit integers or 32, 64, 96 float • signed or unsigned • Must correctly interpret text form and then process consistently • Issues comparing signed to unsigned • e.g. large positive unsigned is negative signed • could be used to thwart buffer overflow check

  20. Why Input Validation? • Lack of validation gives the attackers a chance to run different attacks. • Attacks can insert malformed input that • Crash the system • Leak data • Expose database • Possible attacks • Integer overflow • Injection • Invalid input format

  21. 2. Encoding & Canonicalization • Canonicalization: is the process of converting data that holds more than one possible representation to conform to a standard canonical form. • Ensure that SQL queries containing user-controllable input are encoded correctly to prevent single quote or other characters from altering query

  22. Encoding & Canonicalization • Multiple representation of single characters needs to be brought into account. • Use whitelist input validation and reject non canonical forms of input • Validatefilters should be done afterinput is in canonical form.

  23. 3. Sanatization • Sanitization: is the process of changing something that is considered dangerous into its innocuous form. • Sanitize all data given to complex subsystems such as command shells, relational databases, and commercial off-the-shelf (COTS) parts.

  24. Sanatization • Attackers may be able to invoke unused functionality in these ingredients through the use of SQL, command, or other injection attacks. • The complex subsystem being invoked does not understand the context in which the call is made, hence it would not validate the input. • The calling process understands the context, it is responsible for sanitizing the data before invoking the subsystem.

  25. 4. Error Handling • Murphy's Law “Anything that can go wrong will go wrong“ • Error conditions will happen, and your code needs to deal with them: • Out of memory, disk full, file missing, file corrupted, network error, …

  26. Error Handling • Software should be tested to find out how it does under various error conditions • Simulate errors and see what happens • Simply because your program works on your computer doesn't mean that it will go everywhere else • Many weird things will go wrong when your software is utilized out in the "wild"

  27. Error Handling • Use informative but non-verbose error messages. • How to Write Good Error Messages – UX Planet https://uxplanet.org/how-to-write-good-error-messages-858e4551cd4

  28. Error Handling • Use an index of the value or reference map. • Best practice: redirect errors and exceptions to a custom and default error handling location and depending on the context of where the user has logged in (remote or local), appropriate message details can be displayed.

  29. Lecture Outline • General Practices • C / C++ Language • Java • Specific Tasks Reading • Fedora Security Team Defensive Coding A Guide to Improving Software Security Edition 1 https://docs.fedoraproject.org/en-US/Fedora_Security_Team/1/pdf/Defensive_Coding/Fedora_Security_Team-1-Defensive_Coding-en-US.pdf

  30. II. C / C++ – Core Language • Undefined behaviours • Standard does not describe what happens when the construct is executed • Examples • out-of-bounds array accesses • null pointer dereferences • overflow in signed integer arithmetic • Misuse of global variables • C provides no memory safety.

  31. Out-of-bounds Array Access // Program to demonstrate  // accessing array out of bounds #include <stdio.h> int main() {     int arr[] = {1,2,3,4,5};     printf("arr [0] is %d\n", arr[0]);     // arr[10] is out of bound     printf("arr[10] is %d\n", arr[10]);     return 0; }

  32. Null Pointer Dereferencing • Why this is undefined ? • Because it will incur overhead to check every time if pointer is null or no. Compiler will have to inject this code. • Or, PDP-11 machines on which C was developed, always had 0 at location 0 and this was not a problem.

  33. Null Pointer Dereferencing // Program to demonstrate // null pointer dereferencing #include <stdio.h> int main() { int *arr; printf("*arr is %d\n", *arr); return 0; } Crash

  34. Overflow in Signed Integer // Program to demonstrate signed int overflow #include <stdio.h> #include <limits.h> int main() { int num = INT_MAX; printf("num is %d\n", num); num++; printf("num++ is %d\n", num); return 0; }

  35. Recommendations for pointers and array handling • Keep track of the size of the array you are working with. • Keep a pointer past the last element of the array, and calculate the number of remainingelements by substracting the current position from that pointer. Better • Update a separate variable every time when the position is advanced, is usually less obviously correct. • Use C++ vectors or valarray.

  36. Recommendations for pointers and array handling • Use C++ smart pointers: • shared_ptr • weak_ptr • unique_ptr

  37. Basic Problem Resource sharing is often more efficient than copying But it’s hard to tell when all are done using a resource Must avoid early deletion Must avoid leaks Solution Approach Share both the resource and also a counter Each new reference increments the counter When a reference is done, it decrements the counter When count drops to zero, delete resource and counter “last one out shuts off the lights” shared_ptr reference reference Resource reference counter == 3

  38. shared_ptr // shared_ptr constructor example #include <iostream> #include <memory> int main () { std::shared_ptr<int> p1; std::shared_ptr<int> p2 (new int); std::shared_ptr<int> p3 (new int, std::default_delete<int>()); std::shared_ptr<int> p4 (p2); std::cout << "use_count:\n"; std::cout << "p1: " << p1.use_count() << '\n'; std::cout << "p2: " << p2.use_count() << '\n'; std::cout << "p3: " << p3.use_count() << '\n'; std::cout << "p4: " << p4.use_count() << '\n'; return 0; }

  39. Recommendations for integer arithmetic • Overflow in signed integer arithmetic is undefined. • This means that it is not possible to check for overflow after it happened or it can causedamage it happens. • We need approaches to check for overflow without causing it.

  40. Integer arithmetic overflow example #include <stdio.h> #include <limits.h> int main() { int num = INT_MAX; printf("num is %d\n", num); printf("num*2 is %d\n", num*2); printf("num*3 is %d\n", num*3); printf("num*4 is %d\n", num*4); printf("num*5 is %d\n", num*5); printf("num*6 is %d\n", num*6); return 0; }

  41. Recommendations for integer arithmetic • Use a wider type for calculation, check that result is within bounds & convert to original type. What is the drawback ? • All intermediate results must be checked as well • Addition of unsigned types • Perform the calculation in the corresponding unsigned type and check result to detect the overflow. • For three or more terms, all the intermediate additions have to be checked in this way.

  42. Recommendations for integer arithmetic void report_overflow(void); Unsigned add_unsigned(unsigned a, unsigned b) { unsigned sum = a + b; if (sum < a) { // or sum < b report_overflow(); } return sum; }

More Related