download.bg
 Вход Списание  Новини  Програми  Статии  Форум  Чат   Абонамент  Топ95   Архив 

защита от mysql injection

Автор
Съобщение
anonymous
Пет, 25.05.12, 01:59
Преди около час ме събуди една позната. Хакват ми сайта, помагай. Няма да Ви занимавам с глупости. Но накратко. Оказа се, че е mysql injection. Променяха имената на снимките в базата данни с линкове към някакви порно снимки.
Така и така съм буден, поне да споделя как да се опазите от подобна атака.
В .htaccess слагате следния код:
Options -Indexes
Options +FollowSymlinks
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{QUERY_STRING} union [NC,OR]
RewriteCond %{QUERY_STRING} select [NC,OR]
RewriteCond %{QUERY_STRING} truncate [NC,OR]
RewriteCond %{QUERY_STRING} drop [NC,OR]
RewriteCond %{QUERY_STRING} update [NC]
RewriteRule .* %{REQUEST_URI}? [R,L]
</IfModule>

99, 9% сте защитени :)
За останалия 0,01% (не е за подценяване!) винаги филтрирайте данните подавани от потребителя. За да няма изненади.
Надявам се да Ви е от полза.

insecteater
Пет, 25.05.12, 09:44
Това е само временна кръпка. За да спи спокойно е най добре да си прегледа сорс кода на приложението и да филтрира там както трябва входните данни.

Но наистина е идейно за моментална реакция :)

редактиран от insecteater на 25.05.12 09:44
anonymous
Пет, 25.05.12, 10:09
Забравил си да споменеш, че горното работи САМО за Apache web server!
insecteater
Пет, 25.05.12, 10:27

RE: защита от mysql injection

” Забравил си да споменеш, че горното работи САМО за Apache web server! „

По-точно за сървъри, които поддържат mod-rewrite или съвместим синтаксис. Което не се ограничава само с Apache

редактиран от insecteater на 25.05.12 10:27
anonymous
Пет, 25.05.12, 10:46
Например на nginx няма да стане, той си поддържа mod-rewrite, но с друг синтаксис. Както и да е, няма да флуудя в темата на човека.
insecteater
Пет, 25.05.12, 10:50
Ако имаш идея там как става, може да го копнеш тук. Би било полезно.
anonymous
Съб, 21.07.12, 01:18

RE: защита от mysql injection

” Забравил си да споменеш, че горното работи САМО за Apache web server! „
download_er, Приемам забележката. Може би поради късния час тогава, или че съм разглеждал нейния частен случай. Но, да. Действително това е само за Apache.
anonymous
Съб, 21.07.12, 02:06

RE: защита от mysql injection

” Това е само временна кръпка. За да спи спокойно е най добре да си прегледа сорс кода на приложението и да филтрира там както трябва входните данни.

Но наистина е идейно за моментална реакция :) „

Не винаги е нужно да се филтрират данните подавани от потребителя. По някой път е идейно да се филтрират данните когато се изкарват от базата данни. Разбира, се входящи данни, които се използват за проверка(да се намери нещо и изведе от базата) винаги се филтрират.
Например:
<FORM method="post" action="">
    <input type="text" name="searchFor" /> <input type="submit" name="search" value="Търси" />
</FORM>
<?php
    // code code code
 
    if (isset($_POST['search']) && $_POST['search'] == 'Търси') {
        $query = mysql_query("SELECT * FROM sometable WHERE somerow='$_POST[searchFor]'");
        // code code code
    }

Това е ясно, че е убийствена грешка и задължително трябва да мине през филтър преди да се обърнем към базата данни.

Но, ако имаш за цел да изведеш примерно, колко инча е даден монитор:
// Това малко по- късно ще изглежда по друг начин
echo '<td>Монитор:</td><td>' . $row['monitor'] . '</td>';

А, формата за въвеждане е:
// И това ще има малка промяна
echo '<td>Монитор:</td><td><input type="text" name="monitor" value="' . $monitor . '" /></td>';

То, нямаме никаква представа как ще въведе потребителя инчовете. Дали ще е единична или двойна кавичка, или ще напише инч., или каквото и да е.
Нека да съставим и кода (извинявам се, че ти ги пиша тея неща. Ти си ги знаеш. Но просто за другите) за да е по- лесно обяснимо.
<?php
    // code code 
    $monitor = $_POST['monitor'];
    // code code
    if ($err) { // нещо се е объркало при проверките
        echo '<script>alert("' . $err . '");</script>';
        $_POST['input_date'] = 'active';
    } else {
        if (mysql_query("INSERT INTO sometable (name, anywhere, monitor, matrix, somestuff) VALUES ('$name', '$anywhere', '$monitor', '$matrix', '$somestuff')"))
             // всичко е ок, нека потребителя да знае
    }
    //code code
    if ($_POST['input_date']) { // тука е формата за въвеждане на данните
        // code
        echo '<td>Монитор:</td><td><input type"text" name="monitor" value="' . $monitor . '" /></td>';
        // още код
    }
    // code code
?>

Ето в този пример вкарваме данните директно в базата данни. Разбира се, проверка дали е въвел нещо потребителя и/или дали то има нужната дължина да. Но това зависи от случая. И все пак, ако е пропуснал да въведе данните за монитора например(инчовете), но е въвел всички останали искани(примерно 25 наброй, като модел. марка и т.н.) извеждаме му съобщението за грешката и го хвърляме пак във формата за въвеждане. Не е желателно да искаме пак да въвежда всички данни. Затова и сме сложили value. Но какво става, ако преди това сме филтрирали данните за $monitor. Виждаме се в приключение за да изведем у формата това, което е въвел, точно защото не знаем единична, двойна кавичка или нещо други е използвал.
Ето за това го оставяме без филтър като въвежда, но филтрираме при извеждането:
echo '<td>Монитор:</td><td><input type"text" name="monitor" value="' . htmlspecialchars ($monitor, ENT_QUOTES) . '" /></td>';

Така без значение какво е въвел ще се визуализира правилно, без риск за нас. Съответно и:
// Това малко по- късно ще изглежда по друг начин
echo '<td>Монитор:</td><td>' . $row['monitor'] . '</td>';

ще стане на:
// Това малко по- късно ще изглежда по друг начин
echo '<td>Монитор:</td><td>' . htmlspecialchars($row['monitor'], ENT_QUOTES) . '</td>';

Разбира се това е само един пример. Както и избора на htmlspecialchars е според примера.
Просто исках да покажа, че не винаги е нужно да се филтрират данните подавани от потребителя, а че по някой път е по- удачно да се филтрират при извеждането им.

редактиран от anonymous на 21.07.12 02:08
редактиран от anonymous на 07.08.12 01:53
phrozencrew
Съб, 21.07.12, 18:33
Хубави идеи сте пуснали. Ще се включа и аз с една функция, която превръща $_POST в масив post.
function post($submit){
	if(isset($_POST[$submit])){
	 foreach (array_keys($_POST) as $key){
	  $clearpost = $_POST["$key"];
	  if(preg_match('/submit|fleUpload/i',$key)) continue;
	  $clearpost = preg_replace('@delete|select|insert|update|where@i',"", $clearpost);
	  //$clearpost = preg_replace('/[\x7f-\xff]/', "", $clearpost); // Clear Dirty Data
	  //$clearpost = preg_replace("/хуй|hui|fuck|eba|дейба|ейба|еба|pedal|педал|педераст|педи|майка|maika|тъп|мама/i", "", $clearpost); // Clear Spam
	  $clearpost = preg_replace("/;/", "&#59;", $clearpost);
	  $clearpost = preg_replace("/\*/", "&#42;", $clearpost);
	  $clearpost = preg_replace("/\r\n/", "<br />", $clearpost);
	  $clearpost = preg_replace("/\r/", "<br />", $clearpost);
	  $clearpost = preg_replace("/\n/", "<br />", $clearpost);
	  $clearpost = preg_replace("/</", "<", $clearpost);
	  $clearpost = preg_replace("/=/", "&#61;", $clearpost);
	  $clearpost = preg_replace("/>/", ">", $clearpost);
	  $clearpost = preg_replace("/\'/", "&#39;", $clearpost);
	  $clearpost = preg_replace("/\`/", "&#96;", $clearpost);
	  $clearpost = preg_replace("/\"/", """, $clearpost);
	  // $clearpost = htmlspecialchars($clearpost);
	  if (!get_magic_quotes_gpc()) $clearpost = preg_replace('@\\\@', "&#92;", $clearpost);
	  else {
	   $clearpost = stripslashes($clearpost);
	   $clearpost = preg_replace('@\\\@', "&#92;", $clearpost);
	  }
 
	  $allpost[$key] = $clearpost;
	 }
	 return $allpost;
	}
	else {
		echo "ГРЕШКА при get post!";
		return 1;
	}
}

Използвам функцията по следния начин:
if (isset($_POST["submit"])){
$post = post("submit");
// сега $post става масив с всички полета
...
$post["fieldname"] }

От базата данни измъквам взимам полетата така:
$var = html_entity_decode($var,ENT_QUOTES);

Използвам и някои допълнителни функции, които да ми помогнат. Примерно за превръщането на <br /> в нов ред:
function br2nl($string){
    return preg_replace('/\<br(\s*)?\/?\>/i', "\n", $string);
}

anonymous
Вто, 07.08.12, 01:52

RE: RE: защита от mysql injection

” ...
if (isset($_POST['search]') && $_POST['search'] == 'Търси') {

...

Редактирах го вече, но се чудя как никой не ме е поправил за тази клавиатурна грешка? :)

Коментар

за нас | за разработчици | за реклама | станете автори | in english  © 1998-2024   Experta Ltd.