Полиглот (информатика)

Полиглот в информатике — это компьютерная программа, скрипт или иной файл, который одновременно написан в допустимой форме для нескольких языков программирования или форматов файлов[1]. Термин был введён по аналогии с многоязычием. Полиглот-файл составляется путём комбинирования синтаксиса двух или более различных форматов[2].

Описание

Если полиглот-файл предназначен для компиляции или интерпретации как исходный код, такую программу называют полиглот-программой. При этом форматы файлов и синтаксис исходного кода, по сути, являются потоками байтов, и использование этого сходства — основа создания полиглотов[3]. Полиглот-файлы находят ограниченное практическое применение в задачах совместимости[4], но также могут создавать угрозы безопасности, если используются для обхода валидации или эксплуатации уязвимостей.

История

Полиглот-программы используются как головоломки и курьёзы в хакерской культуре по крайней мере с начала 1990-х годов. Примечательный ранний пример, названный просто polyglot, был опубликован в группе Usenet rec.puzzles в 1991 году и поддерживал восемь языков, хотя появился под влиянием ещё более ранних разработок[5]. В 2000 году полиглот-программа была удостоена приза на Международном конкурсе обфусцированного кода на языке C[6].

В XXI веке полиглот-программы и файлы стали рассматриваться как механизм скрытых каналов для распространения вредоносного ПО[3].[7] Файлы-полиглоты имеют ограниченное практическое применение в задачах совместимости[4].

Конструкция

Полиглот создаётся путём комбинирования синтаксиса двух или более форматов, используя различные синтаксические конструкции, которые либо одинаковы для этих форматов, либо уникальны для каждого языка, но имеют разный смысл. Файл считается полиглотом, если его может правильно интерпретировать более одной программы. Например, PDF-Zip-полиглот может быть открыт и как PDF-документ, и как архив ZIP. Чтобы файл оставался валидным при обработке разными программами, нужно следить, чтобы конструкции, специфичные для одного интерпретатора, игнорировались другим и наоборот. Часто вкладка заключается в помещении специфичных конструкций одного языка в сегменты, интерпретируемые другими как комментарии или обычный текст[1].

Примеры

C, PHP и Bash

Распространённые методы создания полиглот-программы основаны на использовании языков, в которых для комментариев применяются разные символы, а также на переопределении различных токенов в других языках. Это демонстрируется на следующем (передан в общественное достояние) полиглоте на ANSI C, PHP и Bash:

Вариант для Bash

#define a /*
#<?php
echo "\010Hello, world!\n";// 2> /dev/null > /dev/null \ ;
 // 2> /dev/null; x=a;
$x=5; // 2> /dev/null \ ;
if (($x))
 // 2> /dev/null; then
return 0;
// 2> /dev/null; fi
#define e ?>
#define b */
#include <stdio.h>
#define main() int main(void)
#define printf printf(
#define true )
#define function
function main()
{
printf "Hello, world!\n"true/* 2> /dev/null | grep -v true*/;
return 0;
}
#define c /*
main
#*/

Вариант для PHP

#define a /*
#<?php
echo "\010Hello, world!\n";// 2> /dev/null > /dev/null \ ;
 // 2> /dev/null; x=a;
$x=5; // 2> /dev/null \ ;
if (($x))
 // 2> /dev/null; then
return 0;
// 2> /dev/null; fi
#define e ?>
#define b */
#include <stdio.h>
#define main() int main(void)
#define printf printf(
#define true )
#define function
function main()
{
printf "Hello, world!\n"true/* 2> /dev/null | grep -v true*/;
return 0;
}
#define c /*
main
#*/

Вариант для C

#define a /*
#<?php
echo "\010Hello, world!\n";// 2> /dev/null > /dev/null \ ;
 // 2> /dev/null; x=a;
$x=5; // 2> /dev/null \ ;
if (($x))
 // 2> /dev/null; then
return 0;
// 2> /dev/null; fi
#define e ?>
#define b */
#include <stdio.h>
#define main() int main(void)
#define printf printf(
#define true )
#define function
function main()
{
printf "Hello, world!\n"true/* 2> /dev/null | grep -v true*/;
return 0;
}
#define c /*
main
#*/

Особенности:

  • Символ «#» обозначает директиву препроцессора в C, но комментарий в bash и PHP.
  • «//» — комментарий в PHP и C, а в bash — путь к корневой директории.
  • Перенаправление вывода оболочки используется для устранения нежелательных сообщений.
  • Символы PHP «<?php» и «?>» срабатывают даже в строках, объявленных как комментарии.
  • Оператор «function main()» валиден и в PHP, и в bash; директивы #define в C конвертируют его в «int main(void)» при компиляции.
  • Комментарии могут комбинироваться для различных действий.
  • «if (($x))» — корректный синтаксис и для bash, и для PHP.
  • printf — встроенная команда bash, идентичная C-версии за исключением скобок, которые докладываются препроцессором C при компиляции.
  • Завершающие три строки используются лишь bash для вызова функции main. В PHP функция определяется, но не вызывается, а в C явный вызов не требуется.

SNOBOL4, Win32Forth, PureBasicv4.x и REBOL

Следующий код одновременно является программой на SNOBOL4, Win32Forth, PureBasic v4.x и REBOL:

Вариант для SNOBOL

*BUFFER : A.A ; .( Hello, world !) @ To Including?
Macro SkipThis; OUTPUT = Char(10) "Hello, World !"
;OneKeyInput  Input('Char', 1, '[-f2-q1]')  ; Char
End; SNOBOL4 + PureBASIC + Win32Forth + REBOL = <3
EndMacro: OpenConsole() : PrintN("Hello, world !")
Repeat : Until Inkey() :  Macro SomeDummyMacroHere
REBOL  [ Title:  "'Hello, World !' in 4 languages"
CopyLeft:  "Developed in 2010 by Society" ]  Print
"Hello, world !"  EndMacro:  func  [][]  set-modes
system/ports/input [binary: true] Input  set-modes
system/ports/input  [binary: false] NOP:: EndMacro
; Wishing to refine it with new language ? Go on !

Вариант для Forth

*BUFFER : A.A ; .( Hello, world !) @ To Including?
Macro SkipThis; OUTPUT = Char(10) "Hello, World !"
;OneKeyInput  Input('Char', 1, '[-f2-q1]')  ; Char
End; SNOBOL4 + PureBASIC + Win32Forth + REBOL = <3
EndMacro: OpenConsole() : PrintN("Hello, world !")
Repeat : Until Inkey() :  Macro SomeDummyMacroHere
REBOL  [ Title:  "'Hello, World !' in 4 languages"
CopyLeft:  "Developed in 2010 by Society" ]  Print
"Hello, world !"  EndMacro:  func  [][]  set-modes
system/ports/input [binary: true] Input  set-modes
system/ports/input  [binary: false] NOP:: EndMacro
; Wishing to refine it with new language ? Go on !

Вариант для BASIC

*BUFFER : A.A ; .( Hello, world !) @ To Including?
Macro SkipThis; OUTPUT = Char(10) "Hello, World !"
;OneKeyInput  Input('Char', 1, '[-f2-q1]')  ; Char
End; SNOBOL4 + PureBASIC + Win32Forth + REBOL = <3
EndMacro: OpenConsole() : PrintN("Hello, world !")
Repeat : Until Inkey() :  Macro SomeDummyMacroHere
REBOL  [ Title:  "'Hello, World !' in 4 languages"
CopyLeft:  "Developed in 2010 by Society" ]  Print
"Hello, world !"  EndMacro:  func  [][]  set-modes
system/ports/input [binary: true] Input  set-modes
system/ports/input  [binary: false] NOP:: EndMacro
; Wishing to refine it with new language ? Go on !

Вариант для REBOL

*BUFFER : A.A ; .( Hello, world !) @ To Including?
Macro SkipThis; OUTPUT = Char(10) "Hello, World !"
;OneKeyInput  Input('Char', 1, '[-f2-q1]')  ; Char
End; SNOBOL4 + PureBASIC + Win32Forth + REBOL = <3
EndMacro: OpenConsole() : PrintN("Hello, world !")
Repeat : Until Inkey() :  Macro SomeDummyMacroHere
REBOL  [ Title:  "'Hello, World !' in 4 languages"
CopyLeft:  "Developed in 2010 by Society" ]  Print
"Hello, world !"  EndMacro:  func  [][]  set-modes
system/ports/input [binary: true] Input  set-modes
system/ports/input  [binary: false] NOP:: EndMacro
; Wishing to refine it with new language ? Go on !

MS-DOS batch и Perl

Следующий файл выполняется как MS-DOS пакетный файл, а затем повторно запускает себя в Perl:

Вариант для DOS-batch

@rem = ' --PERL--
@echo off
perl "%~dpnx0" %*
goto endofperl
@rem ';
#!perl
print "Hello, world!\n";
__END__
:endofperl

Вариант для Perl

@rem = ' --PERL--
@echo off
perl "%~dpnx0" %*
goto endofperl
@rem ';
#!perl
print "Hello, world!\n";
__END__
:endofperl

Такой подход даёт возможность создавать Perl-скрипты, которые легко исполняются в MS-DOS-среде. При этом нет необходимости, чтобы программа выполняла одну и ту же функцию в разных интерпретаторах.

Типы

Существуют следующие основные типы полиглотов:[3]

  • стековые — несколько файлов конкатенируются друг с другом;
  • паразиты — вторичный формат файла прячется внутри комментариев основного;
  • зипперы — два файла «упакованы» друг в друга через комментарии;
  • полости — вторичный формат внедряется в null-заполненные области основного файла.

Преимущества и недостатки

Полиглотная разметка

Полиглотная разметка предлагается как комбинация достоинств HTML5 и XHTML[8]. Такие документы могут синтаксически анализироваться как HTML (совместимый с SGML), так и XML, формируя при этом одинаковую структуру DOM. Например, чтобы документ HTML5 был полиглотом, он должен иметь правильную DOCTYPE и быть написан как корректный XHTML. Затем такой документ можно передавать как HTML или XHTML в зависимости от поддержки браузера и типа MIME.

Согласно рекомендации html-polyglot[8], для создания полиглот-документа HTML5 предлагается соблюдать следующие правила:

  1. Запрещены инструкции обработки и декларация XML;
  2. Указание кодировки документа;
  3. DOCTYPE;
  4. Пространства имён (namespaces);
  5. Синтаксис элементов (закрывающие теги обязательны; void-элементы — через самозакрывающийся тег);
  6. Содержимое элементов;
  7. Текст (например, pre и textarea не должны начинаться с новой строки);
  8. Атрибуты (все значения атрибутов должны быть в кавычках);
  9. Символьные представления (только amp, lt, gt, apos, quot);
  10. Комментарии;
  11. Скрипты и стилизация разметки.

Самый простой вариант полиглот-документа выглядит так:[8]

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
  <head>
    <title>The title element must not be empty.</title>
  </head>
  <body>
  </body>
</html>

В полиглот-разметке элементы, не являющиеся пустыми (например, script, p, div), не могут быть самозакрывающимися даже если внутри ничего нет:[9] Например, для пустого textarea нужно писать <textarea></textarea>, а не <textarea/>.

Комбинирование форматов

Медицинский графический стандарт DICOM был спроектирован с возможностью полиглотирования с TIFF, что позволяет эффективно хранить одни и те же данные изображений в файле, который подходит и для DICOM-, и для TIFF-просмотрщиков[10].

Совместимость

Языки программирования Python 2 и Python 3 изначально не были разработаны для двусторонней совместимости, но общность синтаксиса позволяет создавать полиглотные Python-программы, которые выполняются и в версии 2, и в версии 3[11].

Безопасность

Полиглот двух форматов может стеганографически внедрить вредоносную нагрузку в визуально безобидный и распространённый контейнер — например, в поле комментариев JPEG, куда допускается произвольное содержимое. Уязвимый обработчик JPEG может быть склонён к выполнению такой нагрузки. Уязвимость связана с несовпадением ожидаемой и реальной структуры файла для программы-интерпретатора[1].

SQL-инъекция — частный случай полиглота, когда сервер ожидает, что пользовательский ввод соответствует определённым ограничениям, но фактически обработчик воспринимает его как SQL-код.

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

Гибкие или расширяемые форматы файлов чаще подвержены полиглотированию, а строгость синтаксической проверки снижает такие риски. Например, стандарт PDF требует, чтобы магическое число %PDF находилось в начале файла, но большинство интерпретаторов принимают файл, если эта строка встречается в пределах первых 1024 байтов[3] что открывает «окно» для внедрения в PDF-полиглоты несовместимого содержания. Из-за разнообразия реализаций решений PDF-рендереры могут интерпретировать один и тот же PDF-файл как совершенно разные документы.[12],

Для выявления вредоносных программ, спрятанных в полиглот-файлах, требуются более сложные методы анализа, чем утилиты вроде file. В 2019 году исследование коммерческих антивирусов показало, что несколько таких продуктов не обнаруживали ни одного из тестировавшихся полиглот-вредоносов[3][2].

В 2019 году стало известно о возможности инъекции вредоносного кода в DICOM-файлы медицинских изображений с помощью полиглот-метода PE-DICOM[13]. Природа атаки осложняет «очистку»: поскольку «вредоносный код как бы сплавлен с легитимными изображениями», автоматическая его санация часто невозможна из-за нормативных ограничений, связанных с данными пациентов[14].

Атака GIFAR

GIFAR — это полиглот-файл, одновременно являющийся GIF-изображением и архивом JAR[15]. Такой файл может эксплуатировать уязвимости, если, например, загружается на веб-сайт для хранения изображений (так как валиден как GIF), но затем его Java-содержимое интерпретируется браузером как код из доверенного источника[16]. Уязвимость была устранена в Java JRE 6 Update 11 (CVE опубликована в декабре 2008 года)[17].[18]

GIFAR-файлы существуют благодаря архитектуре форматов: GIF хранит заголовок в начале, а JAR (как и любой ZIP-подобный формат) — структуру в конце файла[19].

Связанные термины

  • Полиглотное программирование — создание программных систем с использованием нескольких языков программирования, но не обязательно в рамках одного файла[20][21].
  • Полиглотная персистентность (polyglot persistence) — аналогичная концепция для баз данных.

Примечания

  1. 1 2 3 Jonas Magazinius. Polyglots // Proceedings of the 2013 ACM SIGSAC conference on Computer & communications security - CCS '13 / Jonas Magazinius, Billy K. Rios, Andrei Sabelfeld. — 4 ноября 2013. — P. 753–764. — ISBN 9781450324779. — doi:10.1145/2508859.2516685.
  2. 1 2 Bridges, Robert A.; Oesch, Sean; Verma, Miki E.; Iannacone, Michael D.; Huffer, Kelly M. T.; Jewell, Brian; Nichols, Jeff A.; Weber, Brian; Beaver, Justin M.; Smith, Jared M.; Scofield, Daniel; Miles, Craig; Plummer, Thomas; Daniell, Mark; Tall, Anne M. (2023). “Beyond the Hype: An Evaluation of Commercially Available Machine-Learning-Based Malware Detectors”. Digital Threats: Research and Practice. 4 (2): 1—22. arXiv:2012.09214. DOI:10.1145/3567432. S2CID 247218744.
  3. 1 2 3 4 5 Koch, Luke; Oesch, Sean; Adkisson, Mary; Erwin, Sam; Weber, Brian & Chaulagain, Amul (2022), Toward the Detection of Polyglot Files, arΧiv:2203.07561 [cs.CR]. 
  4. 1 2 Benefits of polyglot XHTML5. Дата обращения: 4 сентября 2022. Архивировано 12 октября 2011 года.
  5. Polyglot: A program in eight languages. Дата обращения: 6 сентября 2022. Архивировано 6 сентября 2022 года.
  6. 15th International Obfuscated C Code Contest (2000). Дата обращения: 6 сентября 2022. Архивировано 6 сентября 2022 года.
  7. Koch, Luke; Oesch, Sean; Chaulagain, Amul; Dixon, Jared; Dixon, Matthew; Huettal, Mike; Sadovnik, Amir; Watson, Cory; et al. (2024), On the Abuse and Detection of Polyglot Files, arΧiv:2407.01529 [cs.CR]. 
  8. 1 2 3 Polyglot Markup: A robust profile of the HTML5 vocabulary. Дата обращения: 4 сентября 2022. Архивировано 9 августа 2022 года.
  9. Polyglot Markup: HTML-Compatible XHTML Documents: 6.4 Void Elements. Дата обращения: 2 октября 2012. Архивировано 2 октября 2012 года. W3C Editor's Draft, 9 июля 2012.
  10. DICOM-TIFF dual personality files. Дата обращения: 5 сентября 2022. Архивировано 5 сентября 2022 года.
  11. Schofield, Ed Cheat Sheet: Writing Python 2-3 compatible code. Дата обращения: 6 сентября 2022. Архивировано 6 сентября 2022 года.
  12. Wolf, Julia OMG WTF PDF. 27th Chaos Communication Congress (9 февраля 2011). Дата обращения: 6 сентября 2022. Архивировано 9 октября 2022 года.
  13. Desjardins, Benoit; Mirsky, Yisroel; Ortiz, Markel Picado; Glozman, Zeev; Tarbox, Lawrence; Horn, Robert; Horii, Steven C. (апрель 2020). “DICOM Images Have Been Hacked! Now What?”. American Journal of Roentgenology. 214 (4): 727—735. DOI:10.2214/AJR.19.21958. PMID 31770023. S2CID 208318324. Архивировано из оригинала 2022-09-05. Дата обращения 2022-09-05. Используется устаревший параметр |url-status= (справка); Проверьте дату в |date= (справка на английском)
  14. Ubiquitous Bug Allows HIPAA-Protected Malware to Hide Behind Medical Images (17 апреля 2019). Дата обращения: 5 сентября 2022. Архивировано 5 сентября 2022 года.
  15. Byrd, Christopher How to Create a GIFAR. Дата обращения: 6 марта 2023. Архивировано 6 марта 2023 года.
  16. Eckel, Benjamin The GIFAR Image Vulnerability. Hackaday (5 августа 2008). Дата обращения: 6 марта 2023. Архивировано 6 марта 2023 года.
  17. CVE-2008-5343. cve.mitre.org (4 декабря 2008). Дата обращения: 20 апреля 2021. Архивировано 20 апреля 2021 года.
  18. McMillan, Robert А photo that can steal your online credentials. Infoworld.com (1 августа 2008). Архивировано 18 сентября 2020 года.
  19. Rios, Billy Billy (BK) Rios » SUN Fixes GIFARs (17 декабря 2008). Дата обращения: 20 апреля 2021. Архивировано 14 марта 2016 года.
  20. Fjeldberg, Hans (2008). Polyglot Programming - A Business Perspective (PDF) (Магистерская диссертация). Норвежский университет науки и технологии. Архивировано из оригинала (PDF) 2016-03-04. Дата обращения 2015-05-28. Используется устаревший параметр |url-status= (справка)
  21. Gupta, Tripta Analyzing Polyglot Microservices (англ.). Medium (19 декабря 2018). Дата обращения: 5 августа 2019. Архивировано 5 августа 2019 года.