Commit 08bf63c3 authored by stiwar1's avatar stiwar1 Committed by Rafael Alvarez

new: content/defends/scala/limitar-vida-variable

parent 5a556e0e
def readData(): Unit = {
val bufferSize: Int = 16 * 1024
val zeroes: Byte = Array.ofDim[Byte](bufferSize)
val buffer: ByteBuffer = ByteBuffer.allocateDirect(bufferSize)
try {
for (rdr <- managed((new FileInputStream("file")).getChannel))
while (rdr.read(buffer) > 0) {
// Hacer algo con el búfer
buffer.clear()
buffer.put(zeroes) // sobrescribir el búfer con ceros
buffer.clear()
}
} catch {
case e: Throwable => {}
}
}
\ No newline at end of file
:slug: defends/scala/limitar-tiempo-vida/
:slug: defends/scala/limitar-vida-variable/
:category: scala
:description: Nuestros ethical hackers explican cómo evitar vulnerabilidades de seguridad mediante la creación, manipulación y eliminación correcta de datos o recursos dentro de un programa scala, con el fin de evitar que información confidencial disponible en memoria, sea vulnerable.
:description: Nuestros ethical hackers explican cómo evitar vulnerabilidades de seguridad mediante la creación, manipulación y eliminación correcta de variables u objetos dentro de un programa Scala, evitando que información disponible en memoria pueda ser capturada por usuarios no autorizados.
:keywords: scala, datos sensibles, datos confidenciales, lectura segura, memoria, tiempo de vida.
:defends: yes
= Limitar el tiempo de vida de datos sensibles
= Limitar tiempo de vida de variables
== Necesidad
Eliminar (limpiar) datos, recursos
Eliminar (limpiar) datos, variables
y/o objetos creados por la aplicación
cuando ya no estén en uso.
......@@ -17,9 +17,9 @@ cuando ya no estén en uso.
A continuación se describe las circunstancias
bajo las cuales la siguiente solución tiene sentido:
. Se está desarrollando una aplicación en +Scala+.
. Se está desarrollando una aplicación en +Scala+ versión +2.11.6+ o superior.
. El código debe eliminar información sensible en memoria.
. La aplicación debe limpiar/eliminar datos, recursos
. La aplicación debe limpiar/eliminar datos, variables
y/o objetos creados por la misma cuando ya no estén en uso,<<r1,^[1]^>>
limitando así su tiempo de vida.
......@@ -29,7 +29,7 @@ limitando así su tiempo de vida.
. A continuación se describe un sencillo código de ejemplo demostrativo,
donde se explica la manera de limpiar datos almacenados
dentro de un +ArrayBuffer+<<r2,^[2]^>>:
dentro de un link:http://www.scala-lang.org/api/2.8.1/scala/collection/mutable/ArrayBuffer.html[+ArrayBuffer:+]
+
.test.scala
[source, scala, linenums]
......@@ -46,7 +46,7 @@ Posterior a ello, se crea un nuevo +ArrayBuffer+
cuyo contenido inicial son números del 1 al 5
y son referenciados mediante la variable +mab+.
Luego mediante dicha variable,
podemos acceder al método +clear+
podemos acceder al método link:http://www.scala-lang.org/api/2.7.4/scala/collection/mutable/ArrayBuffer.html#clear%28%29[+clear+]
cuya función es limpiar el contenido del respectivo búfer,
evitando así, que información sensible permanezca en memoria.
......@@ -57,7 +57,7 @@ permite la lectura segura de credenciales
ingresadas desde la consola.
. Dado que es posible reutilizar código +Java+ dentro de +Scala+,
en primer lugar importamos las clases requeridas:<<r3,^[3]^>>
en primer lugar importamos las clases requeridas:<<r2,^[2]^>>
+
.password.scala
[source, scala, linenums]
......@@ -65,7 +65,7 @@ en primer lugar importamos las clases requeridas:<<r3,^[3]^>>
import scala.collection.JavaConversions._
----
. Posterior a lo anterior,
se procede a crear un objeto tipo +Singleton+<<r4,^[4]^>> llamado +Password+.
se procede a crear un objeto tipo link:https://en.wikipedia.org/wiki/Singleton_pattern[+Singleton+] llamado +Password+.
Dentro de este, se define el método +main+
el cual no retorna ningún dato
(esto se especifica mediante +Unit =+).
......@@ -76,14 +76,13 @@ object Password {
def main(args: Array[String]): Unit = {
----
. En la constante +c+
almacenamos una referencia a un objeto de la clase +Console+
mediante el método +console+<<r5,^[5]^>> de la clase +System+:
mediante el método link:https://docs.oracle.com/javase/7/docs/api/java/lang/System.html#console()[+console+] de la clase +System+:
+
[source, scala, linenums]
----
val c: Console = System.console()
val c = System.console()
if (c == null) {
System.err.println("No console.")
System.exit(1)
......@@ -91,14 +90,14 @@ val c: Console = System.console()
----
+
De lo anterior, una vez creado dicho objeto,
se verifica si este es nulo,
es caso de serlo,
se verifica si este es nulo.
En caso de serlo,
se detiene la ejecución del programa
mediante el método +exit+.
. Se lee la información del nombre de usuario
mediante el método +readLine+<<r6,^[6]^>>,
y, por medio del método +readPassword()+<<r7,^[7]^>>
mediante el método link:https://docs.oracle.com/javase/7/docs/api/java/io/Console.html#readLine()[+readLine+],
y, por medio del método link:https://docs.oracle.com/javase/7/docs/api/java/io/Console.html#readPassword()[+readPassword+]
(el cual retorna un +array+ de caracteres)
se lee la contraseña desde la consola
sin imprimir los caracteres en pantalla:
......@@ -116,7 +115,9 @@ simulamos el proceso de validación del usuario
----
val isValidUser: Boolean = verify(username, password)
// limpiar la contraseña
Arrays.fill(password, ' ')
for( a <- 0 to (password.length - 1) ) {
password(a) = '0'
}
if (!isValidUser) {
throw new SecurityException("Invalid Credentials")
}
......@@ -130,67 +131,40 @@ simulamos el proceso de validación del usuario
+
Del anterior bloque de código
se observa que una vez no es necesaria la contraseña,
esta es eliminada o sobrescrita de memoria
mediante el método +fill+<<r8,^[8]^>> de la clase +Arrays+.
* *Lectura segura de ficheros:*
esta es eliminada o sobrescrita de memoria con ceros.
. El siguiente bloque de código +Scala+
especifica el método +readData+:
. Para ejecutar el anterior programa,
desde la terminal se debe ubicar primero en el directorio del proyecto
(en este caso la ruta es +/home/user/proyecto/+),
y ejecutar el comando +scalac+
(se debe tener instalado +Scala+ previamente):
+
.readdata.scala
[source, scala, linenums]
----
def readData(): Unit = {
----
. En dicho método, se declara un búfer de +bytes+ directo
mediante el método +ByteBuffer.allocateDirect()+
especificando el tamaño del mismo:
[source, bash, linenums]
----
~$ cd /home/user/proyecto/
~/home/user/proyecto$ ls
~/home/user/proyecto$ Password.scala
~/home/user/proyecto$ scalac Password.scala
~/home/user/proyecto$ ls
~/home/user/proyecto$ Password.scala Password.class Password$.class Password$$anonfun$main$1.class
----
. Luego de compilar el programa correctamente,
se obtiene el +bytecode+ (archivo +.class+) del programa
y se procede a ejecutar el mismo mediante el comando +scala+:
+
[source, scala, linenums]
[source, bash, linenums]
----
val bufferSize: Int = 16 * 1024
val zeroes: Byte = Array.ofDim[Byte](bufferSize)
val buffer: ByteBuffer = ByteBuffer.allocateDirect(bufferSize)
~/home/user/proyecto$ scala Password
----
. Posterior a ello, a través de un objeto de la clase +FileInputStream+,
se llama al método +getChannel+
para obtener el flujo de datos
asociado a la entrada o fichero actual:
. La salida en consola luego de ejecutar el programa es la siguiente
(los símbolos '*' son simbólicos ya que en pantalla no se verá nada):
+
[source, scala, linenums]
----
try {
for (rdr <- managed((new FileInputStream("file")).getChannel))
----
. Por último, mediante un ciclo +while+ se lee el contenido
de dicho archivo almacenado en el búfer:
+
[source, scala, linenums]
[source, bash, linenums]
----
while (rdr.read(buffer) > 0) {
// Hacer algo con el búfer
buffer.clear()
buffer.put(zeroes) // sobrescribir el búfer con ceros
buffer.clear()
}
} catch {
case e: Throwable => {}
}
}
~/home/user/proyecto$
Ingresa tu nombre de usuario: FLUIDtest
Ingresa tu contraseña: *******
----
+
Note que dentro del ciclo +while+
se lleva a cabo la eliminación manual de los datos del búfer,
limpiándolos o sobrescribiendo su contenido con ceros.
Puedes encontrar soluciones similares
para los siguientes lenguajes: <<r9,C#>>, <<r10,Java>>.
== Descargas
......@@ -200,20 +174,9 @@ pulsando en el siguiente enlace:
. [button]#link:src/password.scala[password.scala >>]# contiene
las instrucciones +scala+ para el manejo de credenciales de manera segura.
. [button]#link:src/readdata.scala[readdata.scala >>]# contiene
las instrucciones +scala+ para la lectura de un fichero desde un búfer.
== Referencias
. [[r1]] REQ.999: La aplicación debe
limpiar/eliminar datos, recursos y/o objetos creados por la misma
cuando ya no estén en uso.
. [[r2]] link:http://www.scala-lang.org/api/2.8.1/scala/collection/mutable/ArrayBuffer.html[ArrayBuffer].
. [[r3]] link:http://www.scala-lang.org/api/2.9.3/scala/collection/JavaConversions$.html[JavaConversions].
. [[r4]] link:https://en.wikipedia.org/wiki/Singleton_pattern[Singleton pattern].
. [[r5]] link:https://docs.oracle.com/javase/7/docs/api/java/lang/System.html#console()[Class System-console].
. [[r6]] link:https://docs.oracle.com/javase/7/docs/api/java/io/Console.html#readLine()[Class Console-readLine].
. [[r7]] link:https://docs.oracle.com/javase/7/docs/api/java/io/Console.html#readPassword()[Class Console-readPassword].
. [[r8]] link:https://docs.oracle.com/javase/7/docs/api/java/util/Arrays.html[Class Arrays].
. [[r9]] link:../../csharp/limitar-tiempo-vida/[C#-Limitar el tiempo de vida de datos sensibles].
. [[r10]] link:../../java/limitar-vida-datos-sensibles/[Java-Limitar el tiempo de vida de datos sensibles].
\ No newline at end of file
. [[r1]] link:../../../rules/998/[REQ.998 Limitar tiempo de vida de variables].
. [[r2]] link:http://www.scala-lang.org/api/2.9.3/scala/collection/JavaConversions$.html[JavaConversions].
. *+CSHARP+* link:../../csharp/limitar-vida-variable/[Limitar tiempo de vida de variables].
. *+JAVA+* link:../../java/limitar-vida-variable/[Limitar tiempo de vida de variables].
\ No newline at end of file
......@@ -3,7 +3,7 @@ import scala.collection.JavaConversions._
object Password {
def main(args: Array[String]): Unit = {
val c: Console = System.console()
val c = System.console()
if (c == null) {
System.err.println("No console.")
System.exit(1)
......@@ -12,7 +12,9 @@ object Password {
val password: Array[Char] = c.readPassword("Enter your password: ")
val isValidUser: Boolean = verify(username, password)
// limpiar la contraseña
Arrays.fill(password, ' ')
for( a <- 0 to (password.length - 1) ) {
password(a) = '0'
}
if (!isValidUser) {
throw new SecurityException("Invalid Credentials")
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment