Function name is decode but it actually verifies signature: _decode_jwt_from_request in flask_jwt_extended lib
Trong 1 lần pentest web app (whitebox), khi kiểm tra phần xác thực của ứng dụng thì mình thấy dev dùng hàm _decode_jwt_from_request, tuy nhiên khi sửa bearer token thì ứng dụng báo Signature verification failed. Mình có đọc đi đọc lại code trong project được cấp thì không thấy chỗ nào verify signature, không có chỗ nào trả về chuỗi "Signarute verification failed".
Mình cũng nhắn tin hỏi dev nhưng dev cũng không rõ luôn 😁, họ chỉ biết nó có verify signature trong hàm này 👌
Mình mất 2 ngày ngồi tìm hiểu + viết 1 project demo + debug mới tìm ra được chỗ verify 😋
Source code demo: https://github.com/doanhnn/debug-decode_jwt_from_request
Endpoint / sử dụng hàm authen trong AuthenService để xác thực
Vào kiểm tra trong hàm authen này thì có gọi đến decode_jwt()
Trong hàm decode_jwt() có sử dụng hàm _decode_jwt_from_request, hàm này sẽ tìm token ở request header nên giá trị biến locations bằng headers.
Để sử dụng hàm này cần phải import lib JWTManager và config một số biến như JWT_ALGORITHM, JWT_PUBLIC_KEY, JWT_DECODE_AUDIENCE, JWT_IDENTITY_CLAIM...
Tham khảo thêm https://darksun-flask-jwt-extended.readthedocs.io/en/latest/options/
Hàm _decode_jwt_from_request này gọi đến hàm decode_token trong file utils.py
Trong file utils, hàm này khởi tạo object jwt_manager với các tham số cấu hình đã config trước đó
Trong hàm _decode_jwt_from_config (trước đó là hàm _decode_jwt_from_request) sẽ decode token để lấy các thông tin như headers, claims chưa được verify (verify_signature = False), kết hợp với thông tin trong config để chuẩn bị các input đầu vào và truyền vào hàm _decode_jwt().
Đến đây thì hàm _decode_jwt gọi đến hàm decode trong lib PyJWT chuẩn của python
Hàm decode này gọi tiếp đến hàm decode_complete()
Sau kha khá lần gọi hàm thì mình mới đến được chỗ cần đến 😄. Biến options hiện tại đang có giá trị là {"verify_aud": True} vì trong config ta có set biến JWT_DECODE_AUDIENCE trong config, code sẽ chạy đến dòng 76 và biến verify_signrature bằng True (nếu trong options đã có key verify_signature thì việc setdefault không có ý nghĩa, nghĩa là trong trường hợp ta set trực tiếp verify_signature bằng False khi truyền vào hàm jwt.decode thì ứng dụng sẽ không verify signature, trong TH còn lại, ứng dụng mặc định sẽ verify signature)
Tiếp theo sẽ đến hàm _verify_signature 😍
Và đây là response trả về khi signature invalid
Các anh dev chỉ check nếu response này trả về thì là báo token invalid, dù không hiểu rõ nhưng vẫn chạy đúng 😁Mình bổ sung thêm 1 ít nữa, nếu lúc chạy mà bị báo KeyError exception "Algorithm not supported" thì là do đang thiếu lib crypto.
Biến _algorithms là giá trị trả về từ hàm get_default_algorithms()
Nếu import lib cryptography thì biến has_crypto (dòng 80 ảnh trên) mới có giá trị true, các algorithm khác mới được add vào biến _algorithms
Khi chưa cài lib cryptography biến _algorithms chỉ có hỗ trợ 4 algorithms
Sau khi bổ sung thêm lib cryptography vào, trong biến _algorithms đã hỗ trợ nhiều algorithm hơn và không báo lỗi nữa (python3 -m pip install cryptography)
Done.
#justforcurious










Nhận xét
Đăng nhận xét