защита от 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 |
Това е само временна кръпка. За да спи спокойно е най добре да си прегледа сорс кода на приложението и да филтрира там както трябва входните данни. Но наистина е идейно за моментална реакция :) | | anonymousПет, 25.05.12, 10:09 |
Забравил си да споменеш, че горното работи САМО за Apache web server! | | insecteaterПет, 25.05.12, 10:27 | RE: защита от mysql injection
” Забравил си да споменеш, че горното работи САМО за Apache web server! „ По-точно за сървъри, които поддържат mod-rewrite или съвместим синтаксис. Което не се ограничава само с Apache | | 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("/;/", ";", $clearpost);
$clearpost = preg_replace("/\*/", "*", $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("/=/", "=", $clearpost);
$clearpost = preg_replace("/>/", ">", $clearpost);
$clearpost = preg_replace("/\'/", "'", $clearpost);
$clearpost = preg_replace("/\`/", "`", $clearpost);
$clearpost = preg_replace("/\"/", """, $clearpost);
// $clearpost = htmlspecialchars($clearpost);
if (!get_magic_quotes_gpc()) $clearpost = preg_replace('@\\\@', "\", $clearpost);
else {
$clearpost = stripslashes($clearpost);
$clearpost = preg_replace('@\\\@', "\", $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'] == 'Търси') { |
... „
Редактирах го вече, но се чудя как никой не ме е поправил за тази клавиатурна грешка? :) | | Коментар |