Search code examples
python-3.xlinuxdockerexploitpwntools

Only "cat" command doesn't print any output after getting shell by pwntool


I was making a simple CTF(Capture The Flag) problem with docker. The current case is simple(It's not a real problem, it's just a test.); enter a specified string and get a shell(/bin/bash) if correct.

The original C source code is here. If the user's input is exactly 1n1tTheJourney2Pwnable, the program runs get_shell() which gives /bin/sh to the user.

// welcome.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>

void alarm_handler() {
    puts("TIME OUT");
    exit(-1);
}
void initialize() {
    setvbuf(stdin, NULL, _IONBF, 0);
    setvbuf(stdout, NULL, _IONBF, 0);
    signal(SIGALRM, alarm_handler);

    alarm(30);
}

void get_shell() {
  char *cmd = "/bin/sh";
  char *args[] = {cmd, NULL};

  execve(cmd, args, NULL);
}

int main() {
    char buf[32];

    initialize();
    printf("input: ");
    scanf("%s", buf);

    if(strcmp(buf,"1n1tTheJourney2Pwnable") == 0) {
        printf("SUCCESS!!\n");
        get_shell();
    } else {
        printf("Wrong..!!\n");
    }

    return 0;

}

Here is the Dockerfile for the problem.

FROM ubuntu:20.04
# user name and the title of the problem are identical
ENV user welcome
ENV port 2023

RUN apt-get update
RUN apt-get install -y
RUN apt-get install -y socat gcc

RUN adduser $user

WORKDIR /home/$user


ADD ./$user.c   /home/$user/$user.c
ADD ./flag      /home/$user/flag

RUN gcc -o /home/$user/$user /home/$user/$user.c

RUN chown $user:$user /home/$user/$user
RUN chown $user:$user /home/$user/flag
RUN chmod 755 /home/$user/$user
RUN chmod 750 /home/$user/flag

USER $user
EXPOSE $port
CMD socat -T 30 TCP-LISTEN:$port,reuseaddr,fork EXEC:/home/$user/$user

I build that Dockerfile as below:

sudo docker build -t system_welcome <dockerfile location>
sudo docker run -p 2023:2023 system_welcome

Of course, this problem is very easy as just typing the following string after establishing a connection by hitting the command nc 127.0.0.1 2023. However, I wanted to demonstrate the basic usage of pwntool. So I wrote a simple script doing so.

from pwn import context, remote, process

context.log_level = 'debug'

#p = process('./welcome')
p = remote('127.0.0.1', 2023)

p.recvuntil(b'input: ')
p.sendline(b'1n1tTheJourney2Pwnable')

p.interactive()

So, the program does work as expected and obtains the shell(/bin/sh). However, as suggested in the picture below, the shell doesn't print anything as a result of cat commands, even though the interactive program received the data. Oddly, results from other commands like id or ls are being shown correctly. enter image description here

It's highly expected of pwntool's problem or Dockerfile's problem, but I couldn't find any solution or tips to resolve this problem, so I need some help related to this.


Solution

  • The root cause of the problem was the difference between \r\n and \n. In the content of the previous question, pwntool received the string data with a delimiter of \r\n, which is used as a new line character in Windows OS. However, I was using Linux(Ubuntu 22.04@WSL2 on Windows 11).

    After inspection, I found flag wasn't written on Linux whose delimiter is \n. (Assumably it would be created in Windows or Mac OS.)

    So, I deleted my flag file with \r\n delimiter and created the flag file again in Linux entirely. After revision, everything worked as I intended and expected.

    enter image description here

    The main cause of the problem was near but I couldn't see for nearly 18 hours(Yeah, it may sound hilarious.). I hope my case would be helpful who having troubles with similar problems with mine. To conclude, neither Docker nor the "pwn" posed any issues.

    More to read: What is the difference between \r\n, \r, and \n?