我们实施了在线服务,可以使用预定义生成PDF 结构体。用户可以选择LaTeX模板,然后使用适当的输入进行编译。
我们担心的问题是安全性,恶意用户无法通过在乳胶文档中注入特殊指令来获取shell访问权。
我们需要一些解决方法或至少我们应该从输入数据中删除的特殊字符列表。
首选语言是PHP,但非常欢迎任何建议,结构和链接。
PS。简而言之,我们正在为LaTeX寻找 mysql_real_escape_string
答案 0 :(得分:15)
这是一些实现Geoff Reedy答案的代码。我将此代码放在公共领域。
<?
$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 );
}
答案 1 :(得分:3)
使用LaTeX执行有害操作的唯一可能性(AFAIK)是允许使用\write18
调用外部命令。这只适用于使用--shell-escape或--enable-write18参数运行LaTeX(取决于您的发行版)。
因此,只要您不使用其中一个参数运行它,您就应该是安全的,而无需过滤掉任何部分。
除此之外,还可以使用\newwrite
,\openout
和\write
命令编写其他文件。让用户创建和(重写)写入文件可能不受欢迎?因此,您可以过滤掉这些命令的出现次数。但是保留某些命令的黑名单很容易失败,因为有意图的人可以通过捏造输入文档来轻易隐藏实际命令。
编辑:使用受限帐户运行LaTeX命令(即不写入非乳胶/项目相关目录)以及禁用\write18
可能比保持一个更简单,更安全“危险”命令黑名单。
答案 2 :(得分:3)
一般而言,如果没有大幅度降低表达性,很难实现纯粹通过转义命令序列来实现安全性,因为没有原则上的方法来区分安全的cs和不安全的cs:Tex只是不够干净的编程语言来实现这一点。我会说放弃这种做法有利于消除安全漏洞的存在。
Veger对Latex中安全漏洞的总结符合我的要求:即问题是shell转义和文件创建。覆盖,尽管他已经错过了shell逃逸漏洞。接下来是一些其他要点,然后是一些建议:
--shell-escape
是不够的,因为它可以在texmf.cnf中隐式启用。您应该明确传递--no-shell-escape
以覆盖texmf.cnf; \write18
是Etex的原语,而不是Knuth的Tex。所以你可以避免实现它的Latexes(不幸的是,它们中的大多数都是这样); \special
命令可以创建.dvi文件,要求dvips执行shell命令。因此,如果使用dvips,则应该传递-R2
命令以禁止调用shell命令; 选项:
\write18
cs和文件创建css未绑定,并且只存在安全调用它们的宏,例如font / toc / bbl创建。这意味着您必须决定您的客户具有哪些功能:他们无法自由选择导入的软件包,但必须使用您对其进行的选择。根据您所考虑的“模板”类型,这可能是一个很好的选择,允许使用使用shell转义的包,但您需要审核进入格式文件的Tex / Latex代码。<强>后记强>
有一篇TUGBoat文章,Server side PDF generation based on LATEX templates,针对我所采取的问题解决了另一个问题,即使用Latex从表单输入生成PDF。
答案 3 :(得分:2)
根据http://www.tug.org/tutorials/latex2e/Special_Characters.html,乳胶中的特殊字符为# $ % & ~ _ ^ \ { }
。大多数都可以使用简单的反斜杠进行转义,但_
^
和\
需要特殊处理。
对于使用\^{}
(或\textasciicircum
)的插入符号,使用\~{}
(或\textasciitilde
)和反斜杠使用\textbackslash
如果您希望用户输入显示为打字机文本,还有\verb
命令可以像\verb+asdf$$&\~^+
一样使用,+
可以是任何字符,但不能在文中。
答案 4 :(得分:0)
您可能希望确保\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/
答案 5 :(得分:0)
在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")
}
}