Not Token for Granted

New phishing campaign against financial services steals OAuth tokens to bypass MFA in O365 accounts

DarkLab recently discovered a suspicious email which we identified as part of an active phishing campaign primarily targeting banks and investment companies worldwide, including a number of targets in Hong Kong. The campaign initially seemed aimed at stealing victims’ credentials, a common tactic among threat actors. However, a closer look showed that threat actors leveraged OAuth2 framework to gain permissions to the victim’s O365 account by exploiting a rogue Azure application. This would have allowed them to bypass multifactor authentication controls and directly access the victim’s account with a stolen OAuth token, rendering this a particularly effective social engineering tactic.

Overall, this campaign shows how financially motivated threat actors are evolving their tactics, techniques, and procedures to exploit companies’ increasing reliance on cloud infrastructure.

Phishing email analysis

The email is sent from a domain of a separate entity, likely compromised by the threat actor before initiating the attack against our client. The email metadata also suggests deliberate spoofing of the SMTP FROM header.

The email contains a fake e-signature verification request, along with a link to “Review and sign”.

The link is crafted to present the user with a request screen (see figure above) to grant permissions to a rogue Azure application. Depending on threat actors’ intent, permissions request can be modified to allow access to cloud-hosted documents and applications, including the email account.

Here is an example of the phishing link:

hxxps:// &redirect_uri=https%3A%2F%2Fkp3jccawgk[.]online&resource= https%3A%2F%2Fkp3jccawgk[.]online&state=xxxxxxxxxxxx #efe1b61bcf8df6b76595xxxxxxxxxxxx

The url above represents an access requested to the Microsoft Identity platform with a request for an authorization code, denoted by the response_type flied. The client_id field denotes the unique ID of an Azure application owned by the threat actor, with a redirect_uri field pointing to a domain – kp3jccawgk[.]online – staged by the threat actor to capture the redirected HTTP request once the victim grants the access permission.

To create such an attack infrastructure the threat actor only needs to register a rogue application under an Azure tenant, and to host a website to capture the URL requests and  authorization codes. The redirected site also contains JavaScript snippets that detect the accessing IP address and details of the victim organisation, very likely for victims’ profiling and filtering out potential accesses from security vendors.

Eventually, the victim is redirected to a blank page, now defunct.

Threat actors would then leverage the rogue application and request a valid access token with the authorization code. They could then access the victim’s O365 account with the permissions granted during the phishing process, and perform a variety of actions from accessing account information to sending emails on behalf of the victim.

This attack aims at stealing access tokens in form of OAuth. This allows direct access to a victim’s account and bypasses the need to steal valid user credentials, including multi-factor authentication.

Attack infrastructure and insights into the campaign

By pivoting on the redirect domain, we were able to identify multiple threat actors’ domains suggesting that they are very likely targeting banks, asset managers, equity firms, and in a lesser degree also law firms and consultancies around the world, including Hong Kong. According to domain registration data, the campaign started at the end of February and it is currently active. Based on the nature of its targeting the campaign appears to be financially-motivated.

Detection and remediation

To detect malicious behavior linked to a user falling victim to a similar phishing email, the most effective way is to monitor Azure audit logs for “Consent to Application” events. These represent users’ approval to grant permissions to third-party applications. Microsoft Cloud App Security is also a good location to detect new OAuth applications with high privileges in the tenant.

Sample Microsoft Azure log showing a Consent to Application event for a malicious Azure application

In the event where an internal user falls victim and consent is given to rogue application, IT teams can manually remediate the applied access under the “Enterprise Application” section of Microsoft Azure portal, and ensure that the user credentials are reset and protected by MFA. As a preventive measure, IT teams are also recommended to leverage the Azure AD Admin Consent to force administrator involvement to gatekeep user data against such kind of attack tactic.

Indicators of compromise

  • 188.166.68[.]51
  • kp3jccawgk[.]online
  • 17l78xgnzj[.]online
  • 4zl8t4sqon[.]online
  • 9ybzef6d2h[.]online
  • cprapid[.]com
  • cts1g02r2c[.]online
  • kp3jccawgk[.]online
  • l7p5g1kwh4[.]online
  • num7ewnkn1[.]online
  • rh6757nysb[.]online
  • wbxputufpj[.]online
  • wzoschqdd0[.]online

Hackaday 2020 – Securing the basics [P-3]

Incident Response and Threat Intelligence Challenge

As we mentioned in our previous posts on the Web and Cloud challenges, every year DarkLab organises a capture the flag cybersecurity competition designed for undergraduate students aiming to raise the competency level of future talents to better prepare them for a meaningful career in cybersecurity.

HackaDay 2020 was held on 2 December 2020, and saw the Open University of Hong Kong’s YH team crowned as winning team, and the Hong Kong University of Science and Technology’s Machine Brickers as runners up.

The theme this year was “Security the Basics”, based on the experience and real life challenges that organisations in Hong Kong have faced in 2020 – as observed by our own Red Team and Incident Response professionals.

In this series of three blog posts, we want to provide the solution to the different challenges students faced. We hope that this will stimulate even more students to get their hands on the keyboard next year! In this post we cover the Incident Response (IR) and Threat Intelligence (TI) questions.

Ransomware Attack Again 1 (50 pts, 14 solves)

Description: Our client has been hit by a ransomware attack. While the rest of the client’s PCs have been restored, the head of IT insists to decrypt the data to recover an important screenshot of server settings and passwords. They refuse to pay the ransom. The sysadmin left only the snapshot of the infected server.

It seems there is not much left to see. We’re reaching out to you, our best malware analyst, to help research and find a way to decrypt the screenshot.

RDP: ,  X is your team number

After connecting via RDP to the machine, we can see another user named sysadmin by navigating around the file system. On that user desktop, the following are found :

  • Ransomware affected file with extension HKADYYY
  • Ransom note HKADYYY-README, containing a flag


Ransomware Attack Again 2 (100 pts, 7 solves)

Description: Other than the ransom note, what other artefacts could you find?

By navigating the windows event logs, we notice a suspicious code snippet under powershell – large base64 payload (powershell with -e option).

The following two values are found by decoding the base64

  • Caller script : . $prog -InV 'MTIzNDU2Nzg5MDEyMzQ1Ng=='
  • Second flag


Ransomware Attack Again 3 (50 pts, 2 solves)

Description: sometimes there is public research on the ransomware behavior which may help you to decrypt the files. Try to surf the net!

A search online will not reveal much, until you check on Twitter, where you will find the following tweet.

The tweet contains the following link :

This post includes a small summary of the ransomware, a decryption routine, and the third flag hackaday{Blrdi3 w!th th3 g00d n@vvS}

Ransomware Attack Again 4 (300 pts, 0 solves)

Description: You are in the final step, tell me the content of the decrypted file!

According to the decryption routine, successful decryption requires two values :

  1. IV : Given by base64 string located in the loader : MTIzNDU2Nzg5MDEyMzQ1Ng==
  • Key-seed : random two-digit and the SID (obtained by checking the user that executed the ransomware i.e. sysadmin)

00S-1-5-21-1580626154-3826959220-856111413-500 to 99S-1-5-21-1580626154-3826959220-856111413-500

The following decryption code is implemented with the IV and Key (two digit is 99):

$IV = "MTIzNDU2Nzg5MDEyMzQ1Ng=="
$Key = "ODgxM2QyOTU4ZjljODAzOGVjMDhiMjljYjFjODgzMGM="
$aesManaged = New-Object "System.Security.Cryptography.AesManaged"
$aesManaged.Mode = [System.Security.Cryptography.CipherMode]::CBC
$aesManaged.Padding = [System.Security.Cryptography.PaddingMode]::Zeros
$aesManaged.BlockSize = 128
$aesManaged.KeySize = 256
$aesManaged.IV = [System.Convert]::FromBase64String($IV)
$aesManaged.Key = [System.Convert]::FromBase64String($Key) 
$decryptor = $aesManaged.CreateDecryptor();
$fileToDecrypt = "C:\path\to\encrypted\file.HKADYYY"
$encryptedFile = [System.IO.File]::ReadAllBytes($fileToDecrypt)
$bytes = $encryptedFile
$unencryptedData = $decryptor.TransformFinalBlock($bytes, 0, $bytes.Length);
Rename-Item -Path $fileToDecrypt -NewName ($fileToDecrypt.Substring(0, ($fileToDecrypt.Length - 8)))

Using the routine to decrypt the file:

Decryption routine will reveal the final flag


That’s is for this blog series, we hope you enjoyed reading and looking forward to seeing you at Hackaday 2021!

Hackaday 2020 – Securing the basics [P-2]

Cloud Challenge

Every year, DarkLab organises a Capture the Flag cybersecurity competition designed for undergraduate students aiming to raise the competency level of future talents to better prepare them for a meaningful career in cybersecurity.

HackaDay 2020 was held on 2 December 2020, and saw the Open University of Hong Kong’s YH team crowned as winning team, and the Hong Kong University of Science and Technology’s Machine Brickers as runners up.

The theme this year was “Security the Basics”, based on the experience and real life challenges that organisations in Hong Kong have faced in 2020 – as observed by our own Red Team and Incident Response professionals.

In this series of three blog posts, we want to provide the solution to the different challenges students faced. We hope that this will stimulate even more students to get their hands on the keyboard next year!

Make it Rain in the Bucket (50 pts, 14 solves)

Description: Unintended sensitive information disclosure comes in many shapes and forms.  You would be surprised with the information you can find through detailed enumeration and a bit of online research.  Can you unlock the secrets within to take you to the next part of the network?

P.S. AWS account is not required for this question

This first challenge is meant to emulate an unsecured AWS s3 bucket. The website is a static webpage hosted as an AWS S3 bucket. When hosting a website as an AWS S3 bucket, the bucket name ( must match the domain name (  By enumerating the site with a ping request, we get the following data:

The ping returns with the domain name If we access the domain, it will return the objects stored in the bucket.

An interesting file should catch your attention – admin_users_only/useraccess.txt -which contains the first flag.

Keys behind the wall (100 pts, 8 solves)

Description: There might be something insecure with this web application, if you could find the keys behind this application, you are one step closer to the image. The flag format is hackadayxxxxxxx

This challenge was meant to emulate a SSRF vulnerability in the application hosted on an AWS EC2 instance.

The SSRF attack allows to request the metadata of the EC2 instance. In AWS the metadata can be access by browsing to

As shown below, the AccessKeyId, SecretAccessKey and token are exposed, and an attacker could then impersonate the role attached on the machine using the temporary credentials and conduct additional discovery. The second flag is the role name.

Secret in the Image (200 pts, 1 solves)

Description: The secret lies in the image

This challenge was meant to emulate a misconfigured AMI-image which allows public access. With the credentials for programmatic access to AWS obtained from the second challenge, we can use our own AWS account to impersonate the role by changing the authentication file ~/.aws/credentials.

Once we assume the role, we can start enumerating the policies attached to the role to determine the level of privilege that the role has.

As shown above, the role has two policies attached. The hackadaypolicy is a custom policy created for this role. The next step would be to enumerate the hackadaypolicy to determine what permissions are assigned in the policy.

The screenshot above shows all the permissions that are assigned to the policy. If we enumerate all the permission given, we would stumble upon ec2:DescribeImage which has the parameter set to public = true with the AMI-ID shown.

This shows that the AMI-image created by this role is set to public, which allows everyone with an AWS account to access it.

We can then search for the instance from the community AMI group and launch the instance.

Once we launch the AMI , the 3rd flag can be found under the /tmp folder of the EC2 instance.

That’s it for this challenge, stay tuned for the third and last post which will walk through the Incident Response and Threat Intelligence challenge.

Hackaday 2020 – Securing the basics [P-1]

Web Challenge

Every year, DarkLab organises a Capture the Flag cybersecurity competition designed for undergraduate students aiming to raise the competency level of future talents to better prepare them for a meaningful career in cybersecurity.

HackaDay 2020 was held on 2 December 2020, and saw the Open University of Hong Kong’s YH team crowned as winning team, and the Hong Kong University of Science and Technology’s Machine Brickers as runners up.

The theme this year was “Security the Basics”, based on the experience and real life challenges that organisations in Hong Kong have faced in 2020 – as observed by our own Red Team and Incident Response professionals.

In this series of three blog posts, we want to provide the solution to the different challenges students faced. We hope that this will stimulate even more students to get their hands on the keyboard next year!

Web Challenge – With great power comes great responsibility!

Hackaday Chat System 1 (100 pts, 4 solves)

This challenge is meant to exploit the broken access controls of a website. After registering and login with an account, you will notice that there are several accounts created (i.e. operator_day1, admin_day1, admin_day2) from the “Select User” drop-down list. The account operator_day1 will be our target for this challenge.

The key element is the user’s UUID form in the user profile page. The user’s UUID for this system is crafted from MD5 hash of the user email. Using an md5 generator, we are able access the profile page of operator_day1 by entering /profile.php?uuid=14a7a7da8dfcba61a4af2b695a553cf0.

Inside operator_day1 profile page, we can retrieve the password SHA256 hash of the user. Using an online hash cracking site, we are able to recover the plaintext password of the operator’s account.

After logging in with the operator account, the flag will be displayed at the chat box.

Hackaday Chat System 2 (150 pts, 1 solve)

This challenge is an extension of the Chat System 1. This time, the account admin_day1 will be our target.

In the operator_day1’s profile, a new endpoint – updateUser.php – is available to update username or password. However, after clicking the button, an error message is prompted saying the naming function is in maintenance.

Using a web proxy tool, we can change the “from” data of the request to delete the name changing parameter. As the endpoint is also vulnerable to parameter injection, adding a new data field “role” would grant us the role of the user.

Here we crafted a request to change the role of operator_day1 to administrator, which is same as the role of admin_day1.

With administrator privileges, we can now change the password of admin_day1 to another one of our choice. (Note that UUID in the request is the one from the admin_day1 account)

After logging in to the system with admin_day1 account, we can retrieve the flag in the chat box.

OTP Member Portal (150 pts, 0 solves)

Description: Multi-factor authentication (MFA) is an electronic authentication method in which user is granted access to a website or application only after successfully presenting two or more pieces of evidence (or factors) to an authentication mechanism: knowledge (something only the user knows), possession (something only the user has), and inherence (something only the user is) – SUPER SAFE!

This challenge aims to bypass the password login process and brute force weak a MFA system.

Once you register an account in the system and complete a normal login process, you can notice that:

  1. You would need an account from Hackaday Chat System in order to receive OTP
  2. The OTP is 3-digit code from 100-999
  3. Account will be locked after 5 incorrect OTP login attempts
  4. You can send request to reset the fail counts and the OTP
  5. The target account of this challenge is
  6. Exploiting the target account in Hackaday Chat System would not work since admins will not receive OTP from chat system
  7. The normal login process is represented in the below graph

The point of exploitation is from the password login. Due to broken access control, after the “password incorrect” message is prompted, we can still access the OTP login page directly with the target account information embedded in the PHP session.

You could therefore write a script to exploit the system by bruteforcing the OTP system:

  1. Login on the account with random password
  2. After seeing the “password incorrect” message, directly access /OTPlogin.php
  3. Brute force the OTP at maximum 4 times
  4. Submit request to resend OTP if all attempts failed
  5. Repeat step 3 and 4 until the OTP login is successful
  6. Access member.php with the same PHP session

A sample program written in Go (otp-sample.go) is provided for reference.

After finishing the above steps, the flag will be displayed at profile.php.

OTP Admin Portal (100 pts, 0 solves)

This challenge aims to exploit the file uploading feature in the system. We are allowed to upload any files to the system with the only limitation being on file size. After uploading a .htaccess file with directory listing enabled (‘Options +Indexes’), we can find the flag with the link provided.

Simple Message Board (250 pts, 3 solves)

Description: I found a message board online and seems that there is a secret hiding which can be only access by the admin. Do you know how to get the secret?

This challenge is aimed at exploiting the message board system with Cross-site scripting (XSS) and/ or Cross-Site Request Forgery (CSRF).

In the message board system, we are given three functions: one for posting a message to the board, one for clearing the log, and one for getting the flag.

It is observed that:

  1. Someone (likely the admin) is frequently accessing the board and clearing logs
  2. Both name and message fields are vulnerable to XSS
  3. There is a hidden field (csrf_token) in the “Get Flag” form
  4. There are PHP session ID and a field named “Admin” in the cookie, changing the value of “Admin” field to “Admin” will not work also

The target of this challenge is to force admin to somehow click the “Get Flag” function or steal the session (cookies) from the admin.

Solution 1

To solve the challenge, we could write a script to force admin to access the “Get Flag” function:



      var xhr = new XMLHttpRequest();"POST", "getflag.php");

      xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");

      xhr.send("csrf_token=" + document.querySelector("input[name=csrf_token]").value);

}, 1)


The script will do the following procedures:

  1. Query the value of csrf_token in the page
  2. Send a form request to getflag.php to trigger the function

As there may be situations that the script run without csrf_token properly loaded, some time delay (such as using settimeout, onerror etc.) is required such that the script would be executed successfully on the admin side.

After sending the script to the board and wait for a second, the flag will be shown on the board.

Solution 2

To tackle the challenge, we could setup a listener (e.g. pastebin) for receiving http request and send the following script to the message board:


By using this script, if admin accessed the message board, a HTTP GET request will be sent to our requestbin service with all cookies logged.

After a short waiting, we will receive the above request with the information we need.

With the cookies of the admin account, we can now get the flag by clicking the “Get Flag” button.

Stay tuned for the second part of this blog series: Cloud challenge.

Presentation is Key

Criminals exploit PowerPoint documents and blog infrastructure to deliver RAT and steal cryptocurrency

DarkLab has recently responded to cybercriminal phishing attempts in APAC exploiting unusual tactics, techniques and procedures (TTPs). While most phishing we observe contain MS Word or Excel attachments, this one exploited malicious PowerPoint (.ppt) files to eventually deploy AsyncRat malware and a bitcoin stealer.

Exploitation of PowerPoint attachments is not entirely new. However, it is rare enough to remain uncommon and therefore increase the chances that unaware users would open malicious attachments.

This phishing campaign, likely still active, appears to be focused on Asia, particularly China, although we also found samples uploaded on a popular multi-vendor AV scanner from countries in Europe.  Most of the titles of the malicious documents are generic. However, the use of titles such as “Hotel Doc” for some of their lures suggests that the hospitality industry is one of the sectors targeted.

Phishing lure analysis

The first phishing email we picked up caught our attention for its use of Traditional Chinese characters used in Hong Kong and Taiwan, as opposed to the Simplified Chinese used in Mainland China. The email included a malicious PowerPoint attachment named 付款詳情.ppt [MD5:
8311c59ef727826c4b54e182a956e312], which contains malicious and obfuscated macros. The macro only  executes when the file is closed by the user, in a likely attempt to avoid raising the victim’s suspicion.

Fig 1 – Deobfuscated payload [MD5: 127538a7d8703ec96a5e39e9fd235c06]

After deobfuscation it is clear that the VBA macro leverages the legitimate binary mshta.exe to connect to a hardcoded URL masked with the URL shortening service. The hardcoded URL eventually redirects to tumharimaakachodamarunmaine[.]blogspot[.]com/p/3-sunda-10-origin[.]html

Attack infrastructure and timeline is a separate address for the better known shortening service. According to bitly’s statistics, the malicious URL discovered was created at the end of February.

Fig 2 – bitly creation data for the malicious URL

The URL points to a server used by the threat actor to stage a range of malicious payloads, from cryptocurrency stealers to an open source remote access trojan (RAT). We will get to that in a second.

Pivoting on the identified staging server revealed a significant number of additional attack infrastructure, a new URL for each phishing document. These servers were all hidden behind the same shortening server and hosted on Blogspot infrastructure.

By checking the URLs creation date on bitly we were able to get a timeline of the malicious campaign, which shows how the threat actor behind it has been active since the beginning of the year and has recently increased their activity.

Fig 3 – timeline of attack infrastructure set up


In terms of payload, we could only examine one malicious URL [Tumharimaakachodamarunmain[.]blogspot[.]com/p/42[.]html] and found a number of scripts. We suspect that other URLs may host different payloads.

Fig 3 – Screenshot of the malicious webpage

The webpage looks benign at first glance. However, accessing it with MSHTA triggers on the victim’s endpoint a number of JavaScript payloads embedded on the website.

The first script executes a set of VBScripts that fetch the content of the following link:


The file is deobfuscated and dropped on %Public%\bin.vbs before execution, and it aims at disabling security controls for subsequent malware executions.

Fig 4 – First script disables system’s security settings

The second script reaches out to the following URL, again with MSHTA :

It contains three additional payloads to disable security defences and hiding attackers’ windows to hide malicious activity.

Then, an additional PowerShell script is executed by loading the script from two additional sites depending on the system architecture.



The payload will reflectively load two additional samples: a heavily obfuscated DLL with anti-analysis mechanisms [MD5: d1a426b9afe2ca1e56cdf48523c684e3], and an open source RAT called AsyncRat [MD5: 47c012de1faac9be5a860b600a06c5ee].

AsyncRat is able to send and receive commands, record keystrokes and screenshots, and upload/download files via SFTP, among other functions.

The threat actors also tries to steal victims’ cryptocurrencies by replacing the legitimate wallet address with one controlled by the attackers. This is done via the Powershell script shown below that looks for BTC wallets addresses in the clipboard and and replaces them with another one. Our research into the attacker’s BTC address shows that it had two small transactions, suggesting the attacker had so far only limited success.

Fig 4 – PowerShell script for cryptocurrency theft

Finally, the last script downloaded from the stager domain attempts to terminate instances of excel.exe and winword.exe in attempt to hide attacker’s tracks.


The attacker’s exploitation of open source malware and abuse freely available Blogspot URLs as malicious infrastructure highlights the increasing lowering barrier of entry for cybercriminal operations in Asia. Despite the relatively low-level nature of this threat in terms of technical sophistication, the use of malicious PowerPoint attachments shows some innovation in their social engineering tactics. Overall, this campaign shows how even low-cost but complex cybercriminal campaigns can pose a threat to organisations by leveraging unusual social engineering techniques and open source tools.

Indicators of Compromise

  • 8311c59ef727826c4b54e182a956e312
  • d1a426b9afe2ca1e56cdf48523c684e3
  • 47c012de1faac9be5a860b600a06c5ee
  • f7fd745b52fb8e791254492eca2c41df9281430dcbc5b56baa715b32eeb417ed
  • ae133004d194c3701d0b2051904d07ad69c901830a710cc2de6cb465c67bdc9d
  • 015224452b3232f76924d4020b45cfc954b80a4f14563d9fe7dadffb1699f090
  • 4be0a1ade0230dc10ef523d30d3f28ab1e70a4b5587086edfcdbfa9b30fb9c9a
  • a07e7d0a6699cbcb960bbe8c3a34b85a878abda0d19cd98d2e0ce170369c7ccf
  • d925e0405f8b9a4c0c06751a36318bcccd54721c107c08dc851fec12b58ec9ab
  • 78599a0757c19b98f6d5ec650a5f80181f90117215edcf5f79c7099c12f9710a
  • 4199e3e42abb7d71ca8183609e80225014ce4b232990d526ec0655b889aac5fd
  • 46730c85c3da44a3bfc2d4786db1bf1b0f13a0c523c3b7ae88749b3538d1b8c1
  • 4f0d613797aa59fbcb957162c37d586e020cfb65a886972b404bbda4473d0b5e
  • 65bbecd4400d257e8eb367b56ec846de4e4efaf3274622fd01c8751adde5d30b
  • 266ffecbcb98bd2401298ca8fbe8bdc9df9fd8ebdfee8acf267a43cedd870050
  • f9498a2b0d6c38da6ad465a0135c5d20817bffeaf5ed09b9de8a7a22ec1ada58
  • 4a90be311633d5052b7ef4c6edd0ccddd472daab1ce183af0763b69d47ce4406
  • dc36dea840aec26090afba82b6a93f706b73c850286e6d80d95bf0604cc72d43
  • 9da6a119d0986bb18a84cef88915c5934074d189b57c0ee62103b24549f1fd51
  • 78599a0757c19b98f6d5ec650a5f80181f90117215edcf5f79c7099c12f9710a