Configuration
Vulnerabilities
Applications are often installed with default settings that attackers
can use to attack them. This is particularly an issue with third party
software where an attacker has easy access to a copy of the same
application or framework you are running. Hackers know the default
account names and passwords. For example, looking at the contents
of data.py
you know that
there's a default administrator account named 'admin' with the
password
'secret'.
Configuration vulnerabilities also include features that
increase attack surface. A common example is a feature that is on by
default but you are not using, so you didn't configure it and the
default configuration is vulnerable. It also includes debug features
like status pages or dumping stack traces on failures.
Information disclosure #1
Read the contents of the database off of a
running server by exploiting a configuration vulnerability.
You should look through the Gruyere code looking for default
configurations or debug features that don't belong there.
Hint 1
Look at all the files installed with Gruyere. Are there any files
that shouldn't be there?
Hint 2
Look for a .gtl
file that isn't referenced anywhere.
Exploit and Fixes
To exploit, you can use the debug dump
page dump.gtl
to display the contents of the database via the following URL:
https://google-gruyere.appspot.com/123/dump.gtl
To fix, always make sure debug features are not
installed. In this case, delete dump.gtl
. This is an
example of the kind of debug feature that might be left in an
application by mistake. If a debug feature like this is necessary,
then it needs to be carefully locked down: only admin users should
have access and only requests from debug IP addresses should be
accepted.
This exploit exposes the users' passwords. Passwords should
never be stored in cleartext. Instead, you should
use password
hashing. The idea is that to authenticate a user, you don't need
to know their password, only be convinced that the user knows it. When
the user sets their password, you store only a cryptographic hash of
the password and a salt value. When the user re-enters their password
later, you recompute the hash and if it matches you conclude the
password is correct. If an attacker obtains the hash value, it's very
difficult for them to reverse that to find the original
password. (Which is a good thing, since
despite lots
of advice to the contrary, users frequently use the same weak
passwords for multiple sites.)
Information disclosure #2
Even after implementing the fix described above, an attacker can
undo it and execute the attack! How can that be?
Hint
You can upload a file of any type.
Exploit and Fixes
To exploit, Gruyere allows the user to upload files of any
type, including .gtl
files. So the attacker can simply
upload their own copy
of dump.gtl
or a
similar file and than access it. In fact, as noted earlier, hosting
arbitrary content on the server is a major security risk whether it's
HTML, JavaScript, Flash or something else. Allowing a file with an
unknown file type may lead to a security hole in the future.
To fix, we should do several things:
- Only files that are part of Gruyere should be treated as templates.
- Don't store user uploaded files in the same place as application files.
- Consider limiting the types of files that can be uploaded (via a
whitelist).
Information disclosure #3
Even after implementing the fixes described above, a similar attack
is still possible through a different attack vector. Can you find it?
This attack isn't a a configuration vulnerability, just bad code.
Hint 1
You can insert something in your private snippet which will display the contents of the database.
Hint 2
This attack is closely related to the previous ones. There is a bug
in the code that expands templates that you can exploit.
Exploit and Fixes
There is a defect in Gruyere's template expansion code that reparses
expanded variables. Specifically, when expanding a block it expands
variables in the block. Then it parses the block as a template and
expands variables again,
To exploit, add this to your private snippet:
{{_db:pprint}}
To fix, modify the template code so it never reparses inserted
variable values. The defect in the code is due to the fact
that ExpandTemplate
calls _ExpandBlocks
followed by _ExpandVariables
,
but _ExpandBlocks
calls ExpandTemplate
on
nested blocks. So if a variable is expanded inside a nested block and
contains something that looks like a variable template, it will get
expanded a second time. That sounds complicated because it is
complicated. Parsing blocks and variables separately is a fundamental
flaw in the design of the expander, so the fix is non-trivial.
This exploit is possible because the template language allows
arbitrary database access. It would be safer if the templates were
only allowed to access data specifically provided to them. For
example, a template could have an associated database query and only
the data matched by that query would be passed to the template. This
would limit the scope of a bug like this to data that the user was
already allowed to access.
AJAX
vulnerabilities
Bad AJAX code allows attackers to modify parts
of your application in ways that you might not expect. In traditional
client development, there is a clear separation between the
application and the data it displays. That's not true in web
applications as the next two attacks will make clear.
DoS via AJAX
Find an attack that prevents users from seeing
their private snippets on the home page. (The attack should be
triggered after clicking the refresh link and without using XSS.)
Hint 1
Can you figure out how to change the value of the private snippet in
the AJAX response?
Hint 2
What happens if a JSON object has a duplicate key value?
Exploit and Fix
To exploit, create a user
named private_snippet
and create at least one
snippet. The JSON response will then be {'private_snippet' :
<user's private snippet>, ..., 'private_snippet' :
<attacker's snippet>}
and the attacker's snippet replaces
the user's.
To fix, the AJAX code needs to make sure that the
data only goes where it's supposed to go. The flaw here is that the
JSON structure is not robust. A better structure would
be [<private_snippet>, {<user> :
<snippet>,...}]
.
Phishing via AJAX
While the previous attack may seem like a minor inconvenience,
careless DOM manipulation can lead to much more serious problems.
Find a way to change the sign in link in the
upper right corner to point to https://evil.example.com
.
(The attack should be triggered after clicking the refresh
link and without using XSS or a script.)
Hint 1
Look at what the script does to replace the snippets on the page. Can
you get it to replace the sign in link?
Hint 2
Look at the AJAX code to see how it replaces each snippet, and then
look at the structure of the home page and see if you can see what
else you might be able to replace. (You can't just replace the sign in
link. You'll have to replace a bit more.)
Exploit and Fix
To exploit, create a user
named menu-right
and publish a snippet that looks exactly
like the right side of the menu bar.
<a href='https://evil.example.com/login'>Sign in</a>
| <a href='https://evil.example.com/newaccount.gtl'>Sign up</a>
If the user is already logged in, the menu bar will look wrong. But
that's ok, since there's a good chance the user will just think they
somehow accidentally got logged out of the web site and log in again.
To fix, the process of modifying the DOM needs to be
made more robust. When user values are used in as DOM element
identifiers, you should ensure that there can't be a conflict as there
is here, for example, applying a prefix to user values
like id="user_"
. Even better, use your own
identifiers rather than user values.
This spoofing attack is easily detected when the user clicks
Sign in and ends up at evil.example.com
. A clever attacker could
do something harder to detect, like replacing the Sign in link with a
script that renders the sign in form on the current page with the form
submission going to their server.
Other Vulnerabilities
Buffer Overflow and Integer Overflow
A buffer overflow vulnerability exists when an
application does not properly guard its buffers and allow user data to
write past the end of a buffer. This excess data can modify other
variables, including pointers and function return addresses, leading
to arbitrary code execution. Historically, buffer overflow
vulnerabilities have been responsible for some of the most widespread
internet attacks
including SQL
Slammer, Blaster
and Code
Red computer worms. The PS2, Xbox and Wii have all been hacked
using buffer overflow exploits.
While not as well
known, integer overflow vulnerabilities can be just as
dangerous. Any time an integer computation silently returns an
incorrect result, the application will operate incorrectly. In the
best case, the application fails. In the worst case, there is a
security bug. For example, if an application checks
that length + 1 < limit
then this
will succeed if length
is the largest positive integer
value, which can then expose a buffer overflow vulnerability.
This codelab doesn't cover overflow vulnerabilities because
Gruyere is written in Python, and therefore not vulnerable to
typical buffer and integer overflow problems. Python won't allow you
to read or write outside the bounds of an array and integers can't
overflow. While C and C++ programs are most commonly known to expose
these vulnerabilities, other languages are not immune. For example,
while Java was designed to prevent buffer overflows, it silently
ignores integer overflow.
Like all applications, Gruyere is vulnerable to platform vulnerabilities. That
is, if there are security bugs in the platforms that Gruyere is built on top
of, then those bugs would also apply to Gruyere. Gruyere's platform
includes: the Python runtime system and libraries, AppEngine, the operating
system that Gruyere runs on and the client side software (including the web
browser) that users use to run Gruyere. While platform vulnerabilities are
important, they are outside the scope of this codelab as you generally can't fix
platform vulnerabilities by making changes to your application. Fixing platform
vulnerabilities yourself is also not practical for many people, but you can
mitigate your risks by making sure that you are diligent in applying security
updates as they are released by platform vendors.
SQL Injection
Just as XSS vulnerabilities allow attackers to inject script into
web pages, SQL
injection vulnerabilities allow attackers to inject arbitrary
scripts into SQL queries. When a SQL query is executed it can either
read or write data, so an attacker can use SQL injection to read your
entire database as well as overwrite it, as described in the classic
Bobby Tables XKCD comic. If you use
SQL, the most important advice is to avoid building queries by string
concatenation: use API calls instead. This codelab doesn't cover SQL
injection because Gruyere doesn't use SQL.
After the Codelab
We hope that you found this codelab instructive. If you want more
practice, there are many more security bugs in Gruyere than the ones
described above. You should attack your own application using what
you've learned and write unit tests to verify that these bugs are not
present and won't get introduced in the future. You should also
consider using fuzz testing tools. For more information about
security at Google, please visit
our blog or
our corporate security page.
If you'd like to share this codelab with others, please consider
tweeting or buzzing about it or posting one of these badges on your
blog or personal page:
|
<a href="https://google-gruyere.appspot.com/">
<img src="//google-gruyere.appspot.com/static/gruyere-badge.png"
style="padding:4pt" border="0" alt="Learn how to make web apps more
secure. Do the Gruyere codelab."></a>
(Line breaks above should be copied verbatim.)
|
|
<a href="https://google-gruyere.appspot.com/">
<img src="//google-gruyere.appspot.com/static/gruyere-40.png"
style="padding:4pt" border="0" title="Learn how to make web apps more
secure. Do the Gruyere codelab." alt="Learn how to make web apps more
secure. Do the Gruyere codelab."></a>
(Line breaks above should be copied verbatim.)
|
© Google 2017 Terms of Service
The code portions of this codelab are licensed under the
Creative Commons Attribution-No Derivative Works 3.0 United States license
<https://creativecommons.org/licenses/by-nd/3.0/us>.
Brief excerpts of the code may be used for educational or
instructional purposes provided this notice is kept intact.
Except as otherwise noted the remainder of this codelab is licensed under the
Creative Commons Attribution 3.0 United States license
<https://creativecommons.org/licenses/by/3.0/us>.