Security
Software
- TLS and WWS, the S of https. TLS is newer and better than SSL
- OS Security modules
- AppArmour for Ubuntu and SuSE
- SELinux for RedHat
- GrSSecurity
- https://letsencrypt.org/
Notes
- (Newman, 2015) Pefer SAML or OpenID Connect
- There are a couple of other downsides, though. First, just as with Basic Auth, we need to securely store our credentials: where do the username and password live? The client will need to find some secure way to store this data. The other problem is that some of the technology in this space to do the authentication is fairly tedious to code for. SAML, in particular, makes implementing a client a painful affair. OpenID Connect has a simpler workflow, but as we discussed earlier it isn’t that well supported yet.
- (Newman, 2015) HMAC over HTTP
- With HMAC the body request along with a private key is hashed, and the resulting hash is sent along with the request. The server then uses its own copy of the private key and the request body to re-create the hash. If it matches, it allows the request. The nice thing here is that if a man in the middle messes with the request, then the hash won’t match and the server knows the request has been tampered with. And the private key is never sent in the request, so it cannot be compromised in transit! The added benefit is that this traffic can then more easily be cached, and the overhead of generating the hashes may well be lower than handling HTTPS traffic (although your mileage may vary).
- There are three downsides to this approach.
- First, both the client and server need a shared secret that needs to be communicated somehow. How do they share it? It could be hardcoded at both ends, but then you have the problem of revoking access if the secret becomes compromised. If you communicate this key over some alternative protocol, then you need to make sure that that protocol is also very secure!
- Second, this is a pattern, not a standard, and thus there are divergent ways of implementing it. As a result, there is a dearth of good, open, and usable implementations of this approach. In general, if this approach interests you, then do some more reading to understand the different ways it is done. I’d go as far as to say just look at how Amazon does this for S3 and copy its approach, especially using a sensible hashing function with a suitably long key like SHA-256. JSON web tokens (JWT) are also worth looking at, as they implement a very similar approach and seem to be gaining traction. But be aware of the difficulty of getting this stuff right. My colleague was working with a team that was implementing its own JWT implementation, omitted a single Boolean check, and invalidated its entire authentication code! Hopefully over time we’ll see more reusable library implementations.
- Finally, understand that this approach ensures only that no third party has manipulated the request and that the private key itself remains private. The rest of the data in the request will still be visible to parties snooping on the network.
- (Newman, 2015) API Keys
- All public APIs from services like Twitter, Google, Flickr, and AWS make use of API keys. API keys allow a service to identify who is making a call, and place limits on what they can do. Often the limits go beyond simply giving access to a resource, and can extend to actions like rate-limiting specific callers to protect quality of service for other people. When it comes to using API keys to handle your own microservice-to-microservice approach, the exact mechanics of how it works will depend on the technology you use. Some systems use a single API key that is shared, and use an approach similar to HMAC as just described. A more common approach is to use a public and private key pair. Typically, you’ll manage keys centrally, just as we would manage identities of people centrally. The gateway model is very popular in this space.
- (Newman, 2015) Decrypt on Demand Encrypt data when you first see it. Only decrypt on demand, and ensure that data is never stored anywhere.
- (Newman, 2015) Intrusion Detection (and Prevention) System Intrusion
- detection systems (IDS) can monitor networks or hosts for suspicious behavior, reporting problems when it sees them. Intrusion prevention systems (IPS), as well as monitoring for suspicious activity, can step in to stop it from happening. Unlike a firewall, which is primarily looking outward to stop bad things from getting in, IDS and IPS are actively looking inside the perimeter for suspect behavior. When you’re starting from scratch, IDS may make most sense. These systems are heuristic-based (as are many application firewalls), and it is possible that the generic starting set of rules will either be too lenient or not lenient enough for how your service behaves. Using a more passive IDS to alert you to problems is a good way to tune your rules before using it in a more active capacity.
- (Newman, 2015) OS Security modules
- Another thing to look at if you are using Linux is the emergence of security modules for the operating system itself. AppArmour, for example, allows you to define how your application is expected to behave, with the kernel keeping an eye on it. If it starts doing something it shouldn’t, the kernel steps in. AppArmour has been around for a while, as has SeLinux. Although technically either of them should work on any modern Linux system, in practice some distributions support one better than the other. AppArmour is used by default in Ubuntu and SuSE, for example, whereas SELinux has traditionally been well supported by RedHat. A newer option is GrSSecurity, which aims to be simpler to use than either AppArmour or GrSecurity while also trying to expand on their capabilities, but it requires a custom kernel to work. I’d suggest taking a look at all three to see which fits your use cases best, but I like the idea of having another layer of protection and prevention at work.
Example from (Newman, 2015)
//TODO: fix this paragraph
- A Worked Example Having a finer-grained system architecture gives us much more freedom in how we implement our security. For those parts that deal with the most sensitive information or expose the most valuable capabilities, we can adopt the strictest security provisions. But for other parts of the system, we can afford to be much more lax in what we worry about.
- Let’s consider MusicCorp once again, and pull some of the preceding concepts together to see where and how we might use some of these security techniques. We’re looking primarily at the security concerns of data in transit and at rest. … shows a subset of the overall system that we’ll be analyzing, which currently shows a crushing lack of regard for security concerns. Everything is sent over plain old HTTP. Here we have standard web browsers that are used by our customers to shop on the site. We also introduce the concept of a third-party royalty gateway: we’ve started working with a third-party company that will handle royalty payments for our new streaming service. It contacts us occasionally to pull down records of what music has been streamed when — information we jealously protect as we are worried about competition from rival companies. Finally, we expose our catalog data to other third parties — for example, allowing the metadata about artist or song to be embedded in music review sites. Inside our network perimeter, we have some collaborating services, which are only ever used internally. For the browser, we’ll use a mix of standard HTTP traffic for nonsecure content, to allow for it to be cached. For secure, logged-in pages, all secure content will be sent over HTTPS, giving our customers extra protection if they are doing things like running on public WiFi networks. When it comes to the third-party royalty payment system, we are concerned not only about the nature of the data we are exposing, but also about making sure the requests we’re getting are legitimate. Here, we insist that our third party uses client certificates. All the data is sent over a secure, cryptographic channel, increasing our ability to ensure we’re being asked for this data by the right person. We do, of course, have to think about what happens when the data leaves our control. Will our partner care about the data as much as we will? For the feeds of catalog data, we want this information shared as widely as possible to allow people to easily buy music from us! However, we don’t want this abused, and we’d like some idea of who is using our data. Here, API keys make perfect sense. Inside the network perimeter, things are a bit more nuanced. How worried are we about people compromising our internal networks? Ideally, we’d like to use HTTPS at a minimum, but managing it is somewhat painful. We decide instead to put the work (initially, at least) into hardening our network perimeter, including having a properly configured firewall and selecting an appropriate hardware or software security appliance to check for malicious traffic (e.g., port scanning or denial-of-service attacks). That said, we are concerned about some of our data and where it lives. We aren’t worried about the catalog service; after all, we want that data shared and have provided an API for it! But we are very concerned about our customers’ data. Here, we decide to encrypt the data held by the customer service, and decrypt data on read. If attackers do penetrate our network, they could still run requests against the customer service’s API, but the current implementation does not allow for the bulk retrieval of customer data. If it did, we would likely consider the use of client certificates to protect this information. Even if attackers compromise the machine the database is running on and manage to download the entire contents, they would need access to the key used to encrypt and decrypt the data to make use if it. Figure 9-5 shows the final picture. As you can see, the choices we made about what technology to use were based on an understanding of the nature of the information being secured. Your own architecture’s security concerns are likely to be very different, and so you may end up with a different-looking solution.
-
Figure 9-5
|BROWSER| |3rd PARTY CONSUMERS| |3rd PARTY ROYALTY SYSTEMS| http & https API keys client certificates | | | ---------------------------------------------------------------- Network perimeter ---------------------------------------------------------------- | | | V V | |WEBSITE| |API GATEWAY| | ---------------------------------------------------------------- Network defences (IPS, etc.) ---------------------------------------------------------------- http | http | | ------------------------- | | | | | | | V V V V V |CATALOG||CUST SERVICE||RECOMMEND SERVICE| |STREAMING SERVICE|
OAuth2
- The OAuth 2.0 authorization framework enables a third-party application to obtain limited access to an HTTP service
- either on behalf of a resource owner by orchestrating an approval interaction between the resource owner and the HTTP service
- or by allowing the third-party application to obtain access on its own behalf.
- simple example:
- MyApp send request to GoogleOAuth2
- Google redirects to authentication page
- Google sends message to
callback Url
withcode
- MyApp sends the code to Backend Server
- Backend Server sends the code + a few other params to Google
- Google returns a token to Backend Server
- Backend Server uses token to get Contacts from Resource Server
// MyApp request to google example
request scope: contacts // name service/resource to be accessed
response type: code // grant the code to be shared with server
client id: provided by google
callback URL: called by Google after user clicks "allow"
OpenID Connect
- On top of OAuth2, for logging (authentication)
- example: Signing with Google
- same as OAuth2 example above points 1 to 5, but instead of token, an user profile (access token and id token) is returned. id token contains information for authentication
// MyApp request to google example
request scope: openid profile email // HERE IS DIFFERENCE WITH OAUTH2 example above
response type: code // grant the code to be shared with server
client id: provided by google
callback URL: called by Google after user clicks "allow"
Threat models (from Micro Focus Internal training)
- Maven Security Dojo Linux
- STRIDE
- Spoofing -> Authentication // Trust no one, Every access must be checked each time.
- Tampering -> Integrity
- Repudiation -> Non Repudiability
- Information Disclosure -> Confidentiality
- Denial of Service -> Availability // limit N of trials, set max pass length (e.g. 64 or 128) as long pass can cause DOS, and some hash algorithms have a max.
- Elevation of privilege -> Authorization // + Grant least privileges, Implement a role based access control system
- see Cross-Site Request Forgery + synchronizer token.
- Defend in depth. Do not rely only on firewall, but also use an Intrusion Detection System: validate IP, use 2 factor authentication, prevent brute-force attack, hash passwords …
- Fail secure - deny access in case of specific failure.
- Fail safe is the reverse - e.g. in case of fire allow access to closed doors so that people can come out of the building
- Make security usable :-)
- Collect only information needed for specific purpose, store it securely, limit access, delete it when done.
- Audit: the action, who, when, how
- SQL injection. Prevent with parametrized queries and prepared statement.
// VULNERABLE
String query = "SELECT account_no, balance_amt FROM accounts WHERE cust_id = '" +
request.getParameter("cust_id") + "'";
try
{
Statement statement = connection.createStatement();
ResultSet rs = statement.executeQuery(query);
}
// FIXED
String query = "SELECT account_no, balance_amt FROM accounts WHERE cust_id = ?";
String custid = request.getParameter("cust_id");
try
{
PreparedStatement pstmt = connection.prepareStatement( query );
pstmt.setString( 1, custid);
ResultSet rs = pstmt.executeQuery( );
}
- OS command injection:
- avoid direct command calls, use built-in library functions or “allow list”
- separate command from data: they must be validated separately
- run with lowest possible privilege
- passowrds -
store(secure_hash(salt+passowrd))
, use unique salt per user not system-wide, change the salt on every password change.- scrypt, bcrypt, pbkdf2
- hash(one way function) + salt, not encryption(requires decryption) + salt
- credit card number -> use encryption.
- product binary download -> hash checksum
- digitally signed file -> hashing for maintaining integrity and then encrypt the hash with signer’s private key.
- Path Traversal Vulnerability
http://example.com/getUserProfile.jsp?item=page1.xml
changed tohttps://example.com/getUserProfile.jsp?item=../../../../etc/passwd
- The attackers may also use escape codes such as
%2e%2e/
for../..
(if the .. Is blocked) (%2e
represents dot) File f = new File(input_path);
can lead to path traversal vulnerability if input_path is not trusted- Prevention: Input validation, create allowlist
- Use
getCanonicalPath()
instead ofgetAbsolutePath()
to get the actual full path name then validate it with allowed folder. - Beyond this use filters to block URLs containing commands or escape code
- see the ZipSlip vulnerability in Java
- XSS Cross Site Scripting -> use
org.owasp.encoder.Encode
Resources
- Newman, S. (2015). Building microservices. O’Reilly Media.