Изучаем java script, php, mysql
четверг, 21 января 2010 г.
просмотр и настрой кодировки mysql
while($rec=mysql_fetch_row($res)) {
print($rec[0] . " = " . $rec[1] . "
\n"); }
mysql_query("set character_set_client='UTF8'");
mysql_query ("set character_set_results='UTF8'");
mysql_query ("set collation_connection='UTF8_general_ci'");
вторник, 19 января 2010 г.
Обновление php
Для начала добавим новый репозитарий Remi себе в систему
wget -P /tmp/ ftp://ftp.pbone.net/mirror/rpms.famillecollet.com/enterprise/5/remi/i386/remi-release-5-7.el5.remi.noarch.rpm
rpm -Uvh remi-release-5*.rpm epel-release-5*.rpm
Теперь говорим системе что нам нужно обновить наш PHP именно из этого репозитория
yum --enablerepo=remi update php
Теперь смотрим нашу версию PHP
php -v
PHP 5.2.5 (cli) (built: Nov 10 2007 10:52:30)
Copyright (c) 1997-2007 The PHP Group
Zend Engine v2.2.0, Copyright (c) 1998-2007 Zend Technologies
Установка phpmyadmin CentOs
# mv phpMyAdmin-2.11.3-english phpmyadmin
# cd phpmyadmin
# cp config.sample.inc.php config.inc.php
# vi config.inc.php
:
$cfg['Servers'][$i]['auth_type'] = ‘http‘; # default is cookies
:
# service httpd restart
You can test by open phpmyadmin by this link :
http://your.domain.com/phpmyadmin/
для 3.5 надо php 5.2
для 2.11 php 4.1
плюс поставить php-mysql
installed php-mysql using yum by typeing -
yum install php-mysql
You should be find pop up for insert your user name and password.
понедельник, 23 июня 2008 г.
SQL инъекции
SQL инъекция (SQL injection) - уязвимость которая возникает
при недостаточной проверке и обработке данных, которые передаются от пользователя, и позволяет модифицировать и выполнять непредвиденные кодом программы SQL запросы.
Инъекция SQL является широко распространенным дефектом безопасности в Internet, что легко используется без специальных программ и не требует глубоких технических знаний.
Использование этой уязвимости дает путь к большим возможностям: как то кража, подмена или уничтожение данных, отказ в обслуживании, и т.д.
В этой статье я попробую объяснить основные риски, которые возникают при взаимодействии междуPHP и базой данных MySQL.
Для наглядности приведу пример простой структуры базы данных, которая является типичной для большинства проектов:
CREATE DATABASE `news`;
USE `news`;
#
# таблица новостей
#
CREATE TABLE `news` (
`id` int(11) NOT NULL auto_increment,
`title` varchar(50) default NULL,
`date` datetime default NULL,
`text` text,
PRIMARY KEY (`id`)
) TYPE=MyISAM;
#
#добавляем некоторые данные
#
INSERT INTO `news` (`id`,`title`,`date`,`text`) VALUES (1,'first news','2005-06-25
16:50:20','news text');
INSERT INTO `news` (`id`,`title`,`date`,`text`) VALUES (2,'second news','2005-06-24
12:12:33','test news');
#
# таблица пользователей
#
CREATE TABLE `users` (
`id` int(11) NOT NULL auto_increment,
`login` varchar(50) default NULL,
`password` varchar(50) default NULL,
`admin` int(1) NULL DEFAULT '0',
PRIMARY KEY (`id`)
) TYPE=MyISAM;
#
# добавляем несколько пользователей, одного с правами админа, другого простого
#
INSERT INTO `users` (`id`,`login`,`password`,`admin`) VALUES (1,'admin','qwerty',1);
INSERT INTO `users` (`id`,`login`,`password`,`admin`) VALUES (2,'user','1111',0);
А теперь образец PHP кода:
$link=mysql_connect("localhost","user","password");
mysql_select_db("sqltest",$link);
if (!empty($_GET["id"])) {
$query="SELECT * FROM `news` WHERE `id`=".$_GET["id"];
$res=mysql_query($query,$link) or die(mysql_error($link));
}
?>
Видим, что запрос формируется в зависимости от значения $_GET["id"]. Для проверки наличия уязвимости достаточно изменить его на значение, которое может вызвать ошибку в выполнении SQL запроса.
Конечно, вывода ошибок может и не быть, но это не означает, что ошибки нет.
как результат "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''' at line 1"
или
результат "Unknown column '1qwerty' in 'where clause'"
запрос
при наличии уязвимости должен выдать результат, аналогичный
Подобные уязвимости позволяют модифицировать запрос в части параметра WHERE.
Первое, что сделает злоумышленник при обнаружении такой уязвимости - исследует, какое количество полей используется в запросе. Для этого задается заведомо неверный id, чтобы исключить вывод реальной информации и объединяется с запросом с одинаковым количеством пустых полей.
количество "null" должно соответствовать количеству полей, которые используются в запросе.
Если запрос выдает ошибку, добавляется еще одно пустое значение, до тех пор пока не исчезнет ошибка и не будет получен результат с пустыми данными. Далее объединенные поля заменяются на значения, которые можно визуально наблюдать на странице.
Например,
теперь на странице, где должен был быть показан заголовок новости, будет красоваться qwerty.
версия MySql
(),null,null
(),null,null
(),null,null
логин текущего пользователя базы данных
(),null,null
имя используемой базы данных
(),null,null
Получение данных из других таблиц:SELECT * FROM `news` WHERE `id`=-1 UNION SELECT null,`password`,null,null from `users`where `id`=1
Вот таким нехитрым способом узнают пароль или хэш пароля админа.
Если же текущий пользователь имеет права доступа к базе "mysql", без малейших проблем злоумышленник получит хэш пароля админа.
Теперь его подбор это просто вопрос времени.
Поиск
Поиск - одно из наиболее уязвимых мест, поскольку одновременно передается большое количество параметров запроса. Пример простого запроса, который выполняет поиск по ключевому слову:SELECT * FROM `news` WHERE `title` LIKE '%$search%' OR `text` LIKE '%$search%'
$search - слово, которое передается с формы.
Злоумышленник может передать в переменной $search = '# теперь запрос будет выглядеть следующим образом:SELECT * FROM `news` WHERE `title` LIKE '%'#%' OR `text` LIKE '%'#%'
Соответственно вместо результатов поиска по ключевому слову будут выданы все данные. Это также позволяет использовать возможность объединения запросов, описанную выше.
Использование параметра ORDER
Часто можно увидеть, что при введении параметров поиска, или выводе информации дают возможность пользователю сортировать данные по определенным полям. Скажу сразу, что использование данной уязвимости не является слишком опасным, поскольку при попытке объединения запросов вызовет ошибку, однако в паре с уязвимостями в других полях есть опасность закомментирования этого параметра.
параметр ORDER формируется в зависимости от переменной $sort
$search =' /*
$sort = */
Будет сформирован следующий запрос:SELECT * FROM `news` WHERE `title` LIKE '%'/*%' OR `text` LIKE '%'/*%' ORDER BY */тем самым закомментируется одно из условий и параметр ORDER
Теперь можно снова объединить запрос, присвоив $sort=*/ UNION SELECT....
Как вариант использования уязвимости этого параметра:SELECT * FROM `users` ORDER BY LENGTH(password);Позволит отсортировать пользователей в зависимости от длины пароля, при условии, что он сохраняется в "чистом" виде.
Авторизация
Попробуем теперь рассмотреть варианты SQL инъекций, которые возникают при авторизации пользователей. Как правило запрос, который проверяет правильность данных авторизации выглядит следующим образом:SELECT * FROM `users` WHERE `login`='$login' AND `password`='$password';
где $login и $password это переменные, которые передаются с формы.
Подобный запрос возвращает данные по пользователю в случае успеха, а в случае неудачи пустой результат.
Соответственно для того, чтобы пройти авторизацию злоумышленнику достаточно модифицировать запрос таким образом, чтобы он вернул ненулевой результат. Задается логин, который соответствует реальному пользователю, а вместо пароля указывается ' OR '1'='1
Или какое-нибудь истинное условие(1, 'a'='a', 1<>2, 3>2, 1+1, ISNULL(NULL), 2 IN (0,1,2), 2 BETWEEN 1 AND 3)
Соответственно запрос будет сформирован следующим образом:SELECT * FROM `users` WHERE `login`='admin' AND `password`='' OR '1'='1';что вернет результат, а как следствие, приведет к несанкционированной авторизации. А если пароли в базе данных хэшированные? Тогда проверку пароля просто "отключают", закомментировав все, что идет после `login`. В форме вместо логина назначается логин реального пользователя и '# тем самым закомментируется проверка пароля.SELECT * FROM `users` WHERE `login`='admin'#' AND `password`='12345'
как вариант 'OR `id`=2#SELECT * FROM `users` WHERE `login`='' OR `id`=2#' AND `password`='12345'
Таким образом можно пройти авторизацию без знания реального логина. Случай сSELECT * FROM `users` WHERE `login`='' OR `admin`=1#' AND `password`='12345'позволяет пройти авторизацию с правами админа.
Большой ошибкой является проверка пароля следующим образом:SELECT * FROM `users` WHERE `login`='$login' AND `password` LIKEпоскольку в этом случае для любого логина подойдет пароль %
'$password'
INSERT & UPDATE
Однако не только SELECT-ы являются уязвимым местом SQL. Не менее уязвимыми могут оказаться INSERT и UPDATE.
Допустим, на сайте есть возможность регистрации пользователей. Запрос, который добавляет нового пользователя:INSERT INTO `users` (`login`, `password`,`admin`) VALUES ('юзер',Уязвимость одного из полей позволяет модифицировать запрос с необходимыми данными.
'пароль',0);
В поле login добавляем юзер', 'пароль', 1)#тем самым добавив пользователя с правами админа.INSERT INTO `users` (`login`, `password`,`admin`) VALUES ('юзер', 'пароль', 1)# ,'пароль',0);Допустим, что поле `admin` находится перед полем `login`, соответственно трюк с заменой данных, которые идут после поля `login` не проходит. Вспоминаем, что синтаксис команды INSERT позволяет добавлять не только одну строчку, а несколько.
Пример уязвимости в поле login:
$login= юзер', 'пароль'),(1,'хакер', 'пароль')#INSERT INTO `users` (`admin`,`login`, `password`) VALUES (0,'юзер',
'пароль'),(1,'хакер', 'пароль')#','пароль');
Таким образом создается 2 записи, одна с правами простого пользователя, другая с желаемыми правами админа.
Подобная ситуация и с UPDATE
Добавление дополнительных полей для изменения:
$login=', `password`='', `admin`='1
Тогда подобный запросUPDATE `users` SET `login`='чайник' WHERE `id`=2;
Модифицируется следующим образом:UPDATE `users` SET `login`='', `password`='', `admin`='1' WHERE `id`=2;
Что произойдет? Пользователь с ID 2 изменит логин и пароль на пустые значения и получит права админа.
Или в случае
$login = ', `password`='' WHERE `id` =1#
Логин и пароль админа станут пустыми.
DELETE
тут все просто, никаких данных получить или изменить не удастся, но удалить лишнее - всегда пожалуйста.
$id=1 OR 1=1
И запросDELETE FROM `news` WHERE `id`=1 OR 1=1;почистит все записи в таблице.
Вместо 1=1 может быть любое истинное условие, про которое говорилось выше. Может спасти параметр LIMIT, который ограничит количество удаленных строк, но не всегда, его могут просто закомментировать.DELETE FROM `news` WHERE `id`=1 OR 1=1# LIMIT 1;
Работа с файлами через SQL-инъекции.
Сильно сомневаюсь, что это где-то может пройти, но справедливости ради нужно описать и такие способы. При включенных привилегиях file можно использовать команды LOAD_FILE и OUTFILE.
Про их опасность можно судить из нижеприведенных запросов:SELECT * FROM `news` WHERE `id`=-1 union select null,LOAD_FILE('/etc/passwd'),null,null;
SELECT * FROM `news` WHERE `id`=-1 union select
null,LOAD_FILE('/home/test/www/dbconf.php'),null,null;
Но на этом все беды еще не заканчиваются.SELECT * FROM `news` WHERE `id`=-1 union select null,'',null,null FROM `news` into outfile
'/home/test/www/test.php';
Вот так записываем файл, который содержит php код. Правда кроме кода, в нем будет еще несколько записей null но это никаким образом не повлияет на работоспособность php кода.
Однако есть несколько условий, благодаря которым эти способы сработают:
Включена привилегия FILE для текущего пользователя базы данных; Права на чтение или запись этих файлов для пользователя, под которым запускается MySQL сервер абсолютный путь к файлу; Magic quotesМагические кавычки делают невозможным использование SQL инъекций в строковых переменных, поскольку автоматически экранирует все ' та " Которые приходят с $_GET та $_POST. DOS через SQL-инъекцию.Чуть не забыл сказать, а знатоки SQL подтвердят, что операция UNION возможна только в MySQL >=4.0.0. С облегчением вздохнули люди, у которых проекты на предыдущих версиях :) Но не все так безопасно, как выглядит на первый взгляд. Логику злоумышленника иногда сложно проследить. "Не получится взломать, так хоть ИтогНа этом все. В этой стстье я старался максимально охватить варианты уязвимостей, которые допускают программисты при создании программ с использованием баз данных MySQL. Однако я более чем уверен, что это далеко Не доверяйте НИКАКИМ данным, которые приходят от пользователя. Речь идет не только о данных, которые передаются массивами $_GET и $_POST. Не следует забывать про $_COOKIE и другие части HTTP-заголовков. Следует помнить про те, что их легко подменить. Не стоит надеяться на опцию PHP "magic quotes" Которые наверно больше мешают чем помогают. Все данные, которые передаются в базу данных должны быть сведены по типам с полями mysql_real_escape_string не экранирует % и _, поэтому не стоит ее использовать в паре с LIKE. Не стоит также сильно надеяться на правильно написанный mod_rewrite. Это только способы для создания "удобных" УРЛ-ов, но уж никак не способ защиты от SQL-инъекций. Отключите вывод информации об ошибках. Не помагайте нехорошим посетителям. Даже если ошибка будет выявлена, отсутствие информации о ней серьезно затруднит ее применение. Помните про разницу между стадией разработки и рабочим проектом. Вывод ошибок и другой детальной информации - ваш союзник на стадии разработки, и союзник злоумышленника в рабочем варианте. Не стоит также прятать их, комментируя в HTML коде, на 1000-чу посетителей найдется 1, который таки найдет подобные вещи. Обрабатывайте ошибки. Напишите обработку SQL запросов таким образом, чтобы информация о них сохранялась в каких-нибудь логах или отсылалась по почте. Не сохраняйте данные доступа к базе данных в файлах, которые не обрабатываются PHP как код. Думаю никому не открыл Америки, но по собственному опыту могу сказать, что подобная практика достаточно распространена. Как правило это файл с расширением *.inc Не создавайте "супер-пользователя" базы данных. Предоставляйте только права, необходимые для выполнения конкретных задач. В поиске стоит ограничить минимальное и максимальное количество символов, являющееся параметрами запроса. Для честного пользователя вполне достаточно от 3-х до 60-70 символов, чтобы удовлетворить свои поисковые интересы, и одновременно вы предупреждаете ситуации, когда поисковым запросом станет том "Войны и мира". Всегда проверяйте количество возвращенных записей после запроса Почти на 90% сайтов, написанных на php встречается такая логическая ошибка, особенно это можно наблюдать, когдаделается запрос на основе полученного ID от пользователя, если руками дать скрипту несуществующий ID - мы увидим достаточно интересные результаты работы некоторых скриптов, вместо того чтобы вернуть 404 программа в лучшем случае ничего не сделает и выведет в браузер чистую страницу. Безопасного вам SQL-я ;)Все описанное в статье было выполнено в качестве эксперимента на тестовой базе, владельцем которой является автор статьи. Никакие данные других людей не были уничтожены или изменены. |
Безопасность MySQL & PHP
Начнем с теории, и выясним, что такое взлом сайта. В моем понимании взлом это получение полного, или частичного доступа к управлению сайта. Допустим, вы являетесь администратором корпоративного сайта, и у вас стоит какой-либо популярный бесплатный движок, работающий на MySQL. В принципе ничего предосудительного в этом нет, но если задуматься, что любой человек может знать точную структуру таблиц, sql запросов и прочей ценной информации, то без можно представить такую картину: Ваши конкуренты или просто недовольный клиент решил вам отомстить, разрушив ваш сайт или нарушив его работу, просто ищут “слабые места” в php скриптах и sql запросах и делают свое дело.
Под слабыми местами я понимаю sql запросы выполненные без какой-либо проверки на верность введенных данных. В качестве примера можно привести примерно следующий кусочек скрипта:
$next = argv[0]; // видите, никакой проверки ввода!
$query = 'SELECT * FROM `table_name` LIMIT 0, $next;";
$result = mysql_query($query);
Как видно из примера, в этот скрипт без особых проблем может быть вставлена SQL инъекция, обычная urlencode()'ированная строка, в начале которой стоит знак прерывания текущего запроса и начала нового “0;”.
К примеру, если скрипт запущен от имени root, то это можно сказать погибель для всего вашего сайта, т.к. без проблем можно сменить пароль на коннект к серверу MySQL и ваш сайт станет недоступным, в том числе и вам:
0;
UPDATE user SET Password=PASSWORD('New_password') WHERE user='root';
FLUSH PRIVILEGES;
Если же скрипт имеет только права на удаление или запись в базу, то можно сделать примерно следующее:
0;
DROP TABLE `table_name`
или
0;
DELETE FROM `registred_user`
Как вы видите, sql инъекция очень страшная вещь, если ей умело пользоваться. Что же делать!, возразите вы мне, а ответ очень прост:
Во-первых: создать несколько пользователей с разными правами, например: один, для записи в базу данных, другой, для чтения из базы, третий для создания новых таблиц и удаления, четвертый для создания новых пользователей, и самое главное, никогда и нигде не открывать соединение с базой от имени пользователя root!!!
Во-вторых: обязательно нужно проверять вводимые данные на корректность ввода. К примеру, проверять тип вводимых переменных с помощью функции is_numeric или is_string или им подобными функциями. Ну, или самостоятельно изменять тип переменных на нужный с помощью функции settype, например settype($next, "integer"); и теперь в $next содержится переменная типа integer.
В-третьих: Весь передаваемый в запрос текст нужно закавычивать с помощью addslashes и addcslashes, что бы избежать присоединения к тексту sql инъекции.
В-четвертых: Не выводите никаких ошибок о работе скрипта, во всяком случае, уже полностью рабочего и отлаженного, вставив функцию error_reporting(0); в начало скрипта.
В-пятых: Можно просто обрезать передаваемые значения до нужной длинны, и при этом проверять тип вводимых данных. Или можно создать собственную процедуру для проверки всех значений переменных используемых для обращения к базе данных, на содержание опасных данных в них.
Как вы могли видеть из выше написанного, что если хакер нашел уязвимость в безопасности скрипта, то ему будет очень просто атаковать ваш сайт или форум. Поэтому в Интернете постоянно появляются вирусы атакующие сайты или форумы работающие на движках в которых нашли уязвимости. И поэтому я являюсь сторонником самодельных скриптов и движков, т.к. хакер может найти уязвимости в таких скриптах, только методом научного тыка, потому что у него нет исходного текста php скрипта. И посему мой вам совет, не ленитесь, пишите скрипты сами, или хотя бы частично изменяйте или проверяйте уже готовые скрипты сторонних производителей. Т.к. зачастую сами производители умышленно делают в скриптах уязвимости (особенно это касается выполнения сайтов “на заказ” или “под ключ”).
суббота, 21 июня 2008 г.
Операции сравнения:
== Равенство (равно)
!= Не равно
! Логическое отрицание
>= Больше или равно
<= Меньше или равно
> Больше
< Меньше (по возможности желательно воздержаться от применения этого типа)
От выражений, имеющих знак "<" следует отказываться по возможности, так, как данный символ может иметь и другое значение в HTML-документах. Во избежание подобных казусов, когда подобное выражение может послужить случайным открытием тега HTML:
if mvar h . . . . . .bgcolor- может интерпретироваться как начало заголовка HTML. Теги HTML в JS программах недопустимы.