Saturday, March 2, 2019

Tracking authentication information with JPCert's Logon Tracker - Usage

This post is a continuation from the previous post. First we load LogonTracer

securitynik@securitynik.local:~/LogonTracer$ python3 logontracer.py --run --port 5678 --user securitynik --password 'Testing1' --server 192.168.0.4

These different arguments are:
    --run: Launch web server
    --port: Port number where the web server operates - In my case this is "5678"
    --user: Neo4j username - In my case this user is "securitynik"
    --password: Neo4j password - In my case this is "Testing1"
    --server: Address where the web server operates - In my case this is "192.168.0.4"

This produced the following at the console:
securitynik@securitynik.local:~/LogonTracer$ python3 logontracer.py --run --port 5678 --user securitynik --password 'Testing1' --server 192.168.0.4
[*] Script start. 2019/02/21 20:12:11
 * Serving Flask app "logontracer" (lazy loading)
 * Environment: production
   WARNING: Do not use the development server in a production environment.
   Use a production WSGI server instead.
 * Debug mode: off
 * Running on http://0.0.0.0:5678/ (Press CTRL+C to quit)

Now that the server is running, let's now access it using our browser.






























Using the "Upload Event Log" at the bottom left hand side of the screen, we are able to provide our Security Event log. We can upload this in either of two formats. Either the raw .evtx file or we can use the Windows Event Viewer and export these logs as XML. It is recommended that you convert your .EVTX file to .XML by exporting the security events from the Windows Event Viewer or some other tool.














While I showed this screen, I actually struggled to get my events in this way. Whenever, I clicked on the "log" screen the log says there was a problem connecting to the database.


As a result, I opened the "Event Viewer" and selected "Save All Events As". Here I provided my filename as "SecurityNik_Security-Events.xml" and specified the type as "XML". Note also rather than selecting all events, you can instead filter the event log for event IDs 4624, 4625, 4768, 4769 and 4776 and then save the filtered file.
securitynik@securitynik:~/LogonTracer$ python3 ./logontracer.py --user securitynik --password Testing1 --xml upload/SecurityNik_Security-events.xml --timezone -5 --server 192.168.0.4
[*] Script start. 2019/02/23 17:04:12
[*] Time zone is -5.
[*] Last record number is 164.
[*] Start parsing the EVTX file.
[*] Parse the EVTX file upload/SecurityNik_Security-events.xml.
[*] Now loading 100 records.
[*] Load finished.
[*] Total Event log is 164.
[*] Calculate ChangeFinder.
[*] Calculate Hidden Markov Model.
/home/securitynik/.local/lib/python3.6/site-packages/hmmlearn/hmm.py:412: RuntimeWarning: divide by zero encountered in log
  return np.log(self.emissionprob_)[:, np.concatenate(X)].T
[*] Calculate PageRank.
[*] Creating a graph data.
[*] Creation of a graph data finished.
[*] Script end. 2019/02/23 17:04:33


Important to note that in order for this to work properly, you need to ensure your security policy is configured to capture event IDs: 4624, 4625, 4768, 4769 and 4776.

Once the log has been imported you can then login to your portal and check your graphs. In my case we see:

























Please note that there is a sample "Security.evtx" file in the "samples" folder of LogonTracer.

I find this to be a very interesting tool you should try it.


Reference:
https://github.com/JPCERTCC/LogonTracer/wiki/How-to-Use

Tracking authentication information with JPCert's Logon Tracker - The Setup

This is a new tool I recently learned about as a result of the update to the SANS SEC504 - one of the classes I teach for the SANS institute. As I'm interested in this not only from a teaching perspective but more so a learning perspective and wanting to use it in my own environment, I decided to look into this via a blog post.

According to the description from the tool's GitHub page "LogonTracer is a tool to investigate malicious logon by visualizing and analyzing Windows Active Directory event logs. This tool associates a host name (or an IP address) and account name found in logon-related events and displays it as a graph. This way, it is possible to see in which account login attempt occurs and which host is used.
This tool can visualize the following event id related to Windows logon based on this research.

    4624: Successful logon
    4625: Logon failure
    4768: Kerberos Authentication (TGT Request)
    4769: Kerberos Service Ticket (ST Request)
    4776: NTLM Authentication
    4672: Assign special privileges"

For this install, I'm using Ubuntu 18 as shown below:
securitynik@securitynik.local:~# lsb_release --all
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 18.04.1 LTS
Release:        18.04
Codename:       bionic

Let's first install Java 8
sudo add-apt-repository ppa:webupd8team/java
sudo apt-get update
sudo apt-get install oracle-java8-installer

Install neo4j Community Edition by first adding its repository:
wget -O - https://debian.neo4j.org/neotechnology.gpg.key | sudo apt-key add -
echo 'deb https://debian.neo4j.org/repo stable/' | sudo tee /etc/apt/sources.list.d/neo4j.list
sudo apt-get update

Let's now install neo4j:
sudo apt-get install neo4j

Now that neo4j is installed, let's make two quick configuration changes. Locate the following two lines:
#dbms.connector.bolt.listen_address=:7687
#dbms.connector.https.listen_address=192.168.0.4:7473

For me I specify the interface I would like neo4j to listen on and thus I made the following change:
dbms.connector.bolt.listen_address=0.0.0.0:7687
dbms.connector.https.listen_address=192.168.0.4:7473

Note above, I also removed the comment "#" from these two lines

Next step ... restart neo4j using systemctl

systemctl restart neo4j

If we next do a "netstat -nltp", we see the host is listening on those two ports above.
securitynik@securitynik.local:/tmp# netstat -nltp

Active Internet connections (only servers)

Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name

....
tcp6       0      0 :::7687                 :::*                    LISTEN      24537/java
tcp6       0      0 192.168.0.4:7473        :::*                    LISTEN      24537/java
tcp6       0      0 192.168.0.4:7474        :::*                    LISTEN      24537/java
....

Next up, connect to the server at http://192.168.0.4:7474 and login to the UI for neo4j.











Using the default credentials of username "neo4j" and password "neo4j", I was able to authenticate and then asked to change my password. I also added the user "securitynik" with password "Testing1". Once my password was changed, the next step was to clone LogonTracer
git clone https://github.com/JPCERTCC/LogonTracer.git


Once finished cloning the following was executed

Taking a loo at the requirements file before we install, we see:

securitynik@securitynik.local:~$ cat LogonTracer/requirements.txt
numpy
py2neo==3.1.2
python-evtx
lxml
changefinder
flask
hmmlearn
scikit-learn==0.19.2

Now that we know what it is trying to install, let's continue
pip3 install -r LogonTracer/requirements.txt

Ensure you have "python3-pip" installed. If not, run

apt-get install python3-pip

If all went well, I guess I will see you in the next post.

Reference:
https://github.com/JPCERTCC/LogonTracer
https://github.com/JPCERTCC/LogonTracer/wiki/for-linux
https://blogs.jpcert.or.jp/en/2017/11/visualise-event-logs-to-identify-compromised-accounts---logontracer-.html
https://gist.github.com/nepobef/0f378ded038b35324e0106fcff79303c
http://debian.neo4j.org/
https://www.first.org/resources/papers/conf2016/FIRST-2016-105.pdf
https://neo4j.com/docs/operations-manual/current/installation/linux/debian/?_ga=2.249168388.2041192375.1507250087-893468657.1507250087
https://neo4j.com/docs/operations-manual/current/installation/linux/debian/
http://debian.neo4j.org/?_ga=2.45025828.1204700703.1550717522-969713451.1550717522
https://neo4j.com/docs/operations-manual/current/installation/linux/tarball/

Understanding password cracking - the basics from a Linux perspective - The Demo

In the previous post, we looked at understanding the basics of password cracking. While in that post we developed some code, this post is just a quick look to see what the output looks like once executed. Note, to make sense of this post, you are better off starting in this previous post if you did not look at it before.

We execute the program by giving it one argument which is the password list (dictionary). This can be any list but I'm using the one I put together in the previous post.

root@securitynik:~# ./passwordCraker.py SecurityNik.lst

Once executed, here is what we have

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
root@securitynik:~# ./passwordCraker.py SecurityNik.lst
passwordCrakcer.py
Author: Nik Alleyne
Author Blog: www.securitynik.com
[*] we will be looking for a match for password '$6$uPdhX/Zf$Kp.rcb4AWwtx0EJq235tzthWXdIEoJnhZjOHbil3od1AyMf3t8Yi6dAPlhbHVG9SLx5VSIPrXTZB8ywpoOJgi.'
[*] Starting password cracking ...
[*] Loading password file 'SecurityNik.lst' into memory ...
[-] Trying password:Passw0rd
[-] Trying password:GuessMe
[-] Trying password:admin
[-] Trying password:root
[-] Trying password:1234567890
[-] Trying password:Password1
[-] Trying password:ftp
[-] Trying password:root
[-] Trying password:SecurityNik
[+] MATCH FOUND! Password is:toor
[+] Password $6$uPdhX/Zf$Kp.rcb4AWwtx0EJq235tzthWXdIEoJnhZjOHbil3od1AyMf3t8Yi6dAPlhbHVG9SLx5VSIPrXTZB8ywpoOJgi.
 MATCHES
 Password $6$uPdhX/Zf$Kp.rcb4AWwtx0EJq235tzthWXdIEoJnhZjOHbil3od1AyMf3t8Yi6dAPlhbHVG9SLx5VSIPrXTZB8ywpoOJgi.

From above, we see we tried a number of different passwords but ultimately found one that matched.

Remember, see the previous post to add more context to this one.

Understanding password cracking - the basics from a Linux perspective

This post is focused on teaching you the basics of password cracking, leveraging a Linux "/etc/shadow" file for our demo.

First let us take a look at a sample entry for from the /etc/shadow

root@securitnik:~# cat /etc/shadow | grep root
root:$6$uPdhX/Zf$Kp.rcb4AWwtx0EJq235tzthWXdIEoJnhZjOHbil3od1AyMf3t8Yi6dAPlhbHVG9SLx5VSIPrXTZB8ywpoOJgi.:17564:0:99999:7:::

Each entry above, separated by the ":" represents a different field. For us we will focus on the first two, with the values "root" and "$6$uPdhX/Zf$Kp.rcb4AWwtx0EJq235tzthWXdIEoJnhZjOHbil3od1AyMf3t8Yi6dAPlhbHVG9SLx5VSIPrXTZB8ywpoOJgi." The first entry represents the username which in this case is "root" and the second the password representation.

From the second field - the password representation - the "6" between the first two "$" represents the encryption algorithm being used. This is further confirmed by looking at our "/etc/login.defs" file with a focus on the "ENCRYPT_METHOD". In our file below, we see "ENCRYPT_METHOD SHA512". This tells us that the system is using SHA512.


root@securitynik:~# cat /etc/login.defs | grep "ENCRYPT_METHOD"
# This variable is deprecated. You should use ENCRYPT_METHOD.
ENCRYPT_METHOD SHA512
# Only used if ENCRYPT_METHOD is set to SHA256 or SHA512.

The second value we need to focus on is the salt, which is in this example "uPdhX/Zf" found between the second and third "$". In this case we are using an 8 byte salt. Consider the salt a random value that is used to make the password stronger. The bigger the salt, the stronger the password should be. For example, an 8 byte salt should make the password harder to crack than a 2 byte crack.

From above, we know the hashing algorithm is SHA512 and we have the salt. The only thing missing now is a string which when we put them all together, we can recompute the password representation. Specifically, this is what we need:
HASH ALGORITHM + SALT + STRING PASSWORD = PASSWORD REPRESENTATION

Here is what we have:
SHA512 (6) +  uPdhX/Zf + ???? = PASSWORD REPRESENTATION

Let's load up python3.7 and leverage it's "crypt" module to help us out here.

root@securitynik:~# python3.7
Python 3.7.2 (default, Jan  3 2019, 02:55:40)
[GCC 8.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import crypt
>>> crypt.crypt("Passw0rd", salt="$6$uPdhX/Zf$")
'$6$uPdhX/Zf$FtB3X5oeGRWXXg92TjXp/9yuy21iBYTa/YMKrCIUtV4rDBd9zK5tZ0mr0sefszzdz0NUbM670CYJw.g1DFkJu.'
>>> crypt.crypt("GuessMe", salt="$6$uPdhX/Zf$")
'$6$uPdhX/Zf$GhShpI0WBBLbDVRkGrOjcnmseqzlduCrXdX0prmlMIMtF/1XlgBKtl4ptpyxJDzvqCQCHeK5iNW1tvEETGmYz0'
>>> 


From above we tried the first password as "Passw0rd" and the second password "GuessMe". However, as you can see above, none of these combinations produced a value that matched our original from the "/etc/shadow" file which is "$6$uPdhX/Zf$Kp.rcb4AWwtx0EJq235tzthWXdIEoJnhZjOHbil3od1AyMf3t8Yi6dAPlhbHVG9SLx5VSIPrXTZB8ywpoOJgi."

At this point, we can continue trying this process entering each password manually until we find a match or we can simply automate this process with a dictionary. Let's choose the latter.

First we need a dictionary. You can find many dictionaries online but let's just create one of our own. To do, let's add 10 words to a file called "SecurityNik.lst".

root@securitynik:~# echo "Passw0rd" >> SecurityNik.lst
root@securitynik:~# echo "GuessMe" >> SecurityNik.lst
root@securitynik:~# echo "admin" >> SecurityNik.lst
root@securitynik:~# echo "root" >> SecurityNik.lst
root@securitynik:~# echo "1234567890" >> SecurityNik.lst
root@securitynik:~# echo "Password1" >> SecurityNik.lst
root@securitynik:~# echo "ftp" >> SecurityNik.lst
root@securitynik:~# echo "root" >> SecurityNik.lst
root@securitynik:~# echo "SecurityNik" >> SecurityNik.lst
root@securitynik:~# echo "toor" >> SecurityNik.lst

When we perform a "cat" on the file, we see:

root@securitynik:~# cat SecurityNik.lst
Passw0rd
GuessMe
admin
root
1234567890
Password1
ftp
root
SecurityNik
toor


Let's now code up our password cracker:


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#!/usr/bin/env python3.7

# passwordCracker.py
# Author: Nik alleyne
# Author Blog: www.securitynik.com
# Date: 2019-02-15

import crypt
from subprocess import call
from sys import exit, argv

# This function handles usage information
def usage():
    print("password_file: A file consisting of passwords you would like to use.")
    print("./passwordCraker.py <password_file>")
    exit(0)


# This function checks to see if the username is found within the file
def passwordCracker(passwordFile):
    # Store the password we are trying to crack as a variable
    passwordToCrack = "$6$uPdhX/Zf$Kp.rcb4AWwtx0EJq235tzthWXdIEoJnhZjOHbil3od1AyMf3t8Yi6dAPlhbHVG9SLx5VSIPrXTZB8ywpoOJgi."
    print("[*] we will be looking for a match for password '{}'".format(passwordToCrack));
    print("[*] Starting password cracking ...")
    print("[*] Loading password file '{}' into memory ...".format(passwordFile))
    
    # Load the file entered on the command line into memory
    passwordFile = open(passwordFile, 'r')

    # Store salt as variable
    passwordSalt = "$6$uPdhX/Zf$"
    passwordFound = False;

    # Read the file line by line
    for line in passwordFile.readlines():
        passwordFound = crypt.crypt(line.strip(),salt=passwordSalt)
        if ( passwordFound == passwordToCrack.strip() ):
            print("[+] MATCH FOUND! Password is:{}".format(line).strip())
            print("[+] Password {} \n MATCHES \n Password {} ".format(passwordToCrack,passwordFound))
            exit(0)
        else:
            print("[-] Trying password:{}".format(line).strip())


if __name__ == '__main__':
    call("clear")
    print("passwordCrakcer.py")
    print("Author: Nik Alleyne")
    print("Author Blog: www.securitynik.com")

    # Check the number of arguments being entered on the command line
    if ( len(argv) != 2 ):
        usage()
        
    # calls the passwordCracker function
    passwordCracker(argv[1])
   

The above code, helps to give us a better understanding of how password cracking works.


Now while we went through this process manually and writing our own code, the reality is, there are tools which can make this process easier for you. More specifically the three that I can immediately recommend are:
1. John the Ripper
2. Hashcat
3. Cain and Abel

While the above tools are helpful, it is important that you understand how some of these tools works and thus I hope this post contributed to making that learning process easier.


References:
https://en.wikipedia.org/wiki/Salt_(cryptography)
https://docs.python.org/3/library/crypt.html
https://docs.python.org/3/tutorial/inputoutput.html#reading-and-writing-files
Python Cheat Sheet Updated for 2022 - from Libraries to Internet Modules (pcwdld.com)