0

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.

KnightChaser
  • 143
  • 1
  • 9
  • It actually prints to docker and content goes to docker logs. Default console from docker-containers goes to docker logs. – fly2matrix Jul 31 '23 at 10:52
  • @fly2matrix However, I observe the docker log of that container, there is nothing related to the output from the command [cat]. Only information related to signals from the program(welcome.c) that is designed to shut down automatically after 30 seconds since the start. I don't think the command results aren't printed to docker itself... (Tbh, I don't know what's wrong.) – KnightChaser Jul 31 '23 at 11:43
  • try something like this : docker run -p 2023:2023 -t system_welcome – fly2matrix Jul 31 '23 at 11:53
  • @fly2matrix I'm sorry but I don't know what's different from my options written on the question... (I also tried your suggestion, but it was to no avail.) – KnightChaser Jul 31 '23 at 12:04
  • @fly2matrix I solved my problem. The main cause was related to delimiters. You can check my answer if you're interested. – KnightChaser Jul 31 '23 at 12:53
  • BTW, `cat` _does_ still copy binary output from its stdin (or command-line-argument files) to stdout even if that content isn't a well-formed text file (which as you noted requires a newline at the end of each line of text); there'd need to be something else in play for that output not to be read or visible. The `'\r\n'` will cause the cursor to go back to the beginning of the line during the process of printing, but it doesn't stop that printing from taking place. – Charles Duffy Jul 31 '23 at 15:33
  • (Mind, if something you do adds _extra_ content, a cursor at the beginning of the line without a newline to cause it to be moved down can lead to whatever was there before the move-to-the-left to be overwritten; alternately, Windows only puts CRLFs _between_ lines, not _after_ lines, so a one-line file won't have one any CRLF sequence at all; but in the general case, where you aren't using something like `while read` expected to process the last line, just `cat`ting a file with Windows newlines works well enough) – Charles Duffy Jul 31 '23 at 15:35

1 Answers1

1

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?

KnightChaser
  • 143
  • 1
  • 9