0

Using phpass to generate hashes, the following string is generated:

$2a$08$KHiiru4yzYh141GUh2xIMew//bCc7rxMuY1rtDApwA66/czIiurLi

Then a standard query:

"INSERT INTO su_auth ( 
                      AuthAlias, AuthUsername, 
                      AuthPass, 
                      AuthSessionID, AuthIP, AuthUserAgent
                    )
                    VALUES ( 
                      'Me', 'Myself',         
                      '$2a$08$KHiiru4yzYh141GUh2xIMew//bCc7rxMuY1rtDApwA66/czIiurLi', 
                       NULL, NULL, NULL
                    )"

A problem arises when the portion $KHiiru4yzYh141GUh2xIMew is viewed as an empty variable and submitted as such (i.e. a null value). The stored string is therefore: $2a$08//bCc7rxMuY1rtDApwA66/czIiurLi. Placing a backslash before the $ works, but is obviously not feasible.

Why does this happen within a quoted string? Why do the preceding $'s not trigger the same reaction? What can I do to prevent it?

Eamonn
  • 1,338
  • 2
  • 21
  • 53
  • 3
    [Use single quotes instead of double quotes for the query.](http://www.php.net/manual/en/language.types.string.php) – PeeHaa May 03 '14 at 12:30
  • @PeeHaa I can do that, but I also want to know why it's happening to that portion specifically, and not the other `$`'s – Eamonn May 03 '14 at 12:33
  • 2
    [Variablenames in PHP don't start with a number.](http://www.php.net/manual/en/language.variables.basics.php) – PeeHaa May 03 '14 at 12:43
  • Oh. Simple as. OK! If you want, submit an answer and I'll accept. – Eamonn May 03 '14 at 12:50

1 Answers1

1

The reason why you are seeing what you are seeing is because you use a double quoted string for the query. In PHP single quoted string are interpreted by PHP. So what happens in your case is that PHP reads the query and sees a variable $KHiiru4yzYh141GUh2xIMew.

This variable is never set obviously and as suck results in a notice:

Notice: Undefined variable: KHiiru4yzYh141GUh2xIMew in...

And will result in null (again because the variable is never set).

To see how PHP reads the string see this explain page.

Now to answer your question why the other $ are not being interpreted as variables. This has to do with the fact that PHP variables don't start with a number. So PHP knows $2 can never be a variable.

Valid variable names in PHP look like:

[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*

There is a way to let a variable start with a number in PHP though: ${'2a'} = 'foo';

So you have four choices to fix your code:

Use single quotes

'INSERT INTO su_auth ( 
     AuthAlias, AuthUsername, AuthPass, AuthSessionID, AuthIP, AuthUserAgent
 ) VALUES ( 
     \'Me\',
     \'Myself\',                                  
     \'$2a$08$KHiiru4yzYh141GUh2xIMew//bCc7rxMuY1rtDApwA66/czIiurLi\', 
     NULL, NULL, NULL
 )'

Concatenate

"INSERT INTO su_auth ( 
     AuthAlias, AuthUsername, AuthPass, AuthSessionID, AuthIP, AuthUserAgent
 ) VALUES ( 
     'Me',
     'Myself',                                  
     '". '$2a$08$KHiiru4yzYh141GUh2xIMew//bCc7rxMuY1rtDApwA66/czIiurLi' . "', 
     NULL, NULL, NULL
 )"

sprintf

echo sprintf("INSERT INTO su_auth (AuthAlias, AuthUsername, AuthPass, AuthSessionID, AuthIP, AuthUserAgent) VALUES ('Me', 'Myself', '%s', null, null, null)", '$2a$08$KHiiru4yzYh141GUh2xIMew//bCc7rxMuY1rtDApwA66/czIiurLi');

WHY ARE YOU USING YOUR DATA DIRECTLY IN YOUR QUERY??? Use prepared statements with bound parameters

$stmt = $connection->prepare('INSERT INTO su_auth (AuthAlias, AuthUsername, AuthPass, AuthSessionID, AuthIP, AuthUserAgent) VALUES (:AuthAlias, :AuthUsername, :AuthPass, :AuthSessionID, :AuthIP, :AuthUserAgent)');
$stmt->execute([
    'AuthAlias'     => 'Me',
    'AuthUsername'  => 'Myself',
    'AuthPass'      => '$2a$08$KHiiru4yzYh141GUh2xIMew//bCc7rxMuY1rtDApwA66/czIiurLi',
    'AuthSessionID' => null,
    'AuthIP'        => null,
    'AuthUserAgent' => null,
]);

Option four would be preferred.

Community
  • 1
  • 1
PeeHaa
  • 71,436
  • 58
  • 190
  • 262