<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[My Publications]]></title><description><![CDATA[My Publications]]></description><link>https://rotem-bar.com</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1620631121826/DvJAdboRv.png</url><title>My Publications</title><link>https://rotem-bar.com</link></image><generator>RSS for Node</generator><lastBuildDate>Mon, 20 Apr 2026 03:03:59 GMT</lastBuildDate><atom:link href="https://rotem-bar.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Hacking 6.5+ million websites => CVE-2022-29455 (Elementor)]]></title><description><![CDATA[Announcing CVE-2022-29455
Actions you should take if you have Elementor installed:

Scan yourself with this nuclei plugin 

wget https://raw.githubusercontent.com/projectdiscovery/nuclei-templates/3581482df1bfe1aef4e7fff96e183f9ef0e5bf13/cves/2022/CV...]]></description><link>https://rotem-bar.com/hacking-65-million-websites-greater-cve-2022-29455-elementor</link><guid isPermaLink="true">https://rotem-bar.com/hacking-65-million-websites-greater-cve-2022-29455-elementor</guid><dc:creator><![CDATA[Rotem Bar]]></dc:creator><pubDate>Sun, 12 Jun 2022 18:40:53 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1655059104169/jEYhRFNrm.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Announcing <a target="_blank" href="https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-29455">CVE-2022-29455</a></p>
<p>Actions you should take if you have <strong>Elementor</strong> installed:</p>
<ol>
<li>Scan yourself with this nuclei plugin </li>
</ol>
<pre><code><span class="hljs-attribute">wget</span> https://raw.githubusercontent.com/projectdiscovery/nuclei-templates/<span class="hljs-number">3581482</span>df<span class="hljs-number">1</span>bfe<span class="hljs-number">1</span>aef<span class="hljs-number">4</span>e<span class="hljs-number">7</span>fff<span class="hljs-number">96</span>e<span class="hljs-number">183</span>f<span class="hljs-number">9</span>ef<span class="hljs-number">0</span>e<span class="hljs-number">5</span>bf<span class="hljs-number">13</span>/cves/<span class="hljs-number">2022</span>/CVE-<span class="hljs-number">2022</span>-<span class="hljs-number">29455</span>.yaml
<span class="hljs-attribute">nuclei</span> -t ./CVE-<span class="hljs-number">2022</span>-<span class="hljs-number">29455</span>.yaml -u https://...
</code></pre><ol>
<li>Verify yourself here - <a target="_blank" href="https://www.rotem-bar.com/elementor">Elementor XSS Tester</a></li>
</ol>
<hr />
<blockquote>
<p>It all started during the Hackerone ambassador WorldCup.</p>
</blockquote>
<p>While scanning our selected target websites we found an interesting wordpress website. After a quick scan for known plugins we found a wordpress plugin installed named "Elementor".</p>
<p><strong>Elementor</strong> is a very popular wordpress plugin that had a few vulnerabilities in the past, see previous vulnerabilities <a target="_blank" href="https://www.cvedetails.com/vulnerability-list/vendor_id-20517/Elementor.html">here</a></p>
<h3 id="heading-credits">Credits</h3>
<p>Before we begin our story some credits are due:</p>
<p><strong>Gal Nagli</strong> from <strong>Salesforce</strong> - Currently 5th place worldwide at HackerOne.<br /><strong>Tomer Zait</strong> from <strong>F5</strong>- Veteran Security Researcher.<br /><strong>Rotem Bar</strong> from <strong>Cider Security</strong> - Creating the first Appsec Marketplace 
<strong>Elementor Security Team</strong> - Amazing security team with awesome response.  </p>
<h3 id="heading-history-recap">History Recap</h3>
<p>While searching for known bugs in Elementor we saw an interesting bug (<a target="_blank" href="https://nvd.nist.gov/vuln/detail/CVE-2021-24891">CVE-2021-24891</a>) that was raised in the past which uses a DOM-XSS to attack a user logged in to the system.<br />Because we already have some knowledge in Javascript and had fun with DOM-XSS together in the past, we decided to deep dive into this CVE.</p>
<p>In <a target="_blank" href="https://nvd.nist.gov/vuln/detail/CVE-2021-24891">CVE-2021-24891</a>, <strong>Joel Beleña</strong>, a cyber security researcher, found out that injecting a payload into the lightbox settings allowed to inject arbitrary javascript into the website where the plugin is used, see more details here - https://www.jbelamor.com/xss-elementor-lightox.html</p>
<p>Dissecting Joel’s vulnerability showed us that the payload used the lightbox settings payload in Elementor to force display the lightbox module and give it custom settings in a base64 payload:</p>
<pre><code><span class="hljs-comment">#elementor-action:action=lightbox&amp;settings=eyJ0eXBlIjoibnVsbCIsImh0bWwiOiI8c2NyaXB0PmFsZXJ0KCd4c3MnKTwvc2NyaXB0PiJ9</span>
</code></pre><p>Base64 Decoding the settings payload returns us the following json, which shows that the attack attempts to set the type to “null” and setting an html parameter which injects raw unsafe html code into the page:</p>
<pre><code>{<span class="hljs-attr">"type"</span>:<span class="hljs-string">"null"</span>,<span class="hljs-attr">"html"</span>:<span class="hljs-string">"&lt;script&gt;alert('xss')&lt;/script&gt;"</span>}
</code></pre><h3 id="heading-back-to-our-story">Back to our story:</h3>
<p>Trying to reproduce the original payload in the website (which had an up to date version) didn’t work, but when reading the code it brought us to the understanding that there are different values which can be put in the parameter “type” shown above which can be investigated.</p>
<p>The original problem happened when the “type” parameter was not catched in the switch case code and as you can see in the code it is setting html received from the user.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1655054459599/kSnowkyxP.png" alt="Screen Shot 2022-06-12 at 20.20.56.png" /></p>
<p>Unfortunately the fix for the vulnerability was in place and the javascript deletes the “html” parameter before passing it to the affected function as seen below</p>
<h3 id="heading-stay-a-while-and-research">Stay a while and research</h3>
<p>First a small disclaimer, all screenshots and our research was done on the obfuscated code inside the browser, later we found out the code is open source and can be much more easier to read, but for learning purposes we are posting the research as is on the obfuscated code which will simulate better your future assessments.</p>
<p>Going back to the whiteboard, we looked at the different “type” parameters the lightbox module accepts:
<strong>image</strong>, <strong>video</strong> and <strong>slideshow</strong></p>
<p>The “image” doesn’t do much so we skipped through it, and decided to continue with the “video” parameter:</p>
<p><strong>First obstacle:</strong><br />When using the "video” parameter it needs also a “url” parameter, There is a check that the “url” parameter has to start with “http” (My guess is that in the past it didn’t have it and someone injected a “javascript://” or something like that)</p>
<p>Dissecting the video function brings in interesting insights. It uses JQuery (t variable) to set the video parameters which are coming from a parameter called “videoParams”:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1655054816139/F25P3OjXs.png" alt="Screen Shot 2022-06-12 at 20.26.53.png" /></p>
<p>As you can see in the code, in order to reach the state of using the jQuery (t) variable we need to add another parameter called “videoType”. When “videoType” is equal to “hosted” the function creates a new  object which is built dynamically and receives parameters "src" and "autoplay" but can be overridden by “videoParams”.<br />Because "videoParams is controlled by the user, we can add whatever parameter to the video object.</p>
<p><strong>Better Explained by demo</strong></p>
<p>Creating a new payload to verify this:</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"type"</span>: <span class="hljs-string">"video"</span>,
  <span class="hljs-attr">"url"</span>: <span class="hljs-string">"http://"</span>,
  <span class="hljs-attr">"videoType"</span>: <span class="hljs-string">"hosted"</span>,
  <span class="hljs-attr">"videoParams"</span>: {
    <span class="hljs-attr">"style"</span>: <span class="hljs-string">"background-color:red"</span>
  }
}
</code></pre>
<p>which when encoded to base64 looks like</p>
<pre><code>eyJ0eXBlIjoidmlkZW8iLCJodG1sIjoieCIsInVybCI6Imh0dHA6Ly8iLCJ2aWRlb1R5cGUiOiJob3N0ZWQiLCJ2aWRlb1BhcmFtcyI6eyJzdHlsZSI6ImJhY2tncm91bmQtY29sb3I6cmVkIn19
</code></pre><p>The payload successfully added a new style parameter which is rendered into the video:
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1655055133408/JLyUDPNxf.png" alt="Screen Shot 2022-06-12 at 20.32.10.png" />
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1655055151090/-SWi_zcCA.png" alt="Screen Shot 2022-06-12 at 20.32.27.png" /></p>
<p>We are able now to color any video we want and make users see a red screen (Further playing with the payload we were able also to change it to a picture and create a nice phishing page)</p>
<h3 id="heading-bug-bounty-is-all-about-impact">Bug bounty is all about impact!!!</h3>
<p>Going through attributes that  can accept, we found that “onerror” is also allowed, and accepts javascript, so quickly creating a new payload with “onerror” parameter gave us the full exploit.</p>
<pre><code>{
    <span class="hljs-attr">"type"</span>: <span class="hljs-string">"video"</span>,
    <span class="hljs-attr">"url"</span>: <span class="hljs-string">"http://"</span>,
    <span class="hljs-attr">"videoType"</span>: <span class="hljs-string">"hosted"</span>,
    <span class="hljs-attr">"videoParams"</span>: {
        <span class="hljs-attr">"onerror"</span>:<span class="hljs-string">"alert(document.domain+' '+document.cookie)"</span>,
        <span class="hljs-attr">"style"</span>: <span class="hljs-string">"background-color:red"</span>
    }
}
</code></pre><pre><code><span class="hljs-attribute">ewogICAgInR5cGUiOiAidmlkZW8iLAogICAgInV</span>
ybCI6ICJodHRwOi8vIiwKICAgICJ2aWRlb1R5cG
UiOiAiaG9zdGVkIiwKICAgICJ2aWRlb1BhcmFtc
yI6IHsKICAgICAgICAib25lcnJvciI6ImFsZXJ0
KGRvY3VtZW50LmRvbWFpbisnICcrZG9jdW1lbnQ
uY29va2llKSIsCiAgICAgICAgInN0eWxlIjogIm
JhY2tncm91bmQtY29sb3I6cmVkIgogICAgfQp9
</code></pre><p>If you want to sneak peek at code you can see the exact area which is vulnerable:
https://github.com/elementor/elementor/blob/release/3.5.0/assets/dev/js/frontend/utils/lightbox/lightbox.js#L257</p>
<h3 id="heading-our-next-steps">Our next steps</h3>
<p>Our target website is vulnerable, but can we find more?</p>
<blockquote>
<p>Elementor is a mega technology, as it is used by at least 6,441,433 websites on the Internet. - BuiltWith</p>
</blockquote>
<p>Luckily for us we have lists of many domains and subdomains we can scan for the technology. Crafting a quick search for the plugin started to give us vulnerable websites:</p>
<pre><code class="lang-bash">cat list.txt | \
cut -d<span class="hljs-string">"/"</span> -f3 | awk <span class="hljs-string">'NF{print $0 "/wp-content/plugins/elementor/assets/js/frontend.min.js"}'</span> | \
httpx -nc -fr -ms <span class="hljs-string">"elementor"</span> -er <span class="hljs-string">"elementor - v[^\s]*"</span>
</code></pre>
<p>Sample scanning..
<img src="https://media.giphy.com/media/St6PxCcDX4afFoTLNZ/giphy.gif" /></p>
<h3 id="heading-disclosure-process">Disclosure process</h3>
<p>The first thing we did was submit the vulnerability to the vendor, so they could start fixing the issue.</p>
<p>We also submitted the vulnerability to the target we researched, letting them know of the vulnerability as we were initially researching them.</p>
<p>Meantime we wanted to prepare for when a fix is available to let all the programs we can find know about it and disclose it in a safe and private matter to customers who are affected by this threat so they can take proper measures to protect themselves. (As this is a DOM based xss, using a WAF cannot help here, but there are other measures customers can take such as hot-patching, removing the plugin, disabling video support etc.)</p>
<blockquote>
<p>The task of reaching affected customers and notifying them in a private matter is not easy.
Many questions arise here. If the vendor has not fixed the vulnerability yet, what does it help if we tell them about it? Also we don’t want to shout publicly about the problem as it can fall into the wrong hands.</p>
</blockquote>
<p>We went on profiling target customers:<br />Many of the Elementor users are smb businesses which cannot really do anything if we tell them about it and should wait for a proper fix.</p>
<p>But we do have bigger companies who also use Elementor with mature bug bounty programs and security disclosure programs which we can safely communicate with and privately disclose to them the vulnerability.</p>
<p>Searching for the possible candidates was the hardest part of this job.<br />We created lists of subdomains of companies that do have VDP/BB programs and do accept 3rd party submissions and scanned them for the found vulnerability, then we started disclosing the problem.</p>
<p><strong>The responses were divided into 3 different types of answers:</strong></p>
<ol>
<li>They accepted the vulnerability and created the needed measures to secure themselves</li>
<li>They do not accept disclosures of 3rd party vendors which affect them</li>
<li>They are already affected by the previous CVE and did not yet patch their systems</li>
</ol>
<h3 id="heading-a-bit-about-the-impact">A bit about the impact</h3>
<p>When found, this vulnerability affected more than 6.5M websites around the world, Every Elementor based website available on the internet was affected if it was hosted by Elementor or self hosted.</p>
<p>As for the Security Impact, an attacker could do the following:</p>
<ul>
<li>Cookies Exfiltration from the affected origins utilizing the Cross Site Scripting vulnerability, that could even allow in certain scenarios into Account Takeovers.</li>
<li>Executing JavaScript on the victim's behalf</li>
<li>SOAP Bypass</li>
<li>CORS Bypass</li>
<li>Defacement</li>
</ul>
<h3 id="heading-pocorgtfo">POC||GTFO</h3>
<p>We were able to create an account takeover POC which when clicked created a new user if an admin was logged in to his wordpress account.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://youtu.be/IXX1jm-rh_g">https://youtu.be/IXX1jm-rh_g</a></div>
<h3 id="heading-disclosure-timeline">Disclosure Timeline</h3>
<p>11/02/2022     - Disclosure to Elementor.<br />23/02/2022     - Public Fix.<br />12/06/2022     - Full Disclosure - Thanks for the <a target="_blank" href="https://patchstack.com/alliance/">patchstack</a> team for helping disclose the CVE.  </p>
<h3 id="heading-bonus-please-test-yourselves">Bonus - Please test yourselves</h3>
<p><a target="_blank" href="https://www.rotem-bar.com/elementor">https://www.rotem-bar.com/elementor</a></p>
<p>Hope you enjoyed the blog</p>
]]></content:encoded></item><item><title><![CDATA[SSRF in Open Distro for Elasticsearch]]></title><description><![CDATA[After an interesting adventure, it's now possible to announce a new  CVE-2021-31828  which effects  Open Distro for ElasticSearch (ODFE) , versions until 1.12.0.2. 
Open Distro is a plugin for ElasticSearch that enhances security, alerting, SQL query...]]></description><link>https://rotem-bar.com/ssrf-in-open-distro-for-elasticsearch-cve-2021-31828</link><guid isPermaLink="true">https://rotem-bar.com/ssrf-in-open-distro-for-elasticsearch-cve-2021-31828</guid><category><![CDATA[AWS]]></category><category><![CDATA[elasticsearch]]></category><category><![CDATA[opensource]]></category><category><![CDATA[Security]]></category><dc:creator><![CDATA[Rotem Bar]]></dc:creator><pubDate>Tue, 11 May 2021 08:07:46 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1620567891455/bG9Ajqtnq.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>After an interesting adventure, it's now possible to announce a new  <a target="_blank" href="https://nvd.nist.gov/vuln/detail/CVE-2021-31828">CVE-2021-31828</a>  which effects <strong> <a target="_blank" href="https://opendistro.github.io/for-elasticsearch/">Open Distro for ElasticSearch (ODFE)</a> , versions until 1.12.0.2.</strong> </p>
<p>Open Distro is a plugin for ElasticSearch that enhances security, alerting, SQL querying, and gives more advanced capabilities.</p>
<p> <a class="post-section-overview" href="#the-story">Jump directly to how it was found</a>  </p>
<h3 id="the-vulnerability">The Vulnerability</h3>
<p><strong>If you are running ODFE 1.12.0.2 and below, It may be possible for existing privileged users to enumerate listening services or interact with configured resources via HTTP requests in your environment. (SSRF)</strong></p>
<p>Do note that the severity and probability may change according to the usage and environment of the specific installation.<br />For example, If only known administrators can access the elastic instance and the elastic instance is isolated from reaching any network then the risk is low.<br />On the other hand, if the elastic instance is reachable by all users in the company and open to clients when no network hardening was done this vulnerability severity may be high and sometimes critical.</p>
<hr />
<p>For starters, before you read about how this CVE was found, if you are using  <a target="_blank" href="https://www.elastic.co/elasticsearch/">Elasticsearch</a>  and using  <a target="_blank" href="https://opendistro.github.io/for-elasticsearch/">Open Distro</a> as part of your installation, now is a good time to go and check the version,  and upgrade the plugin to the latest version, if you are not up to date.</p>
<p>If you are not sure if you are using Open Distro you can go to your ElasticSearch instance and run the command <code>https://{YOUR_IP}:9200/_cat/plugins?v</code> to see if you have the Open Distro plugin installed.  If you are running Open Distro, you will see the following packages in the response:</p>
<pre><code class="lang-text">opendistro-job-scheduler 
opendistro-sql    
opendistro_index_management   
opendistro_security
</code></pre>
<p><strong>Mitigation</strong></p>
<ol>
<li>Upgrade to the latest version of ODFE (1.13.1.0 and above)</li>
<li>Configure the alerting module to access only the needed resources.</li>
</ol>
<p>First thing you’ll need to do is check your  alerting default by running the following command which will show you the default configuration:</p>
<pre><code class="lang-bash">curl -u <span class="hljs-string">"admin:your_password"</span> -k <span class="hljs-string">"https://{YOUR_IP}:9200/_cluster/settings?include_defaults=true"</span> | \
 jq <span class="hljs-string">".defaults.opendistro.alerting"</span>
</code></pre>
<p>Make sure the <strong>destination.allow_list</strong> enables only the required actions, some installations don’t need all features of ODFE and can pose a risk</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"alerting"</span>: {
    <span class="hljs-comment">/**...**/</span>
    <span class="hljs-attr">"destintation"</span>: {
      <span class="hljs-attr">"allow_list"</span>: [
        <span class="hljs-string">"chime"</span>,
        <span class="hljs-string">"slack"</span>,
        <span class="hljs-string">"custom_webook"</span>,
        <span class="hljs-string">"email"</span>,
        <span class="hljs-string">"test_action"</span>
      ]
    }
  }
}
</code></pre>
<p>In the latest patch, ODFE added the field <strong>destination.host.deny_list</strong> which allows an administrator to control which IP addresses the plugin is denied access to. By default this list is empty. 
It is highly recommended to configure at least all known internal networks in order to deny traffic to your internal resources.</p>
<p>Example:</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"alerting"</span>: {
    <span class="hljs-comment">/**...**/</span>
    <span class="hljs-attr">"destintation"</span>: {
      <span class="hljs-attr">"allow_list"</span>: [
        <span class="hljs-string">"custom_webook"</span>,
        <span class="hljs-string">"test_action"</span>
      ],
      <span class="hljs-attr">"host"</span>: {
        <span class="hljs-attr">"deny_list"</span>: [
          <span class="hljs-string">"127.0.0.0/8"</span>,
          <span class="hljs-string">"10.0.0.8/8"</span>,
          <span class="hljs-string">"172.16.0.0/12"</span>,
          <span class="hljs-string">"192.168.0.0/16"</span>
        ]
      }
    }
  }
}
</code></pre>
<p>Ok, now that required a lot of trust…. now that we got the important part out of the way, let’s actually talk about the adventure itself.</p>
<h3 id="the-story">The Story</h3>
<p>Bug bounty and penetration tests are a part of my way of life, Every project I have taken on, I have had the privilege of learning something new, sometimes it’s just small stuff, and other times when I really get lucky, mind-blowing tricks.</p>
<p>The Open Distro CVE adventure actually started off,  after the kick-off with a client, as a seemingly frustrating penetration test. This was because there wasn’t a single line of code written in the actual project itself. The project basically consisted of a supplier combining different open source solutions into one big tech stack, configuring and supporting the system for the needs of the customer.</p>
<p>This actually happens a lot, especially in government contracts, banks, insurance companies, and other large corporates where projects are outsourced to external system integrators.  These system integrators then combine different components into one cohesive solution (really “templatey” type stacks to solve specific problems rapidly).</p>
<hr />
<p>Back to our story, the purpose of this specific solution was to provide a friendly Kibana interface for a  system that does a lot of processing on the backend and ultimately enables users to easily fetch and process data. (As an aside, this is already the second system I’ve seen this year that essentially “ditched” the custom user interface and provides direct access to a highly customized Kibana interface.)</p>
<p>After ticking the regular boxes, and checking the different configurations, and running the required hardening tests, I still wanted to do better. This is where it gets interesting,  I started to investigate what I could potentially do with the permissions granted in the system to a typical user.</p>
<hr />
<p><strong> The OpenDistro plugin </strong></p>
<p>OpenDistro is an AWS-maintained open-source plugin and is actually pretty cool. It provides many capabilities which are missing in ElasticSearch. The experience is like using a native and complementary add-on to ElasticSearch...but by now we know very well, with great power comes great responsibility.</p>
<p>As part of my investigation, I came upon the alerting module. This module allows the user to create an "open distro monitor" (read more about these  <a target="_blank" href="https://opendistro.github.io/for-elasticsearch-docs/docs/alerting/monitors/#create-monitors">here</a> ), define a trigger as a webhook to any resource, control the method type,  as well as have full control of the body.</p>
<p>The first thing that came to my mind when seeing this was a potential SSRF vulnerability. Server Side Request Forgery is a common attack method that exploits one service to make a request on your behalf from other servers. You can read more about this  <a target="_blank" href="https://portswigger.net/web-security/ssrf">here</a> .</p>
<p>After creating a trigger in the alerting module, you can then test it. This is where the SSRF option comes in.   When testing your request it is sent to the requested server, which returns some kind of response. Sweet!</p>
<p>Crafting some script magic I was able to edit a trigger, invoke it, and read the results.
With this ability, I was able to start scanning the network, access the metadata API (which specifically in the project was unhardened), access the Kubernetes API, as well as other local resources.</p>
<p>The next thing an attacker would do in such a scenario is scanning the available resources and cross-reference them with known and reported vulnerabilities, or other open and vulnerable/unauthenticated endpoints. So that’s what I did too.</p>
<p>The alerting module has support for POST, PUT and PATCH access, and because of this POST access, I was able to request a resource from another server and exploit a different known vulnerability in the connected server (out of the scope of this article) to achieve remote code execution (AKA RCE).</p>
<p><strong>Investigating the source of the problem brought me to this source code:</strong></p>
<p>https://github.com/opendistro-for-elasticsearch/alerting/blob/opendistro-1.12/notification/src/main/java/com/amazon/opendistroforelasticsearch/alerting/destination/client/DestinationHttpClient.java#L115</p>
<pre><code class="lang-java">
CustomWebhookMessage customWebhookMessage = (CustomWebhookMessage) message;


uri = buildUri(customWebhookMessage.getUrl(), customWebhookMessage.getScheme(), customWebhookMessage.getHost(),
        customWebhookMessage.getPort(), customWebhookMessage.getPath(), customWebhookMessage.getQueryParams());


httpRequest = constructHttpRequest(((CustomWebhookMessage) message).getMethod());
</code></pre>
<p>This line of code essentially creates HTTP requests based upon user input and sends them without any validations.</p>
<h3 id="remediation-process">Remediation Process</h3>
<p>After searching for how and who to submit this issue, I found that the OpenDistro plugin actually belongs to AWS, and started the disclosure process.</p>
<p>The AWS security team was very responsive, and I want to thank all of the team members involved who took the issue seriously, started the triage process immediately, and kept me in the loop during the whole process.</p>
<p>The fix has now been deployed, and now administrators can upgrade their ODFE plugin and configure a list of allowed hosts to communicate with. (See mitigation section above)</p>
<h3 id="from-an-attackers-perspective">From An Attacker’s Perspective</h3>
<p>Many times attackers that are unable to access resources directly will find the “proxy” resource that will provide them the access they need to your sensitive internal resources and data.  </p>
<p>Once they have a good understanding of the technologies in the stack - it’s a simple search to find vulnerabilities in the different versions, and try to exploit those known vulnerabilities.</p>
<h3 id="lessons-learned">Lessons Learned</h3>
<p><strong>Don’t underestimate yourself in any pentest/bounty program.</strong><br />Don’t leave any stone unturned, especially in areas you think are battle-hardened. You might surprise yourself.</p>
<p><strong>Be aware of the plugin ecosystem.</strong><br />When we come to secure/attack our stacks and systems we can’t only look only at the application itself - but we also need to take into account the different third-party resources they integrate with, and in this case plugins.  Each and every one of these integrations need to be examined individually, as they can be your single point of failure. Take the SolarWinds example, where an old unpatched version was the key to the kingdom.</p>
<p><strong> Test carefully webhooks </strong><br />Because most systems born today use multiple microservices, webhooks and the environment are easily exploited into doing stuff they shouldn't.<br />Any time your service requests external HTTP resources you should validate that users cannot change the target of the server. In the event that this is by design, it will be your responsibility to add the required validations needed to properly secure your other services.</p>
<h3 id="disclosure-and-remediation-timeline">Disclosure &amp; Remediation Timeline:</h3>
<p><strong>24 January</strong> - Reported to AWS<br /><strong>24-26 January</strong> - First response from AWS and start of triage process<br /><strong>26 February</strong> - Fix committed into github repo in version 1.13.1.0<br /><strong>5 March</strong> - Dockerhub updated with version 1.13.1<br /><strong>26 April</strong> - CVE created<br /><strong>6 May</strong> - CVE released<br /><strong>11 May</strong> - Blog published</p>
]]></content:encoded></item><item><title><![CDATA[Developers, Please encode your URLs]]></title><description><![CDATA[Uniform Resource Locators (URLs) are a funny thing. They seem so simple, but yet they have so many small complex rules to them, that all of a sudden, when you try to explain what a url is and the correct way to parse one, you find yourself in a sea o...]]></description><link>https://rotem-bar.com/developers-please-encode-your-urls-e45922fb2a80</link><guid isPermaLink="true">https://rotem-bar.com/developers-please-encode-your-urls-e45922fb2a80</guid><dc:creator><![CDATA[Rotem Bar]]></dc:creator><pubDate>Mon, 26 Oct 2020 17:32:03 GMT</pubDate><content:encoded><![CDATA[<p>Uniform Resource Locators (URLs) are a funny thing. They seem so simple, but yet they have so many small complex rules to them, that all of a sudden, when you try to explain what a url is and the correct way to parse one, you find yourself in a sea of complexity.</p>
<h2 id="the-inner-workings-of-urls">The inner workings of URLs</h2>
<p>Let’s start with the basics. A URL identifies a resource and tells you which method you should use to access it. An example of this is:</p>
<blockquote>
<h1 id="httpswwwappsflyercomwhy-appsflyerhttpsappsflyercomwhy-appsflyer"><a target="_blank" href="https://appsflyer.com/why-appsflyer">https://www.appsflyer.com/why-appsflyer/</a></h1>
</blockquote>
<p>Here the resource is the <a target="_blank" href="https://appsflyer.com/why-appsflyer">https://appsflyer.com/why-appsflyer</a> page
The method used is https which means secure hyper-text transfer protocol.</p>
<p>To take this to the specifications, there are two main RFCs that govern our URL usage. Even though <a target="_blank" href="https://tools.ietf.org/html/rfc3986">RFC3986</a> is the update to <a target="_blank" href="https://tools.ietf.org/html/rfc1738">RFC1738</a>, both schemes are still widely used today by applications.</p>
<p><a target="_blank" href="https://tools.ietf.org/html/rfc3986">**RFC3986</a>**</p>
<pre><code>&lt;scheme&gt;<span class="hljs-regexp">//</span>&lt;user&gt;<span class="hljs-symbol">:</span>@&lt;host&gt;<span class="hljs-symbol">:&lt;port&gt;/&lt;url-path&gt;</span>
</code></pre><p><a target="_blank" href="https://tools.ietf.org/html/rfc1738">**RFC1738</a>**</p>
<pre><code>&lt;scheme&gt;<span class="hljs-regexp">//</span>&lt;user&gt;<span class="hljs-symbol">:&lt;password&gt;</span>@&lt;host&gt;<span class="hljs-symbol">:&lt;port&gt;/&lt;url-path&gt;</span>
</code></pre><p>Note, that in the updated <a target="_blank" href="https://tools.ietf.org/html/rfc3986">RFC3986</a>, using a password in the URL is deprecated — this will be important later on!</p>
<p><strong>A primer on URL encoding</strong></p>
<p>Web browsers request pages from web servers by using URLs. 
URLs can only be sent over the internet using the <a target="_blank" href="https://www.w3schools.com/charsets/ref_html_ascii.asp">ASCII character-set</a>, however, URLs often contain characters outside of this set, therefore the URL has to be encoded into a valid format. 
URL encoding replaces unsafe characters with a percentage sign (%) followed by two hexadecimal digits.</p>
<p>As an example, URLs cannot contain spaces.</p>
<blockquote>
<h1 id="therefore-a-space-in-a-url-is-encoded-to-20">Therefore a space in a URL is encoded to %20.</h1>
</blockquote>
<p>So the URL <strong>“www.appsflyer.com/hello everyone”</strong></p>
<p>would be encoded into <strong>www.appsflyer.com/hello%20everyone</strong></p>
<p>When the web server retrieves this url, they are then able to decode the URL and convert it back into <strong>“<a target="_blank" href="http://www.appsflyer.com/hello">www.appsflyer.com/hello</a> everyone”</strong></p>
<p>For reference of all the URL encodings, visit <a target="_blank" href="https://www.w3schools.com/tags/ref_urlencode.ASP">https://www.w3schools.com/tags/ref_urlencode.ASP</a></p>
<h2 id="urls-within-micro-services">URLs within micro-services</h2>
<p>There are many different methods you can use for inter-service communication, such as REST, gRPC, and messaging brokers such as Kafka or RabbitMQ. In this story, we’ll be focusing on microservice communication using HTTP REST.</p>
<p>Here we have a service that receives a URL with two parameters:</p>
<ul>
<li><p>‘site’:controls which other microservice the query will get sent to;</p>
</li>
<li><p>‘user’: identifies a user in the system;</p>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1620633472333/ZL9YJnNdd.png" alt="service which takes two parameters and builds a new URI" /><em>service which takes two parameters and builds a new URI</em></p>
<p>In this example we added some code that validates the user and creates a new url which gets sent to an internal micro-service. Validating a user from a url parameter that is controlled by the client is not a secure design practise, but this does happen in the real world. We’ve taken this idea as an example to help demonstrate why encoding URLs is so important.</p>
<p>Now in this case we did not explicitly write any code to carry out url decoding or encoding. However, the server engine when processing the request automatically decodes the parameters into the proper variables.
Let’s see the same example but with special characters:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1620633474431/aSvWjHC6i.png" alt="Parameters are encoded in browser and decoding in code" /><em>Parameters are encoded in browser and decoding in code</em></p>
<h2 id="url-tampering">Url Tampering</h2>
<p>In the above examples, the site parameter is not validated and there is no encoding applied. This allows us to tamper with the generated url and control the request.</p>
<p>In the below request, we added a %23(#) in order to convert the following characters in the url to be a fragment. Read more about this <a target="_blank" href="https://en.wikipedia.org/wiki/URI_fragment">here</a>.</p>
<p>In order to identify an issue with no access to the source code, or internal servers, we first attempt to fetch data from our external server. Once we see our external server receive a request, we can let the games begin!!</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1620633478647/WHBIlt_Ju.png" alt="Injected a # to break url building" /><em>Injected a # to break url building</em></p>
<p>The next step is to bypass authorization checks by manipulating the URL.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1620633481676/6yYMU1v2w.png" alt="Overridden second variable by injecting data into first parameter" /><em>Overridden second variable by injecting data into first parameter</em></p>
<p>In this case we are adding our payload to control all elements after https:// and finishing with a # sign which signals the request sender that this is a url fragment.</p>
<p>The result is that a request is sent with a different user to the one that was validated — bypassing the user validation check!</p>
<blockquote>
<p>Note that we couldn’t just change the user parameter because it is validated by our user validation function. We could assume also that the user parameter can come from our sso provider so it can’t be tampered with.</p>
</blockquote>
<h3 id="another-common-scenario">Another common scenario:</h3>
<p>In this example we have two dynamic query parameters — “key” &amp; “user” — which are controlled by the client. Note that the “user” parameter is validated properly.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1620633486569/3ey9ULhnO.png" alt /></p>
<p>With the same concept of parameter manipulation we can add data to the parameter which will inject new variables into requested url.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1620633489980/1Nn_acoHn.png" alt="Overriding the user variable in requested resource" /><em>Overriding the user variable in requested resource</em></p>
<h2 id="fixing-this">Fixing this</h2>
<p>Javascript has a feature called <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent">encodeURIComponent</a>, which allows us to safely put in a URI component into the URI without being afraid of users injecting content to break out of our parameter.</p>
<p>Other frameworks and languages have other solutions. You can lookup your language here <a target="_blank" href="https://rosettacode.org/wiki/URL_encoding">https://rosettacode.org/wiki/URL_encoding</a></p>
<p>Common feedback I receive from developers is that they will need to check with the receiving service that they decode it first. The answer is simple, in 99% of the cases the receiving service uses a common framework which automatically decodes their data. Of course full testing should be performed after doing some changes but it usually does not affect the application.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1620633492162/1zlEgPZYI.png" alt="Encoding made the key to be as requested with no injection possibilities" /><em>Encoding made the key to be as requested with no injection possibilities</em></p>
<h2 id="to-summarize">To summarize</h2>
<p>When passing data between microservices or other external services it is vital to verify that you are building the target url in a safe way.</p>
<p>Going down memory lane, in the early days of software development twenty years ago, we had a similar problem with SQL. Developers would build SQL queries without the knowledge and understanding that they can be injected with custom queries. Today, most developers are familiar with SQL Injection, but not with URL Injection.</p>
<p>Please share this knowledge with all of your developer friends. If this is something new to you or you already know of it, we would love to hear your feedback.</p>
<blockquote>
<p>As for security researchers, you can add a %23(#) or %26(&amp;) to your payloads, weird activity usually is a good sign.</p>
</blockquote>
]]></content:encoded></item><item><title><![CDATA[NGINX may be protecting your applications from traversal attacks without you even knowing]]></title><description><![CDATA[As a security team within a rapidly growing company, we encounter lots of different types of vulnerabilities. We have numerous in-house development teams, all running full speed to build new features into their products, which inevitably also leads t...]]></description><link>https://rotem-bar.com/nginx-traversal</link><guid isPermaLink="true">https://rotem-bar.com/nginx-traversal</guid><dc:creator><![CDATA[Rotem Bar]]></dc:creator><pubDate>Thu, 24 Sep 2020 08:59:08 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1620633463757/qK2phSC5n.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>As a security team within a rapidly growing company, we encounter lots of different types of vulnerabilities. We have numerous in-house development teams, all running full speed to build new features into their products, which inevitably also leads to the introduction of security bugs.</p>
<p>Our mission is to prevent, detect and remediate all security issues within our environment. Our goal is to enable rather than block our developers’ work. In order to achieve this, our strategy has been to share our knowledge through building new processes and systems that help our developers release their latest feature safely without introducing vulnerabilities into our production systems.</p>
<p>This is a story about a traversal vulnerability, how we handled it and why it can also impact your organization.</p>
<h3 id="background"><strong>BACKGROUND:</strong></h3>
<p>We found a <a target="_blank" href="https://owasp.org/www-community/attacks/Path_Traversal">Traversal Vulnerability</a> in one of our application services through our in-house scanner Jirachi (more on this in another post). Although it was a simple traversal attack and seemed easy to exploit, for some reason when testing through our staging site our Proof Of Concept kept failing.</p>
<p>We were able to exploit the directory traversal vulnerability when communicating directly with the service, and thought that this should be an easy Jira ticket to write up. However, when we went to write the full end-to-end POC, the exploit kept failing. We looked at the only other component that had changed between the two tests, and we found that the service was behind an AWS Application Load Balancer (ALB). However, there were no rules, no Web Application Firewall (WAF), nothing — so we couldn’t figure out why the load balancer was preventing our POC.</p>
<p>Investigating the AWS ALB further, we found an HTTP 400 error response that had similarities with an error response in <a target="_blank" href="https://www.nginx.com/">NGINX</a> that we found in a git commit. We quickly downloaded the latest version of NGINX, and digging through the commit history, we found that there was a configuration option called <em>merge_slashes</em>. When we set <em>merge_slashes</em> to “off”, we saw the same behaviour as we did with the ALB. We came to the realisation that the AWS ALB url parsing shares similar functionality as NGINX. Furthermore it was this functionality that was responsible for sending the http 400 error response and not allowing the request to reach the vulnerable application.</p>
<p>We couldn’t give up there though. We had to find a way to get our request to the vulnerable application!</p>
<h2 id="technical-poc-traversal-attack-through-nginx-url-parser">Technical POC: Traversal Attack through NGINX URL parser</h2>
<p>To demonstrate how we can get the malicious request through the NGINX url parser, we put together a sample application.</p>
<p>As you can see below, We created a sample web server code which has a Local File Inclusion vulnerability</p>
<pre><code><span class="hljs-keyword">const</span> express = <span class="hljs-built_in">require</span>(<span class="hljs-string">'express'</span>);
<span class="hljs-keyword">const</span> app = express();
<span class="hljs-keyword">const</span> port = <span class="hljs-number">80</span>;
<span class="hljs-keyword">const</span> fs = <span class="hljs-built_in">require</span>(<span class="hljs-string">'fs'</span>);


app.get(<span class="hljs-string">'*'</span>, <span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> {
    <span class="hljs-keyword">const</span> data = fs.readFileSync(<span class="hljs-string">'secure/'</span> + req.url)
    res.send(data);
})

app.listen(port, <span class="hljs-function">() =&gt;</span> {
    ***<span class="hljs-built_in">console</span>***.log(<span class="hljs-string">`Vulnerable App listening at http://localhost:<span class="hljs-subst">${port}</span>`</span>)
})
</code></pre><p>The server accepts a GET request. The user-supplied url is concatenated with the ‘secure’ string and that file is then sent back to the user.</p>
<p>As an example sending a request to <a target="_blank" href="http://server/1.txt">http://server/1.txt</a> will cause the server to send back a file from &lt;CurrentWorkingDirectory&gt;/secure/1.txt</p>
<p>In order to demonstrate this, we send a GET request directly to the server and in the response we get the content of file 1.txt.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1620633436421/iUOdCiIcI.png" alt="Vulnerable application" /><em>Vulnerable application</em></p>
<p>In order to exploit the traversal vulnerability in this app, we can request a file from a directory one level up by using the ‘../’ notation. Here we request the index.js file directly from the server .</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1620633438497/o52gxk6wK.png" alt="POC —" /><em>POC —</em></p>
<p>Carrying out the same traversal attack through AWS ALB, we received a 400 bad request</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1620633440354/NVThCRNua.png" alt /></p>
<p>However, after some research we found that we can get our malicious request through the url parser by using multiple slashes (‘/’).</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1620633442415/dAPWrS-Lp.png" alt /></p>
<p>In order to demonstrate this point further, the below image shows an attempt at retrieving the /etc/passwd file through an AWS ALB. Once again, we get a 400 bad request.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1620633444781/ongLYBwKP.png" alt /></p>
<p>As before, we’re able to reach the vulnerable application by appending more slashes (‘/’).</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1620633447321/Oef52Grf6.png" alt /></p>
<h2 id="root-cause-analysis">Root Cause Analysis</h2>
<h3 id="how-did-we-know-aws-alb-shares-similar-functionality-in-url-parsing-as-nginx"><strong>How did we know AWS ALB shares similar functionality in url parsing as NGINX?</strong></h3>
<p>When the requests were blocked we saw a certain pattern.</p>
<p>The 400 bad request response from the AWS ALB above had a distinctive html signature:</p>
<pre><code><span class="hljs-tag">&lt;<span class="hljs-name">body</span> <span class="hljs-attr">bgcolor</span>=<span class="hljs-string">”white”</span>&gt;</span> …
</code></pre><p>After simple Google search and digging in GitHub we found that this signature is used by NGINX.</p>
<p>Specifically, we’re able to find which commit and version this error signature was removed in.</p>
<p><a target="_blank" href="https://github.com/nginx/nginx/commit/8117b3f5a06b68afb292ddd19bf6ee6000707232#diff-05d6b8ae21d192f78b349319edaeb9bf">https://github.com/NGINX/NGINX/commit/8117b3f5a06b68afb292ddd19bf6ee6000707232#diff-05d6b8ae21d192f78b349319edaeb9bf</a></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1620633449413/1_VNnlhMs.png" alt /></p>
<p><strong>Fun fact:</strong></p>
<blockquote>
<p>body bgcolor=white was pretty common in the past as IE rendered pages by default in light gray, other browsers let the user select a default background such as black and there was large inconsistency between browsers. Putting bgcolor=white ensured that all browsers display the background as white.</p>
</blockquote>
<h3 id="how-did-we-determine-that-mergeslashes-is-off"><strong>How did we determine that merge_slashes is ‘off’:</strong></h3>
<p>Within the NGINX documentation, we are able to see that the merge_slashes default value is “On”. Therefore two or more ‘/’ characters will be normalized into one ‘/’ character.</p>
<p><a target="_blank" href="http://nginx.org/en/docs/http/ngx_http_core_module.html#merge_slashes">http://NGINX.org/en/docs/http/ngx_http_core_module.html#merge_slashes</a></p>
<p>Enables or disables compression of two or more adjacent slashes in a URI into a single slash.</p>
<pre><code>Syntax: merge_slashes <span class="hljs-keyword">on</span> | <span class="hljs-keyword">off</span>;
<span class="hljs-keyword">Default</span>: merge_slashes <span class="hljs-keyword">on</span>;
Context: http, <span class="hljs-keyword">server</span>
</code></pre><p>When the <em>merge_slashes</em> configuration is turned on, using multiple slashes ‘///’ did not allow us to exploit that vulnerability successfully.</p>
<h3 id="trying-out-our-bypass-on-latest-version-of-nginx"><strong>Trying out our bypass on latest version of NGINX:</strong></h3>
<p>The following shows the POC carried out on the latest stable version of NGINX (v1.18.0) with <em>merge_slashes</em> ‘off’.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1620633452016/tdd_2tzza.png" alt /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1620633453768/p3HQCpZcH.png" alt /></p>
<h3 id="identification-of-nginx-issue"><strong>Identification of NGINX issue:</strong></h3>
<p>In order to better understand how NGINX handles the url, we built a program to test the parsing function within the ngx_http_parse file:</p>
<pre><code>ngx_http_parse_complex_uri(<span class="hljs-keyword">ngx_http_request_t</span> *r, <span class="hljs-keyword">ngx_uint_t</span> merge_slashes)
</code></pre><p>Within this function, the handling of state == sw_dot_dot at <a target="_blank" href="https://github.com/nginx/nginx/blob/master/src/http/ngx_http_parse.c#L1581">https://github.com/NGINX/NGINX/blob/master/src/http/ngx_http_parse.c#L1581</a> is what our tests focus on.</p>
<p>This shows the code written for testing the parsing function.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1620633456618/p4ntzGQMi.png" alt /></p>
<p>Here we can see when we run the test with a regular traversal attack, we get an error and return code 11.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1620633458682/C7HA61ESX.png" alt /></p>
<p>Here we can see that when we run the test with extra slashes, we return 0.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1620633460293/k8Lg4wVMB.png" alt /></p>
<h2 id="what-is-the-impact">What is the Impact?</h2>
<h3 id="the-impact-here-is-complicated"><strong>The impact here is complicated</strong></h3>
<p>Looking at CVE’s we saw about 4000 known directory traversal CVE’s dating from 1999 to 2020. Directory Traversal attacks are here to stay!</p>
<p>Furthermore, companies testing themselves behind any ALB or NGINX solution configured with <em>merge_slashes</em> ‘off’ will probably not find this bug so easily. However, more knowledgable or dedicated attacks would know how to get their malicious request through the url parsing mechanism.</p>
<p>In order to get a better understanding of how wide-spread this issue is, we ran a search on github for <em>merge_slashes</em> ‘off’;. There are 549 Open Source Projects that use this configuration and unknowingly may be blocking malicious requests to applications that are vulnerable.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1620633462130/d2FI1xp-a.png" alt /></p>
<h3 id="could-this-blocking-behaviour-be-changed"><strong>Could this blocking behaviour be changed?</strong></h3>
<p>Not really as we see it.</p>
<p>If traversal is blocked within NGINX, then applications relying on “safe traversal as a feature” will start failing. This is critical for some businesses and therefore, we don’t see this behaviour being changed.</p>
<p><strong>Is this a vulnerability?</strong></p>
<p>NGINX as itself is not a protection solution and AWS ALB is not intended to protect your application. If you are looking for a protection solution, consider using a WAF.</p>
<p><strong>What do we recommend?</strong></p>
<p>If possible, run your tests on the application directly without any load balancers in the middle. If you must test through load balancers, you should ensure that your testing takes into account this behaviour so you don’t miss any possible vulnerabilities.</p>
<h2 id="summary">Summary</h2>
<p>This exercise showed us why it is important to always look around for additional attack vectors, never rely on one protection mechanism and always continue ramping up our security methods.</p>
<p>We do not consider this a vulnerability within NGINX nor AWS Application Load Balancers. By taking this information public, we are hoping that we are able to make organizations more aware of the behaviour displayed in NGINX and ALB and allow them to better test their application to reduce their risks</p>
<p>Stay tuned for more information about our security efforts. In the following weeks, we will be releasing more security tools we built in house and would love to share with the community.</p>
<p><strong>Want to be part of our security adventures? We’re hiring! Contact us at <a target="_blank" href="mailto:security@appsflyer.com">security@appsflyer.com</a></strong></p>
<h3 id="tldr"><strong>TL;DR</strong></h3>
<blockquote>
<h1 id="add-forward-slashes-at-the-beginning-of-your-requests-when-testing-directory-traversal-attacks-through-load-balancers"><em>Add forward slashes at the beginning of your requests when testing directory traversal attacks through load balancers.</em></h1>
</blockquote>
]]></content:encoded></item></channel></rss>