designing software with security in mind?

63
#DevoxxPL @DanielDeogun Designing Software with Security in Mind? Daniel Deogun Omegapoint Platinum Sponsors:

Upload: omegapoint-academy

Post on 07-Aug-2015

185 views

Category:

Software


0 download

TRANSCRIPT

#DevoxxPL @DanielDeogun

Designing Software with Security in Mind?

Daniel DeogunOmegapoint

Platinum Sponsors:

About Me

• Daniel Deogun• Sr Consultant, Omegapoint, Stockholm, Sweden • Started to play with Java in 1997 • Worked in various domains;

• Medtech • Telecom • Gambling • Web

• Strong advocate of DDD, TDD, and Domain Driven Security • Passionate about high quality software and design

Hypothesis

“Crafting software with good design principles along with a security mindset, significantly reduces the number of security flaws in an application.”

- Daniel Deogun

Important Questions

?

Important Questions

?What distinguishes secure software from insecure software?

Important Questions

How should one treat legacy code?

?What distinguishes secure software from insecure software?

Important Questions

How should one treat legacy code?

?What distinguishes secure software from insecure software?

Is it really possible to design secure software?

Important Questions

How should one treat legacy code?

Is security a quality aspect or is quality a security aspect?

?What distinguishes secure software from insecure software?

Is it really possible to design secure software?

OWASP top 10A1 - Injection

A2 - Broken Authentication and Session Management

A3 - Cross-Site Scripting (XSS)

A4 - Insecure Direct Object References

A5 - Security Misconfiguration

A6 - Sensitive Data Exposure

A7 - Missing Function Level Access Control

A8 - Cross-Site Request Forgery (CSRF)

A9 - Using Components with Known Vulnerabilities

A10 - Unvalidated Redirects and Forwards

OWASP top 10

A1 - Injection A3 - Cross-Site Scripting (XSS)

A1 - Injection

“Injection flaws, such as SQL, OS, and LDAP injection occur when untrusted data is sent to an interpreter as part of a command or query. The attacker’s hostile data can trick the interpreter into executing unintended commands or accessing data without proper authorization.”

- OWASP top 10

Example

Address

Regeringsgatan

Street

56

Number

111 56

ZIP Code

Stockholm

City

Sweden

Country

The Code…

public void register(String street, String number, String zip, String city, String country) {//do stuff

}

The Code…

public void register(String street, String number, String zip, String city, String country) {//do stuff

}

Examples of illegal input…

The Code…

public void register(String street, String number, String zip, String city, String country) {//do stuff

}

Examples of illegal input…

register(“Regeringsgatan”, “56”, “111 56”, “Sweden”, “Stockholm”)

Parameters swapped by mistakeIssue:

The Code…

public void register(String street, String number, String zip, String city, String country) {//do stuff

}

Examples of illegal input…

register(“Regeringsgatan”, “or 1=1”, null, “Sweden”, “Stockholm”)

Null parameters, SQL injection, illegal dataIssues:

The Code…

public void register(String street, String number, String zip, String city, String country) {//do stuff

}

Examples of illegal input…

register(StringUtils.repeat("X", 999999999), “56”, “111 56”, “Stockholm”, “Sweden”)

“Unbounded” inputIssue:

Treat it as a Validation Problem

• Illegal data should be rejected through validation • White list input validation • Verify boundary conditions • Input is validated at each entry point • Create a strong security barrier

[Bodiam Castle]

Validation Example

public void register(String street, String number, String zip, String city, String country) {notNull(street);isTrue(street.length() < 101);matchesPattern("^[a-zA-Z åäöÅäö]{3,100}$", street);

notNull(number);isTrue(number.length() < 4);matchesPattern("^[\\d]{1,3}[a-zA-Z]?$", number);

notNull(zip);isTrue(zip.length() < 7);matchesPattern("^\\d{5}|(\\d{3} \\d{2})$", zip);

//more validation…

addressRepository.add(street + “ “ + number, zip, city, country);}

Treat it as a Validation Problem

Upsides+ Prevent illegal data from being processed + Detects illegal data as early as possible + Focuses on legal input values

[Bodiam Castle]

Treat it as a Validation Problem

Upsides+ Prevent illegal data from being processed + Detects illegal data as early as possible + Focuses on legal input values

[Bodiam Castle]

Downsides- Validation and data are separated - Validation logic is often duplicated - Tends to focus on structural correctness and ignore invariants

Second Order Injection Flaw

“An attack vector with structurally correct data

that exploits missing invariant checks between

input parameters or application state”

- Daniel Deogun

Second Order Injection Flaw

“An attack vector with structurally correct data

that exploits missing invariant checks between

input parameters or application state”

- Daniel Deogun

register(“Regeringsgatan”, “56”, “111 56”, “Gothenburg”, “Sweden”)

Structurally correct but violates city - zip code invariantIssue:

Domain Driven Security

• Founded by Dan Bergh Johnsson and Dr. John Wilander • Introduced at JavaPolis (later named Devoxx) in 2006 • Brings in the power of Domain Driven Design into the

realm of security • All input data is mapped to value objects • Combines structural correctness and invariant checks • Validation and data are kept together

[Matrix Code]

What’s the Meaning of the Address Data?

111 56

City reference in ZIP code

Geographical Location

56

House number

Street name

Country

Conceptual Address Model

Address

City

StreetName

Number

Country

ZIP Code

Conceptual Address Model

Address

City

StreetName

Number

Country

ZIP Code

• Invariants - City must exist in Country - Street must exist in City - Building with number must exist on street - ZIP code and City must match

public void register(String street, String number, String zip, String city, String country) {notNull(street);isTrue(street.length() < 101);matchesPattern("^[a-zA-Z åäöÅäö]{3,100}$", street);

notNull(number);isTrue(number.length() < 4);matchesPattern("^[\\d]{1,3}[a-zA-Z]?$", number);

notNull(zip);isTrue(zip.length() < 7);matchesPattern("^\\d{5}|(\\d{3} \\d{2})$", zip);

//more validation…

addressRepository.add(street + “ “ + number, zip, city, country);}

Modeling Example

Modeling Example

public class ZipCode { private final String value;

public ZipCode(final String value) { this.value = validated(value); }

private static String validated(final String value) { notNull(value); isTrue(value.length() < 7); matchesPattern("^\\d{5}|(\\d{3} \\d{2})$", value);

return value; }

//methods with domain logic…}

Modeling Example

public class Address { private final Street street; private final BuildingNumber buildingNumber; private final ZipCode zipCode; private final City city; private final Country country;

public Address(final Street street, final BuildingNumber buildingNumber, final ZipCode zipCode, final City city, final Country country) {

this.street = notNull(street); this.buildingNumber = notNull(buildingNumber); this.zipCode = notNull(zipCode); this.city = notNull(city); this.country = notNull(country);

validateInvariant(city, country); validateInvariant(street, city); validateInvariant(buildingNumber, street); validateInvariant(zipCode, city); }

Modeling Example

public void register(final Street street, final BuildingNumber number, final Zip zip, final City city, final Country country) {

notNull(street);notNull(number);notNull(zip);notNull(city);notNull(country);

addressRepository.add(new Address(street, number, zip, city, country));}

Treat it as a Modeling Problem and use DDS

Upsides+ Tight coupling between data and validation + Promotes white list validation and invariant checks + Use of domain objects reduces duplicated validation + Helps to prevent second order security weaknesses

Treat it as a Modeling Problem and use DDS

Upsides+ Tight coupling between data and validation + Promotes white list validation and invariant checks + Use of domain objects reduces duplicated validation + Helps to prevent second order security weaknesses

Downsides- Involves business and domain experts - May seem less flexible - May cause problems with test data

What About Prepared Statements?

• Are prepared statements redundant when using validated

domain objects?Application

What About Prepared Statements?

• Are prepared statements redundant when using validated

domain objects?Application

• So, yes we definitely should use prepared statements

when interacting with a persistence context

• Prepared statements separate syntactical constructs and data

A3 - XSS Cross Site Scripting

“XSS flaws occur whenever an application takes untrusted data and sends it to a web browser without proper validation or escaping. XSS allows attackers to execute scripts in the victim’s browser which can hijack user sessions, deface web sites, or redirect the user to malicious sites.”

- OWASP top 10

DDD - Bounded Contexts

Shipping Context

Customer Context

Support Context

DDD - Bounded Contexts

Shipping Context

Customer Context

Support Context

• Bounded context is a central pattern in DDD

• Trying to create one unified model of a large

domain is bound to fail

• Bounded contexts are DDD’s way of dealing with large domains

• Mapping interrelationships between contexts is imperative since it

reveals how data flows in the application

Example - Coder’s Blog

• Let’s say we’re running a website where anyone can ask

questions about code

• Is it possible to avoid XSS?

Example - Coder’s Blog Stored XSS

<script>alert(’42’)</script> Browser

Stored XSS & Broken Context Mapping

<script>alert(’42’)</script>

Write Context Read ContextBrowser

Preventing XSS

• Context maps reveals how data flows between contexts

• One cannot rely on white list validation since “evil input” is

valid input

• Proper escaping is needed in the read context to prevent

data from the write context to be interpreted as code

The Reactive Manifesto

• The Reactive Manifesto (http://www.reactivemanifesto.org/) • Reactive Systems are

• Responsive • Resilient • Elastic • Message Driven

Responsive“The system responds in a timely manner if at all possible. … Responsive systems focus on providing rapid and consistent response times, establishing reliable upper bounds so they deliver a consistent quality of service. …”

Reactive Systems

Resilient“The system stays responsive in the face of failure. … any system that is not resilient will be unresponsive after a failure. Resilience is achieved by replication, containment, isolation and delegation. Failures are contained within each component, isolating components from each other and thereby ensuring that parts of the system can fail and recover without compromising the system as a whole. …”

Reactive Systems

Reactive Systems

Elastic“The system stays responsive under varying workload. Reactive Systems can react to changes in the input rate by increasing or decreasing the resources allocated to service these inputs. This implies designs that have no contention points or central bottlenecks, resulting in the ability to shard or replicate components and distribute inputs among them. …”

It’s All About Feedback

• The hacker needs feedback

• A system that behaves strangely due to some input reveals its

internal vulnerabilities

• Let’s look at some good craftsmanship patterns…

Circuit Breakers

“Circuit Breaker is the fundamental pattern for protecting your system from all manner of Integration Points problems.”

- Michael T. Nygard, Release It!, April 2007

Bulkheads

“Bulkheads are effective at maintaining service, or partial service, even in the face of failures. They are especially useful in service-oriented architectures, where the loss of a single service could have repercussions throughout the enterprise.”

- Michael T. Nygard, Release It!, April 2007

Sensitive Value - One Time Read Only

public final class SensitiveValue { private final AtomicReference<String> value;

public SensitiveValue(final String value) { this.value = new AtomicReference<>(validated(value)); }

private static String validated(final String value) { //Validation of input value return value; }

public String value() { return notNull(value.getAndSet(null), "Sensitive value has already been consumed"); }

@Override public boolean equals(final Object o) { throw new UnsupportedOperationException("Not allowed on sensitive value"); }

@Override public int hashCode() { throw new UnsupportedOperationException("Not allowed on sensitive value"); }

@Override public String toString() { return "SensitiveValue value = *****"; }}

“Evil” Test@RunWith(Theories.class)public class ValueObjectTest { private interface IllegalValue {String value();}

@DataPoints public static IllegalValue[] input() { return new IllegalValue[]{ () -> null, () -> "", () -> " ", () -> "A", () -> "AA", () -> " AA ", () -> "1234567890", () -> "<script>alert('42')</script>", () -> "' or '1'='1" }; }

@Rule public ExpectedException exception = ExpectedException.none();

@Theory public void should_be_illegal(final IllegalValue illegal) { exception.expect(ValidationException.class);

new ValueObject(illegal.value()); }

Stack Traces

java.sql.SQLException: Closed Connection at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:112) at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:146) at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:208) at oracle.jdbc.driver.PhysicalConnection.rollback(PhysicalConnection.java:1170) at org.apache.tomcat.dbcp.dbcp.DelegatingConnection.rollback(DelegatingConnection.java:368) at org.apache.tomcat.dbcp.dbcp.PoolingDataSource$PoolGuardConnectionWrapper.rollback(PoolingDataSource.java:323) at net.sf.hibernate.transaction.JDBCTransaction.rollback(JDBCTransaction.java:86) at org.springframework.orm.hibernate.HibernateTransactionManager.doRollback(HibernateTransactionManager.java:529) at org.springframework.transaction.support.AbstractPlatformTransactionManager.processRollback(AbstractPlatformTransact at org.springframework.transaction.support.AbstractPlatformTransactionManager.rollback(AbstractPlatformTransactionMana at org.springframework.transaction.interceptor.TransactionAspectSupport.completeTransactionAfterThrowing(TransactionAs

Stack Traces

java.sql.SQLException: Closed Connection at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:112) at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:146) at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:208) at oracle.jdbc.driver.PhysicalConnection.rollback(PhysicalConnection.java:1170) at org.apache.tomcat.dbcp.dbcp.DelegatingConnection.rollback(DelegatingConnection.java:368) at org.apache.tomcat.dbcp.dbcp.PoolingDataSource$PoolGuardConnectionWrapper.rollback(PoolingDataSource.java:323) at net.sf.hibernate.transaction.JDBCTransaction.rollback(JDBCTransaction.java:86) at org.springframework.orm.hibernate.HibernateTransactionManager.doRollback(HibernateTransactionManager.java:529) at org.springframework.transaction.support.AbstractPlatformTransactionManager.processRollback(AbstractPlatformTransact at org.springframework.transaction.support.AbstractPlatformTransactionManager.rollback(AbstractPlatformTransactionMana at org.springframework.transaction.interceptor.TransactionAspectSupport.completeTransactionAfterThrowing(TransactionAs

Hide It!

Oops!

That’s embarrassing. We’ve seem to have made an error.

Sorry for the inconvenience… [Head in Hands]

Legacy Code

[Room in a mess]

Cyclomatic Complexity

• Published in 1976 by Thomas J. McCabe “A Complexity Measure” i

IEEE Transactions on Software Engineering, Vol. SE-2 No. 4

• A measurement of the number of linearly independent paths through a

program's source code.

public void reserveRoomFor(String meeting, String owner, String roomName, Calendar start, Calendar end, String... invitees) {

final List<Booking> bookings = repository.getBookingsFor(roomName);

if(bookings != null && !bookings.isEmpty()) { for(Booking booking : bookings) { if(booking.collidesWith(new Booking(start, end, meeting, roomName, owner))) { throw new AlreadyReservedException(start, end, roomName, meeting, owner); } } }

repository.store(new Booking(start, end, meeting, roomName, owner));

if(dispatcher == null) { dispatcher = Platform.instance().eventDispatcher(); }

dispatcher.notify(invitees, new Booking(start, end, meeting, roomName, owner));}

Cyclomatic Complexity

Cyclomatic Complexity

public void reserveRoomFor(final Meeting meeting, final Room room) { notNull(meeting); notNull(room);

repository.store(booking(meeting, room));

dispatcher.notify(meeting.invitees, booking(meeting, room)); }

private Booking booking(final Meeting meeting, final Room room) { return new Booking(meeting, room); }

Key Take Aways

• Designing software is difficult

• Security spans across the entire application while development tends to be

from “top to bottom” in an application

• By using good design principles, security becomes a natural part of

development. Not a separate task.

Hypothesis

“Crafting software with good design principles along with a security mindset, significantly reduces the number of security flaws in an application.”

- Daniel Deogun

Hypothesis

“Crafting software with good design principles along with a security mindset, significantly reduces the number of security flaws in an application.”

- Daniel Deogun

Plausi

ble

Thanks

@DanielDeogun

References

• [Bodiam Castle - https://flic.kr/p/5BjV8] by Phillip Capper under license https://creativecommons.org/licenses/by/2.0/

• [Matrix Code - https://flic.kr/p/2Poor] by David.Asch under license https://creativecommons.org/licenses/by-nc-nd/2.0/

• [OWASP top 10] https://www.owasp.org/index.php/Top_10_2013-Top_10

• [Reactive Manifesto] http://www.reactivemanifesto.org/

• [Head in Hands - https://flic.kr/p/7p7raq] by Alex Proimos under license https://creativecommons.org/licenses/by-nc/2.0/

• [Questions - https://flic.kr/p/9ksxQa] by Damián Navas under license https://creativecommons.org/licenses/by-nc-nd/2.0/

• [Room in a mess - https://flic.kr/p/FSrZU] by yan yan under license https://creativecommons.org/licenses/by/2.0/

• [Historic Log Books - https://flic.kr/p/bjViT7] by PSNH under license https://creativecommons.org/licenses/by-nd/2.0/