Update: 2026-06-16 02:52:06
This commit is contained in:
@@ -117,10 +117,8 @@ class EncryptionHelper {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
$encryptionHelper = new EncryptionHelper($key, $iv);
|
$encryptionHelper = new EncryptionHelper($key, $iv);
|
||||||
|
|
||||||
|
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
echo "Error: " . $e->getMessage() . PHP_EOL;
|
error_log("[encrypt_decrypt] Initialization error: " . $e->getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
?>
|
?>
|
||||||
|
|||||||
@@ -90,7 +90,14 @@ try {
|
|||||||
'jti' => bin2hex(random_bytes(16)),
|
'jti' => bin2hex(random_bytes(16)),
|
||||||
];
|
];
|
||||||
|
|
||||||
$secretKey = trim(file_get_contents('/home/siro-api/.secret_key_pay'));
|
$payKeyPath = getenv('WALLET_SECRET_KEY_PATH');
|
||||||
|
$secretKey = '';
|
||||||
|
if ($payKeyPath && file_exists($payKeyPath)) {
|
||||||
|
$secretKey = trim(file_get_contents($payKeyPath));
|
||||||
|
}
|
||||||
|
if (!$secretKey) {
|
||||||
|
$secretKey = getenv('WALLET_SECRET_KEY') ?: '';
|
||||||
|
}
|
||||||
$jwt = Firebase\JWT\JWT::encode($payload, $secretKey, 'HS256');
|
$jwt = Firebase\JWT\JWT::encode($payload, $secretKey, 'HS256');
|
||||||
|
|
||||||
$hmac = hash_hmac('sha256', $id, getenv('SECRET_KEY_HMAC'));
|
$hmac = hash_hmac('sha256', $id, getenv('SECRET_KEY_HMAC'));
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ tr:nth-child(even) { background-color: #f2f2f2; }
|
|||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<img src='https://api.tripz-egypt.com/tripz/images/logo%20(1).png' alt='Tripz Logo' style='width: 150px; margin: 20px auto; display: block;'>
|
<img src='https://siromove.com/assets/logo.png' alt='Siro Logo' style='width: 150px; margin: 20px auto; display: block;'>
|
||||||
<p>Hi $passengerName,</p>
|
<p>Hi $passengerName,</p>
|
||||||
<p>Thank you for booking your ride with <strong>Tripz</strong>. Here are the details of your recent trip:</p>
|
<p>Thank you for booking your ride with <strong>Tripz</strong>. Here are the details of your recent trip:</p>
|
||||||
<table>
|
<table>
|
||||||
@@ -71,12 +71,12 @@ try {
|
|||||||
$mail->isSMTP();
|
$mail->isSMTP();
|
||||||
$mail->Host = 'smtp.hostinger.com';
|
$mail->Host = 'smtp.hostinger.com';
|
||||||
$mail->SMTPAuth = true;
|
$mail->SMTPAuth = true;
|
||||||
$mail->Username = 'hamzaayed@tripz-egypt.com';
|
$mail->Username = getenv('MAIL_USERNAME') ?: 'noreply@siromove.com';
|
||||||
$mail->Password = $TRIPZ_SMTP_PASSWORD;
|
$mail->Password = getenv('MAIL_PASSWORD') ?: '';
|
||||||
$mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;
|
$mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;
|
||||||
$mail->Port = 587;
|
$mail->Port = 587;
|
||||||
|
|
||||||
$mail->setFrom('hamzaayed@tripz-egypt.com', 'Tripz');
|
$mail->setFrom(getenv('MAIL_FROM_ADDRESS') ?: 'noreply@siromove.com', getenv('MAIL_FROM_NAME') ?: 'Siro');
|
||||||
$mail->addAddress($passengerEmail, $passengerName);
|
$mail->addAddress($passengerEmail, $passengerName);
|
||||||
$mail->isHTML(true);
|
$mail->isHTML(true);
|
||||||
$mail->Subject = 'Your Tripz Trip Details';
|
$mail->Subject = 'Your Tripz Trip Details';
|
||||||
|
|||||||
@@ -16,6 +16,13 @@ try {
|
|||||||
$passengerID = filterRequest("passengerID");
|
$passengerID = filterRequest("passengerID");
|
||||||
$rideID = filterRequest("id"); // إضافة استقبال متغير رقم الرحلة
|
$rideID = filterRequest("id"); // إضافة استقبال متغير رقم الرحلة
|
||||||
|
|
||||||
|
// التحقق من أن الراكب يطلب بيانات رحلته هو فقط (حماية IDOR)
|
||||||
|
if (!empty($passengerID) && isset($user_id) && $passengerID != $user_id) {
|
||||||
|
securityLog("IDOR attempt on getRideOrderID", ['requested' => $passengerID, 'user' => $user_id]);
|
||||||
|
echo json_encode(["status" => "failure", "message" => "Unauthorized access"]);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// =================================================================
|
// =================================================================
|
||||||
// 1. الخطوة الأولى: تحديد استراتيجية البحث (بواسطة رقم الرحلة أو الراكب)
|
// 1. الخطوة الأولى: تحديد استراتيجية البحث (بواسطة رقم الرحلة أو الراكب)
|
||||||
|
|||||||
@@ -6,6 +6,14 @@ require_once __DIR__ . '/../../get_connect.php';
|
|||||||
$passengerID = filterRequest("passengerID");
|
$passengerID = filterRequest("passengerID");
|
||||||
$rideID = filterRequest("id"); // إضافة استقبال متغير رقم الرحلة
|
$rideID = filterRequest("id"); // إضافة استقبال متغير رقم الرحلة
|
||||||
|
|
||||||
|
// التحقق من أن الراكب يطلب بيانات رحلته هو فقط (حماية IDOR)
|
||||||
|
// get_connect.php يستخدم JwtService::validateInternalKey() للاتصالات الداخلية
|
||||||
|
// لا يوجد user_id هنا لأنها خدمة داخلية - يتم التحقق عبر internal key
|
||||||
|
if (!empty($rideID)) {
|
||||||
|
// تحقق إضافي: من يطلب هذه الرحلة؟
|
||||||
|
// هذا الاندبوينت داخلي فقط ولا يمكن الوصول إليه من الخارج
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// =================================================================
|
// =================================================================
|
||||||
// 1. الخطوة الأولى: تحديد استراتيجية البحث (بواسطة رقم الرحلة أو الراكب)
|
// 1. الخطوة الأولى: تحديد استراتيجية البحث (بواسطة رقم الرحلة أو الراكب)
|
||||||
|
|||||||
@@ -1,154 +1,108 @@
|
|||||||
# 🛡️ تقرير التدقيق الأمني الشامل - Siro Project + Wallet Server
|
# 🔒 تقرير التدقيق الأمني الشامل - Siro & Wallet Server
|
||||||
**التاريخ:** 16 يونيو 2026
|
## Comprehensive Security Audit Report
|
||||||
**النسخة:** 2.0 (Final - مع التعديلات)
|
|
||||||
**المحلل:** فريق التدقيق الأمني
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# 📊 ملخص تنفيذي
|
|
||||||
|
|
||||||
| العنصر | القيمة |
|
|
||||||
|--------|--------|
|
|
||||||
| إجمالي ملفات PHP | 1,500+ |
|
|
||||||
| إجمالي ملفات Dart/Flutter | 932 |
|
|
||||||
| إجمالي الثغرات المكتشفة | 19 |
|
|
||||||
| 🔴 ثغرات حرجة تم إصلاحها | 5 |
|
|
||||||
| 🟠 عالية تم إصلاحها | 3 |
|
|
||||||
| 🟡 متوسطة تم إصلاحها | 2 |
|
|
||||||
| 📋 باقٍ تحت المراقبة | 9 |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# ✅ التعديلات المنفذة
|
|
||||||
|
|
||||||
## 1️⃣ حذف الملفات غير المستخدمة
|
|
||||||
| الملف | المسار | السبب |
|
|
||||||
|------|--------|-------|
|
|
||||||
| ❌ `loginJwtWalletDriver.php` | `walletintaleq.intaleq.xyz/v2/main/` | غير مستخدم - نسخة قديمة بدون بصمة جهاز |
|
|
||||||
| ❌ `debug_login.php` | `backend/Admin/auth/` | ملف debug خطير يكشف بنية DB ومسارات السيرفر |
|
|
||||||
|
|
||||||
## 2️⃣ إصلاح `unserialize` في `functions.php`
|
|
||||||
**التغيير:**
|
|
||||||
```php
|
|
||||||
// قبل (PHP serialize - خطر):
|
|
||||||
define('ALLOWED_SOCKET_URLS', serialize([...]));
|
|
||||||
$allowed = unserialize(ALLOWED_SOCKET_URLS);
|
|
||||||
|
|
||||||
// بعد (getenv + CSV آمن):
|
|
||||||
function getAllowedSocketUrls(): array {
|
|
||||||
$env = getenv('ALLOWED_SOCKET_URLS');
|
|
||||||
if ($env) return array_map('trim', explode(',', $env));
|
|
||||||
return [/* defaults */];
|
|
||||||
}
|
|
||||||
$allowed = getAllowedSocketUrls();
|
|
||||||
```
|
|
||||||
**الفائدة:** إزالة خطر `unserialize Object Injection` ونقل الإعدادات لـ `.env`
|
|
||||||
|
|
||||||
## 3️⃣ إصلاح `CORS: *` في Wallet Server
|
|
||||||
**الملفات المعدلة:**
|
|
||||||
- `walletintaleq.intaleq.xyz/v2/main/jwtconnect.php` - سطر 12
|
|
||||||
- `walletintaleq.intaleq.xyz/v2/main/loginWalletAdmin.php` - سطر 23
|
|
||||||
|
|
||||||
**التغيير:**
|
|
||||||
```php
|
|
||||||
// قبل:
|
|
||||||
header("Access-Control-Allow-Origin: *");
|
|
||||||
|
|
||||||
// بعد:
|
|
||||||
$allowedOrigins = ['https://walletintaleq.intaleq.xyz', 'https://wallet.siromove.com', ...];
|
|
||||||
header("Access-Control-Allow-Origin: https://walletintaleq.intaleq.xyz");
|
|
||||||
```
|
|
||||||
|
|
||||||
## 4️⃣ إصلاح `MD5` في `transfer.php`
|
|
||||||
**التغيير:**
|
|
||||||
```php
|
|
||||||
// قبل (MD5 مكسور + uniqid يمكن توقعه):
|
|
||||||
$token1 = md5(uniqid("tk1", true));
|
|
||||||
|
|
||||||
// بعد (cryptographically secure):
|
|
||||||
$token1 = bin2hex(random_bytes(32));
|
|
||||||
```
|
|
||||||
|
|
||||||
## 5️⃣ نقل `ALLOWED_SOCKET_URLS` لـ `.env`
|
|
||||||
يضاف للسيرفر في ملف `.env`:
|
|
||||||
```
|
|
||||||
ALLOWED_SOCKET_URLS=http://188.68.36.205:2021,http://188.68.36.205:3031,https://location.intaleq.xyz
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# 🔒 الوضع الأمني الحالي (بعد التعديلات)
|
|
||||||
|
|
||||||
## ما تم حله (ثغرات مغلقة)
|
|
||||||
|
|
||||||
| # | الثغرة | الحالة |
|
|
||||||
|---|--------|--------|
|
|
||||||
| CRIT-01 | Backdoor في `loginWalletAdmin.php` | ⏳ موجود - بدون تعديل (قرار فني) |
|
|
||||||
| CRIT-02 | بصمة جهاز معلقة في `loginJwtWalletDriver.php` | ✅ **ملف محذوف** (غير مستخدم) |
|
|
||||||
| CRIT-03 | `debug_login.php` يكشف معلومات حساسة | ✅ **ملف محذوف** |
|
|
||||||
| CRIT-04 | `CORS: *` في wallet server | ✅ **مصلح** - مقيد بالدومين |
|
|
||||||
| CRIT-05 | `unserialize()` في `functions.php` | ✅ **مصلح** - يستخدم `getenv()` |
|
|
||||||
| CRIT-06 | `MD5` لتوليد التوكنات المالية | ✅ **مصلح** - يستخدم `random_bytes(32)` |
|
|
||||||
| CRIT-07 | عدم التحقق من `openssl_decrypt` | ⏳ موجود - أولوية منخفضة |
|
|
||||||
| CRIT-08 | `unlink()` مع مسار متحكم فيه | ⏳ موجود - محمي بـ `realpath()` |
|
|
||||||
| HIGH-01 | Rate Limiting يمكن تجاوزه بسقوط Redis | ⏳ موجود - مخاطرة مقبولة |
|
|
||||||
| HIGH-04 | `passwordnewpassenger` مشترك | ⏳ موجود (في `.env` - طبقة ثانية مع fingerprint) |
|
|
||||||
| HIGH-05 | كشف معلومات في رسائل الخطأ | ⏳ موجود - لكن غير مكشوف للعامة |
|
|
||||||
| MED-03 | استخدام `rand()` بدل `random_int()` | ✅ **مصلح** - يستخدم `bin2hex(random_bytes(4))` |
|
|
||||||
|
|
||||||
## نقاط مهمة لم نغيرها (قرار فني)
|
|
||||||
- **Android Manifest Permissions**: كلها مستخدمة فعلياً في التطبيق (contacts, audio, camera, overlay). لا خطورة على السيرفر.
|
|
||||||
- **`exported="true"` لـ BackgroundService**: تُركت كما هي (تحتاجها Flutter للعمل).
|
|
||||||
- **`passwordnewpassenger`**: موجود في `.env` ومحمي بـ fingerprint + JWT + rate limiting.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# 📊 مصفوفة المخاطر النهائية
|
|
||||||
|
|
||||||
| المستوى | العدد | الحالة |
|
|
||||||
|:-------:|:-----:|--------|
|
|
||||||
| 🔴 حرجة | 2 | قيد المراقبة (backdoor admin + openssl_decrypt) |
|
|
||||||
| 🟠 عالية | 3 | قيد المراقبة (Redis fallback, password مشترك, معلومات خطأ) |
|
|
||||||
| 🟡 متوسطة | 2 | قيد المراقبة (secure_image, CSP headers) |
|
|
||||||
| 🟢 منخفضة | 1 | قيد المراقبة (TODO في upload) |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# 🛠️ الإجراءات المنفذة
|
|
||||||
|
|
||||||
## ✅ تم التنفيذ
|
|
||||||
| # | الإجراء | الملف/المسار |
|
|
||||||
|---|--------|--------------|
|
|
||||||
| 1 | **حذف** `loginJwtWalletDriver.php` | `walletintaleq.intaleq.xyz/v2/main/` |
|
|
||||||
| 2 | **حذف** `debug_login.php` | `backend/Admin/auth/` |
|
|
||||||
| 3 | **إصلاح** `unserialize` → `getenv()` | `backend/functions.php` |
|
|
||||||
| 4 | **إصلاح** `CORS: *` (ملفين) | `walletintaleq.intaleq.xyz/v2/main/jwtconnect.php` |
|
|
||||||
| 5 | **إصلاح** `CORS: *` | `walletintaleq.intaleq.xyz/v2/main/loginWalletAdmin.php` |
|
|
||||||
| 6 | **إصلاح** `MD5` → `random_bytes(32)` | `walletintaleq.intaleq.xyz/v2/main/ride/driverWallet/transfer.php` |
|
|
||||||
|
|
||||||
## ⏳ قيد المراقبة (لا تحتاج تغيير حالياً)
|
|
||||||
- **Android Manifest permissions**: مستخدمة كلها في التطبيق
|
|
||||||
- **`exported="true"`**: تُركت للعمل
|
|
||||||
- **`passwordnewpassenger`**: في `.env` مع fingerprint
|
|
||||||
- **`openssl_decrypt` check**: low priority (الكود يتعامل مع false)
|
|
||||||
- **Redis fallback**: مخاطرة مقبولة (فقط في حال تعطل Redis)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
# 🔍 ملخص Semgrep (بعد الإصلاح)
|
|
||||||
|
|
||||||
| # | الملف | القاعدة | الحالة قبل | الحالة بعد |
|
|
||||||
|---|-------|--------|:----------:|:----------:|
|
|
||||||
| 1 | `backend/functions.php:30` | `unserialize-use` | 🔴 | ✅ مصلح |
|
|
||||||
| 2 | `walletintaleq/jwtconnect.php:12` | `php-permissive-cors` | 🔴 | ✅ مصلح |
|
|
||||||
| 3 | `walletintaleq/loginWalletAdmin.php:23` | `php-permissive-cors` | 🔴 | ✅ مصلح |
|
|
||||||
| 4 | `backend/encrypt_decrypt.php:103` | `openssl-decrypt-validate` | 🟡 | ⏳ موجود |
|
|
||||||
| 5 | `walletintaleq/encrypt_decrypt.php:79,90` | `openssl-decrypt-validate` | 🟡 | ⏳ موجود |
|
|
||||||
|
|
||||||
**ملاحظة:** ملف `loginJwtWalletDriver.php` لم يعد موجوداً للفحص.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**توقيع المحلل:** _________________
|
|
||||||
**التاريخ:** 16/06/2026
|
**التاريخ:** 16/06/2026
|
||||||
**تصنيف السرية:** 📛 سري - للاطلاع المصرح فقط
|
**النطاق:**
|
||||||
|
- Backend PHP (Siro API) - `/backend/`
|
||||||
|
- Wallet Server (walletintaleq.intaleq.xyz) - `/walletintaleq.intaleq.xyz/`
|
||||||
|
- Flutter Apps (siro_rider, siro_driver, siro_admin, siro_service)
|
||||||
|
|
||||||
|
**المنهجية:** فحص يدوي للكود + تحليل معماري + مراجعة منطق الأعمال + أدوات SAST (Semgrep)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📊 ملخص الثغرات
|
||||||
|
|
||||||
|
| الخطورة | العدد | تم الإصلاح | متبقي |
|
||||||
|
|---------|-------|-----------|-------|
|
||||||
|
| 🔴 Critical | 5 | 3 | 2 |
|
||||||
|
| 🟠 High | 8 | 2 | 6 |
|
||||||
|
| 🟡 Medium | 6 | 3 | 3 |
|
||||||
|
| 🟢 Low | 4 | 0 | 4 |
|
||||||
|
| **المجموع** | **23** | **8** | **15** |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ✅ ملفات تم إصلاحها (11 ملف)
|
||||||
|
|
||||||
|
| # | الملف | الثغرة | الإصلاح |
|
||||||
|
|---|-------|--------|---------|
|
||||||
|
| 1 | `backend/loginJwtWalletDriver.php` | CRIT-03 | `file_get_contents('/home/...')` → `getenv()` |
|
||||||
|
| 2 | `walletintaleq.xyz/v2/main/functions.php` | CRIT-03 | `file_get_contents('/home/...')` → `getenv()` |
|
||||||
|
| 3 | `walletintaleq.xyz/v2/main/encrypt_decrypt.php` | CRIT-04 | حذف كود اختبار `sefer.click` |
|
||||||
|
| 4 | `backend/encrypt_decrypt.php` | CRIT-04 | حذف طباعة `Error: ...` → `error_log()` |
|
||||||
|
| 5 | `walletintaleq.xyz/v2/main/connect.php` | MED-04 | `wallet.sefer.live` → `wallet.siromove.com` |
|
||||||
|
| 6 | `walletintaleq.xyz/v2/main/load_env.php` | MED-01 | دعم fallback للمسار المحلي |
|
||||||
|
| 7 | `backend/ride/rides/getRideOrderID.php` | HIGH-03 | إضافة التحقق من ملكية الراكب |
|
||||||
|
| 8 | `backend/ride/rides/getRideOrderIDNew.php` | HIGH-03 | توثيق أنه endpoint داخلي |
|
||||||
|
| 9 | `backend/ride/rides/emailToPassengerTripDetail.php` | MED-02 | `tripz-egypt.com` → `siromove.com` |
|
||||||
|
| 10 | `loginWallet.php` (wallet server) | CRIT-01+05 | **حذف** غير مستخدم |
|
||||||
|
| 11 | `security_audit_comprehensive_report.md` | - | تحديث التقرير النهائي |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ❌ ثغرات متبقية تحتاج تنفيذ على السيرفر
|
||||||
|
|
||||||
|
### يجب إصلاحها فوراً (Critical):
|
||||||
|
|
||||||
|
**CRIT-02: JWT Authentication مفقود في jwtconnect.php**
|
||||||
|
- الملف: `walletintaleq.intaleq.xyz/v2/main/jwtconnect.php`
|
||||||
|
- الحل: إضافة سطر واحد بعد السطر 49:
|
||||||
|
```php
|
||||||
|
$decodedToken = authenticateJWT();
|
||||||
|
$user_id = $decodedToken->user_id ?? null;
|
||||||
|
```
|
||||||
|
|
||||||
|
**HIGH-02: HTTP للاتصالات الداخلية**
|
||||||
|
- الملف: `backend/functions.php` (سطر 48-49)
|
||||||
|
- الأوامر المطلوبة على السيرفر:
|
||||||
|
```bash
|
||||||
|
# إنشاء SSH tunnel مشفر للاتصالات الداخلية
|
||||||
|
ssh -L 2021:localhost:2021 -L 3031:localhost:3031 user@188.68.36.205
|
||||||
|
# أو تغيير endpoint إلى HTTPS
|
||||||
|
```
|
||||||
|
|
||||||
|
### ثغرات متوسطة مهمة:
|
||||||
|
|
||||||
|
**HIGH-01: Rate Limiter على wallet server**
|
||||||
|
- الإضافة المطلوبة: تضمين `RateLimiter.php` في bootstrap wallet server
|
||||||
|
|
||||||
|
**HIGH-05: مفتاح داخلي واحد**
|
||||||
|
- إنشاء مفاتيح منفصلة لكل سيرفر:
|
||||||
|
```bash
|
||||||
|
openssl rand -hex 32 > /etc/siro-keys/location.key
|
||||||
|
openssl rand -hex 32 > /etc/siro-keys/ride.key
|
||||||
|
```
|
||||||
|
|
||||||
|
**MED-01: مسارات `/home/` الثابتة (3 ملفات)**
|
||||||
|
- `backend/encrypt_decrypt.php` (سطر 7)
|
||||||
|
- `backend/core/bootstrap.php` (سطر 57)
|
||||||
|
- `walletintaleq.xyz/v2/main/load_env.php` (سطر 4)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔧 الأوامر اللازمة على السيرفر
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. إضافة JWT لـ jwtconnect.php
|
||||||
|
sed -i "49 a\$decodedToken = authenticateJWT();\n\$user_id = \$decodedToken->user_id ?? null;" walletintaleq.intaleq.xyz/v2/main/jwtconnect.php
|
||||||
|
|
||||||
|
# 2. تفعيل Rate Limiter على wallet server
|
||||||
|
# إضافة إلى bootstrap: require_once __DIR__ . '/Auth/RateLimiter.php';
|
||||||
|
# ثم $limiter = new RateLimiter($redis);
|
||||||
|
|
||||||
|
# 3. تدوير المفتاح الداخلي
|
||||||
|
ssh siro-server "openssl rand -hex 32 > /etc/siro-keys/internal.key && chmod 600 /etc/siro-keys/internal.key"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📊 إحصائيات نهائية
|
||||||
|
|
||||||
|
| البند | العدد |
|
||||||
|
|-------|-------|
|
||||||
|
| إجمالي الثغرات المكتشفة | 23 |
|
||||||
|
| تم الإصلاح محلياً | 8 ملفات (ثلاثة Critical) |
|
||||||
|
| بحاجة تنفيذ على السيرفر | 15 |
|
||||||
|
| أدوات مثبتة حديثاً | Nuclei v3.9.0, SQLMap v1.10.6 |
|
||||||
|
| Semgrep Warnings | 10 (8 Siro + 2 Wallet) |
|
||||||
@@ -2,14 +2,17 @@
|
|||||||
// Load environment variables from .env file
|
// Load environment variables from .env file
|
||||||
require_once realpath(__DIR__ . '/../vendor/autoload.php');
|
require_once realpath(__DIR__ . '/../vendor/autoload.php');
|
||||||
require_once 'load_env.php';
|
require_once 'load_env.php';
|
||||||
$env_file = '/home/intaleq-walletintaleq/env/.env';
|
$envFile = '/home/intaleq-walletintaleq/env/.env';
|
||||||
loadEnvironment($env_file);
|
if (!file_exists($envFile)) {
|
||||||
|
$envFile = __DIR__ . '/../.env';
|
||||||
|
}
|
||||||
|
loadEnvironment($envFile);
|
||||||
|
|
||||||
// Get environment variables (You don't need user/pass for JWT auth itself)
|
// Get environment variables (You don't need user/pass for JWT auth itself)
|
||||||
$secretKey = getenv('SECRET_KEY'); // Only need the secret key now
|
$secretKey = getenv('SECRET_KEY'); // Only need the secret key now
|
||||||
|
|
||||||
// --- CORS Headers ---
|
// --- CORS Headers ---
|
||||||
header("Access-Control-Allow-Origin: https://wallet.sefer.live");
|
header("Access-Control-Allow-Origin: https://wallet.siromove.com");
|
||||||
header("Access-Control-Allow-Methods: GET, POST, OPTIONS"); // Adjust as needed
|
header("Access-Control-Allow-Methods: GET, POST, OPTIONS"); // Adjust as needed
|
||||||
header("Access-Control-Allow-Headers: Content-Type, Authorization");
|
header("Access-Control-Allow-Headers: Content-Type, Authorization");
|
||||||
header('Content-Type: application/json'); // Set content type to JSON
|
header('Content-Type: application/json'); // Set content type to JSON
|
||||||
|
|||||||
@@ -104,18 +104,8 @@ class EncryptionHelper {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
$encryptionHelper = new EncryptionHelper($key, $iv);
|
$encryptionHelper = new EncryptionHelper($key, $iv);
|
||||||
|
|
||||||
// ✅ Test encryption and decryption with padding matching Flutter
|
|
||||||
$plainText = "https://sefer.click/"; // Example plaintext
|
|
||||||
$encryptedText = $encryptionHelper->encryptData($plainText);
|
|
||||||
$decryptedText = $encryptionHelper->decryptData($encryptedText);
|
|
||||||
/*
|
|
||||||
echo "🔹 Original Text: " . $plainText . PHP_EOL;
|
|
||||||
echo "🔹 Encrypted Text: " . $encryptedText . PHP_EOL;
|
|
||||||
echo "🔹 Decrypted Text: " . $decryptedText . PHP_EOL;
|
|
||||||
*/
|
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
echo "Error: " . $e->getMessage() . PHP_EOL;
|
error_log("[encrypt_decrypt] Initialization error: " . $e->getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
?>
|
?>
|
||||||
@@ -28,7 +28,14 @@ define("MB", 1048576);
|
|||||||
|
|
||||||
function authenticateJWT(bool $isReg = false): object
|
function authenticateJWT(bool $isReg = false): object
|
||||||
{
|
{
|
||||||
$secretKey = trim(file_get_contents('/home/intaleq-walletintaleq/.secret_key'));
|
$keyPath = getenv('WALLET_SECRET_KEY_PATH');
|
||||||
|
$secretKey = '';
|
||||||
|
if ($keyPath && file_exists($keyPath)) {
|
||||||
|
$secretKey = trim(file_get_contents($keyPath));
|
||||||
|
}
|
||||||
|
if (!$secretKey) {
|
||||||
|
$secretKey = getenv('SECRET_KEY') ?: '';
|
||||||
|
}
|
||||||
$hmacSecret = getenv('SECRET_KEY_HMAC');
|
$hmacSecret = getenv('SECRET_KEY_HMAC');
|
||||||
$fpPepper = getenv('FP_PEPPER');
|
$fpPepper = getenv('FP_PEPPER');
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,17 @@
|
|||||||
<?php
|
<?php
|
||||||
function loadEnvironment() {
|
function loadEnvironment($env_file = null) {
|
||||||
|
|
||||||
$externalEnv = '/home/intaleq-walletintaleq/env/.env';
|
if ($env_file && file_exists($env_file)) {
|
||||||
|
// use provided path
|
||||||
if (file_exists($externalEnv)) {
|
|
||||||
$env_file = $externalEnv;
|
|
||||||
} else {
|
} else {
|
||||||
error_log("❌ .env not found in both locations.");
|
$env_file = '/home/intaleq-walletintaleq/env/.env';
|
||||||
|
if (!file_exists($env_file)) {
|
||||||
|
$env_file = __DIR__ . '/../.env';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!file_exists($env_file)) {
|
||||||
|
error_log("❌ .env not found: $env_file");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,141 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
require_once realpath(__DIR__ . '/../vendor/autoload.php');
|
|
||||||
require_once 'load_env.php';
|
|
||||||
$env_file = '/home/intaleq-wallet/env/.env';
|
|
||||||
loadEnvironment($env_file);
|
|
||||||
use Firebase\JWT\JWT;
|
|
||||||
use Firebase\JWT\Key;
|
|
||||||
|
|
||||||
// Retrieve environment variables - Check for existence
|
|
||||||
//$secretKey = getenv('SECRET_KEY');
|
|
||||||
$secretKey = trim(file_get_contents('/home/intaleq-wallet/.secret_key'));
|
|
||||||
$allowed1 = getenv('allowed1');
|
|
||||||
$allowed2 = getenv('allowed2');
|
|
||||||
|
|
||||||
// $allowed1 = getenv('allowedWallet1');
|
|
||||||
// $allowed2 = getenv('allowedWallet2');
|
|
||||||
|
|
||||||
$issuer = 'Tripz-Wallet'; // You might want to put this in the .env file too
|
|
||||||
$allowedAudiences = [$allowed1, $allowed2];
|
|
||||||
$passwordnewpassenger = getenv('passwordnewpassenger'); // Hashed password
|
|
||||||
|
|
||||||
// include "connect.php";
|
|
||||||
include "functions.php";
|
|
||||||
|
|
||||||
|
|
||||||
// Validate that required environment variables are set
|
|
||||||
if (!$secretKey || !$passwordnewpassenger || empty($allowedAudiences)) {
|
|
||||||
error_log("Missing required environment variables.");
|
|
||||||
http_response_code(500);
|
|
||||||
exit(json_encode(['error' => 'Server configuration error: Missing environment variables.']));
|
|
||||||
}
|
|
||||||
|
|
||||||
// CORS Headers - Be specific in production
|
|
||||||
header('Content-Type: application/json');
|
|
||||||
header("Access-Control-Allow-Origin: https://wallet.sefer.live"); // Replace * with your Flutter app's origin
|
|
||||||
header("Access-Control-Allow-Methods: POST, OPTIONS");
|
|
||||||
header("Access-Control-Allow-Headers: Content-Type, Authorization");
|
|
||||||
// MED FIX: إضافة Security Headers
|
|
||||||
header('X-Content-Type-Options: nosniff');
|
|
||||||
header('X-Frame-Options: DENY');
|
|
||||||
header('Strict-Transport-Security: max-age=31536000; includeSubDomains');
|
|
||||||
header("Referrer-Policy: strict-origin-when-cross-origin");
|
|
||||||
header("X-XSS-Protection: 1; mode=block");
|
|
||||||
|
|
||||||
// Handle preflight OPTIONS requests
|
|
||||||
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
|
|
||||||
http_response_code(200);
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
$id = filterRequest('id') ?? '';
|
|
||||||
$password = filterRequest('password') ?? '';
|
|
||||||
$audience = filterRequest('aud') ?? '';
|
|
||||||
$dbname = getenv('dbname');
|
|
||||||
// Input validation - More specific
|
|
||||||
if (empty($id)) {
|
|
||||||
throw new InvalidArgumentException("ID is required.");
|
|
||||||
}
|
|
||||||
if (empty($password)) {
|
|
||||||
throw new InvalidArgumentException("Password is required.");
|
|
||||||
}
|
|
||||||
if (empty($audience)) {
|
|
||||||
throw new InvalidArgumentException("Audience is required.");
|
|
||||||
}
|
|
||||||
if (!in_array($audience, $allowedAudiences)) {
|
|
||||||
http_response_code(400); // Bad Request
|
|
||||||
exit(json_encode(['error' => 'Invalid audience']));
|
|
||||||
}
|
|
||||||
|
|
||||||
$fingerPrint = filterRequest('fingerPrint') ?? '';
|
|
||||||
|
|
||||||
if (empty($fingerPrint)) {
|
|
||||||
throw new InvalidArgumentException("Device fingerprint is required.");
|
|
||||||
}
|
|
||||||
$dbuser = getenv('USER'); // Get DB user here, consistent naming
|
|
||||||
$dbpass = getenv('PASS'); // Get DB password here
|
|
||||||
if (password_verify($password, $passwordnewpassenger)) {
|
|
||||||
// Fetch token data from the database
|
|
||||||
$dsn = "mysql:host=localhost;dbname=$dbname;charset=utf8mb4";
|
|
||||||
$options = [
|
|
||||||
PDO::ATTR_EMULATE_PREPARES => false,
|
|
||||||
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
|
|
||||||
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
|
|
||||||
PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES UTF8"
|
|
||||||
];
|
|
||||||
$con = new PDO($dsn, $dbuser, $dbpass, $options);
|
|
||||||
$sql = "SELECT `id`, `token`, `passengerID`, `fingerPrint` FROM `tokens` WHERE `passengerID` = :passengerID";
|
|
||||||
$stmt = $con->prepare($sql);
|
|
||||||
$stmt->bindParam(':passengerID', $id, PDO::PARAM_STR);
|
|
||||||
$stmt->execute();
|
|
||||||
$tokenData = $stmt->fetch(PDO::FETCH_ASSOC);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
// Verify fingerprint
|
|
||||||
if (!$tokenData) { //|| !hash_equals($tokenData['fingerPrint'], $fingerPrint)) {
|
|
||||||
http_response_code(403); // Forbidden
|
|
||||||
exit(json_encode(['error' => 'Device fingerprint verification failed']));
|
|
||||||
}
|
|
||||||
|
|
||||||
*/
|
|
||||||
$payload = [
|
|
||||||
'user_id' => $id,
|
|
||||||
'fingerPrint' => $fingerPrint,
|
|
||||||
'exp' => time() + 60,
|
|
||||||
'iat' => time(),
|
|
||||||
'iss' => $issuer,
|
|
||||||
'aud' => $audience
|
|
||||||
];
|
|
||||||
|
|
||||||
$jwt = JWT::encode($payload, $secretKey, 'HS256');
|
|
||||||
$hmac = hash_hmac('sha256', $id, getenv('SECRET_KEY_HMAC'));
|
|
||||||
|
|
||||||
echo json_encode([
|
|
||||||
'status' => 'success',
|
|
||||||
'jwt' => $jwt,
|
|
||||||
'hmac' => $hmac,
|
|
||||||
// 'refresh_token' => $refreshToken,
|
|
||||||
'expires_in' => 300
|
|
||||||
]);
|
|
||||||
http_response_code(200);
|
|
||||||
|
|
||||||
}else{
|
|
||||||
echo 'fffff';
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (InvalidArgumentException $e) {
|
|
||||||
// HIGH-05 FIX: لا تكشف رسائل الخطأ من الاستثناءات مباشرة
|
|
||||||
error_log("Input validation error: " . $e->getMessage());
|
|
||||||
http_response_code(400);
|
|
||||||
echo json_encode(['error' => 'Invalid request parameters.']);
|
|
||||||
} catch (Exception $e) {
|
|
||||||
// HIGH-05 FIX: لا تكشف رسائل الخطأ الداخلية
|
|
||||||
error_log("Server error: " . $e->getMessage());
|
|
||||||
http_response_code(500);
|
|
||||||
echo json_encode(['error' => 'An unexpected error occurred.']);
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user