PHP JWT не проверен, кроме PHP

Я использую PHP Firebase JWT для реализации JWT в своем PHP-приложении. Вот мой код

    $payload = [
        'iss' => 'http://test.com',  
        'aud' => 'http://test.com',  
        'iat' => time(),  // Issued at
        'exp' => time() + 3600,  // Expiration (1 hour)
        'data' => [
            'user_id' => $user['id'],
            'email' => $user['email'],
            'role' => $user['role'],
            'is_admin' => $user['isadmin']
        ]
    ];
    $jwt = JWT::encode($payload, $key, 'HS256', $key_file);

После кодирования генерирует токен eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiIsImtpZCI6Ii92YXIvd3d3L215a2V5LmtleSJ9.eyJpc3MiOiJodHRwOi8vdGVzdC5jb20iLCJhdWQiOiJodHRwOi8vdGVzdC5jb20iLCJpYXQiOjE3MjM5NzQ5OTMsImV4cCI6MTcyMzk3ODU5MywiZGF0YSI6eyJ1c2VyX2lkIjoxLCJlbWFpbCI6ImFiYyIsInJvbGUiOiJ1c2VyIiwiaXNfYWRtaW4iOjB9fQ.uC13pivSZGnPr6i8zmPCfEFMsykWR5miIK8t0-DCnug это нормально

Содержимое ключевого файла: hellohellohellohellohellohellohe Я использовал сайт https://jwt.io/ для тестирования своего токена и несколько других сайтов https://dinochiesa.github.io/jwt/

Теперь я хочу, чтобы обычный пользователь сгенерировал токен через любой веб-сайт, изменив ключевой параметр kid и используя любой веб-сайт в Интернете, чтобы его можно было использовать на сайте (демонстрируя уязвимость).

Я столкнулся с двумя проблемами; если я попытаюсь проверить токен с помощью вышеуказанного ключа на любом из веб-сайтов с файлом ключа, он скажет, что он не может сопоставиться или проверить; в чем проблема? Работает ли JWT на основе PHP Firebase по-другому? Я тоже проверил это Подпись JWT не проверяется в PHP

🤔 А знаете ли вы, что...
С PHP можно создавать динамические веб-сайты и веб-приложения.


50
1

Ответ:

Решено

Поскольку вы читаете ключ из файла, а не тестируете его с жестко закодированным значением, трудно увидеть, есть ли в нем дополнительные символы, например, разрывы строк.

Если вы сгенерируете хэш вручную, используя то, что, по вашему мнению, является вашим ключом, вы увидите другую подпись:

$msg = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiIsImtpZCI6Ii92YXIvd3d3L215a2V5LmtleSJ9.eyJpc3MiOiJodHRwOi8vdGVzdC5jb20iLCJhdWQiOiJodHRwOi8vdGVzdC5jb20iLCJpYXQiOjE3MjM5NzQ5OTMsImV4cCI6MTcyMzk3ODU5MywiZGF0YSI6eyJ1c2VyX2lkIjoxLCJlbWFpbCI6ImFiYyIsInJvbGUiOiJ1c2VyIiwiaXNfYWRtaW4iOjB9fQ';
$key = 'hellohellohellohellohellohellohe';
$algorithm = 'SHA256';

$signature = hash_hmac($algorithm, $msg, $key, true);
echo base64_encode($signature);

#=> zBeba1d7bk/OhMeo5P/Aw1aO2v4JxW+8QXGJsCx1AWI=

Но если вы добавите одну новую строку в конце, вы увидите подпись в образце JWT (кроме немного другого варианта кодировки BASE64 с «-» вместо «+»):

$msg = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiIsImtpZCI6Ii92YXIvd3d3L215a2V5LmtleSJ9.eyJpc3MiOiJodHRwOi8vdGVzdC5jb20iLCJhdWQiOiJodHRwOi8vdGVzdC5jb20iLCJpYXQiOjE3MjM5NzQ5OTMsImV4cCI6MTcyMzk3ODU5MywiZGF0YSI6eyJ1c2VyX2lkIjoxLCJlbWFpbCI6ImFiYyIsInJvbGUiOiJ1c2VyIiwiaXNfYWRtaW4iOjB9fQ';
$key = "hellohellohellohellohellohellohe\n";
$algorithm = 'SHA256';

$signature = hash_hmac($algorithm, $msg, $key, true);
echo base64_encode($signature);

#=> uC13pivSZGnPr6i8zmPCfEFMsykWR5miIK8t0+DCnug=

Вы могли бы провести тот же эксперимент непосредственно с функцией JWT::encode, но у меня нет под рукой среды, в которой я мог бы установить библиотеку.