Plaintext Credential Notes on Employee Endpoints

WindowsmacOS

Behavioral Hunt low DPRK IT Worker Fraud

Text files full of passwords in the obvious folders, which DTEX records in DPRK IT-worker casework as an operator's way of keeping credentials for several employers within reach.

What this hunt looks for

DTEX records two related behaviours in its DPRK IT-worker casework: text files holding authentication secrets in the Desktop, Documents and Downloads folders, and multiple logins from different addresses with abnormal file-repository reconnaissance. The first is a working practice, an operator keeping credentials for several employers somewhere reachable, rated low recall with moderate precision.

DTEX's second behaviour, multiple logins from different addresses with abnormal file-repository reconnaissance, matters because placements often end in data theft or extortion. It is read from file-share audit logs, not endpoint file events, so this hunt covers the first behaviour and is most useful run against accounts other hunts have already flagged.

Technique
Unsecured Credentials in files (MITRE ATT&CK T1552.001) on a corporate endpoint held by a fraudulently hired employee.
Data sources
EDR file telemetry
Last updated
2026-10-04

Indicators

The atomic values this hunt matches on, listed separately from the queries so they can be lifted into tooling that speaks none of the query languages below. Every value here is reported by one of the sources cited at the foot of this page.

TypeValueNote
Folder Desktop, Documents, Downloads (Windows and /Users/*/ on macOS) Where DTEX observed text files holding authentication secrets.

Logic

Every query below implements these steps, so the same hunt returns the same result in each product.

  1. Collect: file creations and modifications on Windows and macOS endpoints, last 90 days
  2. Match: the file sits under a Desktop, Documents or Downloads folder (either path separator)
  3. Match: the file name has a credential word (password, pwd, credential, secret, mnemonic) and is .txt, .csv or .rtf
  4. Report: each file with device, account, path and writing process, newest first

Queries

Defender / Sentinel KQL

Written for this site

Credential-named text, CSV and RTF files written to the three user folders on Windows or macOS, matched on the file name alone.

DeviceFileEvents
| where Timestamp > ago(90d)
| where ActionType in ("FileCreated", "FileModified")
| where FolderPath matches regex @"(?i)[\\/](desktop|documents|downloads)([\\/]|$)"
| where FileName matches regex @"(?i)(password|passwd|pwd|credential|creds|secret|mnemonic|backupcode).*\.(txt|csv|rtf)$"
     // optional: short stems that also match ordinary files such as bypass.txt or accounts.csv
     or FileName matches regex @"(?i)(pass|cred|login|logon|account|key|seed|otp|mfa|totp|recovery).*\.(txt|csv|rtf)$"
| project Timestamp, DeviceName, InitiatingProcessAccountName, FolderPath, FileName, InitiatingProcessFileName
| sort by Timestamp desc
Lower-fidelity parts (1)
  • the short stems pass, cred, login, logon, account, key, seed, otp, mfa, totp and recovery — substrings that also match ordinary files such as bypass.txt, monkey.csv or accounts.csv, so the stems add volume faster than precision. Remove: Delete the line beginning // optional: and the or line after it.

Splunk SPL

Written for this site

Credential-named text, CSV and RTF files written to the three user folders on Windows or macOS, matched on the file name alone.

```sourcetype placeholders: index=endpoint sourcetype=file_events with file_path, file_name, host, user and process_name; the path is the full path```
```optional: the second name pattern holds short stems that also match ordinary files such as bypass.txt or accounts.csv```
index=endpoint sourcetype=file_events earliest=-90d
| eval path=lower(file_path), name=lower(file_name)
| where match(path, "[\\\\/](desktop|documents|downloads)[\\\\/]")
| where match(name, "(password|passwd|pwd|credential|creds|secret|mnemonic|backupcode).*\\.(txt|csv|rtf)$") OR match(name, "(pass|cred|login|logon|account|key|seed|otp|mfa|totp|recovery).*\\.(txt|csv|rtf)$")
| table _time, host, user, file_path, file_name, process_name
| sort 0 - _time
Lower-fidelity parts (1)
  • the short stems pass, cred, login, logon, account, key, seed, otp, mfa, totp and recovery — substrings that also match ordinary files such as bypass.txt, monkey.csv or accounts.csv, so the stems add volume faster than precision. Remove: Delete OR match(name, "(pass|cred|...)...") from the last where line and the optional comment above it.

Sigma

Written for this site

A credential-named text, CSV or RTF file created in a user folder, where the name is matched on the file name and not on the folder.

title: Plaintext Credential Note in a User Folder
id: 4a8e1c37-6d52-4f09-b3a1-8c07e2d95f64
status: experimental
description: >
  Detects a text, CSV or RTF file written to a user's Desktop, Documents or
  Downloads folder whose name suggests it holds authentication secrets. DTEX
  observed such files in DPRK IT-worker casework, an operator keeping
  credentials for several employers somewhere reachable, and rates the
  indicator low recall with moderate precision. The file_event category
  covers file creation in most products.
references:
  - https://www.dtex.ai/resources/i3-threat-advisory-inside-the-dprk/
logsource:
  category: file_event
detection:
  selection_folder:
    TargetFilename|contains:
      - '\Desktop\'
      - '\Documents\'
      - '\Downloads\'
      - '/Desktop/'
      - '/Documents/'
      - '/Downloads/'
  selection_name:
    TargetFilename|re|i: '[^\\/]*(password|passwd|pwd|credential|creds|secret|mnemonic|backupcode)[^\\/]*\.(txt|csv|rtf)$'
  # optional: short stems that also match ordinary files such as bypass.txt or accounts.csv
  selection_name_weak:
    TargetFilename|re|i: '[^\\/]*(pass|cred|login|logon|account|key|seed|otp|mfa|totp|recovery)[^\\/]*\.(txt|csv|rtf)$'
  condition: selection_folder and 1 of selection_name*
falsepositives:
  - People who keep a passwords.txt they should not, which says more about security awareness than nationality
level: low
Lower-fidelity parts (1)
  • the short stems pass, cred, login, logon, account, key, seed, otp, mfa, totp and recovery — substrings that also match ordinary files such as bypass.txt, monkey.csv or accounts.csv, so the stems add volume faster than precision. Remove: Delete the # optional: line and selection_name_weak, and change the condition to selection_folder and selection_name.

Elastic

Written for this site

Credential-named text, CSV and RTF files written to the three user folders in Elastic Defend file events.

FROM logs-endpoint.events.file-*
| WHERE @timestamp > NOW() - 90 days AND event.action IN ("creation", "overwrite", "modification")
| EVAL path = TO_LOWER(file.path), name = TO_LOWER(file.name)
| WHERE path RLIKE ".*[\\\\/](desktop|documents|downloads)[\\\\/].*"
| WHERE name RLIKE ".*(password|passwd|pwd|credential|creds|secret|mnemonic|backupcode|pass|cred|login|logon|account|key|seed|otp|mfa|totp|recovery).*\\.(txt|csv|rtf)"
| KEEP @timestamp, host.name, user.name, file.path, process.name
| SORT @timestamp DESC
| LIMIT 200
Lower-fidelity parts (1)
  • the short stems pass, cred, login, logon, account, key, seed, otp, mfa, totp and recovery — substrings that also match ordinary files such as bypass.txt, monkey.csv or accounts.csv, so the stems add volume faster than precision. Remove: Delete |pass|cred|login|logon|account|key|seed|otp|mfa|totp|recovery from the name RLIKE pattern.

Cortex XQL

Written for this site

Credential-named text, CSV and RTF files written to the three user folders in Cortex file events.

dataset = xdr_data
| filter event_type = ENUM.FILE and event_sub_type in (ENUM.FILE_CREATE_NEW, ENUM.FILE_WRITE, ENUM.FILE_RENAME)
| filter action_file_path ~= "(?i)[\\/](desktop|documents|downloads)[\\/]"
| filter action_file_name ~= "(?i)(password|passwd|pwd|credential|creds|secret|mnemonic|backupcode).*\.(txt|csv|rtf)$"
    // optional: short stems that also match ordinary files such as bypass.txt or accounts.csv
    or action_file_name ~= "(?i)(pass|cred|login|logon|account|key|seed|otp|mfa|totp|recovery).*\.(txt|csv|rtf)$"
| fields _time, agent_hostname, actor_effective_username, action_file_path, actor_process_image_name
| sort desc _time
Lower-fidelity parts (1)
  • the short stems pass, cred, login, logon, account, key, seed, otp, mfa, totp and recovery — substrings that also match ordinary files such as bypass.txt, monkey.csv or accounts.csv, so the stems add volume faster than precision. Remove: Delete the line beginning // optional: and the or line after it.

osquery

Written for this site

Credential-named text, CSV and RTF files sitting directly in the three folders of every user profile on this host now.

SELECT path, filename, size, datetime(mtime, 'unixepoch') AS modified
FROM file
WHERE (path LIKE '/Users/%/Desktop/%' OR path LIKE '/Users/%/Documents/%' OR path LIKE '/Users/%/Downloads/%'
    OR path LIKE 'C:\Users\%\Desktop\%' OR path LIKE 'C:\Users\%\Documents\%' OR path LIKE 'C:\Users\%\Downloads\%')
  AND (filename LIKE '%.txt' OR filename LIKE '%.csv' OR filename LIKE '%.rtf')
  AND (filename LIKE '%password%' OR filename LIKE '%passwd%' OR filename LIKE '%pwd%' OR filename LIKE '%credential%' OR filename LIKE '%creds%' OR filename LIKE '%secret%' OR filename LIKE '%mnemonic%' OR filename LIKE '%backupcode%'
       -- optional: short stems that also match ordinary files such as bypass.txt or accounts.csv
       OR filename LIKE '%pass%' OR filename LIKE '%cred%' OR filename LIKE '%login%' OR filename LIKE '%logon%' OR filename LIKE '%account%' OR filename LIKE '%key%' OR filename LIKE '%seed%' OR filename LIKE '%otp%' OR filename LIKE '%mfa%' OR filename LIKE '%totp%' OR filename LIKE '%recovery%');
Lower-fidelity parts (1)
  • the short stems pass, cred, login, logon, account, key, seed, otp, mfa, totp and recovery — substrings that also match ordinary files such as bypass.txt, monkey.csv or accounts.csv, so the stems add volume faster than precision. Remove: Delete the -- optional: line and the OR line after it, leaving the closing parenthesis and semicolon on the line above.

False positives and tuning

Many people keep a passwords.txt they should not, and it says more about security awareness than nationality. Filename matching is only a proxy: secrets in notes.txt are invisible to it.

This is context to pull for an account already flagged by something more precise, not an alert; DTEX rates its recall low.

Backup agents, search indexers and sync clients write to these folders constantly, so exclude service accounts and their processes before reading the result.

Sources

Tuning required before use This hunt is a starting point. Adapt the queries to your schema, validate them against your baseline and tune them for the false positives noted above. Indicators go stale as operators rotate hosts.