Marco de seguridad: Validación de entrada | Mitigaciones
Deshabilite el scripting XSLT para todas las transformaciones mediante hojas de estilos no de confianza
Título | Detalles |
---|---|
Componente | Aplicación web |
Fase de SDL | Build |
Tecnologías aplicables | Genérico |
Atributos | N/D |
Referencias | Seguridad XSLT, Propiedad XsltSettings.EnableScript |
Pasos | XSLT es compatible con el scripting dentro de hojas de estilos mediante el elemento <msxml:script> . Esto permite que se usen funciones personalizadas en una transformación XSLT. El script se ejecuta en el contexto del proceso que lleva a cabo la transformación. El script XSLT debe estar deshabilitado cuando se encuentra en un entorno que no sea de confianza para evitar la ejecución de código no de confianza. Si usa .NET: El scripting XSLT está deshabilitado de forma predeterminada; sin embargo, debe asegurarse de que no se haya habilitado explícitamente por medio de la propiedad XsltSettings.EnableScript . |
Ejemplo
XsltSettings settings = new XsltSettings();
settings.EnableScript = true; // WRONG: THIS SHOULD BE SET TO false
Ejemplo
Si usa MSXML 6.0, el scripting XSLT está deshabilitado de forma predeterminada. Aún así, tiene que asegurarse de que no se haya habilitado explícitamente por medio de la propiedad AllowXsltScript del objeto DOM XML.
doc.setProperty("AllowXsltScript", true); // WRONG: THIS SHOULD BE SET TO false
Ejemplo
Si usa MSXML 5 o una versión anterior, el scripting XSLT está habilitado de forma predeterminada y debe deshabilitarlo explícitamente. Establezca la propiedad AllowXsltScript del objeto DOM XML en false.
doc.setProperty("AllowXsltScript", false); // CORRECT. Setting to false disables XSLT scripting.
Compruebe que cada página que pueda incluir contenido controlable por el usuario quede excluida del rastreo de MIME automático
Título | Detalles |
---|---|
Componente | Aplicación web |
Fase de SDL | Build |
Tecnologías aplicables | Genérico |
Atributos | N/D |
Referencias | IE8 Security Part V - Comprehensive Protection (Seguridad de IE8 (parte V): Protección completa) |
Pasos | Para cada página que podría incluir contenido controlable por el usuario, debe usar el encabezado HTTP Cada tipo de archivo que se entregue desde un servidor web tiene asociado un tipo MIME (también llamado content-type) que describe la naturaleza del contenido (es decir, imagen, texto, aplicación, etc.). El encabezado X-Content-Type-Options es un encabezado HTTP que permite a los desarrolladores especificar que su contenido no se debe someter a un rastreo de MIME. Este encabezado se ha diseñado para mitigar los ataques de rastreo de MIME. Se agregó compatibilidad con este encabezado en Internet Explorer 8 (IE8). Los únicos que se beneficiarán de X-Content-Type-Options son los usuarios de Internet Explorer 8 (IE8). Las versiones anteriores de Internet Explorer no respetan actualmente el encabezado X-Content-Type-Options. Internet Explorer 8 (y versiones posteriores) es el único explorador importante que implementa una característica para excluir del rastreo de MIME. Cuando otros exploradores importantes (Firefox, Safari, Chrome) implementen características similares, si lo hacen, se actualizará esta recomendación para incluir también la sintaxis de esos exploradores. |
Ejemplo
Para habilitar de forma global el encabezado necesario para todas las páginas de la aplicación, puede realizar una de las siguientes acciones:
- Agregue el encabezado en el archivo Web.config si la aplicación está hospedada con Internet Information Services (IIS) 7.
<system.webServer>
<httpProtocol>
<customHeaders>
<add name=""X-Content-Type-Options"" value=""nosniff""/>
</customHeaders>
</httpProtocol>
</system.webServer>
- Agregue el encabezado mediante el método global Application_BeginRequest
void Application_BeginRequest(object sender, EventArgs e)
{
this.Response.Headers[""X-Content-Type-Options""] = ""nosniff"";
}
- Implemente un módulo HTTP personalizado
public class XContentTypeOptionsModule : IHttpModule
{
#region IHttpModule Members
public void Dispose()
{
}
public void Init(HttpApplication context)
{
context.PreSendRequestHeaders += newEventHandler(context_PreSendRequestHeaders);
}
#endregion
void context_PreSendRequestHeaders(object sender, EventArgs e)
{
HttpApplication application = sender as HttpApplication;
if (application == null)
return;
if (application.Response.Headers[""X-Content-Type-Options ""] != null)
return;
application.Response.Headers.Add(""X-Content-Type-Options "", ""nosniff"");
}
}
- Puede habilitar el encabezado necesario solo para páginas específicas si lo agrega a respuestas individuales:
this.Response.Headers[""X-Content-Type-Options""] = ""nosniff"";
Proteja o deshabilite la resolución de entidades XML
Título | Detalles |
---|---|
Componente | Aplicación web |
Fase de SDL | Build |
Tecnologías aplicables | Genérico |
Atributos | N/D |
Referencias | XML Entity Expansion (Expansión de entidad XML), Ataques por denegación de servicio y defensas XML, Información general de seguridad MSXML, Prácticas recomendadas para proteger el código MSXML, NSXMLParserDelegate Protocol Reference (Referencia del protocolo NSXMLParserDelegate), Resolver recursos externos |
Pasos | Aunque no está generalizada, hay una característica de XML que permite al analizador XML expandir las entidades de macro con valores definidos dentro del propio documento o desde orígenes externos. Por ejemplo, el documento podría definir una entidad "companyname" con el valor "Microsoft", de modo que cada vez que el texto "&companyname;" aparezca en el documento, se reemplaza automáticamente por el texto Microsoft. O bien, el documento podría definir una entidad "MSFTStock" que hace referencia a un servicio web externo para capturar el valor actual de las acciones de Microsoft. A continuación, cada vez que "&MSFTStock;" aparece en el documento, se reemplaza automáticamente por el precio actual de las acciones. Sin embargo, se puede abusar de esta funcionalidad para crear las condiciones para una denegación de servicio (DoS). Un atacante puede anidar varias entidades para crear una bomba XML de expansión exponencial que consuma toda la memoria disponible en el sistema. También puede crear una referencia externa que transmita de vuelta una cantidad infinita de datos o que simplemente bloquee el subproceso. Como resultado, todos los equipos deben deshabilitar por completo la resolución de entidades XML internas o externas si su aplicación no la usa o limitar de forma manual la cantidad de memoria y el tiempo que la aplicación puede consumir para la resolución de entidades si esta funcionalidad es absolutamente necesaria. Si la aplicación no necesita la resolución de entidades, deshabilítela. |
Ejemplo
Para el código de .NET Framework, puede usar los enfoques siguientes:
XmlTextReader reader = new XmlTextReader(stream);
reader.ProhibitDtd = true;
XmlReaderSettings settings = new XmlReaderSettings();
settings.ProhibitDtd = true;
XmlReader reader = XmlReader.Create(stream, settings);
// for .NET 4
XmlReaderSettings settings = new XmlReaderSettings();
settings.DtdProcessing = DtdProcessing.Prohibit;
XmlReader reader = XmlReader.Create(stream, settings);
Tenga en cuenta que el valor predeterminado de ProhibitDtd
en XmlReaderSettings
es true, pero en XmlTextReader
es false. Si usa XmlReaderSettings, no es necesario establecer ProhibitDtd en true de forma explícita, pero se recomienda por seguridad. Tenga en cuenta que la clase XmlDocument permite la resolución de entidades de forma predeterminada.
Ejemplo
Para deshabilitar la resolución de entidades para XmlDocuments, use la sobrecarga XmlDocument.Load(XmlReader)
del método Load y establezca las propiedades adecuadas en el argumento XmlReader para deshabilitar la resolución, como se muestra en el código siguiente:
XmlReaderSettings settings = new XmlReaderSettings();
settings.ProhibitDtd = true;
XmlReader reader = XmlReader.Create(stream, settings);
XmlDocument doc = new XmlDocument();
doc.Load(reader);
Ejemplo
Si no es posible deshabilitar la resolución de entidades para su aplicación, establezca la propiedad XmlReaderSettings.MaxCharactersFromEntities en un valor razonable según las necesidades de su aplicación. Esto limitará el impacto de posibles ataques DoS de expansión exponencial. En el código siguiente se muestra un ejemplo de este enfoque:
XmlReaderSettings settings = new XmlReaderSettings();
settings.ProhibitDtd = false;
settings.MaxCharactersFromEntities = 1000;
XmlReader reader = XmlReader.Create(stream, settings);
Ejemplo
Si tiene que resolver entidades en línea pero no necesita resolver externas, establezca la propiedad XmlReaderSettings.XmlResolver en null. Por ejemplo:
XmlReaderSettings settings = new XmlReaderSettings();
settings.ProhibitDtd = false;
settings.MaxCharactersFromEntities = 1000;
settings.XmlResolver = null;
XmlReader reader = XmlReader.Create(stream, settings);
Tenga en cuenta que en MSXML6, ProhibitDTD está establecido en true (deshabilitar el procesamiento de DTD) de forma predeterminada. Para el código de Apple OSX e iOS, puede usar uno de estos dos analizadores XML: NSXMLParser y libXML2.
Las aplicaciones que usan http.sys realizan la comprobación de canonización de URL
Título | Detalles |
---|---|
Componente | Aplicación web |
Fase de SDL | Build |
Tecnologías aplicables | Genérico |
Atributos | N/D |
Referencias | N/D |
Pasos | Cualquier aplicación que use http.sys debe seguir estas instrucciones:
|
Asegúrese de que los controles adecuados estén en vigor al aceptar archivos de usuarios
Título | Detalles |
---|---|
Componente | Aplicación web |
Fase de SDL | Build |
Tecnologías aplicables | Genérico |
Atributos | N/D |
Referencias | Unrestricted File Upload (Carga de archivos sin restricciones), File Signature Table (Tabla de firmas de archivo) |
Pasos | Los archivos cargados presentan un riesgo notable para las aplicaciones. El primer paso en muchos ataques consiste en incluir código en el sistema que va a sufrir el ataque. Después, el ataque solo necesita encontrar una manera de que se ejecute el código. El uso de la carga de archivos ayuda al atacante a llevar a cabo el primer paso. Las consecuencias de la carga de archivos sin restricciones varían, desde la toma de control de todo el sistema, la sobrecarga del sistema de archivos o la base de datos, o el reenvío de ataques a sistemas back-end hasta una simple alteración. Depende de lo que haga la aplicación con el archivo cargado y especialmente de dónde se almacene. Falta la validación del lado servidor para las cargas de archivos. Se deberían implementar los siguientes controles de seguridad para la funcionalidad de carga de archivos:
|
Ejemplo
En lo que respecta al último punto sobre la validación de la firma de formato del archivo, consulte más detalles en la clase que sigue:
private static Dictionary<string, List<byte[]>> fileSignature = new Dictionary<string, List<byte[]>>
{
{ ".DOC", new List<byte[]> { new byte[] { 0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1 } } },
{ ".DOCX", new List<byte[]> { new byte[] { 0x50, 0x4B, 0x03, 0x04 } } },
{ ".PDF", new List<byte[]> { new byte[] { 0x25, 0x50, 0x44, 0x46 } } },
{ ".ZIP", new List<byte[]>
{
new byte[] { 0x50, 0x4B, 0x03, 0x04 },
new byte[] { 0x50, 0x4B, 0x4C, 0x49, 0x54, 0x55 },
new byte[] { 0x50, 0x4B, 0x53, 0x70, 0x58 },
new byte[] { 0x50, 0x4B, 0x05, 0x06 },
new byte[] { 0x50, 0x4B, 0x07, 0x08 },
new byte[] { 0x57, 0x69, 0x6E, 0x5A, 0x69, 0x70 }
}
},
{ ".PNG", new List<byte[]> { new byte[] { 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A } } },
{ ".JPG", new List<byte[]>
{
new byte[] { 0xFF, 0xD8, 0xFF, 0xE0 },
new byte[] { 0xFF, 0xD8, 0xFF, 0xE1 },
new byte[] { 0xFF, 0xD8, 0xFF, 0xE8 }
}
},
{ ".JPEG", new List<byte[]>
{
new byte[] { 0xFF, 0xD8, 0xFF, 0xE0 },
new byte[] { 0xFF, 0xD8, 0xFF, 0xE2 },
new byte[] { 0xFF, 0xD8, 0xFF, 0xE3 }
}
},
{ ".XLS", new List<byte[]>
{
new byte[] { 0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1 },
new byte[] { 0x09, 0x08, 0x10, 0x00, 0x00, 0x06, 0x05, 0x00 },
new byte[] { 0xFD, 0xFF, 0xFF, 0xFF }
}
},
{ ".XLSX", new List<byte[]> { new byte[] { 0x50, 0x4B, 0x03, 0x04 } } },
{ ".GIF", new List<byte[]> { new byte[] { 0x47, 0x49, 0x46, 0x38 } } }
};
public static bool IsValidFileExtension(string fileName, byte[] fileData, byte[] allowedChars)
{
if (string.IsNullOrEmpty(fileName) || fileData == null || fileData.Length == 0)
{
return false;
}
bool flag = false;
string ext = Path.GetExtension(fileName);
if (string.IsNullOrEmpty(ext))
{
return false;
}
ext = ext.ToUpperInvariant();
if (ext.Equals(".TXT") || ext.Equals(".CSV") || ext.Equals(".PRN"))
{
foreach (byte b in fileData)
{
if (b > 0x7F)
{
if (allowedChars != null)
{
if (!allowedChars.Contains(b))
{
return false;
}
}
else
{
return false;
}
}
}
return true;
}
if (!fileSignature.ContainsKey(ext))
{
return true;
}
List<byte[]> sig = fileSignature[ext];
foreach (byte[] b in sig)
{
var curFileSig = new byte[b.Length];
Array.Copy(fileData, curFileSig, b.Length);
if (curFileSig.SequenceEqual(b))
{
flag = true;
break;
}
}
return flag;
}
Asegúrese de que se usen parámetros con seguridad de tipos en la aplicación web para el acceso a datos
Título | Detalles |
---|---|
Componente | Aplicación web |
Fase de SDL | Build |
Tecnologías aplicables | Genérico |
Atributos | N/D |
Referencias | N/D |
Pasos | Si usa la colección de parámetros, SQL trata la entrada como valor literal en lugar de como código ejecutable. La colección de parámetros se puede usar para aplicar restricciones de tipo y longitud a los datos de entrada. Los valores fuera del intervalo desencadenan una excepción. Si no se usan parámetros SQL con seguridad de tipos, los atacantes podrían ejecutar ataques por inyección que se insertan en la entrada sin filtrar. Use parámetros con seguridad de tipos al construir consultas SQL para evitar posibles ataques por inyección de código SQL que pueden producirse con la entrada sin filtrar. Puede usar parámetros con seguridad de tipos con procedimientos almacenados e instrucciones SQL dinámicas. Los parámetros se tratan como valores literales en la base de datos y no como código ejecutable. También se comprueban el tipo y la longitud de los parámetros. |
Ejemplo
En el código siguiente, se muestra cómo usar parámetros con seguridad de tipos con SqlParameterCollection al llamar a un procedimiento almacenado.
using System.Data;
using System.Data.SqlClient;
using (SqlConnection connection = new SqlConnection(connectionString))
{
DataSet userDataset = new DataSet();
SqlDataAdapter myCommand = new SqlDataAdapter("LoginStoredProcedure", connection);
myCommand.SelectCommand.CommandType = CommandType.StoredProcedure;
myCommand.SelectCommand.Parameters.Add("@au_id", SqlDbType.VarChar, 11);
myCommand.SelectCommand.Parameters["@au_id"].Value = SSN.Text;
myCommand.Fill(userDataset);
}
En el ejemplo de código anterior, el valor de entrada no puede tener más de 11 caracteres. Si los datos no se ajustan al tipo o la longitud definidos en el parámetro, la clase SqlParameter produce una excepción.
Use clases de enlace de modelos distintas o listas de filtros de enlace para evitar la vulnerabilidad de asignación masiva de MVC
Título | Detalles |
---|---|
Componente | Aplicación web |
Fase de SDL | Build |
Tecnologías aplicables | MVC5, MVC6 |
Atributos | N/D |
Referencias | Atributos de metadatos, Public Key Security Vulnerability And Mitigation (Vulnerabilidad de seguridad de clave pública y mitigación), Guía completa para la asignación masiva en ASP.NET MVC, Introducción a EF mediante MVC |
Pasos |
|
Codifique la salida web que no sea de confianza antes de representarla
Título | Detalles |
---|---|
Componente | Aplicación web |
Fase de SDL | Build |
Tecnologías aplicables | Genérico, formularios Web Forms, MVC5, MVC6 |
Atributos | N/D |
Referencias | Impedir el scripting entre sitios en ASP.NET, Scripting entre sitios, Hoja de referencia rápida de prevención de (scripting entre sitios) XSS |
Pasos | El scripting entre sitios (normalmente abreviado como XSS) es un vector de ataque para servicios en línea o cualquier aplicación o componente que consuma una entrada desde la Web. Las vulnerabilidades de XSS pueden permitir que un atacante ejecute un script en la máquina de otro usuario por medio de una aplicación web vulnerable. Los scripts malintencionados sirven para robar cookies y alterar de otras formas la máquina de la víctima mediante JavaScript. Se impide el XSS mediante la validación de la entrada del usuario para asegurarse de que esté bien formada y codificada antes de representarla en una página web. La validación de la entrada y la codificación de la salida se pueden realizar con Web Protection Library. En el código administrado (C#, VB.NET, etc.), use uno o varios métodos de codificación adecuados de Web Protection (Anti-XSS) Library, según el contexto donde se manifieste la entrada del usuario: |
Ejemplo
* Encoder.HtmlEncode
* Encoder.HtmlAttributeEncode
* Encoder.JavaScriptEncode
* Encoder.UrlEncode
* Encoder.VisualBasicScriptEncode
* Encoder.XmlEncode
* Encoder.XmlAttributeEncode
* Encoder.CssEncode
* Encoder.LdapEncode
Lleve a cabo la validación de entrada y el filtrado para todas las propiedades de modelo de tipo cadena
Título | Detalles |
---|---|
Componente | Aplicación web |
Fase de SDL | Build |
Tecnologías aplicables | Genérico, MVC5, MVC6 |
Atributos | N/D |
Referencias | Adding Validation (Incorporación de validación), Validating Model Data in an MVC Application (Validación de datos de modelo en una aplicación de MVC), Principios orientativos para las aplicaciones de ASP.NET MVC |
Pasos | Todos los parámetros de entrada se deben validar antes de usarse en la aplicación para asegurarse de que la aplicación esté protegida ante las entradas de usuarios malintencionados. Compruebe los valores de entrada mediante validaciones con expresiones regulares en el lado servidor con una estrategia de validación con lista de elementos permitidos. La entrada de usuario o los parámetros sin sanear pasados a los métodos pueden ocasionar vulnerabilidades por inyección de código. Para las aplicaciones web, los puntos de entrada también pueden ser campos de formulario, QueryStrings, cookies, encabezados HTTP y parámetros de servicio web. Se deben realizar las siguientes comprobaciones de validación de entrada con el enlace de modelos:
|
Se debería aplicar la comprobación de estado a los campos de formulario que acepten todos los caracteres, por ejemplo, editor de texto enriquecido
Título | Detalles |
---|---|
Componente | Aplicación web |
Fase de SDL | Build |
Tecnologías aplicables | Genérico |
Atributos | N/D |
Referencias | Codificación de la entrada no segura, HTMLSanitizer |
Pasos | Identifique todas las etiquetas de marcado estático que desea usar. Es habitual restringir el formato a elementos HTML seguros, como Antes de escribir los datos, codifíquelos en HTML. Esto anula el peligro de cualquier script malintencionado, ya que hace que se traten como texto y no como código ejecutable.
La página en las referencias deshabilita la validación de solicitudes ASP.NET al establecer HtmlSanitizer es una biblioteca .NET que limpia las construcciones que pueden dar lugar a ataques XSS en fragmentos y documentos HTML. Utiliza AngleSharp para analizar, manipular y representar HTML y CSS. Se puede instalar HtmlSanitizer como paquete NuGet, y se puede pasar la entrada del usuario por los métodos de comprobación de estado de HTML o CSS pertinentes, según corresponda, en el lado servidor. Tenga en cuenta que la comprobación de estado como control de seguridad se debe considerar la última opción. La validación de entrada y la codificación de salida son los controles de seguridad que se consideran mejores. |
No asigne elementos DOM a receptores que carezcan de codificación integrada
Título | Detalles |
---|---|
Componente | Aplicación web |
Fase de SDL | Build |
Tecnologías aplicables | Genérico |
Atributos | N/D |
Referencias | N/D |
Pasos | Muchas funciones JavaScript no codifican de forma predeterminada. Cuando se asigna una entrada que no sea de confianza a elementos DOM mediante estas funciones, es posible que se produzcan ejecuciones de scripts entre sitios (XSS). |
Ejemplo
Los siguientes son ejemplos inseguros:
document.getElementByID("div1").innerHtml = value;
$("#userName").html(res.Name);
return $('<div/>').html(value)
$('body').append(resHTML);
No utilice innerHtml
; en su lugar, use innerText
. Igualmente, en lugar de $("#elm").html()
, use $("#elm").text()
.
Valide que todos los redireccionamientos dentro de la aplicación se cierren o se realicen de forma segura
Título | Detalles |
---|---|
Componente | Aplicación web |
Fase de SDL | Build |
Tecnologías aplicables | Genérico |
Atributos | N/D |
Referencias | The OAuth 2.0 Authorization Framework - Open Redirectors (Marco de autorización OAuth 2.0: redirectores abiertos) |
Pasos | El diseño de aplicaciones que requieren redireccionamiento a una ubicación proporcionada por el usuario debe restringir los destinos de redireccionamiento posibles a una lista predefinida de sitios o dominios "seguros". Todos los redireccionamientos en la aplicación deben ser cerrados y seguros. Para ello, siga estos pasos:
|
Implemente la validación de entrada en todos los parámetros de tipo cadena aceptados por métodos de controlador
Título | Detalles |
---|---|
Componente | Aplicación web |
Fase de SDL | Build |
Tecnologías aplicables | Genérico, MVC5, MVC6 |
Atributos | N/D |
Referencias | Validating Model Data in an MVC Application (Validación de datos de modelo en una aplicación de MVC), Principios orientativos para las aplicaciones de ASP.NET MVC |
Pasos | Para los métodos que solo acepten el tipo primitivo de datos como argumento, pero no modelos, se debe realizar la validación de entrada mediante expresiones regulares. Aquí se debería usar Regex.IsMatch con un patrón de regex válido. Si la entrada no coincide con la expresión regular especificada, el control no debería continuar y se debería mostrar una advertencia adecuada con respecto al error de validación. |
Establezca el tiempo de espera del límite superior para el procesamiento de expresiones regulares con el fin de impedir ataques DoS causados por expresiones regulares incorrectas
Título | Detalles |
---|---|
Componente | Aplicación web |
Fase de SDL | Build |
Tecnologías aplicables | Genérico, formularios Web Forms, MVC5, MVC6 |
Atributos | N/D |
Referencias | Propiedad DefaultRegexMatchTimeout |
Pasos | Para evitar los ataques por denegación de servicio contra expresiones regulares creadas incorrectamente, que causan grandes retrocesos, establezca el tiempo de espera predeterminado global. Si el tiempo de procesamiento es mayor que el límite superior definido, se produce una excepción de tiempo de espera. Si no se configura nada, el tiempo de espera sería infinito. |
Ejemplo
Por ejemplo, la siguiente configuración produce una excepción RegexMatchTimeoutException si el procesamiento excede los 5 segundos:
<httpRuntime targetFramework="4.5" defaultRegexMatchTimeout="00:00:05" />
No use Html.Raw en las vistas Razor
Título | Detalles |
---|---|
Componente | Aplicación web |
Fase de SDL | Build |
Tecnologías aplicables | MVC5, MVC6 |
Atributos | N/D |
Referencias | N/D |
Paso | Las páginas Web ASP.NET (Razor) realizan la codificación de HTML automáticamente. Todas las cadenas impresas por fragmentos de código insertados (bloques @) se codifican en HTML de forma automática. Sin embargo, cuando se invoca el método HtmlHelper.Raw , devuelve marcado que no está codificado en HTML. Si se utiliza el método auxiliar Html.Raw() , omite la protección de codificación automática que proporciona Razor. |
Ejemplo
El siguiente ejemplo es inseguro:
<div class="form-group">
@Html.Raw(Model.AccountConfirmText)
</div>
<div class="form-group">
@Html.Raw(Model.PaymentConfirmText)
</div>
</div>
No utilice Html.Raw()
a menos que necesite mostrar marcado. Este método no realiza la codificación de salida implícitamente. Use otros asistentes de ASP.NET, como @Html.DisplayFor()
.
No use consultas dinámicas en procedimientos almacenados
Título | Detalles |
---|---|
Componente | Base de datos |
Fase de SDL | Build |
Tecnologías aplicables | Genérico |
Atributos | N/D |
Referencias | N/D |
Pasos | Un ataque por inyección de código SQL aprovecha vulnerabilidades en la validación de entrada para ejecutar comandos arbitrarios en la base de datos. Puede suceder cuando la aplicación usa una entrada para construir instrucciones SQL dinámicas para acceder a la base de datos. También puede producirse si el código usa procedimientos almacenados a los que se pasan cadenas que contienen entrada de usuario sin procesar. Mediante un ataque por inyección de código SQL, el atacante puede ejecutar comandos arbitrarios en la base de datos. Todas las instrucciones SQL (incluidas las que se encuentran en procedimientos almacenados) deben estar parametrizadas. Las instrucciones SQL parametrizadas aceptarán caracteres que tengan un significado especial en SQL (por ejemplo, las comillas simples) sin problemas porque están fuertemente tipadas. |
Ejemplo
El ejemplo siguiente es de un procedimiento almacenado dinámico inseguro:
CREATE PROCEDURE [dbo].[uspGetProductsByCriteria]
(
@productName nvarchar(200) = NULL,
@startPrice float = NULL,
@endPrice float = NULL
)
AS
BEGIN
DECLARE @sql nvarchar(max)
SELECT @sql = ' SELECT ProductID, ProductName, Description, UnitPrice, ImagePath' +
' FROM dbo.Products WHERE 1 = 1 '
PRINT @sql
IF @productName IS NOT NULL
SELECT @sql = @sql + ' AND ProductName LIKE ''%' + @productName + '%'''
IF @startPrice IS NOT NULL
SELECT @sql = @sql + ' AND UnitPrice > ''' + CONVERT(VARCHAR(10),@startPrice) + ''''
IF @endPrice IS NOT NULL
SELECT @sql = @sql + ' AND UnitPrice < ''' + CONVERT(VARCHAR(10),@endPrice) + ''''
PRINT @sql
EXEC(@sql)
END
Ejemplo
Este es el mismo procedimiento almacenado pero implementado de forma segura:
CREATE PROCEDURE [dbo].[uspGetProductsByCriteriaSecure]
(
@productName nvarchar(200) = NULL,
@startPrice float = NULL,
@endPrice float = NULL
)
AS
BEGIN
SELECT ProductID, ProductName, Description, UnitPrice, ImagePath
FROM dbo.Products where
(@productName IS NULL or ProductName like '%'+ @productName +'%')
AND
(@startPrice IS NULL or UnitPrice > @startPrice)
AND
(@endPrice IS NULL or UnitPrice < @endPrice)
END
Asegúrese de que se lleve a cabo la validación del modelo en métodos de API web
Título | Detalles |
---|---|
Componente | API Web |
Fase de SDL | Build |
Tecnologías aplicables | MVC5, MVC6 |
Atributos | N/D |
Referencias | Validación de modelos en ASP.NET Web API |
Pasos | Cuando un cliente envía datos a una API web, es obligatorio que valide los datos antes de realizar cualquier procesamiento. Para las API web de ASP.NET, cuando aceptan modelos como entrada, utilice anotaciones de datos en los modelos para establecer reglas de validación en las propiedades del modelo. |
Ejemplo
El código siguiente lo demuestra:
using System.ComponentModel.DataAnnotations;
namespace MyApi.Models
{
public class Product
{
public int Id { get; set; }
[Required]
[RegularExpression(@"^[a-zA-Z0-9]*$", ErrorMessage="Only alphanumeric characters are allowed.")]
public string Name { get; set; }
public decimal Price { get; set; }
[Range(0, 999)]
public double Weight { get; set; }
}
}
Ejemplo
En el método de acción de los controladores de API, la validez del modelo se debe comprobar explícitamente como se muestra a continuación:
namespace MyApi.Controllers
{
public class ProductsController : ApiController
{
public HttpResponseMessage Post(Product product)
{
if (ModelState.IsValid)
{
// Do something with the product (not shown).
return new HttpResponseMessage(HttpStatusCode.OK);
}
else
{
return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
}
}
}
}
Implemente la validación de entrada en todos los parámetros de tipo cadena aceptados por métodos de API web
Título | Detalles |
---|---|
Componente | API Web |
Fase de SDL | Build |
Tecnologías aplicables | Genérico, MVC 5, MVC 6 |
Atributos | N/D |
Referencias | Validating Model Data in an MVC Application (Validación de datos de modelo en una aplicación de MVC), Principios orientativos para las aplicaciones de ASP.NET MVC |
Pasos | Para los métodos que solo acepten el tipo primitivo de datos como argumento, pero no modelos, se debe realizar la validación de entrada mediante expresiones regulares. Aquí se debería usar Regex.IsMatch con un patrón de regex válido. Si la entrada no coincide con la expresión regular especificada, el control no debería continuar y se debería mostrar una advertencia adecuada con respecto al error de validación. |
Asegúrese de que se usen parámetros con seguridad de tipos en la API web para el acceso a datos
Título | Detalles |
---|---|
Componente | API Web |
Fase de SDL | Build |
Tecnologías aplicables | Genérico |
Atributos | N/D |
Referencias | N/D |
Pasos | Si usa la colección de parámetros, SQL trata la entrada como valor literal en lugar de como código ejecutable. La colección de parámetros se puede usar para aplicar restricciones de tipo y longitud a los datos de entrada. Los valores fuera del intervalo desencadenan una excepción. Si no se usan parámetros SQL con seguridad de tipos, los atacantes podrían ejecutar ataques por inyección que se insertan en la entrada sin filtrar. Use parámetros con seguridad de tipos al construir consultas SQL para evitar posibles ataques por inyección de código SQL que pueden producirse con la entrada sin filtrar. Puede usar parámetros con seguridad de tipos con procedimientos almacenados e instrucciones SQL dinámicas. Los parámetros se tratan como valores literales en la base de datos y no como código ejecutable. También se comprueban el tipo y la longitud de los parámetros. |
Ejemplo
En el código siguiente, se muestra cómo usar parámetros con seguridad de tipos con SqlParameterCollection al llamar a un procedimiento almacenado.
using System.Data;
using System.Data.SqlClient;
using (SqlConnection connection = new SqlConnection(connectionString))
{
DataSet userDataset = new DataSet();
SqlDataAdapter myCommand = new SqlDataAdapter("LoginStoredProcedure", connection);
myCommand.SelectCommand.CommandType = CommandType.StoredProcedure;
myCommand.SelectCommand.Parameters.Add("@au_id", SqlDbType.VarChar, 11);
myCommand.SelectCommand.Parameters["@au_id"].Value = SSN.Text;
myCommand.Fill(userDataset);
}
En el ejemplo de código anterior, el valor de entrada no puede tener más de 11 caracteres. Si los datos no se ajustan al tipo o la longitud definidos en el parámetro, la clase SqlParameter produce una excepción.
Uso de consultas SQL parametrizadas con Azure Cosmos DB
Título | Detalles |
---|---|
Componente | Azure DocumentDB |
Fase de SDL | Build |
Tecnologías aplicables | Genérico |
Atributos | N/D |
Referencias | Announcing SQL Parameterization in Azure Cosmos DB (Anuncio de la parametrización de SQL en Azure Cosmos DB) |
Pasos | Aunque Azure Cosmos DB únicamente admite consultas de solo lectura, todavía es posible inyectar código SQL si las consultas se crean mediante la concatenación con la entrada del usuario. Es posible que un usuario obtenga acceso a datos a los que no debería acceder dentro de la misma colección mediante el diseño de consultas SQL malintencionadas. Use consultas SQL parametrizadas si las consultas se construyen tomando como base la entrada del usuario. |
Validación de entrada de WCF mediante enlaces de esquema
Título | Detalles |
---|---|
Componente | WCF |
Fase de SDL | Build |
Tecnologías aplicables | Genérico, .NET Framework 3 |
Atributos | N/D |
Referencias | MSDN |
Pasos | La falta de validación conlleva diferentes tipos de ataque por inyección. La validación de mensajes constituye una línea de defensa para la protección de la aplicación WCF. Con este enfoque, se validan los mensajes mediante esquemas para proteger las operaciones del servicio WCF frente al ataque de un cliente malintencionado. Valide todos los mensajes recibidos por el cliente para protegerlo frente al ataque de un servicio malintencionado. La validación de mensajes permite validar mensajes cuando las operaciones consumen contratos de mensaje o de datos, algo que no se puede llevar a cabo mediante la validación de parámetros. La validación de mensajes le permite crear lógica de validación dentro de esquemas, lo cual proporciona más flexibilidad y reduce el tiempo de desarrollo. Los esquemas se pueden reutilizar en distintas aplicaciones dentro de la organización y así crear estándares para la representación de datos. Además, la validación de mensajes permite proteger las operaciones cuando consumen tipos de datos más complejos con contratos que representan lógica de negocios. Para realizar la validación de mensajes, primero cree un esquema que represente las operaciones del servicio y los tipos de datos consumidos por esas operaciones. Después, cree una clase .NET que implemente un inspector de mensajes de cliente personalizado y un inspector de mensajes de distribuidor personalizado para validar los mensajes enviados al servicio o recibidos desde él. A continuación, implemente un comportamiento de punto de conexión personalizado para habilitar la validación de mensajes en el cliente y el servicio. Por último, implemente un elemento de configuración personalizado en la clase que permita exponer el comportamiento de punto de conexión personalizado extendido en el archivo de configuración del servicio o el cliente. |
Validación de entrada de WCF mediante inspectores de parámetros
Título | Detalles |
---|---|
Componente | WCF |
Fase de SDL | Build |
Tecnologías aplicables | Genérico, .NET Framework 3 |
Atributos | N/D |
Referencias | MSDN |
Pasos | La validación de datos y de entrada constituye una importante línea de defensa para la protección de la aplicación WCF. Debería validar todos los parámetros expuestos en las operaciones del servicio WCF para proteger el servicio frente al ataque de un cliente malintencionado. A la inversa, debería validar todos los valores devueltos recibidos por el cliente para protegerlo frente al ataque de un servicio malintencionado. WCF proporciona diferentes puntos de extensibilidad que permiten personalizar el comportamiento en tiempo de ejecución de WCF mediante la creación de extensiones personalizadas. Los inspectores de mensajes y de parámetros son dos mecanismos de extensibilidad que se usan para ejercer un mayor control sobre los datos que pasan entre un cliente y un servicio. Debería usar inspectores de parámetros para la validación de entrada e inspectores de mensajes solo cuando necesite inspeccionar el mensaje completo que fluye dentro y fuera de un servicio. Para llevar a cabo la validación de entrada, generará una clase .NET e implementará un inspector de parámetros personalizado para validar los parámetros en las operaciones de su servicio. Después, implementará un comportamiento de punto de conexión personalizado para habilitar la validación tanto en el cliente como en el servicio. Por último, implementará un elemento de configuración personalizado en la clase que permita exponer el comportamiento de punto de conexión personalizado extendido en el archivo de configuración del servicio o del cliente. |