Ele geçirilmiş bir OpenCart mağazası kendini nadiren belli eder. Ne sayfanın yerine konmuş bir mesaj vardır ne de fidye notu; yalnızca biraz tuhaf duran birkaç ayrıntı. Kimsenin açtığını hatırlamadığı bir yönetici hesabı. İçinde yalnızca JPEG olması gereken bir klasörde duran PHP dosyası. Ödemesi hiçbir zaman tamamlanmayan küçük siparişlerden oluşan bir yığın. E-ticarete sızan saldırgan kalıcı olmak ister, çünkü sessiz bir dayanak gürültülü olandan daha çok kazandırır.
Aşağıdakiler, bir mağaza sahibi bakmamızı istediğinde en sık karşılaştığımız beş işaret — genelde ortaya çıktıkları sırayla ve her biri, şüpheyi cevaba çeviren komut ya da sorguyla birlikte. Buradaki kontrollerin tamamı okuma amaçlıdır. Hiçbir şeyi değiştirmeden önce beşini de çalıştırın: ilk temizlik turu, sorunun ne kadar geriye gittiğini anlamanızı sağlayacak zaman damgalarını genellikle yok eder.
1. Kimsenin açmadığı bir yönetici hesabı
oc_user tablosu veritabanınızdaki en kısa listedir ve denetlemesi en hızlı yerdir. Yalnızca yeni satırları değil, hepsini okuyun: uzun süredir kullanılmayan bir hesabın adını değiştirmek kullanıcı sayısını sabit bıraktığı için yeni hesap açmaktan daha az dikkat çeker.
SELECT user_id, username, user_group_id, status, date_added
FROM oc_user
ORDER BY date_added DESC;
SELECT user_group_id, name, LENGTH(permission) AS perm_size
FROM oc_user_group;
SELECT api_id, username, status, date_added, date_modified FROM oc_api;
SELECT * FROM oc_api_ip;Bu çıktıda üç şey önemli. user_group_id değeri 1 olan kullanıcı, adı ne olursa olsun tam yetkili yöneticidir. permission sütunu diğerlerine göre belirgin biçimde büyümüş bir kullanıcı grubu, genellikle gözle görülür bir yönetici açmak yerine düşük yetkili bir grubun yetkilerinin genişletildiği anlamına gelir. oc_api ise sahiplerin çoğunun tamamen unuttuğu hesaptır: status değeri 1 olan ve oc_api_ip tablosunda karşılığı bulunmayan bir API kullanıcısı, kullanıcı listesinde hiç görünmeyen ve hiçbir parola politikasına takılmayan bir giriş kapısıdır.
2. PHP'nin işi olmayan yerdeki PHP dosyaları
OpenCart yüklenen dosyaları image/catalog ve system/storage/upload altına yazar. Bu iki yolda da çalıştırılabilir kod bulunmamalıdır; system/storage/logs ve system/storage/cache için de aynısı geçerlidir. Bunlardan birinde duran tek bir küçük PHP dosyası, klasik kalıcı arka kapıdır: parola değişikliğinden, tema kurulumundan ve insanların “siteyi temizledik” derken kastettiği işlemlerin çoğundan sağ çıkar.
cd /var/www/store
find image system/storage -type f \( -name '*.php' -o -name '*.phtml' -o -name '*.phar' \) -printf '%TY-%Tm-%Td %p\n'
find . -type f -name '*.php' -newermt '2026-07-01' | head -50
grep -rlE 'eval\(|base64_decode\(|gzinflate\(|assert\(' --include='*.php' catalog admin system imageGerçek temizliklerden iki uyarı. Kalıp aramak özensiz arka kapıları bulur, dikkatli yazılmış olanları değil: gelen bir parametreyi diske yazan bir dosyada şüpheli tek bir anahtar kelime bulunmaz. Zaman damgaları da yalan söyler, çünkü touch tek komutluk iştir. Sağlam duran tek karşılaştırma, kullandığınız sürümün temiz kopyasıyla yapılandır.
cd /tmp
curl -LO https://github.com/opencart/opencart/archive/refs/tags/4.0.2.3.zip
unzip -q 4.0.2.3.zip
diff -rq opencart-4.0.2.3/upload /var/www/store | grep -v 'system/storage'diff çıktısında catalog, admin ve system altında görünen her şey ya sizin özelleştirmenizdir ya da başkasının. Çekirdek dosyalarına dokunulmamış bir mağazada bu liste neredeyse boş olmalı ve içindeki her satırın bir sahibi bulunmalıdır.
3. Gelen ama hiç ödenmeyen siparişler
OpenCart sipariş satırını ödeme sağlayıcısı cevap vermeden önce, order_status_id = 0 ile yazar; yönetim panelindeki “eksik siparişler” filtresi bunları gösterir. Günde birkaç tanesi sıradan sepet terkidir. Dar bir adres kümesinden saatte yüzlercesi ise kart testidir: birileri çalınmış kartlardan hangilerinin hâlâ çalıştığını sizin ödeme adımınızla deniyordur ve bunun bedelini işlem ücretleriyle, uzun vadede de üye iş yeri hesabınızı riske atan dolandırıcılık oranıyla siz ödersiniz.
SELECT DATE(date_added) AS d, COUNT(*) AS n
FROM oc_order
WHERE order_status_id = 0 AND date_added > NOW() - INTERVAL 14 DAY
GROUP BY d ORDER BY d;
SELECT ip, COUNT(*) AS n, MIN(date_added) AS first_seen, MAX(date_added) AS last_seen
FROM oc_order
WHERE date_added > NOW() - INTERVAL 7 DAY
GROUP BY ip HAVING n > 20 ORDER BY n DESC LIMIT 20;oc_order tablosunda ayrıca forwarded_ip, user_agent ve accept_language sütunları vardır. Onlarca farklı adrese yayılmış ama tek bir tarayıcı imzası ve tek bir dil değeri taşıyan sipariş öbeği müşteri değil, otomasyondur. Bu maddede her zaman mağazanız ele geçirilmiş olmaz — çoğu zaman ödeme adımınız bedava test aracı olarak kullanılıyordur — ama yine de aynı listeye girer, çünkü verilecek karar her hâlükârda bir güvenlik kararıdır: ödeme rotasının önüne hız sınırı koymak, ödeme adımından önce doğrulama eklemek ve bu süre boyunca üyeliksiz alışverişin açık kalıp kalmayacağına bakmak.
4. Vitrininizin başkasının JavaScript'ini servis etmesi
Kart bilgisi çalan bir kodun arka kapı dosyasına ihtiyacı yoktur. İhtiyacı olan tek şey, saklanan ve her sayfada basılan bir HTML parçasıdır; OpenCart bunun için birkaç yer sunar: tema şablonları, sayfa düzenindeki modüller ve ayar tablosunun kendisi. Mağaza sahipleri dosya sistemine bakar, oc_setting içindeki bir değerin de aynı sadakatle ekrana basıldığını unutur.
SELECT store_id, `code`, `key`, LEFT(`value`, 120) AS preview
FROM oc_setting
WHERE `value` LIKE '%<script%' OR `value` LIKE '%.js%';Ardından şablonları okuyun. 3.0.x sürümünde vitrin teması catalog/view/theme/<tema>/template altındadır; OpenCart 4 varsayılan şablonları catalog/view/template içine, üçüncü taraf temaları da extension/<ad>/catalog/view/template altına taşıdı. Her iki sürümde de eklenen kod genellikle alt bilgi (footer) ya da ödeme şablonuna düşer, çünkü buralar her yerde basılır ve nadiren gözden geçirilir.
grep -rn '<script' /var/www/store/catalog/view/template /var/www/store/extension \
| grep -viE 'catalog/view/javascript|jquery|bootstrap'Bir saklanma yeri daha var ve yalnızca 3.0.x'te bulunur: oc_modification tablosu. OCMOD değişiklikleri, çekirdeğin system/storage/modification altında üretilen kopyasına uygulanan XML yamalarıdır; yani kötü niyetli bir modification, sizin inceleyeceğiniz dosyaya hiç dokunmadan bir controller'ı çalışma anında yeniden yazabilir. Önce tabloyu, sonra diskte ürettiği dosyaları kontrol edin. OpenCart 4 bu mekanizmayı kaldırdı — orada eklentiler extension/ altına gerçek dosyalar koyar — ve bu, 4.x'in gerçekten daha zor saklanılan az sayıdaki noktasından biridir.
5. İstemediğiniz e-posta, yük ve itibar
Beşinci işaret genelde dışarıdan gelir: sipariş e-postaları spam klasörüne düşmeye başlar, hosting sağlayıcısı uyarı gönderir ya da ödeme kuruluşu ters ibraz düzenini sorar. Sinyal dışarıdan geldiğinde ihlal çoktan haftalıktır. Daha erken yakalayan kontroller şunlar.
- Müşteriniz olmayan adreslere giden mesajlarla dolu bir e-posta kuyruğu — bunu OpenCart panelinden değil, sunucuda mailq ya da exim -bp ile okuyun.
- Mağaza boştayken, sabahın dördünde yüksek kalmaya devam eden PHP-FPM işlemci kullanımı.
- Web kullanıcısından tanımadığınız sunuculara giden bağlantılar; yoğun bir dakikada ss -tnp çalıştırmak görmeye yeter.
- Ekibinizden kimsenin eklemediği, web kullanıcısına ait cron kayıtları: crontab -l -u www-data.
- Search Console'da hiç oluşturmadığınız sayfaların dizine eklendiğini görmek — klasik yönlendirme spam'i; çoğu zaman yalnızca arama motoru botlarına servis edilir ve kendi tarayıcınızda görünmez.
Bu maddelerin her birinin tek başına masum bir açıklaması olabilir. İkisinin birlikte görülmesi ya da birinin ilk dört bölümdeki herhangi bir bulguyla birleşmesi, aksi kanıtlanana kadar ihlaldir.
İlk bir saatte ne yapmalı
- 1Anlık kopya alın: tam dosya arşivi ve mysqldump, sunucunun dışında saklanmak üzere. Bu hem delil hem geri dönüş noktasıdır; gözü kapalı geri yükleyeceğiniz bir yedek değildir.
- 2Kart verisi açığa çıkmış olabilirse Ayarlar bölümünün Sunucu sekmesinden bakım moduna alın ve ödeme kuruluşunuza siz haber verin, onlar size sormadan önce.
- 3Şüpheli yönetici hesaplarını ve API anahtarlarını silmeden pasifleştirin; her user_id'yi date_added ile birlikte not edin.
- 4Oturumları geçersiz kılın: system/storage/session içeriğini temizleyin, veritabanı oturum motorunu kullanıyorsanız oc_session tablosunu boşaltın. Herkes çıkış yapmış olur; zaten amaç budur.
- 5Kimlik bilgilerini şu sırayla değiştirin: hosting ve SSH, config.php ile admin/config.php içindeki veritabanı kullanıcısı, arayüzden yönetici parolaları, API anahtarları, ardından eklenti ayarlarında duran üçüncü taraf anahtarları.
- 6Dosyalara ancak bundan sonra dokunun ve temizliği, bulduğunuz dosyaları silerek değil, çekirdeği bilinen temiz bir sürümle değiştirerek yapın.
Giriş kapısı genelde nerede çıkıyor
Temizlediğimiz mağazalarda giriş noktası neredeyse hiçbir zaman yeni keşfedilmiş bir açık olmuyor. Yüklediği dosyanın türünü denetlemeyen, güncelliğini yitirmiş bir eklenti oluyor; bir kez satın alınıp bir daha güncellenmemiş bir tema; başka bir serviste sızmış ve burada da kullanılan bir yönetici parolası; güvenlik yaması almayı bırakmış bir PHP sürümünde çalışan eski bir OpenCart; ya da taşıma sonrası paylaşımlı sunucuda herkesin okuyabildiği bir config.php.
Bu liste aynı zamanda düzeltme planıdır. Giriş kapısını kapatmadan dosyaları geri yüklemek size temiz bir mağaza ve bir hafta sonra aynı ihlali kazandırır. Bu yüzden bir olay, envanterle biter: her eklenti, sürümü, son güncelleme tarihi ve artık geliştiricisi olmayanlar hakkında verilmiş bir karar.
Ne zaman bize yazın
Bu işaretlerden ikisi ya da daha fazlası mağazanıza uyuyorsa elinizdekini bize gönderin: şüpheli satırlar, dosya listesi, log kayıtları. Lansman kampanyası boyunca tüm işler saatlik 10 $ + KDV ile faturalanır; olay müdahalesi de buna dahildir. İşe başlamadan önce saat tahminini alır, siz onaylarsınız. İlk yanıt 2 saat içinde, Pzt–Cmt 09:00–22:00 (GMT+3) arasında verilir. Olayın tam ortasındaysanız konu satırında belirtin ve biz konuşmadan önce hiçbir şeyi temizlemeyin.
OAuth, JWT ve OWASP odaklı güvenlik mimarisi; tehdit modelleme.