Speaking at OWASP NZ Day 2016 was certainly quite an experience. Prior to it I had only really spoken to local user groups: 30-50 people max – so being thrown in front of 600 pretty clued up people was, as some would say, akin to being thrown into the deep end. Sadly, I remain quite disappointed that I didn’t manage to catch many of the afternoon talks due to having a bright idea of taking the 6:30am flight to Auckland and subsequently falling asleep in my hotel room during the lunch break. However, what I did manage to see made one thing very clear: the only way a higher standard of security can be produced by your developers is by working alongside them as opposed to taking the stance of a dictator – shooting down their code, questioning their competency and generally doing anything that makes it clear you’re the boss.

In this post I’ll provide a recap on the main content of my talk: the ideas and solutions behind making security a core focal point of your development with minimal disruption to standard processes.

bloody agile…

One commonly observed challenge of the agile methodology is the serious time constraints it imposes. Some may see this as a strength, as it promotes the concept of regular deliveries and forces developers to write code more efficiently. In saying that, it must be realised that efficient code != robust code… so are the time ‘savings’ really worth it if you’re knowingly deploying risks? Or, perhaps those involved in the crime that is devop’s don’t even see the risk…

Anyway, those of us who work in the realm of security – quite fairly – find it incomprehensible that a job can be rushed and still done to an acceptable standard. In fact, we see first-hand most days that agile more often than not leads to poor quality code being churned out, and security being left in the hands of frameworks with little attention paid as to whether or not the frameworks actually provide a secure implementation of their functions.

The question then becomes, how can security be baked into an agile development program? Well, it can be through a few tasks:

  • Risk Assessment:  Developers need to be aware of what risks their software may face.
  • Risk Education: They must understand what those risks imply.
  • Development Education: With knowledge of what risks their software faces, they must know how to mitigate the risks.
  • Development Verification: The mitigation’s must be effective.

In a recent post I demonstrated my FooBlog project, which takes care of both risk education and development education. HackMe’s are very beneficial for education programs as, for the most part, developers are very hands on people who learn more effectively through doing rather than being spoken to. On top of FooBlog there are two more projects that work together to deliver serious value to developers:

  • Security Knowledge Framework.
  • Automated Security Testing.

 

security knowledge framework

The Security Knowledge Framework (SKF), an official OWASP project authored by Glenn ten Cate and Riccardo ten Cate, is hands-down one of the most brilliant tools that can be introduced into the arsenal of development teams who are concerned about security. It takes care of risk assessment, risk education and development education – all in one single, slick Python Flask web application.

Your typical development project may make use of SKF as follows:

  1. Outline the functionality developed in each sprint.
  2. Create a unique risk knowledge base for each sprint that will inform developers of the risks that will need to be considered and how to mitigate them.
  3. Use the code examples (either for C# or PHP) to assist in mitigating the risks.
  4. Produce a checklist for the entire project.

SKF uses the OWASP Application Security Verification Standard (ASVS) to structure it’s standards. The standards in SKF map 1:1 with the official ASVS standard and are updated whenever a change to the standard is made. In my company the ASVS standard has been used since it’s inception, so SKF has integrated into our processes with minimal effort. The standard is split into 19 categories, ranging from architecture to cryptography at rest, and each category has anywhere up to 32 criteria attached to it. Each criteria is allocated either level 1, 2 or 3 – level 3 being the most complex. In practice it must be ensured that each criteria is met and tested at certain points in a project – so you could require level 1 to be met for a pilot release that will handle dummy data, and level 3 for a UAT or production release that will handle data of a sensitive nature. To define what criteria of the standard the functionality developed in a particular sprint must meet, and track your progress in meeting that overall, you can use SKF.

SKF, as noted above, is a Python Flask application. Whilst you can spin it up on your desktop, if it is to be used by your wider company it’s better suited deployed behind Apache using WSGI. Below is the rough install process I used (it assumes you’ve already loaded a signed certificate and key onto the server into /etc/ssl):

Disable IPv6:

net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
net.ipv6.conf.lo.disable_ipv6 = 1

Install dependencies:

apt-get update
apt-get install –yes git apache2 libapache2-mod-wsgi sqlite3 lib32z1-dev python-dev libxml2-dev libxslt-dev libffi-dev libssl-dev python-pip
a2enmod wsgi
pip install https://github.com/mitsuhiko/flask/tarball/master owasp-skf

Create the directory structure and pull down the latest build of SKF:

mkdir /owaspskf
cd /owaspskf
git clone https://github.com/blabla1337/skf-flask.git
cd skf-flask/skf
sed -i “s/, ssl_context=’adhoc’//” skf.py
touch skf.wsgi

Into skf.wsgi enter:

import sys, os
sys.path.insert (0,’/owaspskf/skf-flask/skf’)
os.chdir(“/owaspskf/skf-flask/skf”)
from skf import app as application

Enter the Apache directory structure:

cd /etc/apache2

Comment out listen directives in /etc/apache2/ports.conf

To /etc/apache2/mods-available/ssl.conf add:

SSLCipherSuite EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH
SSLHonorCipherOrder on
SSLProtocol All -SSLv2 -SSLv3
SSLCompression off

Edit /etc/apache2/conf-available/security.conf:

ServerTokens Prod
ServerSignature Off

Also add:

Header always set Strict-Transport-Security “max-age=31536000; includeSubdomains”
Header set X-XSS-Protection “1; mode=block”
Header always append X-Frame-Options SAMEORIGIN
Header set X-Content-Type-Options nosniff

Create the SKF virtual host config:

cd sites-available
touch skf.conf

Into skf.conf enter:

WSGIRestrictStdout Off
Listen 443

WSGIDaemonProcess skf user=www-data group=www-data threads=5
WSGIScriptAlias / /owaspskf/skf-flask/skf/skf.wsgi
SSLEngine on
SSLCertificateFile /etc/ssl/certs/skf.pem
SSLCertificateKeyFile /etc/ssl/private/skf.key
SSLCertificateChainFile /etc/ssl/certs/skf_chain.pem

WSGIProcessGroup skf
WSGIApplicationGroup %{GLOBAL}
Order deny,allow
Allow from all
 Require all granted

Enable the site:

a2dissite 000-default.conf
a2ensite skf.conf

Set permissions on the SKF directories:

chmod +x /owaspskf/skf-flask/skf/skf.py
chown -R www-data:www-data /owaspskf/skf-flask

Edit /etc/apache2/mods-enabled/wsgi.conf and add between the tags:
SetHandler wsgi-script

# Deny access to compiled binaries
# You should not serve these to anyone

Order Deny,Allow
Deny from all

Enable the SSL module and restart Apache:

a2enmod ssl
a2enmod headers
service apache2 restart

For my host I provisioned an Xubuntu 14.04 VM with 1 vCPU, 2GB memory and a single 20GB disk. It copes with ~5 users on it at most times of the day.

If running SKF behind a proxy I’d recommend either explicitly defining the proxy in the skf.py file, or using urllib. Changes in blue below:

#1:
import os, markdown, datetime, string, base64, re, sys, re, requests, mimetypes, smtplib, urllib

#2:
r = requests.get(“http://raw.githubusercontent.com/blabla1337/skf-flask/master/setup.py”, proxies=urllib.getproxies())

or

#1:
bcrypt = Bcrypt(app)

http_proxy = “your proxy”
https_proxy = “your proxy”
proxyDict = {
    “http” : http_proxy,
    “https” : https_proxy
}

#2:
r = requests.get(“http://raw.githubusercontent.com/blabla1337/skf-flask/master/setup.py”, proxies=proxyDict)

The result? Try for yourself on the demo site!

 

automated security testing

Another great OWASP project is the renowned intercepting proxy Zed Attack Proxy (ZAP). One relatively unknown feature of ZAP is the API it offers. The API allows you to do most things that you could in a GUI session:

  • Configure targets.
  • Define the context.
  • Spider a target.
  • Passive scan a target.
  • Active scan a target.

However, ZAP alone cannot be treated as an intelligent tester – it requires a little guidance. To provide this guidance Selenium Webdriver can be used to execute actions that ZAP will later use to derive it’s own tests from. As an example, for FooBlog I use it to log in, submit a comment on a post and then submit a review of a merchandise item. ZAP is then able to log in (and the context defines this as out of scope for active scans, so not to accidentally log the session out), fuzz the comment function and then fuzz the review function. Tying this all together is a script I’ve developed known as electrode, and to compliment it (as I haven’t had much sucess with ZAP discovering SQL Injection vulnerabilities) sqlmap can assess select pages for SQL injection vulnerabilities and the OWASP Dependency Check plugin can ascertain whether there are any CVE listed vulnerabilities for the project’s dependencies.

All tests can be defined in the configuration of a project in Jenkins:

note the sqlmap syntax

So, whenever you run a build you can develop a baseline level of confidence that your project won’t be hit by script kiddies and the likes.

The electrode Python script requires a number of variables to be configured prior to testing, e.g.

  • protocol: http or https.
  • target: The target of your application.
  • pagesToExclude: A string array of pages to be excluded in the scan.
  • username: Username to use for login.
  • password: Password to use for login.
  • loginUrl: URL of the login page.
  • loggedInElement: ID of an element that will be present once logged in.
  • usernameText: ID of the username textbox.
  • passwordText: ID of the password textbox.
  • loginButton: ID of the button to be pressed for login.
  • loginButtonIsLinkbutton: Is the button to be pressed an ASP.NET Linkbutton? True or False. A Linkbutton is interacted with differently by Selenium.
  • zap_url: ip:port of the ZAP listener.

Tests are to be added to the tests object array. Syntax is as follows:

tests.append(Test(‘description’,’url’,{‘form ID:’ ‘text’,’form ID:’ ‘text’}, {‘submit button ID’: ‘is ASP.NET linkbutton (True/False)’})

For example:

tests.append(Test(‘Search Test’, ‘https://example.com‘, {‘searchText’: ‘espresso‘}, {‘submitButton‘: True}))

This will:

  1. Browse to https://example.com
  2. Enter ‘espresso’ into the textbox with ID ‘searchText’.
  3. Click on the ASP.NET Linkbutton with ID ‘submitButton’.

Another example is:

tests.append(Test(‘Search Test‘, ‘https://example.com/foo?id=1‘, {‘nameText‘: ‘Bob Dole‘,’commentText‘: ‘An example.‘}, {‘submitButton‘: False}))

This will:

  1. Browse to https://example.com/foo?id=1
  2. Enter ‘Bob Dole’ into the textbox with ID ‘nameText’, and ‘An example.’ into the textbox with ID ‘commentText’.
  3. Click on the regular button with ID ‘submitButton’.

Update (13/8/16): The latest build of Electrode uses an external configuration file and is far more robust. It does, however, have the same overall functionality. You can find the source code here.

Following a successful build, reports will be produced for the dependency check, electrode scan and sqlmap:

 

You can find the source code and documentation for electrode on my Bitbucket.

 

summary

As illustrated above, ensuring that security remains a core focal point of development teams who practice the agile development methodology can be achieved with relatively little disruption to standard processes. Based on my own experiences I feel that many developers want to produce robust, secure products… they just lack the knowledge on how to do so, and/or – at present – feel so resource constrained that they believe they can’t afford the time to exercise secure development practices. Typically it has been a case of ‘best endeavours’ during development and crossing ones fingers when the time comes to a pre-production pentest.

To summarise my suggestions:

  •  SKF: This web application gives developers a way of easily determining what risks they need to be aware of and how to combat them.
  • Continuous Security Testing: Integrating some basic security testing into continuous integration picks up on any obvious mistakes that may have been made by developers.

Of course, however, you cannot rely soley on these two points to give you sufficient assurance that your development is completely free of vulnerabilities. Until such time as AI surpasses the level of a trained security consultant, pentesting will remain an essential, manual task.

2 thoughts on “building stronger walls

  1. Re your OWASP NZ Day talk. You did really well Chris, your talk was informative, interesting, you held the audiences attention and your speaking style appeared to be calm and confident. It always helps when you know your topic… as you do. As the OWASP NZ chapter leader that helped to organise the con, I can confidently say your talk was one of the highlights of the conference and I'm looking forward to your next one!

    Good points discussed in this post. There's a post I wrote a couple of years ago along these lines of Agile vs Quality and how to combine them (http://blog.binarymist.net/2014/01/25/essentials-for-creating-and-maintaining-a-high-performance-development-team/).

    Re the OWASP ZAP regression testing: Good to see some discussion on this, as the ZAP API is a very powerful and useful tool, providing QA security regression for a very small price tag ($0 with a little effort to train ZAP). I did a POC on this and it's now part of NodeGoat. Check it out over here (https://github.com/binarymist/NodeGoat/wiki/Security-Regression-Testing-with-Zap-API).

    Excellent Post!

    Like

  2. Some more thoughts on this:

    Re: “One commonly observed challenge of the agile methodology is the serious time constraints it imposes.” Agile actually doesn't impose any time constraint. The time constraint is created by The Team. If we're talking Scrum, Sprints are a defined length of time (1 to 4 weeks usually), but consistently the same length. Agile only imposes the time constraints that the “professionals” (team members) pull on them selves. This is decided in Sprint Planning Topic One. The “professionals” have a tendency to under estimate how long tasks will take. This is why we often see them under pressure, it's self inflicted. If they are under pressure for any other reason, then what we think is Scrum is not Scrum. The team members are always the ones that decide how much to pull into each Sprint. A lot of it is due to peer pressure. In sprint planning we have a team of developers. No one wants to stand out as the developer estimating the largest time spans.

    Re: “Some may see this as a strength, as it promotes the concept of regular deliveries and forces developers to write code more efficiently”. It is a strength which ever way you look at it, if it doesn't appear that way, then Scrum is not working as it should be (by the book). No one or thing forces the developers other than themselves. This comes down to their own estimations. If they are struggling, they only have themselves to blame. They alone decide how much they could get through, and as the “increment” is just a “forecast”. The Development Team members decide whether they want to make their forecast or not. The pressure applied is only applied by themselves. No buts about this.

    Re: “efficient code != robust code”. Both efficient code and robust code are estimable. If a Scrum team is delivering a defective increment, the increment is not Done (it does not meet the definition of done), which means The Team did not meet their forecast. Which means The Team is failing, not Scrum. As the Scrum guide says “Each Increment is additive to all prior Increments and thoroughly tested, ensuring that all Increments work together. As Scrum Teams mature, it is expected that their definitions of “Done” will expand to include more stringent criteria for higher quality.”. So… if the quality is not there, then we have the problem with “code monkey” as discussed in the previous link I posted. The problem is the team members, not the process framework “Scrum”.

    You have to look deeper than Agile. Agile is not the problem. The people are. As a friend we both know likes to say… “If you can't change the people, change the people.”

    The root cause of what you're witnessing here is developers that under estimate tasks. Why? Because they are not wired to think about quality, and even more so, security. Security is just a form of quality. All this quality stuff gets in the way when you're trying to pump code out. What's needed then?

    1) Education for them
    2) Desire to be a professional developer (that's right, if you're not taking quality and thus security seriously, you're not a professional, you're a code monkey… sorry)
    3) At least one professional in the team that has great people skills, is an excellent developer and is bent on quality, and that means security also. AKA quality (with strong security focus) champion.
    4) Probably some others, can't think of right now though.

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

w

Connecting to %s