Ves al contingut principal

Seguretat

Permisos carpetes

La seguretat comença amb la configuració correcta de permisos per al directori on s'emmagatzemaran els fitxers pujats.

  1. Propietat: El directori de destí ha de ser propietat de l'usuari que executa el servidor web (o almenys el grup al qual pertany). En sistemes Linux/Unix, l'usuari sol ser www-data o apache.

  2. Permisos: Cal configurar els permisos de manera que el servidor web pugui escriure i llegir fitxers, però que el risc d'execució de codi maliciós sigui mínim.

    • Permís d'dscriptura (Write - w): És indispensable per a que PHP, que s'executa com l'usuari del servidor web, pugui desar el fitxer temporal.

    • Configuració recomanada: 755 (rwxr-xr-x) o 775 (rwxrwxr-x) si l'usuari del servidor web pertany al grup propietari de la carpeta.

      • chmod 755 /ruta/a/uploads

  3. Seguretat addicional:

    • Ubicació: Si és possible, col·loca el directori d'uploads fora de l'arrel pública del web (public_html o htdocs). Si han de ser accessibles públicament (com les imatges), fes-ho mitjançant un script de descàrrega.

    • Fitxer .htaccess: Si el directori es troba a l'arrel pública, utilitza un fitxer .htaccess per denegar l'execució d'scripts (.php, .phtml, etc.) en aquesta carpeta:

    Fragmento de código

    # Dins de la carpeta d'uploads
    <Files ~ "\.php$">
        Deny from all
    </Files>
    AddHandler default-handler .php .phtml .php3

És molt recomanable col·locar els directoris d'uploads fora de l'arrel pública de l'aplicació web per motius de seguretat.

Per què els uploads han d'estar fora l'arrel pública?

L'arrel pública (sovint anomenada public_html, www o htdocs) és el directori al qual el servidor web dóna accés directe als usuaris a través d'una URL (p. ex., https://elmeudomini.cat/imatge.jpg).

El principal risc d'emmagatzemar fitxers pujats aquí és l'execució de codi maliciós:

  1. Execució directa: Si un atacant aconsegueix pujar un fitxer maliciós amb extensió .php o .phtml, el servidor web (per defecte) l'executarà directament quan l'usuari hi accedeixi per URL. El codi maliciós podria robar dades de l'aplicació, o fins i tot prendre control del servidor.

  2. Omissió de validació: Encara que implementis controls de seguretat al teu codi PHP, algunes configuracions de servidor web o tècniques d'atac (com les dobles extensions, p. ex., virus.php.jpg) poden permetre que el servidor interpreti el fitxer com a codi executable.

  3. Accés incontrolat: Si l'arxiu és fora de l'arrel pública, un usuari malintencionat no pot adreçar-s'hi directament mitjançant una URL. La única manera d'accedir-hi és a través del teu propi script PHP, el qual pot aplicar regles de seguretat, autorització i logging abans de servir el fitxer.

En resum: La separació assegura que el teu codi PHP sigui l'únic intermediari entre l'usuari i el fitxer, permetent aplicar sempre la lògica d'accés i seguretat.

El terme PHTML és una extensió de fitxer que s'utilitza principalment per a fitxers de plantilles (o templates) que contenen una barreja de codi HTML i codi PHP

 

Llavors, com descarregar fitxers?

Per permetre la descàrrega d'aquests fitxers (per exemple, per mostrar una imatge o descarregar un PDF) sense exposar el directori, s'utilitza un script intermediari PHP que llegeix el fitxer i l'envia al navegador. Aquest procés es coneix com a file streaming o descàrrega forçada.

El mecanisme consisteix a utilitzar les capçaleres HTTP per indicar al navegador que el que s'està enviant és un fitxer per a ser descarregat o mostrat amb un tipus MIME específic.

Passos script descàrrega:

  1. Validació i Autenticació:

    • Verificar que l'usuari estigui autenticat i tingui permís per accedir a l'arxiu.

    • Verificar la ruta de l'arxiu per evitar atacs de path traversal (../).

  2. Definir la Ruta:

    • Definir la ruta completa del fitxer al servidor. Aquesta ruta NO ha d'estar accessible per URL.

    PHP

    $file_path = '/ruta/privada/al/directori/uploads/' . $nom_segur_arxiu;
  3. Enviar Capçaleres:

    • El script verifica si el fitxer existeix i, si és així, envia les capçaleres necessàries:

    PHP

    // S'atura la memòria cau per garantir la descàrrega
    header("Pragma: public");
    header("Expires: 0");
    header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
    
    // 1. Capçalera del Tipus de Contingut (MIME)
    // Es recomana detectar el tipus MIME real, p. ex., amb mime_content_type($file_path)
    header("Content-Type: application/octet-stream"); // Tipus genèric per forçar la descàrrega
    
    // 2. Capçalera de Mida
    header("Content-Length: " . filesize($file_path));
    
    // 3. Capçalera de Disposició del Contingut
    // "attachment" força la descàrrega; "inline" mostra el contingut (com una imatge).
    // filename="nom.pdf" estableix el nom que el navegador utilitzarà per al fitxer.
    header('Content-Disposition: attachment; filename="' . basename($nom_segur_arxiu) . '"');
  4. Llegir i Enviar el Contingut:

    • Finalment, es llegeix el contingut del fitxer i s'envia a la sortida (output):

    PHP

    // Bucle per llegir fitxers grans de manera eficient
    readfile($file_path);
    exit;

Així, l'usuari accedeix a una URL com https://elmeudomini.cat/descarrega.php?id=123, i és el script de descarrega.php qui localitza i serveix el fitxer de la zona privada, assegurant que la descàrrega estigui sempre controlada.

Seguretat addicional

Aquests paràmetres es gestionen directament dins el teu codi PHP i són la línia de defensa més important:

  • Validació del fitxer temporal: Abans de cridar move_uploaded_file(), SEMPRE utilitza is_uploaded_file($_FILES['arxiu']['tmp_name']) per assegurar-te que el fitxer prové d'una pujada HTTP vàlida i evitar atacs que intenten moure fitxers arbitraris del sistema.

  • Validació de mida: Comprova que $_FILES['arxiu']['size'] estigui dins d'un rang acceptable definit per l'aplicació (més estricte que el límit de php.ini).

  • Validació de tipus:

    • Tipus MIME: Comprova $_FILES['arxiu']['type']. Tot i que no és infal·lible, és una primera defensa.

    • Extensió: Comprova l'extensió per assegurar que coincideix amb la dels fitxers permesos (e.g., .jpg, .pdf).

    • Inspecció de contingut: Per a fitxers crítics (especialment imatges), utilitza funcions com getimagesize() per verificar que el fitxer sigui realment una imatge vàlida.

  • Renombratge segur: Mai desis el fitxer amb el nom original ($_FILES['arxiu']['name']).

    • Genera un nom d'arxiu únic i aleatori (p. ex., usant uniqid() i/o hash()).

    • Afegeix l'extensió validada (no la de l'usuari) al final. Això evita atacs de path traversal (../..) o l'execució de fitxers maliciosos amb doble extensió (image.jpg.php).

  • Gestió d'errors: Comprova $_FILES['arxiu']['error'] per gestionar problemes com fitxers massa grans (codi 1 o 2), o pujades parcials (codi 3).