Thursday, October 30, 2014

Node.js "Error: too many parameters at queryparse"

If you've been using Express' body-parser and attempting to process large data submissions (aka forms with more than 1000 elements or 1000 sub-elements, you may have run into the following error:

Error: too many parameters
    at queryparse (/project/node_modules/body-parser/lib/types/urlencoded.js:120:17)
    at parse (/project/node_modules/body-parser/lib/types/urlencoded.js:64:9)

This is due to the fact the urlencode defaults to 1000 parameters by default. If you have a large form or just an abnormally large JSON submission, you'll need to increase this limit by doing the following:

var bodyParser = require('body-parser');

app.use(bodyParser.urlencoded({
        extended: false,
    parameterLimit: 10000,
    limit: 1024 * 1024 * 10
}));
app.use(bodyParser.json({
        extended: false,
    parameterLimit: 10000,
    limit: 1024 * 1024 * 10
}));


This will allow you to provide up to 10,000 parameters (increase as needed) and 10 MB of data (also adjustable).

Tuesday, October 14, 2014

How to Disable SSLv3 on AWS Elastic Load Balancers

In a blog post today, Google announced that a vulnerability in SSLv3 had been found that could allow attackers to intercept data that had previously been assumed to be secured. Luckily, a very small portion of the web (IE6 users on Windows XP) still use SSLv3, so it can safely, for the most part, be disabled to mitigate the risk from this issue.

http://googleonlinesecurity.blogspot.com/2014/10/this-poodle-bites-exploiting-ssl-30.html

UPDATE 10/15: As Andrew and Julio point out in the comments below, AWS has since updated their default cipher security policies. Replace steps 5 and 6.

To modify the ciphers on AWS ELBs, follow the following steps:

1) Log into the AWS console and click on "Load Balancers."
2) Find the load balancer that handles your site's traffic (you shouldn't need to worry about internal VPC LBs, etc.)
3) Click the "Listeners" tab
4) Find the HTTPS/443 listener and click "Edit" under the cipher column
5) Change the option to "Custom"
6) Uncheck the SSLv3 option
5) Change the policy to "ELBSecurityPolicy-2014-10" which disables SSLv3 for you.
6) Save.

This should be sufficient to mitigate this risk with the information that is currently known.

Redirect HTTP to HTTPS Behind AWS Elastic Load Balancer - Node.js and Apache

Apache

When you enable HTTPS for your website, you should enforce that HTTPS is being used by automatically redirecting users who access your site over HTTP to the HTTPS version. When using Apache, this is done via a host redirect entry with mod_rewrite:

<VirtualHost *:80>

# Beginning declarations here

RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^.*$ https://%{SERVER_NAME}%{REQUEST_URI}

# Rest of entry here...
</VirtualHost>

Apache Behind an ELB

However, in the Amazon Web Services world, most applications utilize the load balancer as an SSL-termination point. This means that the traffic is decrypted at the load balancer and all traffic being sent to the final destination instances is actually sent over HTTP (from a security standpoint, this is generally an accepted practice as the load balancer and instance are in the same network, and thus secure from eavesdropping). If you used the rule above, your users would wind up in an endless redirect loop.

To fix this, the "RewriteCond" needs to be changed to:

RewriteCond %{HTTP:X-Forwarded-Proto} !https

This rule will check to see which protocol the user was using before he or she hit the load balancer - which is what HTTPS redirection should use.

Node.js

When using Node.js, the same thing can be accomplished by inserting some middleware that listens for all traffic and redirects the non-HTTPS requests to their HTTPS equivalents.

var myApp = express () ,
myServer = http.createServer(myApp);

myApp.use(function redirectHTTP(req, res, next) {
  if (!req.secure) {
    return res.redirect('https://' + req.headers.host + req.url);
  }
  next();
});

Node.js Behind an ELB

Just as in our first Apache example, this works great until it is placed behind a load balancer. If you're using a load balancer, you need to make some modifications. Instead of "req.secure", do the following:

if (req.headers['x-forwarded-proto'] && req.headers['x-forwarded-proto'].toLowerCase() === 'http') {
return res.redirect('https://' + req.headers.host + req.url);
}

Using these techniques, you should be able to enforce the new HTTPS version of your website. Remember - if you serve both an HTTPS and an HTTP version of your site, the HTTPS is rendered pointless unless you also redirect the HTTP requests.