Sei sulla pagina 1di 22

TABLE OF CONTENTS TABLE OF CONTENTS ............................................................................................................... 1 A. INTRODUCTION ...................................................................................................................... 2 The GIAC Certification Program ........................................................................................... 2 B.

THE GIAC SECURE SOFTWARE PROGRAMMER (GSSP) EXAMINATION ....................... 2 C. DEADLINES AND EXAMINATION SCHEDULE ..................................................................... 3 D. REGISTRATION FEES ............................................................................................................ 3 E. REGISTRATION PROCESS .................................................................................................... 3 F. ELIGIBILITY REQUIREMENTS ............................................................................................... 4 G. EXAMINATION INFORMATION .............................................................................................. 4 Examination Development ..................................................................................................... 4 Examination Content .............................................................................................................. 4 Reference List ......................................................................................................................... 4 Practice Test ........................................................................................................................... 4 Examination Time Limits ....................................................................................................... 4 Certification............................................................................................................................. 4 Additional Certification Information ..................................................................................... 5 H. SAMPLE QUESTIONS AND ANSWERS ................................................................................ 7 Appendix A: C Secure Coding Tasks, Skills and Knowledge ............................................... 10 Appendix B: Helpful Resources .............................................................................................. 20 Book References for Software Security ............................................................................. 20 Websites & Podcasts for Software Security ...................................................................... 21

A. INTRODUCTION Governments, companies, and educational institutions are doomed to deal with endless streams of software vulnerabilities unless programmers learn to write much more secure code. Several initiatives are underway to improve secure programming skills and knowledge. Symantec, Oracle, Microsoft, and a few other software companies are conducting short courses for their programmers; software firms like SPI Dynamics and Fortify Technology are working with universities to provide automated, real-time feedback to student programmers; and dozens of universities are creating elective courses on secure programming. Yet, even if all of those initiatives are successful, they are unlikely to affect even two percent of the existing 1.5 million programmers already in the work force or those who will be entering the work force over the next five years. To answer this growing need, the SANS Institute, in connection with the Global Information Assurance Certification (GIAC) organization, has organized a testing and certification program for software programmers/developers that is designed to enable reliable measurements of technical proficiency and expertise in identifying and correcting the common programming errors that lead to security vulnerabilities. SANS is the most trusted and by far the largest source for information security training and certification in the world. It also develops, maintains, and makes available at no cost, the largest collection of research documents about various aspects of information and software security, and it operates the Internet's early warning system - Internet Storm Center. SANS provides intensive, immersion training designed to help candidates master the practical steps necessary for defending applications, systems and networks against the most dangerous threats - the ones being actively exploited.

The GIAC Certification Program http://www.giac.org


Founded in 1999 to validate the real-world skills of IT security professionals and developers, GIAC stands for Global Information Assurance Certification. GIAC's purpose is to provide assurance that a certified individual has practical awareness, knowledge, and skills in key areas of computer, network and application/software security. These certifications are available for a variety of responsibilities that reflect the current practice of information security and secure software development. GIAC is unique in measuring specific knowledge areas instead of general purpose knowledge. B. THE GIAC SECURE SOFTWARE PROGRAMMER (GSSP) EXAMINATION http://www.giac.org/certifications/software/ The GIAC Secure Software Programmer (GSSP) allows candidates to demonstrate mastery of the knowledge and skills needed to deal with common programming errors that lead to most security problems in one or more specific languages: Java and J2EE PHP C Perl C++ ASP.NET and .NET

The examinations are primarily for programmers/developers who develop and maintain code. Those involved with software code review/audit, QA and testing will also be able to demonstrate valuable skills. The exams focus on the common errors that programmers make that lead to vulnerabilities. They target implementation issues in individual programming languages as well as secure programming principles that are directly relevant to every day coding activities. In contrast to tests that measure book learning, this test measures an individuals ability to identify coding errors and to apply the widely accepted rules and recommendations that constitute the core of secure coding. Many of the test questions use code samples in which the test taker is asked to find errors and decide how to eliminate them. C. DEADLINES AND EXAMINATION SCHEDULE The GSSP is administered at established proctored testing facilities. For full information on the GIAC proctor program, please see http://www.giac.org/proctor/. Once you have completed the registration process and receive access to your certification, you will have (4) months to complete your certification. D. REGISTRATION FEES The GSSP-C is currently available through the GIAC Challenge Certification program. The registration fee for the GSSP-C is $899.00. Payments may be made via Visa, MasterCard, money order, cashiers check, or personal check. The fee must be paid in U.S. funds. The application fee is non-refundable and must be received by GIAC for your registration to be complete. E. REGISTRATION PROCESS The registration steps include: 1. It is suggested that you review the candidate handbook prior to completing registration. Follow the instructions given, and address any questions to GIAC (info@giac.org). Failure to follow the instructions can lead to the denial of registration. 2. You must have a SANS portal account to register. If you do not have a portal account, you may create one by visiting https://portal.sans.org/. 3. Once you have a SANS portal account you may register for the GSSP certification by visiting the following link and selecting the GIAC Secure Software Programmer-C (GSSP-C) offering. https://www.sans.org/registration/register.php?conferenceid=1251 Please note that registration for the GSSP examination may be refused or GIAC certification may be revoked for any of the following reasons:

Incomplete registration Falsifying or misrepresenting registration information Adjudicated penalty for violation of the GIAC Code of Ethics If you are notified of revocation, you will also be notified of the available appeal process. F. ELIGIBILITY REQUIREMENTS There are no eligibility requirements to register for the GSSP. G. EXAMINATION INFORMATION Examination Development The development of a valid GSSP examination began with a clear and concise definition of the knowledge, skills, and abilities needed for competent job performance. Using interviews, surveys, and group discussions, SANS worked with subject matter experts to delineate critical job components. The knowledge and skill bases for the questions on the multiple-choice examination were derived from the actual practice of software programmers. Specifically, the GSSP is built in three stages. First the team agrees on the tasks and rules that a secure programmer uses in each language. Then they rank those tasks and rules on three criteria: criticality of risk if the rule is broken, importance of the rule, and frequency with which the rule should be employed. Using those ratings they compute the number of questions that will be on the test for each task/rule set. Finally they develop and vet questions. This ensures that the questions will adequately reflect the actual importance of the rules being tested. Examination Content The certification examination consists of 100 multiple-choice questions. The full content blueprint can be found in Appendix A. As noted in the Exam Development section above, experts have provided input for the difficulty level of all questions used on the exams. That information is used to develop examination forms that have comparable difficulty levels. Reference List A reference list of potential study materials is located in Appendix B. Some of the material will be helpful in preparing for the assessments. This is not intended as a complete list or an endorsement, but simply as a starter for those interested in learning more. Practice Test Two practice exams are provided with GSSP certification attempts. Examination Time Limits You will be given four (4) hours to complete the test. Certification Those who gain passing scores at the foundation level will earn the GIAC Secure Software Programmer (GSSP) certification. A designation will follow the letters reflecting the language in which the certification was earned. For example, a programmer who passes the C exam would receive the GSSP-C designation.
4

The GSSP certification will be valid for four years. You will become eligible to apply for re-certification one (1) year prior to your certification expiration. You must register for recertification before your certification expiration date. To re-certify, you must pass the current examination being offered. Additional Certification Information For more information on the certification process, including our Proctoring Policy, GIAC Code of Ethics, Accommodations for Individuals with Disabilities, Examination Retakes, Scheduling your Exam and Test Taking Procedures, please visit the following sites: http://www.giac.org/ http://www.giac.org/proctor/ http://www.giac.org/information http://www.giac.org/GIAC_silver_handbook.pdf

H. SAMPLE QUESTIONS AND ANSWERS Sample Questions 1) What non-secure practice does the following function exhibit?

char *readbuf(char buf[]) { printf("Enter input >"); . return(gets(buf)); } A. The function calls gets() B. The size of the array buf is not explicitly given in the function declaration. C. The call to printf() is vulnerable to an attack in which data overflows the program
stack, changing the return address. D. Nothing, this code is secure 2) What is the resulting type of the addition operation in the following code, assuming a twos complement representation and that char is eight bits and int is 32-bits?

unsigned char c = 5; unsigned char d = 7; if (c + d > UCHAR_MAX) abort();


A. B. C. D.

unsigned char signed char signed int unsigned int

3) What of the following integer operations cannot result in an integer overflow? A. B. C. D. Multiplication Division Unary negation Right shift

4) In the expression E1 >> E2, if E1 has a signed type and a negative value, the resulting operation is A. B. C. D. undefined an arithmetic shift a logical shift implementation defined

5) Arc-injection attacks (also known as return-to-libc attacks) are dangerous because: A. B. C. D. they cannot be prevented by making writable pages non-executable they can cause a buffer overflow the vulnerable code can be executed in any memory segment the injected code can circumvent normal input validation techniques

6) Which line of code can be exploited to write outside the bounds of an object?
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. #include <stdio.h> #include <string.h> void usage(char *ptCommand) { char usage [1023]; snprintf(usage, 1023, Usage: %s <target>\n, ptCommand); printf(usage); } int main(int argc, char * argv[]) { if (argc < 2) usage(argv[0]); }

A. B. C. D.

Line 5 Line 6 Line 9 Line 10

7) Vulnerabilities resulting from race conditions can be eliminated by making conflicting race windows:

A. B. C. D.

as small as possible shuttered critical sections mutually exclusive

8) What coding defect exists in the following C function?

char *copybuf(char str[]) { char *p; p = malloc(strlen(str)+1); (void) strcpy(p, str); return(p); }
A. B. C. D. It calls strcpy() rather than strncpy It does not check the return value of malloc(). It does not cast the type of malloc to be a char *. Nothing, this function is correct

9) What is the value of size in the following program equal to?

void func(char s[]) { size_t size = sizeof(s) / sizeof(s[0]); } int main(void) { char str[] = "0123456789"; func(str); }
A. B. C. D.

sizeof("0123456789") sizeof("0123456789") + 1 sizeof(char *) sizeof("0123456789") / sizeof(char)

10) Which statement declares p as a constant pointer to type T? A. B. C. D.

T T p p

* const const * * const const *

p; p; T; T;

Sample Question Answers 1) Answer (A) The function calls gets() Explanation: The gets() function cannot be called securely because there is no way to restrict the number of bytes that are read. The call to printf() is incorrectly formulated (it should take a minimum of two arguments) but not vulnerable to attack because an attacker cannot influence the format string. Although the size of an array such as buf is normally passed as a separate argument, this approach can work by convention provided the character array passed to the readbuf() function is of sufficient length. 2) Answer (C) signed int Explanation: Both the unsigned char c and the unsigned char d are subject to integer promotions when used in an expression. In the case that these values are eight-bit twos complements representation they have a possible range of 0-255. Because this range can be fully represented as a 32-bit int type, the integer promotion rules of both C and C++ dictate that these values be converted to signed int and that the addition operation be performed as a 32-bit operation. 3) Answer (D) right shift Explanation: Right shift operations cannot result in a buffer overflow because the resulting value can always be represented. Multiplication is especially prone to overflow because relatively small operands can result in value that cannot be represented in the resulting type. Division can result in overflow for signed, twos complement integers when the dividend is the

minimum value for a type (the most negative value) and the divisor is -1. Unary negation results in overflow when the minimum value for a type is negated. 4) Answer (D) implementation defined Explanation: Right shift may be implemented as either an arithmetic shift (sign-extended) or logical shift (zero-filled). The C89 Committee affirmed the freedom in implementation granted by K&R in not requiring the signed right shift operation to sign extend, since such a requirement might slow down fast code and since the usefulness of sign extended shifts is marginal. (Shifting a negative twos complement integer arithmetically right one place is not the same as dividing by two!) 5) Answer (A) they cannot be prevented by making writable pages non-executable Explanation: Arc-injection attacks cannot be prevented by making writing pages nonexecutable because they work by executing code that is already presenting the code segment. They cannot cause buffer overflows (buffer overflows are caused by trying to store too much data into too small of a space, or by poor programmingdepending on your perspective). 6) Answer: (B) Line 6 Explanation: This program is susceptible to a format string vulnerability because an attacker can provide a malicious argument for argv[0] which, when interpreted by the call to printf() on line 6, can result in an arbitrary write. The call to on line 5 is not susceptible to a buffer overflow because the snprintf() function is used, which limits the amount of data written to destination buffer. 7) Answer: (D) Mutually exclusive. Explanation: Race conditions are eliminated by making conflicting race windows mutually exclusive. In other words, once a potential race window begins execution, no conflicting race window can be allowed to execute until the first race window has completed. 8) Answer: (B) It does not check the return value of malloc(). Explanation: It is possible for the call to malloc() to fail and return a NULL pointer, which is then passed as the destination argument to strcpy(). The return value from the call to malloc() does not need to be cast because it is either declared as char * (in older implementations of C) or as void * which does not require a cast. 9) Answer: (C) sizeof(char *) Explanation: When passed to a function, an array type decays into a pointer to the first element in the array the type of the actual argument represented by s in func() is char *. The sizeof(s[0]) a char is always equal to one so size = sizeof(char *). 10) Answer: (A) T * const p; Explanation: When const appears to the right of the * it refers to the pointer p; when it appears to the left of the * it refers to the type T.

Appendix A

This is a living document. Download the most recent version at www.sans-ssi.org. Please send suggestions and comments to spa@sans.org

C Secure Coding Tasks, Skills and Knowledge


This document enumerates common C coding tasks and identifies rules, recommendations, and guidelines for accomplishing these tasks securely. Task 1: C programs must interact securely with their environment. Programs must accept inputs from the environment and properly validate and process these inputs including command line arguments and environment variables. Programs must also be able to invoke external programs in a secure fashion. 01.1.1 Input Validation. The programmer must securely process inputs from all aspects of the environment, then correctly decode, canonicalize, and validate those inputs. Understand and apply secure coding rules: 1. All input sources must be identified. Data from all untrusted sources must be fully specified and the data validated against these specifications. Ensure that all inputs are of the expected data type and are syntactically and semantically valid. 2. Use the strongest form of input validation possible for your program, for example, indirect selection from a menu of choices. 3. Assume that your client can be spoofed or modified in a client/server or threetiered architecture. 4. Reject all input that is too short or too long for the program. 5. Set and enforce reasonable range restrictions. Reject all numeric input that is below the minimum valid value or above the maximum valid value. 6. Do not use functions that input character data and automatically convert the data if these functions do not properly handle all valid inputs. 7. Treat all environmental variables with suspicion. Do not make assumptions about the size, value, or existence of an environment variable. 8. Convert all input into canonical forms, and validate input after the input has been converted (including appropriate decoding). This applies to pathnames and filenames as well as URLs and other input strings that contain character sequences that can be subsequently converted to other sequences. 9. Ensure that each input is only decoded once. Skill in: 1. Preventing vulnerabilities resulting from buffer overflows, path traversal, canonicalization errors, and missing XML validation. 2. Preventing spoofing attacks. 01.1.2 Data sanitization The programmer must correctly sanitize, encode, and pass data to subsystems and external processes in a way that prevents attackers from directly influencing their behavior. Understand and apply secure coding rules: 1. Prevent command injection attacks caused by passing user-controlled input to complex subsystems such as command interpreters. Where user input is required

GSSP(GIACSecureSoftwareProgrammer)

10

for such an invocation, fully specify allowable forms of strings to be passed to the complex subsystem, and sanitize these strings against these specifications prior to invocation. 2. Escape all metacharacters, using built-in functions when available. 3. When interfacing with a relational database, reject all user input that contains SQL metacharacters that are not found in your white list. Escape any SQL metacharacters that your application needs to accept, such as single quotes in names. Always prepare SQL statements. Skill in: 1. Preventing OS command injection, cross-site scripting (XSS), SQL injection and CRLF injection attacks. 01.1.3 Invocation The programmer must invoke external programs by maintaining full control over the environment in which the program runs, ensuring that the correct program is invoked, and only using the expected arguments. Understand and apply secure coding rules: 1. Sanitize the environment before invoking external programs. Consider purging the environment of all environmental variables except those that your program requires, and have these variables default to safe values. 2. Allow for the possibility of multiple environment variables with the same name, or that these variables might contain untrusted values. 3. Ensure that search paths cannot contain any locations that are not under your control or otherwise trusted. 4. Ensure that you have full control over all arguments to the component that you are invoking, stripping out argument separators and quotes. 5. Avoid invoking a general purpose command interpreter to execute a program when the functionality of the command interpreter is not required. This can be accomplished, for example, by using exec() instead of system(). 6. If invocation occurs through externally accessible resources such as named pipes, these resources should verify the integrity and origin of incoming requests. 7. Do not to spawn processes with excessive privileges. 8. Do not pass confidential data to program as command arguments as a user running the ps command may be able to view this data Skill in: 1. Preventing vulnerabilities resulting from untrusted search paths and origin validation errors. 2. Preventing argument Injection attacks. Task 2: C programmers must be able to manage dynamically allocated resources such as dynamically allocated memory. 01.2.1 Memory Management The programmer must properly allocate, manage, and deallocate memory. Understand and apply secure coding rules: 1. Only free memory allocated dynamically. 2. Avoid freeing memory multiple times by allocating and deallocating memory in the same module, at the same level of abstraction; and by techniques such as reference counting. 3. Do not access freed memory. 4. Avoid allocating zero bytes of memory. 5. Ensure that size arguments to memory allocation functions are valid. 6. Free dynamically allocated memory exactly once. 7. Set pointers to deallocated memory to null immediately after freeing the memory.

11

8. Check potentially null pointers for the null value before accessing them. 9. Calculate buffer sizes correctly, allowing for the data type differences such as character width (char vs wchar_t) and the presence of terminating null bytes. 10. Keep track of the size of dynamically allocated memory to avoid buffer overflows. 11. Carefully evaluated rarely executed paths and error handling code for memoryrelated errors. 12. Establish and enforce resource quota to prevent denial-of-service attacks. 13. Do not leave sensitive information exposed in memory longer than required. a. Clear or overwrite all sensitive information stored in memory that is no longer required, for example, before deallocation. b. Use volatile pointers to prevent compiler optimizations from removing these memory wipes from the executable code. c. Completely initialize all memory objects, especially those that might be serialized and transmitted to an untrusted endpoint. Do not realloc() memory containing sensitive information. Skill in: 1. Preventing vulnerabilities resulting from buffer overflows, memory leaks, freeing the same memory multiple times, and writing to already freed memory. 2. Preventing heap inspection and denial-of-service attacks. 01.2.2 Stack Management - The programmer must understand how the stack is used to support program execution and how to properly secure it. Understand and apply secure coding rules: 1. Programmers must understand what information is on allocated on the stack, and how to protect it. 2. Programmers must understand how to prevent the stack from unbounded growth. Skill in: 1. Using the stack securely and efficiently. Task 3: C programmers must be able to perform input/output from streams and files and interact with the operating system to manage the file system. 01.3.1 Formatted Output Programmers must carefully control inputs to formatted output functions. Understand and apply secure coding rules: 1. Do not pass user controlled input into the format parameter of formatted input/output functions such as printf(), fprintf(), and sprintf(). 2. Ensure that all localization strings have the expected format specifiers. 3. For well-formed output such as records, ensure that the fields do not contain separator characters. Skill in: 1. Preventing format string vulnerabilities as well as vulnerabilities resulting from buffer overflows. 2. Preventing memory inspection, information leaks, and denial-of-service attacks. 01.3.2 Stream and File IO Programmers must create, modify, and delete the correct files and streams with appropriate privileges and permissions. Understand and apply secure coding rules: 1. Drop process privileges before writing to a file that can be modified by a user. In general, perform all file I/O with the reduced privileges. 2. Canonicalize file names originating from untrusted sources. 3. Create files and directory structures with appropriate access permissions to prevent unintended access. 4. Test to see if the file already exists when creating a file.

12

5. Prefer functions that do not rely on file names for identification. Identify files using multiple file attributes, for example, by comparing file ownership or creation time. 6. Ensure that file descriptors are not leaked to untrusted processes. 7. Avoid time of check / time of use race conditions. 8. Employ directory restriction operations such as chroot() or jail() to restrict access to files. 9. Use absolute paths where possible for file names to prevent traversal attacks. 10. Avoid the use of functions such as gets() that do not constrain the size of the input. 11. Do not convert the value returned by a character input/output function to char if that value is going to be compared to EOF. Use feof() and ferror() to detect endof-file and file errors. 12. When reading strings don't assume a newline character is read or even that character data has been read. Skill in: 1. Preventing vulnerabilities resulting from race conditions (including TOCTOU) and insecure permissions. 2. Preventing path traversal attacks, symbolic link attacks, and hard link attacks. 01.3.3 Temporary FilesThe programmer must properly create, protect, and delete temporary files. Understand and apply secure coding rules: 1. Avoid creating temporary files in shared directories. If you absolutely must create a temporary file in a shared directory use mkstemp() or the TR 24731-1 tmpfile_s() function. 2. Avoid the use of functions such as tmpnam(), tempnam() and mktemp() that cause race conditions and functions like tmpfile() that may generate predictable names Skill in: 1. Preventing vulnerabilities resulting from race conditions (including TOCTOU) and insecure permissions. 2. Preventing path traversal attacks, symbolic link attacks, and hard link attacks. Task 4: C programmers must be able to employ specific security mechanisms in addition to the core functionality of the program. 01.4.1 Identification, Authorization & AuthenticationThe programmer must properly conduct authentication and prevent attackers from bypassing the authentication to gain access to restricted resources. Understand and apply secure coding rules: 1. Have a basic understanding of the relative strengths of various types of authentication, including two-factor authentication, and their implications on usability. 2. Protect against replay and spoofing attacks. 3. Don't use hard-coded passwords or account names. 4. Use proper hashing to protect passwords. 5. Dont store passwords or keys in plaintext. 6. Employ standardized and known strong protocols and libraries for authentication. 7. Employ authentication commensurate to the value of the data being secured. 8. Where the security value of the data requiring authentication is unknown, allow selection from secure methods of authentication, and set the default to a type of authentication that balances strength with psychological acceptability. 9. Base access decisions on permission rather than exclusion. 10. Understand the role that permissions play in restricting access to resources, the

13

risks associated with privileges, and the need for proper authorization. 11. Always verify the users authorization for a particular resource. Do not base authorization decisions using data that the user can directly modify. Skill in: 1. Preventing authentication bypass by alternative name attacks, alternative path/channel attacks, replay attacks, and spoofing attacks. 01.4.2 Privacy and encryptionThe programmer must protect data at rest or in transit and correctly perform the appropriate encryption and decryption. The programmer must prevent sensitive information from leaking to untrusted parties. The programmer must understand the relative strengths and weaknesses of commonly used cryptographic schemes, including hashing. Understand and apply secure coding rules: 1. Understand the role of encryption in protecting privacy. 2. Never invent your own encryption. Only use well-established schemes that have been subjected to exhaustive public evaluation by trained cryptographers. 3. Understand that randomness plays an important role in cryptographic features, as well as generating unique or unpredictable identifiers, such as user IDs, filenames, or session IDs. Ensure the functions you call generate cryptographic randomness, not statistical randomness. 4. When generating random data for cryptographic operations, gather data from as many sources as possible, append the data into one long string and use a cryptographically secure hash algorithm to hash the data to produce the final random value. 5. Where possible, use standard known interfaces to produce cryptographically random data (but do not use the C99 rand() function which produces predictable values). 6. Use sources with high entropy, but be able to handle when entropy is low. Depending on the technology being used, the source could block or produce numbers that are less random than required. 7. For pseudo-random number generators, use seeds that cannot be predicted by an outsider. Information such as process ID or system time are often predictable. Ensure that you are generating a sufficiently broad range of random numbers, to reduce the chances that they can be guessed using brute force attacks. 8. Avoid storing passwords or encryption keys. Instead, store hashes of the password or key so that provided values can be validated without requiring the storage of the original for comparison. Where password or encryption keys are required for recovery, store the keys on isolated media and use key escrow or splitting techniques if the keys are of a particularly sensitive nature. 9. Try to prevent your process from dumping core and writing an image to disk. 10. Dont provide feedback from error messages, logs, and other sources that provide implementation details or contain sensitive information such as passwords. 11. Avoid security through obscurity. Assume that any security mechanism that your software employs can be reversed engineered by the adversary. 12. Remove debug symbols from the production version of your software. 13. Make sure that incoming data or communications cannot be tampered with, from the source or in transit. 14. Assume that your client (or server) code can be modified or subverted to send data or perform actions that a legitimate process would not. 15. Know the limitations of typical schemes for protecting information. 16. Understand the privacy implications of data that you process, and protect it

14

appropriately. 17. Before transferring data to another process, strip all sensitive data from areas that are not directly under the users control, such as temporary fields. Skill in: 1. Preventing vulnerabilities resulting from insufficient randomness, plaintext storage of sensitive information, weak encryption, reversible one-way hashes, missing required cryptographic steps, key management errors, insufficient entropy in PRNG, predictability, and a small space of random values 01.4.3 Secure designsThe programmer must be able to select or create secure designs and implement these correctly. Understand and apply secure coding rules: 1. Programmers must understand the terminology and basic concepts behind the most common vulnerabilities and attacks to create secure designs and to help avoid implementation errors that could lead to vulnerabilities. 2. Run at the lowest privilege level possible. Perform privileged tasks early, the drop privileges as soon as possible, and follow the correct procedures in dropping them. Where feasible, split privileged code and other code into separate components, and carefully check access between these components. Consider designs that allow components that interact with untrusted data sources to run with reduced privileges. Identify all possible privilege chains, and ensure that multiple privileges cannot be combined to acquire an even greater privilege than you intend. Ensure that operations that drop privilege succeed and properly handle cases where they do not. 3. Avoid trust boundary violation occurs where a program blurs the line between what is trusted and what is untrusted. The most common way to make this mistake is to allow trusted and untrusted data, or data and control flow information, to commingle in the same data structure. 4. Log security relevant events such as login, logoff, and credential changes. Skill in: 1. Developing, selecting, and implementing secure designs. Task 5: C programmers must be able to deal with concurrency issues including issues arriving from concurrent threads, processes, and tasks. 01.5.1 ConcurrencyThe programmer must prevent execution ordering of concurrent flows that results in undesired behavior such as race conditions or deadlock. Understand and apply secure coding rules: 1. Multithreaded programs must be designed carefully to avoid race conditions, deadlock, double-locking, forgetting to unlock, and priority failures such as priority inversion, infinite overtaking, and starvation. The existence of these problems can be induced or aggravated by an attacker. 2. Avoid race conditions by using atomic operations to access shared data. Where these are not possible, employ locking to serialize access to such data, whether it is in the form of files or shared memory. Ensure that concurrency resources, such as locks and shared memory, are only accessible to controlled processes and threads. 3. Avoid time-of-check to time-of-use (TOCTOU) defects, where the security of an operation is checked in one operation, then the operation is performed afterward, by using operating system access checks instead of designing your own access control (never use access()) and by performing file operations on open file descriptors instead of filenames (e.g., use fchmod() instead of chmod()). 4. Do not trust compilers to generate code that is thread-safe. Do not call nonreentrant library functions from within signal handlers.

15

5. Anticipate asynchronous events, such as an interrupted connection in the middle of data transfer. Skill in: 1. Preventing vulnerabilities resulting from signal handler race conditions, time-ofcheck time-of-use (TOCTOU), deadlock, and resource exhaustion. Task 6: C programmers must understand how to use built-in data types and more complex data types based upon these primitive types. 01.6.1 Null-terminated byte strings (NTBS) The programmer must properly use null-terminated byte strings and know about safer alternatives. Understand and apply secure coding rules: 1. Allocate adequate space when copying bounded strings. 2. Guarantee that all NTBS are null-terminated, and that there are no off-by-one errors that cause the null byte to be written to the wrong location, or overwritten by later code. 3. Do not inadvertently truncate strings, particularly while copying. 4. Use safe string libraries, such as CERT managed strings or StrSafe where possible. 5. Validate strings with carefully constructed parsers. Standard string-based formats, such as XML, can be parsed with standard libraries that are often better vetted than custom parsers. 6. Avoid common errors while using null-terminated byte strings a. Avoid object copies through pointers if the objects are not necessarily of the same types. b. Do not provide the length of a buffer in characters to a function that accepts the size of the buffer in bytes, and the other way around. c. Where possible, use only those functions that stick to one convention to avoid confusion. d. Avoid allowing user input to affect the termination condition of a loop e. Do not compare strings by pointer value except where the "atom" pattern is being employed for strings. f. When using standard C string library functions, always allocate sufficient space for the null-termination character. Skill in: 1. Preventing vulnerabilities resulting from buffer overflows, null-termination errors, and string truncation errors. 01.6.2 IntegerThe programmer must correctly manage integers by detecting and avoiding errors related to signedness, overflow, truncation, and range errors. Understand and apply secure coding rules: 1. Avoid integer operations where the result is different from a result that would be obtained using infinite range integers. In particular, eliminate unexpected values resulting from integer overflow, truncation, and sign errors. a. Use explicit width types (e.g. uint32_t, int16_t, DWORD, etc..) for code where the precision of a number must be a specific bit width. b. Use the size_t or rsize_t types when representing the size of an object c. Use unsigned types for values that should never be negative, such as lengths and most array indices and offsets. d. Do not make assumptions about whether or not the char data type is signed. e. Make sure conversions do not result in a loss of data or in misinterpreted data. f. Use safe integer libraries, such as IntSafe or SafeInt, where available. g. Ensure that arithmetic operations can not overflow or that the program

16

detects and correctly handles such overflow. Skill in: 1. Preventing vulnerabilities resulting from integer overflow, integer sign errors, integer truncation, and integer range errors. 01.6.3 Other data types The programmer must correctly manage other data types such as arrays, floats, pointers, and objects. Understand and apply secure coding rules: 1. Arrays a. Be careful using the size of operator to determine the size of an array. b. Guarantee that array indices are within the valid range. c. Use consistent array notation across all source files. d. Ensure size arguments for variable length array are in a valid range. 2. Floating point a. Take granularity into account when comparing floating point values. b. Do not use floating point variables as loop counters. c. Prevent domain errors in math functions. 3. Pointers a. Avoid casting integer values into pointers. b. Avoid pointer arithmetic on pointers that do not point to parts of the same memory object. c. Do not allow user inputs to specify function pointers. 4. Structures a. Validate any offsets that are used within data structures. b. Do not perform byte-by-byte comparisons between structures. c. Do not assume the size of a structure is the sum of the of the sizes of its members. Skill in: 1. Preventing vulnerabilities resulting from array indexing errors and buffer overflows. Task 7: C programmers must correctly handle all error conditions. 01.7.1 Return ValuesThe programmer must handle all possible return values from each function call, including error and unusual conditions. Understand and apply secure coding rules: 1. Check return values for all functions that may return error conditions unless you can demonstrate that the condition under which the function could fail can never happen, or failure is irrelevant to the programs correct, secure, and robust operation. Functions that intuitively can never fail, such as close(), can fail under certain circumstances. 2. If function failure is an unrecoverable error, at least wrap the function in a version that checks the return value and aborts upon error. 3. Always check the return value of malloc() and by nothrow invocations of the new operator. Ensure that you account for all possible return values. Skill in: 1. Preventing vulnerabilities resulting from unchecked return values. 2. Preventing privilege escalation, symbolic link attacks and hard link attacks. Task 8: C programmers must code correctly and use effective coding styles (this is a catch-all category). 01.8.1 Coding style The programmer must follow conventions that make code understandable and maintainable, in a way that minimizes the chances of inadvertently introducing vulnerabilities and improves the chances of discovering existing vulnerabilities and security flaws.

17

Understand and apply secure coding rules: 1. Use a consistent coding style and format. 2. Strive for logical completeness. 3. Use comments consistently and in a readable fashion. 4. Identifiers a. Use visually distinct identifiers to eliminate errors resulting from incorrectly recognizing the spelling of an identifier during the development and review of code. b. Do not define multiple identifiers that vary only with respect to one or more visually similar characters. c. Try to make the initial portions of long identifiers unique for easier recognition. d. Employ consistent naming conventions when naming variables, functions, and other named objects. e. Try to make names explanatory without being overly long. f. Adopt a strategy for short names, for example, i is always an int, and u is always an unsigned int. g. Do not use the same variable name in two scopes where one scope is contained in another. 5. Use parentheses for precedence of operation. 6. Do not employ functions that are known to be dangerous from a security standpoint. Avoid functions that are known to be used erroneously. Either use safe versions of dangerous functions or rewrite the functions entirely using secure design principles. If a dangerous function must be used, then document its limitations and pay careful attention to the code using such functions to ensure that they are used in a manner that will not facilitate a security exploit. 7. Identify dead code during code reviews and remove it. This includes code that cannot be reached for any set of inputs but does not include code that catches impossible cases; this type of code is critical for robustness. 8. Remove unused debug code in the software. Alternately, enclose all optional debug code in conditional compilation structures and explicitly test for the use of the debug code through debug level flags. 9. Constants a. Declare immutable values as rvalues or unmodifiable lvalues. b. Const-qualify objects methods that do not modify the state of the object. c. Declare data members private and use const when returning references to private attributes. d. Do not cast away a const qualification. 10. Preprocessor a. Use the preprocessor judiciously. b. Prefer inline functions to macros. c. Use parentheses around variable names within macros, and macro expansions must always be parenthesized. 11. Avoid implementation-defined behavior and/or document your assumptions. 12. Use standard types of fixed precision (e.g. int32_t) when precision requirements are known. 13. Write code that makes as few assumptions about the underlying system as possible. Where system-dependent operations are required, isolate such operations in system dependent modules. 14. Evaluate the use of security mechanisms provided by your compiler, including buffer overflow protection feature. Skill in:

18

1. Defining and applying coding styles that improve readability and understandability and decrease the chances of introducing new vulnerabilities or improve the chances of discovering existing vulnerabilities. 01.8.2 Code correctlyThe programmer must write correct code, even in cases where incorrect code does not impact program operation in normal use, due to the associated risks. Understand and apply secure coding rules: 1. Avoid errors of omission or addition where necessary characters are omitted, or characters are accidentally included, and the resulting code still compiles cleanly but behaves in an unexpected fashion. For example, do not inadvertently mix assignment and comparison operators within conditional expressions by adding or omitting a = character. 2. Dont take the size of a pointer to determine the size of a type. 3. Operands to the size of operator should not contain side effects. 4. The second operands of the logical AND and OR operators should not contain side effects. 5. Do not cast away a const qualification. 6. Do not depend on order of evaluation between sequence points or reference uninitialized variables. 7. Do not refer to an object outside of its lifetime. 8. All fetches and stores must be within the bounds of an existing object. This is of particular concern when fetching or storing an array element because these operations are largely unchecked. 9. Ensure that all variables are initialized before reading from them. 10. Ensure that your code does not make assumptions about the precision of numeric values unless the variables that store such values can be shown to support such precision. 11. Compile cleanly at high warning levels. Skill in: Preventing vulnerabilities resulting from initialization errors.

19

Appendix B:

Helpful References

Below is a list of some material that will help programmers and security professionals learn more about secure programming. Some of the material will also be helpful in preparing for the assessments. This is not intended as a complete list or an endorsement, but simply as a starter for those interested in learning more. Book References for Software Security 19 Deadly Sins of Software Security Michael Howard, David LeBlanc, John Viega Building Secure Software: How to Avoid Security Problems the Right Way John Viega, Gary McGraw Exploiting Software: How to Break Code Gary McGraw, Greg Hoglund Foundations of Security: What Every Programmer Needs to Know Neil Daswani, Christoph Kern, Anita Kesavan Introduction to Computer Security Matt Bishop J2EE & Java: Developing Secure Web Applications with Java Technology (Hacking Exposed) Art Taylor, Brian Buege, Randy Layman Secure Coding in C and C++ Robert Seacord Secure Coding: Principles and Practices Ken Van Wyk, Mark Graff Hacking Exposed: Web Applications Scambray, Shema, Sima Secure Programming Cookbook for C and C++ John Viega, Matt Messier Security and Usability Simson Garfinkel, Lori Faith Cranor Software Security: Building Security In Gary McGraw The Art of Software Security Assessment: Identifying and Preventing Software Vulnerabilities Mark Dowd, John McDonald, Justin Schuh

20

The Security Development Lifecycle Michael Howard, Steve Lipner Web Security, Privacy & Commerce, Second Edition Simson Garfinkel, Gene Spafford Writing Secure Code, Second Edition Michael Howard, David C. LeBlanc Websites & Podcasts for Software Security: OWASP - Open Web Application Security Project http://www.owasp.org/index.php/Main_Page Microsoft Corporation - Security Developer Center http://msdn2.microsoft.com/en-us/security/aa570401.aspx MITRE - Common Weakness Enumeration (CWE) http://cwe.mitre.org/ CERT - Secure Coding Initiative http://www.cert.org/secure-coding/

21

Potrebbero piacerti anche