<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.4.1">Jekyll</generator><link href="/feed.xml" rel="self" type="application/atom+xml" /><link href="/" rel="alternate" type="text/html" /><updated>2026-03-17T01:00:28+00:00</updated><id>/feed.xml</id><title type="html">Bounce Security</title><subtitle>Efficient, Value-Driven Product Security</subtitle><entry><title type="html">Making your preparations</title><link href="/blog/2025/07/09/making-your-preparations.html" rel="alternate" type="text/html" title="Making your preparations" /><published>2025-07-09T12:30:00+00:00</published><updated>2025-07-09T12:30:00+00:00</updated><id>/blog/2025/07/09/making-your-preparations</id><content type="html" xml:base="/blog/2025/07/09/making-your-preparations.html"><![CDATA[<h4 id="introduction">Introduction</h4>

<p>Your course is confirmed and you’re ready to go? Fantastic! That’s a major milestone worth celebrating. 🎉 Now that you’re past the proposal phase, it’s time to think about the practical preparations that will ensure your course is not just delivered, but delivered smoothly and memorably.</p>

<p>In this post, I’ll walk you through essential pre-course considerations, from visa planning to organizing handouts, so that nothing catches you off guard when it’s go time.</p>

<h4 id="visa-considerations-more-than-just-a-stamp">Visa Considerations: More Than Just a Stamp</h4>

<p>While not strictly a financial issue, visa planning is a <em>must-do</em> if you’re delivering a course abroad. Skipping this step could derail your training before it begins.</p>

<h5 id="getting-a-visa-to-enter-the-country">Getting a Visa to Enter the Country</h5>

<p>Ask yourself: <em>How easy is it for me to enter the country where I’ll be training?</em></p>

<p>If you don’t have the privilege of a streamlined entry process (like the US ESTA or the upcoming EU ETIAS), start early. Some visa applications take weeks or even months. Even the time between your course being accepted and the conference date might not be enough, especially if there is a backlog.</p>

<p><img src="/assets/img/bhseries/31.jpeg" alt="image" /></p>

<h5 id="getting-a-visa-that-lets-you-get-paid">Getting a Visa That Lets You Get Paid</h5>

<p>Here’s where things get tricky. I’m not a lawyer (technically, I’m an accountant but I’ve never practiced), so this isn’t legal advice. However, be aware: Getting paid to train abroad might require a different visa than just attending a conference.</p>

<p>Check whether you’ll legally be allowed to <em>work</em> (i.e. deliver training) and <em>get paid</em> while in that country. Conferences often won’t have definitive guidance on this either so it’s your responsibility to do the homework.</p>

<p>Note that the US in particular has gotten stricter about this and in some cases people were detained at immigration for attempting to come in to work on the wrong visa.</p>

<h4 id="supplementary-materials-going-the-extra-mile">Supplementary Materials: Going the Extra Mile</h4>

<p>Beyond your core curriculum, it’s a great idea to prepare supplementary materials that enhance the learning experience. These can include physical goodies, printed handouts, or digital resources. Let’s break them down.</p>

<h6 id="goodies-and-extras">Goodies and Extras</h6>

<p>If you’ve promised participants anything extra (such as stickers, USB drives, branded gear) now’s the time to deliver. But beware: You might not know your final headcount until right before the event.</p>

<p>At Black Hat 2023, my attendee numbers jumped by 50% in just two weeks.</p>

<p>So, plan generously. It’s better to have a few extras than run out and disappoint attendees. For expensive items, consider a cutoff: for example, <em>“Free hardware kit for sign-ups received 3+ weeks in advance.”</em></p>

<p><img src="/assets/img/bhseries/32.jpeg" alt="image" /></p>

<h5 id="course-materials">Course Materials</h5>

<p>For in-person training, I’m a big fan of printed materials. When exercises require referring to multiple documents, printed copies save participants from constantly alt-tabbing between different screens.</p>

<p>I always print and bring these materials myself to ensure quality and timing. The exception? At Black Hat, they print a course workbook for you which is a nice touch!</p>

<p><strong>Pro Tip:</strong> Never pack your printed materials in checked luggage. Ask me why one day :)</p>

<p><img src="/assets/img/bhseries/workbooks.jpg" alt="image" class="blog-image" /></p>

<p>On one occasion where I wanted to go a little above and beyond, I ordered plastic document folders via Amazon to the venue. Each participant got one to organize their handouts, plus some extras like sticky dividers and branded stickers.</p>

<p><img src="/assets/img/bhseries/attendee_pack.jpg" alt="image" class="blog-image" /></p>

<p>Printed materials are great during the course, but soft copies are critical for long-term reference. I provide PDFs unless I want students to edit the files themselves.</p>

<p>I “drip feed” exercise materials throughout the course, which adds a bit of complexity but keeps students from jumping ahead. For slides, I always ensure the numbering on the handouts matches the numbering on screen. This keeps everyone on track.</p>

<p><img src="/assets/img/bhseries/33.jpeg" alt="image" /></p>

<h4 id="dont-overthink-it-focus-on-delivery">Don’t Overthink It: Focus on Delivery</h4>

<p>While all this prep helps, don’t lose sight of what truly matters, the <em>content</em> and the <em>experience</em>. Your delivery, your energy, and the interactions you create with participants are what make your course memorable.</p>

<p>Handouts and goodies? They’re just the icing on the cake.</p>

<h4 id="looking-for-more">Looking for more?</h4>

<p>That’s a wrap for now but I have more ideas in the pipeline. Did you find this helpful? Let me know what you’d like to hear more about or which questions you want answered next.</p>

<p>Let’s make your next training the best one yet. 🚀</p>]]></content><author><name>josh</name></author><category term="blog" /><summary type="html"><![CDATA[Introduction]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="/assets/img/bhseries/32.jpeg" /><media:content medium="image" url="/assets/img/bhseries/32.jpeg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Selling and Marketing your course</title><link href="/blog/2025/06/24/selling-your-course.html" rel="alternate" type="text/html" title="Selling and Marketing your course" /><published>2025-06-24T12:30:00+00:00</published><updated>2025-06-24T12:30:00+00:00</updated><id>/blog/2025/06/24/selling-your-course</id><content type="html" xml:base="/blog/2025/06/24/selling-your-course.html"><![CDATA[<h4 id="introduction">Introduction</h4>

<p>So your course got accepted? <strong>Congratulations!</strong> 🎉 That’s a huge win and shows your proposal resonated with the review board. But now comes the real challenge: <strong>getting people to actually attend</strong>.</p>

<p>However, on this specific topic, I cannot pretend to be an expert or to have seen major success when doing this. I will try and provide my perspective and ideas but your mileage will certainly vary. There are plenty of other things you might want to try and maybe even consult with other people with more expertise.</p>

<h4 id="size-of-the-field-size-of-the-audience">Size of the Field, Size of the Audience</h4>

<p>Before diving into promotion tactics, it’s worth understanding the competitive landscape.</p>

<p>Three big factors influence how easy or hard it will be to sell your course:</p>

<ol>
  <li>How many people usually attend training at the conference?</li>
  <li>How many <strong>other</strong> courses are being offered?</li>
  <li>Can you attract people to attend the conference <strong>specifically for your course</strong>?</li>
</ol>

<p><img src="/assets/img/bhseries/11.jpeg" alt="Cybersecurity" /></p>

<p>For example:</p>

<ul>
  <li><strong>OWASP Global AppSec</strong> events often run up to 10 courses in parallel, with around 100-200 total attendees at the training and around 800 attendees at the conference.</li>
  <li><strong>Black Hat USA</strong>, on the other hand, may feature <strong>~140</strong> courses. I remember seeing a lunch room packed with <strong>1,000+ people</strong> during training days.</li>
</ul>

<p>Whilst the numbers at Black Hat may sound particularly promising, note that <strong>distribution isn’t equal</strong>. Some courses are held in huge rooms with dozens of students, while others are tucked away with small groups.</p>

<p>This makes it crucial to <strong>stand out</strong>.
I’ve already discussed finding your niche at length in previous posts. In addition to this, I have also tried ensuring the course appears relatively high up in the course list through an “optimised” title and also adding an explanatory video to the course description wherever possible (but more on videos further down).</p>

<p>I can’t say it dramatically boosted my numbers, but who knows what would’ve happened if I had named the course “Zebra Security Essentials”? 🤷‍♂️</p>

<p>Either way, <strong>don’t rely solely on being listed on the website</strong>. You probably want to do more than that.</p>

<h4 id="what-you-actually-get-from-the-conference">What You Actually Get from the Conference</h4>

<p>Many conferences do <strong>minimal marketing</strong> for individual courses.</p>

<p>Most conferences might tweet or post once or twice on LinkedIn or other social media networks. I haven’t trained at TyphoonCon, but it’s one of the only instances I’ve seen a conference do <strong>promoted tweets for individual courses</strong>.</p>

<p>You can sometimes ask organizers to amplify your own posts — but their support is limited and often hinges on you already having a <strong>strong social media presence</strong>.</p>

<p><img src="/assets/img/bhseries/12.jpeg" alt="Cybersecurity" /></p>

<h4 id="building-your-social-media-presence">Building Your Social Media Presence</h4>

<p>If you have a strong social media presence then you are clearly already good at self-promotion so that will help a lot in this context. You can probably skip this section (although I’d love to hear your tips 😀).</p>

<p>I made an effort to increase my social media activity a little (specifically on Twitter and LinkedIn) in the run up to these courses. I grew my follower count slightly and made an effort to post more frequently and try and engage with other posts. I would usually focus on subject matter related to my course including sometimes mentioning work I was doing on developing the course.</p>

<p>I also made an effort to prepare some short videos as this seemed to be a good way of communicating information in an effective way and be in line with how many people seem to consume information right now. I was also able to outsource the video editing which saved time. I varied between videos specifically about the course and also short videos on related topics.</p>

<p>Some interesting discussions developed from both text and video posts and in general I think that having an active social media presence has professional benefits anyway. It does however require a lot of effort to have an impact.</p>

<p><img src="/assets/img/bhseries/13.jpeg" alt="Cybersecurity" /></p>

<h2 id="other-ways-to-build-awareness">Other Ways to Build Awareness</h2>

<p>If social media isn’t your thing (or isn’t enough), here are some alternative channels I explored:</p>

<h5 id="-conference-talks">🎤 Conference Talks</h5>

<p>Speaking at conferences, specifically on your training topic or even on other related topics, is a great way to <strong>build credibility</strong>, expand your presence in the industry, and push your course at the same time.</p>

<p>I couldn’t fund travel to overseas events, but I looked for conferences that <strong>cover speaker expenses</strong>. My largest target was Black Hat USA 2023 so I pushed particularly hard in late 2022/early 2023.</p>

<p>This resulted in:</p>
<ul>
  <li><strong>October 2022</strong> - OWASP Global AppSec San Francisco (Training + Talk)</li>
  <li><strong>January 2023</strong> - NDC Security in Oslo + OWASP Oslo Meetup</li>
  <li><strong>February 2023</strong> - OWASP Global AppSec Dublin (Training)</li>
  <li><strong>April 2023</strong> - QCon London (Speaking)</li>
  <li><strong>June 2023</strong> - DevTalks Bucharest (Speaking)</li>
</ul>

<p>I’d often mention my course at the end of talks or during conversations at these events.</p>

<p><img src="/assets/img/bhseries/14.jpeg" alt="Cybersecurity" /></p>

<h5 id="️-podcasts">🎙️ Podcasts</h5>

<p>Podcasts are another great channel. Less travel but plenty of reach.</p>

<p>I got some great benefits from being a podcast guest including:</p>

<ul>
  <li>Exposure to new audiences</li>
  <li>Valuable feedback on course content</li>
  <li>Deeper conversations that helped refine the material</li>
</ul>

<p>Many podcasts welcome guest suggestions — especially if you have an interesting perspective or topic to pitch.</p>

<h5 id="-paid-marketing-spoiler-meh">💸 Paid Marketing (Spoiler: Meh)</h5>

<p>We tried a small LinkedIn ad campaign. Honestly? No real impact.</p>

<p>Paid ads likely require consistent investment and long-term strategy to pay off. Not ideal for one-off training sessions or a short-term effort.</p>

<h4 id="the-hard-part-self-promotion-is-draining">The Hard Part: Self-Promotion is Draining</h4>

<p>In truth, I found this part <strong>exhausting</strong>.</p>

<ul>
  <li>I’m not a fan of social media pressure.</li>
  <li>I don’t want to be constantly travelling.</li>
  <li>Conference prep takes a toll on time, not just money.</li>
</ul>

<p>All this meant I wasn’t as consistent or aggressive in promoting as I could have been.</p>

<p>For me, the bottom line was that every time I asked course attendees how they found out about the course, they almost exclusively said it was from browsing the conference website and not from social media posts or any other channel.</p>

<p>So lately, I’ve toned it down. Just a few social posts and that’s it.</p>

<h4 id="the-stress-of-gono-go">The Stress of GO/NO-GO</h4>

<p>As I mentioned in a previous post, there’s often a GO/NO-GO decision looming.</p>

<ul>
  <li>Will enough seats sell to justify running the course?</li>
  <li>Will it hit both your <strong>and</strong> the conference’s break-even point?</li>
</ul>

<p>That decision can be stressful. And a little embarrassing if the course gets pulled after a few people have already signed up.</p>

<p>In 2023 I made this more difficult for myself as I planned a family vacation around Black Hat USA. If the training had been cancelled, I’d have had to pay all my own expenses to get to the conference or skip the conference but still travel to the US for holiday.</p>

<p>Luckily, it worked out. But I stressed about it for months. The feeling of relief and excitement I felt when Black Hat confirmed my course was running was unreal.</p>

<p><img src="/assets/img/bhseries/15.jpeg" alt="Cybersecurity" /></p>

<h4 id="a-specialist-discipline">A Specialist Discipline</h4>

<p>Let’s be realistic, sales and marketing is a specialist skillset. You’ll find countless experts who can speak to it better than I can. Hopefully this section provided some useful context although I accept that it is not super actionable.</p>

<p>My most active period was late 2022 through early 2023. While I can’t say how much the self-promotion effort changed the outcome, the opportunity to train at Black Hat and attend DEFCON made it <strong>absolutely worthwhile</strong>.</p>

<p>Only you can decide how much time, energy, and budget to invest in promoting your course. What’s right for you might not be right for someone else.</p>

<h5 id="next-post-make-your-preparations">Next Post: Make Your Preparations</h5>

<p>If your course is confirmed, amazing! In the next post, I’ll walk through the preparations you’ll want to make to help ensure it’s a success.</p>]]></content><author><name>josh</name></author><category term="blog" /><summary type="html"><![CDATA[Introduction]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="/assets/img/bhseries/12.jpeg" /><media:content medium="image" url="/assets/img/bhseries/12.jpeg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Writing your Submission</title><link href="/blog/2025/06/03/writing-your-submission.html" rel="alternate" type="text/html" title="Writing your Submission" /><published>2025-06-03T06:30:00+00:00</published><updated>2025-06-03T06:30:00+00:00</updated><id>/blog/2025/06/03/writing-your-submission</id><content type="html" xml:base="/blog/2025/06/03/writing-your-submission.html"><![CDATA[<h4 id="introduction">Introduction</h4>

<p>You’ve figured out your finances, carved out your niche, and built exercises that pack a punch. Now comes a critical step: getting your course accepted by a conference.</p>

<p>In this post, we’ll dive into how to write a compelling Call for Training (CfT) submission that catches the eye of both review boards and potential attendees.</p>

<p><img src="/assets/img/bhseries/1.png" alt="Cybersecurity" class="blog-image-tall" /></p>

<h4 id="plan-ahead-timing-is-everything">Plan Ahead: Timing is Everything</h4>

<p>CfTs (Calls for Training) often open earlier than the main Call for Papers (CfP). For example, Black Hat and OWASP usually open their CfTs more than <strong>six months</strong> before the event, and they might only stay open for a month.</p>

<p>Failing to plan here could mean missing your window altogether. This means you are going to want to put CfT dates in your calendar and prepare your materials well in advance.</p>

<p><img src="/assets/img/bhseries/2.jpeg" alt="Cybersecurity" class="blog-image-tall" /></p>

<h4 id="know-your-audiences">Know Your Audiences</h4>

<p>Crafting a strong CfT submission requires you to speak to <strong>two distinct audiences</strong>:</p>

<h5 id="1-the-conference-review-board">1. The Conference Review Board</h5>

<p>This group is experienced, discerning, and reviewing dozens (if not hundreds) of submissions. You generally have lots of space to provide them with information about the course and you want to try and differentiate it from the many other submissions they are reviewing.</p>

<p>The key things they care about will be:</p>

<ul>
  <li>How your course <strong>stands out</strong> from the rest.</li>
  <li>Its <strong>technical depth</strong> and relevance.</li>
  <li>Your <strong>credibility</strong> as a trainer.</li>
  <li>How interactive your course is.</li>
</ul>

<p>💡 <strong>Pro Tip</strong>: Include testimonials, past success stories, and why you’re uniquely positioned to teach this subject.</p>

<h5 id="2-your-potential-attendees">2. Your Potential Attendees</h5>

<p>Potential attendees will often only see a small portion of your submission — usually the <strong>abstract</strong> or <strong>summary</strong>. You need to ensure that you include the right information to help them make a decision. You may also have character/word limits to comply with here. (However, I invite you to compare the Black Hat abstract word limit to the length of the abstracts on the training pages 🙃)</p>

<p>Potential attendees are going to want to know:</p>

<ul>
  <li>“Is this course <strong>useful</strong> to me?”</li>
  <li>“Will it help me solve <strong>real problems</strong>?”</li>
  <li>“Will I walk away with <strong>tangible skills</strong>?”</li>
</ul>

<p>Arguably the third audience is your potential attendee’s manager who they are going to have to justify the course to but I think the considerations are similar to those of the potential attendee. To be absolutely clear, you are writing a sales pitch and you need to be thinking and writing accordingly.</p>

<p><img src="/assets/img/bhseries/3.jpeg" alt="Cybersecurity" class="blog-image-tall" /></p>

<h5 id="writing-for-both-key-tips">Writing for Both: Key Tips</h5>

<p>Here’s my approach to balancing both needs:</p>

<ul>
  <li>Keep it short, <strong>punchy</strong>, and <strong>scannable</strong>.</li>
  <li>Address a <strong>relatable pain point</strong>. You want to make your reader think, “That’s me! I need help solving that problem!”</li>
  <li>Be clear on <strong>what participants will do</strong> during the course.</li>
  <li>Make it <strong>sound like fun</strong> to take part in the course!</li>
  <li>Highlight clear, <strong>actionable takeaways</strong>.</li>
</ul>

<p><img src="/assets/img/bhseries/4.jpeg" alt="Cybersecurity" class="blog-image-tall" /></p>

<h4 id="align-with-conference-guidance">Align with Conference Guidance</h4>

<p>Each conference will have its own specific perspective and content that it is looking for. If you are clearly not aligned with that, your submission may be doomed from the start.</p>

<p>Read the CfT guidelines carefully and align your submission accordingly. If the guidance includes sample abstracts or criteria, read through them and ask yourself how well your submission compares to them.</p>

<p><img src="/assets/img/bhseries/5.jpeg" alt="Cybersecurity" class="blog-image-tall" /></p>

<h4 id="for-first-time-trainers">For First-Time Trainers</h4>

<p>New to delivering public training courses? You’ll likely need to prove you can <strong>teach effectively</strong>.
For example, Black Hat requests new trainers to provide ~60 slides of training material plus other information as well so make sure you have that ready in time for the CfT as well.</p>

<p>Any prior experience or videos or whatever else you can provide at this stage will help if you are not a well known trainer. I have also provided ratings and testimonials I have received when training and speaking at other venues.</p>

<h4 id="mission-essential-task-list-metl">Mission Essential Task List (METL)</h4>

<p>Full credit for this point has to go to <a href="https://www.linkedin.com/in/daniel-cuthbert0x/">Daniel Cuthbert</a> from the Black Hat Training Review board who has made it clear on a number of occasions that this is something he expects to see from submissions. Also to <a href="https://www.linkedin.com/in/avidouglen/">AviD</a>, my boss at Bounce Security who has made this standard procedure within Bounce for training course preparation.</p>

<p>A METL is a detailed course breakdown, how long you’ll spend on each topic and what will be covered.</p>

<p>This shows you’ve done more than brainstormed ideas, you’ve <strong>planned</strong> and <strong>structured</strong> the course in a logical way. It should include:</p>
<ul>
  <li>Topic breakdowns with time estimates</li>
  <li>Timings for hands-on to show the lecture-to-exercise ratio</li>
  <li>How learning outcomes map to course segments</li>
</ul>

<p><img src="/assets/img/bhseries/6.jpeg" alt="Cybersecurity" class="blog-image-tall" /></p>

<p>As a some-time CfT reviewer, I can tell you: if your submission lacks this level of clarity, it’s unlikely to make the cut.</p>

<h4 id="get-feedback-before-you-submit">Get Feedback Before You Submit</h4>

<p>Even seasoned trainers benefit from a second pair of eyes.</p>

<p>Tips:</p>
<ul>
  <li>Ask a <strong>former CfT reviewer</strong> if possible.</li>
  <li>At the very least, someone familiar with the material.</li>
  <li>If English isn’t your first language, get a <strong>native speaker</strong> to review.</li>
</ul>

<p>At Bounce Security, our internal review process made a huge difference — right down to workshop titles and tagline polish.</p>

<p>It is highly unlikely you will get feedback from the conference or the review board during the CfT process, regardless of how early you submit. It is possible you might be able to get some feedback if the submission gets rejected but that is already a little too late…</p>

<p><img src="/assets/img/bhseries/7.jpeg" alt="Cybersecurity" class="blog-image-tall" /></p>

<h4 id="add-goodies-if-you-can">Add Goodies (If You Can)</h4>

<p>Extras can make your course more appealing:</p>

<ul>
  <li>Hardware courses might include take-home <strong>tool-kits</strong>.</li>
  <li>Some courses provide pre-configured <strong>VMs</strong> or helpful documents.</li>
  <li>One course at Black Hat even included a <strong>laptop</strong> for every attendee (ambitious, but memorable!).</li>
</ul>

<p>I don’t think these bonuses necessarily replace a compelling course proposition but they might sweeten the deal..</p>

<p>I include special working documents in my course. We’ve also considered offering <strong>follow-up consulting hours</strong> though we haven’t gone forward with that for now. I did notice however that this year Sensepost is <a href="https://x.com/sensepost_train/status/1924472706931528093">offering an extended Q&amp;A session</a> after their courses.</p>

<h4 id="the-waiting-game">The Waiting Game</h4>

<p>Once you’ve submitted… now you wait.</p>

<p>Don’t be discouraged by rejections, they happen to all of us.</p>

<p>I have been rejected multiple times, even after I have been accepted at previous events from the same organisation. E.g. I have never been accepted by Black Hat Asia and was accepted by Black Hat EU for a couple of years but then rejected the following year.</p>

<p>Always ask for feedback (if available) and <strong>iterate</strong> on your submission.</p>

<p><img src="/assets/img/bhseries/8.jpeg" alt="Cybersecurity" class="blog-image-tall" /></p>

<h4 id="coming-up-selling-your-course">Coming Up: Selling Your Course</h4>

<p>If you got accepted, congrats! That’s a huge achievement. 🎉 🎉</p>

<p>But now comes the next big challenge: <strong>getting people to sign up</strong>.</p>

<p>In the next post, I’ll talk about marketing your course in an attempt to turn your hard work into a full classroom.</p>]]></content><author><name>josh</name></author><category term="blog" /><summary type="html"><![CDATA[Introduction]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="/assets/img/bhseries/1.png" /><media:content medium="image" url="/assets/img/bhseries/1.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Planning the Practical</title><link href="/blog/2025/05/13/planning-the-practical.html" rel="alternate" type="text/html" title="Planning the Practical" /><published>2025-05-13T06:30:00+00:00</published><updated>2025-05-13T06:30:00+00:00</updated><id>/blog/2025/05/13/planning-the-practical</id><content type="html" xml:base="/blog/2025/05/13/planning-the-practical.html"><![CDATA[<h4 id="introduction">Introduction</h4>

<p>Let’s be honest: nobody’s signing up for a training course just to sit and listen to someone talk for 7–8 hours a day.</p>

<p>People come to <em>do the things</em>, to get their hands dirty, apply what they’ve learned, and leave with new skills they can actually use. And that’s your edge.</p>

<p>In this post, I talk about how to make the hands-on elements of your course not just functional, but an integral part of the course.</p>

<p><img src="/assets/img/bhseries/practicalintro.png" alt="alt text" /></p>

<h4 id="splitting-the-day-labs-vs-lectures">Splitting the Day: Labs vs. Lectures</h4>

<p>The Black Hat Call for Training (CFT) recommends at least <strong>40% of your course be practical</strong>. That’s great news as it means you only need to talk for 4–5 hours a day.</p>

<p>But here’s the catch: you now need to figure out how to entertain your attendees the remaining time.</p>

<p>I can tell you that the practical segments are <em>the</em> part attendees remember most and will define their takeaway experience. You therefore need to make these segments sound compelling enough for the review board and the potential attendees.</p>

<h4 id="traditional-practical-labs">Traditional, Practical Labs</h4>

<p>If you’re teaching a very hands-on skill such as offensive security, reverse engineering, cloud config hardening, practical labs are likely your core.</p>

<p>But just saying “we have labs” isn’t enough, how are these labs going to work.</p>

<h5 id="initial-considerations">Initial Considerations</h5>

<p>Here’s what you need to think through — trust me, these details matter:</p>

<ul>
  <li>How do you make tasks challenging <strong>yet solvable</strong>?</li>
  <li>Are the exercises <strong>accessible and achievable</strong> by people at a variety of skill levels?</li>
  <li>Will you want to <strong>centrally track</strong> attendee process and if so, how?</li>
  <li>Is it a <strong>competition</strong> or self-paced?</li>
  <li>Can you stretch your <strong>most advanced students</strong>?</li>
  <li>How can you test that your <strong>labs still work</strong> before each run? Is that manual or automated?</li>
  <li>How will you keep lab content <strong>up to date</strong> if your subject moves fast?</li>
  <li>How many students can you <strong>realistically support and troubleshoot</strong> for at once?</li>
  <li>Do you have an automated way to reset your labs to a <strong>known good state</strong>?</li>
</ul>

<p><img src="/assets/img/bhseries/labconsiderations.png" alt="alt text" /></p>

<h5 id="providing-lab-access">Providing Lab Access</h5>

<p>One of the biggest questions: how will students access the labs?</p>

<ul>
  <li>Do they need to <strong>install software</strong>?</li>
  <li>Is specific <strong>hardware/software</strong> required?</li>
  <li>Do they need a <strong>virtualization tool</strong>?</li>
  <li>Will they need <strong>admin access</strong>?</li>
</ul>

<p>If the answer to any of these is yes, expect friction and maybe a few frustrated emails.</p>

<h4 id="hosted-labs-the-modern-standard">Hosted Labs: The Modern Standard</h4>

<p>In the old days, trainers would lug laptops and servers into conference venues. Now? <strong>Cloud-hosted labs</strong> are the norm.</p>

<p>Sensepost set the gold standard for this almost 10 years ago as they discuss in <a href="https://sensepost.com/blog/2015/into-the-cloud/">their blogpost here</a>. Nowadays, this should probably just be the standard.</p>

<p>But don’t let the cloud fool you into thinking it’s simpler. It comes with its own set of questions:</p>

<ul>
  <li>Can your labs <strong>scale</strong> to support dozens (or hundreds) of users?</li>
  <li>How will you <strong>automate provisioning</strong> for each user?</li>
  <li>Do students <strong>authenticate individually</strong>? How will you set this up</li>
  <li>Have you secured your environment from… creative attendees?
    <ul>
      <li><em>Yes, someone once deployed ransomware in someone’s training lab environment. Be ready!</em></li>
    </ul>
  </li>
  <li>Will students have <strong>post-course access</strong>? (Bonus points if yes.)</li>
</ul>

<p><img src="/assets/img/bhseries/labcloud.png" alt="alt text" /></p>

<h4 id="when-hacking-isnt-the-goal-creative-practical-exercises">When “Hacking” Isn’t the Goal: Creative Practical Exercises</h4>

<p>What if your course isn’t about hacking or coding? Then you’ll need to get creative.</p>

<p>In my case, I built two distinct types of exercises from scratch and they actually became the highlight of the course.</p>

<p>(I go into quite a lot of detail here but I hope it helps other people with their thought process. Feel free to skip if you don’t want the details)</p>

<h5 id="vulnerability-triage">Vulnerability Triage</h5>

<p>The first was a <strong>vulnerability triage</strong> challenge.</p>

<p>Students worked in groups, reviewing fictional findings from tools like SAST, DAST, and SCA. They had a simulated codebase or running app as a reference, but running tools wasn’t the goal or even part of the exercise.</p>

<p>Instead, they had to prioritize the vulnerabilities and more importantly, <strong>explain their reasoning</strong>.</p>

<p>Why? Because the course and therefore the exercises focused on <em>process</em> and <em>decision-making</em>, not tool mastery.</p>

<p><img src="/assets/img/bhseries/vulntriage.png" alt="alt text" /></p>

<p>This exercise built on the lectures and gave students a chance to the new ideas in a low-stakes setting.</p>

<h5 id="organisational-process">Organisational Process</h5>

<p>The second type of exercise asked: <em>How do you roll out a security tool across an organisation?</em></p>

<p>Students had to plan an implementation using a working document based on the content in the lectures. Sounds fun, right? Well I had to work a little on the fun part.</p>

<p>Since attendees came from diverse backgrounds I created a <strong>fictional company case study</strong> for everyone to work from. I also prepared a tech stack, fake team leads, and a slightly sinister app to keep things fun. All teams worked from the same case study as I felt it would make it easier for teams to compare notes afterwards.</p>

<p>But how would they provide their feedback?</p>

<p>Enter: <strong>The Simulated Stakeholder</strong></p>

<p>Rather than each team presenting their plan to the entire class (which might be a little repetitive), I introduced the simulated stakeholder, in most cases the CTO of the simulated company.</p>

<p>(I think this was probably inspired by exercises we did back when I worked at Deloitte as part of training for more senior roles.)</p>

<p>Each team nominated one person to role-play the CTO. All the “CTOs” joined me in a breakout session, where I worked through the working document with them and guided them on the kinds of questions and expectations a real executive might have and how best to interact with the teams.</p>

<p>Then, each CTO joined a <em>different</em> team, and that team had to <strong>justify their plan to a skeptical senior stakeholder</strong>.</p>

<p>Aside from the simulated stakeholders getting much amusement from their sudden promotion to CTO (although I think on one occasion a stakeholder was actually a CTO in their day job), this was a great way to give the teams something to work towards and also stimulate discussion.</p>

<p>It was also an important illustration of one of the key lessons from the course which is the importance of getting senior level buy-in.</p>

<p><img src="/assets/img/bhseries/stakeholder.png" alt="alt text" /></p>

<h4 id="other-ideas">Other Ideas</h4>

<p>I’ll save the story about the time I built a multi-player game based on the ASVS entirely in Google Sheets for another post, or over a beer. 🍻</p>

<p>Just know that even if it sounds weird, it might actually work.</p>

<h4 id="the-real-point">The Real Point</h4>

<p>Yes, I wanted to show off some my cool ideas but the real message is this: You can go beyond traditional “labs” and build creative, impactful exercises that magnify the impact of your course.</p>

<p>Don’t limit yourself to hacking and code. Remember that the rarest and most valuable skill in security is the ability to communicate and persuade. Think about courses which build that muscle as well.</p>

<h4 id="next-post-putting-pen-to-paper">Next Post: Putting pen to paper</h4>

<p>So now, having figured out your financials, your niche, and your exercises, you now need to actually get accepted by a conference.</p>

<p>In the next post, I’ll walk through how to write a compelling Call for Training (CFT) submission.</p>]]></content><author><name>josh</name></author><category term="blog" /><summary type="html"><![CDATA[Introduction]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="/assets/img/bhseries/practical.png" /><media:content medium="image" url="/assets/img/bhseries/practical.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Finding your niche/selling point</title><link href="/blog/2025/04/20/find-your-niche.html" rel="alternate" type="text/html" title="Finding your niche/selling point" /><published>2025-04-20T05:31:00+00:00</published><updated>2025-04-20T05:31:00+00:00</updated><id>/blog/2025/04/20/find-your-niche</id><content type="html" xml:base="/blog/2025/04/20/find-your-niche.html"><![CDATA[<h4 id="introduction">Introduction</h4>

<p>If you’re thinking about creating a training course, one of the biggest questions you’ll face early on is: <em>Will anyone actually want this?</em> In this post, we’ll explore how you can evaluate whether your course idea stands a chance in an already packed marketplace for professional training.</p>

<p><img src="/assets/img/bhseries/crossroads.png" alt="alt text" /></p>

<h4 id="market-research">Market Research</h4>

<p>In a previous post, I mentioned that I already had a good grasp of the application security training landscape, which gave me an edge in knowing which topics were oversaturated. If you’re not yet as familiar with your own niche, I would suggest you do some market research. Here are some areas you might want to consider.</p>

<h5 id="history-of-training-courses-at-your-target-conferences">History of training courses at your target conferences</h5>

<p>Conferences will often maintain historical websites where you can see the courses they have previously offered.</p>

<p>Black Hat maintains an archive of past training courses with <a href="https://www.blackhat.com/us-25/training/schedule/">predictable</a> <a href="https://www.blackhat.com/asia-24/training/schedule/">URL</a> <a href="https://www.blackhat.com/eu-23/training/schedule/">patterns</a>, making it easy to explore previous years’ offerings. Keep in mind that not all Black Hat events are created equal, Black Hat USA is significantly larger than its counterparts in Asia and Europe.</p>

<p>As for satellite events like Black Hat Spring Trainings, I have never seen a formal Call for Training. It’s possible these are invite-only affairs, favoring trainers with a strong sales history, but that’s just a theory.</p>

<p><img src="/assets/img/bhseries/sleuthing.png" alt="alt text" /></p>

<p>If you’re targeting an OWASP event, they also have a historical record of courses available though it might require a bit of sleuthing. (Hint: all recent OWASP websites have been based in GitHub).</p>

<p>For smaller or more specialized conferences, you’ll need to do your own detective work to uncover historical data.</p>

<h5 id="check-out-offensive-security">Check out Offensive Security</h5>

<p>Offensive Security offers a well-known set of training programs. You can probably guess where their focus lies. If your topic overlaps with theirs, take a hard look at how your course differentiates itself. Their content is well-established and widely respected so if you’re in their arena, you need a unique angle.</p>

<h5 id="review-the-sans-catalogue">Review the SANS catalogue</h5>

<p>SANS offers a massive range of courses often at premium prices but keep in mind that many of them run for six full days. That means a shorter, more affordable course on a similar subject might still appeal to time and budget conscious learners.</p>

<p><img src="/assets/img/bhseries/comparison.png" alt="alt text" /></p>

<h5 id="explore-other-sources">Explore other sources</h5>

<p>Don’t stop there. Depending on your topic, there may be other educational offerings in your space: self-paced labs, YouTube tutorials, Massive Open Online Courses (MOOCs), and more.</p>

<p>Ask yourself: <em>What will learners gain from your course that they can’t easily get from free or low-cost resources?</em> Your value proposition needs to go beyond content, it should include engagement, interaction, depth, or application.</p>

<h4 id="finding-the-niche">Finding the niche</h4>

<p>The sweet spot for your course lies at the intersection of three things:</p>

<ol>
  <li>A subject you’re passionate and knowledgeable about</li>
  <li>A real gap in the current training market</li>
  <li>A compelling reason for someone to pay for it</li>
</ol>

<p>If you’re struggling to identify that gap, don’t be discouraged. It <em>is</em> a tricky balancing act. The ideal topic needs to be fresh and interesting to the conference review board <em>and</em> relevant enough that your potential attendees can justify the time and money it takes to attend.</p>

<p><img src="/assets/img/bhseries/journey.png" alt="alt text" /></p>

<p>On the other hand, the cybersecurity field in particular is constantly evolving. New technologies and threats emerge regularly each one a chance for you to carve out your own area of expertise. There are plenty of unsolved problems and overlooked areas that need attention.</p>

<p>Remember, your audience will often have to convince their manager that your course is worth the investment. Help them make the case by choosing a topic that solves real problems, enhances valuable skills, or supports strategic goals.</p>

<h4 id="next-post-practical-exercises">Next Post: Practical Exercises</h4>

<p>In the next post, we’ll focus on the major differentiator that can elevate your course above the rest: hands-on activities. Because let’s face it no one wants to sit through two days of lectures. What participants get to <em>do</em> during your course is just as important as what they learn.</p>]]></content><author><name>josh</name></author><category term="blog" /><summary type="html"><![CDATA[Introduction]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="/assets/img/bhseries/niche.png" /><media:content medium="image" url="/assets/img/bhseries/niche.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Working out your financials</title><link href="/blog/2025/04/01/work-out-your-financials.html" rel="alternate" type="text/html" title="Working out your financials" /><published>2025-04-01T04:30:00+00:00</published><updated>2025-04-01T04:30:00+00:00</updated><id>/blog/2025/04/01/work-out-your-financials</id><content type="html" xml:base="/blog/2025/04/01/work-out-your-financials.html"><![CDATA[<p><img src="/assets/img/bhseries/financials.png" alt="image" class="blog-image" /></p>

<h4 id="introduction">Introduction</h4>

<p>In my previous post, I briefly touched on the financial realities of delivering training courses. In this post, I’ll explore this topic in greater depth.</p>

<h4 id="making-your-millions">Making your millions??</h4>

<p>If your goal is a big financial success, training courses will probably not be your golden ticket. That is why I want to tackle this topic up front. You will need to think about this but you also need to be realistic.</p>

<p>Developing a course requires significant upfront investment, and even after launch, it demands ongoing “care and feeding”. Keeping content fresh and relevant is crucial, and that means regularly:</p>

<ul>
  <li>Updating material to reflect industry changes</li>
  <li>Incorporating new insights and experiences</li>
  <li>Ensuring training exercises still function as intended</li>
  <li>Revising and updating technical components of exercises</li>
  <li>Adapting exercises to maintain relevance</li>
  <li>Applying feedback from previous course sessions</li>
</ul>

<p>If you can identify a subject that is broad enough to appeal to a large audience, different enough from existing options to generate demand, and also low-maintenance in terms of updates, then you might have a high-profit opportunity.</p>

<p>But let me know if you do manage that as it is pretty tough…</p>

<p><img src="/assets/img/bhseries/mazetomoney.png" alt="alt text" class="blog-image" /></p>

<p>In my case, the course I built falls into a slightly specialized category. While maintenance isn’t overwhelming, I have only delivered it 5–8 times so far.</p>

<h4 id="non-financial-benefits">Non-financial benefits</h4>

<p>On the other hand, there are other benefits that may be attractive to you.</p>

<p>The experience of preparing and delivering a course at this level may itself be valuable to your professional development. It may also bring a boost to your public profile and your resume.</p>

<p>Depending on your planned career trajectory, these aspects may be more valuable than money. However, your current employer may not see things this way. 🙃</p>

<h4 id="recouping-your-investment">Recouping your investment</h4>

<p>Before you make a profit you are going to need to cover your initial investment.</p>

<p>The most basic investment is any actual money you spend to deliver the course in person. There are a bunch of considerations for this so I will cover it in more detail a little further down.</p>

<p>The real cost however is (or at least should be) the time you spend building the course. You certainly don’t want to spend a lot of time building a course which no one wants to attend.</p>

<p>To try and mitigate this risk for my course, I took a phased approach. I started by delivering a one-hour overview at the Open Security Summit, followed by a one-day version at OWASP Global AppSec.</p>

<p>These smaller commitments helped me gauge audience reception and refine my content. The one-day course also allowed me to test my experimental exercises (more on that later). While this phase didn’t compensate for all the time investment, it provided some validation that the course was worthwhile and effective and therefore I should continue investing in it.</p>

<p>Striking the right balance is key: invest enough to prove the concept and demonstrate viability, but avoid committing excessive resources to an untested idea that might not work out.</p>

<p><img src="/assets/img/bhseries/balance.png" alt="alt text" class="blog-image" /></p>

<h4 id="breaking-even-on-an-single-course-session">Breaking even on an single course session</h4>

<p>If you are able to afford to pay expenses to deliver training “for the exposure”, then you don’t need to worry about this. In most cases however, you will need to have a plan.</p>

<p>Virtual training is simpler financially: as long as you cover your time cost, you’re in the clear. In-person training, however, introduces a host of additional expenses and complications and I will try and cover some of these here.</p>

<p>For in-person training, you need to figure out what your break even point is. Specifically, how many people need to register to get the revenue required to break even. Obviously the first thing you need to know is what share of the course income you will receive from the venue which is hosting the training. This might be fixed or flexible depending on the conference.</p>

<p><img src="/assets/img/bhseries/model.png" alt="alt text" class="blog-image" /></p>

<p>You can then start building a break even and profit calculator based on your expected expenses. I usually prepare an Excel spreadsheet or Google Doc to work this out and recalculate dynamically.</p>

<h5 id="key-expenses-to-consider">Key Expenses to Consider</h5>

<p>Different conferences handle costs in different ways. Expenses that conferences might cover for you (wholly or partly) include:</p>

<ul>
  <li>Flight costs</li>
  <li>Hotel costs</li>
  <li>Venue costs including food and beverage.</li>
</ul>

<p>Examples that I have seen:</p>

<ul>
  <li>Black Hat publishes information on the <a href="https://www.blackhat.com/call-for-training.html">public CFT page</a>.</li>
  <li>OWASP covers all venue costs but not hotel and flight.</li>
  <li>Other conferences equally split costs and then equally split the profit as well.</li>
</ul>

<p>All conferences I have seen also give trainers a free conference ticket which could also be worth a lot.</p>

<p><img src="/assets/img/bhseries/expenses.png" alt="alt text" class="blog-image" /></p>

<p>Beyond travel and accommodation, factor in additional costs such as:</p>

<ul>
  <li>Airport transfers</li>
  <li>Meals and per diems</li>
  <li>Printed materials or giveaways for participants, (I have a bunch of print-outs I prepare and hand-out over the duration of the course and I often buy and bring snacks as well)</li>
</ul>

<h5 id="the-hidden-cost-your-time">The Hidden Cost: Your Time</h5>

<p>If you’re self-employed or consulting, or you are doing this separate to your employer, your time has an opportunity cost. Time spent training is time you could have spent on client work or other revenue-generating activities. Don’t forget to include travel days as well.</p>

<h5 id="revenue-per-course-day">Revenue Per Course Day</h5>

<p>Different conferences handle pricing and revenue shares in various ways:</p>

<ul>
  <li><strong>OWASP</strong> charges attendees a flat daily rate for training, meaning a three-day course costs three times as much as a one-day course, with no discounts. Trainers receive 40% of net revenue up to $10,000 USD, and 50% of net revenues above $10,000 USD (this is public information).</li>
  <li>As can be seen on <a href="https://www.blackhat.com/us-25/training/schedule/index.html">the public training page</a>, <strong>Black Hat</strong> training ticket costs vary between courses and there are also various early-bird stages. Interestingly, a four-day Black Hat course doesn’t necessarily cost attendees twice as much as a two-day course.</li>
  <li><strong>Some conferences</strong> pay a fixed rate per course, contingent on meeting a minimum number of registrants.</li>
</ul>

<p>Note that at <strong>Black Hat USA</strong>, trainers can deliver the same two-day course twice (Sat-Sun and Mon-Tues).</p>

<h5 id="set-your-minimum-up-front">Set Your minimum up-front</h5>

<p>Most conferences will ask what your financial minimum is upfront and you should be able to use the information above, plus the conference’s specific terms, to figure that out.  You’ll need to maintain close communication with them to determine when to make a GO/NO-GO decision.</p>

<p><img src="/assets/img/bhseries/fork.png" alt="alt text" class="blog-image" /></p>

<h4 id="the-conferences-minimum">The conference’s minimum</h4>

<p>Conferences themselves will generally have financial break-even points, and they won’t run training that doesn’t meet minimum registration numbers. Be clear on these thresholds and when there conference team will make their final decision.</p>

<p>Also, keep in mind that waiting on a conference decision could mean higher flight costs if you delay booking.</p>

<h4 id="next-post-figuring-out-your-selling-point">Next Post: Figuring out your selling point</h4>

<p>The financial aspects are only a small part of the equation. To truly succeed, you need a compelling reason for people to choose your course over others in a crowded market. In the next post, I’ll discuss how to carve out your unique value proposition and attract the right audience.</p>]]></content><author><name>josh</name></author><category term="blog" /><summary type="html"><![CDATA[]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="/assets/img/bhseries/financials.png" /><media:content medium="image" url="/assets/img/bhseries/financials.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">What is my motivation? What should your motivation be?</title><link href="/blog/2025/02/24/What-is-my-motivation-What-should-be-yours.html" rel="alternate" type="text/html" title="What is my motivation? What should your motivation be?" /><published>2025-02-24T12:30:00+00:00</published><updated>2025-02-24T12:30:00+00:00</updated><id>/blog/2025/02/24/What-is-my-motivation-What-should-be-yours</id><content type="html" xml:base="/blog/2025/02/24/What-is-my-motivation-What-should-be-yours.html"><![CDATA[<p><img src="/assets/img/bhseries/whoami.png" alt="image" class="blog-image" /></p>

<h4 id="introduction">Introduction</h4>

<p>In this post, I’ll share some personal background about how I started delivering public training courses and why I pursued this path. My aim is to provide context for the later chapters and help you reflect on the motivation required for such an undertaking.</p>

<p>Admittedly, this chapter focuses more on my experiences than actionable advice, so if you’re confident in your motivation, feel free to jump to the bottom line: <a href="#your-motivation">what to expect from this journey</a>.</p>

<h4 id="some-background">Some Background</h4>

<p>At my previous employer, I had always looked admiringly at the posters on the wall of the office from when my previous boss (AppSec legend, <a href="https://www.linkedin.com/in/erezmetula/">Erez Metula</a>) had delivered some of the early mobile security training courses at Black Hat USA. (I have my own poster up on the wall as an homage to that, <a href="https://www.youtube.com/watch?v=Ybm4Vr7rQgo">as you can see in some of my videos</a>).</p>

<p>While the company had moved away from training by the time I joined, the prestige of Black Hat training always stood out to me as a mark of excellence.</p>

<p>Separately, I had the opportunity to review training course submissions for Global AppSec Tel Aviv 2019, as well as for local conferences.</p>

<p><img src="/assets/img/bhseries/globalappsectlv2019.jpeg" alt="A blurry photo of Dhruv Shah delivering some hands-on hacking training at Global AppSec Tel Aviv 2019" class="blog-image" /></p>

<p>These experiences, combined with my background in developing and delivering training, gave me a solid understanding of the application security training landscape.</p>

<h4 id="starting-at-bounce-security">Starting at Bounce Security</h4>

<p>However, I’m not sure that my new boss (AppSec legend, <a href="/team-members/avi.html">AviD</a>) had any of that in mind when he asked me, shortly after I had started working with him, if I was interested in developing any training courses. Avi is well known for his threat modeling training which he has been delivering for many years now and working with him, it was a natural thing for him to ask.</p>

<p>Little did we know the journey this simple question would take us on…</p>

<h4 id="scratching-an-itch">Scratching an Itch</h4>

<p>As I considered Avi’s question, I reflected on a common challenge I had observed at several client organizations. Many had adopted tools like SAST, DAST, and SCA, only to become overwhelmed by excessive findings, technical hurdles, and conflicts over who was responsible for addressing issues. Instead of improving security, these tools often created frustration, reduced morale, and, paradoxically, worsened overall security outcomes.</p>

<p><img src="/assets/img/bhseries/sastdastsca.jpg" alt="Getting stabbed by AppSec tools..." class="blog-image" /></p>

<p>The more I thought about it, the more it seemed like a gap in a crowded market for AppSec training courses. Most courses focused on the technical aspects of tools—installation, configuration, and automation. Having seen these tools in real-life, it seemed like no one wanted to talk about the people and process aspects of using these tools. (Hindsight has shown how much of a problem this is in AppSec in general, not just related to tools which provided the inspiration for the next evolution of this course.)</p>

<h4 id="my-motivation">My Motivation</h4>

<p>With Avi’s encouragement, I began drafting an outline for a 2-day course to address this gap. I poured my experiences and observations into a detailed structure, focusing on practical, actionable content.</p>

<p>And this is a critical point. I don’t love designing training courses, I don’t love writing slides. Maybe some people do, I don’t know…</p>

<p><img src="/assets/img/bhseries/business.gif" alt="But that's none of my business..." class="blog-image" /></p>

<p>However, I felt strongly enough about this and was passionate enough to push through and pull all of this together. And then stick with it when things got harder later on. I was determined that this was valuable content and that I wanted to do the work to get this released.</p>

<h4 id="your-motivation">Your Motivation</h4>

<p>The key takeaway here is that creating, marketing, and delivering a training course is a demanding and time-intensive journey. If you’re new to teaching or presenting, it may push you out of your comfort zone, requiring you to build skills like public speaking and effective communication.</p>

<p>Before starting, ensure you are genuinely passionate about the subject. Passion will sustain you through the challenges and keep you motivated to deliver valuable content.</p>

<h4 id="next-post-the-financial-aspect">Next Post: The Financial Aspect</h4>

<p>For me, the motivation to create this course wasn’t financial. Much of the work occurred during downtime between projects, and while course revenue has offset some of the investment, it hasn’t fully covered the effort. However, the experiences and opportunities it created have been invaluable.</p>

<p>In the next post, I’ll discuss the financial realities of creating and delivering training courses in detail.</p>]]></content><author><name>josh</name></author><category term="blog" /><summary type="html"><![CDATA[]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="/assets/img/bhseries/whoami.png" /><media:content medium="image" url="/assets/img/bhseries/whoami.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">So, you want to train at Black Hat (or other conferences)? An Introduction</title><link href="/blog/2025/01/21/so-you-want-to-train-at-black-hat-introduction.html" rel="alternate" type="text/html" title="So, you want to train at Black Hat (or other conferences)? An Introduction" /><published>2025-01-21T10:30:00+00:00</published><updated>2025-01-21T10:30:00+00:00</updated><id>/blog/2025/01/21/so-you-want-to-train-at-black-hat-introduction</id><content type="html" xml:base="/blog/2025/01/21/so-you-want-to-train-at-black-hat-introduction.html"><![CDATA[<p><img src="/assets/img/BHUSA23.jpg" alt="image" class="blog-image" /></p>

<h4 id="introduction">Introduction</h4>

<p>Welcome to a new blog series exploring the process of preparing, submitting, and delivering training courses at conferences such as <a href="https://www.blackhat.com/trainings/">Black Hat</a>, <a href="https://owasp.org/events">OWASP Global AppSec conferences</a>, and <a href="https://ndc-security.com/">NDC Security</a>. In this introductory post, I will provide an overview of what this series entails and share the inspiration behind it.</p>

<h4 id="background">Background</h4>

<p><img src="/assets/img/bhseries/trainer.png" alt="image" class="blog-image" /></p>

<p>The idea for this series has been on my mind for some time, but it was only during a recent flight that I felt ready to begin writing. Over the past few years, I have embarked on an unexpected journey that has been both rewarding and challenging. This experience has equipped me with valuable insights and lessons that I am eager to share.</p>

<p>This series aims to inspire and guide individuals considering a similar endeavor, offering practical advice and serving as a planning resource. Whether you are contemplating delivering a course or simply curious about the process, I hope these posts provide clarity and motivation.</p>

<h4 id="chapters-in-the-series">Chapters in the Series</h4>

<p>The blog series is structured into chapters that follow the chronological steps of my journey. While the posts are designed to be read sequentially, I recommend reading the entire series to gain a comprehensive understanding before deciding if this path aligns with your goals.</p>

<p><img src="/assets/img/bhseries/roadmap.png" alt="image" class="blog-image" /></p>

<p>The planned chapters include:</p>

<ul>
  <li>Introduction (this post)</li>
  <li>What Was My Motivation? What Motivation Do You Need?</li>
  <li>How Do the Financials Work for a Training Course?</li>
  <li>What Is the Niche/Selling Point for Your Course?</li>
  <li>Planning the Practical Side: How Will You Make It Engaging?</li>
  <li>How Should You Write Your Submission to Maximize Acceptance Chances?</li>
  <li>How Can You Effectively Market Your Course?</li>
  <li>What Preparations Should You Make Before Traveling?<br />
<!--- What Was My Experience Like, and What Should You Expect?--></li>
</ul>

<p>A complete list of published posts can be found <a href="#top">at the top of this page</a>.</p>

<p>I welcome your feedback, questions, and suggestions for additional topics to cover. Feel free to reach out to me on <a href="https://twitter.com/JoshCGrossman">Twitter</a> or <a href="https://www.linkedin.com/in/joshcgrossman/">LinkedIn</a>. As this series evolves, following me will ensure you are notified when new posts are published.</p>

<h4 id="next-post-my-motivation">Next Post: My Motivation</h4>

<p>In the next post, I will go into my personal motivations for delivering public training courses and share the factors that guided me along this path. I hope it provides insight and encouragement as you consider your own journey.</p>]]></content><author><name>josh</name></author><category term="blog" /><summary type="html"><![CDATA[]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="/assets/img/BHUSA23.jpg" /><media:content medium="image" url="/assets/img/BHUSA23.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Knowing is half the battle</title><link href="/blog/2025/01/06/situational-awareness-in-appsec.html" rel="alternate" type="text/html" title="Knowing is half the battle" /><published>2025-01-06T09:45:21+00:00</published><updated>2025-01-06T09:45:21+00:00</updated><id>/blog/2025/01/06/situational-awareness-in-appsec</id><content type="html" xml:base="/blog/2025/01/06/situational-awareness-in-appsec.html"><![CDATA[<h2 id="introduction">Introduction</h2>

<p>AppSec architects (sometimes known as AppSec engineers) have a tough job. As a small team within a larger development organization, they are tasked with figuring out how to ensure that software is being built securely and being available to provide support in doing this.</p>

<p>Amongst other things, this involves being aware of what development activity is actually going on.</p>

<p>And as GI Joe famously taught us:</p>

<p><img src="/assets/img/2025-01-06-situational/knowing.png" alt="knowing is half the battle" class="blog-image" /></p>

<p>For some of our clients we operate as part-time AppSec architects either joining their existing team or becoming their team. As we are acting as virtual employees, we generally request some access to internal systems to get some situational awareness into development activity (or activity in general) within the organization. Otherwise we are operating completely at “arms length” without insight into what they are working on and how they work.</p>

<p>Additionally, most organizations nowadays are distributed in some way. That might be by having multiple international offices or a remote/hybrid working environment. This makes access to their internal communication systems even more important in order to be able to effectively interact with the team.</p>

<p>Since it came up recently, I thought it would be valuable to go into a little more detail about the sorts of systems we request access to and how this can help us.</p>

<p>Some of our uses here are a little more unorthodox and many will be useful ideas for regular, full time employed, AppSec architects as well.</p>

<p>So take a look and also let me know if you think there is anything I have missed 😀</p>

<p><img src="/assets/img/2025-01-06-situational/sitware.png" alt="map representing situational awareness" class="blog-image" /></p>

<p>For each system, I will give:</p>

<ul>
  <li><strong>Explanation</strong> - A brief overview of each system type and what it does</li>
  <li><strong>System examples</strong> - Some examples that you might see “in the wild”</li>
  <li><strong>Information provided</strong> - What useful information can we gather from the system to increase our situational awareness?
    <ul>
      <li>In some cases we might be able to use some slightly more sneaky tricks to discover useful information.</li>
    </ul>
  </li>
  <li><strong>Usage cases for AppSec</strong> - How we can use the system for our own purposes</li>
</ul>

<h3 id="security-systems-and-platforms">Security systems and platforms</h3>

<p>I am not going to mention these in detail as it almost goes without saying that these would be useful for AppSec work. My intention in this post is to focus on the more mainstream organizational systems.</p>

<hr />

<h2 id="developer-ticketing-system">Developer Ticketing system</h2>

<p><strong><a href="#top">Back to top ↑</a></strong></p>

<h3 id="explanation">Explanation</h3>

<p>This will be the system that the development organization uses to guide developers on what they will be working on at any point in time. It might be used just for regular work tracking, (e.g. you are working on this piece of functionality today,) or it might also be used for bug tracking as well, (i.e. QA will open tracking tickets when they find quality bugs.)</p>

<p>Either way, it tends to be a key system that developers (and maybe other development staff) use to organize their day.</p>

<p><img src="/assets/img/2025-01-06-situational/ticket.png" alt="ticketing system" class="blog-image" /></p>

<h3 id="system-examples">System examples</h3>

<p>Examples of systems like this include:</p>

<div class="list-awesome-system">
  <ul>
    <li>Jira</li>
    <li>GitHub Issues</li>
    <li>Gitlab Issues</li>
    <li>Trello</li>
    <li>Notion</li>
  </ul>
</div>

<h3 id="information-provided">Information provided</h3>

<p>We can use this system to discover information including:</p>

<div class="list-awesome-info">
  <ul>
    <li>What development work is currently going on:
      <ul>
        <li>New features? (Do we need to get in the loop for design security)</li>
        <li>Bug fixing? (Security related, do they have a security impact?)</li>
      </ul>
    </li>
    <li>What stage are they up to? (Just starting, nearly finished, etc)</li>
    <li>Who from the team is working on it? (and therefore who do we need to ask questions to)</li>
    <li>Potential links to design documentation (so we are prepared with questions to ask)</li>
  </ul>
</div>

<h3 id="usage-cases-for-appsec">Usage cases for AppSec</h3>

<p>This system can be useful for our own work, allowing us to:</p>

<div class="list-awesome-action">
  <ul>
    <li>Open tickets for vulnerabilities so that the work can be prioritized alongside other bugs or work.</li>
    <li>Create a dashboard for tracking vulnerability bugs and progress in addressing them</li>
    <li>Open tickets for other work such as design reviews alongside the standard development tickets</li>
    <li>Maybe even automatically have sub tickets be opened for security tasks (such as threat modeling) when development task tickets get opened for a new feature or development.</li>
  </ul>
</div>

<hr />

<h2 id="company-email">Company email</h2>

<p><strong><a href="#top">Back to top ↑</a></strong></p>

<h3 id="explanation-1">Explanation</h3>

<p>A personal mailbox in the company’s internal email system. I think we know what email is by now but the scope here is to have an account where when we send an email, it doesn’t have a scary “this is an external email” message at the top.</p>

<p><img src="/assets/img/2025-01-06-situational/email.png" alt="email system" class="blog-image" /></p>

<h3 id="system-examples-1">System examples</h3>

<p>Examples of systems like this include:</p>

<div class="list-awesome-system">
  <ul>
    <li>Office 365</li>
    <li>Google Workspace</li>
    <li>Zoho</li>
  </ul>
</div>

<h3 id="information-provided-1">Information provided</h3>

<p>We can use this system to discover information including:</p>

<div class="list-awesome-info">
  <ul>
    <li>Address book of staff so you can find their contact details from their name and maybe also where they work (useful if you want to physically find them or figure out what timezone they are on)</li>
    <li>Getting access to shared email mailing lists
      <ul>
        <li>(I once had a case where the first I heard about a new feature was from a company wide update announcing it’s release. I then went and discovered a critical vulnerability in it!)</li>
      </ul>
    </li>
    <li>Discover when people are out of office (no point in bothering people when they aren’t around)</li>
    <li>Organizational charts, loads of useful information including:
      <ul>
        <li>Who reports to whom</li>
        <li>Who works with whom</li>
        <li>If this isn’t maintained here, you might want to try and find it from somewhere else.</li>
      </ul>
    </li>
  </ul>
</div>

<h3 id="usage-cases-for-appsec-1">Usage cases for AppSec</h3>

<p>This system can be useful for our own work, allowing us to:</p>

<div class="list-awesome-action">
  <ul>
    <li>Communicate with people (obviously 🙃)</li>
    <li>Sending periodic updates on what is going on in the world of AppSec and within the internal AppSec team using internal mailing lists - Good to build awareness and for internal “marketing” of AppSec. (Obviously you don’t want to overdo this!)</li>
    <li>Demonstrate that we are more integrated and have a real human identity within the organization. This should differentiate us from a regular “arms length” or “short term” consultant</li>
    <li>Demonstrate why the company should take you more seriously since they spent money to give you an account</li>
  </ul>
</div>

<hr />

<h2 id="company-calendar">Company calendar</h2>

<p><strong><a href="#top">Back to top ↑</a></strong></p>

<h3 id="explanation-2">Explanation</h3>

<p>The place where employees plan their meetings and potentially structure their day in other ways.</p>

<p><img src="/assets/img/2025-01-06-situational/calendar.png" alt="calendar image" class="blog-image" /></p>

<h3 id="system-examples-2">System examples</h3>

<p>Mostly the same systems as for internal email.</p>

<h3 id="information-provided-2">Information provided</h3>

<p>We can use this system to discover information including:</p>

<div class="list-awesome-info">
  <ul>
    <li>When people are free or busy to make it easier to schedule meetings and avoid rounds of trying to find mutually acceptable times.</li>
    <li>Where people are working - sometimes this will indicate if they are in the office.</li>
  </ul>
</div>

<h4 id="slightly-sneakier-information-we-can-gather-from-it">Slightly sneakier information we can gather from it</h4>

<p>If we are struggling to get traction or cooperation within development teams, calendars can sometimes also reveal some other interesting information.</p>

<p>This could include:</p>

<ul>
  <li>Looking at the meetings which people have on their calendars in order to understand who is meeting with whom and about what. This might reveal information on new developments or new development plans.</li>
  <li>Planning documents or other notes documents might also be attached to meeting invites and therefore reveal information about what they are working on.</li>
</ul>

<h3 id="usage-cases-for-appsec-2">Usage cases for AppSec</h3>

<p>This system can be useful for our own work, allowing us to:</p>

<div class="list-awesome-action">
  <ul>
    <li>Send internal meeting invites using internal conference platform (more on this below)</li>
    <li>Look more official by sending meeting invites from a company email address.</li>
  </ul>
</div>

<hr />

<h2 id="internal-chat-system">Internal chat system</h2>

<p><strong><a href="#top">Back to top ↑</a></strong></p>

<h3 id="explanation-3">Explanation</h3>

<p>Most organizations will have a more informal system for internal ad hoc conversations without the overhead and formality of email. It will usually include both person to person conversations and also groups.</p>

<p><img src="/assets/img/2025-01-06-situational/chat.png" alt="chat image" class="blog-image" /></p>

<h3 id="system-examples-3">System examples</h3>

<p>Examples of systems like this include:</p>

<div class="list-awesome-system">
  <ul>
    <li>Slack</li>
    <li>Discord</li>
    <li>Microsoft Teams</li>
    <li>IRC (maybe, maybe not…)</li>
  </ul>
</div>

<h3 id="information-provided-3">Information provided</h3>

<p>We can use this system to discover information including:</p>

<div class="list-awesome-info">
  <ul>
    <li>What is going on in the company that’s not directly related to security, such as:
      <ul>
        <li>Company holidays so you know when not to bother people</li>
        <li>Problematic/unfortunate events. Might be another indication that this is a not a good time for the company or for someone in particular.</li>
        <li>New joiners to the company who might be relevant to be in touch with them.</li>
      </ul>
    </li>
    <li>Discover when people are out of office. Another source other than email or calendar.</li>
    <li>Search for information that might help you understand the applications including:
      <ul>
        <li>Historic information</li>
        <li>Valid object identifiers to use when querying the application</li>
        <li>Discussions/solutions for errors that you might see</li>
      </ul>
    </li>
    <li>Discover new third party products being on boarded</li>
  </ul>
</div>

<h4 id="slightly-sneakier-information-we-can-gather-from-it-1">Slightly sneakier information we can gather from it</h4>

<p>If we are struggling to get traction or cooperation within development teams, chat systems can sometimes also reveal some other interesting information. This could include:</p>

<ul>
  <li>Search for secret information or secrets being shared. Maybe you need test credentials but can’t anyone who will provide them…</li>
  <li>Lurking in groups to discover potential issues. I was once lurking in a group where someone asked for the easiest way to forge a production token so as to do some testing.</li>
</ul>

<h3 id="usage-cases-for-appsec-3">Usage cases for AppSec</h3>

<p>This system can be useful for our own work, allowing us to:</p>

<div class="list-awesome-action">
  <ul>
    <li>Create ad hoc groups to discuss particular issues or events with a specific team of people.</li>
    <li>Build automations to alert on particular events.</li>
    <li>Another channel to communicate with people. “Did you see my email?”</li>
    <li>Vary communication mechanisms since different people communicate better in different ways. Some might prefer email, some might prefer chat.</li>
  </ul>
</div>

<hr />

<h2 id="internal-conference-platform">Internal conference platform</h2>

<p><strong><a href="#top">Back to top ↑</a></strong></p>

<h3 id="explanation-4">Explanation</h3>

<p>The audio/video conferencing platform which the company uses for its internal meetings.</p>

<p><img src="/assets/img/2025-01-06-situational/videoconf.png" alt="videoconf image" class="blog-image" /></p>

<h3 id="system-examples-4">System examples</h3>

<p>Examples of systems like this include:</p>

<div class="list-awesome-system">
  <ul>
    <li>Microsoft Teams</li>
    <li>Google Meet</li>
    <li>Zoom</li>
    <li>Cisco WebEx</li>
  </ul>
</div>

<h3 id="usage-cases-for-appsec-4">Usage cases for AppSec</h3>

<p>There probably isn’t much data we can gather from this but this system can be useful for our own work in lots of ways, allowing us to:</p>

<div class="list-awesome-action">
  <ul>
    <li>Set up internal meetings - As noted above it makes it look more like we belong.</li>
    <li>Use internal physical conference hardware. Often companies have their videoconferencing system integrated into their physical meeting rooms meaning if you want to do a hybrid meeting you will struggle using an external platform.</li>
    <li>Avoid the friction of waiting rooms because you are a guest in the company’s conferencing system.</li>
    <li>Avoid having to ask other people to set up calls</li>
    <li>Avoid restrictions on sharing documents and other information during conference. Some systems have restrictions on sharing with external parties.</li>
    <li>Potential preserve the chat from the meeting to be referenced afterwards.</li>
    <li>Chat with participants beforehand and afterwards.</li>
    <li>Potentially preserve the attendee list for the meeting.</li>
    <li>Easily join prescheduled or periodic meetings which might be of interest.</li>
  </ul>
</div>

<hr />

<h2 id="internal-documentation--file-storage-platform">Internal documentation / file storage platform</h2>

<p><strong><a href="#top">Back to top ↑</a></strong></p>

<h3 id="explanation-5">Explanation</h3>

<p>The place where employees document long form information about the company, the application, etc. This could include both simple documents but also larger files such as meeting recordings.</p>

<p><img src="/assets/img/2025-01-06-situational/library.png" alt="library image" class="blog-image" /></p>

<h3 id="system-examples-5">System examples</h3>

<p>Examples of systems like this include:</p>

<div class="list-awesome-system">
  <ul>
    <li>Confluence</li>
    <li>Sharepoint / Office 365</li>
    <li>Notion</li>
    <li>Google Drive / Google Workspace</li>
  </ul>
</div>

<h3 id="information-provided-4">Information provided</h3>

<p>We can use this system to discover information including:</p>

<div class="list-awesome-info">
  <ul>
    <li>All sorts of backgrounds information and documentation including design documentation and how specific security mechanisms work.
      <ul>
        <li>Obviously it depends on how well updated the documentation is.</li>
      </ul>
    </li>
    <li>Track ongoing tasks or features from project planning documentation</li>
  </ul>
</div>

<h3 id="usage-cases-for-appsec-5">Usage cases for AppSec</h3>

<p>This system can be useful for our own work, allowing us to:</p>

<div class="list-awesome-action">
  <ul>
    <li>Create security documentation and diagrams in a platform that the company are familiar with.</li>
    <li>Add our comments and questions to existing documents.</li>
    <li>Upload files and other materials to a storage location which is native to the organization rather than relying on some external storage</li>
  </ul>
</div>

<hr />

<h2 id="source-control-system-and-continuous-integration">Source control system and Continuous Integration</h2>

<p><strong><a href="#top">Back to top ↑</a></strong></p>

<h3 id="explanation-6">Explanation</h3>

<p>The system the company uses to store their source code and also to perform compilation/build processes.</p>

<p><img src="/assets/img/2025-01-06-situational/source.png" alt="source image" class="blog-image" /></p>

<h3 id="system-examples-6">System examples</h3>

<p>Examples of source control systems include:</p>

<div class="list-awesome-system">
  <ul>
    <li>GitHub</li>
    <li>Gitlab</li>
    <li>Bitbucket</li>
    <li>SVN</li>
    <li>Azure DevOps</li>
  </ul>
</div>

<p>Examples of CI systems include:</p>

<div class="list-awesome-system">
  <ul>
    <li>GitHub Actions</li>
    <li>Gitlab CI</li>
    <li>Circle CI</li>
    <li>Travis CI</li>
    <li>Jenkins</li>
    <li>Azure DevOps</li>
  </ul>
</div>

<h3 id="information-provided-5">Information provided</h3>

<p>We can use this system to discover information including:</p>

<div class="list-awesome-info">
  <ul>
    <li>See application code without having to specifically ask each time and keep it updated.</li>
    <li>See infrastructure as code definitions if this is how the organization operates.</li>
    <li>See which developers are working on what parts of the code base.</li>
    <li>See who last person was to touch this code and potentially ask them question.</li>
    <li>See history of changes to understand remediations implemented or understand regressions.</li>
  </ul>
</div>

<h3 id="usage-cases-for-appsec-6">Usage cases for AppSec</h3>

<p>This system can be useful for our own work, allowing us to:</p>

<div class="list-awesome-action">
  <ul>
    <li>Perform ad hoc security scanning and testing.</li>
    <li>Prepare security automations for processes such as change or deployment approval requirements.</li>
    <li>Integrate automated security scanning into existing automated processes.</li>
    <li>Keep our automation experiments within the company’s control and track our changes.</li>
  </ul>
</div>

<hr />

<h2 id="cloud-management-platforms">Cloud Management Platforms</h2>

<p><strong><a href="#top">Back to top ↑</a></strong></p>

<h3 id="explanation-7">Explanation</h3>

<p>Most organizations are using cloud hosted infrastructure to host their applications. Some may be entirely cloud based or cloud native. There will generally be a management platform where all of this infrastructure is managed. Visibility of this platform will be even more important if the company is not using “Infrastructure as Code” to configure it.</p>

<p>For our purposes, access to the API might be even better than the graphical console.</p>

<p><img src="/assets/img/2025-01-06-situational/cloudplatforms.png" alt="cloud platforms image" class="blog-image" /></p>

<h3 id="system-examples-7">System examples</h3>

<p>Examples of systems like this include:</p>

<div class="list-awesome-system">
  <ul>
    <li>Amazon Web Services management console</li>
    <li>Microsoft Azure portal</li>
    <li>Google Cloud Platform console</li>
    <li>Digital Ocean admin interface</li>
  </ul>
</div>

<h3 id="information-provided-6">Information provided</h3>

<p>We can use this system to discover information including:</p>

<div class="list-awesome-info">
  <ul>
    <li>What cloud resources are currently deployed.</li>
    <li>Which different deployment environments are available including which are considered “production” and which are not.</li>
    <li>Any logging, monitoring, or security relevant information which the platform provides</li>
  </ul>
</div>

<h3 id="usage-cases-for-appsec-7">Usage cases for AppSec</h3>

<p>This system can be useful for our own work, allowing us to:</p>

<div class="list-awesome-action">
  <ul>
    <li>Deploy our own infrastructure for our own internal tools or mechanisms rather than having to rely on separate mechanisms.</li>
    <li>Utilize scans which pull information directly from the cloud platform API.</li>
  </ul>
</div>

<hr />

<h2 id="observability">Observability</h2>

<p><strong><a href="#top">Back to top ↑</a></strong></p>

<h3 id="explanation-8">Explanation</h3>

<p>This is the posh new word for logging :) The overall goal is to give developers and operations team more insight into what is going on in the running application, especially in production.</p>

<p><img src="/assets/img/2025-01-06-situational/observability.jpg" alt="observability image" class="blog-image" /></p>

<h3 id="system-examples-8">System examples</h3>

<p>Examples of systems like this include:</p>

<div class="list-awesome-system">
  <ul>
    <li>DataDog</li>
    <li>Logz.io</li>
    <li>Sentry</li>
    <li>New Relic</li>
  </ul>
</div>

<h3 id="information-provided-7">Information provided</h3>

<p>We can use this system to discover information including:</p>

<div class="list-awesome-info">
  <ul>
    <li>The impact of our actions in real time when performing security testing.</li>
    <li>The level of coverage that a DAST tool or penetration test is giving us if we have a way of knowing which traffic relates to the tool or test.</li>
    <li>Potentially being able to discover who is responsible for what within the application portfolio if they are associated with alerting for particular applications.</li>
  </ul>
</div>

<h3 id="usage-cases-for-appsec-8">Usage cases for AppSec</h3>

<p>This system can be useful for our own work, allowing us to:</p>

<div class="list-awesome-action">
  <ul>
    <li>Set up custom application detections and alerts the a similar way to the approach defined by the OWASP AppSensor project.</li>
    <li>Investigate suspicious activity in realtime without having to request log files each time.</li>
  </ul>
</div>

<hr />

<h2 id="in-conclusion">In conclusion</h2>

<p>This post got a little long but hopefully provides you with a useful overview of how you can use organizational systems to operate more effectively as an AppSec architect.</p>

<p>What did I miss out? Let me know on <a href="https://twitter.com/JoshCGrossman">Twitter</a>, <a href="https://bsky.app/profile/joshcgrossman.com">Blue Sky</a> or <a href="https://www.linkedin.com/in/joshcgrossman/">LinkedIn</a>!</p>]]></content><author><name>josh</name></author><category term="blog" /><summary type="html"><![CDATA[Introduction]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="/assets/img/2025-01-06-situational/knowing.png" /><media:content medium="image" url="/assets/img/2025-01-06-situational/knowing.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">When the “safe” is worse than you thought</title><link href="/blog/2024/03/28/when-the-safe-is-worse-than-you-thought.html" rel="alternate" type="text/html" title="When the “safe” is worse than you thought" /><published>2024-03-28T09:45:21+00:00</published><updated>2024-03-28T09:45:21+00:00</updated><id>/blog/2024/03/28/when-the-safe-is-worse-than-you-thought</id><content type="html" xml:base="/blog/2024/03/28/when-the-safe-is-worse-than-you-thought.html"><![CDATA[<h2 id="introduction">Introduction</h2>

<p><a href="/blog/2024/02/20/when-the-safe-is-bad-and-the-unsafe-is-safe.html">My previous post</a> was about better understanding the situation when you make software security recommendations and how that can often be quite tricky. I illustrated this with the way that the Prisma ORM handles SQL injection.</p>

<p><img src="/assets/img/2024-04-02-prisma-2/pie.jpg" alt="Picture of pie representing me eating humble pie" class="blog-image" /></p>

<p>As it turns out, I proved myself correct almost immediately by discovering that I had overestimated the strict accuracy of the documentation and underestimated the ability of developers to get the job done in whatever way possible.</p>

<p>In this post, I’ll explain what happened and the revised guidance around Prisma ORM.</p>

<h2 id="suggesting-the-safe-method">Suggesting the “safe” method</h2>

<p><img src="/assets/img/2024-04-02-prisma-2/inconceivable.png" alt="image" class="blog-image" /></p>

<h3 id="original-documentation">Original documentation</h3>

<p>So my previous post was very much in line with how I understood Prisma’s documentation of the <code class="language-plaintext highlighter-rouge">$queryRaw</code> function, (or at least how their documentation used to look). You can see an extract here:</p>

<p><img src="/assets/img/2024-04-02-prisma-2/docs-extract.png" alt="image" class="blog-image" /></p>

<p>(See original documentation <a href="https://web.archive.org/web/20240229151956/https://www.prisma.io/docs/orm/prisma-client/queries/raw-database-access/raw-queries#raw-queries-with-relational-databases">at this archive link</a>.)</p>

<p>My feeling from the documentation was that the <code class="language-plaintext highlighter-rouge">$queryRaw</code> and <code class="language-plaintext highlighter-rouge">$executeRaw</code> functions were safe but if you wanted to generate a query dynamically into a variable somewhere other than directly in these functions, it would not be possible.</p>

<p>I was currently looking at a use case which required this type of dynamic query generation so I was expecting that developers would therefore not be able to use <code class="language-plaintext highlighter-rouge">$queryRaw</code> and that instead they would need to use <code class="language-plaintext highlighter-rouge">$queryRawUnsafe</code>.</p>

<h3 id="inconceivableor-is-it">Inconceivable…or is it?</h3>

<p>But, as I said above, I had underestimated developers…</p>

<p>(Developers clearly make the best hackers!)</p>

<p>They came up with something like this stunning piece of code which got me scratching my head as to why on earth it worked.</p>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">import</span> <span class="p">{</span> <span class="nx">PrismaClient</span> <span class="p">}</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">@prisma/client</span><span class="dl">'</span>

<span class="kd">const</span> <span class="nx">prisma</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">PrismaClient</span><span class="p">()</span>

<span class="kd">const</span> <span class="nx">untrustedInput</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">lomo@prisma.io</span><span class="se">\'</span><span class="s1"> OR </span><span class="se">\'</span><span class="s1">1</span><span class="se">\'</span><span class="s1">=</span><span class="se">\'</span><span class="s1">1</span><span class="dl">'</span>
<span class="kd">const</span> <span class="nx">sql</span> <span class="o">=</span> <span class="s2">`
  SELECT * FROM "User" WHERE email = '</span><span class="p">${</span><span class="nx">untrustedInput</span><span class="p">}</span><span class="s2">';
`</span>

<span class="kd">const</span> <span class="nx">templateString</span><span class="p">:</span> <span class="nx">any</span> <span class="o">=</span> <span class="p">[</span><span class="nx">sql</span><span class="p">];</span>
<span class="nx">templateString</span><span class="p">.</span><span class="nx">raw</span> <span class="o">=</span> <span class="nx">sql</span><span class="p">;</span>

<span class="kd">const</span> <span class="nx">users</span> <span class="o">=</span> <span class="k">await</span> <span class="nx">prisma</span><span class="p">.</span><span class="nf">$queryRaw</span><span class="p">(</span><span class="nx">templateString</span><span class="p">)</span>
<span class="nx">console</span><span class="p">.</span><span class="nf">log</span><span class="p">(</span><span class="nx">users</span><span class="p">)</span>
</code></pre></div></div>

<p>Head-scratcher or not, this works and in the example above leads to an SQL injection vulnerability, despite using the “safe” method.</p>

<blockquote>
  <p><strong>Note:</strong> You can try the examples in this section in the <a href="https://playground.prisma.io/examples/advanced/raw-queries/with-argument">Prisma Playground</a> although be aware that:</p>

  <ul>
    <li>Prisma Playground sometimes errors out so you might need a few attempts before it works…
      <ul>
        <li>Alternatively, you can try <a href="https://github.com/BounceSecurity/prisma-playground-simulator">this offline version</a> I created.</li>
      </ul>
    </li>
    <li>Prisma Playground runs JavaScript so you may need to take that into account. For example, in the version above you will need to remove the <code class="language-plaintext highlighter-rouge">: any</code> from <code class="language-plaintext highlighter-rouge">const templateString: any = [sql];</code> in order for the code to run.</li>
  </ul>
</blockquote>

<h3 id="so-why-does-this-work">So, why does this work?</h3>

<p>The short reason is that we are talking about JavaScript where pretty much anything goes 😂. (Well actually, this was Typescript, but it turns out you can persuade it to act like JavaScript without too much trouble 🤦‍♂️.)</p>

<p>The long reason for why this works is that the <code class="language-plaintext highlighter-rouge">$queryRaw</code> function accepts two possible object types, the <a href="https://microsoft.github.io/PowerBI-JavaScript/interfaces/_node_modules_typedoc_node_modules_typescript_lib_lib_es5_d_.templatestringsarray.html">TemplateStringsArray</a> type (which Typescript uses as the object type for Tagged Templates that I described in the previous post) or an <a href="https://github.com/blakeembrey/sql-template-tag">Sql</a> object which itself is based on Tagged Templates.</p>

<p>A Tagged Template has a property called raw and through the use of the any keyword, the developer has created an object that looked similar enough to a Tagged Template object to be accepted by the <code class="language-plaintext highlighter-rouge">$queryRaw</code> function in both JavaScript and Typescript.</p>

<h3 id="a-simpler-bypass">A simpler bypass</h3>

<p>In fact, it turns out that you don’t even need to go to this much effort. Prisma supplies a helper method called raw which pretty much does this for you but for the Sql type so now making this function unsafe is as simple as the following code.</p>

<div class="language-ts highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">import</span> <span class="p">{</span> <span class="nx">Prisma</span><span class="p">,</span> <span class="nx">PrismaClient</span> <span class="p">}</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">@prisma/client</span><span class="dl">'</span>

<span class="kd">const</span> <span class="nx">prisma</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">PrismaClient</span><span class="p">();</span>

<span class="kd">const</span> <span class="nx">untrustedInput</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">lomo@prisma.io</span><span class="se">\'</span><span class="s1"> OR </span><span class="se">\'</span><span class="s1">1</span><span class="se">\'</span><span class="s1">=</span><span class="se">\'</span><span class="s1">1</span><span class="dl">'</span>

<span class="kd">const</span> <span class="nx">users</span> <span class="o">=</span> <span class="k">await</span> <span class="nx">prisma</span><span class="p">.</span><span class="nx">$queryRaw</span><span class="s2">`
 SELECT * FROM "User" WHERE email = '</span><span class="p">${</span><span class="nx">Prisma</span><span class="p">.</span><span class="nf">raw</span><span class="p">(</span><span class="nx">untrustedInput</span><span class="p">)}</span><span class="s2">';
`</span>
<span class="nx">console</span><span class="p">.</span><span class="nf">log</span><span class="p">(</span><span class="nx">users</span><span class="p">)</span>
</code></pre></div></div>

<p>I did another LinkedIn poll to see if people would pick up on this but there were still people who thought that this was not vulnerable.</p>

<p><img src="/assets/img/2024-04-02-prisma-2/linkedinpoll.png" alt="image" class="blog-image-tall blog-image" /></p>

<p><a href="https://www.linkedin.com/feed/update/urn:li:activity:7175089981831405568/">LinkedIn Post link</a></p>

<p>If you dig deep enough, you can see warnings about this particular function and it is also a lot easier to discover if it is being used than the previous method. But more on that later.</p>

<h2 id="so-now-what">So now what?</h2>

<h3 id="the-best-option-for-being-safe">The best option for being safe</h3>

<p>Having seen all this, I decided that I need to find a way of making the unsafe usage of the safe function safe again.</p>

<p>The best way of doing this would be to build a safe <code class="language-plaintext highlighter-rouge">Sql</code> object which includes parameter markers and parameters and then pass that to the <code class="language-plaintext highlighter-rouge">$queryRaw</code> function.</p>

<p>Unfortunately, this is still not a usable solution if you want to dynamically build the query bit by bit as you need to have all the text strings surrounding the parameters in separate variables which is pretty fiddly.</p>

<div class="language-ts highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// Example is safe if the text query below is completely trusted content</span>
<span class="kd">const</span> <span class="nx">query1</span> <span class="o">=</span> <span class="s2">`SELECT id, name FROM "User" WHERE name = `</span> <span class="c1">// The first parameter would be inserted after this string</span>
<span class="kd">const</span> <span class="nx">query2</span> <span class="o">=</span> <span class="s2">` OR name = `</span> <span class="c1">// The second parameter would be inserted after this string</span>

<span class="kd">const</span> <span class="nx">inputString1</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">Fred</span><span class="dl">"</span>
<span class="kd">const</span> <span class="nx">inputString2</span> <span class="o">=</span> <span class="s2">`'Sarah' UNION SELECT id, title FROM "Post"`</span>

<span class="kd">const</span> <span class="nx">query</span> <span class="o">=</span> <span class="nx">Prisma</span><span class="p">.</span><span class="nf">sql</span><span class="p">([</span><span class="nx">query1</span><span class="p">,</span> <span class="nx">query2</span><span class="p">,</span> <span class="dl">""</span><span class="p">],</span> <span class="nx">inputString1</span><span class="p">,</span> <span class="nx">inputString2</span><span class="p">)</span>
<span class="kd">const</span> <span class="nx">result</span> <span class="o">=</span> <span class="k">await</span> <span class="nx">prisma</span><span class="p">.</span><span class="nf">$queryRaw</span><span class="p">(</span><span class="nx">query</span><span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nf">log</span><span class="p">(</span><span class="nx">result</span><span class="p">);</span>
</code></pre></div></div>

<h3 id="playing-the-uno-reverse-code">Playing the Uno reverse code</h3>

<p><img src="/assets/img/2024-04-02-prisma-2/unoreverse.png" alt="image" class="blog-image" /></p>

<p>In the end, I was inspired by the original bypass code to generate my own <code class="language-plaintext highlighter-rouge">Sql</code> object but this time create it safely with parameters. You technically shouldn’t be able to generate the <code class="language-plaintext highlighter-rouge">Sql</code> object in this way because the <code class="language-plaintext highlighter-rouge">values</code> property is readonly and it won’t support multiple databases but since this is Javascript we can get away with it 🙃.</p>

<p>This code allows the dynamic generation of a query, using parameterization, which could then be used with <code class="language-plaintext highlighter-rouge">$queryRaw</code> or <code class="language-plaintext highlighter-rouge">$executeRaw</code>.</p>

<div class="language-ts highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// Version for Typescript</span>
<span class="kd">const</span> <span class="nx">query</span><span class="p">:</span> <span class="kr">any</span>

<span class="c1">// Version for Javascript</span>
<span class="kd">const</span> <span class="nx">query</span>

<span class="c1">// Safe if the text query below is completely trusted content</span>
<span class="nx">query</span> <span class="o">=</span> <span class="nx">Prisma</span><span class="p">.</span><span class="nx">sql</span><span class="s2">`SELECT id, name FROM "User" WHERE name = $1`</span>

<span class="c1">// inputString can be untrusted input</span>
<span class="kd">const</span> <span class="nx">inputString</span> <span class="o">=</span> <span class="s2">`'Sarah' UNION SELECT id, title FROM "Post"`</span>
<span class="nx">query</span><span class="p">.</span><span class="nx">values</span> <span class="o">=</span> <span class="p">[</span><span class="nx">inputString</span><span class="p">]</span>

<span class="kd">const</span> <span class="nx">result</span> <span class="o">=</span> <span class="k">await</span> <span class="nx">prisma</span><span class="p">.</span><span class="nf">$queryRaw</span><span class="p">(</span><span class="nx">query</span><span class="p">)</span>
<span class="nx">console</span><span class="p">.</span><span class="nf">log</span><span class="p">(</span><span class="nx">result</span><span class="p">)</span>
</code></pre></div></div>

<h3 id="but-is-it-safe">But is it safe?</h3>

<p>So where does this leave us? This updated code is safe at the moment but it could still be made unsafe.</p>

<p>This type of dynamic query building will always need to be done with caution, with careful attention being paid to how the queries are being built. If the dynamic queries are being built programmatically, hopefully you can be more confident that this treatment is being correctly applied. If developers are still manually building these dynamic queries one by one, you may have more reason for concern</p>

<p>In the meantime, I submitted some quite extensive updates to the Prisma documentation to hopefully make these considerations clearer. You can see the updated documentation <a href="https://www.prisma.io/docs/orm/prisma-client/queries/raw-database-access/raw-queries#sql-injection-prevention">at this link</a>.</p>

<p>(Thanks to the team at Prisma for being open to my suggestions 😀)</p>

<h2 id="in-conclusion">In conclusion</h2>

<p>Well at a meta-level, this is another great illustration of the day to day challenges in software security. Sometimes you can’t even rely on the documentation…</p>

<p>I think the key conclusions here are:</p>

<ul>
  <li>Raw queries will always be dangerous and require extra attention because they are so easy to get wrong.</li>
  <li>This is one of the reasons why SQL injection is still so prevalent and we certainly haven’t eradicated it yet.</li>
  <li>Being able to detect these sort of edge cases or changes in the way things are done is super important. In a future post, we’ll try and demonstrate how…</li>
</ul>]]></content><author><name>josh</name></author><category term="blog" /><summary type="html"><![CDATA[Introduction My previous post was about better understanding the situation when you make software security recommendations and how that can often be quite tricky. I illustrated this with the way that the Prisma ORM handles SQL injection. As it turns out, I proved myself correct almost immediately by discovering that I had overestimated the strict accuracy of the documentation and underestimated the ability of developers to get the job done in whatever way possible. In this post, I’ll explain what happened and the revised guidance around Prisma ORM. Suggesting the “safe” method Original documentation So my previous post was very much in line with how I understood Prisma’s documentation of the $queryRaw function, (or at least how their documentation used to look). You can see an extract here: (See original documentation at this archive link.) My feeling from the documentation was that the $queryRaw and $executeRaw functions were safe but if you wanted to generate a query dynamically into a variable somewhere other than directly in these functions, it would not be possible. I was currently looking at a use case which required this type of dynamic query generation so I was expecting that developers would therefore not be able to use $queryRaw and that instead they would need to use $queryRawUnsafe. Inconceivable…or is it? But, as I said above, I had underestimated developers… (Developers clearly make the best hackers!) They came up with something like this stunning piece of code which got me scratching my head as to why on earth it worked. import { PrismaClient } from '@prisma/client' const prisma = new PrismaClient() const untrustedInput = 'lomo@prisma.io\' OR \'1\'=\'1' const sql = ` SELECT * FROM "User" WHERE email = '${untrustedInput}'; ` const templateString: any = [sql]; templateString.raw = sql; const users = await prisma.$queryRaw(templateString) console.log(users) Head-scratcher or not, this works and in the example above leads to an SQL injection vulnerability, despite using the “safe” method. Note: You can try the examples in this section in the Prisma Playground although be aware that: Prisma Playground sometimes errors out so you might need a few attempts before it works… Alternatively, you can try this offline version I created. Prisma Playground runs JavaScript so you may need to take that into account. For example, in the version above you will need to remove the : any from const templateString: any = [sql]; in order for the code to run. So, why does this work? The short reason is that we are talking about JavaScript where pretty much anything goes 😂. (Well actually, this was Typescript, but it turns out you can persuade it to act like JavaScript without too much trouble 🤦‍♂️.) The long reason for why this works is that the $queryRaw function accepts two possible object types, the TemplateStringsArray type (which Typescript uses as the object type for Tagged Templates that I described in the previous post) or an Sql object which itself is based on Tagged Templates. A Tagged Template has a property called raw and through the use of the any keyword, the developer has created an object that looked similar enough to a Tagged Template object to be accepted by the $queryRaw function in both JavaScript and Typescript. A simpler bypass In fact, it turns out that you don’t even need to go to this much effort. Prisma supplies a helper method called raw which pretty much does this for you but for the Sql type so now making this function unsafe is as simple as the following code. import { Prisma, PrismaClient } from '@prisma/client' const prisma = new PrismaClient(); const untrustedInput = 'lomo@prisma.io\' OR \'1\'=\'1' const users = await prisma.$queryRaw` SELECT * FROM "User" WHERE email = '${Prisma.raw(untrustedInput)}'; ` console.log(users) I did another LinkedIn poll to see if people would pick up on this but there were still people who thought that this was not vulnerable. LinkedIn Post link If you dig deep enough, you can see warnings about this particular function and it is also a lot easier to discover if it is being used than the previous method. But more on that later. So now what? The best option for being safe Having seen all this, I decided that I need to find a way of making the unsafe usage of the safe function safe again. The best way of doing this would be to build a safe Sql object which includes parameter markers and parameters and then pass that to the $queryRaw function. Unfortunately, this is still not a usable solution if you want to dynamically build the query bit by bit as you need to have all the text strings surrounding the parameters in separate variables which is pretty fiddly. // Example is safe if the text query below is completely trusted content const query1 = `SELECT id, name FROM "User" WHERE name = ` // The first parameter would be inserted after this string const query2 = ` OR name = ` // The second parameter would be inserted after this string const inputString1 = "Fred" const inputString2 = `'Sarah' UNION SELECT id, title FROM "Post"` const query = Prisma.sql([query1, query2, ""], inputString1, inputString2) const result = await prisma.$queryRaw(query); console.log(result); Playing the Uno reverse code In the end, I was inspired by the original bypass code to generate my own Sql object but this time create it safely with parameters. You technically shouldn’t be able to generate the Sql object in this way because the values property is readonly and it won’t support multiple databases but since this is Javascript we can get away with it 🙃. This code allows the dynamic generation of a query, using parameterization, which could then be used with $queryRaw or $executeRaw. // Version for Typescript const query: any // Version for Javascript const query // Safe if the text query below is completely trusted content query = Prisma.sql`SELECT id, name FROM "User" WHERE name = $1` // inputString can be untrusted input const inputString = `'Sarah' UNION SELECT id, title FROM "Post"` query.values = [inputString] const result = await prisma.$queryRaw(query) console.log(result) But is it safe? So where does this leave us? This updated code is safe at the moment but it could still be made unsafe. This type of dynamic query building will always need to be done with caution, with careful attention being paid to how the queries are being built. If the dynamic queries are being built programmatically, hopefully you can be more confident that this treatment is being correctly applied. If developers are still manually building these dynamic queries one by one, you may have more reason for concern In the meantime, I submitted some quite extensive updates to the Prisma documentation to hopefully make these considerations clearer. You can see the updated documentation at this link. (Thanks to the team at Prisma for being open to my suggestions 😀) In conclusion Well at a meta-level, this is another great illustration of the day to day challenges in software security. Sometimes you can’t even rely on the documentation… I think the key conclusions here are: Raw queries will always be dangerous and require extra attention because they are so easy to get wrong. This is one of the reasons why SQL injection is still so prevalent and we certainly haven’t eradicated it yet. Being able to detect these sort of edge cases or changes in the way things are done is super important. In a future post, we’ll try and demonstrate how…]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="/assets/img/2024-04-02-prisma-2/pie.jpg" /><media:content medium="image" url="/assets/img/2024-04-02-prisma-2/pie.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry></feed>