Signal R-Un inciso entre el 3-1 y 3-2

Tras esta cita mía por twitter, para informar de las alusiones en el anterior post a Luis

Está mañana se monta un bonita conversación que por favor no dejes de leer y sobre todo vuelve y sigue leyendo.

https://twitter.com/luisruizpavon/status/436770399620456448

Según el equipo de SignalR no debemos de validar en el servidor y si en cada cliente, copio cita literal de la documentación.

Safely handling input from clients

To ensure that a malicious user does not send script to other users, you must encode all input from clients that is intended for broadcast to other clients. You should encode messages on the receiving clients rather than the server, because your SignalR application may have many different types of clients. Therefore, HTML-encoding works for a web client, but not for other types of clients. For example, a web client method to display a chat message would safely handle the user name and message by calling the html() function.

chat.client.addMessageToPage = function (name, message) {
    // Html encode display name and message. 
    var encodedName = $('<div />').text(name).html();
    var encodedMsg = $('<div />').text(message).html();
    // Add the message to the page. 
    $('#discussion').append('<li><strong>' + encodedName
        + '</strong>:  ' + encodedMsg + '</li>');
};

Lo primero es que me parece un ejemplo malísimo de sanitización, puesto que convertir a texto lo que el usuario me está demandando como texto enriquecido/html es cuando poco saltarte a la torera lo que el usuario espera de tu aplicación, que no es otra cosa que un chat con video,link,imagenes, etc….

Ahora si para curarte lo que haces es matar todas esas funcionalidades como que ….

Es por eso por lo que en el anterior post SignalR 3 de 1 escribí este párrafo.

Es más las herramientas AntiXss de MVC y he buscado y probado alguna que otra o son muy restrictivas o bien alguna que otra cosa se comen el ataque y por tanto siempre estás con el miedo en el cuerpo.

En este caso el ejemplo es eso muy restrictivo, aunque se sigue comiendo el constructor.constructor(alert(1)) y sigo diciendo lo mismo. Que depende de donde hagas el binding será o no peligroso.

Os pongo un ejemplo, absurdo pero que a cualquiera se le puede ocurrir ponerlo en marcha con un dato que dependa de una entrada.

image

Ahora solo tienes que pulsar en cada una de las entradas de tu chat capado de funcionalidades y sanitizado para comerte otro ataque de Fernandito.

Evidentemente que tu eres muy malo, como desarrollador y es por eso por lo que has dejado una puerta abierta que otro está aprovechando, pero nadie te está informando de todos los posibles errores que puedes cometer y como dije es tu obligación y no de SignalR. Solo que me siento contento de haberlo dicho tan claro y tan alto (SIGNALR NO TIENE NINGUNA PROTECCIÓN ANTIXSS Y MVC LA QUE TIENE NO ES BUENA).

Si ya habéis leído la conversación de twitter, yo abogo por hacer esto en el servidor y no en el cliente y os cuento el porque.

El UsuarioA tiene la app en un teléfono y el UsuarioB en un pagina web, según nos recomienda el equipo deberías de sanititzar en el teléfono y en la web y dejar que te entre a tu servidor cualquier tipo de código.

Y en un principio te puede parecer lógico, pero que ocurre si tu chat también tiene la posibilidad de enviar a terceros usuarios fuera de tu organización los mensajes recibidos por correo electrónico, siguiendo con la propuesta del equipo tu estás expandiendo código malicioso sin darte cuenta y que dependerá que el tercer usuario se vea afectado según que aplicación lo está recibiendo.

La preguntas que te deberías de hacer es

1-¿Ese tercero está protegido?

2-¿Conoces las herramientas que utiliza esa otra persona?

3-¿Vas a sanitizar en tres puntos Telefono,Web y Servidor(antes de enviar el mensaje?

No ves más lógico hacerlo en un punto y curarte en salud, pero que ocurre que hacer una librería AntiXss y prevenir todos los casos como poco es costosa y muy difícil de mantener. Y yo en el caso del equipo de SignalR hubiese hecho lo mismo, solo les puedo reprochar que en la página web y al principio en rojo y muy grande ponga

“CUIDADO QUE NO ESTAMOS CUBRIENDO TODOS ESTOS POSIBLES PROBLEMAS”

Conclusiones

Simplemente es una aclaración y que me importa bastante poco lo que me diga una fuente y me da lo mismo su procedencia sin previo análisis de lo que puede ocurrir.

Ya habéis visto que ni siquiera la propuesta es buena (simplemente es un ejemplo dirán algunos,xDDDD).

Y yo respondo si, pero uno que van a copiar seguro miles de personas.

Así que utiliza SignalR como buena herramienta que es y protégete de AntiXss siempre y en el servidor, ya os he puesto un ejemplo donde la propuesta del equipo se queda sin fundamentos.

 

SignalR 3 de 1

A muchos de vosotros os puede parecer gracioso el título y otros muchos pensareis que Pedro se ha equivocado y quería poner como titulo “SignalR 1 de 3”.

Otro buen titulo podría ser “Fernando III y la reconquista de Ubeda” alguno me va a entender

Pues no, no me he equivocado simplemente es que quiero escribir de SignalR al revés y dando prioridad a lo más importante.

Que SignalR es una gran framework, librería,etc magnífico. No se lo voy a discutir a nadie, lo que si voy a discutir es la grandiosidad de una línea y las cosas que pasamos por alto y que a la postre nos pueden hacer más daño del que nos podemos imaginar.

Aclarado el título y demás vamos manos a la obra y para ello que mejor ejemplo que un sistema de notificaciones. Os describo brevemente los requisitos del sistema.

Nuestro gerente nos dice al equipo de programación que todos los miembros de la empresa tienen que tener conocimiento de los movimientos de la competencia en tiempo real. Yo que me declaro “Fernando III(programador oxidado)”

Le digo que fácil no es y que hay que estudiarlo muy detenidamente.

Claro el jefe como buen jefe lo que hace es apretar y apretar hasta que evidentemente salta la voz del programador moderno, ese que todo lo que le cae en sus manos es bueno y magnífico.

Su respuesta es inmediataSonrisa lo hacemos con SignalR y Jquery en dos horas y así cada uno de la empresa puede conocer a la competencia en tiempo real. Que pasa en ese momento, que los programadores oxidados nos ponemos en Sleep(hasta el infinito y dejamos trabajar).

Efectivamente gracias a las bondades de SignalR y Jquery el programador modernista hace lo siguiente.

Un Hub de SignalR, permíteme Luis que coja tu código de este magnifico ejemplo cpu-monitor que me ayudo a decir, voy a mirar SignalR por primera vez. Y también te pido permiso para que lo pueda dejar con este aspecto para ver el ejemplo del post.

image

Que si señores que solo necesito eso a nivel de servidor mas el Startup de Katana/Owin donde indico que quiero trabajar con SignalR.

image

Por último un controlador mvc con una línea y una vista muy sencilla que se encarga de toda la magia.

Metodo del controlador.

image

Vista.

image

Y evidentemente el resultado es el esperado por el más optimista y moderno del equipo.

image

No dos horas, en menos de 10 minutos acabo de montar lo que me comento el gerente y ahora si que tengo claro que me sube el sueldo, vamos ni 50 líneas de código y eso que les parecía de estudio, jejeje ya lo tenemos.

Vamos que no tengo abuela y soy un “Crack”

Después de todas estos logros conseguidos por el “programador moderno” y la conversación con el gerente llega al departamento eufórico y enseñándoselo a todo el mundo.

Ahora empieza el momento de Fernando III, que sin más le dice “chavalote buen trabajo”, luego lo miro.

Lo primero que le llega a la cabeza a “Fernando III” no es otra cosa que probar si SignalR tiene algún tipo de prevención AntiXss y rápidamente se da cuenta que evidentemente no cumple con el patrón “Cuidadín”

No dice otra cosa que tengas prevención por lo que te entra que una vez dentro el mal ya está hecho y poca solución tiene.

Primer principio que no cumple SignalR actúa al contrario, todo lo que llega es bueno y por tanto lo devuelvo. Y siempre será tu obligación validar las entradas, puesto que no existe ningún mecanismo automático, quizá ese no sea su cometido, pero si el tuyo.

Con lo cual que hace en ese momento Fernandito, harto de escuchar todos los días que cosa tras cosa, todo es maravilloso. Rápido va a enviar esta cadena al resto de la empresa y quiere ver que pasa.

 

<a href="data:text/html;base64,

PHNjcmlwdD5hbGVydCgnaG9sYSBzb3kgZmVybmFuZ

Gl0byB5IG5vIHNhYmVzIGxvIHF1ZSB0ZSBoYSBjYWlkbyB

tb2Rlcm5pdG8nKTwvc2NyaXB0Pg==" target="_blank">Una cosa interesante de la competencia</a>

Y que serán esas letras tan raras que ha enviado “Fernandito”, aunque lo vais a ver en vuestros exploradores os lo voy a contar muy resumidamente, que a buen entendedor pocas palabras bastan.

image

Si, SignalR no te dota de ningún mecanismo AntiXss.

Es más las herramientas AntiXss de MVC y he buscado y probado alguna que otra o son muy restrictivas o bien alguna que otra cosa se comen y por tanto siempre estás con el miedo en el cuerpo.

Os animo a que hagáis una prueba con  la siguiente instrucción JavaScript en la  consola de vuestros exploradores y después la pases como parámetro de una url .

constructor.constructor(alert(1))()

Como mínimo la vas a serializar en tu bb.dd y solo depende de donde hagas Binding de esa sentencia JavaScript para que sea o no peligrosa, pero de antemano se pasa en la actualidad un porcentaje muy alto de los filtros AntiXss que he comprobado.

Si a esto le sumamos la tendencia excesiva de uso de token como mecanismo de seguridad en la web frente a cookies, veo una laguna durante cierto tiempo plagada de miedos y de errores muy gordos que pueden comprometer seriamente la seguridad.

Como la serie trata de 3 capítulos os adelanto de que vamos a hablar en los siguientes.

Capitulo 3 de 2. Vamos a ver como ese tipo de ataque lo puedo solucionar con Angularjs aunque jamás lo recomendaré.

Capitulo 3 de 3. Como intuí que SignalR no tenía ningún filtro de protección AntiXss. Y veremos también las diferencias en el cliente entre utilizar Server Send Event y foreverFrame.

Conclusiones.

1. En ningún momento pienses que SignalR es malo, solo piensa en seguridad cuando la utilices.

2.No eres más dichoso por avisar antes, sino por avisar antes y decir las cosas claras, que por ningún sitio he visto esto y hay tenéis la prueba de que no me estoy inventando nada.

 

 

 

 

 

.

JWT(Json Web Token) Cuando?

Sí a alguien esto no le suena a nada, lo primero que le recomendaría sería leer la especificación.

JSON Web Token (JWT)

El objetivo de este post es hacer un breve resumen de lo que es JWT y cuando deberías de utilizarlo.

Lo primero es que no lo veo como un sistema para securizar una api, aunque tengo que reconocer que utilizando “Access control de Azure” lo puedes conseguir.

¿Como yo creo un JWT?

Lo primero es crear un objeto Header básicamente con los siguientes datos, esta claro que lo podéis hacer desde c# o desde el lenguaje donde os sintáis mas felices.

Yo de momento os lo voy a mostrar en Json para no tener que dar vueltas.

{typ:”JWT”,alg:”HS256”}

Sí el token lo emite “Access Control de Azure”  os llega un atributo más que no es otro que el Thumbprint del certificado con las siguientes conversiones y por tanto no encriptaciones.

El Thumprint se muestra como una cadena en Hexadecimal y lo que nos llega es esta convertida a base64UrlEndoced.

Es decir un token desde ACS nos llega así.

{«typ»:»JWT»,»alg»:»RS256″,»x5t»:»LF3aEfMmXEeFkVldf-_WLjVXHHo»}

No voy a entrar de momento a explicar cual es la diferencia en el “alg” puesto que es obvia.

Lo que asusta es encontrarte esto en el Header.

 «x5t»:»LF3aEfMmXEeFkVldf-_WLjVXHHo»

Fácil de resolver búsqueda en Google con los siguientes términos “x5t jwt” y buceando en el siguiente documento JSON Web Token (JWT) – Claims and Signing  nos encontramos con esto.

 

image

Vamos para comérteloSonrisa

The «x5t» (x.509 certificate thumbprint) header parameter provides a base64url encoded SHA-256 thumbprint (a.k.a. digest) of the DER encoding of an X.509 certificate that can be used to match a certificate. This header parameter is OPTIONAL.

Tranquilos, que no pasa nada vamos a utilizar unas sencillos metodos de c# para descubrir esta magia.

Dado el siguiente Thumprint

2C5DDA11F3265C478591595D7FEFD62E35571C7A» vamos a ver como obtenemos esto otro que es lo que nos llega “LF3aEfMmXEeFkVldf-_WLjVXHHo”.

Para ello necesitamos estos helper en c# que nos ayudarán a lo largo del post.

DecodeHesString

image

ConvertHexDigit

image

 

Y por último estos dos métodos sobrecargados para poder convertir a Base64UrlEncode.

image

Sino me he equivocado y después de acceder al certificado que puedes ver desde “Certificados y claves de Acs” y ver esto 2C5DDA11F3265C478591595D7FEFD62E35571C7A podemos ejecutar esta linea en c# y obtener el x5t.

var misterio = Base64UrlEncode( DecodeHexString(«2C5DDA11F3265C478591595D7FEFD62E35571C7A»));

Y la pregunta es ¿Para que se utiliza esto en Acs si es optional el parametro?.

Sencillo, para comprobar que estás validando y no firmando el token JWT con un certificado valido. Es decir el servidor firma con la clave privada y tu validas con la pública, más se hace una comprobación de este dato.

El siguiente paso es jugar con la segunda parte del token y a esto se le llama playload. Mas bien un formato libre donde puede poner una serie de información en el token que después puedo utilizar.

Tenemos que destacar los siguientes claims.

Registered Claim Names

Aparte de estos (Todos OPTIONAL) tu puedes poner los que quieras, más claims evidentemente más información susceptible de ser capturada y por tanto explotada.

Un ejemplo sencillo sería algo como esto.

{«iss»:»joe»,
  «exp»:1300819380,
  «http://example.com/is_root»:true}

Con lo cual una vez conocido el Header y el Playload lo que hacemos es convertir ambos a Base64UrlEncoded que por supuesto no significa más que eso codificar.

Y por tanto fácil de descodificar con lo que obtenemos una serie de caracteres y ambos valores los concatenamos con un “.”

Ejemplo.

eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9
.
eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh

0dHA6Ly9leGFt
cGxlLmNvbS9pc19yb290Ijp0cnVlfQ

Una cosa que nos debe de quedar clara es que esto está codificado y no encriptado, con lo cual es una fuente de información valiosa para obtener email,client-id(Oauth), name, etc,etc.. Es decir cuanto más información incluyas más información expones.

Por último tenemos dos formas de mandar un JWT.

1. PlainText. Simplemtne al final se le agrega un “.” y el algoritmo de encriptación es “node” con lo cual tu token quedaría de la siguiente forma.

Base64UrlEncoded(Header).Base64UrlEndoced(PlayLoad).

En una palabra cualquiera podría reproducir este token a su gusto con poco esfuerzo y os pongo un ejemplo, imaginad por un momento que twitter utilizase esto. Yo hoy soy xxxx y mañana podría ser yyyy y hacer lo que hace yyyy si que el se enterase.

Con lo cual mi recomendación es muy sencilla no se debe de utilizar excepto que sea dentro de tu propia organización sin salir a ningún sitio y te quieras ahorrar el tiempo de encriptar el token.

2. Encrypted JWT.

La forma de generarlo sería igual al anterior pero cumpliendo con el siguiente patrón.

Se cogen los valores devueltos por PlainText  y se codifican con un algoritmo.

HS256,RS256(Recomendado),etc,etc.

Base64UrlEncoded(Header).

Base64UrlEndoced(PlayLoad).

Base64UrlEndoced(hmac(Header+.+PlayLoad))

Vamos a pensar. A partir de este momento cuantos de los algoritmos que se pueden utilizar para encriptación son susceptibles a un ataque del tipo “Force-Brute”. Cuando lo vi por primera vez pensé en esta ecuación de primer grado.

2X=6.

Es decir solo depende de la capacidad de cálculo para que yo sepa cual es tu clave secreta con la que estás firmando los tokens.

Como diría Yoda “Si quieres la luz ver, y conoces dos partes fácil te será encontrar el camino”.

En una palabra, tu no te vas a enterar en la vida que yo voy a hacer un “Force-Brute” puesto que voy a utilizar mi propio token para conocer tu secret key y por tanto poder generar nuevos, siempre que no utilices un certificado.

Ya que en ese caso yo solo conoceré en el caso de Azure(Acs) la clave pública y no la clave secreta, cosa que me va a permitir validar el token y no emitir nuevos tokenSonrisa Bien,Bien…. Pero hasta cuando eso no es vulnerable?

Tuve la suerte de compartir con el amigo @3lcarry la generación de token JWT para integrar nuestro sistema con SalesForce y después integrar con Google Drive.

Ambos utilizan un sistema muy parecido donde después de registrar una app y el administrador dotar a esta de una serie de permisos, tu sin la iteración del usuario puedes hacer cosas en su nombre. Es decir en ningún caso el usuario tiene que autenticarse contra Google o contra SalesForce ni contra ningún proveedor de identidad.

Para entendernos, esas dos plataformas utilizan JWT como mecanismo de autorización Server To Server y ambas me devuelven un token de sesion(access-token) que expira en 3600 segundos y que tienen sus mecanismos de revocación y de refresco enviando un nuevo JWT para obtener un access-.token. Es decir en ningún caso se envia el JWT en la cabecera http.

Lo siguiente que yo me tengo que plantear es como obtengo un “access-token” con los proveedores SalesForce y Google, sencillo se hace un post al servidor desde tu servidor pasando los siguientes parametros.

gran-type:urn:ietf:params:oauth:grant-type:jwt-bearer

assertion:JWT(formado desde tu servidor y enviado a su servidor)

Aparte de esto en la cabecera del post se envía.

Content-Type: application/x-www-form-urlencoded

Vamos que la posiblidad de que alguien sea capaz de generar token haciendo una comunicación Server-To-Server es complicada. Puesto que después de hacer el POST tu ya no trabajas con un JWT sino con un access-token que es igual que un token de Oauth 2.0.

Y ahora la pregunta es porque Azure lo hace diferente, porque te autenticas contra un proveedor de identidad y después de hacer todo el flujo Oauth 2.0 u OpenId en el caso de que el proveedor sea Google. Azure te devuelve un JWT que tu decides pasar a tu Api.

¿Tienes claro que RSA es seguro?

¿Conocidas dos partes podrías descubrir la tercera(clave privada)?

Yo tengo serías dudas de que ha fecha de hoy eso no se pueda obtener.

Con lo cual no me parece un mecanismo acertado utilizar JWT y Acs para aplicaciones web, quizás eso solo está pensado para aplicaciones del tipo Windows 8, Windows Phone y alguno ha malinterpretado su uso, incluso aún siendo para estás dos plataformas, tengo mis miedos, puesto que nadie me impide capturar en ambas el trafico http y por medio de mi token poder generar otros, para otros usuarios. Sigo insistiendo que el firmar el token con un Certificado me está protegiendo de momento, vamos creoSonrisa.

Bueno desmenuzado JWT, sigo pensando exclusivamente en su utilización “SERVER TO SERVER” y con este obtener un access-token  que es el que utilizo en la cabecera de Autorización. Cualquiera puede ser proveedor de JWT.

Podemos inventar lo que se quiera y aplicarlo donde nos plazca, pero acuérdate cada vez que lo pongas en marcha de estas palabras “Force-Brute” o de esta ecuación de primer grado 2x=6.

Repito que luego parece otra cosaSonrisa. El token de ACS excepto que trasmites información delicada del usuario en cada round trip, que es más pesado que un “access-token” y que vas en contra del resto del mundo. Es seguro,hasta donde llegan mis conocimientos para romper una clave privada de un certificado.

Pero aplica la ecuación de primer grado y piensa que tengo mucha información para poder despejar la x y también la necesaria como para saber como se forma PKCS1, lo mismo es cuestión de tiempo.

Otras referencias.

Using OAuth 2.0 for Server to Server Applications

OAuth 2.0 JWT Bearer Token Flow

pure JavaScript implementation of JWT ( JSON Web Token ) and JWS ( JSON Web Signature ) Aquí os podéis divertir un ratoSonrisa.

Cookies vs Tokens. Getting auth right with Angular.JS Yo esto no lo haría en la vida. Si quieres puedes utilizar esto Brute Force c# y probar.

Conclusiones.

Cuando vamos a trabajar como el resto, quizá esté soñando una vez más.