Ru-Board.club
← Вернуться в раздел «Web-программирование»

» Безопасное программирование на PHP

Автор: Cheery
Дата сообщения: 16.09.2009 19:29
israel_rider

Цитата:
Нельзя ли послать Вам этот файл, что бы Вы на него посмотрели?

выкладываем на файлообменник и даем ссылку тут. и все личные вопросы в ПМ
Автор: israel_rider
Дата сообщения: 30.09.2009 00:36
Пипл. Вот такой вопрос. Сайт, с которым я работаю выполнен так, что в адресной строке не виден реальный путь к файлу. В корне лежит htaccess, в котором куча инструкций rewrite. На сайте я устанавливаю биллинговую страничку для оплаты через кредитки через процессинговую фирму. Связь осуществляется через https.

Поскольку протокол https, и поэтому все ссылки, связывающие страничку с сайтом должны быть абсолютные, страничку я делаю отдельно. Делать её как динамическую часть сайта проблематично. То есть она у меня будет как бы… полустатическая…, то есть работающая как бы отдельно от основного механизма сайта.

Вопрос. Если путь к файлам этой страничке будет виден в адресной строке, понижу ли я тем самым уровень безопасности сайта? Принципиально ли вообше, что бы в адресной строке не было видно реальных путей к реальным файлам и самих файлов, их названий? С точки зрения безопасности.
Автор: Cheery
Дата сообщения: 30.09.2009 00:38
israel_rider
откуда мы знаем что за файлы и какую роль играют?
Автор: israel_rider
Дата сообщения: 30.09.2009 00:42
Я же написал, что за файлы. Файлы, через которые идёт биллинг на сайте по протоколу https. Оплата кредитными картами через процессинговый центр.
Автор: Cheery
Дата сообщения: 30.09.2009 00:43
israel_rider

Цитата:
Я же написал, что за файлы. Файлы, через которые идёт биллинг на сайте по протоколу https. Оплата кредитными картами через процессинговый центр

и что? вы их инклудите куда то? или прямо вызываете?
если идет сначала проверка авторизации в них и нет дыры, то какая разница то, что вы в лоб обращаетесь, а что через rewrite?
Автор: israel_rider
Дата сообщения: 30.09.2009 01:13

Цитата:
вы их инклудите куда то? или прямо вызываете?

Я их вызываю прямо. Путь в адресной строке - реальный.

Цитата:
если идет сначала проверка авторизации в них и нет дыры,

Авторизация требуется только на заключительном этапе оплаты. Заказчик хочет, что бы биллинговую страницу видели и неавторизированные пользователи.
На счёт дыр.... Вводимые пользователями данные я проверяю функциями, написанными разработчиками СМS для этой цели. Достаточно ли тщательна ли эта проверка, судить не мне. На счёт других дыр.... Я думаю, дыры есть везде и всегда. Всё зависит от того , насколько сильно желание взломать сайт. А моя задача простая - сохранить уровень защищённости сайта, заданный разработчиками СМS, и не понизить его.
Короче, то, что Вы, Cheery сказали, звучит стрёмно. Поэтому боюсь, что мне всё же придётся скрывать истинное расположение указанных файлов через инструкции rewrite.
Автор: israel_rider
Дата сообщения: 11.10.2009 20:58
На сайте, над которым я сейчас работаю, определён базовый класс tep, в функции – конструкторе которой присутствует только одна строчка:

Код:
var $AllRequest;
function tep()
{
    $this->AllRequest    =    $_REQUEST;
}
Автор: andead
Дата сообщения: 11.10.2009 21:38
israel_rider

Код: function tep()
{
foreach($_REQUEST as $key => $val){
$this->AllRequest[$key] = mysql_real_escape_string($val);
}
}
}
Автор: israel_rider
Дата сообщения: 11.10.2009 21:47
andead, я поясню свой вопрос. Фукцию, которую я привёл, я выдрал с СМS, которую писали супер проффессионалы, и продают её теперь не за одну сотню баксов...
И эти супер проффессионалы написали код с кучей проверок вместо использования всего двух извесных мне хрестоматийных функций - mysql_real_escape_string() и htmlspecialchars().
Вот я и задаю вопрос более опытным профессионалам на форуме - почему? Чем они руководствовались? Что в их коде такого особенного? Это оправдано, то, что они понаворотили?
Автор: andead
Дата сообщения: 11.10.2009 22:27
может они писали этот код в эпоху php < 4.3.0)) имхо задавать такие вопросы без предоставления исходников всей cms не корректно. может где то в начале $_REQUEST обрабатывается должным образом
Автор: israel_rider
Дата сообщения: 11.10.2009 22:31
То есть, если я правильно тебя понимаю, твой ответ - проверять при помощи mysql_real_escape_string() и htmlspecialchars() и всё? И не париться?
Автор: Cheery
Дата сообщения: 11.10.2009 22:44
israel_rider

Цитата:
твой ответ - проверять при помощи mysql_real_escape_string() и htmlspecialchars() и всё? И не париться?

если правильно использовать, то да
Автор: israel_rider
Дата сообщения: 11.10.2009 22:50
Cheery, помогите пожалуйста. Напишите, что Вы имеете в виду, говоря - "если правильно использовать"? Применительно к моему, конкретно описываемому мною случаю, когда приходится проверять данные, не зная заранее, где они после будут использоваться - в SQL запросе, или выводиться прямо на веб-стренице.
А ещё лучше, дайте пример кода. Ведь код, то который здесь требуется, всего пару строк.
Автор: Cheery
Дата сообщения: 11.10.2009 23:15
israel_rider

Цитата:
говоря - "если правильно использовать"

если руки растут не из того места, то даже с нужными вещами можно наделать столько дыр.

Цитата:
Применительно к моему, конкретно описываемому мною случаю, когда приходится проверять данные, не зная заранее, где они после будут использоваться - в SQL запросе, или выводиться прямо на веб-стренице.

и? применяйте и экранирование и преобразование htmlentities
Автор: israel_rider
Дата сообщения: 11.10.2009 23:47

Цитата:
применяйте и экранирование и преобразование htmlentities

Спасибо, понял. Значит, получается так -


Код:
function tep()
{
foreach($_REQUEST as $key => $val){
$preliminary = mysql_real_escape_string($val);
$this->AllRequest[$key] = htmlspecialchars($preliminary);
}
}
Автор: andead
Дата сообщения: 11.10.2009 23:49
israel_rider
да, ну и желательно приводить типы
Автор: israel_rider
Дата сообщения: 11.10.2009 23:56
Принудительно приводить типы? А к чему их приводить? Делать все передаваемые данные "string"? Так а у меня же там ещё и "integer" передаюся.... И поди, знай, может даже где нибудь ещё и "float" затешется....
Поясните пожалуйста, я не понимаю....
Автор: israel_rider
Дата сообщения: 12.10.2009 15:32
Я очень сожалею, что ни кто из знающих профессионалов так и не ответил на мой последний вопрос. Неужели его сочли настолько глупым и нелепым? А у меня уже возникла следующая проблема, и как раз с типами.
Дело в том, что, как я уже написал, работа сайта требует самые разные типы в «$_REQUEST». Так вот, и функция mysql_real_escape_string() и htmlspecialchars() на входе требуют «string». И когда через «$_REQUEST» потребовалось передать массив, сайт сработал неправильно. Пришлось переписать конструктор. И теперь он выглядит так:

Код:
var $AllRequest;

function __construct()
{

$MySqlHostname = "localhost";
$MySqlUsername = "имя";
$MySqlPassword = "пароль";
$MySqlDatabase = "база данных";
$dblink = mysql_connect($MySqlHostname, $MySqlUsername, $MySqlPassword) or die("Error :: Unable to connect to database");
mysql_select_db($MySqlDatabase) or die( "Error :: Unable to select database");
        mysql_query("SET NAMES UTF8");

foreach($_REQUEST as $key => $val){
if (is_array($val)) $this->AllRequest =    $_REQUEST;
else {
$preliminary = mysql_real_escape_string($val);
$this->AllRequest[$key] = htmlspecialchars($preliminary);
}
}
}
Автор: andead
Дата сообщения: 12.10.2009 16:04

Цитата:
А к чему их приводить

к тем что используются в mysql


Цитата:
Так а у меня же там ещё и "integer" передаюся.... И поди, знай, может даже где нибудь ещё и "float" затешется....

а кто сказал что будет легко?)


Цитата:
так и не ответил на мой последний вопрос

вам два человека одно и тоже написали


Цитата:
Следовательно вопрос – если в «$_REQUEST» будет содержаться массив, как его проверять?

зачем его проверять? вынесите функцию обработки переменной в отдельную функцию и обрабатывайте хоть строки, хоть массивы через рекурсию
Автор: israel_rider
Дата сообщения: 12.10.2009 16:07

Цитата:
вынесите функцию обработки переменной в отдельную функцию и обрабатывайте хоть строки, хоть массивы через рекурсию

Класс. Всё понял. Спасибо. Прямо сейчас и займусь.
Автор: israel_rider
Дата сообщения: 13.10.2009 15:14
Как всё просто показалось вначале.... В результате, только через сутки долбления головой о стену узнал о существовании функции array_walk_recursive(), которая позволила реализовать поданную andead - ом идею....

Добавлено:
Вот что получилось в результате:

Код:
function __construct()
{
$AllRequest = $_REQUEST;
array_walk_recursive($AllRequest, array($this, 'security_check'));

$this->AllRequest = $AllRequest;
}


function security_check(&$item, $key)
    {
if (!is_numeric($item)) {
$MySqlHostname = "localhost";
$MySqlUsername = "имя";
$MySqlPassword = "пароль";
$MySqlDatabase = "база";
$dblink = mysql_connect($MySqlHostname, $MySqlUsername, $MySqlPassword) or die("Error :: Unable to connect to database");
mysql_select_db($MySqlDatabase) or die( "Error :: Unable to select database");
mysql_query("SET NAMES UTF8");
        
$item = htmlspecialchars($item, ENT_QUOTES);
$item = mysql_real_escape_string($item);
}
   }
Автор: evle
Дата сообщения: 16.10.2009 19:49
israel_rider
1. Отдельное подключение к базе и запрос для каждого поля в REQUEST — это, конечно, гениально, но, боюсь, хостер не оценит.
2. Лучше всё-таки понять, что же делают функции htmlspecialchars и mysql_real_escape_string, и зачем они это делают, чтобы не было соблазна мешать их в кучу.
3. На мой вкус обрабатывать весь REQUEST таким образом несколько избыточно. Если, конечно, он целиком потом не пойдёт в запрос.
Автор: Cheery
Дата сообщения: 16.10.2009 20:52
evle

Цитата:
Отдельное подключение к базе и запрос для каждого поля в REQUEST — это, конечно, гениально, но, боюсь, хостер не оценит.

http://us2.php.net/mysql_connect

Цитата:
If a second call is made to mysql_connect() with the same arguments, no new link will be established, but instead, the link identifier of the already opened link will be returned. The new_link parameter modifies this behavior and makes mysql_connect() always open a new link, even if mysql_connect() was called before with the same parameters. In SQL safe mode, this parameter is ignored.


но насчет выбора базы и тд - да.. лишнее..


israel_rider
я делаю так

Код: function db_connect()
{
static $connected = 0;

if (!$connected) {
$link = @mysql_connect(DB_HOST, DB_UID, DB_PWD);
if ($link) {
mysql_select_db(DB_DB);
$connected = 1;
} else {
exit("Unable to connect to database. Please try again later.\n");
}
}
}
Автор: israel_rider
Дата сообщения: 16.10.2009 20:55
evle, рад твоим критическим замечаниям. Попробую всё же объяснить свою позицию, что бы в результате диалога я смог выбрать наиболее правильное решение.
Дело в том, что как я уже писал выше, когда начал обсуждать данную проблему, я обнаружил, что 80 процентов данных из REQUEST идут затем в запросы базы данных не проверяясь. И, в то же время, эти данные идут через базовый класс. Поэтому я и принял решение поставить функцию проверки в этой единственной точке, через которую они проходят. Вместо того, чтобы лазить по всему сайту (немаленькому) выискивать, и переделывать все запросы. У меня тоже были сомнения, не перегружу ли я хостинг. И я их высказывал несколькими постами выше. Если ты мог видеть. И если ты мог видеть, я получил ответ, что вроде бы и ни чего страшного. Что и практика подтвердила тоже. Ни я, ни мой клиент – хозяин сайта, после установки моей функции не почувствовали, что сайт стал работать медленнее.
Далее. Я знаю,
Цитата:
что же делают функции htmlspecialchars и mysql_real_escape_string, и зачем они это делают
но, как я уже писал несколькими постами выше, данные из REQUEST идут и в запросы к базе данных, и выводятся на сайте и их видит пользователь. Поэтому я и решил проверять REQUEST обоими функциями в одном месте, вместо того, что бы лазить по всему сайту, и вставлять каждую из этих функций именно в то место, где нужна именно она. И об этом я консультировался постами выше, и в принципе, получил ответ, что да, сделать так можно. Все это можно видеть несколькими постами выше.
Позже, идея проверять REQUEST обоими функциями подряд дала мне ошибку, и я от этой идеи отказался. Об этом я подробно написал здесь - http://forum.ru-board.com/topic.cgi?forum=31&topic=15632 .
Короче, всё, что сказал ты и я, можно подытожить короткой фразой – Да, обрабатывая весь REQUEST в одном месте я увеличиваю нагрузку на сервер, но альтернатива этому получается только одна – по сути, переделывать весь сайт.
Я буду счастлив продолжить диалог, что бы всё понять, и принять наиболее правильное решение. Прошу прощения, если что то до меня доходит не сразу.


Добавлено:
Cheery, поясните пожалуйта, я правильно понял идею Вашей функции? Смысл её в строке - static $connected = 0;
То есть идея в том, что, если подключение к базе данных уже существует, функция просто не сработает? Поскольку $connected уже будет равно единице? То есть, не будет ненужных, паралельных подключений, перегружающих сервер?
Автор: Cheery
Дата сообщения: 16.10.2009 21:51
israel_rider
честное слово - вы порой утомляете. вы что то нового кроме static увидели? ну зачем переспрашивать очевидное.
данный способ не сработает только в одном случае - если база вылетит на момент работы скрипта (то есть зависит от его длительности). соединение установится, но что то потом может не сработать.
а так - не важно какую функцию работы с базой вызовите - сначала установится соединение и больше не будет дергать базу. Кроме случая когда вызывается mysql_close в лоб - тогда этот метод тоже выдаст ошибку
Автор: evle
Дата сообщения: 17.10.2009 14:27
Cheery
Хм. Согласен; не знал, что php это кеширует. Видимо, как раз для таких случаев. :-)
israel_rider

Цитата:
я получил ответ, что вроде бы и ни чего страшного

Что-то я не вижу, чтобы кто-то утверждал, что

Код:
mysql_select_db($MySqlDatabase) or die( "Error :: Unable to select database");
mysql_query("SET NAMES UTF8");
Автор: israel_rider
Дата сообщения: 17.10.2009 16:05
evle , на счёт замещания, что нельзя помещать подсоединение к базе даннвх в цикл, спасибо. Теперь понял, сейчас переделаю. Один из вариантов - поместить туда функцию от Cheery. Тогда, если соединение с базой уже установлено, второй раз оно вызываться уже не будет.


Добавлено:
На счёт второй части твоего замечания тоже огромное спасибо! Тоже всё понял в конце концов. Буду делать выводы.
В результате всего разговора я понял, что мне не удасться проверять данные поступающие из REQUEST в одном месте. Мне придётся в каждом конкретном случае применять или htmlspecialchars или mysql_real_escape_string, в зависимости от того, как используются конкретные данные.
Автор: evle
Дата сообщения: 17.10.2009 20:27
Боюсь, ты так и не понял. Ни htmlspecialchars, ни mysql_real_escape_string не предназначены для «проверки» входных данных. mysql_real_escape_string оформляет строку для использования в запросе. htmlspecialchars готовит выходные данные для вставки в html. В обоих случаях данные уже считаются корректными, вопрос лишь в правильном их «отображении». Соответственно, применяемая функция должна соответствовать синтаксису выходного формата.

Так вот, ни то, что поступает в базу, ни то, что выдаётся на страницу, не связано напрямую с REQUEST. Туда должны попадать уже проверенные и отфильтрованные данные. Проверку можно делать чем-нибудь таким, простым strip_tags, приведением к int для чисел, и т. п. Проверка зависит от ожидаемых данных; если в поле ожидалось число, а оказалась дата, твоя функция никак это не обработает. Максимум, не допустит ошибки в синтаксисе SQL и инъекции. При вставке таких данных произойдёт преобразование типов, и в базе окажется чёрт те что, хотя обычно и довольно безобидное.

Надеюсь, не зря писал.
Автор: israel_rider
Дата сообщения: 17.10.2009 20:30
Нет не зря. Сейчас буду пробовать переделывать...
Автор: evle
Дата сообщения: 17.10.2009 20:31
Да, и по поводу соединения с базой. На мой вкус, логичнее делать это один раз и сильно заранее. Где-нибудь в конструкторе того, что будет записывать данные.

Страницы: 1234567

Предыдущая тема: WAP+PHP и русские буквы


Форум Ru-Board.club — поднят 15-09-2016 числа. Цель - сохранить наследие старого Ru-Board, истории становления российского интернета. Сделано для людей.