· kaynak dev.to (home feed)
Presend ücretsiz QR phishing tarama API'si ekledi, Cloudflare Workers için sıfırdan bir PNG decoder yazdı
Presend'un yeni ücretsiz API endpoint'i, JPEG ve PNG yüklemelerindeki QR kodlarını çözüyor ve gömülü URL'yi URLhaus'a karşı kontrol ediyor; bu, gönderinin Microsoft'a dayandırarak yıllık yüzde 146 olarak verdiği quishing büyümesine bir yanıt.

Presend, ücretsiz API'sine bir QR kod phishing tarayıcısı ekledi ve bunu çalışır hale getirmek bir PNG decoder'ı elle yazmayı gerektirdi. Bir dev.go gönderisinde, aracın arkasındaki ekip yeni endpoint'i ve rutin bir kütüphane entegrasyonunu sıfırdan bir uygulamaya dönüştüren runtime kısıtlamalarını ele alıyor.
Bunun motivasyonu, "quishing" olarak adlandırılan — QR kodlar aracılığıyla gerçekleştirilen phishing — yaygınlaşması. Gönderi, Microsoft'un 2026 raporuna dayanarak yıl bazında büyümeyi ilk çeyrekte yüzde 146 olarak veriyor; QR kodların artık tüm phishing saldırılarının kabaca yüzde 12'sinin arkasında olduğunu, 2021'de yüzde 1'in altında olduğunu belirtiyor. Bu yöntem, kötü amaçlı bağlantı bir görselin içinde bulunduğu için işe yarıyor; metin tabanlı e-posta filtreleri URL'yi hiç görmüyor.
Endpoint ne yapıyor
Yeni route olan POST /api/qr-scan, JPEG veya PNG biçiminde yüklenen bir görseli kabul ediyor, içinde bulunursa QR kodunu çözüyor ve — çözülen içerik bir URL olduğunda — bu URL'yi aynı istekte URLhaus'a karşı kontrol ediyor. Presend'un API'sinin geri kalanıyla uyumlu olarak, kayıt ve API anahtarı gerektirmeden ücretsiz kullanılabiliyor. Amaç, posta hatlarına kod çözme ile itibar kontrolünü tek bir çağrıda birleştiren bir arayüz sunmak ve görsel içine gömülü bağlantıların yarattığı boşluğu kapatmak.
PNG decoder neden elle yazılmak zorunda kaldı
API, Cloudflare Workers üzerinde çalışıyor; bu ortamda Canvas yok, Node Buffer yok, dosya sistemi yok ve ayrıca script boyutu konusunda sıkı bir sınır var. QR kod çözme aslında kolay kısımdı: jsQR bağımlılığı olmayan saf bir JavaScript kütüphanesi ve jpeg-js, useTArray seçeneği içsel bir Buffer.alloc çağrısını Uint8Array ile değiştirdiğinde JPEG'i işliyor.
PNG ise daha zordu. Format için standart JavaScript kütüphanesi olan pngjs, Node'un yerleşik zlib modülüne bağımlı ve Workers bu modülü sağlamıyor. Ancak Workers, web standardı bir API olan DecompressionStream('deflate') ifadesini sunuyor ve PNG piksel verisi deflate ile sıkıştırıldığından, açma işi runtime'a devredilebilirdi. Geri kalan her şeyin elle yazılması gerekiyordu: chunk yapısını ayrıştırmak (boyutlar ve renk türü için IHDR, sıkıştırılmış piksel verisi içeren bir veya daha fazla IDAT chunk'ı, dosyayı kapatan IEND), her satır başındaki filtre işlemini geri çevirmek — 0 ile 4 arasında bir baş baytın None, Sub, Up, Average veya Paeth'i seçmesi — ve pikselleri yeniden birleştirmek. Yazar, decoder'ı köşelerinde ve merkezinde bilinen piksel değerlerine sahip bir PNG ile doğruladı ve tam eşleşme aldı.
Bozan vaka, en yaygın olandı
Bitmiş decoder'a gerçek bir QR kodu vermek bir hata üretti: yalnızca 8-bit PNG'ler destekleniyordu ve görsel 1-bit'ti. Yazarın test materyallerini oluşturmak için kullandığı Python qrcode kütüphanesi dahil çoğu QR kod üreteci, siyah-beyaz bir görselin piksel başına yalnızca bir bit gerektirmesi nedeniyle varsayılan olarak 1-bit PNG üretiyor. Başka bir deyişle, endpoint'in için tasarlandığı yol, başlangıçta başa çıkamadığı yoldu ve olduğu gibi yayınlamak gerçek dünyadaki QR kodların çoğunda başarısız olacaktı.
Düzeltme, bayt altı piksel paketlemeyi desteklemeyi gerektirdi: birden fazla piksel tek bir baytı, en anlamlı bit önce gelecek şekilde paylaşıyor ve her satırın verisi tam bir bayta tamamlanıyor. Bu sırada bir spesifikasyon detayı önemliydi — filtre yeniden yapımı için geriye dönük mesafe olan "piksel başına bayt" değeri, gerçek derinlikten bağımsız olarak 8'in altındaki her bit derinliği için 1 olarak tanımlanıyor.
Doğru runtime'da hata ayıklama üzerine bir not
jsQR, ortam algılaması self'e atama yapan bir UMD paketi olarak geliyor ve bu, ES-module bağlamında düz Node altında çöküyor. Yazarın ilk içgüdüsü kütüphaneyi yamalamaktı, ancak Workers — tarayıcılar gibi — self'i gerçek bir global olarak sunuyor ve gerçek runtime'a karşı test, onun değiştirilmeden çalıştığını gösterdi. Gönderide işaret edilen daha geniş ders: yerel bir Node script'i ile bir edge runtime farklı ortamlardır ve bu tür uyumsuzluklar, daha fazla runtime npm'in büyük kısmına Node'a dair işlenmiş varsayımlardan uzaklaştıkça geliştiricileri sürprizlere sürüklemeye devam edecek.
Neden önemli
Quishing tam da yalnızca metni inceleyen filtrelerden kaçabildiği için hızla büyüyor ve gönderinin Microsoft'a atfettiği büyüme rakamları, phishing bağlantılarının nasıl teslim edildiğinde anlamlı bir değişimi tarif ediyor. Bir QR görselini çözen ve URL'yi tek bir çağrıda kontrol eden ücretsiz, anahtarsız bir endpoint, posta akışı işleten herkes için görsel farkındalı kontroller ekleme eşiğini düşürüyor. Mühendislik hikayesi ayrıca daha geniş bir eğilimin habercisi: Workers gibi edge runtime'lar yaygınlaştıkça Node iç yapılarına bağlı paketler bozuluyor ve DecompressionStream gibi taşınabilir web standardı API'ler daha güvenli bir temel haline geliyor. Presend kodu GitHub'da yayınladı; decoder vendor/png-decoder.js içinde ve endpoint functions/api/qr-scan.js içinde.
- #phishing
- #qr-codes
- #cloudflare-workers
- #api
- #png