Developers and security: It’s a lot more than just turning on SSL. In this session we’re going to learn to think differently about designing and coding in Java so that the application is less open to being attacked and (bonus) is often of higher quality. This talk will cover seven types of development issues that can get your application into trouble. With code examples (of course), we’ll explore a series of common code pitfalls and explain how to design and code differently. There is much to learn when creating a secure application - take your first steps here.
2. @spoole167
This Session is about Java
security
• It’s about how to start thinking
about secure application design
• It’s about how to improve your
development processes
• It’s about why this really matters
• It’s a taster only
There’s not much Java in it..
4. @spoole167
A bit of a marketing
exercise
• 2005 Fortify Software released a
paper called
“Seven Pernicious Kingdoms: A
Taxonomy of Software Security
Errors”
• It caught on among the security
community
17. @spoole167
Problems caused by metacharacters, alternate encodings and
numeric representations. General security problems result from
trusting input.
Input Validation and Representation
18. @spoole167
Input Validation and Representation
Forms Input.
1. Browser javascript code validates the form
2. Send the data to the server over a websocket as JSON.
3. Server turns JSON into Java
Browser Server
WS
http
19. @spoole167
Input Validation and Representation
My application only expects local war files to be loaded…
‘file://dir/app.war’
20. @spoole167
Input Validation and Representation
My application only expects local war files to be loaded…
‘http://badserver.com/badapp.war’
What happens if I get this?
21. @spoole167
Input Validation and Representation
Pretty obviously you cannot ever
trust what a client sends you. Ever.
Browser Server
22. @spoole167
Input from an end point is an obvious place to be cautious
Think of it like this…
Every API you write OR call. Whether REST interface or a simple class. Is
a ‘contract’
If that contract is not explicit and enforced your code is vulnerable.
Input Validation and Representation “It is the callers responsibility”
24. @spoole167
Input Validation and Representation
public class Driver {
private static final String DEFAULT_EXEC = "/usr/local/bin/docker";
private boolean error;
private String docker;
private File outputFile;
private List results=new LinkedList();
public Driver() {
this(DEFAULT_EXEC);
}
public Driver(String driver) {
docker = driver;
outputFile = new File("/tmp/docker.out");
}
Path to the docker exe
Where to put the output
25. @spoole167
Input Validation and Representation
Driver driver = new Driver();
…
List l = driver.run(“ps –a”);
if (driver.hasError() == false) {
System.out.println(l);
}
public class Driver {
private static final String DEFAULT_EXEC = "/usr/local/bin/docker";
private boolean error;
private String docker;
private File outputFile;
private List results=new LinkedList();
public Driver() {
this(DEFAULT_EXEC);
}
public Driver(String driver) {
docker = driver;
outputFile = new File("/tmp/docker.out");
}
26. @spoole167
Input Validation and Representation
Driver driver = new Driver();
…
List l = driver.run(“ps –a”);
if (driver.hasError() == false) {
System.out.println(l);
}
public class Driver {
private static final String DEFAULT_EXEC = "/usr/local/bin/docker";
private boolean error;
private String docker;
private File outputFile;
private List results=new LinkedList();
public Driver() {
this(DEFAULT_EXEC);
}
public Driver(String driver) {
docker = driver;
outputFile = new File("/tmp/docker.out");
}
27. @spoole167
What’s wrong with this code?
Input Validation and Representation
public class Driver {
private static final String DEFAULT_EXEC = "/usr/local/bin/docker";
private boolean error;
private String docker;
private File outputFile;
private List results=new LinkedList();
public Driver() {
this(DEFAULT_EXEC);
}
public Driver(String driver) {
docker = driver;
outputFile = new File("/tmp/docker.out");
}
28. @spoole167
This field is never validated.
Does it really point to a docker executable?
What would happen if it was set to some
other executable?
Could simply run a version check on it!
“docker –version”
Input Validation and Representation
public class Driver {
private static final String DEFAULT_EXEC = "/usr/local/bin/docker";
private boolean error;
private String docker;
private File outputFile;
private List results=new LinkedList();
public Driver() {
this(DEFAULT_EXEC);
}
public Driver(String driver) {
docker = driver;
outputFile = new File("/tmp/docker.out");
}
29. @spoole167
Even if the field was validated
during construction it can still be
changed afterwards.
Relying on constructor validation
only is also poor practise.
(Re)validate before usage
Input Validation and Representation
public class Driver {
private static final String DEFAULT_EXEC = "/usr/local/bin/docker";
private boolean error;
private String docker;
private File outputFile;
private List results=new LinkedList();
public Driver() {
this(DEFAULT_EXEC);
}
public Driver(String driver) {
docker = driver;
outputFile = new File("/tmp/docker.out");
}
30. @spoole167
What about this field?
Set to “/tmp/docker.out” ?
Input Validation and Representation
public class Driver {
private static final String DEFAULT_EXEC = "/usr/local/bin/docker";
private boolean error;
private String docker;
private File outputFile;
private List results=new LinkedList();
public Driver() {
this(DEFAULT_EXEC);
}
public Driver(String driver) {
docker = driver;
outputFile = new File("/tmp/docker.out");
}
31. @spoole167
What validation does
Java.io.File do?
Input Validation and Representation
public class Driver {
private static final String DEFAULT_EXEC = "/usr/local/bin/docker";
private boolean error;
private String docker;
private File outputFile;
private List results=new LinkedList();
public Driver() {
this(DEFAULT_EXEC);
}
public Driver(String driver) {
docker = driver;
outputFile = new File("/tmp/docker.out");
}
32. @spoole167
public File(String pathname) {
if (pathname == null) {
throw new NullPointerException();
}
this.path = fs.normalize(pathname);
this.prefixLength = fs.prefixLength(this.path);
}
private static final FileSystem fs = DefaultFileSystem.getFileSystem();
“A normal Win32 pathname contains no duplicate slashes,
except possibly for a UNC prefix, and does not end with a slash.
It may be the empty string. Normalized Win32 pathnames have
the convenient property that the length of the prefix almost
uniquely identifies the type of the path and whether it is
absolute or relative”
What validation does
Java.io.File do?
- Not much!
35. @spoole167
Input Validation and Representation
Who uses Java serialization?
Do you use RMI, JMX, JMS, Spring Service Invokers?
36. @spoole167
XMLEncoder (XML)
XStream (XML/JSON/various)
Kryo (binary)
Hessian/Burlap (binary/XML)
Castor (XML)
json-io (JSON)
Jackson (JSON)
Fastjson (JSON)
Red5 IO AMF (AMF)
Apache Flex BlazeDS (AMF)
Flamingo AMF (AMF)
GraniteDS (AMF)
WebORB for Java (AMF)
SnakeYAML (YAML)
jYAML (YAML)
YamlBeans (YAML)
Input Validation and Representation
How about one of these?
37. @spoole167
Input Validation and Representation
Any place you rely on:
persistence, messaging, remote ejb
rmi / jmx , rmi-iiop, CDI
There’s some form of serialization going on.
38. @spoole167
public class LayerCake {
private int layers;
public LayerCake(int layers) {
if(layers<1 || layers > 3)
throw new IllegalArgumentException("number of layers is invalid");
this.layers=layers;
}
Constructors do not get called
During deserialisation
So I can make this value anything I want
What the bad guys do
39. @spoole167
Input Validation and Representation
https://github.com/GrrrDog/Java-Deserialization-Cheat-Sheet
What the good and bad guys do
42. @spoole167
With serialisation vulnerabilities I
may be able to get the code to
overwrite a critical file somewhere
else.
If I modify both the exe and file
fields I can control what data gets
written to your system
What the bad guys do
public class Driver {
private static final String DEFAULT_EXEC = "/usr/local/bin/docker";
private boolean error;
private String docker;
private File outputFile;
private List results=new LinkedList();
public Driver() {
this(DEFAULT_EXEC);
}
public Driver(String driver) {
docker = driver;
outputFile = new File("/tmp/docker.out");
}
Remember, constructors are not
called during deserialization. The
data is simply inserted.
44. @spoole167
#1: all data received must be considered
untrusted and potentially dangerous.
• Data means anything that
comes in – command lines,
env variables, sockets, GUI,
REST , even data coming
from your own server…
• You must never trust the
systems who send you data.
• You can almost never trust
the systems you retrieve
data from
• You must validate data
when you get it AND before
you use it
Input Validation and Representation
46. @spoole167
API Abuse
My tool tags all the
containers it creates with
“adoptopenjdk=true”
That makes it easier to
retrieve only the relevant
containers when talking to
docker.
I have a test to check I can
create such containers
String id = createSimpleContainer(TEST_IMAGE_NAME);
ContainerInfo ci=inspectContainer(id);
assertTrue(ci.labels().containsKey(“adoptopenjdk”);
47. @spoole167
API Abuse
But I want to make sure
that the calls to docker are
really working.
So I have a ‘get all’ method.
It’s not used in production
But its exposed as a test
end point…
String id = createSimpleContainer(TEST_IMAGE_NAME);
List<Container> allc = allContainerList();
assertTrue(allc.isEmpty()==false);
get("/test/v1/*" , (req, res) ->plimsoll.test_v1_request.handleRequest(req,res));
48. @spoole167
API Abuse
A common vulnerability pattern is to find hidden end points like ones just for
testing.
Reading the code on github or just Googling for your sites metadata can easily
reveal them
And of course test end points tend to have less security
Never have APIs that are just for ‘testing’ or bypass normal
authentication processes..
51. @spoole167
API Abuse
My tool allows for complex scenarios to be created.
JVM = Hotspot or OpenJ9
App Server = Tomcat or Jetty
Various versions strings.
The combinations are sent one by one…
JVM=Hotspot, AppServer=Tomcat, AppVersion=9.0
52. @spoole167
API Abuse
The code validates the entries as being
individually
correct..
✓ JVM=Hotspot
✓ AppServer=Tomcat
✓ AppVersion=9.4.9
But not that the combinations are valid!
53. @spoole167
API Abuse
My code also returns lists of containers so there
are page / page size type parameters..
“list containers from page 7 with page size 100”
“list containers from page 1 with page size 10”
54. @spoole167
API Abuse
My code also returns lists of containers so there
are page / page size type parameters..
“list containers from page 7 with page size 100”
“list containers from page 1 with page size 10”
What about..
“list containers from page 0 with page size -100”
“list containers from page -1 with page size 10”
“list containers from page MAX_INT with page size -MAX_INT”
55. 55
Try likely entry points and all the http verbs
GET /users/1
DELETE /api/v1/users/1
OPTIONS /api/v1/user/1
HEAD /api/v1/user/1
POST /users/1
What the bad guys do
56. 56
Play with the headers and cookies
POST /api/v1/user HTTP/1.1
Host: developer.mozilla.org
Content-Length: 64
Content-Type: application/x-
www-form-urlencoded
What the bad guys do
57. 57
Can I get the service to fail or break?
404 “Not Found”
503 “Service Unavailable”
“500 Internal Server Error”
Different errors from different components?
What the bad guys do
58. 58
If I can find a static endpoint
service I might be able to get
at the filesystem…
GET /api/v1/images/a/../../../../../../etc/passwd
What the bad guys do
59. 59
Fuzzing calls and data..
GET /users/1
POST /users/2
PUT /users/20000?name=“(select
GET /users/-1
GET /users/$INT_MAX
What the bad guys do
61. 61
Fuzzing calls and data.
Fuzz urls, json payloads, xml payloads, binary payloads …
Import / export / upload / download options ..
Command line options, file formats …
“known-to-be-dangerous” values
In the public domain
Widespread
& mature
Automatic ‘protocol’
detection & exploitation
What the bad guys do
62. @spoole167
#2 Never give control to the
caller by accepting
unconstrained instructions
• Calling endpoints that are
hidden
• Finding hidden fields in your
requests and changing them
• Sending unexpected but
pseudo-valid combinations of
data
• Exploring the data ranges (+
and - )
• Using an API out of context.
(like credit card validation)
• Exploiting query languages
(SQL injection plus. JQ, or
Xpath etc)
• most systems assume any call
to it is correct and do minimal
validation once the individual
elements are accepted.
API Abuse
64. @spoole167
Errors
private Properties loadConfig() {
Properties p = new Properties( System.getProperties() );
File f = new File("plimsoll.properties");
if (f.exists()) {
FileReader fr;
try {
fr = new FileReader(f);
p.load(fr);
fr.close();
} catch (IOException e) {
}
return p;
}
Some code – reads a
config file…
65. @spoole167
Errors
private Properties loadConfig() {
Properties p = new Properties( System.getProperties() );
File f = new File("plimsoll.properties");
if (f.exists()) {
FileReader fr;
try {
fr = new FileReader(f);
p.load(fr);
fr.close();
} catch (IOException e) {
}
return p;
}
Don’t assume that only
the errors you expect will
occur - such as
FileNotFoundException
66. @spoole167
Errors
private Properties loadConfig() {
Properties p = new Properties( System.getProperties() );
File f = new File("plimsoll.properties");
if (f.exists()) {
FileReader fr;
try {
fr = new FileReader(f);
p.load(fr);
fr.close();
} catch (FileNotFoundException e) {
// allowed
} catch (IOException e) {
// not expected
}
return p;
}
Better!
67. @spoole167
Errors
Catching or throwing exceptions in a more generic manner than needed can hide
the activities of the attacker
Either because of a lack of specific info in logging and log analysis
i.e: “Config file not found”. Vs “Unexpected IO Error reading the config file”
Or simply because the unusual exception is treated as usual
68. @spoole167
Errors
Catching or throwing exceptions in a more generic manner than needed can hide
the activities of the attacker
Either because of a lack of specific info in logging and log analysis
i.e: “Config file not found”. Vs “Unexpected IO Error reading the config file”
Or simply because the unusual exception is treated as usual
BTW - catching NullPointer Exceptions as a way of detecting ‘expected’ nulls is also
poor practice – as described above. You simply can’t tell which NPE is which.
74. @spoole167
JsonObject jo=new JsonObject();
for(int i=0;i<l.getLength();i++) {
Node n= l.item(i);
switch( n.getNodeName() ) {
case "address" : jo.add(parseAddress(n)); break;
case "name" : jo.add(parseName(n)); break;
case "balance" : jo.add(parseBalance(n)); break;
case ”overdraft": jo.add(parseOverdraft(n)); break;
}
}
So you have to change your code
75. @spoole167
This happens a lot<account>
<name>
Mega Corp Limited
</name>
<address>
The Citadel
London
SW1
</address>
<balance amount="100" currency="EURO"/>
<overdraft limit=”500" />
<credit>Low</credit>
</account>
76. @spoole167
String handlerName = handlers.getProperty(n.getNodeName().toLowerCase());
try {
Class c = Class.forName(handlerName);
IHandler handler = (IHandler) c.newInstance();
jo.add(handler.convert(handler));
} catch (Exception e) {
String errorInfo = "could not create class for handler" + n.getNodeName() + " class=" + handlerName;
throw new IOException(errorInfo, e);
}
}
private static Properties handlers = new
Properties(file,System.getProperties());
You change your code
address=com.foo.standard.AddressHandler
balance=com.foo.standard.BalanceHandler
name=com.foo.standard.NameHandler
78. @spoole167
And when things go wrong you get a nice error message
java.io.IOException: could not create class for handler credit
class=null
String errorInfo = "could not create class for handler" + n.getNodeName() +
"class=" + handlerName;
throw new IOException(errorInfo, e);
Missing handler in the properties file
79. @spoole167
And when things go wrong you get a nice error message
java.io.IOException: could not create class for handler credit
class=com.foo.handler.CreditHandler
String errorInfo = "could not create class for handler" + n.getNodeName() +
"class=" + handlerName;
throw new IOException(errorInfo, e);
Missing class on the classpath
80. @spoole167
What happens with this data?
<account>
<name>
Mega Corp Limited
</name>
<address>
The Citadel
London
SW1
</address>
<balance amount="100" currency="EURO"/>
<java.ext.dirs/>
</account>
What the bad guys do
81. @spoole167
String errorInfo = "could not create class for handler" + n.getNodeName() +
"class=" + handlerName;
throw new IOException(errorInfo, e);
java.io.IOException: could not create class for handler java.ext.dirs class
=/Users/spoole/Library/Java/Extensions:
/Library/Java/JavaVirtualMachines/jdk1.8.0_102.jdk/Contents/Home/jre/lib/ext:
/Library/Java/Extensions:/Network/Library/Java/Extensions:
/System/Library/Java/Extensions:
/usr/lib/java
What the bad guys do
82. 82
Stack traces and error messages really help
More help I’m on the right track
More component info
What the bad guys do
84. @spoole167
java.lang.NullPointerException at com.stoneware.server.auth.OpenIDProviders.getProviderFromUrl(qx:91) at
org.apache.jsp.openid.openIDClaim_jsp._jspService(openIDClaim_jsp.java:248) at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70) at
javax.servlet.http.HttpServlet.service(HttpServlet.java:790) at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:438) at
org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:396) at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:340) at
org.eclipse.jetty.jsp.JettyJspServlet.service(JettyJspServlet.java:107) at javax.servlet.http.HttpServlet.service(HttpServlet.java:790) at
org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:812) at
org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1669) at com.stoneware.filter.VersionCheckFilter.doFilter(wtb:391) at
org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1652) at com.stoneware.filter.SecurityFilter.doFilter(sed:802) at
org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1652) at com.stoneware.relay.b.A.doFilter(tlc:1671) at
org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1652) at com.stoneware.filter.SessionIDFilter.doFilter(bvb:1475) at
org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1652) at com.stoneware.relay.managers.f.doFilter(or:500) at
org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1652) at
org.eclipse.jetty.websocket.server.WebSocketUpgradeFilter.doFilter(WebSocketUpgradeFilter.java:224) at
org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1652) at
org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:585) at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143)
at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:542) at
org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:223) at
org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1127) at
org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:515) at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:185)
at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1061) at
org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141) at
org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:215) at
org.eclipse.jetty.server.handler.HandlerList.handle(HandlerList.java:52) at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:97) at
org.eclipse.jetty.rewrite.handler.RewriteHandler.handle(RewriteHandler.java:332) at org.eclipse.jetty.servlets.gzip.GzipHandler.handle(GzipHandler.java:479)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:97) at
org.eclipse.jetty.server.handler.RequestLogHandler.handle(RequestLogHandler.java:95) at
org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:97) at
com.codahale.metrics.jetty9.InstrumentedHandler.handle(InstrumentedHandler.java:190) at
org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:97) at org.eclipse.jetty.server.Server.handle(Server.java:499) at
org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:311) at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:257) at
org.eclipse.jetty.io.AbstractConnection$2.run(AbstractConnection.java:544) at
org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:635) at
org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:555) at java.lang.Thread.run(Unknown Source)
Error traces can be used to identify what you’re running –
down to working out the version number…
What the bad guys do
85. 85
Log / alert unexpected behavior
✓ Build in an expectation of what the client will be doing with
the data.
✓ All log entries must be useful – generic errors don’t help.
✓ Be careful about the amount of extra info in a log –
remember the bad guys may gain access to them too
Following good API design doesn’t mean you have to be too helpful.
Errors
86. @spoole167
#3 Error paths are as critical as normal flows
#4 Report only enough information to
identify the situation
• In general we’re poor at
dealing with errors in our
code.
• Developers focus on the
positive side.
• With consequential lack of
testing for error paths and
checking correct behavior
Errors
88. @spoole167
Can you rely on having a secure encrypted connection?
Browser Exploit Against
SSL/TLS (BEAST)
Compression
Ratio Info-leak
Made Easy
(CRIME)
Browser Reconnaissance and
Exfiltration via Adaptive
Compression of Hypertext
(BREACH)
Padding Oracle On Downgraded
Legacy Encryption (POODLE)
What the bad guys do
89. @spoole167
All data to and from the API is public
Even if you have a secure connection to the client
Man in the middle Reverse
engineered
client or app
Malware / xss
In the browser
What the bad guys do
91. @spoole167
Phew.
• So many things ways your
application can be
vulnerable.
• Security is not something
you add after. It’s always a
part of your design thinking.
93. @spoole167
Security Features
Many vulnerabilities come from poor authentication and access control
methods but ‘Security’ is a wider topic.
Confidentiality : Managing the data in your care
Cryptography : methods to ensure information is kept private
Privilege management: Ensuring actors are who they say they are
94. @spoole167
“I don’t need any security as the system is local…”
Security Features
Browser Server
Docker
Daemon
Remote
repositories
Local
repositories
WS
Cmd line
http
Adopt Server
http
95. @spoole167
“I don’t need any security as the system is local…”
Security Features
Browser Server
Docker
Daemon
Remote
repositories
Local
repositories
WS
Cmd line
http
Adopt Server
http
The browser is vulnerable to Cross Site Scripting attacks. So a remote attacker could get on to your system
96. @spoole167
“I don’t need any security as the system is local…”
Security Features
Browser Server
Docker
Daemon
Remote
repositories
Local
repositories
WS
Cmd line
http
Adopt Server
http
Since my tool uses an API that is unconstrained (ie the command line). The attacker could do anything
And the tool is downloading and running code from the web – another attack point
97. @spoole167
“I don’t need any security as the system is local…”
Security Features
Browser Server
Docker
Daemon
Remote
repositories
Local
repositories
WS
Cmd line
http
Adopt Server
http
The docker instance may have access to a secure repository. Without security my tool is enabling an easy bypass of
any access controls. The contents of the server are now available for a hacker to explore or use.
98. @spoole167
“I don’t need any security as the system is local…”
Security Features
Browser Server
Docker
Daemon
Remote
repositories
Local
repositories
WS
Cmd line
http
Adopt Server
http
So actually my tool needs really good security features.
100. @spoole167
Security Features
Trusting the end user not to tamper with the data
Cookie[] cookies =
request.getCookies();
for (int i =0; i< cookies.length; i++) {
Cookie c = cookies[i];
if (c.getName().equals("role")) {
userRole = c.getValue();
}
}
101. @spoole167
Security Features
Trusting the end user not to tamper with the data
Cookie[] cookies =
request.getCookies();
for (int i =0; i< cookies.length; i++) {
Cookie c = cookies[i];
if (c.getName().equals("role")) {
userRole = c.getValue();
}
}
Does encryption solve this?
102. @spoole167
Security Features
Trusting the end user not to tamper with the data
Cookie[] cookies =
request.getCookies();
for (int i =0; i< cookies.length; i++) {
Cookie c = cookies[i];
if (c.getName().equals("role")) {
userRole = c.getValue();
}
}
No!
XSS attacks often replace encrypted
cookies etc with ones from another
session that has the required
privileges.
You must have additional privilege
management processes in play
103. @spoole167
Security Features
Having endpoints that allows the
client to read the config
get: ”/api/v1/config/<key_name>”.
Returns json :
{ “key”: key_name , “value” : value }
public String getConfigValue(String key) {
return config.getProperty(key);
}
private Properties loadConfig() {
Properties p = new Properties( System.getProperties() );
..
Poor confidentiality management
104. @spoole167
Security Features
My code has a endpoint that allows the
client to read the config
get: ”/api/v1/config/<key_name>”.
Returns json :
{ “key”: key_name , “value” : value }
public String getConfigValue(String key) {
return config.getProperty(key);
}
private Properties loadConfig() {
Properties p = new Properties( System.getProperties() );
..
Poor confidentiality management
Since the config was backed by
System.getProperties all system
properties are exposed..
109. @spoole167
private Properties loadConfig() {
Properties p = new Properties( System.getProperties() );
File f = new File("plimsoll.properties");
if (f.exists()) {
FileReader fr;
try {
fr = new FileReader(f);
p.load(fr);
fr.close();
} catch (IOException e) {
}
return p;
}
Security Features
Unsophisticated credentials management
-Ddocker.user=foo -Ddocker.password=bar.
Storing information
In text files. Easily
readable.
Easily changed
on the command line.
(turns up in the logs)
110. @spoole167
Yet another Google search:
filetype:password jmxremote
I found something…
#
# Following are two commented-out entries. The
"measureRole" role has
# password "QED". The "controlRole" role has password
"R&D".
#
monitorRole C0gnitive!
controlRole C0gnitive!
What the bad guys do
115. @spoole167We’ve found 72,609 code results
AlwaysValidTrustManager
TrustAllServersWrappingTrustManager
A very friendly, accepting trust
manager factory. Allows anything
through. all kind of certificates are
accepted and trusted.
A very trusting trust manager that
accepts anything
// Install the all-trusting trust
manager
OverTrustingTrustProvider
AllTrustingSecurityManagerPlugin.java
AcceptingTrustManagerFactory.java
AllTrustingCertHttpRequester.java
Security Features
116. @spoole167We’ve found 72,609 code results
AlwaysValidTrustManager
TrustAllServersWrappingTrustManager
A very friendly, accepting trust
manager factory. Allows anything
through. all kind of certificates are
accepted and trusted.
A very trusting trust manager that
accepts anything
// Install the all-trusting trust
manager
OverTrustingTrustProvider
AllTrustingSecurityManagerPlugin.java
AcceptingTrustManagerFactory.java
AllTrustingCertHttpRequester.java
Security Features
How many are in your
dependencies?
117. @spoole167
Security Features
Defaulting to full access or running too much under privilege
method() {
AccessController.doPrivileged( new PrivilegedAction())
{
public Object run() {
// my app goes here
}
};
}
118. @spoole167
#5 Access controls as near to business logic as possible
#6 Keep credentials encrypted, safe and out of memory
#7 Fail safely
#8 Know your responsibilities for others
• For many the word ‘security’
is content free. Its all
someone elses problem.
• It’s not – every system needs
to understand its security
posture.
• Where do you check access
control?
• Where and do you store
credentials?
• Will you default to a safe
mode or an ‘all access pass
mode’ ?
• BTW - How much code gets
run before you say no?
Security Features
119. @spoole167
This is straightforward
If your system is too complex
to understand
Or just poorly written. It’s
more likely to have edge cases,
weak spots etc
So more open to being
attacked
Code Quality
#9 Keep it simple
# 10 Have a full test suite
# 11 test for failing conditions:
even security related
Poor code quality leading to unpredictable behaviour and
opportunities to stress the system in unexpected ways
121. @spoole167
Encapsulation
Insufficient encapsulation of critical data or functionality
Errors that allow functionality or data
to cross trust boundaries
Escalation of data access privileges
Insecure import of untrusted code
Exposure of information through
unprotected resources
#12 use immutable state where at all possible
#13 Do not give away extraneous data
#14 Only hold the least amount of critical data – and throw it away as soon as possible
#15 Reduce functionality to just the usecases needed - No nice-to-haves !
122. @spoole167
#16 control of state never
leaves your system
• Client can send you requests
to change state but it must
never own the state.
Time and State
Unexpected interactions between threads, processes, time,
and information (shared state)
people put state into a cookie and
assume it cant be modified if
encrypted..
What happens if someone sends you
an encrypted state object from another
session…
Did you have a flag in the state that
said the user had higher privileges.?
123. @spoole167
• All the parts of your development
process
• The tools you use
• Your dependencies
• The operating system
• The build machines.
• The code repository
• All these can be vulnerable to
attack.
Environment
124. @spoole167
Authentication, access control, confidentiality,
cryptography, privilege management.
Unexpected interactions between
threads, processes, time, and information
(shared state)
Errors related to error handling
Problems caused by metacharacters,
alternate encodings and numeric
representations. General security problems
result from trusting input.
Using an API in a manner contrary to its
intended use
Insufficient encapsulation of critical data or
functionality
Everything that is outside of the source
code but is still critical to the security of the
application
Time and State
Poor code quality leading to unpredictable
behaviour and opportunities to stress the
system in unexpected ways.
Errors
API abuse
Code Quality
Security Features
Encapsulation
Input Validation and Representation
Environment
125. @spoole167
Summary
1. Hackers use sophisticated tooling to attack you
2. These tools look for known vulnerabilities and common design errors.
3. Everyone makes mistakes (some of which we don’t know about yet)
4. Relying on one single form of defense is the ultimate foolishness
5. Right now its about defense In depth
6. Make sure you have alarm systems: Invest in detection, invest in the
strongest encryption, invest in security testing, design for defense
7. Take a long hard look at your design choices – easy for developers = easy
for hackers
8. Turn your suspicion detector way up when using other peoples code
126. There are bad guys out there and your
application is at risk
Don’t make it worse by ignoring the problem
https://www.flickr.com/photos/koolmann/
@spoole167