strwoc
strwoc

Reputation: 531

The best way to secure yourself against sql injection in nodejs

Here's the setup.

I'm sending a POST using ajax where I send the parameters for procedures to nodejs server. In this particular case, username and code.

This POST calls a request.get to a web service that executes a procedure that uses those two parameters.

For example

app.post('url/:username/:code', function(req,res,next){

 var procedure = 'EXECUTE procedureName'+req.params.code;

  request.get('myWslink/myService.asmx/service?
  callback=&userName='+req.params.username+'&procedureName='+procedure, function(){});
});

The front end user cannot see my webservice url, my request.get url or my procedure name but he can still see the parameters being sent (username, code) and he can change these parameters enabling him to execute a procedure he's not supposed to execute.

He can also call a POST request a bunch of times and fill up the database with a bunch of junk if it's an insert procedure.

What would be the best way to protect myself against these exploits?

Upvotes: 1

Views: 360

Answers (2)

Jon Lamendola
Jon Lamendola

Reputation: 101

A few suggestions here:

Don't do meta-programming to this extent. Make seperate routes on your application for each procedure, and then inject those 'codes' yourself. This will allow you to do things like validate the users input to ensure it isn't garbage data being passed in, as well as rate-limit specific routes to ensure the DB isn't filled with garbage.

You could also create a whitelist array of allowed 'codes' and make sure that whitelist.instanceOf(procedure) != -1 but this wouldn't let you do per-route input validation.

Even if you manually included the procedure, there's still a problem. In your existing code, the call out to the external service places the 'req.params.username' parameter before procedureName. For most HTTP parsing frameworks, parameters are first come, first serve. One of the first attacks I would try after seeing this code would be to inject '&procedureName=something_i_shouldnt_be_able_to_call' into my username. This would cause the procedureName attribute you are including to be ignored, while the one I submitted would be used instead. You can prevent this by either placing the user-input based params last and URI-encoding the user input prior to string interpolation, or by including your querystring as an object named 'qs' passed into the options argument to request.

Whether or not this creates a SQL injection vulnerability is entirely dependent on how the web service parses the arguments and executes the procedure. The optimal case would be that the service URI decodes each parameter, and then passes those in as arguments to either a PDO or a prepared statement. My guess is that it's using PDO, given the way it's being called.

So what I would suggest here ultimately is to URI encode each of your user-input supplied parameters, and use the qs object passed into request options as mentioned above, rather than just interpolating strings. Once you've done that, you can take any or all of these steps to help validate:

  1. Attempt to do things like inject single quotes into your user input manually.
  2. Run a tool like sqlmap on that particular route to test for SQL injection. This will give you a fairly robust testing without requiring in-depth knowledge of SQL injection techniques.
  3. Schedule an application security assessment with an experienced node.js security professional. ( I'm available at liftsecurity.io )

To reiterate - Don't trust users to give you the procedure code - make seperate routes and insert that data yourself, URI encode all user input before further processing, and use the request options object like: {qs:{name:value}} instead of string interpolation.

With those protections, you'll likely be just fine, as it seems to be using stored procedures here. Unless you can find confirmation of that in the web service's documentation, however, the only way to be sure of that is through one of the methods I suggested above.

Hope this helps!

Upvotes: 1

localhost
localhost

Reputation: 513

For preventing the sql injection you can escape the input data on your webservice. and for avoid multiple fake entries in database you can add a unique token with each post request and verify that token on your webservice, If the token is legitimate then allow the insertion if not then avoid that insertion. you are using the webservice so as far as I think you will have to keep those tokens in database for verifying.

Upvotes: 0

Related Questions