Защита конфигурации от …




Принцип обмена данными из 1С с сайтом (на MySQL) и выдачи (публикации) этих данных по запросу.
PHP-Скрипт автоматической загрузки данных из файла данных в формате CSV в базу данных сайта работающего на WordPress.

В продолжение моей темы: 1С:Альфа-Авто Автосалон Автосервис: обмен с сайтом.
С помощью данного скрипта можно загружать в автоматическом режиме, по расписанию, данные сервисных книжек (ремонтов авто) из 1С:Альфа-Авто Автосалон Автосервис.
Также можно загружать данные в ручном режиме: для этого делается скрытая страница, где размещается специальная кнопка.
Комментарии размещенные внутри скрипта разъяснят логику и порядок действия.
Комментарии с "/////    echo" использовались для отладки.
Дополнительно создана таблица для журналирования результатов загрузки данных.
Скрипт включает в себя защиту от SQL инъекций (думаю безопасность соблюдена в полной мере).
В кратце:
1. Пишется скрипт, который запускает этот.
2. Создается регламентное задание в WordPress, по которому запускается скрипт из п.1. 
3. Этот скрипт осуществляет проверку на существование файла обмена в папке.
4. Если данные не новые, загрузка не производится.
5. Если данные новые, очищается таблица сервисных книжек.
6. Загружаются новые данные.

Собственно сам скрипт:

<?php // Полная загрузка сервисных книжек, создан 2024-01-05 12:44:55

global $wpdb2;
global $failure;
global $file_hist;

/////  echo '<H2><b>Старт загрузки</b></H2><br>';

$failure=FALSE;
//подключаемся к базе
$wpdb2 = include_once 'connection.php'; ; // подключаемся к MySQL
// если не удалось подключиться, и нужно оборвать PHP с сообщением об этой ошибке
if (!empty($wpdb2->error))
{
/////   echo '<H2><b>Ошибка подключения к БД, завершение.</b></H2><br>';
$failure=TRUE;
wp_die( $wpdb2->error );
}

$m_size_file=0;
$m_mtime_file=0;
$m_comment='';
/////проверка существования файлов выгрузки из 1С
////файл выгрузки сервисных книжек
$file_hist = ABSPATH.'/_1c_alfa_exchange/AA_hist.csv';
if (!file_exists($file_hist))
{
/////   echo '<H2><b>Файл обмена с сервисными книжками не существует.</b></H2><br>';
$m_comment='Файл обмена с сервисными книжками не существует';
$failure=TRUE;
}

/////инициируем таблицу лога
/////если не существует файла то возврат и ничего не делаем
if ($failure){
///включает защиту от SQL инъекций и данные можно передавать как есть, например: $_GET['foo']
/////   echo '<H2><b>Попытка вставить запись в лог таблицу</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>$m_mtime_file,'last_size_upload'=>$m_size_file,'comment'=>$m_comment));
wp_die();
/////    echo '<H2><b>Возврат в начало.</b></H2><br>';
return $failure;
}
/////проверка лога загрузки, что бы не загружать тоже самое
$masiv_data_file=stat($file_hist);   ////передаем в массив свойство файла
$m_size_file=$masiv_data_file[7];    ////получаем размер файла
$m_mtime_file=$masiv_data_file[9];   ////получаем дату модификации файла
////создаем запрос на получение последней удачной загрузки
////выбираем по штампу времени создания (редактирования) файла загрузки AA_hist.csv, $m_mtime_file

/////   echo '<H2><b>Размер файла: '.$m_size_file.'</b></H2><br>';
/////   echo '<H2><b>Штамп времени файла: '.$m_mtime_file.'</b></H2><br>';
/////   echo '<H2><b>Формирование запроса на выборку из лога</b></H2><br>';
////препарируем запрос
$text_zaprosa=$wpdb2->prepare("SELECT * FROM `vin_logs` WHERE `last_mtime_upload` = %s", $m_mtime_file);
$results=$wpdb2->get_results($text_zaprosa);

if ($results)
{   foreach ( $results as $r)
{
////если штамп времени и размер файла совпадают, возврат
if (($r->last_mtime_upload==$m_mtime_file) && ($r->last_size_upload==$m_size_file))
{////echo '<H2><b>Возврат в начало, т.к. найдена запись в логе.</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>$m_mtime_file,'last_size_upload'=>$m_size_file,'comment'=>'Загрузка отменена, новых данных нет, т.к. найдена запись в логе.'));
wp_die();
return $failure;
}
}
}
////если данные новые, пишем в лог запись о начале загрузки
/////echo '<H2><b>Попытка вставить запись о начале загрузки в лог таблицу</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>0, 'last_size_upload'=>$m_size_file, 'comment'=>'Начало загрузки'));

////очищаем таблицу
$clear_tbl_zap=$wpdb2->prepare("TRUNCATE TABLE %s", 'vin_history');
$clear_tbl_zap_repl=str_replace("'","`",$clear_tbl_zap);
$results=$wpdb2->query($clear_tbl_zap_repl);
/////   echo '<H2><b>Очистка таблицы сервисных книжек</b></H2><br>';
if (empty($results))
{
/////   echo '<H2><b>Ошибка очистки таблицы книжек, завершение.</b></H2><br>';
//// если очистка не удалась, возврат
$failure=TRUE;
wp_die();
return $failure;
}

////загружаем данные
$table='vin_history';         // Имя таблицы для импорта
//$file_hist Имя CSV файла, откуда берется информация     // (путь от корня web-сервера)
$delim=';';          // Разделитель полей в CSV файле
$enclosed='"';      // Кавычки для содержимого полей
$escaped='\

28 Comments

  1. coolseo

    Если вставлять в модуль приложения «ПередНачаломРаботыСистемы» , то ругается

    {МодульУправляемогоПриложения(17,7)}: Переменная не определена (Обработки)

    ОБ = <<?>>Обработки.СтартСистемы.Создать(); (Проверка: Тонкий клиент)

    Перенес в общий модуль и усе полетело. Под управляемые формы.

    Спасибо!!!

    Reply
  2. Alien_job

    =) Почти патч Бармина для 1С

    ПользовательБД.Пароль = Новый УникальныйИдентификатор(); //Вот и всё.

    Этот код можно во внешнюю обработочку в комплексе с принудительным завершением сеансов.

    Reply
  3. StBender

    Как насолить конторе из которой увольняешься, что ли?

    Reply
  4. hakerxp

    (3), в данном случае каждый найдет для себя как применить. Я применял для «подстраховки» при работе с клиентом.

    Reply
  5. Fox-trot

    странно что не потребовалось УстановитьПривилегированныйРежим(Истина)

    Reply
  6. vasyak319

    Под обычным юзером это сдохнет на первой же попытке удалить роль.

    Reply
  7. h00k

    Печально только, что подобная «защита» ни от чего не защищает. Ну разве что в файловом режиме отключение займет на пару минут дольше.

    Reply
  8. planar74

    Как растерять клиентов — практическое руководство.

    Reply
  9. wbazil

    всегда когда открываю публикации с подобными названиями, с надеждой думаю «…. неужели что то новое придумали….», а нет пока все по старому

    человек с «доступом» в гугл снимет такую защиту на раз два

    Reply
  10. madonov

    При выполнении функции ПроверкаСтарта() на клиенте будет производиться сравнение со временем на машине пользователя, а значит и для обхода надо только перевести время.

    Хотя бы на сервере время получать надо, хотя и в этом случае защита от дурака. А, ну название публикации впринципе вполне соответствует.

    Reply
  11. WKBAPKA

    (10) madonov,

    так для этого и гуглить не надо… просто зайти в конфигуратор 🙂

    Reply
  12. hakerxp

    Перевод времени не поможет, если система уже сделала свое дело. Теперь только может зайти один пользователь, который знает новый пароль.

    Reply
  13. hakerxp

    (9) wbazil, и с головой))

    Reply
  14. baton_pk

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

    Reply
  15. vde69

    вещь бестолковая… админу сервера невозможно запретить вход в конфигуратор…

    имея доступ к физическим данным (SQL, файловая, пости или любая другая субд) я войду в конфигуратор менее чем за 5 минут…

    Reply
  16. d_z_k

    Если честно, то обработка чисто для своих нужд, для использования она очень сильно сыровата.

    Нет — не запретов, не доступа, не закрытие кода и т.п.

    И использование в разделе «Защита и шифрование» не имеет толка и смысла.

    Reply
  17. Stim213

    Интересно, как будет выглядеть взимодействие с клиентом.

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

    Клиент через некоторое время перечисляет сумму и вы говорите — дайте мне доступ в базу, я отключу блокировку?

    или ждете, когда блокировка сделает своё чОрное дело, и берете деньги за разблокировку?

    Не боитесь найти себя себя потом случайно без сознания с переломанными ногами?

    Reply
  18. Stim213

    + если так хотите защиту от невыплат — сделайте при запуске обращение к своей БД в интернете.

    Ищите там, я не знаю, по строке соединения и выдавайте ответ — разрешить/запретить работу.

    хотя все равно это тупиковый путь

    Reply
  19. h00k

    (18) Stim213, вообще-то единственный разумный способ: обработка проверяет наличие ключа, например файла с определенным именем. Если ключ не найден, то через в час N блокирует доступ к конфигурации/ части функционала. После оплаты клиенту высылается инсталлятор ключа и работу в конфигурации можно продолжать.

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

    Reply
  20. hakerxp

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

    Reply
  21. Stim213

    (19) h00k, а как вы будете проверять имя файла/лицензии?

    Если ИмяФайла = «0101201232131» Тогда ?

    любой знакомый одмин обойдет такую защиту как нефик делать. Любой школьник сможет разобраться как создать фейковый файл лицензии.

    да и как вообще вы видите работу в офлайн режиме, когда работа у клиента, а расчеты на стадии оплаты?

    После оплаты — «подождите, я пришлю вам файлик, положите его в третью папку сверху в папке с базой в корне це» ?

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

    Reply
  22. baton_pk

    (21) Stim213,

    в него ид клиента, от него — разрешение/отказ на продолжение работы функционала.

    ну, тут должна быть более хитрая система, иначе простая подмена хоста сведёт защиту на нет.

    Reply
  23. V.Nikonov

    Система защищенная только при старте крайне легко «ломается». Эффективной защита станет если она будет многоступенчатой и блокирующей не только старт но и выполнение критически важного функционала! Разумеется шифрации должна подвергаться не только стартовая функция но и основной функционал.

    Метка защиты может располагаться не только в виде «замаскированного файла» или обращения к Интернет-Базе лицензирования, но и в виде специфичных записей реестра. Защита через Интернет может и хороша, но требует обязательности наличия Интернета на клиенте, что не всегда получается…

    Согласен, что любая защита не абсолютна! Весть вопрос в стоимости преодоления защиты. Паролирование текста модуля не самая надежное средство спрятать от посторонних глаз функционал. Запароленный код можно декодировать… Есть идеи размещения кода в отдельном шифруемом файле… Но, по моему проще, записать заказчика в черный список и принять для себя «финансовую потерю», чем городить огород с защитой… Предложенный вариант сработает только для Заказчиков-Дилетантов.

    Reply
  24. V.Nikonov

    (17) Stim213, Вероятно подразумевается передача клиенту Демо-Базы, с последующей заменой на рабочий вариант…

    Reply
  25. vasyak319

    (21) Stim213, «в него ид клиента, от него — разрешение/отказ на продолжение работы функционала»

    Ну да, ведь никто не догадается редиректнуть это обращение на локалхост, чтобы тот всегда отвечал на него «можно работать».

    Reply
  26. Nuuq

    (2) Alien_job, )))))

    Reply
  27. h00k

    (21) Stim213, Мне вот интересно, вы программист или как?

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

    Дополнительно могу подчеркнуть, что естественно моя реализация основана не на файлах, но принцип работы схож. И кстати, я даже не задумываясь назову 3-5 человек, которых мой алгоритм защиты не остановит, но школьники и большая часть 1С-ников его не осилят…

    (24) V.Nikonov, нет, в данном случае я имел в виду именно полнофункциональную разработку в которой предусмотрен триальный период. Для продолжения работы с которой достаточно просто активировать ключ.

    Есть и другой вариант реализации, при отсутствии ключа устанавливается ограничение в 100 обрабатываемых объектов.

    П.С.: Нет защит которые не ломаются, есть защиты с разной «себестоимостью» взлома. Причем в некоторых случаях, например мне скучно стало или достала рутина, экономическая составляющая взлома становится вторична, так-как процесс сам по себе интересный.

    Reply
  28. vasyak319

    Оффтопик, но вспомнилось: есть на свете чуваки, которые разрабатывают и продают конфу для ювелирки. В конфе всё, что можно, поставлено без исходных кодов и есть какой-то супергиперсервер защиты, которому нужен ключ, иначе конфа говорит «А теперь я буду обычной УТ 10.3».

    Так вот, разработчикам, видимо, самим лениво было возиться со своей защитой, поэтому в куске кода, который решает, будет ли конфа ювелиркой или УТ 10.3, стоит проверка типа:

    Если Найти(ИмяКомпа,»Несколько имён каких-то компов, разделённых запятыми»)=0 Тогда
    ПроверитьКлючИВыматериться();
    Иначе
    Возврат «Ура, я ювелирка!»;
    КонецЕсли;
    

    Это стояло у знакомцев на терминале и жутко бесило тем, что частенько переставало видеть ключ. Я им сказал, что самый простой и дешевый способ — назвать терминальный сервер одним из имён из того списка.

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *