Вчера я вкратце рассмотрел те неопределенности и опасность, которую несет использование коротких ссылок. Как минимум мы не можем точно знать, что ожидает нас при открытии короткой ссылки — страница с информацией или файл для загрузки и т.д. В пределе короткая ссылка может использоваться злоумышленниками для того, чтобы замаскировать опасный сайт. Сегодня рассмотрим один из возможных вариантов проверки короткой ссылки на предмет её опасности для пользователя. Прежде всего определимся с тем, какие инструменты мы будем использовать. Ну, Delphi — это само собой. А что касается остального — читаем далее.
Вы никогда не задумывались откуда, например FireFox знает, что Вы собираетесь перейти на опасный сайт? Понятно, что должна существовать некая база данных, содержащая информацию об опасных сайтах, например как у Google, но как получить к ней доступ? Я провел небольшой поиск подобных баз данных в Интернете и вот, что мне удалось собрать.
Базы данных по опасным сайтам
PhishTank — это база по сайтам, которые были замечены в фишинге. Также, PhishTank предоставляет после регистрации бесплатный доступ к API. По сути — к получению базы данных по опасным сайтам в форматах xml, json или csv. Также можно получить данные об опасных сайтах и без регистрации. Все ссылки на файлы содержатся на странице Developers. На текущий момент PhishTank содержит 2848 записи по сайтам, замеченным в фишинге.
Malware Domain List — содержит данные по сайтам, замеченным в распространении опасного ПО, вирусов, порнографии и т.д. Для бесплатного скачивания доступны данные по опасным доменам в форматах XML и TXT.
SURBL — на данный момент самая крупная из всех обнаруженных мной баз данных по опасным сайтам. В базах surbl содержатся сайта замеченные в фишинге, распространении вредоносного ПО, порно, спама и т.д. Базы формируются на основе обращений пользователей, а также с использованием других открытых баз данных по опасным сайтам интернета. На момент моей первой встречи с SURBL база опасных сайтов насчитывала >500000 сайтов. Кстати, этой же базой пользуется такой Касперский :). Вобщем, я решил остановиться на использовании именно этой базы данных.
Теперь рассмотрим алгоритм проверки короткой ссылки на предмет опасности.
Алгоритм проверки короткой ссылки
Что касается проверки короткой ссылки, то эту задачу можно разделить на три части:
1. Получить свежий список опасных сайтов от surbl. Так как база surbl составляется на основе других крупных баз, то получение наиболее полного списка опасных сайтов для нас упрощается — достаточно скачать всего 1 (но «тяжелый») файл с данными.
2. Проследить всю цепочку редиректов, начиная от редиректа сервиса сокращения ссылок и заканчивая моментом, когда очередной запрос Head вернет нам код статуса 200, 404 и т.д. То есть пока не «упремся» в адрес с которого редиректов более нет.
3. Проверяем всю цепочку доменов по нашей локальной базе данных и выводим результат.
Как видите, все достаточно просто. Теперь преступим к реализации этого алгоритма в Delphi.
Реализация алгоритма
В работе с http-протоколом я буду использовать Synapse.
1. Получение актуальной базы опасных сайтов.
Так как файл с базой достаточно объемный (около 10 Mb), то его скачивание может занять достаточно много времени. Поэтому следует предусмотреть при скачивании какую-либо визуализацию процесса скачивания. Например, как рассмотрено в посте «Synapse. Скачиваем данные с ProgressBar’ом.«.
Теперь посмотрим как можно проследить всю цепочку редиректов, начиная от сервиса коротки ссылок и заканчивая целевой страницей. Сделать это, используя Synapse довольно просто:
uses httpsend, synautil; function GetTargetURL(const aHeaders: TStringList): string; var i:integer; begin Result:=''; if aHeaders=nil then Exit; for i:=0 to aHeaders.Count - 1 do begin if pos('location:',LowerCase(aHeaders[i]))>0 then begin Result:=copy(aHeaders[i],11,length(aHeaders[i])-pos('location:',LowerCase(aHeaders[i]))); break; end; end; end; procedure GetChain(const aURL: string); var i:integer; Prot, User, Pass, host,Port, Path, Para, URI: string; RedirectURL:string; begin RedirectURL:=aURl; with THTTPSend.Create do begin repeat ParseURL(RedirectURL, Prot, User, Pass, Host, Port, Path, Para); FDomainChains.Add(Host); if HTTPMethod('HEAD',RedirectURL) then begin RedirectURL:=GetTargetURL(Headers); headers.Clear; Document.Clear; if Length(Trim(RedirectURL))=0 then break; end else break; until (ResultCode=200)or(ResultCode>=404); end; end;
ParseURL — это метод из модуля synautil — разбирает URL на составные части.
Теперь, в зависимости от того, какой из баз данных Вы решите воспосльзоваться, можно просматривать каждый из доменов в цепочке на предмет его опасности. Я решил для себя проверять не отдельные URL’ы, а домены целиком.
В целом представленный пример проверки подойдет для проверки любой ссылки, а выбор той или иной базы данных поможет проверить сайт на спаммность, фишинг, распространение вредоносного ПО и т.д. или на все сразу, если будите использовать surbl.

Спасибо, хорошая наработка
Интересная информация по synapse. Могли бы Вы осветить про то, как вместе с synapse использовать сжатие трафика (GZip, Deflate). С использование библиотеки: DelphiZlib к примеру (http://www.base2ti.com). Спасибо.
С GZip по большому счёту пока дел не имел, но думаю попробовать ег использование в каком-нибудь проекте. Как получится что-нибудь путнее — отпишусь :)
>С использование библиотеки: DelphiZlib
Подключаешь в uses ZLibExGZ;
Если в ответе сервера есть gzip, то GZDecompressStream(HTTPDocument, OutStream);
где HTTPDocument и OutStream имеют тип, например, TMemoryStream.
Очень хороший пример,собираю по крупицам примеры работы с этой библиотекой,не подскажете где можно поподробней о ней почитать?
Кое-какие материалы на русском есть у меня в блоге, а так я все, что касается Synapse искал также по крупицам на форумах
спасибо.а тогда не подскажете хорошие материалы на английском?
Только офф.сайт. У меня с английским в послднее время нелады, поэтому в буржунет я не ходок :)
Подскажите пожалуйста, как проверить HTTPS сайт (код ответа). Пользуюсь этим
if HTTP_.HTTPMethod(‘GET’, ‘http://mysite.com’) then Response:=HTTP_.Resultcode;
А как проверить ‘https://mysite.com’? Всегда возвращяет ноль.
Спасибо!
Подключить модуль ssl_openssl.pas, положить в папку с программой 2 dll, про которые я говорил здесь и повторить то же самое, что используете Вы, т.е.:
if HTTP_.HTTPMethod(‘GET’, ‘http://mysite.com’) then Response:=HTTP_.Resultcode;Оперативненько, однако. Аж не привычно :))
Спасибо, все сразу заработало. Про ssl_openssl совсем забыл.