달력

4

« 2024/4 »

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

'nebula level 10'에 해당되는 글 1

  1. 2017.07.19 [문제풀이] Nebula, Level09, Level10

※ LEVEL 09


Q. There’s a C setuid wrapper for some vulnerable PHP code…


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<?php
 
function spam($email)
{
  $email = preg_replace("/\./"" dot "$email);
  $email = preg_replace("/@/"" AT "$email);
  
  return $email;
}
 
function markup($filename$use_me)
{
  $contents = file_get_contents($filename);
 
  $contents = preg_replace("/(\[email (.*)\])/e""spam(\"\\2\")"$contents);
  $contents = preg_replace("/\[/""<"$contents);
  $contents = preg_replace("/\]/"">"$contents);
 
  return $contents;
}
 
$output = markup($argv[1], $argv[2]);
 
print $output;
 
?>
cs



A. 여기는 /e modifier의 기능으로 발생되는 취약점이다. 


e(PCRE_REPLACE_EVAL) modifier 

이 변경자를 지정하면 preg_replace()는 변경할 문자열을 PHP 코드로 처리하고, 그 결과를 검색된 문자열을 이용하여 일반적인 치환을 한다. 작은 따옴표, 큰 따옴표, 백슬래시와 NULL 문자는 백슬래시로 이스케이프된다. 

preg_replace()만 이 변경자를 사용하고 다른 PCRE 함수는 무시한다. 

출처 : http://php.net/manual/kr/reference.pcre.pattern.modifiers.php


지금은 preg_replace 함수에서 지원되지 않는 변경자란다. 대신 preg_replace_callback 함수를 사용하라는디~

(e modifier : This feature was DEPRECATED in PHP 5.5.0, and REMOVED as of PHP 7.0.0) 



그럼 문제풀이로 들어가보도록 하겠다. 

 

[그림 1] e modifier 테스트 


인터넷에 찾아보니까 크게 두가지로 명령어를 실행시키는 것 같았다. 그래서 일단 테스트 목적상 php 파일을 만들어놓고 동작시켜보았다.


[그림 2] 테스트 결과


결과는 두 가지 방법 모두 실행되었다.


[그림 3] 문제풀이 실행


하지만 실제 문제에 대입하였을 때에는 ` ` 로 감싸는 방식의 명령어 실행은 동작하지 않았다. 뭐가 문제인지 모르겠다.


[그림 4] 플래그 획득 


사실 치환 대상이 되는 문자열이라서 PHP 엔진이 다르게 인식하는 지 몰라도 실제 PHP 파일에서는 {${ }} 와 같은 대괄호를 씌우지 않고 단순히 system(sh) 라고만 하여도 실행이 되더라. 물론 파싱하는 과정에서 e modifier가 인식할 수 있도록 도와주는 지시자일 것이라 어림짐작은 하고 있다만..

(정확한 원인에 대해 아시는 분이 있다면 알려주시길 바랍니당 -ㅅ-)




※ LEVEL 10 


Q. The setuid binary at /home/flag10/flag10 binary will upload any file given, as long as it meets the requirements of the access() system call.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
 
int main(int argc, char **argv)
{
  char *file;
  char *host;
 
  if(argc < 3) {
      printf("%s file host\n\tsends file to host if you have access to it\n", argv[0]);
      exit(1);
  }
 
  file = argv[1];
  host = argv[2];
 
  if(access(argv[1], R_OK) == 0) {
      int fd;
      int ffd;
      int rc;
      struct sockaddr_in sin;
      char buffer[4096];
 
      printf("Connecting to %s:18211 .. ", host); fflush(stdout);
 
      fd = socket(AF_INET, SOCK_STREAM, 0);
 
      memset(&sin, 0sizeof(struct sockaddr_in));
      sin.sin_family = AF_INET;
      sin.sin_addr.s_addr = inet_addr(host);
      sin.sin_port = htons(18211);
 
      if(connect(fd, (void *)&sin, sizeof(struct sockaddr_in)) == -1) {
          printf("Unable to connect to host %s\n", host);
          exit(EXIT_FAILURE);
      }
 
#define HITHERE ".oO Oo.\n"
      if(write(fd, HITHERE, strlen(HITHERE)) == -1) {
          printf("Unable to write banner to host %s\n", host);
          exit(EXIT_FAILURE);
      }
#undef HITHERE
 
      printf("Connected!\nSending file .. "); fflush(stdout);
 
      ffd = open(file, O_RDONLY);
      if(ffd == -1) {
          printf("Damn. Unable to open file\n");
          exit(EXIT_FAILURE);
      }
 
      rc = read(ffd, buffer, sizeof(buffer));
      if(rc == -1) {
          printf("Unable to read from file: %s\n", strerror(errno));
          exit(EXIT_FAILURE);
      }
 
      write(fd, buffer, rc);
 
      printf("wrote file!\n");
 
  } else {
      printf("You don't have access to %s\n", file);
  }
}
cs


A. 본 문제는 레이스 컨디션에 관련된 문제이다. 

즉 access 함수로 접근 가능 여부를 판단하고 open 함수로 파일을 여는 시간 차이를 활용한다. 


 [그림 5] token 파일 접근 권한


본 워게임은 token 파일의 내용을 얻어야 하는데 보시다시피 읽기 권한이 없는 것을 알 수 있다. 따라서 조금 전에 말한 바와 같이 우리는 두 함수가 실행되는 그 차이를 이용해서 token 파일을 읽어올 것이다. 


간단히 순서는 !

1. fake_token 파일 생성

2. fake_token 파일과 token 파일을 링크할 링크 파일 생성

3. 포트 오픈 

4. flag10 실행 파일의 인자로 2번에서 생성한 링크 파일을 제공 


위 순서를 계속 반복할 것이다. 


[그림 6] 파일 생성 및 링크 


[그림 7] flag10 실행


[그림 8] token 획득


[그림 9] 플래그 획득 


이상~!

:
Posted by einai