2010-03-29 17 views
15

Abbiamo implementato il servizio online dove è possibile generare PDF con la struttura predefinita . L'utente può scegliere un modello LaTeX e quindi compilarlo con un input appropriato.Come sfuggire/strisciare caratteri speciali nel documento LaTeX?

La domanda che ci preoccupa è la sicurezza, che l'utente malintenzionato non è stato in grado di ottenere l'accesso alla shell tramite l'iniezione di istruzioni speciali nel documento in lattice.

Abbiamo bisogno di qualche soluzione per questo o almeno un elenco di caratteri speciali che dovremmo eliminare dai dati di input.

La lingua preferita è PHP, ma suggerimenti, costruzioni e collegamenti sono molto apprezzati.

PS. In poche parole, stiamo cercando mysql_real_escape_string per LaTeX

+0

io non sono sicuro di che tipo di codice maligno può essere scritto in LaTeX, ma sono abbastanza sicuro che non c'è PHP equivalente di mysql_real_escape_string per LaTeX. Immagino che vorresti semplicemente inventare alcune espressioni regolari per tagliare linee che non vuoi, purché tu sappia cosa stai cercando. –

+0

Ho risposto alla domanda e poi ho realizzato che non sono sicuro che la mia risposta risponda alla domanda.Di che tipo di modelli stiamo parlando: modelli basati su webform tipici o su alcuni file caricati con markup in lattice? Quest'ultimo è un problema a cui stavo pensando autonomamente ... –

+0

@Charles Stewart: la domanda è nata nella generazione di PDF dagli input webform, ma la domanda più generale sugli upload è anche interessante! – Igor

risposta

3

L'unica possibilità (AFAIK) per eseguire operazioni pericolose usando lattice è di consentire la possibilità di chiamare comandi esterni utilizzando \write18. Funziona solo se si esegue LaTeX con l'argomento --shell-escape o --enable-write18 (a seconda della distribuzione).

Quindi, se non lo si esegue con uno di questi argomenti, si dovrebbe essere sicuri senza la necessità di filtrare le parti.

Oltre a ciò, si è ancora in grado di scrivere altri file utilizzando i comandi \newwrite, \openout e \write. Avere l'utente di creare e (sopra) scrivere file potrebbe essere indesiderato? Quindi puoi filtrare le occorrenze di questi comandi. Ma mantenere le liste nere di determinati comandi è soggetto a fallire poiché qualcuno con una cattiva intenzione può facilmente nascondere l'effettivo comando oscurando il documento di input.

Edit: l'esecuzione del comando di LaTeX utilizzando un account limitato (vale a dire senza la scrittura a/directory relativi al progetto non in lattice) in combinazione con la disattivazione \write18 potrebbe essere più facile e più sicuro di mantenere una lista nera di 'pericoloso' comandi.

+0

Grazie Veger! La tua risposta unita al post di Geoff Reedy dà quella ricevuta perfetta a prova di intrusione. – Igor

+1

Gli utenti possono scrivere loop LaTeX dannosi per la CPU. –

+0

Gli utenti possono ancora leggere file arbitrari, ad es. usando '\ input {/ etc/passwd}'. – pcworld

2

Secondo http://www.tug.org/tutorials/latex2e/Special_Characters.html i caratteri speciali in lattice sono # $ % & ~ _^\ { }. La maggior parte può essere sfuggita con una semplice barra rovesciata ma _^ e \ richiedono un trattamento speciale.

Per uso accento circonflesso \^{} (o \textasciicircum), per l'uso tilde \~{} (o \textasciitilde) e per il backslash utilizzare \textbackslash

Se si desidera che l'input dell'utente di apparire come testo macchina da scrivere, c'è anche il comando \verb che può essere usato come \verb+asdf$$&\~^+, il + può essere qualsiasi carattere ma non può essere nel testo.

+0

Vero, ma questi caratteri non rappresentano una minaccia alla sicurezza per il servizio online OP. – Veger

+1

Se sfuggono questi caratteri, in particolare \, allora si impedirebbe loro di inserire qualsiasi markup. Questa è la cosa più simile a un equivalente di 'mysql_real_escape_string'. – staticsan

+0

@Veger: Sì come il simbolo "'" non fa danno nella query SQL, MA nel posto corretto, e se non si vuole permettere di iniettare alcuni caratteri speciali specifici di LaTeX è necessario sfuggire allo stesso modo come fai per le query SQL. Questo stavo cercando e trova la risposta molto appropriata! – Igor

2

In generale, è difficile ottenere la sicurezza esclusivamente tramite sequenze di comandi di escape senza ridurre drasticamente l'espressività, dal momento che non esiste un modo di principio per distinguere i c sicuri da quelli non sicuri: Tex non è un linguaggio di programmazione sufficientemente pulito per consentire questo .Direi abbandonare questo approccio per eliminare l'esistenza di buchi nella sicurezza.

Il riepilogo di Veger dei buchi di sicurezza in Latex è conforme al mio: cioè, i problemi sono gli escape di shell e la creazione di file .overwriting, sebbene abbia perso una vulnerabilità di escape shell. Alcuni punti aggiuntivi seguono, poi alcune raccomandazioni:

  1. Non è sufficiente per evitare di invocare attivamente --shell-escape, poiché può essere implicitamente abilitata in texmf.cnf. È necessario passare esplicitamente --no-shell-escape per sovrascrivere texmf.cnf;
  2. \write18 è un primitivo di Etex, non di Knuth Tex. In questo modo è possibile evitare i Latex che lo implementano (che, sfortunatamente, è la maggior parte di essi);
  3. Se si utilizza Dvips, esiste un altro rischio: i comandi \special possono creare file .dvi che richiedono a dvips di eseguire i comandi della shell. Quindi dovresti, se usi dvips, passare il comando -R2 per proibire il richiamo dei comandi della shell;
  4. texmf.cnf consente di specificare dove Tex può creare file;
  5. Potrebbe non essere possibile evitare la disattivazione della creazione di caratteri se si desidera che i client abbiano molta libertà in cui i caratteri possano essere creati. Dai uno sguardo allo the notes on security for Kpathsea; il comportamento predefinito mi sembra ragionevole, ma potresti avere un albero dei caratteri per utente, per impedire a un utente di calpestare un altro utente.

Opzioni:

  1. Sandbox invocazioni lattice del vostro cliente, e consentire loro la libertà di comportarsi male nella sandbox;
  2. Fidati dei valori predefiniti di kpathsea e proibisci l'uso di shell escape in latex e qualsiasi altro eseguibile utilizzato per creare l'output PDF;
  3. Riduce drasticamente l'espressività, impedendo ai client la possibilità di creare file di font o qualsiasi nuovo file specificato dal cliente. Esegui il latex come un processo che può solo scrivere su determinati file già esistenti;
  4. È possibile creare un file di formato in cui il cs di \write18 e il css di creazione del file non sono vincolati e solo le macro che li invocano in modo sicuro, ad esempio per la creazione di font/toc/bbl, esistono. Ciò significa che devi decidere quale funzionalità hanno i tuoi clienti: non sarebbero in grado di scegliere liberamente quali pacchetti importano, ma devono fare uso delle scelte che hai imposto loro. A seconda del tipo di "template" che hai in mente, questa potrebbe essere una buona opzione, permettendo l'uso di pacchetti che usano gli escape di shell, ma dovrai controllare il codice Tex/Latex che va nel tuo file di formato.

PostScript

C'è un articolo rimorchiatore, Server side PDF generation based on LATEX templates, indirizzamento altro assumere questione a quello che ho preso, cioè si generano PDF dall'input modulo utilizzando lattice.

+0

Grazie, Charles! La tua spiegazione va oltre la mia esperienza con LaTeX. L'ultimo collegamento è stato estremamente utile per me e i riferimenti alla fine di questo articolo danno molte informazioni su questo argomento. – Igor

15

Ecco un codice per implementare la risposta di Geoff Reedy. Metto questo codice di dominio pubblico.

<? 

$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); 
} 
+6

È necessario modificare "\\ textbackslash" in "\\ textbackslash {}" per garantire un'elaborazione corretta quando il backslash precede immediatamente il testo. Ho provato a modificarlo, ma StackOverflow non consentirebbe una modifica di due caratteri :-( – ruquay