Commit Graph
28 Commits
Author SHA1 Message Date
Hamza-Ayed b938e287c6 Update: 2026-08-07 05:05:45 2026-08-07 05:05:46 +03:00
Hamza-Ayed 977d238c84 Update: 2026-08-07 05:03:39 2026-08-07 05:03:39 +03:00
Hamza-Ayed 8e7c4a7104 Update: 2026-08-07 04:35:28 2026-08-07 04:35:28 +03:00
Hamza-Ayed 2b9f696372 Update: 2026-08-03 00:20:40 2026-08-03 00:20:40 +03:00
Hamza-Ayed 2c962bf80a Update: 2026-08-02 22:51:18 2026-08-02 22:51:18 +03:00
Hamza-Ayed e03b9c30d5 Update: 2026-07-25 18:43:44 2026-07-25 18:43:44 +03:00
Hamza-Ayed 8d3e63d1c7 Update: 2026-07-25 18:40:38 2026-07-25 18:40:38 +03:00
Hamza-AyedandClaude Opus 5 2135edcf43 Close the remaining ciphertext joins and a SQL injection in email verification
- Customer-service notes joined to the account by comparing encrypted phone
  columns. Both notes tables now carry phone_key, written when a note is
  saved, and the three joins match on it.
- The email_verifications join was comparing a plaintext column against an
  encrypted one, so it never matched and `verified` was always NULL in both
  passenger and driver sign-in. It is now resolved in PHP against the
  decrypted address, which fixes a pre-existing bug rather than only
  preparing for GCM.
- auth/sendVerifyEmail.php built all three of its statements by interpolating
  the request values into SQL. Any caller could inject through the email or
  token field. Now parameterised.
- serviceapp/register.php duplicate detection consults the users indexes and
  writes them with the row.

Sweep confirms no join or lookup compares two encrypted columns any more.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-25 16:48:10 +03:00
Hamza-AyedandClaude Opus 5 35a66935aa Repair verification joins broken by the OTP key change; extend backfill
Storing the verification phone as a keyed HMAC fixed OTP lookups but broke
every query that joined those tables back to the account, because
phone_verification*.phone_number no longer holds the same value as
driver.phone / passengers.phone. Six joins were affected, and four of them
feed the `verified` flag that the rider and driver apps check at sign-in — so
this was already failing under the current CBC mode, not only after a switch
to GCM.

Accounts now carry phone_key, computed exactly as otpPhoneKey() does, and the
joins match on it. It is written at registration for both apps and populated
for existing rows by the backfill.

The backfill also covers the columns added for the remaining lookups:
users.email_bidx/phone_bidx and driver.national_bidx, which were migrated but
never populated, and honours a per-field prefix so phone_key reproduces
otpPhoneKey's exact output.

Insert column/value counts verified with a paren-aware parser after editing.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-25 16:40:53 +03:00
Hamza-AyedandClaude Opus 5 8d7e3118b5 Migrate remaining encrypted-column lookups to the blind index
Completes the set of queries that matched a freshly encrypted value against a
stored one, which only works while encryption is deterministic. Each keeps its
original comparison and adds an index comparison in the same WHERE, so nothing
changes today.

- passenger sign-in by email, service-staff sign-in, Firebase token lookup
- driver lookup by phone and by national number
- admin ride lookup and ride monitor (both tables)
- nabeh: driver status, user resolution, ride history, complaint submission

transit_org_admins lives in the transit database and has no index column, so
login there falls back to decrypting the small set of active admins and
comparing normalised numbers.

Schema: adds users.email_bidx/phone_bidx and driver.national_bidx with their
indexes.

Verified that every :*_bidx placeholder introduced is actually bound — an
unbound one is a fatal error at request time, not a silent miss.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-25 16:36:32 +03:00
Hamza-AyedandClaude Opus 5 39b5a7fc7f Keep OTP phone numbers recoverable for customer-service follow-up
Storing the verification phone as a keyed HMAC made OTP lookups independent
of the encryption mode, but the hash is one-way — and customer service reads
those same rows to chase people who requested a code and never finished
registering. That workflow would have lost the number entirely.

The verification tables now carry both forms: phone_number holds the lookup
key, and a new phone_enc column holds the encrypted number, which is
decryptable when a human needs to call.

The two follow-up queries also compared the verification row against the
driver/passengers tables and the notes tables by matching ciphertext, which
only ever worked because encryption was deterministic. Under GCM every number
would have looked unregistered and every note would have disappeared. Both now
read the number from phone_enc and match on normalised plaintext, so they are
correct under either mode.

Rows written before phone_enc existed are skipped rather than shown without a
number.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-25 16:27:29 +03:00
Hamza-AyedandClaude Opus 5 4009af8dd3 Add campaign launcher and app version manager; fix SQL injection in updatePackages
serviceapp/updatePackages.php built its UPDATE by interpolating the request
values straight into the SQL string, so any caller with a valid token could
execute arbitrary SQL through the version field. It now uses bound
parameters, requires an admin role, validates the version format, and writes
an audit entry.

trigger_campaign.php gains dry_run=1: it performs the same Gemini analysis
and target selection but returns before creating the promo code and before
dispatching any notification. Launching without previewing was the only
option before, and a launch writes a seven-day discount and pushes to every
passenger in the country.

Console:
- Campaign launcher with a mandatory preview. Launching stays disabled until
  the current parameters have been previewed, and re-locks if any parameter
  changes afterwards or once a launch completes.
- App version manager with the same version-format check as the server and a
  confirmation naming the old and new values.

Cache busting: assets are served straight off a bind mount with no version,
so browsers kept running the previously cached build after a deploy. Both
asset links now carry ?v=, and the build id is shown in Session & Security
and printed in the diagnostics report.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-25 14:41:27 +03:00
Hamza-Ayed 9cc14864a3 Update: 2026-06-29 00:26:08 2026-06-29 00:26:08 +03:00
Hamza-Ayed 03f26ce825 Update: 2026-06-29 00:12:38 2026-06-29 00:12:39 +03:00
Hamza-Ayed 1b6e172a4a Update: 2026-06-28 23:14:46 2026-06-28 23:14:46 +03:00
Hamza-Ayed da9e6eb981 Update: 2026-06-26 04:04:03 2026-06-26 04:04:04 +03:00
Hamza-Ayed f53177e715 Update: 2026-06-26 02:29:35 2026-06-26 02:29:35 +03:00
Hamza-Ayed 21f5105fa1 Update: 2026-06-26 02:00:23 2026-06-26 02:00:23 +03:00
Hamza-Ayed 9b61bd50c8 Update: 2026-06-25 18:39:01 2026-06-25 18:39:01 +03:00
Hamza-Ayed 28b8558b6d add 8-tab review page, review controller, updateDriverToActive handles new fields, drivers_cant_register navigates to review 2026-06-25 17:05:11 +03:00
Hamza-Ayed d4db89f04e add documents+ai_data to getDriverDetails, create rejectDriver endpoint, add rejected_reason column 2026-06-25 17:01:44 +03:00
Hamza-Ayed 3543fdd2cd Fix #21: High-severity fixes (H-01 through H-06)
H-01: Egypt document uploads - added path traversal prevention (basename),
       replaced HTTP_HOST with APP_DOMAIN env var
H-02: 7 remaining hardcoded /home/siro-api/ paths replaced with env vars
       (ENV_FILE_PATH, INTERNAL_SOCKET_KEY_PATH, WEBHOOK_SECRET_KEY_PATH)
H-03: serviceapp/updateDriver.php - added ownership check (user_id must match
       driverID or user must be admin); non-admins blocked from changing
       password/status/email/phone
H-04: ggg.php - replaced weak client-supplied phone auth with proper admin
       JWT authentication via JwtService
H-05: Static IV fallback in encrypt_decrypt.php already documented as legacy
H-06: Wallet shared password noted as design limitation (mitigated by
       fingerprint verification + short token TTL)
- Also fixed functions.php log message (removed hardcoded path)
2026-06-17 07:56:57 +03:00
Hamza-Ayed 72eeb24cd7 Fix #18: Exception leak remediation across 87 PHP files
- Replaced all client-facing $e->getMessage() with generic error messages
- Added error_log() with filename prefix to all catch blocks
- Covered jsonError(), echo, and json_encode() response patterns
- Also fixed 2 remaining display_errors=1 and add_invoice.php leak
- Script-assisted fix for 75 files, manual fix for 12 remaining edge cases
2026-06-17 07:48:31 +03:00
Hamza-Ayed fc58529b09 Update: 2026-06-16 01:17:28 2026-06-16 01:17:29 +03:00
Hamza-Ayed 2321b78244 Update: 2026-06-15 01:37:40 2026-06-15 01:37:41 +03:00
Hamza-Ayed f907212c57 Update: 2026-06-12 20:40:40 2026-06-12 20:40:40 +03:00
Hamza-Ayed c5170a88d2 Update: 2026-06-11 13:47:39 2026-06-11 13:47:40 +03:00
Hamza-Ayed d8901e1a87 first commit 2026-06-09 08:40:31 +03:00