safe_mode
está habilitada, a opção safe_mode_exec_dir
impede que o PHP execute comandos apenas dos diretórios especificados. Embora a ausência da entrada safe_mode_exec_dir
não represente por si só uma vulnerabilidade de segurança, essa complacência adicional pode ser explorada por invasores em conjunto com outras vulnerabilidades para tornar as explorações ainda mais perigosas.open_basedir
especifica o diretório de trabalho que pode ser alterado.open_basedir
tenta impedir que programas PHP operem em arquivos fora das árvores de diretórios especificadas em php.ini. Se o diretório de trabalho for especificado com .
, isso poderá ser alterado por um invasor com o uso de chdir()
.open_basedir
seja uma vantagem geral para a segurança, a implementação é afetada por uma condição de corrida que pode permitir que os invasores se esquivem de suas restrições em algumas circunstâncias [2]. Existe uma condição de corrida TOCTOU (tempo de verificação/tempo de uso) entre o momento em que o PHP realiza a verificação de permissão de acesso e o momento em que o arquivo é aberto. Tal como acontece com condições de corrida no sistema de arquivos em outras linguagens, essa condição de corrida pode permitir que os invasores substituam um link simbólico para um arquivo, aprovado em uma verificação de controle de acesso, por outro para o qual o teste seria reprovado de outra forma, obtendo assim acesso ao arquivo protegido.register_globals
faz com que o PHP registre todas as variáveis EGPCS (Ambiente, GET, POST, Cookie e Servidor) em um nível global, em que elas podem ser acessadas em qualquer escopo de qualquer programa PHP. Essa opção incentiva os programadores a escrever programas mais ou menos inconscientes da origem dos valores dos quais eles dependem, o que pode provocar comportamentos inesperados em ambientes bem-intencionados e deixar as portas abertas para invasores em ambientes mal-intencionados. Reconhecendo as perigosas implicações de segurança de register_globals
, essa opção foi desabilitada por padrão no PHP 4.2.0 e foi preterida e removida no PHP 6.$username
origina-se da sessão controlada pelo servidor, mas, em vez disso, um invasor pode fornecer um valor mal-intencionado para $username
como um parâmetro de solicitação. Com a opção register_globals
habilitada, esse código incluirá um valor mal-intencionado enviado por um invasor no conteúdo HTML dinâmico que ele gera.
<?php
if (isset($username)) {
echo "Hello <b>$username</b>";
} else {
echo "Hello <b>Guest</b><br />";
echo "Would you like to login?";
}
?>
safe_mode
é um dos recursos de segurança mais importantes no PHP. Quando safe_mode
está desabilitada, o PHP opera em arquivos com as permissões do usuário que a invocou, que muitas vezes é um usuário privilegiado. Embora a configuração do PHP com a opção safe_mode
desabilitada por si só não introduza uma vulnerabilidade de segurança, essa complacência adicional pode ser explorada por invasores em conjunto com outras vulnerabilidades para tornar as explorações ainda mais perigosas.session.use_trans_sid
faz com que o PHP transmita a ID de sessão na URL, tornando muito mais fácil para os invasores sequestrar sessões ativas ou enganar os usuários a usarem uma sessão existente que já está sob controle desses invasores.
...
EXEC CICS
INGNORE CONDITION ERROR
END-EXEC.
...
doExchange()
.
try {
doExchange();
}
catch (RareException e) {
// this can never happen
}
RareException
fosse lançado, o programa continuaria sendo executado como se nada incomum tivesse ocorrido. O programa não registra nenhuma evidência indicando a situação especial, potencialmente frustrando qualquer tentativa posterior de explicar o comportamento do programa.DoExchange()
.
try {
DoExchange();
}
catch (RareException e) {
// this can never happen
}
RareException
tivesse que ser lançada alguma vez, o programa continuaria a ser executado como se nada incomum tivesse ocorrido. O programa não registra nenhuma evidência que indique a situação especial, possivelmente frustrando qualquer tentativa posterior de explicar o comportamento do programa.doExchange()
.
try {
doExchange();
}
catch (RareException e) {
// this can never happen
}
RareException
tivesse que ser lançada alguma vez, o programa continuaria a ser executado como se nada incomum tivesse ocorrido. O programa não registra nenhuma evidência que indique a situação especial, possivelmente frustrando qualquer tentativa posterior de explicar o comportamento do programa.doExchange()
.
try {
doExchange();
}
catch (exception $e) {
// this can never happen
}
RareException
tivesse que ser lançada alguma vez, o programa continuaria a ser executado como se nada incomum tivesse ocorrido. O programa não registra nenhuma evidência que indique a situação especial, possivelmente frustrando qualquer tentativa posterior de explicar o comportamento do programa.open()
.
try:
f = open('myfile.txt')
s = f.readline()
i = int(s.strip())
except:
# This will never happen
pass
RareException
tivesse que ser lançada alguma vez, o programa continuaria a ser executado como se nada incomum tivesse ocorrido. O programa não registra nenhuma evidência que indique a situação especial, possivelmente frustrando qualquer tentativa posterior de explicar o comportamento do programa.
PROCEDURE do_it_all
IS
BEGIN
BEGIN
INSERT INTO table1 VALUES(...);
COMMIT;
EXCEPTION
WHEN OTHERS THEN NULL;
END;
END do_it_all;
Exception
, pode obscurecer exceções que merecem tratamento especial ou que não devem ser detectadas a essa altura no programa. A captura uma exceção excessivamente ampla destrói em essência a finalidade de exceções .NET com tipo definido, podendo tornar-se um procedimento particularmente perigoso se o programa crescer e começar a lançar novos tipos de exceções. Os novos tipos de exceção não receberão nenhuma atenção.
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()
for modificado de forma a lançar um novo tipo de exceção que deve ser tratado de maneira diferente, o bloco "catch" amplo impedirá que o compilador aponte a situação. Além disso, o novo bloco "catch" também passará a lidar com exceções dos tipos ApplicationException
e NullReferenceException
, o que não é a intenção do programador.Exception
, pode obscurecer exceções que merecem tratamento especial ou que não devem ser detectadas a essa altura no programa. A captura uma exceção excessivamente ampla destrói em essência a finalidade de exceções de Java com tipo definido, podendo tornar-se um procedimento particularmente perigoso se o programa crescer e começar a lançar novos tipos de exceções. Os novos tipos de exceção não receberão nenhuma atenção.
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()
for modificado de forma a lançar um novo tipo de exceção que deve ser tratado de maneira diferente, o bloco "catch" amplo impedirá que o compilador aponte a situação. Além disso, o novo bloco "catch" também passará a lidar com exceções derivadas de RuntimeException
, como ClassCastException
e NullPointerException
, o que não é a intenção do programador.Exception
ou Throwable
dificulta o trabalho de tratamento de erros e recuperação por parte dos chamadores. O mecanismo de exceção do Java está configurado para facilitar a tarefa dos chamadores de antecipar o que pode dar errado e escrever um código para lidar com cada circunstância excepcional específica. Declarar que um método lança uma forma genérica de exceção derrota esse sistema.
public void doExchange()
throws IOException, InvocationTargetException,
SQLException {
...
}
public void doExchange()
throws Exception {
...
}
doExchange()
introduz um novo tipo de exceção que deve ser tratado de forma diferente do que exceções anteriores, não haverá nenhuma maneira simples de fazer cumprir essa exigência.NullPointerException
é uma prática imprópria.NullPointerException
em três circunstâncias:NullPointerException
para sinalizar uma condição de erro.NullPointerException
por engano.
try {
mysteryMethod();
}
catch (NullPointerException npe) {
}
NullReferenceException
é uma prática imprópria.NullReferenceException
em três circunstâncias:NullReferenceException
para sinalizar uma condição de erro.NullReferenceException
por engano.
try {
MysteryMethod();
}
catch (NullReferenceException npe) {
}
finally
fará com que exceções sejam perdidas.finally
fará com que qualquer exceção que possa ser lançada no bloco "try" seja descartada.MagicException
lançada pela segunda chamada para doMagic
com true
transmitido para ela nunca será entregue para o chamador. A instrução de retorno dentro do bloco finally
fará com que a exceção seja descartada.
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
fará com que exceções sejam perdidas.finally
fará com que qualquer exceção que possa ser lançada no bloco "try" seja descartada.exception
lançada pela segunda chamada para doMagic
com True
transmitido para ela nunca será entregue para o chamador. A instrução de retorno dentro do bloco finally
fará com que a exceção seja descartada."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
não for lançado novamente, o thread em questão não poderá realmente ser desativado.ThreadDeath
só devem ser capturados se um aplicativos precisar de uma limpeza depois de ter sido finalizado de forma assíncrona. Se um erro ThreadDeath
for capturado, é importante que ele seja novamente lançado para que o thread realmente seja desativado. O objetivo de lançar ThreadDeath
é interromper um thread. Se ThreadDeath
for engolido, ele poderá impedir que um thread seja interrompido e resultar em um comportamento inesperado, pois, quem quer que tenha lançado ThreadDeath
originalmente, espera que o thread seja interrompido.ThreadDeath
, mas não volta a lançá-lo.
try
{
//some code
}
catch(ThreadDeath td)
{
//clean up code
}
throw
dentro de um bloco finally
rompe a progressão lógica via try-catch-finally
.finally
são sempre executados depois de seus blocos try-catch
correspondentes e são frequentemente utilizados para liberar recursos alocados, como identificadores de arquivos ou cursores de banco de dados. Lançar uma exceção em um bloco finally
pode ignorar o código de limpeza crítico, pois a execução normal do programa será interrompida.stmt.close()
é ignorada quando a FileNotFoundException
é lançada.
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
e javax.net.ssl.SSLPeerUnverifiedException
transmitem erros importantes relacionados a uma conexão SSL. Se esses erros não forem tratados explicitamente, a conexão poderá ser deixada em um estado inesperado e 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
ou Console.Error
no lugar de um recurso dedicado de registro em log dificulta o monitoramento do comportamento do programa.
public class MyClass {
...
Console.WriteLine("hello world");
...
}
Console.WriteLine()
.Console.WriteLine
pode indicar um descuido na mudança para um sistema de registro em log estruturado.os.Stdout
ou os.Stderr
no lugar de um recurso dedicado de registro em log dificulta o monitoramento do comportamento do programa.
...
func foo(){
fmt.Println("Hello World")
}
fmt.Println()
.os.Stdout
ou os.Stderr
pode indicar um descuido na mudança para um sistema de registro em log estruturado.System.out
ou System.err
no lugar de um recurso dedicado de registro em log dificulta o monitoramento do comportamento do programa.
public class MyClass
...
System.out.println("hello world");
...
}
System.out.println()
.System.out
ou System.err
pode indicar um descuido na mudança para um sistema de registro em log estruturado.process.stdout
ou process.stderr
no lugar de um recurso dedicado de registro em log dificulta o monitoramento do comportamento do programa.
process.stdin.on('readable', function(){
var s = process.stdin.read();
if (s != null){
process.stdout.write(s);
}
});
process.stdout.write()
.process.stdout
ou process.stderr
pode indicar um descuido na mudança para um sistema de registro em log estruturado.print
ou println
no lugar de um recurso dedicado de registro em log dificulta o monitoramento do comportamento do programa.
class MyClass {
...
println("hello world")
...
}
}
print
ou println
.
sys.stdout.write("hello world")
sys.stdout
ou sys.stderr
pode indicar um descuido na mudança para um sistema de registro em log estruturado.Kernel.puts
, Kernel.warn
ou Kernel.printf
em vez de um recurso de registro em log dedicado torna difícil monitorar o comportamento do programa.
...
puts "hello world"
...
Kernel.puts
.Kernel.puts
,Kernel.warn
or Kernel.printf
pode indicar um descuido na alteração para um sistema de registro em log estruturado.Logger
, mas registra informações em um fluxo de saída do sistema:
require 'logger'
...
logger = Logger.new($stdout)
logger.info("hello world")
...