2012-03-30 19 views
6

Sto scrivendo un sistema per un'applicazione browser che memorizzerà alcuni particolari script php in un database e quindi li estrarrà ed eseguirli quando necessario. All'inizio ho provato a usare exec() e piping per riprodurre l'output di uno script che ha ottenuto gli script dal database e li ha stampati. Questo ha funzionato in un caso d'uso, ma non in tutti, e si sente fragile comunque, quindi sto cercando un modo migliore.Includi dallo stream "php: // memory"

Ora sto tentando di farlo utilizzando un flusso di file PHP in memoria. Ad esempio:

$thing = <<<'TEST' 
<?php 

$thing = array(); 

print "Testing code in here."; 
var_dump($thing); 

?> 
TEST; 

$filename = "php://memory"; 

$fp = fopen($filename, "w+b"); 
fwrite($fp, $thing); 
//rewind($fp); 

fclose($fp); 

include "php://memory"; 

Tuttavia, non viene stampato nulla quando viene eseguito lo script. Questo è possibile anche con questo mezzo, e se no, c'è un altro modo per farlo? Sto cercando di evitare di dover scrivere file temporanei e leggere da loro, poiché sono sicuro che l'accesso al filesystem rallenterebbe le cose. C'è un URL che posso fornire a "include" in modo che legga il flusso di memoria come se fosse un file?

Non penso che lo eval() faccia ciò, poiché, se ricordo bene, è limitato a una sola riga.

Inoltre, per favore nessuna risposta "eval = include = hell". Gli utenti non amministratori non hanno accesso a scrivere gli script memorizzati nel database, so che questo richiede un trattamento speciale per il ciclo di vita della mia applicazione.

+0

mio parola, ero totalmente sbagliato. Eval funziona per più di una linea. Non l'ho nemmeno provato lol ... supponiamo che funzionerà allora. Tuttavia, sono ancora curioso dei flussi di file archiviati in memoria, quindi se qualcuno ha una risposta a questa parte, sarei grato. –

+0

C'è un motivo particolare per cui non si desidera creare file? Il filesystem è un database per i file. E: OMG NON ​​FARLO CHE È PERICOLOSO. Non importa se solo gli amministratori possono scrivere su questi file php, non appena si ha un bug di SQL injection o qualcuno riesce a ottenere/indovinare/rivelare le proprie credenziali MySQL -> insta-remote-code-execution. – mensi

risposta

5

È necessario utilizzare stream_get_contents per leggere dallo php://memory stream. Non puoi includerlo direttamente.

4

eval() e include sono praticamente uguali. Quindi eval() funziona con più linee, solo FYI. Tuttavia, preferirei lo include qui, penso sempre che sia più veloce. Forse ho torto, nessuna idea.

Tuttavia, penso che dovresti eseguire il debug del tuo codice, non vedo un motivo perché questo non dovrebbe funzionare. Potrebbe essere necessario il puntatore rewind (che hai commentato), ma quello che dovresti controllare è, that your PHP configuration allows to include URLs. So che quell'impostazione impedisce l'uso degli URI data://, quindi potrebbe essere abilitato.

Inoltre, si può sempre provare se PHP può aprire la memoria utilizzando file_get_contents e scaricare. Questo dovrebbe darti il ​​codice. In caso contrario, hai già commesso un errore (ad esempio, nessun riavvolgimento o qualcosa di simile).

Edit: io non sono venuto così lontano (demo):

<?php 
/** 
* Include from “php://memory” stream 
* @link https://stackoverflow.com/q/9944867/367456 
*/ 

$thing = <<<TEST 
<?php 
\$thing = array(); 
print "Testing code in here."; 
var_dump(\$thing); 
TEST; 

$filename = "php://memory"; 

$fp = fopen($filename, "w+b"); 
fwrite($fp, $thing); 
rewind($fp); 

var_dump(stream_get_contents($fp)); 

Questo è quello che ho scoperto:

  1. Non si dovrebbe chiudere il "file". php://memory è uno stream una volta chiuso scomparirà.
  2. È necessario accedere allo $fp come flusso di, che non è possibile per include fuori dalla casella AFAIK.
  3. Sarà quindi necessario creare un wrapper di flusso che associa una risorsa di flusso a un nome di file.
  4. Al termine, è possibile includere un flusso di memoria.
  5. Le impostazioni PHP che è necessario verificare in ogni caso. Ce ne sono più di uno, consultare il manuale PHP.

Potrebbe essere più facile da utilizzare i dati in notazione URI (demo):

<?php 
/** 
* Include from “php://memory” stream 
* @link https://stackoverflow.com/q/9944867/367456 
*/ 

$thing = <<<TEST 
<?php 
\$thing = array(); 
print "Testing code in here."; 
var_dump(\$thing); 
TEST; 

include 'data://text/plain;,'. urlencode($thing); 

Vedi pure: Include code from a PHP stream

+0

Questo dà un errore variabile non definito. Per risolvere il problema, cambia 'var_dump ($ thing);' a 'var_dump (\ $ thing);' –

+0

@ CláudioSilva: risolto. Grazie per il suggerimento. – hakre

0

Se c'è un modo per includere da php: // memoria allora questo è una grave vulnerabilità. Sebbene abbia molti usi, eval viene usato abbastanza spesso con tecniche di offuscamento del codice per nascondere il codice dannoso.

(Ogni strumento è un'arma se lo si tiene a destra.)

Detto questo, c'è (per fortuna) non sembra essere un modo ovvio per includere da php: // memoria