CSRF Уязвимост, как да се справя с нея

georgi27

Registered
добър ден, след много бройно чете за CSRF тук намерих урок с Token Който добавих в формата за регистрация , но Acunetix не спря да реве за CSRF

PHP:
<?php require_once ('style.php');
head("yes");
headmes("no");
leftmenu("no");
?>



<script type="text/javascript" src="https://code.jquery.com/jquery-2.2.0.min.js"></script>  

<script type="text/javascript">
document.onkeydown = function (e) {
  if (e.keyCode === 116) {
    return false;
  }
};</script>


<script type="text/javascript" src="inc/js/passy.js"></script>	
	
<script language="javascript">
var xmlhttp

function showHint(str)
{
if (str.length==0)
{
document.getElementById("txtHint").innerHTML="";
return;
}
xmlhttp=GetXmlHttpObject();
if (xmlhttp==null)
{
alert ("Your browser does not support XMLHTTP!");
return;
}
var url="/chekuname.php";
url=url+"?q="+str;
url=url+"&sid="+Math.random();
xmlhttp.onreadystatechange=stateChanged;
xmlhttp.open("GET",url,true);
xmlhttp.send(null);
}

function stateChanged()
{
if (xmlhttp.readyState==4)
{
document.getElementById("txtHint").innerHTML=xmlhttp.responseText;
}
}

function GetXmlHttpObject()
{
if (window.XMLHttpRequest)
{
// code for IE7+, Firefox, Chrome, Opera, Safari
return new XMLHttpRequest();
}
if (window.ActiveXObject)
{
// code for IE6, IE5
return new ActiveXObject("Microsoft.XMLHTTP");
}
return null;
}
</script>
<?php
$ip = $_SERVER["REMOTE_ADDR"];
if ($_COOKIE['username']) { echo "<div class='success'>
			<p><center>Вие сте влязъл</p></center></div>"; } else {
$user = mysql_real_escape_string($_POST['user']);
$csnick = mysql_real_escape_string($_POST['csnick']);
$email = mysql_real_escape_string($_POST['mail']);
$pol = mysql_real_escape_string($_POST['pol']);
$pr = mysql_real_escape_string($_POST['agree']);
$god = mysql_real_escape_string($_POST['godini']);
$rank = mysql_real_escape_string($_POST['rank']);
$avatar = "/images/noavatar.png";
$opisanie = "Не е посочено!";
$web = "Не е посочено!";
$grad = mysql_real_escape_string($_POST['grad']);
$date = date('d.m.Y');
$time = date("H:i:s");
$mes_avtor = 'test site';
$mes_title = 'Добре дошли '.$site_name.'';
$mes_post = 'Добре дошли '.$site_name.'!
Забавлявайте се!
';
 if (isset($_POST['davai'])) {

		
		if(empty($_POST['user']) || empty($_POST['pass']) || empty($_POST['pass1'])){
		echo '<div class="error"><div class="txt"><center>Грешка! <a href="'.$pach.'register.php">Назад</a></center></div></div>';
		} else 
		if (empty(preg_match('#^(([a-z0-9!\#$%&\\\'*+/=?^_`{|}~-]+\.?)*[a-z0-9!\#$%&\\\'*+/=?^_`{|}~-]+)@(([a-z0-9-_]+\.?)*[a-z0-9-_]+)\.[a-z]{2,}$#i',$_POST['mail']))) 
		{
		echo'<div class="error"><div class="txt"><center>Не валиден емайл <a href="'.$pach.'register.php">Назад</a></center></div></div>';}
		else {
			$captcha = mysql_real_escape_string($_POST['capcode']);
			$cookie = mysql_real_escape_string($_COOKIE['capcode']);

			if("$capcode" !== "$cookie") { echo '<div class="error"><div class="txt"><center> Невалиден код <a href="'.$pach.'register.php">Назад</a></center></div></div>'; }
			else {
				if ($_POST['pass'] == $_POST['pass1']) {
					$pass = md5(md5($_POST['pass']));
						$chek = mysql_query("SELECT * FROM users WHERE username='$user'") or die(mysql_error());
						$chek = mysql_num_rows($chek);
			if ($chek == '1') { 
				echo '<div class="error"><div class="txt"><center>Този потребител е зает! <a href="'.$pach.'register.php">Назад</a></center></div></div>'; 
			} else {
				if (empty($_POST['skype'])) {
					$skype = "Не е посочено!";
				} else { 
					$skype = mysql_real_escape_string($_POST["skype"]);
				}
			if	(empty($_POST['web'])) {
					$web = "Не е посочено!";
				} else { 
					$web = mysql_real_escape_string($_POST["web"]);
				}
				if	(empty($_POST['yourname'])) {
					$yourname = "Не е посочено!";
				} else { 
					$yourname = mysql_real_escape_string($_POST["yourname"]);
				}
				if	(empty($_POST['csnick'])) {
					$csnick = "Не е посочено!";
				} else { 
					$csnick = mysql_real_escape_string($_POST["csnick"]);
				}
				if (empty($_POST['avatar'])) {
					$avatar = "/images/no-avatar.png";
				} else { 
					$avatar = mysql_real_escape_string($_POST["avatar"]);
				}	
if ($pol == "Мъж" || $pol == "Жена") {
					$pol = mysql_real_escape_string($_POST["pol"]);
				} else {
					$pol = "Не е посочено";
				}	
if (empty($_POST['grad'])) {
					$grad = "Не е посочено";
				} else { 
					$grad = mysql_real_escape_string($_POST["grad"]);
				}					
				mysql_query("INSERT INTO users (grad,username, password, email, skype, sex, godini, avatar, ip, rank, opisanie, date, time, web, csnick, yourname) VALUES('$grad','$user', '$pass', '$email', '$skype', '$pol', '$god', '$avatar', '$ip', '4','$opisanie', '$date', '$time', '$web', '$csnick', '$yourname')")or die(mysql_error());
				mysql_query("INSERT messages (user,avtor,title,post,date,time) VALUES ('$user','$mes_avtor','$mes_title','$mes_post','$date','$time')") or die(mysql_error());
			echo  '<div class="success"><p><center> Благодарим Ви <a href="'.$pach.'index.php">Назад</a></center></p></div>';
		} } else {
									echo '<div class="error"><div class="txt"><center> Нестана :) <a href="'.$pach.'register.php">Назад</a></center></div></div>';
				} 
 } }
} else {

		if(isSet($_POST['submit'])) {
if(isSet($_SESSION['token']) && $_POST['token'] == $_SESSION['token']) { //проверяваме ключа
echo 'ОК';
} else { //ако има проблем го връщваме в началната страница.
header("Location: ./index.php");
}
} else {
$token = md5(uniqid(rand(), true)); //генерираме нашия уникален ключ
$_SESSION['token'] = $token; //запазваме го в сесия
echo '	
	<form action="" method="post">
		<div class="border content">
			<div class="container-1">
				

<fieldset><input type="hidden" name="ip" value="<?php echo $ip; ?>">
 <div class="formElement">
					<div class="formFieldLabel">
						<label for="username">Потребителско име:<font color="red">*</font></label>
					</div>
					<div class="formField">
				<input type="text" class="inputText" name="user" value="" id="txt1" onkeyup="showHint(this.value)" maxlength="20">
						<div id="txtHint"></div>					</div>
					<div class="formFieldDesc">
						<p>Потребителското име трябва да бъде поне 3 символа и най-много 20.</p>
					</div>
				</div>
  <div class="formElement">
					<div class="formFieldLabel">
						<label for="csnick">CSnick:<font color="red">*</font></label>
					</div>
					<div class="formField">
						<input type="text" class="inputText" name="csnick" value=""/>
											</div>
					<div class="formFieldDesc">
						<p></p>
					</div>
				</div>
				  <div class="formElement">
					<div class="formFieldLabel">
						<label for="csnick">Парола:<font color="red">*</font></label>
					</div>
					<div class="formField">
						<input type="password" id="pass" class="inputText" name="pass" AUTOCOMPLETE="off" value="">
											</div>
					<div class="formFieldDesc">
						<p>	<script>$(\'#pass\').passStrengthify();</script></p>
					</div>
				</div>
<div class="formElement">
					<div class="formFieldLabel">
						<label for="confirmPassword">Потвърди парола:<font color="red">*</font></label>
					</div>
					<div class="formField">
						<input type="password" class="inputText" name="pass1" AUTOCOMPLETE="off" value=""  />
											</div>
					<div class="formFieldDesc">
						<p>Моля потвърдете вашата парола!</p>
					</div>
				</div>

	<div class="formElement">
					<div class="formFieldLabel">
						<label for="email">Имейл адрес:<font color="red">*</font></label>
					</div>
					<div class="formField">
						<input type="text" class="inputText" name="mail"/>
											</div>
					<div class="formFieldDesc">
						<p>Моля въведете вашият имейл адрес!</p>
					</div>
				</div>
				
				<div class="formElement">
					<div class="formFieldLabel">
						<label for="skype">Skype:</label>
					</div>
					<div class="formField">
						<input type="text" class="inputText" name="skype"/>
											</div>
					<div class="formFieldDesc">
						<p>Моля въведете вашият Skype!</p>
					</div>
				</div>
		<div class="formElement">
					<div class="formFieldLabel">
						<label for="avatar">Аватар:</label>
					</div>
					<div class="formField">
						<input type="text" class="inputText" name="avatar"/>
											</div>
					<div class="formFieldDesc">
						<p>Добавят се само с <font color="red">външен линк</font>!</p>
					</div>
				</div>
				
		

	<div class="formElement">
					<div class="formFieldLabel">
						<label for="skype">Пол:</label>
					</div>
					<div class="formField">
						<select name="pol" >
<option value="Мъж">Мъж</option>
<option value="Жена">Жена</option>
</select>
											</div>
					<div class="formFieldDesc">
						<p>Какъв пол сте</p>
					</div>
				</div>
	
				

	<div class="formElement">
					<div class="formFieldLabel">
						<label for="skype">Подредете картинката:</label>
					</div>
					<div class="formField">';

 if (!class_exists('KeyCAPTCHA_CLASS')) {
	
	include('keycaptcha_testsite_net.php');
}
$kc_o = new KeyCAPTCHA_CLASS();
echo $kc_o->render_js();
 
 if (!class_exists('KeyCAPTCHA_CLASS')) {
	
	include('keycaptcha_testsite_net.php');
}
$kc_o = new KeyCAPTCHA_CLASS();
if ($kc_o->check_result($_POST['capcode'])) {

}
else {
	
}							echo'		</div>
					<div class="formFieldDesc">
						<p></p>
					</div>
				</div>

  <div class="formSubmit">
  <input type="hidden" name="capcode" id="capcode" value="false" />
    <input type="hidden" name="token" value="' . $token . '" /><input type="submit" value="Регистрирай се!" id="newpass" class="button5" name="davai" />
			<input type="reset" accesskey="r" value="Рестарт" class="button5"/>
		</div>
 

  
</div>
		</div>	</fieldset>
	
	</form>';

}
 } } 


						


right_menu("no");
footer("yes");
?>

И постоянно ми излиза това

Код:
Attack details
Form name: <empty>
Form action: http://127.0.0.1/register
Form method: POST

Form inputs:

ip [Hidden]
user [Text]
csnick [Text]
pass [Password]
pass1 [Password]
mail [Text]
skype [Text]
avatar [Text]
pol [Select]
capcode [Hidden]
token [Hidden]
davai [Submit]
 
Не съм ти чел кода, водя се по въведението. Та, защо ти е CSRF защита на формата за регистрация?
 
Защото освен на тази форма и на другите из сайта който имам , acunetix си прави точно каквото си пожелае, прави си регистрации , спами из целия сайт и нямам желание както се случи преди време потребител да се регистрира и веднага да си добави точки в базата данни, несъм много запознат много с тези хакерски работи както и много неща съм позабравил в програмирането и започвам на ново . По интересното беше че като сканира сайта нямаше други оплаквания
 
CSRF няма да те спаси от това, някой да се регистрира в сайта ти и да си добави точки... нито пък от спама. Това е атака към потребителите (и към администраторите), не към приложението.

Още в началото на отговорът сетваш някакъв уникален ключ в бисквитката. Във формата слагаш скрито поле, което държи същият ключ. При постването сравняваш ключовете от бисквитката и от скритото поле, и ако всичко е наред - караш нататък с твоята си логика.
 
След много чете на логовете на apache въпросния потребител , сетва тези точки дирекно от тук през пост формата
PHP:
<?php
if (preg_match("'/inc/charge.php'", $_SERVER['SCRIPT_NAME'])) { header("Location: ../../../404.php");
die (); }

?>
<center>
<div id="container">
	<div class="mypets">Тарифа 1,20лв. (ДДС) => 10 Кредита (натиснете за повече информация)</div>
    <div class="thepet">
    <div id="linkbody">
    <?php echo "$tekst1";?>
	<?php
if(isset($_POST['ok'])) {
                $code = mysql_real_escape_string($_POST['code']);
        if(mobio_checkcode($servID1, $code) == 1) {
		mysql_query("INSERT INTO payments (userid, time, credits) VALUES ('".$user_id."', $timehook, '$credits1')") or die(mysql_error);
         mysql_query("UPDATE `users` SET `credits` = `credits` + $credits1 WHERE `id` = '".$user_id."'") or die(mysql_error);
                echo "<div class=\"system success\"><p>Бяха ви добавени $credits1 кредита</p></div>";
        }else{
                echo "<div class=\"system error\"><p>Грешен SMS код за достъп</p></div>";
        }
}else{
?>
<form method="post" name="smscode">
SMS Код: <input type="text" class="text" name="code">
<input type="submit" class="button5" name="ok" value="Добави"/>
</form>
<?php }?>		
        </div>
    </div>
</div>
<br><hr>
<div id="container">
	<div class="mypets">Тарифа 2,40лв. (ДДС) => 20 Кредитa (натиснете за повече информация)</div>
    <div class="thepet">
    <div id="linkbody">
    <?php echo "$tekst2";?>
	<?php
if(isset($_POST['ok1'])) {

                $code1 = mysql_real_escape_string($_POST['code1']);
        if(mobio_checkcode($servID2, $code1) == 1) {
		mysql_query("INSERT INTO payments (userid, time, credits) VALUES ('".$user_id."', $timehook, '$credits2')") or die(mysql_error);
                                mysql_query("UPDATE `users` SET `credits` = `credits` + $credits2 WHERE `id` = '".$user_id."'") or die(mysql_error);
                echo "<div class=\"system success\"><p>Бяха ви добавени $credits2 кредита</p></div>";
        }else{
                echo "<div class=\"system error\"><p>Грешен SMS код за достъп</p></div>";
        }
}else{
?>
<form method="post" name="smscode">
SMS Код: <input type="text" class="text" name="code1">
<input type="submit" class="button5" name="ok1" value="Добави"/>
</form>
<?php } ?>
            </div>
        </div>
    </div>
<br><hr>
<div id="container">
	<div class="mypets">Тарифа 4,80лв. (ДДС) => 40 Кредитa (натиснете за повече информация)</div>
    <div class="thepet">
    <div id="linkbody">
    <?php echo "$tekst3";?>
	<?php

if(isset($_POST['ok2'])) {

                $code2 = mysql_real_escape_string($_POST['code2']);
        if(mobio_checkcode($servID3, $code2) == 1) {
		mysql_query("INSERT INTO payments (userid, time, credits) VALUES ('".$user_id."', $timehook, '$credits3')") or die(mysql_error);
                                mysql_query("UPDATE `users` SET `credits` = `credits` + $credits3 WHERE `id` = '".$user_id."'") or die(mysql_error);
                echo "<div class=\"system success\"><p>Бяха ви добавени $credits3 кредита</p></div>";
        }else{
                echo "<div class=\"system error\"><p>Грешен SMS код за достъп</p></div>";
        }
}else{
?>
<form method="post" name="smscode">
SMS Код: <input type="text" class="text" name="code2">
<input type="submit" class="button5" name="ok2" value="Добави"/>
</form>
<?php }?>
            </div>
        </div>
    </div>
<br><hr>	
<div id="container">
	<div class="mypets">Тарифа 6,00лв. (ДДС) => 60 Кредитa (натиснете за повече информация)</div>
    <div class="thepet">
    <div id="linkbody">
    <?php echo "$tekst4";?>
	<?php

if(isset($_POST['ok3'])) {

              $code3 = mysql_real_escape_string($_POST['code3']);
        if(mobio_checkcode($servID4, $code3) == 1) {
		mysql_query("INSERT INTO payments (userid, time, credits) VALUES ('".$user_id."', $timehook, '$credits4')") or die(mysql_error);
                                mysql_query("UPDATE `users` SET `credits` = `credits` + $credits4 WHERE `id` = '".$user_id."'") or die(mysql_error);
                echo "<div class=\"system success\"><p>Бяха ви добавени $credits4 кредита</p></div>";
        }else{
                echo "<div class=\"system error\"><p>Грешен SMS код за достъп</p></div>";
        }
}else{
?>
<form method="post" name="smscode">
SMS Код: <input type="text" class="text" name="code3">
<input type="submit" class="button5" name="ok3" value="Добави"/>
</form>
<?php }
?>
            </div>
        </div>
    </div></center>
 
Ако mobio_checkcode() не е написана много умно или има достъп до $user_id, $timehook и/или $credits(1, 2, 3, 4), и ти не си ги санитизирал, ще стане много неприятно.
 
pix3l каза:
Ако mobio_checkcode() не е написана много умно или има достъп до $user_id, $timehook и/или $credits(1, 2, 3, 4), и ти не си ги санитизирал, ще стане много неприятно.
Според теб , как да го оправа, това е проверката

PHP:
function mobio_checkcode($servID, $code, $debug=0) {
$res_lines = file("http://www.mobio.bg/code/checkcode.php?servID=$servID&code=$code");
$ret = 0;
if($res_lines) {
if(strstr("PAYBG=OK", $res_lines[0])) {
$ret = 1;
}else{
if($debug)
echo $line."\n";
}
}else{
if($debug)
echo "Unable to connect to mobio.bg server.\n";
$ret = 0;
}
return $ret;
}

така взимам усер_ид

PHP:
$profile = "SELECT * FROM users WHERE username = 'mysql_real_escape_string($_COOKIE[username])'";
$profile = mysql_query($profile);
$profile = mysql_fetch_assoc($profile);
$user_id = mysql_real_escape_string($profile[id]);
 
Не мога да си спомня, PHP викаше ли функции, когато са написани така:

Код:
$profile = "SELECT * FROM users WHERE username = 'mysql_real_escape_string($_COOKIE[username])'";

Ако не - от тук може да се инжектира SQL. Провери дали вика функции, когато са в стринг, щото в момента нямам PHP да тествам. Online редакторите твърдят, че името на функцията просто става част от стринга.
 
pix3l каза:
Не мога да си спомня, PHP викаше ли функции, когато са написани така:

Код:
$profile = "SELECT * FROM users WHERE username = 'mysql_real_escape_string($_COOKIE[username])'";

Ако не - от тук може да се инжектира SQL. Провери дали вика функции, когато са в стринг, щото в момента нямам PHP да тествам. Online редакторите твърдят, че името на функцията просто става част от стринга.
Да, защото всичко между две кавички е стринг, интерполират се само променливите, не и функциите. Трябва да извадиш mysql_real_escape_string извън стринга:

PHP:
$profile = "SELECT * FROM users WHERE username = ' " . mysql_real_escape_string($_COOKIE["username"])." ' ";

Като трябва да се отбележи, че това е силно непрепоръчително. Трябва да се използват prepared statements, а параметрите да се подават на базата отделно.
 
anonimen каза:
pix3l каза:
Не мога да си спомня, PHP викаше ли функции, когато са написани така:

Код:
$profile = "SELECT * FROM users WHERE username = 'mysql_real_escape_string($_COOKIE[username])'";

Ако не - от тук може да се инжектира SQL. Провери дали вика функции, когато са в стринг, щото в момента нямам PHP да тествам. Online редакторите твърдят, че името на функцията просто става част от стринга.
Да, защото всичко между две кавички е стринг, интерполират се само променливите, не и функциите. Трябва да извадиш mysql_real_escape_string извън стринга:

PHP:
$profile = "SELECT * FROM users WHERE username = ' " . mysql_real_escape_string($_COOKIE["username"])." ' ";

Като трябва да се отбележи, че това е силно непрепоръчително. Трябва да се използват prepared statements, а параметрите да се подават на базата отделно.

Добре ще пробвам и ще видим какво ще се получи
 
georgi27 каза:
добър ден, след много бройно чете за CSRF тук намерих урок с Token Който добавих в формата за регистрация , но Acunetix не спря да реве за CSRF

Защо се доверяваш и разсъждаваш според софтуер, като Acunetix?

Пример: пусни за сканиране някой известен сайт и ще ти покаже дадени минуси в дизайна например и т.н... Не е решение!
Препоръчвам ти да го оставиш настрана, освен ако не желаеш, да "download-ваш" изображения и да виждаш останалата информация, което е доста оскъдна...

Ако имаш съмнения в кода на цялото уеб съдържание, по-добре се насочи към модулите, които извличат информация от базата.
И все пак не ми стана ясно, как "реве" Acunetix, но препоръчвам например да се информираш с - "що е то XSS". :?:
 

Горе