Topic: Ar apsaugotų nuo SQL injekcijų?

<?php

class sql_inject
{
    var $urlRedirect;
    var $bdestroy_session;
    var $rq;
    var $bLog;

    function sql_inject($mLog=FALSE,$bdestroy_session=FALSE,$urlRedirect=FALSE)
    {
        $this->bLog = (($mLog!=FALSE)?$mLog:'');
        $this->urlRedirect = ($urlRedirect);
        $this->bdestroy_session = $bdestroy_session;
        $this->rq = '';
    }

    function test($sRQ)
    {
        $this->rq = $sRQ;
        $sRQ = strtolower(urldecode($sRQ));
        $sRQ = str_replace( chr(0) , '' , $sRQ );
        $aValues = array();
        $aTemp = array();
        $aWords = array();
        $aSep = array(' and ',' or ');
        $sConditions = '(';
        $matches = array();
        $sSep = '';
        
        $sql_inject_patterns = array(
        '--',
        '\/\*',
        '\*\/',
        '\'',
        '"',
        '(union([\s\+\(\n\r\t]+)(select|all))',
        '[\s\+\n\r\t\(]+select[\s\+\n\r\t\)\'"`]+',
        '[\s\+\n\r\t\)`]+where[\s\+\n\r\t\(`]*',
        '[\s\+\n\r\t\)\'"`]+(from|regexp|rlike|delete|update|insert|truncate|drop|create|rename)[\s\+\n\r\t\(`]+',
        'exec',
        'cmd',
        'xp_',
        'information_schema\.',
        '[\s\+\n\r\t\)\'"`]*(or|and)[\s\+\n\r\t\(\'"]+(.*?)[\s\+\n\r\t\'"]*[=<>]+[\s\+\n\r\t\'"]*(.*?)',
        '(concat|load_file|mid|like|ord|ascii|lower|lcase|find_in_set|substring|benchmark|md5)[\s\+\n\r\t]*\('
        );
        
        if (is_int((strpos($sRQ,"#")))&&$this->_in_post('#')) return $this->detect();
        if (preg_match('/' . implode('|', $sql_inject_patterns) . '/is', $sRQ, $regs)) return $this->detect();

        if (is_int(strpos($sRQ,';'))){
            $aTemp = explode(';',$sRQ);
            if ($this->_in_post($aTemp[1])) return $this->detect();
        }

        $aTemp = preg_split('/[\s\+\)]+where[\s\+\(]*/i', $sRQ, -1, PREG_SPLIT_NO_EMPTY);
        if (count($aTemp)==1) return FALSE;
        $sConditions = $aTemp[1];
        $aWords = explode(" ",$sConditions);
        if(strcasecmp($aWords[0],'select')!=0) $aSep[] = ',';
        $sSep = '('.implode('|',$aSep).')';
        $aValues = preg_split($sSep,$sConditions,-1, PREG_SPLIT_NO_EMPTY);

        foreach($aValues as $i => $v)
        {
            if (is_int(strpos($v,'=')))
            {
                 $aTemp = explode('=',$v);
                 if (trim($aTemp[0])==trim($aTemp[1])) return $this->detect();
            }

            if (is_int(strpos($v,'<>')))
            {
                $aTemp = explode('<>',$v);
                if ((trim($aTemp[0])!=trim($aTemp[1]))&& ($this->_in_post('<>'))) return $this->detect();
            }
        }

        if (strpos($sConditions,' null'))
        {
            if (preg_match("/null +is +null/",$sConditions)) return $this->detect();
            if (preg_match("/is +not +null/",$sConditions,$matches))
            {
                foreach($matches as $i => $v)
                {
                    if ($this->_in_post($v))return $this->detect();
                }
            }
        }

        if (preg_match("/[a-z0-9]+ +between +[a-z0-9]+ +and +[a-z0-9]+/",$sConditions,$matches))
        {
            $Temp = explode(' between ',$matches[0]);
            $Evaluate = $Temp[0];
            $Temp = explode(' and ',$Temp[1]);
            if ((strcasecmp($Evaluate,$Temp[0])>0) && (strcasecmp($Evaluate,$Temp[1])<0) && $this->_in_post($matches[0])) return $this->detect();
        }
        return FALSE;
    }

    function _in_post($value)
    {
        foreach($_POST as $i => $v)
        {
             if (is_int(strpos(strtolower($v),$value))) return TRUE;
        }
        return FALSE;
    }

    function detect()
    {
        if ($this->bLog)
        {
            $fp = @fopen($this->bLog,'a+');
            if ($fp)
            {
                fputs($fp,"\r\n".date("d-m-Y H:i:s").' ['.$this->rq.'] from: '.$this->sIp = getenv("REMOTE_ADDR").'; ServerName: '.$this->servAd = getenv("SERVER_NAME"));
                fclose($fp);
                
            }
        }
        if ($this->bdestroy_session) @@session_destroy();
        if ($this->urlRedirect!=''){
             if (!headers_sent())  header("location: $this->urlRedirect");
        }
        return TRUE;
    }
}



if ($_SERVER["QUERY_STRING"] != "")
{
  $log = '/injections/sql.log' ; /// Surasau SQL injekcija
  $redirect = "../index.php" ; /// SQL injekcijos atveju pakraunamas puslapis
  $sql = new sql_inject($log,TRUE,$redirect);
  $sql->test($_SERVER["QUERY_STRING"]);
}
?>

Ar apsaugotų nuo sql injekcijų šitoks kodas?

Re: Ar apsaugotų nuo SQL injekcijų?

O ne geriau naudoti jau parašytas ir milijardus kartų ištestuotas funkcijas? Rašyti savo gali nebent tuo atveju jei žinai VISUS galimus sql injekcijos variantus.

MongoDB Certified Developer
MongoDB Certified DBA
Zend Certified Engineer

3 (edited by xeranas 2011-09-23 14:10:23)

Re: Ar apsaugotų nuo SQL injekcijų?

Jei iš čia paėmiai: http://www.phpclasses.org/package/1341- … tacks.html nepamiršk description'o iki galo perskaityti:

Notice: this class recognise only some of the known types of SQL injection methods and so it is not yet ready to deal with all possible ways to perform this kind of attack.

Datos nepastebėjau bet spėju kad klasė jau seniausiai yra out-dated. Jei nežinai kas yra ta SQL injection ir kaip ji veikia neapsaugos joks kodas...

No warning? No action? I hate this situation!

4 (edited by neturiuVardo 2011-09-23 20:02:08)

Re: Ar apsaugotų nuo SQL injekcijų?

Kas čia per.. O kuom mysql_real_escape_string blogai?

Re: Ar apsaugotų nuo SQL injekcijų?

neturiuVardo wrote:

Kas čia per.. O kuom mysql_real_escape_string blogai?

Na mysql_real_escape_string() nėr blogai, jeigu teisingai naudoji (-;