Vulnerability of the Day
Back to schedule
Buffer Overflow
Description. See CWE-120
Example: stack-buffer-overflow.zip
Mitigations: Keep track of your array sizes. Check the size of
your buffer as it is inputted. In the case of C, use functions like
strncpy()
instead of
strcpy()
. Avoid functions like
gets
that don't check the input size.
Notes
- Buffer overflows have been very common for a long time
- If you are clever enough, you can override the return pointer
on the stack frame so that your own code is then executed.
- Languages that enforce array lengths are not susceptible to
this classic form (e.g. Java)
- Merely turning on the stack protector is not enough. We could
easily craft an exploit that stays within the stack frame.
Integer Overflow
Description. See CWE-190
Examples: integer-overflow.zip.
Also for an interesting example from Firefox, check out the CVE-2010-2753,
and corresponding
bugzilla, especially the patch
to fix.
Mitigations:
- Check the size of your integers, considering what would
happen if it wrapped around
- Watch the casting - don't just ignore those compiler
warnings!
- Libraries such as SafeInt or BigInteger might be more
suitable if the problem is very complex
Notes
- A wraparound combined with a
malloc
operation
can result in a zero-sized buffer being allocated - leading to a
zero-byte buffer, which will always be overflowed.
- In practice, most integer wraparounds come from improper
casting, not as much from math operations.
- It's impractical to always check every integer for wraparound
after every operation. But, keep this as a consideration in sensitive
situations.
SQL Injection
Description. See CWE-89
Examples: sql-injection.zip.
Mitigations:
- The only acceptable mitigation are properly-used
prepared statements. These API calls are supported by all SQL
standards, and separate the logic of the query from its input
entirely (i.e. pre-compile the SQL). No string concatenation should
be used. Key: don't allow any possibility to let user input turn into
executable code.
- Escaping characters has proven to be a poor substitute, as
changing character sets makes this a moving target and quite hard.
- Using an OO-relational mapper (e.g. Hibernate) can mitigate
this. However, string concatenation on the Hibernate query language
can result in basically the same thing.
Notes
- Currently the top problem on the CWE Top 25 vulnerabilities.
Very common today.
- Can be done in pretty much all languages that can execute
SQL: Java, Ruby, PHP, etc.
- Not particularly hard to find or fix, you just have to know
about it.
- A lot of people will tell you that you need lots of tools to
fix SQL injection. It's all snakeoil... just use prepared statements.
- See this classic XKCD.
OS Command Injection
Description. See CWE-78
Examples:
Mitigations:
- Many languages allow limiting an OS call to a single command,
which can limit the injection.
- Generally speaking, be very careful with OS calls. Avoid, if
possible. Usually, APIs exist that can accomplish the same thing.
- Only allow certain input to these commands, as opposed to
blocking or escaping bad output.
Notes
- Web application technologies like PHP and Ruby on Rails make
these OS calls very easy these days. These are very dangerous, as
getting access to the underlying web server can have a huge impact.
- It's tempting to think you can just use a quick grep function
or call a separate script, but be sure to think twice about that
interaction.
Hard-coded Credentials
Description. See CWE-798
Examples: hardcoded-credentials.zip
Mitigations:
- Extract your credentials out to a properties file, then
install your system with the proper permissions on that properties
file.
- Corollary: don't include default passwords anyway, make the
user define them upon installation
Notes
- Believe it or not, this is another common problem. It's a
common misconception that you can keep secrets in your source code.
- Same kind of concept applies to encryption keys, or
pseudo-random number generator seeds.
- Obfuscation isn't the answer because reverse engineering is
easier than you think. (Takes time and some skill, which crowds
have).
- License keys have had this problem. Many companies today
resort to a remote authentication for license products. But even
then, it's still a tough problem today for desktop client
applications (e.g. Windows Genuine Advantage).
- Hardcoding credentials also breaks maintainability and
deployability. What if your database password was guessed, and you
had to change it?
Log overflow
Description. See CWE-400 for
a general description. Related CWEs are CWE-779 and
CWE-770.
Printing out to a console or logger usually ends up in a text file. If
an attacker knows this, and the logging is unrestricted, then
attackers can fill up the log file and crash the machine by filling up
the hard drive. This is a denial of service attack that is
particularly difficult to recover from. Plus, weird things happen when
the entire hard drive is completely out of bytes, so attackers can
take advantage of this.
Examples: log-overflow.zip.
Linux kernel has had this issue as well.
Mitigations:
- Use a logging library (e.g. log4j). In configuring your
logger, be sure to use rolling log files. These can be rotated on a
daily basis, or by size.
- Be sure to actually test this functionality yourself.
Notes
- Mostly an issue in applications that run on servers, although
desktop clients are not immune to this
- The disadvantage of this mitigation is that you can
potentially lose your logs if they get over-rotated. Attackers can
potentially take advantage of this fact by intentionally overflowing
the logs to erase the evidence. But other protections, like request
limits, can mitigate that problem too.
- As a general rule, avoid unlimited hard drive storage (e.g.
uploading photos). Sometimes it's easier to just store images as
BLOBS in a database (where the table sizes are often limited by
default), as opposed to dealing with the OS directly.
Path Traversal
Description. See CWE-22
Examples: path-traversal.zip.
Also, see this
issue (CVE-2009-2902) or its entry in the CVE
in Tomcat where they allowed web applications be named "...war", which
could be used for arbitrary file deletion outside of the webapp
sandbox.
Mitigations:
- Remember that path strings are very flexible - they can be
relative or absolute. So
a/b/c.txt
is the same as a/b/../b/c.txt
.
The canonical form of any file is just the absolute path
name, e.g. /home/someone/a.txt
- Better to leave the canonicalization to the programming
language. Java uses
getCanonicalPath()
, it's called realpath()
in C, PHP, and Perl. They actually ping the filesystem to interpret
the path string.
- Tactic: canonicalize your sandboxed directory, canonicalize
the final filename you are about to open, and compare the two with
startsWith
.
Notes
- Another one that's common to web applications especially.
This often appears in PHP apps that delegate code to the operating
system, or use flat file storage.
- Akin to SQL Injection where it's string concatenation gone
wrong. Sadly, there's no version of a prepared statement for files
(e.g. set the directory separately from the file name), so
new
File(sandbox, filename)
is still vulnerable to this.
- The myriad of exploits for this one over the years has shown
that blacklisting is not a good approach. Better to just convert to
absolute, and check the directory from there.
- Can also be a danger with configuration files. In the
interest of defense in depth, it might be wise to do this kind of
check when a properties file contains the name of another file.
Cross-Site Scripting (XSS)
Description. See CWE-79
Examples: Use the XAMPP installation as described in the web applications activity.
Mitigations:
- Converting HTML characters to their escaped form (e.g. <
to <) is the safest approach. Only allowing some input is a
good idea, but sometimes you want certain characters to be allowed
and escaping allows for that flexibility.
- However! Knowing which characters to escape is very
tricky. I strongly recommend using an external library, and not just
rolling your own. Check out how complicated it is at OWASP's
XSS Cheat Sheet.
Notes
- Widely considered among the most dangerous vulnerabilities
today. XSS vulnerabilities have affected GMail, Twitter, Facebook,
Hotmail, Yahoo Mail, and just about every other major web application
out there.
- Executing Javascript on another person's machine can result
in a vast number of exploits. In every case, the asset of cross-site
scripting is the user interface. The two main exploits of XSS are:
- A good discussion of XSS, including some fascinating
historical exploits, is on the Ruby
on Rails security page.
- Note that XSS does not always have to be done inside
<script> tags, it can be done in CSS injection, inside image
metadata, and in many other situations.
Cross-Site Request Forgery (CSRF)
Description. See CWE-352.
Another good
description. Essentially, when an HTTP GET request makes a persistent
modification, then you can get users to make changes to other websites
they are already authenticated into.
Examples: Use the given XAMPP with DVWA to construct a CSRF
attack. An example exploit would be getting a user to load an HTML
page with this image:
<img
src="http://127.0.0.1/dvwa/vulnerabilities/csrf/?password_new=12345&password_conf=12345&Change=Change#">
Mitigations:
- As a rule, don't allow GET actions to perform persistent
modifications to the website. GET requests are much easier to forge
than POST requests.
- If a GET does still need to make a modification, then require
authentication within that HTTP request (see DVWA as an example).
- Session tokens should not be allowed in URLs, only in
cookies.
- Consider why you are allowing clients to create GET requests
for other clients anyway (e.g. email clients hiding
img
tags from users initially).
Notes
- Technically, this is not cross-site scripting as no script is
being executed on user's browser. However, CSRFs allow attackers to
fool victims into sending GET requests to malicious sites or by
modifying something in the app itself.
- CSRF is one reason that many email clients don't show images
upon initially showing an email.
Open Redirect
Description. See CWE-601
Examples:
Mitigations:
- Input validation, although more than just validating
character strings - look up the URL itself. Make your whitelist a set
of known, safe, URLs within your app. Only allowing input that
redirects to your own site is also a big step.
- Like file paths and path traversal vulnerabilities, URLs can
get pretty complicated. Java has a
normalize()
method in
the URI
class that helps you canonicalize your URL before checking it. This
is especially helpful if you are in an untrusted site situation (e.g.
your webapp is hosted on the same site as untrusted webapps and you
want to block intra-site redirects like ../evilsite
).
Notes
- While our example uses a form post, exploits more often occur
in URL parameters (e.g.
http://yourwebsite.com/somethingvulnerable.jsp?redirect=www.evilwebsite.com
)
- Detecting this one is the hard part. Most usages of redirects
are when the URLs are not connected to user input (and are therefore
safe). But, whenever user input eventually leads to a redirect,
consider this issue.
- This is a popular vulnerability used in phishing attacks
(i.e. social engineering). Suppose PayPal had an open redirect
vulnerability. Then an attacker could spam people asking them to
check their paypal accounts. The URLs start with
paypal.com
,
so most users would consider them safe and click through.
Hashing and Salt
Description. See CWE-759. If
an attacker breaks in to a system that provides authentication, they
should not be able to access the passwords. Historically, people would
hash (digest) algorithms to accomplish this. However, commonly-guessed
passwords are still vulnerable, as attackers can make "rainbow
tables", or digests of common passwords.
Examples:
- hashing-salt.zip. The given
example is an authentication example that demonstrates the different
ways you can store a password and still authenticate. User sets their
password, which gets salted and then digested (hashed). Every time
the user authenticates, the system then salts and digests the
password, and checks the results.
Mitigations:
- Append a secret "salt" string that only the server knows
before digesting. This will make those digests unrecognizable.
- Make sure that the salt is set by the final user, not
hardcoded or set by default. Server salt is like default passwords or
PRNG seeds - secrets that users should set by default.
Notes
- Don't ever store passwords in plain text. This means that
your "reset password" feature, should never email passwords
in plaintext (because you don't have that anymore!). If you ever
notice a website that does this, they are not hashing their
passwords.
- Don't make your salt easily guessable. Any long string is
fine, since you won't need to remember again.
Log Neutralization
Description. See CWE-117. If
you allow newlines in your logs, then attackers can forge log entries,
throwing investigations off. Related to generalized CRLF Injection ( CWE-93)
Examples:
Mitigations:
- Don't allow newlines in your logs - remove them entirely.
- Depending on what tools are used to analyze logs, the CRLF
character might not be enough. Consider
<br>
if
you can view logs online, too.
- Don't forget to log the situation where a newline is
injected, too.
Notes
- This is one vulnerability that is explicitly a repudiation
threat.
- By itself, this is pretty innocuous. In conjunction with
other attacks, an attacker can provide misinformation in the logs
that throws off the post-exploit investigation.
- Developers who have access to previous logs (or similar logs)
can easily guess or reverse-engineer your patterns, making the result
indistinguishable. Take a look at CAPEC
attack pattern 93.
- Oddly enough, common logging libraries like
java.util.logging
and log4j
don't have an option to remove newlines.
Java Reflection Abuse
Description. See CWE-470.
Despite what you might assume, Java allows you to access private
variables in other classes via its Reflection API. In untrusted API
situations (e.g. plug-in architectures), this can lead to malicious
libraries accessing and tampering with sensitive data.
Examples:
- reflection-abuse.zip.
Running
make
will result in the exploit, make
safe
results in running it under a security manager.
- The ColdFusion database access API has this vulnerability (CVE-2004-2331)
Mitigations:
- Use the Java Security Manager to limit privileged API
situations. While this feature is turned off by default, it's
actually critical for deploying a Java application securely (e.g. in
a servlet container).
Notes
- Many Java servers utilize a strict, security policy (e.g.
Tomcat), however, many default installations of such servers do not
force you to set up your security policy with the Java virtual
machine.
- The Java security manager blocks all kinds of other sensitive
actions, such as
System.exit(1);
, file system access, or
using reflection to instantiate singletons.
- The Deployment & Distribution lecture covers more details
on the Java Security Manager
- PHP also allows this kind of behavior, and third-party
security manager libraries provide similar functionality as the Java
Security Manager.
Uncontrolled Format String
Description. See CWE-134. In
C, printing using
printf(str)
instead of
printf("%s", str)
results in the user being able to control the format string. This is
especially egregious when you look at the
%x
and
%n
codes, which allow users to read and write arbirary bytes to arbitrary
memory locations.
Examples:
- format-string.zip. Run
make
to see some interesting exploits. Also, be sure to check out what read-memory.rb
does (requires make
first)
Mitigations:
- Just use a format string!
- Watch your compiler warnings, which look like:
warning:
format not a string literal and no format arguments
Notes
- The key that makes the
%x
code work is that
printf is a varargs function. If you add more %x
codes
to the string, printf just starts reading memory locations from where
it left off - right at the call stack.
- This one is just as severe as buffer overflow, as it can
allow arbitrary remote code execution.
- Entire
books have been written on elaborate exploits of format string
vulnerabilities
XML Embedded DTDs
Description. See CWE-827.
XML allows for validation of their input using Document Type
Definitions (DTDs). These DTDs are pretty flexible, and allow for
things like reading in external files. However, users can embed their
own DTDs in the header of an XML file, thereby accessing the file
system directly.
Examples: xml-dtd.zip.
Mitigations:
- In most languages, you can disable validation of embedded
DTDs with ease.
- However, make sure you test this closely, as Java's built-in
SAX parser does not always respect
setValidating(false)
and setExpandEntityReferences(false)
depending on the
environment. In that case, you need to override the entity resolver
(see the given example).
Notes
- Ironically, DTDs were originally intended for XML validation,
but it got warped into more of a user convenience. So yes, fixing
this vulnerability means turning off "validation".
- A similar vulnerability is the XML bomb,
which expands XML entities expoentially (causing a DoS by filling up
the memory). However, most XML parsers have limiting defaults for
expanding XML entities, so that XML bombs are (practically speaking)
no longer an issue as long as developers don't explicitly turn off
the limits. An example XML bomb is included in the above zip.
Insecure PRNGs
Description. See CWE-338.
Most pseudo-random number generators (PRNGs) are not designed to be
secure, and with improper management can be easily guessed by a
variety of methods.
Examples:
- prngs.zip. DeckDealer is a simplified
example of a card shuffling class where the PRNG was seeded by the
time, and an outside program could just create a database of possible
seeds and check the results.
- A famous example of this occurred in Debian distributions of
OpenSSL, as described in depth here .
Mitigations:
- Use PRNGs that are designed to be secure: e.g.
java.util.SecureRandom
instead of java.util.Random
.
- Don't use predictable seeds, such as:
- Seeds that are reset consistently. Re-seeding doesn't make
the PRNG any more secure (or "random").
- Millisecond time. In 100 years, there are only 3*10^12
milliseconds, which a botnet can easily enumerate through.
- Nanosecond time. If attackers know roughly when you reset
your seed, they can narrow down the space for guessing.
- Process IDs. Even smaller space than millisecond time.
- Anything else that can be guessed.
Instead, have the user set a secret token upon installation, and
protect that secret token.
Notes
- The need for secure PRNGs arises in many different
situations, such as cryptographic seeds, multi-factor authentication
mechanisms, and session tokens. In most cases, a broken PRNG has
devastating effects (e.g. predicting all future session tokens)
Cache Poisoning
Description. See the CAPEC-141
attack pattern.
Examples:
- A very famous vulnerability (CVE-2008-1447)
in BIND, a DNS protocol that runs at the heart of the internet, had
a cache poisoning vulnerablitity that went undiscovered for decades
until it was found and actively exploited in 2008. DNS maps names to
IP addresses and uses a complex, multi-tiered form of caching
throughout the internet's root nodes. Attackers were able to cause
certain domain names (Yahoo was one of them) to map to different
servers on malicious IP addresses for some users, depending on your
nearest DNS host.
- A similar vulnerability in dnscache (CVE-2008-4392)
attacked the "Start of Authority" requests. The reports show some
relatively simple patches (this
and this)
that essentially do input validation and handle the boundary cases
better.
Mitigations:
- If possible, don't allow users to set their own cache
expiration dates
- If possible, don't allow users much control over caches to
begin with
- As always, input validation helps, but it should not comprise
the whole solution.
- If you implement your own cache, be sure to put some extra
checks in place for expiration dates and purging policies. Build the
feature so that the expiration date is not set by the user, or at the
very least validated to a specific range. If it's worth the
performance hit, periodically purge the cache regardless of
expiration dates.
Notes
- If your system's assets are cached, then your cache becomes
an asset. Consider this possibility in your risk analysis and
planning for new features.
- Historically, cache poisoning has most often applied to
networking situations. The concept, however, is not specific to
networking.
- Cache poisoning can also occur in a web applications if the
attacker can set HTTP headers. In particular, setting HTTP headers
like Last-Modified can fool both the victim's browser cache and
server-side caches (e.g. Squid) into keeping exploits like XSS and
CSRF cached for multiple requests. To mitigate this, never allow user
data to be used in HTTP response headers.
- In the security community, this is often considered more of
an attack than a vulnerability, as often the mistake is not in the
cache itself, it's in the surrounding systems that employ the cache.
Time of Check, Time of Use (TOCTOU)
Description. See CWE-367.
Examples:
Mitigations:
- When possible, try to make transactions as atomic as
possible. If the technology provides a way to check and change in a
single transaction, do it. But this is not always possible.
- To make exploits harder, minimize the time between checking
and using.
- Limit the number of processes that can access a single file (or other resource without much concurrency checking).
- Recheck the resource for integrity after using it.
Notes
- Sometimes this cannot ever be fully mitigated, depending on
the technology and situation.
- This vulnerability is typically a concurrency issue, so all
of best design practices of concurrency apply here.