Java application security the hard
way - a workshop for the serious
developer
Devoxx UK
2018
Outline
• 9:30 - 11:00
• 20: (SP) Intros & ‘The Economics of
Cybercrime’
• 40: (SP) Bad Guy tactics – Discovery and
Attack
• 30: (SM) Community hacking…
• 11:00 -11:30 break
• 11:30 – 13:00
• 50: (SP) Application design – why you’re
doing it wrong…
• 30: (SM) Development Processes & tooling
• 10: Wrap up
Credits
This workshop is a
collaborative effort between
IBM, Snyk and Sonatype
Thanks especially to Ilkka
Turunen from Sonatype
About us
Steve Poole
Developer Advocate, IBM
@spoole167 @sjmaple
Simon Maple
Director of Developer
Relations, Snyk
This workshop 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
The economics of cybercrime
In 2016 Cybercrime was
estimated to be worth
450 Billion Dollars
@spoole167
Organized Cybercrime is the most profitable type of crime
In 2016 The illicit drug trade
was estimated to be worth
435 Billion Dollars
Organized Cybercrime is the most profitable type of crime
• Guess which one has the least risk to the criminal ?
• Guess which is growing the fastest ?
• Guess which one is the hardest to prosecute ?
• Guess which one is predicted to reach 2100 Billion Dollars by 2019?
• Guess which one is predicted to reach 6000 Billion Dollars by 2021?
@spoole167
0
1000
2000
3000
4000
5000
6000
2013 2014 2015 2016 2017 2018 2019 2020 2021
Cybercrime Drug trade
That’s about £600 for every
person on the planet
Cyber attackers use vulnerabilities to get into your system
And go through your system to another (and repeat)
To steal your data To change your data To crash your systems Use your compute power
if (multiWrapper.hasErrors()) {
if(validation!=null){
validation.addActionError( … );
}
}
This is a major vulnerability
So is this. Just two characters
Vulnerabilities are almost always simple
there are no smoking guns
Exploits are chaining together vulnerabilities
https://www.flickr.com/photos/84744710@N06/
“Common
Vulnerabilities
& Exposures”
• https://cve.mitre.org
• The Standard place find details about ‘CVEs’
• International cyber security community effort
• Common naming convention and unique
references.
• Allows you to know when a problem is resolved
in something you are using
‘CVEs’ https://cve.mitre.org/cgi-bin/cvekey.cgi?keyword=*
keywords=java serialization “12”
keyword=java “1761”
CVE-2016-0686
“Unspecified vulnerability in Oracle Java SE 6u113, 7u99, and 8u77
and Java SE Embedded 8u77 allows remote attackers to affect
confidentiality, integrity, and availability via vectors related to
Serialization.”
That’s all you will find about this fix
Talking about the details of a fix or flaw in public is just like
tweeting your credit card # and pin
So we don’t. We give
you information about
the impact instead.
Apache struts 2 - the Equifax affair
Attackers used Remote Code Execution to steal data over
a long period
CVE-2017-5638 The Jakarta Multipart parser in Apache Struts 2 2.3.x before 2.3.32 and
2.5.x before 2.5.10.1 has incorrect exception handling and error-
message generation during file-upload attempts, which allows remote
attackers to execute arbitrary commands via a crafted Content-Type,
Content-Disposition, or Content-Length HTTP header, as exploited in the
wild in March 2017 with a Content-Type header containing a #cmd=
string.
Large Scale Exploit
March 9
First ‘whoami’ is run
AprMar May Jun Jul Aug Sept
March 7
Apache Struts releases
updated version to thwart
vulnerability
CVE-2017-5638
July 29
Breach is
discovered by
Equifax.
Sept 7
A new strutcs RCE
vulnerability is
announced and fixed.
CVE-2017-9805
Probe Crisis Management
March 5 vulnerability and fixed
Time to EXPLOIT?Source: Adapted from IBM X-Force / Analysis by Gartner Research (September 2016)
Year of Date Reported
2006 2007 2008 2009 2010 2011 2012 2013 2104 2015
10
20
30
40
50
0
AverageDaystoExploit
Average
45
15
2017
2 days
Vulnerabilities are almost always simple
Exploits are chained together vulnerabilities
Everyone has vulnerabilities
Time to exploit is almost instant
• Look for CVE’s at
https://cve.mitre.org
• Understanding the
categorization and
evaluation process is key to
knowing how dangerous a
vulnerability is
• Ignoring critical updates is
high risk
Errors
Discovery and Attack
Here’s how it work in practice
• New vulnerability announced: “Remote Code Execution” types are
the best
• Start with “net fishing” – who’s vulnerable? Is there an exploit?
The Jakarta Multipart parser in Apache Struts 2 2.3.x before 2.3.32 and
2.5.x before 2.5.10.1 has incorrect exception handling and error-
message generation during file-upload attempts, which allows remote
attackers to execute arbitrary commands via a crafted Content-Type,
Content-Disposition, or Content-Length HTTP header, as exploited in the
wild in March 2017 with a Content-Type header containing a #cmd=
string.
CVE-2017-5638
Things we can do..
#1 : Search for know meta
data identifiers for Apache
Struts
File types like ‘action’ or do’
Pick one…
Things we can do..
#2 : Search for other
vulnerabilities you might have..
What version of a server are
you running?
Using Chrome developer tools
Pick the network tab
Pick network tab
Turn on recording and refresh
Turn on recording (red means on)
Select the
first entry…
Hello nginx
What
vulnerabilities
does nginx
1.12.2 have?
https://cve.mitre.org/cgi-
bin/cvekey.cgi?keyword=nginx+1.12.2
Things we can do #3
Get more information about
the target site
Search for
the ip
address of
the site
https://www.shodan.io
Things we can do #4
Shodan.io lets us search for
technology usage..
Things we can do #5
How about looking for existing
exploits?
Things we can do #6
Use tools to run the exploits..
Things we can do #7
Use other easily available
tools..
https://www.wappalyzer.com/
https://www.barclays.co.uk/
Click on Wappalyzer
Wappalyzer
says
A bit more
digging in the
headers
Apache Server:
2.4.6
D3: 3.5.17 jQuery: 2.2.4
Adobe
Experience
Manager: 4.2.2
OS: Redhat
Enterprise Linux
ip address:
157.83.96.72
Physical location
Twickenham
Open ports: 80,
443
SSL certificate
chains
jquery has a
nice
vulnerability
Apache
Server 2.4.6
– released
22 Jul 2013
https://www.cvedetails.com
Your go…
Check out your servers here
www.wappalyzer.com
www.shodan.io
Look at your headers etc
using Chrome Developer tools
Visit the cve site
cve.mitre.org
www.cvedetails.com
Look for known vulnerabilities
in your software
snyk.io
filetype:do
Play with google and find some
interesting targets
filetype:action
https://nvd.nist.gov/vuln/detail/CVE-2017-5638
Read about the information collated about a vulnerability
Live Hack
We saw how much information
is available about servers,
software etc
.
How much sophisticated
tooling is available in the open.
How people are building
exploits for vulnerabilities very
quickly.
After the break we’ll start to
talk about what you can do to
start to address the problems.
Outline
• 9:30 - 11:00
• 20: (SP) Intros & ‘The Economics of
Cybercrime’
• 40: (SP) Bad Guy tactics – Discovery and
Attack
• 30: (SM) Community hacking…
• 11:00 -11:30 break
• 11:30 – 13:00
• 50: (SP) Application design – why you’re
doing it wrong…
• 30: (SM) Development Processes
• 10: Wrap up
Break Read about Jenkins vulnerability CVE-2017-1000353
Can you find a vulnerable server on shodan.io
Hint – Jenkins has a header called X-Jenkins
This section is intended
you a taster for how you
can design your software
to be less vulnerable to
attack
Software design flaws are grouped into “7 Pernicious Kingdoms”
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
In fact there are more than 7

Seven
Pernicious
Kingdoms
Security Features
Time and State
Errors
Input Validation and Representation
API Abuse
Code Quality
Encapsulation
Environment
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
Section Flow
Using a real scenario
walk though some of
the 7PK looking at
code and thinking
about design
My scenario
• I’m developing a tool for Adopt OpenJDK
• Make it easy for others to get the new
drivers
• Make it easy to try out the new Java
versions with common app servers and user
applications.
• It’s designed to run locally but will
eventually be hostable
Plimsoll
Browser Server
Docker
Daemon
Remote
repositories
Local
repositories
WS
Cmd line
http
Adopt Server
http
Problems caused by metacharacters, alternate encodings and
numeric representations. General security problems result from
trusting input.
Input Validation and Representation
Input Validation and Representation
Forms Input.
Browser javascript code validates the form
Send the data to the server over a websocket as JSON.
Server turns JSON into Java object assuming it’s a valid
PlimsollCommand object
public class PlimsollCommand {
public String type;
public Object msg;
}
{ ‘type’ : cmd_id , ‘msg’ : {} }
Input Validation and Representation
Forms Input.
Browser javascript code validates the form
Send the data to the server over a websocket as JSON.
Server turns JSON into Java object assuming it’s a valid
PlimsollCommand object
public class PlimsollCommand {
public String type;
public Object msg;
}
Actually I expect a Map but
Object is easier to use with
the JSON parser
{ ‘type’ : cmd_id , ‘msg’ : {} }
Input Validation and Representation
My application only expects local war files to be loaded…
{ ‘type’ : ‘upload’ ,
‘msg’ : { ‘war’ : ‘file://dir/app.war’ }
}
This example gets converted into java objects
quite easily. Lets the user point me at their
application on disk. What happens if the
browser sends me this?
{ ‘type’ : ‘upload’ ,
‘msg’ : { ‘war’ :
‘http://badserver.com/badapp.war’ }
}
Input Validation and Representation
Forms Input.
Browser javascript code validates the form
Send the data to the server over a websocket as JSON.
Server turns JSON into Java object assuming it’s a valid
PlimsollCommand object
public class PlimsollCommand {
public String type;
public Object msg;
}
What would happen if the
JSON data was actually a list?
{ ‘type’ : cmd_id , ‘msg’ : [ ‘a’ , ‘bad’ , ‘thing’ ] }
Input Validation and Representation
Forms Input.
Browser javascript code validates the form
Send the data to the server over a websocket as JSON.
Server turns JSON into Java object assuming it’s a valid
PlimsollCommand object
public class PlimsollCommand {
public String type;
public Object msg;
}
Pretty obviously you cannot ever
trust what a client sends you. Ever.
What would happen if the
JSON data was actually a list?
• Input from an end point is an obvious place to be cautious
• Think of it like this…
• Every API you write. Whether REST interface or a simple class defines
a ‘contract’ with the caller.
• If that contract is not explicit and enforced your code is vulnerable.
• And it’s even more subtle than that…
Input Validation and Representation “It is the callers responsibility”
Browser Server
Docker
Daemon
Remote
repositories
Local
repositories
WS
Cmd line
http
Input Validation and Representation
Adopt Server
http
My tool uses the docker command line interface to retrieve information and run containers
“docker images”
“docker run –it ubuntu /bin/bash”
Input Validation and Representation
public classDockerCommandLineDriver{
privatestaticfinalStringDEFAULT_EXEC ="/usr/local/bin/docker";
privateStringdocker;
privatebooleanerror;
privateFileoutputFile;
privateListresults=newLinkedList();
staticenumCMD{
active,images,containers
};
privatestaticfinalString[]cmds =newString[]{ "ps-a", "images","containerls -a"};
public DockerCommandLineDriver(){
this(DEFAULT_EXEC);
}
public DockerCommandLineDriver(Stringdriver){
docker= driver;
outputFile= newFile("/tmp/docker.out");
}
Input Validation and Representation
public classDockerCommandLineDriver{
privatestaticfinalStringDEFAULT_EXEC ="/usr/local/bin/docker";
privateStringdocker;
privatebooleanerror;
privateFileoutputFile;
privateListresults=newLinkedList();
staticenumCMD{
active,images,containers
};
privatestaticfinalString[]cmds =newString[]{ "ps-a", "images","containerls -a"};
public DockerCommandLineDriver(){
this(DEFAULT_EXEC);
}
public DockerCommandLineDriver(Stringdriver){
docker= driver;
outputFile= newFile("/tmp/docker.out");
}
DockerCommandLineDrivercld = newDockerCommandLineDriver();
…
Listl= cld.run(CMD.active);
if(cld.hasError()==false){
System.out.println(l);
}
Input Validation and Representation
DockerCommandLineDrivercld = newDockerCommandLineDriver();
…
Listl= cld.run(CMD.active);
if(cld.hasError()==false){
System.out.println(l);
}
public Listrun(CMDcmd) {
Stringcmdline =cmds[cmd.ordinal()];
cmdline =docker +""+cmdline;
String[]parts=cmdline.split(" ");
ProcessBuilder pb=new ProcessBuilder(parts);
pb.redirectErrorStream(true);
pb.redirectOutput(ProcessBuilder.Redirect.to(outputFile));
try{
Process p=pb.start();
intresult =p.waitFor();
error=result !=0;
} catch (IOException | InterruptedException e) {
error=true;
}
return saveResults();
}
What’s wrong with this code?
public classDockerCommandLineDriver{
privatestaticfinalStringDEFAULT_EXEC ="/usr/local/bin/docker";
privateStringdocker;
privatebooleanerror;
privateFileoutputFile;
privateListresults=newLinkedList();
staticenumCMD{
active,images,containers
};
privatestaticfinalString[]cmds =newString[]{ "ps-a", "images","containerls -a"};
public DockerCommandLineDriver(){
this(DEFAULT_EXEC);
}
public DockerCommandLineDriver(Stringdriver){
docker= driver;
outputFile= newFile("/tmp/docker.out");
}
Input Validation and Representation
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!
public classDockerCommandLineDriver{
privatestaticfinalStringDEFAULT_EXEC ="/usr/local/bin/docker";
privateStringdocker;
privatebooleanerror;
privateFileoutputFile;
privateListresults=newLinkedList();
staticenumCMD{
active,images,containers
};
privatestaticfinalString[]cmds =newString[]{ "ps-a", "images","containerls -a"};
public DockerCommandLineDriver(){
this(DEFAULT_EXEC);
}
public DockerCommandLineDriver(Stringdriver){
docker= driver;
outputFile= newFile("/tmp/docker.out");
}
“docker –version”
Input Validation and Representation
Even if the field was validated
during construction it can still be
changed afterwards.
Relying on constructor validation
only is also poor practise.
public classDockerCommandLineDriver{
privatestaticfinalStringDEFAULT_EXEC ="/usr/local/bin/docker";
privateStringdocker;
privatebooleanerror;
privateFileoutputFile;
privateListresults=newLinkedList();
staticenumCMD{
active,images,containers
};
privatestaticfinalString[]cmds =newString[]{ "ps-a", "images","containerls -a"};
public DockerCommandLineDriver(){
this(DEFAULT_EXEC);
}
public DockerCommandLineDriver(Stringdriver){
docker= driver;
outputFile= newFile("/tmp/docker.out");
}
(Re)validate just before usage
Input Validation and Representation
What about this field?
Set to “/tmp/docker.out” ?
public classDockerCommandLineDriver{
privatestaticfinalStringDEFAULT_EXEC ="/usr/local/bin/docker";
privateStringdocker;
privatebooleanerror;
privateFileoutputFile;
privateListresults=newLinkedList();
staticenumCMD{
active,images,containers
};
privatestaticfinalString[]cmds =newString[]{ "ps-a", "images","containerls -a"};
public DockerCommandLineDriver(){
this(DEFAULT_EXEC);
}
public DockerCommandLineDriver(Stringdriver){
docker= driver;
outputFile= newFile("/tmp/docker.out");
}
Input Validation and Representation
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
Remember constructors are not
called during deserialization. The
data is simply inserted.
public classDockerCommandLineDriver{
privatestaticfinalStringDEFAULT_EXEC ="/usr/local/bin/docker";
privateStringdocker;
privatebooleanerror;
privateFileoutputFile;
privateListresults=newLinkedList();
staticenumCMD{
active,images,containers
};
privatestaticfinalString[]cmds =newString[]{ "ps-a", "images","containerls -a"};
public DockerCommandLineDriver(){
this(DEFAULT_EXEC);
}
public DockerCommandLineDriver(Stringdriver){
docker= driver;
outputFile= newFile("/tmp/docker.out");
}
Input Validation and Representation
#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
Using an API in a manner contrary to its intended use
API Abuse
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
@Test
voidtestCreatedContainerHasPlimsollLabel() {
Plimsoll p=new Plimsoll();
Stringid =p.docker.createSimpleContainer(TEST_IMAGE_NAME);
ContainerInfo ci=p.docker.inspectContainer(id);
assertNotNull(ci);
assertTrue(ci.config().labels().containsKey(DockerController.LABEL_ID));
assertTrue(p.docker.removeContainer(id));
}
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…
@Test
voidtestAllContainersListHasEntries() {
Plimsoll p=new Plimsoll();
Stringid =p.docker.createSimpleContainer(TEST_IMAGE_NAME);
assertNotNull(id);
List<Container> allc =p.docker.allContainerList();
assertTrue(allc.isEmpty()==false);
assertTrue(p.docker.removeContainer(id));
}
get("/test/v1/*" , (req, res) ->plimsoll.test_v1_request.handleRequest(req,res));
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..
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
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!
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”
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”
Content-Type: %{(#_='multipart/form-data').
(#_memberAccess=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS)
.
(@java.lang.Runtime@getRuntime().exec('curl
localhost:8000'))}
https://dzone.com/articles/will-it-pwn-cve-2017-5638-remote-code-
execution-in
Apache Struts
OGNL
If type contains “multipart/form-data’
try to parse it as form data
This fails and as part of the building an error message the
OGNL is evaluated…
#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
Errors
Errors related to error handling
Errors
private Properties loadConfig() {
Propertiesp= newProperties(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…
Errors
private Properties loadConfig() {
Propertiesp= newProperties(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 assuming that only
the errors you expect will
occur - such as
FileNotFoundException
Errors
private Properties loadConfig() {
Propertiesp= newProperties(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!
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
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.
Errors
Being to helpful can also be a problem.
public IHandlerloadHandler(String datatype) throws IOException {
StringclassName=handlers.get(datatype);
Class<IHandler> handlerClass;
try{
handlerClass = (Class<IHandler>) Class.forName(className);
return handlerClass.newInstance();
}catch (Exception e) {
throw new IOException("handler for type "+datatype+" of class "+className+" cannot beloaded");
}
}
Errors
What happens at runtime?
public IHandlerloadHandler(String datatype) throws IOException {
StringclassName=handlers.get(datatype);
Class<IHandler> handlerClass;
try{
handlerClass = (Class<IHandler>) Class.forName(className);
return handlerClass.newInstance();
}catch (Exception e) {
throw new IOException("handler for type "+datatype+" of class "+className+" cannot beloaded");
}
}
try {
IHandlerh=loadHandler("foo.data");
…
}
catch (IOException e) {
System.out.println(e.getMessage());
}
Errors
What errors might happen?
public IHandlerloadHandler(String datatype) throws IOException {
StringclassName=handlers.get(datatype);
Class<IHandler> handlerClass;
try{
handlerClass = (Class<IHandler>) Class.forName(className);
return handlerClass.newInstance();
}catch (Exception e) {
throw new IOException("handler for type "+datatype+" of class "+className+" cannot beloaded");
}
}
try {
IHandlerh=loadHandler("foo.data");
…
}
catch (IOException e) {
System.out.println(e.getMessage());
}
Errors
public IHandlerloadHandler(String datatype) throws IOException {
StringclassName=handlers.get(datatype);
Class<IHandler> handlerClass;
try{
handlerClass = (Class<IHandler>) Class.forName(className);
return handlerClass.newInstance();
}catch (Exception e) {
throw new IOException("handler for type "+datatype+" of class "+className+" cannot beloaded");
}
}
try {
IHandlerh=loadHandler("foo.data");
…
}
catch (IOException e) {
System.out.println(e.getMessage());
}
Handler for type foo.data of class null cannot be loaded
Handler for type foo.data of class com.acme.handler
cannot be loaded
What errors might happen?
Errors
public IHandlerloadHandler(String datatype) throws IOException {
StringclassName=handlers.get(datatype);
Class<IHandler> handlerClass;
try{
handlerClass = (Class<IHandler>) Class.forName(className);
return handlerClass.newInstance();
}catch (Exception e) {
throw new IOException("handler for type "+datatype+" of class "+className+" cannot beloaded");
}
}
try {
IHandlerh=loadHandler("java.ext.dirs");
…
}
catch (IOException e) {
System.out.println(e.getMessage());
}
Handler for type java.ext.dirs of 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 cannot be loaded
What errors might happen?
Quite often ‘handlers’
will be a Properties
object.backed by
System.getProperties so
you can use –D on the
command line
Errors
Driving code down error paths is a profitable exercise
for the attacker. Many Remote Code Execution
vulnerabilities occur due to code execution during
object instantiation etc – even if subsequently failing a
class cast or similar
Correct error
management
is the flipside
of correct
validation
#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
Security Features
Authentication, access control, confidentiality, cryptography, privilege management.
Security Features
“I don’t need any security as the
system is local…”
“I’ll add security later”
“I’m not sure what security means”
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
“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
“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
“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
“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.
“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.
Security Features
A few examples of vulnerable designs
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();
}
}
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?
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
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 StringgetConfigValue(String key) {
return config.getProperty(key);
}
private Properties loadConfig() {
Properties p=new Properties( System.getProperties() );
..
Poor confidentiality management
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 StringgetConfigValue(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 my system
properties are exposed..
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)
Security Features
Unsophisticated credentials management
That end up in your git repo…
Q: Can you easily remove password data from your
repo once committed?
Security Features
Unsophisticated credentials management
That end up in your git repo…
A: these people seem to think so..
TrustManager[] trustAllCerts = new TrustManager[]{
new X509TrustManager() {
public X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(
X509Certificate[] certs, String authType) {
}
public void checkServerTrusted(
X509Certificate[] certs, String authType) {
}
public boolean isClientTrusted( X509Certificate[] cert) {
return true;
}
public boolean isServerTrusted( X509Certificate[] cert) {
return true;
}
}}
Security Features
Deliberate weakening of security
protocols
Security Features
Defaulting to full access or running too much under privilege
method() {
AccessController.doPrivileged( new PrivilegedAction())
{
public Object run() {
// my app goes here
}
};
}
#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
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
Using the command line version
of docker (when I could use the
REST API)
Having a selection process for
items with a specific tag.
(Exposes all the docker data if
hacked)
Insecure API to read config
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 and 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
Soon as possible
#15 Reduce functionality to just the usecases needed.
No nice-to-haves !
#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.?
• 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
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
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.
Development
Processes and Tooling
DevCDCI
Pro
d
QA
UATBuil
d
Public Component
Repositories
Source
Control
DeployRepository
Developers
Where does ‘security’ belong?
DevCDCI
Pro
d
QA
UATBuil
d
Public Component
Repositories
Source
Control
DeployRepository
Developers
Most rely solely on
penetration testing the
end product
DevCDCI
Pro
d
QA
UATBuil
d
Public Component
Repositories
Source
Control
DeployRepository
Developers
Some have ‘policies’
about dependency
management
Developers
to
operations
to security
But its almost all ‘nag’ based
Struts vulnerability
announced
The breach
Breach
discovered.
New Struts and Spring
vulnerabilities.
12 months since
Equifax breach.
0
20,000
40,000
60,000
80,000
100,000
120,000
Mar-17 Apr-17 May-17 Jun-17 Jul-17 Aug-17 Sep-17 Oct-17 Nov-17 Dec-17 Jan-18 Feb-18 Mar-18
Total
Breach
disclosed.
80% SHOW POOR CYBER HYGIENE
Number of vulnerable Struts component downloads per month
Which isn’t working
DevCDCI
Pro
d
QA
UATBuild
Public Component
Repositories
Source Control DeployRepository
Developers
What do we do?
Solve your supply
chain problems
1 Solve your own
quality problems –
trust but verify
2 Create discipline
3
Know what you
run – List every
deployment
Test your
dependencies as
you would unit
test your code
Don’t hide
information –
SHARE IT
More help
snyk.ioAnalysis
Tools
snyk.io
www.sonarqube.org
Analysis
Tools
Analysis
Tools
find-sec-bugs.github.io
Analysis
Tools
Analysis
Tools
Splunk® Light www.splunk.com
Full-Feature Log Search and Analy
Gauntlt
BE MEAN TOYOUR CODEANDLIKEIT
gauntlt.org
Bdd style security testing
Testing
Tools
cwe.mitre.org
Coding
Practises
1. Input Validation and Representation
2. API Abuse
3. Security Features
4. Time and State
5. Error Handling
6. Code Quality
7. Encapsulation
* Environment
The Seven Pernicious Kingdoms
Secure
Coding
Guidelines
for
Java SE
http://www.oracle.com/technetwork/java/seccodeguide-139067.html
Secure by Design - Security Design Principles for the
Rest of Us
https://www.slideshare.net/EoinWoods1/secure-by-design-security-design-principles-
for-the-rest-of-us
Online
Guides
Online
Guides
https://www.owasp.org
Reducing Risk (Serialization)
@spoole167
https://www.ibm.com/developerworks/library/se-lookahead/
DevCDCI
Pro
d
QA
UATBuild
Public Component
Repositories
Source Control DeployRepository
Developers
Wrapup
The bad news
• Vulnerabilities are the gateway into the system
• Systems with vulnerabilities are easily found
• Everyone has vulnerabilities
• 2 days from publication to attack
• Exploits are easily found
• Developers don’t think about security
• Application design thinking suffers
• Development processes etc suffer
The good
news
Help is out there
Tooling to protect all parts of
your pipeline exist
Designing secure software
starts with an attitude of mind.
Security testing is not hard to
add.
Summary
Keep current.
Every vulnerability fix you apply is one less way in.
Learn more about secure coding
Compartmentalize. Separate data, code, access controls etc.
Just like bulkhead doors in a ship: ensure one compromise
doesn’t sink your boat.
Design for intrusion. Review you levels of ‘helpfulness’ and
flexibility and learn about Penetration Testing
Learn more about security tools & services
Understand that making your development life easier makes
the hackers job easier
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/

Java application security the hard way - a workshop for the serious developer

  • 1.
    Java application securitythe hard way - a workshop for the serious developer Devoxx UK 2018
  • 2.
    Outline • 9:30 -11:00 • 20: (SP) Intros & ‘The Economics of Cybercrime’ • 40: (SP) Bad Guy tactics – Discovery and Attack • 30: (SM) Community hacking… • 11:00 -11:30 break • 11:30 – 13:00 • 50: (SP) Application design – why you’re doing it wrong… • 30: (SM) Development Processes & tooling • 10: Wrap up
  • 3.
    Credits This workshop isa collaborative effort between IBM, Snyk and Sonatype Thanks especially to Ilkka Turunen from Sonatype
  • 4.
    About us Steve Poole DeveloperAdvocate, IBM @spoole167 @sjmaple Simon Maple Director of Developer Relations, Snyk
  • 5.
    This workshop is aboutJava 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
  • 6.
    The economics ofcybercrime
  • 7.
    In 2016 Cybercrimewas estimated to be worth 450 Billion Dollars @spoole167 Organized Cybercrime is the most profitable type of crime In 2016 The illicit drug trade was estimated to be worth 435 Billion Dollars
  • 8.
    Organized Cybercrime isthe most profitable type of crime • Guess which one has the least risk to the criminal ? • Guess which is growing the fastest ? • Guess which one is the hardest to prosecute ? • Guess which one is predicted to reach 2100 Billion Dollars by 2019? • Guess which one is predicted to reach 6000 Billion Dollars by 2021? @spoole167
  • 9.
    0 1000 2000 3000 4000 5000 6000 2013 2014 20152016 2017 2018 2019 2020 2021 Cybercrime Drug trade
  • 10.
    That’s about £600for every person on the planet
  • 11.
    Cyber attackers usevulnerabilities to get into your system And go through your system to another (and repeat) To steal your data To change your data To crash your systems Use your compute power
  • 12.
  • 13.
    So is this.Just two characters
  • 14.
    Vulnerabilities are almostalways simple there are no smoking guns Exploits are chaining together vulnerabilities https://www.flickr.com/photos/84744710@N06/
  • 15.
    “Common Vulnerabilities & Exposures” • https://cve.mitre.org •The Standard place find details about ‘CVEs’ • International cyber security community effort • Common naming convention and unique references. • Allows you to know when a problem is resolved in something you are using
  • 16.
  • 17.
    CVE-2016-0686 “Unspecified vulnerability inOracle Java SE 6u113, 7u99, and 8u77 and Java SE Embedded 8u77 allows remote attackers to affect confidentiality, integrity, and availability via vectors related to Serialization.” That’s all you will find about this fix
  • 18.
    Talking about thedetails of a fix or flaw in public is just like tweeting your credit card # and pin So we don’t. We give you information about the impact instead.
  • 19.
    Apache struts 2- the Equifax affair Attackers used Remote Code Execution to steal data over a long period CVE-2017-5638 The Jakarta Multipart parser in Apache Struts 2 2.3.x before 2.3.32 and 2.5.x before 2.5.10.1 has incorrect exception handling and error- message generation during file-upload attempts, which allows remote attackers to execute arbitrary commands via a crafted Content-Type, Content-Disposition, or Content-Length HTTP header, as exploited in the wild in March 2017 with a Content-Type header containing a #cmd= string.
  • 20.
    Large Scale Exploit March9 First ‘whoami’ is run AprMar May Jun Jul Aug Sept March 7 Apache Struts releases updated version to thwart vulnerability CVE-2017-5638 July 29 Breach is discovered by Equifax. Sept 7 A new strutcs RCE vulnerability is announced and fixed. CVE-2017-9805 Probe Crisis Management March 5 vulnerability and fixed
  • 21.
    Time to EXPLOIT?Source:Adapted from IBM X-Force / Analysis by Gartner Research (September 2016) Year of Date Reported 2006 2007 2008 2009 2010 2011 2012 2013 2104 2015 10 20 30 40 50 0 AverageDaystoExploit Average 45 15 2017
  • 22.
  • 23.
    Vulnerabilities are almostalways simple Exploits are chained together vulnerabilities Everyone has vulnerabilities Time to exploit is almost instant • Look for CVE’s at https://cve.mitre.org • Understanding the categorization and evaluation process is key to knowing how dangerous a vulnerability is • Ignoring critical updates is high risk Errors
  • 24.
  • 25.
    Here’s how itwork in practice • New vulnerability announced: “Remote Code Execution” types are the best • Start with “net fishing” – who’s vulnerable? Is there an exploit? The Jakarta Multipart parser in Apache Struts 2 2.3.x before 2.3.32 and 2.5.x before 2.5.10.1 has incorrect exception handling and error- message generation during file-upload attempts, which allows remote attackers to execute arbitrary commands via a crafted Content-Type, Content-Disposition, or Content-Length HTTP header, as exploited in the wild in March 2017 with a Content-Type header containing a #cmd= string. CVE-2017-5638
  • 26.
    Things we cando.. #1 : Search for know meta data identifiers for Apache Struts File types like ‘action’ or do’
  • 28.
  • 30.
    Things we cando.. #2 : Search for other vulnerabilities you might have.. What version of a server are you running?
  • 31.
  • 32.
    Pick the networktab Pick network tab
  • 33.
    Turn on recordingand refresh Turn on recording (red means on)
  • 34.
  • 35.
  • 36.
  • 37.
    Things we cando #3 Get more information about the target site
  • 38.
    Search for the ip addressof the site https://www.shodan.io
  • 40.
    Things we cando #4 Shodan.io lets us search for technology usage..
  • 43.
    Things we cando #5 How about looking for existing exploits?
  • 46.
    Things we cando #6 Use tools to run the exploits..
  • 48.
    Things we cando #7 Use other easily available tools.. https://www.wappalyzer.com/
  • 49.
  • 50.
  • 51.
  • 52.
    A bit more diggingin the headers Apache Server: 2.4.6 D3: 3.5.17 jQuery: 2.2.4 Adobe Experience Manager: 4.2.2 OS: Redhat Enterprise Linux ip address: 157.83.96.72 Physical location Twickenham Open ports: 80, 443 SSL certificate chains
  • 53.
  • 54.
    Apache Server 2.4.6 – released 22Jul 2013 https://www.cvedetails.com
  • 55.
    Your go… Check outyour servers here www.wappalyzer.com www.shodan.io Look at your headers etc using Chrome Developer tools Visit the cve site cve.mitre.org www.cvedetails.com Look for known vulnerabilities in your software snyk.io filetype:do Play with google and find some interesting targets filetype:action https://nvd.nist.gov/vuln/detail/CVE-2017-5638 Read about the information collated about a vulnerability
  • 56.
  • 57.
    We saw howmuch information is available about servers, software etc . How much sophisticated tooling is available in the open. How people are building exploits for vulnerabilities very quickly. After the break we’ll start to talk about what you can do to start to address the problems.
  • 58.
    Outline • 9:30 -11:00 • 20: (SP) Intros & ‘The Economics of Cybercrime’ • 40: (SP) Bad Guy tactics – Discovery and Attack • 30: (SM) Community hacking… • 11:00 -11:30 break • 11:30 – 13:00 • 50: (SP) Application design – why you’re doing it wrong… • 30: (SM) Development Processes • 10: Wrap up
  • 59.
    Break Read aboutJenkins vulnerability CVE-2017-1000353 Can you find a vulnerable server on shodan.io Hint – Jenkins has a header called X-Jenkins
  • 60.
    This section isintended you a taster for how you can design your software to be less vulnerable to attack
  • 61.
    Software design flawsare grouped into “7 Pernicious Kingdoms”
  • 62.
    A bit ofa 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
  • 63.
    In fact thereare more than 7 
  • 64.
    Seven Pernicious Kingdoms Security Features Time andState Errors Input Validation and Representation API Abuse Code Quality Encapsulation Environment
  • 65.
    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
  • 66.
    Section Flow Using areal scenario walk though some of the 7PK looking at code and thinking about design
  • 67.
    My scenario • I’mdeveloping a tool for Adopt OpenJDK • Make it easy for others to get the new drivers • Make it easy to try out the new Java versions with common app servers and user applications. • It’s designed to run locally but will eventually be hostable
  • 68.
  • 69.
  • 70.
    Problems caused bymetacharacters, alternate encodings and numeric representations. General security problems result from trusting input. Input Validation and Representation
  • 71.
    Input Validation andRepresentation Forms Input. Browser javascript code validates the form Send the data to the server over a websocket as JSON. Server turns JSON into Java object assuming it’s a valid PlimsollCommand object public class PlimsollCommand { public String type; public Object msg; } { ‘type’ : cmd_id , ‘msg’ : {} }
  • 72.
    Input Validation andRepresentation Forms Input. Browser javascript code validates the form Send the data to the server over a websocket as JSON. Server turns JSON into Java object assuming it’s a valid PlimsollCommand object public class PlimsollCommand { public String type; public Object msg; } Actually I expect a Map but Object is easier to use with the JSON parser { ‘type’ : cmd_id , ‘msg’ : {} }
  • 73.
    Input Validation andRepresentation My application only expects local war files to be loaded… { ‘type’ : ‘upload’ , ‘msg’ : { ‘war’ : ‘file://dir/app.war’ } } This example gets converted into java objects quite easily. Lets the user point me at their application on disk. What happens if the browser sends me this? { ‘type’ : ‘upload’ , ‘msg’ : { ‘war’ : ‘http://badserver.com/badapp.war’ } }
  • 74.
    Input Validation andRepresentation Forms Input. Browser javascript code validates the form Send the data to the server over a websocket as JSON. Server turns JSON into Java object assuming it’s a valid PlimsollCommand object public class PlimsollCommand { public String type; public Object msg; } What would happen if the JSON data was actually a list? { ‘type’ : cmd_id , ‘msg’ : [ ‘a’ , ‘bad’ , ‘thing’ ] }
  • 75.
    Input Validation andRepresentation Forms Input. Browser javascript code validates the form Send the data to the server over a websocket as JSON. Server turns JSON into Java object assuming it’s a valid PlimsollCommand object public class PlimsollCommand { public String type; public Object msg; } Pretty obviously you cannot ever trust what a client sends you. Ever. What would happen if the JSON data was actually a list?
  • 76.
    • Input froman end point is an obvious place to be cautious • Think of it like this… • Every API you write. Whether REST interface or a simple class defines a ‘contract’ with the caller. • If that contract is not explicit and enforced your code is vulnerable. • And it’s even more subtle than that… Input Validation and Representation “It is the callers responsibility”
  • 77.
    Browser Server Docker Daemon Remote repositories Local repositories WS Cmd line http InputValidation and Representation Adopt Server http My tool uses the docker command line interface to retrieve information and run containers “docker images” “docker run –it ubuntu /bin/bash”
  • 78.
    Input Validation andRepresentation public classDockerCommandLineDriver{ privatestaticfinalStringDEFAULT_EXEC ="/usr/local/bin/docker"; privateStringdocker; privatebooleanerror; privateFileoutputFile; privateListresults=newLinkedList(); staticenumCMD{ active,images,containers }; privatestaticfinalString[]cmds =newString[]{ "ps-a", "images","containerls -a"}; public DockerCommandLineDriver(){ this(DEFAULT_EXEC); } public DockerCommandLineDriver(Stringdriver){ docker= driver; outputFile= newFile("/tmp/docker.out"); }
  • 79.
    Input Validation andRepresentation public classDockerCommandLineDriver{ privatestaticfinalStringDEFAULT_EXEC ="/usr/local/bin/docker"; privateStringdocker; privatebooleanerror; privateFileoutputFile; privateListresults=newLinkedList(); staticenumCMD{ active,images,containers }; privatestaticfinalString[]cmds =newString[]{ "ps-a", "images","containerls -a"}; public DockerCommandLineDriver(){ this(DEFAULT_EXEC); } public DockerCommandLineDriver(Stringdriver){ docker= driver; outputFile= newFile("/tmp/docker.out"); } DockerCommandLineDrivercld = newDockerCommandLineDriver(); … Listl= cld.run(CMD.active); if(cld.hasError()==false){ System.out.println(l); }
  • 80.
    Input Validation andRepresentation DockerCommandLineDrivercld = newDockerCommandLineDriver(); … Listl= cld.run(CMD.active); if(cld.hasError()==false){ System.out.println(l); } public Listrun(CMDcmd) { Stringcmdline =cmds[cmd.ordinal()]; cmdline =docker +""+cmdline; String[]parts=cmdline.split(" "); ProcessBuilder pb=new ProcessBuilder(parts); pb.redirectErrorStream(true); pb.redirectOutput(ProcessBuilder.Redirect.to(outputFile)); try{ Process p=pb.start(); intresult =p.waitFor(); error=result !=0; } catch (IOException | InterruptedException e) { error=true; } return saveResults(); }
  • 81.
    What’s wrong withthis code? public classDockerCommandLineDriver{ privatestaticfinalStringDEFAULT_EXEC ="/usr/local/bin/docker"; privateStringdocker; privatebooleanerror; privateFileoutputFile; privateListresults=newLinkedList(); staticenumCMD{ active,images,containers }; privatestaticfinalString[]cmds =newString[]{ "ps-a", "images","containerls -a"}; public DockerCommandLineDriver(){ this(DEFAULT_EXEC); } public DockerCommandLineDriver(Stringdriver){ docker= driver; outputFile= newFile("/tmp/docker.out"); } Input Validation and Representation
  • 82.
    This field isnever 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! public classDockerCommandLineDriver{ privatestaticfinalStringDEFAULT_EXEC ="/usr/local/bin/docker"; privateStringdocker; privatebooleanerror; privateFileoutputFile; privateListresults=newLinkedList(); staticenumCMD{ active,images,containers }; privatestaticfinalString[]cmds =newString[]{ "ps-a", "images","containerls -a"}; public DockerCommandLineDriver(){ this(DEFAULT_EXEC); } public DockerCommandLineDriver(Stringdriver){ docker= driver; outputFile= newFile("/tmp/docker.out"); } “docker –version” Input Validation and Representation
  • 83.
    Even if thefield was validated during construction it can still be changed afterwards. Relying on constructor validation only is also poor practise. public classDockerCommandLineDriver{ privatestaticfinalStringDEFAULT_EXEC ="/usr/local/bin/docker"; privateStringdocker; privatebooleanerror; privateFileoutputFile; privateListresults=newLinkedList(); staticenumCMD{ active,images,containers }; privatestaticfinalString[]cmds =newString[]{ "ps-a", "images","containerls -a"}; public DockerCommandLineDriver(){ this(DEFAULT_EXEC); } public DockerCommandLineDriver(Stringdriver){ docker= driver; outputFile= newFile("/tmp/docker.out"); } (Re)validate just before usage Input Validation and Representation
  • 84.
    What about thisfield? Set to “/tmp/docker.out” ? public classDockerCommandLineDriver{ privatestaticfinalStringDEFAULT_EXEC ="/usr/local/bin/docker"; privateStringdocker; privatebooleanerror; privateFileoutputFile; privateListresults=newLinkedList(); staticenumCMD{ active,images,containers }; privatestaticfinalString[]cmds =newString[]{ "ps-a", "images","containerls -a"}; public DockerCommandLineDriver(){ this(DEFAULT_EXEC); } public DockerCommandLineDriver(Stringdriver){ docker= driver; outputFile= newFile("/tmp/docker.out"); } Input Validation and Representation
  • 85.
    With serialisation vulnerabilitiesI 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 Remember constructors are not called during deserialization. The data is simply inserted. public classDockerCommandLineDriver{ privatestaticfinalStringDEFAULT_EXEC ="/usr/local/bin/docker"; privateStringdocker; privatebooleanerror; privateFileoutputFile; privateListresults=newLinkedList(); staticenumCMD{ active,images,containers }; privatestaticfinalString[]cmds =newString[]{ "ps-a", "images","containerls -a"}; public DockerCommandLineDriver(){ this(DEFAULT_EXEC); } public DockerCommandLineDriver(Stringdriver){ docker= driver; outputFile= newFile("/tmp/docker.out"); } Input Validation and Representation
  • 86.
    #1: all datareceived 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
  • 87.
    Using an APIin a manner contrary to its intended use API Abuse
  • 88.
    API Abuse My tooltags 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 @Test voidtestCreatedContainerHasPlimsollLabel() { Plimsoll p=new Plimsoll(); Stringid =p.docker.createSimpleContainer(TEST_IMAGE_NAME); ContainerInfo ci=p.docker.inspectContainer(id); assertNotNull(ci); assertTrue(ci.config().labels().containsKey(DockerController.LABEL_ID)); assertTrue(p.docker.removeContainer(id)); }
  • 89.
    API Abuse But Iwant 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… @Test voidtestAllContainersListHasEntries() { Plimsoll p=new Plimsoll(); Stringid =p.docker.createSimpleContainer(TEST_IMAGE_NAME); assertNotNull(id); List<Container> allc =p.docker.allContainerList(); assertTrue(allc.isEmpty()==false); assertTrue(p.docker.removeContainer(id)); } get("/test/v1/*" , (req, res) ->plimsoll.test_v1_request.handleRequest(req,res));
  • 90.
    API Abuse A commonvulnerability 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..
  • 91.
    API Abuse My toolallows 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
  • 92.
    API Abuse The codevalidates the entries as being individually correct..  JVM=Hotspot  AppServer=Tomcat  AppVersion=9.4.9 But not that the combinations are valid!
  • 93.
    API Abuse My codealso 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”
  • 94.
    API Abuse My codealso 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”
  • 95.
  • 96.
    #2 Never givecontrol 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
  • 97.
  • 98.
    Errors private Properties loadConfig(){ Propertiesp= newProperties(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…
  • 99.
    Errors private Properties loadConfig(){ Propertiesp= newProperties(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 assuming that only the errors you expect will occur - such as FileNotFoundException
  • 100.
    Errors private Properties loadConfig(){ Propertiesp= newProperties(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!
  • 101.
    Errors Catching or throwingexceptions 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
  • 102.
    Errors Catching or throwingexceptions 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.
  • 103.
    Errors Being to helpfulcan also be a problem. public IHandlerloadHandler(String datatype) throws IOException { StringclassName=handlers.get(datatype); Class<IHandler> handlerClass; try{ handlerClass = (Class<IHandler>) Class.forName(className); return handlerClass.newInstance(); }catch (Exception e) { throw new IOException("handler for type "+datatype+" of class "+className+" cannot beloaded"); } }
  • 104.
    Errors What happens atruntime? public IHandlerloadHandler(String datatype) throws IOException { StringclassName=handlers.get(datatype); Class<IHandler> handlerClass; try{ handlerClass = (Class<IHandler>) Class.forName(className); return handlerClass.newInstance(); }catch (Exception e) { throw new IOException("handler for type "+datatype+" of class "+className+" cannot beloaded"); } } try { IHandlerh=loadHandler("foo.data"); … } catch (IOException e) { System.out.println(e.getMessage()); }
  • 105.
    Errors What errors mighthappen? public IHandlerloadHandler(String datatype) throws IOException { StringclassName=handlers.get(datatype); Class<IHandler> handlerClass; try{ handlerClass = (Class<IHandler>) Class.forName(className); return handlerClass.newInstance(); }catch (Exception e) { throw new IOException("handler for type "+datatype+" of class "+className+" cannot beloaded"); } } try { IHandlerh=loadHandler("foo.data"); … } catch (IOException e) { System.out.println(e.getMessage()); }
  • 106.
    Errors public IHandlerloadHandler(String datatype)throws IOException { StringclassName=handlers.get(datatype); Class<IHandler> handlerClass; try{ handlerClass = (Class<IHandler>) Class.forName(className); return handlerClass.newInstance(); }catch (Exception e) { throw new IOException("handler for type "+datatype+" of class "+className+" cannot beloaded"); } } try { IHandlerh=loadHandler("foo.data"); … } catch (IOException e) { System.out.println(e.getMessage()); } Handler for type foo.data of class null cannot be loaded Handler for type foo.data of class com.acme.handler cannot be loaded What errors might happen?
  • 107.
    Errors public IHandlerloadHandler(String datatype)throws IOException { StringclassName=handlers.get(datatype); Class<IHandler> handlerClass; try{ handlerClass = (Class<IHandler>) Class.forName(className); return handlerClass.newInstance(); }catch (Exception e) { throw new IOException("handler for type "+datatype+" of class "+className+" cannot beloaded"); } } try { IHandlerh=loadHandler("java.ext.dirs"); … } catch (IOException e) { System.out.println(e.getMessage()); } Handler for type java.ext.dirs of 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 cannot be loaded What errors might happen? Quite often ‘handlers’ will be a Properties object.backed by System.getProperties so you can use –D on the command line
  • 108.
    Errors Driving code downerror paths is a profitable exercise for the attacker. Many Remote Code Execution vulnerabilities occur due to code execution during object instantiation etc – even if subsequently failing a class cast or similar Correct error management is the flipside of correct validation
  • 109.
    #3 Error pathsare 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
  • 110.
    Security Features Authentication, accesscontrol, confidentiality, cryptography, privilege management.
  • 111.
    Security Features “I don’tneed any security as the system is local…” “I’ll add security later” “I’m not sure what security means”
  • 112.
    Security Features Many vulnerabilitiescome 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
  • 113.
    “I don’t needany security as the system is local…” Security Features Browser Server Docker Daemon Remote repositories Local repositories WS Cmd line http Adopt Server http
  • 114.
    “I don’t needany 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
  • 115.
    “I don’t needany 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
  • 116.
    “I don’t needany 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.
  • 117.
    “I don’t needany 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.
  • 118.
    Security Features A fewexamples of vulnerable designs
  • 119.
    Security Features Trusting theend 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(); } }
  • 120.
    Security Features Trusting theend 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?
  • 121.
    Security Features Trusting theend 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
  • 122.
    Security Features My codehas a endpoint that allows the client to read the config get: ”/api/v1/config/<key_name>”. Returns json : { “key”: key_name , “value” : value } public StringgetConfigValue(String key) { return config.getProperty(key); } private Properties loadConfig() { Properties p=new Properties( System.getProperties() ); .. Poor confidentiality management
  • 123.
    Security Features My codehas a endpoint that allows the client to read the config get: ”/api/v1/config/<key_name>”. Returns json : { “key”: key_name , “value” : value } public StringgetConfigValue(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 my system properties are exposed..
  • 124.
    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)
  • 125.
    Security Features Unsophisticated credentialsmanagement That end up in your git repo… Q: Can you easily remove password data from your repo once committed?
  • 126.
    Security Features Unsophisticated credentialsmanagement That end up in your git repo… A: these people seem to think so..
  • 127.
    TrustManager[] trustAllCerts =new TrustManager[]{ new X509TrustManager() { public X509Certificate[] getAcceptedIssuers() { return null; } public void checkClientTrusted( X509Certificate[] certs, String authType) { } public void checkServerTrusted( X509Certificate[] certs, String authType) { } public boolean isClientTrusted( X509Certificate[] cert) { return true; } public boolean isServerTrusted( X509Certificate[] cert) { return true; } }} Security Features Deliberate weakening of security protocols
  • 128.
    Security Features Defaulting tofull access or running too much under privilege method() { AccessController.doPrivileged( new PrivilegedAction()) { public Object run() { // my app goes here } }; }
  • 129.
    #5 Access controlsas 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
  • 130.
    This is straightforward Ifyour 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
  • 131.
    Using the commandline version of docker (when I could use the REST API) Having a selection process for items with a specific tag. (Exposes all the docker data if hacked) Insecure API to read config 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 and 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 Soon as possible #15 Reduce functionality to just the usecases needed. No nice-to-haves !
  • 132.
    #16 control ofstate 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.?
  • 133.
    • All theparts 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
  • 134.
    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
  • 135.
    Phew. • So manythings ways your application can be vulnerable. • Security is not something you add after. It’s always a part of your design thinking.
  • 136.
  • 137.
  • 138.
  • 139.
  • 140.
  • 141.
    Struts vulnerability announced The breach Breach discovered. NewStruts and Spring vulnerabilities. 12 months since Equifax breach. 0 20,000 40,000 60,000 80,000 100,000 120,000 Mar-17 Apr-17 May-17 Jun-17 Jul-17 Aug-17 Sep-17 Oct-17 Nov-17 Dec-17 Jan-18 Feb-18 Mar-18 Total Breach disclosed. 80% SHOW POOR CYBER HYGIENE Number of vulnerable Struts component downloads per month Which isn’t working
  • 142.
  • 143.
    Solve your supply chainproblems 1 Solve your own quality problems – trust but verify 2 Create discipline 3
  • 144.
    Know what you run– List every deployment
  • 145.
    Test your dependencies as youwould unit test your code
  • 146.
  • 147.
  • 148.
  • 149.
  • 150.
  • 151.
  • 152.
  • 153.
    Gauntlt BE MEAN TOYOURCODEANDLIKEIT gauntlt.org Bdd style security testing Testing Tools
  • 154.
  • 156.
    1. Input Validationand Representation 2. API Abuse 3. Security Features 4. Time and State 5. Error Handling 6. Code Quality 7. Encapsulation * Environment The Seven Pernicious Kingdoms
  • 157.
  • 158.
    Secure by Design- Security Design Principles for the Rest of Us https://www.slideshare.net/EoinWoods1/secure-by-design-security-design-principles- for-the-rest-of-us Online Guides
  • 159.
  • 160.
  • 161.
  • 162.
  • 163.
    The bad news •Vulnerabilities are the gateway into the system • Systems with vulnerabilities are easily found • Everyone has vulnerabilities • 2 days from publication to attack • Exploits are easily found • Developers don’t think about security • Application design thinking suffers • Development processes etc suffer
  • 164.
    The good news Help isout there Tooling to protect all parts of your pipeline exist Designing secure software starts with an attitude of mind. Security testing is not hard to add.
  • 165.
    Summary Keep current. Every vulnerabilityfix you apply is one less way in. Learn more about secure coding Compartmentalize. Separate data, code, access controls etc. Just like bulkhead doors in a ship: ensure one compromise doesn’t sink your boat. Design for intrusion. Review you levels of ‘helpfulness’ and flexibility and learn about Penetration Testing Learn more about security tools & services Understand that making your development life easier makes the hackers job easier
  • 166.
    There are badguys out there and your application is at risk Don’t make it worse by ignoring the problem https://www.flickr.com/photos/koolmann/

Editor's Notes

  • #138 Run through to CI / CD relatively quickly. 2min max. When there, focus on discussing * ‘what happens when we introduce the questions of ‘what about security vulnerabilities?’ ‘What about licensing?’ Most companies solve these manually. Takes long time. Ask the attendees how they deal with it? When you know, start explaining we believe these should be automated throughout the SLCD instead of being at the very beginning or very end. Reveal each label, discuss briefly implications BEGIN DEMO FLOW. Stop after each major theme briefly for questiosn IDE Policy Jenkins / Bamboo REPORT – Vulnerabilities – Licensing – important to know what persona to know what to focus on here JIRA – DASHBOARD AT THE END OF THE DEMO – ASK FOR THEIR IMPRESSIONS “And that’s the end of the demo. What do you think, could this be useful?” => Helps set the stage for value affirmation and future next steps
  • #139 Run through to CI / CD relatively quickly. 2min max. When there, focus on discussing * ‘what happens when we introduce the questions of ‘what about security vulnerabilities?’ ‘What about licensing?’ Most companies solve these manually. Takes long time. Ask the attendees how they deal with it? When you know, start explaining we believe these should be automated throughout the SLCD instead of being at the very beginning or very end. Reveal each label, discuss briefly implications BEGIN DEMO FLOW. Stop after each major theme briefly for questiosn IDE Policy Jenkins / Bamboo REPORT – Vulnerabilities – Licensing – important to know what persona to know what to focus on here JIRA – DASHBOARD AT THE END OF THE DEMO – ASK FOR THEIR IMPRESSIONS “And that’s the end of the demo. What do you think, could this be useful?” => Helps set the stage for value affirmation and future next steps
  • #140 Run through to CI / CD relatively quickly. 2min max. When there, focus on discussing * ‘what happens when we introduce the questions of ‘what about security vulnerabilities?’ ‘What about licensing?’ Most companies solve these manually. Takes long time. Ask the attendees how they deal with it? When you know, start explaining we believe these should be automated throughout the SLCD instead of being at the very beginning or very end. Reveal each label, discuss briefly implications BEGIN DEMO FLOW. Stop after each major theme briefly for questiosn IDE Policy Jenkins / Bamboo REPORT – Vulnerabilities – Licensing – important to know what persona to know what to focus on here JIRA – DASHBOARD AT THE END OF THE DEMO – ASK FOR THEIR IMPRESSIONS “And that’s the end of the demo. What do you think, could this be useful?” => Helps set the stage for value affirmation and future next steps
  • #143 Run through to CI / CD relatively quickly. 2min max. When there, focus on discussing * ‘what happens when we introduce the questions of ‘what about security vulnerabilities?’ ‘What about licensing?’ Most companies solve these manually. Takes long time. Ask the attendees how they deal with it? When you know, start explaining we believe these should be automated throughout the SLCD instead of being at the very beginning or very end. Reveal each label, discuss briefly implications BEGIN DEMO FLOW. Stop after each major theme briefly for questiosn IDE Policy Jenkins / Bamboo REPORT – Vulnerabilities – Licensing – important to know what persona to know what to focus on here JIRA – DASHBOARD AT THE END OF THE DEMO – ASK FOR THEIR IMPRESSIONS “And that’s the end of the demo. What do you think, could this be useful?” => Helps set the stage for value affirmation and future next steps
  • #162 Run through to CI / CD relatively quickly. 2min max. When there, focus on discussing * ‘what happens when we introduce the questions of ‘what about security vulnerabilities?’ ‘What about licensing?’ Most companies solve these manually. Takes long time. Ask the attendees how they deal with it? When you know, start explaining we believe these should be automated throughout the SLCD instead of being at the very beginning or very end. Reveal each label, discuss briefly implications BEGIN DEMO FLOW. Stop after each major theme briefly for questiosn IDE Policy Jenkins / Bamboo REPORT – Vulnerabilities – Licensing – important to know what persona to know what to focus on here JIRA – DASHBOARD AT THE END OF THE DEMO – ASK FOR THEIR IMPRESSIONS “And that’s the end of the demo. What do you think, could this be useful?” => Helps set the stage for value affirmation and future next steps