Attackers plant SCF, URL, and LNK files with malicious icon file paths on file shares to escalate privileges or maintain persistence. This attack only requires the user to browse to the location of the malicious file. This artifact enumerates file shares and returns an event for each file with a remote icon. It can also scan a target root directory since attackers commonly use other locations like desktops.
name: Windows.Detection.RemoteIconForcedAuth
author: ACEResponder.com
description: |
Attackers plant SCF, URL, and LNK files with malicious icon file paths
on file shares to escalate privileges or maintain persistence. This attack
only requires the user to browse to the location of the malicious file.
This artifact enumerates file shares and returns an event for each file with a
remote icon. It can also scan a target root directory since attackers commonly
use other locations like desktops.
reference:
- https://www.cisa.gov/news-events/alerts/2017/10/20/advanced-persistent-threat-activity-targeting-energy-and-other
- https://attack.mitre.org/techniques/T1187/
- https://github.com/mdsecactivebreach/Farmer
# Can be CLIENT, CLIENT_EVENT, SERVER, SERVER_EVENT
type: CLIENT
parameters:
- name: AllShares
description: Scan all file shares on the host (excluding hidden shares). This option will ignore TargetFolder.
type: bool
default: Y
- name: AllowList
description: Each entry in the AllowList is checked against the TargetHost field. Matches are omitted.
type: csv
default: |
TargetHost
- name: TargetFolder
description: Root folder to search for SCF, URL, and LNK files. Uncheck AllShares to run. Backslashes should be escaped.
default: C:\\
imports:
- Windows.Forensics.Lnk
sources:
- precondition:
SELECT OS From info() where OS = 'windows'
query: |
LET script = '''
$out = @()
(Get-SmbShare | Where-Object {-not $_.Name.endswith('$')} | Select-Object -property Path) | %{
$out += New-Object PSObject -Property @{
Path = $_.Path + '\**\*.lnk'
}
$out += New-Object PSObject -Property @{
Path = $_.Path + '\**\*.url'
}
$out += New-Object PSObject -Property @{
Path = $_.Path + '\**\*.scf'
}
}
$out | ConvertTo-Json
'''
LET paths = SELECT * FROM if(
condition=AllShares,
then={SELECT * FROM foreach(row={SELECT Stdout FROM execve(argv=["Powershell", "-ExecutionPolicy","unrestricted", "-c", script], length=1000000)}, query = {SELECT * FROM parse_json_array(data=Stdout)})},
else={SELECT * FROM parse_json_array(data='[{"Path":"'+TargetFolder+'\**\*"}]')}
)
LET hits = SELECT *, {
SELECT *
FROM Artifact.Windows.Forensics.Lnk(Glob=FullPath)
WHERE FullPath =~ "lnk$"
} as lnk_file,
{
SELECT Data,
parse_string_with_regex(
string=Data,
regex=['IconFile=(?P<IconLocation>.*)']) AS parsed
FROM read_file(filenames=[FullPath])
WHERE FullPath =~ '(scf|url)'
} AS url_file
FROM glob(globs=array(a={SELECT * FROM paths}))
WHERE FullPath =~ "(scf|url|lnk)$" AND (lnk_file.Icons=~'^\\\\' OR url_file.parsed.IconLocation=~'^\\\\')
LET final = SELECT *, parse_string_with_regex(string=IconLocation,regex=['^\\\\\\\\(?P<host>\[^\\\\\]+)']).host AS TargetHost FROM foreach(row={SELECT * FROM hits}, query={
SELECT * FROM if(
condition=lnk_file,
then={SELECT Name, ModTime, FullPath, OSPath, Mtime, Btime, Ctime, Atime, lnk_file.Icons AS IconLocation FROM hits WHERE lnk_file.Icons},
else={SELECT Name, ModTime, FullPath, OSPath, Mtime, Btime, Ctime, Atime, url_file.parsed.IconLocation AS IconLocation, url_file.Data AS Data FROM hits}
)
}) WHERE NOT TargetHost IN AllowList.TargetHost AND IconLocation
SELECT * FROM final