You are here: Links of Interest » HEIG-VD » [SLO] Sécurité Logicielle » Labo 02 - Lizord
Labo 02 - Lizord
Labo 02 - Lizord
The objective is to win to consecutive games of Rock-paper-scissors-lizard-Spock with a remote server. After 20 wins the server sends back a flag.
Part 1
By connecting to the server and playing for a while we can see that the server always play the same set of moves.
With this information in hand we can deduce the server exposes a vulnerability of type CWE-330 Insufficiently Random Values. This means we can create a script that tries a move then stores the counter to this move when it loses and tries the whole sequence again. This should allow us to break the complete sequence in a maximum of 20 tries.
Exploit
To exploit this vulnerability I have written a script that learns the move sequence by playing iteratively against the server advance to the next move.
# Move counters counters = { "Paper": ("Scissors", "Lizard"), "Rock": ("Paper", "Spock"), "Lizard": ("Rock", "Scissors"), "Spock": ("Lizard", "Paper"), "Scissors": ("Spock", "Rock") } # Sequence of moves sequence = [None] * 25 attempt = 0 while(True): # open server connection sk = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sk.connect(('<addr>', 9991)) rx_data(sk) # get welcome message rx_data(sk) # get first prompt attempt += 1 print("starting attempt", attempt) for idx in range(0, 25): # Get the move to play from the sequence move = sequence[idx] # If the correct move is not known, pick one at random if move is None: move = choice(list(counters.keys())) print("move", idx, "play", move, end=" ") try: # send move to server tx_data(sk, move) # get move result result = rx_data(sk).strip() if 'Draw' in result: print("draw", end=" ") win_move = move else: win_move, _, _ = result.split(' ') prompt = rx_data(sk).strip() if 'You lost' in prompt: print("lost to", win_move, end=" ") counter = choice(counters[win_move]) print("counter is", counter) sequence[idx] = counter break else: print("wins") if 'Choisir' not in prompt: print (prompt) if sequence[idx] is None: sequence[idx] = move except: print("Error, last data:", last_rx) exit() # close socket sk.close()
Result
starting attempt 11 move 0 play Lizard wins move 1 play Scissors wins move 2 play Spock wins move 3 play Scissors wins move 4 play Rock wins move 5 play Spock wins move 6 play Scissors wins move 7 play Lizard wins move 8 play Spock wins move 9 play Rock wins move 10 play Lizard wins move 11 play Spock wins move 12 play Lizard wins move 13 play Scissors wins move 14 play Rock wins move 15 play Lizard wins move 16 play Paper wins move 17 play Lizard wins move 18 play Lizard wins move 19 play Paper wins Congratulations, you won 20 times in a raw ! Wow, you're clearly the best ! Take this as a present. Here is your winning number: 217'384'040'199'995