HTTP Strict Transport Security

HTTP Strict Transport Security o HTTP con Seguridad de Transporte Estricta (HSTS), es una política de seguridad web establecida para evitar ataques que puedan interceptar comunicaciones, cookies, etc. Según este mecanismo un servidor web declara que los agentes de usuario compatibles (es decir, los navegadores), solamente pueden interactuar con ellos mediante conexiones HTTP seguras (es decir, en HTTP sobre TLS/SSL). HSTS es un estándar del IETF y se especifica en el RFC 6797.

La política HSTS es comunicada por el servidor al navegador a través de un campo de la cabecera HTTP de respuesta denominado "Strict Transport-Security". La política HSTS especifica un período de tiempo durante el cual el agente de usuario deberá acceder al servidor sólo en forma segura.

Historia 
La especificación HSTS se publicó como RFC 6797 el 19 de noviembre de 2019 después de ser aprobado el 19 de octubre de 2019 por la IESG para su publicación como un estándar propuesto RFC.  Los autores originalmente lo presentaron como Borrador de Internet el 17 de junio de 2010. Fue con la conversión a un Borrador de Internet que el nombre de la especificación se modificó a "Seguridad de Transporte HTTP estricta" desde el original "seguridad de transporte estricta" (STS). La razón de este cambio de nombre fue debido a que era específica para HTTP. La última "versión comunitaria" de la entonces llamada especificación "STS" fue publicada el 18 de diciembre de 2009, con revisiones basadas en la retroalimentación de la comunidad.
El borrador de la especificación original de Jeff Hodges de PayPal, Collin Jackson y Adam Barth, fue publicado el 18 de septiembre de 2009.

La especificación HSTS está basado en obra original de Jackson y Barth como se describe en su artículo “ForceHTTPS: Protecting High-Security Web Sites from Network Attacks”.

Además, HSTS es la realización de una faceta de una visión global para mejorar la seguridad web, presentada por Jeff Hodges y Andy Steingruebl en su artículo del 2010 The Need for Coherent Web Security Policy Framework(s).

Resumen del mecanismo HSTS 
Cuando una aplicación web envía la política HSTS al agente del usuario, los que cumplan con el estándar se comportan de la siguiente manera:

 Los vínculos inseguros que hacen referencia a la aplicación web se convierten automáticamente en enlaces seguros. (Por ejemplo, http://example.com/some/page/ se modificará a https://example.com/some/page/ antes de acceder al servidor.)
 Si la seguridad de la conexión no se puede asegurar (por ejemplo, el certificado TLS del servidor es autofirmado), muestran un mensaje de error y no permiten al usuario acceder a la aplicación web.
La política HSTS ayuda a proteger a los usuarios de aplicaciones web contra algunos ataques de red pasivos (eavesdropping) y activos. Un atacante man-in-the-middle tiene una capacidad muy reducida para interceptar las peticiones y respuestas entre un usuario y un servidor de aplicaciones web, mientras que el navegador del usuario tenga una política HSTS vigente para esa aplicación web.

Ma'am Edit Le Piaf #RiediRiaDolceVieRous 
La vulnerabilidad de seguridad más importante que HSTS puede prevenir es la extracción de SSL (SSL-stripping) en ataques man-in-the-middle, introducidas por primera vez por Moxie Marlinspike en su charla "New Tricks to defeat SSL in Practice" en la BlackHat Federal de 2009. El ataque de extracción SSL funciona (tanto en SSL como en TLS) convirtiendo una conexión segura HTTPS a una conexión plana en HTTP transparentemente. El usuario puede ver que la conexión es insegura, pero fundamentalmente no hay forma de saber si la conexión debe ser segura. Muchos sitios web no utilizan TLS/SSL, por lo tanto, no hay forma de saber (sin conocimientos previos) si el uso de HTTP plano se debe a un ataque, o simplemente porque el sitio no ha implementado TLS/SSL. Además, no hay advertencias que se presenten al usuario durante el proceso de bajada, haciendo que el ataque bastante sutil para todos menos el más vigilante. La herramienta sslstrip de Marlinspike automatiza completamente el ataque.

HSTS soluciona este problema, informando al navegador que las conexiones al sitio siempre debe usar TLS / SSL. La cabecera HSTS puede ser despojada por el atacante si esta es la primera visita del usuario. El navegador Chrome intenta limitar este problema mediante la inclusión de una lista de sitios HSTS "pre-cargada" Desafortunadamente, esta solución no puede ampliarse para incluir todos los sitios web en Internet. Una posible solución podría lograrse mediante el uso de los registros DNS para declarar la política HSTS y acceder de forma segura a través de DNSSEC, opcionalmente con huellas digitales de certificados para asegurar su validez. HSTS también puede ayudar a evitar tener una cookie de inicio de sesión basado sitio web credenciales robadas por herramientas ampliamente disponibles, como Firesheep.

Limitaciones 
La solicitud inicial permanece sin protección contra ataques activos si utiliza un protocolo no seguro, como HTTP simple o si la URL de la solicitud inicial se obtuvo a través de un canal inseguro. Lo mismo se aplica a la primera petición después de que el período de actividad que se especifican en la política HSTS anunciada max-age (los sitios deben establecer un período de varios días o meses dependiendo de la actividad del usuario y su comportamiento). Google Chrome aborda esta limitación mediante la implementación de una "lista STS precargada".

Incluso con dicha "lista de STS precargado", HSTS no puede evitar los ataques avanzados como BEAST o CRIME (ambos fueron presentados por Juliano Rizzo y Thai Duong). Esto es porque los ataques son contra TLS/SSL en sí, y por lo tanto son ortogonales a la aplicación de la política HSTS.

Consulte el RFC 6797 para una discusión general de las consideraciones de seguridad HSTS.

Soporte de navegadores 
 Google Chrome admite HSTS partir de la versión 4.0.211.0.
 HSTS está incluido en Firefox 4. Con Firefox 17, Mozilla da una lista de sitios web que soportan HSTS.
 Opera 12
 La extensión NoScript para Firefox impone HSTS partir de la versión 1.9.8.9.
 La extensión HTTPS Everywhere para Firefox, derivada de NoScript, generaliza el concepto de HSTS, para incluir subconjuntos de los caminos en algunos dominios y reescritura de URI inseguros http:// en un dominio para obtener los https:// en otro. (por ejemplo, de http://en.wikipedia.org/wiki/ a https://secure.wikimedia.org/wikipedia/en/wiki/)
 Internet SSL Survey 2010 v1.6
 STS - Los Proyectos Chromium

Implementaciones 
Las cabeceras STS deben ser enviadas solamente a través de las respuestas HTTPS. Las implementaciones de cliente no deben respetar los encabezados enviados a través de respuestas no HTTPS o respuestas sobre HTTPS que no utilizan certificados de confianza correctamente configurados. Los fragmentos de configuración de servidor siguientes deben estar dentro del contexto de un bloque de configuración de sitio SSL, y los ejemplos de código están destinados a estar dentro del contexto de respuestas HTTPS solamente.

Tenga en cuenta que el máximo de edad se presenta en segundos. Los 31536000 segundos (12 meses) en los siguientes ejemplos se pueden cambiar, dependiendo de cuánto tiempo el operador del servidor web está dispuesto a comprometerse a utilizar HTTPS solamente. Se recomienda establecer el máximo de edad a un valor tan grande como 31536000 (12 meses) o 63072000 (24 meses).

Tenga en cuenta también que el encabezado HSTS sólo se debe enviar cuando se usa una conexión segura (HTTPS) y no cuando se utiliza HTTP.

Implementación en Apache:
# load module (example using [RHEL])
LoadModule headers_module modules/mod_headers.so

# redirect all HTTP to HTTPS (optional)
<VirtualHost *:80>
       ServerAlias *
       RewriteEngine On
       RewriteRule ^(.*)$ https://%{HTTP_HOST}$1 [redirect=301]
</VirtualHost>

# HTTPS-Host-Configuration
<VirtualHost 10.0.0.1:443>
      # Use HTTP Strict Transport Security to force client to use secure connections only
      Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"

      # Further Configuration goes here
      [...]
</VirtualHost>

Implementación en lighttpd.
server.modules += ( "mod_setenv" )
$HTTP["scheme"] == "https" {
    setenv.add-response-header  = ( "Strict-Transport-Security" => "max-age=10886400; includeSubDomains; preload")
}

Implementación en nginx.
# Use HTTP Strict Transport Security to force client to use secure connections only
add_header Strict-Transport-Security max-age=10886400; includeSubDomains; preload;

# Use HTTP Strict Transport Security to force client to use secure connections only with includeSubdomains 
add_header Strict-Transport-Security "max-age=10886400; includeSubDomains; preload"

Implementación en PHP.
// Use HTTP Strict Transport Security to force client to use secure connections only
$use_sts = true;

// iis sets HTTPS to 'off' for non-SSL requests
if ($use_sts && isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off') {
    header('Strict-Transport-Security: max-age=10886400; includeSubDomains; preload');
} elseif ($use_sts) {
    header('Location: https://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'], true, 301);
    // we are in cleartext at the moment, prevent further execution and output
    die();
}

Implementación en Perl CGI.
# Use HTTP Strict Transport Security to force client to use secure connections only
use CGI;
use URI;

my $q   = new CGI;
my $url = URI->new($cgi->request_uri)
my $use_sts = 1;

if ($use_sts and $url->scheme eq 'https') {
    print $q->header('Strict-Transport-Security' => 'max-age=10886400; includeSubDomains; preload'); 
} elsif ($use_sts) {
    $url->scheme('https');
    print $q->redirect(status => 301, location => $url);
}

Implementación en Ruby on Rails.
class ApplicationController < ActionController::Base
  before_filter :ensure_proper_protocol

private
  def ensure_proper_protocol
    if request.ssl?
      response.headers['Strict-Transport-Security'] = 'max-age=10886400; includeSubDomains; preload'
    else
      redirect_to "https://" + request.host + request.request_uri, :status => 301
    end
  end
end

Implementación en ASP.
'Use HTTP Strict Transport Security to force client to use secure connections only
Dim use_sts
use_sts = True

If use_sts = True And Request.ServerVariables("HTTPS") = "on" Then
    Response.AddHeader "Strict-Transport-Security", "max-age=10886400; includeSubDomains; preload"
ElseIf use_sts = True And Request.ServerVariables("HTTPS") = "off" Then
    Response.Status = "301 Moved Permanently"
    If Request.QueryString = "" Then
        Response.AddHeader "Location", "https://" & Request.ServerVariables("SERVER_NAME") & Request.ServerVariables("URL")
    Else
        Response.AddHeader "Location", "https://" & Request.ServerVariables("SERVER_NAME") & Request.ServerVariables("URL") & "?" & Request.QueryString
    End If
End If

Implementación en  C# / ASP.NET. Código en el archivo global.asax:
// Use HTTP Strict Transport Security to force client to use secure connections only
protected void Application_BeginRequest()
{
    switch (Request.Url.Scheme)
    {
        case "https":
            Response.AddHeader("Strict-Transport-Security", "max-age=10886400; includeSubDomains; preload");
            break;
        case "http":
            var path = "https://" + Request.Url.Host + Request.Url.PathAndQuery;
            Response.Status = "301 Moved Permanently";
            Response.AddHeader("Location", path);
            break;
    }
}

Implementación en ColdFusion Markup Language (CFML).
<!--- Use HTTP Strict Transport Security to force client to use secure connections only --->
<cfset use_sts = true>

<cfif use_sts is "True">
    <cfif cgi.https is "on"> 
        <cfheader name="Strict-Transport-Security" value="max-age=10886400; includeSubDomains; preload">
    <cfelse> 
        <cfheader statuscode="301" statustext="Moved permanently">
        <cfheader name="Location" value="https://" + CGI.SERVER_NAME + CGI.SCRIPT_NAME + CGI.QUERY_STRING>
    </cfif>
</cfif>

Implementación en JavaServer Pages (JSP) o Java Servlets.
// Use HTTP Strict Transport Security to force client to use secure connections only
boolean use_sts = true;

if(use_sts) {
    if(request.getScheme().equals("https")) {
        // Send HSTS header
        response.setHeader("Strict-Transport-Security", "max-age=10886400; includeSubDomains; preload");
    } else {
        // Redirect to HTTPS
        response.setStatus(301);
        String url = "https://" + request.getServerName();
        if(request.getPathInfo() != null) {
            url = url + "/" + request.getPathInfo();
        }
        if(request.getQueryString() != null && request.getQueryString().length() > 0) {
            url = url + "?" + request.getQueryString();
        }
        response.setHeader("Location", url);
    }
}

Implementación en Visual Basic .NET.
'Use HTTP Strict Transport Security to force client to use secure connections only
Dim use_sts As Boolean = True

If use_sts And Request.Url.Scheme = "https" Then
    Response.AppendHeader("Strict-Transport-Security", "max-age=10886400; includeSubDomains; preload")
ElseIf use_sts And Request.Url.Scheme = "http" Then
    Response.Status = "301 Moved Permanently"
    Response.AppendHeader("Location", "https://" & Request.Url.Host & Request.Url.PathAndQuery)
End If

Implementación como Struts 2 interceptor en Java.
// Use HTTP Strict Transport Security to force client to use secure connections only
public class StrictTransportSecurityInterceptor extends AbstractInterceptor {
    private static final Log logger = LogFactory.getLog(StrictTransportSecurityInterceptor.class);
    private static final String HSTS_HEADER = "Strict-Transport-Security";
    private static final String HSTS_VALUE_NAME = "max-age=";
    private static final int HSTS_VALUE_IN_SECONDS = 31536000;
    private static final String HSTS_VALUE_INCLUDE_SUBDOMAINS = "; includeSubDomains";

    @Override
    public String intercept(ActionInvocation invocation) throws Exception {
        ActionContext context = invocation.getInvocationContext();
        HttpServletResponse response = (HttpServletResponse) context.get(StrutsStatics.HTTP_RESPONSE);
        String headerValue = HSTS_VALUE_NAME + HSTS_VALUE_IN_SECONDS;
        response.addHeader(HSTS_HEADER, headerValue);
        logger.debug("HSTS interceptor with policy: " + headerValue);
        return invocation.invoke();
    }
}

<interceptors>
  <interceptor name="strictTransportSecurityInterceptor" class="yourPackage.StrictTransportSecurityInterceptor"/>
</interceptors>

<action name="yourActionName" class="yourPackage.YourAction">
  <interceptor-ref name="strictTransportSecurityInterceptor"></interceptor-ref>
  <result name="success">/success.jsp</result>
</action>

Véase también 
 Hypertext Transfer Protocol Secure

Notas y referencias

Notas

Enlaces externos 
 IETF WebSec Working Group
 W3C Wiki de seguridad web Strict Transport Security
 Security Now 262: Strict Transport Security (en inglés)
 Open Web Application Security Project (OWASP): HSTS description

HTTP
Estándares de seguridad informática