└── README.md /README.md: -------------------------------------------------------------------------------- 1 | # Security Guide for Developers 2 | - [Really Important stuff](#really-important-stuff) 3 | - [General best practices](#general-best-practices) 4 | - [Development Process](#development-process) 5 | - [Application Design](#application-design) 6 | - [General protection](#general-protection) 7 | - [Testing](#testing) 8 | - [Running Application](#running-application) 9 | - [Data protection](#data-protection) 10 | - [Application design](#application-design) 11 | - [Cookies](#cookies) 12 | - [Validation](#validation) 13 | - [Error Handling and Logging](#error-handling-and-logging) 14 | - [Authentication and Authorisation](#authentication--authorisation) 15 | - [Session Management](#session-management) 16 | - [File uploads - Virus scanning](#file-uploads) 17 | - [Web services - API keys, JWTs, CORS](#web-service-security) 18 | - [Communication security - TLS](#communication-security) 19 | - [Automated security testing](#automated-security-testing) 20 | - [Resources](#useful-resources-and-books) 21 | 22 | # Really important stuff! 23 | - don’t put live data on any local device unless it has been signed off for such usage 24 | - only access live / sensitive data under strict guidance (each service should have rules around its usage) 25 | - understand the policies around where you should store your source code. NEVER put information such as passwords, API Keys or IP addresses in code repositories, even private ones. 26 | 27 | # General best practices 28 | 29 | ## Development process 30 | - security should be part of the agile delivery process and be applied per story 31 | - use the [OWASP Security Testing Framework](https://www.owasp.org/index.php/The_OWASP_Testing_Framework) for a checklist 32 | - enforce [protected branches](https://github.com/blog/2051-protected-branches-and-required-status-checks) 33 | - enforce reviews via [pull requests](https://help.github.com/articles/using-pull-requests/) 34 | - require [signed commits](https://help.github.com/articles/signing-commits-using-gpg/) 35 | - have a well defined, understood and enforced peer review process 36 | - ensure you have fast, repeatable deploys with automated testing 37 | - monitor for security advisories and patches and update when necessary 38 | 39 | ## Application design 40 | 41 | - favour simple systems; they are easier to secure 42 | - adhere to the principles of [clean code](https://www.amazon.co.uk/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882) - this makes applications easier to understand 43 | - consider [design by contract](https://en.wikipedia.org/wiki/Design_by_contract). [Preconditions](https://en.wikipedia.org/wiki/Precondition) set input constraints, [postconditions](https://en.wikipedia.org/wiki/Postcondition) what must be true; test against these 44 | - reduce the attack surface by removing unnecessary code / libraries endpoints, remove demo enabling code, default passwords etc. 45 | - minimise integrations, understand and protect against compromised 3rd parties (e.g. a script sourced from an untrusted 3rd party could be malicious) 46 | - favour small components with a clear, [single responsibility](https://blog.8thlight.com/uncle-bob/2014/05/08/SingleReponsibilityPrinciple.html) 47 | - favour using established libraries and frameworks over rolling your own. However, import only trustworthy software and always verify its integrity 48 | - avoid the use of shared variables / [globals](http://programmers.stackexchange.com/questions/148108/why-is-global-state-so-evil) 49 | - prefer [immutability](http://miles.no/blogg/why-care-about-functional-programming-part-1-immutability) 50 | - avoid nulls by using [Option](https://en.wikipedia.org/wiki/Option_type) e.g. [Scala Option](http://danielwestheide.com/blog/2012/12/19/the-neophytes-guide-to-scala-part-5-the-option-type.html) and [Java Optional](http://onelineatatime.io/optional-guava-and-java-8/) 51 | 52 | ## General protection 53 | 54 | - be careful using <script src> unless you have complete control over the script that is loaded 55 | - if submitting a form modifies data or stage, use POST not GET 56 | - avoid [SQL injection](https://www.owasp.org/index.php/SQL_Injection_Prevention_Cheat_Sheet) / javascript injection by ensuring all queries are [parameterised](https://www.owasp.org/index.php/Query_Parameterization_Cheat_Sheet) (and / or use e.g. an [ORM](https://en.wikipedia.org/wiki/Object-relational_mapping), [Active Record](http://www.martinfowler.com/eaaCatalog/activeRecord.html)) 57 | - protect against cross site scripting [(XSS)](https://www.owasp.org/index.php/XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet) by escaping / sanitising untrusted data using a standard security encoding library. Also consider using [Content Security Policy] (https://w3c.github.io/webappsec-csp/2/) headers to whitelist assets a page can load 58 | - protect against cross site request forgery [(CSRF)](https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)) which target state-changing requests. Check standard headers to verify the request is same origin AND check a CSRF token 59 | - ensure that resources you load are as expected by using [subresource integrity](https://www.w3.org/TR/SRI/) 60 | - use HTTP Strict Transport Security [(HSTS)](https://www.owasp.org/index.php/HTTP_Strict_Transport_Security_Cheat_Sheet) with e.g. a "Strict-Transport-Security: max-age=8640000; includeSubDomains" HTTP Header to protected against SSL strip attacks. Consider entering your domain into the [HSTS preload list](https://hstspreload.appspot.com/) 61 | - protect against [clickjacking](https://www.owasp.org/index.php/Clickjacking_Defense_Cheat_Sheet) by using the "X-Frame-Options: DENY" HTTP Header 62 | - Don’t use [JSONP](http://stackoverflow.com/questions/3839966/can-anyone-explain-what-jsonp-is-in-layman-terms) to send sensitive data. Since JSONP is valid JavaScript, it’s not protected by the same-origin policy 63 | - do not eval any non-verified String (e.g. don't eval a String expected to contain JSON - use JSON.parse instead) 64 | - do not store session ids in [LocalStorage](https://www.sitepoint.com/html5-local-storage-revisited/). Think carefully before putting any sensitive data in local storage, even when encrypted 65 | - prefer sessionStorage to localStorage if persistence longer than the browser session is not required 66 | - validate URLs passed to XMLHttpRequest.open (browsers allow these to be cross-domain) 67 | - only use [WebSockets](http://www.html5rocks.com/en/tutorials/websockets/basics/) over TLS (wss://) and be aware that communication can be spoofed / hijacked through XSS 68 | - use [different subdomains](https://www.gov.uk/service-manual/operations/operating-servicegovuk-subdomains.html) for public facing web pages, static assets and administration 69 | 70 | ## Cookies 71 | 72 | - use [secure](https://www.owasp.org/index.php/SecureFlag), signed, [httpOnly](https://www.owasp.org/index.php/HttpOnly) cookies when possible (and mandatory if it contains account information) 73 | - encrypt any sensitive data with e.g. [cookie-encyption (node)](https://www.npmjs.com/package/cookie-encryption) 74 | - avoid putting sensitive information in 3rd party cookies 75 | 76 | ## Testing 77 | 78 | - favour [Test Driven Development](https://en.wikipedia.org/wiki/Test-driven_development) to encourage good test coverage and application design 79 | - test in an environment configured like live (infrastructure, replication, TLS etc.) with similar data profiles (but not with live data) as early as possible 80 | - any testing against live data in non prod environments (even if scrubbed / anonymised) needs appropriate signoff 81 | - use Continuous Integration (CI) and ensure good automated unit, integration, acceptance, smoke, performance, security tests 82 | - undertake an IT Health Check (ITHC, [Penetration Test, Pen Test](https://en.wikipedia.org/wiki/Penetration_test)) for new services or significant changes 83 | - consider use of a version of [chaos monkey](http://www.ibm.com/developerworks/library/a-devops4/) e.g. [Simian Army](https://github.com/Netflix/SimianArmy) to test random instance failures 84 | 85 | ## Running application 86 | 87 | - always use HTTPS (ensure you use [TLS](https://en.wikipedia.org/wiki/Transport_Layer_Security) 1.2) 88 | - web applications must use a properly configured Web Application Firewall [(WAF)](https://www.owasp.org/index.php/Web_Application_Firewall) e.g. [NAXSI](https://github.com/nbs-system/naxsi) 89 | - remove unnecessary functionality and code 90 | - if exceptions occur, fail securely 91 | - monitor metrics e.g. [Sysdig](http://www.sysdig.org/) 92 | - create audit for successful and unsuccessful login attempts, unsuccessful authorisation attempts, logouts etc. 93 | - disable unused [HTTP methods](https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html) 94 | - restrict all applications and services to running with the minimum set of privileges / permissions 95 | - isolate dev environments from the production network, and allow access to dev from authorised users only (dev environments can be a common attack vector) 96 | 97 | ## Validation 98 | 99 | - perform integrity checks to ensure there has been no tampering of e.g. hidden fields or transaction ids. Can use [checksum](https://en.wikipedia.org/wiki/Checksum), [HMAC](https://tools.ietf.org/html/rfc2104), encryption or digital signature depending on the risk 100 | - server-side validation of all inputs, including headers, cookies, redirects 101 | - prefer to [accept known good](https://www.owasp.org/index.php/XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet) input rather than [reject known bad](https://www.owasp.org/index.php/Data_Validation#Reject_known_bad) input 102 | - sanitise input if necessary (e.g. strip out whitespace or hyphens from phone numbers) 103 | - ensure option selects, checkbox and radio contain only allowable (given) values 104 | - validate data type / length / range / allowed chars 105 | - always re-validate previously entered form data in case it has been surreptitiously altered; hidden fields should be validated too 106 | - all validation failures should result in input rejection with an appropriate message to the user 107 | - have automated tests to check a reasonable range of validation failures are as expected 108 | 109 | 110 | ## Error handling and logging 111 | 112 | - do not log sensitive information (e.g. account information or session identifiers) unless necessary 113 | - ensure no debugging / stack traces are displayed to the end user in production 114 | - use generic error messages and custom error pages in production 115 | - prevent tampering of logs by ensuring they are read only and do not allow deletions 116 | - ensure a mechanism exists to conduct log analysis 117 | - restrict access to logs 118 | 119 | ## Data protection 120 | 121 | - do not store passwords, connection strings etc. in plain text 122 | - understand the data that will be used, its retention and removal policy 123 | - understand who will be accessing the service / data, with what devices via what networks / 3rd party services 124 | - only store and use the minimum amount of data required to fulfil the user need; allow users to view only the data they need 125 | - don't (provide interfaces that) allow arbitrary querying of data 126 | - don't allow download of bulk data-sets or too much data to be visible on a page 127 | - rate limit access to large data-sets and record access attempts (also limit the number of transactions a user or device can perform in a given time period) 128 | - enforce use of database schemas, even for noSQL databases by using e.g. [Mongoose](http://mongoosejs.com/docs/guide.html) for MongoDB 129 | - avoid caching data within services unless necessary 130 | - protect caches / temp files containing sensitive data from unauthorised usage and purge them ASAP 131 | - use synchronous cryptography (shared secret) e.g. [AES](https://en.wikipedia.org/wiki/Advanced_Encryption_Standard) to encrypt / decrypt your own data if its sensitive. 132 | - Ensure a shared key is held securely and separately to the data, preferably in a separate key vault (e.g. [Vault](https://www.vaultproject.io/)) that your service can access when it needs a key 133 | - use a key management process e.g. leveraging [Amazon KMS](https://aws.amazon.com/kms/) 134 | - encrypt backups (you will need to know which keys are required to handle which version) 135 | - encode fields that have especially sensitive values 136 | - disable autocomplete on forms for sensitive fields 137 | - not transmit any sensitive information within the URL 138 | - disable client-side caching for pages containing sensitive data by using appropriate [HTTP cache headers](https://www.keycdn.com/blog/http-cache-headers/) i.e. "Cache-Control: no-store", "Expires: 0" and "Pragma: no-cache" 139 | - anonymise data (ensuring re-identification cannot take place) sent to reporting tools or being used as test data 140 | - consider encrypting partially completed forms under a key held by the user if you do not need to use this data 141 | - applications should connect to databases with different credentials for each trust distinction e.g. user, read-only, admin, guest 142 | 143 | ## Authentication / authorisation 144 | 145 | - refer to the [CESG password guidance](https://www.cesg.gov.uk/guidance/password-guidance-simplifying-your-approach) when deciding your password policy for users 146 | - if authentication is required, authenticate and authorise on every request 147 | - use centralised authentication controls, favour SSO 148 | - if authentication services go down they should not give users unauthorised access 149 | - authentication failure should give no information as to which part failed - all error responses should be generic and the same 150 | - separate authentication and authorisation from the resource that is being requested 151 | - admin / account management functions should be particularly secure 152 | - any credential store should only use cryptographically strong one-way salted hashes that don’t allow brute-force attacks. (use bcrypt, scrypt or PBKDF2). Salt length should be at least 128 bits and can be stored in db (prevents [rainbow attacks](http://security.stackexchange.com/questions/379/what-are-rainbow-tables-and-how-are-they-used)) 153 | - enforce the changing of temporary or default passwords when they are used 154 | - password reset links should be time-limited and one-time use only 155 | - prevent users from reusing a password 156 | - notify users when a password reset occurs 157 | - indicate the last attempted login to a user 158 | - think carefully about the implications of using "Remember Me" 159 | - re-authenticate users before performing any critical operation such as uploading files 160 | - more secure: use multi-factor authentication (MFA / 2FA) to obtain one-time passwords (OTP). Favour [Google Authenticator](https://en.wikipedia.org/wiki/Google_Authenticator), [Authy](https://www.authy.com/developers/) etc. over SMS (which has weak encryption standards that allow for man-in-the-middle attacks) 161 | - consider introducing captcha after a number of login failures 162 | - lock the account after a number of login failures for a given period of time 163 | - enable all users to be force logged out (e.g. invalidating all session cookies) 164 | - be prepared to change the hashing mechanism; ensure you can do it in the fly when users need to log in 165 | 166 | ## Session management 167 | 168 | - session IDs should be unique, non guessable and non-sequential and suitably long 169 | - use [httpOnly](https://www.owasp.org/index.php/HttpOnly), [secure](https://www.owasp.org/index.php/SecureFlag), [session cookies](http://cookiecontroller.com/internet-cookies/session-cookies/) to store session ids client-side 170 | - use httpOnly, secure, signed, encrypted session cookies if you want to store session data client-side 171 | - set the path and domain for cookies to a suitably restricted value 172 | - session inactivity timeout should be as short as possible 173 | - logout should always be available 174 | - expire session ids after a defined period (to reduce impact of session hijacking) 175 | - session invalidation (due to e.g. timeout, logout, expiration or unauthorised reuse) should immediately delete the session id + session data on the server and client (include a Set-Cookie directive in the response with an expiration time in the past) 176 | - always create a new session (therefore new session id in a cookie) when re-authenticating, to avoid [session fixation](https://www.owasp.org/index.php/Session_fixation) attacks; never store the session id in the URL 177 | - sensitive session data should be stored on the server 178 | - clear out expired server-side session data frequently 179 | - do not allow concurrent logins for the same user id 180 | - session identifiers should only be in the HTTP cookie header (not in a GET request or anywhere else) 181 | - for sensitive data require per request rather than per session tokens 182 | 183 | ## Integration 184 | 185 | - ensure there is a clear, tightly defined schema using e.g. [JSON Schema](http://json-schema.org/) for each integration point and ensure all input is validated against this schema 186 | - automated tests should verify that messages conform to the expect schema for each integration point 187 | - rate limit inputs and check payload size 188 | -- consider using the [circuit breaker](http://martinfowler.com/bliki/CircuitBreaker.html) design pattern at integration points 189 | 190 | ## Communication security 191 | 192 | - implement transport encryption for the transmission of all sensitive information and supplement with encryption of the payload if necessary 193 | - ensure TLS certificates cover the domain and sub-domains, are current and from a trusted Certificate Authority, and be installed with intermediate certificates when required 194 | - specify character encodings for all connections 195 | - do not allow the mix of TLS and non-TLS content 196 | - filter parameters containing sensitive info in the HTTP referer header when linking to external sites 197 | 198 | 199 | 200 | ## File uploads 201 | 202 | - require authentication first if appropriate 203 | - check file type, characters, size etc. 204 | - virus / malware scan, preferably in a disposable container 205 | - turn of exec privileges on file upload directories and ensure file is read-only 206 | 207 | ## Web service security 208 | - OWASP have a good [REST Security Cheatsheet](https://www.owasp.org/index.php/REST_Security_Cheat_Sheet) 209 | - favour JSON Web Tokens [(JWT)](https://jwt.io/) in the header as the format for security tokens and protect their integrity with a [MAC](https://en.wikipedia.org/wiki/Message_authentication_code) 210 | - use API Keys in the authorization header to throttle clients and reduce impact of denial of service attacks. Do not rely on them to protect sensitive resources because they are easy to compromise 211 | - consider 2-way TLS [client certs](https://www.owasp.org/index.php/Transport_Layer_Protection_Cheat_Sheet#Client-Side_Certificates) if your application is integrating via a web service. However, implementation and trouble-shooting can be onerous and revoking and reissuing certificates a complexity 212 | - whitelist allowable methods and reject non-allowed with 405 213 | - be aware of authorisation needs in service-to-service communication, and avoid the confused deputy problem where a service calls another without providing the appropriate authorisation information. Using [external ids](https://aws.amazon.com/blogs/security/how-to-use-external-id-when-granting-access-to-your-aws-resources/) can help here. 214 | - the server should always send the Content-Type header with the correct Content-Type, and include a charset 215 | - reject a request with 406 Not Acceptable response if the Content-Type is not supported 216 | - disable CORS headers unless cross-domain calls are needed. If they are needed, be as specific as possible 217 | - consider logging token validation errors to help detect attacks 218 | 219 | 220 | # Automated security testing 221 | Whilst projects will have a penetration test and IT health check, these are periodic tasks. We also encourage teams to run automated security testing tools so they can pick up security vulnerabilities much more quickly. We recommend that security testing tools are run on a regular basis, not just when code is pushed. This is because new vulnerabilities may emerge without you having made any changes to your application. 222 | 223 | ## NodeJS dependency security testing - Snyk 224 | Snyk checks your NodeJS applications dependencies for vulnerabilities. 225 | 226 | We recommend 2 ways to use Snyk: 227 | 228 | 1) Github integration 229 | Snyk can automatically raise PRs against your repository to fix vulnerabilities, more details available here: 230 | https://snyk.io/docs/github/ 231 | 232 | 2) Manually 233 | Snyk has a CLI that you can use manually or as part of a CI pipeline. The easiest way to configure this is to: 234 | - Locally run **snyk wizard** 235 | - The wizard will offer to add code to your package json to run snyk vulnerability testing alongside your usual npm test jobs 236 | - Accept this and any CI test jobs will fail if there are new vulnerabilities 237 | 238 | ## Scala dependency security testing - SBT Dependency Check 239 | SBT Dependency Check checks your dependencies against the OWASP database of vulnerable modules. It does work but is relatively immature, so not as easy to use as Snyk. [You can find SBT dependency check here](https://github.com/albuch/sbt-dependency-check) 240 | 241 | ## Java dependency security testing 242 | OWASP provide some tools for this, which includes a command line tool as well as a maven plugin. This is essentially the same tool as SBT Dependency Check above, just more for Java. [You can find Dependency Check for Java here](https://www.owasp.org/index.php/OWASP_Dependency_Check) 243 | 244 | ## Tech specific libraries 245 | 246 | - Node 247 | - [Lusca](https://github.com/krakenjs/lusca) 248 | - [helmet](https://github.com/helmetjs/helmet) 249 | - [node security project](https://nodesecurity.io/) [nsp on GitHub](https://github.com/nodesecurity/nsp) 250 | 251 | ## Useful resources and books 252 | 253 | - [National Cyber Security Centre Secure Development Practices Guide](https://github.com/ukncsc/secure-development-and-deployment/) 254 | - [OWASP Top 10 Project](https://www.owasp.org/index.php/Category:OWASP_Top_Ten_Project) 255 | - [Web Application Security - A Beginner's Guide](https://www.mhprofessional.com/product.php?isbn=0071776168) 256 | - [Identity and Data Security for Web Developers](http://shop.oreilly.com/product/0636920044376.do) 257 | - [The Web Application Hacker's Handbook](http://eu.wiley.com/WileyCDA/WileyTitle/productCd-1118026470.html) 258 | - [HTTP protocol security considerations](https://www.w3.org/Protocols/rfc2616/rfc2616-sec15.html) 259 | - [OWASP cheat sheets](https://www.owasp.org/images/9/9a/OWASP_Cheatsheets_Book.pdf) 260 | - [OWASP secure coding practices](https://www.owasp.org/images/0/08/OWASP_SCP_Quick_Reference_Guide_v2.pdf) 261 | - [CESG Enterprise security decisions](https://www.cesg.gov.uk/guidance/security-considerations-common-enterprise-it-decisions) 262 | - [CESG password guidance](https://www.cesg.gov.uk/guidance/password-guidance-simplifying-your-approach) 263 | - [CESG 10 steps to cyber security](https://www.cesg.gov.uk/10-steps-cyber-security) 264 | - [CESG Protecting bulk and personal data](https://www.cesg.gov.uk/guidance/protecting-bulk-personal-data) 265 | - [CESG Security Design Principles for Digital Services](https://www.cesg.gov.uk/guidance/security-design-principles-digital-services-0) 266 | - [CESG TLS guidance for external services](https://www.cesg.gov.uk/guidance/transport-layer-security-tls-external-facing-services) 267 | --------------------------------------------------------------------------------