applications secure by default

100
Platinum Sponsors: #DevoxxPL Applications secure by default Sławomir Jasek

Upload: securing

Post on 08-Aug-2015

64 views

Category:

Software


0 download

TRANSCRIPT

Page 1: Applications secure by default

Platinum Sponsors:

#DevoxxPL

Applications secure by default

Sławomir Jasek

Page 2: Applications secure by default

Pentester / security consultant.

Assessments and consultancy regarding

security of various applications - web,

mobile, embedded, ...

Since 2003 / over 400 systems and

applications

Sławomir Jasek

Page 3: Applications secure by default

Code insecure by default

Blacklisting vs whitelisting

Features vs security

Access control

Beware the "silver bullets"

Fight back!

Devops

The Takeaway

Agenda

Page 4: Applications secure by default

INSECURE BY DEFAULT

Page 5: Applications secure 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

Page 6: Applications secure by default

$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!

Page 7: Applications secure by default

file_get_contents(https language:php

Page 8: Applications secure by default

file_get_contents verify_peer

Only 1 programmer in 51 uses verify_peer options.

Often to explicitly disable it ;)

Page 9: Applications secure by default

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.

Page 10: Applications secure by default

$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

Page 11: Applications 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

Page 12: Applications secure by default

// 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

Page 13: Applications secure by default

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...

Page 14: Applications secure by default

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

Page 15: Applications secure by default

BLACKLISTING

Page 16: Applications secure by default

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

Page 17: Applications secure by default

--- 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

Page 18: Applications secure by default

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...

Page 19: Applications secure by default

-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

Page 20: Applications secure by default

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

Page 21: Applications secure by default

+------------------------+

| 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 | ...

Page 22: Applications secure by default

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

Page 23: Applications secure by default

FEATURES VS SECURITY

Page 24: Applications secure by default

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])

Page 25: Applications secure by default

PUT

http://app.com/users/66?user[first]=Slawomir

&user[last]=Jasek&user[email]=slawomir.jasek

@securing.pl

RoR – user edit form

Page 26: Applications secure by default

PUT

http://app.com/users/66?user[first]=Slawomir

&user[last]=Jasek&user[email]=slawomir.jasek

@securing.pl&user[admin]=true

RoR – mass assignment

Page 27: Applications secure by default

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)

Page 28: Applications secure by default

GitHub PWND

http://www.h-online.com/security/news/item/GitHub-security-incident-highlights-Ruby-on-Rails-problem-1463207.html

Page 29: Applications secure by default

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

Page 30: Applications secure by default

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

Page 32: Applications secure by default

Before:

<%=HTMLEncoder.encode(((Person)person).getAd

dress().getStreet())%>

After (EL):

<c:out value="person.address.street"/>

Expression language – starring major frameworks

Page 33: Applications secure by default
Page 34: Applications secure by default

DEMO

- The security impact

Page 35: Applications secure by default

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

Page 36: Applications secure by default

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

Page 37: Applications secure by default

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\']\u003d\u0023foo')(\u0023foo\u003dnew%20

java.lang.Boolean("false")))&(asdf)(('\u0023rt.exit(1)')(\u0023rt\u

[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...

Page 38: Applications secure by default

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

Page 39: Applications secure by default

data=%3C%3Fxml+version%3D%221.0%22%3F%3E%0A%3Cuser%3E%0A%C2%A0%C2%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%2Fuser%3E

HTML decoded:

<?xml version="1.0"?>

<user>

<firstname>Jan</firstname>

<lastname>Kowalski</lastname>

</user>

XML parsing

Page 40: Applications secure by default

<?xml version="1.0"?>

<!DOCTYPE lolz [

<!ENTITY lol "lol">

<!ELEMENT lolz (#PCDATA)>

]>

<lolz>&lol;</lolz>

<lolz>lol</lolz>

XML parsing: DOCTYPE

Page 41: Applications secure by default

<?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

Page 42: Applications secure by default

<?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

Page 43: Applications secure by default

ROTFL TO DEATH!!!

Page 44: Applications secure by default

<!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

Page 45: Applications secure by default

FB XXE

Page 46: Applications secure by default

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

Page 47: Applications secure by default

ACCESS CONTROL

Page 48: Applications secure by default

Access control: typical scenario

Page 49: Applications secure by default

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

Page 50: Applications secure by default

<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

Page 51: Applications secure by default

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

Page 52: Applications secure by default

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:

Page 53: Applications secure by default

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

Page 54: Applications secure by default

Real story: account history – select your account

Page 55: Applications secure by default

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)

Page 56: Applications secure by default

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

Page 57: Applications secure by default

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

Page 58: Applications secure by default

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.

Page 59: Applications secure by default

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

Page 60: Applications secure by default

Automatically encrypts paths with individual, session-based and unique key:

www.app.com/admin/user/edit

www.app.com/?x=XSn4MUyv6Uke22d9vEuGgR8yZa5-TkeuxlXeeVypcehJ8HQgNbj(...)

Apache Wicket

Page 61: Applications secure by default

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.ButtonServerRpc","click",[{"altKey":false,"relativeX":"42","relativeY":"23","ctrlKey":false,"button":"LEFT","shiftKey":false,"clientX":"1109","clientY":"598","metaKey":false,"type":"1"}]]],"syncId":14}

Vaadin

Page 62: Applications secure by default

BEWARE

Page 63: Applications secure by default

There's no silver bullet!

Hadi Hariri keynote on Monday

Page 64: Applications secure by default

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;"

Page 65: Applications secure by default

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');--

Page 66: Applications secure by default

Encode special chars properly in context!

• HTML element

• HTML atribute

• JavaScript

• JSON

• CSS / style

• URL

Encode properly

Page 67: Applications secure by default

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

Page 68: Applications secure by default

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;

Page 69: Applications secure by default

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;

Page 70: Applications secure by default

NoSQL. There is no sql injection.

There is nosql injection!

Instead of

' OR 1=1 --

try

a'; return 1=1; var dummy='a

NoSQL

Page 71: Applications secure by default

Change SMS authorization phone number in internet banking application

Application logic flaws

Page 72: Applications secure by default

What could possibly go wrong?

Change SMS authorization phone number in internet banking application

Page 73: Applications secure by default

The scenario missed in functional tests

Change SMS authorization phone number in internet banking application

Page 74: Applications secure by default

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.

Page 75: Applications secure by default

FIGHT BACK!

- Intrusion detection and prevention

Page 76: Applications secure by default

• 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

Page 77: Applications secure by default

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

Page 78: Applications secure by default

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

Page 79: Applications secure by default

DEVOPS

- Default infrastructure

Page 80: Applications secure by default

Default error handling

Reveals information on used components, helps to attack known vulnerabilities

Page 81: Applications secure by default

Trading application – binary protocol

Page 82: Applications secure by default

Trading application – binary protocol

Page 83: Applications secure by default

Trading application – binary protocol

Page 84: Applications secure by default

And what if we...

Page 85: Applications secure by default

And how about...

Page 86: Applications secure by default

<soapenv:Body> <registerUserResponse soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">

<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

Page 87: Applications secure by default

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.

Page 88: Applications secure by default

Architecture

Page 89: Applications secure by default

Default HTTP error response

Reveals used version

Page 90: Applications secure by default

Known vulnerabilities based on version

Page 91: Applications secure by default

Apache Tomcat < 6.0.20

Page 92: Applications secure by default

<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

Page 93: Applications secure by default

Apache Tomcat Manager

Page 94: Applications secure by default

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"};

Page 95: Applications secure by default

OWASP dependency check / dependency track

Automatically checks for known vulnerabilities in used components

https://www.owasp.org/index.php/OWASP_Dependency_Track

Page 96: Applications secure by default

THE TAKEAWAY

Page 97: Applications secure by default

• 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

Page 98: Applications secure by default

Our presentations (including this one), resources

www.securing.pl/en/resources/

Free security consultancy service:

www.securing.pl/konsultacje

See also

Page 99: Applications secure by default

And for the Happy(?)-End – the pentester’s view

Features at low cost compromising on security is just obscene ;) Let’s do it better!

Page 100: Applications secure by default

Thank you,

looking forward to contact!

[email protected]

MORE THAN SECURITY TESTING

Free security consultancy service:

www.securing.pl/konsultacje