Mysql
 sql >> Baza danych >  >> RDS >> Mysql

Czy mysql_real_escape_string() i mysql_escape_string() są wystarczające do zapewnienia bezpieczeństwa aplikacji?

@Charles jest bardzo poprawny!

Narażasz się na wiele rodzajów znanych Ataki SQL, w tym, jak wspomniałeś

  • Wstrzyknięcie SQL:Tak! Mysql_Escape_String prawdopodobnie STILL sprawia, że ​​jesteś podatny na iniekcje SQL, w zależności od tego, gdzie używasz zmiennych PHP w swoich zapytaniach.

Rozważ to:

$sql = "SELECT number FROM PhoneNumbers " .
       "WHERE " . mysql_real_escape_string($field) . " = " . mysql_real_escape_string($value);  

Czy można w ten sposób bezpiecznie i dokładnie uciec? NIE! Czemu? ponieważ haker nadal może to zrobić:

Powtórz za mną:

mysql_real_escape_string() jest przeznaczony tylko do ucieczki danych zmiennych, NIE nazwy tabel, nazwy kolumn, a zwłaszcza nie LIMIT pól.

  • LIKE exploity:LIKE „$data%”, gdzie $data może być „%”, co zwróci WSZYSTKIE rekordy… co może być bardzo dobrze luka w zabezpieczeniach... wyobraź sobie wyszukiwanie według ostatnich czterech cyfr karty kredytowej... Ups! Teraz hakerzy mogą potencjalnie otrzymać każdy numer karty kredytowej w Twoim systemie! (BTW:Przechowywanie pełnych kart kredytowych rzadko jest zalecane!)

  • Exploity Charset:bez względu na to, co mówią hejterzy, Internet Explorer jest nadal , w 2011 roku, podatny na exploity zestawu znaków, a to jest jeśli poprawnie zaprojektowałeś stronę HTML, z odpowiednikiem <meta name="charset" value="UTF-8"/> ! Ataki te są BARDZO paskudne, ponieważ dają hakerowi taką samą kontrolę, jak zwykłe zastrzyki SQL:np. pełny.

Oto przykładowy kod demonstrujący to wszystko:

// Contains class DBConfig; database information.
require_once('../.dbcreds');                       

$dblink = mysql_connect(DBConfig::$host, DBConfig::$user, DBConfig::$pass);
mysql_select_db(DBConfig::$db);
//print_r($argv);

$sql = sprintf("SELECT url FROM GrabbedURLs WHERE %s LIKE '%s%%' LIMIT %s",
               mysql_real_escape_string($argv[1]),
               mysql_real_escape_string($argv[2]),
               mysql_real_escape_string($argv[3]));
echo "SQL: $sql\n";
$qq = mysql_query($sql);
while (($data = mysql_fetch_array($qq)))
{
        print_r($data);
}

Oto wyniki tego kodu po przekazaniu różnych danych wejściowych:

$ php sql_exploits.php url http://www.reddit.com id
SQL generated: SELECT url FROM GrabbedURLs 
               WHERE url LIKE 'http://www.reddit.com%'
               ORDER BY id;
Returns: Just URLs beginning w/ "http://www.reddit.com"

$ php sql_exploits.php url % id
SQL generated: SELECT url FROM GrabbedURLs 
               WHERE url LIKE '%%' 
               ORDER BY id;
Results: Returns every result Not what you programmed, ergo an exploit --

$ php sql_exploits.php 1=1'http://www.reddit.com ' id Results:Zwraca każdą kolumnę i każdy wynik.

Następnie są NAPRAWDĘ paskudne exploity LIMIT:

$ php sql_exploits.php url 
> 'http://www.reddit.com'
> "UNION SELECT name FROM CachedDomains"
Generated SQL: SELECT url FROM GrabbedURLs 
               WHERE url LIKE 'http://reddit.com%' 
               LIMIT 1 
               UNION
               SELECT name FROM CachedDomains;
Returns:  An entirely unexpected, potentially (probably) unauthorized query
          from another, completely different table. 

To, czy rozumiesz SQL w atakach, czy nie, jest nieistotne. Wykazało to, że mysql_real_escape_string() jest łatwe omijane przez nawet najbardziej niedojrzałych hakerów. To dlatego, że jest to REAKTYWNY mechanizm obronny. Naprawia tylko bardzo ograniczone i ZNANE luki w bazie danych.

Wszelkie ucieczki NIGDY nie będą wystarczające do zabezpieczenia baz danych. W rzeczywistości możesz jawnie REAGOWAĆ na każdy ZNANY exploit, a w przyszłości Twój kod najprawdopodobniej stanie się podatny na ataki wykryte w przyszłości.

Właściwa i jedyna (naprawdę) obrona jest PROAKTYWNA:Użyj przygotowanych oświadczeń. Przygotowane instrukcje są projektowane ze szczególną starannością, tak aby wykonywany był TYLKO prawidłowy i ZAPROGRAMOWANY SQL. Oznacza to, że jeśli zostanie wykonane poprawnie, szanse na wykonanie nieoczekiwanego kodu SQL są radykalnie zmniejszone.

Teoretycznie przygotowane instrukcje, które są doskonale zaimplementowane, byłyby odporne na WSZYSTKIE ataki, znane i nieznane, ponieważ są techniką PO STRONIE SERWERA, obsługiwaną przez SAME SERWERY BAZ DANYCH oraz biblioteki, które współpracują z językiem programowania. Dlatego ZAWSZE masz gwarancję, że będziesz chroniony przed KAŻDYM ZNANYM HAKEM, co najmniej.

I to mniej kodu:

$pdo = new PDO($dsn);

$column = 'url';
$value = 'http://www.stackoverflow.com/';
$limit = 1;

$validColumns = array('url', 'last_fetched');

// Make sure to validate whether $column is a valid search parameter.
// Default to 'id' if it's an invalid column.
if (!in_array($column, $validColumns) { $column = 'id'; }


$statement = $pdo->prepare('SELECT url FROM GrabbedURLs ' .
                           'WHERE ' . $column . '=? ' .
                           'LIMIT ' . intval($limit));
$statement->execute(array($value));
while (($data = $statement->fetch())) { }

Teraz to nie było takie trudne, prawda? I to czterdzieści siedem procent mniej kodu (195 znaków (PDO) vs 375 znaków (mysql_). Nazywam to „pełnym wygranej”.

EDYCJA:Aby rozwiązać wszystkie kontrowersje, które wywołała ta odpowiedź, pozwól mi powtórzyć to, co już powiedziałem:

Korzystanie z przygotowanych instrukcji pozwala na wykorzystanie środków ochronnych samego serwera SQL, a zatem jesteś chroniony przed rzeczami, o których wiedzą ludzie zajmujący się serwerem SQL. Dzięki temu dodatkowemu poziomowi ochrony jesteś o wiele bezpieczniejszy niż zwykła ucieczka, bez względu na to, jak dokładna.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Eksportuj dane z bazy danych MySQL

  2. Jak uzyskać wiele zliczeń za pomocą pojedynczego zapytania w MySQL?

  3. Łączenie się ze zdalnym serwerem MySQL za pomocą PHP

  4. Błąd nieznanej kolumny w 'liście pól' w zapytaniu MySQL Update

  5. Jak zarządzać sesjami w Node.js za pomocą Passport, Redis i MySQL