Как вывести/убрать специальные символы в документе LaTeX?
Мы внедрили онлайн-сервис, где можно создавать PDF с предопределенным
состав. Пользователь может выбрать шаблон LaTeX, а затем скомпилировать его с соответствующими входами.
Вопрос, о котором мы беспокоимся, - это безопасность, что злоумышленник не смог получить доступ к оболочке через инъекцию специальной инструкции в латексный документ.
Нам нужно обходное решение для этого или, по крайней мере, списка специальных символов, которые мы должны удалить из входных данных.
Предпочтительным языком будет PHP, но любые предложения, конструкции и ссылки приветствуются.
PS. в нескольких словах мы ищем mysql_real_escape_string для LaTeX
Ответы
Ответ 1
Единственная возможность (AFAIK) выполнять вредные операции с использованием LaTeX - это возможность возможности вызова внешних команд с помощью \write18
. Это работает только при запуске LaTeX с аргументом -shell-escape или -enable-write18 (в зависимости от вашего дистрибутива).
Итак, пока вы не запускаете его с одним из этих аргументов, вы должны быть в безопасности, не отфильтровывая какие-либо части.
Кроме того, все еще можно записывать другие файлы с помощью команд \newwrite
, \openout
и \write
. Может ли пользователь создавать и (над) писать файлы, может быть нежелательным? Таким образом, вы можете отфильтровать вхождения этих команд. Но сохранение черных списков определенных команд подвержено ошибкам, так как кто-то с плохим намерением может легко скрыть действительную команду, опуская входной документ.
Изменить: запуск команды LaTeX с использованием ограниченной учетной записи (т.е. отсутствие записи в каталоги, не связанные с латекс/проект) в сочетании с отключением \write18
, может быть проще и безопаснее, чем содержать черный список "опасных" команд.
Ответ 2
Вот какой код для реализации ответа Джеффа Риди. Я размещаю этот код в общедоступном домене.
<?
$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
В целом, достижение безопасности исключительно посредством экранирования командных последовательностей трудно обойтись без радикального уменьшения выразительности, поскольку нет принципиального способа отличить безопасные cs от небезопасных: Tex - это просто не достаточно чистый язык программирования, чтобы это разрешить. Я бы сказал, отказаться от этого подхода в пользу устранения наличия дыр в безопасности.
Резюме ошибок безопасности в Latex соответствует моей работе: например, проблемы - это экранирование оболочки и создание файла. Перезапись, хотя он и упустил уязвимость при выходе из оболочки. Далее следуют некоторые дополнительные пункты, затем некоторые рекомендации:
- Недостаточно избегать активного вызова
--shell-escape
, поскольку он может быть неявно включен в texmf.cnf. Вы должны явно передать --no-shell-escape
для переопределения texmf.cnf;
-
\write18
- это примитив Etex, а не Knuth Tex, поэтому вы можете избежать латексов, которые его реализуют (что, к сожалению, большинство из них);
- Если вы используете Dvips, существует еще один риск: команды
\special
могут создавать файлы .dvi, которые запрашивают dvips для выполнения команд оболочки. Поэтому, если вы используете dvips, передайте команду -R2
, чтобы запретить вызов команд оболочки;
- texmf.cnf позволяет указать, где Tex может создавать файлы;
- Возможно, вам не удастся отключить создание шрифтов, если вы хотите, чтобы ваши клиенты имели большую свободу в том, какие шрифты они могут создавать. Взгляните на заметки о безопасности для Kpathsea; поведение по умолчанию кажется мне разумным, но вы можете иметь дерево пользовательских шрифтов, чтобы один пользователь не ступил на другие пальцы пользователей.
Параметры:
- Песочница для ваших клиентских латексных вызовов и позволяйте им свободно ошибаться в песочнице;
- Доверяйте значениям по умолчанию kpathsea и запрещайте экранировать оболочки в латекс и любые другие исполняемые файлы, используемые для создания PDF файла;
- Резко уменьшить выразительность, запрещая вашим клиентам возможность создавать файлы шрифтов или любые новые файлы, указанные клиентом. Запускайте латекс как процесс, который может записывать только некоторые уже существующие файлы;
- Вы можете создать файл формата, в котором
\write18
cs и создание файла css не связаны, и существуют только макросы, которые вызывают их безопасно, например, для создания шрифта /toc/bbl. Это означает, что вам нужно решить, какие функции у ваших клиентов есть: они не смогут свободно выбирать, какие пакеты им импортировать, но должны использовать выбранные вами варианты. В зависимости от того, какие "шаблоны" вы имеете в виду, это может быть хорошим вариантом, позволяющим использовать пакеты, которые используют экраны оболочки, но вам нужно будет проверить код Tex/Latex, который входит в ваш файл формата.
Postscript
Там есть статья TUGBoat, Генерация на стороне сервера на основе шаблонов LATEX, обращаясь к другому вопросу, к вопросу, которое я взял, а именно создание PDF файлов из ввода формы с использованием латекса.
Ответ 4
В соответствии с http://www.tug.org/tutorials/latex2e/Special_Characters.html специальные символы в латексе # $ % & ~ _ ^ \ { }
. Большинство из них можно избежать с помощью простой обратной косой черты, но _
^
и \
нуждаются в специальной обработке.
Для использования каретки \^{}
(или \textasciicircum
) для использования тильды \~{}
(или \textasciitilde
) и для обратного слэша используйте \textbackslash
Если вы хотите, чтобы пользовательский ввод отображался в виде текста пишущей машинки, есть также команда \verb
, которая может использоваться как \verb+asdf$$&\~^+
, +
может быть любым символом, но не может быть в тексте.
Ответ 5
Вероятно, вы захотите убедиться, что ваш \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/
Ответ 6
В 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")
}
}