Finding an Authorization Bypass on my Own Website
Permissive parsing strikes again, MySQLjs by would accept objects as values for a parameterized query with a somewhat surprising default behaviour. The key issue here though is that MySQLjs exposes an interface entirely like prepared statements, but is actually crafting the query on the client side rather than using server-side prepared statements.
Query: SELECT * FROM users WHERE ?
Parameter Value: {"password": "example"}
Results in: SELECT * FROM users WHERE `password` = "example"
In this example it kinda makes sense, passing in an object for a more complex replacement, but it also supports that replace when you would expect a simple value to be injected.
Query: SELECT * FROM example WHERE some_column = ?
Parameter Value: {"some_column": 1}
Results in: SELECT * FROM example WHERE some_column = `some_column` = 1
Its this second example, that is likely to occur, yet might introduce a vulnerability. Looking at that WHERE
condition this breaks down into two comparisions some_column = some_column
which will resolve to true
since both are pointing to the same column, that is then compared with 1
which is a “truthy” value.
Maxwell Dulin encounted this within his blog’s authentication system:
async viewUserInfo(user,password){
//prepared statements prevent SQL injections
var query = "SELECT * FROM Users where username = ? AND password = ?";
const [rows, fields] = await pool.query(query, [user,password]);
return rows;
}
For this code, the user
value is passed in directly, but the password
will be hashed first, so it cannot be an unexpected object, but the user
can be. Which is exactly what the attack was.
{
"username": {
"username" : 1
},
"password":"<some_password>"
}
The query in this case will resolve to:
SELECT * From Users WHERE username = `username` = 1 AND password = <some-hash>
Leading to the first condition (username) being true
for all rows in the database, and then as long as one user has the password the second condition will also be true and the login will proceed.