SQLi и mysqli_real_escape_string

dakata__92

Super Moderator
Колеги, попаднах на един проект в който се ползва real_escape_string вместо prepare statements. Не си заслужава да отделям време за пренаписването на всичко. Търся си по-читав метод за филтриране на SQLi.
Код:
public function escape($string)
{
	if (!isset($string) || empty($string)) {
		return null;
	}
    if (is_numeric($string)) {
		return $string;
	}
	
	$nonDisplayables = array(
        '/%0[0-8bcef]/',        // URL encoded 00-08, 11, 12, 14, 15
        '/%1[0-9a-f]/',         // url encoded 16-31
        '/[\x00-\x08]/',        // 00-08
        '/\x0b/',               // 11
        '/\x0c/',               // 12
        '/[\x0e-\x1f]/',        // 14-31
        '/\27/'
    );
	$data = '';
	foreach ($nonDisplayables as $regex) {
		$data = preg_replace( $regex, '', $data);
	}
	
    return mysqli_real_escape_string($data);
}
 
uphero каза:
Чисти всичко което не е букви и цифри и не го мисли :D
Честно да ти кажа си го мислех и аз. :D :D :D Проекта е доста стар и разчита на тази функция, а за prepare statements трябва да се пренапише светилата. Търся си нещо една идея по-сигурно за филтриране на данните.
 
Тази функция работи ли, не връща ли винаги празен низ заради това $data = '';? (то това е най-сигурното решение де :D )
 
djman каза:
Тази функция работи ли, не връща ли винаги празен низ заради това $data = '';? (то това е най-сигурното решение де :D )

Е как бе нали отдолу пълните датата във foreach-a :D
 
deam0n каза:
djman каза:
Тази функция работи ли, не връща ли винаги празен низ заради това $data = '';? (то това е най-сигурното решение де :D )

Е как бе нали отдолу пълните датата във foreach-a :D

няма да върне нищо
http://phpfiddle.org/main/code/8kbe-gf0c
 
Извинявам се!!! Копирал съм функцията от тестови клас не реалната:
Код:
function escape($string)
{
	if (!isset($string) || empty($string)) {
		return null;
	}
    if (is_numeric($string)) {
		return $string;
	}
	
	$nonDisplayables = [
        '/%0[0-8bcef]/',        // URL encoded 00-08, 11, 12, 14, 15
        '/%1[0-9a-f]/',         // url encoded 16-31
        '/[\x00-\x08]/',        // 00-08
        '/\x0b/',               // 11
        '/\x0c/',               // 12
        '/[\x0e-\x1f]/',        // 14-31
        '/\27/'
    ];
	$data = '';
	foreach ($nonDisplayables as $regex) {
		$data = preg_replace( $regex, '', $string);
	}
	
    return $data;
}
Колегата, над мен е познал. Както и да е. Просто търся вариант да я подобря или заменя. Нямам и доверие в сегашната и форма.
 
Ако това е истинската функция, то и тя не е вярна ‑ ще замести с "" само последното nonDisplayable...
 
Подозирам, че вместо това:

Код:
	$data = '';
	foreach ($nonDisplayables as $regex) {
		$data = preg_replace( $regex, '', $string);
	}
	
    return $data;

си имал предвид това:
Код:
	$data = $string;
	foreach ($nonDisplayables as $regex) {
		$data = preg_replace( $regex, '', $data);
	}
	
    return $data;

Но не виждам защо ти е да ползваш нова променлива, вместо направо в $string да ескейпваш. php нали е copy-on-write, няма опасност да омажеш външния scope.
 
Ако е голям проект, според мен не се мъчи с някакви такива функции да се опитваш да покриеш всеки един случай - безсмислено е.

В такъв случай разучи проекта и отсей местата, където може да се направи инжекция и там си прави валидация на данните преди да ги пуснеш към заявката.
Знам, че искаш да минеш с промяната на едно място и да си решиш проблемите навсякъде, но предвид, че е стар проект ме съмнява да има качествени тестове, с които да се докаже, че си се защитил.

Върви стъпка по стъпка - от най-често използваните места, до най-рядко.
 
Колеги, търся вариант да подобря и подсигуря работата mysqli_real_escape_string. Преобразувам стринга винаги в енкодинг UTF-8, чарсета на базата също е подаден в UTF-8. Идеята ми е да избегна по-екзотичните заявки от рода на:

"\xbf\x27 OR 1=1 /*"
縗' OR 1=1 /*

С тези примерни атаки се справих, като оправих чарсета на базата. Не бе подаден такъв. Търся минимално влагане на време и ресурс. Предстои пълно пренаписване на системата, въпроса е, че на първо време остана само тази "дупка" за подобряване.
 

Горе