Practical APPSEC starts with people first, processes second, and technology last
Application Security (APPSEC) is the subset of Information Security that is focused on hardening software to protect humans, be it customers, partners, and the public at large. The software itself must be designed to be more secure because security cannot effectively be bolted on at the end of the development process. It’s an old time idea, but security is about people, processes, and technology in that order. Let’s look at how a web application goes astray by people’s knowledge, incentives, and the working of the development process.
Software security is incredibly hard to get right for structural reasons of how people work on software projects. Very well intentioned developers, focused on building incredible software will end up producing a web application with a JavaScript frontend (that runs in the user’s browser), an API service, and a backend database that looks like:
In this illustration, the dashed red lines indicate logical threat boundaries. In threat modeling, these are used to illustrate where authentication decisions are made or where network firewalls control access.
This pattern has a number of inherent security weaknesses when security is not part of the design and testing of this web application, including:
- ineffective security checks in the JavaScript application that are not duplicated in the backend;
- GraphQL queries that are susceptible to manipulation with insufficient access control and validation;
- databases that provide no additional access control because all communication to and from the web application is via database owner / super user credentials;
- and many, many other problems we see again and again in our secure code review work.
At a high level, many of the structural challenges boil down to:
- Software requirements are usually written to focus on functional requirements, that is the functionality that is desired;
- Security has classically been treated as either a non-functional requirement that is imposed from outside of the requirements, or worse, the “It is not our job it’s the security team’s job to protect us” mentality;
- Developers are incentivized to build
- only what is minimally necessary to satisfy the requested functionality,
- as quickly as possible,
- and then move on;
- and while no developers want to ship insecure software, most do not have the knowledge necessary to advocate for security.
I want to reiterate that the problem is not lazy developers. Almost every developer I speak with wants to create secure software, but they just don’t know how to do so. There are great resources available to teach the fundamentals, including awareness pieces like the OWASP Top 10 and books like Alice and Bob Learn Application Security, which Rietta has made part of our welcome package for all new team members.
Developer education is not enough! As companies we have to work on the incentives. Security needs to be a fundamental part of your development process. Basic threat modeling needs to be part of every user story discussion with security considerations part of the definition of done for each story and each feature. Your team should be using abuser stories to track things that the system shall not allow. Automated testing is necessary for rapid patching and needs to be crafted as part of your quality control process.
If you need help with this process, Rietta teaches a hands-on Software Security Project Management workshop designed for both developers, project managers, and non-technical stakeholders. Our happy clients include companies in the Fortune 500.
Remember that security is about people, processes, and technology (in that order). The best ideas are timeless and ironically do not make security vendors a lot of money, so they do not pitch our companies on it. Let us all endeavor to have our companies invest in people first. If you get people and process right, the technology part is far less relevant than so many make it out to be.
∎
Bonus: So what’s wrong with that VERY INSECURE design?
If you are wondering what the biggest mistake in the design illustrated above, look at where the threat boundaries are placed. Some of the issues are:
- The JSON API trusts the React JavaScript client. This means that either REST calls or GraphQL calls are being directly processed and sent to the database. The threat boundary should be drawn around the web service and all API calls authenticated, authorized, and treated as hostile input.
- The JSON API Server has direct read/write access to the databases but is not within the same threat boundary. This means that the main database is probably directly exposed to the Internet (common with Heroku hosted applications) and thus any credential leak is a database breach.
- The JSON API talks directly to the Search Database, if this database is an unauthenticated MongoDB then it can be exposed to the Internet. This happens ALL THE TIME with security misconfigured databases and object stores in the cloud.
- The JSON API has full read/write access to all of the database records. If the data is sufficiently sensitive, additional middleware should be part of the design and database permissions should be partitioned to provide better defense in depth.
We could unpack more. This is an example of running through a threat modeling process given a data flow diagram. It is an extremely helpful process that is part of what your team needs to be doing as part of the development process. The biggest sin in this example though is #1. Never trust user supplied input, including from your frontend application.