Very High
CVE-2023-45249
CVE ID
AttackerKB requires a CVE ID in order to pull vulnerability data and references from the CVE list and the National Vulnerability Database. If available, please supply below:
Add References:
CVE-2023-45249
MITRE ATT&CK
Collection
Command and Control
Credential Access
Defense Evasion
Discovery
Execution
Exfiltration
Impact
Initial Access
Lateral Movement
Persistence
Privilege Escalation
Topic Tags
Description
Remote command execution due to use of default passwords. The following products are affected: Acronis Cyber Infrastructure (ACI) before build 5.0.1-61, Acronis Cyber Infrastructure (ACI) before build 5.1.1-71, Acronis Cyber Infrastructure (ACI) before build 5.2.1-69, Acronis Cyber Infrastructure (ACI) before build 5.3.1-53, Acronis Cyber Infrastructure (ACI) before build 5.4.4-132.
Add Assessment
Ratings
-
Attacker ValueVery High
-
ExploitabilityHigh
Technical Analysis
On 24 July, Acronis published the security advisory SEC-6452: Remote command execution due to use of default passwords where default passwords are exploited to gain admin access to the Acronis Cyber Infrastructure. It was also reported by Acronis that this vulnerability was actively exploited by cyber criminals and patched 9 months ago.
If you search for actual examples of the exploit, no detailed technical publications are available, so I thought let’s give it a go and figure out what this vulnerability is all about.
So I downloaded a Acronis Cyber Infrastructure (ACI) appliance 4.7
from their website and installed it on VirtualBox (see this article).
After completing the installation process, you access the Acronis Web Portal on port 8888 via HTTPS with the admin credentials set during the installation. You can also the access the appliance directly by logging in as root. These credentials are also asked and set during the installation process. This is of course very helpful to analyze the server image because you have full access to appliance and the installed software.
So lets start the search for our default passwords!!!
Let’s check first the user credentials available on the appliance itself by checking the /etc/password
and /etc/shadow
files.
Not much to gain here. The only password hash available in the /etc/shadow
file is for user root
which is set during the initial setup of the ACI appliance.
Next in line is to investigate the user credentials available in the Acronis Web Portal.
If you login as admin, you will find in the settings->user and projects
section, three default users:
- admin
- backup-service-user
- vstorage-service-user
User admin credentials are set during the installation process so that rules out the default password.
Both the backup-service-user and storage-service-user are potential candidates where the storage-service-user is the most promising candidate because this user is default enabled and has the role system-administrator assigned.
The appliance has a PostgreSQL DB that stores all configuration information. The users, passwords and roles are stored in the keystone
database.
You can easily query the database by logging into the appliance as root and switch to the postgres
user and access the database with psql
.
Acronis Cyber Infrastructure release 4.7 ======================================================================== = Warning! Do not enable third-party repositories. Install third-party = = software only from the default repository. Use only commands allowed = = in the product documentation. = ======================================================================== [root@aci-471-53 ~]# su postgres bash-4.2$ psql could not change directory to "/root": Permission denied psql (11.16) Type "help" for help. postgres=# \l List of databases Name | Owner | Encoding | Collate | Ctype | Access privileges ------------+------------+----------+-------------+-------------+----------------------- coredns | coredns | UTF8 | en_US.UTF-8 | en_US.UTF-8 | grafana | grafana | UTF8 | en_US.UTF-8 | en_US.UTF-8 | keystone | vstoradmin | UTF8 | en_US.UTF-8 | en_US.UTF-8 | postgres | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | template0 | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =c/postgres + | | | | | postgres=CTc/postgres template1 | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =c/postgres + | | | | | postgres=CTc/postgres vstoradmin | vstoradmin | UTF8 | en_US.UTF-8 | en_US.UTF-8 | (7 rows) postgres=# \c keystone You are now connected to database "keystone" as user "postgres". keystone=# select * from "local_user"; id | user_id | domain_id | name | failed_auth_count | failed_auth_at ----+----------------------------------+-----------+-----------------------+-------------------+---------------- 1 | a56cc7f698fa41d99d1c9dd22aa73580 | default | vstorage-service-user | 0 | 2 | 57bf107a224145c6a1217c71da5f4911 | default | backup-service-user | | 3 | fad1606d29a64ff6b7c45b1128551a97 | default | admin | 0 | (3 rows) keystone=# select * from "password"; id | local_user_id | expires_at | self_service | password_hash | created_at_int | expires_at_int | created_at ----+---------------+----------------------------+--------------+--------------------------------------------------------------+------------------+------------------+---------------------------- 1 | 1 | 2024-08-05 11:31:58.573171 | f | $2b$12$/.ZPGchRUlOGJcNO2S.bOOF3ykww0vShNEr/jwZxvQtksCzGHYcrO | 1653058897767616 | 1722857518573171 | 2022-05-20 15:01:37.767616 2 | 1 | | f | $2b$12$YKyODw1N3mTO9qj7ch1h6O2qZQGjSgW/CIKyQ2Tz7A49sJvHI0r/q | 1722857518573171 | | 2024-08-05 11:31:58.573171 3 | 3 | | f | $2b$12$3PT2/rbf4rkNBPThiZclyeD/FFP5UXLs4bTfg0L27LeSjqyxNQ2xO | 1722857529542615 | | 2024-08-05 11:32:09.542615 (3 rows)
We can query the users and the password hashes, which is promising but “Are these default passwords?”, and if yes, “What is the password?”
To answers these questions, we need to dig a bit deeper within the appliance and figure out what happens during the initial installation and configuration setup of the appliance.
One very interesting directory is /usr/libexec/vstorage-ui-backend/libexec
that holds most of initial configuration shell scripts called during the installation of the appliance.
[root@aci-471-53 libexec]# pwd /usr/libexec/vstorage-ui-backend/libexec [root@aci-471-53 libexec]# ls alua-functions.sh keystone-service-init.sh oneshot-0021-enable-russian-language.sh bouncer-functions.sh logging.sh oneshot-cleanup-wal-archive.sh check-backend.sh oneshot-0008-upgrade-to-roles-sets.sh oneshot-disable-wal-archiving.sh clear-vips.sh oneshot-0009-upgrade-db.sh oneshot-init-keystone.sh db-functions.sh oneshot-0010-disable-pghba-ident-entry.sh oneshot-migrate-roles-to-agent.sh dns-functions.sh oneshot-0011-init-coredns.sh on-master.sh functions.sh oneshot-0012-enable-ha-for-postgresql.sh on-standby.sh gen-certificate.sh oneshot-0013-clean-up-mdses-in-order-to-add-dns-srv-recs.sh pg-convert-layout.sh ha-ovh-setup oneshot-0014-create-self-service-roles-in-keystone.sh pg-scripts.sh ha-ovh-teardown oneshot-0015-clean-up-mdses-in-order-to-activate-vstorage-target-manager.sh pg-switch-to-hot-standby.sh ha-scripts.sh oneshot-0016-update-internal-endpoint-in-keystone.sh pg-switch-to-master.sh init-backend.sh oneshot-0017-create-roles-implication-in-keystone.sh set-vips.sh init-grafana.sh oneshot-0018-create-backup-service-user.sh takeover-management-node.sh init-postinstall.sh oneshot-0019-create-compute-cert.sh utils-functions.sh keystone-functions.sh oneshot-0019-enable-postgres-backup.sh uwsgi-backend-stop.sh keystone-gen-env.sh oneshot-0020-turn-off-aip-early-access.sh [root@aci-471-53 libexec]#
I am not gonna dwell on all scripts, but the oneshot-init-keystone.sh
is an interesting script to explore what is happening during initial installation.
#!/usr/bin/env bash #set -x . ~vstoradmin/libexec/logging.sh LOG_FILE="/var/log/vstorage-ui-backend/init_keystone.log" BACKEND_CONFIG=/usr/libexec/vstorage-ui-backend/etc/backend.cfg log_init "${LOG_FILE}" exec &>>"${LOG_FILE}" . ~vstoradmin/libexec/db-functions.sh . ~vstoradmin/libexec/keystone-functions.sh grep -q -w "KEYSTONE_SERVICE_PASSWORD" ${BACKEND_CONFIG} || init_keystone
It calls two other scripts db-functions.sh
and keystone-functions.sh
which are worthwhile to explore and the last grep
command is very interesting where a KEYSTONE_SERVICE_PASSWORD
is queried from the file /usr/libexec/vstorage-ui-backend/etc/backend.cfg
.
We are getting closer…
If we check the file /usr/libexec/vstorage-ui-backend/etc/backend.cfg
it actually reveals the password of the vstorage-service-user!!!
KEYSTONE_USER_MIGRATION=True KEYSTONE_SERVICE_USER='vstorage-service-user' KEYSTONE_SERVICE_PASSWORD='3bfda47e79d62f7798e38acc7ff6' KEYSTONE_SERVICE_PROJECT='admin' KEYSTONE_ENDPOINT='https://127.0.0.1:5000/v3'
Is this the famous default password? Mmm, this looks too simple…
Let’s check how this password is ending up in this config file.
Let’s explore the other two scripts.
Browsing thru keystone-functions.sh
the first function gen_keystone_passwd()
already shows that the password gets randomly generated with openssl
for the vstorage-service-user
. This looks like a dead-end street.
function gen_keystone_passwd() { sudo -u vstoradmin openssl rand -hex 14 2>/dev/null [ $? -ne 0 ] && error "Unable to generate password for keystone service user" || : }
But…
After exploring the second script db-functions.sh
, interesting new information is revealed because it seems that during the creation and configuration of the database, default passwords are indeed being used.
configure_db() { log_inf "Configure database..." create_user "vstoradmin" "CREATEDB CREATEROLE LOGIN REPLICATION PASSWORD 'vstoradmin'" create_database "vstoradmin" "vstoradmin" log_inf "Database has been configured" }
Database user vstoradmin
seems to have a default password vstoradmin.
That is really interesting, so let’s validate this in the database by querying the passwords for these DB users which are stored in the postgres database table below.
postgres=# select * from "pg_authid"; rolname | rolsuper | rolinherit | rolcreaterole | rolcreatedb | rolcanlogin | rolreplication | rolbypassrls | rolconnlimit | rolpassword | rolvaliduntil ---------------------------+----------+------------+---------------+-------------+-------------+----------------+--------------+--------------+-------------------------------------+--------------- postgres | t | t | t | t | t | t | t | -1 | | pg_monitor | f | t | f | f | f | f | f | -1 | | pg_read_all_settings | f | t | f | f | f | f | f | -1 | | pg_read_all_stats | f | t | f | f | f | f | f | -1 | | pg_stat_scan_tables | f | t | f | f | f | f | f | -1 | | pg_read_server_files | f | t | f | f | f | f | f | -1 | | pg_write_server_files | f | t | f | f | f | f | f | -1 | | pg_execute_server_program | f | t | f | f | f | f | f | -1 | | pg_signal_backend | f | t | f | f | f | f | f | -1 | | vstoradmin | f | t | t | t | t | t | f | -1 | md5dc23b46758bc7e2c4d3d19493c492aae | coredns | f | t | f | f | t | f | f | -1 | md56e2738b0f8848df4ed98977974c83a7e | grafana | f | t | f | f | t | f | f | -1 | | (12 rows)
We can see the md5 hashed passwords in the table for user vstoradmin
and coredns
which are in the typical PostgreSQL format of the string “md5” followed by the md5 hash of a string comprised of the password followed by the postgres username.
Let’s use this logic and check if these accounts are using default passwords with hashcat
.
# cat md5.hash 6e2738b0f8848df4ed98977974c83a7e dc23b46758bc7e2c4d3d19493c492aae # cat password.txt vstoradminvstoradmin corednscoredns # hashcat --show -a 0 -m 0 md5.hash password.txt 6e2738b0f8848df4ed98977974c83a7e:corednscoredns dc23b46758bc7e2c4d3d19493c492aae:vstoradminvstoradmin
Or you can do the other way around .
[root@aci-471-53 libexec]# echo -n "md5"; echo -n "vstoradminvstoradmin" | md5sum | awk '{print $1}' md5dc23b46758bc7e2c4d3d19493c492aae [root@aci-471-53 libexec]# echo -n "md5"; echo -n "corednscoredns" | md5sum | awk '{print $1}' md56e2738b0f8848df4ed98977974c83a7e [root@aci-471-53 libexec]#
And BINGO, the md5 hashed passwords are matching and we have found default passwords!!!!
The final confirmation is to validate a patched version of the Acronis Cyber Infrastructure and check if these flaws have been mitigated.
Checking the db-functions.sh
on a patched ACI 5.0.1-61
appliance, shows that no default password is set in the configure_db()
function.
configure_db() { log_inf "Configure database..." create_user "vstoradmin" "CREATEDB CREATEROLE LOGIN REPLICATION" create_database "vstoradmin" "vstoradmin" log_inf "Database has been configured" }
Also the pg_auth
table in the postgres database does not show any passwords for the vstoradmin
and coredns
database users.
This confirms that the use of default passwords for these accounts have been mitigated.
postgres=# select * from "pg_authid"; rolname | rolsuper | rolinherit | rolcreaterole | rolcreatedb | rolcanlogin | rolreplication | rolbypassrls | rolconnlimit | rolpassword | rolvalidu ntil ---------------------------+----------+------------+---------------+-------------+-------------+----------------+--------------+--------------+-------------+---------- ----- postgres | t | t | t | t | t | t | t | -1 | | pg_monitor | f | t | f | f | f | f | f | -1 | | pg_read_all_settings | f | t | f | f | f | f | f | -1 | | pg_read_all_stats | f | t | f | f | f | f | f | -1 | | pg_stat_scan_tables | f | t | f | f | f | f | f | -1 | | pg_read_server_files | f | t | f | f | f | f | f | -1 | | pg_write_server_files | f | t | f | f | f | f | f | -1 | | pg_execute_server_program | f | t | f | f | f | f | f | -1 | | pg_signal_backend | f | t | f | f | f | f | f | -1 | | vstoradmin | f | t | t | t | t | t | f | -1 | | coredns | f | t | f | f | t | f | f | -1 | | grafana | f | t | f | f | t | f | f | -1 | | (12 rows) postgres=#
The exploit
Now we want to understand how we can exploit this vulnerability.
After digging into the keystone
db with the privileges of the vstoradmin
user, it already shows that we can easily add a new administrative user by editing it directly in the keystone
database. This administrative user allows us to upload ssh-keys via the ACI Web Portal that enables direct root access via SSH to the appliance.
You will need access to Acronis Web Portal, the PostgreSQL database and the SSH service, but if these three services are available and accessible from the outside world, you can easily hack yourself into any non-patched ACI appliance as user root.
I have created an Metasploit module that does all the magic for you.
You can find this module in Metasploit as PR 19463 – Acronis Cyber Infrastructure default password remote code execution.
Mitigation
You should patch your ACI appliance immediately following the Acronis security advisory SEC-6452.
References
CVE-2023-45249
Acronis security advisory SEC-6452
Acronis ACI Downloads
Metasploit PR 19463 – Acronis Cyber Infrastructure default password remote code execution
Would you also like to delete your Exploited in the Wild Report?
Delete Assessment Only Delete Assessment and Exploited in the Wild ReportCVSS V3 Severity and Metrics
General Information
Vendors
- acronis
Products
- cyber infrastructure
Exploited in the Wild
Would you like to delete this Exploited in the Wild Report?
Yes, delete this reportWould you like to delete this Exploited in the Wild Report?
Yes, delete this reportReferences
Additional Info
Technical Analysis
Report as Emergent Threat Response
Report as Exploited in the Wild
CVE ID
AttackerKB requires a CVE ID in order to pull vulnerability data and references from the CVE list and the National Vulnerability Database. If available, please supply below:
@h00die-gr3y Wow!! Thank you for the very thoughtful and detailed write-up!
@ccondon-r7 you are most welcome!!!