О dip.:studija в печати (Naujoji komunikacija № 8)

O Dabarties interneto prokektų studija (dip.:studija или dip.:studio) и её поездке в Каны наконец опубликовали статью в NK: Naujoji komunikacija № 8 – “Medijų karas”. Единственное средство массовой информации в Литве, которое уделило должное внимание достижениям компании. Пусть только в печатном виде, пусть и с опозданием – но огромной статьёй с фотографиями на 3 страницы.

Вот такая короткая новость о компании, в которой я работаю.

Google Toolbar для Firefox

Не прошло и года, как Google выпустила toolbar для нашего всеми любимого Firefox с поддержкой своих кнопок, Google bookmark а так-же можно любой документ, поддерживаемый в Google Docs & Spreadsheets втащить в Firefox и он откроется в Google Docs & Spreadsheets. При установки сам взял кнопки, которые я использую в Google toolbar у Internet Explorer 6. С праздником!

Что ищут здесь посетители

Вообще, самый популярный запрос в этот блог: где/как/от куда/каким способом скачать IE6 или просто Internet Explorer. Так вот, скачать его можно было прямо с сайта Microsoft. Вообще, весь процесс описан в статье: Download IE6 – In FULL….. We show you HOW!. Ну или коротко, но запутано тут: Как скачать Microsoft Internet Explorer 6.

А теперь 13 самых интересных запросов за последние 30 дней, по которым люди пришли в этот блог:

  • водочное меню – хорошее сочетание, правда про водку я особо не писал никогда, за исключением одного раза
  • кол-во запросов в live.com – вот чего не знаю, того не знаю, вообще, народ, зачем вам это?
  • установка ajax на apache – а вам основы учить надо, а лучше вообще, бросить строить web
  • взлом zaza – производиться ломом, монтировкой, любым тупым предметом по голове
  • делаем реактивный двигатель на велосипед – обязательно опишу потом, как к ракете приделывали педеальную тягу и прочие нетрадиционные способы передвижения между галактик
  • исследование скачать – можно конкретнее, какое исследование вы ищите?
  • регистрация домена в зоне lt – элементарно, Ватсон – domreg.lt
  • установка – обязательно произведу установку памятника, операционной системы любой сложности и размера, крана, красной клизмы и прочих устанавливаемых; интересно, установку чего они искали?
  • польша идиотизм – как странно некоторые страницы трактуют поисковые страницы
  • острые полиморфические психические растройства – да да, встречаются иногда, но мы с ними боремся, да; а ещё я как суслик свистеть умею и мысли читать на расстоянии
  • готовые баннеры скачать – а вот зачем вам скачивать чьито готовые баннеры? Свои сделать/заказать слабо?
  • как apache читает – как и любой другой индеец, apache читает свои письмена в стандарном направлении для древне-америнакского проязыка, если индеец старый – он их не читает а знает наизусть
  • apache хватает только на 4 часа – экий вы маньяк, замучить индейца за 4 часа в щепки – да вы монстр просто и главное его вам мало, вы ещё хотите; современные жители того материка, на котором жили индейцы, их истребляли долгие годы, а вы за 4 часа со всеми детьми

А остальное совсем по теме.

5 лет на одном CMS

Не прошло и 5 лет, как Вильнюсская коллегия сменила CMS, который поддерживал её главный сайт. Наконец, мой (ладно, наш) RISING CMS отдохнёт в архивах на болванках и не будет отдавать страницы пользователям интернета. Сайты факультетов пока не изменились, но я думаю, они очень скоро это изменят. Ко всему прочему, коллегия сменила и дизайн сайта, который весьма не дурной, по сравнения с прошлым разом.

А мне теперь придётся во всех CV и портфолио пометить, что сайт Вильнюсской коллегии мой CMS поддерживал с 2002 по 2007 год. RIP, RISING, RIP.

На замену RISING CMS они выбрали CMS Made Simple, в котором за 15 минут удалось найти XSS type1 (они знают и уже залатали его у себя на сервер). Посмотрим, как им будет везти дальше.

Edomus опять атакует – их ответ

Их ответ не заставил себя долго ждать. Justinas Šimkus отписал в течении часа. Очень извинялся. У них видети-ли ошибка возможно произошла. Может быть ввели по ошибке кто. Советует нажать на ссылку отписаться внизу письма. Нажмём. Посмотрим что будет. В прошлый раз вроде как не помогло.

Мне вот интересно, чесно говоря, кто и как ввёл 2 разных адреса: мой и супруги. Я повторюсь, мой общедоступен, а вот адрес супруги создан примерно 3 месяца назат и нигде, кроме порталов поиска работы не светился. Явно список либо купили, либо украли, я даже очень подозреваю у кого (кстати, писал об этом).

А вообще, рекомендую им провести реорганизацию их спам-рассылки:

  1. подтверждение об регистрации, чтобы кто попало кого попало не регистрировал. Элементарное письмо при регистрации (ой, а тогда купленые/ворованные листы нельзя будет использовать).
  2. более явное объяснение в каждом письме, почему Я получил это письмо (нет, я понимаю, что вроде “я сам” регистрировался, но всё же, напомнить не помешает из уважения к пользователю).
  3. персонализация писем. Хотите эффективности – знайте своих “клиентов” в лицо, хотябы по имени (при регистрации попросите ввести, пусть не обязательно, но будет), те кто интересуется недвижимостью, обязательно введут, а потом, это можно использовать в разных целях.
  4. вот вы его разослали, а, учитывая урлы в письме, вы ну никак не измеряете эффективность своей рассылки. Пустая трата денег. Хотя, учитывая их/ваш бизнес денег мешками и их можно очень сильно тратить. А, или либо я чего-то не знаю о реферерах при нажатие ссылки в письме. Нет, я знаю, вы не узнаете, сколько людей прочло, но вы точно бы знали, сколько получателей заинтересовала та или иная информация, какой эффект дало письмо.
  5. не рассылать её вообще .)

Как, бывает, хранят пароли

Я, пока, опущу ту вкусную часть, как при помощи SQL-Injection можно получить пароли пользователей, но желающие могут самостоятельно прочесть IV раздел мануала о Безопастности – SQL Injection . И расскажу о самой неприятной (ок, не всем не приятной) привычке – открытых паролях и том как их хранят в других случаях.

Итак, первый и самый простой случай, когда пароли хранятся в таблице (название не имеет значения, но очень часто это бывает таблица users, admins или members, возможны разные префиксы), в поле password (обычно нужные поля очень легко узнать по форме регистрации или логина). Оно очень приятно, когда у сайта есть уязвимость ввиде SQL-Injection – вытянуть пароль и логин нужного вам пользователя не составит никакого труда. Время, нужно на поиск, занимает от 10 минут до нескольких часов – всё зависит от мастерства и фортуны (но не стоит исключать человеческий фактор). Кстати, если базу уводят (физический дамп с сервера), создателям скажут “спасибо”. Такие разработчики обычто оставляют незащищённый phpMyAdmin на сервере в легко доступном месте, а иногда оставляют SQL-Injection в скрипте логина в CMS. Вы конечно скажете – бред, не может быть, но всё-же такие случаи встречаются в моей практике и не раз.

Более сложный вариан для взломщиков – когда пароли хешируют. Обычно, встречаются варианты когда пароль просто хеширую при помощи md5 или других функций. Хотя тут, народ исхитрился иметь небольшие базы готовых хешей. Значит и тут пароли могут пострадать – вопрос размера базы хешей и то, какой это хеш. Конечно, все пароли не раскроют. Часто в базе – словари, фразы, а всякие “kld8jSkhYakKd772” там наврятли будут – всё зависит от размера базы, вашей удачи и, иногда, от теории вероятности (про коллизию не забываем, да).

Итак, в резюме, получается, что с паролями излишняя параноидальность вам/нам не помешает. Если вы поманипулируете с паролями пользователей (да и администраторов) – вам это не повредит ни в коем случае. Сделать пару SALT, докинуть чего из “логина”, добавить битовую операцию, потом сделать base64 енкодинг и только потом хеш – это наверняка затруднит восстановление ворованного пароля.

А что вы посоветуете?

Что я знаю о register_globals

Постоянно сталкиваюсь с серверами, где по умолчанию register_globals = On. Да, мне ничто не мешает взять .htaccess и отключить: php_value register_globals Off или написать письмо администратору сервера. Однако, иногда и сам забываешь о той угрозе, которую несёт в себе register_globals = On.

Для того, что-бы воспользоваться чем-то, что даёт вам register_globals = On, нужно либо иметь на руках исходники скрипта, либо быть очень счастливым с…м сыном (ну ещё есть шанс, что ошибки, выбрасываемые PHP вам помогут). Естественно, речь идёт о Global Scope.

На днях я перебирал один маленький сайтик, где PHP используется только для того, что бы можно было удобно и быстро подключить хедер и футер, меню и для страниц легко менять тайтл и мета данные. Такой классический сайт из учебника, плюс несколько наворотов, которые позволяют кешировать сайт на стороне клиента так, как будто это статически HTML. Теоретически, если отключить expose_php и сделать ServerSignature Off, а ServerTokens Prod мало кто догадается, что это PHP.
И нашёл я там одну переменную, которая отвечала за подключение отдельного CSS для страницы. Она была задекларированна не во всех файлах, а толxко там, где требовался дополнительный CSS файл. Именно в тех файлах, где эта переменная не была установлена, её можно было установить при помощи GET, POST или COOKIE (ведь мы помним о variables_order). Плюс никакой фильтрации. Идеальное место для XSS type1 атаки. Но для такой атаки имя переменной нужно знать.

Есть ещё такой стиль программирования, когда массивы никто не декларирует, а сразу к ним обращается. Я имею ввиду, что некоторые программисты не пользуются таким выражением: $arr = array ();, а сразу выполнят присваивание: $arr[] = ‘some value’;. Опять же через GET, POST или COOKIE в таком случае можно передать первые ключи для массива $arr. И тогда сколько таких переменных есть у них, которые можно поменять, зная их имена?

Вроде и нет ничего страшного, действует только на Global Scope, надо знать название переменной, но вы не можете гарантировать, что копия сайта е попала в руки мальчишам-плохишам. Так, однажды, получив исходники одной CMS, можно досконально изучить её код, найти уязвимые места, а потом вскрыть этак сайтов 10-15 с одной и той-же ошибкой. Именно так однажды случилось с CMS моего знакомого: CMS решал, человек залоглен или нет, опираясь на онду переменную $admin_id. Стоило сделать запрос admin.php?admin_id=1 и коробочка раскрылась и даже не смотря на то, что этот $admin_id должен был придти из сессии – н там не был установлен (я взял новую сессию) и скрипт пощитал, что всё впорядке и можно пользоваться.

Короткое резюме: пишите свои проекты с учётом register_globals = Off; если вы уверены, что вами написанный проект отлично работает с register_globals = Off, а на сервере register_globals = On – отключите register_globals, так как в редких случаях это может вызвать неадекватное поведения вашего проекта; если вам приходиться работать со скриптами, которые требуют register_globals = On (только в том случае, если это необходимо), будьте предельно бдительны, не сделайте глупых ошибок, связанных со свойством register_globals = On, а также проведите аудит скрипта на возможные ошибки – вы последний, кто его редактировал и все бочки посыпятся на вас.

Заметки о загрузке файлов с PHP

Знаете, я не специалист по безопастности, но постоянно встречаюсь с элементарными проблемами любого WEB-программиста. А за последнюю неделю в жизни/работе призошло не мало изменений, связанных с безопасностью. Первое что очень сильно повлияло – это PHP Security conference, на котором показали на сколько бывают глупы создатели сайтов. Второе – это то, что я уже проверить и накопать на окружающих сайтах и своём коде.

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

Элементарная форма. Элементарный скрипт. Для того, что-бы нормально обработать картинку на “любом” сервере, её в начале нужно двигать в свой каталог на сервере. Чаще всего это где-то внутри DocumentRoot, и в редких случаях вне его. Почему? А никто не отменял случаев с включенным open_basedir. И вроде нет ничего опасного в том, что я написал, но, если файл попал в DocumentRoot – его можно соответственно вызвать броузером. А если вы не проверили что это за файл – могут быть проблемы. Ведь могли загрузить и PHP или Perl скрипт, в котором может быть бог знает что.

И я не буду скрывать, что я купился на этой форме. Да, тут я лажанулся. Я понадеялся на getimagesize. Оказалось – зря. В первую очередь нужно проверять расширение файла в массиве $_FILES[‘userfile’][‘name’] и ещё перед выполнением move_uploaded_file. И не забудьте провериться перед этим с is_uploaded_file.

Вот на расширении файла я и попался. Я этим (по непонятным мне причинам) очень сильно принебрёг и понадеялся на функцию getimagesize. А вот она то и подвела. Оказывается (установлено экспериментальным путём на локальном PHP версии 4.4) – при загрузке файла с расширением .php (помните, я этим принебрёг), если в этот файл всунуть первые 128 байт из PNG файла, getimagesize считает что это картинка. Соответственно PHP файл попал на сервер, а что дальше бывает, я вам рассказывать не буду.

Некоторые говорят, что нужно ещё проверять $_FILES[‘userfile’][‘type’], но доверять ему нельзя – это данные, которые нам посылает клиент и они могут быть легко потделаны на строне клиента.

Загружая файл, не рекомендуют полностью доверят и $_FILES[‘userfile’][‘name’] – только профильтровав, или только расширение. Если же его прямо вписать, возможна атака путём подделки имени файла (скажем впишут вам ../../../index.php, а если у вас suEXEC или su_php можно и пострадать). Причём, они (создатели PHP) даже не подумали это дело отфильтровать автоматически, хотя в примере Validating file uploads создатели мануала об этом подумали (сам пример на данный момент мне не понятен).

Если разобрать пример Validating file uploads, а мне он виден вот таким совсем не понятно, каким образом они установили что происходит “Possible file upload attack!”? Ведь файл будет сдвинут в каталог /var/www/uploads/, а если он не будет сдвинут – следовательно, либо нету прав на это, либо исходный файл пропал. По моему, там должна была функция is_uploaded_file, а move_uploaded_file уже потом.

Итак, короткое резюме: проверять файл по разрешению и разрешать загружать только те файлы, которые 100% не будут выполнены сервером как скрипты (я бы разрешал загружать только картинки); не доверять $_FILES[‘userfile’][‘name’], проверять и фильтровать её, если используете; если файл переноситься во временное место для обработки, постарайтесь это место либо держать вне DocumentRoot, либо закрыть его при помощи .htaccess; не доверять вообще $_FILES[‘userfile’][‘type’]; пользуйтесь функциями is_uploaded_file и move_uploaded_file; проверяйте и перепроверяйте параметры.

Если у вас есть комментарии на эту тему, советы или замечания какие – пишите.