كيفية الهروب/تجريد الشخصيات الخاصة في وثيقة اللاتكس؟
سؤال
قمنا بتنفيذ الخدمة عبر الإنترنت حيث من الممكن إنشاء PDF بهيكل محدد مسبقًا. يمكن للمستخدم اختيار قالب اللاتكس ثم تجميعه مع مدخلات مناسبة.
والسؤال الذي نشعر به هو الأمن ، وأن المستخدم الضار لم يتمكن من الوصول إلى قذيفة من خلال حقن التعليمات الخاصة في مستند اللاتكس.
نحتاج إلى بعض الحلول لهذا أو على الأقل قائمة بالأحرف الخاصة التي يجب أن نتجنبها من بيانات الإدخال.
ستكون اللغة المفضلة هي PHP ، ولكن أي اقتراحات ، والإنشاءات والروابط موضع ترحيب للغاية.
ملاحظة. في بعض الكلمات التي نبحث عنها mysql_real_escape_string للملازم
المحلول
الاحتمال الوحيد (AFAIK) لإجراء عمليات ضارة باستخدام LaTeX هو تمكين إمكانية استدعاء الأوامر الخارجية باستخدام \write18
. يعمل هذا فقط إذا قمت بتشغيل LaTex مع حجة-SHELL-ESCAPE أو-القابلة للتمكين -WRITE18 (اعتمادًا على توزيعك).
طالما أنك لا تقوم بتشغيله مع إحدى هذه الحجج ، يجب أن تكون آمنًا دون الحاجة إلى تصفية أي أجزاء.
إلى جانب ذلك ، لا يزال المرء قادرًا على كتابة ملفات أخرى باستخدام \newwrite
, \openout
و \write
الأوامر. قد يكون إنشاء الملفات (أكثر من) إنشاء الملفات غير مرغوب فيها؟ لذلك يمكنك تصفية حوادث هذه الأوامر. لكن الحفاظ على السوداء في أوامر معينة عرضة للفشل لأن شخصًا ما لديه نية سيئة يمكنه بسهولة إخفاء الأمر الفعلي عن طريق وضع مستند الإدخال.
تعديل: تشغيل الأمر اللاتكس باستخدام حساب محدود (أي عدم الكتابة إلى الدلائل غير اللاتكس/المشروع) بالاقتران مع تعطيل \write18
قد يكون أسهل وأمانًا من الاحتفاظ بقائمة سوداء لأوامر "خطرة".
نصائح أخرى
إليك بعض التعليمات البرمجية لتنفيذ إجابة جيف ريدي. أضع هذا الرمز في المجال العام.
<?
$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 );
}
بشكل عام ، من الصعب القيام بتحقيق الأمن من خلال التسلسلات التي تفرغ من الأوامر دون تقليل التعبير بشكل كبير ، لأنه لا توجد طريقة مبدئية لتمييز CS الآمنة عن تلك غير الآمنة: Tex ليست مجرد لغة برمجة نظيفة بما يكفي للسماح بذلك. أود أن أقول التخلي عن هذا النهج لصالح القضاء على وجود الثقوب الأمنية.
ملخص VEGER للثقوب الأمنية في اللاتكس يتوافق مع الألغام: أي القضايا هي هروب الصدفة وإنشاء الملفات. الكتابة ، على الرغم من أنه فاته قابلية الهروب من قذيفة. تتبع بعض النقاط الإضافية ، ثم بعض التوصيات:
- لا يكفي تجنب التذرع بنشاط
--shell-escape
, ، لأنه يمكن تمكينه ضمنيًا في texmf.cnf. يجب أن تمر صراحة--no-shell-escape
لتجاوز texmf.cnf ؛ \write18
هي بدائية من Etex ، وليس Knuth's Tex. حتى تتمكن من تجنب اللاتكس التي تنفذها (والتي ، للأسف ، هي معظمها) ؛- إذا كنت تستخدم DVIPS ، فهناك خطر آخر:
\special
يمكن للأوامر إنشاء ملفات .dvi التي تطلب من DVIPs تنفيذ أوامر shell. لذلك يجب عليك ، إذا كنت تستخدم DVIPS ، اجتياز-R2
أمر لا سمح التذرع بأوامر shell ؛ - يتيح لك Texmf.cnf تحديد المكان الذي يمكن أن يقوم فيه Tex بإنشاء ملفات ؛
- قد لا تكون قادرًا على تجنب تعطيل إنشاء الخطوط إذا كنت تريد الكثير من الحرية التي قد يقومون بها. ألق نظرة على ملاحظات على الأمن ل KPATHSEA; ؛ يبدو السلوك الافتراضي معقولًا بالنسبة لي ، ولكن قد يكون لديك شجرة خطية لكل مستخدم ، لمنع انطلاق أحد المستخدمين على أصابع مستخدمين أخرى.
خيارات:
- Sandbox Invocations the LaTex الخاص بعميلك ، والسماح لهم بالحرية في سوء التصرف في صندوق الرمل ؛
- الثقة في الافتراضات في KPATHSEA ، والانهابات الممنوعة في اللاتكس وأي تنفيذيات أخرى تستخدم لبناء إخراج PDF ؛
- قلل بشكل كبير من التعبير ، مما يمنع عملائك القدرة على إنشاء ملفات الخطوط أو أي ملفات جديدة محددة العميل. قم بتشغيل LATEX كعملية لا يمكنها الكتابة إلا إلى بعض الملفات الموجودة بالفعل ؛
- يمكنك إنشاء ملف تنسيق فيه
\write18
CS ، و CSS CREAN ، ليست ملزمة ، ولا توجد وحده وحدات الماكرو التي تستدعيها بأمان ، مثل إنشاء الخطوط/TOC/BBL. هذا يعني أنه يتعين عليك أن تقرر الوظائف التي يتمتع بها عملاؤك: لن يتمكنوا من اختيار الحزم التي تستوردها بحرية ، ولكن يجب عليهم الاستفادة من الخيارات التي فرضتها عليها. اعتمادًا على نوع "القوالب" التي تفكر فيها ، قد يكون هذا خيارًا جيدًا ، مما يتيح استخدام الحزم التي تستخدم هروب Shell ، ولكن ستحتاج إلى تدقيق رمز Tex/LaTex الذي ينتقل إلى ملف التنسيق الخاص بك.
PostScript
هناك مقال زورق ، جيل PDF جانب الخادم استنادًا إلى قوالب اللاتكس, ، معالجة آخر سؤال حول السؤال الذي أخذته ، وهو إنشاء ملفات PDF من إدخال النموذج باستخدام LaTeX.
بالنسبة الى http://www.tug.org/tutorials/latex2e/special_characters.html الشخصيات الخاصة في LaTex # $ % & ~ _ ^ \ { }
. يمكن الهروب من معظمهم مع اندلاء خلفي بسيط ولكن _
^
و \
تحتاج معاملة خاصة.
لاستخدام الكاريت \^{}
(أو \textasciicircum
) ، لاستخدام تيلد \~{}
(أو \textasciitilde
) وللاستخدام الخلفي \textbackslash
إذا كنت تريد أن تظهر إدخال المستخدم كنص آلة كاتبة ، فهناك أيضًا \verb
الأمر الذي يمكن استخدامه مثل \verb+asdf$$&\~^+
, ، ال +
يمكن أن يكون أي حرف ولكن لا يمكن أن يكون في النص.
ربما تريد التأكد من أن \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/
في 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")
}
}