Alquymia


ALQ{pok3m00n_th3_flag}

Um dos desafios em Alquymia foi um caso de (CWE-190) Integer Overflow que permitiu obter a flag.

O código foi disponibilizado em C, sendo ele:

#include <stdio.h>  
#include <stdlib.h>  
int main()  
{  
	int con;  
	con = 0;  
	int account_balance = 1100;  
	while(con == 0){  
  
		printf("Bem-vindo à loja de trocas de Pokémon\n");  
		printf("Aqui trocamos Pokémons\n\n");  
  
		printf("1. Verificar saldo de moedas\n");  
		printf("2. Trocar por Pokémons\n");  
		printf("3. Sair\n\n");  
  
		int menu;  
  
		printf("Escolha uma opção no menu: ");  
		fflush(stdout);  
		fflush(stdin);  
		scanf("%d", &menu);  
		if(menu == 1){  
			printf("\n - Saldo: %d \n\n", account_balance);  
		}  
		else if(menu == 2){  
			printf("\nAtualmente disponíveis para troca: \n\n");  
			printf("1. Pikachu\n");  
			printf("2. Charizard 1337\n\n");  
			printf("Escolha: ");  
			fflush(stdout);  
			int auction_choice;  
			fflush(stdin);  
			scanf("%d", &auction_choice);  
			if(auction_choice == 1){  
				printf("\nEsse Pokémom custa 900 moedas cada, insira a quantidade desejada: ");  
				fflush(stdout);  
				int number_pokemons = 0;  
				fflush(stdin);  
				scanf("%d", &number_pokemons);  
					if(number_pokemons > 0){  
						int total_cost = 0;  
						total_cost = 900*number_pokemons;  
						printf("\nO custo final é: %d\n", total_cost);  
		  
						if(total_cost <= account_balance){  
							account_balance = account_balance - total_cost;  
							printf("\nSeu saldo atual após a transação: %d\n\n", account_balance);  
						}  
					else{  
						printf("Saldo insuficiente para completar a transação\n");  
					}  
				fflush(stdout);  
				}  
			}  
		else if(auction_choice == 2){  
		printf("\nCharizard 1337 custa 100000 moedas, e só temos 1 em estoque.\n\n");  
		printf("Digite 1 para comprar: ");  
		int bid = 0;  
		fflush(stdout);  
		fflush(stdin);  
		scanf("%d", &bid);  
		  
		if(bid == 1){  
  
			if(account_balance > 100000){  
			FILE *f = fopen("flag.txt", "r");  
			if(f == NULL){  
				printf("Flag não encontrada, por favor execute isso no servidor.\n");  
			exit(0);  
			}  
			char buf[64];  
			fgets(buf, 63, f);  
			printf("SEU POKEMON É: %s\n", buf);  
		}  
	  
		else{  
		printf("\n - Saldo insuficiente para a transação.\n\n");  
		}
	}  
}  
fflush(stdout);  
}  
else{  
con = 1;  
}  
  
}  
fflush(stdout);  
	return 0;  
}

A vulnerabilidade estava na hora da leitura da quantidade de Pokémon a serem comprados. Quando o número digitado, multiplicado por 900 (preço do Pikachu), excedesse a quantidade máxima reservada por variável do tipo int em C (2147483647), então, após a multiplicação, o valor do saldo era transformado em um número muito alto, permitindo a compra do Charizzard e obtendo a Flag.