Jekyll2023-08-15T03:02:42+00:00https://vickieli.dev/feed.xmlVickie Li’s Security BlogVickie Li's Security Blog.Vickie LiTech Writing vs GPT2023-08-14T00:00:00+00:002023-08-14T00:00:00+00:00https://vickieli.dev/ai/ai-tech-writing<p>Is AI replacing technical writers and developer advocates?</p>
<p>I recently stumbled on a Twitter discussion debating whether the role of developer relations (DevRel) / developer advocates would become obsolete due to generative AI, such as GPT.</p>
<p>DevRels are the people who create and maintain a community around a product. Their responsibilities include writing documentation and blog posts, producing educational content like videos, newsletters, and podcasts, and organizing or participating in tech events.</p>
<p>Although it’s unlikely that the face-to-face aspect of DevRel can be replaced anytime soon, a big part of many DevRel positions is generating digital content: specifically technical writing, such as external-facing documentation and blogs. For example, while working in both DevRel and technical writing, I frequently had to explain security concepts in-depth to software engineers. So I decided to prompt ChatGPT to create a blog post about XSS and see how it does.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Create a blog post that explains XSS vulnerabilities.\
The audience of the blog post should be software engineers.\
The post should include different types of XSS,\
and how to write XSS safe code,\
with both examples of vulnerable code and how to fix them.
</code></pre></div></div>
<p>ChatGPT generated this article. (Feel free to skim and skip forward to my commentary below.)</p>
<blockquote>
<p>Start ChatGPT Article</p>
</blockquote>
<p><code class="language-plaintext highlighter-rouge">Protect Your Web Application: Understanding and Preventing Cross-Site Scripting (XSS) Vulnerabilities</code></p>
<p><em>Introduction</em></p>
<p><em>As software engineers, we all want to create web applications that are both functional and secure. However, one of the most dangerous security threats that can impact a web application is Cross-Site Scripting (XSS) vulnerabilities. In this blog post, we will explore the different types of XSS vulnerabilities and discuss best practices for writing XSS-safe code.</em></p>
<p><em>Types of XSS Vulnerabilities</em></p>
<p><em>XSS vulnerabilities can be categorized into three main types: Reflected XSS, Stored XSS, and DOM-Based XSS. Reflected XSS happens when user input is reflected back to the user in an unescaped form, allowing malicious code to be injected. Stored XSS, on the other hand, occurs when malicious code is injected into a database and is served to all users who access the affected page. Finally, DOM-Based XSS targets the client-side scripts that manipulate the Document Object Model (DOM).</em></p>
<p><em>Risks of XSS Vulnerabilities</em></p>
<p><em>XSS vulnerabilities can lead to several risks, including data theft, malware distribution, and website defacement. When a web application is vulnerable to XSS attacks, an attacker can steal sensitive data, execute malicious scripts, or even take over the entire website. Some examples of real-world incidents involving XSS vulnerabilities include the MySpace worm and the Samy worm.</em></p>
<p><em>Best Practices for Writing XSS Safe Code</em></p>
<p><em>To prevent XSS vulnerabilities, you should implement input validation and sanitization, output encoding and escaping, and the proper use of cookies. Let’s take a closer look at each of these practices:</em></p>
<ol>
<li><em>Input Validation and Sanitization: Validate all user input to ensure it meets expected criteria and sanitize it to remove any malicious code.</em></li>
<li><em>Output Encoding and Escaping: Encode all output to prevent malicious code from being injected into a web page. Escaping special characters like <, >, and & is also crucial.</em></li>
<li><em>Proper Use of Cookies: Use HTTPOnly and Secure cookies to prevent cookie theft and ensure that cookies are only transmitted over encrypted connections.</em></li>
</ol>
<p><em>Examples of Vulnerable Code and How to Fix Them</em></p>
<p><em>Here are some examples of vulnerable code and how to fix them:</em></p>
<p><em>Vulnerable Code:</em></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>document.write("<h1>Welcome, " + username + "!</h1>");
</code></pre></div></div>
<p><em>This code is vulnerable to Reflected XSS attacks because the variable </em><code class="language-plaintext highlighter-rouge">*username*</code><em> is not sanitized.</em></p>
<p><em>Fixed Code:</em></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>document.write("<h1>Welcome, " + escapeHTML(username) + "!</h1>");
</code></pre></div></div>
<p><em>The </em><code class="language-plaintext highlighter-rouge">*escapeHTML()*</code><em> function will encode special characters in the </em><code class="language-plaintext highlighter-rouge">*username*</code><em> variable to prevent XSS attacks.</em></p>
<p><em>Vulnerable Code:</em></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><input type="text" value="<%= user.name %>">
</code></pre></div></div>
<p><em>This code is vulnerable to Stored XSS attacks because the </em><code class="language-plaintext highlighter-rouge">*user.name*</code><em> variable is not sanitized.</em></p>
<p><em>Fixed Code:</em></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><input type="text" value="<%= escapeHTML(user.name) %>">
</code></pre></div></div>
<p><em>Using the </em><code class="language-plaintext highlighter-rouge">*escapeHTML()*</code><em> function will encode special characters in the </em><code class="language-plaintext highlighter-rouge">*user.name*</code><em> variable to prevent XSS attacks.</em></p>
<p><em>Tools for Identifying and Preventing XSS Vulnerabilities</em></p>
<p><em>Several tools are available to help identify and prevent XSS vulnerabilities, such as static and dynamic analysis tools, penetration testing, and third-party security services. It’s important to incorporate these tools into your web application development process to ensure your code is secure.</em></p>
<p><em>Conclusion</em></p>
<p><em>XSS vulnerabilities are a serious threat to the security of web applications, but by following best practices for writing XSS-safe code and using available tools, we can prevent them from being exploited. Remember to always validate and sanitize user input, encode output, and use secure cookies to protect your web application from XSS attacks.</em></p>
<blockquote>
<p>End ChatGPT Article</p>
</blockquote>
<p>Initially, the article looks solid. It covers a lot of topics related to XSS that readers may find useful. However, I can’t say that ChatGPT is a great technical writer. It missed out on a lot of things that make tutorials or documentation helpful.</p>
<h2 id="anticipating-a-readers-needs">Anticipating a reader’s needs</h2>
<p>The majority of mental labor that goes into writing is anticipating the audience’s needs, and figuring out what they came here for. For example, you’d need to understand your audience, and what prior knowledge they are likely to have, and decide which concepts to introduce, in what order, and to what depth. You’ll also need to predict what trouble spots your audience may run into in the article, and build up to complex topics incrementally.</p>
<p>For instance, in the “Types of XSS Vulnerabilities” section, the generated article states that “<em>Reflected XSS happens when user input is reflected back to the user in an unescaped form, allowing malicious code to be injected.</em>”</p>
<p>What does “reflected back” mean? What type of malicious code should one inject? Would someone unfamiliar with XSS understand these terms intuitively? A good technical article should bridge gaps between topics and introduce new technical content based on pre-existing knowledge, which is what I found the most lacking in the generated article.</p>
<h2 id="depth-of-understanding-and-research">Depth of understanding and research</h2>
<p>The AI introduced a very high-level overview of the topic but lacked direction on which details to include. It would take someone with more in-depth knowledge of XSS to provide these follow-up prompts. The depth of knowledge provided by GPT-generated content is directly related to the prompter’s understanding of the topic.</p>
<p>For example, for an article targeted toward software engineers, the article’s discussion about prevention and sanitization is too shallow. To make the article more useful, I’ll need to ask ChatGPT to discuss what these sanitization functions do, how they prevent certain types of XSS, and if there are attacker techniques that can bypass the protection.</p>
<h2 id="forming-opinions">Forming opinions</h2>
<p>When asked about the best practices to prevent XSS in certain contexts, ChatGPT struggled to provide a well-argued response, and simply stated that “<em>All of the methods mentioned in the blog post — input validation and sanitization, output encoding and escaping, and proper use of cookies — are important and should be implemented together to prevent XSS vulnerabilities effectively.</em>”</p>
<p>Although GPT should have a much deeper reserve of XSS knowledge than me, this advice sounds like it came from someone with a shallow understanding of the topic. Forming technical opinions requires an understanding of the broader context around the technical problem and making generalizations based on multiple scenarios. GPT does not have this capability.</p>
<h2 id="bottom-line">Bottom line</h2>
<p>AI cannot fully replace human writers or authors — not yet, at least. There are many things that ChatGPT is good at, but writing is not one of them.</p>
<p>ChatGPT could make writers more efficient by helping them create outlines and introductions, and edit their work. However, ChatGPT is not a great technical writer by itself, and creating a good article with ChatGPT would likely require a good human writer as the prompter.</p>
<p>Nonetheless, it’s likely that its writing abilities will improve in the near future. For now, I’ll just use GPT as a writing and research assistant.</p>
<p>Want to connect? What other security concepts do you want to learn about? I’d love to know. Feel free to connect on Twitter <a href="https://twitter.com/vickieli7">@vickieli7</a>.</p>
<p><em>This article was written by a human and copyedited by ChatGPT.</em></p>Vickie LiIs AI replacing technical writers and developer advocates?ChatGPT: Build me a Recon Tool!2023-04-12T00:00:00+00:002023-04-12T00:00:00+00:00https://vickieli.dev/ai/chatgpt-recon-tool<p>Using ChatGPT to build a simple hacking recon tool</p>
<p>In Chapter 5 of <a href="https://nostarch.com/bug-bounty-bootcamp">Bug Bounty Bootcamp</a>, I talked about how you can write a simple bash script to automate recon tasks before hacking and bug bounty hunting. Then just a year later, ChatGPT came around.</p>
<p>I am still a huge proponent of learning to script so that you can understand how tools work and fine-tune open-source tools for yourself. But when it comes to translating your tooling ideas into code, you could probably let ChatGPT do the heavy lifting. So this time, I tried to replicate the recon tool I wrote in the book with ChatGPT.</p>
<p>Let’s see what it comes up with! :)</p>
<h2 id="v1-basic-functionality">v1: basic functionality</h2>
<p>I started by describing the simple tool we built in Chapter 5 of Bug Bounty Bootcamp to ChatGPT:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Please write a bash script that will:
--- Look for open ports
--- Look for subdomains
--- Look for file paths
On a target domain, and store the scan results to file.
The script should be able to scan multiple domains at once,
and produce human-readable report files.
</code></pre></div></div>
<p>Seems like a fairly simple prompt, here’s what ChatGPT came back with:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">#!/bin/bash</span>
<span class="c"># Set the target domains as an array</span>
<span class="nv">domains</span><span class="o">=(</span><span class="s2">"example.com"</span> <span class="s2">"test.com"</span><span class="o">)</span>
<span class="c"># Define the output directory</span>
<span class="nv">output_dir</span><span class="o">=</span><span class="s2">"./scan_results"</span>
<span class="c"># Loop through the target domains</span>
<span class="k">for </span>domain <span class="k">in</span> <span class="s2">"</span><span class="k">${</span><span class="nv">domains</span><span class="p">[@]</span><span class="k">}</span><span class="s2">"</span>
<span class="k">do</span>
<span class="c"># Create a directory for the current domain's results</span>
<span class="nb">mkdir</span> <span class="nt">-p</span> <span class="s2">"</span><span class="nv">$output_dir</span><span class="s2">/</span><span class="nv">$domain</span><span class="s2">"</span>
<span class="c"># Run the nmap command to scan for open ports</span>
nmap <span class="nt">-v</span> <span class="nt">-oN</span> <span class="s2">"</span><span class="nv">$output_dir</span><span class="s2">/</span><span class="nv">$domain</span><span class="s2">/open_ports.txt"</span> <span class="s2">"</span><span class="nv">$domain</span><span class="s2">"</span>
<span class="c"># Run the sublist3r command to scan for subdomains</span>
sublist3r <span class="nt">-d</span> <span class="s2">"</span><span class="nv">$domain</span><span class="s2">"</span> <span class="nt">-o</span> <span class="s2">"</span><span class="nv">$output_dir</span><span class="s2">/</span><span class="nv">$domain</span><span class="s2">/subdomains.txt"</span>
<span class="c"># Use Gobuster to scan for file paths</span>
gobuster <span class="nb">dir</span> <span class="nt">-u</span> <span class="s2">"https://</span><span class="nv">$domain</span><span class="s2">"</span> <span class="nt">-w</span> /usr/share/wordlists/dirb/common.txt <span class="nt">-o</span> <span class="s2">"</span><span class="nv">$output_dir</span><span class="s2">/</span><span class="nv">$domain</span><span class="s2">/file_paths.txt"</span> <span class="nt">-k</span>
<span class="k">done</span>
</code></pre></div></div>
<p>This generated script scans the target domains for open ports, subdomains, and file paths. The results for each domain are stored in a separate directory within the <code class="language-plaintext highlighter-rouge">scan_results</code> folder. Here, ChatGPT assumed that I was using Kali Linux since the <code class="language-plaintext highlighter-rouge">/usr/share/wordlists/dirb/common.txt</code> is a wordlist included in Kali by default.</p>
<p>ChatGPT recommended using <code class="language-plaintext highlighter-rouge">Nmap</code>, <code class="language-plaintext highlighter-rouge">Sublist3r</code>, and <code class="language-plaintext highlighter-rouge">Gobuster</code> for the scan. It also provided the instructions for using the tool:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>To use this script, save it to a file (e.g., scan_domains.sh),
make it executable (chmod +x scan_domains.sh), and run it (./scan_domains.sh).
Make sure to install the required tools (nmap, sublist3r, and gobuster)
before running the script.
</code></pre></div></div>
<h2 id="v2-making-it-interactive">v2: making it interactive</h2>
<p>I wanted the tool to be interactive, so I instructed ChatGPT to change the script:</p>
<p>Please make the tool interactive, and make each scan type optional.</p>
<p>This newly generated script prompts the user for the target domains and scan types. The user can choose which scan types to run by entering ‘y’ or ‘n’ for each one.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">#!/bin/bash</span>
<span class="c"># Define the output directory</span>
<span class="nv">output_dir</span><span class="o">=</span><span class="s2">"./scan_results"</span>
<span class="c"># Prompt the user for the target domain(s)</span>
<span class="nb">read</span> <span class="nt">-p</span> <span class="s2">"Enter the target domain(s) (comma-separated): "</span> domain_list
<span class="c"># Convert the comma-separated list to an array</span>
<span class="nv">IFS</span><span class="o">=</span><span class="s1">','</span> <span class="nb">read</span> <span class="nt">-ra</span> domains <span class="o"><<<</span> <span class="s2">"</span><span class="nv">$domain_list</span><span class="s2">"</span>
<span class="c"># Prompt the user for the scan type(s)</span>
<span class="nb">read</span> <span class="nt">-p</span> <span class="s2">"Do you want to scan for open ports? [y/n]: "</span> scan_ports
<span class="nb">read</span> <span class="nt">-p</span> <span class="s2">"Do you want to scan for subdomains? [y/n]: "</span> scan_subdomains
<span class="nb">read</span> <span class="nt">-p</span> <span class="s2">"Do you want to scan for file paths? [y/n]: "</span> scan_paths
<span class="c"># Loop through the target domains</span>
<span class="k">for </span>domain <span class="k">in</span> <span class="s2">"</span><span class="k">${</span><span class="nv">domains</span><span class="p">[@]</span><span class="k">}</span><span class="s2">"</span>
<span class="k">do</span>
<span class="c"># Create a directory for the current domain's results</span>
<span class="nb">mkdir</span> <span class="nt">-p</span> <span class="s2">"</span><span class="nv">$output_dir</span><span class="s2">/</span><span class="nv">$domain</span><span class="s2">"</span>
<span class="c"># Scan for open ports if requested</span>
<span class="k">if</span> <span class="o">[[</span> <span class="nv">$scan_ports</span> <span class="o">==</span> <span class="s2">"y"</span> <span class="o">]]</span>
<span class="k">then
</span>nmap <span class="nt">-v</span> <span class="nt">-oN</span> <span class="s2">"</span><span class="nv">$output_dir</span><span class="s2">/</span><span class="nv">$domain</span><span class="s2">/open_ports.txt"</span> <span class="s2">"</span><span class="nv">$domain</span><span class="s2">"</span>
<span class="k">fi</span>
<span class="c"># Scan for subdomains if requested</span>
<span class="k">if</span> <span class="o">[[</span> <span class="nv">$scan_subdomains</span> <span class="o">==</span> <span class="s2">"y"</span> <span class="o">]]</span>
<span class="k">then
</span>sublist3r <span class="nt">-d</span> <span class="s2">"</span><span class="nv">$domain</span><span class="s2">"</span> <span class="nt">-o</span> <span class="s2">"</span><span class="nv">$output_dir</span><span class="s2">/</span><span class="nv">$domain</span><span class="s2">/subdomains.txt"</span>
<span class="k">fi</span>
<span class="c"># Scan for file paths if requested</span>
<span class="k">if</span> <span class="o">[[</span> <span class="nv">$scan_paths</span> <span class="o">==</span> <span class="s2">"y"</span> <span class="o">]]</span>
<span class="k">then
</span>gobuster <span class="nb">dir</span> <span class="nt">-u</span> <span class="s2">"https://</span><span class="nv">$domain</span><span class="s2">"</span> <span class="nt">-w</span> /usr/share/wordlists/dirb/common.txt <span class="nt">-o</span> <span class="s2">"</span><span class="nv">$output_dir</span><span class="s2">/</span><span class="nv">$domain</span><span class="s2">/file_paths.txt"</span> <span class="nt">-k</span>
<span class="k">fi
done</span>
</code></pre></div></div>
<h2 id="v3-add-notification-functionality">v3: add notification functionality</h2>
<p>Finally, I asked ChatGPT to change the tool so that it would automatically run every night, and notify me of new findings.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Schedule the script to run everyday at midnight,
and notify me if it found anything different from the previous scan.
</code></pre></div></div>
<p>Here’s the final version of the tool. The script compares the new scan results with previous ones using Git and sends an email to your email address if there are any differences.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">#!/bin/bash</span>
<span class="c"># Define the output directory</span>
<span class="nv">output_dir</span><span class="o">=</span><span class="s2">"./scan_results"</span>
<span class="c"># Prompt the user for the target domain(s)</span>
<span class="nb">read</span> <span class="nt">-p</span> <span class="s2">"Enter the target domain(s) (comma-separated): "</span> domain_list
<span class="c"># Convert the comma-separated list to an array</span>
<span class="nv">IFS</span><span class="o">=</span><span class="s1">','</span> <span class="nb">read</span> <span class="nt">-ra</span> domains <span class="o"><<<</span> <span class="s2">"</span><span class="nv">$domain_list</span><span class="s2">"</span>
<span class="c"># Loop through the target domains</span>
<span class="k">for </span>domain <span class="k">in</span> <span class="s2">"</span><span class="k">${</span><span class="nv">domains</span><span class="p">[@]</span><span class="k">}</span><span class="s2">"</span>
<span class="k">do</span>
<span class="c"># Create a directory for the current domain's results</span>
<span class="nb">mkdir</span> <span class="nt">-p</span> <span class="s2">"</span><span class="nv">$output_dir</span><span class="s2">/</span><span class="nv">$domain</span><span class="s2">"</span>
<span class="c"># Scan for open ports</span>
nmap <span class="nt">-v</span> <span class="nt">-oN</span> <span class="s2">"</span><span class="nv">$output_dir</span><span class="s2">/</span><span class="nv">$domain</span><span class="s2">/open_ports.txt"</span> <span class="s2">"</span><span class="nv">$domain</span><span class="s2">"</span>
<span class="c"># Scan for subdomains</span>
sublist3r <span class="nt">-d</span> <span class="s2">"</span><span class="nv">$domain</span><span class="s2">"</span> <span class="nt">-o</span> <span class="s2">"</span><span class="nv">$output_dir</span><span class="s2">/</span><span class="nv">$domain</span><span class="s2">/subdomains.txt"</span>
<span class="c"># Scan for file paths</span>
gobuster <span class="nb">dir</span> <span class="nt">-u</span> <span class="s2">"https://</span><span class="nv">$domain</span><span class="s2">"</span> <span class="nt">-w</span> /usr/share/wordlists/dirb/common.txt <span class="nt">-o</span> <span class="s2">"</span><span class="nv">$output_dir</span><span class="s2">/</span><span class="nv">$domain</span><span class="s2">/file_paths.txt"</span> <span class="nt">-k</span>
<span class="k">done</span>
<span class="c"># Compare the new scan results with the previous ones and send an email if there are any differences</span>
<span class="nv">changes</span><span class="o">=</span><span class="si">$(</span>git <span class="nt">--git-dir</span><span class="o">=</span><span class="s2">"</span><span class="nv">$output_dir</span><span class="s2">/.git"</span> <span class="nt">--work-tree</span><span class="o">=</span><span class="s2">"</span><span class="nv">$output_dir</span><span class="s2">"</span> diff HEAD~1 HEAD<span class="si">)</span>
<span class="k">if</span> <span class="o">[[</span> <span class="nt">-n</span> <span class="nv">$changes</span> <span class="o">]]</span>
<span class="k">then
</span><span class="nb">echo</span> <span class="s2">"</span><span class="nv">$changes</span><span class="s2">"</span> | mail <span class="nt">-s</span> <span class="s2">"Scan results for </span><span class="nv">$domain</span><span class="s2"> have changed"</span> youremail@example.com
<span class="k">fi</span>
</code></pre></div></div>
<p>ChatGPT also created a line you can put in your crontab to schedule nightly scans:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>0 0 <span class="k">*</span> <span class="k">*</span> <span class="k">*</span> /path/to/script.sh <span class="o">>></span> /path/to/logfile.log 2>&1
</code></pre></div></div>
<p>However, this script is not really usable since it’s supposed to run without human intervention. Although ChatGPT removed the user prompts to select scan types, it is still prompting the user for target domains. After I pointed that out, ChatGPT fixed the script:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">#!/bin/bash</span>
<span class="c"># Define the target domains</span>
<span class="nv">domains</span><span class="o">=(</span><span class="s2">"example.com"</span> <span class="s2">"test.com"</span> <span class="s2">"example.org"</span><span class="o">)</span>
<span class="c"># Define the output directory</span>
<span class="nv">output_dir</span><span class="o">=</span><span class="s2">"./scan_results"</span>
<span class="c"># Loop through the target domains</span>
<span class="k">for </span>domain <span class="k">in</span> <span class="s2">"</span><span class="k">${</span><span class="nv">domains</span><span class="p">[@]</span><span class="k">}</span><span class="s2">"</span>
<span class="k">do</span>
<span class="c"># Create a directory for the current domain's results</span>
<span class="nb">mkdir</span> <span class="nt">-p</span> <span class="s2">"</span><span class="nv">$output_dir</span><span class="s2">/</span><span class="nv">$domain</span><span class="s2">"</span>
<span class="c"># Scan for open ports</span>
nmap <span class="nt">-v</span> <span class="nt">-oN</span> <span class="s2">"</span><span class="nv">$output_dir</span><span class="s2">/</span><span class="nv">$domain</span><span class="s2">/open_ports.txt"</span> <span class="s2">"</span><span class="nv">$domain</span><span class="s2">"</span>
<span class="c"># Scan for subdomains</span>
sublist3r <span class="nt">-d</span> <span class="s2">"</span><span class="nv">$domain</span><span class="s2">"</span> <span class="nt">-o</span> <span class="s2">"</span><span class="nv">$output_dir</span><span class="s2">/</span><span class="nv">$domain</span><span class="s2">/subdomains.txt"</span>
<span class="c"># Scan for file paths</span>
gobuster <span class="nb">dir</span> <span class="nt">-u</span> <span class="s2">"https://</span><span class="nv">$domain</span><span class="s2">"</span> <span class="nt">-w</span> /usr/share/wordlists/dirb/common.txt <span class="nt">-o</span> <span class="s2">"</span><span class="nv">$output_dir</span><span class="s2">/</span><span class="nv">$domain</span><span class="s2">/file_paths.txt"</span> <span class="nt">-k</span>
<span class="k">done</span>
<span class="c"># Compare the new scan results with the previous ones and send an email if there are any differences</span>
<span class="nv">changes</span><span class="o">=</span><span class="si">$(</span>git <span class="nt">--git-dir</span><span class="o">=</span><span class="s2">"</span><span class="nv">$output_dir</span><span class="s2">/.git"</span> <span class="nt">--work-tree</span><span class="o">=</span><span class="s2">"</span><span class="nv">$output_dir</span><span class="s2">"</span> diff HEAD~1 HEAD<span class="si">)</span>
<span class="k">if</span> <span class="o">[[</span> <span class="nt">-n</span> <span class="nv">$changes</span> <span class="o">]]</span>
<span class="k">then
</span><span class="nb">echo</span> <span class="s2">"</span><span class="nv">$changes</span><span class="s2">"</span> | mail <span class="nt">-s</span> <span class="s2">"Scan results have changed"</span> youremail@example.com
<span class="k">fi</span>
</code></pre></div></div>
<p>This is the tool we built in Chapter 5, and it took ChatGPT a total of 3 minutes to replicate the functionality. I imagine it would be easy to build out more complicated tools as well.</p>
<p>It was pretty amazing to see ChatGPT at work. It made some incorrect assumptions and did not build a usable tool right away. But if you understand how to program, this will make it very easy to add new functionality to your tools or get a jump start on anything you are building.</p>
<p>Understanding how to write accurate and efficient ChatGPT prompts is probably the next big security skill.</p>
<p>Want to connect? What other security concepts do you want to learn about? I’d love to know. Feel free to connect on Twitter <a href="https://twitter.com/vickieli7">@vickieli7</a>.</p>Vickie LiUsing ChatGPT to build a simple hacking recon toolDesigning Secure Software: A Guide for Developers2023-02-17T00:00:00+00:002023-02-17T00:00:00+00:00https://vickieli.dev/book%20reviews/designing-secure-software<p>AppSec engineer’s book club #001 — discussing Loren Kohnfelder’s book</p>
<p>Many of my followers have been asking me for book recommendations. After all, who doesn’t love a new tech book? Books are my favorite way to absorb new information, especially when learning something new.</p>
<p>I’ve wanted to start a security engineer’s book club to share book recommendations, notes, and summaries for a while now. Over the past year, I’ve read quite a few good technical and non-technical books, including the following:</p>
<ul>
<li>“Designing Secure Software: A Guide for Developers” by Loren Kohnfelder</li>
<li>“Container Security: Fundamental Technology Concepts that Protect Containerized Applications” by Liz Rice</li>
<li>“Hacking APIs: Breaking Web Application Programming Interfaces” by Corey J. Ball</li>
<li>“Bug Bounty Bootcamp: The Guide to Finding and Reporting Web Vulnerabilities” by Vickie Li :)</li>
<li>“The Staff Engineer’s Path: A Guide for Individual Contributors Navigating Growth and Change” by Tanya Reilly, and more.</li>
</ul>
<p>I keep a few next to my desk because I constantly find myself referencing them. In these articles, I hope to share with you some of the best engineering books I’ve read in the past year and hear from you about your favorite tech books.</p>
<p>Today, let’s discuss Loren Kohnfelder’s “Designing Secure Software: A Guide for Developers.” And as with all No Starch Press titles, the book’s cover art is ridiculously good.</p>
<p><img src="https://miro.medium.com/max/344/0*XEjDAof1U2oOL1wC.jpg" alt="" /></p>
<h2 id="summary">Summary</h2>
<p>“Designing Secure Software” has three parts: concepts, design, and implementation. “Concepts” goes through fundamental security concepts, like CIA (confidentiality, integrity, and availability), how to threat model an application, and some structural ways of securing an application (minimize data exposure, etc.). It also talks about secure design patterns and using cryptography safely.</p>
<p>“Design” goes into how to think about design from a security perspective and do security design reviews. This is an essential skill for many product security engineers, and I find myself referencing it repeatedly.</p>
<p>“Implementation” talks about secure programming and avoiding common implementation pitfalls like input issues that lead to vulnerabilities and SOP (Same-Origin Policy) issues. This part of the book also talks about writing security tests.</p>
<p>This book is one of the tech books I enjoyed reading last year. Technical books that read smoothly are rare, and this is one of them. The book provides a good overview of the application security field and gives you the resources to explore more.</p>
<p>One thing I found disappointing was that the chapter on cryptography felt cursory. Since the author is the inventor of digital certificates, I came into the book with the presumption that he would dive deeper into the topic.</p>
<h2 id="how-to-read-this-book">How To Read This Book</h2>
<p>This is not a technical reference book but an “intro to product security” college course. The book is meant for software engineers who want to learn more about security or security professionals diving into application security.</p>
<p>The author introduces most major skills in application security at a high level, so there are more effective ways of learning from it than simply reading through the book. I would suggest taking notes of key points while reading and taking the time to practice applying the concepts instead.</p>
<p>For example, when reading about security requirements, try listing security requirements in a project you are working on in addition to understanding the examples in the book.</p>
<h3 id="assignment-list">Assignment list</h3>
<p>The book has a list of exercises that supplement the concepts it introduces. Here are my picks of exercises from the book. Feel free to try them out. They will help you improve your skills in appsec even if you have not read the book.</p>
<ul>
<li>Threat model a piece of software or a component of the larger system. For bonus points, threat model the component using different threat modeling frameworks and see if your results differ.</li>
<li>Retroactively create a design doc for a piece of software you created or use and review it from a security perspective. Identify components in the software where security matters the most and assess its security strengths and weaknesses. Suggest mitigation or alternative designs based on your findings.</li>
<li>To get a feel of realistic vulnerabilities, participate in open-source projects’ bug bounty or vulnerability disclosure programs. Identify the root cause of the bug and suggest code changes to fix the bug.</li>
<li>Identify locations of untrusted input on the same open-source project and test whether it’s protected against XSS, SQL injections, and path traversal.</li>
<li>Check out an old version of open-source software with a known vulnerability. Write a test that confirms the vulnerability.</li>
</ul>
<p>You can always design your own assignments from the concept you’ve learned. Or perhaps, design a “college course” curriculum with an assignment list based on the book and teach product security to yourself.</p>
<blockquote>
<p>“If debugging is the process of removing software bugs, then programming must be the process of putting them in.”</p>
<p>– Edsger W. Dijkstra</p>
</blockquote>
<p>That’s it for today’s article! Writing truly is a muscle that atrophies. I regret not blogging for this long, but it feels good to be back. Thanks for reading, as always.</p>Vickie LiAppSec engineer’s book club #001 — discussing Loren Kohnfelder’s bookMy Technical Writing Process2022-06-06T00:00:00+00:002022-06-06T00:00:00+00:00https://vickieli.dev/chitchat/tech-writing<p>How I write technical posts and hacking tutorials…</p>
<p>Some of the questions I get the most online are “How do I start hacking?” and “How could I write better technical posts?” After the announcement of my book, I also had people asking me what that process entails.</p>
<p>I love technical writing because it’s a way of sharing knowledge. You can share what you’ve learned and expedite the learning process for others without ever meeting them in person. So I encourage most technical folks to give writing a try. It’s a great way to clarify your thoughts, understand a concept more deeply, and participate in indirect mentorship.</p>
<p>My writing process has not always been the same. I started my blog two years ago, and it wasn’t until I started doing it professionally that I settled on something that worked for me. I have established a solid routine that helps me write consistently and efficiently.</p>
<p>In this article, I will share an overview of my process. I hope it will help you gain some insight into how to write technical content and make you give writing a try too.</p>
<h2 id="research">Research</h2>
<p>The first step to writing any technical article, blog post, or book chapter is research. I try to find out everything I can about a topic. I read the documentation about a technology, I read blog posts and write-ups about a technique, and collect as much information about a subject as possible. I make detailed notes during this process and organize the information I found. I also fact-check everything I read about and test out all payloads, code, and exploits to see that they all work.</p>
<h2 id="outlining">Outlining</h2>
<p>The next step is outlining. And this is probably the most challenging part of the entire process. In this step, I am figuring out what information to include, what not to include, what sequence to introduce concepts in, and what structure of writing would be the best for the information at hand.</p>
<p>This step takes a lot of time and often goes through multiple iterations. And I often find myself changing the outline and structure of an article later in the writing process. For example, for my book Bug Bounty Bootcamp, I had to do a major overhaul of all the chapter outlines six months into writing.</p>
<p>I would argue that this is the most important part of the process (along with research) since this is when you’ll be deciding what you’ll be presenting to the reader and how.</p>
<h2 id="dumping-words-out">Dumping Words Out</h2>
<p>Next, I go through my outline and fill out all the relevant information for each outlined item. I typically have my notes from the research phase by my side. The goal is to translate the concepts I’ve learned there into plain, spoken English.</p>
<p>An important thing to remember at this point is not to edit yourself when writing. Simply capture all your thoughts that you want to express and quit worrying about style and grammar. Those can all come later.</p>
<h2 id="making-art">Making Art</h2>
<p>If the article requires diagrams or infographics, this is when I make them. There’s not much to say about this process since it’s very much dependent on your personal style. For instance, I prefer hand-drawn graphs over something generated by software like Canva or Google Sheets. I also prefer to inject a bit of playfulness or humor into my graphics. But it all depends on preference.</p>
<p>With that said, all good technical art has one defining trait: Less is more. Don’t try to convey too much in a single JPEG. Distill what is necessary, what will complement your post, and throw out anything else.</p>
<h2 id="take-a-break">Take a Break</h2>
<p>Before the editorial stages, I always take a break. I typically schedule my entire writing process into at least two days so that I am not editing my writing from the same day. This helps me look at my article with a fresh set of eyes.</p>
<h2 id="technical-edit">Technical Edit</h2>
<p>Once you have your baseline of technical content and all artwork, the next step is to ensure that both the text and images are technically correct and do not contain any mistakes.</p>
<p>Besides blatant technical mistakes, you should also look for technical holes in the content. Is there anything that you failed to explain? Are there any logical jumps? Is there something that could use more explanation or a reference to another resource?</p>
<h2 id="common-knowledge-edit">Common Knowledge Edit</h2>
<p>The next step is what I call the “common knowledge” edit. In this phase, I try to read my writing as someone else — someone with no prior knowledge about my topic and is instead equipped with the “common knowledge” for my target audience. For instance, for a security code review article for developers, I can assume that my readers already understand the concepts of HTTP, cookies, encryption, etc.</p>
<p>When writing my book, I also assume that readers have read previous chapters, so I can add that knowledge to my “common knowledge.”</p>
<h2 id="copy-edit-copy-edit-copy-edit">Copy Edit, Copy Edit, Copy Edit</h2>
<p>By this point, the technical content of your article is fixed. The next thing to do is to refine the words and sentences. Delete the content that doesn’t add meaning or clarity to your article, think of ways of phrasing each sentence better, and review your word choices.</p>
<p>Clean up the language and make sure that the article flows, makes logical sense, and is easy to read.</p>
<h2 id="grammar-check">Grammar Check</h2>
<p>Next, I run my article through a grammar checker. This step is essential! Good grammar ensures that your writing will not be misunderstood.</p>
<p>When you first start, don’t be discouraged when your grammar checker finds hundreds of mistakes in one article. Your grammar will improve once you learn good writing habits, which will naturally happen after you write a lot.</p>
<h2 id="reading-out-loud">Reading Out Loud</h2>
<p>Finally, read your article out loud for a final check. Reading an article out loud is the ultimate check to see if your article is easy to read and often uncovers those last inconsistencies and mistakes.</p>
<p>Thanks for reading! Connect with me on <a href="https://twitter.com/vickieli7">Twitter</a>.</p>
<p>You can find my book, Bug Bounty Bootcamp, at <a href="https://nostarch.com/bug-bounty-bootcamp">Bug Bounty Bootcamp</a>.</p>Vickie LiHow I write technical posts and hacking tutorials…How To Review Code For Vulnerabilities2021-11-04T00:00:00+00:002021-11-04T00:00:00+00:00https://vickieli.dev/development/code-review-intro<p>Performing a source code review is one of the best ways to find security issues in an application. But how do you do it?</p>
<p>In this tutorial, I will go through some tactics for performing a security code review on your application.</p>
<h2 id="prerequisites">Prerequisites</h2>
<p>Before you start reviewing code, learn what the most common vulnerabilities are for the target application type. Getting familiar with the indicators and signatures of those vulnerabilities will help you identify similar patterns in source code. For example, the signature for an XXE vulnerability is passing user-supplied XML to a parser without disabling DTDs or external entities. (More about XXEs <a href="https://blog.shiftleft.io/intro-to-xxe-vulnerabilities-appsec-simplified-80be40102815">here</a>.)</p>
<p>Although vulnerabilities have common patterns in code, these patterns can look quite different in different contexts. Knowing the programming language, frameworks, and libraries you are working with will help you spot vulnerable patterns more accurately.</p>
<h2 id="some-code-analysis-jargon">Some Code Analysis Jargon</h2>
<p>Before we go on, there are a few concepts that you should understand: “sources”, “sinks”, and “data flow”. In code analysis speak, a “source” is the code that allows a vulnerability to happen. Whereas a “sink” is where the vulnerability actually happens.</p>
<p>Take command injection vulnerabilities, for example. A “source” in this case could be a function that takes in user input. Whereas the “sink” would be functions that execute system commands. If the untrusted user input can get from “source” to “sink” without proper sanitization or validation, there is a command injection vulnerability.</p>
<p>Many common vulnerabilities can be identified by tracking this “data flow” from appropriate sources to corresponding sinks.</p>
<h2 id="quick-start-hunting">Quick Start Hunting</h2>
<p>If you are short on time, focusing on a few issues can help you discover the most common and severe issues.</p>
<p>Start by searching for strings, keywords, and code patterns known to be indicators for vulnerabilities or misconfiguration. For example, hardcoded credentials such as API keys, encryption keys, and database passwords can be discovered by grepping for keywords such as “key”, “secret”, “password”, or a regex search for hex or base64 strings. Don’t forget to search in your git history for these strings as well.</p>
<p>Unchecked use of dangerous functions and outdated dependencies are also a huge source of bugs. Grep for dangerous functions and see if they are reachable by user-controlled data. For example, you can search for strings like and “system()” and “eval()” for potential command injections. Search through your dependencies to see if any of them they are outdated.</p>
<p>The “grepping” technique may help you identify vulnerabilities fast, but it cannot help you identify deeper and more nuanced vulnerabilities in your application. That’s why you’ll probably want to dig deeper into data flow analysis.</p>
<h2 id="digging-deeper">Digging Deeper</h2>
<p>You can complement the above strategy with a more extensive source code review if you have time.</p>
<p>Focus on areas of code that deal with user input. User input locations such as HTTP request parameters, HTTP headers, HTTP request paths, database entries, file reads, and file uploads provide the entry points for attackers to exploit the application’s vulnerabilities. Tracing data flow from these functions to corresponding sinks can help you find common vulnerabilities such as stored-XSS, SQL injections, shell uploads, and XXEs.</p>
<p>Then, review code that performs critical functionalities in the application. This includes code that deals with authorization, authentication and other logic critical to business functions. Look at the protection mechanisms implemented and see if you can bypass them. At the same time, check how business and user data is being transported. Is sensitive information transported and stored safely?</p>
<p>Finally, look out for configuration issues specific to your application. Make sure that your application is using secure settings according to best practices.</p>
<h2 id="what-about-sast">What about SAST?</h2>
<p>As you can see, manual code review can be quite tedious and time-consuming. Using SAST (Static Analysis Security Testing) tools is a great way to speed up the process. Good SAST tools identify vulnerable patterns for you so that you can focus on analyzing the impact and exploitability of the vulnerability.</p>
<p>Automation can help you with other components of the security review as well. For example, SCA (Software Composition Analysis) tools automates the dependency tracking process. SCA tools keep track of an application’s dependencies and alert you if new CVEs are found.</p>
<p>Code scanning tools are not a hundred percent accurate. So the best way to build secure software is to use tools to find possible vulnerabilities, then conduct a manual code review to validate them. This way, you can ensure that as few bugs make it to production as possible.</p>
<p>For more information about conducting code reviews, visit this guide: <a href="https://owasp.org/www-pdf-archive/OWASP_Code_Review_Guide_v2.pdf">https://owasp.org/www-pdf-archive/OWASP_Code_Review_Guide_v2.pdf</a>.</p>Vickie LiPerforming a source code review is one of the best ways to find security issues in an application. But how do you do it?5 Steps To Learn New Things Effectively2021-09-21T00:00:00+00:002021-09-21T00:00:00+00:00https://vickieli.dev/chitchat/learn-new-things<p>Teach yourself computer science, cybersecurity, or anything, really.</p>
<p>Recently, a lot of you have been reaching out to me asking how you can get started in the infosec industry. You asked me what kind of skills you need, what type of certificates you should get, and which programming languages you should learn. But I believe that to succeed in the tech industry, there is no single skill that you really “must know,” except <em>how to teach yourself new things effectively</em>.</p>
<p>So today, I’d like to talk about one of the most important lessons you’ll ever learn in both computer science and cybersecurity:</p>
<p><strong>How to effectively teach yourself new things.</strong></p>
<p>If you are a student trying to become a developer or a security professional, then knowing how to teach yourself is really useful when you don’t have access to a mentor or an official degree program in that field.</p>
<p>And as the field of technology is constantly changing, it’s really important that you master the skill of teaching yourself new things so that you can upgrade your skill set even after you’ve successfully launched a career in the field. Let’s get started!</p>
<h2 id="step-1-make-a-plan">Step 1: Make a Plan</h2>
<p>The first step to teaching yourself is to make a plan. Remember when you are taking a university or high school course, on the first day of each course, you always receive a syllabus that outlines exactly what you will be learning that semester and what the timeline would look like. When you are teaching yourself, you want to do the same thing.</p>
<p>In order to effectively teach yourself, you need to first determine:</p>
<ul>
<li>What are the topics you need to learn?</li>
<li>What are the subtopics you need to master in order to master that topic?</li>
<li>In what sequence and timing should you teach these concepts to yourself?</li>
</ul>
<p>And as a beginner, this can be quite hard, because you don’t know what the field is actually about yet. So how do you go about making your learning plan?</p>
<p>Let’s say that you are trying to learn about a new vulnerability class: server-side request forgery (SSRF). How do you identify the major themes of this topic? The first thing I recommend doing is that you can google the topic and look at the major headlines of each article about that topic. For instance, let’s look at this article about <a href="https://portswigger.net/web-security/ssrf">SSRF</a>.</p>
<p>You can see that the article talks about what SSRF is, the types of SSRF, and how to bypass SSRF protection. You can write these down on a list of things that you need to know about the topic. Do this for a few articles: go through the main themes of posts from different authors to get a high-level overview of the topic, because no one article can talk about all the aspects of a topic and do it correctly.</p>
<p>You can then order the list of topics and determine how to teach yourself and in what order. Start with the topic that requires the least knowledge about the subject matter, then proceed to learn about things that build on top of knowledge you have already learned. And that brings us to our next tip.</p>
<h2 id="step-2-take-it-slow">Step 2: Take It Slow</h2>
<p>Understanding a topic deeply usually takes much more time than you think. So I recommend budgeting at least twice the time you think you need for each subtopic and stick to that timeline. So if you think a concept will take you two days to understand, spend four days on it.</p>
<p>Even if you do gain a basic understanding of the topic well under the timeline, spending extra time researching a topic will only deepen your understanding of the subject matter.</p>
<p>Going back to our previous example, I would recommend spending at least one week devoted to each of these topics: SSRF basics, types of SSRF, and SSRF protection bypass. If you have already gained a good understanding of basic SSRF protection bypasses on day three of SSRF protection bypass week, spend the rest of the week reading up on more obscure instances of SSRF protection bypass and try to think of new and novel ways to do it in different environments. This kind of devoted research time will help you learn more deeply about a subject than most tutorials or courses can offer you.</p>
<h2 id="step-3-find-your-learning-style">Step 3: Find Your Learning Style</h2>
<p>Next up, different people will prefer to learn in different ways. And you’ll probably find that you prefer to learn about different topics in different ways too.</p>
<p>So experiment with different types of learning resources like blogs, videos, and interactive tutorials to see what you prefer. I personally really like writing things down and teaching others. Experiment to find out how you learn best.</p>
<h2 id="step-4-verify-your-sources">Step 4: Verify Your Sources</h2>
<p>People who teach others online make mistakes too. I have certainly made mistakes in my blog posts. So it’s always good to verify your knowledge using multiple different versions of the same resource instead of using one resource as your only source of information.</p>
<p>For instance, if you are learning how to efficiently build a certain functionality, take that Stack Overflow answer with a grain of salt. What do other people say about the topic? What do the top experts in the field say about the topic? Always use more than one source of information and never trust a resource completely. And that brings us to our final tip.</p>
<h2 id="step-5-test-yourself-and-track-your-progress">Step 5: Test Yourself and Track Your Progress</h2>
<p>As you execute your own learning plan, you need to make sure that you are on track and actually learning what you should be learning. And reading about a topic versus actually retaining the knowledge are two very different things. You need to test yourself to measure your progress.</p>
<p>There are a lot of ways to test your knowledge. One of the things I like to do is to write down everything I know about a topic, and then go back and reference my notes to see if I missed anything or got anything wrong. For instance, let’s say you are learning about defending against SQL injection. You can try to write down every defense you know against SQL injection, then explain their differences, in what context you should use each defense, and so on.</p>
<p>And for a lot of things in CS or in cybersecurity, understanding and being able to execute are two different things. You might understand a concept theoretically, but you need to actually do it to make sure that you can. So in this case, your exam for yourself should include projects rather than the conceptual validation I talked about earlier. For example, if you want to learn how to write code that is safe from SQL injection, you can write a simple program and then try to attack your own program with SQL injection. The key is to make sure that you understood something, rather than assuming that you do just because you studied it.</p>
<p>This will help you make sure that you are on track, and help you gain confidence in your abilities too.</p>
<h2 id="lastly-a-word-on-feeling-overwhelmed">Lastly: A Word on Feeling Overwhelmed</h2>
<p>During this process, there will be times when you cannot immediately understand something, or you feel like something is completely beyond your level. That’s totally normal.</p>
<p>Learning is not always a linear process. You will gain a better understanding of a concept once you learn about other concepts in the field or once your brain has had the time to process it. Sometimes, the best thing to do is to let it go and come back to it later.</p>
<p>Learning something that is not immediately relevant, like learning an older version of a language or framework, or reading an outdated technical book can help too. You can often gain intuition and comfort in the topic this way even if the technical commands or exploits are not immediately useful. So that is another strategy you can take when you are stuck.</p>
<p>What other security concepts do you want to learn about? I’d love to know. Feel free to connect on Twitter <a href="https://twitter.com/vickieli7">@vickieli7</a>.</p>Vickie LiTeach yourself computer science, cybersecurity, or anything, really.They are all Injection Vulnerabilities!2021-07-16T00:00:00+00:002021-07-16T00:00:00+00:00https://vickieli.dev/hacking/injections<p>What do SQL injections, command injections, and cross-site scripting have in common? The answer is that they are all injection vulnerabilities!</p>
<p>Lately, I have been thinking a lot about how to teach security. And something I think is really important when learning about security is understanding the fundamentals of why something is happening. So instead of learning about a singular technique or vulnerability class, you want to understand the underlying mechanisms of what caused these issues and why a certain attack is working the way it is.</p>
<h2 id="the-fundamentals-of-injections">The fundamentals of injections</h2>
<p>Injection issues are super common. They are the underlying issue for a huge percentage of vulnerabilities found in real-world applications. So today, let’s dive into the fundamental mechanisms of injection flaws.</p>
<p>In a single sentence, injections happen when applications cannot properly distinguish between untrusted user data and code.</p>
<h2 id="untrusted-user-data">Untrusted user data</h2>
<p>So the first piece of the equation is untrusted user data. Untrusted user data can come in the form of HTTP request parameters, HTTP headers, and cookies. They can also come from databases or stored files that can be modified by the user. If the application does not properly process the untrusted user data before inserting it into a command or query, the program’s interpreter will confuse the user input as a part of a command or a query. In this case, attackers can send data to an application in a way that will change the meaning of its commands.</p>
<p>In a SQL injection attack, for example, the attacker injects data to manipulate SQL commands. And in an XSS attack, the attacker injects data that manipulates the logic of scripts in HTML documents. So Any program that combines user data with programming commands or code is potentially vulnerable.</p>
<p>Also, it’s important to remember that this manipulation can happen any time this piece of data is being processed or used. Even if the malicious user data is not used by the application right away, the untrusted data can eventually travel somewhere in the program where it can do something bad, such as a dangerous function or an unprotected query. And this is where they cause damage to the application, its data, or its users.</p>
<h2 id="preventing-injection-vulnerabilities">Preventing injection vulnerabilities</h2>
<p>That’s why injections are so difficult to prevent. Untrusted data can attack any application component that it touches down the stream. And for every piece of untrusted data the application receives, it needs to detect and neutralize attacks targeting every part of the application. And application might think a piece of data is safe because it does not contain any special characters used for triggering XSS when the attacker intends to trigger an SQL injection instead. It’s not always straightforward to determine what data is safe and data is not, because safe and unsafe data looks very different in different parts of the application.</p>
<h4 id="input-validation">Input validation</h4>
<p>So how do you protect against these threats? The first thing you can do is to validate the untrusted data. This means that you either implement a blocklist to reject any input that contains dangerous characters that might affect application components. Or you implement an allowlist that only allows input strings with known good characters. For example, let’s say that you are implementing a sign-up functionality. Since you know that the data is going to be inserted into a SQL query, you reject any username input that are special characters in SQL, like the single quote. Or, you can implement a rule that only allows alphanumeric characters.</p>
<p>But sometimes blocklists are hard to do because you don’t always know which characters are going to be significant to application components down the line. If you just miss one special character, that can allow attackers to bypass protection.</p>
<p>And allowlists may be too restrictive and in some cases, and sometimes you might need to accept special characters like single quotes in user input fields. For example, if a user named Conan O’Brien is signing up, he should be allowed to use a single quote in his name.</p>
<h4 id="parameterization">Parameterization</h4>
<p>Another possible defense against injection is parameterization. Parameterization refers to compiling the code part of a command before any user-supplied parameters are inserted.</p>
<p>This means that instead of concatenating user input into program commands and sending it to the server to be compiled, you define all the logic first, compile it, then insert user input into the command right before execution. After the user input is inserted into the final command, the command will not be parsed and compiled again. And anything that was not in the original statement will be treated as string data, and not executable code. So the program logic part of your command will remain intact.</p>
<p>This allows the database to distinguish between the code part and the data part of the command, regardless of what the user input looks like. This method is very effective in preventing some injection vulnerabilities, but cannot be used in every context in code.</p>
<h4 id="escaping">Escaping</h4>
<p>And finally, you can escape special characters instead. Escaping means that you encode special characters in user input so that they are treated as data and not as special characters. By using special markers and syntax to mark special characters in user input, escaping lets the interpreter know that the data is not intended to be executed.</p>
<p>But this method comes with its problems as well. For one, you must use the exact encoding syntax for every downstream parser or risk the encoded values being misinterpreted by a parser. You might also forget to escape some characters, which attackers can use to neutralize your encoding attempts. So a key to preventing injection vulnerabilities is to understand how parsers of different languages work, and which parsers run first in your processes.</p>
<p>And that’s it for today’s security lesson. This blog post might be a bit general but understanding the fundamentals of injection vulnerabilities will give you a good foundation to start studying more complex and weird cases of injection vulnerabilities. So I hope this helps you form an intuition of how injection attacks and protections work. Thanks for reading!</p>
<p>What other security concepts do you want to learn about? I’d love to know. Feel free to connect on Twitter <a href="https://twitter.com/vickieli7">@vickieli7</a>.</p>Vickie LiWhat do SQL injections, command injections, and cross-site scripting have in common? The answer is that they are all injection vulnerabilities!How to Connect with Anyone in 30 Seconds2021-03-23T00:00:00+00:002021-03-23T00:00:00+00:00https://vickieli.dev/books/small-talk<p>For anyone who has ever felt ridiculously awkward in social situations.</p>
<h3 id="i-fcking-hate-small-talk--says-everyone-ever">“I F*CKING HATE SMALL-TALK.” — Says everyone, ever.</h3>
<p>Hating small-talk seems to be a pretty common sentiment nowadays.</p>
<p>A while ago, I even encountered a student organization on campus that is working to “Ban Small-talk, and embrace Big-talk”!</p>
<p>With all the casual reluctance and even organized social movements, small-talk sure seems like one of the most despised parts of our social lives. That’s why I was so surprised when I stumbled across the book <em>How to be Good at Small-talk: The Rules of Connection in 30 Seconds</em> by Japanese Author <em>Saito Takashi.</em> Why would someone write a book dedicated to such a hated topic? (There is no English edition of the book, so the title is a rough translation from the Japanese title.)</p>
<p>The book makes a case for the importance of small-talk and tries to answer the following questions:</p>
<p>Could quality small-talk really be the key to a good social life?</p>
<p>How could we make small-talk easier and more pleasant for everyone involved?</p>
<p>How could we use small-talk to further our relationships in our schools, businesses, and families?</p>
<h2 id="the-importance-of-small-talk-the-meaning-in-meaningless-conversation">The Importance of Small-talk: the Meaning in Meaningless Conversation</h2>
<p>Here’s what most people get wrong about conversations: It’s not just your words that are saying things!</p>
<p>People despise small-talk because the words spoken don’t convey much meaning. We all know that the weather is pleasant outside, we all know that your dinner was microwaved leftovers, and we all know what happened at Superbowl the other day!</p>
<p>But words are not the only part of a conversation that conveys information. Our expressions, emotional presence, energy, and physical posture all do something to the people we interact with. And this kind of information exchange is what small-talk does best.</p>
<p>Small-talk breaks down emotional and physical barriers and create familiarity between the two parties involved. This establishes a common baseline emotional state that allows for more meaningful conversation. Think: the appetizer or a drink before the main dish. Perhaps not as exciting as the main course, but definitely elevates the entire experience.</p>
<p>Small-talk is also a statement of intention: it conveys to a stranger your friendliness and acceptance. Small-talk often sculpts first impressions of your personality when you meet someone.</p>
<p>Even among people who are already familiar with each other, small-talk facilitates further emotional bonds by allowing people to enjoy each other’s company in a stress-free way that does not require the mental energy needed for deeper conversations.</p>
<h2 id="how-to-small-talk-skillfully">How to Small-talk Skillfully</h2>
<p>The author argues that small-talk is a skill that can be refined through practice. The book breaks down the elements of small-talk and what we can do to become better at it.</p>
<h3 id="the-first-five-seconds">The first five seconds</h3>
<p>The first five seconds of any encounter is crucial if you want to escalate the encounter into a good-old exchange of pleasantries.</p>
<p>The author suggests that instead of simply saying “hello” and calling it a day, say “hello + <em>X”</em>. The X part can be anything that is relevant to the other person that serves as a catalyst to kick start a conversation. For example:</p>
<ul>
<li>Good morning! Wow, did you see the construction across the street!</li>
<li>Hello! Nice weather today, huh? I’m so glad spring is finally returning.</li>
</ul>
<p>These conversations don’t have to be engaging or entertaining, they simply serve as a signal to others that you are open to having a casual conversation.</p>
<p>Another way of conveying openness and acceptance during the first five seconds is to give a compliment on something visual about the other person. Something like: “Wow! I love your earrings! Where did you get them?” It doesn’t matter how or what you compliment the person on, but the fact that you do it. Compliments, however trivial, makes the other feel seen and appreciated.</p>
<h3 id="continuing-the-vibe">Continuing the vibe</h3>
<p>Having a conversation is like playing catch: you gotta keep the ball flowing!</p>
<p>Avoid making conclusions to the conversation or offer summarizing opinions. Instead, always reply with questions, and allow the other person to continue the conversation easily. Comment on what the other said and redirect the spotlight onto each other to naturally extend the conversation.</p>
<p>Lastly, our body language also matters and can greatly impact the vibe of the exchange. It is best to sit at an angle instead of directly facing each other. And find something to do with your body and hands, like sip coffee or go for a walk during the conversation to take the pressure off the words you are saying.</p>
<h3 id="avoiding-conversation-killers">Avoiding conversation killers</h3>
<p>The worst conversation killer is an overactive ego and concern for one’s image. Stop thinking about yourself, and be genuinely interested in the person you’re conversing with! Especially if you are bad with words, keeping the spotlight on the other person is the best way to enjoy the conversation.</p>
<p>Another conversation killer is perceived judgment. People don’t want to be judged or put down. If your replies give the impression that you are not accepting of others’ opinions, the conversation can quickly die for fear of judgment. One way to resolve this but still express your honest opinion is to acknowledge first and refute later. First, point out the validities of the other’s points and parts you agree with, then express your own opposing views. This can look like: “While I do agree that … I had a different experience …”</p>
<h2 id="advanced-small-talk-beyond-the-30-seconds">Advanced Small-talk: Beyond the 30 Seconds</h2>
<p>To continue building rapport beyond the first thirty seconds, you’ll need to customize your small-talk towards your targeted audience.</p>
<h3 id="map-out-their-likes-and-dislikes">Map out their likes and dislikes</h3>
<p>First, map out a person’s likes and dislikes and find commonalities between the two of you. Mutual likes and dislikes are the best bonding vehicles there is.</p>
<p>If you can create a reliable system that maps out the likes and dislikes, values and thought processes of a person, you can reliably structure conversations to suit both of you. Talk about what excites them, what they value and how they think about the world. Reflect on your similarities and offer your own experiences.</p>
<h3 id="practice">Practice</h3>
<p>Additionally, the best way to get good at small talk is to practice. We live in a society where you can get by with very little conversation: you can order delivery and get food, and buy tons of stuff off Amazon, all without initiating a single conversation or saying hello to anyone.</p>
<p>Practice your small-talk skills! Talk to baristas, librarians, and waitresses, and ask about their days. Not only will you improve your ability to converse with anyone, but you’d surely bright-up someone else’s day as well.</p>
<p><em>Note: Spoken from personal experience, do not try this on US airport security employees. That will only bring unnecessary suspicion and will potentially make you miss your flight!</em></p>
<h3 id="prepare-conversation-topics">Prepare conversation topics</h3>
<p>It’s also good to have a couple of conversation topics on hand that will work for most people. Some of these topics include:</p>
<ul>
<li>What are you doing with your free time lately?</li>
<li>What are you excited about recently?</li>
<li>Tell me something good that happened to you today!</li>
</ul>
<p>These topics are like social lubricants that allow you to transition into positive, fun exchanges quickly. Keep in mind that these conversation starters should elicit positive emotion and remain lighthearted.</p>
<h2 id="a-book-about-small-talk-a-book-about-relationships">A Book about Small-talk, a Book about Relationships</h2>
<p><em>How to be Good at Small-talk: The Rules of Connection in 30 Seconds</em> by <em>Saito Takashi </em>seems to be a book about small-talk but is really a book about establishing and maintaining relationships.</p>
<p>Although sometimes relationships come naturally, more often it is the result of intentional maintenance and diligent effort. By learning how to converse better, we can bring the benefits of small-talk to others: light conversations help people destress and take their minds off what is troubling them in life. And by facilitating quality small-talk, you can improve your social life and bring happiness to others.</p>
<p>Thanks for reading! Connect with me at https://twitter.com/vickieli7.</p>Vickie LiFor anyone who has ever felt ridiculously awkward in social situations.Writing for the Web2021-03-05T00:00:00+00:002021-03-05T00:00:00+00:00https://vickieli.dev/chitchat/web-writing<p>A guide for writing better technical articles + blog posts.</p>
<p>One of the questions I get the most in my Twitter DMs is “How do I write better technical blog posts”?</p>
<p>Technical writing is a specialist skill, and I am by no means an expert. But over the past few years, writing my technical blog has taught me a lot about writing for the Internet. So today, here are my tips to help you produce better technical articles.</p>
<ul>
<li>Simplify</li>
</ul>
<p>Good writing is easy to read. This is especially true when writing on the Internet. On the Internet, your technical blog post has the potential to be shared anywhere in the world. You never know who will come across your content and what their background will be. Simple articles allow non-native speakers and novices to consume your article. Short sentences and paragraphs also make your article easier to read for people using mobile devices.</p>
<p>You want your content to be understandable by the largest group of readers. So it is essential to keep it simple. I am not suggesting that you dumb down your technical content. But you should try to use simple words and sentence structures whenever possible. Avoid jargon, abbreviations, and obscure references. And when you can explain something with one word, never use ten.</p>
<p>Next, simplify your sentences and paragraphs. The rule of thumb that I use is “one idea per sentence and one concept per paragraph.” Do not try to say too much in one go. Keep sentences short. If your sentence is getting too long, divide it up to two.</p>
<ul>
<li>Chunk it up</li>
</ul>
<p>Writing a blog post is not like writing a research paper or a book because the way people consume information on the Internet is different. When people read your blog posts, they might scan the entire article before committing time to reading it. They might be browsing Twitter or checking their phones at the same time. They might be reading your article on a tiny smartphone screen.</p>
<p>So when writing Internet content, it’s important to deliver a good digital experience. Divide your article up into easily digestible chunks. Ensure that each section is marked by appropriate headers and subheaders and that you are introducing concepts in a sequence that makes sense. This makes it easier for readers to revisit, share, or reference different parts of your article.</p>
<ul>
<li>Edit</li>
</ul>
<p>Let’s be honest. Your first draft is horrible. The first draft of this post was significantly more horrible than the version you are reading now. That’s why you should always edit your blog posts.</p>
<p>First, check the organization of your article. Does the article say everything you want to say? Does it do so in a structure that makes logical sense? Next, delete any sentences or paragraphs that do not add meaning or value to your article. Remove redundancies, wishy-washy phrases like “I think,” “you should,” and “probably.” Finally, check for grammar issues, either manually or with a grammar checker.</p>
<p>Most of the time, editing cuts the word count of my first draft down significantly. That’s a good thing! It means that the article is becoming more precise, direct, and clear.</p>
<ul>
<li>What about writer’s block?</li>
</ul>
<p>But what about writer’s block? One of the issues you might encounter when writing is simply coming up with the next sentence, paragraph, and so on.</p>
<p>If you already have a topic in mind, a good way to combat writer’s block is to start with an outline. Create an outline, layout the headings and subheadings, then fill out each section. This will help you stick to a clear article structure as well.</p>
<p>Another way to combat writer’s block is to just start writing! A lot of writing difficulties are caused by inhibition. When I am writing, I often find myself self-editing and nitpicking about the details of my blog post. I become self-conscious about how my writing will be read and become unable to write naturally. In this case, it is important to remember that you will be editing the article later on. So for the first draft, just write whatever comes to your mind! Use bad grammar, use wishy-washy words, and don’t think too much about the tips I mentioned in this article. You can always edit it later.</p>
<p>And as always, have fun! Writing technical blog posts is a fantastic way to share your learning and make friends with the same interests. If you would like to share your blog or your blogging experience with me, feel free to connect at https://twitter.com/vickieli7.</p>Vickie LiA guide for writing better technical articles + blog posts.Building a Security-First Culture2021-01-25T00:00:00+00:002021-01-25T00:00:00+00:00https://vickieli.dev/development/wearing-masks<p>And why Application Security is like wearing masks.</p>
<p>Wearing a face mask to prevent coronavirus is becoming the norm in my city. It was hit heavily by the COVID crisis, and now we have reached an unspoken consensus: wear masks, wherever you go.</p>
<p>This is quite different from where we were just a few months ago. Face masks had a bad reputation, and the local health department had a hard time getting people to wear them. What was stopping people from wearing masks? It turns out, people hate masks because they make breathing difficult, make glasses foggy, and can look quite awkward. But the pros of masks outweigh the cons. And by wearing face masks, we protect ourselves and our communities from the virus.</p>
<p>Application security is like wearing masks. Implementing secure practices requires a lot of effort but is ultimately good for you. Security tools get a bad rep. Developers worry they would slow them down, make their work look bad, or even cost them their jobs when something goes wrong. In particular, static analysis tools are known for producing false positives that require a lot of manpower to deal with. Remediation advice is usually generic and cryptic, requiring the developers to spend time reading through extended documentation.</p>
<p>Despite these barriers, how can we create a culture around prioritizing application security like we created a culture of wearing masks?</p>
<ul>
<li>Present the evidence</li>
</ul>
<p>When the pandemic first started, one of the barriers that prevented people from wearing masks was a lack of awareness. Will wearing masks really prevent the virus? Is the virus that dangerous? Is wearing a mask even worth the hassle?</p>
<p>To help developers write secure code, we need to help developers learn about security and how security impacts their users. Beyond standard security training that teaches developers about technicalities like XXS, SQLi, and insecure deserialization, we need to introduce security training in a way that is relevant to their work.</p>
<p>We need a developer education solution that is efficient, engaging, and easy to absorb. Unfortunately, currently available resources out there are often painfully generic or consist of large blocks of text. By incorporating security education into the development process, we can create motivation for learning about security. Make learning fun, and make it clear why developers should care.</p>
<ul>
<li>Make it easy</li>
</ul>
<p>Just like wearing masks, writing secure software can be uncomfortable. Scanning, testing, and fixing code inevitably introduce friction into a developer’s workflow. We need to make developing secure code as easy and painless as possible by focusing on making security tools developer-friendly.</p>
<p>Like we made face masks better by using good material and design, we can design security tools to be comfortable. Here at <a href="https://www.shiftleft.io/">ShiftLeft</a>, we make static analysis painless by making scans fast and integrating with developers’ favorite tools. To build a secure culture, we need to show developers that security best practices like code scanning don’t have to slow them down.</p>
<ul>
<li>Create a mask-wearing culture</li>
</ul>
<p>Finally, the most powerful thing we can do to change behavior is to create a positive social norm. When we want people to wear masks, we tie mask-wearing to positive social values, like protecting others against the coronavirus.</p>
<p>We can do the same thing for application security. In addition to prioritizing fast development and code quality, we need to establish a cultural norm that encourages secure development. By encouraging secure practices, celebrating security wins, and rewarding caution, we can make secure the de-facto culture in our development teams.</p>
<p>This article is co-authored by <a href="https://medium.com/u/6789436b04be?source=post_page-----b7858d509cf--------------------------------">Prabhu Subramanian</a>, Lead Product Architect at <a href="https://www.shiftleft.io/">ShiftLeft Inc</a>.</p>
<p>Thanks for reading! What is the most challenging part of developing secure software for you? I’d love to know. Feel free to connect on Twitter <a href="https://twitter.com/vickieli7">@vickieli7</a>.</p>Vickie LiAnd why Application Security is like wearing masks.