2009 CWE/SANS TOP 25 MOST DANGEROUS PROGRAMMING ERRORS POROUS DEFENSES BRIAN STRICKLIN 2009 CWE/SANS TOP 25 MOST DANGEROUS PROGRAMMING ERRORS CWE: Common Weakness Enumeration SANS: SysAdmin, Audit, Networking, and Security Basically a community that provides a unified, measureable set of SW weaknesses Provide computer security training Among more than 700 security weaknesses that can lead to exploitable vulnerabilities POROUS DEFENSES Defensive techniques that are often misused, abused, or just plain ignored POROUS DEFENSES CWE-285: Improper Access Control (Authorization) CWE-327: Use of a Broken or Risky Cryptographic Algorithm CWE-259: Hard-Coded Password CWE-732: Insecure Permission Assignment for Critical Resource CWE-330: Use of Insufficiently Random Values CWE-250: Execution with Unnecessary Privileges CWE-602: Client-Side Enforcement of Server-Side Security CWE-285: IMPROPER ACCESS CONTROL (AUTHORIZATION) SUMMARY When access controls are not applied consistently, or at all If you don't ensure that users are only doing what they're allowed -- attackers will try to exploit this and perform unauthorized functions that you only intended for restricted users This can lead to a wide range of problems, including information leaks and denial of service CWE-285: IMPROPER ACCESS CONTROL (AUTHORIZATION) Time of Introduction Architecture and Design Implementation Operation Common Consequences Availability Confidentiality Integrity Allowing access to unauthorized users can result in an attacker gaining access to the sensitive resources being protected, possibly modifying or removing them, or performing unauthorized actions. Likelihood of Exploit High CWE-285: IMPROPER ACCESS CONTROL (AUTHORIZATION) POTENTIAL MITIGATIONS Divide the application into anonymous, normal, privileged, and administrative areas. Map roles with data and functionality. Use role-based access control (RBAC) to enforce the roles at the appropriate boundaries. Note that this will not protect a user from attacking others with the same role. Use known good authorization frameworks. Use the access control capabilities of your OS and server environment and define your access control lists accordingly. Use a "default deny" policy when defining ACLs. CWE-327: USE OF A BROKEN OR RISKY CRYPTOGRAPHIC ALGORITHM INTRODUCTION If you are handling sensitive data or you need to protect a communication channel, you may be using cryptography to prevent attackers from reading it. You may be tempted to develop your own encryption scheme in the hopes of making it difficult for attackers to crack. This kind of grow-your-own cryptography is a welcome sight to attackers. Cryptography is just plain hard. If brilliant mathematicians and computer scientists worldwide can't get it right, you probably won’t either. You might think you created a brand-new algorithm that nobody will figure out, but it's more likely that you're reinventing the wheel. CWE-327: USE OF A BROKEN OR RISKY CRYPTOGRAPHIC ALGORITHM SUMMARY The use of a broken or risky cryptographic algorithm is an unnecessary risk that may result in the disclosure of sensitive information The use of a non-standard algorithm is dangerous because a determined attacker may be able to break the algorithm and compromise whatever data has been protected CWE-327: USE OF A BROKEN OR RISKY CRYPTOGRAPHIC ALGORITHM Time of Introduction Common Consequences Architecture and Design Confidentiality The confidentiality of sensitive data may be compromised. Integrity The integrity of sensitive data may be compromised. Accountability Any accountability to message content preserved by cryptography may be subject to attack. Likelihood of Exploit Medium to High DEMONSTRATIVE EXAMPLES These code examples use the Data Encryption Standard (DES). Once considered a strong algorithm, it is now regarded as insufficient for many applications. It has been replaced by Advanced Encryption Standard (AES). C/C++ Example: EVP_des_ecb(); Java Example: Cipher des=Cipher.getInstance("DES..."); des.initEncrypt(key2); OBSERVED EXAMPLES Default configuration of product uses MD5 instead of stronger algorithms that are available, simplifying forgery of certificates. Product substitutes characters with other characters in a fixed way, and also leaves certain input characters unchanged. Attackers can infer private IP addresses by dividing each octet by the MD5 hash of '20'. product only uses "XOR" to obfuscate sensitive data product only uses "XOR" and a fixed key to obfuscate sensitive data Product uses the hash of a hash for authentication, allowing attackers to gain privileges if they can obtain the original hash. Product uses DES when MD5 has been specified in the configuration, resulting in weaker-than-expected password hashes. Product uses "ROT-25" to obfuscate the password in the registry. CWE-327: USE OF A BROKEN OR RISKY CRYPTOGRAPHIC ALGORITHM POTENTIAL MITIGATIONS Do not develop your own cryptographic algorithms. They will likely be exposed to attacks that are well-understood by cryptographers. Reverse engineering techniques are mature. Use a well-vetted algorithm that is currently considered to be strong by experts in the field, and select well-tested implementations. Periodically ensure that you aren't using obsolete cryptography. Some older algorithms, once thought to require a billion years of computing time, can now be broken in days or hours. Design your software so that you can replace one cryptographic algorithm with another. This will make it easier to upgrade to stronger algorithms. CWE-259: HARD-CODED PASSWORD INTRODUCTION Hard-coding a password into your software's authentication module is extremely convenient - for skilled reverse engineers. While it might shrink testing and support budgets, it can greatly reduce the security of software. CWE-259: HARD-CODED PASSWORD SUMMARY Inbound Authentication: the software contains an authentication mechanism that checks for a hard-coded password. Outbound Communication: the software connects to another system or component, and it contains hard-coded password for connecting to that component. CWE-259: HARD-CODED PASSWORD Time of Introduction Implementation Architecture and Design Common Consequences Authentication If hard-coded passwords are used, it is almost certain that malicious users will gain access through the account in question. Likelihood of Exploit Very High DEMONSTRATIVE EXAMPLE The following code uses a hard-coded password to connect to a database, this is an external hard-coded password: ... DriverManager.getConnection(url, "scott", "tiger"); ... Once the program has shipped, there is no going back from the database user "scott" with a password of "tiger" unless the program is patched. If attackers can access the byte code for the application, they can access the disassembled code. The result of this operation might look something like the following for the example above: javap -c ConnMngr.class 22: ldc #36; //String jdbc:mysql://ixne.com/rxsql 24: ldc #38; //String scott 26: ldc #17; //String tiger DEMONSTRATIVE EXAMPLE Example of an internal hard-coded password in the back-end: C/C++ Example: int VerifyAdmin(char *password) { if (strcmp(password, "Mew!")) { printf("Incorrect Password!\n"); return(0) } printf("Entering Diagnostic Mode...\n"); return(1); } CWE-259: HARD-CODED PASSWORD POTENTIAL MITIGATIONS For outbound authentication: store passwords outside of the code in a strongly-protected, encrypted configuration file or database that is protected from access by others. Properly protect the key. For inbound authentication: Rather than hard-code a default username and password for first time logins, utilize a "first login" mode that requires the user to enter a unique strong password. Perform access control checks and limit which entities can access the feature that requires the hard-coded password. CWE-732: INSECURE PERMISSION ASSIGNMENT FOR CRITICAL RESOURCE INTRODUCTION The software specifies permissions for a security-critical resource in a way that allows that resource to be read or modified by unintended actors. When a resource is given a permissions setting that provides access to a wider range of actors than required, it could lead to the disclosure of sensitive information, or the modification of that resource by unintended parties. CWE-732: INSECURE PERMISSION ASSIGNMENT FOR CRITICAL RESOURCE Time of Introduction Architecture and Design Implementation Installation Operation Likelihood of Exploit Medium to High CWE-732: INSECURE PERMISSION ASSIGNMENT FOR CRITICAL RESOURCE POTENTIAL MITIGATIONS When using a critical resource such as a configuration file, check to see if the resource has insecure permissions (such as being modifiable by any regular user), and generate an error or even exit the software if there is a possibility that the resource could have been modified by an unauthorized party. Divide the application into anonymous, normal, privileged, and administrative areas. Define distinct user groups, privileges, and roles. Map these against data, functionality, and the related resources. Then set the permissions accordingly. During program startup, explicitly set the default permissions to the most restrictive setting possible. CWE-330: USE OF INSUFFICIENTLY RANDOM VALUES INTRODUCTION Software may use insufficiently random numbers or values in a security context that depends on unpredictable numbers. Image how quickly a Las Vegas casino would go out of business if gamblers could predict the next roll of the dice, spin of the wheel, or turn of the card. If you use security features that require good randomness, but you don't provide it, then you'll have attackers laughing all the way to the bank. Pseudo-Random Number Generators (PRNG) are commonly used, but a variety of things can go wrong. Once an attacker can determine which algorithm is being used, they can guess the next random number often enough to launch a successful attack after a relatively small number of tries. When software receives predictable values in a context requiring unpredictability, it may be possible for an attacker to guess those predictable values, and use this guess to impersonate another user or access sensitive information. CWE-330: USE OF INSUFFICIENTLY RANDOM VALUES Computers are deterministic machines, and as such are unable to produce true randomness. Pseudo-Random Number Generators (PRNGs) approximate randomness algorithmically, starting with a seed from which subsequent values are calculated. There are two types of PRNGs: statistical and cryptographic. Statistical PRNGs provide useful statistical properties, but their output is highly predictable and forms an easy to reproduce numeric stream that is unsuitable for use in cases where security depends on generated values being unpredictable. Cryptographic PRNGs address this problem by generating output that is more difficult to predict. For a value to be cryptographically secure, it must be impossible or highly improbable for an attacker to distinguish between it and a truly random value. CWE-330: USE OF INSUFFICIENTLY RANDOM VALUES Time of Introduction Architecture and Design Likelihood of Exploit Medium to High DEMONSTRATIVE EXAMPLE The following code uses a statistical PRNG to create a URL for a receipt that remains active for some period of time after a purchase. String GenerateReceiptURL(String baseUrl) { Random ranGen = new Random(); ranGen.setSeed((new Date()).getTime()); return(baseUrl + Gen.nextInt(400000000) + ".html"); } This code uses the Random.nextInt() function to generate "unique" identifiers for the receipt pages it generates. Because Random.nextInt() is a statistical PRNG, it is easy for an attacker to guess the strings it generates. It would be more secure if it used a random number generator that did not produce predictable receipt identifiers, such as a cryptographic PRNG. CWE-330: USE OF INSUFFICIENTLY RANDOM VALUES POTENTIAL MITIGATIONS Use a well-vetted algorithm that is currently considered to be strong by experts in the field, and select well-tested implementations with adequate length seeds. In general, if a pseudo-random number generator is not advertised as being cryptographically secure, then it is probably a statistical PRNG and should not be used in security-sensitive contexts. Perform tests on data to catch obvious entropy problems. Attach a monitor to the process and look for library functions that indicate when randomness is being used. Run the process multiple times to see if the seed changes. Look for library or system calls that access predictable information such as process IDs and system time. CWE-250: EXECUTION WITH UNNECESSARY PRIVILEGES SUMMARY The software performs an operation at a privilege level that is higher than the minimum level required creates new weaknesses or amplifies the consequences of other weaknesses. SW performing as root or Administrator, can disable the normal security checks being performed by the OS or surrounding environment. Other pre-existing weaknesses can turn into security vulnerabilities if they occur while operating at raised privileges. CWE-250: EXECUTION WITH UNNECESSARY PRIVILEGES Time of Introduction Common Consequences Installation Architecture and Design Operation Confidentiality Integrity Availability An attacker will be able to gain access to any resources that are allowed by the extra privileges. Common results include executing code, disabling services, and reading restricted data. Likelihood of Exploit Medium OBSERVED EXAMPLES Installation script installs some programs as setuid when they shouldn't be. OS incorrectly installs a program with setuid privileges, allowing users to gain privileges. FTP client program on a certain OS runs with setuid privileges and has a buffer overflow. Most clients do not need extra privileges, so an overflow is not a vulnerability for those clients. Program does not drop privileges before calling another program, allowing code execution. setuid root program allows creation of arbitrary files through command line argument. Program runs with privileges and calls another program with the same privileges, which allows read of arbitrary files. Composite: application running with high privileges allows user to specify a restricted file to process, which generates a parsing error that leaks the contents of the file. CWE-250: EXECUTION WITH UNNECESSARY PRIVILEGES POTENTIAL MITIGATIONS Identify the functionality that requires additional privileges, such as access to privileged operating system resources. Wrap and centralize this functionality if possible, and isolate the privileged code as much as possible from other code. Raise privileges as late as possible, and drop them as soon as possible, and make sure privileges have been dropped successfully. Perform extensive input validation for any privileged code that must be exposed to the user and reject anything that does not fit your strict requirements. If circumstances force you to run with extra privileges, then determine the minimum access level necessary. First identify the different permissions that the software and its users will need to perform their actions, such as file read and write permissions or network socket permissions. Then explicitly allow those actions while denying all else. CWE-602: CLIENT-SIDE ENFORCEMENT OF SERVER-SIDE SECURITY INTRODUCTION The software has a server that relies on the client to implement a mechanism that is intended to protect the server. When the server relies on protection mechanisms placed on the client side, an attacker can modify the client-side behavior to bypass the protection. CWE-602: CLIENT-SIDE ENFORCEMENT OF SERVER-SIDE SECURITY Time of Introduction Architecture and Design Likelihood of Exploit Medium CLIENT-SIDE (client.pl) … $sock = OpenSocket($server, 1234); writeSocket($sock, "AUTH $username $password\n"); $resp = readSocket($sock); if ($resp eq "success") { # username/pass is valid, go ahead and update the info! writeSocket($sock, "CHANGE-ADDRESS $username $address\n"; } else { print "ERROR: Invalid Authentication!\n"; } SERVER-SIDE (server.pl): $sock = acceptSocket(1234); ($cmd, $args) = ParseClientRequest($sock); if ($cmd eq "AUTH") { ($username, $pass) = split(/\s+/, $args, 2); $result = AuthenticateUser($username, $pass); writeSocket($sock, "$result\n"); # does not close the socket on failure; assumes the # user will try again } elsif ($cmd eq "CHANGE-ADDRESS") { if (validateAddress($args)) { $res = UpdateDatabaseRecord($username, "address", $args); writeSocket($sock, "SUCCESS\n"); } else { writeSocket($sock, "FAILURE -- address is malformed\n"); } } CWE-602: CLIENT-SIDE ENFORCEMENT OF SERVER-SIDE SECURITY POTENTIAL MITIGATIONS For any security checks that are performed on the client side, ensure that these checks are duplicated on the server side. Attackers can bypass the client-side checks by modifying values after the checks have been performed, or by changing the client to remove the client-side checks entirely. Use integrity checking and strong authentication to ensure that the inputs are coming from a trusted source. 2009 CWE/SANS TOP 25 MOST DANGEROUS PROGRAMMING ERRORS POROUS DEFENSES All information from this presentation is available at Top 25 Most Dangerous Programming Errors http://cwe.mitre.org/top25/