skip to Main Content

I know that I need to salt the hash, I’m just curious how a SQLInjection attack would be executed against this and I want to mitigate the risk

if (username && password) {
    db.get(`SELECT * FROM users WHERE username = ? AND password = ?`, [username, hashString], (err, row) => {
      if (err) {
        console.error(err);
      } else {
        if (row) {
          console.log('Login sucessful');
          console.log('username input: ' + username + ' password input: ' + password + ' hash of password: ' + hashString);
          console.log(row);
          response.redirect('/index.html');
        } else {
          console.log('username input: ' + username + ' password input: ' + password + ' hash of password: ' + hashString);
          console.log(row);
          console.log('Invalid username or password');
          
          response.redirect('/login.html');
          response.end();
        }
      }
    });
  } else {
    response.send('Please enter a username and password!');
    response.end();
  }
});

I tried adding some sql commands into the username and password slot. Nothing happens in the password box since it’s being hashed before it gets inserted into the sql command

2

Answers


  1. The code appears to be using parameterized queries, which helps to prevent SQL injection attacks. However, one potential risk in the code is that the hashString parameter is not defined in the code snippet provided, so it is unclear how it is being generated. If it is being generated in an insecure way, it could potentially be manipulated by an attacker to execute a SQL injection attack.

    Example

    A SQL injection attack could be attempted by entering a username and password combination that includes SQL code as part of the input. For example, an attacker could enter the following input as the password:

    password' OR 1=1 --
    

    This input would cause the SQL query to evaluate as follows:

    SELECT * FROM users WHERE username = 'username' AND password = 'password' OR 1=1 --'
    

    The double dash at the end of the input is a comment marker in SQL, which causes the remainder of the query to be ignored. The OR 1=1 condition is always true, which means that the query will return all rows from the users table, allowing the attacker to log in without a valid password.

    Migrate this risk

    To mitigate this risk, it is recommended to ensure that any input parameters used in the SQL query are properly sanitized and validated before being used. Additionally, it is recommended to use parameterized queries with prepared statements to prevent SQL injection attacks.

    Update based on comment about hashString

    Using SHA-512 for hashing passwords does not directly increase the risk of an SQL injection attack.

    However, using SHA-512 for password hashing is less secure compared to dedicated password hashing algorithms like bcrypt, scrypt, or Argon2. It does not provide sufficient protection against brute-force attacks and does not include a unique salt for each user, making it vulnerable to precomputed tables of hashed passwords (like rainbow tables).

    It’s not related to your original question but important to note, so here’s a quick example. I would recommend figuring out how you could implement it in your codebase if it’s important to you.

    const bcrypt = require(‘bcrypt’);
    const saltRounds = 10; // This value determines the "cost" of the hashing algorithm. A higher value means more computational power is required to hash and verify passwords, which is generally more secure. You can adjust this value based on your requirements.

    npm install bcrypt
    # or
    yarn add bcrypt
    
    // Hash a password (saltRounds is kind of the "cost" or "work factor")
    bcrypt.hash(password, saltRounds, (err, hash) => {
      if (err) {
        console.error(err);
      } else {
        // Save the hashed password to the database
      }
    });
    
    // Verify a password
    bcrypt.compare(password, hash, (err, result) => {
      if (err) {
        console.error(err);
      } else {
        // If 'result' is true, the password is correct.
      }
    });
    
    Login or Signup to reply.
  2. Concept

    The concept is simple it all boils down to the core SQL query.
    these are the things to remember:

    • ‘–‘ represent comments.
    • ‘ is essential depending on where you place it.

    Now answer the question:

        SELECT * FROM users WHERE username =? AND password =?
    

    The above is the SQL query and the question mark is the endpoint for input.
    and there is no sanitization in place.
    So for the server to be manipulated we must comment out the check feature and the query must return true.

    '-- : Will when injected in the username section

    This will be the result:

        SELECT * FROM users WHERE username =''-- AND password =?
    

    The result will be like the password section will be commented and the check will be ignored.

    Let’s change it a bit and set the payload to be: '1=1--

    Now, this will be the final query: SELECT * FROM users WHERE username =''1=1 -- AND password =?

    Now 1=1 is True that’s universal so the ” will return nothing and 1=1 will return True and the password section is ignored and the login is successful is bypassed.

    Preventions

    For prevention, there are 2 ways and both work well together they are:

    • Sanitization
    • WAF

    When done on a normal application using a WAF won’t be appropriate but using sanitization is effective. the WAF operates by blocking such attacks once detected but sanitization strictly forbids certain inputs.

    A basic sanitization code in Python:

        import re
        
        def s_u(username):
            # Remove any characters that are not letters, numbers, or underscores
            sanitized_username = re.sub(r'[^w]', '', username)
            # Remove any leading or trailing spaces
            sanitized_username = sanitized_username.strip()
            return sanitized_username
        
        
        def s_p(password):
            # Remove any characters that are not letters, numbers, or underscores
            sanitized_username = re.sub(r'[^w]', '', username)
            # Remove any leading or trailing spaces
            sanitized_password = password.strip()
            return sanitized_password
    

    The above code blocks characters such as ',-[] etc cause these are a few of the most commonly used codes for injecting such attacks. Based on your usage you can manipulate it for using extra or not using extra characters but the more sanitized the better.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search