User Defined Errors

• Userland code may trigger custom errors

trigger_error(
 "something went wrong",
 E_USER_WARNING);

• These errors may be handled with a custom error handler function

function myHandler($code, $text, $file, $line) {
 
 if ($code == E_USER_WARNING) {
 echo 'WARNING: ' .
 htmlspecialchars($text);
 return true;
 }
 
 return false;
}

• If the custom error handler function returns true, php´s error handling does not kick in

• Custom error handler function needs to be registered using set_error_handler(“myHandler”).

Example

<?php
 function myErrorHandler($errno, $errstr, $errfile, $errline) {
 echo "<b>Custom error:</b> [$errno] $errstr<br>";
 echo " Error on line $errline in $errfile<br>";
 }

set_error_handler("myErrorHandler");
 
 $test=2;

if ($test>1) {
 trigger_error("A custom error has been triggered");
 }
?>

Error Display

• By default, all errors included in error_reporting are reported in php´s output

• This behavior can – and should – be deactivated on production systems using the display_errors = off php.ini setting

• Errors should still be logged, using the log_errors = on php.ini setting

• The error log is a file set in the error_log php configuration setting. if set to syslog, errors are logged in the system log independent on the operating system used.

Error Levels

• PHP supports several types of errors

o notices at runtime
o errors during parsing (prevents code execution)
o warnings at runtime
o fatal errors at runtime (stop code execution)
o Core errors and warnings
o user-defined notices, warnings, and errors

• php configuration setting error_reporting, or php’s error_reporting() function may be used to define which kinds of errors shall be reported

• Value is an integer, or – much more convenient – a bitmask based on pre-defined constants

o E_NOTICE, E_PARSE, E_WARNING, E_ERROR

o E_CORE_WARNING, E_CORE_ERROR

o E_USER_NOTICE, E_USER_WARNING ,E_USER_ERROR

o E_STRICT(„best practices“ notices)

o E_DEPRECATED (features that might disappear in future php versions)

o E_ALL(everything) o and some more

• Typical production setting: E_ALL & ~E_DEPRECATED & ~E_STRICT

Exception Handling

Exception handling is used to change the normal flow of the code execution if a specified error (exceptional) condition occurs. This condition is called an exception.

Exceptions or errors (more on that see below) end code execution, unless they are handled with try-catch.

try {
// code that throws an Exception
} catch (Exception $ex) {
// Exception is handled, code
continues
}

Several catch statements may be used to differentiate between several kinds of exceptions and errors.

try {
// code that throws an Exception
} catch (CustomExceptionClass $ex) {
// custom Exception is handled
} catch (Exception $ex) {
// Exception is handled
} catch (Error $err) {
// Error is handled
}

Several errors may be handled with the same code.

try {
// code that throws an Exception
} catch (Exception | CustomException $ex)
{
// custom Exception and Exception
}

Optional finally block contains code that runs after the trycatch block, no matter whether an error was caught or not

This is what normally happens when an exception is triggered:

  • The current code state is saved
  • The code execution will switch to a predefined (custom) exception handler function
  • Depending on the situation, the handler may then resume the execution from the saved code state, terminate the script execution or continue the script from a different location in the code

Error Class

• Since php 7, many errors php reports now throw an error exception, not a fatal error as before.

• Subclasses of error exist for the specific type of error, such as parseerror or typeerror.

• To facilitate backwards compatibility, error is not derived from exception.

• Both error and exception implement the throwable interface

Escape Output

• One of two fundamental security rules: (1) filter and validate all input; (2) escape output

• Always escape outside data unless previously filtered

• Typical output formats that require escaping when containing user data: html, json, sql

•  Never rely on client side (javascript) filtering

• Functions used to escape data before outputting within html: htmlspecialchars() htmlentities() strip_tags()

Input Filtering

• Input is everything that comes as part of the http request

• Some data does not seem to be input, but may contain data originating from the user, thus must be considered as input (ex: session data that was originally supplied by the user)

Character Set

• Risk

 attack vectors may employ a non-standard char set (ex: utf-8 encoded) that may be missed by filtering, but executed by the browser

• counter

 Use the same char set for filtering as the target procedure

 convert charsets prior to filtering content-type: text/html; charset=”utf-8″

 use php’s filter extension

 use filters native to the database (ex: db quoting functions)

Email Injection

Email injection is a security vulnerability that can occur in Internet applications that are used to send email messages. It is the email equivalent of HTTP Header Injection. Like SQL injection attacks, this vulnerability is one of a general class of vulnerabilities that occur when one programming language is embedded within another.

Counter Measures

• Do not provide open relays

• Open the smtp port only if essential

• Use a ‘tarpits’ technique to slow requests as a means of dissuading attacks

escapeshellcmd

escapeshellcmd() escapes any characters in a string that might be used to trick a shell command into executing arbitrary commands. This function should be used to make sure that any data coming from user input is escaped before this data is passed to the exec() or system() functions, or to the backtick operator.

Following characters are preceded by a backslash: &#;`|*?~<>^()[]{}$\, \x0A and \xFF. ‘ and ” are escaped only if they are not paired. In Windows, all these characters plus % and ! are replaced by a space instead.

<?php
 $command = './configure '.$_POST['configure_options'];
 $escaped_command = escapeshellcmd($command);
 system($escaped_command);
 ?>