Güvenlik
Güvenlik modelimiz tek cümlede: saldırılacak bir sunucuda hiçbir şey yok. Aşağıdakilerin tamamı DevTools'unuzdan doğrulanabilir.
Mimari
Üretici, Cloudflare Pages üzerinden sunulan statik tek sayfalı bir uygulamadır: kullanıcı hesabı yok, kimlik doğrulama yok ve oluşturma akışının hiçbir yerinde arka uç kod yolu yok. Her QR oluşturma, kodlama, tarama ve işleme işlemi tamamen tarayıcınızda çalışır. Yanında bir küçük sunucusuz uç nokta bulunur ve bu, gizlenmek yerine burada listelenir: /api/contact (gönderdiğiniz veriyi Cloudflare D1'de saklayan ve bize e-postayla ileten iletişim formu). Bir QR kodu oluştururken çağrılmaz; URL güvenlik kontrolü check.qr.abundera.ai adresinde ayrı bir üründür. QR kodunun güvenli olup olmadığını kontrol et
Tehdit modeli
Üretici herhangi bir kullanıcı verisi toplamadığı, saklamadığı veya iletmediği için (yukarıdaki iki uç nokta yalnızca açıkça kendilerine gönderdiğinizi işler), en yaygın web uygulaması tehditleri, kimlik bilgisi hırsızlığı, veritabanı ihlali, oturum ele geçirme, sunucu taraflı enjeksiyon, ona uygulanmaz. Kalan saldırı yüzeyi, kaynağımızdan sunulan statik varlık paketidir (HTML, CSS, JavaScript). Şu varsayımlarla tasarım yapıyoruz:
- Kaynak ele geçirme: bir saldırgan paketlenmiş varlıklarımızdan birini kötü amaçlı bir varlıkla değiştirir. Aşağıdaki CSP patlama yarıçapını sınırlar; cache-buster token'ları bilinen iyi bir sürüme geri dönüşü kolaylaştırır.
- Kullanıcı tarafından sağlanan girdi: QR yükleri, vCard isimleri, WiFi şifreleri, toplu CSV satırları, taranan görüntü içerikleri. Her girdi yolu, DOM'a geri işlendiğinde güvenilmez olarak ele alınır.
- Kullanıcı tarafından sağlanan görseller: vCard fotoğraf URL'leri ve logo yüklemeleri. Görseller bir canvas'a işlenir, asla ham biçimlendirme olarak DOM'a gömülmez.
- Üçüncü taraf tarayıcı uzantıları: kapsam dışı. Tarayıcınızdaki bir uzantının her sayfayı değiştirme izni varsa, bizim sayfamızı da değiştirebilir. Garantilerimiz, sayfa değiştirilmeden yüklendiğinde geçerlidir.
İçerik Güvenlik Politikası, direktife göre
Aşağıdaki politika, bu sayfa derlendiğinde dağıtılan _headers dosyasından okunur, bu yüzden kenarın gönderdiğinden sapamaz. Herhangi bir isteğin yanıt başlıklarında doğrulayın.
Content-Security-Policy:
default-src 'self';
script-src 'self' https://abundera.ai 'wasm-unsafe-eval' https://challenges.cloudflare.com;
worker-src 'self' blob:;
style-src 'self' 'unsafe-inline' https://abundera.ai;
font-src 'self';
img-src 'self' data: blob: https:;
connect-src 'self' https: https://challenges.cloudflare.com;
frame-src 'self' https://challenges.cloudflare.com;
frame-ancestors 'none';
base-uri 'self';
form-action 'self'Her direktifin ne yapmasına izin verdiği ve nerede taviz verdiği:
default-src 'self', sert taban. Açıkça gevşetmediğimiz her şey aynı kaynakta kalır.script-src 'self' https://abundera.ai 'wasm-unsafe-eval' https://challenges.cloudflare.com, satır içi<script>yok,eval()yok.abundera.aikendi üst alan adımızdır ve tek bir paylaşılan komut dosyası sunar, dil seçici.challenges.cloudflare.com, yalnızca /contact/'da kullanılan Turnstile widget'ıdır.'wasm-unsafe-eval', QR encoder kütüphanemizin WebAssembly derleme yolu için gereklidir; gelenekseleval()'e izin VERMEZ. Kendi ön dağıtım kontrolümüz, satır içi komut dosyaları için her HTML sayfasını tarar ve derlemeyi başarısız kılar.style-src 'self' 'unsafe-inline', gerçek bir taviz. QR önizlememiz, piksel düzeyindeki renkleri satır içinde hesaplar (ayrı modüller üzerindeki style özellikleri). Hash tabanlı bir izin listesi işe yarardı ancak bir dağıtım olmaksızın herhangi bir stil güncellemesinde başarısız olurdu. Ödün: biraz daha zayıf stil politikasını kabul ediyoruz; stil her halükarda veri sızdıramaz (CSS'ninconnect-srcerişimi yoktur).img-src 'self' data: blob: https:, satır içi QR render'ları içindata:, dışa aktarma indirme URL'leri içinblob:, kullanıcı tarafından sağlanan vCard fotoğraf ve avatar URL'leri içinhttps:. Kullanıcı tarafından sağlanan URL'ler asla çalıştırılmaz, yalnızca işlenir. Şunu bilin ki bu direktif aynı zamanda bir giden kanaldır: sayfada çalışan herhangi bir komut dosyası herhangi bir HTTPS ana bilgisayarından bir görüntü isteyebilir ve veriyi URL'ye koyabilir. Bunu kabul ediyoruz çünkü özellik bunu gerektiriyor ve politikayı su geçirmez olarak tanımlamak yerine burada bunu söylüyoruz.connect-src 'self' https: https://challenges.cloudflare.com, dikkatlice okunması gereken direktif.https:bir şema kaynağıdır:fetch(), XMLHttpRequest, TLS üzerinden WebSocket, EventSource vesendBeacon()'ın yalnızca yazdığınız değil, herhangi bir HTTPS kaynağına ulaşmasına izin verir. Bu, vCard fotoğraf alanının ve URL güvenlik kontrolünün yapıştırdığınız bir adresi getirebilmesi içindir. Kötü amaçlı bir komut dosyası tarafından veri sızıntısını önlemez; komut dosyası biz olarak çalışmaya başladığında hiçbir CSP direktifi bunu önlemez. Veri sızıntısını önleyen şey, gönderdiğimiz kodun böyle istekler yapmamasıdır, bunu Network sekmesinde izleyebilirsiniz.frame-src 'self' https://challenges.cloudflare.com, yalnızca Turnstile widget'ı çerçevelenebilir.frame-ancestors 'none', başka hiçbir site bizi gömemez. Clickjacking'i önler.base-uri 'self', kötü amaçlı olarak enjekte edilen bir<base>etiketi, göreli URL'leri saldırganın kaynağına yönlendiremez.form-action 'self', enjekte edilen herhangi bir form yalnızca kaynağımıza geri gönderebilir. İletişim formu, herhangi bir yere gönderim yapan tek formdur.
CSP'nin yapamadıkları
CSP, tarayıcının kodu nereden yükleyeceğini sınırlar. Yüklenen kodun ne yaptığını denetlemez. Kaynağımız ele geçirilseydi (tehdit modelindeki ilk madde), saldırganın komut dosyası yukarıdaki connect-src ve img-src izinleri dahil bizimkiyle aynı izinlerle çalışırdı. Buna karşı savunmalarımız CSP'nin öncesinde yer alır: dağıtımlar kapsamlı token'lara sahip tek bir Cloudflare hesabı üzerinden yapılır, varlık dosya adları içerik özetlenir böylece değiştirilmiş bir dosya kendisine referans veren her URL'yi değiştirir ve service worker yalnızca aynı kaynaklı GET yanıtlarını önbelleğe alır. Manifesto, siteyi gönderildiği haliyle tanımlar. Bu, hiçbir web sayfasının asla bir yere veri gönderemeyeceği iddiası değildir ve bizi bu daha dar, denetlenebilir ifadeyle sorumlu tutmanızı tercih ederiz.
/bio/* (kullanıcı tarafından sağlanan avatarlar için gevşetilmiş img-src) ve /embed/* (kasıtlı yerleştirme için gevşetilmiş frame-ancestors) için farklı CSP politikaları geçerlidir. Her ikisi de site/_headers içinde belgelenmiştir.
Taşıma ve çerçeveleme başlıkları
- HSTS:
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload, 1 yıl, tüm alt alan adları, HSTS ön yükleme listesine uygun. HTTP'ye düşürme işlemleri uyumlu tarayıcılar tarafından reddedilir. - X-Frame-Options: DENY, CSP
frame-ancestorsile gereksiz, eski tarayıcı kapsamı için tutulur. - X-Content-Type-Options: nosniff, MIME karışıklığı saldırılarını önler.
- Referrer-Policy: strict-origin-when-cross-origin, giden bağlantı tıklamaları kaynağı sızdırır ancak yolu sızdırmaz.
- Permissions-Policy:
camera=(self), microphone=(), geolocation=(), kameraya yalnızca kendi tarayıcımız için izin verilir; mikrofon ve konum, gömülü olsa bile açıkça reddedilir.
Service worker
Service worker'ımız (site/sw.js) yalnızca aynı kaynaklı varlıkları önbelleğe alır. Fetch işleyicisi, kaynaklar arası istekleri ve GET dışı yöntemleri açıkça reddeder, mantığı /sw.js'de okuyabilirsiniz (kaynak, takip edilebilecek kadar küçültülmeden gönderilir). Önbellek yazmaları event.waitUntil() içine sarılır, böylece navigasyon ortasında bırakılamazlar.
Girdi sanitizasyonu
Kullanıcı girdisini kabul eden her işleme yolu, bunu güvenilmez metin olarak ele alır:
- QR yük önizlemeleri
innerHTMLdeğil,textContentkullanır. - Paylaşım hedefleri (pano,
navigator.share()) kullanıcı metnini biçimlendirme olarak değil, dize olarak iletir. - SVG dışa aktarımları, encoder kütüphanemiz tarafından oluşturulur; kullanıcı içeriği, SVG elemanları olarak enjekte edilmeden
<image>xlink:href'e base64 olarak kodlanır. - Baskı önizlemeleri
document.write()değil, blob URL kullanır. - localStorage ayrıştırması
try/catchiçine sarılır, bozuk bir girdi, canlı bir kod yoluna açılabilecek bir istisna değil, yeni boş bir varsayılan değer verir. - Kullanıcı tarafından sağlanan ve "Bağlantıyı aç" düğmeleri olarak gösterilen URL'ler
http(s)://ile sınırlıdır,javascript:vedata:şemaları reddedilir.
Kaynaklar arası görüntü getirme
Bir kullanıcı vCard fotoğrafı veya logo olarak bir https: URL'si yapıştırdığında, tarayıcı bunu CORS ve CSP'mizin img-src izin listesine tabi olarak getirir. Görüntü bir canvas'a işlenir. Asla canlı DOM olmaz, asla kod olarak çalışmaz ve asla kaynağımıza ulaşmaz, getirme işlemi tarayıcı → uzak görüntü şeklindedir ve sonuç istemci tarafında çizilir. Uzak bir görüntü URL'sini kontrol eden bir saldırgan, URL'nin yüklendiğini izleyebilir (kendi sunucusundaki bir log satırı) ancak sayfamızdan hiçbir şeyi sızdıramaz.
Alt Kaynak Bütünlüğü (SRI)
Gönderdiğimiz tüm JavaScript ve CSS aynı kaynaktandır. Üçüncü taraf komut dosyaları veya stil sayfaları yüklemiyoruz, bu nedenle SRI hash'leri geçerli değildir. Üçüncü taraf bir varlık yükleyecek olursak, üzerine bir SRI integrity özelliği ekleyeceğiz ve hash güncelleme sürecini bu sayfada belgeleyeceğiz.
Güvenlik açığı bildirme
Abundera QR'ı etkileyen bir güvenlik sorunu keşfederseniz, kodumuzdaki, dağıtımımızdaki veya gönderdiğimiz bir bağımlılıktaki, lütfen bunu özel olarak security@abundera.ai adresine bildirin. 72 saat içinde önceliklendirmeyi hedefliyoruz. /.well-known/security.txt dosyamızdaki iletişim bilgileri aracılığıyla da bize ulaşabilirsiniz.
Henüz ödüllü hata programı yok
Şu an için ücretli ödüller sunmuyoruz, ancak onaylanan her geçerli rapor, değişiklik günlüğünde kredi ve kamuya açık teşekkürümüzü alır.
Yukarıdakileri doğrulayın
Bu sayfadaki her iddia, bize güvenmek zorunda kalmadan tarayıcınızın DevTools'undan doğrulanabilir:
- CSP: DevTools → Network →
/→ Headers.Content-Security-Policyyanıt başlığını okuyun. - HSTS + güvenlik başlıkları: aynı yer, tüm
Strict-Transport-Security,X-Frame-Optionsvb. görünür durumdadır. - Giden çağrı yok: DevTools → Network → Fetch/XHR. Bir QR oluşturun. Sayacın sıfırda kaldığını izleyin.
- Service worker kapsamı: DevTools → Application → Service Workers. Komut dosyası kaynağını ve önbelleğe alınan varlık listesini doğrulayın.
- Çerez yok: DevTools → Application → Cookies. Boş.
- Tam kılavuz: manifestonun doğrulama bölümü.
İletişim
Güvenlik açıklamaları: security@abundera.ai