CDN and “Cache-Control: max-age”

If we ever use “max-age” for content that is partially dynamic in the sense that it may or may not change in “X” minutes and we use a CDN to cache that and we also have a “max-age” header then we need to remember to do this:

  1. Ensure that the max-age is counted down by the CDN each and every time it is accessed
  2. Or, if it is not counted down then ensure that the HTTP “Date:” header also should not change as well

The reasoning is that the clients (browsers etc.) would use these two values to decide on refreshing the cache.

Consider an OCSP response which is served through a CDN. We also know that the OCSP response has a “nextUpdate” temporal value and the RFC 5019 clearly states that the “max-age” should be less (or equal to since it seems that the clients allow for equality as a positive case as well) than the “nextUpdate“.

The issue is when the “max-age” is not counted down by the CDN and the value in the “Date:” header is – we get an issue where the OCSP response might be stale but it is not timed out of the cache either for validation or a fetch.

Levenshtein Part 2: Dynamic Programming

Proceeding from the earlier post on the same topic, we have the following code for a Dynamic Programming bottom-up approach to the Levenshtein “Edit Distance” algorithm where all the weights are simply “1” for insert, delete, substitute operations. Note that this would be also referred to the “tabular” approach as well since we fill up a matrix as we go along.

In a later post, we would attempt to reduce the space requirement from O(m.n) to a constant. In another post, we would provide a way to configure the weights and thereby providing weighted edges to the DAG.

 

And the test code:

Levenshtein: elementary recursion – a gateway to DP

This is my first post on Levenshtein Algorithm: a way to calculate the edit distance between two strings. A way to calculate the cost to transmute a string1 to a string2.

The comments in the codebase are useful for comprehension on their own. I start with the recursing and building a matrix where the answer (the cost to transmute or convert str1 into str2) lies at index [m][n] for the first implementation. For the second case, the cost would be at index [0][0].

This is the gateway to elucidating DP through the implementation of this algorithm. We would implement in ways that classify as DP (both memoization and tabulation) as well as plain and simple recursion or iteration with no DP components. We start with vanilla recursion in the following codebase. Please review the comments in the codebase to understand why this is not DP. A future post would elucidate DP.

 

A snippet of the test code:

REST and API naming

There is a debate on the API naming in the world of REST – more than there should be. As per the famous dissertation – and I paraphrase – any information / artifact / entity / process (and so on) that can be named (or addressed) can be a resource. And there could be collection of resources that could be addressed as well.  For instance: a business process of “student enrollment” can be a resource and a “student” or a collection “students” are resources as well.

While designing a REST API,  we generally like to rush through the naming and that is not all right since frequent revisions to the name space would certainly affect the consumers thereby this becomes a critical piece.

We also need to consider the granularity of the API: the more finely granular the more the more populated the name space would be and perhaps require clients that are smarter and knowledgeable of the  business processes if they are present. I would in brief present an example that would elucidate the above.

Suppose we have to design an API that would deal with student enrollments into courses. Relative URIs follow:

and so on.
Among the many questions, one could be:

Q: Why do we have “/studentsEnrollment” instead of “/students/enrollment”?

A.  “/students” is being taken as a collection and “/students/{student_id}” make more sense than a business process suffix as in “/students/enrollment”.

 References:

Architectural Styles and the Design of Network-based Software Architectures

Rest API Design – Resource Modeling

Spring 4.1 (Web MVC) and earlier versions and the MVC trailing slashes issue on Tomcat

There is an issue with Spring Web component in terms of handling slashes “forward slash” when Tomcat is in the mix. Found the issue when our web application in Production received GET requests with 2 trailing slashes in the path info and the Spring Dispatcher Servlet was not able to map it to a controller even though the Spring Dispatcher Servlet is the root servlet.

Filed an issue with the Spring Jira and it has been corroborated and it is scheduled to be fixed in an upcoming release.

Please see the following issue in the Spring Jira:

https://jira.spring.io/browse/SPR-12372

BTW: the quick fix is to map the Spring Dispatcher Servlet with a wildcard as in:

OpenSSL v 1.0.2: building / compiling from source (Linux / CentOS / Red Hat)

As a precursor of installing a web server such as Apache (http version 2.4.10) and to avail of certain features as in able to configure the certificate chain on a certificate basis, we need to update to this version.

An earlier post detailed the steps to compile the OpenSSL v1.0.1 series and this one would cover the next version. The steps remain the same however the earlier post is more detailed.

  1. Run “config”
  2. Run “make”
  3. Run “make test”
  4. Run “make install”

A little more granularity:


$ ./config shared --prefix=/installs/openssl-1.0.2

Here: I have specified the installation folder to be explicit. You could point it to any other location or go with the default “/usr/local/ssl”. Note that if you would like to compile in the ECC Optimizations (ECC accelerator) refer to my earlier post.


$ make
$ make test
$ make install

You might face build issues as in “gcc” not being available or an incorrect version. Try “yum update gcc”.

The final step is to set the environment as in:


export LD_LIBRARY_PATH=/installs/openssl-1.0.2/lib:$LD_LIBRARY_PATH
export PATH=/installs/openssl-1.0.2/bin:$PATH

DTLS and OpenSSL: quick setup for server and client

To quickly setup either a DTLS server or client, the “s_client” and the “s_server” utilities can be utilized.

On the server, run “s_server”, provide it the certificate and the private key and specify the port:


$ openssl s_server -cert cert.pem -key pk.pem -dtls1 -accept 4444
Enter pass phrase for pk.pem:
Using default temp DH parameters
Using default temp ECDH parameters
ACCEPT
----

On the client, run “s_client” and you would see something akin to the following:


$ openssl s_client -dtls1 -connect xx.xx.xx.xx:4444 -debug
...
...
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES256-SHA
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
Protocol : DTLSv1
Cipher : ECDHE-RSA-AES256-SHA
Session-ID: ....
Session-ID-ctx:
Master-Key: .....
Key-Arg : None
PSK identity: None
PSK identity hint: None
SRP username: None
TLS session ticket:

CVE-2014-3513 – OPENSSL_NO_SRTP – is it compiled into your version of OpenSSL

If you would want to confirm if your version of OpenSSL that was compiled months ago (and the options specified at that time are forgotten) provides for SRTP support then one way to do that would be to utilize “objmap” on linux. If you see functions such as the following then it was not compiled with the “OPENSSL_NO_SRTP” option.

It seems that SRTP is compiled by default and is supported by default.

The command to use:

SSL 3.0 and POODLE (CVE-2014-3566)

We have a new vulnerability well explained here. The easiest solution is to remove support for SSL 3.0 from the web server – that in itself is a trivial thing to do – be it Apache or Nginx. However there might be clients that support SSL 3.0 exclusively and none of the TLS versions.

As of now I see that Chrome, Firefox 33 and the Google Web Server (the server that powers its sites) supports this extension.

Once support for TLS Fallback Signaling Cipher Suite Value (SCSV) is available in OpenSSL then the web servers would support it as well.

References:

OpenSSL Heartbeat vulnerability – Heartbleed and Java, BouncyCastle, How to write a program to check

To write a program to validate if a particular web server that runs on a version susceptible to “heartbleed”, one could use the plethora of free tests on the web such as the ones linked from the Wikipedia link on the subject. I am the author of the heartbleed test for Symantec SSL at: “https://ssltools.websecurity.symantec.com/checker/views/certCheck.jsp“.  Note: the codebase in that is completely different and follows a completely different approach to what I am going to release to the general public: a sample code that demonstrates heartbeat requests with BouncyCastle.

However, if the server that is to be verified is not accessible from the outside, you would need to write your own or download one. There are quite a few of python, Go and even one that details the changes to be made to OpenSSL s_client and use them to discover the vulnerability. Some of them work, some some of the time and when they do not, one need to understand why.

The following sections would briefly explain the OpenSSL vulnerability and the fix and how to write one of your own.

The vulnerability

An improper  heartbeat (HB) request would lead to a vulnerable web server leaking the content in its memory. This content could be a secret key or its password and so on.

While testing my HB tester program, noticed that there were attacks on my external facing web server at a rate of 2 every 10 minutes. There are a lot of attacks going on at this time.

The HB request

The request is in the following format:


HB request => ContentType (1 byte) : TLS Version (2 bytes: major and minor) : Record Size (2 bytes) : Encrypted or not Encrypted bytes

An example in hex: 18 0303 00cc and then the encrypted or not encrypted HB message follows.

More:

Encrypted or not Encrypted bytes => HB message Type : Payload Size : Payload : Padding

An example in hex for a non encrypted HB request message: 1 00cf and the actual payload and padding follow.

An improper HB request

An improper or attack vector request would create a payload of size less than what it specifies in the “Payload”. As simple as that.

An improper HB request to a vulnerable OpenSSL installation would result in it returning a HB response. The same request to a patched / not vulnerable OpenSSL (or any other web server that is not susceptible to HB) would result in a TLS alert.

The vulnerability in a little more detail

The malformed message results in an affected OpenSSL version returning a payload of the same size that is specified in the HB request irrespective of the real payload in the request. The affected OpenSSL version does not validate this aspect and the response payload is read from the memory going way beyond and leaking memory contents.

 The patch

The patch is a test of the payload length specified in the request and the actual payload size.

if (1 + 2 + payload + 16 > s->s3->rrec.length) return 0;
/* silently discard per RFC 6520 sec. 4 */

If the 1 byte that specifies the size of the HB record type (request in this case) plus the 2 bytes of that specify the payload length plus the size of the payload that is specified plus the minimum size of the padding (that is 16 bytes) is GREATER than the record length then no HB response is to be returned.

Design of a program to test for this vulnerability using Java

  1. Create a Java Socket to the web server
  2. Get a sample of a TLS ClientHello from TCPDUMP (Use s_client to send in a HB request and capture the packets to get the sample) (Make sure that it has the Heartbeat Extension setup to allow for heartbeats).
  3. Write the TLS ClientHello bytes to the socket
  4. Read the ServerHello response bytes till the end
  5. Sent in the malformed HB request (construct it in the way that is described above)
  6. Check the response: if it not an TLS alert then the web server is vulnerable. The server could reset the connection or timeout and we can assume – in these cases – that the server is not vulnerable. However there is a infinitesimal chance of a false negative especially in case of a connection timeout (and consequently the server certified to be not vulnerable) then the connection time out could be due to an actual connection issue! Note that to circumvent the heartbleed issue, network adminstrators have deployed firewall rules that would time out a heartbeat request – valid or not.

There are a huge number of types of web servers out there. The above steps would in all probability work in properly diagnosing this vulnerability in Apache and Nginx on Linux but would fail with IBM HTTP Web Server or IIS. In such a scenario, one would parse the complete ServerHello and check whether it is an extended ServerHello and if it is would check for the existence of the heartbeat extension.

Also note, that the SSL version 3.0 RFC does not allow an extended ClientHello or a ServerHello so the suggestion is to use a TLS 1.0 ClientHello in this case.

The other alternate approach would be to use BouncyCastle and send in heartbeat requests after the TLS session has been established: check out TLSProtocolHandler. If I have time, I would post that piece of code for your perusal. However as of now, I have experimented with BouncyCastle and have been successful in:

  • Establishing a TLS session
  • Sending in an encrypted “valid” TLS heartbeat request and received an encrypted heartbeat response.
  • Sending in an encrypted “invalid” TLS heartbeart request and received an encrypted heartbeat response if the server is vulnerable to heartbleed. Else, we receive an Alert, connection reset or a socket read timeout that points to a patched or a server unaffected by heartbleed.

NB: It seems to me that a valid heartbeat request is only allowed by OpenSSL after a TLS session has been established. I have tested (and you can test either with s_client or your own tool perhaps using BouncyCastle) sending a valid heartbeat request after establishing a TLS session. I established a valid TLS session and sent in an encrypted heartbeat and was able to elicit a heartbeat response using java and bouncycastle. I have not cleaned out the code and once I do will post it. So empirically, it seems that even in OpenSSL versions that are broken, a valid heartbeat request right after ServerHelloDone is disallowed. That would be the reason that a heartbeat response is not forthcoming for a valid heartbeat request send before the TLS handshake is complete.

Happy testing.