miércoles, 6 de julio de 2016

#HSTS. ¿Qué es y cómo lo implanto en mi empresa? Parte 2

Compartir este artículo:
Buenas a todos, en el post de hoy me gustaría continuar la cadena de posts sobre HTTPS, y hoy la iniciaré compartiendo un paper académico titulado "Upgrading HTTPS in mid-air: An empirical study of strict transport security and key pinning", publicado por investigadores de Princeton:

Abstract—We have conducted the first in-depth empirical study of two important new web security features, strict transport security (HSTS) and public-key pinning. Both have been added to the web platform to harden HTTPS, the prevailing standard for secure web browsing. While HSTS is further along, both features still have very limited deployment at a few large websites and a long tail of small security-conscious sites. We find evidence of developers not understanding the correct use of these features, with a substantial portion using them in invalid or illogical ways. We also identify a number of subtle but important errors in practical deployments which often undermine the security these new features are meant to provide. For example, the majority of pinned domains undermine the security benefits by loading non-pinned resources with the ability to hijack the page. A substantial portion of HSTS domains and nearly all pinned domains leaked cookie values, including login cookies, due to the poorly-understood interaction between HTTP cookies and the same-origin policy. Our findings highlight that the web platform, as well as modern web sites, are large and complicated enough to make even conceptually simple security upgrades challenging to deploy in practice. 
En el estudio analizaron un gran número de grandes sitios web de Internet, de los cuales un 35,4%, es decir, 1 de cada 3, no soportaba HSTS (y hablamos de grandes sitios web).




Os dejo la fuente del estudio para que podáis echarle un vistazo:


Volviendo al punto donde nos quedamos la pasada semana, vamos a continuar con más ejemplos de implementaciones de HSTS (vía Wikipedia):


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 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>


Cómo veis, es bastante sencillo de implementar desde el punto de vista técnico, y el mayor problema provendrá de la complejidad de los servicios que precisemos fortificar.

Esto es todo por hoy, nos vemos en el próximo post.

Saludos!

1 comentario:

  1. Aquí un ejemplo de como se haría en node.js con Express:

    app.use(function(req, res, next){
    var valueInSeconds = 10886400;
    res.set('Strict-Transport-Security', 'max-age=' + valueInSeconds + '; includeSubDomains');
    next();
    });

    ResponderEliminar

Related Posts Plugin for WordPress, Blogger...