Main  /  Edit version 27  /  Edit version 28  /   /  Users Area

Difference "Secure Programming with CppCMS" ver. 27 versus ver. 28

Content:

<!--toc-->
## Introduction
Security is one of the major concerns in development of web applications as they are instantly exposed to the world that is full of potential attackers.
Writing web applications today is very similar to walking
over a minefield. If you don't have proper tools and knowledge you are most likely going to loose a "virtual leg".
## State of Mind
There are several golden rules in writing secure web applications:
1. Never trust users input.
2. Think - "How can I attack my application"
3. Learn common vulnerabilities and methods to prevent them so you at least would not do the mistakes others did.
So when it comes to writing web applications always remember that there *is* somebody who would actually try
to do something bad to your site and you are lucky if you
will discover this.
What is even more important that at some point, your
_will_ make a mistake and your web site
_will_ be cracked and you'll have to do a hard work
to restore it. So keep backups and even more important
check your [restore procedures](http://www.joelonsoftware.com/items/2009/12/14.html) work.
## SQL Injections
This is one of the most basic problems that
web developer should be familiar with.
Have you ever written code like:
std::string query=
"SELECT 1 from users "
"WHERE username='" + username +"' AND "
" password='" + password "';
mysql_query(conn,query.c_str());
...
What is the problem?
Assume that password value is
' OR ''='
So the query would look like
SELECT 1 from users
WHERE username='user' AND
password='' OR ''=''
Which would always return 1...
So you get authenticated for knowing SQL `:-)` and not
having proper password
If you ever did that then you should not continue
web development till you read this article:
[SQL Injection](http://en.wikipedia.org/wiki/SQL_injection)
How do you prevent SQL injections?
Use prepared statements. [CppDB library](http://art-blog.no-ip.info/sql/cppdb/) provides all tools you need.
Just rewrite the example above"
sql << "SELECT 1 FROM users "
"WHERE username=? AND password=?"
<< username << password;
Now the values of ? would be _properly_ substituted
with correct values with their real equivalent.
The query as value would be physically separated.
## Sessions
HTTP protocol is stateless so in order to keep
a track of the users on our web site we store
an information in the session. For example:
session().set("username",username);
Now we can know who is the user. Now if we have
the `username` in the session we know what he can
do for example.
There are two ways to store the data in the session:
1. Store all the data at the server side saving a unique
session id at the client side in cookie.
2. Store all the data at the client side in a cookie and
we ensure its validity by digitally signing it.
See: [CppCMS Configuration: session](http://art-blog.no-ip.info/wikipp/en/page/cppcms_1x_config#session)
This cookie is very valuable information as if attacker
gets this cookie he can impersonate himself to this
particular user.
### What to store in the session?
It is ok to store some not-so valuable information
like user name user id and may be some properties
then can affect user itself.
However there are several things you should not
keep in session: user permissions and rights.
Remember that each user can have more then one active
session. Consider you store his rights in the session,
now we want to drop his right and we can't as we don't
know which sessions belong to the user.
### Session handling is cookie based
In CppCMS session handing is cookie based and
only cookie based, so trust CppCMS and don't
reinvent your own methods.
There are many popular methods to store session
id that have design flaws. For example, consider
a popular method of keeping session id in the query string:
http://www.mybank.com/?sid=1234564435
Now publish a link `http://attckers_site.com/` on the
`www.mybank.com` web site. The innocent user
clicks on this link the attacker get user's session id
in the Referrer HTTP header.
Now attacker can go to `www.mybank.com` add `?sid=1234564435` to the URL and transfer all
users money to his account.
So don't reinvent the wheel, use CppCMS session
mechanism that handles this in safely for you.
### Client side storage considerations (Replay attack)
Client side storage is very useful as it allows to
keep all the data at the client side without need
of keeping tack of file system or using DB for
the session storage.
This is especially critical for high performance
applications.
However client side storage has one important
security problem - we have no way to invalidate it
by anything else then timeout.
Consider a situation were we playing a game where
on each level we need to select a one answer from 4.
Now consider user had made a mistake. Now he is not
pleased and he restores his previous cookie and now
goes to the same level again - returns back in time.
There is no way to reset his session to level 1 because
he always can go back in time.
So client side storage in very good thing to use but
you should be very careful with it.
### Server side storage
When using server side storage on file system,
it is very good idea to change the default directory
that CppCMS stores sessions in `/tmp/cppcms_sessions`
to some other location so it would be harder to
to access this data in case of security exploits
on maybe some other parts of program.
For example if the attacker gets the listing of this
directory he would know all session ids in the system.
### Hiding session data.
Sometimes it is useful to store some data in the
session the way the user would not know what it contains.
There is no problem when you are using server side storage,
however when you use client side storage you need
to encrypt the data.
CppCMS provides an option to use encryption such that
the data stored on the client side would be [automatically
encrypted](http://art-blog.no-ip.info/wikipp/en/page/cppcms_1x_config#session.client.cbc)
Use it if you don't want user to see the data you
store in its session.
### Session expiration
There are two basic methods used for session expiration: fixed and renew. See [session.expire](http://art-blog.no-ip.info/wikipp/en/page/cppcms_1x_config#session.expire)
1. `fixed` - the session would expire in fixed period of time since its creation. Use this for all critical parts. Because if the session is hijacked it would limit the amount
of time the attacker can spend on the web site.
2. `renew` - the session is automatically renewed on every visit. It is very user friendly policy, but it allows
to keep the session virtually forever.
Now when bad things happen and we want to invalidate
all existing sessions.
- Server side storage: just clear the directory that
keeps the sessions. By default it is `/tmp/cppcms_sessions/`
- Client side storage: change the secret key of the
the hmac signature.
### Session Fixation
This is a kind of attack that is used for impersonating
other users.
Consider example:
1. Attacker goes to a bank side and receives a session id - special cookie.
2. Attacker injects this cookie to the innocent user using
some kind of XSS attack (see below).
3. User logs in into bank, because the had received the
cookie he already has the session id and this session id
receives some additional rights like to do operations
on the bank account.
4. Attacker goes to the bank site using the same cookie
stored in the user's browser and performs any kind
of operations user can do.
How to prevent this?
cppcms::session_interface::reset_session();
By calling this function during the critical operations
like user log-in the session id would be replaced with
a new one:
if(authentication_ok()) {
session().reset_session();
session().set("user_id",id);
}
This simple operation would prevent session fixation attacks.
### Client side session private keys
In order to use client side session storage
you need to create a secret private keys for this
purpose.
They can be easily generated using `cppcms_make_key` tool.
Don't forget that these keys are top secret, if
attacker discovers them he would be able to escalate
his rights to any level and forge any session data.
## Cross Site Scripting (XSS)
[Cross Site Scripting](http://en.wikipedia.org/wiki/Cross-site_scripting) in one of the most dangerous problems
web developers should deal with.
Most web application deal with content, sometimes it
may be very rich HTML content. Allowing user to
set his own HTML content as-is provides lots of
tool for attacking web site via injecting JavaScript
and for example storing uses session cookies,
and escalating user privileges to much higher ones,
defacing web sites and much more
Many dangerous things can be done even without
writing Java Script code but only using simple
CSS: [Clickjacking](http://en.wikipedia.org/wiki/Clickjacking), [defacement](http://en.wikipedia.org/wiki/Website_defacement) and more.
So if you want to display a rich content you are
most likely need to apply some XSS filters to prevent
bad things.
### Do not allow HTML
First and most basic rule... Do not allow user to
write HTML content on the web site.
This is done by template system by default. Any value
that is displayed on the web site is escaped by default
such that HTTP attributes like `<` are
converted to the save values like `&lt;`.
However you should notice two things:
1. This does not makes it safe if you,
for example write the value inside `href` attribute.
You should use `urlencode` filter (done automatically
with `<% url %>` url-mapper.
Consider:
<a href='/blog/post/<%= title %>'>
Now user creates a title
' onmouseover='alert(XSS)' '
And even after escaping he gets:
<a href='/blog/post/' onmouseover='alert(XSS)' >
Which allow code execution.
Using `<% url %>` tag or urlencode filter would solve the problem:
<a href='<% url "/post/" using tile %>'>
or
<a href='/blog/post/<%= title | urlencode %>'>
2. When you inject some content to the attributes,
always use double quotes `"` as they are escaped
by the default filter, while. the single quotes
are untouched.
This is correct code:
<img alt="<%= alternative %>" ... >
This one may lead to XSS:
<img alt='<%= alternative %>' ... >
If alternative is `text' onclick="alert(xss)" class='`.
would generate a code like:
<img alt='text' onclick="alert(xss)" class='' ...
2. The escape filter is applied only when no other
filters are used so if you use stuff like this:
<h1><%= title | to_title %></h1>
The content would not be escaped as one filter is already used. So you need to add `escape` filter explicitly
<h1><%= title | to_title | escape %></h1>
### XSS Filter
Sometimes we do need rich HTML content. In such cases
we must ensure that the generated HTML do not include
malicious code.
CppCMS provides XSS filters that allow to filter HTML
content using strict white-list rules.
Then can be found under [`cppcms::xss`](http://art-blog.no-ip.info/cppcms_ref_v0_99/namespacecppcms_1_1xss.html) namespace.
The filter uses a predefined set of rules that define
what HTML tags and attributes can be used.
The web developer should carefully select the tags
ones allow to use for content. Special care should be
given for url and style attributes.
Starting from CppCMS 0.99.10 it is possible to create
policy file using simple JSON format.
The policy can be loaded from file by simple calling:
cppcms::xss::rules rules(path_to_file);
And then content can be filtered as:
safe = cppcms::xss:filter(unsafe,rules);
It would validate the input and remove all tags and
properties that do not fit this policy.
For example, this JSON file defiles the simple rule that
can be used with basic TinyMCE WYSIWYG editor:
{
"encoding" : "UTF-8",
"entities" : [ "nbsp" ],
"tags" : {
"opening_and_closing" : [
"p",
"ul","ol","li",
"strong", "em",
"span",
"a"
],
"stand_alone" : [ "br" , "hr" ]
},
"attributes" : [
{
"tags" : [ "a" ],
"attributes" : [ "href" ],
"type" : "absolute_uri"
},
{
"tags" : [ "span" ],
"attributes" : [ "style" ],
"type" : "regex",
"expression" :
"(\\s*text-decoration\\s*:\\s*(underline|line-through)\\s*;)*"
}
]
}
Of course more complex input requires more complex rules. So
when you write such rules make sure:
1. You use only special `uri` attributes for URL tags like `href` or `src` - the primary candidate for Javascipt code injection.
2. Be very careful and strict with allowed CSS styles - best - do not allow them or use very strict set of
used styles. Remember CSS allows XSS injection as well using `url()` tags and is very "helpful" in creation of
click-jacking attacks.
### CSS Styles
CSS styles can be very dangerous. Best practice - do
not allow them at all!
The simplest example would be a click-jacking.
<a href="http://example.com/attack.html"
style="display: block; z-index: 100000;
opacity: 0.5; position: fixed;
top: 0px; left: 0;
width: 1000000px; height: 100000px;
background-color: red;"> </a>
Such style that does not include any URL or unsafe
JavaScript code allows to steal clicks for users.
So if you do allow CSS styles specify the exact
attributes that you allow as it is shown in the example
abive.
### Remember!
Vast majority of web attacks like session hijacking,
session fixation, privileges escalation, impersonating,
start with a simple XSS hole...
## Cross Site Request Forgery (CSRF)
### The attack
Is yet another dangerous and frequently used attack.
Consider a situation. On your web site you have a
simple web form, that allows for example to update some
content:
<form method="post" action="/update">
<input type="hidden" name="id" value="1434">
<textarea name="content">...</textarea>
<input type="submit" value="Update">
</form>
It is placed on www.mysite.com.
Now the controller code validates that the user
that perform this operation allows to do it (has
valid user in session with valid privileges)
Now the attacker creates a small form on his site
www.foe-cats.com that rates cute kittens and writes a
simple form:
<form method="post" action="http://mysite.com/update">
<input type="hidden" name="id" value="1434">
<input type="hidden" name="conent" value="My Site Sucks">
<input type="checkbox" ... > ...
<input type="submit" value="Rate Kittens">
</form>
The only task that remains for the attacker is to
make sure that somebody with correct rights
registered on the mysite.com would rate the
kittens.
Of course much more dangerous things could be done
this way.
### Prevention
There are many different ways to do this, like
never updating data on GET requests or
checking referrer had been proven to have some
security faults.
Currently the best known technique is to use
session specific secret token set withing the
form request.
In order to use CSRF prevention feature you need
to do two things:
1. Set [`security.csrf.enable`](/wikipp/en/page/cppcms_1x_config#security.csrf.enable) option to true, such that every session would have such token.
2. Add hidden token to every POST form using `<% csrf %>` tag.
For example:
<form action="/url" method="post"><% csrf %>
<% form as_p my_form %>
</form>
It would automatically inject the hidden input that would
include session specific CSRF token:
<input type="hidden" name="_csrf" value="df_d482">
And this token would be validated upon `cppcms::form::load`
call automatically.
This efficient and simple technique would prevent
CSRF attacks.
_Remember:_ it should be done for "POST" forms only as
"GET" forms may disclose the secret token in Referrer
header.
### Protect Login forms (or other forms that do not need session information)
### Login CSRF
The CSRF protection depends on session validation, so in order to protect a form, a session must exists when the page is rendered (even for forms that have no other need for session values - like login forms.)
To
protect the login method from Login CSRF attacks, the login() method should
This opens an opportunity for Login CSRF attack.
Consider:
- Bob uses Alice's web site `www.alice.com`
- Eve creates an account on `www.alice.com`
- Eve creates a web site `www.eves-kittens.com` and creates a simple form for rating cute kittens:
<form action="http://www.alice.com/login" method="post" >
<input type="hidden" name="user" value="Eve" >
<input type="hidden" name="pass" value="xyz" >
<input type="submit" value="Cute!">
</form>
- Now Eve asks Bob to rate kittens and it does. Effectively logging himself in into `www.alice.com` on behave of Eve.
- Now every operation that Bob does on the `www.alice.com` web site is performed on behave of Eve and now Eve can for example spy on Bob. Or trick Bob to transfer money to himself effectively transferring them to Eve.
To protect the login method from Login CSRF attacks, the login() method should
look something similar to this (this application pattern should be applied
to all forms where a session isn't present upon the initial rendering of a
form):
void login()
{
login_content c;
if(request().request_method() == "POST" && session().is_set().("prelogin")) {
c.myform.load(context());
if(c.myform.validate() && correct_login(myform))) { // perform form validation and then user validation
session().reset_session();
session().erase("prelogin");
session().set("id",some_id_I_created); // or some other login id stored in the session
response().set_redirect_header("/some/path");
return;
}
}
session.set("prelogin","");
render("loginform",c);
}
This makes sure that the session is actually created
prior to logging in into the web site and thus the
CSRF token is created and checked.
## Random numbers generation
At some point you'll need to deal with random
numbers generation. And [this sample](http://xkcd.com/221/)
would be very good example how not to do things.
However even if you thing that the code like:
int getRandomNumber()
{
return rand();
}
Is better then your are wrong.
Built in C and C++ library pseudo-random number generators
are good for mathematical purposes but they are predictable.
If you want truly random numbers (as for generating some
UUIDs or generating some secret unguessable keys) use
`cppcms::urandom_device` that uses OS services for
generation of proper, cryptographically safe numbers
that can be used for these purposes.
## Character Set Considerations
One of the things that can be used for exploits is
messing up-with character set, providing invalid
character set.
There are many exploits that use invalid character
set to do bad things, for example XSS. This is
especially frequent with non-ASCII compatible
encodings like Shift-JIS.
So the recommendation is to use Unicode UTF-8 encoding
anywhere and validate the input.
CppCMS text widgets forms, JSON parser do this by default.
However if for some reason you prefer to use POST/GET
data directly like:
msg = request().post("message");
Do yourself a favor and validate or filter text encoding using even very simple:
msg = request().post("message");
msg = booster::locale::conv::utf_to_utf<char>(
msg,
booster::locale::conv::skip);
That would remove all invalid UTF-8 sequences.
## C and C++ Security
I put this section C++ secure programming the
last one mostly because most of C++ programmers
know about these issues forgetting that there
are lots of danger in web programming.
### General Notes
C++ language is considered unsafe - it does not provide
array boundary checks by default, uses pointer and many
other "dangerous stuff"
However unlike C, C++ is high level language that
provides abstraction for many things. So using
modern language techniques programming in C++ is
not more dangerous then programming in Java, Python or Ruby.
### Buffer Overflow
Is one of the classic problems:
sprintf(small_buff,"%d",huge_number);
strcpy(small_buffer,huge_string)
These are probably the classic examples of buffer
overflows...
However, in C++ you have `std::string` and `std::stringstream` and allow you to prevent using
these "dangerous" functions and write safer code.
You can use tools like `booster::locale::format` and
of course many tools that come with Boost libraries.
Use them and not "old-school" tools, they will
help you to write safe code and forget about
this problem.
### Dangling pointers
Consider situation:
foo *p=new foo();
...
delete p;
And accidentally on some later point.
p->bar();
The problem that there is some unknown data located
at the pointer. There are techniques can be used
to execute miscellaneous during access to dangling pointer.
The standard solution:
delete p;
p=0;
Is good but it should be done manually and so somebody
at some point will forget it.
How to deal with it right? Use smart pointers.
- `booster::shared_ptr` - smart reference counting pointer (or `std::shared_ptr` for C++0x compilers)
- `std::auto_ptr` or `std::unique_ptr` for C++0x compilers
- Other smart pointers with different copy policies in
booster namespace `hold_ptr`, `clone_ptr`, `copy_ptr` and
more.
They will solve you actually 3 problems not 1.
- Dangling pointers - they will reset them to 0 automatically.
- Memory leaks - manage memory automatically for you
- Make code exception safe such that, if the exception
is thrown between `new` and `delete` the object will
be properly destroyed by smart pointer.
### Integer overflows
Consider you are accepting from the user some number like
a size of data chunk he is going to send and then
add some data you add and ensure that it fits the
required limits:
unsigned user_data_size = // input from user
char *user_data = ...; // some input
unsigned my_data_size = sizeof(my_data);
char buffer[SOME_LIMIT];
if(user_data_size + sizeof(my_data) <= sizeof(buffer)) {
memcpy(buffer,some_data,user_data_size);
memcpy(buffer+user_data_size,
my_data,sizeof(my_data));
}
What is the problem? The code looks perfectly correct
but... lets set `user_data_size=0xFFFFFFFF` and lets
assume that `sizeof(my_data)` is 4 then `user_data_size+sizeof(my_data)` would be 3 and deferentially
smaller then `sizeof(buffer)` but the next `memcpy`
would cause severe buffer overflow...
How to prevent it? Always put the user supplied
data on its own the comparison side.
if(user_data_size <= sizeof(buffer)-sizeof(my_data)) {
...
}
Note signess of the numbers compare signed with signed
and unsigned with unsigned.
## What happens if we still fail?
Even if we take all precautions, we still, sooner
or later will fail.
The question is how to minimize the possible damage.
### After Failure
The most important thing you should care about is backups.
You need to do _backups_ of the software, data
files and of course the data base.
But what is even more important is to check that
you can restore your web site easily from the last
backup. So make regular checks that your restore procedures
work properly. So on the day the bad thing happens you
will be prepared.
It is important to keep logs - logs from your web
server your application logs. In any case of suspicious
operation... Report it to the log. It would be
very helpful to understand what happened.
If the application crashes in production environment
it is very hard to understand what exactly happened.
So when you deploy the application compile it with
debug information. Use CMake's flag `-DCMAKE_BUILD_TYPE=RelWithDebInfo` or just use GCC's
flags `-O2 -g`. Enable core dumps - if the program
crashes you'll be able to open it with debugger
and see what exactly had happened.
### Running as limited user
As we all know bugs happen and software crashes and
crash may give an attacker an opportunity to execute
his own code.
So it is very good idea to run CppCMS under limited user.
If you use a web server to control CppCMS's process life
time for you, then most likely your process will run
under underprivileged user, however if you use
your own service don't forget these two configuration
sections:
- [daemon](/wikipp/en/page/cppcms_1x_config#daemon) - for Unix daemon
- [winservice](/wikipp/en/page/cppcms_1x_config#winservice) - for Windows service.
Create a limited user that can do almost anything and run
the process under it. This way even if attacker succeeds
to execute some code he will not be able to do too much.
CppCMS's daemon allows to provide a `chroot` jail for
the process significantly limiting the parts of the
file system the process can access. The [daemon.chroot](/wikipp/en/page/cppcms_1x_config#daemon.chroot) option
would make it much harder to exploit the security holes
in the application.
## Links
- [Ruby On Rails Security Guide](http://guides.rubyonrails.org/security.html) - very good security programming guide.
- [Open Web Application Security Project](https://www.owasp.org/index.php/Main_Page)
- [XSS Cheat Sheet](http://ha.ckers.org/xss.html) - a wide set of examples of XSS attacks

About

CppCMS is a web development framework for performance demanding applications.

Support This Project

SourceForge.net Logo

Поддержать проект

CppCMS needs You


Navigation

Main Page


Valid CSS | Valid XHTML 1.0