AWS Photo unlimited storage

Published 11-07-2018

Les personnes abonnées au service Amazon Prime, bénéficient de plusieurs services en plus de la réception de colis en 1 jour ouvre.

Nous allons exploiter une faille dans le service Amazon Photo qui est compris dans l’abonnement Amazon Prime.

Pour bénéficier du stockage photo en illimité, il faut uploader des images au format jpeg. Tous les autres fichiers seront facturé.

Si on prend une image au format jpeg, qu’on append à la fin du fichier un deuxième fichier (peut importe le type ou la taille) et qu’on upload le fichier sur Amazon photo, l’upload s’éffectue et lors du download, le fichier téléchargé sera identique au fichier uploadé :D.

Il reste plus qu’à extraire le fichier caché dans la photo.

Notre photo en hexa avec un fichier et l’offset ou ce trouve le fichier pour pouvoir l’extraire.

Notre fichier contient toujours l’image

le fichier original et le fichier telechargé sont toujours identiques

❯ shasum *
ae8c0f1f07c5cf1f40e346dcb1532c411a7a7dd5  44795252265_d97d2d65b8_o.jpg
ae8c0f1f07c5cf1f40e346dcb1532c411a7a7dd5  44795252265_d97d2d65b8_o_amazon.jpg

Et le fichier ce trouve bien dans le stockage dedié à amazon photo

Il y à une limite d’upload. Un fichier ne peut pas depasser 50 Go.

Testé avec une image de 1x1 pixel, ca fonctionne aussi :D.

Clique -> Le code pour cacher un fichier dans une image :

// To compile this code : gcc append.c -o append
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <string.h>
#include <stdbool.h>

static inline bool	usage(int argc)
{
	if (argc != 3) {
		puts("Usage : ./fusion photo.jpeg file_append");
		return (false);
	}
	return (true);
}

int	open_files(char **argv, int *fd_source, int *fd_target)
{
	if ( (*fd_source = open(argv[1], O_RDWR | O_APPEND)) == -1) {
		perror("open");
		return (errno);
	}
	if ( (*fd_target = open(argv[2], O_RDONLY)) == -1) {
		perror("open");
		return (errno);
	}
	return (0);
}

off_t	go_to_end_of_file(int fd_source)
{
	off_t	offset = 0;

	offset = lseek(fd_source, 0, SEEK_END);
	if (offset == -1) {
		perror("lseek");
		return (-1);/
	}
	return (offset);
}

bool	write_to_file(int fd_source, int fd_target)
{
	int		ret = 0;
	char	*buff = NULL;

	// Alloc buffer for read;
	buff = calloc(sizeof(char), 4096);
	if (buff == NULL) {
		printf("calloc error");
		return (false);
	}

	// read target file in jpeg file
	while ((ret = read(fd_target, buff, (size_t)4096)) > 0)
		write(fd_source, buff, (size_t)ret);

	free(buff);
	buff = NULL;

	if (ret == -1) {
		perror("write");
		return (false);
	}
	return (true);
}

int	main(int argc, char **argv)
{
	int			fd_source = 0;
	int			fd_target = 0;
	off_t		offset = 0;

	// Print usage if command bad formatted
	if (usage(argc) == false)
		return (EXIT_FAILURE);

	// Open source file and target file
	open_files(argv, &fd_source, &fd_target);

	// move file offset at end
	offset = go_to_end_of_file(fd_source);
	if (offset == -1)
		return (EXIT_FAILURE);

	// append target file in source file
	if (write_to_file(fd_source, fd_target) == false)
		return (EXIT_FAILURE);

	// write offset where our target begin at end of file
	write(fd_source, &offset, sizeof(offset));

	close(fd_source);
	close(fd_target);

	puts("Fusion success");
}

Clique -> Le code pour recuperer notre fichier :

// To compile this code : gcc split.c -o split
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <string.h>
#include <stdbool.h>

static inline bool	usage(int argc, char *bin)
{
	if (argc != 3) {
		printf("Usage : %s file_to_split new_file", bin);
		return (false);
	}
	return (true);
}

static off_t	get_offset(int fd)
{
	off_t		size_file = 0;
	struct stat	st;

	fstat(fd, &st);

	// set offset where the size is stored
	if (lseek(fd, (off_t)st.st_size - (off_t)sizeof(size_file), SEEK_SET) == -1) {
		perror("lseek");
		exit(errno);
	}

	// read size of hidden file
	if (read(fd, &size_file, sizeof(size_file)) < 1) {
		perror("read");
		exit(errno);
	}

	// replace offset at begin
	if (lseek(fd, 0, SEEK_SET) == -1) {
		perror("lseek");
		exit(errno);
	}

	return (size_file);
}

static bool	split(int fd, off_t offset, char *file)
{
	struct stat	st;
	char	*buff = NULL;
	int		ret = 0;
	int		fd_new_file = 0;

	fstat(fd, &st);
	lseek(fd, offset, SEEK_SET);

	buff = calloc(sizeof(char), 4096);
	if (buff == NULL) {
		printf("calloc error");
		return (false);
	}

	// Create new file
	if ((fd_new_file = open(file, O_CREAT | O_RDWR, 0744)) == -1) {
		perror("open");
		free(buff);
		buff = NULL;
		exit (errno);
	}

	// write hiddent file in new file
	while ((ret = read(fd, buff, (size_t)4096)) == 4096)
		write(fd_new_file, buff, (size_t)ret);

	// write last part without offset
	if ((unsigned long)ret > sizeof(off_t))
		write(fd_new_file, buff, (size_t)ret - sizeof(off_t));

	free(buff);
	buff = NULL;

	return (true);
}

int	main(int argc, char **argv)
{
	int		fd = 0;
	off_t	offset = 0;

	// Print usage if command bad formatted
	if (usage(argc, argv[0]) == false)
		return (EXIT_FAILURE);

	fd = open(argv[1], O_RDONLY);
	if (fd == -1) {
		perror("open");
		return (EXIT_FAILURE);
	}

	offset = get_offset(fd);

	if (split(fd, offset, argv[2]) == false)
		return (EXIT_FAILURE);

	printf("%s created !", argv[2]);

	return (0);
}