Hot File

Create Best Practices When Working With Sensitive Data: Securing Your Application

View: 616    Dowload: 0   Comment: 0   Post by: hanhga  
Author: none   Category: MySQL   Fields: Other

0 point/1 review File has been tested

To stop attackers from using SQL Injection, you have to escape all users' input so they can't inject SQL queries into your application(for example, during a login)

Introduction

To stop attackers from using SQL Injection, you have to escape all users' input so they can't inject SQL queries into your application(for example, during a login). In pretty much all of the database drivers, for all languages, there is an option to escape user input. For example in node-mysql for Node.js, instead of doing your queries like this:

connection.query('SELECT * FROM users WHERE name = \''+ username +'\' AND password = \''+ password '\';', function (err, rows, fields) {

You can automatically escape them using this syntax:

connection.query('SELECT * FROM users WHERE name = ? AND password = ?;', [ username, password ], function (err, rows, fields) {

Variables from the array provided as a second argument to the query method will be inserted in place of question marks in the query string and will be automatically escaped. The same can be done in PHP using PDO's prepared statements:

$stmt = $dbh->prepare("SELECT * FROM users WHERE name = ? AND password = ?;");
$stmt->bindParam(1, $username);
$stmt->bindParam(2, $password);
 
$stmt->execute();

Even if you escape your database queries, you never know if a bug in your application has let some malicious code through. If you have written your app in a way to where you always assume that the content in the database is safe, then your users are endangered. For example, this code:

if ($result = $mysqli->query('SELECT * FROM users WHERE name = "'. $mysqli->escape_string($username) .'";')) {
    if ($row = $result->fetch_assoc()) {
        if ($result = $mysqli->query('SELECT * FROM someData WHERE uid = '. $row['id'] .';')) {
            ...
        }
    }
}

Is unsafe! If something goes wrong and the id of the user contains some SQL injection code, then you are going to have problems. $row['id'] should also be escaped using the escape_string() method, like so:

if ($result = $mysqli->query('SELECT * FROM users WHERE name = "'. $mysqli->escape_string($username) .'";')) {
    if ($row = $result->fetch_assoc()) {
        if ($result = $mysqli->query('SELECT * FROM someData WHERE uid = '. $mysqli->escape_string($row['id']) .';')) {
            ...
        }
    }
}

Now imagine this situation: some genius hackers break through your carefully crafted security and get their hands on your database. They then begin to brute-force all of your users' passwords. If you used a salt when hashing them, you can sleep peacefully and assure your users that their data is safe. Because unless the attacker has a quantum computer in their basement, it will take them years to crack any of the passwords.

Using a salt means that you append a few random characters to the password before hashing (these characters are what is called the salt) and store them with the password. You may think that this is not very secure, since the attacker will know the salt if they gain access to the database. But since the salt is different for every user, even if two of them use the same password their hashes will be different. This forces the attacker to crack them one by one, which makes it very time consuming and usually not worth the time wasted. This also means that the attacker can't userainbow tables or a dictionary to lookup the passwords.

First you should generate the salt. For example, you could usecrypto.randomBytes():

var crypto = require('crypto');
/*
    this should be done on request with the user's data for registration,
    instead of just adding it to the database
*/
 
crypto.randomBytes(16, function (e, salt) {

This function will throw an error if, according to the Node.js documentation, "there is not enough entropy to generate cryptographically strong data". In such a case, you should either try again or use crypto.pseudoRandomBytes(), which generates non-cryptographically strong random bytes, but since this will only happen occasionally, we can use it:

if (e) {
    salt = crypto.pseudoRandomBytes(16);
}

Now let's add the data. For simplicity, I'll only use a username, password and salt in this example:

/* password and username should be extracted from request body */
    var hash = crypto.createHash('sha-256').update(password + salt.toString()).digest('hex');
    sql.query('INSERT INTO users VALUES(?, ?, ?);', [ username, password, salt ], function (err, rows, fields) {
        /* your other app logic here, what happes after the user data is into the database */
    });
});

When your user wants to login, you have to get the salt from the database and then check the password:

sql.query('SELECT salt FROM users WHERE name = ?;', [ username ], function (err, rows, fields) {
    if (rows.length < 1) {
        /* the user does not exist */
    } else {
        var hash = crypto.createHash('sha-256').update(password + rows[0].salt).digest('hex');
        sql.query('SELECT 1 FROM users WHERE name = ? AND password = ?;', [ username, hash ], function (err, rows, fields) {
            if (rows.length < 1) {
                /* wrong password */
            } else {
                /* password ok */
            }
        });
    }
});

And that's pretty much it. Now let's see how we can do this using PHP.

In PHP this is much simpler, because the built in functions password_hash() andpassword_verify() automatically uses a salt and the hash returned contains it, so you don't even need another column in the database (or field in case of NoSQL). It would look something like this:

$stmt = $dbh->prepare("INSERT INTO users VALUES (?, ?);");
$stmt->bindParam(1, $username);
/* hash the password, the function adds random salt automatically */
$stmt->bindParam(2, password_hash($password));
 
$stmt->execute();

To check the login, you just have to call password_verify(). It automatically gets the salt from the hash so you only need to supply the hash from your database and the plaintext password to compare. The needed code, is as follows:

$stmt = $dbh->prepare("SELECT password FROM users WHERE name = ?;");
$stmt->bindParam(1, $username);
 
$stmt->execute();
 
$row = $stmt->fetch(PDO::FETCH_ASSOC);
 
if ($row) {
    /* check if the password matches */
    if (password_verify($password, $row['password'])) {
        /* password ok! */
    }
} else {
    /* the user does not exist */
}

This is one of the best defense mechanisms you can use to protect your machine and therefore your users. You need elevated privileges for a couple of things, mainly listening on port numbers lower than 1024 or messing with system files. But you should never run any app as root when you do not need to, just in case the attacker finds a bug in your code that allows them to execute commands on your server and if the code is running as a privileged user, it's game over. The attacker can do whatever they want and will probably be done before you even notice anything. This is why you should drop the privileges as fast as possible. In Node.js it would look like this:

var app = http.createServer(...);
 
...
 
app.listen(80); // listen on the 80 port, to do so you have to run your app as root user
process.setuid('app_user'); // drop privileges - switch to a non-root user - only POSIX platforms sadly

The process.setuid() function will change the user identity of the process to the one passed to it - it can be either a numerical ID or a username string (in the second case, this function will block while getting the ID of the user). The user should be unprivileged and only have access to the app-specific files, to limit the risk of giving the attacker access to anything else on your machine.

 

Some people say (for example in this comment on dropping root privileges), that the solution above is not perfect and they prefer to use authbind instead. It's your decision which one you choose to use and it pretty much depends on your setup. But anyways, authbind is a command that was designed for this purpose - it allows your app to bind to ports lower than 1024 without root privileges (so it's only covering that scenario). To use it, first create a file: /etc/authbind/byport/port, where port is the port number you want to bind to and make it executable by the user you will use, to execute your app. Then switch to your user and start the app like this:

authbind node yourapp.js

Or like this from root:

su -c 'authbind node yourapp.js' youruser

With this, you can accomplish the same end goal as with the POSIX solution, just now using authbind instead, if that's what you prefer.

 

Create Best Practices When Working With Sensitive Data: Securing Your Application

Create Best Practices When Working With Sensitive Data: Securing Your Application Posted on 12-01-2016  To stop attackers from using SQL Injection, you have to escape all users' input so they can't inject SQL queries into your application(for example, during a login) 5/10 616

Comment:

To comment you must be logged in members.

Files with category

  • SQL Query to Find Nth Highest Salary of Employee with java

    View: 196    Download: 0   Comment: 0   Author: none  

    SQL Query to Find Nth Highest Salary of Employee with java

    Category: MySQL
    Fields: Other

    0/0 review
    This is a very common interview question if you are going for the role at junior level. Most of the people learn it character by character, but few understand how this query works.

  • World OOP With PHP and MySQL

    View: 956    Download: 0   Comment: 0   Author: none  

    World OOP With PHP and MySQL

    Category: MySQL
    Fields: Other

    0.32142857142857/14 review
    Setting up the skeleton of our class is fairly simple once we figure out exactly what we need.

  • How to Build a Newsletter System With PHP and MySQL

    View: 1183    Download: 0   Comment: 0   Author: none  

    How to Build a Newsletter System With PHP and MySQL

    Category: MySQL
    Fields: Other

    1.125/4 review
    When starting any project, I like to layout the folders before I start coding, so lets do that now.

  • Top 20+ MySQL Best Practices that can not be ignored

    View: 893    Download: 0   Comment: 0   Author: none  

    Top 20+ MySQL Best Practices that can not be ignored

    Category: MySQL
    Fields: Other

    1.6666666666667/3 review
    Database operations often tend to be the main bottleneck for most web applications today.

  • Create a PHP/MySQL Powered Forum from Scratch

    View: 1040    Download: 0   Comment: 0   Author: none  

    Create a PHP/MySQL Powered Forum from Scratch

    Category: MySQL
    Fields: Other

    1.5/3 review
    In this tutorial, we're going to build a PHP/MySQL powered forum from scratch.

  • Triggers Introduction to MySQL

    View: 256    Download: 0   Comment: 0   Author: none  

    Triggers Introduction to MySQL

    Category: MySQL
    Fields: Other

    1.6666666666667/3 review
    I would guess, even armed with this knowledge, that a good many of you are not taking advantage of triggers with MySQL.

  • How to Stored Procedures in MySQL 5

    View: 247    Download: 0   Comment: 0   Author: none  

    How to Stored Procedures in MySQL 5

    Category: MySQL
    Fields: Other

    2.25/2 review
    MySQL 5 introduced a plethora of new features - stored procedures being one of the most significant. In this tutorial, we will focus on what they are, and how they can make your life easier.

  • The strength of the PDO and. MySQLi: Which Should You Use?

    View: 267    Download: 0   Comment: 0   Author: none  

    The strength of the PDO and. MySQLi: Which Should You Use?

    Category: MySQL
    Fields: Other

    1.5/3 review
    When accessing a database in PHP, we have two choices: MySQLi and PDO. So what should you know before choosing one?

 
Newsletter Email

File suggestion for you

File top downloads

logo codetitle
Codetitle.com - library source code to share, download the file to the community
Copyright © 2015. All rights reserved. codetitle.com Develope by Vinagon .Ltd