immersive labs application security
11 TopicsAdvanced CTF Challenge: Serial Maze
Need hint on Serial Maze. Have gone through html & javascript, couldn't find the token. Using dirb found one endpoint "http://10.102.17.87/2257", its response "What a pickle... You need the secret to continue." No sure how to proceed form here. Thanks, Sabil72Views0likes3CommentsSnort Rules: Ep.9 – Exploit Kits
I am pulling my hair with question number 8 Create a Snort rule to detect the third GET request in the second PCAP file, then submit the token. This one should do it but it is not working. alert tcp any any -> any any (msg:"detect the third GET request"; content:"e31e6edb08bf0ae9fbb32210b24540b6fl"; sid:1000001) I tried so many rules base on the first GET header and still unable to get the token. Any tips?67Views0likes1CommentVibe coding your way to a ZAP MCP server
If you haven’t heard already, Model Context Protocol (MCP) is a new, standardised way that LLMs and AI agents can communicate with external tools. Lots of people in the AI community have been calling it a “USB-C for AI” because you only need one connector for many tools. Today, however, I’m not going to go deep into the weeds about MCP particulars or what a typed JSON-RPC envelope is. Instead, I’m taking you on an adventure I embarked on a few weeks ago. It involved me talking to ZAP in plain English, going to get a cup of coffee, and coming back to a report on a vulnerable web application. But before I embarked on my quest, I needed some equipment: An LLM: I went with Claude Sonnet 4, from Anthropic’s family of foundational models and the creator of MCP. A way to interact with an LLM that can also use MCP servers: Conveniently, Claude has a wonderful desktop app that lets you do this easily. Some MCP servers: Most importantly, the Filesystem MCP server for the ultimate budget-friendly Claude Code imitation. An SDK to write my own ZAP MCP server, to avoid re-inventing the MCP wheel. The Python MCP SDK did nicely. With these tools in hand, it was time to see how far I could take this idea, based purely on vibe coding. Andrej Kaparthy, co-founder of OpenAI (the creators of ChatGPT) and coiner of the term, explains: “There's a new kind of coding I call "vibe coding", where you fully give in to the vibes, embrace exponentials, and forget that the code even exists”. Vibing responsibly While it’s tempting to be allured by the simplicity of telling an LLM to “code me a ZAP MCP server” and have it produce lines of code, it’s generally in your long-term interests to have some understanding of what you’re trying to achieve. Then, you can ask the AI to either expand on that understanding or formulate a plan before it attempts to execute. Don’t just take it from me; this is Anthropic’s first recommended workflow for using Agentic AI. With responsible vibing in mind, I crafted a fairly simple exploratory prompt. I want to create an MCP server for the open-source proxy tool ZAP. I know it already has a comprehensive Python SDK for interacting with it in an automated fashion. How could I leverage the existing SDK to create a ZAP MCP server easily? Putting the code into vibe coding I enabled Claude to read and write files using the Filesystem MCP to create the ZAP MCP server project. In the long run, this saved a lot of time copying and pasting code back and forth between VSCode and Claude Desktop. To do this, I just had to write a small bit of JSON to configure the Filesystem MCP so it knew what directories it could access. Once I’d set that, I restarted Claude Desktop for it to take effect. The next prompt was as simple as telling Claude where it should create the Python project, which version to use, and what configuration file to use for dependencies: Use the fileserver MCP to create the necessary project and code files for this ZAP MCP project in the directory ~/Development/mcp/zap-mcp which you have access to. The project should use Python 3.12 and dependencies set up with a pyproject.toml. And just like that, the AI is using one MCP to write another. Vibe check I love a YOLO code execution as much as anyone, but I decided to take a look at the project code it created, since I was running this directly on my personal computer. The main file is 1200 lines of code! But why should I care if I don’t have to write or maintain any of it myself? # Initialize MCP server self.server = Server(“zap-mcp-server”) I’m more interested in where the MCP stuff is actually happening. Here, the code initializes an MCP server, which makes sense, since I was trying to build one. On line 4, you can see a decorator @self.server.call_tool() is used to handle when the function is called by an MCP client, such as Claude Desktop. Interestingly, it chose to skip the higher-level @server.tool() function that handles all the boilerplate. But again, why should I care if I’m not writing it? The only other particularly interesting part is that the actual code to perform an action in ZAP is about three lines long. That’s because it’s leveraging the wonderful ZAP SDK, just like I planned in the first prompt. Then there’s another decorator on line 4 of this code snippet. Again, the code used the lower-level decorator function list_tools() because it used call_tool() to explicitly list what tools were available from the ZAP MCP server to the MCP client. Ultimately, this gave me more control over the input data – which was useful when interfacing with another SDK that was expecting certain types and structures like the ZAP one I was working with. I quickly checked the code, and then I was almost ready to take this MCP server for a spin! There was just one last bit of JSON configuration to do. I had to specify how to run the server, and from what directory. After one last restart of Claude Desktop, I was ready to make ZAP get to work, through the magic of plain English and MCP servers. Right…? WRONG! Turns out the vibes weren’t checked well enough, and they went from being immaculate to immensely painful. A fair few errors popped up before I could successfully get this to even run one ZAP command. So I manually fixed this code like a responsible developer kept feeding the errors into Claude until it fixed them. Which eventually gave me the ability to get the MCP tool working! Vibe code victory! Key takeaways I’ll leave you with a few lessons I took away from this project: Vibe coding is more than just a meme. It has genuine uses, especially for prototyping. That doesn’t mean it’s capable of autonomously creating projects from start to finish that are ready for enterprise deployment (yet). “Context engineering” is just as important as a good prompt. Use tools such as Claude’s Project Knowledge to improve an LLM's domain knowledge. MCP can be an incredibly powerful tool, but it doesn’t come without risks. You’re potentially giving information to parties that don’t have the same data privacy policies as the LLM you’re using. You’re authorizing actions on your behalf that you may not be aware of. MCPs aren’t particularly different or difficult to build than to a normal client server architecture. If you have a tool with an API, you’ll be surprised at how quickly you can turn it into an MCP server. That’s it! Thanks for coming on this adventure with me. I hope you get inspired to start writing and using your own MCP servers.64Views1like0CommentsFrom XSS and SQLi to AI-generated code and supply-chain compromise: How application security is evolving
Keeping up with vulnerabilities is like playing a never-ending game of whack-a-mole. One day, we were knee-deep in XSS payloads and buffer overflows; the next, developers everywhere were plugging SQL injection holes with duct tape and regex. A lot of our earlier tech wasn’t built with security in mind – or at least not at the forefront of our minds. But over the past two decades, the culture has changed, and developers are shifting left. Programming languages, as well as the frameworks and ecosystems around them, are evolving and adapting to evade security threats. XSS: From everyday headache to “mostly handled” Remember when cross-site scripting (XSS) was every web developer’s nightmare? In the 2000s, it seemed like every other website was vulnerable. If you were lucky, your users’ only punishment was an annoying pop-up. If not, credentials and session cookies were up for grabs. Modern languages and frameworks took proactive steps in their designs. Today, many of them have built-in protections against common vulnerabilities like XSS. Some examples are: React, Angular, Vue: Automatically escape output by default. You have to go out of your way to render raw HTML (and they make you feel guilty about it). Django, Ruby on Rails, ASP.NET Core: Templates escape user input by default. Browsers: Even they pitch in, with features like Content Security Policy (CSP). It’s still possible to write a vulnerable application, but the bar is higher. As a result, attackers have a bigger hurdle to jump over. This is thanks to the evolution of how languages and frameworks approach security – not as a feature, but as the default. SQL injection: OR 1=1 is mostly history SQL injection once powered major data breaches. Now, parameterized queries have become the norm, and we’re on our way to leaving those days behind. Object-Relational Mappers (ORMs) like SQLAlchemy, Entity Framework, and Hibernate generate safe SQL. Most modern languages make string concatenation in queries unnecessary (and uncool). Even PHP, once infamous for its “raw SQL everywhere” approach, now encourages prepared statements and offers safe database APIs. Not a perfect world, but much improved. It’s crucial to keep in mind, however, that technology shouldn’t be relied upon uncritically to keep applications secure. Developers must do their due diligence. Memory mischief: The rise of Rust (and memory-managed languages) C and C++ are legendary for performance. And legendary for buffer overflows, use-after-free, and all manner of memory mischief. Enter memory-safe languages: Java, C#, Python: Garbage collection and managed memory eliminate entire classes of bugs. Rust: Takes it up a notch with ownership semantics, preventing data races and dangling pointers at compile time. A lot of system-level work has migrated to these “safer” languages, and the impact is apparent in everything from embedded devices to operating systems (hello, Rust in the Linux kernel). The new frontiers: AI and supply chain attacks Just as one threat starts to become old news, new threats emerge. Two of these are: Supply chain compromise The SolarWinds breach and NPM “event-stream” incident have put supply chain attacks in the spotlight over the last decade. It goes to highlight that you can write perfect code and still get breached because a dependency many levels deep was compromised. Some of the changes we’re seeing as a result: Package registries are adopting MFA and signing requirements. Software Bill of Materials (SBOM) is becoming a must-have, especially in regulated industries. But the battle is ongoing. If anything, our code is more interconnected than ever, and the rise of “vibe coding” is complicating matters further. AI-generated code AI tools like GitHub Copilot and ChatGPT are generating millions of code snippets. This is a double-edged sword. You get increased productivity, but the code is often vulnerable. This is partly a reflection of the insecurities in the code that the models were trained on. I asked ChatGPT 4.5 to identify the vulnerability in the following code and it couldn't. Can you? Leave a reply with your thoughts! @limits(calls=6, period=60) @app.route("/change-password", methods=["POST"]) def change_password(): user = session.get("user") if not user: return jsonify({"message": "Unauthorised"}), 401 data = request.get_json() password = data.get("new_password") if not password: return jsonify({"message": "Password is required"}), 400 if not db.change_password(user, password): return jsonify({"message": "Failed to change password"}), 500 return jsonify({"message": "Password changed successfully"}), 200 @limits(calls=6, period=60) @app.route("/login", methods=["GET", "POST"]) def login(): data = request.get_json() user = data.get("user") password = data.get("password") if not user or not password: return jsonify({"message": "Username and password are required"}), 400 if not db.authenticate(user, password): return jsonify({"message": "Invalid username or password"}), 401 session["user"] = user return jsonify({"message": "Logged in successfully"}), 200 The changes I expect to see going forward are: Guidelines and governance for AI-generated code: Programming languages or coding standards may soon explicitly include guidelines, validation rules, or security frameworks tailored to AI-assisted coding, ensuring generated code adheres to secure patterns. Work is already being done to create rules files for improved security. Integrated security checks at the IDE level: IDEs may embed deeper vulnerability scanning and real-time feedback directly within coding processes. Development environments or compilers may also come integrated with validation tools specifically attuned to potential weaknesses inherent in AI-generated code. Increased reliance on static/dynamic security analysis tools: Enhanced automated scanning integrated into CI/CD pipelines, detecting flaws pre-deployment. Keeping people in the loop: Security awareness should be a top priority, so everyone is ready for the worst-case scenario. Proving and improving skills: Developers’ training should increasingly emphasize secure coding, particularly when assisted by AI tools. At the current stage, thorough PR reviews are more crucial than ever. As with any code, always review and test AI-generated code, especially for security-sensitive logic. AI is a tool, not an auditor. Security: Not a feature, but a default Application security has come a long way from the Wild West days of the early internet. The biggest shift in the software development landscape is that security is no longer a bolt-on. Modern programming languages and ecosystems try to make the secure path the easy path. Defaults are safe (escaped output, parameterized queries), dangerous operations are noisy (compiler warnings, explicit function names), and security updates are automated (thanks to package managers and CI/CD integrations). Of course, attackers are creative, and the landscape is always shifting. But the evolution of programming languages, as well as the surrounding tools and communities, means developers have a fighting chance. While we face newer threats like AI-generated code vulnerabilities and supply chain compromise, the foundations are getting stronger. The key is to keep learning, stay skeptical, and use the tools at your disposal properly. The biggest shift I would like to see is the human element no longer being viewed as the “weakest link”. The moles never stop popping up, but now, at least, we have better mallets – and the resources to help us use them.91Views2likes0CommentsAWS Systems Manager: Demonstrate Your Skills
Hi. I'm trying to complete the final lab in the AWS Systems Manager: Demonstrate your skills lab. I'm trying to create an IAM policy as requested, but it isn't being accepted. Here is the question: And here is my policy: { "Version": "2012-10-17", "Statement": [ { "Sid": "VisualEditor0", "Effect": "Allow", "Action": [ "s3:GetObject", "s3:GetObjectVersion" ], "Resource": [ "arn:aws:s3:::arn:aws:s3:::aws-ssm-eu-west-1/*", "arn:aws:s3:::arn:aws:s3:::amazon-ssm-eu-west-1/*", "arn:aws:s3:::arn:aws:s3:::amazon-ssm-packages-eu-west-1/*", "arn:aws:s3:::arn:aws:s3:::aws-ssm-document-attachments-eu-west-1/*", "arn:aws:s3:::arn:aws:s3:::patch-baseline-snapshot-eu-west-1/*", "arn:aws:s3:::arn:aws:s3:::aws-quicksetup-patchpolicy-*/*", "arn:aws:s3:::arn:aws:s3:::metroliate-1c81a515/*" ] }, { "Sid": "VisualEditor1", "Effect": "Allow", "Action": "s3:PutObject", "Resource": "arn:aws:s3:::arn:aws:s3:::metrolio-ssm-logs-74c21f24/*" }, { "Sid": "VisualEditor2", "Effect": "Allow", "Action": "s3:GetEncryptionConfiguration", "Resource": "arn:aws:s3:::arn:aws:s3:::metrolio-ssm-logs-74c21f24" } ] } Any help on what I'm doing wrong would be much appreciated.Solved41Views0likes2CommentsDecoding Coding: Picking a Language
These days, more and more jobs can benefit from being able to write simple scripts and programs, especially in cybersecurity. For example, pulling data from an API, scraping web pages, or processing large data files to extract information – the list of uses is virtually endless! Tempting as it is to dive right in, there are several things worth thinking about before you begin. This article will discuss one of the most important choices – selecting a language. What to consider when choosing a language A basic understanding of programming languages can make your life easier, increasing your adaptability and finesse in different environments. But with tons of languages like Python, Java, JavaScript, Go, Rust, and more, which one should you choose? Here are the crucial factors to consider: What's available Can you install whatever language you like to run your code, or are there limitations? If you have an enterprise-managed computer, you might not be able to install new software or languages, and you may need to use the default options. For Windows, this is PowerShell. Bash Script is the equivalent for Mac and Linux devices, and Python is often available too. Your personal experience and interest This one might sound obvious, but it does matter. We learn better and faster when we're invested in the subject. Look at your previous experiences. Have you worked with any programming languages before? Did you enjoy them? For example, if you had a good experience working with Python, let that guide your decision! That said, don't shy away from learning something new if there's a good reason or you’re curious to do so. What's trending in your organization Does your organization or team predominantly use a specific language? Not only would learning that one help you communicate better with your colleagues, but it could also give you an edge while working with systems developed in that language. Plus, there’ll be plenty of people to talk to if you get stuck! The language's capabilities and nature Like people, different languages have different strengths. Some are fantastic for web development (like JavaScript), while others are better suited for system-level programming (like C). Python is often an excellent choice. It's considered easy to learn, incredibly flexible, and powerful due to the huge catalog of packages available. While it isn't as fast as many other languages, for most purposes, it's usually more than fast enough. Java is a very widely used object-oriented programming language and can be extremely fast. The learning curve is steeper than Python, but there are loads of learning resources available. JavaScript (not to be confused with Java!) isn’t as useful for quick standalone scripts or applications, but it's the dominant language for websites and browsers, so understanding it is practically a superpower for testing and manipulating websites and applications. C and C++ allow low-level access to memory and offer a lot of flexibility – incredibly helpful when evaluating systems with these languages at their core. Available tools and training Great tools can make tough jobs easier. Certain programming languages have robust toolsets that can help automate your tasks. For instance, Python has a wide array of libraries and frameworks that make handling big projects a cinch while saving you time and effort – why reinvent the wheel when you can just import it? Take a look at what training is available for the language you’re interested in. Older and more popular languages are likely to have more to choose from, but there’s loads out there and a lot of it is free! Also, consider what tools you might already have access to within your organization. Community and support If a programming language has a large active community, it means help is readily available when you get stuck. Languages like Python, JavaScript, and Java have strong communities and plenty of online resources available. Scope for growth If you're planning to learn a language, why not pick one that's in demand? Check job boards, look at industry trends, and see if learning a particular language can give your professional growth a boost! Summary Remember, no language is “the best". The best is the one that suits your needs and circumstances. You might even find mastering multiple programming languages useful over time. Just like speaking multiple languages, the more you know, the better you can communicate in different environments! Once you understand some of the basic programming concepts, like variables and loops, it’s easier to learn a second or third language. Learning a programming language may initially seem like climbing a steep mountain. But once you get the hang of it, you'll realize that the view from the top was well worth the hike! Want to take the next step? Here are some lab collections that may help you learn a bit more about PowerShell and Python: PowerShell Basics Offensive PowerShell Introduction to Python Scripting Share your thoughts If you’re new to coding, tell us what language you’re trying out! Why did you pick it, and would you make the same choice again? Are there any specific challenges you found or any relevant experiences you’d like to share?71Views1like2CommentsIntroduction to Elastic: Ep.9 - ES|QL
I’m stuck on question 18 i need this to complete the lab. The question says ‘Perform a final query using all of the techniques used in the previous questions. What is the average speed per hour for ALL trips that start in the borough of “Brooklyn” and end in the borough of “Manhattan”? Provide your answer to at least three decimal places. any ideas?91Views1like1CommentWeaponization: Payloads – Obfuscation Using PowerShell
For question 5 to 7 I have completed but I am not able to find the tokens.txt file. Any hint or guidance? how to get that or where to find? Q7: Save the result to a file named shell.txt in the /home/iml-user/Desktop/ directory. If you've done this correctly, a token will be added to token.txt54Views0likes1CommentSecure Code Comments: One Easy Way to Steward Your Application Security Culture
While traditional code comments focus on explaining the code's functionality, security-focused comments are crucial to promoting secure coding practices throughout the development lifecycle (SDLC). By making this simple tactic part of your natural workflow, you can assert your knowledge and become a security champion. Let's explore how integrating security comments into your code can benefit you and the security team. Leading Forward Using Secure Code Comments Integrating security into your daily coding isn't just about ticking requirement boxes; it's about building a security mindset that makes you indispensable. Secure-code comments are low-hanging fruit for sharing knowledge, learning from others, and making security a seamless part of your day. Senior developers and application security champions can quickly and effectively educate other developers about best practices without leaving the comfort of their Integrated Development Environment (IDE). Best practice for code comments suggests emphasizing the why, not the what. Security-focused comments are no different. Meanwhile, they play a crucial role in promoting secure coding practices, enabling teams to: Explain Key Security Moves: Share the rationale behind specific security measures, such as input validation, encryption, and access control mechanisms. Flag Red Flags: Spot potential weaknesses in your code, like SQL injection, cross-site scripting (XSS), and unprotected data. Share Knowledge: Link to relevant security standards, guidelines, and resources and facilitate efficient code reviews. Enhancing Code with Security Comments–Two Examples Example 1: Preventing SQL Injection with Parameterized Queries (Python) Let’s consider a simplified Python function, which performs a simple insert operation into a database: def insert_user(conn, name, email): """ Inserts a new user into the 'user' table. Args: conn: A sqlite3 connection object. name: The name of the user. email: The email address of the user. Returns: None This function uses a parameterized query to prevent SQL injection vulnerabilities. See: CWE-89 https://cwe.mitre.org/data/definitions/89.html By using placeholders (e.g., `?`) and passing the actual values as separate arguments, we avoid direct string concatenation. This ensures that user-supplied input cannot be manipulated to modify SQL commands. """ sql = """INSERT INTO user (name, email) VALUES (?, ?)""" cur = conn.cursor() cur.execute(sql, (name, email)) conn.commit() cur.close() As you can see, in addition to the regular docstring, we succinctly mention why we’re using parameterized queries over string concatenation. We also reference a CWE and provide a link for anyone who wants to learn more. With just three extra sentences in a function comment, we’ve given less experienced developers who are code spelunking a quick lesson (or reminder) about why and how to prevent SQL injection. Example 2: Mitigating XSS Vulnerabilities with DOMPurify (React) Let’s take a look at another example, this time on a React frontend. Here, we’re knowingly doing something potentially dangerous but effectively communicating to other developers the mitigations applied. /** * Displays user-generated HTML content, sanitizing it with DOMPurify to prevent XSS vulnerabilities. * * This component uses `dangerouslySetInnerHTML` because the content being displayed *must* include HTML markup. * Alternatives like rendering plain text or using a limited subset of HTML tags are not sufficient for this use case. See: https://kanban.system/t/123 * **Security Considerations:** * * **CWE-79 (Improper Neutralization of Special Elements used in an HTML Page): https://cwe.mitre.org/data/definitions/79.html * This code directly addresses CWE-79 by sanitizing the user-provided HTML before rendering it. Without sanitization, malicious * users could inject JavaScript code that would be executed in the context of the website, leading to * XSS attacks. * * **Why not just use textContent?** If we used `textContent` or similar methods, any HTML tags in the user * input would be treated as plain text and displayed as-is. This would prevent XSS, but it would * also defeat the purpose of allowing users to input HTML in the first place. * * **Why DOMPurify?** DOMPurify is a widely used and well-maintained library specifically designed for * sanitizing HTML. It's more robust and secure than attempting to create a custom sanitization * solution. It handles a wide range of potential XSS attack vectors. * * @param {string} htmlContent The user-generated HTML content. This is assumed to be untrusted. * @returns {JSX.Element} The sanitized HTML rendered within a div. */ function SafeHTMLDisplay({ htmlContent }) { const sanitizedHTML = DOMPurify.sanitize(htmlContent); return ( <div dangerouslySetInnerHTML={{ __html: sanitizedHTML }} /> ); } This time we go into more detail about the why. Let’s break it down: First, it’s important to acknowledge that the original approach isn’t best practice. Second, you can level up developer awareness about alternative options.Then, connect the dots for maximum impact, sharing why this approach is required to satisfy product requirements. Finally, it’s important to detail security considerations with CWE IDs, codifying the weakness you’re proactively mitigating; yes, you can even justify the introduction of another dependency compared to a custom implementation. Any future developer tasked with modifying the comment feature will quickly understand the importance of keeping this mitigation rather than “cleaning up the code” because it still functions “the same” without it. As an AppSec developer or security champion, you’ve just avoided another security report being raised because of a regression introduced by an over-eager junior developer. It's well worth the 15 lines of extra code. Even better, any security engineer performing a secure code review will be much more confident that their developer understands why they wrote the code the way they did. This knowledge, in turn, expedites that coveted ‘approve’ on their pull request, reducing the time to get the code safely into production. Identifying and codifying vulnerabilities with Find the Flaw Setting the tone with security-focused comments largely falls to the lead developer or security champion, presenting an easy opportunity for aspiring champions to stand out. Remember, the goal is to identify and codify weaknesses in code before or as it is being written; this approach ensures others can craft easy-to-understand security comments too. Whether you’re just starting out or looking to grow your skillset, Immersive AppSec’s Find the Flaw collections provide ample opportunities to build critical DevSecOps muscle memory. You’ll learn to identify various common vulnerabilities in code and recognize what CWE IDs they correspond to. Writing security-focused comments will feel like second nature when you're coding up a storm! Beyond Code Comments: Empowering Your Manager to Recognize the Power of AppSec Training Code comments are a valuable AppSec tool, albeit only one piece of the puzzle. To cultivate a developer-led security culture, organizations need managers who recognize the power of comprehensive training programs for their elite developers. These programs support proactive developers with the knowledge and skills to build secure applications from the ground up. As a result, the organization achieves development velocity SLAs and application security simultaneously. Remember to share your experience learning by doing, gaining the attackers’ perspective, which Immersive Labs AppSec offers. Your manager and teammates should recognize the value of using safe, real-world scenarios and interactive exercises, such that the training you do (now) targets the problems you have (now). Share your thoughts Check out this Find the Flaw collection and then share your thoughts with The Human Connection community: For developers: Does adding security rationale to your comments feel like an ‘easy enough' lift? For security champions: Are you already using this technique or something similar? How have you convinced other developers to adopt this style of commenting?60Views1like0Comments