Fix #19: Plaintext OTP hashing + hardcoded server paths
- Changed OTP storage in Admin/auth/login.php from plaintext to sha256 hash - Updated Admin/auth/verify_login.php to hash user input before comparison - Replaced hardcoded /home/siro-api/ paths with environment variables: - ERROR_LOG_PATH, ENV_FILE_PATH, SECRET_KEY_PAY_PATH, SECRET_KEY_PATH - Falls back to __DIR__-relative paths when env vars are unset
This commit is contained in:
@@ -140,11 +140,12 @@ try {
|
|||||||
$success = sendWhatsAppFromServer($phone, $messageBody);
|
$success = sendWhatsAppFromServer($phone, $messageBody);
|
||||||
|
|
||||||
if ($success) {
|
if ($success) {
|
||||||
// حفظ الرمز كما هو في قاعدة البيانات (بدون تشفير)
|
// تخزين هاش للـ OTP بدلاً من النص الصريح
|
||||||
|
$otpHash = hash('sha256', (string)$otp);
|
||||||
$stmt = $con->prepare("INSERT INTO token_verification_admin (phone_number, token, expiration_time)
|
$stmt = $con->prepare("INSERT INTO token_verification_admin (phone_number, token, expiration_time)
|
||||||
VALUES (?, ?, DATE_ADD(NOW(), INTERVAL 10 MINUTE))
|
VALUES (?, ?, DATE_ADD(NOW(), INTERVAL 10 MINUTE))
|
||||||
ON DUPLICATE KEY UPDATE token = VALUES(token), expiration_time = VALUES(expiration_time)");
|
ON DUPLICATE KEY UPDATE token = VALUES(token), expiration_time = VALUES(expiration_time)");
|
||||||
$stmt->execute([$encryptedPhone, $otp]);
|
$stmt->execute([$encryptedPhone, $otpHash]);
|
||||||
|
|
||||||
// إخفاء جزء من الرقم في الاستجابة للأمان
|
// إخفاء جزء من الرقم في الاستجابة للأمان
|
||||||
$maskedPhone = substr($phone, 0, 4) . '****' . substr($phone, -3);
|
$maskedPhone = substr($phone, 0, 4) . '****' . substr($phone, -3);
|
||||||
|
|||||||
@@ -22,12 +22,13 @@ if ($admin->role !== 'admin' && $admin->role !== 'super_admin') {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// جلب المفتاح المشترك لسيرفر المحفظة
|
// جلب المفتاح المشترك لسيرفر المحفظة من متغير البيئة أو الملف
|
||||||
$payKeyPath = '/home/siro-api/.secret_key_pay';
|
$payKeyPath = getenv('SECRET_KEY_PAY_PATH');
|
||||||
$payKey = file_exists($payKeyPath) ? trim(file_get_contents($payKeyPath)) : getenv('SECRET_KEY_PAY');
|
$payKey = ($payKeyPath && file_exists($payKeyPath)) ? trim(file_get_contents($payKeyPath)) : getenv('SECRET_KEY_PAY');
|
||||||
|
|
||||||
if (empty($payKey)) {
|
if (empty($payKey)) {
|
||||||
$payKey = trim(@file_get_contents('/home/siro-api/.secret_key'));
|
$fallbackPath = getenv('SECRET_KEY_PATH');
|
||||||
|
$payKey = ($fallbackPath && file_exists($fallbackPath)) ? trim(file_get_contents($fallbackPath)) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (empty($payKey)) {
|
if (empty($payKey)) {
|
||||||
|
|||||||
@@ -39,14 +39,14 @@ try {
|
|||||||
// فك تشفيره لو احتجنا إرساله أو عرضه، لكن هنا نحن نحتاج المشفر للبحث
|
// فك تشفيره لو احتجنا إرساله أو عرضه، لكن هنا نحن نحتاج المشفر للبحث
|
||||||
// $phone = $encryptionHelper->decryptData($encryptedPhone);
|
// $phone = $encryptionHelper->decryptData($encryptedPhone);
|
||||||
|
|
||||||
// تشفير الرمز (OTP) القادم من التطبيق للمقارنة
|
// هاش الرمز (OTP) القادم من التطبيق للمقارنة
|
||||||
$encryptedOtp = $encryptionHelper->encryptData((string)$otp);
|
$otpHash = hash('sha256', (string)$otp);
|
||||||
|
|
||||||
// 3. التحقق من الـ OTP (باستخدام القيم المشفرة)
|
// 3. التحقق من الـ OTP
|
||||||
$stmt = $con->prepare("SELECT * FROM token_verification_admin
|
$stmt = $con->prepare("SELECT * FROM token_verification_admin
|
||||||
WHERE phone_number = ? AND token = ?
|
WHERE phone_number = ? AND token = ?
|
||||||
AND expiration_time >= NOW()");
|
AND expiration_time >= NOW()");
|
||||||
$stmt->execute([$encryptedPhone, $encryptedOtp]);
|
$stmt->execute([$encryptedPhone, $otpHash]);
|
||||||
|
|
||||||
if ($stmt->rowCount() === 0) {
|
if ($stmt->rowCount() === 0) {
|
||||||
jsonError("رمز التحقق غير صالح أو منتهي الصلاحية.");
|
jsonError("رمز التحقق غير صالح أو منتهي الصلاحية.");
|
||||||
|
|||||||
@@ -20,10 +20,7 @@ if ($debugMode) {
|
|||||||
ini_set('log_errors', '1');
|
ini_set('log_errors', '1');
|
||||||
|
|
||||||
// تحديد مسار اللوج بشكل ديناميكي (محلياً أو سيرفر)
|
// تحديد مسار اللوج بشكل ديناميكي (محلياً أو سيرفر)
|
||||||
$logPath = '/home/siro-api/logs/php_errors.log';
|
$logPath = getenv('ERROR_LOG_PATH') ?: (__DIR__ . '/../logs/php_errors.log');
|
||||||
if (!file_exists(dirname($logPath)) || !is_writable(dirname($logPath))) {
|
|
||||||
$logPath = __DIR__ . '/../logs/php_errors.log';
|
|
||||||
}
|
|
||||||
ini_set('error_log', $logPath);
|
ini_set('error_log', $logPath);
|
||||||
|
|
||||||
header_remove('X-Powered-By');
|
header_remove('X-Powered-By');
|
||||||
@@ -54,10 +51,7 @@ if ($vendorPath) require_once $vendorPath;
|
|||||||
require_once __DIR__ . '/helpers.php';
|
require_once __DIR__ . '/helpers.php';
|
||||||
|
|
||||||
// تحديد مسار الـ .env بشكل ديناميكي
|
// تحديد مسار الـ .env بشكل ديناميكي
|
||||||
$envFile = '/home/siro-api/env/.env';
|
$envFile = getenv('ENV_FILE_PATH') ?: (__DIR__ . '/../.env');
|
||||||
if (!file_exists($envFile)) {
|
|
||||||
$envFile = __DIR__ . '/../.env'; // مسار محلي افتراضي
|
|
||||||
}
|
|
||||||
loadEnvironment($envFile);
|
loadEnvironment($envFile);
|
||||||
|
|
||||||
// 4. Redis Connection (Singleton)
|
// 4. Redis Connection (Singleton)
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
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/siro-api/env/.env';
|
$env_file = getenv('ENV_FILE_PATH') ?: (__DIR__ . '/../../../env/.env');
|
||||||
loadEnvironment($env_file);
|
loadEnvironment($env_file);
|
||||||
|
|
||||||
// ✅ FIX C-02: استخدام getenv بدلاً من file_get_contents الثابت
|
// ✅ FIX C-02: استخدام getenv بدلاً من file_get_contents الثابت
|
||||||
|
|||||||
Reference in New Issue
Block a user