The software uses external input to construct a pathname that should be within a restricted directory, but it does not properly neutralize absolute path sequences such as "/abs/path" that can resolve to a location that is outside of that directory.
Extended Description
This allows attackers to traverse the file system to access files or directories that are outside of the restricted directory.
Time of Introduction
Architecture and Design
Implementation
Applicable Platforms
Languages
All
Common Consequences
Scope
Effect
Integrity
Confidentiality
Availability
Technical Impact: Execute unauthorized code or
commands
The attacker may be able to create or overwrite critical files that
are used to execute code, such as programs or libraries.
Integrity
Technical Impact: Modify files or
directories
The attacker may be able to overwrite or create critical files, such
as programs, libraries, or important data. If the targeted file is used
for a security mechanism, then the attacker may be able to bypass that
mechanism. For example, appending a new account at the end of a password
file may allow an attacker to bypass authentication.
Confidentiality
Technical Impact: Read files or
directories
The attacker may be able read the contents of unexpected files and
expose sensitive data. If the targeted file is used for a security
mechanism, then the attacker may be able to bypass that mechanism. For
example, by reading a password file, the attacker could conduct brute
force password guessing attacks in order to break into an account on the
system.
Availability
Technical Impact: DoS: crash / exit /
restart
The attacker may be able to overwrite, delete, or corrupt unexpected
critical files such as programs, libraries, or important data. This may
prevent the software from working at all and in the case of a protection
mechanisms such as authentication, it has the potential to lockout every
user of the software.
Demonstrative Examples
Example 1
In the example below, the path to a dictionary file is read from a
system property and used to initialize a File object.
However, the path is not validated or modified to prevent it from
containing absolute path sequences before creating the File object. This
allows anyone who can control the system property to determine what file
is used. Ideally, the path should be resolved relative to some kind of
application or user home directory.
Example 2
The following code demonstrates the unrestricted upload of a file
with a Java servlet and a path traversal vulnerability. The action attribute
of an HTML form is sending the upload file request to the Java
servlet.
When submitted the Java servlet's doPost method will receive the
request, extract the name of the file from the Http request header, read
the file contents from the request and output the file to the local
upload directory.
(Bad Code)
Example
Language: Java
public class FileUploadServlet extends HttpServlet {
BufferedWriter bw = new BufferedWriter(new
FileWriter(uploadLocation+filename, true));
for (String line; (line=br.readLine())!=null; )
{
if (line.indexOf(boundary) == -1) {
bw.write(line);
bw.newLine();
bw.flush();
}
} //end of for loop
bw.close();
} catch (IOException ex) {...}
// output successful upload response HTML page
}
// output unsuccessful upload response HTML page
else
{...}
}
...
}
As with the previous example this code does not perform a check on the
type of the file being uploaded. This could allow an attacker to upload
any executable file or other file with malicious code.
Additionally, the creation of the BufferedWriter object is subject to relative path traversal (CWE-22, CWE-23). Depending on the executing environment, the attacker may be able to specify arbitrary files to write to, leading to a wide variety of consequences, from code execution, XSS (CWE-79), or system crash.
Mail client allows remote attackers to overwrite
arbitrary files via an e-mail message containing a uuencoded attachment that
specifies the full pathname for the file to be modified.
FTP server allows remote attackers to list
arbitrary directories by using the "ls" command and including the drive
letter name (e.g. C:) in the requested pathname.
Remote attackers can read arbitrary files via an
HTTP request whose argument is a filename of the form "C:" (Drive letter),
"//absolute/path", or ".." .
FTP server allows a remote attacker to retrieve
privileged web server system information by specifying arbitrary paths in
the UNC format (\\computername\sharename).
[REF-7] Mark Dowd, John McDonald
and Justin Schuh. "The Art of Software Security Assessment". Chapter 9, "Filenames and Paths", Page
503.. 1st Edition. Addison Wesley. 2006.
Acceptance of Extraneous Untrusted Data With Trusted Data
Definition in a New Window
Weakness ID: 349 (Weakness Base)
Status: Draft
Description
Description Summary
The software, when processing trusted data, accepts any untrusted data that is also included with the trusted data, treating the untrusted data as if it were trusted.
Time of Introduction
Architecture and Design
Implementation
Applicable Platforms
Languages
All
Common Consequences
Scope
Effect
Access Control
Integrity
Technical Impact: Bypass protection
mechanism; Modify application
data
An attacker could package untrusted data with trusted data to bypass
protection mechanisms to gain access to and possibly modify sensitive
data.
Access of Resource Using Incompatible Type ('Type Confusion')
Definition in a New Window
Weakness ID: 843 (Weakness Base)
Status: Incomplete
Description
Description Summary
The program allocates or initializes a resource such as a pointer, object, or variable using one type, but it later accesses that resource using a type that is incompatible with the original type.
Extended Description
When the program accesses the resource using an incompatible type, this could trigger logical errors because the resource does not have expected properties. In languages without memory safety, such as C and C++, type confusion can lead to out-of-bounds memory access.
While this weakness is frequently associated with unions when parsing data with many different embedded object types in C, it can be present in any application that can interpret the same variable or memory location in multiple ways.
This weakness is not unique to C and C++. For example, errors in PHP applications can be triggered by providing array parameters when scalars are expected, or vice versa. Languages such as Perl, which perform automatic conversion of a variable of one type when it is accessed as if it were another type, can also contain these issues.
Alternate Terms
Object Type Confusion
Time of Introduction
Implementation
Applicable Platforms
Languages
C
C++
Language-independent
Type-unsafe Languages
Demonstrative Examples
Example 1
The following code uses a union to support the representation of
different types of messages. It formats messages differently, depending on
their type.
(Bad Code)
Example
Language: C
#define NAME_TYPE 1
#define ID_TYPE 2
struct MessageBuffer
{
int msgType;
union {
char *name;
int nameID;
};
};
int main (int argc, char **argv) {
struct MessageBuffer buf;
char *defaultMessage = "Hello World";
buf.msgType = NAME_TYPE;
buf.name = defaultMessage;
printf("Pointer of buf.name is %p\n", buf.name);
/* This particular value for nameID is used to make the
code architecture-independent. If coming from untrusted input,
it could be any value. */
buf.nameID = (int)(defaultMessage + 1);
printf("Pointer of buf.name is now %p\n", buf.name);
if (buf.msgType == NAME_TYPE) {
printf("Message: %s\n", buf.name);
}
else {
printf("Message: Use ID %d\n", buf.nameID);
}
}
The code intends to process the message as a NAME_TYPE, and sets the
default message to "Hello World." However, since both buf.name and
buf.nameID are part of the same union, they can act as aliases for the
same memory location, depending on memory layout after
compilation.
As a result, modification of buf.nameID - an int - can effectively
modify the pointer that is stored in buf.name - a string.
Execution of the program might generate output such as:
Pointer of name is 10830
Pointer of name is now 10831
Message: ello World
Notice how the pointer for buf.name was changed, even though buf.name
was not explicitly modified.
In this case, the first "H" character of the message is omitted.
However, if an attacker is able to fully control the value of
buf.nameID, then buf.name could contain an arbitrary pointer, leading to
out-of-bounds reads or writes.
Example 2
The following PHP code accepts a value, adds 5, and prints the
sum.
(Bad Code)
Example
Language: PHP
$value = $_GET['value'];
$sum = $value + 5;
echo "value parameter is '$value'<p>";
echo "SUM is $sum";
When called with the following query string:
value=123
the program calculates the sum and prints out:
SUM is 128
However, the attacker could supply a query string such as:
value[]=123
The "[]" array syntax causes $value to be treated as an array type,
which then generates a fatal error when calculating $sum:
Fatal error: Unsupported operand types in program.php on line
2
Example 3
The following Perl code is intended to look up the privileges for
user ID's between 0 and 3, by performing an access of the
$UserPrivilegeArray reference. It is expected that only userID 3 is an admin
(since this is listed in the third element of the array).
(Bad Code)
Example
Language: Perl
my $UserPrivilegeArray = ["user", "user", "admin", "user"];
In this case, the programmer intended to use
"$UserPrivilegeArray->{$userID}" to access the proper position in
the array. But because the subscript was omitted, the "user" string was
compared to the scalar representation of the $UserPrivilegeArray
reference, which might be of the form "ARRAY(0x229e8)" or
similar.
Since the logic also "fails open" (CWE-636), the result of this bug is that all users are assigned administrator privileges.
While this is a forced example, it demonstrates how type confusion can
have security consequences, even in memory-safe languages.
Improperly-parsed file containing records of
different types leads to code execution when a memory location is
interpreted as a different object than
intended.
Type confusion weaknesses have received some attention by applied
researchers and major software vendors for C and C++ code. Some
publicly-reported vulnerabilities probably have type confusion as a
root-cause weakness, but these may be described as "memory corruption"
instead. This weakness seems likely to gain prominence in upcoming
years.
For other languages, there are very few public reports of type confusion
weaknesses. These are probably under-studied. Since many programs rely
directly or indirectly on loose typing, a potential "type confusion"
behavior might be intentional, possibly requiring more manual
analysis.
[REF-7] Mark Dowd, John McDonald
and Justin Schuh. "The Art of Software Security Assessment". Chapter 7, "Type Confusion", Page 319.. 1st Edition. Addison Wesley. 2006.
Access to Critical Private Variable via Public Method
Definition in a New Window
Weakness ID: 767 (Weakness Variant)
Status: Incomplete
Description
Description Summary
The software defines a public method that reads or modifies a private variable.
Extended Description
If an attacker modifies the variable to contain unexpected values, this could violate assumptions from other parts of the code. Additionally, if an attacker can read the private variable, it may expose sensitive information or make it easier to launch further attacks.
Time of Introduction
Architecture and Design
Implementation
Applicable Platforms
Languages
C++
C#
Java
Common Consequences
Scope
Effect
Integrity
Other
Technical Impact: Modify application
data; Other
Likelihood of Exploit
Low to Medium
Demonstrative Examples
Example 1
The following example declares a critical variable to be private,
and then allows the variable to be modified by public methods.
(Bad Code)
Example
Language: C++
private: float price;
public: void changePrice(float newPrice) {
price = newPrice;
}
Example 2
The following example could be used to implement a user forum where
a single user (UID) can switch between multiple profiles (PID).
(Bad Code)
Example
Language: Java
public class Client {
private int UID;
public int PID;
private String userName;
public Client(String userName){
PID = getDefaultProfileID();
UID = mapUserNametoUID( userName );
this.userName = userName;
}
public void setPID(int ID) {
UID = ID;
}
}
The programmer implemented setPID with the intention of modifying the
PID variable, but due to a typo. accidentally specified the critical
variable UID instead. If the program allows profile IDs to be between 1
and 10, but a UID of 1 means the user is treated as an admin, then a
user could gain administrative privileges as a result of this
typo.
Potential Mitigations
Phase: Implementation
Use class accessor and mutator methods appropriately. Perform
validation when accepting data from a public method that is intended to
modify a critical private variable. Also be sure that appropriate access
controls are being applied when a public method interfaces with critical
data.
This entry is closely associated with access control for public methods.
If the public methods are restricted with proper access controls, then the
information in the private variable will not be exposed to unexpected
parties. There may be chaining or composite relationships between improper
access controls and this weakness.
The accidental addition of a data-structure sentinel can cause serious programming logic problems.
Extended Description
Data-structure sentinels are often used to mark the structure of data. A common example of this is the null character at the end of strings or a special sentinel to mark the end of a linked list. It is dangerous to allow this type of control data to be easily accessible. Therefore, it is important to protect from the addition or modification of sentinels.
Time of Introduction
Architecture and Design
Implementation
Applicable Platforms
Languages
C
C++
Common Consequences
Scope
Effect
Integrity
Technical Impact: Modify application
data
Generally this error will cause the data structure to not work
properly by truncating the data.
Likelihood of Exploit
High to Very High
Demonstrative Examples
Example 1
The following example assigns some character values to a list of
characters and prints them each individually, and then as a string. The
third character value is intended to be an integer taken from user input and
converted to an int.
The first print statement will print each character separated by a
space. However, if a non-integer is read from stdin by getc, then atoi
will not make a conversion and return 0. When foo is printed as a
string, the 0 at character foo[2] will act as a NULL terminator and
foo[3] will never be printed.
Potential Mitigations
Phases: Implementation; Architecture and Design
Encapsulate the user from interacting with data sentinels. Validate
user input to verify that sentinels are not present.
Phase: Implementation
Proper error checking can reduce the risk of inadvertently introducing
sentinel values into data. For example, if a parsing function fails or
encounters an error, it might return a value that is the same as the
sentinel.
Phase: Architecture and Design
Use an abstraction library to abstract away risky APIs. This is not a
complete solution.
Phase: Operation
Use OS-level preventative functionality. This is not a complete
solution.
An algorithm in a product has an inefficient worst-case computational complexity that may be detrimental to system performance and can be triggered by an attacker, typically using crafted manipulations that ensure that the worst case is being reached.
Product allows attackers to cause multiple copies
of a program to be loaded more quickly than the program can detect that
other copies are running, then exit. This type of error should probably have
its own category, where teardown takes more time than
initialization.
Network monitoring system allows remote attackers
to cause a denial of service (CPU consumption and detection outage) via
crafted network traffic, aka a "backtracking
attack."
Wiki allows remote attackers to cause a denial of
service (CPU consumption) by performing a diff between large, crafted pages
that trigger the worst case algorithmic
complexity.
Wiki allows remote attackers to cause a denial of
service (CPU consumption) by performing a diff between large, crafted pages
that trigger the worst case algorithmic complexity.
Allocation of File Descriptors or Handles Without Limits or Throttling
Definition in a New Window
Weakness ID: 774 (Weakness Variant)
Status: Incomplete
Description
Description Summary
The software allocates file descriptors or handles on behalf of an actor without imposing any restrictions on how many descriptors can be allocated, in violation of the intended security policy for that actor.
Extended Description
This can cause the software to consume all available file descriptors or handles, which can prevent other processes from performing critical file processing operations.
When allocating resources without limits, an attacker could prevent
all other processes from accessing the same type of resource.
Likelihood of Exploit
Medium to High
Potential Mitigations
Phases: Operation; Architecture and Design
Strategy: Limit Resource Consumption
Use resource-limiting settings provided by the operating system or
environment. For example, when managing system resources in POSIX,
setrlimit() can be used to set limits for certain types of resources,
and getrlimit() can determine how many resources are available. However,
these functions are not available on all operating systems.
When the current levels get close to the maximum that is defined for the application (see CWE-770), then limit the allocation of further resources to privileged users; alternately, begin releasing resources for less-privileged users. While this mitigation may protect the system from attack, it will not necessarily stop attackers from adversely impacting other users.
Ensure that the application performs the appropriate error checks and error handling in case resources become unavailable (CWE-703).
Vulnerability theory is largely about how behaviors and resources
interact. "Resource exhaustion" can be regarded as either a consequence or
an attack, depending on the perspective. This entry is an attempt to reflect
one of the underlying weaknesses that enable these attacks (or consequences)
to take place.
References
[REF-7] Mark Dowd, John McDonald
and Justin Schuh. "The Art of Software Security Assessment". Chapter 10, "Resource Limits", Page 574.. 1st Edition. Addison Wesley. 2006.
Allocation of Resources Without Limits or Throttling
Definition in a New Window
Weakness ID: 770 (Weakness Base)
Status: Incomplete
Description
Description Summary
The software allocates a reusable resource or group of resources on behalf of an actor without imposing any restrictions on how many resources can be allocated, in violation of the intended security policy for that actor.
When allocating resources without limits, an attacker could prevent
other systems, applications, or processes from accessing the same type
of resource.
Likelihood of Exploit
Medium to High
Detection Methods
Manual Static Analysis
Manual static analysis can be useful for finding this weakness, but it
might not achieve desired code coverage within limited time constraints.
If denial-of-service is not considered a significant risk, or if there
is strong emphasis on consequences such as code execution, then manual
analysis may not focus on this weakness at all.
Fuzzing
While fuzzing is typically geared toward finding low-level
implementation bugs, it can inadvertently find uncontrolled resource
allocation problems. This can occur when the fuzzer generates a large
number of test cases but does not restart the targeted software in
between test cases. If an individual test case produces a crash, but it
does not do so reliably, then an inability to limit resource allocation
may be the cause.
When the allocation is directly affected by numeric inputs, then
fuzzing may produce indications of this weakness.
Effectiveness: Opportunistic
Automated Dynamic Analysis
Certain automated dynamic analysis techniques may be effective in
producing side effects of uncontrolled resource allocation problems,
especially with resources such as processes, memory, and connections.
The technique may involve generating a large number of requests to the
software within a short time frame. Manual analysis is likely required
to interpret the results.
Automated Static Analysis
Specialized configuration or tuning may be required to train automated
tools to recognize this weakness.
Automated static analysis typically has limited utility in recognizing
unlimited allocation problems, except for the missing release of
program-independent system resources such as files, sockets, and
processes, or unchecked arguments to memory. For system resources,
automated static analysis may be able to detect circumstances in which
resources are not released after they have expired, or if too much of a
resource is requested at once, as can occur with memory. Automated
analysis of configuration files may be able to detect settings that do
not specify a maximum value.
Automated static analysis tools will not be appropriate for detecting
exhaustion of custom resources, such as an intended security policy in
which a bulletin board user is only allowed to make a limited number of
posts per day.
Demonstrative Examples
Example 1
This code allocates a socket and forks each time it receives a new
connection.
(Bad Code)
Example Languages: C and C++
sock=socket(AF_INET, SOCK_STREAM, 0);
while (1) {
newsock=accept(sock, ...);
printf("A connection has been accepted\n");
pid = fork();
}
The program does not track how many connections have been made, and it
does not limit the number of connections. Because forking is a
relatively expensive operation, an attacker would be able to cause the
system to run out of CPU, processes, or memory by making a large number
of connections. Alternatively, an attacker could consume all available
connections, preventing others from accessing the system
remotely.
Example 2
In the following example a server socket connection is used to
accept a request to store data on the local file system using a specified
filename. The method openSocketConnection establishes a server socket to
accept requests from a client. When a client establishes a connection to
this service the getNextMessage method is first used to retrieve from the
socket the name of the file to store the data, the openFileToWrite method
will validate the filename and open a file to write to on the local file
system. The getNextMessage is then used within a while loop to continuously
read data from the socket and output the data to the file until there is no
longer any data from the socket.
(Bad Code)
Example Languages: C and C++
int writeDataFromSocketToFile(char *host, int port)
{
char filename[FILENAME_SIZE];
char buffer[BUFFER_SIZE];
int socket = openSocketConnection(host, port);
if (socket < 0) {
printf("Unable to open socket connection");
return(FAIL);
}
if (getNextMessage(socket, filename, FILENAME_SIZE) >
0) {
if (openFileToWrite(filename) > 0) {
while (getNextMessage(socket, buffer, BUFFER_SIZE)
> 0){
if (!(writeToFile(buffer) > 0))
break;
}
}
closeFile();
}
closeSocket(socket);
}
This example creates a situation where data can be dumped to a file on
the local file system without any limits on the size of the file. This
could potentially exhaust file or disk resources and/or limit other
clients' ability to access the service.
Example 3
In the following example, the processMessage method receives a two
dimensional character array containing the message to be processed. The
two-dimensional character array contains the length of the message in the
first character array and the message body in the second character array.
The getMessageLength method retrieves the integer value of the length from
the first character array. After validating that the message length is
greater than zero, the body character array pointer points to the start of
the second character array of the two-dimensional character array and memory
is allocated for the new body character array.
(Bad Code)
Example Languages: C and C++
/* process message accepts a two-dimensional character array of
the form [length][body] containing the message to be processed
*/
int processMessage(char **message)
{
char *body;
int length = getMessageLength(message[0]);
if (length > 0) {
body = &message[1][0];
processMessageBody(body);
return(SUCCESS);
}
else {
printf("Unable to process message; invalid message
length");
return(FAIL);
}
}
This example creates a situation where the length of the body
character array can be very large and will consume excessive memory,
exhausting system resources. This can be avoided by restricting the
length of the second character array with a maximum length check
Also, consider changing the type from 'int' to 'unsigned int', so that you are always guaranteed that the number is positive. This might not be possible if the protocol specifically requires allowing negative values, or if you cannot control the return value from getMessageLength(), but it could simplify the check to ensure the input is positive, and eliminate other errors such as signed-to-unsigned conversion errors (CWE-195) that may occur elsewhere in the code.
(Good Code)
Example Languages: C and C++
unsigned int length = getMessageLength(message[0]);
if ((length > 0) && (length <
MAX_LENGTH)) {...}
Example 4
In the following example, a server object creates a server socket
and accepts client connections to the socket. For every client connection to
the socket a separate thread object is generated using the
ClientSocketThread class that handles request made by the client through the
socket.
(Bad Code)
Example
Language: Java
public void acceptConnections() {
try {
ServerSocket serverSocket = new
ServerSocket(SERVER_PORT);
int counter = 0;
boolean hasConnections = true;
while (hasConnections) {
Socket client = serverSocket.accept();
Thread t = new Thread(new
ClientSocketThread(client));
In this example there is no limit to the number of client connections
and client threads that are created. Allowing an unlimited number of
client connections and threads could potentially overwhelm the system
and system resources.
The server should limit the number of client connections and the
client threads that are created. This can be easily done by creating a
thread pool object that limits the number of threads that are
generated.
(Good Code)
Example
Language: Java
public static final int SERVER_PORT = 4444;
public static final int MAX_CONNECTIONS = 10;
...
public void acceptConnections() {
try {
ServerSocket serverSocket = new
ServerSocket(SERVER_PORT);
int counter = 0;
boolean hasConnections = true;
while (hasConnections) {
hasConnections = checkForMoreConnections();
Socket client = serverSocket.accept();
Thread t = new Thread(new
ClientSocketThread(client));
ExecutorService pool =
Executors.newFixedThreadPool(MAX_CONNECTIONS);
pool.execute(t);
}
serverSocket.close();
} catch (IOException ex) {...}
}
Example 5
An unnamed web site allowed a user to purchase tickets for an event.
A menu option allowed the user to purchase up to 10 tickets, but the back
end did not restrict the actual number of tickets that could be
purchased.
CMS does not restrict the number of searches that
can occur simultaneously, leading to resource
exhaustion.
Potential Mitigations
Phase: Requirements
Clearly specify the minimum and maximum expectations for capabilities,
and dictate which behaviors are acceptable when resource allocation
reaches limits.
Phase: Architecture and Design
Limit the amount of resources that are accessible to unprivileged users. Set per-user limits for resources. Allow the system administrator to define these limits. Be careful to avoid CWE-410.
Phase: Architecture and Design
Design throttling mechanisms into the system architecture. The best
protection is to limit the amount of resources that an unauthorized user
can cause to be expended. A strong authentication and access control
model will help prevent such attacks from occurring in the first place,
and it will help the administrator to identify who is committing the
abuse. The login application should be protected against DoS attacks as
much as possible. Limiting the database access, perhaps by caching
result sets, can help minimize the resources expended. To further limit
the potential for a DoS attack, consider tracking the rate of requests
received from users and blocking requests that exceed a defined rate
threshold.
Phase: Implementation
Strategy: Input Validation
Assume all input is malicious. Use an "accept known good" input
validation strategy, i.e., use a whitelist of acceptable inputs that
strictly conform to specifications. Reject any input that does not
strictly conform to specifications, or transform it into something that
does.
When performing input validation, consider all potentially relevant
properties, including length, type of input, the full range of
acceptable values, missing or extra inputs, syntax, consistency across
related fields, and conformance to business rules. As an example of
business rule logic, "boat" may be syntactically valid because it only
contains alphanumeric characters, but it is not valid if the input is
only expected to contain colors such as "red" or "blue."
Do not rely exclusively on looking for malicious or malformed inputs
(i.e., do not rely on a blacklist). A blacklist is likely to miss at
least one undesirable input, especially if the code's environment
changes. This can give attackers enough room to bypass the intended
validation. However, blacklists can be useful for detecting potential
attacks or determining which inputs are so malformed that they should be
rejected outright.
This will only be applicable to cases where user input can influence
the size or frequency of resource allocations.
Phase: Architecture and Design
For any security checks that are performed on the client side, ensure that these checks are duplicated on the server side, in order to avoid CWE-602. 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. Then, these modified values would be submitted to the server.
Phase: Architecture and Design
Mitigation of resource exhaustion attacks requires that the target
system either:
recognizes the attack and denies that user further access for a
given amount of time, typically by using increasing time
delays
uniformly throttles all requests in order to make it more
difficult to consume resources more quickly than they can again be
freed.
The first of these solutions is an issue in itself though, since it
may allow attackers to prevent the use of the system by a particular
valid user. If the attacker impersonates the valid user, he may be able
to prevent the user from accessing the server in question.
The second solution can be difficult to effectively institute -- and
even when properly done, it does not provide a full solution. It simply
requires more resources on the part of the attacker.
Phase: Architecture and Design
Ensure that protocols have specific limits of scale placed on
them.
Phases: Architecture and Design; Implementation
If the program must fail, ensure that it fails gracefully (fails
closed). There may be a temptation to simply let the program fail poorly
in cases such as low memory conditions, but an attacker may be able to
assert control before the software has fully exited. Alternately, an
uncontrolled failure could cause cascading problems with other
downstream components; for example, the program could send a signal to a
downstream process so the process immediately knows that a problem has
occurred and has a better chance of recovery.
Ensure that all failures in resource allocation place the system into
a safe posture.
Phases: Operation; Architecture and Design
Strategy: Limit Resource Consumption
Use resource-limiting settings provided by the operating system or
environment. For example, when managing system resources in POSIX,
setrlimit() can be used to set limits for certain types of resources,
and getrlimit() can determine how many resources are available. However,
these functions are not available on all operating systems.
When the current levels get close to the maximum that is defined for the application (see CWE-770), then limit the allocation of further resources to privileged users; alternately, begin releasing resources for less-privileged users. While this mitigation may protect the system from attack, it will not necessarily stop attackers from adversely impacting other users.
Ensure that the application performs the appropriate error checks and error handling in case resources become unavailable (CWE-703).
Vulnerability theory is largely about how behaviors and resources
interact. "Resource exhaustion" can be regarded as either a consequence or
an attack, depending on the perspective. This entry is an attempt to reflect
one of the underlying weaknesses that enable these attacks (or consequences)
to take place.
Taxonomy Mappings
Mapped Taxonomy Name
Node ID
Fit
Mapped Node Name
CERT Java Secure Coding
FIO04-J
Close resources when they are no longer
needed
CERT Java Secure Coding
SER12-J
Avoid memory and resource leaks during
serialization
CERT Java Secure Coding
MSC05-J
Do not exhaust heap space
CERT C++ Secure Coding
MEM12-CPP
Do not assume infinite heap space
CERT C++ Secure Coding
FIO42-CPP
Ensure files are properly closed when they are no longer
needed
Joao Antunes, Nuno Ferreira Neves
and Paulo Verissimo. "Detection and Prediction of Resource-Exhaustion
Vulnerabilities". Proceedings of the IEEE International Symposium on
Software Reliability Engineering (ISSRE). November 2008. <http://homepages.di.fc.ul.pt/~nuno/PAPERS/ISSRE08.pdf>.
[REF-11] M. Howard and
D. LeBlanc. "Writing Secure Code". Chapter 17, "Protecting Against Denial of Service Attacks"
Page 517. 2nd Edition. Microsoft. 2002.
[REF-7] Mark Dowd, John McDonald
and Justin Schuh. "The Art of Software Security Assessment". Chapter 10, "Resource Limits", Page 574.. 1st Edition. Addison Wesley. 2006.
Maintenance Notes
"Resource exhaustion" (CWE-400) is currently treated as a weakness, although it is more like a category of weaknesses that all have the same type of consequence. While this entry treats CWE-400 as a parent in view 1000, the relationship is probably more appropriately described as a chain.
The code contains a control flow path that does not reflect the algorithm that the path is intended to implement, leading to incorrectbehavior any time this path is navigated.
Extended Description
This weakness captures cases in which a particular code segment is always incorrect with respect to the algorithm that it is implementing. For example, if a C programmer intends to include multiple statements in a single block but does not include the enclosing braces (CWE-483), then the logic is always incorrect. This issue is in contrast to most weaknesses in which the code usually behaves correctly, except when it is externally manipulated in malicious ways.
Time of Introduction
Architecture and Design
Implementation
Operation
Modes of Introduction
This issue typically appears in rarely-tested code, since the
"always-incorrect" nature will be detected as a bug during normal
usage.
This node could possibly be split into lower-level nodes. "Early Return" is for returning control to the caller too soon (e.g., CWE-584). "Excess Return" is when control is returned too far up the call stack (CWE-600, CWE-395). "Improper control limitation" occurs when the product maintains control at a lower level of execution, when control should be returned "further" up the call stack (CWE-455). "Incorrect syntax" covers code that's "just plain wrong" such as CWE-484 and CWE-483.
Software operating in a MAC OS environment, where .DS_Store is in effect, must carefully manage hard links, otherwise an attacker may be able to leverage a hard link from .DS_Store to overwrite arbitrary files and gain privileges.
Time of Introduction
Architecture and Design
Implementation
Operation
Applicable Platforms
Languages
All
Common Consequences
Scope
Effect
Confidentiality
Integrity
Technical Impact: Read files or
directories; Modify files or
directories
The Finder in Mac OS X and earlier allows local
users to overwrite arbitrary files and gain privileges by creating a hard
link from the .DS_Store file to an arbitrary
file.
This entry, which originated from PLOVER, probably stems from a common
manipulation that is used to exploit symlink and hard link following
weaknesses, like /etc/passwd is often used for UNIX-based exploits. As such,
it is probably too low-level for inclusion in CWE.
The software does not sufficiently delimit the arguments being passed to a component in another control sphere, allowing alternate arguments to be provided, leading to potentially security-relevant changes.
Time of Introduction
Architecture and Design
Implementation
Applicable Platforms
Languages
All
Common Consequences
Scope
Effect
Confidentiality
Integrity
Availability
Other
Technical Impact: Execute unauthorized code or
commands; Alter execution
logic; Read application
data; Modify application
data
An attacker could include arguments that allow unintended commands or
code to be executed, allow sensitive data to be read or modified or
could cause other unintended behavior.
Demonstrative Examples
Example 1
The following simple program accepts a filename as a command line
argument and displays the contents of the file back to the user. The program
is installed setuid root because it is intended for use as a learning tool
to allow system administrators in-training to inspect privileged system
files without giving them the ability to modify them or damage the
system.
(Bad Code)
Example
Language: C
int main(char* argc, char** argv) {
char cmd[CMD_MAX] = "/usr/bin/cat ";
strcat(cmd, argv[1]);
system(cmd);
}
Because the program runs with root privileges, the call to system()
also executes with root privileges. If a user specifies a standard
filename, the call works as expected. However, if an attacker passes a
string of the form ";rm -rf /", then the call to system() fails to
execute cat due to a lack of arguments and then plows on to recursively
delete the contents of the root partition.
Web browser executes Telnet sessions using
command line arguments that are specified by the web site, which could allow
remote attackers to execute arbitrary commands.
Web browser allows remote attackers to execute
commands by spawning Telnet with a log file option on the command line and
writing arbitrary code into an executable file which is later executed.
Argument injection vulnerability in the mail
function for PHP may allow attackers to bypass safe mode restrictions and
modify command line arguments to the MTA (e.g. sendmail) possibly executing
commands.
Help and Support center in windows does not
properly validate HCP URLs, which allows remote attackers to execute
arbitrary code via quotation marks in an "hcp://" URL.
Mail client does not sufficiently filter
parameters of mailto: URLs when using them as arguments to mail executable,
which allows remote attackers to execute arbitrary programs.
Mail client allows remote attackers to execute
arbitrary code via a URI that uses a UNC network share pathname to provide
an alternate configuration file.
Argument injection vulnerability in TellMe 1.2 and
earlier allows remote attackers to modify command line arguments for the
Whois program and obtain sensitive information via "--" style options in the
q_Host parameter.
Beagle before 0.2.5 can produce certain insecure
command lines to launch external helper applications while indexing, which
allows attackers to execute arbitrary commands. NOTE: it is not immediately
clear whether this issue involves argument injection, shell metacharacters,
or other issues.
Argument injection vulnerability in Internet
Explorer 6 for Windows XP SP2 allows user-assisted remote attackers to
modify command line arguments to an invoked mail client via " (double quote)
characters in a mailto: scheme handler, as demonstrated by launching
Microsoft Outlook with an arbitrary filename as an attachment. NOTE: it is
not clear whether this issue is implementation-specific or a problem in the
Microsoft API.
Argument injection vulnerability in Mozilla
Firefox 1.0.6 allows user-assisted remote attackers to modify command line
arguments to an invoked mail client via " (double quote) characters in a
mailto: scheme handler, as demonstrated by launching Microsoft Outlook with
an arbitrary filename as an attachment. NOTE: it is not clear whether this
issue is implementation-specific or a problem in the Microsoft
API.
Argument injection vulnerability in Avant Browser
10.1 Build 17 allows user-assisted remote attackers to modify command line
arguments to an invoked mail client via " (double quote) characters in a
mailto: scheme handler, as demonstrated by launching Microsoft Outlook with
an arbitrary filename as an attachment. NOTE: it is not clear whether this
issue is implementation-specific or a problem in the Microsoft
API.
Argument injection vulnerability in the URI
handler in Skype 2.0.*.104 and 2.5.*.0 through 2.5.*.78 for Windows allows
remote authorized attackers to download arbitrary files via a URL that
contains certain command-line switches.
Argument injection vulnerability in WinSCP 3.8.1
build 328 allows remote attackers to upload or download arbitrary files via
encoded spaces and double-quote characters in a scp or sftp
URI.
Argument injection vulnerability in the Windows
Object Packager (packager.exe) in Microsoft Windows XP SP1 and SP2 and
Server 2003 SP1 and earlier allows remote user-assisted attackers to execute
arbitrary commands via a crafted file with a "/" (slash) character in the
filename of the Command Line property, followed by a valid file extension,
which causes the command before the slash to be executed, aka "Object
Packager Dialogue Spoofing Vulnerability."
Argument injection vulnerability in HyperAccess
8.4 allows user-assisted remote attackers to execute arbitrary vbscript and
commands via the /r option in a telnet:// URI, which is configured to use
hawin32.exe.
Argument injection vulnerability in the telnet
daemon (in.telnetd) in Solaris 10 and 11 (SunOS 5.10 and 5.11) misinterprets
certain client "-f" sequences as valid requests for the login program to
skip authentication, which allows remote attackers to log into certain
accounts, as demonstrated by the bin account.
Language interpreter's mail function accepts another argument that is concatenated to a string used in a dangerous popen() call. Since there is no neutralization of this argument, both OS Command Injection (CWE-78) and Argument Injection (CWE-88) are possible.
Potential Mitigations
Phase: Architecture and Design
Strategy: Input Validation
Understand all the potential areas where untrusted inputs can enter
your software: parameters or arguments, cookies, anything read from the
network, environment variables, request headers as well as content, URL
components, e-mail, files, databases, and any external systems that
provide data to the application. Perform input validation at
well-defined interfaces.
Phase: Implementation
Strategy: Input Validation
Assume all input is malicious. Use an "accept known good" input
validation strategy, i.e., use a whitelist of acceptable inputs that
strictly conform to specifications. Reject any input that does not
strictly conform to specifications, or transform it into something that
does.
When performing input validation, consider all potentially relevant
properties, including length, type of input, the full range of
acceptable values, missing or extra inputs, syntax, consistency across
related fields, and conformance to business rules. As an example of
business rule logic, "boat" may be syntactically valid because it only
contains alphanumeric characters, but it is not valid if the input is
only expected to contain colors such as "red" or "blue."
Do not rely exclusively on looking for malicious or malformed inputs
(i.e., do not rely on a blacklist). A blacklist is likely to miss at
least one undesirable input, especially if the code's environment
changes. This can give attackers enough room to bypass the intended
validation. However, blacklists can be useful for detecting potential
attacks or determining which inputs are so malformed that they should be
rejected outright.
Phase: Implementation
Directly convert your input type into the expected data type, such as
using a conversion function that translates a string into a number.
After converting to the expected data type, ensure that the input's
values fall within the expected range of allowable values and that
multi-field consistencies are maintained.
Phase: Implementation
Inputs should be decoded and canonicalized to the application's current internal representation before being validated (CWE-180, CWE-181). Make sure that your application does not inadvertently decode the same input twice (CWE-174). Such errors could be used to bypass whitelist schemes by introducing dangerous inputs after they have been checked. Use libraries such as the OWASP ESAPI Canonicalization control.
Consider performing repeated canonicalization until your input does
not change any more. This will avoid double-decoding and similar
scenarios, but it might inadvertently modify inputs that are allowed to
contain properly-encoded dangerous content.
Phase: Implementation
When exchanging data between components, ensure that both components
are using the same character encoding. Ensure that the proper encoding
is applied at each interface. Explicitly set the encoding you are using
whenever the protocol allows you to do so.
Phase: Implementation
When your application combines data from multiple sources, perform the
validation after the sources have been combined. The individual data
elements may pass the validation step but violate the intended
restrictions after they have been combined.
Phase: Testing
Use automated static analysis tools that target this type of weakness.
Many modern techniques use data flow analysis to minimize the number of
false positives. This is not a perfect solution, since 100% accuracy and
coverage are not feasible.
Phase: Testing
Use dynamic tools and techniques that interact with the software using
large test suites with many diverse inputs, such as fuzz testing
(fuzzing), robustness testing, and fault injection. The software's
operation may slow down, but it should not become unstable, crash, or
generate incorrect results.
Weakness Ordinalities
Ordinality
Description
Primary
(where
the weakness exists independent of other weaknesses)
At one layer of abstraction, this can overlap other weaknesses that have
whitespace problems, e.g. injection of javascript into attributes of HTML
tags.
Affected Resources
System Process
Causal Nature
Explicit
Taxonomy Mappings
Mapped Taxonomy Name
Node ID
Fit
Mapped Node Name
PLOVER
Argument Injection or Modification
CERT C Secure Coding
ENV03-C
Sanitize the environment when invoking external
programs
CERT C Secure Coding
ENV04-C
Do not call system() if you do not need a command
processor
CERT C Secure Coding
STR02-C
Sanitize data passed to complex subsystems
WASC
30
Mail Command Injection
CERT C++ Secure Coding
STR02-CPP
Sanitize data passed to complex subsystems
CERT C++ Secure Coding
ENV03-CPP
Sanitize the environment when invoking external
programs
CERT C++ Secure Coding
ENV04-CPP
Do not call system() if you do not need a command
processor
[REF-7] Mark Dowd, John McDonald
and Justin Schuh. "The Art of Software Security Assessment". Chapter 10, "The Argument Array", Page
567.. 1st Edition. Addison Wesley. 2006.
The program declares an array public, final, and static, which is not sufficient to prevent the array's contents from being modified.
Extended Description
Because arrays are mutable objects, the final constraint requires that the array object itself be assigned only once, but makes no guarantees about the values of the array elements. Since the array is public, a malicious program can change the values stored in the array. As such, in most cases an array declared public, final and static is a bug.
Time of Introduction
Implementation
Applicable Platforms
Languages
Java
Common Consequences
Scope
Effect
Integrity
Technical Impact: Modify application
data
Demonstrative Examples
Example 1
The following Java Applet code mistakenly declares an array public,
final and static.
(Bad Code)
Example
Language: Java
public final class urlTool extends Applet {
public final static URL[] urls;
...
}
Potential Mitigations
Phase: Implementation
In most situations the array should be made private.
Background Details
Mobile code, in this case a Java Applet, is code that is transmitted
across a network and executed on a remote machine. Because mobile code
developers have little if any control of the environment in which their code
will execute, special security concerns become relevant. One of the biggest
environmental threats results from the risk that the mobile code will run
side-by-side with other, potentially malicious, mobile code. Because all of
the popular web browsers execute code from multiple sources together in the
same JVM, many of the security guidelines for mobile code are focused on
preventing manipulation of your objects' state and behavior by adversaries
who have access to the same virtual machine where your program is
running.
Weakness Ordinalities
Ordinality
Description
Primary
(where
the weakness exists independent of other weaknesses)
Debugging messages help attackers learn about the system and plan a form of attack.
Extended Description
ASP .NET applications can be configured to produce debug binaries. These binaries give detailed debugging messages and should not be used in production environments. Debug binaries are meant to be used in a development or testing environment and can pose a security risk if they are deployed to production.
Time of Introduction
Implementation
Operation
Applicable Platforms
Languages
.NET
Common Consequences
Scope
Effect
Confidentiality
Technical Impact: Read application
data
Attackers can leverage the additional information they gain from
debugging output to mount attacks targeted on the framework, database,
or other resources used by the application.
Demonstrative Examples
Example 1
The file web.config contains the debug mode setting. Setting debug
to "true" will let the browser display debugging information.
(Bad Code)
Example
Language: XML
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.web>
<compilation
defaultLanguage="c#"
debug="true"
/>
...
</system.web>
</configuration>
Change the debug mode to false when the application is deployed into
production.
Potential Mitigations
Phase: System Configuration
Avoid releasing debug binaries into the production environment. Change
the debug mode to false when the application is deployed into
production.
Background Details
The debug attribute of the <compilation> tag defines whether
compiled binaries should include debugging information. The use of debug
binaries causes an application to provide as much information about itself
as possible to the user.
ASP.NET Misconfiguration: Missing Custom Error Page
Definition in a New Window
Weakness ID: 12 (Weakness Variant)
Status: Draft
Description
Description Summary
An ASP .NET application must enable custom error pages in order to prevent attackers from mining information from the framework's built-in responses.
Time of Introduction
Implementation
Operation
Applicable Platforms
Languages
.NET
Common Consequences
Scope
Effect
Confidentiality
Technical Impact: Read application
data
Default error pages gives detailed information about the error that
occurred, and should not be used in production environments.
Attackers can leverage the additional information provided by a
default error page to mount attacks targeted on the framework, database,
or other resources used by the application.
Demonstrative Examples
Example 1
An insecure ASP.NET application setting:
(Bad Code)
Example
Language: ASP.NET
<customErrors mode="Off" />
Custom error message mode is turned off. An ASP.NET error message with
detailed stack trace and platform versions will be returned.
Here is a more secure setting:
(Good Code)
Example
Language: ASP.NET
<customErrors mode="RemoteOnly" />
Custom error message mode for remote users only. No defaultRedirect
error page is specified. The local user on the web server will see a
detailed stack trace. For remote users, an ASP.NET error message with
the server customError configuration setting and the platform version
will be returned.
Potential Mitigations
Phases: System Configuration; Implementation
Handle exceptions appropriately in source code. The best practice is
to use a custom error message. Make sure that the mode attribute is set
to "RemoteOnly" in the web.config file as shown in the following
example.
(Good Code)
<customErrors mode="RemoteOnly" />
The mode attribute of the <customErrors> tag in the
Web.config file defines whether custom or default error pages are used.
It should be configured to use a custom page as follows:
ASP.NET Misconfiguration: Not Using Input Validation Framework
Definition in a New Window
Weakness ID: 554 (Weakness Variant)
Status: Draft
Description
Description Summary
The ASP.NET application does not use an input validation framework.
Time of Introduction
Architecture and Design
Implementation
Applicable Platforms
Languages
.NET
Common Consequences
Scope
Effect
Integrity
Technical Impact: Unexpected state
Unchecked input leads to cross-site scripting, process control, and
SQL injection vulnerabilities, among others.
Potential Mitigations
Phase: Architecture and Design
Use the ASP.NET validation framework to check all program input before
it is processed by the application. Example uses of the validation
framework include checking to ensure that:
Phone number fields contain only valid characters in phone
numbers
Boolean values are only "T" or "F"
Free-form strings are of a reasonable length and
composition
ASP.NET Misconfiguration: Password in Configuration File
Definition in a New Window
Weakness ID: 13 (Weakness Variant)
Status: Draft
Description
Description Summary
Storing a plaintext password in a configuration file allows anyone who can read the file access to the password-protected resource making them an easy target for attackers.
Time of Introduction
Architecture and Design
Implementation
Common Consequences
Scope
Effect
Access Control
Technical Impact: Gain privileges / assume
identity
Demonstrative Examples
Example 1
The following connectionString has clear text
credentials.
The following example shows a portion of a configuration file for an
ASP.Net application. This configuration file includes username and password
information for a connection to a database but the pair is stored in
plaintext.
Username and password information should not be included in a
configuration file or a properties file in plaintext as this will allow
anyone who can read the file access to the resource. If possible,
encrypt this information.
Potential Mitigations
Phase: Implementation
Credentials stored in configuration files should be encrypted, Use
standard APIs and industry accepted algorithms to encrypt the
credentials stored in configuration files.
ASP.NET Misconfiguration: Use of Identity Impersonation
Definition in a New Window
Weakness ID: 556 (Weakness Variant)
Status: Incomplete
Description
Description Summary
Configuring an ASP.NET application to run with impersonated credentials may give the application unnecessary privileges.
Extended Description
The use of impersonated credentials allows an ASP.NET application to run with either the privileges of the client on whose behalf it is executing or with arbitrary privileges granted in its configuration.
Time of Introduction
Implementation
Operation
Common Consequences
Scope
Effect
Access Control
Technical Impact: Gain privileges / assume
identity
The code uses an operator for assignment when the intention was to perform a comparison.
Extended Description
In many languages the compare statement is very close in appearance to the assignment statement and are often confused. This bug is generally the result of a typo and usually causes obvious problems with program execution. If the comparison is in an if statement, the if statement will usually evaluate the value of the right-hand side of the predicate.
Time of Introduction
Implementation
Applicable Platforms
Languages
C
C++
Java
.NET
Common Consequences
Scope
Effect
Other
Technical Impact: Alter execution
logic
Likelihood of Exploit
Low
Demonstrative Examples
Example 1
The following C/C++ and C# examples attempt to validate an int input
parameter against the integer value 100.
(Bad Code)
Example Languages: C and C#
int isValid(int value) {
if (value=100) {
printf("Value is valid\n");
return(1);
}
printf("Value is not valid\n");
return(0);
}
(Bad Code)
Example
Language: C#
bool isValid(int value) {
if (value=100) {
Console.WriteLine("Value is valid.");
return true;
}
Console.WriteLine("Value is not valid.");
return false;
}
However, the expression to be evaluated in the if statement uses the
assignment operator "=" rather than the comparison operator "==". The
result of using the assignment operator instead of the comparison
operator causes the int variable to be reassigned locally and the
expression in the if statement will always evaluate to the value on the
right hand side of the expression. This will result in the input value
not being properly validated, which can cause unexpected results.
Example 2
In this example, we show how assigning instead of comparing can impact code when values are being passed by reference instead of by value. Consider a scenario in which a string is being processed from user input. Assume the string has already been formatted such that different user inputs are concatenated with the colon character. When the processString function is called, the test for the colon character will result in an insertion of the colon character instead, adding new input separators. Since the string was passed by reference, the data sentinels will be inserted in the original string (CWE-464), and further processing of the inputs will be altered, possibly malformed..
(Bad Code)
Example
Language: C
void processString (char *str) {
int i;
for(i=0; i<strlen(str); i++) {
if (isalnum(str[i])){
processChar(str[i]);
}
else if (str[i] = ':') {
movingToNewInput();}
}
}
}
Example 3
The following Java example attempts to perform some processing based
on the boolean value of the input parameter. However, the expression to be
evaluated in the if statement uses the assignment operator "=" rather than
the comparison operator "==". As with the previous examples, the variable
will be reassigned locally and the expression in the if statement will
evaluate to true and unintended processing may occur.
(Bad Code)
Example
Language: Java
public void checkValid(boolean isValid) {
if (isValid = true) {
System.out.println("Performing processing");
doSomethingImportant();
}
else {
System.out.println("Not Valid, do not perform
processing");
return;
}
}
While most Java compilers will catch the use of an assignment operator
when a comparison operator is required, for boolean variables in Java
the use of the assignment operator within an expression is allowed. If
possible, try to avoid using comparison operators on boolean variables
in java. Instead, let the values of the variables stand for themselves,
as in the following code.
(Good Code)
Example
Language: Java
public void checkValid(boolean isValid) {
if (isValid) {
System.out.println("Performing processing");
doSomethingImportant();
}
else {
System.out.println("Not Valid, do not perform
processing");
return;
}
}
Alternatively, to test for false, just use the boolean NOT
operator.
(Good Code)
Example
Language: Java
public void checkValid(boolean isValid) {
if (!isValid) {
System.out.println("Not Valid, do not perform
processing");
return;
}
System.out.println("Performing processing");
doSomethingImportant();
}
Example 4
(Bad Code)
Example
Language: C
void called(int foo){
if (foo=1) printf("foo\n");
}
int main() {
called(2);
return 0;
}
Potential Mitigations
Phase: Testing
Many IDEs and static analysis products will detect this
problem.
Phase: Implementation
Place constants on the left. If one attempts to assign a constant with
a variable, the compiler will of course produce an error.
[REF-7] Mark Dowd, John McDonald
and Justin Schuh. "The Art of Software Security Assessment". Chapter 6, "Typos", Page 289.. 1st Edition. Addison Wesley. 2006.
The software sets a pointer to a specific address other than NULL or 0.
Extended Description
Using a fixed address is not portable because that address will probably not be valid in all environments or platforms.
Time of Introduction
Architecture and Design
Implementation
Applicable Platforms
Languages
C
C++
C#
Assembly
Common Consequences
Scope
Effect
Integrity
Confidentiality
Availability
Technical Impact: Execute unauthorized code or
commands
If one executes code at a known location, an attacker might be able to
inject code there beforehand.
Availability
Technical Impact: DoS: crash / exit /
restart
If the code is ported to another platform or environment, the pointer
is likely to be invalid and cause a crash.
Confidentiality
Integrity
Technical Impact: Read memory; Modify memory
The data at a known pointer location can be easily read or influenced
by an attacker.
Demonstrative Examples
Example 1
This code assumes a particular function will always be found at a
particular address. It assigns a pointer to that address and calls the
function.
(Bad Code)
Example
Language: C
int (*pt2Function) (float, char, char)=0x08040000;
int result2 = (*pt2Function) (12, 'a', 'b');
// Here we can inject code to execute.
The same function may not always be found at the same memory address.
This could lead to a crash, or an attacker may alter the memory at the
expected address, leading to arbitrary code execution.
Potential Mitigations
Phase: Implementation
Never set a pointer to a fixed address.
Weakness Ordinalities
Ordinality
Description
Primary
(where
the weakness exists independent of other weaknesses)
Software that does not appropriately monitor or control resource consumption can lead to adverse system performance.
Extended Description
This situation is amplified if the software allows malicious users or attackers to consume more resources than their access level permits. Exploiting such a weakness can lead to asymmetric resource consumption, aiding in amplification attacks against the system or the network.
The software performs authentication based on the name of a resource being accessed, or the name of the actor performing the access, but it does not properly check all possible names for that resource or actor.
Bypass of authentication for files using "\"
(backslash) or "%5C" (encoded backslash).
Potential Mitigations
Phase: Architecture and Design
Strategy: Input Validation
Avoid making decisions based on names of resources (e.g. files) if
those resources can have alternate names.
Phase: Implementation
Strategy: Input Validation
Assume all input is malicious. Use an "accept known good" input
validation strategy, i.e., use a whitelist of acceptable inputs that
strictly conform to specifications. Reject any input that does not
strictly conform to specifications, or transform it into something that
does.
When performing input validation, consider all potentially relevant
properties, including length, type of input, the full range of
acceptable values, missing or extra inputs, syntax, consistency across
related fields, and conformance to business rules. As an example of
business rule logic, "boat" may be syntactically valid because it only
contains alphanumeric characters, but it is not valid if the input is
only expected to contain colors such as "red" or "blue."
Do not rely exclusively on looking for malicious or malformed inputs
(i.e., do not rely on a blacklist). A blacklist is likely to miss at
least one undesirable input, especially if the code's environment
changes. This can give attackers enough room to bypass the intended
validation. However, blacklists can be useful for detecting potential
attacks or determining which inputs are so malformed that they should be
rejected outright.
Phase: Implementation
Strategy: Input Validation
Inputs should be decoded and canonicalized to the application's current internal representation before being validated (CWE-180). Make sure that the application does not decode the same input twice (CWE-174). Such errors could be used to bypass whitelist validation schemes by introducing dangerous inputs after they have been checked.
The authentication scheme or implementation uses key data elements that are assumed to be immutable, but can be controlled or modified by the attacker.
Time of Introduction
Architecture and Design
Implementation
Applicable Platforms
Languages
All
Common Consequences
Scope
Effect
Access Control
Technical Impact: Bypass protection
mechanism
Demonstrative Examples
Example 1
In the following example, an "authenticated" cookie is used to
determine whether or not a user should be granted access to a system. Of
course, modifying the value of a cookie on the client-side is trivial, but
many developers assume that cookies are essentially immutable.
(Bad Code)
Example
Language: Java
boolean authenticated = new
Boolean(getCookieValue("authenticated")).booleanValue();
The authentication algorithm is sound, but the implemented mechanism can be bypassed as the result of a separate weakness that is primary to the authentication error.
The password is not properly checked, which allows
remote attackers to bypass access controls by sending a 1-byte password that
matches the first character of the real password.
Chain: Forum software does not properly initialize
an array, which inadvertently sets the password to a single character,
allowing remote attackers to easily guess the password and gain
administrative privileges.
This attack-focused weakness is caused by improperly implemented authentication schemes that are subject to spoofing attacks.
Time of Introduction
Architecture and Design
Implementation
Common Consequences
Scope
Effect
Access Control
Technical Impact: Bypass protection
mechanism; Gain privileges / assume
identity
This weakness can allow an attacker to access resources which are not
otherwise accessible without proper authentication.
Demonstrative Examples
Example 1
Here, an authentication mechanism implemented in Java relies on an
IP address for source validation. If an attacker is able to spoof the IP,
however, he may be able to bypass such an authentication
mechanism.
(Bad Code)
Example
Language: Java
String sourceIP = request.getRemoteAddr();
if (sourceIP != null &&
sourceIP.equals(APPROVED_IP)) {
authenticated = true;
}
Example 2
Both of these examples check if a request is from a trusted address
before responding to the request.
The code only verifies the address as stored in the request packet. An
attacker can spoof this address, thus impersonating a trusted client
Example 3
The following code samples use a DNS lookup in order to decide
whether or not an inbound request is from a trusted host. If an attacker can
poison the DNS cache, they can gain trusted status.
(Bad Code)
Example
Language: C
struct hostent *hp;struct in_addr myaddr;
char* tHost = "trustme.example.com";
myaddr.s_addr=inet_addr(ip_addr_string);
hp = gethostbyaddr((char *) &myaddr, sizeof(struct
in_addr), AF_INET);
if (hp && !strncmp(hp->h_name, tHost,
sizeof(tHost))) {
trusted = true;
} else {
trusted = false;
}
(Bad Code)
Example
Language: Java
String ip = request.getRemoteAddr();
InetAddress addr = InetAddress.getByName(ip);
if (addr.getCanonicalHostName().endsWith("trustme.com")) {
IP addresses are more reliable than DNS names, but they can also be
spoofed. Attackers can easily forge the source IP address of the packets
they send, but response packets will return to the forged IP address. To
see the response packets, the attacker has to sniff the traffic between
the victim machine and the forged IP address. In order to accomplish the
required sniffing, attackers typically attempt to locate themselves on
the same subnet as the victim machine. Attackers may be able to
circumvent this requirement by using source routing, but source routing
is disabled across much of the Internet today. In summary, IP address
verification can be a useful part of an authentication scheme, but it
should not be the single factor required for authentication.
[REF-7] Mark Dowd, John McDonald
and Justin Schuh. "The Art of Software Security Assessment". Chapter 3, "Spoofing and Identification", Page
72.. 1st Edition. Addison Wesley. 2006.
[REF-7] Mark Dowd, John McDonald
and Justin Schuh. "The Art of Software Security Assessment". Chapter 2, "Untrustworthy Credentials", Page
37.. 1st Edition. Addison Wesley. 2006.
Authentication Bypass: OpenSSL CTX Object Modified after SSL Objects are Created
Definition in a New Window
Weakness ID: 593 (Weakness Variant)
Status: Draft
Description
Description Summary
The software modifies the SSL context after connection creation has begun.
Extended Description
If the program modifies the SSL_CTX object after creating SSL objects from it, there is the possibility that older SSL objects created from the original context could all be affected by that change.
Time of Introduction
Architecture and Design
Implementation
Common Consequences
Scope
Effect
Access Control
Technical Impact: Bypass protection
mechanism
No authentication takes place in this process, bypassing an assumed
protection of encryption.
Confidentiality
Technical Impact: Read application
data
The encrypted communication between a user and a trusted host may be
subject to a "man in the middle" sniffing attack.
Demonstrative Examples
Example 1
(Bad Code)
Example
Language: C
#define CERT "secret.pem"
#define CERT2 "secret2.pem"
int main(){
SSL_CTX *ctx;
SSL *ssl;
init_OpenSSL();
seed_prng();
ctx = SSL_CTX_new(SSLv23_method());
if (SSL_CTX_use_certificate_chain_file(ctx, CERT) != 1)
int_error("Error loading certificate from file");
if (SSL_CTX_use_PrivateKey_file(ctx, CERT, SSL_FILETYPE_PEM)
!= 1)
int_error("Error loading private key from file");
if (!(ssl = SSL_new(ctx)))
int_error("Error creating an SSL context");
if ( SSL_CTX_set_default_passwd_cb(ctx, "new default password"
!= 1))
int_error("Doing something which is dangerous to do
anyways");
if (!(ssl2 = SSL_new(ctx)))
int_error("Error creating an SSL context");
}
Potential Mitigations
Phase: Architecture and Design
Use a language which provides a cryptography framework at a higher
level of abstraction.
Phase: Implementation
Most SSL_CTX functions have SSL counterparts that act on SSL-type
objects.
Phase: Implementation
Applications should set up an SSL_CTX completely, before creating SSL
objects from it.
Authorization Bypass Through User-Controlled SQL Primary Key
Definition in a New Window
Weakness ID: 566 (Weakness Variant)
Status: Incomplete
Description
Description Summary
The software uses a database table that includes records that should not be accessible to an actor, but it executes a SQL statement with a primary key that can be controlled by that actor.
Extended Description
When a user can set a primary key to any value, then the user can modify the key to point to unauthorized records.
Database access control errors occur when:
Data enters a program from an untrusted source.
The data is used to specify the value of a primary key in a SQL query.
The untrusted source does not have the permissions to be able to access all rows in the associated table.
The following code uses a parameterized statement, which escapes
metacharacters and prevents SQL injection vulnerabilities, to construct and
execute a SQL query that searches for an invoice matching the specified
identifier [1]. The identifier is selected from a list of all invoices
associated with the current authenticated user.
(Bad Code)
Example
Language: C#
...
conn = new SqlConnection(_ConnectionString);
conn.Open();
int16 id = System.Convert.ToInt16(invoiceID.Text);
SqlCommand query = new SqlCommand( "SELECT * FROM invoices WHERE
id = @id", conn);
The problem is that the developer has not considered all of the
possible values of id. Although the interface generates a list of
invoice identifiers that belong to the current user, an attacker can
bypass this interface to request any desired invoice. Because the code
in this example does not check to ensure that the user has permission to
access the requested invoice, it will display any invoice, even if it
does not belong to the current user.
Potential Mitigations
Phase: Implementation
Assume all input is malicious. Use a standard input validation
mechanism to validate all input for length, type, syntax, and business
rules before accepting the data. Use an "accept known good" validation
strategy.
Phase: Implementation
Use a parameterized query AND make sure that the accepted values
conform to the business rules. Construct your SQL statement
accordingly.
Linux kernel 2.2 and above allow promiscuous mode
using a different method than previous versions, and ifconfig is not aware
of the new method (alternate path property).
chain: Code was ported from a case-sensitive Unix
platform to a case-insensitive Windows platform where filetype handlers
treat .jsp and .JSP as different extensions. JSP source code may be read
because .JSP defaults to the filetype "text".
The software uses the size of a source buffer when reading from or writing to a destination buffer, which may cause it to access memory that is outside of the bounds of the buffer.
Extended Description
When the size of the destination is smaller than the size of the source, a buffer overflow could occur.
Buffer overflows generally lead to crashes. Other attacks leading to
lack of availability are possible, including putting the program into an
infinite loop.
Integrity
Confidentiality
Availability
Technical Impact: Execute unauthorized code or
commands
Buffer overflows often can be used to execute arbitrary code, which is
usually outside the scope of a program's implicit security
policy.
Access Control
Technical Impact: Bypass protection
mechanism
When the consequence is arbitrary code execution, this can often be
used to subvert any other security service.
Likelihood of Exploit
Medium to High
Demonstrative Examples
Example 1
In the following example, the source character string is copied to
the dest character string using the method strncpy.
(Bad Code)
Example Languages: C and C++
...
char source[21] = "the character string";
char dest[12];
strncpy(dest, source, sizeof(source)-1);
...
However, in the call to strncpy the source character string is used
within the sizeof call to determine the number of characters to copy.
This will create a buffer overflow as the size of the source character
string is greater than the dest character string. The dest character
string should be used within the sizeof call to ensure that the correct
number of characters are copied, as shown below.
(Good Code)
Example Languages: C and C++
...
char source[21] = "the character string";
char dest[12];
strncpy(dest, source, sizeof(dest)-1);
...
Example 2
In this example, the method outputFilenameToLog outputs a filename
to a log file. The method arguments include a pointer to a character string
containing the file name and an integer for the number of characters in the
string. The filename is copied to a buffer where the buffer size is set to a
maximum size for inputs to the log file. The method then calls another
method to save the contents of the buffer to the log file.
(Bad Code)
Example Languages: C and C++
#define LOG_INPUT_SIZE 40
// saves the file name to a log file
int outputFilenameToLog(char *filename, int length) {
int success;
// buffer with size set to maximum size for input to log
file
char buf[LOG_INPUT_SIZE];
// copy filename to buffer
strncpy(buf, filename, length);
// save to log file
success = saveToLogFile(buf);
return success;
}
However, in this case the string copy method, strncpy, mistakenly uses
the length method argument to determine the number of characters to copy
rather than using the size of the local character string, buf. This can
lead to a buffer overflow if the number of characters contained in
character string pointed to by filename is larger then the number of
characters allowed for the local character string. The string copy
method should use the buf character string within a sizeof call to
ensure that only characters up to the size of the buf array are copied
to avoid a buffer overflow, as shown below.
(Good Code)
Example Languages: C and C++
...
// copy filename to buffer
strncpy(buf, filename, sizeof(buf)-1);
...
Potential Mitigations
Phase: Architecture and Design
Use an abstraction library to abstract away risky APIs. Examples
include the Safe C String Library (SafeStr) by Viega, and the Strsafe.h
library from Microsoft. This is not a complete solution, since many
buffer overflows are not related to strings.
Phase: Build and Compilation
Use automatic buffer overflow detection mechanisms that are offered by
certain compilers or compiler extensions. Examples include StackGuard,
ProPolice and the Microsoft Visual Studio /GS flag. This is not
necessarily a complete solution, since these canary-based mechanisms
only detect certain types of overflows. In addition, the result is still
a denial of service, since the typical response is to exit the
application.
Phase: Implementation
Programmers should adhere to the following rules when allocating and
managing their applications memory: Double check that your buffer is as
large as you specify. When using functions that accept a number of bytes
to copy, such as strncpy(), be aware that if the destination buffer size
is equal to the source buffer size, it may not NULL-terminate the
string. Check buffer boundaries if calling this function in a loop and
make sure you are not in danger of writing past the allocated space.
Truncate all input strings to a reasonable length before passing them to
the copy and concatenation functions
Phase: Operation
Strategy: Environment Hardening
Use a feature like Address Space Layout Randomization (ASLR) [R.806.3] [R.806.5].
Effectiveness: Defense in Depth
This is not a complete solution. However, it forces the attacker to
guess an unknown value that changes every program execution. In
addition, an attack could still cause a denial of service, since the
typical response is to exit the application.
Phase: Operation
Strategy: Environment Hardening
Use a CPU and operating system that offers Data Execution Protection (NX) or its equivalent [R.806.5] [R.806.6].
Effectiveness: Defense in Depth
This is not a complete solution, since buffer overflows could be used
to overwrite nearby variables to modify the software's state in
dangerous ways. In addition, it cannot be used in cases in which
self-modifying code is required. Finally, an attack could still cause a
denial of service, since the typical response is to exit the
application.
Phases: Build and Compilation; Operation
Most mitigating technologies at the compiler or OS level to date
address only a subset of buffer overflow problems and rarely provide
complete protection against even that subset. It is good practice to
implement strategies to increase the workload of an attacker, such as
leaving the attacker to guess an unknown value that changes every
program execution.
Weakness Ordinalities
Ordinality
Description
Resultant
(where
the weakness is typically related to the presence of some other
weaknesses)
Primary
(where
the weakness exists independent of other weaknesses)
The software uses a sequential operation to read or write a buffer, but it uses an incorrect length value that causes it to access memory that is outside of the bounds of the buffer.
Extended Description
When the length value exceeds the size of the destination, a buffer overflow could occur.
Time of Introduction
Implementation
Applicable Platforms
Languages
C: (Often)
C++: (Often)
Assembly
Common Consequences
Scope
Effect
Integrity
Confidentiality
Availability
Technical Impact: Execute unauthorized code or
commands
Buffer overflows often can be used to execute arbitrary code, which is
usually outside the scope of a program's implicit security policy. This
can often be used to subvert any other security service.
Buffer overflows generally lead to crashes. Other attacks leading to
lack of availability are possible, including putting the program into an
infinite loop.
Likelihood of Exploit
Medium to High
Detection Methods
Automated Static Analysis
This weakness can often be detected using automated static analysis
tools. Many modern tools use data flow analysis or constraint-based
techniques to minimize the number of false positives.
Automated static analysis generally does not account for environmental
considerations when reporting out-of-bounds memory operations. This can
make it difficult for users to determine which warnings should be
investigated first. For example, an analysis tool might report buffer
overflows that originate from command line arguments in a program that
is not expected to run with setuid or other special privileges.
Effectiveness: High
Detection techniques for buffer-related errors are more mature than
for most other weakness types.
Automated Dynamic Analysis
This weakness can be detected using dynamic tools and techniques that
interact with the software using large test suites with many diverse
inputs, such as fuzz testing (fuzzing), robustness testing, and fault
injection. The software's operation may slow down, but it should not
become unstable, crash, or generate incorrect results.
Effectiveness: Moderate
Without visibility into the code, black box methods may not be able to
sufficiently distinguish this weakness from others, requiring manual
methods to diagnose the underlying problem.
Manual Analysis
Manual analysis can be useful for finding this weakness, but it might
not achieve desired code coverage within limited time constraints. This
becomes difficult for weaknesses that must be considered for all inputs,
since the attack surface can be too large.
Demonstrative Examples
Example 1
This example takes an IP address from a user, verifies that it is
well formed and then looks up the hostname and copies it into a
buffer.
(Bad Code)
Example
Language: C
void host_lookup(char *user_supplied_addr){
struct hostent *hp;
in_addr_t *addr;
char hostname[64];
in_addr_t inet_addr(const char *cp);
/*routine that ensures user_supplied_addr is in the right
format for conversion */
validate_addr_form(user_supplied_addr);
addr = inet_addr(user_supplied_addr);
hp = gethostbyaddr( addr, sizeof(struct in_addr),
AF_INET);
strcpy(hostname, hp->h_name);
}
This function allocates a buffer of 64 bytes to store the hostname
under the assumption that the maximum length value of hostname is 64
bytes, however there is no guarantee that the hostname will not be
larger than 64 bytes. If an attacker specifies an address which resolves
to a very large hostname, then we may overwrite sensitive data or even
relinquish control flow to the attacker.
Note that this example also contains an unchecked return value (CWE-252) that can lead to a NULL pointer dereference (CWE-476).
Example 2
In the following example, the source character string is copied to
the dest character string using the method strncpy.
(Bad Code)
Example Languages: C and C++
...
char source[21] = "the character string";
char dest[12];
strncpy(dest, source, sizeof(source)-1);
...
However, in the call to strncpy the source character string is used
within the sizeof call to determine the number of characters to copy.
This will create a buffer overflow as the size of the source character
string is greater than the dest character string. The dest character
string should be used within the sizeof call to ensure that the correct
number of characters are copied, as shown below.
(Good Code)
Example Languages: C and C++
...
char source[21] = "the character string";
char dest[12];
strncpy(dest, source, sizeof(dest)-1);
...
Example 3
In this example, the method outputFilenameToLog outputs a filename
to a log file. The method arguments include a pointer to a character string
containing the file name and an integer for the number of characters in the
string. The filename is copied to a buffer where the buffer size is set to a
maximum size for inputs to the log file. The method then calls another
method to save the contents of the buffer to the log file.
(Bad Code)
Example Languages: C and C++
#define LOG_INPUT_SIZE 40
// saves the file name to a log file
int outputFilenameToLog(char *filename, int length) {
int success;
// buffer with size set to maximum size for input to log
file
char buf[LOG_INPUT_SIZE];
// copy filename to buffer
strncpy(buf, filename, length);
// save to log file
success = saveToLogFile(buf);
return success;
}
However, in this case the string copy method, strncpy, mistakenly uses
the length method argument to determine the number of characters to copy
rather than using the size of the local character string, buf. This can
lead to a buffer overflow if the number of characters contained in
character string pointed to by filename is larger then the number of
characters allowed for the local character string. The string copy
method should use the buf character string within a sizeof call to
ensure that only characters up to the size of the buf array are copied
to avoid a buffer overflow, as shown below.
Language interpreter API function doesn't validate
length argument, leading to information
exposure
Potential Mitigations
Phase: Requirements
Strategy: Language Selection
Use a language that does not allow this weakness to occur or provides
constructs that make this weakness easier to avoid.
For example, many languages that perform their own memory management,
such as Java and Perl, are not subject to buffer overflows. Other
languages, such as Ada and C#, typically provide overflow protection,
but the protection can be disabled by the programmer.
Be wary that a language's interface to native code may still be
subject to overflows, even if the language itself is theoretically safe.
Phase: Architecture and Design
Strategy: Libraries or Frameworks
Use a vetted library or framework that does not allow this weakness to
occur or provides constructs that make this weakness easier to
avoid.
Examples include the Safe C String Library (SafeStr) by Messier and Viega [R.805.6], and the Strsafe.h library from Microsoft [R.805.7]. These libraries provide safer versions of overflow-prone string-handling functions.
This is not a complete solution, since many buffer overflows are not
related to strings.
Phase: Build and Compilation
Strategy: Compilation or Build Hardening
Run or compile the software using features or extensions that
automatically provide a protection mechanism that mitigates or
eliminates buffer overflows.
For example, certain compilers and extensions provide automatic buffer
overflow detection mechanisms that are built into the compiled code.
Examples include the Microsoft Visual Studio /GS flag, Fedora/Red Hat
FORTIFY_SOURCE GCC flag, StackGuard, and ProPolice.
Effectiveness: Defense in Depth
This is not necessarily a complete solution, since these mechanisms
can only detect certain types of overflows. In addition, an attack could
still cause a denial of service, since the typical response is to exit
the application.
Phase: Implementation
Consider adhering to the following rules when allocating and managing
an application's memory:
Double check that your buffer is as large as you specify.
When using functions that accept a number of bytes to copy, such
as strncpy(), be aware that if the destination buffer size is equal
to the source buffer size, it may not NULL-terminate the
string.
Check buffer boundaries if accessing the buffer in a loop and make
sure you are not in danger of writing past the allocated
space.
If necessary, truncate all input strings to a reasonable length
before passing them to the copy and concatenation functions.
Phase: Architecture and Design
For any security checks that are performed on the client side, ensure that these checks are duplicated on the server side, in order to avoid CWE-602. 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. Then, these modified values would be submitted to the server.
Phase: Operation
Strategy: Environment Hardening
Use a feature like Address Space Layout Randomization (ASLR) [R.805.2] [R.805.4].
Effectiveness: Defense in Depth
This is not a complete solution. However, it forces the attacker to
guess an unknown value that changes every program execution. In
addition, an attack could still cause a denial of service, since the
typical response is to exit the application.
Phase: Operation
Strategy: Environment Hardening
Use a CPU and operating system that offers Data Execution Protection (NX) or its equivalent [R.805.3] [R.805.6].
Effectiveness: Defense in Depth
This is not a complete solution, since buffer overflows could be used
to overwrite nearby variables to modify the software's state in
dangerous ways. In addition, it cannot be used in cases in which
self-modifying code is required. Finally, an attack could still cause a
denial of service, since the typical response is to exit the
application.
Phases: Architecture and Design; Operation
Strategy: Environment Hardening
Run your code using the lowest privileges that are required to accomplish the necessary tasks [R.805.9]. If possible, create isolated accounts with limited privileges that are only used for a single task. That way, a successful attack will not immediately give the attacker access to the rest of the software or its environment. For example, database applications rarely need to run as the database administrator, especially in day-to-day operations.
Phases: Architecture and Design; Operation
Strategy: Sandbox or Jail
Run the code in a "jail" or similar sandbox environment that enforces
strict boundaries between the process and the operating system. This may
effectively restrict which files can be accessed in a particular
directory or which commands can be executed by the software.
OS-level examples include the Unix chroot jail, AppArmor, and SELinux.
In general, managed code may provide some protection. For example,
java.io.FilePermission in the Java SecurityManager allows the software
to specify restrictions on file operations.
This may not be a feasible solution, and it only limits the impact to
the operating system; the rest of the application may still be subject
to compromise.
Be careful to avoid CWE-243 and other weaknesses related to jails.
Effectiveness: Limited
The effectiveness of this mitigation depends on the prevention
capabilities of the specific sandbox or jail being used and might only
help to reduce the scope of an attack, such as restricting the attacker
to certain system calls or limiting the portion of the file system that
can be accessed.
Weakness Ordinalities
Ordinality
Description
Resultant
(where
the weakness is typically related to the presence of some other
weaknesses)
Primary
(where
the weakness exists independent of other weaknesses)
Buffer Copy without Checking Size of Input ('Classic Buffer Overflow')
Definition in a New Window
Weakness ID: 120 (Weakness Base)
Status: Incomplete
Description
Description Summary
The program copies an input buffer to an output buffer without verifying that the size of the input buffer is less than the size of the output buffer, leading to a buffer overflow.
Extended Description
A buffer overflow condition exists when a program attempts to put more data in a buffer than it can hold, or when a program attempts to put data in a memory area outside of the boundaries of a buffer. The simplest type of error, and the most common cause of buffer overflows, is the "classic" case in which the program copies the buffer without restricting how much is copied. Other variants exist, but the existence of a classic overflow strongly suggests that the programmer is not considering even the most basic of security protections.
Alternate Terms
buffer overrun:
Some prominent vendors and researchers use the term "buffer overrun,"
but most people use "buffer overflow."
Unbounded Transfer
Terminology Notes
Many issues that are now called "buffer overflows" are substantively
different than the "classic" overflow, including entirely different bug
types that rely on overflow exploit techniques, such as integer signedness
errors, integer overflows, and format string bugs. This imprecise
terminology can make it difficult to determine which variant is being
reported.
Time of Introduction
Implementation
Applicable Platforms
Languages
C
C++
Assembly
Common Consequences
Scope
Effect
Integrity
Confidentiality
Availability
Technical Impact: Execute unauthorized code or
commands
Buffer overflows often can be used to execute arbitrary code, which is
usually outside the scope of a program's implicit security policy. This
can often be used to subvert any other security service.
Buffer overflows generally lead to crashes. Other attacks leading to
lack of availability are possible, including putting the program into an
infinite loop.
Likelihood of Exploit
High to Very High
Detection Methods
Automated Static Analysis
This weakness can often be detected using automated static analysis
tools. Many modern tools use data flow analysis or constraint-based
techniques to minimize the number of false positives.
Automated static analysis generally does not account for environmental
considerations when reporting out-of-bounds memory operations. This can
make it difficult for users to determine which warnings should be
investigated first. For example, an analysis tool might report buffer
overflows that originate from command line arguments in a program that
is not expected to run with setuid or other special privileges.
Effectiveness: High
Detection techniques for buffer-related errors are more mature than
for most other weakness types.
Automated Dynamic Analysis
This weakness can be detected using dynamic tools and techniques that
interact with the software using large test suites with many diverse
inputs, such as fuzz testing (fuzzing), robustness testing, and fault
injection. The software's operation may slow down, but it should not
become unstable, crash, or generate incorrect results.
Manual Analysis
Manual analysis can be useful for finding this weakness, but it might
not achieve desired code coverage within limited time constraints. This
becomes difficult for weaknesses that must be considered for all inputs,
since the attack surface can be too large.
Demonstrative Examples
Example 1
The following code asks the user to enter their last name and then
attempts to store the value entered in the last_name array.
(Bad Code)
Example
Language: C
char last_name[20];
printf ("Enter your last name: ");
scanf ("%s", last_name);
The problem with the code above is that it does not restrict or limit
the size of the name entered by the user. If the user enters
"Very_very_long_last_name" which is 24 characters long, then a buffer
overflow will occur since the array can only hold 20 characters total.
Example 2
The following code attempts to create a local copy of a buffer to
perform some manipulations to the data.
(Bad Code)
Example
Language: C
void manipulate_string(char* string){
char buf[24];
strcpy(buf, string);
...
}
However, the programmer does not ensure that the size of the data
pointed to by string will fit in the local buffer and blindly copies the
data with the potentially dangerous strcpy() function. This may result
in a buffer overflow condition if an attacker can influence the contents
of the string parameter.
Example 3
The excerpt below calls the gets() function in C, which is
inherently unsafe.
(Bad Code)
Example
Language: C
char buf[24];
printf("Please enter your name and press
<Enter>\n");
gets(buf);
...
}
However, the programmer uses the function gets() which is inherently
unsafe because it blindly copies all input from STDIN to the buffer
without restricting how much is copied. This allows the user to provide
a string that is larger than the buffer size, resulting in an overflow
condition.
Example 4
In the following example, a server accepts connections from a client
and processes the client request. After accepting a client connection, the
program will obtain client information using the gethostbyaddr method, copy
the hostname of the client that connected to a local variable and output the
hostname of the client to a log file.
(Bad Code)
Example Languages: C and C++
...
struct hostent *clienthp;
char hostname[MAX_LEN];
// create server socket, bind to server address and listen on
socket
...
// accept client connections and process requests
int count = 0;
for (count = 0; count < MAX_CONNECTIONS; count++)
{
int clientlen = sizeof(struct sockaddr_in);
int clientsocket = accept(serversocket, (struct sockaddr
*)&clientaddr, &clientlen);
logOutput("Accepted client connection from host ",
hostname);
// process client request
...
close(clientsocket);
}
}
close(serversocket);
...
However, the hostname of the client that connected may be longer than
the allocated size for the local hostname variable. This will result in
a buffer overflow when copying the client hostname to the local variable
using the strcpy method.
By replacing a valid cookie value with an
extremely long string of characters, an attacker may overflow the
application's buffers.
Potential Mitigations
Phase: Requirements
Strategy: Language Selection
Use a language that does not allow this weakness to occur or provides
constructs that make this weakness easier to avoid.
For example, many languages that perform their own memory management,
such as Java and Perl, are not subject to buffer overflows. Other
languages, such as Ada and C#, typically provide overflow protection,
but the protection can be disabled by the programmer.
Be wary that a language's interface to native code may still be
subject to overflows, even if the language itself is theoretically safe.
Phase: Architecture and Design
Strategy: Libraries or Frameworks
Use a vetted library or framework that does not allow this weakness to
occur or provides constructs that make this weakness easier to
avoid.
Examples include the Safe C String Library (SafeStr) by Messier and Viega [R.120.4], and the Strsafe.h library from Microsoft [R.120.3]. These libraries provide safer versions of overflow-prone string-handling functions.
This is not a complete solution, since many buffer overflows are not
related to strings.
Phase: Build and Compilation
Strategy: Compilation or Build Hardening
Run or compile the software using features or extensions that
automatically provide a protection mechanism that mitigates or
eliminates buffer overflows.
For example, certain compilers and extensions provide automatic buffer
overflow detection mechanisms that are built into the compiled code.
Examples include the Microsoft Visual Studio /GS flag, Fedora/Red Hat
FORTIFY_SOURCE GCC flag, StackGuard, and ProPolice.
Effectiveness: Defense in Depth
This is not necessarily a complete solution, since these mechanisms
can only detect certain types of overflows. In addition, an attack could
still cause a denial of service, since the typical response is to exit
the application.
Phase: Implementation
Consider adhering to the following rules when allocating and managing
an application's memory:
Double check that your buffer is as large as you specify.
When using functions that accept a number of bytes to copy, such
as strncpy(), be aware that if the destination buffer size is equal
to the source buffer size, it may not NULL-terminate the
string.
Check buffer boundaries if accessing the buffer in a loop and make
sure you are not in danger of writing past the allocated
space.
If necessary, truncate all input strings to a reasonable length
before passing them to the copy and concatenation functions.
Phase: Implementation
Strategy: Input Validation
Assume all input is malicious. Use an "accept known good" input
validation strategy, i.e., use a whitelist of acceptable inputs that
strictly conform to specifications. Reject any input that does not
strictly conform to specifications, or transform it into something that
does.
When performing input validation, consider all potentially relevant
properties, including length, type of input, the full range of
acceptable values, missing or extra inputs, syntax, consistency across
related fields, and conformance to business rules. As an example of
business rule logic, "boat" may be syntactically valid because it only
contains alphanumeric characters, but it is not valid if the input is
only expected to contain colors such as "red" or "blue."
Do not rely exclusively on looking for malicious or malformed inputs
(i.e., do not rely on a blacklist). A blacklist is likely to miss at
least one undesirable input, especially if the code's environment
changes. This can give attackers enough room to bypass the intended
validation. However, blacklists can be useful for detecting potential
attacks or determining which inputs are so malformed that they should be
rejected outright.
Phase: Architecture and Design
For any security checks that are performed on the client side, ensure that these checks are duplicated on the server side, in order to avoid CWE-602. 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. Then, these modified values would be submitted to the server.
Phase: Operation
Strategy: Environment Hardening
Use a feature like Address Space Layout Randomization (ASLR) [R.120.5] [R.120.7].
Effectiveness: Defense in Depth
This is not a complete solution. However, it forces the attacker to
guess an unknown value that changes every program execution. In
addition, an attack could still cause a denial of service, since the
typical response is to exit the application.
Phase: Operation
Strategy: Environment Hardening
Use a CPU and operating system that offers Data Execution Protection (NX) or its equivalent [R.120.7] [R.120.9].
Effectiveness: Defense in Depth
This is not a complete solution, since buffer overflows could be used
to overwrite nearby variables to modify the software's state in
dangerous ways. In addition, it cannot be used in cases in which
self-modifying code is required. Finally, an attack could still cause a
denial of service, since the typical response is to exit the
application.
Phases: Build and Compilation; Operation
Most mitigating technologies at the compiler or OS level to date
address only a subset of buffer overflow problems and rarely provide
complete protection against even that subset. It is good practice to
implement strategies to increase the workload of an attacker, such as
leaving the attacker to guess an unknown value that changes every
program execution.
Phase: Implementation
Replace unbounded copy functions with analogous functions that support
length arguments, such as strcpy with strncpy. Create these if they are
not available.
Effectiveness: Moderate
This approach is still susceptible to calculation errors, including issues such as off-by-one errors (CWE-193) and incorrectly calculating buffer lengths (CWE-131).
Phase: Architecture and Design
Strategy: Enforcement by Conversion
When the set of acceptable objects, such as filenames or URLs, is
limited or known, create a mapping from a set of fixed input values
(such as numeric IDs) to the actual filenames or URLs, and reject all
other inputs.
Phases: Architecture and Design; Operation
Strategy: Environment Hardening
Run your code using the lowest privileges that are required to accomplish the necessary tasks [R.120.10]. If possible, create isolated accounts with limited privileges that are only used for a single task. That way, a successful attack will not immediately give the attacker access to the rest of the software or its environment. For example, database applications rarely need to run as the database administrator, especially in day-to-day operations.
Phases: Architecture and Design; Operation
Strategy: Sandbox or Jail
Run the code in a "jail" or similar sandbox environment that enforces
strict boundaries between the process and the operating system. This may
effectively restrict which files can be accessed in a particular
directory or which commands can be executed by the software.
OS-level examples include the Unix chroot jail, AppArmor, and SELinux.
In general, managed code may provide some protection. For example,
java.io.FilePermission in the Java SecurityManager allows the software
to specify restrictions on file operations.
This may not be a feasible solution, and it only limits the impact to
the operating system; the rest of the application may still be subject
to compromise.
Be careful to avoid CWE-243 and other weaknesses related to jails.
Effectiveness: Limited
The effectiveness of this mitigation depends on the prevention
capabilities of the specific sandbox or jail being used and might only
help to reduce the scope of an attack, such as restricting the attacker
to certain system calls or limiting the portion of the file system that
can be accessed.
Weakness Ordinalities
Ordinality
Description
Resultant
(where
the weakness is typically related to the presence of some other
weaknesses)
Primary
(where
the weakness exists independent of other weaknesses)
At the code level, stack-based and heap-based overflows do not differ
significantly, so there usually is not a need to distinguish them. From the
attacker perspective, they can be quite different, since different
techniques are required to exploit them.
Affected Resources
Memory
Functional Areas
Memory Management
Causal Nature
Explicit
Taxonomy Mappings
Mapped Taxonomy Name
Node ID
Fit
Mapped Node Name
PLOVER
Unbounded Transfer ('classic overflow')
7 Pernicious Kingdoms
Buffer Overflow
CLASP
Buffer overflow
OWASP Top Ten 2004
A1
CWE_More_Specific
Unvalidated Input
OWASP Top Ten 2004
A5
CWE_More_Specific
Buffer Overflows
CERT C Secure Coding
STR35-C
Do not copy data from an unbounded source to a fixed-length
array
WASC
7
Buffer Overflow
CERT C++ Secure Coding
STR35-CPP
Do not copy data from an unbounded source to a fixed-length
array
A weakness where the code path includes a Buffer Write Operation such
that:
1. the expected size of the buffer is greater than the actual size of
the buffer where expected size is equal to the sum of the size of the
data item and the position in the buffer
Where Buffer Write Operation is a statement that writes a data item of a
certain size into a buffer at a certain position and at a certain
index
References
[R.120.1] [REF-11] M. Howard and
D. LeBlanc. "Writing Secure Code". Chapter 5, "Public Enemy #1: The Buffer Overrun" Page
127. 2nd Edition. Microsoft. 2002.
[R.120.2] [REF-17] Michael Howard, David LeBlanc
and John Viega. "24 Deadly Sins of Software Security". "Sin 5: Buffer Overruns." Page 89. McGraw-Hill. 2010.
[R.120.11] [REF-7] Mark Dowd, John McDonald
and Justin Schuh. "The Art of Software Security Assessment". Chapter 3, "Nonexecutable Stack", Page
76.. 1st Edition. Addison Wesley. 2006.
[R.120.12] [REF-7] Mark Dowd, John McDonald
and Justin Schuh. "The Art of Software Security Assessment". Chapter 5, "Protection Mechanisms", Page
189.. 1st Edition. Addison Wesley. 2006.
[R.120.13] [REF-7] Mark Dowd, John McDonald
and Justin Schuh. "The Art of Software Security Assessment". Chapter 8, "C String Handling", Page 388.. 1st Edition. Addison Wesley. 2006.
The software reads from a buffer using buffer access mechanisms such as indexes or pointers that reference memory locations after the targeted buffer.
Extended Description
This typically occurs when the pointer or its index is incremented to a position beyond the bounds of the buffer or when pointer arithmetic results in a position outside of the valid memory location to name a few. This may result in exposure of sensitive information or possibly a crash.
Time of Introduction
Implementation
Applicable Platforms
Languages
C
C++
Common Consequences
Scope
Effect
Confidentiality
Technical Impact: Read memory
Demonstrative Examples
Example 1
In the following C/C++ example the method processMessageFromSocket()
will get a message from a socket, placed into a buffer, and will parse the
contents of the buffer into a structure that contains the message length and
the message body. A for loop is used to copy the message body into a local
character string which will be passed to another method for
processing.
(Bad Code)
Example Languages: C and C++
int processMessageFromSocket(int socket) {
int success;
char buffer[BUFFER_SIZE];
char message[MESSAGE_SIZE];
// get message from socket and store into buffer
//Ignoring possibliity that buffer >
BUFFER_SIZE
if (getMessage(socket, buffer, BUFFER_SIZE) > 0)
{
// place contents of the buffer into message
structure
ExMessage *msg = recastBuffer(buffer);
// copy message body into string for
processing
int index;
for (index = 0; index < msg->msgLength;
index++) {
message[index] = msg->msgBody[index];
}
message[index] = '\0';
// process message
success = processMessage(message);
}
return success;
}
However, the message length variable from the structure is used as the condition for ending the for loop without validating that the message length variable accurately reflects the length of message body. This can result in a buffer over read by reading from memory beyond the bounds of the buffer if the message length variable indicates a length that is longer than the size of a message body (CWE-130).
Weakness Ordinalities
Ordinality
Description
Primary
(where
the weakness exists independent of other weaknesses)
The software reads from a buffer using buffer access mechanisms such as indexes or pointers that reference memory locations prior to the targeted buffer.
Extended Description
This typically occurs when the pointer or its index is decremented to a position before the buffer, when pointer arithmetic results in a position before the beginning of the valid memory location, or when a negative index is used. This may result in exposure of sensitive information or possibly a crash.
Time of Introduction
Implementation
Applicable Platforms
Languages
C
C++
Common Consequences
Scope
Effect
Confidentiality
Technical Impact: Read memory
Weakness Ordinalities
Ordinality
Description
Primary
(where
the weakness exists independent of other weaknesses)
The software writes to a buffer using an index or pointer that references a memory location prior to the beginning of the buffer.
Extended Description
This typically occurs when a pointer or its index is decremented to a position before the buffer, when pointer arithmetic results in a position before the beginning of the valid memory location, or when a negative index is used.
Alternate Terms
buffer underrun:
Some prominent vendors and researchers use the term "buffer underrun". "Buffer underflow" is more commonly used, although both terms are also sometimes used to describe a buffer under-read (CWE-127).
Out of bounds memory access will very likely result in the corruption
of relevant memory, and perhaps instructions, possibly leading to a
crash.
Integrity
Confidentiality
Availability
Access Control
Other
Technical Impact: Execute unauthorized code or
commands; Modify memory; Bypass protection
mechanism; Other
If the corrupted memory can be effectively controlled, it may be
possible to execute arbitrary code. If the corrupted memory is data
rather than instructions, the system will continue to function with
improper changes, possibly in violation of an implicit or explicit
policy. The consequences would only be limited by how the affected data
is used, such as an adjacent memory location that is used to specify
whether the user has special privileges.
Access Control
Other
Technical Impact: Bypass protection
mechanism; Other
When the consequence is arbitrary code execution, this can often be
used to subvert any other security service.
Likelihood of Exploit
Medium
Demonstrative Examples
Example 1
In the following C/C++ example, a utility function is used to trim
trailing whitespace from a character string. The function copies the input
string to a local character string and uses a while statement to remove the
trailing whitespace by moving backward through the string and overwriting
whitespace with a NUL character.
(Bad Code)
Example Languages: C and C++
char* trimTrailingWhitespace(char *strMessage, int length)
{
char *retMessage;
char *message = malloc(sizeof(char)*(length+1));
// copy input string to a temporary string
char message[length+1];
int index;
for (index = 0; index < length; index++) {
message[index] = strMessage[index];
}
message[index] = '\0';
// trim trailing whitespace
int len = index-1;
while (isspace(message[len])) {
message[len] = '\0';
len--;
}
// return string without trailing whitespace
retMessage = message;
return retMessage;
}
However, this function can cause a buffer underwrite if the input
character string contains all whitespace. On some systems the while
statement will move backwards past the beginning of a character string
and will call the isspace() function on an address outside of the bounds
of the local buffer.
Example 2
The following is an example of code that may result in a buffer
underwrite, if find() returns a negative value to indicate that ch is not
found in srcBuf:
Buffer underflow from an all-whitespace string,
which causes a counter to be decremented before the buffer while looking for
a non-whitespace character.
This could be resultant from several errors, including a bad offset or an array index that decrements before the beginning of the buffer (see CWE-129).
Research Gaps
Much attention has been paid to buffer overflows, but "underflows"
sometimes exist in products that are relatively free of overflows, so it is
likely that this variant has been under-studied.
Causal Nature
Explicit
Taxonomy Mappings
Mapped Taxonomy Name
Node ID
Fit
Mapped Node Name
PLOVER
UNDER - Boundary beginning violation ('buffer
underflow'?)
The software uses an API function that does not exist on all versions of the target platform. This could cause portability problems or inconsistencies that allow denial of service or other consequences.
Extended Description
Some functions that offer security features supported by the OS are not available on all versions of the OS in common use. Likewise, functions are often deprecated or made obsolete for security reasons and should not be used.
Time of Introduction
Architecture and Design
Implementation
Common Consequences
Scope
Effect
Other
Technical Impact: Quality degradation
Potential Mitigations
Phase: Implementation
Always test your code on any platform on which it is targeted to run
on.
Phase: Testing
Test your code on the newest and oldest platform on which it is
targeted to run on.
Phase: Testing
Develop a system to test for API functions that are not portable.
The program calls a thread's run() method instead of calling start(), which causes the code to run in the thread of the caller instead of the callee.
Extended Description
In most cases a direct call to a Thread object's run() method is a bug. The programmer intended to begin a new thread of control, but accidentally called run() instead of start(), so the run() method will execute in the caller's thread of control.
Time of Introduction
Implementation
Applicable Platforms
Languages
Java
Common Consequences
Scope
Effect
Other
Technical Impact: Quality degradation; Varies by context
Demonstrative Examples
Example 1
The following excerpt from a Java program mistakenly calls run()
instead of start().
(Bad Code)
Example
Language: Java
Thread thr = new Thread() {
public void run() {
...
}
};
thr.run();
Potential Mitigations
Phase: Implementation
Use the start() method instead of the run() method.
The software contains a clone() method that does not call super.clone() to obtain the new object.
Extended Description
All implementations of clone() should obtain the new object by calling super.clone(). If a class does not follow this convention, a subclass's clone() method will return an object of the wrong type.
The following two classes demonstrate a bug introduced by not
calling super.clone(). Because of the way Kibitzer implements clone(),
FancyKibitzer's clone method will return an object of type Kibitzer instead
of FancyKibitzer.
(Bad Code)
Example
Language: Java
public class Kibitzer {
public Object clone() throws CloneNotSupportedException
{
Object returnMe = new Kibitzer();
...
}
}
public class FancyKibitzer extends Kibitzer{
public Object clone() throws CloneNotSupportedException
{
Object returnMe = super.clone();
...
}
}
Potential Mitigations
Phase: Implementation
Call super.clone() within your clone() method, when obtaining a new
object.
Phase: Implementation
In some cases, you can eliminate the clone method altogether and use
copy constructors.
The code contains a class with sensitive data, but the class is cloneable. The data can then be accessed by cloning the class.
Extended Description
Cloneable classes are effectively open classes, since data cannot be hidden in them. Classes that do not explicitly deny cloning can be cloned by any other class without running the constructor.
Time of Introduction
Implementation
Applicable Platforms
Languages
C++
Java
.NET
Common Consequences
Scope
Effect
Access Control
Technical Impact: Bypass protection
mechanism
A class that can be cloned can be produced without executing the
constructor. This is dangerous since the constructor may perform
security-related checks. By allowing the object to be cloned, those
checks may be bypassed.
Likelihood of Exploit
Medium
Demonstrative Examples
Example 1
(Bad Code)
Example
Language: Java
public class CloneClient {
public CloneClient() //throws
java.lang.CloneNotSupportedException {
Teacher t1 = new Teacher("guddu","22,nagar road");
//...
// Do some stuff to remove the teacher.
Teacher t2 = (Teacher)t1.clone();
System.out.println(t2.name);
}
public static void main(String args[]) {
new CloneClient();
}
}
class Teacher implements Cloneable {
public Object clone() {
try {
return super.clone();
}
catch (java.lang.CloneNotSupportedException e) {
throw new RuntimeException(e.toString());
}
}
public String name;
public String clas;
public Teacher(String name,String clas) {
this.name = name;
this.clas = clas;
}
}
Potential Mitigations
Phase: Implementation
Make classes uncloneable by defining a clone function like:
(Mitigation Code)
Example
Language: Java
public final void clone() throws
java.lang.CloneNotSupportedException {
throw new java.lang.CloneNotSupportedException();
}
Phase: Implementation
If you do make your classes clonable, ensure that your clone method is
final and throw super.clone().
The software does not follow certain coding rules for development, which can lead to resultant weaknesses or increase the severity of the associated vulnerabilities.
Time of Introduction
Architecture and Design
Implementation
Applicable Platforms
Languages
All
Common Consequences
Scope
Effect
Other
Technical Impact: Other
Potential Mitigations
Phase: Implementation
Document and closely follow coding standards.
Phases: Testing; Implementation
Where possible, use automated tools to enforce the standards.
chain: HTTP server protects against ".." but allows "." variants such as "////./../.../". If the server removes "/.." sequences, the result would collapse into an unsafe value "////../" (CWE-182).
XSS protection mechanism strips a
<script> sequence that is nested in another
<script> sequence.
Potential Mitigations
Phase: Architecture and Design
Strategy: Input Validation
Avoid making decisions based on names of resources (e.g. files) if
those resources can have alternate names.
Phase: Implementation
Strategy: Input Validation
Assume all input is malicious. Use an "accept known good" input
validation strategy, i.e., use a whitelist of acceptable inputs that
strictly conform to specifications. Reject any input that does not
strictly conform to specifications, or transform it into something that
does.
When performing input validation, consider all potentially relevant
properties, including length, type of input, the full range of
acceptable values, missing or extra inputs, syntax, consistency across
related fields, and conformance to business rules. As an example of
business rule logic, "boat" may be syntactically valid because it only
contains alphanumeric characters, but it is not valid if the input is
only expected to contain colors such as "red" or "blue."
Do not rely exclusively on looking for malicious or malformed inputs
(i.e., do not rely on a blacklist). A blacklist is likely to miss at
least one undesirable input, especially if the code's environment
changes. This can give attackers enough room to bypass the intended
validation. However, blacklists can be useful for detecting potential
attacks or determining which inputs are so malformed that they should be
rejected outright.
Phase: Implementation
Strategy: Input Validation
Inputs should be decoded and canonicalized to the application's current internal representation before being validated (CWE-180). Make sure that the application does not decode the same input twice (CWE-174). Such errors could be used to bypass whitelist validation schemes by introducing dangerous inputs after they have been checked.
Canonicalize the name to match that of the file system's
representation of the name. This can sometimes be achieved with an
available API (e.g. in Win32 the GetFullPathName function).
Overlaps regular expressions, although an implementation might not
necessarily use regexp's.
Relevant Properties
Trustability
Taxonomy Mappings
Mapped Taxonomy Name
Node ID
Fit
Mapped Node Name
PLOVER
Collapse of Data into Unsafe Value
CERT Java Secure Coding
IDS11-J
Eliminate noncharacter code points before
validation
References
[REF-7] Mark Dowd, John McDonald
and Justin Schuh. "The Art of Software Security Assessment". Chapter 8, "Character Stripping Vulnerabilities", Page
437.. 1st Edition. Addison Wesley. 2006.
A possible shell file exists in /cgi-bin/ or other accessible directories. This is extremely dangerous and can be used by an attacker to execute commands on the web server.
Time of Introduction
Implementation
Operation
Common Consequences
Scope
Effect
Confidentiality
Integrity
Availability
Technical Impact: Execute unauthorized code or
commands
Potential Mitigations
Phases: Installation; System Configuration
Remove any Shells accessible under the web root folder and children
directories.
The code uses an operator for comparison when the intention was to perform an assignment.
Extended Description
In many languages, the compare statement is very close in appearance to the assignment statement; they are often confused.
Time of Introduction
Implementation
Applicable Platforms
Languages
C
C++
Modes of Introduction
This bug primarily originates from a typo.
Common Consequences
Scope
Effect
Availability
Integrity
Technical Impact: Unexpected state
The assignment will not take place, which should cause obvious program
execution problems.
Likelihood of Exploit
Low
Demonstrative Examples
Example 1
(Bad Code)
Example Languages: C and C++ and Java
void called(int foo) {
foo==1;
if (foo==1) printf("foo\n");
}
int main() {
called(2);
return 0;
}
Example 2
The following C/C++ example shows a simple implementation of a stack
that includes methods for adding and removing integer values from the stack.
The example uses pointers to add and remove integer values to the stack
array variable.
(Bad Code)
Example Languages: C and C++
#define SIZE 50
int *tos, *p1, stack[SIZE];
void push(int i) {
p1++;
if(p1==(tos+SIZE)) {
// Print stack overflow error message and
exit
}
*p1 == i;
}
int pop(void) {
if(p1==tos) {
// Print stack underflow error message and
exit
}
p1--;
return *(p1+1);
}
int main(int argc, char *argv[]) {
// initialize tos and p1 to point to the top of
stack
tos = stack;
p1 = stack;
// code to add and remove items from stack
...
return 0;
}
The push method includes an expression to assign the integer value to
the location in the stack pointed to by the pointer variable.
However, this expression uses the comparison operator "==" rather than
the assignment operator "=". The result of using the comparison operator
instead of the assignment operator causes erroneous values to be entered
into the stack and can cause unexpected results.
Potential Mitigations
Phase: Testing
Many IDEs and static analysis products will detect this
problem.
[REF-7] Mark Dowd, John McDonald
and Justin Schuh. "The Art of Software Security Assessment". Chapter 6, "Typos", Page 289.. 1st Edition. Addison Wesley. 2006.
The program compares classes by name, which can cause it to use the wrong class when multiple classes can have the same name.
Extended Description
If the decision to trust the methods and data of an object is based on the name of a class, it is possible for malicious users to send objects of the same name as trusted classes and thereby gain the trust afforded to known classes and types.
Time of Introduction
Implementation
Applicable Platforms
Languages
Java
Common Consequences
Scope
Effect
Integrity
Confidentiality
Availability
Technical Impact: Execute unauthorized code or
commands
If a program relies solely on the name of an object to determine
identity, it may execute the incorrect or unintended code.
Likelihood of Exploit
High
Demonstrative Examples
Example 1
In this example, the expression in the if statement compares the
class of the inputClass object to a trusted class by comparing the class
names.
(Bad Code)
Example
Language: Java
if (inputClass.getClass().getName().equals("TrustedClassName"))
{
// Do something assuming you trust inputClass
// ...
}
However, multiple classes can have the same name therefore comparing
an object's class by name can allow untrusted classes of the same name
as the trusted class to be use to execute unintended or incorrect code.
To compare the class of an object to the intended class the getClass()
method and the comparison operator "==" should be used to ensure the
correct trusted class is used, as shown in the following example.
(Good Code)
Example
Language: Java
if (inputClass.getClass() == TrustedClass.class) {
// Do something assuming you trust inputClass
// ...
}
Example 2
In this example, the Java class, TrustedClass, overrides the equals
method of the parent class Object to determine equivalence of objects of the
class. The overridden equals method first determines if the object, obj, is
the same class as the TrustedClass object and then compares the object's
fields to determine if the objects are equivalent.
(Bad Code)
Example
Language: Java
public class TrustedClass {
...
@Override
public boolean equals(Object obj) {
boolean isEquals = false;
// first check to see if the object is of the same
class
if
(obj.getClass().getName().equals(this.getClass().getName()))
{
// then compare object fields
...
if (...) {
isEquals = true;
}
}
return isEquals;
}
...
}
However, the equals method compares the class names of the object,
obj, and the TrustedClass object to determine if they are the same
class. As with the previous example using the name of the class to
compare the class of objects can lead to the execution of unintended or
incorrect code if the object passed to the equals method is of another
class with the same name. To compare the class of an object to the
intended class, the getClass() method and the comparison operator "=="
should be used to ensure the correct trusted class is used, as shown in
the following example.
(Good Code)
Example
Language: Java
public boolean equals(Object obj) {
...
// first check to see if the object is of the same
class
if (obj.getClass() == this.getClass()) {
...
}
...
}
Potential Mitigations
Phase: Implementation
Use class equivalency to determine type. Rather than use the class
name to determine if an object is of a given type, use the getClass()
method, and == operator.
Comparison of Object References Instead of Object Contents
Definition in a New Window
Weakness ID: 595 (Weakness Base)
Status: Incomplete
Description
Description Summary
The program compares object references instead of the contents of the objects themselves, preventing it from detecting equivalent objects.
Time of Introduction
Implementation
Common Consequences
Scope
Effect
Other
Technical Impact: Other
This weakness can lead to erroneous results that can cause unexpected
application behaviors.
Demonstrative Examples
Example 1
In the example below, two Java String objects are declared and
initialized with the same string values and an if statement is used to
determine if the strings are equivalent.
(Bad Code)
Example
Language: Java
String str1 = new String("Hello");
String str2 = new String("Hello");
if (str1 == str2) {
System.out.println("str1 == str2");
}
However, the if statement will not be executed as the strings are
compared using the "==" operator. For Java objects, such as String
objects, the "==" operator compares object references, not object
values. While the two String objects above contain the same string
values, they refer to different object references, so the
System.out.println statement will not be executed. To compare object
values, the previous code could be modified to use the equals
method:
(Good Code)
if (str1.equals(str2)) {
System.out.println("str1 equals str2");
}
Example 2
In the following Java example, two BankAccount objects are compared
in the isSameAccount method using the == operator.
(Bad Code)
Example
Language: Java
public boolean isSameAccount(BankAccount accountA, BankAccount
accountB) {
return accountA == accountB;
}
Using the == operator to compare objects may produce incorrect or
deceptive results by comparing object references rather than values. The
equals() method should be used to ensure correct results or objects
should contain a member variable that uniquely identifies the object.
The following example shows the use of the equals() method to compare
the BankAccount objects and the next example uses a class get method to
retrieve the bank account number that uniquely identifies the
BankAccount object to compare the objects.
(Good Code)
Example
Language: Java
public boolean isSameAccount(BankAccount accountA, BankAccount
accountB) {
return accountA.equals(accountB);
}
Potential Mitigations
Phase: Implementation
Use the equals() method to compare objects instead of the == operator.
If using ==, it is important for performance reasons that your objects
are created by a static factory, not by a constructor.
Other Notes
This problem can cause unexpected application behavior. Comparing objects
using == usually produces deceptive results, since the == operator compares
object references rather than values. To use == on a string, the programmer
has to make sure that these objects are unique in the program, that is, that
they don't have the equals method defined or have a static factory that
produces unique objects.
Sensitive memory is cleared according to the source code, but compiler optimizations leave the memory untouched when it is not read from again, aka "dead store removal."
Extended Description
This compiler optimization error occurs when:
1. Secret data are stored in memory.
2. The secret data are scrubbed from memory by overwriting its contents.
3. The source code is compiled using an optimizing compiler, which identifies and removes the function that overwrites the contents as a dead store because the memory is not used subsequently.
This weakness will allow data that has not been cleared from memory to
be read. If this data contains sensitive password information, then an
attacker can read the password and use the information to bypass
protection mechanisms.
Detection Methods
Black Box
This specific weakness is impossible to detect using black box
methods. While an analyst could examine memory to see that it has not
been scrubbed, an analysis of the executable would not be successful.
This is because the compiler has already removed the relevant code. Only
the source code shows whether the programmer intended to clear the
memory or not, so this weakness is indistinguishable from others.
White Box
This weakness is only detectable using white box methods (see black
box detection factor). Careful analysis is required to determine if the
code is likely to be removed by the compiler.
Demonstrative Examples
Example 1
The following code reads a password from the user, uses the password
to connect to a back-end mainframe and then attempts to scrub the password
from memory using memset().
(Bad Code)
Example
Language: C
void GetData(char *MFAddr) {
char pwd[64];
if (GetPasswordFromUser(pwd, sizeof(pwd))) {
if (ConnectToMainframe(MFAddr, pwd)) {
// Interaction with mainframe
}
}
memset(pwd, 0, sizeof(pwd));
}
The code in the example will behave correctly if it is executed
verbatim, but if the code is compiled using an optimizing compiler, such
as Microsoft Visual C++ .NET or GCC 3.x, then the call to memset() will
be removed as a dead store because the buffer pwd is not used after its
value is overwritten [18]. Because the buffer pwd contains a sensitive
value, the application may be vulnerable to attack if the data are left
memory resident. If attackers are able to access the correct region of
memory, they may use the recovered password to gain control of the
system.
It is common practice to overwrite sensitive data manipulated in
memory, such as passwords or cryptographic keys, in order to prevent
attackers from learning system secrets. However, with the advent of
optimizing compilers, programs do not always behave as their source code
alone would suggest. In the example, the compiler interprets the call to
memset() as dead code because the memory being written to is not
subsequently used, despite the fact that there is clearly a security
motivation for the operation to occur. The problem here is that many
compilers, and in fact many programming languages, do not take this and
other security concerns into consideration in their efforts to improve
efficiency.
Attackers typically exploit this type of vulnerability by using a
core dump or runtime mechanism to access the memory used by a particular
application and recover the secret information. Once an attacker has
access to the secret information, it is relatively straightforward to
further exploit the system and possibly compromise other resources with
which the application interacts.
Potential Mitigations
Phase: Implementation
Store the sensitive data in a "volatile" memory location if
available.
Phase: Build and Compilation
If possible, configure your compiler so that it does not remove dead
stores.
Phase: Architecture and Design
Where possible, encrypt sensitive data that are used by a software
system.
Concurrent Execution using Shared Resource with Improper Synchronization ('Race Condition')
Definition in a New Window
Weakness ID: 362 (Weakness Class)
Status: Draft
Description
Description Summary
The program contains a code sequence that can run concurrently with other code, and the code sequence requires temporary, exclusive access to a shared resource, but a timing window exists in which the shared resource can be modified by another code sequence that is operating concurrently.
Extended Description
This can have security implications when the expected synchronization is in security-critical code, such as recording whether a user is authenticated or modifying important state information that should not be influenced by an outsider.
A race condition occurs within concurrent environments, and is effectively a property of a code sequence. Depending on the context, a code sequence may be in the form of a function call, a small number of instructions, a series of program invocations, etc.
A race condition violates these properties, which are closely related:
Exclusivity - the code sequence is given exclusive access to the shared resource, i.e., no other code sequence can modify properties of the shared resource before the original sequence has completed execution.
Atomicity - the code sequence is behaviorally atomic, i.e., no other thread or process can concurrently execute the same sequence of instructions (or a subset) against the same resource.
A race condition exists when an "interfering code sequence" can still access the shared resource, violating exclusivity. Programmers may assume that certain code sequences execute too quickly to be affected by an interfering code sequence; when they are not, this violates atomicity. For example, the single "x++" statement may appear atomic at the code layer, but it is actually non-atomic at the instruction layer, since it involves a read (the original value of x), followed by a computation (x+1), followed by a write (save the result to x).
The interfering code sequence could be "trusted" or "untrusted." A trusted interfering code sequence occurs within the program; it cannot be modified by the attacker, and it can only be invoked indirectly. An untrusted interfering code sequence can be authored directly by the attacker, and typically it is external to the vulnerable program.
Time of Introduction
Architecture and Design
Implementation
Applicable Platforms
Languages
C: (Sometimes)
C++: (Sometimes)
Java: (Sometimes)
Language-independent
Architectural Paradigms
Concurrent Systems Operating on Shared Resources: (Often)
When a race condition makes it possible to bypass a resource cleanup routine or trigger multiple initialization routines, it may lead to resource exhaustion (CWE-400).
When a race condition allows multiple control flows to access a
resource simultaneously, it might lead the program(s) into unexpected
states, possibly resulting in a crash.
Confidentiality
Integrity
Technical Impact: Read files or
directories; Read application
data
When a race condition is combined with predictable resource names and loose permissions, it may be possible for an attacker to overwrite or access confidential data (CWE-59).
Likelihood of Exploit
Medium
Detection Methods
Black Box
Black box methods may be able to identify evidence of race conditions
via methods such as multiple simultaneous connections, which may cause
the software to become instable or crash. However, race conditions with
very narrow timing windows would not be detectable.
White Box
Common idioms are detectable in white box analysis, such as time-of-check-time-of-use (TOCTOU) file operations (CWE-367), or double-checked locking (CWE-609).
Automated Dynamic Analysis
This weakness can be detected using dynamic tools and techniques that
interact with the software using large test suites with many diverse
inputs, such as fuzz testing (fuzzing), robustness testing, and fault
injection. The software's operation may slow down, but it should not
become unstable, crash, or generate incorrect results.
Race conditions may be detected with a stress-test by calling the
software simultaneously from a large number of threads or processes, and
look for evidence of any unexpected behavior.
Insert breakpoints or delays in between relevant code statements to
artificially expand the race window so that it will be easier to
detect.
Effectiveness: Moderate
Demonstrative Examples
Example 1
This code could be used in an e-commerce application that supports
transfers between accounts. It takes the total amount of the transfer, sends
it to the new account, and deducts the amount from the original
account.
(Bad Code)
Example
Language: Perl
$transfer_amount = GetTransferAmount();
$balance = GetBalanceFromDatabase();
if ($transfer_amount < 0) {
FatalError("Bad Transfer Amount");
}
$newbalance = $balance - $transfer_amount;
if (($balance - $transfer_amount) < 0) {
FatalError("Insufficient Funds");
}
SendNewBalanceToDatabase($newbalance);
NotifyUser("Transfer of $transfer_amount succeeded.");
NotifyUser("New balance: $newbalance");
A race condition could occur between the calls to
GetBalanceFromDatabase() and SendNewBalanceToDatabase().
Suppose the balance is initially 100.00. An attack could be
constructed as follows:
(Attack)
Example
Language: PseudoCode
The attacker makes two simultaneous calls of the program, CALLER-1
and CALLER-2. Both callers are for the same user account.
CALLER-1 (the attacker) is associated with PROGRAM-1 (the instance
that handles CALLER-1). CALLER-2 is associated with
PROGRAM-2.
CALLER-1 makes a transfer request of 80.00.
PROGRAM-1 calls GetBalanceFromDatabase and sets $balance to
100.00
PROGRAM-1 calculates $newbalance as 20.00, then calls
SendNewBalanceToDatabase().
Due to high server load, the PROGRAM-1 call to
SendNewBalanceToDatabase() encounters a delay.
CALLER-2 makes a transfer request of 1.00.
PROGRAM-2 calls GetBalanceFromDatabase() and sets $balance to
100.00. This happens because the previous PROGRAM-1 request was not
processed yet.
PROGRAM-2 determines the new balance as 99.00.
After the initial delay, PROGRAM-1 commits its balance to the
database, setting it to 20.00.
PROGRAM-2 sends a request to update the database, setting the
balance to 99.00
At this stage, the attacker should have a balance of 19.00 (due to
81.00 worth of transfers), but the balance is 99.00, as recorded in the
database.
To prevent this weakness, the programmer has several options,
including using a lock to prevent multiple simultaneous requests to the
web application, or using a synchronization mechanism that includes all
the code between GetBalanceFromDatabase() and
SendNewBalanceToDatabase().
Example 2
The following function attempts to acquire a lock in order to
perform operations on a shared resource.
(Bad Code)
Example
Language: C
void f(pthread_mutex_t *mutex) {
pthread_mutex_lock(mutex);
/* access shared resource */
pthread_mutex_unlock(mutex);
}
However, the code does not check the value returned by
pthread_mutex_lock() for errors. If pthread_mutex_lock() cannot acquire
the mutex for any reason, the function may introduce a race condition
into the program and result in undefined behavior.
In order to avoid data races, correctly written programs must check
the result of thread synchronization functions and appropriately handle
all errors, either by attempting to recover from them or reporting it to
higher levels.
chain: time-of-check time-of-use (TOCTOU) race
condition in program allows bypass of protection mechanism that was designed
to prevent symlink attacks.
chain: time-of-check time-of-use (TOCTOU) race
condition in program allows bypass of protection mechanism that was designed
to prevent symlink attacks.
chain: race condition might allow resource to be
released before operating on it, leading to NULL dereference
Potential Mitigations
Phase: Architecture and Design
In languages that support it, use synchronization primitives. Only
wrap these around critical code to minimize the impact on
performance.
Phase: Architecture and Design
Use thread-safe capabilities such as the data access abstraction in
Spring.
Phase: Architecture and Design
Minimize the usage of shared resources in order to remove as much
complexity as possible from the control flow and to reduce the
likelihood of unexpected conditions occurring.
Additionally, this will minimize the amount of synchronization necessary and may even help to reduce the likelihood of a denial of service where an attacker may be able to repeatedly trigger a critical section (CWE-400).
Phase: Implementation
When using multithreading and operating on shared variables, only use
thread-safe functions.
Phase: Implementation
Use atomic operations on shared variables. Be wary of innocent-looking
constructs such as "x++". This may appear atomic at the code layer, but
it is actually non-atomic at the instruction layer, since it involves a
read, followed by a computation, followed by a write.
Phase: Implementation
Use a mutex if available, but be sure to avoid related weaknesses such as CWE-412.
Phase: Implementation
Avoid double-checked locking (CWE-609) and other implementation errors that arise when trying to avoid the overhead of synchronization.
Phase: Implementation
Disable interrupts or signals over critical parts of the code, but
also make sure that the code does not go into a large or infinite
loop.
Phase: Implementation
Use the volatile type modifier for critical variables to avoid
unexpected compiler optimization or reordering. This does not
necessarily solve the synchronization problem, but it can help.
Phases: Architecture and Design; Operation
Strategy: Environment Hardening
Run your code using the lowest privileges that are required to accomplish the necessary tasks [R.362.11]. If possible, create isolated accounts with limited privileges that are only used for a single task. That way, a successful attack will not immediately give the attacker access to the rest of the software or its environment. For example, database applications rarely need to run as the database administrator, especially in day-to-day operations.
Race conditions in web applications are under-studied and probably
under-reported. However, in 2008 there has been growing interest in this
area.
Much of the focus of race condition research has been in Time-of-check Time-of-use (TOCTOU) variants (CWE-367), but many race conditions are related to synchronization problems that do not necessarily require a time-of-check.
Taxonomy Mappings
Mapped Taxonomy Name
Node ID
Fit
Mapped Node Name
PLOVER
Race Conditions
CERT C Secure Coding
FIO31-C
Do not simultaneously open the same file multiple
times
CERT Java Secure Coding
VNA03-J
Do not assume that a group of calls to independently atomic
methods is atomic
CERT C++ Secure Coding
FIO31-CPP
Do not simultaneously open the same file multiple
times
Leveraging Time-of-Check and Time-of-Use (TOCTOU) Race Conditions
References
[R.362.1] [REF-17] Michael Howard, David LeBlanc
and John Viega. "24 Deadly Sins of Software Security". "Sin 13: Race Conditions." Page 205. McGraw-Hill. 2010.
[R.362.2] Andrei Alexandrescu. "volatile - Multithreaded Programmer's Best
Friend". Dr. Dobb's. 2008-02-01. <http://www.ddj.com/cpp/184403766>.
The relationship between race conditions and synchronization problems (CWE-662) needs to be further developed. They are not necessarily two perspectives of the same core concept, since synchronization is only one technique for avoiding race conditions, and synchronization can be used for other purposes besides race condition prevention.
This tries to cover various problems in which improper data are included within a "container."
Time of Introduction
Architecture and Design
Implementation
Applicable Platforms
Languages
All
Common Consequences
Scope
Effect
Other
Technical Impact: Other
Potential Mitigations
Phase: Architecture and Design
Strategy: Separation of Privilege
Compartmentalize the system to have "safe" areas where trust
boundaries can be unambiguously drawn. Do not allow sensitive data to go
outside of the trust boundary and always be careful when interfacing
with a compartment outside of the safe area.
Ensure that appropriate compartmentalization is built into the system
design and that the compartmentalization serves to allow for and further
reinforce privilege separation functionality. Architects and designers
should rely on the principle of least privilege to decide when it is
appropriate to use and to drop system privileges.
A product performs a series of non-atomic actions to switch between contexts that cross privilege or other security boundaries, but a race condition allows an attacker to modify or misrepresent the product's behavior during the switch.
Extended Description
This is commonly seen in web browser vulnerabilities in which the attacker can perform certain actions while the browser is transitioning from a trusted to an untrusted domain, or vice versa, and the browser performs the actions on one domain using the trust level and resources of the other domain.
Time of Introduction
Architecture and Design
Implementation
Applicable Platforms
Languages
All
Common Consequences
Scope
Effect
Integrity
Confidentiality
Technical Impact: Modify application
data; Read application
data
Chain: race condition (CWE-362) from improper handling of a page transition in web client while an applet is loading (CWE-368) leads to use after free (CWE-416)
Browser updates address bar as soon as user clicks
on a link instead of when the page has loaded, allowing spoofing by
redirecting to another page using onUnload method. ** this is one example of
the role of "hooks" and context switches, and should be captured somehow -
also a race condition of sorts **
XSS when web browser executes Javascript events in
the context of a new page while it's being loaded, allowing interaction with
previous page in different domain.
Web browser fills in address bar of clicked-on
link before page has been loaded, and doesn't update
afterward.
Weakness Ordinalities
Ordinality
Description
Primary
This weakness can be primary to almost anything, depending on the
context of the race condition.
Resultant
This weakness can be resultant from insufficient compartmentalization (CWE-653), incorrect locking, improper initialization or shutdown, or a number of other weaknesses.
Under-studied as a concept. Frequency unknown; few vulnerability reports
give enough detail to know when a context switching race condition is a
factor.