TI-2026-011 โ "The Personal Touch" โ When Attackers Know Your Name, Your Family, Your Services, and Your Passwords
๐ Executive Summary
Between March 25 and May 7, 2026, our Cowrie SSH honeypot captured evidence of two distinct but coordinated attack campaigns targeting our infrastructure by name. Unlike the ~76,000 opportunistic brute-force attempts logged during this period from ~2,900 IPs, these campaigns demonstrate intimate knowledge of our domain, services, personnel, leaked credentials, and personal relationships.
Campaign A ("Wordlist Blitz") used 19 IPs to deliver 1,763 credential attempts with 326 algorithmically-generated passwords derived from our domain name. Usernames included actual running services on our Kubernetes cluster โ Portainer, PeerTube, and Docker Registry. All attempts used automated libssh-based tooling with 64.2% round-robin IP rotation between consecutive attempts.
Campaign B ("Credential Leak / OSINT Recon") used 23 IPs to deliver 72+ surgical credential attempts using 6 confirmed targeted passwords โ including credentials leaked from a previously-exposed service, a password constructed from our admin handle combined with a keyboard-walk pattern, a Romanian-language word meaning "Thank you," and even the default password for Apache Guacamole (wrong guess โ we use KasmVNC). Usernames were derived from deep personal OSINT: the operator's real full name, a family member's name spelled backwards with a number appended, both owned domains, internal service account names, and the mail server subdomain.
Neither campaign achieved access. All leaked credentials had already been rotated. Every web-facing service is protected by Authelia SSO with mandatory two-factor authentication (TOTP / security keys) โ even if a password were guessed correctly, the attacker would need a physical token or authenticator app. The previously-exposed service had been secured. When this analysis revealed that one of the targeted passwords was still active on internal systems, emergency credential rotation was triggered within hours, and all affected services were updated across the entire infrastructure.
Assessment: HIGH confidence same operator. A single IP address โ 87.106.149.146 (IONOS, Germany) โ was used in both campaigns: 177 brute-force attempts via libssh (Campaign A) followed by a single surgical attempt via SSH-2.0-Go with a post-quantum key exchange algorithm (Campaign B). This cross-campaign pivot eliminates the possibility of independent operations and proves shared infrastructure.
๐ Two Campaigns, One Operator โ The Attack Architecture
These two campaigns use different tools, different IP pools, and different tactics โ but share domain knowledge, timing, infrastructure providers, and one smoking-gun IP. Assessment: HIGH confidence same operator or coordinated group.
IPs: 19 (all libssh 0.7โ0.11)
Attempts: 1,763
Passwords: 326 (algorithmically generated from domain name)
Strategy: Volumetric brute-force with round-robin IP rotation
IP Switch Rate: 64.2% between consecutive attempts
Waves: 5 distinct attack waves with progressive service enumeration
Key Tell: Targeted usernames match actual K8s services
IPs: 23 (SSH-2.0-Go, paramiko, Ganymed, libssh2)
Attempts: 72+
Passwords: 6 (confirmed leaked + constructed credentials)
Strategy: Surgical credential stuffing with personal OSINT
Behavior: 1-2 targeted attempts per IP, then rotate
Phases: 4 progressive phases of escalating personal knowledge
Key Tell: Reversed family member name as username
87.106.149.146 (IONOS, Germany) used libssh for Campaign A (177 attempts) then SSH-2.0-Go for Campaign B (1 attempt) โ with a post-quantum key exchange algorithm (ML-KEM 768).Campaign B validated leaked credentials (surgical) โ Campaign A weaponized domain knowledge (volumetric). Different tools, same infrastructure.
โก Campaign A: "Wordlist Blitz" โ 326 Algorithmic Passwords from Our Domain Name
๐ฏ Service-Aware Targeting
The attacker didn't guess usernames โ they enumerated our actual running services and used them as SSH usernames. Three of the nine targeted usernames correspond to real services on our Kubernetes cluster:
๐งฎ Password Generation Algorithm โ Reverse-Engineered
We fully reverse-engineered the attacker's password generation algorithm. The 326 passwords are not from a generic wordlist โ they follow a clear algorithmic pattern built entirely from our domain name:
BASE_WORDS = {
domain_short: ["on", "On"],
domain_part: ["shuffle", "Shuffle", "SHUFFLE"],
domain_full: ["shuffleon", "Shuffleon", "SHUFFLEON"],
service: ["portainer", "Portainer"]
}
LEETSPEAK_MAP (applied to "shuffle" variants only) = {
'S' โ ['$', '5'], // Dollar sign, digit 5
'l' โ ['|', '1'], // Pipe character, digit 1
'e' โ ['3', '0'], // Digit 3, digit 0
case โ [lower, UPPER] // Applied to all combinations
}
// Generates: $huff|3, $HUFF1E0, 5HUFFL3O, SHUFF|EO, etc. (82 variants)
NUMERIC_STEMS = [0,1,2,3,4,5,6,7,8,9, 123, 420, 666, 69, 2025,2026,2027,2028]
SUFFIX_DECORATORS = ["", "!", "!!!", "!@#"]
// bare, single bang, triple bang, keyboard-shift-123
PASSWORD = BASE_WORD + NUMERIC_STEM + SUFFIX_DECORATOR
// Examples: On2026!, portainer420!@#, Shuffle123!!!, on666!
The year range 2025โ2028 in the suffixes is notable โ the attacker anticipated passwords might be updated annually and covered future years. The inclusion of 420, 666, 69 as numeric stems reflects common "edgy" password choices users make. The triple-bang (!!!) and shift-sequence (!@#) decorators show awareness of common password complexity patterns.
๐ Attack Waves โ Progressive Service Enumeration
$HUFF|3O, 5huff1e. Opening salvo with most complex passwords first.pi:raspberry, root:openmediavault. Testing for Raspberry Pi or NAS devices on the same IP.root:Ferrari โ but using SSH-2.0-Go instead of libssh. This is the cross-campaign pivot.The progressive addition of service-specific usernames across waves (portainer in Wave 2, peertube+registry in Wave 4) reveals ongoing reconnaissance between attack phases. The attacker isn't just spraying โ they're actively scanning, discovering new services, and updating their attack configuration.
๐ IP Rotation โ 19-Node Round-Robin Botnet
- 64.2% of consecutive attempts originate from a different IP โ classic round-robin proxy rotation
- Median inter-attempt interval: ~60 seconds
- Top node (SPARKED HOST, US) contributed 30.8% of attempts across 4 of 5 waves
- PROTON66 (Russian bulletproof hosting) contributed 13.3% but only appeared in Wave 1, then retired
- All 19 IPs use
libssh(versions 0.7.1โ0.11.3) โ same automated brute-force framework - Dominant HASSH fingerprint
f93d28ee0c77e2612b27491518d909f4shared across 11 of 19 IPs - Attacks occur during European/Americas business hours (10:00โ20:00 UTC), no weekend activity
๐ฏ Campaign B: "Credential Leak" โ The Personal Touch
๐ Targeted Credentials โ 6 Passwords, Each Telling a Story
[REDACTED_PASSWORD_A] โ 43 attempts[REDACTED_PASSWORD_B] โ 8 attempts[REDACTED_PASSWORD_C] โ 1 attempt[REDACTED_PASSWORD_D] โ 1 attempt[REDACTED_PASSWORD_E] โ 4 attempts[REDACTED_PASSWORD_F] โ 2 attempts๐ง OSINT Knowledge Demonstrated โ We Know What You Know
The attacker progressively revealed deeper levels of personal knowledge about the target. We have catalogued every piece of intelligence they demonstrated:
| Knowledge Level | What the Attacker Knew | Likely Source | Severity |
|---|---|---|---|
| ๐ข Public | Primary domain name | DNS / Web | Low |
| ๐ก Semi-Public | Operator's real full name | WHOIS / LinkedIn / Breach DB | Medium |
| ๐ก Semi-Public | Full email address | Breach database (associated with leaked password) | Medium |
| ๐ Private | Leaked password from previously-exposed service | Credential stuffing DB / Direct service access | High |
| ๐ Private | Service-specific credential mutation (exact variant) | Actual Portainer credential leak โ not guesswork | High |
| ๐ Private | Operator's handle / alias pattern | GitHub/Gitea profile, service naming convention | High |
| ๐ Private | Handle + keyboard-walk password construction | Human analysis โ constructed, not leaked | High |
| ๐ Private | Second owned domain | Web scraping / cert transparency / WHOIS cross-ref | Medium |
| ๐ Private | Internal service/admin account names | Gitea enumeration / K8s service discovery | High |
| ๐ Private | Mail server subdomain structure | Certificate transparency / DNS MX records | Medium |
| ๐ Private | Remote desktop service exists (guessed wrong technology) | Port scanning / service fingerprinting | Medium |
| ๐ด Intimate | Family member's first name | Social media / public records / personal OSINT | Critical |
| ๐ด Intimate | Family name reversed + number as username | Human intelligence analysis โ not automatable | Critical |
| ๐ด Intimate | Operator's nationality / native language | Cultural/linguistic knowledge ("Thank you" in native language) | Critical |
The most striking findings: (1) the reversed family member name โ reversing a name and appending a number is a human-creative operation that cannot be produced by automated OSINT tools; (2) the handle + keyboard-walk password construction โ this is not from any breach database, it's a manually crafted guess combining the operator's known alias with a common password-building technique; (3) the native-language password โ this places the attacker or their intelligence source within the operator's cultural sphere.
๐ Four Phases of Escalation
Simple
root:[leaked_password] pairs, 1โ3 per IP. Diverse off-the-shelf SSH tools (Ganymed, paramiko).Purpose: Testing whether the leaked credential still grants root access. Also: the most revealing single IP (MEVSPACE, Poland) tests ALL 6 passwords in priority order during this phase โ
[REDACTED_PASSWORD_F] first (highest confidence default), then [REDACTED_PASSWORD_E] (constructed), then [REDACTED_PASSWORD_A] (leaked), then [REDACTED_PASSWORD_B] (cultural). The ordering reveals a human operator, not a script.
Personal email address, real full name, operator handle, domain name โ all as usernames.
Key event: Ethiopian IP fires 20 attempts in 75 seconds using a 5-username rotation cycle (full email, real name, root, admin, domain) repeated 4 times โ automated loop with hardcoded personal data.
Purpose: The attacker has correlated the leaked credential with the domain owner's real identity.
Each IP fires 1โ2 unique targeted credentials. SSH-2.0-Go dominates (11 of 13 IPs) โ consolidated tooling.
Key usernames deployed:
โข Internal Gitea project name โ
[redacted_service]:googleโข Reversed family name + number @ second domain
โข Full mail subdomain โ
webmaster@mailserver.[domain]โข Family member service account โ
[family_prefix]-[family_name]โข Primary admin account โ
[admin_handle]โข Portainer-specific credential variant (exact mutation)
Purpose: Full OSINT dump โ deploying everything gathered in a final coordinated burst.
root:Ferrari via SSH-2.0-Go โ from the same IP that ran 177 Campaign A libssh attempts days earlier.HASSH includes
mlkem768x25519-sha256 โ a post-quantum key encapsulation mechanism (ML-KEM 768 / Kyber), indicating Go 1.23+ with x/crypto post-quantum support. This is cutting-edge SSH tooling.Significance: This is the smoking gun โ direct proof that Campaign A and Campaign B share infrastructure.
๐ The Smoking Gun โ Cross-Campaign IP Pivot Analysis
IP 87.106.149.146 (IONOS, AS8560, Germany) is the key that locks these two campaigns together:
SSH-2.0-libssh_0.10.6HASSH:
f93d28ee...909f4Usernames: shuffleon, on, root, registry, shuffle
Passwords: On/portainer mutations (algorithmic)
SSH-2.0-GoHASSH:
16443846...4397 (includes ML-KEM 768 post-quantum)Username: root
Password: Ferrari (unique credential โ not used elsewhere)
Two toolkits deployed from one machine = one operator or shared access = coordinated operation.
๐ Infrastructure-Wide Cross-Correlation
We queried every log source across our entire infrastructure for activity from all 42 campaign IPs:
| System | Result | Detail |
|---|---|---|
| CrowdSec (IPS) | โ ALL 42 BANNED | Every campaign IP is blocked via community threat-intel-feed (~26,742 IPs). Bans refreshed daily. |
| auth.log (real SSH) | โ CLEAN | Zero hits โ no campaign IP reached the actual SSH service. They only reached the honeypot. |
| syslog | โ CLEAN | Zero hits from any campaign IP. |
| Traefik (reverse proxy) | โ CLEAN | Zero HTTP/HTTPS requests โ the attack was SSH-only, no web probing. |
| Authelia (SSO gateway) | โ CLEAN | Zero login attempts via the web authentication gateway. 2FA never challenged. |
| Loki (centralized logs) | โ CLEAN | Only cowrie (honeypot) logs contain campaign IPs. No other service was touched. |
| Remote Desktop Service | โ PROTECTED | Behind Authelia forward-auth with mandatory 2FA. Attacker tried guacadmin (wrong technology โ it's KasmVNC, not Apache Guacamole). |
๐ต๏ธ Reconstructed Attacker OSINT Workflow
Based on every credential and username used, we can reconstruct the attacker's intelligence-gathering process with high confidence:
๐ฌ Deep Dive: The Most Revealing Single IP
One IP โ from MEVSPACE, Poland (AS201814) โ is the most information-rich node in Campaign B. It used all 6 targeted passwords across 3 distinct visits spanning 15 days, always as root:
Visit 1 โ April 4 (5 minutes, 4 credentials):
root : [REDACTED_PASSWORD_F] โ Guacamole default (tried FIRST โ highest confidence)
root : [REDACTED_PASSWORD_E] โ Handle + keyboard walk (constructed)
root : [REDACTED_PASSWORD_A] โ Leaked credential (confirmed breach)
root : [REDACTED_PASSWORD_B] โ Native-language "Thank you" (cultural OSINT)
Visit 2 โ April 9 (95 minutes, 4 credentials):
root : [REDACTED_PASSWORD_E] โ Retry
root : [REDACTED_PASSWORD_A] โ Retry
root : [REDACTED_PASSWORD_F] โ Retry
root : [REDACTED_PASSWORD_B] โ Retry
Visit 3 โ April 19 (single attempt):
root : [REDACTED_PASSWORD_A] โ Final check โ "does it work yet?"
Analysis: The credential ordering is significant. The Guacamole default is tried first (easiest default to verify), then the constructed handle+keyboard-walk (second-highest confidence โ attacker thought this was the admin password), then the leaked credential, then the cultural password. This is a human operator making decisions about credential priority, not an automated rotation. The 10-day gap between Visit 2 and Visit 3, with only the leaked password retried, suggests the operator is checking whether the target re-enabled the compromised credential.
๐ก๏ธ Our Response โ From Detection to Remediation
This dossier is not just analysis โ it triggered a real defensive response. Here is what happened when we discovered the scope of the targeting:
๐จ Indicators of Compromise (IOCs)
Campaign A โ Source IPs (19)
136.0.251.107 # SPARKED HOST LLC, US (AS397032) โ primary node, 543 attempts
37.77.150.223 # PROTON66, RU (AS198953) โ known bulletproof hosting
161.132.53.175 # Red Cientifica Peruana, PE (AS3132)
87.106.149.146 # IONOS, DE (AS8560) โ โ ๏ธ CROSS-CAMPAIGN PIVOT
174.138.57.46 # DigitalOcean, US (AS14061)
161.132.38.88 # Red Cientifica Peruana, PE (AS3132)
211.37.174.180 # Korea Telecom, KR (AS4766)
152.70.91.107 # Oracle Corporation, US (AS31898)
130.61.190.249 # Oracle Corporation, US (AS31898)
49.12.209.227 # Hetzner, DE (AS24940)
178.104.220.57 # Hetzner, DE (AS24940)
157.245.87.15 # DigitalOcean, US (AS14061)
204.168.170.106 # Hetzner, DE (AS24940)
185.182.187.151 # Contabo, DE (AS51167)
167.172.64.25 # DigitalOcean, US (AS14061)
212.227.146.182 # IONOS, DE (AS8560)
178.18.243.195 # Contabo, DE (AS51167)
86.48.25.218 # Contabo Inc., US (AS40021)
159.89.244.38 # DigitalOcean, US (AS14061)
Campaign B โ Source IPs (23)
190.8.175.6 # SpedyNet Telecom, BR (AS271011) โ Ganymed_null
195.3.220.88 # MEVSPACE, PL (AS201814) โ MOST REVEALING: all 6 passwords across 3 visits
143.202.208.242 # Red Paraguaya Telecom, PY (AS264631) โ Ganymed_null
161.97.175.65 # Contabo, DE (AS51167) โ Ganymed_null
103.40.188.143 # UIH, TH (AS38794) โ paramiko 2.12.0, [REDACTED_PASSWORD_E] only
146.190.230.216 # DigitalOcean, US (AS14061) โ Ganymed_null
203.144.76.188 # CAMGSM Cellcard, KH (AS17976) โ paramiko 4.0.0, personal usernames
197.156.73.177 # EthioNet, ET (AS24757) โ 20 rapid attempts with full email + real name
150.241.116.234 # XORA, GBโUS (AS215590) โ paramiko 3.4.0
54.36.107.28 # OVH, FR (AS16276) โ SSH-2.0-Go
146.56.175.142 # Oracle BMC, JP (AS31898) โ SSH-2.0-Go, reversed family name
69.55.49.49 # DigitalOcean, US (AS14061) โ SSH-2.0-Go, mail subdomain
62.171.187.208 # Contabo, DE (AS51167) โ SSH-2.0-Go
51.195.118.158 # OVH, FR (AS16276) โ SSH-2.0-Go
71.19.147.24 # prgmr.com, US (AS47066) โ SSH-2.0-Go
193.40.147.36 # EENET, EE (AS3221) โ SSH-2.0-Go, Estonian academic network
66.42.91.230 # Vultr, US (AS20473) โ SSH-2.0-Go, mail subdomain username
88.99.38.128 # Hetzner, DE (AS24940) โ SSH-2.0-Go
198.98.58.139 # FranTech/PONYNET, US (AS53667) โ SSH-2.0-Go, known bulletproof hosting
116.203.142.168 # Hetzner, DE (AS24940) โ SSH-2.0-Go
50.198.160.188 # Comcast Cable, US (AS7922) โ SSH-2.0-Go, residential IP
103.26.136.30 # GRAMEEN Communications, BD (AS58946) โ paramiko 2.12.0, [REDACTED_PASSWORD_E] only
87.106.149.146 # IONOS, DE (AS8560) โ SSH-2.0-Go โ โ ๏ธ CROSS-CAMPAIGN PIVOT (also Campaign A)
SSH Client Fingerprints (HASSH)
# Campaign A โ libssh brute-force framework (19 IPs)
03a80b21afa810682a776a7d42e5e6fb # libssh 0.11.x โ primary SPARKED node
f93d28ee0c77e2612b27491518d909f4 # libssh 0.10.6 โ dominant fingerprint (11 IPs)
3335afa7a75e84f8348f05c623c5ecf9 # libssh 0.9.6
944eec3005f2db3a98d8ac77f714d070 # libssh 0.9.3
495ca0813b1c4f9c1d7fc18e45e3956c # libssh 0.7.1
70e363185f617f7b0e5aa1e6cba68722 # libssh 0.8.7
# Campaign B โ OSINT / credential stuffing toolkit (23 IPs)
0a07365cc01fa9fc82608ba4019af499 # SSH-2.0-Go โ Phase 3 dominant (12 IPs)
16443846184eafde36765c9bab2f4397 # SSH-2.0-Go โ cross-campaign pivot, includes ML-KEM 768 (post-quantum)
1ab01ea559275860be73fe29c5d077bd # Ganymed_null โ Phase 1 (4 IPs)
a2de0f306611e0957be704f5b0e35a82 # paramiko 3.5.1 / 4.0.0
a704be057881f0b1d623cd263e477a8b # paramiko 2.12.0 (TH + BD IPs โ [REDACTED_PASSWORD_E] probes)
1df281da760a0c16d115179a9ea5957c # libssh2 1.10.0 (ET IP โ rapid personal targeting)
87e3d9ffee0540b0390f8a5b9c343c08 # paramiko 3.4.0
๐บ๏ธ MITRE ATT&CK Mapping
| Tactic | Technique | ID | Campaign |
|---|---|---|---|
| Reconnaissance | Active Scanning: Vulnerability Scanning | T1595.002 | A, B |
| Reconnaissance | Gather Victim Identity: Email Addresses | T1589.002 | B |
| Reconnaissance | Gather Victim Identity: Credentials | T1589.001 | B |
| Reconnaissance | Gather Victim Org: Business Relationships | T1591.002 | B |
| Reconnaissance | Search Open Technical DBs: WHOIS | T1596.002 | B |
| Reconnaissance | Search Open Technical DBs: Certificates | T1596.003 | B |
| Reconnaissance | Search Open Websites/Domains | T1593 | A, B |
| Resource Dev | Acquire Infrastructure: VPS | T1583.003 | A, B |
| Resource Dev | Compromise Infrastructure: Server | T1584.004 | B |
| Resource Dev | Obtain Capabilities: Tool | T1588.002 | A |
| Initial Access | Brute Force: Credential Stuffing | T1110.004 | B |
| Initial Access | Brute Force: Password Spraying | T1110.003 | A |
| Initial Access | Brute Force: Password Guessing | T1110.001 | A |
๐ Lessons Learned & Defensive Takeaways
- Honeypot captured full attack telemetry โ awareness before damage
- Leaked credentials had already been rotated โ zero successful logins
- Previously-exposed service had been secured before the attack
- All web services protected by Authelia SSO with mandatory 2FA (TOTP/security keys)
- CrowdSec community threat-intel feed had all 42 IPs pre-banned
- Emergency credential rotation triggered by analysis โ remediated within hours
- 326 algorithmically-generated passwords: 0% success rate
- 72+ surgical OSINT-based attempts: 0% success rate
- Leaked credentials persist in attacker databases indefinitely
- Exposed services get catalogued even after being secured
- Personal information (names, family, nationality) is weaponizable
- Running services can be enumerated and used as username targets
- Attackers invest in multi-week, multi-phase reconnaissance
- Password patterns (handle + keyboard walk) are predictable to sophisticated attackers
- A single breach can seed entirely new attack campaigns months later
- Attackers use post-quantum cryptography in their tools โ they're evolving
- SSH key-only authentication โ disable password auth on all exposed SSH services
- Multi-factor authentication โ enforce 2FA (TOTP or hardware keys) on all web-facing services via a centralized SSO gateway
- WHOIS privacy โ enable registrant privacy on all domains to limit personal OSINT surface
- Service exposure audit โ regularly scan your own infrastructure and minimize exposed management interfaces
- Breach monitoring โ subscribe to HaveIBeenPwned and similar services for all associated emails
- Certificate transparency monitoring โ track new certificates issued for your domains
- Avoid password patterns โ handles, keyboard walks, and cultural words are predictable; use generated high-entropy passwords
- HASSH-based detection โ the identified HASSH fingerprints can be used in IDS/IPS rules
- Deploy honeypots โ this entire analysis was possible because a honeypot captured the attempts. Without it, the targeted nature of these attacks would have been invisible in standard firewall logs
- Credential rotation after any exposure โ rotate ALL credentials when any service is exposed, not just the directly affected ones
๐ We See Everything
This dossier documents what happens when opportunistic scanning meets targeted intelligence โ and when the target is paying attention. Among ~76,000 generic brute-force attempts from ~2,900 IPs, two campaigns stood out โ not because of their volume, but because of their knowledge.
The attacker knew our domain, our services, our names, our family, and our old passwords. They reversed a family member's name, wrote "thank you" in our native language, constructed a password from our handle and a keyboard walk, tried the default for Apache Guacamole (wrong technology), and generated 326 passwords from our domain using leetspeak and year-based suffixes. They used 42 IPs across 16 countries, rotated between SSH toolkits, and deployed a post-quantum key exchange algorithm in their final probe.
We reverse-engineered their password generation algorithm. We reconstructed their OSINT workflow step by step. We identified every IP, every fingerprint, every credential, every username they tried. We traced the single IP that links both campaigns. We checked every log source across our infrastructure and confirmed zero lateral movement. We identified the credential they constructed โ and rotated it within hours.
They failed because every leaked credential had been rotated. They failed because the exposed service had been secured. They failed because every web service requires two-factor authentication โ a password alone is not enough. And when their reconnaissance uncovered a constructed credential that was still active, our honeypot analysis detected it and triggered emergency rotation before it could be exploited.
The internet remembers every service you've ever exposed, every credential you've ever leaked, and every name you've ever published. The difference between a breach and a dossier is whether you're watching your own honeypots.
We were watching.
Data source: Cowrie SSH honeypot (port 2222). Analysis period: March 25 โ May 7, 2026 (44 days). All IOCs are published for community defense. Personally identifiable information has been redacted from this public report. Full unredacted version retained for law enforcement and incident response purposes.