The OpenNET Project / Index page

[ новости /+++ | форум | теги | ]



Вариант для распечатки  
Пред. тема | След. тема 
Форум Разговоры, обсуждение новостей
Режим отображения отдельной подветви беседы [ Отслеживать ]

Оглавление

Уязвимость в OpenSMTPD, позволяющая удалённо выполнить код с..., opennews (?), 29-Янв-20, (0) [смотреть все] +1

Сообщения [Сортировка по времени | RSS]


6. "Уязвимость в OpenSMTPD, позволяющая удалённо выполнить код с..."  –2 +/
Сообщение от Анонимус2 (?), 29-Янв-20, 10:16 
>sh -c ""

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

Ответить | Правка | Наверх | Cообщить модератору

11. "Уязвимость в OpenSMTPD, позволяющая удалённо выполнить код с..."  +3 +/
Сообщение от Аноним (11), 29-Янв-20, 10:47 
Будьте так добры, накидайте ссылочек, как необходимо делать по вашему мнению.
Ответить | Правка | Наверх | Cообщить модератору

13. "Уязвимость в OpenSMTPD, позволяющая удалённо выполнить код с..."  +4 +/
Сообщение от Нононим (?), 29-Янв-20, 10:54 
Оне выгонять учились, а не тому как надо делать.
Ответить | Правка | Наверх | Cообщить модератору

22. "Уязвимость в OpenSMTPD, позволяющая удалённо выполнить код с..."  –3 +/
Сообщение от Аноним (22), 29-Янв-20, 12:40 
Смотри postfix
Ответить | Правка | К родителю #11 | Наверх | Cообщить модератору

25. "Уязвимость в OpenSMTPD, позволяющая удалённо выполнить код с..."  +1 +/
Сообщение от Дон Ягон (ok), 29-Янв-20, 13:20 
> Смотри postfix

Тот же postfix тоже позволяет запускать команду mda шеллом.

https://github.com/vdukhovni/postfix/blob/master/postfix/src...
https://github.com/vdukhovni/postfix/blob/master/postfix/src...

Да, старается этого избегать, по возможности. Но сам факт - некоторую функциональность логичнее реализовывать именно так, а не писать свой недо-sh.

Проблема не в том, что процесс OpenSMTPD запускает какие-то субкоманды шелом, а в том, что недостаточно хорошо проверяет входные данные.

Ответить | Правка | Наверх | Cообщить модератору

41. "Уязвимость в OpenSMTPD, позволяющая удалённо выполнить код с..."  +5 +/
Сообщение от Ordu (ok), 29-Янв-20, 14:52 
> Проблема не в том, что процесс OpenSMTPD запускает какие-то субкоманды шелом, а в том, что недостаточно хорошо проверяет входные данные.

Не совсем. То что он недостаточно хорошо проверяет -- это проблема. Но то, что он запускает субкоманды шеллом -- это тоже проблема. Если ты написал функцию pipe_to_mda(...) то эта функция должна запускать mda и только. Если при специально подобранных аргументах она может запустить не только mda, а ещё и "rm -rf /*", то это проблема. Может быть лишь потенциальная, но проблема.

Безбажного кода не бывает -- все это знают, но мало кто понимает. То, что безбажного кода не бывает означает, что если твоя pipe_to_mda может при специально подобранных аргументах вызвать "rm -rf /*", то тебе не удастся доказать, что твоя программа не запустит "rm -rf /*" ни при каком вводе.

Тут на деле встаёт вопрос ко всему проект OpenBSD: они не могут не знать, что exec на sh -- это штука, без которой сложно обойтись в unix. И они не могут не знать, что эта штука -- постоянный источник дыр в unix'овом софте. Если присмотреться, то корень проблемы в том, что при передаче аргументов через exec эти аргументы приходится кодировать в шелловские строки и чтобы sh потом декодировал их по своим заморочным правилам. То есть, образно говоря, надо собрать строку-скрипт и выполнить на неё eval. execle чуть лучше в этом смысле, чем system, но как показывает даже эта новость -- ненамного. И есть ведь напрашивающийся способ борьбы с этой проблемой: нужно взять и реализовать некое подмножество sh в виде C'шной библиотеки. Чтобы можно было бы написать, например:

sh_c("mail.local", "-f", from, to)

и быть уверенным, что это приведёт к тому, что будет создан процесс mail.local с argv вида {"mail.local", "-f", from, to}.

Можно и с пайпами как-нибудь разрулиться, даже несмотря на убожество C, например:

shellcommand_t base_cmd = sh_cmd("mail.local", "-f", from, to);
shellcommand_t pipe_cmd = sh_pipe_from(command_input, base_cmd);

sh_spawn(pipe_cmd);

Да, из-за отсутствия параметризации типов в C, тут возможно придётся создавать типы чьи размеры будут неизвестны на этапе компиляции, и из-за этого придётся дёргать malloc почём зря, да ещё и оптимизации пойдут лесом, но, во-первых, может если подумать можно сделать всё не настолько плохо, во-вторых, какая разница: надо очень постараться, чтобы это получилось медленнее, чем старт шелла.

Да, тут возможны проблемы с обработкой ошибок -- библиотека внутри будет дёргать много сисколлов, каждый из них может возвращать коды ошибок, и как-то надо эти ошибки прокидывать в код, дёргающий API библиотеки. Там опять же придётся повозиться и отсутствие параметризованных типов нисколько не упрощает эту возню. Но если всё совсем плохо, можно все сисколлы вызывать непосредственно из sh_spawn, и возвращать оттуда структурку описывающую результат, и к ней грядку методов для разгребания этого результата.

Да, такая библиотечка не решит всех проблем. Например, если mail.local при специально подобранных from и to будет вызывать "rm -rf /*", то тут ничего не сделаешь на уровне библиотеки.

Но фишка-то в том, что проблемы экранирования специсимволов шелла прекратят существовать. Потому что экранирование будет не нужно. Одна библиотека устраняет целый класс ошибок, довольно распространённых причём. Почему OpenBSD до сих пор не написала такую библиотеку и не перевела весь свой код на её использование, вместо всех этих system да execle -- мне не ясно. Подозреваю, что это юниксвей головного мозга.

Ответить | Правка | Наверх | Cообщить модератору

44. "Уязвимость в OpenSMTPD, позволяющая удалённо выполнить код с..."  +1 +/
Сообщение от Дон Ягон (ok), 29-Янв-20, 15:13 
Для начала, спасибо за развёрнутое сообщение с текстом по существу вопроса.

> Если ты написал функцию pipe_to_mda(...) то эта функция должна запускать mda и только.

Если всё слишком хардкодить, получится прокрустово ложе. Даже postfix, в котором, насколько я вижу, сделано сильно больше, чтобы не запускать sh, даже он в некоторых случаях запускает его.

> Если при специально подобранных аргументах она может запустить не только mda, а ещё и "rm -rf /*", то это проблема. Может быть лишь потенциальная, но проблема.

Безусловно.

> И они не могут не знать, что эта штука -- постоянный источник дыр в unix'овом софте.

Знают. И даже пытаются валидировать входные данные, чтобы предотвратить это. Из-за ошибки в оной валидации проблема и возникла.

> нужно взять и реализовать некое подмножество sh в виде C'шной библиотеки

Я не понимаю, чем валидация данных в отдельной библиотеке лучше, чем в коде самого OpenSMTPD. Как допустить, так и недопустить ошибку можно в обоих случаях. Универсализация?
Скорее всего, программы не являющиеся SMTP-демоном будут хотеть другие данные на вход и набор допустимых символов будет отличаться (и как бы не всецело).

> Но фишка-то в том, что проблемы экранирования специсимволов шелла прекратят существовать.
>  Почему OpenBSD до сих пор не написала такую библиотеку и не перевела весь свой код на её использование

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

Ответить | Правка | Наверх | Cообщить модератору

62. "Уязвимость в OpenSMTPD, позволяющая удалённо выполнить код с..."  +/
Сообщение от Ordu (ok), 29-Янв-20, 17:43 
> Я не понимаю, чем валидация данных в отдельной библиотеке лучше, чем в коде самого OpenSMTPD.

Во-первых, там не нужна валидация. Нельзя сказать, чтобы совсем не нужна, но сравни:

execle("/usr/libexec/mail.local", "mail.local", "-f", from, to);

и

execle("/bin/sh", "sh", "-c", "/usr/libexec/mail.local", "-f", from, to)

Разница между этими вариантами в том, что во втором последние четыре аргумента читаются шеллом из его argv и _интерпретируются_, прежде чем передаются в mail.local. Это будто мы взяли и чисто по фану на каждый аргумент вызвали некий аналог eval, под названием shell expansion (который с радостью выполнит команду, если её записать в виде $(rm -rf /*) или `rm -rf /*`). Чтобы этого избежать во втором варианте, мы включаем экранирование, чтобы после shell expansion'а, mail.local получил бы именно то, что исходно лежало в переменных from и to, а не что-то иное. Или иными словами: мы знаем, что на from и to будет вызвана функция expand и в mail.local будут переданы аргументы expand(from) и expand(to), но нам надо передать from и to, поэтому мы создаём функцию unexpand, такую что \forall x expand(unexpand(x)) == x, и после этого мы передаём в mail.local значения expand(unexpand(from)) и expand(unexpand(to)).

В первом варианте мы непросредственно прокидываем содержимое from и to в mail.local через егойный argv, нам не нужен unexpand, потому что нет никакого expand. Но мы лишаемся шелловского job control'а, что становится особенно болезненным, если нам надо через пайпы что-то прокидывать в вызываемую команду, или через пайпы же вычитывать вывод вызываемой команды.


Но, как бы там не было, в обоих случае вызываемая программа должна валидировать вход. Как она это делает -- мы не знаем, и это нас не касается. Может быть программа складывает значения в sql базу данных, и поэтому значения from и to надо экранировать по sql-правилам экранирования. Может быть она создаёт файл с именем from, и поэтому ей надо что-то сделать с from, преобразовать в строку которая может быть именем файла. Но это уже проблемы вызываемой программы. (точнее в идеале именно она должна этим заниматься, иногда это невозможно или слишком сложно, но не в том случае, о котором новость).

То есть, валидация нужна, но это не должно быть заботой вызывающего кода. Вызывающий код должен обрабатывать ошибки, а не валидировать вход.


Во-вторых, даже если бы валидация от шелла и нужна была бы, то она была бы нужна в библиотеке, которой пользуются многие. В этой библиотеке были бы баги, но одни на всех. Устранение бага в библиотеке устраняет баги у всех. Ресурсы вложенные в аудит кода, в тестирование кода разными методами будут возвращаться всем проектам. Если мы представим на секундочку модель разработки софта, в которой многие проекты вызывают шелл, и каждый проект вкладывает какое-то количество ресурсов в то, чтобы обезбажить этот вызов шелла, и сравним её с моделью, в которой есть единая библиотека, чей API гарантирует отсутствие багов, баги могут скрываться лишь в реализации, и в обезбаживание этой реализации вкладывается суммарное количество ресурсов, которое в первой модели вкладывалось в обезбаживание частных реализаций, то какой вариант будет безбажнее?

Да, тут есть свои подводные камни: баг, найденный в библиотеке, сделает уязвимыми многие программы. Но system и exec("sh", ...) -- это весьма распространённые штуки в *nix, то есть существует множество людей заинтересованных в том, чтобы делать это максимально надёжно и безопасно, а значит можно вбухать реально много ресурсов в то, чтобы продумать API и вылизать реализацию. Плюс не обязательно внедрять эту библиотеку сразу везде и в продакшн. Можно форкнуть заинтересованные проекты и тащить пару лет форки, крича на всех углах о том, какие у нас безопасные форки, провоцируя других на то, чтобы они доказывали бы нам, насколько глубоко мы ошибаемся. Некоторые доказательства будут сопровождаться эксплоитами, что будет очень полезно нам. Через несколько несовместимых переписываний API мы доберёмся до v1.0, и тогда... Но для этого нужно, чтобы за проектом стояла организация типа OpenBSD, которая давала бы маркетинга и оплачивала бы хотя бы одного квалифицированного программиста на полную занятость.

> Насколько я могу понимать, никто не написал универсальную библиотеку, решающую проблемы экранирования спецсимволов на все случаи жизни.

Я говорю не об универсальной библиотеке, экранирующая спецсимволы, я говорю о /bin/sh в виде подгружаемой библиотеки. В некотором смысле, семантически это sh, но с другим синтаксисом. Этот синтаксис более многословный и неудобный для использования в командной строке, и вообще без компиляции с ним не поработаешь. Зато он оптимизирован на избегание _распространённых_ проблем вызванных ошибками экранирования.

Ответить | Правка | Наверх | Cообщить модератору

86. "Уязвимость в OpenSMTPD, позволяющая удалённо выполнить код с..."  +/
Сообщение от Дон Ягон (ok), 29-Янв-20, 20:04 
> Разница между этими вариантами в том, что во втором последние четыре аргумента читаются шеллом из его argv и _интерпретируются_, прежде чем передаются в mail.local. Это будто мы взяли и чисто по фану на каждый аргумент вызвали некий аналог eval, под названием shell expansion (который с радостью выполнит команду, если её записать в виде $(rm -rf /*) или `rm -rf /*`).

Описанная проблема понятна, её разработчики OpenSMTPD пытаются решать списком допустимых символов и эскейпингом. Т.е. вызвать тот же rm таким способом, как ты описал, в конкретном случае не получилось бы.

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

Но ведь в данном случае, вызываемая программа и есть /bin/sh. И проблема не в том, что мы передали что-то не то в /usr/libexec/mail.local, а в том, что мы завершили shell-команду символом ";" и выполнили (ошибочно) кусок того, что после ";" с правами локального юзера, которому предназначалось письмо.

> Я говорю не об универсальной библиотеке, экранирующая спецсимволы, я говорю о /bin/sh в виде подгружаемой библиотеки. В некотором смысле, семантически это sh, но с другим синтаксисом. Этот синтаксис более многословный и неудобный для использования в командной строке, и вообще без компиляции с ним не поработаешь. Зато он оптимизирован на избегание _распространённых_ проблем вызванных ошибками экранирования.

Я несколько неверно высказался, что проблема в неверной валидации входных данных. Ну то есть это так, но "[функция] smtp_mailaddr() имеет логическую ошибку, из-за которой в случае передачи пустого домена в email, функция возвращает успешный код проверки, даже если часть адреса до "@" содержит недопустимые символы" - это не то, что можно было бы пофиксить условной libsh.

Я вообще не уверен, что есть серебрянная пуля, защищающая от подобного рода ошибок.

Условная libsh, в зависимости от того, как она будет сделана, может быть и будет решать какие-то типовые проблемы, в то же время, ИМХО, в бОльшей части случаев практичнее просто ответственно подходить к валидации входных данных, а не использовать комплексные решения (unix-way головного мозга, да).

Ответить | Правка | Наверх | Cообщить модератору

102. "Уязвимость в OpenSMTPD, позволяющая удалённо выполнить код с..."  +/
Сообщение от Ordu (ok), 30-Янв-20, 00:27 
>> Разница между этими вариантами в том, что во втором последние четыре аргумента читаются шеллом из его argv и _интерпретируются_, прежде чем передаются в mail.local. Это будто мы взяли и чисто по фану на каждый аргумент вызвали некий аналог eval, под названием shell expansion (который с радостью выполнит команду, если её записать в виде $(rm -rf /*) или `rm -rf /*`).
> Описанная проблема понятна, её разработчики OpenSMTPD пытаются решать списком допустимых
> символов и эскейпингом. Т.е. вызвать тот же rm таким способом, как
> ты описал, в конкретном случае не получилось бы.

Да, но и тем не менее логическая ошибка в коде экранизации привела к возможности эксплуатации этой ошибки. Никакого запаса прочности. Сколько ещё ненайденных ошибок прячется в коде экранизации? Есть ли быстрый надёжный способ найти все code-path ведущие к этому execle и доказать, что во всех этих случаях экранизация выполняется верно? Где гарантия, что будущие правки кода не создадут кодопути к этому execle, которые нарушат допущения и засунут туда неэкранированные строки?

> Я несколько неверно высказался, что проблема в неверной валидации входных данных. Ну
> то есть это так, но "[функция] smtp_mailaddr() имеет логическую ошибку, из-за
> которой в случае передачи пустого домена в email, функция возвращает успешный
> код проверки, даже если часть адреса до "@" содержит недопустимые символы"
> - это не то, что можно было бы пофиксить условной libsh.

Так уж и не мог бы пофиксить? В случае с условной libsh этот инвалидный почтовый адрес ушёл бы бэкэнду, тот бы либо переслал дальше, либо сообщил о несуществующем адресе. Я не к тому, что ошибку с синтаксически кривым адресом будет более правильным обрабатывать в mda_agent, чем в MTA -- хз, на самом деле: бекенду всё равно нужно проверить валидность, почему бы не свалить эту проверку на него и не париться о ней? -- но, как минимум, при таком раскладе класс опасности ошибки был бы существенно ниже.

> Я вообще не уверен, что есть серебрянная пуля, защищающая от подобного рода
> ошибок.
> Условная libsh, в зависимости от того, как она будет сделана, может быть
> и будет решать какие-то типовые проблемы, в то же время, ИМХО,
> в бОльшей части случаев практичнее просто ответственно подходить к валидации входных
> данных, а не использовать комплексные решения (unix-way головного мозга, да).

Бороться с каждой ошибкой в отдельности -- это хорошо, но выделять классы ошибок и использовать AoE спеллы против них -- это гораздо эффективнее. Да, AoE -- не серебряная пуля, но они высвобождают ресуры под то, чтобы бороться с ошибками, которые нам ещё не удалось прибить AoE оружием. Бывают AoE "спеллы", которые требуют, например, кучу дополнительной памяти, или ещё как-то повышают требования к железу, или вообще сильно не бесплатны. Но здесь "плата" за AoE -- это виртуально однократно вложенные усилия в разработку libsh. Никаких накладных расходов в runtime, более того потенциально могут быть возможности срезать эти накладные расходы в рантайме.

Ответить | Правка | Наверх | Cообщить модератору

129. "Уязвимость в OpenSMTPD, позволяющая удалённо выполнить код с..."  +/
Сообщение от Дон Ягон (ok), 30-Янв-20, 14:38 
Сори за долгий ответ, не хотелось отвечать совсем не подумав.

> Есть ли быстрый надёжный способ найти все code-path ведущие к этому execle и доказать, что во всех этих случаях экранизация выполняется верно?

Я такого способа не знаю.

> Где гарантия, что будущие правки кода не создадут кодопути к этому execle, которые нарушат допущения и засунут туда неэкранированные строки?

Гарантий нет.

> Так уж и не мог бы пофиксить? В случае с условной libsh этот инвалидный почтовый адрес ушёл бы бэкэнду, тот бы либо переслал дальше, либо сообщил о несуществующем адресе. Я не к тому, что ошибку с синтаксически кривым адресом будет более правильным обрабатывать в mda_agent, чем в MTA -- хз, на самом деле: бекенду всё равно нужно проверить валидность, почему бы не свалить эту проверку на него и не париться о ней? -- но, как минимум, при таком раскладе класс опасности ошибки был бы существенно ниже.

Всё верно. Но и корректная логика валидации в текущем снизила бы класс опасности ошибки?

> Бороться с каждой ошибкой в отдельности -- это хорошо, но выделять классы ошибок и использовать AoE спеллы против них -- это гораздо эффективнее. Да, AoE -- не серебряная пуля, но они высвобождают ресуры под то, чтобы бороться с ошибками, которые нам ещё не удалось прибить AoE оружием.
> Но здесь "плата" за AoE -- это виртуально однократно вложенные усилия в разработку libsh.

В теории я согласен с тобой. На практике я не уверен, что платой будут однократно вложенные усилия - могу допустить, что чинить ошибки придётся очень долго или бесконечно. Это если речь про условную универсальную libsh.
Но на самом деле, я сегодня с утра задумался о том, почему я вообще завёл про это речь.
Кажется, более адекватно было бы рассматривать не условный libsh, а возможность использовать какой-то dsl или даже условный python.
Но и тут приходится (имхо) выбирать между двумя крайностями:
* Готовый язык (типа python), вероятно, as-is будет слишком мощный и его придётся огораживать, примерно также, как сейчас огораживается shell.
* DSL, который, в теории, можно написать строго под свои задачи, и который может и не содержать лишнего. Если отказаться от универсализации, то могу согласиться, что это может быть и более хорошим вариант, чем текущий.

Универсальный вариант у меня по-прежнему вызывает сомнения, в том плане, что разработка подобного мне кажется долгим и сложным мероприятием, без гарантий достижения желаемых целей.
Может я неправ, да.

Ответить | Правка | Наверх | Cообщить модератору

90. "Уязвимость в OpenSMTPD, позволяющая удалённо выполнить код с..."  +/
Сообщение от Дон Ягон (ok), 29-Янв-20, 20:54 
>> Но, как бы там не было, в обоих случае вызываемая программа должна валидировать вход.
>> То есть, валидация нужна, но это не должно быть заботой вызывающего кода. Вызывающий код должен обрабатывать ошибки, а не валидировать вход.
> Но ведь в данном случае, вызываемая программа и есть /bin/sh. И проблема не в том, что мы передали что-то не то в /usr/libexec/mail.local, а в том, что мы завершили shell-команду символом ";" и выполнили (ошибочно) кусок того, что после ";" с правами локального юзера, которому предназначалось письмо.

Ну да, в случае libsh (условного), мы бы вызывали саму программу. Но тогда бы да, были бы проблемы по меньшей мере с пайпами. И не было бы проблем с эскейпингом и т.п.

> Если мы представим на секундочку модель разработки софта, в которой многие проекты вызывают шелл, и каждый проект вкладывает какое-то количество ресурсов в то, чтобы обезбажить этот вызов шелла, и сравним её с моделью, в которой есть единая библиотека, чей API гарантирует отсутствие багов, баги могут скрываться лишь в реализации, и в обезбаживание этой реализации вкладывается суммарное количество ресурсов, которое в первой модели вкладывалось в обезбаживание частных реализаций, то какой вариант будет безбажнее?

Вот честно - не знаю. Решить общую задачу, как правило, сложнее, чем частную. Потому что придётся рассматривать значительно бОльшее количество возможных кейсов (я КО, да).

Ответить | Правка | К родителю #62 | Наверх | Cообщить модератору

32. "Уязвимость в OpenSMTPD, позволяющая удалённо выполнить код с..."  +/
Сообщение от Аноним (11), 29-Янв-20, 13:55 
Спс
Ответить | Правка | К родителю #22 | Наверх | Cообщить модератору

109. "Уязвимость в OpenSMTPD, позволяющая удалённо выполнить код с..."  +/
Сообщение от Аноним (109), 30-Янв-20, 01:14 
> Будьте так добры, накидайте ссылочек, как необходимо делать по вашему мнению.
> Смотри postfix

В postfix было так: https://www.exploit-db.com/exploits/34896
Уязвимость в bash CVE-2014-6271. А подход в postfix такой же.

Смотрите тогда уж qmail.

Ответить | Правка | К родителю #22 | Наверх | Cообщить модератору

114. "Уязвимость в OpenSMTPD, позволяющая удалённо выполнить код с..."  +/
Сообщение от Анонимус2 (?), 30-Янв-20, 11:35 
Не делать вызов sh программно вообще никогда, не видел пока ни одной программы сложнее hello world где бы это не привело к уязвимостям. В данном случае - вызывать mail.local напрямую, без обёртки в виде шелла.
Если уж администратору сильно захотелось запустить шелл - ему нужно дать возможность вместо mail.local запустить произвольный файл, пусть пишет его на чем угодно - хоть шелл, хоть си, хоть джаваскрипт.
Ответить | Правка | К родителю #11 | Наверх | Cообщить модератору

135. "Уязвимость в OpenSMTPD, позволяющая удалённо выполнить код с..."  +/
Сообщение от Аноним (-), 31-Янв-20, 07:11 
Во-во. А если какие-то параметры отдать надо - то наверное все-таки не в sh -c, такая конструкция заведомо заявка на залет. Шелл больно уж много всего специально трактует так что кормить его из недоверяемых данных - чего, рута по DHCP все уже забыли, мыло было?
Ответить | Правка | Наверх | Cообщить модератору

Архив | Удалить

Рекомендовать для помещения в FAQ | Индекс форумов | Темы | Пред. тема | След. тема




Партнёры:
PostgresPro
Inferno Solutions
Hosting by Hoster.ru
Хостинг:

Закладки на сайте
Проследить за страницей
Created 1996-2024 by Maxim Chirkov
Добавить, Поддержать, Вебмастеру