SSDLC Quick Wins

Securing the software (development) lifecycle of a large organization will usually not happen overnight, especially not if you have to start very much at the beginning.

It’s therefore vital to focus on quick wins first – measures that are effective and easy to implement at the same time. This is not only important from a risk perspective but also to archive quickly visible successes of your initiative and to show its value to your organization. Also, not everybody is able to run a large-scale application security program, implementing quick wins should usually be always possible though.

Here is my personal top ten list of quick wins:

#1 – Promote Software Security Principles

Creating and establishing comprehensive secure development requirements, e.g. in form of an AppSec policy, standards or internal AppSec frameworks is important to establish a baseline but it will usually take a lot of time. Even if you use a template such as TSS-WEB you will still have to adapt it to your organization, discuss it with many relevant stakeholders, make the organization aware of it and plan its implementation.

Therefore, I find it really useful to start with a set of important security principles that are easy to comprehend and agree on. Here are some examples of such principles that can be described and linked to relevant mitigation controls:

  1. Security is not a feature
  2. Assume that the network is not secure & data is untrusted by default
  3. Teams are responsible for the security their code
  4. Discuss potential threats of features & changes before implementing them
  5. Implement & automate security tests where possible
  6. Only use mature and secure technologies
  7. Try to prevent vulnerabilities from being introduced in the first place
  8. Regularly question security assumptions from the past
  9. Continuously improve
  10. Share your knowledge

Such a set of simple principles is especially useful for explaining the most important security practices and relevant measures to developers when it is supported by management. Managing support is a crucial aspect here and it will be usually much easier to archive for a shortlist than for a complex policy.

You may want to call this your Software Security Manifesto if you need a catching title. Have a look at Synopsis Agile Security Manifesto or the Rugged Software Manifesto for reference.

#2 – Organize AppSec Awareness Workshops

A general understanding of important security threats and best practices for applications is a vital requirement for every developer. Many companies try to approach this by conducting comprehensive secure coding trainings for developers.

From my personal experience, the effect of such training is often quite limited though. Especially when developers haven’t been much in contact with security practices before. Then such training can even have an adverse effect – e.g. a negative mindset towards security.

Therefore, I recommend starting with short (~ 90 minutes) technical awareness sessions that focus on motivations behind AppSec measures, common AppSec threats (e.g. based on OWASP Top Ten), best practices, and of course the software security principles from above. Do not only offer this to developers but with the whole team’s members plus (!) product owners. The latter is so important because they are the ones that need to understand the importance of such measures at most.

It does make a lot of sense to also address other stakeholders, especially on the business side, but usually with a customized session format.

Technical AppSec awareness workshops are a great first stop in order to promote a learning culture in your organization. In the next step you could still conduct in-depth training sessions with practical exercises, but perhaps only with a reduced group of developers. Also, specialized computer-based training solutions exist which work great on demand and could complement such activities.

#3 – Engage with Dev Teams

Don’t reach out to dev teams not until you’ve finished your security standards and guidelines. You will lose a lot of valuable time because are usually do not wait that you have your requirements ready but will continue working on new applications and features without them.

Therefore, security should engage with teams as soon as possible. We call this shift left. This is also important to get continuous input for the requirements you’re working on. It does not matter if you cannot provide a comprehensive framework at this point. Start informally by discussing existing security controls, potential threats, and relevant mitigations with your dev teams.

Such threat modeling sessions are usually not taking much time and are very efficient. As a next step, you can develop tools, templates, processes, or catalogs that help you improving this activity over time.

Also, try to engage with new development projects early (e.g. by participating in relevant sessions with security architecture). At this early point of development, you are able to define way more security requirements even without a finished internal standard or policy.

Many organizations gained really positive experiences with internal security coaching (or consulting) that they provide to their dev teams. Such a coach could participate in relevant refinements, planning events, and/or within a dedicated Security Jour Fixe (aka Security Refinement). You could also establish regular office hours by which coaches are available for anyone and without a meeting invite.

Usually, such a coaching role would be filled at first by an external consultant (therefore a quick win) but could be provided by internals at a later time.

#4 – Start an AppSec Security Community

Establishing a positive security culture is perhaps the most important aspect of all. You will not be able to archive much without it. Have a look at the Salesforce approach to see an interesting case stud on how it can work.

One important aspect here is security communities for developers. This sounds like much and can in fact include a lot of activities but you can start very small, for example with a regular security JF. It is really helpful to set up an application security portal (e.g. in your Confluence) that you use to work on requirements and guidelines with the community and to share results with the rest of the development organization.

Every team has to appoint a Security Champion (and a deputy) who participates in the community and basically works as a multiplier function, team representative, and point of contact for the security of that particular team.

Create a community wiki and collect meeting minutes, polls, and other relevant information there.

#5 – Create Practicable Guidance

Many organizations already have documented requirements or guidelines on secure coding practices. Unfortunately, though, these are often either based on a lot of copy-and-paste, lists of external links (e.g. to various OWASP sites), or just far from finished. Such documentation may of course then serve only as a fig leave to be presented when someone asks for it, but will most likely not result in more secure applications.

So it makes a lot of sense to first focus on guidelines, questionnaires such as checklists that are practicable. By practicable I mean (1) easy to understand and apply (2) focussed on relevant aspects (3) limited in their length.

Some examples:

  • A list of the ten most important coding measures for relevant programming languages.
  • A questionnaire for product owners that helps them identify relevant security requirements based on technical questions.
  • A list of simple attack vectors that functional testers can be used for lightweight security tests.
  • Hardening checklists for most relevant tech stacks.
  • A pre-release checklists that outlines important security tasks for each release.

The latter one actually provides a form of a lightweight security gate based on a self-assessment by which teams/projects can figure out if they miss something. But the focus here should really be what is actually helpful. Don’t try to cover all existing threats or measures.

Create an AppSec portal and publish all guidance, links, and your community pages there.

#6 – Implement Secure Defaults

The best way to mitigate a vulnerability is to prevent it from being introduced in the first place. There are several ways to accomplish this, using a language or framework that is not susceptible to a certain threat is perhaps the best one. If this is not possible you can often set or use secure defaults – settings that a developer needs to be explicitly changed to make the code insecure. I sometimes describe this as part of a secure foundation approach.

JSTL is a good example of a very simple secure default. If you output a variable using the <c:out> tag

<c:out value="${content}" />

it gets automatically HTML entity encoded by default which usually prevents Cross-site scripting (XSS). A developer must explicitly set “escape=false” to circumvent this default setting. Other modern view technologies work in a similar way.

Frameworks like Angular do it even better by making it so hard for developers to inject JavaScript code that you will usually not find many Angular-based applications with an XSS. There are a lot of similar possible defaults for other vulnerabilities (e.g. encryption, information disclosure, error handling, XXE, SQLi).

Being able to define secure defaults must not require a framework that supports it explicitly. You will often be able to overwrite insecure defaults, e.g. using boilerplates, templates, or provisioning scripts. This is not limited to code but also to deployments, configurations, etc.

#7 – Automate Simple Security Checks

This brings us to my next point: security automation. There are many tools, both commercial and open-source, that can be used to scan for vulnerabilities in code, dependencies, and configuration. Automating such tests can be a great quick win if you focus on tools that are easy to integrate (e.g. in your Jenkins pipeline or IDE) and that decent good results for a particular technology (e.g. spotbugs for Java gosec for Go). You should begin with high-risk vulnerabilities and by fixing them and low-hanging fruits, respectively. If you have to evaluate and introduce a completely new tool here, then this will be probably no quick win of course.

I really like the concept of using pre-commit hooks for simple security checks. The idea here is to implement simple but very accurate checks that are automatically executed on every committed code and refuse a commit if something is found. There are a couple of scenarios that you’ll be able to implement here. For instance for the detection of insecure algorithms, settings, or committed secrets (see below). Have a look at pre-commit.com for more examples here.

Another quick win is to implement or extend functional security tests for existing security controls (e.g. testing various authentication and access controls). According to the Privacy Rights Clearinghouse, a vast number of data breaches occur due to incorrectly implemented technical (security) controls. It is therefore vital to implement comprehensive tests here for both positive and negative use cases. This does often not require many resources.

Lastly, simple security automation can also include automatic remediation. This works usually great in cloud environments where we often use Lambda functions to deactivate risky IAM permissions. But we can also apply this thinking to many on-prem or application-level scenarios.

#8 – Harden Applications

Application hardening is another field where you can reach a lot of impacts quite quickly without changing a single line of code.

Have a look at your productive applications, especially those exposed to the Internet but not only them. Remove functionality, services, and routes that are not required or protect them with IP binding or something similar if possible. We call this attack surface reduction.

Make everything available by TLS and harden your TLS stack. There are a lot of tools such as Qualy’s SSL Server Test that help you with that. Please note, being able to secure the application level requires that the network and host layer is already secured.

A great quick win is to activate a common HTTP security header. Most of them have very limited risks of impacting an application functionality can therefore often be set centrally (e.g. on a load balancer). practically There are a lot of useful tools that help you finding the right header and settings as well.

If you have a Web Application Firewall (WAF) already available in your organization consider using it as an additional layer of protection for all your internet-facing applications. A WAF will not replace secure software development but can reduce the exploitability of vulnerabilities in production, which is especially important for applications that are not actively developed or tested.

#9 – Protect Application Secrets

Disclosure of application secrets (e.g. technical prod credentials / API Keys, symmetric keys, or X.509 private keys) are a major reason for many of today’s data leaks. So protecting these secrets is crucial.

One major problem here is that secrets are stored in code or as plaintext in config files. Luckily, a couple of tools such as GitRobTalisman, Truffle Hog or Git Secrets exist that you can use to easily identify secrets here and that you

There are a couple of ways to protect secrets. Perhaps the best one is by injecting them from a secure (and secured) secret vault such as Hashicorp Vault, AWS Secret Manager, or KeyWhiz. Since implementing such a system is not always that easy, you could look for other ways to protect your secrets better, at least until you have a vault. For instance, you could store relevant config files in your prod environment.

#10 – Perform Pentests with Lessons Learned

Pentests are a great method for identifying common vulnerabilities (known unknowns), as well as quite unexpected ones (unknown unknowns), in an application. The value of a pentest is therefore quite undisputed and widely used, especially by larger companies – 87.7% of the BSIMM11 participants used it. Personally, I don’t know any larger organization that is not conducting pentests, at least of their internet-facing applications.

If you are not performing regular (external) pentest yet you should start using them, ideally regularly and based on a testing policy.

And if you are, you should think about how you can improve such tests and results. One important aspect is to discuss the findings afterward. Think about how you could prevent findings from being introduced again (e.g. by establishing secure defaults or by integrating automated security checks) and document findings that you cannot or will not fix for some reason so that the next pentest does not report them again.

Lesson learned sessions are very valuable for continuously improving the security of your applications and your SSDLC. Plus, they should not be limited to just pentests but also applied to other activities (e.g. incident management) as well.

Conclusion

There is a lot you can do to improve the security of your software development within a limited time frame and with limited resources. Focussing on quick wins (or low-hanging fruits) is a virtual part of a large-scale security initiative as well because it allows you to archive quick successes and to prove the practical value of your initiative for the organization.

Of course, there is usually more than implementing quick wins you should do. Begin working on other, medium- and long-term, activities in parallel (e.g. your AppSec roadmap, AppSec strategy, AppSec framework, or AST tool evaluation) to not lose time.

Also, start by understanding how software development works in your organization, what software is in development, what technologies are used, what applications are in production, and which of them are exposed to the Internet.

Leave a Comment