La computación distribuida trata sobre el tiempo y el estado. Es decir, para que más de un componente se comunique, debe compartir el estado, y todo esto requiere tiempo.
La mayoría de programadores antropomorfizan su trabajo. Piensan en un único puesto de control que lleva a cabo todo el programa de igual forma que harían ellos si tuviesen que realizar la tarea ellos mismos. Sin embargo, los equipos modernos cambian entre tareas con gran rapidez y, en una CPU múltiple con varios núcleos, o en los sistemas distribuidos, dos eventos pueden llevarse a cabo a la vez exactamente. Estos defectos hacen que sea urgente que se unan posturas entre el modelo de los programadores sobre cómo un programa se ejecuta y lo que sucede en la realidad. Dichos defectos están relacionados con interacciones inesperadas entre los puestos, los procesos, el tiempo y la información. Estas interacciones se producen a través del estado compartido: semáforos, variables, el sistema de archivos y, básicamente, cualquier cosa que pueda guardar información.
HttpSessionState
puede dañar la confiabilidad de la aplicación.HttpSessionState
, sus atributos y cualquier objeto al que hagan referencia en la memoria. Este modelo limita el estado de sesiones activas que puede alojar la memoria del sistema de un solo equipo. Para ampliar la capacidad más allá de estas limitaciones, los servidores se configuran con frecuencia para almacenar la información de estado de sesión, lo que permite ampliar la capacidad y efectuar la replicación entre varios equipos a fin de mejorar el rendimiento general. Para almacenar su estado de sesión, el servidor debe serializar el objeto HttpSessionState
, para lo que es necesario que todos los objetos almacenados sean serializables.[Serializable]
. Además, si el objeto requiere métodos de serialización personalizados, también debe implementar la interfaz ISerializable
.
public class DataGlob {
String GlobName;
String GlobValue;
public void AddToSession(HttpSessionState session) {
session["glob"] = this;
}
}
sleep()
mientras se mantiene un bloqueo puede provocar una pérdida de rendimiento y podría ocasionar un interbloqueo.sleep()
mientras se mantiene un bloqueo podría causar que todos los demás subprocesos esperen a que el recurso se libere, lo que podría dar lugar a un rendimiento degradado y un interbloqueo. sleep()
mientras mantiene un bloqueo.
ReentrantLock rl = new ReentrantLock();
...
rl.lock();
Thread.sleep(500);
...
rl.unlock();
if (fitz == null) {
synchronized (this) {
if (fitz == null) {
fitz = new Fitzer();
}
}
}
return fitz;
Fitzer()
, pero no desea pagar el coste de la sincronización cada vez que se llame al código. A este giro se le conoce como bloqueo de doble comprobación.Fitzer()
. Consulte la declaración "El bloqueo de doble comprobación está roto" para obtener más información [1].pthread_mutex_unlock()
antes de que otro subproceso empiece a ejecutarse. Si el subproceso que señala no puede desbloquear la exclusión mutua, la llamada pthread_cond_wait()
del segundo subproceso no volverá y el subproceso no se ejecutará. pthread_cond_signal()
, pero no puede desbloquear la exclusión mutua en la que espera el otro subproceso.
...
pthread_mutex_lock(&count_mutex);
// Signal waiting thread
pthread_cond_signal(&count_threshold_cv);
...
...
if (tmpnam_r(filename)){
FILE* tmp = fopen(filename,"wb+");
while((recv(sock,recvbuf,DATA_SIZE, 0) > 0)&&(amt!=0))
amt = fwrite(recvbuf,1,DATA_SIZE,tmp);
}
...
tmpnam()
, tempnam()
, mktemp()
y sus equivalentes de C++ precedidos de un _
(carácter de subrayado), así como de la función GetTempFileName()
de la API de Windows. Este grupo de funciones presenta una condición de carrera subyacente en relación con el nombre de archivo seleccionado. Aunque las funciones garantizan que el nombre de archivo es exclusivo en el momento de seleccionarlo, no hay ningún mecanismo que impida que otro proceso o un usuario malintencionado cree un archivo con el mismo nombre tras seleccionarlo, pero antes de que la aplicación intente abrirlo. Más allá del riesgo de conflicto legítimo provocado por otra llamada a la misma función, hay una alta probabilidad de que un usuario malintencionado pueda crear un conflicto malicioso debido a que los nombres de archivo generados por estas funciones no son lo suficientemente aleatorios para que sean difíciles de adivinar. open()
mediante los indicadores O_CREAT
y O_EXCL
, o a CreateFile()
mediante el atributo CREATE_NEW
, que presentará errores si el archivo ya existe y, por lo tanto, impide los tipos de ataques descritos anteriormente. Sin embargo, si un usuario malintencionado puede predecir con precisión una secuencia de nombres de archivo temporales, es posible que se impida que la aplicación abra el almacenamiento temporal necesario, lo que provocaría un ataque de denegación de servicio (DoS). Este tipo de ataque no sería difícil de implementar dado el reducido nivel de aleatoriedad empleado en la selección de los nombres de archivo generados por estas funciones.tmpfile()
y sus equivalentes de C++ precedidos de _
(carácter de subrayado), así como de una función de biblioteca C mkstemp()
con un comportamiento más eficaz.tmpfile()
crean un nombre de archivo exclusivo y abren el archivo del mismo modo que lo haría fopen()
si transfiriese los indicadores "wb+"
, es decir, como un archivo binario en modo de lectura/escritura. Si el archivo ya existe, tmpfile()
se truncará para establecer el tamaño cero, posiblemente en un intento por apaciguar las inquietudes de seguridad mencionadas anteriormente en cuanto a la condición de carrera que se produce entre la selección del nombre de archivo supuestamente exclusivo y la posterior apertura del archivo seleccionado. Sin embargo, este comportamiento no soluciona claramente los problemas de seguridad de la función. En primer lugar, un atacante puede crear previamente el archivo con permisos de acceso moderados que probablemente conservará el archivo abierto por tmpfile()
. Además, en los sistemas basados en Unix, si el usuario malintencionado crea previamente el archivo como vínculo a otro archivo importante, la aplicación puede utilizar los permisos posiblemente elevados para truncar ese archivo, dañándolo en nombre del usuario malintencionado. Por último, si tmpfile()
crea un nuevo archivo, los permisos de acceso aplicados al mismo variarán de un sistema operativo a otro, lo que puede dejar vulnerable la aplicación, incluso aunque el usuario malintencionado pueda predecir por adelantado el nombre de archivo que se va a usar.mkstemp()
supone un método razonablemente seguro para crear archivos temporales. Este intentará crear y abrir un archivo exclusivo basado en una plantilla de nombre de archivo proporcionada por el usuario, junto con una serie de caracteres generados aleatoriamente. Si no puede crear este archivo, presentará errores y devolverá -1
. En los sistemas modernos, el archivo se abre mediante el modo 0600
, lo que implica que el archivo se protegerá frente a su manipulación a menos que el usuario cambie de forma explícita los permisos de acceso. No obstante, mkstemp()
aún presenta problemas en relación con el uso de nombres de archivo predecibles y puede dejar vulnerable una aplicación frente a ataques de denegación de servicio si un usuario malintencionado provoca que mkstemp()
presente fallos mediante la predicción y la creación previa de los nombres de archivo que se van a utilizar.
...
try:
tmp_filename = os.tempnam()
tmp_file = open(tmp_filename, 'w')
data = s.recv(4096)
while True:
more = s.recv(4096)
tmp_file.write(more)
if not more:
break
except socket.timeout:
errMsg = "Connection timed-out while connecting"
self.logger.exception(errMsg)
raise Exception
...
open()
mediante los indicadores os.O_CREAT
y os.O_EXCL
, que presentará errores si el archivo ya existe y, por lo tanto, impedirá los tipos de ataques descritos anteriormente. Sin embargo, si un usuario malintencionado puede predecir con precisión una secuencia de nombres de archivo temporales, es posible que se impida que la aplicación abra el almacenamiento temporal necesario, lo que provocaría un ataque de denegación de servicio (DoS). Este tipo de ataque no sería difícil de implementar dado el reducido nivel de aleatoriedad empleado en la selección de los nombres de archivo generados por estas funciones.tmpfile()
.tmpfile()
crean un nombre de archivo exclusivo y abren el archivo del mismo modo que lo haría open()
si transfiriese los indicadores "wb+"
, es decir, como un archivo binario en modo de lectura/escritura. Si el archivo ya existe, tmpfile()
se truncará para establecer el tamaño cero, posiblemente en un intento por apaciguar las inquietudes de seguridad mencionadas anteriormente en cuanto a la condición de carrera que se produce entre la selección del nombre de archivo supuestamente exclusivo y la posterior apertura del archivo seleccionado. Sin embargo, este comportamiento no soluciona claramente los problemas de seguridad de la función. En primer lugar, un atacante puede crear previamente el archivo con permisos de acceso moderados que probablemente conservará el archivo abierto por tmpfile()
. Además, en los sistemas basados en Unix, si el usuario malintencionado crea previamente el archivo como vínculo a otro archivo importante, la aplicación puede utilizar los permisos posiblemente elevados para truncar ese archivo, dañándolo en nombre del usuario malintencionado. Por último, si tmpfile()
crea un nuevo archivo, los permisos de acceso aplicados al mismo variarán de un sistema operativo a otro, lo que puede dejar vulnerable la aplicación, incluso aunque el usuario malintencionado pueda predecir por adelantado el nombre de archivo que se va a usar.
...
HttpSession sesssion = request.getSession(true);
sesssion.setMaxInactiveInterval(-1);
...
HttpSession
puede dañar la confiabilidad de la aplicación.HttpSession
entre varios JVM. De este modo, si un JVM deja de estar disponible otro puede intervenir y ocupar su lugar sin deteriorar el flujo de la aplicación.Serializable
.
public class DataGlob {
String globName;
String globValue;
public void addToSession(HttpSession session) {
session.setAttribute("glob", this);
}
}
...
var authenticated = true;
...
database_connect.query('SELECT * FROM users WHERE name == ? AND password = ? LIMIT 1', userNameFromUser, passwordFromUser, function(err, results){
if (!err && results.length > 0){
authenticated = true;
}else{
authenticated = false;
}
});
if (authenticated){
//do something privileged stuff
authenticatedActions();
}else{
sendUnathenticatedMessage();
}
true
; en caso contrario, como false
. Desafortunadamente, como hay E/S que bloquea la devolución de llamada, esta se ejecutará de forma asíncrona y puede que se ejecute después de la comprobación if (authenticated)
, y como el valor predeterminado era true, irá en la instrucción if tanto si el usuario se ha autenticado realmente como si no.
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(new File(Environment.getExternalStorageDirectory() + "/download/" + "app.apk")), "application/vnd.android.package-archive");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
CBL_CHECK_FILE_EXIST
para comprobar si el archivo existe antes de crear uno y lleva a cabo las operaciones necesarias.
CALL "CBL_CHECK_FILE_EXIST" USING
filename
file-details
RETURNING status-code
END-CALL
IF status-code NOT = 0
MOVE 3 to access-mode
MOVE 0 to deny-mode
MOVE 0 to device
CALL "CBL_CREATE_FILE" USING
filename
access-mode
deny-mode
device
file-handle
RETURNING status-code
END-CALL
END-IF
CBL_CHECK_FILE_EXIST
se comporta tal y como se esperaba y devuelve un valor distinto de cero, que indica que el archivo no existe. Sin embargo, dado que tanto CBL_CHECK_FILE_EXIST
como CBL_CREATE_FILE
operan sobre los nombres de los archivos y no sobre los identificadores, no hay garantía de que la variable filename
todavía se refiera al mismo archivo en el disco cuando se pase a CBL_CREATE_FILE
que era cuando se pasó a CBL_CHECK_FILE_EXIST
. Si un atacante crea un filename
después de la llamada a CBL_CHECK_FILE_EXIST
, la llamada a CBL_CREATE_FILE
fallará, lo que llevará al programa a creer que el archivo está vacío, cuando de hecho este contiene datos controlados por el atacante.root
que realiza ciertas operaciones de archivo en nombre de usuarios no privilegiados, y usa comprobaciones de acceso para asegurar que este no usa sus privilegios origen para realizar operaciones que no deberían estar disponibles para el usuario actual. Engañando al programa para que realice una operación que no sería permisible de otro modo, el atacante puede ganar ciertos privilegios superiores.parse()
y format()
de java.text.Format
contienen un error de diseño que puede ocasionar que un usuario vea los datos de otro usuario.parse()
y format()
de java.text.Format
contienen una condición de carrera que puede ocasionar que un usuario vea los datos de otro usuario.
public class Common {
private static SimpleDateFormat dateFormat;
...
public String format(Date date) {
return dateFormat.format(date);
}
...
final OtherClass dateFormatAccess=new OtherClass();
...
public void function_running_in_thread1(){
System.out.println("Time in thread 1 should be 12/31/69 4:00 PM, found: "+ dateFormatAccess.format(new Date(0)));
}
public void function_running_in_thread2(){
System.out.println("Time in thread 2 should be around 12/29/09 6:26 AM, found: "+ dateFormatAccess.format(new Date(System.currentTimeMillis())));
}
}
format()
.RoamingFolder
o RoamingSettings
de la clase Windows.Storage.ApplicationData
.RoamingFolder
y RoamingSettings
obtienen un contenedor en el almacén de datos de aplicaciones de movilidad, que luego se puede usar para compartir datos entre dos o varios dispositivos. Al escribir y leer los objetos almacenados en el almacén de datos de aplicaciones de movilidad, el desarrollador aumenta los riesgos. Estos abarcan la confidencialidad, la integridad y la disponibilidad de los datos, las aplicaciones y los sistemas que comparten esos objetos a través de dicho almacén.free()
dos veces con el mismo valor, se puede producir un buffer overflow. Si un programa llama a free()
dos veces con el mismo argumento, las estructuras de datos de administración de memoria del programa se dañan. Esto puede provocar que el programa se bloquee o, en algunas circunstancias, que se realicen dos llamadas posteriores a malloc()
para devolver la misma referencia. Si malloc()
devuelve el mismo valor dos veces y el programa concede posteriormente al usuario malintencionado control de los datos escritos en la memoria que se ha asignado dos veces, el programa será vulnerable a un ataque de buffer overflow.
void sh(int dummy) {
...
free(global2);
free(global1);
...
}
int main(int argc,char* argv[]) {
...
signal(SIGHUP,sh);
signal(SIGTERM,sh);
...
}
public class GuestBook extends HttpServlet {
String name;
protected void doPost (HttpServletRequest req, HttpServletResponse res) {
name = req.getParameter("name");
...
out.println(name + ", thanks for visiting!");
}
}
Dick
" a name
Jane
" a name
Jane, thanks for visiting!
"Jane, thanks for visiting!
"
public class ConnectionManager {
private static Connection conn = initDbConn();
...
}
<http auto-config="true">
...
<session-management session-fixation-protection="none"/>
</http>
Example 1
, el atacante logra esto mediante un método directo obvio que no resulta adecuado para ataques donde los sitios web son menos populares. Sin embargo, no hay que bajar la guardia, ya que los atacantes disponen de muchas herramientas para eludir las limitaciones de este vector de ataque. La técnica más habitual que utilizan los atacantes consiste en aprovechar las vulnerabilidades Cross-Site Scripting o de división de respuestas HTTP en el sitio de destino [1]. Al engañar a la víctima para que envíe una solicitud malintencionada a una aplicación vulnerable que muestra JavaScript u otro código en su explorador, el atacante puede crear una cookie que provocará que la víctima vuelva a utilizar el identificador de sesión controlado por el atacante.bank.example.com
y recipes.example.com
, una vulnerabilidad en una aplicación puede permitir que un atacante establezca una cookie con un identificador de sesión fijo, que se utilizará en todas las interacciones con cualquier aplicación que se encuentre en el dominio example.com
[2].use_strict_mode
en las cookies de sesión.
ini_set("session.use_strict_mode", "0");