Насколько опасен этот код PHP? - PullRequest
3 голосов
/ 06 марта 2009

Насколько опасен этот php код? Что с этим можно сделать?

$name = $_POST["user"];
$pwd = $_POST["pwd"];
$query = "SELECT name,pwd FROM users WHERE name = '$name' AND pwd = '$pwd'";

Ответы [ 13 ]

24 голосов
/ 06 марта 2009

Возможные проблемы:

  1. SQL-инъекция
  2. XSS Injection (если бы этот код был запросом на вставку, это было бы определенной проблемой)
  3. Простой текстовый пароль

Ваш оператор SQL может быть проблематичным. Это плохая практика - оставлять себя открытым для SQL-инъекций.

Внедрение SQL плохо . Поверь мне.

Если вы хотите отобразить $ user на HTML-странице, вы можете не захотеть включать возможность "взломать" ваш макет, введя такие команды как

<H1>HI MOM</H1>

или куча javascript .

Кроме того, никогда не храните свой пароль в виде обычного текста (хорошо, поймайте cagcowboy!). Это дает слишком много полномочий людям, управляющим (или взламывающим) вашу базу данных. Вы никогда не должны знать чей-либо пароль.

Попробуйте такую ​​тактику:

// mostly pulled from http://snippets.dzone.com/posts/show/2738
function MakeSafe($unsafestring) 
{
    $unsafestring= htmlentities($unsafestring, ENT_QUOTES);

    if (get_magic_quotes_gpc()) 
    { 
        $unsafestring= stripslashes($unsafestring); 
    }

    $unsafestring= mysql_real_escape_string(trim($unsafestring));
    $unsafestring= strip_tags($unsafestring);
    $unsafestring= str_replace("\r\n", "", $unsafestring);

    return $unsafestring;
} 

// Call a function to make sure the variables you are 
// pulling in are not able to inject sql into your 
// sql statement causing massive doom and destruction.

$name = MakeSafe( $_POST["user"] );
$pwd = MakeSafe( $_POST["pwd"] );

// As suggested by cagcowboy: 
// You should NEVER store passwords decrypted.
// Ever.  
// sha1 creates a hash of your password
// pack helps to shrink your hash
// base64_encode turns it into base64
$pwd = base64_encode(pack("H*",sha1($pwd)))
14 голосов
/ 06 марта 2009

Это так опасно: xkcd bobby tables

12 голосов
/ 06 марта 2009

Этот код очень безопасен, если вы никогда не передадите $ query в базу данных SQL.

12 голосов
/ 06 марта 2009

Кроме SQL-инъекций, похоже, что ваши пароли могут храниться в виде обычного текста, что не очень хорошо.

3 голосов
/ 06 марта 2009

Он не только подвержен SQL-инъекциям, но и не будет работать в тех случаях, когда инъекция даже не предназначена:

Например, пользователю нужно имя «Гийом Франсуа Антуан, маркиз де Лоспиталь». Поскольку имя пользователя содержит кавычку и вы не можете ее избежать, ваш запрос не будет выполнен, хотя пользователь никогда не хотел взламывать систему!

Либо используйте PDO , либо делайте это следующим образом:

<code>$query = sprintf(
                   "SELECT 1 FROM users WHERE name = '%s' AND password = '%s'",
                   mysql_real_escape_string($_POST['name']),
                   mysql_real_escape_string(md5($_POST['password']))
                 );
3 голосов
/ 06 марта 2009

Если бы вы опубликовали 0';drop table users;-- для имени

ваша команда в конечном итоге будет

select name, pwd form users where name='0'; 
drop table users; --'and pwd = '[VALUE OF PWD]'

Итак, сначала он получит ваши данные, затем уничтожит вашу таблицу пользователей и ничего не сделает с остальными, поскольку это комментарий.

Некоторые команды mysql в php будут выполнять несколько запросов при передаче sql, лучший способ избежать этого - параметризованные запросы.

Я использую PDO для доступа к БД и очень рекомендую его. У меня нет ссылок на макушку, но я помню учебники, которые я использовал в топе Google.

2 голосов
/ 06 марта 2009

Верьте или нет, это безопасно ... если magic_quotes_gpc включен. Которого никогда не будет в PHP6, поэтому исправление до этого является хорошей идеей.

1 голос
/ 06 марта 2009
  1. $_POST['user'] = "' or 1=1; --"; Любой получает мгновенный доступ к вашему приложению

  2. $_POST['user'] = "'; DROP TABLE user; --"; Поцелуй свой (платный?) Список пользователей до свидания

  3. Если вы позже отобразите $ name в своих выходных данных, это может привести к атаке с внедрением XSS

0 голосов
/ 06 марта 2009

Когда пользовательские данные вызываются в запросе SQL, всегда санируйте данные с помощью mysql_real_escape_string.

Кроме того, вы должны хранить только соленый хеш пароля вместо самого пароля. Вы можете использовать следующую функцию для генерации и проверки соленого хэша со случайным значением соли:

function saltedHash($data, $hash=null)
{
    if (is_null($hash)) {
        $salt = substr(md5(uniqid(rand())), 0, 8);
    } else {
        $salt = substr($hash, 0, 8);
    }
    $h = $salt.md5($salt.$data);
    if (!is_null($hash)) {
        return $h === $hash;
    }
    return $h;
}

Все вместе:

$query = 'SELECT pwd FROM users WHERE name = "'.mysql_real_escape_string($_POST['user']).'"';
$res = mysql_query($query);
if (mysql_num_rows($res)) {
   $row = mysql_fetch_assoc($res);
   if (saltedHash($_POST["pwd"], $row['pwd'])) {
       // authentic
   } else {
       // incorrect password
   }
} else {
   // incorrect username
}
0 голосов
/ 06 марта 2009

Это небезопасно, вы можете посмотреть что-то вроде PDO PHP PDO

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...