[Upload-labs] explicación detallada de pass-09 ~ pass-12

[Upload-labs] explicación detallada de pass-09 ~ pass-12


[Pass-09] Bypass lógico de filtrado

1. Análisis del código fuente

#index.php
$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
    
    
    if (file_exists($UPLOAD_ADDR)) {
    
    
        $deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf",".htaccess");
        $file_name = trim($_FILES['upload_file']['name']);  //去除首尾空格
        $file_name = deldot($file_name);//删除文件名末尾的点
        $file_ext = strrchr($file_name, '.');  //取后缀名
        $file_ext = strtolower($file_ext); //转换为小写
        $file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA
        $file_ext = trim($file_ext); //首尾去空
        
        if (!in_array($file_ext, $deny_ext)) {
    
    
            if (move_uploaded_file($_FILES['upload_file']['tmp_name'], $UPLOAD_ADDR . '/' . $_FILES['upload_file']['name'])) {
    
    
                $img_path = $UPLOAD_ADDR . '/' . $file_name;
                $is_upload = true;
            }
        } else {
    
    
            $msg = '此文件不允许上传';
        }
    } else {
    
    
        $msg = $UPLOAD_ADDR . '文件夹不存在,请手工创建!';
    }
}

Como se puede ver en el código anterior, se utilizan casi todas las posturas de filtrado anteriores y parece que no hay forma de evitarlo.

Sin embargo, una auditoría cuidadosa del código encontró que el secreto original está en la función deldot ():

#common.php
<?php
function deldot($s){
    
    
	for($i = strlen($s)-1;$i>0;$i--){
    
    
		$c = substr($s,$i,1);  //substr(string,start,length)第一个字符从0开始
		if($i == strlen($s)-1 and $c != '.'){
    
    
			return $s;
		}

		if($c != '.'){
    
    
			return substr($s,0,$i+1);
		}
	}
}
?>

La función no tiene nada de malo, es una verificación de bucle. Si el final es un punto, avanzará un bit, y si no es un punto, se tomará la cadena antes de esa posición.

La laguna aquí es que el parámetro no usa la función deldot () nuevamente para eliminar el último punto al final de la capa de filtro.

Por lo tanto, el nombre del archivo se puede construir muma.php. ., es decir, agregar un espacio y un espacio después de php, de modo que después de que se filtre el código anterior .php., la lista negra se pueda omitir con éxito y la función de Windows se utilice para eliminar automáticamente el final del archivo. nombre del sufijo al guardar el archivo El punto hace que apache lo analice correctamente.

2. Proceso de prueba

Las viejas reglas, primero intente cargar un archivo troyano:

imagen-20210319200850437

Use burp para capturar el paquete y cambie el nombre del sufijo a.php. .

imagen-20210319201206972

Repetir, la carga se realizó correctamente.

Ver archivos cargados:

imagen-20210319201349341

Efectivamente, Windows es muy íntimo para eliminar el punto detrás de php.

Simplemente conéctelo con un cuchillo de cocina.

resumen:

Este nivel es una laguna causada por un procesamiento inadecuado de la lógica de filtrado y no hay filtrado de bucle de puntos de sufijo.


[Pass-10] Omisión de escritura doble

1. Análisis del código fuente

$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
    
    
    if (file_exists($UPLOAD_ADDR)) {
    
    
        $deny_ext = array("php","php5","php4","php3","php2","html","htm","phtml","jsp","jspa","jspx","jsw","jsv","jspf","jtml","asp","aspx","asa","asax","ascx","ashx","asmx","cer","swf","htaccess");

        $file_name = trim($_FILES['upload_file']['name']);  //去除首尾空格
        $file_name = str_ireplace($deny_ext,"", $file_name);  //将黑名单中的字符串替换为空
        if (move_uploaded_file($_FILES['upload_file']['tmp_name'], $UPLOAD_ADDR . '/' . $file_name)) {
    
    
            $img_path = $UPLOAD_ADDR . '/' .$file_name;
            $is_upload = true;
        }
    } else {
    
    
        $msg = $UPLOAD_ADDR . '文件夹不存在,请手工创建!';
    }
}

Como se puede ver en el código anterior, el sufijo del nombre del archivo que cargará el backend se comparará de acuerdo con una lista negra y se reemplazará con una vacía. Este es un reemplazo, así que escriba dos veces el nombre del sufijo para omitirlo.

2. Proceso de prueba

Intente cargar primero:

imagen-20210319210812901

Use burp para capturar el paquete y escriba dos veces el sufijo php:

imagen-20210319211132739

Repetir, la carga se realizó correctamente. ¿Pero el sufijo se cambió a hpp? ? ? ¿Cuál es la situación?

Piénselo detenidamente, la lógica de reemplazo es reemplazar de adelante hacia atrás, .phphppprimero reemplace el php anterior con vacío y luego el restohpp

Así que cambie la posición de la escritura doble: .pphphpesto debería estar bien

imagen-20210319211749462

¡Bastante seguro! Luego conéctelo con un cuchillo de cocina.

resumen:

La lógica de filtrado de este nivel es diferente a la anterior. Reemplaza el nombre del sufijo sensible por vacío, y luego se carga correctamente independientemente de si es legal o no. En el desarrollo y uso real, se generará una gran cantidad de archivos basura , ocupando espacio de almacenamiento, y también habrá potencial. Por ejemplo, si hay un archivo que contiene una vulnerabilidad, el archivo troyano seguirá siendo explotado.

Este nivel solo reemplaza los sufijos sensibles con los vacíos a la vez, por lo que se puede omitir la escritura doble, pero preste atención a la posición de la escritura doble y al orden lógico de reemplazo.


[Pass-11] GET% 00 truncado

1. Análisis del código fuente

$is_upload = false;
$msg = null;
if(isset($_POST['submit'])){
    
    
    $ext_arr = array('jpg','png','gif');  //设置白名单
    $file_ext = substr($_FILES['upload_file']['name'],strrpos($_FILES['upload_file']['name'],".")+1); //取后缀名
    if(in_array($file_ext,$ext_arr)){
    
    
        $temp_file = $_FILES['upload_file']['tmp_name'];
        $img_path = $_GET['save_path']."/".rand(10, 99).date("YmdHis").".".$file_ext; //截断就在这里发生

        if(move_uploaded_file($temp_file,$img_path)){
    
    
            $is_upload = true;
        }
        else{
    
    
            $msg = '上传失败!';
        }
    }
    else{
    
    
        $msg = "只允许上传.jpg|.png|.gif类型文件!";
    }
}

Aquí se utiliza un mecanismo de lista blanca. Si el sufijo es jpg, png y gif, se cambia el nombre del archivo y se guarda.

2. Proceso de prueba

Primero cargue un archivo php y descubra que solo los archivos con sufijos png, jpg y gif pueden cargarse. En base a esto, se considera que debería ser un filtro de lista blanca.

imagen-20210319220733960

Usa eructos para capturar el paquete y echa un vistazo:

imagen-20210319221135127

Como se muestra en la figura, se encuentra que la ruta de guardado del archivo cargado se envía en la solicitud de publicación, lo que significa que la ruta es controlable y puede intentar usar% 00 para cortarla y omitirla.

¿Qué es % 00 ?

% 00 es la representación hexadecimal de NULL. Cuando el sistema operativo lee el archivo, cuando encuentra NULL, pensará que el archivo ha finalizado y el siguiente contenido ya no se leerá.

% 00 condiciones de derivación de truncamiento:

1. La versión de php es inferior a 5.3.4

2 、 magic_quotes_gpc = Desactivado

La función magic_quotes_gpc (interruptor de comillas mágicas), cuando magic_quotes_gpc = On, la función en php es juzgar y analizar los datos solicitados por el usuario, tales como: publicar, obtener, caracteres especiales de los datos de la cookie (', ", \, NULL) Agrega una barra invertida para escapar.

El principio de bypass de truncamiento% 00 :

$img_path = $_GET['save_path']."/".rand(10, 99).date("YmdHis").".".$file_ext;

Este código php se utiliza para establecer la ruta donde se guarda el archivo subido. En circunstancias normales, la ruta se configurará así../upload//随机数+时间qianxun.jpg

Pero si la ruta donde se guarda el archivo es controlable, podemos cambiar la ruta a../upload/1.php%00

Entonces la lógica de pasar al empalme de fondo es../upload/1.phpNULL/随机数+时间qianxun.jpg

Pero cuando el sistema operativo lea debido al truncamiento NULL, solo leerá ../upload/1.phphasta

Esta operación equivale a guardar el archivo qianxun.jpg cargado como../upload/1.php

Debido a que qianxun.jpg es solo un archivo troyano con un sufijo modificado, y en este momento, el nombre del archivo se cambia a 1.php debido a la omisión de truncamiento, por lo que apache puede analizarlo correctamente.

¡Vamos! !

Modifique la ruta para ../upload/1.php%00reenviar:

imagen-20210319225014029

El resultado fue un error. Podemos mirar el mensaje de error y encontrar que se escapó 0. . .

Puede ser porque magic_quotes_gpc está activado. Para reproducir la vulnerabilidad, cambie la configuración de magic_quotes a off en el archivo de configuración php y guárdelo, y luego reinicie Apache.

imagen-20210319225441239

Intentar otra vez:

imagen-20210320083616640

Como se muestra en la figura, la carga se realizó correctamente.

Ver archivos cargados:

imagen-20210320083728051

Utilice el navegador para acceder al archivo:

imagen-20210320083941327

resumen:

Escenarios utilizados para el truncamiento% 00:

En la mayoría de los casos, la prueba se realiza capturando el paquete y cambiando el nombre del archivo. Agregue el formato hexadecimal% 00 al final del sufijo del nombre del archivo, por ejemplo: filename = '1.php [null] .jpg', pero en php, $FILES['file']['name']cuando se obtiene el nombre del archivo Se ha cortado, se vuelve 1.phptan incapaz de escapar del if(in_array($file_ext,$ext_arr))filtrado de back-end .

Hay otra situación:

Si el nombre del archivo se obtiene a través de la URL y el archivo se guarda en segundo plano, se usa $_REQUEST['file_name']el $_GET['file_name']nombre del archivo o el nombre del archivo se empalma detrás de la ruta, como :, $file_path="upload/".$_REQUEST['file_name'].rand(10,99).date("YmdHis").".".$file_ext;en este momento, solo necesita cambiar el valor en el parámetro url a file_name = 1.php%00.jpg, y luego cargue el sufijo del archivo troyano directamente Cambie el jpg; la lógica del back-end es que la imagen del troyano se puede filtrar a través de la lista blanca porque el sufijo es .jpg. viene. $_REQUEST['file_name']El valor obtenido se 1.php%00.jpgempalma después de la ruta upload/1.php[null].jpg+随机数+时间+后缀名. Debido al truncamiento de null, la última ruta de archivo guardada para upload/1.php. ¡Es equivalente a cambiar directamente el nombre del caballo de la imagen a 1.php, para que apache pueda analizarlo con éxito!

Otra situación:

Este es el caso de este nivel, la ruta de guardado se pasa desde la url, por lo que el usuario puede controlar, agregar directamente% 00 a la ruta y cortar al guardar, el efecto es el mismo.


[Pass-12] POST% 00 truncado

1. Análisis del código fuente

$is_upload = false;
$msg = null;
if(isset($_POST['submit'])){
    
    
    $ext_arr = array('jpg','png','gif');
    $file_ext = substr($_FILES['upload_file']['name'],strrpos($_FILES['upload_file']['name'],".")+1);
    if(in_array($file_ext,$ext_arr)){
    
    
        $temp_file = $_FILES['upload_file']['tmp_name'];
        $img_path = $_POST['save_path']."/".rand(10, 99).date("YmdHis").".".$file_ext;  
        //将post传递的文件保存路径直接拼接到了最终的路径中
        if(move_uploaded_file($temp_file,$img_path)){
    
    
            $is_upload = true;
        }
        else{
    
    
            $msg = "上传失败";
        }
    }
    else{
    
    
        $msg = "只允许上传.jpg|.png|.gif类型文件!";
    }
}

2. Proceso de prueba

Cargue un archivo troyano:

imagen-20210320105501703

Usa eructos para capturar paquetes:

imagen-20210320105704726

Se encuentra que el correo pasa la ruta de guardado del archivo.

Pruebe el método de truncamiento% 00:

imagen-20210320110244796

Cambie el hexadecimal 2b de + al hexadecimal 00 de null y presione Enter.

Debido a que la ruta de este archivo de nivel pasa a través de la solicitud de publicación,% 00 no se puede usar directamente, porque el fondo no se decodificará automáticamente, así que agregue 00 en forma hexadecimal.

Antes del cambio Despues del cambio
imagen-20210320110457742 imagen-20210320110524151

imagen-20210320110809631

Una vez colocado el paquete, la carga se realiza correctamente, como se muestra en la figura.

Conéctese con un helicóptero:

imagen-20210320111231939

¡éxito!

resumen:

Este nivel sigue siendo similar al nivel anterior, pero la forma en que se pasa la ruta es diferente, lo que significa que la forma de 00 es diferente. El último nivel es la transmisión GET, por lo que se usa% 00. Este nivel es la transmisión POST, por lo que se usa 00 en forma hexadecimal.

Creo que es posible juzgar si existe la posibilidad de desvío de truncamiento 00. El punto clave es si el usuario puede controlar la ruta donde se guarda el archivo cargado en segundo plano, si es el nombre del archivo o la ruta de guardado pasada por parte del usuario, ya sea que se empalme directamente en la ruta final, si es así, entonces es peligroso.


Supongo que te gusta

Origin blog.csdn.net/qq_43665434/article/details/115024749
Recomendado
Clasificación