SlideShare a Scribd company logo
Platinum Sponsors:
#DevoxxPL
Applications secure by default
Sławomir Jasek
Pentester / security consultant.
Assessments and consultancy regarding
security of various applications - web,
mobile, embedded, ...
Since 2003 / over 400 systems and
applications
Sławomir Jasek
Code insecure by default
Blacklisting vs whitelisting
Features vs security
Access control
Beware the "silver bullets"
Fight back!
Devops
The Takeaway
Agenda
INSECURE BY DEFAULT
$url =
'https://api.twitter.com/1/statuses/public_timeline.json';
$result = file_get_contents($url);
Is there anything wrong?
The default setting does not verify hostname
=> Man in the Middle
$url = 'https://api.twitter.com/1/statuses/public_timeline.json';
$contextOptions = array(
'ssl' => array(
'verify_peer' => true,
'cafile' => '/etc/ssl/certs/ca-certificates.crt',
'verify_depth' => 5,
'CN_match' => 'api.twitter.com',
'disable_compression' => true,
'SNI_enabled' => true,
'ciphers' => 'ALL!EXPORT!EXPORT40!EXPORT56!aNULL!LOW!RC4'
)
);
$sslContext = stream_context_create($contextOptions);
$result = file_get_contents($url, NULL, $sslContext);
The proper way
http://phpsecurity.readthedocs.org/en/latest/Transport-Layer-Security-%28HTTPS-SSL-and-TLS%29.html
Defaults to false!
file_get_contents(https language:php
file_get_contents verify_peer
Only 1 programmer in 51
uses verify_peer options.
Often to explicitly disable it ;)
The default value changed only recently in PHP 5.6.0.
But there is hope...
All the previous versions susceptible to Man-In-The-Middle attacks.
$url =
'https://api.twitter.com/1/statuses/public_timeline.json';
$req = curl_init($url);
curl_setopt($req, CURLOPT_RETURNTRANSFER, TRUE);
$result = curl_exec($req);
Curl - secure by default
// Open SSLSocket directly
SocketFactory sf = SSLSocketFactory.getDefault();
SSLSocket socket = (SSLSocket) sf.createSocket("mail.google.com", 443);
SSLSession s = socket.getSession();
// ... use socket ...
socket.close();
Java: SSL SocketFactory
// Open SSLSocket directly
SocketFactory sf = SSLSocketFactory.getDefault();
SSLSocket socket = (SSLSocket) sf.createSocket("mail.google.com", 443);
SSLSession s = socket.getSession();
// Verify that the certicate hostname is for mail.google.com
HostnameVerifier hv = HttpsURLConnection.getDefaultHostnameVerifier();
if (!hv.verify("mail.google.com", s)) {
throw new SSLHandshakeException("Expected mail.google.com, "
"found " + s.getPeerPrincipal());
}
// ... use socket ...
socket.close();
https://developer.android.com/training/articles/security-ssl.html#WarningsSslSocket
SSL SocketFactory
And the docs do not help
https://developer.android.com/training/articles/security-ssl.html#WarningsSslSocket
Pentester’s experience: all tested Android apps using
SSLSocket were vulnerable.
Despite the bold warnings and proper example code...
URL url = new URL("https://mail.google.com");
URLConnection urlConnection = url.openConnection();
InputStream in = urlConnection.getInputStream();
copyInputStreamToOutputStream(in, System.out);
You need to explicitly disable verification.
Pentester’s experience: only a few tested Android apps
using urlConnection were deliberately broken.
HTTPS – the proper way
BLACKLISTING
Attack scenario:
http://localhost/foo/bar.action?<script>alert(1)</script>
Lack of proper output encoding.
Intruder runs hostile javascript in a victim’s browser
(aka „Cross Site Scripting”).
Struts 2 – XSS vulnerability
--- struts2/trunk/core/src/main/java/org/apache/struts2/views/util/UrlHelper.java
2008/01/24 07:37:32 614813
+++ struts2/trunk/core/src/main/java/org/apache/struts2/views/util/UrlHelper.java
2008/01/24 07:39:45 614814
@@ -174,10 +174,14 @@
buildParametersString(params, link, "&");
}
- String result;
+ String result = link.toString();
+
+ if (result.indexOf("<script>") >= 0){
+ result = result.replaceAll("<script>", "script");
+ }
Fix - blacklisting
Attack 1:
/myAction.action?param"><sCript>alert('XSS');</sCript>=1
This is very similiar to the vulnerability in Security Bulletin S2-002; however,
the implemented fix for S2-002 only checks for "<script>", not "<sCript>".
Attack 2:
/myAction.action?param"onMouseOver%3D"javascript:alert('XSS');">=1
Simply checking for <script> isn't sufficient because certain attributes can be
injected to execute javascript. In attack 2, the user simply has to hover over
the link with their mouse and arbitrary javascript will be executed.
https://issues.apache.org/jira/browse/WW-3410
2 years later...
-builder.append(name)
+builder.append(translateAndEncode(name))
That was 19 characters - exactly 4.78 times less than 91
characters used in first, unsuccessful „blacklist” fix.
Final fix
We found an XSS vulnerability, as usually recommended
to properly encode relevant characters in the output
context.
Retest #1: <script> does not work, but <Script> does ;)
Retest #2: <Script> nor <sCript> does not work. But onclick does.
Retest #3: onclick does not work, but onmouseover does.
Retest #4: onmouseover fixed, but onmousedown not ;)
Retest #5: ...
From the pentester's diary
+------------------------+
| XSS_PAYLOAD |
+------------------------+
| onclick= |
| ondblclick= |
| onmousedown= |
| onmousemove= |
| onmouseover= |
| onmouseout= |
| onmouseup= |
| onkeydown= |
| onkeypress= |
| onkeyup= |
| onabort= |
| onerror= |
| onload= |
| onresize= |
Finally, we broke into database via sql-injection
| onscroll= |
| onunload= |
| onblur= |
| onchange= |
| onfocus= |
| onreset= |
| onselect= |
| onsubmit= |
| onevent= |
| <script |
| script> |
| <svg |
| svg> |
| javascript: |
| <iframe |
| iframe> |
| <form |
| form> |
| <input |
| ''iframe'' |
| "iframe" |
| document.createelement |
| string.fromcharcode( |
| <img/src |
| submit() |
| document.location. |
| alert( |
| <img |
| <vbscript |
...
www.example.com/?file=../etc/passwd
Fix: remove ../
www.example.com/?file=....//etc/passwd
www.example.com/?file=....//etc/passwd
www.example.com/?file=../etc/passwd
Proper way: whitelist of allowed characters.
Path traversal
FEATURES VS SECURITY
Define user
# fields: [:id, :first, :last, :email, :admin]
class User < ActiveRecord::Base
End
RoR – user edit form
User edit form
user = User.find(params[:id])
user.update_attributes(params[:user])
PUT
http://app.com/users/66?user[first]=Slawomir
&user[last]=Jasek&user[email]=slawomir.jasek
@securing.pl
RoR – user edit form
PUT
http://app.com/users/66?user[first]=Slawomir
&user[last]=Jasek&user[email]=slawomir.jasek
@securing.pl&user[admin]=true
RoR – mass assignment
You were supposed to manually add whitelisted:
class User < ActiveRecord::Base
attr_accessible :first, :last, :email
end
or blacklisted parameters:
class User < ActiveRecord::Base
attr_protected :admin
end
RoR – mass assignment (2012)
GitHub PWND
http://www.h-online.com/security/news/item/GitHub-security-incident-highlights-Ruby-on-Rails-problem-1463207.html
Change default value of global config parameter turning
the mass assignment off:
# Enforce whitelist mode for mass assignment.
# This will create an empty whitelist of attributes available for mass-
assignment for all models
# in your app. As such, your models will need to explicitly whitelist or
blacklist accessible
# parameters by using an attr_accessible or attr_protected declaration.
<%= comment_if :skip_active_record %>
config.active_record.whitelist_attributes = true
Fix - evolution
config.active_record.mass_assignment_sanitizer
It will raise an
ActiveModel::MassAssignmentSecurity::Error
any time your application attempts to mass-assign
something it shouldn't.
RoR 3.2: Mass assignment sanitizer
Secure by default. You must first call permit on the params hash
with the keys that are allowed for a specific action:
# Require that :user be a key in the params Hash,
# and only accept whitelisted attributes
def user_params
params.require(:user).permit(:first, :last, :email)
end
http://code.tutsplus.com/tutorials/mass-assignment-rails-and-you--net-31695
RoR 4: Strong Parameters
Before:
<%=HTMLEncoder.encode(((Person)person).getAd
dress().getStreet())%>
After (EL):
<c:out value="person.address.street"/>
Expression language – starring major frameworks
Applications secure by default
DEMO
- The security impact
Major frameworks: Spring, JBoss
SEAM, Struts...
Easy to detect, automatic tools
to exploit remotely into shell.
The "no man's land".
(as I have pointed out in 2012)
http://prezi.com/awm8psp-i1ok/no-mans-land
Expression Language flaws
https://play.google.com/store/apps/details?id=com.cleanmaster.security.struts2
2003: parameter names like: @System@exit(1)
"Patrick says he has fixed it" ;)
2008.06: the # can be encoded in u0023
('u0023' + 'session['user'])(unused)=0wn3d
Released Xwork 2.0.5 – blacklisted the attack
2008.10: removed space characters and the exploit still
works ;)
('u0023'+'session['user'])(unused)=0wn3d
The fix - features vs security
2010: You can access the context and turn the settings on:
http://mydomain/MyStruts.action?('u0023_memberAccess['allowStatic
MethodAccess']')(meh)=true&(aaa)(('u0023context['xwork.MethodAcc
essor.denyMethodExecution']u003du0023foo')(u0023foou003dnew%20
java.lang.Boolean("false")))&(asdf)(('u0023rt.exit(1)')(u0023rtu
003d@java.lang.Runtime@getRuntime()))=1
Fix: whitelist allowed chars in parameter names
2011: User input is evaluated as an OGNL expression when there's a
conversion error.
2011: The problem concerns not only parameters, but also cookie
values
The fix – continued...
2012: fix based on whitelisting acceptable parameter names closed
the vulnerability only partially. Still possible RCE with slightly modified
attack syntax.
Fix: deny evaluation in parameter names.
2013: The second evaluation happens when redirect result reads it
from the stack and uses the previously injected code as redirect
parameter.
I won't reveal all the following episodes, I encourage you to read on:
http://struts.apache.org/docs/security-bulletins.html
There's a lot of action! Struts.action.
The fix – continued
data=%3C%3Fxml+version%3D%221.0%22%3F%3E%0A%3Cuser%3E%0A%C2%A0%C
2%A0%C2%A0%C2%A0%3Cfirstname%3EJan%3C%2Ffirstname%3E%0A%C2%A0%C2
%A0%C2%A0%C2%A0%3Clastname%3EKowalski%3C%2Flastname%3E%0A%3C%2Fu
ser%3E
HTML decoded:
<?xml version="1.0"?>
<user>
<firstname>Jan</firstname>
<lastname>Kowalski</lastname>
</user>
XML parsing
<?xml version="1.0"?>
<!DOCTYPE lolz [
<!ENTITY lol "lol">
<!ELEMENT lolz (#PCDATA)>
]>
<lolz>&lol;</lolz>
<lolz>lol</lolz>
XML parsing: DOCTYPE
<?xml version="1.0"?>
<!DOCTYPE lolz [
<!ENTITY lol "lol">
<!ENTITY lol1
"&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;">
<!ELEMENT lolz (#PCDATA)>
]>
<lolz>&lol1;</lolz>
<lolz>lollollollollollollollollollol</lolz>
XML parsing: DOCTYPE
<?xml version="1.0"?>
<!DOCTYPE lolz [
<!ENTITY lol "lol">
<!ELEMENT lolz (#PCDATA)>
<!ENTITY lol1 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;">
<!ENTITY lol2 "&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;">
<!ENTITY lol3 "&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;">
<!ENTITY lol4 "&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;">
<!ENTITY lol5 "&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;">
<!ENTITY lol6 "&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;">
<!ENTITY lol7 "&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;">
<!ENTITY lol8 "&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;">
<!ENTITY lol9 "&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;">
]>
<lolz>&lol9;</lolz>
<user>
<firstname>Jan</firstname>
<lastname>Kowalski</lastname>
</user>
"The Man Who Laughs"
http://en.wikipedia.org/wiki/Billion_laughs
ROTFL TO DEATH!!!
<!ENTITY xxe SYSTEM "file:///etc/passwd" >]>
<foo>&xxe;</foo>
As seen in Google, Facebook, Ebay and about 80%
of tested applications processing user input as XML.
It may be even worse
FB XXE
Technology Default DTD processing value
.NET 4 settings.DtdProcessing =
DtdProcessing.Prohibit;
.NET 3.5 ProhibitDtd in XmlReaderSettings is true, but
ProhibitDtd in XmlTextReader is false
LibXML2 (C++ ) starting with libxml2 version 2.9 (2012), XXE has been disabled
by default
NSXMLDocument
(iOS)
iOS5 and later: Only entities that don't require network access
are loaded.
iOS4 and earlier: All external entities are loaded by default.
Xerces 2 disallow-doctype-decl=false
Xerces 1 external-general-entities=true
PHP Have to manually disable:
libxml_disable_entity_loader(true);
Default DTD processing in various parsers
ACCESS CONTROL
Access control: typical scenario
Student tries to invoke administrative functions
GET /course/quiz/solutions
GET /admin/course/cancel
Student tries to access restricted data
GET /course/view/42
Student tries to alter his account rights.
POST /user/edit
roles=[student,admin]
Access control: typical attack
<security:intercept-url pattern="/user/add"
access="hasRole('ROLE_ADMIN') or hasRole('ROLE_MANAGER')" />
<security:intercept-url pattern="/user/view"
access="hasRole('ROLE_ADMIN')
or hasRole('ROLE_MANAGER')
or hasRole('ROLE_PRINCIPAL')
or hasRole('ROLE_TEACHER')
or hasRole('ROLE_STUDENT')" />
Approach 1: Spring Security
It works for simple apps, with unsophisticated role policies
(e.g. separated admin interface).
Will not work for:
POST /user/edit HTTP/1.1
task=MODIFY_RIGHTS&id=34
Has concept of „roles”, but out of the box does not have
concept of „permissions”. Spring ACL on the other hand is
too complex.
Does not help a lot with access to specific instance (e.g.
other user’s data)
Spring Security
Complex hard-coded checks in application code,
needed to be manually loaded to every endpoint:
If (( user.isRole('ROLE_ADMIN') ||
user.isRole('ROLE_MANAGER') ||
user.isRole('ROLE_PRINCIPAL') ) ||
( user.isRole('ROLE_TEACHER') &&
user.isTeacher(course) ) ||
( user.isRole('ROLE_STUDENT') &&
(user.isStudent(course) )
...and you will probably end-up with:
One simple "if" statement, permissions separated from roles.
if ( currentUser.isPermitted("users:add") ) {
//add an user
}
int courseId=request.getInt("course")
if ( currentUser.isPermitted("courses:view:"+courseId) ) {
//show contents of course
}
Apache Shiro – permission based access control
Real story: account history – select your account
The REST API request
GET /services/history/account/85101022350445200448009906 HTTP/1.1
SA-DeviceId: 940109f08ba56a89
SA-SessionId: 826175
Accept: application/json
Host: acc
Connection: Keep-Alive
User-Agent: Apache-HttpClient/UNAVAILABLE (java 1.4)
The REST API request
GET /services/history/account/45101022350445200448005388 HTTP/1.1
SA-DeviceId: 940109f08ba56a89
SA-SessionId: 826175
Accept: application/json
Host: acc
Connection: Keep-Alive
User-Agent: Apache-HttpClient/UNAVAILABLE (java 1.4)
Change the acc number -> get other user’s data
John:
<select name="account">
<option value=0 >85101022350445200448009906</option>
<option value=1 >34101022350445200448009905</option>
<option value=2 >41101022350445200448009904</option>
</select>
Mary:
<select name="account">
<option value=0 >45101022350445200448005388</option>
<option value=1 >31101022350445200448005390</option>
</select>
The better way?
"Local" ID mapped server-side
into real values
The better way?
SA-DeviceId: d4c79a0fd994b1f3
SA-SessionId: 850073
GET /services/history/account/1 HTTP/1.1
SA-DeviceId: 940109f08ba56a89
SA-SessionId: 826175
Accept: application/json
Host: acc
Connection: Keep-Alive
User-Agent: Apache-HttpClient/UNAVAILABLE (java 1.4)
It is(?) by design not possible to attack other user's data.
Would be great if not...
John:
GET /services/history/account/2
HTTP/1.1
SA-DeviceId: 940109f08ba56a89
SA-SessionId: 826175
Accept: application/json
Host: acc
Connection: Keep-Alive
API just works as a proxy to backend system.
Default session mechanism from backend – just incrementing IDs ;)
Mary:
GET /services/history/account/2
HTTP/1.1
SA-DeviceId: d4c79a0fd994b1f3
SA-SessionId: 826179
Accept: application/json
Host: acc
Connection: Keep-Alive
Trivial to guess other user's sessionId
Automatically encrypts paths with individual, session-
based and unique key:
www.app.com/admin/user/edit
www.app.com/?x=XSn4MUyv6Uke22d9vEuGgR8yZa5-
TkeuxlXeeVypcehJ8HQgNbj(...)
Apache Wicket
The browser works on rendered GUI elements, POSTs to the
server event-driven actions (e.g. mouse clicks in certain location).
It is by design not possible to invoke actions that are not in GUI.
POST /dashboard/UIDL/?v-uiId=0 HTTP/1.1
Host: demo.vaadin.com
{"csrfToken":"981b1cd6-66df-481c-9d6e-
6c293eb70ea3","rpc":[["283","v","v",["positionx",["i","440"]]],["283","
v","v",["positiony",["i","139"]]],["309","com.vaadin.shared.ui.button.B
uttonServerRpc","click",[{"altKey":false,"relativeX":"42","relativeY":"
23","ctrlKey":false,"button":"LEFT","shiftKey":false,"clientX":"1109","
clientY":"598","metaKey":false,"type":"1"}]]],"syncId":14}
Vaadin
BEWARE
There's no silver bullet!
Hadi Hariri keynote on Monday
Automagic output encoding by framework
A framework automatically encodes special chars into
HTML:
<bean:write name="transferFormId" property="trn_recipient"/>
ATTACK: trn_recipient="<script>alert('xss')</script>
<input type="text" name="trn_recipient"
value="&quot;&lt;script&gt;alert('xss')&lt;/script&gt;"
Beware the security mechanism use cases
But unfortunatelly that does not help when you put a
value from end-user directly into javascript context:
<script> var split='<bean:write name="transferFormId"
property="trn_recipient">'; splitRecipient(split);
</script>
ATTACK: trn_recipient=';alert('xss');--
<script> var split='';alert('xss');--
Encode special chars properly in context!
• HTML element
• HTML atribute
• JavaScript
• JSON
• CSS / style
• URL
Encode properly
Prepared statement / call
String sql = "select * from users where
firstname=? and lastname=?";
query = conn.prepareStatement(sql);
firstname = request.getParameter("first");
lastname = request.getParameter("last");
query.setString(1, firstname);
query.setString(2, lastname);
result = query.executeQuery();
String sql = "{call
USERS.search(" + "?" + ", ?)}";
call = conn.prepareCall(sql);
firstname = request.getParameter("first");
lastname = request.getParameter("last");
call.setString(1, firstname);
call.setString(2, lastname);
call.execute();
prepared statement prepared call
Called stored procedure
PROCEDURE search(
p_firstname IN T_STRING,
p_lastname IN T_STRING,
) IS
(...)
v_sql_select := ' SELECT distinct a.USER_ID';
v_sql_from := ' FROM APP_WEB.USERS a ';
v_sql_where := ' WHERE a.USER_ID is not null ';
IF p_firstname is not null THEN
v_sql_where := v_sql_where || ' and lower(trim(a.FIRSTNAME)) =
lower(trim(' || P_FIRSTNAME || ')) ';
END IF;
SQL injection inside stored procedure
PROCEDURE search(
p_firstname IN T_STRING,
p_lastname IN T_STRING,
) IS
(...)
v_sql_select := ' SELECT distinct a.USER_ID';
v_sql_from := ' FROM APP_WEB.USERS a ';
v_sql_where := ' WHERE a.USER_ID is not null ';
IF p_firstname is not null THEN
v_sql_where := v_sql_where || ' and lower(trim(a.FIRSTNAME)) =
lower(trim('|| 'adam')) union select version,'x' from v$instance-- || ')) ';
END IF;
NoSQL. There is no sql injection.
There is nosql injection!
Instead of
' OR 1=1 --
try
a'; return 1=1; var dummy='a
NoSQL
Change SMS authorization phone number in internet banking application
Application logic flaws
What could possibly go wrong?
Change SMS authorization phone number in internet banking application
The scenario missed in functional tests
Change SMS authorization phone number in internet banking application
The evil wins
The application did verify only the SMS code from the new phone.
And intruder with access to user session can take over the authorization.
FIGHT BACK!
- Intrusion detection and prevention
• Input validation server-side when client-side
validation exists
• Non-user editable parameters/values (hidden fields,
checkboxes, radio buttons, select lists)
• Forced browsing to common attack entry points or
honeypot URL (e.g. in robots.txt)
• Obvious sqli, xss inj attacks
• Workflow sequence abuse
Intrusion detection – level basic
http://www.slideshare.net/JimManico/top-ten-defenses-v10 slide 60
One of the most annoying experiences during test was
automatic logout on every test-case in application that
required manual interaction to authenticate.
Active intrusion prevention
OWASP AppSensor
Conceptual framework and methodology to implement intrusion detection and
automated response into applications.
https://www.owasp.org/index.php/OWASP_AppSensor_Project
OWASP mod_security core ruleset
An easily "pluggable" set of generic attack detection rules that
provide a base level of protection for any web application.
https://www.owasp.org/index.php/Category:OWASP_ModSecurity_Core_Rule_Set_Project
Basic tools
DEVOPS
- Default infrastructure
Default error handling
Reveals information on used components,
helps to attack known vulnerabilities
Trading application – binary protocol
Trading application – binary protocol
Trading application – binary protocol
And what if we...
And how about...
<soapenv:Body> <registerUserResponse
soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encodin
g/">
<registerUserReturn xsi:type="xsd:string">
&lt;error code=&quot;266&quot; &gt;Incorrect
login&lt;/error&gt;
</registerUserReturn></registerUserResponse></soapenv:Body>
• Incorrect password
• Incorrect first name
• Group with name null
doesn't exist
• Group with name admin doesn't exist
• Group with name Administrator
doesn't exist
• And how about „root”?
RegisterUser
Game Over
<soapenv:Body>
<registerUserResponse
soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/
encoding/">
<registerUserReturn xsi:type="xsd:string">
User was registered sucessfully with id=5392745
Access to system with administartor rights.
Possible to manage accounts of all other users.
Architecture
Default HTTP error response
Reveals used version
Known vulnerabilities based on version
Apache Tomcat < 6.0.20
<role rolename="tomcat"/>
<role rolename="role1"/>
<user username="tomcat" password="tomcat" roles="tomcat"/>
<user username="both" password="tomcat" roles="tomcat,role1"/>
<user username="role1" password="tomcat" roles="role1"/>
tomcat-users.xml
Apache Tomcat Manager
Tomcat worm using weak passwords
http://www.symantec.com/connect/blogs/all-your-tomcat-are-belong-bad-guys
tryLogins = {
"admin:admin",
"tomcat:tomcat",
"admin:",
"tomcat:",
"root:root",
"manager:manager",
"tomcat:admin",
"admin:password"};
OWASP dependency check / dependency track
Automatically checks for known
vulnerabilities in used components
https://www.owasp.org/index.php/OWASP_Dependency_Track
THE TAKEAWAY
• Use secure design architecture
• Least privilege principle (default: deny)
• Code that enforces good practices
• Leverage existing security mechanisms, but be aware
of their shortcomings and secure use scenario.
• Secure configuration
• Keep the components up to date
• Change default credentials
• Harden the configuration
• Leverage additional layers of protection (IDS, WAF)
Key takeaways
Our presentations (including this one), resources
www.securing.pl/en/resources/
Free security consultancy service:
www.securing.pl/konsultacje
See also
And for the Happy(?)-End – the pentester’s view
Features at low cost compromising on security is just obscene ;) Let’s do it better!
Thank you,
looking forward to contact!
slawomir.jasek@securing.pl
MORE THAN
SECURITY
TESTING
Free security consultancy service:
www.securing.pl/konsultacje

More Related Content

PDF
IoThings you don't even need to hack
Slawomir Jasek
 
PDF
Applications secure by default
SecuRing
 
PPTX
In The Middle of Printers - The (In)Security of Pull Printing solutions - Hac...
Jakub Kałużny
 
PPTX
Ten Commandments of Secure Coding
Mateusz Olejarka
 
PDF
44CON London 2015 - Jtagsploitation: 5 wires, 5 ways to root
44CON
 
PPTX
Java bytecode Malware Analysis
Brian Baskin
 
PPTX
Shameful Secrets of Proprietary Network Protocols - OWASP AppSec EU 2014
Jakub Kałużny
 
PDF
Art of Web Backdoor - Pichaya Morimoto
Pichaya Morimoto
 
IoThings you don't even need to hack
Slawomir Jasek
 
Applications secure by default
SecuRing
 
In The Middle of Printers - The (In)Security of Pull Printing solutions - Hac...
Jakub Kałużny
 
Ten Commandments of Secure Coding
Mateusz Olejarka
 
44CON London 2015 - Jtagsploitation: 5 wires, 5 ways to root
44CON
 
Java bytecode Malware Analysis
Brian Baskin
 
Shameful Secrets of Proprietary Network Protocols - OWASP AppSec EU 2014
Jakub Kałużny
 
Art of Web Backdoor - Pichaya Morimoto
Pichaya Morimoto
 

What's hot (20)

PPTX
BSides London 2015 - Proprietary network protocols - risky business on the wire.
Jakub Kałużny
 
PPTX
Introducing Intelligence Into Your Malware Analysis
Brian Baskin
 
PDF
OS X Malware: Let's Play Doctor
Synack
 
PDF
Smart Sheriff, Dumb Idea, the wild west of government assisted parenting
Abraham Aranguren
 
PDF
Ekoparty 2017 - The Bug Hunter's Methodology
bugcrowd
 
PPT
Defending Against Attacks With Rails
Tony Amoyal
 
PPTX
Security in PHP - 那些在滲透測試的小技巧
Orange Tsai
 
ODT
Kioptrix 2014 5
Jayesh Patel
 
PPTX
How to drive a malware analyst crazy
Michael Boman
 
PPT
Much ado about randomness. What is really a random number?
Aleksandr Yampolskiy
 
PDF
Offensive cyber security: Smashing the stack with Python
Malachi Jones
 
PDF
Breaking Vaults - Stealing Lastpass Protected Secrets by Martin Vigo
Shakacon
 
PDF
[CB16] 80時間でWebを一周:クロムミウムオートメーションによるスケーラブルなフィンガープリント by Isaac Dawson
CODE BLUE
 
PPTX
Эксплуатируем неэксплуатируемые уязвимости SAP
Positive Hack Days
 
PDF
Synack at AppSec California with Patrick Wardle
Synack
 
PDF
Embedded device hacking Session i
Malachi Jones
 
PDF
Corporations - the new victims of targeted ransomware
Cyber Security Alliance
 
PPTX
Internet banking safeguards vulnerabilities - OWASP AppSec EU 2016
SecuRing
 
PPTX
Make profit with UI-Redressing attacks.
n|u - The Open Security Community
 
BSides London 2015 - Proprietary network protocols - risky business on the wire.
Jakub Kałużny
 
Introducing Intelligence Into Your Malware Analysis
Brian Baskin
 
OS X Malware: Let's Play Doctor
Synack
 
Smart Sheriff, Dumb Idea, the wild west of government assisted parenting
Abraham Aranguren
 
Ekoparty 2017 - The Bug Hunter's Methodology
bugcrowd
 
Defending Against Attacks With Rails
Tony Amoyal
 
Security in PHP - 那些在滲透測試的小技巧
Orange Tsai
 
Kioptrix 2014 5
Jayesh Patel
 
How to drive a malware analyst crazy
Michael Boman
 
Much ado about randomness. What is really a random number?
Aleksandr Yampolskiy
 
Offensive cyber security: Smashing the stack with Python
Malachi Jones
 
Breaking Vaults - Stealing Lastpass Protected Secrets by Martin Vigo
Shakacon
 
[CB16] 80時間でWebを一周:クロムミウムオートメーションによるスケーラブルなフィンガープリント by Isaac Dawson
CODE BLUE
 
Эксплуатируем неэксплуатируемые уязвимости SAP
Positive Hack Days
 
Synack at AppSec California with Patrick Wardle
Synack
 
Embedded device hacking Session i
Malachi Jones
 
Corporations - the new victims of targeted ransomware
Cyber Security Alliance
 
Internet banking safeguards vulnerabilities - OWASP AppSec EU 2016
SecuRing
 
Make profit with UI-Redressing attacks.
n|u - The Open Security Community
 
Ad

Similar to Applications secure by default (20)

PPT
PHPUG Presentation
Damon Cortesi
 
PDF
Web Application Firewall: Suckseed or Succeed
Prathan Phongthiproek
 
PDF
DDD17 - Web Applications Automated Security Testing in a Continuous Delivery...
Fedir RYKHTIK
 
PDF
The top 10 security issues in web applications
Devnology
 
PPTX
Security: Odoo Code Hardening
Odoo
 
PDF
Whatever it takes - Fixing SQLIA and XSS in the process
guest3379bd
 
PDF
Evolution Of Web Security
Chris Shiflett
 
KEY
DVWA BruCON Workshop
testuser1223
 
PDF
Waf.js: How to Protect Web Applications using JavaScript
Denis Kolegov
 
PDF
Rails Security
Wen-Tien Chang
 
PPTX
Hacking 101 (Session 2)
Nitroxis Sprl
 
PDF
Drupal campleuven: Secure Drupal Development
Steven Van den Hout
 
PDF
IstSec'14 - İbrahim BALİÇ - Automated Malware Analysis
BGA Cyber Security
 
PPTX
Application and Website Security -- Fundamental Edition
Daniel Owens
 
PDF
Security in Node.JS and Express:
Petros Demetrakopoulos
 
PPTX
[CB16] Esoteric Web Application Vulnerabilities by Andrés Riancho
CODE BLUE
 
PDF
Kraken Front-Trends
PayPal
 
PPTX
Let's write secure Drupal code! - DrupalCamp London 2019
Balázs Tatár
 
PPT
Web application security
Ravi Raj
 
PPTX
Secure Coding for NodeJS
Thang Chung
 
PHPUG Presentation
Damon Cortesi
 
Web Application Firewall: Suckseed or Succeed
Prathan Phongthiproek
 
DDD17 - Web Applications Automated Security Testing in a Continuous Delivery...
Fedir RYKHTIK
 
The top 10 security issues in web applications
Devnology
 
Security: Odoo Code Hardening
Odoo
 
Whatever it takes - Fixing SQLIA and XSS in the process
guest3379bd
 
Evolution Of Web Security
Chris Shiflett
 
DVWA BruCON Workshop
testuser1223
 
Waf.js: How to Protect Web Applications using JavaScript
Denis Kolegov
 
Rails Security
Wen-Tien Chang
 
Hacking 101 (Session 2)
Nitroxis Sprl
 
Drupal campleuven: Secure Drupal Development
Steven Van den Hout
 
IstSec'14 - İbrahim BALİÇ - Automated Malware Analysis
BGA Cyber Security
 
Application and Website Security -- Fundamental Edition
Daniel Owens
 
Security in Node.JS and Express:
Petros Demetrakopoulos
 
[CB16] Esoteric Web Application Vulnerabilities by Andrés Riancho
CODE BLUE
 
Kraken Front-Trends
PayPal
 
Let's write secure Drupal code! - DrupalCamp London 2019
Balázs Tatár
 
Web application security
Ravi Raj
 
Secure Coding for NodeJS
Thang Chung
 
Ad

More from Slawomir Jasek (9)

PDF
Hardwear.io 2018 BLE Security Essentials workshop
Slawomir Jasek
 
PDF
A 2018 practical guide to hacking RFID/NFC
Slawomir Jasek
 
PDF
Cant touch this: cloning any Android HCE contactless card
Slawomir Jasek
 
PDF
Gattacking Bluetooth Smart devices - introducing new BLE MITM proxy tool
Slawomir Jasek
 
PDF
Hacking Bluetooth Smart
Slawomir Jasek
 
PDF
Jak włamałem się do banku
Slawomir Jasek
 
PPTX
Testowanie bezpieczeństwa aplikacji mobilnych
Slawomir Jasek
 
PDF
Shameful secrets of proprietary network protocols
Slawomir Jasek
 
PDF
(Nie)bezpieczenstwo aplikacji mobilnych
Slawomir Jasek
 
Hardwear.io 2018 BLE Security Essentials workshop
Slawomir Jasek
 
A 2018 practical guide to hacking RFID/NFC
Slawomir Jasek
 
Cant touch this: cloning any Android HCE contactless card
Slawomir Jasek
 
Gattacking Bluetooth Smart devices - introducing new BLE MITM proxy tool
Slawomir Jasek
 
Hacking Bluetooth Smart
Slawomir Jasek
 
Jak włamałem się do banku
Slawomir Jasek
 
Testowanie bezpieczeństwa aplikacji mobilnych
Slawomir Jasek
 
Shameful secrets of proprietary network protocols
Slawomir Jasek
 
(Nie)bezpieczenstwo aplikacji mobilnych
Slawomir Jasek
 

Recently uploaded (20)

PDF
On Software Engineers' Productivity - Beyond Misleading Metrics
Romén Rodríguez-Gil
 
PDF
lesson-2-rules-of-netiquette.pdf.bshhsjdj
jasmenrojas249
 
PDF
Enhancing Healthcare RPM Platforms with Contextual AI Integration
Cadabra Studio
 
PDF
49784907924775488180_LRN2959_Data_Pump_23ai.pdf
Abilash868456
 
PDF
New Download FL Studio Crack Full Version [Latest 2025]
imang66g
 
PPT
Why Reliable Server Maintenance Service in New York is Crucial for Your Business
Sam Vohra
 
PPTX
ASSIGNMENT_1[1][1][1][1][1] (1) variables.pptx
kr2589474
 
PDF
ChatPharo: an Open Architecture for Understanding How to Talk Live to LLMs
ESUG
 
PDF
Using licensed Data Loss Prevention (DLP) as a strategic proactive data secur...
Q-Advise
 
PDF
WatchTraderHub - Watch Dealer software with inventory management and multi-ch...
WatchDealer Pavel
 
DOCX
Can You Build Dashboards Using Open Source Visualization Tool.docx
Varsha Nayak
 
PDF
Summary Of Odoo 18.1 to 18.4 : The Way For Odoo 19
CandidRoot Solutions Private Limited
 
PDF
49785682629390197565_LRN3014_Migrating_the_Beast.pdf
Abilash868456
 
PPTX
slidesgo-unlocking-the-code-the-dynamic-dance-of-variables-and-constants-2024...
kr2589474
 
PPTX
TRAVEL APIs | WHITE LABEL TRAVEL API | TOP TRAVEL APIs
philipnathen82
 
PDF
What to consider before purchasing Microsoft 365 Business Premium_PDF.pdf
Q-Advise
 
PDF
Generating Union types w/ Static Analysis
K. Matthew Dupree
 
PPTX
Maximizing Revenue with Marketo Measure: A Deep Dive into Multi-Touch Attribu...
bbedford2
 
PDF
Protecting the Digital World Cyber Securit
dnthakkar16
 
PDF
Adobe Illustrator Crack Full Download (Latest Version 2025) Pre-Activated
imang66g
 
On Software Engineers' Productivity - Beyond Misleading Metrics
Romén Rodríguez-Gil
 
lesson-2-rules-of-netiquette.pdf.bshhsjdj
jasmenrojas249
 
Enhancing Healthcare RPM Platforms with Contextual AI Integration
Cadabra Studio
 
49784907924775488180_LRN2959_Data_Pump_23ai.pdf
Abilash868456
 
New Download FL Studio Crack Full Version [Latest 2025]
imang66g
 
Why Reliable Server Maintenance Service in New York is Crucial for Your Business
Sam Vohra
 
ASSIGNMENT_1[1][1][1][1][1] (1) variables.pptx
kr2589474
 
ChatPharo: an Open Architecture for Understanding How to Talk Live to LLMs
ESUG
 
Using licensed Data Loss Prevention (DLP) as a strategic proactive data secur...
Q-Advise
 
WatchTraderHub - Watch Dealer software with inventory management and multi-ch...
WatchDealer Pavel
 
Can You Build Dashboards Using Open Source Visualization Tool.docx
Varsha Nayak
 
Summary Of Odoo 18.1 to 18.4 : The Way For Odoo 19
CandidRoot Solutions Private Limited
 
49785682629390197565_LRN3014_Migrating_the_Beast.pdf
Abilash868456
 
slidesgo-unlocking-the-code-the-dynamic-dance-of-variables-and-constants-2024...
kr2589474
 
TRAVEL APIs | WHITE LABEL TRAVEL API | TOP TRAVEL APIs
philipnathen82
 
What to consider before purchasing Microsoft 365 Business Premium_PDF.pdf
Q-Advise
 
Generating Union types w/ Static Analysis
K. Matthew Dupree
 
Maximizing Revenue with Marketo Measure: A Deep Dive into Multi-Touch Attribu...
bbedford2
 
Protecting the Digital World Cyber Securit
dnthakkar16
 
Adobe Illustrator Crack Full Download (Latest Version 2025) Pre-Activated
imang66g
 

Applications secure by default

  • 2. Pentester / security consultant. Assessments and consultancy regarding security of various applications - web, mobile, embedded, ... Since 2003 / over 400 systems and applications Sławomir Jasek
  • 3. Code insecure by default Blacklisting vs whitelisting Features vs security Access control Beware the "silver bullets" Fight back! Devops The Takeaway Agenda
  • 5. $url = 'https://api.twitter.com/1/statuses/public_timeline.json'; $result = file_get_contents($url); Is there anything wrong? The default setting does not verify hostname => Man in the Middle
  • 6. $url = 'https://api.twitter.com/1/statuses/public_timeline.json'; $contextOptions = array( 'ssl' => array( 'verify_peer' => true, 'cafile' => '/etc/ssl/certs/ca-certificates.crt', 'verify_depth' => 5, 'CN_match' => 'api.twitter.com', 'disable_compression' => true, 'SNI_enabled' => true, 'ciphers' => 'ALL!EXPORT!EXPORT40!EXPORT56!aNULL!LOW!RC4' ) ); $sslContext = stream_context_create($contextOptions); $result = file_get_contents($url, NULL, $sslContext); The proper way http://phpsecurity.readthedocs.org/en/latest/Transport-Layer-Security-%28HTTPS-SSL-and-TLS%29.html Defaults to false!
  • 8. file_get_contents verify_peer Only 1 programmer in 51 uses verify_peer options. Often to explicitly disable it ;)
  • 9. The default value changed only recently in PHP 5.6.0. But there is hope... All the previous versions susceptible to Man-In-The-Middle attacks.
  • 10. $url = 'https://api.twitter.com/1/statuses/public_timeline.json'; $req = curl_init($url); curl_setopt($req, CURLOPT_RETURNTRANSFER, TRUE); $result = curl_exec($req); Curl - secure by default
  • 11. // Open SSLSocket directly SocketFactory sf = SSLSocketFactory.getDefault(); SSLSocket socket = (SSLSocket) sf.createSocket("mail.google.com", 443); SSLSession s = socket.getSession(); // ... use socket ... socket.close(); Java: SSL SocketFactory
  • 12. // Open SSLSocket directly SocketFactory sf = SSLSocketFactory.getDefault(); SSLSocket socket = (SSLSocket) sf.createSocket("mail.google.com", 443); SSLSession s = socket.getSession(); // Verify that the certicate hostname is for mail.google.com HostnameVerifier hv = HttpsURLConnection.getDefaultHostnameVerifier(); if (!hv.verify("mail.google.com", s)) { throw new SSLHandshakeException("Expected mail.google.com, " "found " + s.getPeerPrincipal()); } // ... use socket ... socket.close(); https://developer.android.com/training/articles/security-ssl.html#WarningsSslSocket SSL SocketFactory
  • 13. And the docs do not help https://developer.android.com/training/articles/security-ssl.html#WarningsSslSocket Pentester’s experience: all tested Android apps using SSLSocket were vulnerable. Despite the bold warnings and proper example code...
  • 14. URL url = new URL("https://mail.google.com"); URLConnection urlConnection = url.openConnection(); InputStream in = urlConnection.getInputStream(); copyInputStreamToOutputStream(in, System.out); You need to explicitly disable verification. Pentester’s experience: only a few tested Android apps using urlConnection were deliberately broken. HTTPS – the proper way
  • 16. Attack scenario: http://localhost/foo/bar.action?<script>alert(1)</script> Lack of proper output encoding. Intruder runs hostile javascript in a victim’s browser (aka „Cross Site Scripting”). Struts 2 – XSS vulnerability
  • 17. --- struts2/trunk/core/src/main/java/org/apache/struts2/views/util/UrlHelper.java 2008/01/24 07:37:32 614813 +++ struts2/trunk/core/src/main/java/org/apache/struts2/views/util/UrlHelper.java 2008/01/24 07:39:45 614814 @@ -174,10 +174,14 @@ buildParametersString(params, link, "&"); } - String result; + String result = link.toString(); + + if (result.indexOf("<script>") >= 0){ + result = result.replaceAll("<script>", "script"); + } Fix - blacklisting
  • 18. Attack 1: /myAction.action?param"><sCript>alert('XSS');</sCript>=1 This is very similiar to the vulnerability in Security Bulletin S2-002; however, the implemented fix for S2-002 only checks for "<script>", not "<sCript>". Attack 2: /myAction.action?param"onMouseOver%3D"javascript:alert('XSS');">=1 Simply checking for <script> isn't sufficient because certain attributes can be injected to execute javascript. In attack 2, the user simply has to hover over the link with their mouse and arbitrary javascript will be executed. https://issues.apache.org/jira/browse/WW-3410 2 years later...
  • 19. -builder.append(name) +builder.append(translateAndEncode(name)) That was 19 characters - exactly 4.78 times less than 91 characters used in first, unsuccessful „blacklist” fix. Final fix
  • 20. We found an XSS vulnerability, as usually recommended to properly encode relevant characters in the output context. Retest #1: <script> does not work, but <Script> does ;) Retest #2: <Script> nor <sCript> does not work. But onclick does. Retest #3: onclick does not work, but onmouseover does. Retest #4: onmouseover fixed, but onmousedown not ;) Retest #5: ... From the pentester's diary
  • 21. +------------------------+ | XSS_PAYLOAD | +------------------------+ | onclick= | | ondblclick= | | onmousedown= | | onmousemove= | | onmouseover= | | onmouseout= | | onmouseup= | | onkeydown= | | onkeypress= | | onkeyup= | | onabort= | | onerror= | | onload= | | onresize= | Finally, we broke into database via sql-injection | onscroll= | | onunload= | | onblur= | | onchange= | | onfocus= | | onreset= | | onselect= | | onsubmit= | | onevent= | | <script | | script> | | <svg | | svg> | | javascript: | | <iframe | | iframe> | | <form | | form> | | <input | | ''iframe'' | | "iframe" | | document.createelement | | string.fromcharcode( | | <img/src | | submit() | | document.location. | | alert( | | <img | | <vbscript | ...
  • 24. Define user # fields: [:id, :first, :last, :email, :admin] class User < ActiveRecord::Base End RoR – user edit form User edit form user = User.find(params[:id]) user.update_attributes(params[:user])
  • 27. You were supposed to manually add whitelisted: class User < ActiveRecord::Base attr_accessible :first, :last, :email end or blacklisted parameters: class User < ActiveRecord::Base attr_protected :admin end RoR – mass assignment (2012)
  • 29. Change default value of global config parameter turning the mass assignment off: # Enforce whitelist mode for mass assignment. # This will create an empty whitelist of attributes available for mass- assignment for all models # in your app. As such, your models will need to explicitly whitelist or blacklist accessible # parameters by using an attr_accessible or attr_protected declaration. <%= comment_if :skip_active_record %> config.active_record.whitelist_attributes = true Fix - evolution
  • 30. config.active_record.mass_assignment_sanitizer It will raise an ActiveModel::MassAssignmentSecurity::Error any time your application attempts to mass-assign something it shouldn't. RoR 3.2: Mass assignment sanitizer
  • 31. Secure by default. You must first call permit on the params hash with the keys that are allowed for a specific action: # Require that :user be a key in the params Hash, # and only accept whitelisted attributes def user_params params.require(:user).permit(:first, :last, :email) end http://code.tutsplus.com/tutorials/mass-assignment-rails-and-you--net-31695 RoR 4: Strong Parameters
  • 35. Major frameworks: Spring, JBoss SEAM, Struts... Easy to detect, automatic tools to exploit remotely into shell. The "no man's land". (as I have pointed out in 2012) http://prezi.com/awm8psp-i1ok/no-mans-land Expression Language flaws https://play.google.com/store/apps/details?id=com.cleanmaster.security.struts2
  • 36. 2003: parameter names like: @System@exit(1) "Patrick says he has fixed it" ;) 2008.06: the # can be encoded in u0023 ('u0023' + 'session['user'])(unused)=0wn3d Released Xwork 2.0.5 – blacklisted the attack 2008.10: removed space characters and the exploit still works ;) ('u0023'+'session['user'])(unused)=0wn3d The fix - features vs security
  • 37. 2010: You can access the context and turn the settings on: http://mydomain/MyStruts.action?('u0023_memberAccess['allowStatic MethodAccess']')(meh)=true&(aaa)(('u0023context['xwork.MethodAcc essor.denyMethodExecution']u003du0023foo')(u0023foou003dnew%20 java.lang.Boolean("false")))&(asdf)(('u0023rt.exit(1)')(u0023rtu [email protected]@getRuntime()))=1 Fix: whitelist allowed chars in parameter names 2011: User input is evaluated as an OGNL expression when there's a conversion error. 2011: The problem concerns not only parameters, but also cookie values The fix – continued...
  • 38. 2012: fix based on whitelisting acceptable parameter names closed the vulnerability only partially. Still possible RCE with slightly modified attack syntax. Fix: deny evaluation in parameter names. 2013: The second evaluation happens when redirect result reads it from the stack and uses the previously injected code as redirect parameter. I won't reveal all the following episodes, I encourage you to read on: http://struts.apache.org/docs/security-bulletins.html There's a lot of action! Struts.action. The fix – continued
  • 40. <?xml version="1.0"?> <!DOCTYPE lolz [ <!ENTITY lol "lol"> <!ELEMENT lolz (#PCDATA)> ]> <lolz>&lol;</lolz> <lolz>lol</lolz> XML parsing: DOCTYPE
  • 41. <?xml version="1.0"?> <!DOCTYPE lolz [ <!ENTITY lol "lol"> <!ENTITY lol1 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;"> <!ELEMENT lolz (#PCDATA)> ]> <lolz>&lol1;</lolz> <lolz>lollollollollollollollollollol</lolz> XML parsing: DOCTYPE
  • 42. <?xml version="1.0"?> <!DOCTYPE lolz [ <!ENTITY lol "lol"> <!ELEMENT lolz (#PCDATA)> <!ENTITY lol1 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;"> <!ENTITY lol2 "&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;"> <!ENTITY lol3 "&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;"> <!ENTITY lol4 "&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;"> <!ENTITY lol5 "&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;"> <!ENTITY lol6 "&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;"> <!ENTITY lol7 "&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;"> <!ENTITY lol8 "&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;"> <!ENTITY lol9 "&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;"> ]> <lolz>&lol9;</lolz> <user> <firstname>Jan</firstname> <lastname>Kowalski</lastname> </user> "The Man Who Laughs" http://en.wikipedia.org/wiki/Billion_laughs
  • 44. <!ENTITY xxe SYSTEM "file:///etc/passwd" >]> <foo>&xxe;</foo> As seen in Google, Facebook, Ebay and about 80% of tested applications processing user input as XML. It may be even worse
  • 46. Technology Default DTD processing value .NET 4 settings.DtdProcessing = DtdProcessing.Prohibit; .NET 3.5 ProhibitDtd in XmlReaderSettings is true, but ProhibitDtd in XmlTextReader is false LibXML2 (C++ ) starting with libxml2 version 2.9 (2012), XXE has been disabled by default NSXMLDocument (iOS) iOS5 and later: Only entities that don't require network access are loaded. iOS4 and earlier: All external entities are loaded by default. Xerces 2 disallow-doctype-decl=false Xerces 1 external-general-entities=true PHP Have to manually disable: libxml_disable_entity_loader(true); Default DTD processing in various parsers
  • 49. Student tries to invoke administrative functions GET /course/quiz/solutions GET /admin/course/cancel Student tries to access restricted data GET /course/view/42 Student tries to alter his account rights. POST /user/edit roles=[student,admin] Access control: typical attack
  • 50. <security:intercept-url pattern="/user/add" access="hasRole('ROLE_ADMIN') or hasRole('ROLE_MANAGER')" /> <security:intercept-url pattern="/user/view" access="hasRole('ROLE_ADMIN') or hasRole('ROLE_MANAGER') or hasRole('ROLE_PRINCIPAL') or hasRole('ROLE_TEACHER') or hasRole('ROLE_STUDENT')" /> Approach 1: Spring Security
  • 51. It works for simple apps, with unsophisticated role policies (e.g. separated admin interface). Will not work for: POST /user/edit HTTP/1.1 task=MODIFY_RIGHTS&id=34 Has concept of „roles”, but out of the box does not have concept of „permissions”. Spring ACL on the other hand is too complex. Does not help a lot with access to specific instance (e.g. other user’s data) Spring Security
  • 52. Complex hard-coded checks in application code, needed to be manually loaded to every endpoint: If (( user.isRole('ROLE_ADMIN') || user.isRole('ROLE_MANAGER') || user.isRole('ROLE_PRINCIPAL') ) || ( user.isRole('ROLE_TEACHER') && user.isTeacher(course) ) || ( user.isRole('ROLE_STUDENT') && (user.isStudent(course) ) ...and you will probably end-up with:
  • 53. One simple "if" statement, permissions separated from roles. if ( currentUser.isPermitted("users:add") ) { //add an user } int courseId=request.getInt("course") if ( currentUser.isPermitted("courses:view:"+courseId) ) { //show contents of course } Apache Shiro – permission based access control
  • 54. Real story: account history – select your account
  • 55. The REST API request GET /services/history/account/85101022350445200448009906 HTTP/1.1 SA-DeviceId: 940109f08ba56a89 SA-SessionId: 826175 Accept: application/json Host: acc Connection: Keep-Alive User-Agent: Apache-HttpClient/UNAVAILABLE (java 1.4)
  • 56. The REST API request GET /services/history/account/45101022350445200448005388 HTTP/1.1 SA-DeviceId: 940109f08ba56a89 SA-SessionId: 826175 Accept: application/json Host: acc Connection: Keep-Alive User-Agent: Apache-HttpClient/UNAVAILABLE (java 1.4) Change the acc number -> get other user’s data
  • 57. John: <select name="account"> <option value=0 >85101022350445200448009906</option> <option value=1 >34101022350445200448009905</option> <option value=2 >41101022350445200448009904</option> </select> Mary: <select name="account"> <option value=0 >45101022350445200448005388</option> <option value=1 >31101022350445200448005390</option> </select> The better way? "Local" ID mapped server-side into real values
  • 58. The better way? SA-DeviceId: d4c79a0fd994b1f3 SA-SessionId: 850073 GET /services/history/account/1 HTTP/1.1 SA-DeviceId: 940109f08ba56a89 SA-SessionId: 826175 Accept: application/json Host: acc Connection: Keep-Alive User-Agent: Apache-HttpClient/UNAVAILABLE (java 1.4) It is(?) by design not possible to attack other user's data.
  • 59. Would be great if not... John: GET /services/history/account/2 HTTP/1.1 SA-DeviceId: 940109f08ba56a89 SA-SessionId: 826175 Accept: application/json Host: acc Connection: Keep-Alive API just works as a proxy to backend system. Default session mechanism from backend – just incrementing IDs ;) Mary: GET /services/history/account/2 HTTP/1.1 SA-DeviceId: d4c79a0fd994b1f3 SA-SessionId: 826179 Accept: application/json Host: acc Connection: Keep-Alive Trivial to guess other user's sessionId
  • 60. Automatically encrypts paths with individual, session- based and unique key: www.app.com/admin/user/edit www.app.com/?x=XSn4MUyv6Uke22d9vEuGgR8yZa5- TkeuxlXeeVypcehJ8HQgNbj(...) Apache Wicket
  • 61. The browser works on rendered GUI elements, POSTs to the server event-driven actions (e.g. mouse clicks in certain location). It is by design not possible to invoke actions that are not in GUI. POST /dashboard/UIDL/?v-uiId=0 HTTP/1.1 Host: demo.vaadin.com {"csrfToken":"981b1cd6-66df-481c-9d6e- 6c293eb70ea3","rpc":[["283","v","v",["positionx",["i","440"]]],["283"," v","v",["positiony",["i","139"]]],["309","com.vaadin.shared.ui.button.B uttonServerRpc","click",[{"altKey":false,"relativeX":"42","relativeY":" 23","ctrlKey":false,"button":"LEFT","shiftKey":false,"clientX":"1109"," clientY":"598","metaKey":false,"type":"1"}]]],"syncId":14} Vaadin
  • 63. There's no silver bullet! Hadi Hariri keynote on Monday
  • 64. Automagic output encoding by framework A framework automatically encodes special chars into HTML: <bean:write name="transferFormId" property="trn_recipient"/> ATTACK: trn_recipient="<script>alert('xss')</script> <input type="text" name="trn_recipient" value="&quot;&lt;script&gt;alert('xss')&lt;/script&gt;"
  • 65. Beware the security mechanism use cases But unfortunatelly that does not help when you put a value from end-user directly into javascript context: <script> var split='<bean:write name="transferFormId" property="trn_recipient">'; splitRecipient(split); </script> ATTACK: trn_recipient=';alert('xss');-- <script> var split='';alert('xss');--
  • 66. Encode special chars properly in context! • HTML element • HTML atribute • JavaScript • JSON • CSS / style • URL Encode properly
  • 67. Prepared statement / call String sql = "select * from users where firstname=? and lastname=?"; query = conn.prepareStatement(sql); firstname = request.getParameter("first"); lastname = request.getParameter("last"); query.setString(1, firstname); query.setString(2, lastname); result = query.executeQuery(); String sql = "{call USERS.search(" + "?" + ", ?)}"; call = conn.prepareCall(sql); firstname = request.getParameter("first"); lastname = request.getParameter("last"); call.setString(1, firstname); call.setString(2, lastname); call.execute(); prepared statement prepared call
  • 68. Called stored procedure PROCEDURE search( p_firstname IN T_STRING, p_lastname IN T_STRING, ) IS (...) v_sql_select := ' SELECT distinct a.USER_ID'; v_sql_from := ' FROM APP_WEB.USERS a '; v_sql_where := ' WHERE a.USER_ID is not null '; IF p_firstname is not null THEN v_sql_where := v_sql_where || ' and lower(trim(a.FIRSTNAME)) = lower(trim(' || P_FIRSTNAME || ')) '; END IF;
  • 69. SQL injection inside stored procedure PROCEDURE search( p_firstname IN T_STRING, p_lastname IN T_STRING, ) IS (...) v_sql_select := ' SELECT distinct a.USER_ID'; v_sql_from := ' FROM APP_WEB.USERS a '; v_sql_where := ' WHERE a.USER_ID is not null '; IF p_firstname is not null THEN v_sql_where := v_sql_where || ' and lower(trim(a.FIRSTNAME)) = lower(trim('|| 'adam')) union select version,'x' from v$instance-- || ')) '; END IF;
  • 70. NoSQL. There is no sql injection. There is nosql injection! Instead of ' OR 1=1 -- try a'; return 1=1; var dummy='a NoSQL
  • 71. Change SMS authorization phone number in internet banking application Application logic flaws
  • 72. What could possibly go wrong? Change SMS authorization phone number in internet banking application
  • 73. The scenario missed in functional tests Change SMS authorization phone number in internet banking application
  • 74. The evil wins The application did verify only the SMS code from the new phone. And intruder with access to user session can take over the authorization.
  • 75. FIGHT BACK! - Intrusion detection and prevention
  • 76. • Input validation server-side when client-side validation exists • Non-user editable parameters/values (hidden fields, checkboxes, radio buttons, select lists) • Forced browsing to common attack entry points or honeypot URL (e.g. in robots.txt) • Obvious sqli, xss inj attacks • Workflow sequence abuse Intrusion detection – level basic http://www.slideshare.net/JimManico/top-ten-defenses-v10 slide 60
  • 77. One of the most annoying experiences during test was automatic logout on every test-case in application that required manual interaction to authenticate. Active intrusion prevention
  • 78. OWASP AppSensor Conceptual framework and methodology to implement intrusion detection and automated response into applications. https://www.owasp.org/index.php/OWASP_AppSensor_Project OWASP mod_security core ruleset An easily "pluggable" set of generic attack detection rules that provide a base level of protection for any web application. https://www.owasp.org/index.php/Category:OWASP_ModSecurity_Core_Rule_Set_Project Basic tools
  • 80. Default error handling Reveals information on used components, helps to attack known vulnerabilities
  • 81. Trading application – binary protocol
  • 82. Trading application – binary protocol
  • 83. Trading application – binary protocol
  • 84. And what if we...
  • 86. <soapenv:Body> <registerUserResponse soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encodin g/"> <registerUserReturn xsi:type="xsd:string"> &lt;error code=&quot;266&quot; &gt;Incorrect login&lt;/error&gt; </registerUserReturn></registerUserResponse></soapenv:Body> • Incorrect password • Incorrect first name • Group with name null doesn't exist • Group with name admin doesn't exist • Group with name Administrator doesn't exist • And how about „root”? RegisterUser
  • 89. Default HTTP error response Reveals used version
  • 91. Apache Tomcat < 6.0.20
  • 92. <role rolename="tomcat"/> <role rolename="role1"/> <user username="tomcat" password="tomcat" roles="tomcat"/> <user username="both" password="tomcat" roles="tomcat,role1"/> <user username="role1" password="tomcat" roles="role1"/> tomcat-users.xml
  • 94. Tomcat worm using weak passwords http://www.symantec.com/connect/blogs/all-your-tomcat-are-belong-bad-guys tryLogins = { "admin:admin", "tomcat:tomcat", "admin:", "tomcat:", "root:root", "manager:manager", "tomcat:admin", "admin:password"};
  • 95. OWASP dependency check / dependency track Automatically checks for known vulnerabilities in used components https://www.owasp.org/index.php/OWASP_Dependency_Track
  • 97. • Use secure design architecture • Least privilege principle (default: deny) • Code that enforces good practices • Leverage existing security mechanisms, but be aware of their shortcomings and secure use scenario. • Secure configuration • Keep the components up to date • Change default credentials • Harden the configuration • Leverage additional layers of protection (IDS, WAF) Key takeaways
  • 98. Our presentations (including this one), resources www.securing.pl/en/resources/ Free security consultancy service: www.securing.pl/konsultacje See also
  • 99. And for the Happy(?)-End – the pentester’s view Features at low cost compromising on security is just obscene ;) Let’s do it better!
  • 100. Thank you, looking forward to contact! [email protected] MORE THAN SECURITY TESTING Free security consultancy service: www.securing.pl/konsultacje