Безопасность (Статей: 18)

С помощью этого кода можно отследить попытки взлома

<?
if (isset($_GET['act'])) {
$ua = htmlentities(substr($_SERVER['HTTP_USER_AGENT'], 0, 100), ENT_QUOTES);
$ip = long2ip($_SERVER['REMOTE_ADDR']);
$url = $_SERVER['HTTP_HOST'];
if(!preg_match("#^([A-z0-9])+$#ui", $_GET['act'])) mysql_query("INSERT INTO `hakers` SET `url` = '$url', `kak` = '".mysql_real_escape_string($_GET['act'])."', `ip` = '$ip', `ua` = '$ua', `date_hak` = '". time() ."'");
}
?>

вписываем этот код туда где у нас есть $_GET['act']
и создаем таблицу
CREATE TABLE IF NOT EXISTS `hakers` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`url` varchar(100) NOT NULL,
`kak` varchar(100) NOT NULL,
`ip` varchar(100) NOT NULL,
`ua` varchar(100) NOT NULL,
`date_hak` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=6 ;
и теперь все урлы вида url/?act=чтототам (где кроме A-z0-9 есть другие символы будут записываться в базу)
публичные форумы и движки, работающие с MySQL. Но далеко не все ясно представляют себе, насколько опасным может быть непродуманное использование MySQL в скриптах.
Как это есть?
Без знаний основ языка SQL трудно что-либо понять. Прежде всего разберемся, в чем заключается суть атаки типа SQL injection. К примеру, на атакуемом сервере стоит следующий PHP-скрипт, который на основе поля category_id делает выборку заголовков статей из таблицы articles и выводит их пользователю:
//подключаемся к MySQL
mysql_connect($dbhost, $dbuname, $dbpass) or die(mysql_error());
mysql_select_db($dbname) or die(mysql_error());
$cid=$_GET["cid"];
$result=mysql_query("SELECT article_id, article_title FROM articles where category_id=$cid"); // <- уязвимый запрос
while( $out = mysql_fetch_array( $result)):
echo "Статья: ".$out['article_id']." ".$out['article_title']."<br>";
endwhile;
//выводим результат в виде списка
В переводе с языка MySQL запрос звучит так: "ВЫБРАТЬ ид_статей, заголовки_статей ИЗ таблицы_статей ГДЕ ид_категории равно $cid". На первый взгляд все верно, по ссылке типа http://serv.com/read.php?cid=3 скрипт работает нормально и выводит пользователю список статей, принадлежащих категории 3.
Но что если пользователь - никакой не пользователь, а обыкновенный хакер? Тогда он сделает запрос http://serv.com/read.php?cid=3' (именно с кавычкой) и получит что-то вроде: Warning: mysql_fetch_array(): supplied argument is not a valid MySQL result resource in /usr/local/apache/htdocs/read.php on line 14.
Почему ошибка? Посмотрим, что запросил PHP у MySQL. Переменная $cid равна 1', тогда запрос принимает неверный с точки зрения MySQL вид: SELECT article_id, article_title FROM articles where category_id=1'. При синтаксической ошибке в запросе MySQL отвечает строкой "ERROR 1064: You have an error in your SQL syntax...". PHP не может распознать этот ответ и сообщает об ошибке, на основе которой хакер может судить о присутствии уязвимости типа SQL Injection. Очевидно, что злоумышленник получит возможность задавать переменной $cid любые значения ($cid=$_GET[cid]) и, следовательно, модифицировать запрос к MySQL. Например, если $cid будет равна "1 OR 1" (без кавычек в начале и в конце), то MySQL выдаст все записи, независимо от category_id, так как запрос будет иметь вид (..) where category_id=1 OR 1. То есть либо category_id = 1 (подойдут лишь записи с category_id, равными 1), либо 1 (подойдут все записи, так как число больше нуля - всегда истина).
Только что описанные действия как раз и называются SQL Injection - иньекция SQL-кода в запрос скрипта к MySQL. С помощью SQL Injection злоумышленник может получить доступ к тем данным, к которым имеет доступ уязвимый скрипт: пароли к закрытой части сайта, информация о кредитных картах, пароль к админке и т.д. Хакер при удачном для него стечении обстоятельств получит возможность выполнять команды на сервере.
Как атакуют?
Классический пример уязвимости типа SQL Injection - следующий запрос: SELECT * FROM admins WHERE login='$login' AND password=MD5('$password').
Допустим, он будет проверять подлинность введенных реквизитов для входа в админскую часть какого-нибудь форума. Переменные $login и $password являются логином и паролем соответственно, и пользователь вводит их в HTML-форму. PHP посылает рассматриваемый запрос и проверяет: если количество возвращенных от MySQL записей больше нуля, то админ с такими реквизитами существует, а пользователь авторизуется, если иначе (таких записей нет и логин/пароль неверные) - пользователя направят на fsb.ru.
Как взломщик использует SQL Injection в этом случае? Все элементарно. Злоумышленнику требуется, чтобы MySQL вернул PHP-скрипту хотя бы одну запись. Значит, необходимо модифицировать запрос так, чтобы выбирались все записи таблицы независимо от правильности введенных реквизитов. Вспоминаем фишку с "OR 1". Кроме того, в MySQL, как и в любом языке, существуют комментарии. Комментарии обозначаются либо --комментарий (комментарий в конце строки), либо /*комментарий*/ (комментарий где угодно). Причем если второй тип комментария стоит в конце строки, закрывающий знак '*/' необязателен. Итак, взломщик введет в качестве логина строку anyword' OR 1/*, а в качестве пароля - anyword2. Тогда запрос принимает такой вид: SELECT * FROM admins WHERE login='anyword' OR 1/* AND password=MD5('anyword2'). А в переводе на человеческий язык: ВЫБРАТЬ все ИЗ таблицы_admins ГДЕ логин равен 'anyword' ИЛИ 1, а остальное воспринимается как комментарий, что позволяет отсечь ненужную часть запроса. В результате MySQL вернет все записи из таблицы admins даже независимо от того, существует админ с логином anyword или нет, и скрипт пропустит хакера в админку. Такая уязвимость была обнаружена, например, в Advanced Guestbook. Она позволяла войти в администраторскую часть не зная пароля и внутри нее читать файлы. Но SQL Injection этого типа обычно не позволяют злоумышленнику получить данные из таблицы.
Union и MySQL версии 4
Вернемся к скрипту получения заголовков статей. На самом деле он позволяет взломщику получить гораздо больше, чем список всех статей. Дело в том, что в MySQL версии 4 добавлен новый оператор - UNION, который используется для объединения результатов работы нескольких команд SELECT в один набор результатов. Например: SELECT article_id, article_title FROM articles UNION SELECT id, title FROM polls. В результате MySQL возвращает N записей, где N - количество записей из результата запроса слева плюс количество записей из результата запроса справа. И все это в том порядке, в каком идут запросы, отделяемые UNION.

Но существуют некоторые ограничения по использованию UNION:
1. число указываемых столбцов во всех запросах должно быть одинаковым: недопутимо, чтобы первый запрос выбирал, например, id, name, title, а второй только article_title;
2. типы указываемых столбцов одного запроса должны соответствовать типам указываемых столбцов остальных запросов: если в одном запросе выбираются столбцы типа INT, TEXT, TEXT, TINYTEXT, то и в остальных запросах должны выбираться столбцы такого же типа и в таком же порядке;
3. UNION не может идти после операторов LIMIT и ORDER.
Так как же UNION может стать пособником злоумышленника? В нашем скрипте присутствует запрос "SELECT article_id, article_title FROM articles where category_id=$cid". Что мешает хакеру, используя SQL injection, вставить еще один SELECT-запрос и выбрать нужные ему данные? Правильно: ничего!
Допустим, цель хакера - получить логины и пароли всех авторов, которые могут добавлять статьи. Есть скрипт чтения списка статей http://serv.com/read.php?cid=1, подверженный SQL injection. Первым делом хакер узнает версию MySQL, с которой работает скрипт. Для этого он сделает следующий запрос: http://serv.com/read.php?cid=1+/*!40000+AND+0*/. Если скрипт вернет пустую страницу, значит, версия MySQL >= 4. Почему именно так? Число 40000 - версия MySQL, записанная без точек. Если версия, которая стоит на сервере, больше или равна этому числу, то заключенный в /**/ код выполнится как часть запроса. В результате ни одна запись не подойдет под запрос и скрипт не вернет ничего. Зная версию MySQL, хакер сделает вывод о том, сработает фишка с UNION или нет. В случае если MySQL третьей версии, фишка работать не будет. В нашем случае MySQL >= 4 и злоумышленник все-таки воспользуется UNION.
Для начала взломщик составит верный UNION-запрос, то есть подберет действительное количество указываемых столбцов, которое бы совпало с количеством указываемых столбцов левого запроса (вспоминай правила работы с UNION). Хакер не имеет в распоряжении исходников скрипта (если, конечно, скрипт не публичный) и поэтому не знает, какой именно запрос шлет скрипт к MySQL. Придется подбирать вручную - модифицировать запрос вот таким образом: http://serv.com/read.php?cid=1+UNION+SELECT+1. И тут о своем присутствии объявит ошибка, так как количество запрашиваемых столбцов не совпадает. Хакер увеличивает количество столбцов еще на единицу: http://serv.com/read.php?cid=1+UNION+SELECT+1,2 - получает список статей из категории 1, а также в самом конце две цифры: 1 и 2. Следовательно, он верно подобрал запрос.
Посмотрим на модифицированный запрос от PHP к MySQL: SELECT article_id, article_title FROM articles where category_id=1 UNION SELECT 1,2. В ответ MySQL возвращает результат первого SELECT (список статей) и результат второго SELECT - число "1" в первом столбце и "2" во втором столбце (SELECT+1,2). Другими словами, теперь, подставляя вместо '1' и '2' реальные имена столбцов из любой таблицы, можно будет заполучить их значения.
Составив верный SELECT+UNION запрос, хакер постарается подобрать название таблицы с нужными ему данными. Например, таблица с данными пользователей будет, скорее всего, называться users, Users, accounts, members, admins, а таблица с данными о кредитных картах - cc, orders, customers, orderlog и т.д. Для этого злоумышленник сделает следующий запрос: http://serv.com/read.php?cid=1+UNION+SELECT+1,2+FROM+users. И если таблица users существует, то PHP-скрипт выполнится без ошибок и выведет список статей плюс '1 2', иначе - выдаст ошибку. Так можно подбирать имена таблиц до тех пор, пока не будет найдена нужная.

В нашем случае "нужная" таблица – это authors, в которой хранятся данные об авторе: имя автора, его логин и пароль. Теперь задача хакера - подобрать правильные имена столбцов с нужными ему данными, чаще всего с логином и паролем. Имена столбцов он станет подбирать по аналогии с именем таблицы, то есть для логина столбец, скорее всего, будет называться login или username, а для пароля - password, passw и т.д. Запрос будет выглядеть так: http://serv.com/read.php?cid=1+UNION+SELECT+1,login+from+authors.
Почему хакер не стал вставлять имя столбца вместо единицы? Ему нужна текстовая информация (логин, пароль), а в нашем случае в левом запросе SELECT на первом месте идет article_id, имеющий тип INT. Следовательно, в правом запросе хакер не может ставить на первое место имя столбца с текстовой информацией (правила UNION).
Итак, выполнив запрос http://serv.com/read.php?cid=1+UNION+SELECT+1,login+from+authors, взломщик находит список логинов всех авторов, а подставив поле password - список паролей. И получает желанные логины и пароли авторов, а админ сервера – подмоченную репутацию. Но это только в нашем примере Фортуна улыбнулась злоумышленнику так широко: он быстро подобрал количество столбцов, а в реальной жизни количество столбцов может достигать 30-40.
UNION и нюансы
Теперь рассмотрим некоторые ситуации, в которых использование UNION затруднено по тем или иным причинам.
Ситуация 1
Левый запрос возвращает лишь числовое значение. Что-то вроде SELECT code FROM artciles WHERE id = $id. Что будет делать хакер? Средства MySQL позволяют проводить различные действия над строками, к примеру, выделение подстроки, склеивание нескольких строк в одну, перевод из CHAR в INT и т.п. Благодаря этим функциям хакер имеет возможность выудить интересующую его информацию по одному символу. К примеру, требуется достать пароль из таблицы admins, используя приведенный выше запрос. Чтобы получить ASCII-код первого символа пароля, сделаем следующий запрос к скрипту: http://127.0.0.1/read.php?cid=1+union+select+ASCII(SUBSTRING(password,1,1))+from+admins. Функция SUBSTRING(name,$a,$b) в MySQL выделяет $b символов из значения столбца name начиная с символа под номером $a. Функция ASCII($x) возвращает ASCII-код символа $x. Для получения последующих символов следует просто менять второй параметр функции SUBSTRING до тех пор, пока ответом не будет 0. Подобный способ был использован в эксплойте для одной из версий phpBB.
Ситуация 2
SQL Injection находится в середине SQL-запроса. Например: SELECT code FROM artciles WHERE id = $id AND blah='NO' AND active='Y' LIMIT 10. Для правильной эксплуатации хакер просто откомментирует идущий следом за Injection код, то есть к вставляемому коду добавит /* или --. Пробелы в запросе взломщик может заменить на /**/, что полезно в случае если скрипт фильтрует пробелы.
Ситуация 3
Случается и такое, что в PHP-коде подряд идет несколько SQL-запросов, подверженных Injection. И все они используют переменную, в которую злоумышленник вставляет SQL-код. Например (опускаю PHP):
$result=mysql_query("SELECT article_id, article_title FROM articles where category_id=$cid");
//php code here
$result=mysql_query("SELECT article_name FROM articles where category_id=$cid");
//тут вывод результата
Это довольно неприятно для хакера, так как для первого запроса SQL Injection пройдет нормально, а для второго UNION - уже нет, так как количество запрашиваемых столбцов отличается. И если программист, писавший код, предусмотрел остановку скрипта в случае ошибки типа "... or die("Database error!")", то эксплуатация обычными методами невозможна, так как скрипт остановится раньше, чем будет выведет результат.
Ситуация 4
Скрипт выводит не весь результа
-1
Принцип атаки внедрения SQL
Допустим, серверное ПО, получив входной параметр id, использует его для создания SQL-запроса. Рассмотрим следующий PHP-скрипт:
# Предыдущий код скрипта...
$id = $_REQUEST['id'];
$res = mysql_query("SELECT * FROM news WHERE id_news = $id");
# Следующий код скрипта...
Если на сервер передан параметр id, равный 5 (например так: http://example.org/sсriрt.php?id=5), то выполнится следующий SQL-запрос:
SELECT * FROM news WHERE id_news = 5
Но если злоумышленник передаст в качестве параметра id строку -1 OR 1=1 (например, так: http://example.org/sсriрt.php?id=-1+OR+1=1), то выполнится запрос:
SELECT * FROM news WHERE id_news = -1 OR 1=1
Таким образом, изменение входных параметров путём добавления в них конструкций языка SQL вызывает изменение в логике выполнения SQL-запроса (в данном примере вместо новости с заданным идентификатором будут выбраны все имеющиеся в базе новости, поскольку выражение 1=1 всегда истинно).
[править]Внедрение в строковые параметры
Предположим, серверное ПО, получив запрос на поиск данных в новостях параметром search_text, использует его в следующем SQL-запросе (здесь параметры экранируются кавычками):

$search_text = $_REQUEST['search_text'];
$res = mysql_query("SELECT id_news, news_date, news_caption, news_text, news_id_author
FROM news WHERE news_caption LIKE('%$search_text%')");
Сделав запрос вида http://example.org/sсriрt.php?search_text=Test мы получим выполнение следующего SQL-запроса:
SELECT id_news, news_date, news_caption, news_text, news_id_author FROM news
WHERE news_caption LIKE('%Test%')
Но, внедрив в параметр search_text символ кавычки (который используется в запросе), мы можем кардинально изменить поведение SQL-запроса. Например, передав в качестве параметра search_text значение ')+and+(news_id_author='1, мы вызовем к выполнению запрос:
SELECT id_news, news_date, news_caption, news_text, news_id_author FROM news
WHERE news_caption LIKE('%') AND (news_id_author='1%')
[править]Использование UNION
Язык SQL позволяет объединять результаты нескольких запросов при помощи оператора UNION. Это предоставляет злоумышленнику возможность получить несанкционированный доступ к данным.
Рассмотрим скрипт отображения новости (идентификатор новости, которую необходимо отобразить, передается в параметре id):
$res = mysql_query("SELECT id_news, header, body, author FROM news WHERE id_news = " . $_REQUEST['id']);
Если злоумышленник передаст в качестве параметра id конструкцию -1 UNION SELECT 1,username, password,1 FROM admin, это вызовет выполнение SQL-запроса
SELECT id_news, header, body, author FROM news WHERE id_news = -1 UNION SELECT 1,username,password,1 FROM admin
Так как новости с идентификатором −1 заведомо не существует, из таблицы news не будет выбрано ни одной записи, однако в результат попадут записи, несанкционированно отобранные из таблицы admin в результате инъекции SQL.
[править]Использование UNION + group_concat()
В некоторых случаях хакер может провести атаку, но не может видеть более одной колонки. В случае MySQL взломщик может воспользоваться функцией:
group_concat(col, symbol, col)
которая объединяет несколько колонок в одну. Например, для примера данного выше вызов функции будет таким:
-1 UNION SELECT group_concat(username, 0x3a, password) FROM admin
[править]Экранирование хоста запроса
Зачастую, SQL-запрос, подверженный данной уязвимости, имеет структуру, усложняющую или препятствующую использованию union. Например скрипт
$res = mysql_query("SELECT author FROM news WHERE id=" . $_REQUEST['id'] ." AND author LIKE ('a%')");
отображает имя автора новости по передаваемому идентификатору id только при условии, что имя начинается с буквы а, и внедрение кода с использованием оператора UNION затруднительно.
В таких случаях, злоумышленниками используется метод экранирования части запроса при помощи символов комментария(/* или -- в зависимости от типа СУБД).
В данном примере, злоумышленник может передать в скрипт параметр id со значением -1 UNION SELECT password FROM admin/*, выполнив таким образом запрос
SELECT author FROM news WHERE id=-1 UNION SELECT password FROM admin/* AND author LIKE ('a%')
в котором часть запроса ( AND author LIKE ('a%')) помечена как комментарий и не влияет на выполнение.
[править]Расщепление SQL-запроса
Для разделения команд в языке SQL используется символ ; (точка с запятой), внедряя этот символ в запрос, злоумышленник получает возможность выполнить несколько команд в одном запросе, однако не все диалекты SQL поддерживают такую возможность. MySQL, например, не поддерживает.
Например, если в параметры скрипта
$id = $_REQUEST['id'];
$res = mysql_query("SELECT * FROM news WHERE id_news = $id");
злоумышленником передается конструкция, содержащая точку с запятой, например 12;INSERT INTO admin (username, password) VALUES ('HaCkEr', 'foo'); то в одном запросе будут выполнены 2 команды
SELECT * FROM news WHERE id_news = 12;
INSERT INTO admin (username, password) VALUES ('HaCkEr', 'foo');
и в таблицу admin будет несанкционированно добавлена запись HaCkEr.
Здравствуйте.
Работая программистом в государственных учреждениях, часто сталкивался с проблемой сложных паролей. Необходимо чтобы пароль был достаточно сложным, чтобы его нельзя было подобрать, и достаточно простым для запоминания.
Эту задачу решил после прочтения одной статьи, в которой говорилось об использовании карты местности, для генерации паролей. В подробности этого метода вдаваться я в этой статье не буду, а лучше расскажу мой.
Метод основан на зрительной и ассоциативной памяти (которая у человека в разы лучше, чем символьная), а так же на необычной двухфакторной защите, первым фактором (данными) будет являться некая придуманная пользователем история, вторым фактором (принадлежащим объектом) будет являться связь этой истории с конкретным человеком. С учетом того, что у каждого человека, за его хоть и недолгую жизнь, может быть огромное множество историй, этот факт можно отнести к принадлежащему объекту.
И так суть метода сводится к следующему: пользователю вместо поля ввода пароля дается таблица размерностью ~15*15, в каждой ячейке таблицы, небольшое изображение объекта или какого-то действия с описанием. Пользователь придумывает небольшую историю и, нажимая на изображения, формирует из них ее эквивалент, на пример: история - я рано утром ухожу на работу и прихожу поздно вечером; эквивалент - изображение-аналог пользователя, движения, рассвета, работы, возврата и заката. При каждом выборе изображений они выстраиваются в ряд и, если пользователь считает что ряд закончен, каждое изображение автоматически заменяется ~3 символами, закрепленными за изображением. Так формируется довольно сложный и длинный пароль, при чем пароль может быть даже не известен пользователю, поэтому исключается ситуация случайного разглашения. Этот пароль передается на сервер и записывается, как обычный. В следующий раз пользователю необходимо будет вспомнить историю и выстроить из таких же изображений ее эквивалент, система снова сформирует пароль и пользователь войдет.
Плюсами системы является генерация очень сложных паролей, которые невозможно определить методом перебора; защита от «Кей логгеров» (работа с мышью); простота запоминания; возможность записывать историю на физические носители, так как, даже узнав историю не просто определить какие картинки были выбраны для построения эквивалента.
Здравствуйте.
Мало кто конечно углубляется при написании интернет проекта о опасности передачи данных по незащищенным каналам, но рано или поздно нам приходится сталкиваться с проблемой перехвата данных. Особенно остро стоит эта проблема при регистрации и аутентификации пользователей, ведь часто данные передаются по каналам в открытом видел и хешируются на стороне сервера (редко встречал реализации md5 на JS, хотя сам всегда пользовался), реже передается хешь, при чем всегда один и тот же (так как обычно хешируется пароль или некие данные + пароль). Такой механизм имеет такую же уязвимость, что и передача открытого пароля, хеш можно перехватить и перебором найти пароль. Предлагаемый мной в данной статье способ не новый, но его суть в том, что пароль никогда не передается в открытом виде или в повторяющимся хеше (даже при регистраци). При каждой аутентификации хеш меняется, более того, в базе никогда не хранится пароль или хеш пароля, хранится связка пароля и случайного числа. Еще одним плюсом метода является то, что даже при использовании двух одинаковых паролей по каналам связи будут передаваться совершенно разные хеши этих паролей.
Плюсов у такого механизма много, но и минусы есть, основной это довольно большие затраты ресурсов клиента и сервера, другим минусом является необходимость перерегистрации пользователя (повторного ввода секретного ключа для обновления зерна и счетчика) при подходе счетчика к нулю.
И так в чем же состоит суть этой методики. Начну с терминов:
Секретный ключ - известная только пользователю последовательность символов (пароль);
Зерно (открытый ключ) - сгенерированная сервером последовательность из ~5 случайных символов, хранящаяся вместе с логином пользователя на сервере;
Итератор (счетчик) - текущее число итераций хеш функции. Хранится на сервере вместе с логином и зерном;
Алгоритмы метода: Регистрация - пользователь задает свой логин и передает его на сервер, сервер записывает его в базу и сразу генерирует зерно и устанавливает итератор данного пользователя в максимальное значение (на пример 300), после чего передает зерно и значение итератора клиенту. Теперь пользователь определяет свой пароль (секретный ключ), браузер получив пароль от пользователя и зерно с итератором от сервера создает связку пароль + зерно и применяет к данной связке хеш функцию (на пример md5), затем к полученному хешу применяет снова хеш функцию и так столько раз, сколько указано в итераторе. Полученную строку браузер передает на сервер. Сервер уменьшает значение итератора для заново пользователя на 1 и записывает полученный от него хеш к зерну, логину и итератору. Таким образом при регистрации пароль не передается в открытом виде и не хранится в базе в виде простой связки.
Аутентификация - пользователь вводит свой логин и передает его серверу, сервер находит данный логин в базе и передает пользователю его зерно и значение итератора. Пользователь теперь вводит пароль и браузер создает связку пароль + зерно и применяет на нее хеш функцию столько раз, сколько указано в итераторе. Полученный хеш он передает на сервер. Сервер применяет к нему хеш функцию еще один раз и сравнивает получившееся с хранимом у него хешем данного пользователя, если они одинаковы, то аутентификация считается успешной и сервер записывает полученный от пользователя хеш (который был до наложения на него сервером хеш функции) и заменяем им хранимый в базе хеш, а так же уменьшает значение итератора на 1. Таким образом при каждом входе пользователя будет применяться разное количество хеш обработок связки пароль + зерно, и за счет этого передаваемый хеш будет всегда разный. Более того даже при подходе итератора к нулю и необходимости заново перерегистрироваться, зерно уже будет другим и это будет приводит к созданию все новых хешей.
Вы, наверное, встречались с тем, что на разных сайтах можно найти одинаковую информацию. А всё это происходит следующим образом: один сайт является первоисточником, а все остальные просто копируют данную информацию на свой сайт (причём порой не заморачивая себе голову сохранением авторских прав или постановкой ссылки на первоисточник). Хорошо, конечно, когда нужную информацию можно найти везде, но непонятно, почему это происходит без ведома автора??? Ведь на просьбу использовать какой-либо материал обычно отвечают положительно (придётся разместить ссылку).
Возникает вопрос: как в данном случае поступать автору? Хорошо, если вашу информацию использовали на одном-двух сайтах, но если таких сайтов десять и более, то не разбираться же со всеми! Так вот, в данной статье речь пойдёт о том, как затруднить подобным "авторам" копирование ваших материалов.
1 способ: в тег <BODY> включить параметр oncopy="return false" . Это не даст скопировать информацию в буфер. Конечно, текст можно взять из исходного кода (щелчок правой кнопкой мыши на странице => Просмотр HTML-кода). А если код сложный, то на это потребуется много времени.
2 способ: включить в <BODY> параметр onselectstart="return false". Данный способ запрещает выделение текста вообще. Замечательно! - скажете вы. Я бы так не сказал. Данный способ, в отличие от первого, явно показывает, что информацию пытаются защитить. И если в первом случае "злоумышленник" "поломает" себе голову (а некоторая часть и бросит это дело), то в данном случае он наверняка полезет в исходный код.
Вот парочка способов. Существуют java-скрипты, запрещающие нажатие правой кнопки мыши, но в любом случае, посмотреть исходный код возможность есть (с использованием скриптов затрудняется сохранение картинок, хотя и тут - WebCopier в помощь).
Вы, возможно, слышали, что использование её может привести к небезопасной работе вашей программы (скрипта). Но давайте разберемся, как эту опцию могут использовать в противоправных целях и как от этого защититься.
Что представляет собой register_globals?
Это опция в php.ini, которая указывает на необходимость регистрации переменных, полученных методом POST или GET в глобальный массив $GLOBALS.
Для ясности приведу пример при register_globals=On.
Есть файл "index.php" с содержимым:
<?
echo $asd.' - локальная переменная<br>';
echo $GLOBALS['asd'].' - ссылка в глобальном массиве $GLOBALS<br>';
echo $_GET['asd'].' - $_GET["asd"]';
?>
В адресной строке напишем: index.php?asd=123
Получим:
123 - локальная переменная
123 - ссылка в глобальном массиве $GLOBALS
123 - $_GET['asd']
Как мы видим, создались 2 переменные: одна локальная (+ ссылка в $GLOBALS), другая в массиве $_GET. Многие не используют массив $_GET вообще, они продолжают обрабатывать переменную $asd после получения ее извне.
Но давайте вдумаемся, зачем нам "загрязнять" массив $GLOBALS? Для этого у нас есть специальные массивы, хранящие данные, переданные методами GET (массив $_GET) и POST (массив $_POST).
Тот же самый пример, но при register_globals=Off:
- глобальная переменная
- ссылка в глобальном массиве $GLOBALS
123 - $_GET['asd']
Т.о. не была создана локальная переменная и для манипулирования с <$asd> мы должны использовать массив $_GET.
Возможно, уже сейчас вы изменили свое мнение о register_globals.
Вероятно, вам придется, что-то переписать в своих программах, но оно того стоит.
А теперь я расскажу вам, как взломщик может воспользоваться этой опцией в своих целях, т.е. при register_globals=On.
Начну от простого к сложному.
Часто мы видим предупреждения:
Notice: Undefined variable: asd(название переменной) in ****
Что это значит? Это значит, что переменная $asd не была определена явно.
Например, некоторые люди балуются подобным:
<?
for($i= 0;$i<10;$i++)
{
@$asd.=$i;
}

echo $asd
?>

Т.е. не определив переменную, сразу начинают ее использовать. Приведенный код по идее не страшен, но задумайтесь, а вдруг эта самая переменная $asd, в последствии записывается в файл? Например, напишем следующее в строке адреса: "index.php?asd=LUSER+" и получим: "LUSER 0123456789". Ну разве приятно будет увидеть такое? Не думаю.
Предположим мы пишем систему аутентификации пользователя:

<?
if($_POST['login']=='login'&&$_POST['pass']=='pass')
{
    $valid_user=TRUE; // Юзер корректный
}

if($valid_user)
{
   echo 'Здравствуйте, пользователь';
}
else echo 'В доступе отказано'
?>
Привел я заведомо дырявую систему, стоит нам только написать в адресной строке "index.php?valid_user=1" и мы получим надпись "Здравствуйте, пользователь"
Этого бы не случилось, если бы мы написали так:
<?
if($_POST['login']=='login'&&$_POST['pass']=='pass')
{
    $valid_user=TRUE; // Юзер корректный
}
else $valid_user=FALSE;

if($valid_user)
{
   echo 'Здравствуйте, пользователь';
}
else echo 'В доступе отказано'
?>
Т.е. сами определили переменную $valid_user, как FALSE в случае неудачи.

Продолжим далее:
Теперь использование функции IsSet() становиться небезопасно, т.к. любой может подменить переменную на угодную ему.

Приведу пример с sql-инъекцией:
<?
if(@$some_conditions) // некоторые условия
{
    $where='id=3';
}

echo $query='SELECT id, title, description FROM table '
.'WHERE '.(IsSet($where)?$where:'id=4')
?>
В адресной строке напишем:

"index.php?where=id=0 + UNION + ALL + SELECT + login, + password, + null + FROM + admin + where + login='admin'",

получим sql-инъекцию:

SELECT id, title, description FROM table WHERE id=0
UNION ALL SELECT login, password, null FROM admin where login='admin'

И взломщик получает ваши явки и паролиsad

Как вы видите, все примеры имеют дыры в защите, которые можно эксплуатировать через включенный register_globals.

Справиться с подобным можно, если всегда определять переменную вне зависимости от условий. Или же использовать инкапсуляцию переменных в функциях, т.е. когда вы определяете функцию, то переменные внутри нее будут закрыты извне, например:

<?
function asd()
{
// Какие то действия

if(IsSet($where))
{
    echo $where;
}
else echo '$where не существует';
}
asd();
?>


Теперь, если мы напишем в адресной строке: "index.php?where=123"
Даст: "$where не существует"
Но это при условии, что вы не устанавливаете переменную $where как глобальную, т.е. "global $where"

Я могу придумать еще очень много примеров, но думаю, что приведенных мною вам будет достаточно для понимания.
Хочу сказать, что все эти проблемы канут в лета, когда вы установите опцию register_globals=Off и попробуете заново все приведенные выше примеры.

Это можно сделать как в php.ini, но большинство хостинг провайдеров вам это не позволят, потому придется воспользоваться файлом .htaccess

Создаем файл с названием: .htaccess
Запишем в него:

php_flag register_globals off

И все, теперь некоторые вопросы безопасности решеныsmile

Немного о причине написания мной этой статьи:
Лично я никогда не использовал register_globals = on, т.к. мне казалось это нелогичным. Также я знал, что это еще один "+" к защите. Но в полной мере я не осознавал, насколько это может быть опасно. Случилось это когда я решил написать GSMgen - Google SiteMap generator, который должен был работать безопасно и при включенном register_globals. Когда же я начал его тестировать, у меня был шок: так как мне нравится использовать функцию IsSet(), я нашел в ней непосредственную уязвимость, и в процессе мне пришлось от этого отказатьсяsad Что поделаешь...

Я очень надеюсь, что эта статья изменит ваше мнение относительно register_globals. Думаю, что со временем все хостинг провайдеры будут ставить register_globals = off по умолчанию. Но пока этого нет, вы знаете как с этим бороться;-)
Оружие хакеров или как искать дыры.
Допустим вы изучили какую-нибудь дыру, будь то Уникод например или дыры в PHP, но как найти дырявый сайт? Ведь на угад в адресе вводить, что пальцем в небо… Здесь я попробуй рассказать вам как это делаю я и какие способы есть еще
Вы наверняка слышали от кого-нибудь, что : «Оружие хакеров – поисковики!», но не могли этого понять. Я тоже по первости не мог всосать, причем тут поисковики, теперь всосал =). Давайте подробно разберем пример на поиске дырявых PHP. На самом деле все очень просто. Ну во-первых, нужно найти php страницы, для этого в поиске вводим:
Index.php
Теперь подумаем, сколько же сайтов в инете на php написано? Очень много, нужно как-нибудь укоротить найденное. Например добавим домен, если вы хотите искать только русские php сайты то запрос будет выглядеть примерно так:
.ru/index.php
Вот, количество найденных сайтов сократилось, но убрались лишь не нужные нам, что дальше… А дальше вот что. Дыра эта, про которую я уже писал, не в самой php, а в PHP-Nuke, ага, значит добавим запрос следующим образом:
.ru/index.php & nuke
Теперь поисковик будет искать все русские php сайты/порталы и из найденных выберет все, которые Nuke =). Далее читаем мою статью (Хакерство-Интернет-Админ-портала…) и проверяем найденное на вшивость. Вот и все!

Как это делают другие. Вообще я знаю два способа, это вышеописанный и с помощью РОБОТОВ. БОТы, это специальные проги, которые дают ваш запрос на поисковики и возвращают результат, что очень экономит время поиска дыр. Сам я о них знаю мало. Если кто знает больше, в смысле, их точный алгоритм плиз говорите, я собираюсь написать БОТ, для участников HackZone. Дело в том, что в инете я найти их не мог, если кто знает ссылки, тоже скидывайте.

Теперь пара советов. Во-первых, лучше всего искать на домене com, он более большой, отсюда и больше уязвимых сайтов. Во-вторых, поиск можно ограничивать до бесконечности, например, если вам нужны лишь порталы знакомств, то запорс будет выглядеть примерно так:
.ru/index.php & nuke & знакомства и т.д.
Скрытый контент: Для выполнения действия необходимо авторизоваться!
Запрет индексации сайта поисковыми ботами при помощи.htaccess

При активной разработке многие используют копии сайта в других доменах, для эксперементов или доработки сайтов (не на работающем же вносить изменения).
И вот многие сталкиваются с проблемой как отгородить поисковики от этого домена и притом оставить рабочую версию сайта


Проще всего и без вмешательств в код это сделать при помощи .htaccess
Создаем файл .htaccess и пишем в нем:

SetEnvIfNoCase User-Agent "^Yandex" search_bot
SetEnvIfNoCase User-Agent "^Yahoo" search_bot
SetEnvIfNoCase User-Agent "^igdeSpyder" search_bot
SetEnvIfNoCase User-Agent "^Robot" search_bot
SetEnvIfNoCase User-Agent "^Googlebot" search_bot
SetEnvIfNoCase User-Agent "^msnbot" search_bot
SetEnvIfNoCase User-Agent "^Aport" search_bot
SetEnvIfNoCase User-Agent "^Mail" search_bot
SetEnvIfNoCase User-Agent "^bot" search_bot
SetEnvIfNoCase User-Agent "^spider" search_bot
SetEnvIfNoCase User-Agent "^php" search_bot
SetEnvIfNoCase User-Agent "^Parser" search_bot

<Limit GET POST HEAD>
Order Allow,Deny
Allow from all
Deny from env=search_bot
</Limit>
для проверки работоспособности можно использовать следующий PHP-скрипт
<?php
if(empty($_POST)) {
?>
<form action="?" method="post">
<table><caption>Открываем сайт представлясь под любым User-Agent</caption>
<tr><td>User-Agent</td><td><input type="text" size="40" name="ua" value="GoogleBot"></td></tr>
<tr><td>Host</td><td><input type="text" size="40" name="host" value="www.exemple.com"></td></tr>
<tr><td>GET</td><td><input type="text" size="40" name="get" value="/index.php"></td></tr>
<tr><td> </td><td><input type="submit" value='Отправить'></td></tr>
</table>
</form>
<?php
} else {
echo "<b>Отправляем заголовки:</b><br>";
$host=$_POST['host'];
$get=$_POST['get'];
$ua=$_POST['ua'];
$headers=array(
'get'=>'GET '.$get.' HTTP/1.0',
'host'=>'host:'.$host,
'useragent'=>'User-Agent:'.$ua,
'cc'=>'Connection: close'
);
echo "<pre>"; print_r($headers); echo "</pre><br><br><b>Ответ сервера:</b><br>";
$out="";
$spy=fsockopen($host,80,$errno,$errstr,20);
if(!$spy) $page.="<font color=red>Ошибка создания сокета</font>";
elseif(fwrite($spy,implode("\r\n",$headers)."\r\n\r\n"))
while(!feof($spy))
$out.=fgets($spy,1024);
echo '<pre>'.htmlspecialchars($out).'</pre>';
}
?>
ну вот теперь Боты могут спать сколько вы пожелаете krut
Определение: ddos атака - сокращение от «distributed denial of service attack»

При помощи этих атак временно падали крупнейшие и известнейшие компании, такие как yahoo!, ebay, buy.com, amazon.com, cnn.com и целый ряд других ...

Я не буду жевать сопли и напишу то, о чем как правило никто не никогда не пишет в статьях про ddos.

В основном то что мы видим в сети это поверхностные описания удачных атак, или вопли пострадавших от них.

1) Цель и принцип ddos

Цель ddos вывести обьект атаки из рабочего состояния что может повлечь за собой большие финансовые потери во время ***а или расходы на оборудование для защиты от него и з/п специалистов. Любой вебмастер понимает, что *** его сайтов на 2-3 часа нанесет серьезный вред бизнесу, а если на неделю, то ресурс скорее всего придется поднимать с нуля снова . Я вообще не говорю о владельцах платных сайтов и серьезных Е-комерс ресурсов, чьи убытки могут составлять десятки тысяч долларов в день.

Технология ddos атак подразумевает метод грубой силы - вы тем или иным способом пытаетесь "забить" канал, открывая максимально возможное количество соединений на тот или иной сервис или отправки огромного кол-ва информации которое сервер не в состоянии обработать. все это ведет к потере скорости или полной остановке (зависанию) атакуемого ресурса.

2) ddos - это distributed атака,
то есть распространенная, когда вас атакует не один сервер от которого можно легко закрыться фаирволом, а сразу тысячи или десятки тыс., иногда могут быть сотни тысяч и миллионы атакующих ботов ( многие называют их зомби )

Что есть зомби ?

Зомби - это зараженный программой (или сломанный) компьютер или сервер, который будет выполнять команды управляющего сервера.

Как компьютер становится зомби ?

Зомби создаются как правило используя эксплоиты для ОС. Заражая машины через веб браузер при посещении сайтов, при получении почты, или через установку программного обеспечения с установленными в него троянами.

Как много может быть зомби ?

cуществуют дыры которые до сих пор не закрыты и иногда процент заражаемости трафика может достигать 80 % всего трафика на сайте, спам может рассылаться огромными тиражами и как результат мы имеем десятки тысяч зомби.

В зависимости от совершенства кода на самом зомби они могут выполнять разные типы запросов на сервера, иногда делая себя совсем не видимыми для фаирвола или сложно отличимыми от реального серфера, что разумеется усложняет борьбу с ними.

Типы атак я описывать не стану они очень сильно варьируются от старинных типа пинг и syn флуда до новых разработанных персонально для новой атаки.

Все они ведут к тому что сервер ложится как правило и попытки его вернуть к жизни заканчиваются тем, что он снова лежит.

В общем довольно грустная история с ddos атаками. Многие хостеры просто выключают сервера в случае обнаружения атаки. Это демонстрирует то, что они не могут реально ничего с ними поделать.

Борьба с ddos

Это самый наверное интересный кусочек, а так же самый сложный.

Самое сложное в том что борьба с ddos в 98 % случаев ложится на плечи вебмастера, так как провайдеры в большинстве своем просто бьют болт и стандартная схема у них, это поставить на нуль роутинг ваши ip и таким образом для них проблема ddos решена. Вебмастера такое решение не очень радует, так как его сайты при этом ложатся вообще.

Конечно, есть продвинутые провайдеры, которые могут посодейтвовать в борьбе, но это редкость и опять же наджо будет им платить пятизначные цифры что бы иметь какое то влияние на них. Так что остается решать проблемы самому, о том как их решать я и расскажу вам.

1) На уровне сервера.
Сервер должен иметь удаленный ребут и вывод консоли сервера на другой ip адрес по ssh протоколу. Это позволит вам быстро перезагружать сервер, что бывает более чем нужно в самом начале ddos атаки. Вывод консоли позволит полностью выключить ssh на сервере. Это необходимо потому, что его тоже очень часто досят вместе например с вебсервером, что бы усложнить работу админа сервера или сделать сервер вовсе не доступным для администрации.

2) На уровне сервисов сервера.
Секюрити аудит – must be, то-есть, по-русски, должен быть сделан, все сервисы машины должны быть отпатчены от всех известных и не известных дырок. О тюнинге веб сервера под ddos атаками можно писать целую книгу, поэтому я не буду лишать себя куска хлеба. smile

3) На уровне сети.
Для начала блокируются все то, что может дать больше инфы атакующему о вас. Блокируется пинг и трейс. Сервер убирается под nat. Маскируется его ip как только это возможно. Это уже очень професиональный способ защиты сервера путем прятания его ip адреса. Применяется в многих платных системах защиты от ddos.

4) На уровне провайдера.
Через анализ пакетов или через блокирование ip адресов.

5) На уровне железа.
Применяя хардварные решения от ведущих фирм производителей типа Сisco, 3com, nortel и тп. Данные решения борьбы на аппаратном уровне потребуют больших финансовых затрат от 10к и выше. Комплексные решения обойдутся около 50-80 тыс долларов. Так же сюда можно отнести производителей 3rd party оборудования для хардварной защиты. Большая их часть действует по принципу анализа пакетов и дальнейшей их фильтрации где нужный пакеты проходят к серверу, а ненужные фильтруются и сегменты сети откуда они пришли блокируются роутером или фаирволом. Более продвинутые системы умеют прятать ваш сервер полностью и в сети никогда не встретится его ip адрес и его прямое сканирование и ddos атака невозможны.

6) На уровне админов вашего сервера.
Используя логи фаирвола сервера вы видите кучу ip адресов откуда на вас идут атаки. Вы можете анализировать его и искать уязвимые рабочие станции среди них, из 10000 машин 1-3 обязательно окажутся доступными для того что бы по ним полазить. Вы можете найти самого зомбика который осуществляет атаку на вас. Далее его можно попытаться поковырять, чтобы найти кто пускает атаки на вас и если повезет найти контрольный сервер и как вариант контратаковать его. Хотя такое будет не возможно если ddos атака не контролируемая, а например вирусная. Напомню, это когда вас атакуют рабочие станции которые были заражены предварительно и их действия не контролируются вручную, они не очень опасны так как если вы смените, например, ip и домен, то такая атака умрет сама.

7) Комбинированное использование всех систем.

В заключение хочу сказать что всё, что тут написано не покрывает и 80 % всех методов борьбы с ddos и на эту тему работают очень много людей во всем мире. Так что я в этой небольшой статье не смогу описать всего, даже если очень захочу. Но, надеюсь, она вам немного поможет для понятия азов того, как необходимо бороться с ddos атаками.
Облако тегов / Авторы