safe_mode
está activado, la opción safe_mode_exec_dir
restringe la ejecución de comandos por parte de PHP a los comandos de los directorios especificados. Aunque la ausencia de una entrada safe_mode_exec_dir
no supone una vulnerabilidad de seguridad en sí misma, los atacantes pueden aprovechar esta indulgencia añadida junto con otras vulnerabilidades para realizar acciones más peligrosas.open_basedir
especifica el directorio de trabajo que se puede cambiar.open_basedir
intenta evitar que los programas PHP operen en archivos fuera de los árboles de directorio especificados en el archivo php.ini. Si se especifica el directorio de trabajo con .
, puede cambiarlo potencialmente un atacante que usechdir()
.open_basedir
es un beneficio general para la seguridad, la implementación sufre una condición de carrera que puede permitir a los atacantes burlar las restricciones en algunas circunstancias [2]. Existe una condición de carrera de hora de comprobación/hora de uso (TOCTOU) entre la hora a la que PHP realiza la comprobación de permiso de acceso y el momento en que se abre el archivo. Como ocurre con las condiciones de carrera de los sistemas de archivos en otros lenguajes, esta condición de carrera puede permitir a los atacantes que sustituyan un symlink a un archivo que pasa una comprobación de control de acceso por otro que no superaría la prueba, obteniendo así acceso al archivo protegido.register_globals
hace que PHP registre todas las variables EGPCS (entorno, GET, POST, cookie y servidor) de forma global, por lo que se puede acceder a ellas en cualquier ámbito de cualquier programa de PHP. Esta opción anima a los programadores a escribir programas más o menos desconocedores del origen de los valores en los que confían, lo cual puede provocar un comportamiento inesperado en entornos bienintencionados y deja la puerta abierta a los atacantes en entornos malintencionados. Al reconocerse las peligrosas implicaciones de seguridad de register_globals
, esta opción estaba desactivada de forma predeterminada en PHP 4.2.0 y se eliminó en PHP 6.$username
se origina desde la sesión controlada por el servidor, pero un atacante puede suministrar un valor malintencionado para $username
como un parámetro de solicitud. Con register_globals
activado, este código incluirá un valor malintencionado enviado por un atacante en el contenido HTML dinámico que genere.
<?php
if (isset($username)) {
echo "Hello <b>$username</b>";
} else {
echo "Hello <b>Guest</b><br />";
echo "Would you like to login?";
}
?>
safe_mode
es una de las funciones de seguridad más importantes de PHP. Cuando safe_mode
está desactivado, PHP trabaja en los archivos con los permisos del usuario que lo invocó, que por lo general es un usuario con privilegios. Aunque configurar PHP con safe_mode
desactivado no supone una vulnerabilidad de seguridad en sí misma, los atacantes pueden aprovechar esta indulgencia añadida junto con otras vulnerabilidades para realizar acciones más peligrosas.session.use_trans_sid
está activada, PHP pasa el id. de sesión en la URL, lo cual hace mucho más sencillo para los atacantes secuestrar las sesiones activas o engañar a los usuarios para que utilicen una sesión existente que ya controla un atacante.
...
EXEC CICS
INGNORE CONDITION ERROR
END-EXEC.
...
doExchange()
.
try {
doExchange();
}
catch (RareException e) {
// this can never happen
}
RareException
, el programa continuaría ejecutándose como si no hubiera ocurrido nada inusual. El programa no registra ninguna evidencia que aluda a la situación especial, lo que podría frustrar cualquier intento posterior de explicar el comportamiento del programa.DoExchange()
.
try {
DoExchange();
}
catch (RareException e) {
// this can never happen
}
RareException
se fuese a iniciar en algún momento, el programa seguiría ejecutándose como si no hubiese ocurrido nada inusual. El programa no registrará ninguna prueba que indique la situación especial, evitando potencialmente cualquier intento posterior de explicar el comportamiento del programa.doExchange()
.
try {
doExchange();
}
catch (RareException e) {
// this can never happen
}
RareException
se fuese a iniciar en algún momento, el programa seguiría ejecutándose como si no hubiese ocurrido nada inusual. El programa no registrará ninguna prueba que indique la situación especial, evitando potencialmente cualquier intento posterior de explicar el comportamiento del programa.doExchange()
.
try {
doExchange();
}
catch (exception $e) {
// this can never happen
}
RareException
se fuese a iniciar en algún momento, el programa seguiría ejecutándose como si no hubiese ocurrido nada inusual. El programa no registrará ninguna prueba que indique la situación especial, evitando potencialmente cualquier intento posterior de explicar el comportamiento del programa.open()
.
try:
f = open('myfile.txt')
s = f.readline()
i = int(s.strip())
except:
# This will never happen
pass
RareException
se fuese a iniciar en algún momento, el programa seguiría ejecutándose como si no hubiese ocurrido nada inusual. El programa no registrará ninguna prueba que indique la situación especial, evitando potencialmente cualquier intento posterior de explicar el comportamiento del programa.
PROCEDURE do_it_all
IS
BEGIN
BEGIN
INSERT INTO table1 VALUES(...);
COMMIT;
EXCEPTION
WHEN OTHERS THEN NULL;
END;
END do_it_all;
Exception
, se pueden ocultar excepciones que requieran un tratamiento especial o que no se deberían obtener en este punto del programa. Si se obtiene una excepción demasiado amplia, básicamente hace fracasar el propósito de las excepciones tipificadas de .NET, y puede resultar particularmente peligroso si el programa se desarrolla y comienza a iniciar nuevos tipos de excepciones. Los nuevos tipos de excepciones quedarán desatendidas.
try {
DoExchange();
}
catch (IOException e) {
logger.Error("DoExchange failed", e);
}
catch (FormatException e) {
logger.Error("DoExchange failed", e);
}
catch (TimeoutException e) {
logger.Error("DoExchange failed", e);
}
try {
DoExchange();
}
catch (Exception e) {
logger.Error("DoExchange failed", e);
}
DoExchange()
para iniciar un nuevo tipo de excepción que debería tratarse de forma diferente, el amplio bloque catch evitará que el compilador señale la situación. Además, ahora el bloque catch nuevo tratará también excepciones de los tipos ApplicationException
y NullReferenceException
, lo cual no es el propósito del programador.Exception
, se pueden ocultar excepciones que requieran un tratamiento especial o que no se deberían obtener en este punto del programa. Si se obtiene una excepción demasiado amplia, básicamente hace fracasar el propósito de las excepciones tipificadas de Java, y puede resultar particularmente peligroso si el programa se desarrolla y comienza a iniciar nuevos tipos de excepciones. Los nuevos tipos de excepciones quedarán desatendidas.
try {
doExchange();
}
catch (IOException e) {
logger.error("doExchange failed", e);
}
catch (InvocationTargetException e) {
logger.error("doExchange failed", e);
}
catch (SQLException e) {
logger.error("doExchange failed", e);
}
try {
doExchange();
}
catch (Exception e) {
logger.error("doExchange failed", e);
}
doExchange()
para iniciar un nuevo tipo de excepción que debería tratarse de forma diferente, el amplio bloque catch evitará que el compilador señale la situación. Es más, el nuevo bloque de filtrado ahora también administra las excepciones derivadas de RuntimeException
como ClassCastException
y NullPointerException
, que no es el propósito del programador.Exception
o Throwable
dificulta a los autores de llamada hacer un buen trabajo en cuanto al tratamiento y la recuperación de errores. El mecanismo de excepciones de Java se ha configurado para facilitar a los autores de llamada la anticipación de qué puede salir mal y escribir código para administrar cada circunstancia de excepción específica. Declarar que un método lance una forma genérica de excepción frustra este sistema.
public void doExchange()
throws IOException, InvocationTargetException,
SQLException {
...
}
public void doExchange()
throws Exception {
...
}
doExchange()
introduce un nuevo tipo de excepción que debería tratarse de forma diferente a las excepciones anteriores, no hay una forma fácil de exigir este requisito.NullPointerException
.NullPointerException
bajo tres circunstancias:NullPointerException
para señalar una condición de error.NullPointerException
.
try {
mysteryMethod();
}
catch (NullPointerException npe) {
}
NullReferenceException
.NullReferenceException
bajo tres circunstancias:NullReferenceException
para señalar una condición de error.NullReferenceException
.
try {
MysteryMethod();
}
catch (NullReferenceException npe) {
}
finally
provocará que las excepciones se pierdan.finally
provocará que todas las excepciones que se puedan lanzar en el bloque try se descarten.MagicException
lanzada por la segunda llamada para doMagic
con true
transferido a ella nunca se entregará al autor de llamada. La instrucción return dentro del bloque finally
provocará que la excepción se descarte.
public class MagicTrick {
public static class MagicException extends Exception { }
public static void main(String[] args) {
System.out.println("Watch as this magical code makes an " +
"exception disappear before your very eyes!");
System.out.println("First, the kind of exception handling " +
"you're used to:");
try {
doMagic(false);
} catch (MagicException e) {
// An exception will be caught here
e.printStackTrace();
}
System.out.println("Now, the magic:");
try {
doMagic(true);
} catch (MagicException e) {
// No exception caught here, the finally block ate it
e.printStackTrace();
}
System.out.println("tada!");
}
public static void doMagic(boolean returnFromFinally)
throws MagicException {
try {
throw new MagicException();
}
finally {
if (returnFromFinally) {
return;
}
}
}
}
finally
provocará que las excepciones se pierdan.finally
provocará que todas las excepciones que se puedan lanzar en el bloque try se descarten.exception
lanzada por la segunda llamada para doMagic
con True
transferido a ella nunca se entregará al autor de llamada. La instrucción RETURN dentro del bloque finally
provocará que la excepción se descarte."disappear before your very eyes!" . PHP_EOL;
echo "First, the kind of exception handling " .
"you're used to:" . PHP_EOL;
try {
doMagic(False);
} catch (exception $e) {
// An exception will be caught here
echo $e->getMessage();
}
echo "Now, the magic:" . PHP_EOL;
try {
doMagic(True);
} catch (exception $e) {
// No exception caught here, the finally block ate it
echo $e->getMessage();
}
echo "Tada!" . PHP_EOL;
function doMagic($returnFromFinally) {
try {
throw new Exception("Magic Exception" . PHP_EOL);
}
finally {
if ($returnFromFinally) {
return;
}
}
}
?>
ThreadDeath
no se vuelve a lanzar, el subproceso en cuestión podría no acabar.ThreadDeath
solo deben filtrarse si una aplicación tiene que limpiar después de finalizar de forma asíncrona. Si se filtra un error ThreadDeath
, es importante que se vuelva a lanzar para que el subproceso finalice realmente. El propósito de lanzar ThreadDeath
es detener un subproceso. Si ThreadDeath
es absorbido, puede impedir que un subproceso se detenga y dé lugar a un comportamiento inesperado, puesto que quien haya lanzado originalmente ThreadDeath
espera que el subproceso se detenga.ThreadDeath
, pero no lo vuelve a lanzar.
try
{
//some code
}
catch(ThreadDeath td)
{
//clean up code
}
throw
dentro de un bloque finally
rompe la progresión lógica de try-catch-finally
.finally
siempre se ejecutan después de su bloque try-catch
correspondiente y se utilizan frecuentemente para liberar recursos asignados, como controladores de archivos o cursores de base de datos. Lanzar una excepción en un bloque finally
puede derivar el código de limpieza crítico, puesto que la ejecución normal del programa se interrumpirá. stmt.close()
se deriva cuando se lanza la FileNotFoundException
.
public void processTransaction(Connection conn) throws FileNotFoundException
{
FileInputStream fis = null;
Statement stmt = null;
try
{
stmt = conn.createStatement();
fis = new FileInputStream("badFile.txt");
...
}
catch (FileNotFoundException fe)
{
log("File not found.");
}
catch (SQLException se)
{
//handle error
}
finally
{
if (fis == null)
{
throw new FileNotFoundException();
}
if (stmt != null)
{
try
{
stmt.close();
}
catch (SQLException e)
{
log(e);
}
}
}
}
javax.net.ssl.SSLHandshakeException
, javax.net.ssl.SSLKeyException
y javax.net.ssl.SSLPeerUnverifiedException
transmiten errores importantes relacionados con una conexión SSL. Si estos errores no se administran explícitamente, la conexión puede dejarse en un estado inesperado y potencialmente inseguro.
private final Logger logger =
Logger.getLogger(MyClass.class);
public class MyClass {
private final static Logger good =
Logger.getLogger(MyClass.class);
private final static Logger bad =
Logger.getLogger(MyClass.class);
private final static Logger ugly =
Logger.getLogger(MyClass.class);
...
}
Console.Out
o Console.Error
en lugar de una interfaz de registro dedicada, es difícil supervisar el comportamiento del programa.
public class MyClass {
...
Console.WriteLine("hello world");
...
}
Console.WriteLine()
.Console.WriteLine
podría indicar un descuido en el paso a un sistema de registro estructurado.os.Stdout
o os.Stderr
en lugar de una interfaz de registro dedicada, es difícil supervisar el comportamiento del programa.
...
func foo(){
fmt.Println("Hello World")
}
fmt.Println()
.os.Stdout
o os.Stderr
puede indicar un descuido en el paso a un sistema estructurado de registro.System.out
o System.err
en lugar de una interfaz de registro dedicada, es difícil supervisar el comportamiento del programa.
public class MyClass
...
System.out.println("hello world");
...
}
System.out.println()
.System.out
o System.err
podría indicar un descuido en el paso a un sistema estructurado de registro.process.stdout
o process.stderr
en lugar de una interfaz de registro dedicada, resulta más difícil supervisar el comportamiento del programa.
process.stdin.on('readable', function(){
var s = process.stdin.read();
if (s != null){
process.stdout.write(s);
}
});
process.stdout.write()
.process.stdout
o process.stderr
podría indicar un descuido en el paso a un sistema estructurado de registro.print
o println
en lugar de una interfaz de registro dedicada, es difícil supervisar el comportamiento del programa.
class MyClass {
...
println("hello world")
...
}
}
print
o println
.
sys.stdout.write("hola, mundo")
sys.stdout
o sys.stderr
podría indicar un descuido en el paso a un sistema estructurado de registro.Kernel.puts
,Kernel.warn
o Kernel.printf
en lugar de una interfaz de registro dedicada, resulta más difícil supervisar el comportamiento del programa.
...
puts "hello world"
...
Kernel.puts
.Kernel.puts
,Kernel.warn
o Kernel.printf
podría indicar un descuido en el paso a un sistema estructurado de registro.Logger
, pero registra información en un flujo de salida del sistema:
require 'logger'
...
logger = Logger.new($stdout)
logger.info("hello world")
...