2012-03-30 13 views
6

Estoy escribiendo un sistema para una aplicación de navegador que almacenará algunos scripts php particulares en una base de datos y luego los sacará y ejecutará cuando sea necesario. Al principio intenté usar exec() y piping para obtener el resultado de un script que sacaba los scripts de la base de datos y los imprimía. Esto funcionó en un caso de uso, pero no en todos, y se siente frágil de todos modos, entonces estoy buscando una mejor manera.Incluir desde la secuencia "php: // memory"

Ahora estoy intentando lograr esto a través del uso de una secuencia de archivos PHP en la memoria. Por ejemplo:

$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"; 

Sin embargo, no se imprime nada cuando se ejecuta la secuencia de comandos. ¿Esto es incluso posible por este medio, y si no, hay otra manera de hacer esto? Estoy tratando de evitar tener que escribir archivos temporales y leer de ellos, ya que estoy seguro de que acceder al sistema de archivos ralentizaría las cosas. ¿Hay alguna URL que pueda proporcionar para "incluir" para que lea la secuencia de la memoria como si fuera un archivo?

No creo que eval() haga esto, ya que, si mal no recuerdo, se limita a una sola línea.

Además, no hay respuestas "eval = include = hell". Los usuarios que no son administradores no tienen acceso para escribir los scripts almacenados en la base de datos, sé que esto requiere un tratamiento especial durante el ciclo de vida de mi aplicación.

+0

Mi palabra, estaba totalmente equivocado. Eval funciona para más de una línea. Ni siquiera lo intenté jajaja ... supongo que eso funcionará entonces. Sin embargo, todavía tengo curiosidad acerca de las secuencias de archivos almacenadas en la memoria, por lo que si alguien tiene una respuesta a esa parte, estaría agradecido. –

+0

¿Hay algún motivo en particular por el que no desee crear archivos? El sistema de archivos es una base de datos para archivos. Y: Dios mío, no lo hagas, eso es peligroso. No importa si solo los administradores pueden escribir en estos archivos php, tan pronto como tenga un error de inyección SQL o alguien logre obtener/adivinar/revelar sus credenciales de MySQL -> insta-remote-code-execution. – mensi

Respuesta

4

eval() y include son en realidad bastante iguales. Entonces, eval() funciona con varias líneas, solo para su información. Sin embargo, preferiría include aquí, siempre pienso que es más rápido. Tal vez estoy equivocado, no tengo idea.

Sin embargo, creo que debe depurar su código, no veo una razón per se por qué no debería funcionar. Es posible que necesite rewind el puntero (lo ha comentado), pero lo que debe verificar de primera mano es that your PHP configuration allows to include URLs. Sé que esa configuración evita el uso de los URI data://, por lo que puede tener esto habilitado.

También siempre puedes probar si PHP puede abrir la memoria usando file_get_contents y desechar. Esto debería darte el código. Si no, ya cometió un error (por ejemplo, no rebobinar o algo similar).

Editar: No hemos llegado tan lejos (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)); 

Esto es lo que descubrí:

  1. No debe cerrar el "archivo". php://memory es una secuencia una vez cerrada que desaparecerá.
  2. Necesita acceder al $fp como una secuencia, que no es posible para include fuera de la caja AFAIK.
  3. Debería crear una envoltura de flujo que asigne un recurso de flujo a un nombre de archivo.
  4. Cuando haya hecho eso, puede incluir una secuencia de memoria.
  5. La configuración de PHP que necesita comprobar de todos modos. Hay más de uno, consulte el manual de PHP.

Puede ser que sea más fácil utilizar el URI de datos (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); 

Ver también: Include code from a PHP stream

+0

Esto da un error variable indefinido. Para solucionarlo, cambie 'var_dump ($ thing);' a 'var_dump (\ $ thing);' –

+0

@ CláudioSilva: Fixed. Thx por la pista. – hakre

0

Si hay una manera de incluir de php: // memoria entonces este es una vulnerabilidad seria Si bien tiene muchos usos, eval se usa con bastante frecuencia con técnicas de ocultación de código para ocultar código malicioso.

(Cada herramienta es un arma si se mantiene bien.)

Con esto dicho, hay (afortunadamente) no parece haber ninguna manera obvia para incluir de php: // memoria