[Resuelto]: Alternativa a una solución de escapar comillas simples y dobles

Iniciado por Leguim, 31 Julio 2020, 00:17 AM

0 Miembros y 1 Visitante están viendo este tema.

Leguim

Cita de: MinusFour en 31 Julio 2020, 03:42 AM
El punto es que no debería haber comillas en los hashes. Así que tu función no hace nada.

No entiendo que me querés decir.

MinusFour

Cita de: MiguelCanellas en 31 Julio 2020, 04:04 AM
No entiendo que me querés decir.

Usuario viene con contraseña: ´´"'´´"'

Tu, como administrador responsable, no utilizas la contraseña del usuario para nada y corres una función hash para obtener algo como:

$2y$10$.vGA1O9wmRjrwAVXD98HNOgsNpDczlqm3Jq7KnEd1rVAGv3Fykk1a

La cual no tiene ningún apostrofe, acento o comillas. Así que tu función que remplaza comillas... no hace nada.

Leguim

Cita de: MinusFour en 31 Julio 2020, 04:53 AM
Usuario viene con contraseña: ´´"'´´"'

Tu, como administrador responsable, no utilizas la contraseña del usuario para nada y corres una función hash para obtener algo como:

$2y$10$.vGA1O9wmRjrwAVXD98HNOgsNpDczlqm3Jq7KnEd1rVAGv3Fykk1a

La cual no tiene ningún apostrofe, acento o comillas. Así que tu función que remplaza comillas... no hace nada.

Tenes razón, igual quiero aclarar que yo no iba a reemplazar las comillas si se trataba de una contraseña. Solamente verificaba y no lo dejaba continuar si enviaba las comillas.

Claro con el cifrado ya se van las comillas y no hace falta, me ahorro un paso innecesario.

Gracias!

WHK

Las buenas prácticas dicen que no debes escapar ningun caracter de entrada, solo los de salida o de envío.

Cada lugar utiliza su propia secuencia de escape de caracteres, el agregar backslash a caracteres especiales no es "porque si", es un estándar definido para evitar vulnerabilidades y que todo funcione bien, pero no todos los estandares y secuencias de escape son iguales.

Lo primero es lo primero, hay que saber que no se deben abusar de los backslash o reemplazo de comillas cuando no se requiera por un estandar a modo de secuencia de escape, por ejemplo:

SQL utliza como secuencia de escape el backslash, asi que si haces una consulta sql manual desde php no debes hacer un reemplazo de caracteres manualmente, para eso existe mysql_real_escape_strting(), HTML utiliza como secuencia de escapes el htmlentities, asi que cuando vayas a exponer contenido sobre HTML debes utilizar la secuencia de escape que viene integrado con php que es htmlspecialchars() y ENT_QUOTES, si vas a incrustar contenido dentro de variables de javascript de manera dinámica debes utilizar la secuencia de escape de caracteres de ecmascript que son los caracteres unicode \u0000 o hexadecimales de tipo \x00 o backslash, pero ojo, en javascript la secuencia de escape no es la misma que la de un sql, no todo se arregla con un backslash, por ejemplo, puedes tener un xss con un simple salto de línea y no lo podrás escapar con un backslash, para eso ya existen funciones que escapan los caracteres especiales.

Una secuencia de escape de caracteres está diseñado por lo general para lenguajes interpretables como bash scripting, php, javascript, html, etc, y estas secuencias impiden conflictos de rompimiento de cadenas, esto provoca una inyección, por ejemplo:

Digamos que tengo esta frase: "Mi nombre es: $nombre y mi apellido es $apellido", entonces, que sucede si en nombre pongo: "nombre y mi apellido es x", entonces la frase quedaría así: "Mi nombre es: nombre y mi apellido es x y mi apellido es $apellido", ves? he inyectado dos apellidos porque no existía un delimitador en la palabra nombre ni en apellido, entonces para evitar estas situaciones existen las secuencias de escapes, por ejemplo, en este caso puedo añadir un - entre cada espacio en blanco, entonces quedaría asi: "Mi nombre es: nombre-y-mi-apellido-es-x y mi apellido es $apellido". Como puedes ver, ahora si se puede diferenciar el nombre del apellido real.

Con los lenguajes de programación sucede lo mismo, si en SQL los valores de tipo texto están encerrados en comillas, entonces como puedes ingresar una comilla como valor? esta rompería la cadena de cierre e inyectarías instrucciones sql, para eso se antepone un backslash, para asegurarse que quieres ingresar una comilla como valor y no rompa la cadena. En HTML pasa lo mismo, si quieres que se  vea una etiqueta html no la escribes tal cual o el navegador la interpretará, para eso existen los htmlentities, sino, inyectarás código html provocando un xss.

En resumidas, no debes agregar backslash asi porque si a cualquier texto o reemplazar caracteres, para eso existen los estandares y si agregas caracteres donde no debes puedes abrir problemas de seguridad, los backslash no se usan porque si, se usan para evitar rompimiento de cadenas y en cada lenguaje o situación el escape es distinto y en cada caso existen funciones nativas que te ayudan a hacer esos escapes.

Por ejemplo, digamos que quieres insertar una cadena de texto de manera dinámica dentro de una etiqueta script en html, debes uilizar dos tipos de secuencia de escape distintos, debes utilizar escape para html y para javascipt potqe javascript estará dentro de html:

<script>var cadena = '$cadena';</script>

Primeramente $cadena debe estar escapado para javascript, el cual debe evitar todo caracter especial y ser reemplazado por valores en hexadecimales, luego de eso debe ser escapado en htmlentities para evitar una inyeccion en html (aunque no se pueda inyectar debido a la transformación de caracteres especiales en hexadecimal pero es por buena práctica). Por ejemplo:

<script>
for(var i = 0; &lt;= 100; i++){
   var cadena = '\x0C\x3ch1\x3e Texto';
}
</script>


Como puedes ver, la cadena de texto contiene salto de línea y caracteres html y fueron escapados, pero si te fijas tambien, el for de javascript debiera decir "<=" pero está escapado en htmlentities debido a que el código que se encuentra dentro de la etiqueta <script> debe ser interpretada por el motor que interpreta html y luego que decodifica su contenido lo evaluará como código javascript. Que de todas maneras funcione sin escapar no quiere decir que sea correcto, para ello los navegadores web utilizan una tecnología llamada "tolerancia a errores", eso quiere decir que cuando deben interpretar el código lo corrigen de manera automática dentro de lo posible y luego lo pasan a memoria, por ejemplo, si escribes una etiqueta sin cerrar en xhtml esta se toma como inválido pero el navegador lo muestra de todas maneras, pero hablando estrictamente, el caracter "<" dentro de html sin escapar es un error de sintaxis y el navegador no debiera mostrar el contenido del sitio web, pero de todas maneras lo hace pero no está correcto.

la cadena en javascript va a memoria en mdo plano, eso quiere decir que sin escapar, en la memoria el valor de la cadena equivaldrá al texto con el salto de linea mas la etiqueta html, asi que cuando javascript necesite usar esa cadena y mostrarla sobre un espacio html debe escaparlo.

La solución no pasa por eliminar caracteres o detectar cosas peligrosas como con htmlpurifier o algun ids, la idea es programar como corresponde utilizando los estandares como se debe evitando inyecciones usando las secuencias de escapes como se deben, con eso no debieras porque tener vulnerabilidades de tipo inyección ni debieras porque estar eliminando caracteres o detectando textos peligrosos. Por ejemplo, si en el foro quiero escribir una etiqueta <script> ¿porqué debiera detectarlo como peligroso e impedir que lo escriba?, la idea mas bien es permitirme hacerlo y que esta sea guardada y mostrada de manera segura sin alterar el texto original, eso es una buena práctica en el desarrollo.

Vamos, para todo esto no necesitas hacer nada manualmente, de todo eso se encargarn los frameworks, generalmente debes utilizar secuencias de escape para todo cuando no usas frameworks. Por ejemplo, en codeigniter usas active record y no necesitas usar secuencia de escape para sql, con jquery y valores dinamicos por etiquetas no necesitas escribir valores directamente en javascript asi que no necesitas escaparlos y jquery puede insertar textos ya escapados con .text().

Saludos.

[u]nsigned

Está bien que aprendas estos detalles en PHP vanilla. Pero si vas a dedicarte al desarrollo de software de forma profesional deberías considerar aprender un framework como Laravel o CodeIgniter, la principal ventaja de usar un framework es que ellos ya implementan soluciones para sanitizar cadenas, evitar ataques como CSRF o Inyecciones SQL y ademas te dan librerías ya armadas para las cosas mas comunes como la conexión a base de datos con algún ORM, manejo de sesiones, archivos, etc... La gracias de esto es evitar tener que ocuparse de esas tareas y centrarse solo en el desarrollo y la lógica de negocio de tu aplicación.

PD: Veo que ninguno del staff se percató de mover el tema al subforo de PHP  :silbar:

No hay atajo ante la duda, el misterio se hace aquí...
Se hace carne en cada uno, el misterio es existir!

Leguim

WHK:

Woao Gracias por toda esa información es realmente interesante todo lo que dijiste, te pasaste  ;-)

Unsigned:

Más que nada quiero programar no tanto por si encuentro trabajo de esto (por lo menos por el momento) es que quiero emprender con una aplicación que tengo rato queriéndola hacer.

Sí, investigue de ataques XSS, CSRF, Inyecciones de SQL, robo de sesiones, este otro ataque que no me acuerdo el nombre... en el que una persona puede meter ahí algo raro en las variables de la url que son los $_GET creo que era algo con header, no me acuerdo la verdad...

La subida de archivos al servidor, la cifrado de contraseñas y algunas cosillas que ya logré solventar (espero) ya hice los testeos y todo parece marchar bien...

Gracias!

¿Por qué tantas vistas el tema?  :xD

WHK

Pues generalmente ese tipo de vulnerabilidades los ves con mucho mas frecuencia en desarrollos que no hacen uso de frameworks, ya que al hacer todo a mano tambien hay que preocuparse de toda la seguridad de manera manual, y en mas de una ocación se te pasará algún detalle de seguridad, por eso el uso de frameworks hace que sea menos viable un ataque efectivo de tipo inyección ya que están preparados para evitar ese tipo de cosas. Eso no quiere decir que los desarrollos que usan frameworks no sean vulnerables, pero por lo menos no a cosas tan básicas.

Si quieres hacer un desarrollo pequeño manualmente tendrás que preocuparte manualmente de los tipos de datos, filtrado de datos, prevencion de vulnerabilidades, etc, en cambio si usas un framework solo tendrás que preocuparte por la lógica y las vistas nada más, no tienes que preocuparte por la escalabilidad o en cosas básicas como en una inyección sql.

Si estás recien aprendiendo te recomiendo aprender otros lenguajes como java y usar frameworks como spring, ya que este integra mecanismos de seguridad automatizados mucho mas avanzados que php, por ejemplo, usas templates thymeleaf que escapa automaticamente los caracteres para evitar xss, el spring security te da mecanismos de seguridad contra csrf, manejo de autenticaciones, autorización a secciones, etc.