Earlier this week Google released details on a new security flaw that some of their researchers found in SSL version 3.0.
POODLE, the name given to this vulnerability, stands for “Padding Oracle On Downgraded Legacy Encryption”. Attackers using POODLE can gain access to plaintext in some areas in a SSL connection. This could be used to extract important information such as a session cookie, which would allow the attacker to hijack an account and pretend to be that user.
Unlike Heartbleed and Shellshock, which were two other major vulnerabilities found this year, POODLE is not something that you can protect yourself against with a single patch, at least when it comes to servers.
Google has already stated that they will be phasing-out support for SSL 3.0 in all their products, which includes Google Chrome. SSL 3.0 can also be manually disabled on most browsers right now.
For servers, guides have been published on how to disable the protocol on popular web server software such as Apache and Nginx. However, I haven’t seen many articles on the web on how to fix this on Node.js.
Luckily, I stumbled upon this useful post by @3rd-Eden on GitHub:
Protecting against POODLE in node.js
Patching the vulnerability is very simple, but it does require modifying your code:
Step 1: Check if the server allows SSL 3.0:
On Unix systems, you can use the openssl client to quickly check if a server is vulnerable:
openssl s_client -ssl3 -connect <hostname>:443
If the client is able to do a successful handshake, then it is very likely that the server is vulnerable to POODLE.
Step 2: Disable SSL 3.0 on the server settings object
If your server is accepting SSL 3.0 connections, you will need to find where the https.createServer()
function is being called.
Once you have located the file, you will need to load in the constants module:
var constants = require('constants');
Then locate the options
object provided as the first argument to createServer()
and add the following lines to the options object:
var options = {
...
secureProtocol: 'SSLv23_method',
secureOptions: constants.SSL_OP_NO_SSLv3,
}
var server = https.createServer(options, app);
This configuration will disable SSL 3.0 on your node.js server. Please note that this might make your website incompatible with really old browsers.
Step 3: Check that it worked
Relaunch your server and repeat step 1 to check that the client is unable to negotiate a connection successfully with SSL 3.0
Step 4: Wait for an official patch:
There seems to be an ongoing discussion on whether to make this the default behavior for node.js in future versions:
These are two problems I’ve worked on from my Artificial Intelligence class this semester. These are problems which can take a really long time if done naively, hence the goal is to come up with solutions that use some heuristic to come up with the answer faster.
Snake-in-the-box
The Snake-in-the-box problem begins with a n dimensional hypercube. It consists of finding a path (the “snake”) in this cube, in which every node has exactly two neighbors that are also in the path. The only exception is the head and tail, which can be connected to each other in other to create a continuous path.
Example 4-dimensional hypercube:
A nice property about each node in a n-dimension cube is that they can be represented in n-digit binary numbers, and the difference between neighbors is one bit flip (In a 4-dimension hypercube, 0000
and 0001
are neighbors).
This property allows us to easily compute the neighbors of each node, regardless of the dimension of the cube, which means that if we write a program to compute the solution we don’t necessarily have to compute and store every node in the cube.
While computing a 3 or 4 dimensional hypercube is very trivial, as we move up to higher dimensions, the space needed grows exponentially.
A almost-naive solution
The following is an almost-naive (a.k.a partially brute-force) solution to this problem. It takes advantage of the bit-flip property, but it lacks any other heuristic or optimization.
The problem with this implementation lies on the fact that it still has to do a full search.
It’s written in PHP, and it’s very object-oriented, so it’s not super fast, but it does get the correct solution if you let it run for long enough:
https://github.com/eduard44/snakes
So far I’ve been able to get solutions for dimensions 3 to 6: 4, 7, 13, 26. Dimension 6 took a really long time to process on my cheap VPS, so I’m not expecting dimension 7 to finish any time soon.
Possible future steps are: Rewrite the whole thing in a more efficient language like C++ or implement some heuristic or algorithm that accelerates the execution runtime.
Sample output
$ hhvm run.php snakes -d 3
> Largest path found was: 4
$ hhvm run.php snakes -d 4
> Largest path found was: 7
Update 1: Randomized version
Another approach to this problem is to randomly select the path every time. This means that the search algorithm can return anywhere between the actual longest snake and 1.
To compensate for this, we can run the algorithm for multiple iterations, and keep track of the longest result.
This does not necessarily yield the correct solution, but it allows us to take a look at paths that at least get closer to the longest solution on higher dimensions.
As a nice added extra, I was able to use a Symfony component for displaying information about the progress of the program, including an estimate of how much time it will take to go through all the iterations:
Find the zebra
The find the zebra problem is much simpler. It consists of a group of five houses, which are next to each other in a neighborhood. Each house has 5 properties:
- A color
- The nationality of the owner
- A pet/animal
- The favorite drink of the owner
- The favorite cigar/smoke brand of the owner (It’s an old problem, on 2014 you could replace it with something like favorite smartphone brand)
To find the solution, you must derivate rules from other rules recursively. The rules provided are (via Wikipedia):
- There are five houses
- The Englishman lives in the red house
- The Spaniard owns the dog
- Coffee is drunk in the green house
- The Ukrainian drinks tea
- The green house is immediately to the right of the ivory house
- The Old Gold smoker owns snails
- Kools are smoked in the yellow house
- Milk is drunk in the middle house
- The Norwegian lives in the first house
- The man who smokes Chesterfields lives in the house next to the man with the fox
- Kools are smoked in the house next to the house where the horse is kept
- The Lucky Strike smoker drinks orange juice
- The Japanese smokes Parliaments
- The Norwegian lives next to the blue house
The two questions asked are: Who drinks water? and who owns the zebra?
Solution by elimination
To approach I took to this problem, revolves around coming up with all possible permutations and eliminating possible solutions by applying each rule one by one.
How do we represent the problem?
I chose to store the problem in a two-dimensional array (a matrix), in which each row is a category and each column is a house. This means that we have a matrix of 5 x 5.
On each row, we have 5! = 120
possible permutations (Permutation formula). On the whole table, we have (5!) * 5 = 600
possible arrangements.
It is simple to compute each of these arrangements and store them in memory, but individually checking that they meet the ruleset might take a really long time.
Reducing the initial size
The good news is that we don’t have to check every single arrangement. How? You may have noticed that three of the rules above are marked in bold. These rules are special because they are the only rules that give us a hint on where to start. From them we know that:
- The Norwegian lives in the first house
- The blue house is the second house
- Milk is drank in the third (middle) house
So, when we are generating our array of all possible combinations, we can safely discard combinations that do not meet these conditions, greatly reducing our search space.
Applying rules
For all the other rules, we apply a similar strategy. We take the array of possible combinations, check which combinations match the rule and discard those that don’t. At the end, every rule we apply, reduces the size of the search to a smaller subset, meaning that each subsequent rule will execute faster. This will lead to better execution time than if we checked each combination individually against all rules.
The code:
I used NodeJS (JavaScript) to implement this solution, which ran pretty fast (about 1-2 mins, depending on the CPU). At the end, it actually found two solutions!
Please note that some of the nouns might be different from the rules above since our class used a different problem, but it’s essentially the same ruleset.
You can check the code here:
https://github.com/etcinit/ai-zebra1
Sample output
$ node zebra.js
[{
nationalities:
[ 'Norwegian', 'Ukrainian', 'Englishman', 'Spaniard', 'Japanese' ],
colors: [ 'Yellow', 'Blue', 'Red', 'White', 'Green' ],
drinks: [ 'Water', 'Tea', 'Milk', 'Juice', 'Coffee' ],
pets: [ 'Fox', 'Horse', 'Serpent', 'Dog', 'Zebra' ],
smokes:
[ 'Kool', 'Chesterfield', 'Winston', 'Lucky Strike', 'Kent' ]
}, {
nationalities:
[ 'Norwegian', 'Ukrainian', 'Englishman', 'Japanese', 'Spaniard' ],
colors: [ 'Yellow', 'Blue', 'Red', 'Green', 'White' ],
drinks: [ 'Water', 'Tea', 'Milk', 'Coffee', 'Juice' ],
pets: [ 'Fox', 'Horse', 'Serpent', 'Zebra', 'Dog' ],
smokes:
[ 'Kool', 'Chesterfield', 'Winston', 'Kent', 'Lucky Strike' ]
}]