| Titre | Lybbn Django-Vue-Lyadmin 6dcf930833d76d51780e12e024254a431e653f69 Hard-coded Cryptographic Key |
|---|
| Description | Django-Vue-Lyadmin is a Django 4.x + Vue3 administration and management system. Its backend
ships a hard-coded Django SECRET_KEY and does not configure a separate JWT signing key, so
djangorestframework-simplejwt falls back to SECRET_KEY as the HMAC key used to sign and verify
access tokens. That value is a literal committed to the public repository and is therefore
identical in every clone. In addition, the initialisation SQL shipped with the repository
(backend/lyadmin_db.sql) seeds the superadmin row with a fixed UUID primary key, so a forged
token does not even require the attacker to guess an identifier.
Affected component: backend/application/settings.py
revision: commit 6dcf930833d76d51780e12e024254a431e653f69 (master, 2026-09-13)
line 26: from config import *
line 32: SECRET_KEY = 'django-insecure-n=x1q3sl^3va9tb&ty$p1b+kob@eb%wh0bn&8yj&!bp05201314'
line 134: AUTH_USER_MODEL = 'mysystem.Users'
lines 399-400: DEFAULT_AUTHENTICATION_CLASSES uses the stock
rest_framework_simplejwt.authentication.JWTAuthentication
lines 424-431: the SIMPLE_JWT mapping, which contains no SIGNING_KEY entry
Because SIMPLE_JWT omits SIGNING_KEY and simplejwt's own default is
SIGNING_KEY = settings.SECRET_KEY, the public literal becomes the JWT signing key. CoreModel
(backend/utils/models.py, lines 14-24) declares the primary key as a UUID CharField, so the
token's user_id claim is that UUID, and backend/lyadmin_db.sql pins the superadmin UUID to
456b688c-8ad5-46de-bc2e-d41d8047bd42. The stock JWTAuthentication verifies only the signature,
the token_type claim and the user_id lookup; there is no server-side session binding and no
revocation list.
The vendor documentation (README, section "其他说明", item 1) does instruct operators to change
SECRET_KEY and shows how to generate a replacement, and this is taken into account here. The
reported defect is that the shipped default is exploitable as-is and nothing warns at startup.
A related hardening gap: the SECRET_KEY assignment at line 32 comes after the wildcard import
at line 26, so an operator who sets SECRET_KEY in config.py - the project's conventional
configuration file - has it silently overwritten.
Reproduction, verified end-to-end on a default local deployment. Only GET requests were used.
1. Deploy following the README, importing the bundled lyadmin_db.sql, and leave SECRET_KEY
unchanged.
2. Self-sign an access token: HMAC-SHA256 over base64url(header) + "." + base64url(payload)
using the SECRET_KEY literal as the key.
header = {"typ":"JWT","alg":"HS256"}
payload = {"token_type":"access","exp":<future>,"iat":<now>,"jti":"<random>",
"user_id":"456b688c-8ad5-46de-bc2e-d41d8047bd42"}
AUTH_HEADER_TYPES is ('JWT',), so the request header prefix is "JWT", not "Bearer".
3. GET /api/system/user/user_info/ with no token returns
{"code":4001,"data":null,"msg":"身份认证信息未提供。"}
4. The same request carrying the self-signed token returns
{"code":2000,...,"data":{"name":"超级管理员",...}} - the caller is resolved as the
superadmin.
5. GET /api/system/menu/ with that token returns {"code":2000,...,"total":32}, the complete
administration menu tree.
Cross-checks that rule out "any token is accepted":
- The same payload signed with a different key returns {"code":4001,"msg":"身份认证已过期"}.
The signature is validated, so the effective key must be exactly the committed literal.
- The same literal used to sign a token for the low-privilege "test" account returns
{"code":4000,"msg":"您没有执行该操作的权限。"}. Code 4000 means the forged identity was
accepted and only the permission check failed, whereas 4001 is the authentication-failure
code. This is the decisive evidence that the forgery is effective rather than a false
positive.
Impact: an instance that never changed SECRET_KEY - that is, one deployed exactly as the
README's default instructions describe - can be taken over without any credential. The
attacker can read, create, modify and delete everything reachable by the superadmin role
(users, roles, menu permissions, departments, dictionaries, platform settings, and the mall
and order modules) and can create a persistent administrator account. Because both the signing
key and the superadmin UUID are public constants of the project, one forged token is valid
against all such instances with no per-instance adaptation.
CVSS v3.1: 9.8 (Critical) - CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
CVSS v4.0: 9.3 (Critical) - CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N
Weakness: CWE-321 (Use of Hard-coded Cryptographic Key); CWE-287 (Improper Authentication).
Product disambiguation: this entry concerns Lybbn Django-Vue-Lyadmin. It is not
django-vue-admin (maintained by caoqianming), a different project that carries its own
advisory CVE-2026-82835 for improper access control. The two codebases, maintainers and root
causes are unrelated, so this report should not be merged with that entry.
Vendor notification: the maintainer was notified through the project's public issue tracker;
the issue URL is provided in the Advisory / Exploit field of this submission. |
|---|
| La source | ⚠️ https://github.com/lybbn/django-vue-lyadmin/issues/3 |
|---|
| Utilisateur | HiiragiHaru (UID 101255) |
|---|
| Soumission | 16/09/2026 04:17 (il y a 20 jours) |
|---|
| Modérer | 05/10/2026 12:38 (19 days later) |
|---|
| Statut | Accepté |
|---|
| Entrée VulDB | 413586 [Lybbn Django-Vue-Lyadmin jusqu’à 3.2.12 JWT Signing settings.py SECRET_KEY chiffrement faible] |
|---|
| Points | 20 |
|---|