CVE-2021-3560는 linux 운영체제 CVE-2021-4034는 Linux 운영체제에 기본적으로 설치되는 "Polkit" 패키지의 "pkexec"에서 발생하는 LPE(Local Privilage Escalation) 취약점입니다. 해당 취약점은 polkit-1의 "0.105-26ubuntu1" 이하 버전에서 유효하며 로컬 환경에서 일반 사용자가 root 권한인 계정을 생성하고 탈취하는 작업을 수행합니다.
공격 시도전 다음 구문을 통해 polkit-1 버전을 확인하실 수 있습니다.
apt list --installed | grep policykit-1
또한 accountservice, gnome-control-center가 설치되어 있는지 확인해야 합니다.
아래 구문을 통해 확인 가능합니다.
rhel/centos/fedora : rpm -qa
debian/ubuntu : dpkg -l
이번 취약점을 이해하기 위해서는 Polkit과 dbus에 대한 이해가 필요합니다.
Polkit은 Linux 사용자가 보다 높은 수준의 작업을 수행할때 권한이 있는지 확인하기 위해 사용됩니다.
polkit은 권한 인증을 관리하기 위해 만들어진 프로그램이며, 권한 인증을 위해 동작할때 pkexec 유틸리티가 동작합니다. 이해가 되지 않는다면 콘솔에서는 sudo를 사용하는 대안으로 pkexec를 사용한다고 생각해도 좋을거 같습니다.
dbus-demon과 polkit의 연관성도 알아두면 이해에 도움이 됩니다.
D-Bus (Desktop Bus) 시스템은 리눅스 및 유닉스 기반 시스템에서 프로세스 간 통신(IPC)을 제공하는 메시지 시스템입니다. D-Bus 시스템에서 dbus-demon은 중앙에서 모든 통신을 처리하고 다른 네 프로세스가 D-Bus 메시지를 통해 서로 통신하며 서로의 자격 증명을 확인하도록 하며 이과정에서 취약점이 발생합니다.
해당 취약점은 polkit이 인증 요청을 처리할때 dbus-daemon으로부터 전달되는 인증 요청을 특정 타이밍에 취소하여 polkit이 이를 인지하지 못하고 작업을 수행하는 취약점입니다. polkit의 polkit_system_bus_name_get_creds_sync 함수는 오류가 발생해도 오류 매개변수를 설정한 후에도 TRUE를 반환하는 이상 동작을 보입니다. 이 때문에, polkit에서 오류를 올바르게 처리하지 못하고, 오류가 발생했을 때 해당 요청을 UID 0인 프로세스로부터 온 것처럼 처리합니다. 즉, 루트 프로세스로부터 온 요청이라고 인식 후 승인하는 것입니다.
다음은 코드상에서 취약점이 발생하는 부분입니다.
check_authorization_sync (arg1, arg2, ...) {
...
/* every subject has a user; this is supplied by the client, so we rely
* on the caller to validate its acceptability. */
user_of_subject = polkit_backend_session_monitor_get_user_for_subject (priv->session_monitor,
subject, NULL,
error);
if (user_of_subject == NULL)
goto out;
/* special case: uid 0, root, is _always_ authorized for anything */
if (POLKIT_IS_UNIX_USER (user_of_subject) && polkit_unix_user_get_uid (POLKIT_UNIX_USER (user_of_subject)) == 0)
{
result = polkit_authorization_result_new (TRUE, FALSE, NULL);
goto out;
}
이 코드의 주요 문제점은 error 값이 확인되지 않는다는 것입니다. polkit_backend_session_monitor_get_user_for_subject 함수는 사용자에 대한 정보를 가져오려고 시도하지만, 이 과정에서 오류가 발생할 수 있습니다. 일반적으로, 이러한 오류가 발생하면 함수는 NULL을 반환하고, error 변수에 오류 정보를 저장합니다.
그러나 위 코드에서는 user_of_subject가 NULL인 경우에만 처리를 중단하고 (goto out;), error 값을 확인하지 않습니다. 이로 인해 user_of_subject가 NULL이 아닌 경우에 오류가 발생했음에도 이를 무시하고 계속 진행하여 문제가 발생합니다.
특히 문제가 되는 것은 user_of_subject가 NULL이 아니고 POLKIT_IS_UNIX_USER이며, polkit_unix_user_get_uid가 0(즉, 루트 사용자)을 반환하는 경우입니다. 이 경우, 해당 요청은 루트 사용자로부터 온 것처럼 처리되어 자동으로 승인되어 버리는 문제가 발생합니다.
요약하자면, 이 취약점은 polkit의 check_authorization_sync 함수 내에서 user_of_subject가 NULL이 아닐 때 오류(error) 값을 확인하지 않아 발생하는 취약점입니다. 이 취약점은 user_of_subject가 루트 사용자(UID 0)로 잘못 간주될 때 인증 우회가 발생합니다.

dbus-send를 사용하여 sudo 권한(또는 나중에 새 사용자에게 설정할 비밀번호)이 있는 새 계정 생성을 요청하는 dbus 메시지를 account-daemon에 수동으로 보냅니다.

"test1" 사용자 계정을 생성하고, 0.006초 즈음에 프로세스를 종료합니다.

"test1" 사용자의 사용자 ID와 그룹 ID를 표시한후 사용할 패스워드 해시를 생성합니다.

"test1" 사용자의 비밀번호와 uid를 맞춰주고, 0.006초 후에 프로세스를 종료합니다.

현재 사용자의 sudo 권한과 관련된 정보를 표시한후 현재 사용자를 루트 사용자로 전환합니다.
이렇게 취약점이 터지는 이유와 사용 방법에 대해서 알아보았습니다.
dbus 메시지를 dbus-daemon(서로 다른 프로세스가통신할 수 있도록하는 API)에 수동으로 보낸 다음 요청이 완전히 처리되기 전에 요청을 종료하면 polkit의 취약한 인증체계를 통해 권한을 부여할 수 있었습니다.
Reference)
https://github.blog/2021-06-10-privilege-escalation-polkit-root-on-linux-with-bug/