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

Здравейте и аз имам въпрос. Четох преди време някъде че XSS може да заобиколи защитите като вместо <script> се използва кодираният еквивалент от типа на %3C%73%63%72%69%70%74%3E .Как може да се опазиме от подобна атака.
 
teroristd каза:
Здравейте и аз имам въпрос. Четох преди време някъде че XSS може да заобиколи защитите като вместо <script> се използва кодираният еквивалент от типа на %3C%73%63%72%69%70%74%3E .Как може да се опазиме от подобна атака.


htmlspecialchars(),addslashes()
 
еми точно това ми е мисълта че по този начин се преминава през htmlspecialchars() защото той преработва знаците така

■'&' (ampersand) becomes '&'
■'"' (double quote) becomes '"' when ENT_NOQUOTES is not set.
■''' (single quote) becomes ''' only when ENT_QUOTES is set.
■'<' (less than) becomes '<'
■'>' (greater than) becomes '>'

а по този начин няма да има проблеми с написването на скрипт надявам се да сте ме разбрали :twisted:

%3C%73%63%72%69%70%74%3E
 
rawurldecore/urldecode ти го декодира примера, ако това питаш.
После можеш да го минеш стринга през каквото си поискаш.

Най-добрата защита според мен е не да премахваш определени символи, а да пропускаш определени символи. Например само aplha/num.
 
Ето ти пример за защитена страница.
Код:
<?php
	function security_start_session($ssl, $timeout, $maxtime, $ip){
		// ... security checks
		session_start();
		session_regenerate_id(true);
		return 1;
	}
	if (security_start_session(0, 6*60, 20*60, 1) != 1){
		echo "<br>session destroyed!";
		return;
	}
?>
<html>
<head>
	<title>WorldBank.dom XSRF protected page</title>
</head>
<body>
<?php
	if( isset($_REQUEST['submit'])){
		if ($_SESSION['token']!=$_POST['token'] || !isset($_SESSION['token'] || !isset($_POST['token'])){
			session_unset();
			session_destroy();
			echo "Invalid session</body></html>";
			return;
		}
		else{
			echo 'Form is submitted';
		}
	}
	else{
		echo '<form action="xsrf.php" method="POST">';
		$_SESSION['token'] = uniqid(rand(), true);
		echo '<input type="hidden" name="token" value="'.$_SESSION['token'].'">';
		echo '<input type="submit" name="submit">';
		echo '</form><br><br><br>';
	}
?>
</body></html>


Тук се използва потребителска сесия ,което се прави в помечето случай
виж токените,от там сме сигурни ,че формата е изпълнена на нашия съврър.
Иначе
<?php
if( isset($_REQUEST['submit'])){
echo 'Form is submitted';
}
else {
echo '<form action="xsrf.php" method="POST">';
echo '<input type="submit" name="submit">';
echo '</form><br><br><br>';
}
?>

Това е незащитената форма.
Ако напишем
Код:
<form action="saita ti/xsrf.php" method="POST">
<input type="submit" name="submit">
</form>
и го изпълним на друг сървър формата пак ще бъде изпратена.


Другият начин е чрез „$_SERVER['HTTP_REFERER']„.
От там проверяваме от къде е дошла заявката..
Код:
if (isset($_SERVER['HTTP_REFERER'] && $_SERVER['HTTP_REFERER']!="http://worldbank.dom/xsrf.php"){
				echo 'You are redirected by third party form - probably you are a XSRF attack victim!';
				return;
			}
 
Според мен най добрият начин за криптиране на парола.
Код:
<?php
$pass = '123456';
$md5 = md5('123456' . $pass . '123456');	
$md5e = md5($md5);
echo $md5e;
?>
Пробвайте да я кракнете ^^
 
Освен че прави offline атаката два пъти по-бавна заради двете md5 операции и че salt-овете "123456" обезсмислят до известна степен атака rainbow таблици, този алгоритъм не предоставя кой знае какви предимства пред md5 хеш функцията приложена веднъж. Освен ако не разчиташ на това, че атакуващият не знае алгоритъма, което е tricky - щом може да се добере до хешовете ти, твърде вероятно има достъп и до PHP сорса и може да види как се прави. Да разчиташ че няма да го направи означава, че вярваш в идеята за "security through obscurity".


В общият случай, паролите се подсилват срещу offline атаки, ползвайки key derivation функции като PBKDF2. Тъй като PHP разработчиците никога не са били силно загрижени за сигурността на PHP приложенията, и досега няма вградена PBKDF2 функция в езика. Разбира се, има опити за нещо подобно, примерно това:

http://www.openwall.com/phpass/

което между другото се използва в по-новите версии на wordpress и phpbb.


И все пак, PBKDF2 е по-сигурен алгоритъм и по-гъвкав: освен броя итерации можеш да използваш различен хеш алгоритъм и дължината на изходният низ е контролируема. В идеалният случай, дължината на изходната стойност трябва да е равна на дължината на изхода от използваната хеш функция (20 байта при SHA1, 16 при MD5).

Колкото по-голям брой итерации ползваш, толкова повече време ще отнеме на тези които атакуват хеша да открият паролата. При стойности от 10-20 хиляди, най-вероятно ще ги откажеш. Единственият проблем е че ако имаш натоварен сайт, в който често се автентицират потребители, можеш да изтормозиш сървъра.

P.S ето ти PBKDF2 имплементация на PHP:

http://www.itnewb.com/v/Encrypting-Passwords-with-PHP-for-Storage-Using-the-RSA-PBKDF2-Standard
 
RSA доста тормози сървъра наистина. За добър баланс между производителност и защита може да ползваш sha256 примерно с различен salt.
 
Това няма нищо общо с RSA алгоритъма, а е един от стандартите (PKCS5), които се разработват от RSA Security.

Идеята на PBKDF2 е следната: имаш salt, имаш парола, последователно хешираш паролата+salt-а определен брой пъти, да речем 1000 пъти. Крайният резултат е хешираната парола. Този определен брой пъти се контролира - колкото по-голям е, толкова повече време се bruteforce-ва низа.

Разбира се, нещата са малко по-сложни: вместо да прави md5(pass,salt) или нещо от сорта, при PBKDF2 се ползва HMAC функция, което на практика е сходно, само дето и паролата и salt-а се pad-ват докато дължината им не стане определена.

RSA (или каквато и да е друга асиметрична криптография), няма нищо общо с това.
 
Наистина доста полезно е това със PBKDF2. И не всеки път може да има досъп до соурс кода защото аката може да е от типа SQLi ,но все пак си прав.
Доста интересен код е накрая се получава това
n&=��n��荮��fR'gGޞ�"j��I��
o.o Това вече ми се струва невъзможно. :D
 
Да, това е грозно, ако трябва да влиза в SQL база, трябва първо да се мине през base64_encode().

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

Вариант 1: всички хешове от базата ползват различни salt-ове. Тогава за всеки низ, трябва да го хеширам, ползвайки различен salt и да сравнявам резултата със съответния хеш от базата. Ако m ни е времето за хеширане на един низ, n ни е броят хешове в базата и x ни е крайния брой низове, които пробваме да хешираме, времето за което ще се изпълни атаката е:

T = m*n*x


Вариант 2: всички хешове от базата ползват един и същ salt. Тогава е абсолютно достатъчно да хеширам низа и да сравня резултата с всеки хеш от базата, т.е времето за атаката ни става:

T = m*x

демек не зависи от броя хешове в базата. Ако в базата има 1000 хеширани пароли, то една bruteforce или dictionary атака ще отнеме 1000 пъти повече време за атакуващият при положение че се ползват различни salt-ове. Сами си правете сметките има ли смисъл или няма смисъл :)

Така че да се salt-ва с низ-константа ("12345") не е много добра идея :)

Та оттук следва другият извод: винаги salt-а трябва да е различен. Най-добре е да се ползва някакъв генератор за псевдослучайни числа.
 
като се направи с rand(), салта трябва да се запише някъде.
Следователно - обезсмисля се :)
 
Няма проблем salt-а да се пази в cleartext - така или иначе това се налага :)

С rand() директно може, но има едно ограничение, защото генерираните числа са с максимална големина RAND_MAX, демек 4 милиарда или до 10 символа.

Между другото, генераторите за псевдослучайни числа имат други слабости, но те не касаят толкова хеширането на пароли. Ето едно такава ситуация, където при положение че на един хост имаш инсталиран php-nuke и punbb, можеш да ресетнеш админската парола на punbb и да "предскажеш" новогенерираната със 100% сигурност:

http://www.gat3way.eu/index.php?mact=News,cntnt01,detail,0&cntnt01articleid=98&cntnt01returnid=55

http://www.gat3way.eu/index.php?mact=News,cntnt01,detail,0&cntnt01articleid=99&cntnt01returnid=55

Обяснено е горе-долу добре, има сорс код на "експлойта", както и видео, което го демонтрира.
 
За salt на потребителска парола обикновенно ползвам потр. име или негово производно. Няма смисъл да записвам информация в още едно поле.
 
Аз пък все си мисля, че ако има 1 поленце, което да взима time() в момента, в който е регистриран потребителя ще свърши доста полезна работа :)

Примерно кодче:
Код:
<?php
$username = "t0m3kk"; //Потребителското име
$password = "web-tourist"; //Паролата, която въвежда потребителя
$regtime = "1278776019"; //Момента, в който избрах да извърша теста!
$pass = md5($regtime.$username.$password);

echo $pass; 
?>

Даже си мисля, че и това би свършило работа... примерно:
Код:
<?php
$user = substr("t0m3kk", 1, -1);
$pass = substr("web-tourist", 2, -2);
$pass = md5($user.$pass);
echo "$pass";
?>

като по всяко време може да се добави и нещо от сорта на...
Код:
$host = explode(".", $_SERVER['SERVER_ADDR']);
$pass = md5($host[0].$user.$host[1].$pass.$host[2]);

Просто не виждам смисъл какво толкова се притеснявате как да хеширате паролите си :) Нещо такова (особенно като това последното) би отказало доста голяма част от "хакерите" :)

като ако искате да ползвате $host[3] може да си добавите примерно още нещо, за да ви стане от сорта на:
Код:
$pass = md5($host[0].$user.$host[1].$pass.$host[2].$something.$host[3]);

Общо взето ще го върне в първи клас даже може и в предучилищната освен ако не знае начина ви на криптиране :)
 
И какво ще стане като решиш да си смениш хостинга? Ще пазиш в базата за всеки акаунт какво е било IP-то на сървъра когато е създаван?

Хора, не правете грешката да преоткривате колелото и да си измисляте собствени password hashing алгоритми - в повечето случаи няма да го направите по-добре, отколкото неща, които са измисляни от големите глави, минавали много пъти peer review, атакувано от много хора неуспешно и доказано в практиката.

А това да вярваш, че лошите няма как да разберат какво правиш е малко безумно. В смисъл аз не си го позволявам, а работата ми е да пиша приложения на C. PHP е интерпретаторен език и който може да ти отвори файла, ще си го прочете, без да му се налага да ползва за целта gdb, ollydbg и да се дзвери в дизасембирания код. И наистина, не можеш да си сигурен че лошите няма да ти изчетат сорса, просто защото не зависи от теб. От теб зависи единствено сигурността на уеб-приложението - като го качиш на споделен хостинг, не можеш да знаеш кое друго уеб приложение ще пробият. Не можеш да си сигурен как се администрира сървъра и дали няма малоумни грешки в конфигурацията, която да даде на лошите административен достъп. Всъщност, дори не знаеш дали няма да ти троянизират машината и да ти вземат FTP акаунта с който си качваш сайта на хостинга.
 

Back
Горе