Функцията clean_query се извиква от get_sql_for_clause. При четене на кода на функцията ще видим, че работата на тази функцията е да създава клаузи за условието в SQL заявка, по-специално нейната работа ще бъде да обработва получените данни, да комбинира тези данни в условие в SQL заявката и да ги върне към родителската функция. Така можем да контролираме данните за връщане на тази функция, което означава, че можем да контролираме SQL заявката и да изпълним SQL инжекция.

Анализ

Във версия 5.8.3 на Wordpress e поправен този бъг. Сравнявайки промените, можем да видим, че във функцията clean_query е добавена проверка $query[‘field’] преди обработката на променливата $query[‘terms’].

sql injection in wordpress

Функцията clean_query се извиква от get_sql_for_clause. При четене на кода на функцията ще видим, че работата на тази функцията е да създава клаузи за условието в SQL заявка, по-специално нейната работа ще бъде да обработва получените данни, да комбинира тези данни в условие в SQL заявката и да ги върне към родителската функция. Така можем да контролираме данните за връщане на тази функция, което означава, че можем да контролираме SQL заявката и да изпълним SQL инжекция.

sql injection in wordpress

Връщайки се към функцията clean_query, без тази промяна, по подразбиране стойностите в $query[‘terms’] просто ще бъдат премахнати и след това ще се извикат $this->transform_query( $query, ‘term_taxonomy_id’) ;.

За да се избегне if, $query[‘taxonomy’] трябва да е празна или стойност за is_taxonomy_hierarchical да върне false.

sql injection in wordpress

Във функцията transform_query ще провери $query['field'] == $resulting_field, така че ако променливата $query['field'] е term_taxonomy_id, тогава можем да излезем от функцията, без да променяме $query ['terms'] стойност на променливата. (За сравнението тук се използва == и страда от вратичката на слаби сравнения. В някои случаи тази грешка може да се използва за създаване на условно сравнение по желание).

sql injection in wordpress

След излизане от функцията, интерпретаторът ще се върне на мястото, където е извикана функцията clean_query, което е функцията get_sql_for_clause, стойността в променливата $query['terms'] ще се използва директно като условие на SQL заявката и водеща към SQL инжекция.

sql injection in wordpress

Така в обобщение, за да се случи SQL инжекция, трябва да бъдат изпълнени две условия: $query['field'] is term_taxonomy_id $query['taxonomy'] е празна или is_taxonomy_hierarchical($query['taxonomy']) === false води до следната грешка:

sql injection in wordpress

Експлойт

Въпреки че това е грешка в ядрото на Wordpress, не задейства грешката, така че трябва да се обърнем към намиране на грешки в плъгини и теми. Плъгинът/темата ще извика класа WP_Query, когато искаме да направиме заявка към базата данни, начинът да разпознаем грешката от изходния код е, когато използваме WP_Query($data) и $data е нещо, което можем да контролираме.

Например WP_Query(json_decode($_POST[‘query_vars’])), тогава товарът ще изглежда така:

query_vars={“tax_query”:{“0”:{“field”:”term_taxonomy_id”,”terms”:[“”]}}} or query_vars={“tax_query”:{“0”:{“taxonomy “:”nav_menu”,”field”:true,”terms”:[“”]}}}

Когато създаваме среда за тестване на грешки, активирането на функцията DEBUG ще направи възможно откриването на SQL инжекция базирана на грешки:

Заключение

В корекцията на Wordpress е добавена проверка на $query[‘field’], в противен случай $query[‘terms’] ще се преобразува в цяло число, така че SQLi да не може да се случи.

Поради големия брой плъгини и теми за WordPress, нашият екип се фокусира само върху търсенето на тези с изтегляния над 100 000 и безплатна версия.

В резултат на това бяха открити доста плъгини и теми, засегнати от уязвимостта.