Skip to content

Commit

Permalink
Read kernel messages from both klogctl() and /var/log/dmesg
Browse files Browse the repository at this point in the history
  • Loading branch information
bcoles committed Jan 23, 2023
1 parent 76a8ce1 commit e3af92d
Show file tree
Hide file tree
Showing 19 changed files with 686 additions and 231 deletions.
2 changes: 0 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,6 @@ all :
-$(CC) $(FLAGS) $(SRC_DIR)/sysfs_iscsi_transport_handle.c -o $(BUILD_DIR)/sysfs_iscsi_transport_handle.o
-$(CC) $(FLAGS) $(SRC_DIR)/sysfs-module-sections.c -o $(BUILD_DIR)/sysfs-module-sections.o
-$(CC) $(FLAGS) $(SRC_DIR)/sysfs_nf_conntrack.c -o $(BUILD_DIR)/sysfs_nf_conntrack.o
-$(CC) $(FLAGS) $(SRC_DIR)/syslog_backtrace.c -o $(BUILD_DIR)/syslog_backtrace.o
-$(CC) $(FLAGS) $(SRC_DIR)/syslog_free_reserved_area.c -o $(BUILD_DIR)/syslog_free_reserved_area.o

clean :
rm -f $(BUILD_DIR)/*.o
67 changes: 54 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ Supports:
## Usage

```
sudo apt install libc-dev make gcc git
sudo apt install libc-dev make gcc binutils git
git clone https://github.com/bcoles/kasld
cd kasld
./kasld
Expand Down Expand Up @@ -105,16 +105,29 @@ additional noteworthy techniques not included for various reasons.
Kernel and system logs (`dmesg` / `syslog`) offer a wealth of information, including
kernel pointers and the layout of virtual and physical memory.

Several KASLD components search the kernel message ring buffer for kernel addresses.
The following KASLD components read from `dmesg` and `/var/log/dmesg`:

* [dmesg_android_ion_snapshot.c](src/dmesg_android_ion_snapshot.c)
* [dmesg_backtrace.c](src/dmesg_backtrace.c)
* [dmesg_check_for_initrd.c](src/dmesg_check_for_initrd.c)
* [dmesg_driver_component_ops.c](src/dmesg_driver_component_ops.c)
* [dmesg_early_init_dt_add_memory_arch.c](src/dmesg_early_init_dt_add_memory_arch.c)
* [dmesg_ex_handler_msr.c](src/dmesg_ex_handler_msr.c)
* [dmesg_fake_numa_init.c](src/dmesg_fake_numa_init.c)
* [dmesg_free_area_init_node.c](src/dmesg_free_area_init_node.c)
* [dmesg_free_reserved_area.c](src/dmesg_free_reserved_area.c)
* [dmesg_kaslr-disabled.c](src/dmesg_kaslr-disabled.c)
* [dmesg_mem_init_kernel_layout.c](src/dmesg_mem_init_kernel_layout.c)
* [dmesg_mmu_idmap.c](src/dmesg_mmu_idmap.c)

Historically, raw kernel pointers were frequently printed to the system log
without using the [`%pK` printk format](https://www.kernel.org/doc/html/latest/core-api/printk-formats.html).

* https://github.com/torvalds/linux/search?p=1&q=%25pK&type=Commits

Several KASLD components search the kernel ring buffer for kernel addresses.
Refer to `dmesg_*` files in the [src](src/) directory.

Bugs which trigger a kernel oops can be used to leak kernel pointers by reading
the associated backtrace from system log (on systems with `kernel.panic_on_oops = 0`).
the associated backtrace from system logs (on systems with `kernel.panic_on_oops = 0`).

There are countless examples. A few simple examples are available in the [extra](extra/) directory:

Expand All @@ -128,11 +141,17 @@ unprivileged access.

System log files (ie, `/var/log/syslog`) are readable only by privileged users
on modern distros. On Debian/Ubuntu systems, users in the `adm` group also have
read permissions on various system log files in `/var/log/`. Typically the first
user created on an Ubuntu system is a member of the `adm` group.
read permissions on various system log files in `/var/log/`:

Several KASLD components read from `/var/log/syslog`.
Refer to `syslog_*` files in the [src](src/) directory.
```
$ ls -la /var/log/syslog /var/log/kern.log /var/log/dmesg
-rw-r----- 1 root adm 147726 Jan 8 01:43 /var/log/dmesg
-rw-r----- 1 syslog adm 230 Jan 15 00:00 /var/log/kern.log
-rw-r----- 1 syslog adm 8322 Jan 15 04:26 /var/log/syslog
```

Typically the first user created during installation of an Ubuntu system
is a member of the `adm` group and will have read access to these files.

Additionally, [an initscript bug](https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=867747)
present from 2017-2019 caused the `/var/log/dmesg` log file to be generated
Expand All @@ -157,7 +176,7 @@ readable in some non-default configurations.
There are a plethora of viable hardware-related attacks which can be used to break
KASLR, in particular timing side-channels and transient execution attacks.

KASLD includes the following hardare-related KASLR breaks:
KASLD includes the following hardware-related KASLR breaks:

* [EntryBleed (CVE-2022-4543)](src/entrybleed.c)

Expand All @@ -179,7 +198,8 @@ address to `0x4000_0000 / 0x20_0000 = 512` possible locations.
Weaknesses in randomisation can decrease entropy, further limiting the possible kernel
locations in memory and making the kernel easier to locate.

KASLR may be disabled if insufficient randomness is generated during boot (for example, if `get_kaslr_seed()` fails on ARM64).
KASLR may be disabled if insufficient randomness is generated during boot
(for example, if `get_kaslr_seed()` fails on ARM64).

Refer to the [Weak Entropy](#weak-entropy) section for more information.

Expand Down Expand Up @@ -233,8 +253,20 @@ Refer to the [Weak Entropy](#weak-entropy) section for more information.

[LVI: Hijacking Transient Execution through Microarchitectural Load Value Injection](https://www.semanticscholar.org/paper/LVI:-Hijacking-Transient-Execution-through-Load-Bulck-Moghimi/5cbf634d4308a30b2cddb4c769056750233ddaf6) (Jo Van Bulck, Daniel Moghimi, Michael Schwarz, Moritz Lipp, Marina Minkin, Daniel Genkin, Yuval Yarom, Berk Sunar, Daniel Gruss, and Frank Piessens, 2020)

[Exploiting Microarchitectural Optimizations from Software](https://diglib.tugraz.at/download.php?id=61adc85670183&location=browse) (Moritz Lipp. 2021)

[Hardening the Kernel Against Unprivileged Attacks](https://www.cc0x1f.net/publications/thesis.pdf) (Claudio Canella, 2022)

[ThermalBleed: A Practical Thermal Side-Channel Attack](https://ieeexplore.ieee.org/stamp/stamp.jsp?arnumber=9727162) (Taehun Kim, Youngjoo Shin. 2022)

AMD prefetch and power-based side channel attacks (CVE-2021-26318):

* https://www.amd.com/en/corporate/product-security/bulletin/amd-sb-1017
* [AMD Prefetch Attacks through Power and Time](https://www.usenix.org/conference/usenixsecurity22/presentation/lipp) (Moritz Lipp, Daniel Gruss, Michael Schwarz. 2022)
* https://www.usenix.org/system/files/sec22-lipp.pdf
* USENIX Security 2022 Presentation: https://www.youtube.com/watch?v=bTV-9-B26_w
* https://github.com/amdprefetch/amd-prefetch-attacks/tree/master/case-studies/kaslr-break

Microarchitectural Data Sampling (MDS) side-channel attacks:

* [Fallout: Leaking Data on Meltdown-resistant CPUs](https://mdsattacks.com/files/fallout.pdf) (Claudio Canella, Daniel Genkin, Lukas Giner, Daniel Gruss, Moritz Lipp, Marina Minkin, Daniel Moghimi, Frank Piessens, Michael Schwarz, Berk Sunar, Jo Van Bulck, Yuval Yarom, 2019)
Expand Down Expand Up @@ -319,7 +351,13 @@ TagBleed: Tagged Translation Lookaside Buffer (TLB) side-channel attacks:

### Kernel Info Leaks

Patched bugs caught by KernelMemorySanitizer (KMSAN):
Patched kernel info leak bugs:

* [https://github.com/torvalds/linux/search?p=1&type=Commits&q=kernel-infoleak](https://github.com/torvalds/linux/search?p=1&type=Commits&q=kernel-infoleak)
* `git clone https://github.com/torvalds/linux && cd linux && git log | grep 'kernel-infoleak'`

Patched kernel info leak bugs caught by KernelMemorySanitizer (KMSAN):

* [https://github.com/torvalds/linux/search?p=1&type=Commits&q=BUG: KMSAN: kernel-infoleak](https://github.com/torvalds/linux/search?p=1&type=Commits&q=BUG:%20KMSAN:%20kernel-infoleak)
* `git clone https://github.com/torvalds/linux && cd linux && git log | grep "BUG: KMSAN: kernel-infoleak"`

Expand All @@ -332,7 +370,10 @@ Remote kernel pointer leak via IP packet headers (CVE-2019-10639):

* [From IP ID to Device ID and KASLR Bypass](https://arxiv.org/pdf/1906.10478.pdf)

[show_floppy kernel function pointer leak](https://www.exploit-db.com/exploits/44325) (CVE-2018-7273) (requires `floppy` driver).
floppy block driver `show_floppy` kernel function pointer leak (CVE-2018-7273) (requires `floppy` driver and access to `dmesg`).

* [Linux Kernel < 4.15.4 - 'show_floppy' KASLR Address Leak](https://www.exploit-db.com/exploits/44325) (Gregory Draperi. 2018)
* https://xorl.wordpress.com/2018/03/18/cve-2018-7273-linux-kernel-floppy-information-leak/

`kernel_waitid` leak (CVE-2017-14954) (affects kernels 4.13-rc1 to 4.13.4):

Expand Down
10 changes: 0 additions & 10 deletions kasld
Original file line number Diff line number Diff line change
Expand Up @@ -179,16 +179,6 @@ if [ -x "${build}/sysfs_nf_conntrack.o" ]; then
echo
fi

if [ -x "${build}/syslog_backtrace.o" ]; then
"${build}/syslog_backtrace.o"
echo
fi

if [ -x "${build}/syslog_free_reserved_area.o" ]; then
"${build}/syslog_free_reserved_area.o"
echo
fi

# slow - leave last
if [ -x "${build}/mincore.o" ]; then
"${build}/mincore.o"
Expand Down
50 changes: 49 additions & 1 deletion src/dmesg_android_ion_snapshot.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
// Android ION drivers were removed in kernel v5.11-rc1.
//
// Requires:
// - kernel.dmesg_restrict = 0; or CAP_SYSLOG capabilities.
// - kernel.dmesg_restrict = 0; or CAP_SYSLOG capabilities; or
// readable /var/log/dmesg.
//
// References:
// https://lwn.net/Articles/576966/
Expand Down Expand Up @@ -64,8 +65,55 @@ unsigned long search_dmesg_ion_snapshot() {
return 0;
}

unsigned long search_dmesg_log_file_ion_snapshot() {
FILE *f;
char *endptr;
char *substr;
char *addr_buf;
char *line_buf;
const char *path = "/var/log/dmesg";
const char *needle1 = "ion_snapshot: ";
const char *needle2 = "and copy to 0x";
unsigned long addr = 0;
char buff[BUFSIZ];

printf("[.] searching %s for '%s' ...\n", path, needle1);

f = fopen(path, "rb");
if (f == NULL) {
perror("[-] fopen");
return 0;
}

while ((fgets(buff, BUFSIZ, f)) != NULL) {
substr = strstr(buff, needle1);
if (substr == NULL)
continue;

line_buf = strtok(substr, "\n");
if (line_buf == NULL)
break;

addr_buf = strstr(substr, needle2);
if (addr_buf == NULL)
break;

addr = strtoul(&addr_buf[strlen(needle2)], &endptr, 16);

if (addr >= KERNEL_BASE_MIN && addr <= KERNEL_BASE_MAX)
break;
}

fclose(f);

return addr;
}

int main() {
unsigned long addr = search_dmesg_ion_snapshot();
if (!addr)
addr = search_dmesg_log_file_ion_snapshot();

if (!addr)
return 1;

Expand Down
46 changes: 45 additions & 1 deletion src/dmesg_backtrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
// that looks like a kernel pointer.
//
// Requires:
// - kernel.dmesg_restrict = 0; or CAP_SYSLOG capabilities.
// - kernel.dmesg_restrict = 0; or CAP_SYSLOG capabilities; or
// readable /var/log/dmesg.
// - kernel.panic_on_oops = 0 (Default on most systems).
// ---
// <[email protected]>
Expand Down Expand Up @@ -49,8 +50,51 @@ unsigned long search_dmesg_kernel_pointers() {
return addr;
}

unsigned long search_dmesg_log_file_kernel_pointers() {
FILE *f;
char *ptr;
char *endptr;
char *line = 0;
size_t size = 0;
const char *path = "/var/log/dmesg";
unsigned long leaked_addr = 0;
unsigned long addr = 0;

printf("[.] searching %s for call trace kernel pointers ...\n", path);

f = fopen(path, "rb");

if (f == NULL) {
perror("[-] fopen");
return 0;
}

while ((getline(&line, &size, f)) != -1) {
ptr = strtok(line, "[<");
while ((ptr = strtok(NULL, "[<")) != NULL) {
leaked_addr = strtoul(&ptr[0], &endptr, 16);

if (!leaked_addr)
continue;

if (leaked_addr >= KERNEL_BASE_MIN && leaked_addr <= KERNEL_BASE_MAX) {
// printf("Found kernel pointer: %lx\n", leaked_addr);
if (!addr || leaked_addr < addr)
addr = leaked_addr;
}
}
}

fclose(f);

return addr;
}

int main() {
unsigned long addr = search_dmesg_kernel_pointers();
if (!addr)
addr = search_dmesg_log_file_kernel_pointers();

if (!addr)
return 1;

Expand Down
51 changes: 48 additions & 3 deletions src/dmesg_check_for_initrd.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
//
// Requires:
// - CONFIG_BLK_DEV_INITRD=y
// - kernel.dmesg_restrict = 0; or CAP_SYSLOG capabilities.
// - kernel.dmesg_restrict = 0; or CAP_SYSLOG capabilities; or
// readable /var/log/dmesg.
//
// References:
// https://elixir.bootlin.com/linux/v6.1.1/source/arch/powerpc/kernel/setup-common.c#L385
Expand All @@ -24,7 +25,7 @@
#include <string.h>
#include <unistd.h>

unsigned long get_kernel_addr_dmesg_check_for_initrd() {
unsigned long search_dmesg_check_for_initrd() {
char *syslog;
char *endptr;
char *substr;
Expand Down Expand Up @@ -57,8 +58,52 @@ unsigned long get_kernel_addr_dmesg_check_for_initrd() {
return 0;
}

unsigned long search_dmesg_log_file_check_for_initrd() {
FILE *f;
char *endptr;
char *substr;
char *line_buf;
const char *path = "/var/log/dmesg";
const char *needle = "Found initrd at 0x";
unsigned long addr = 0;
char buff[BUFSIZ];

printf("[.] searching %s for check_for_initrd() info ...\n", path);

f = fopen(path, "rb");
if (f == NULL) {
perror("[-] fopen");
return 0;
}

while ((fgets(buff, BUFSIZ, f)) != NULL) {
substr = strstr(buff, needle);
if (substr == NULL)
continue;

line_buf = strtok(substr, "\n");
if (line_buf == NULL)
break;

/* Found initrd at 0xc000000001a00000:0xc000000002a26000 */
// printf("%s\n", line_buf);

addr = strtoul(&line_buf[strlen(needle)], &endptr, 16);

if (addr >= KERNEL_BASE_MIN && addr <= KERNEL_BASE_MAX)
break;
}

fclose(f);

return addr;
}

int main() {
unsigned long addr = get_kernel_addr_dmesg_check_for_initrd();
unsigned long addr = search_dmesg_check_for_initrd();
if (!addr)
addr = search_dmesg_log_file_check_for_initrd();

if (!addr)
return 1;

Expand Down
Loading

0 comments on commit e3af92d

Please sign in to comment.