Categories
PHP Seguridad Sql Injection Web

Ejercicio de fin de Semana: Evitar SQL Injection con PHP

A través de tweako (visto hace algunos minutos en menéame) llegué a un artículo -en inglés- que explica como protegerse de ataques de Inyección de SQL con PHP. En el mencionado artículo, en la última parte aparecen las siguientes dos porciones de código:

php:

<?php

# Ok, so I'm going to oversecure a query to the database that selects an article
# by using the given article ID.
# Here is the code.

//Database connection is present
//Make sure that the id is actually given

if (isset($_GET['id']))
{
        $id = $_GET['id'];
}
else
{
        die('Please provide an article ID');
}
 
//Make sure that its an integer
if (is_integer($id))
{
        die('Please enter a valid article ID');
}
 
//Validate that its in between the ranges 1 and 10,000
if ($id < 1 || $id > 10000)
{
        die('Please enter a valid artile ID');
}
 
//Construct the query
$SQL = "SELECT * FROM posts WHERE postID = '".$id."'";

echo $SQL; // Línea agregada

?>

php:

<?php

# This next one will validate a username before its entered into the database.

//Database connection is present
//Make sure that the id is actually given
if (isset($_GET['username']))
{
        $username = $_GET['username'];
}
else
{
        die('Please provide a username');
}
//Get the length of the username
$length = strlen($username);
//Validate the length
if ($length < 3 || $length > 20) // parte modificada
{
        die('Please enter a username between 3 and 20 characters long');
}
//Make sure that its safe to enter the database.
$username = mysql_real_escape_string($username);
//Construct the query
$SQL = "SELECT * FROM username WHERE username = '".$username."'";
//Show the username
echo 'Username: '.stripslashes($username);
//Send the query and close the connection to the database

?>

Los códigos mostrados ¿son correctos? si no es así, ¿qué errores tiene?.

Categories
PHP Quiz Seguridad Web WordPress XSS

WordPress, XSS y CSRF – Parte 2

En la primera parte vimos un poco de los problemas que tiene usar $_SERVER['PHP_SELF'] sin ningún tipo de validación. Para esta segunda parte, he preparado un pequeño quiz que básicamente refleja los problemas reportados en WordPress.

La siguiente porción de código es una versión resumida del contenido de los archivos wp-includes/vars.php y wp-includes/functions.php (función wp_nonce_ays):

php:

<?php

$PHP_SELF = $_SERVER['PHP_SELF'];
if ( preg_match('#([^/]+\.php)$#', $PHP_SELF, $self_matches) ) {
        $pagina_actual = $self_matches[1];
} else {
        $pagina_actual = 'wp.php';
}

?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="es" lang="es">     
<head>
        <title>Wordpress demo</title>
</head>
<body id="main">
        <form action="<?php echo $pagina_actual; ?>" method="post">
                <input name="foo" id="foo" type="text" tabindex="0" />
                <input name="postback" id="postback" type="submit" value="Enviar" tabindex="1" />
        </form>
</body>
</html>

¿Algún ejemplo que aproveche el bug que existe en el código de prueba? (de preferencia que funcione en varios navegadores)

Nota: Por motivos de seguridad no voy a facilitarles una página de prueba, puesto que por más que ponga los ejemplos en un subdominio, éstos son accesibles también desde el dominio principal, haciendo vulnerable a XSS mi instalación de WordPress 😀 --quise usar Dreamhost, pero para este caso no sirve.

Categories
MySQL PHP

Tip: Ahorrar consultas en MySQL

Seguramente los usuarios más experimentados ya están al tanto de que, a partir de MySQL 4.1, se puede usar una sentencia ON DUPLICATE KEY UPDATE, que permite actualizar los campos que se especifiquen si es que falla la inserción al no cumplirse las restricciones PRIMARY KEY o UNIQUE.

Por ejemplo, el siguiente código:

php:

function recommend( $post ) {
        global $wpdb;
        if( array_search( $post, $_SESSION['recpost'] ) == NULL && is_numeric( $post ) ) {
                $r = mysql_query( 'SELECT * FROM '.$wpdb->prefix.'recit WHERE id_post = '.$post );
                if( mysql_num_rows( $r ) == 0 ) {
                        $q = 'INSERT INTO '.$wpdb->prefix.'recit SET rec = rec+1, id_post = '.$post;
                }
                else {
                        $q = 'UPDATE '.$wpdb->prefix.'recit SET rec = rec+1 WHERE id_post = '.$post;
                }
                $wpdb->query( $q );
                $_SESSION['recpost'][] = $post;
        }
}

Se puede resumir en:

php:

function recommend( $post ) {
        global $wpdb;
        if( array_search( $post, $_SESSION['recpost'] ) == NULL && is_numeric( $post ) ) {
                $q = "INSERT INTO {$wpdb->prefix}recit (rec, id_post) VALUES (0, '$post')
                                ON DUPLICATE KEY UPDATE rec = rec + 1"
;
                $wpdb->query( $q );
                $_SESSION['recpost'][] = $post;
        }
}

En fin, espero que sea de utilidad para alguien 😉

Categories
PHP Seguridad Sql Injection XSS

Filtros genéricos y la seguridad

Hace algún tiempo ya había comentado que este tipo de funciones en general son de poca utilidad y dan una falsa sensación de seguridad a los que las usan.

php:

function antiinjection($str) {
        $banwords = array ("'", ",", ";", "--", " or ", ")", "(", " OR ", " and ", " AND ","\n","\r");
        if ( eregi ( "[a-zA-Z0-9]+", $str ) ) {
                $str = str_replace ( $banwords, '', ( $str ) );
        } else {
                $str = NULL;
        }
        $str = trim($str);
        $str = strip_tags($str);
        $str = stripslashes($str);
        $str = addslashes($str);
        $str = htmlspecialchars($str);
        return $str;
}

¿Qué problemas le encuentran al código mostrado?

Categories
PHP Seguridad Web

Marzo, el mes de los bugs de PHP

Tal y como lo había comentado Stefan Esser luego de su salida de PHP Security Response Team, él revela en una entrevista realizada en securityfocus.com, que en marzo se liberarán alrededor de 31 bugs presentes en el código de PHP.

We will disclose different types of bugs, mainly buffer overflows or double free(/destruction) vulnerabilities, some only local, but some remotely trigger-able (for example, because they are in functions usually exposed to user input). Additionally there are some trivial bypass vulnerabilities in PHP's own protection features. Only holes within the code shipped with the default distribution of PHP will be disclosed. That means we will not disclose holes in extensions that only exist in PECL, while we are sure that those contain vulnerabilities, too. Most of the holes were previously disclosed to the vendor, but not all.

Probablemente se generará mucha polémica por la liberación de estos bugs, habrá que ver como se desenvuelven las cosas.