Как экранировать / удалить специальные символы в документе LaTeX? - PullRequest
15 голосов
/ 30 марта 2010

Мы внедрили онлайн-сервис, где можно генерировать PDF с предопределенными состав. Пользователь может выбрать шаблон LaTeX и затем скомпилировать его с соответствующими входными данными.

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

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

PS. в нескольких словах мы ищем mysql_real_escape_string для LaTeX

Ответы [ 6 ]

15 голосов
/ 24 марта 2011

Вот некоторый код для реализации ответа Джеффа Риди. Я размещаю этот код в открытом доступе.

<?

$test = "Test characters: # $ % & ~ _ ^ \ { }.";
header( "content-type:text/plain" );
print latexSpecialChars( $test );
exit;

function latexSpecialChars( $string )
{
    $map = array( 
            "#"=>"\\#",
            "$"=>"\\$",
            "%"=>"\\%",
            "&"=>"\\&",
            "~"=>"\\~{}",
            "_"=>"\\_",
            "^"=>"\\^{}",
            "\\"=>"\\textbackslash",
            "{"=>"\\{",
            "}"=>"\\}",
    );
    return preg_replace( "/([\^\%~\\\\#\$%&_\{\}])/e", "\$map['$1']", $string );
}
3 голосов
/ 30 марта 2010

В целом, достижение безопасности исключительно через экранирование последовательностей команд трудно сделать без резкого снижения выразительности, поскольку нет принципиального способа отличить безопасные cs от небезопасных: Tex просто не достаточно чистый язык программирования, чтобы допустить это. Я бы сказал, отказаться от этого подхода в пользу устранения существования дыр в безопасности.

Резюме Вегера о дырах в безопасности в Latex соответствует моему: проблемы заключаются в экранировании оболочки и создании файла. Перезаписи, хотя он упустил уязвимость экранирования оболочки. Далее следуют некоторые дополнительные пункты, затем некоторые рекомендации:

  1. Недостаточно избежать активного вызова --shell-escape, поскольку его можно неявно включить в texmf.cnf. Вы должны явно передать --no-shell-escape для переопределения texmf.cnf;
  2. \write18 - это примитив Etex, а не Tex Кнута. Таким образом, вы можете избежать латексов, которые его реализуют (к сожалению, большинство из них);
  3. Если вы используете Dvips, существует еще один риск: \special команды могут создавать файлы .dvi, которые просят dvips выполнять команды оболочки. Поэтому вы должны, если вы используете dvips, передать команду -R2, чтобы запретить вызов команд оболочки;
  4. texmf.cnf позволяет указать, где Tex может создавать файлы;
  5. Возможно, вам не удастся отключить создание шрифтов, если вы хотите, чтобы ваши клиенты имели большую свободу в том, какие шрифты они могут создавать. Взгляните на заметки о безопасности для Kpathsea ; поведение по умолчанию мне кажется разумным, но вы можете использовать дерево шрифтов для каждого пользователя, чтобы один пользователь не наступал на пальцы других пользователей.

Опции:

  1. Поместите в песочницу латексные вызовы вашего клиента и предоставьте им свободу вести себя в песочнице;
  2. Доверьтесь значениям по умолчанию kpathsea и запретите экранирование оболочки в латексе и любых других исполняемых файлах, используемых для создания вывода PDF;
  3. Значительно уменьшите выразительность, запретив вашим клиентам возможность создавать файлы шрифтов или любые новые файлы, указанные клиентом. Запускать латекс как процесс, который может записывать только в определенные уже существующие файлы;
  4. Вы можете создать файл формата, в котором \write18 cs и css создания файла не связаны, и существуют только макросы, которые их безопасно вызывают, например, для создания шрифта / toc / bbl. Это означает, что вы должны решить, какие функции имеют ваши клиенты: они не смогут свободно выбирать, какие пакеты импортировать, но должны использовать варианты, которые вы им навязали. В зависимости от того, какие «шаблоны» вы имеете в виду, это может быть хорошим вариантом, позволяющим использовать пакеты, использующие экранирование оболочки, но вам нужно будет проверять код Tex / Latex, который входит в ваш файл формата.

Постскриптум

Есть статья TUGBoat, Генерация PDF на стороне сервера на основе шаблонов LATEX , в которой рассматривается другой подход к вопросу, который я взял, а именно: создание PDF-файлов из форм ввода с использованием Latex.

3 голосов
/ 30 марта 2010

Единственная возможность (AFAIK) выполнять вредоносные операции с использованием LaTeX - это возможность вызова внешних команд с использованием \write18. Это работает, только если вы запускаете LaTeX с аргументом --shell-escape или --enable-write18 (в зависимости от вашего дистрибутива).

Так что, пока вы не запускаете его с одним из этих аргументов, вы должны быть в безопасности без необходимости отфильтровывать какие-либо части.

Кроме того, можно по-прежнему записывать другие файлы с помощью команд \newwrite, \openout и \write. Если пользователь создает и (перезаписывает) файлы, может быть нежелательным? Таким образом, вы можете отфильтровать вхождения этих команд. Но сохранение в черных списках некоторых команд может привести к сбою, поскольку кто-то с плохим намерением может легко скрыть фактическую команду, запутав входной документ.

Редактировать : Выполнение команды LaTeX с использованием ограниченной учетной записи (т.е. без записи в каталоги, не относящиеся к латексу / проекту) в сочетании с отключением \write18 может быть проще и безопаснее, чем сохранение черного списка ' опасные команды.

2 голосов
/ 30 марта 2010

Согласно http://www.tug.org/tutorials/latex2e/Special_Characters.html специальными символами в латексе являются # $ % & ~ _ ^ \ { }. Большинству можно избежать с помощью простой обратной косой черты, но _ ^ и \ требуют особого обращения.

Для каретки \^{} (или \textasciicircum), для тильды \~{} (или \textasciitilde) и для обратной косой черты \textbackslash

Если вы хотите, чтобы пользовательский ввод отображался в виде текста на пишущей машинке, существует также команда \verb, которую можно использовать, например, \verb+asdf$$&\~^+, + может быть любым символом, но не может быть в тексте.

0 голосов
/ 08 июня 2019

В Scala я использую этот фрагмент.

package punychar.rellyfiler.latex

object LaTexEscape {

   def textbf_boldfont(x: String): String = s"\\textbf{${x}}"

   def escapeSpecialCharacters(input: String): String = {
      return if (input == null) null
      else
         input
            .replaceAll("\\\\", "\\\\textbackslash ")
            .replaceAll("([#$%&_{}])", "\\\\$1")
            .replaceAll("([<>])", "\\\u0024$1\\\u0024")
            .replaceAll("~", "\\\\textasciitilde ")
            .replaceAll("\\^", "\\\\textasciicircum ")
   }

}

и эти тесты

package punychar.rellyfiler.latex

import org.scalatest.FlatSpec

import punychar.rellyfiler.latex.LaTexEscape.escapeSpecialCharacters

class Test extends FlatSpec {

   "LaTex Escape" should "escape basic special characters by preceding backslash" in {
      assert(escapeSpecialCharacters("&%$#_{}") == "\\&\\%\\$\\#\\_\\{\\}")
   }

   "LaTex Escape" should "should describe tilde by words" in {
      assert(escapeSpecialCharacters("~") == "\\textasciitilde ")
   }

   "LaTex Escape" should "should describe circum by words" in {
      assert(escapeSpecialCharacters("^") == "\\textasciicircum ")
   }

   "LaTex Escape" should "should desribe backslash by words" in {
      assert(escapeSpecialCharacters("\\") == "\\textbackslash ")
   }

   "LaTex Escape" should "deal with combinations of special characters, too" in {
      assert(escapeSpecialCharacters("~blabla\\x") == "\\textasciitilde blabla\\textbackslash x")
   }
}
0 голосов
/ 30 марта 2010

Возможно, вы захотите убедиться, что ваш \write18 отключен.

См. http://www.fceia.unr.edu.ar/lcc/cdrom/Instalaciones/LaTex/MiKTex/doc/ch04s08.html и http://www.texdev.net/2009/10/06/what-does-write18-mean/

...