Uploader PHP [Vulnerabilidad]
Muy buenas, en este caso vengo a explicar como se puede explotar una vulnerabilidad en un upload.php. Hay más información sobre esto en el foro, pero lo que he visto o es en video o no está explicado como a mi me gustaría que me lo explicaran.
Lo primero que tenemos que saber es que es un uploader en php.
Un uploader en php es un código que nos va a permitir subir un archivo a una página web.
En este caso nuestro código de prueba vulnerable va a ser el siguiente (El codigo no es propio, es este modificado).
- <html>
- <head>
- <style type="text/css">
- .upload{
- background:#e7e7e7;
- box-shadow:0px 0px 10px black;
- width:500px;
- height:200px;
- margin-right:auto;
- margin-left:auto;
- border-radius:20px;
- }
- form{
- margin: 126px auto 0;
- width: 225px;
- }
- label{
- display: block;
- }
- input[type="file"]{
- display: block;
- margin: 8px 0;
- }
- div.resultado{
- margin: 25px auto 0;
- width: 225px;
- }
- div.resultado img{
- border: 2px solid #EEEEEE;
- height: auto;
- width: 225px;
- }
- </style>
- </head>
- <body>
- <div class="upload">
- <form action="" method="post" enctype="multipart/form-data">
- <br><br>Sube un archivo:
- <input type="file" name="archivo" id="archivo" /> <br>
- <input type="submit" name="boton" value="Subir" />
- </form>
- <div>
- <div class="resultado">
- <?php
- // Hacemos una condicion en la que solo permitiremos que se suban imagenes y que sean menores a 20 KB
- if ((true==true) && ($_FILES["archivo"]["size"] < 200000000)) {
- //Si es que hubo un error en la subida, mostrarlo, de la variable $_FILES podemos extraer el valor de [error], que almacena un valor booleano (1 o 0).
- if ($_FILES["archivo"]["error"] > 0) {
- echo $_FILES["archivo"]["error"] . "<br />";
- } else {
- // Si no hubo ningun error, hacemos otra condicion para asegurarnos que el archivo no sea repetido
- echo $_FILES["archivo"]["name"] . " ya existe. ";
- } else {
- // Si no es un archivo repetido y no hubo ningun error, procedemos a subir a la carpeta /archivos, seguido de eso mostramos la imagen subida
- "archivos/" . $_FILES["archivo"]["name"]);
- echo "Archivo Subido <br />";
- echo "<img src='archivos/".$_FILES["archivo"]["name"]."' />";
- }
- }
- } else {
- echo "Archivo no permitido";
- }
- }
- ?>
- </div>
- </body>
- </html>
Este código nos deja subir archivos de cualquier extensión y aquí es donde nosotros nos vamos a aprovechar. En este caso yo voy a subir una shell c99.php, que es muy intuitiva de manejar.
Ya solo nos quedaría ir al directorio está el archivo malicios, en este caso: "/archivos/c99.php".
Dejo aquí una foto de la shell. El funcionamiento como digo es muy intuitivo.
(Ya se que tengo que activar Windows xD)
Ahora voy a mostrar un filtro que NO DEBÉIS USAR y como hacer un bypass, es decir, saltarse el filtro.(Despues mostrare el filtro final).
- <html>
- <head>
- <style type="text/css">
- .upload{
- background:#e7e7e7;
- box-shadow:0px 0px 10px black;
- width:500px;
- height:200px;
- margin-right:auto;
- margin-left:auto;
- border-radius:20px;
- }
- form{
- margin: 126px auto 0;
- width: 225px;
- }
- label{
- display: block;
- }
- input[type="file"]{
- display: block;
- margin: 8px 0;
- }
- div.resultado{
- margin: 25px auto 0;
- width: 225px;
- }
- div.resultado img{
- border: 2px solid #EEEEEE;
- height: auto;
- width: 225px;
- }
- </style>
- </head>
- <body>
- <div class="upload">
- <form action="" method="post" enctype="multipart/form-data">
- <br><br>Sube un archivo:
- <input type="file" name="archivo" id="archivo" /> <br>
- <input type="submit" name="boton" value="Subir" />
- </form>
- <div>
- <div class="resultado">
- <?php
- // Hacemos una condicion en la que solo permitiremos que se suban imagenes y que sean menores a 20 KB
- if ((($_FILES["archivo"]["type"] == "image/gif") ||
- ($_FILES["archivo"]["type"] == "image/jpeg") ||
- ($_FILES["archivo"]["type"] == "image/pjpeg")) &&
- ($_FILES["archivo"]["size"] < 20000)) {
- //Si es que hubo un error en la subida, mostrarlo, de la variable $_FILES podemos extraer el valor de [error], que almacena un valor booleano (1 o 0).
- if ($_FILES["archivo"]["error"] > 0) {
- echo $_FILES["archivo"]["error"] . "<br />";
- } else {
- // Si no hubo ningun error, hacemos otra condicion para asegurarnos que el archivo no sea repetido
- echo $_FILES["archivo"]["name"] . " ya existe. ";
- } else {
- // Si no es un archivo repetido y no hubo ningun error, procedemos a subir a la carpeta /archivos, seguido de eso mostramos la imagen subida
- "archivos/" . $_FILES["archivo"]["name"]);
- echo "Archivo Subido <br />";
- echo "<img src='archivos/".$_FILES["archivo"]["name"]."' />";
- }
- }
- } else {
- echo "Archivo no permitido";
- }
- }
- ?>
- </div>
- </body>
- </html>
Si os fijáis en estas lineas:
- if ((($_FILES["archivo"]["type"] == "image/gif") ||
- ($_FILES["archivo"]["type"] == "image/jpeg") ||
- ($_FILES["archivo"]["type"] == "image/pjpeg")) &&
- ($_FILES["archivo"]["size"] < 20000))
Lo que hace el php es comprobar el content type del archivo y no comprueba la terminación del archivo (si es php, html, etc). Para saltarte este filtro lo que hay que hacer es lo siguiente:
1º Hay que descargarse firefox, ya que vamos a usar una herramienta de firefox para esta prueba.
2º Hay que renombrar el archivo c99.php a c99.jpg, ya que es un tipo de los archivos que nos permite subir este uploader.
3º En la web le damos a examinar y ponemos nuestro archivo c99.jpg (NO LE DAMOS A SUBIR TODAVIA). Tiene que quedar asi.
4º Iniciamos Tamper Data. (Está en el menú de arriba en la barra de herramientas).
5º Le damos a comenzar modificación.
6º Ya podemos darle a enviar el archivo, nos saldra una pantallita y le tenemos que dar a modificar.
7º Entonces nos saldrá otra pantalla y tenemos que modificar el código de la derecha.
En ese código hay que buscar algo de este estilo.
filename="c99.jpg"\r\nContent-Type: image/jpeg\r\n\r\n
Y cambiar "c99.jpg" por c99.php. Le das a enviar y listo.
Esto saltará el filtro ya que aunque estas subiendo el archivo con la terminación
.php el content type es de un jpg, y el código del upload comprueba el content
type y no la terminación.
Por último una forma de arreglar esto sería añadir estas líneas.
El código ha sido editado porque como decía @seth seguía siendo vulnerable.
- foreach ($blacklist as $item) {
- echo "No se permiten archivos PHP";
- exit;
- }
- }
Con lo que el código final quedaría así.
- <html>
- <head>
- <style type="text/css">
- .upload{
- background:#e7e7e7;
- box-shadow:0px 0px 10px black;
- width:500px;
- height:200px;
- margin-right:auto;
- margin-left:auto;
- border-radius:20px;
- }
- form{
- margin: 126px auto 0;
- width: 225px;
- }
- label{
- display: block;
- }
- input[type="file"]{
- display: block;
- margin: 8px 0;
- }
- div.resultado{
- margin: 25px auto 0;
- width: 225px;
- }
- div.resultado img{
- border: 2px solid #EEEEEE;
- height: auto;
- width: 225px;
- }
- </style>
- </head>
- <body>
- <div class="upload">
- <form action="" method="post" enctype="multipart/form-data">
- <br><br>Sube un archivo:
- <input type="file" name="archivo" id="archivo" /> <br>
- <input type="submit" name="boton" value="Subir" />
- </form>
- <div>
- <div class="resultado">
- <?php
- foreach ($blacklist as $item) {
- echo "No se permiten archivos PHP";
- exit;
- }
- }
- // Hacemos una condicion en la que solo permitiremos que se suban imagenes y que sean menores a 20 KB
- if ((($_FILES["archivo"]["type"] == "image/gif") ||
- ($_FILES["archivo"]["type"] == "image/jpeg") ||
- ($_FILES["archivo"]["type"] == "image/pjpeg")) &&
- ($_FILES["archivo"]["size"] < 200000000)) {
- //Si es que hubo un error en la subida, mostrarlo, de la variable $_FILES podemos extraer el valor de [error], que almacena un valor booleano (1 o 0).
- if ($_FILES["archivo"]["error"] > 0) {
- echo $_FILES["archivo"]["error"] . "<br />";
- } else {
- // Si no hubo ningun error, hacemos otra condicion para asegurarnos que el archivo no sea repetido
- echo $_FILES["archivo"]["name"] . " ya existe. ";
- } else {
- // Si no es un archivo repetido y no hubo ningun error, procedemos a subir a la carpeta /archivos, seguido de eso mostramos la imagen subida
- "archivos/" . $_FILES["archivo"]["name"]);
- echo "Archivo Subido <br />";
- echo "<img src='archivos/".$_FILES["archivo"]["name"]."' />";
- }
- }
- } else {
- echo "Archivo no permitido";
- }
- }
- ?>
- </div>
- </body>
- </html>
-------------------------
Post escrito por: @RoloMijan
Twitter: https://twitter.com/RoloMijan
0 Comentarios