2010-03-29 11 views
6

uso CodeIgniter, y tiene problemas con la piratería. ¿Es posible hacer que la inyección de SQL para el código de usuario abajo:Login ejemplo de código que ha sido cortado a través de la inyección de SQL, aunque mysql_real_escape_string ...

function process_login() 
{ 
    $username = mysql_real_escape_string($this->input->post('username'));  
    $password = mysql_real_escape_string(MD5($this->input->post('password'))); 

    //Check user table 
    $query = $this->db->getwhere('users', array('username'=>$username, 'password'=>$password)); 

    if ($query->num_rows() > 0) 
    { 
     // success login data 

Am I utilizando el mysql_real_escape_string mal, o qué?

+0

use htmlentities después de real_escape_string y mejor haga datos en formato binario –

+6

¿Cómo sabe que ha sido pirateado a través de SQL Injection? – Gumbo

+0

Depende del ataque. Si el hacker obtuvo acceso no autorizado a una cuenta, es posible que escuche las quejas de la víctima, pero de lo contrario es posible que nunca lo sepa. Si el pirata informático alteró los contenidos de la base de datos o abandonó las tablas por completo, se dará cuenta de cuándo el sistema deja de funcionar. – Anton

Respuesta

4

Eche un vistazo a this vieja pregunta.
yo usaría:

$sql = "SELECT * FROM users WHERE username = '?' AND password= '?'"; 
$dbResult = $this->db->query($sql, array($this->input->post('username')),array($this->input->post('password'))); 
+0

entonces, ¿no es necesario hacer mysql_real_escape_string de esta manera? –

+0

No, si usa enlaces de consulta en el método query(). http://codeigniter.com/user_guide/database/queries.html – systempuntoout

6

No se han publicado lo que no probablemente no es vulnerable a la inyección SQL. Aunque getwhere() podría estar haciendo stripslashes(), no estoy seguro.

Es probable que si hubo Inyección SQL que está en otra parte de su aplicación. El atacante podría usar esta vulnerabilidad para obtener su extremadamente débil md5() hash, descifrarlo y luego iniciar sesión. Use cualquier miembro de la familia sha2, sha-256 es una gran opción.

Si su sitio ha sido borrado, dudo seriamente que sea una inyección SQL. Es difícil automatizar la explotación de la inyección sql para desfigurar sitios web, pero es posible. Me aseguraría de que todas las bibliotecas y aplicaciones instaladas estén completamente actualizadas. Especialmente si tienes un CMS o foro. Puede ejecutar un escaneo OpenVAS en su sitio para ver si encuentra algún software antiguo.

+0

En realidad, debe usar PBKDF2 - Ejemplo de código de Explenation plus: http://www.itnewb.com/v/Encrypting-Passwords-with-PHP-for -Storage-Using-the-RSA-PBKDF2-Standard – Halcyon

+0

@Frits van Campen si es demasiado pesado para que un atacante lo levante, entonces es demasiado pesado para tus servidores. – rook

+0

PBKDF2 está diseñado especialmente para este propósito. sha-256 no es. No soy cripto-profesional, pero estoy dispuesto a confiar en su palabra. Hubo un artículo sobre esto en /. recientemente. http://ask.slashdot.org/story/11/06/05/0135206/Ask-Slashdot-Is-SHA-512-the-Way-To-Go – Halcyon

3

Si se trata de un truco en curso, entonces considere seriamente poner algún registro en su lugar para registrar el nombre de usuario/contraseña en un archivo en alguna parte. Si se trata de una inyección sql a través de este fragmento de inicio de sesión, aparecerá en este nuevo archivo de registro en algún lugar. Y mientras lo hace, si puede, registre la consulta SQL generada también.

En cualquier caso, recuerde que mysql_real_escape_string() solo cubre los metacaracteres de mysql: comillas simples, comillas dobles, punto y coma, etc ... Todavía es completamente posible hackear la función de inicio de sesión mediante el cambio de un parámetro booleano . Imposible decir si su función "getwhere" es vulnerable, pero considere el caso donde la contraseña presentada es "xyz OR (1 = 1)". La consulta generada podría terminar buscando algo así como

SELECT id FROM users WHERE users=someusername AND password=xyz OR (1=1); 

consulta perfectamente válido, y también ha pasado por mysql_real_escape_string intacta, ya que no contiene ninguno de los meta-caracteres críticos.

+2

la consulta generada tendrá comillas simples alrededor del someusername y de las cadenas xyz, por lo que en este caso no se dañará –

1

Es mi entendimiento de que Active Records escaparán adecuadamente los valores para usted. Por lo tanto, con $query = $this->db->getwhere() NO es necesario que use mysql_real_escape_string().

embargo, siempre se debe utilizar algún tipo de validación del controlador. En particular, puede limitar el nombre de usuario y la contraseña a ciertos caracteres a través de una expresión regular. Esto siempre se sugiere.

Además, si te golpean con ataques típicos a menudo, luego usa PHPPS. Es un sistema de detección de intrusiones que te ayudará a evitar que los ataques causen realmente daños, ya que puedes generar un error o aviso de algún tipo.

También puede desear ver este tutorial sobre cuestiones de seguridad. http://net.tutsplus.com/tutorials/php/codeigniter-from-scratch-security/

1

Si todas sus funciones y accesadores hacen lo que su nombre parece sugerir, entonces este script no es vulnerable a SQL Injection.

En cuanto a si está utilizando mysql_real_escape_string correctamente ... sí y no. Sí, tienes la idea correcta, pero en realidad la estás utilizando en exceso. Si MD5 la contraseña, esa entrada ahora está limpia y no se puede usar para la inyección, por lo que la llamada mysql_real_escape_string es superflua. Así que esto estaría bien:

$username = mysql_real_escape_string($this->input->post('username'));  
$password = MD5($this->input->post('password')); 

Como se mencionó anteriormente, MD5 es un algoritmo hash bastante débil por sí mismo. Mire en SHA y salando un hash.

Para contrarrestar una respuesta anterior publicada, si un usuario ingresa "xyz OR (1 = 1)" como contraseña, eso no representa ninguna amenaza para su script por dos razones.

1) MD5 hash convertiría que a un hash inofensivo (por ejemplo, 'd131dd02c5e6eec4693d9a0698aff95c'), por lo que la consulta algo en la línea de SELECT id FROM users WHERE users='username' AND password='d131dd02c5e6eec4693d9a0698aff95c';

2) mysql_real_escape_string inyecciones previene 'cadena', que es inyecciones que requerirían una comilla simple o doble para salir de la consulta SQL esperada, pero no evita (por ejemplo) la inyección con entrada numérica, que necesitaría usar la conversión de tipo para bloquear.

Todo depende de su llamada "$ this-> db-> getwhere". Si eso solo genera la consulta normalmente sin hacer nada funky (como pelar citas, o tratar cadenas como enteros [que lanzarían un error de todos modos], etc.) simplemente no eres vulnerable en este script. Si pudieras dar más detalles sobre el 'tipo' de pirateo que has experimentado, probablemente podríamos darte una guía sobre dónde buscar. ¿Estabas desfigurado?

No he jugado con CodeIgnitor, pero espero que sus funciones integradas de entrada/base de datos no hagan nada raro, así que a menos que haya editado usted mismo la función getwhere, probablemente esté bien en este punto en particular.

+1

En realidad, debería usar PBKDF2 - Ejemplo de código de Explenation plus: http://www.itnewb.com/v/Encrypting-Passwords- with-PHP-for-Storage-Using-the-RSA-PBKDF2-Standard – Halcyon

+0

bcrypt es otra buena opción para el almacenamiento de contraseñas http://codahale.com/how-to-safely-store-a-password/ –

+0

Nunca discutas eso una cierta variable "es segura debido a su posible contenido". Si lo hace, entonces debe inspeccionar todas las variables posibles, independientemente de si realmente necesita o no escaparse, y todo su código se ve inseguro al principio, porque la mitad del escape parece haber desaparecido. Así que nunca discutas que algo no necesita escapar, ¡siempre ** escapar! – Sven

0

El código que proporcionó no es vulnerable a la inyección SQL, pero nunca debe poner contraseñas en las consultas, ni siquiera hash, porque no puede estar seguro si la consulta se guarda en el registro del servidor o no, y generalmente no t tener control sobre quién puede tener acceso a eso.
Consulta/carga el registro del usuario por nombre de usuario, y luego compara el hash de la contraseña en $ _POST con eso.

5

base de datos

A juzgar por su código Veo que estás no utilizando la última versión CI (2.0.2 a partir del 06/12).

Como se indica en la changelog la función getwhere() (que ahora se llama get_where()) ha sido abandonado como para la versión 2.0.
En cuanto a la aplicación de everty, se recomienda encarecidamente actualizar su versión actual, ya que ha habido muchas correcciones de errores mientras tanto y siempre debe confiar en la versión más segura disponible.

mysql_real_escape_string generalmente se considera "suficiente" para proporcionar un buen nivel de seguridad en sus consultas, pero como sucedió con su predecesor (mysql_escape_string) no es 100% seguro contra todo tipo de ataque, por lo que confiamos plenamente en eso no es la mejor práctica alrededor. Aunque es seguro, todavía hay ataques que pueden pasar este filtro.
Compruebe, entre los muchos, this question on SO para obtener más información al respecto.

En codeignier: Si estaba desarrollando su aplicación personalizada, sugeriría que al menos utiliza las extensiones mysqli o, mejor aún, la clase PDO; declaraciones preparadas son indudablemente más seguras y deberían ser favorecidas sobre todo lo demás.

Pero estamos en el contexto del marco, y Codeigniter viene con 3 excelentes maneras de consultar de forma segura su base de datos, aplicando la herramienta correcta a la entrada correcta sin tener que preocuparse por eso. Estoy hablando de query bindings and manual escaping with $this->db->escape() family y Active Record Class
Puede encontrar ejemplos de uso en las direcciones URL que acabo de vincular, o leer las respuestas de otros compañeros aquí, por lo que no entraré en los detalles de cada procedimiento en esta publicación.

contraseña

En cuanto a su contraseña, como se ha dicho por otros usuarios, md5() es una alghoritm hash ahora defectuoso. Hay tablas de arco iris por ahí que puede descifrar la contraseña MD5 en un período relativamente corto de tiempo, por lo que está mejor con algorhytms hash mayor nivel de seguridad, como sha1() o sha256, sha512, and other

en CodeIgniter: CodeIgniter viene con una clase security helper, que le proporciona una función útil, do_hash() (podría ser dohash() en su instalación anterior), que puede recibir el algoritmo hash. como parámetro (actualmente creo que solo admite md5 y sha1) y de forma predeterminada es sha1().

Otras observaciones

No estoy del todo claro por qué culpar a su nombre de usuario para sus inyecciones SQL. ¿Son esos los únicos 2 formularios en toda su aplicación?
No proporciona la información para indicar si usa los parámetros $ _GET o si sigue la segmentación del URI nativo, pero creo que está haciendo esto, así que supongo que está a salvo de este punto de vista.

Debería asegurarse de que no haya ningún otro formulario en su sitio web que contenga entradas ingresadas en la base de datos, de lo contrario puede asegurar su inicio de sesión cuánto desea, pero alguien podría penetrar a través de una puerta trasera y leer desde allí su tabla de base de datos y inicie sesión en su sitio web de una manera "legítima".

Además, puede haber otra fuente de intrusión, como una cookie comprometida, por ejemplo. Como consejo, siempre que elijas utilizar un marco (y te estás haciendo un favor mayor que si lo hicieras desde cero) tendrías que usar MÁS de sus características, especialmente cuando se trata de seguridad. Es una pregunta enorme y muy delicada, por lo que DEBE dar a este tema su máxima prioridad, y un marco bien desarrollado, con una gran comunidad y actualizaciones frecuentes es lo más cercano a la seguridad que puede obtener.
Por lo tanto, se le aconseja actualizar su instalación de CI (las guías se pueden encontrar here en su manual. Elija su versión y siga las instrucciones), siempre use las mejores herramientas que se le dan para cada tarea, y no piense que bloquear su puerta lo mantendrá a salvo de una intrusión desde sus ventanas. Siempre revise a fondo e investigue todas las posibles causas.

Adición tardía: No olvide XSS, CSRF, sesiones de fijación y otros problemas de seguridad.

+0

Esta es una excelente respuesta. – Nacho

0

El código parece ser resistente a los ataques de inyección. Estás tomando md5 del campo de contraseña que deja fuera cualquier ataque de inyección en ese campo. El campo vulnerable es el nombre de usuario del que está escapando de todos modos. ¿Estás seguro de que esto es un ataque de inyección?

¿Hay algún otro campo como campos señal_acceso pasado a lo largo de prevenir CSRF

siguientes son causas probables de comportamiento extraño:

  • está utilizando el controlador mysqli en la configuración de base de datos y escapar cadena de acuerdo con lib MySQL . Intente proporcionar $this->db->conn_id como segundo parámetro al mysql_real_escape_string y revise los registros de php en busca de advertencias.
  • mysql_real_escape_string necesita connection link identifier como segundo parámetro. Si no lo proporciona, experimentará un comportamiento extraño. He sufrido esto con Codeigniter. En mi caso, mysql_real_escape_string devolvía cadenas vacías. Si el caso es el mismo para usted, verifique que no tenga contraseñas vacías ni nombres de usuario en su tabla de usuarios (es menos probable).
Cuestiones relacionadas