Joven hacker sonriendo

Hackeamos su software

cero falsos positivos

Inteligencia experta + automatización eficaz

Verificar extensión y tamaño de archivos

Nuestros ethical hackers explican cómo evitar vulnerabilidades de seguridad mediante la programación segura en ASP.NET al verificar la extensión y el tamaño de los archivos. Para evitar brechas de seguridad es importante realizar validaciones adicionales en los archivos antes de subirlos.

Necesidad

Verificar la extensión y el tamaño de los archivos en ASP.NET.

Contexto

A continuación se describen las circunstancias bajo las cuales la siguiente solución tiene sentido:

  1. Se está desarrollando una aplicación en ASP.NET.

  2. Se desea verificar el tamaño de un archivo antes de usarlo.

  3. Se desea verificar la extensión de un archivo antes de utilizarlo.

Solución

Para programar una aplicación segura y robusta, no basta solo con validar las entradas de la misma. También es necesario realizar procesos de validación y verificación de todos los archivos que de alguna forma interactúan con ella. De esta forma se evita ingresen archivos con contenidos maliciosos o que puedan comprometer de alguna forma la disponibilidad, confidencialidad o integridad del sistema.

En el caso de ASP.NET utilizaremos la clase FileUpload para realizar estas validaciones. Gráficamente la clase FileUpload muestra un cuadro de control de texto y un botón de Examinar que le permite a un usuario seleccionar un archivo y subirlo al servidor [1]. En este artículo abordaremos 3 temas principales: uso básico, validación de tamaño y validación de extensión.

Uso básico

En la siguiente porción de código, se muestra el uso de la clase FileUpload: .example.cs

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
<%@ Page Language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
  <head>
    <title>FileUpload.SaveAs Method Example</title>
    <script runat="server">

      protected void  UploadButton_Click(object sender, EventArgs e) {
        // Before attempting to save the file, verify
        // that the FileUpload control contains a file.
        if (FileUpload1.HasFile)
          // Call a helper method routine to save the file.
          SaveFile(FileUpload1.PostedFile);
        else
          // Notify the user that a file was not uploaded.
          UploadStatusLabel.Text = "You did not specify a file to upload.";
      }

      void SaveFile(HttpPostedFile file) {
        // Specify the path to save the uploaded file to.
        string savePath = "c:\\temp\\uploads\\";

        // Get the name of the file to upload.
        string fileName = FileUpload1.FileName;

        // Create the path and file name to check for duplicates.
        string pathToCheck = savePath + fileName;

        // Create a temporary file name to use for checking duplicates.
        string tempfileName = "";

        // Check to see if a file already exists with the
        // same name as the file to upload.
        if (System.IO.File.Exists(pathToCheck)) {
          int counter = 2;
          while (System.IO.File.Exists(pathToCheck)) {
            // if a file with this name already exists,
            // prefix the filename with a number.
            tempfileName = counter.ToString() + fileName;
            pathToCheck = savePath + tempfileName;
            counter ++;
          }

          fileName = tempfileName;
          // Notify the user that the file name was changed.
          UploadStatusLabel.Text = "A file with the same name already exists." +
                                   "<br />Your file was saved as " + fileName;
        }

        else {
          // Notify the user that the file was saved successfully.
          UploadStatusLabel.Text = "Your file was uploaded successfully.";
        }
        // Append the name of the file to upload to the path.
        savePath += fileName;
        // Call the SaveAs method to save the uploaded
        // file to the specified directory.
        FileUpload1.SaveAs(savePath);
      }
    </script>
  </head>
  <body>
    <h3>FileUpload.SaveAs Method Example</h3>
    <form id="Form1" runat="server">
      <h4>Select a file to upload:</h4>
      <asp:FileUpload id="FileUpload1"
                      runat="server">
      </asp:FileUpload>
      <br /><br />

      <asp:Button id="UploadButton"
                  Text="Upload file"
                  OnClick="UploadButton_Click"
                  runat="server">
       </asp:Button>

      <hr />

      <asp:Label id="UploadStatusLabel"
                 runat="server">
      </asp:Label>
    </form>
  </body>
</html>

Validación de tamaño

Una forma de realizar un ataque de denegación de servicio (DoS) consiste en sobrecargar el servidor con archivos de miles de gigas o teras de contenido. Para evitar esto es necesario limitar el tamaño de los archivos que pueden ser subidos. Por defecto, los controles de la clase FileUpload establecen este límite en 4096 KB (4 MB). Para cambiar el valor por defecto del límite de tamaño de archivo, modifica el valor del atributo maxRequestLength con el tamaño de archivo máximo permitido. Este cambio se aplicará de forma local para la página actual. Si se desea modificar el tamaño máximo permitido a nivel de toda la aplicación es necesario modificar el atributo maxRequestLength en el archivo Web.Config.

Validación de extensión

Para efectuar la validación de extensión de archivos se utilizan diferentes métodos. Uno de los métodos consiste en utilizar expresiones regulares, utilizando clases como RegularExpressionValidator. Sin embargo este método de validación puede ser evadido por atacantes con archivos que tienen las extensiones adecuadas, pero con un contenido que no corresponde con la extensión y en muchos casos puede ser malicioso.

Por ello es recomendable utilizar los encabezados del archivo, detectando el MIME Type del archivo en los datos binarios. Para realizar esto se utilizan funciones como FindMimeFromData o DLLs como urlmon.dll [3]. A continuación se presenta un ejemplo de un algoritmo de validación de extensiones utilizando urlmon.dll:

extvalidation.cs
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
[DllImport(@"urlmon.dll", CharSet = CharSet.Auto)]
private extern static System.UInt32 FindMimeFromData(
  System.UInt32 pBC,
  [MarshalAs(UnmanagedType.LPStr)] System.String pwzUrl,
  [MarshalAs(UnmanagedType.LPArray)] byte[] pBuffer,
  System.UInt32 cbSize,
  [MarshalAs(UnmanagedType.LPStr)] System.String pwzMimeProposed,
  System.UInt32 dwMimeFlags,
  out System.UInt32 ppwzMimeOut,
  System.UInt32 dwReserverd
);

public string getMimeFromFile(string filename) {
  if (!File.Exists(filename))
    throw new FileNotFoundException(filename + " not found");

    byte[] buffer = new byte[256];
    using (FileStream fs = new FileStream(filename, FileMode.Open)) {
      if (fs.Length >= 256)
        fs.Read(buffer, 0, 256);
      else
        fs.Read(buffer, 0, (int)fs.Length);
    }
  try {
    System.UInt32 mimetype;
    FindMimeFromData(0, null, buffer, 256, null, 0, out mimetype, 0);
    System.IntPtr mimeTypePtr = new IntPtr(mimetype);
    string mime = Marshal.PtrToStringUni(mimeTypePtr);
    Marshal.FreeCoTaskMem(mimeTypePtr);
    return mime;
  }
  catch (Exception e) {
    return "unknown/unknown";
  }
}

Descargas

Puedes descargar el código fuente pulsando en el siguiente enlace:




Haz un comentario

Estado de los servicios - Términos de Uso