Yaygın bir algı, SEMGREP için kurallar yazmanın Codeql’den daha kolay olmasıdır. Yaklaşık bir yıldır bu statik kod analiz araçlarının her ikisiyle de kapsamlı bir şekilde çalıştıktan sonra bazı düşüncelerim var. Bir uygulayıcı olarak, bu araçların kesin çalışmalarını bilmem gerekmiyor, ancak son zamanlarda teorik temellerine derin bir dalış, burada düşüncelerimi pekiştirmem için bana ilham verdi.
Codeql ve Semgrep OSS, özel kural desteğine sahip ana ücretsiz kod analiz araçlarıdır. XPath sorguları ve Java eklentileri yazmayı “özel kural desteği” olarak saymadığınız sürece. Bununla birlikte, CodeQL’in öğrenme eğrisinin çoğunun meydana geldiği yerde kural sözdizimleri açısından büyük farklılıklar gösterirler.
Codeql, tipik bir SQL sorgusu gibi görünen QL dilini kullanır. select
Ve where
hükümler:
/* github/codeql/blob/main/javascript/ql/src/Electron/AllowRunningInsecureContent.ql */
/**
* @name Enabling Electron allowRunningInsecureContent
* @description Enabling allowRunningInsecureContent can allow remote code execution.
* @kind problem
* @problem.severity error
* @security-severity 8.8
* @precision very-high
* @tags security
* frameworks/electron
* external/cwe/cwe-494
* @id js/enabling-electron-insecure-content
*/
import javascript
from DataFlow::PropWrite allowRunningInsecureContent, Electron::WebPreferences preferences
where
allowRunningInsecureContent = preferences.getAPropertyWrite("allowRunningInsecureContent") and
allowRunningInsecureContent.getRhs().mayHaveBooleanValue(true)
select allowRunningInsecureContent, "Enabling allowRunningInsecureContent is strongly discouraged."
Bununla birlikte, bu bir tuzaktır: QL’ye bir veritabanı sorgu dili gibi yaklaşmak sadece harabeye yol açacaktır. Dokümantasyonlarının belirttiği gibi, QL, “genellikle sorgu dili olarak kullanılan bir bildirim mantık programlama dili” olan Datalog’a dayanmaktadır. Benim almam, QL’nin sorgu yapmak için nesne odaklı bir programlama dili olması. İyi QL yazmak için, Codeql standart kütüphanesindeki çeşitli sınıflara ve tahminlerine (IE yöntemleri) çok aşina olmanız gerekir. Örneğin, yukarıdaki sorguda, preferences.getAPropertyWrite("allowRunningInsecureContent")
A.Ş. DataFlow::PropWrite
Eşitlik karşılaştırması için çalışma için örnek.
Buna karşılık, SEMGREP kuralı sözdizimi örüntü odaklıdır. Bunu görselleştirmek için, Codeql örneğiyle aynı güvenlik açığını kontrol eden aşağıdaki SEMGREP kuralını düşünün.
# ajinabraham/njsscan/blob/master/njsscan/rules/semantic_grep/electronjs/security_electron.yaml
rules:
- id: electron_allow_http
patterns:
- pattern-either:
- pattern: >
new BrowserWindow({webPreferences: {allowRunningInsecureContent:
true}})
- pattern: |
var $X = {webPreferences: {allowRunningInsecureContent: true}};
message: >-
Application can load content over HTTP and that makes the app vulnerable
to Man in the middle attacks.
languages:
- javascript
severity: ERROR
metadata:
owasp-web: a6
cwe: cwe-319
Genel olarak, eğitimsiz gözün kuralın ne yaptığını anlaması daha kolay görünüyor. Tabii ki, bu Semgrep’in evinde oynuyor; Aslında, bir Regex araması bile bunu başarabilirdi (dolayısıyla grep
Semgrep’te). Gerçek güvenlik açıklarını tanımlayan yüksek kaliteli kurallar için kanıtlama zemini leke takibidir. Semgrep sadece ücretli SemGrep Pro ürününde global leke takibi sunarken, Codeql bunu kutudan çıkarabilir.
Bunun nedeni, iki araç modelinin kaynak kodunun nasıl modellenmesidir. Semgrep, kodu genel bir soyut sözdizimi ağacı olarak ayırır ve temsil eder. Bu bir özet daha doğru bir şekilde etiketlenebilir semantik Ağaç çünkü anlamsal olarak eşdeğer kodu da çöker. Daha sonra, bu AST’yi Semgrep’in kural sözdiziminde kalıplarla eşleştirilebilen bir ara dile (IL) dönüştürür.
Bu ayrıştırma-ana-o zamana geçişe yaklaşım, dil desteği eklemeyi çok daha kolay hale getirir, çünkü yalnızca ayrıştırma adımı hakkında endişelenmeniz gerekir. Bununla birlikte, AST’ler leke takibi için en uygun değildir. Ağaç yapısı yönlendirilmiş bir grafik değildir, bu nedenle veri veya kontrol akışı hakkında doğrudan bilgi sağlayamaz; Bunun için bir veri akışı grafiğine (DFG) ve kontrol akış grafiğine (CFG) ihtiyacınız var. Ayrıştırma ve dönüşüm adımları, sınıf mirası ve küresel değişken yayılma gibi dile özgü davranışlar hakkında ayrıntıları da kaybeder. Bunların hepsi Semgrep’in leke izlemesi için tasarım ödünleşmelerine yansıyor:
- Yol Hassasiyeti Yok: Hepsi potansiyel Bazılarının mümkün olmasa da, yürütme yolları göz önünde bulundurulur.
- İşaretçi veya şekil analizi yok: Takma Bu önemsiz yollarla gerçekleşir, örneğin diziler veya işaretçiler gibi tespit edilemez. Dizilerdeki veya diğer veri yapılarındaki tek tek öğeler izlenmez. DataFlow motoru, leke izleme için sınırlı alan hassasiyetini destekler, ancak henüz sürekli yayılma için değil.
- Sağlamlık garantisi yok: Semgrep, etkilerini göz ardı ediyor
eval
-Program durumunda benzeri işlevler. En kötü durum ses varsayımları değil, daha ziyade “makul” olanlar.
Buna karşılık, Codeql, veri ve kontrol akışı dahil olmak üzere, dil ve kontrol akışı da dahil olmak üzere çok fazla ilişkisel veri çıkarmaya çalışır. Her dili jenerik bir AST’ye ayrıştırmak yerine, her dil için özel bir çıkarıcı çalıştırır. Derlenmiş diller için, derleyiciyi standart kütüphaneler gibi ek bilgileri ayıklamak için bile kullanır. Codeql’s’e hızlı bir göz atın go
ekstraktör. Her programlama dilinin bir QL sorgusunda kullanılabilecek kendi özel sınıfları vardır. Örneğin, Python Codeql kitaplığı Call
JavaScript varken işlev çağrıları için sınıf CallExpression
. Bu fark, her dilin sözdizimi adlandırma kurallarından kaynaklanır.
Codeql’in yaklaşımı, daha yüksek bir özgüllük ile daha derin sorgular yapmasına izin verir. Yerelden küresel analize ve veri akışından leke izlemeye geçerken bazı kayıplar olsa da, SEMGREP kadar fazla gücü (daha iyi bir kelime eksikliği nedeniyle) feda etmez. Vazgeçtiği şey, Semgrep’in yeni programlama dillerini hızlı bir şekilde destekleme ve her yerde koşma yeteneğidir; Derlenmiş bir dil kod tabanını tarıyorsanız ve oluşturma adımı başarısız olursa, saatlerce hata ayıklama ile karşılaşırsınız.
Bununla birlikte, hem güvenlik açığı araştırmalarında hem de devsecops bağlamında özel kurallar yazan biri olarak, temel endişem ön uç, yani kural sözdizimi ve kural yazma deneyimidir.
Kural yazma söz konusu olduğunda, Codeql’in QL’si nesne odaklı bir programlama dilidir. Bu gerçeği, tanıtım öğreticilerinden geçerken olabildiğince uzun süre önleyebilirsiniz, ancak prodüksiyona hazır kurallar yazmaya başladığınızda, gerçeklikle yüzleşmenin zamanı geldi. Genellikle kullanım örneklerinden yoksun olan ve alt tipler, (doğrudan ve dolaylı) süperpitler, dal türleri, sendika türleri vb. FileNameSourceAsSource
içinde semmle.javascript.security.dataflow.ShellCommandInjectionFromEnvironmentCustomizations
çalışır. Codeql, hile sayfalarına ve Boilerplate şablonlarına yardımcı olmaya çalışır, ancak QL yazmanın okuma kodundan büyük bir bağlam anahtarı gerektirdiği gerçeği devam etmektedir.
Buna karşılık, Semgrep’in desen sözdizimi, taradığınız gerçek koda çok benziyor. Kesin bir eşleşme ile başlayabilir, ardından kuralınızı genelleştirmek için değişken adlar ve diziler gibi genel öğeleri yavaş yavaş soyutlayabilirsiniz. Endişelenmene gerek yok programlama ve odaklanabilir eşleşen. Bununla birlikte, SEMGREP’in Codeql’in leke izleme yeteneğine yetişmeye çalışırken, karmaşık ilişkileri ifade etmek için kural sözdizimine gittikçe daha fazla eğildiğinden endişeliyim. Örneğin:
pattern-propagators:
- pattern: |
$TO.foo($FROM)
from: $FROM
to: $TO
requires: A
replace-labels: [A, C]
label: B
Burada etiketlerle neler olup bittiğini hemen belli değil. Codeql’in avantajı, veritabanı oluşturma adımında çok fazla leke izleme karmaşıklığının önden yüklenmesidir, oysa SemGREP, motorun nasıl çalıştığı için bu karmaşıklığı kural sözdizimine taşımak zorundadır. Ayrıca, desen odaklı bir sözdizimine karşı sorgu yönelimli bir ifadesi de vardır.
Codeql’in katil özelliği, genişletilmiş kurulum işlemini geçtikten sonra VS kodu uzantısıdır. CODEQL kuralları için bir IDE gibi bir şeye güzelce entegre olur, veritabanlarını yeniden oluşturmanıza ve kural bulgularını CLI yerine kullanıcı arayüzünden görselleştirmenize olanak tanır. Bunu, her bir taint adımı sonucu için koddaki konuma doğrudan tıklayabileceğiniz için, leke izleme sorgularını hata ayıklamak için özellikle yararlı buldum. Birim testleri, performans izleme ve AST görselleştirme gibi başka özelliklere sahiptir.
[Image from CodeQL documentation]
Semgrep’in yineleme için katil özelliği, aynı pencerede bir test kuralları yazmanıza izin veren bir web uygulaması olan Semgrep Playground’dur. Hataları hızlı bir şekilde düzeltebilmeniz için kuralınızla eşleştirilen kod satırlarını yararlı bir şekilde vurgular. Bir dezavantajı, tüm kodunuzu Semgrep’in yürütüldüğü API sunucusuna göndermesidir, bu nedenle SemGrep’i yerel olarak çalıştırmak kadar hızlı değildir ve hassas kodu anonimleştirmeniz gerekir. Neyse ki, SEMGREP kısa süre önce tarayıcıda WebAssembly kullanarak Semgrep’i çalıştıran bir turbo modu duyurdu, ancak henüz yayınlanmadı. Bu arada, SEMGREP’in vs kod uzantısı daha çok geliştiricilere ve SaaS entegrasyonuna odaklanmıştır ve Codeql vs kod uzantısının kuralları yerel olarak test etmeyi kolaylaştıran birçok özellikten yoksundur.
Semgrep kolayca kurulabilir pip
Paket, pencerelerde çalışmaz. Elbette, bunu Linux için Windows Subsytem’de çalıştırabilirsiniz, ancak WSL2, Linux VM’den monte edilen Windows dosya sistemine erişirken dosya G/Ç’de büyük bir performans hit alır. Ve evet, kaynak kodunu WSL2 dosya sistemine kopyalayabilirsiniz, ancak kurumsal ortamlarda WSL2 ile iyi oynamayan ağ paylaşımları ve VPN’lerle uğraşmanız gerekir. Makineniz pencereleri çalıştırıyorsa gereksiz bir sürtünme katmanı ekler.
Codeql’in ikili dosyaları Windows’ta çalışırken, kurulum biraz daha dahildir, çünkü özel sorgular yazmak için çalışma alanını düzgün bir şekilde yapılandırmanız gerekir. Masaüstünüzde bir QL kural dosyası oluşturmaya ve bir veritabanında çalıştırmaya çalışırsanız, büyük olasılıkla başarısız olur ERROR: Could not resolve module
. Bu, QL’nin aslında bir programlama dili olduğunu hatırlatıyor, çünkü bağımlılıkları bir qlpack.yml
önce dosya. Hiçbir yere kural yazamazsınız; “Codeql çalışma alanına” ihtiyacınız var. Keşke bir çeşit olsaydı create-react-app
Codeql kuralları için, ancak zaten çok fazla yük gibi geliyor.
Genel olarak, büyük ölçüde kod tabanlarını sorgulama yaklaşımından dolayı Semgrep kuralı yazmanın başlamasını daha kolay buluyorum. Hızlı bir kural yazabilir, yineleme yapabilir ve sonuçlara geçebilirim, CodeQL ise bir tavşan dokümantasyon ve hata ayıklama deliğine yol açabilir. Bununla birlikte, daha karmaşık leke izleme sorgularına doğru ilerledikçe, muhtemelen CodeQL ile çalışmaya başlamanız gerekir (veya SEMGREP Pro için Pay).
Çok fazla kod tarama ihtiyaçlarınıza da bağlıdır. Bir kuruluşun DevSecops boru hattı için bir dizi kural oluşturuyorsanız, taramaların kırılma (bir yapı adımı gibi) konusunda endişelenmeden büyük, çeşitli kod tabanlarıyla hızlı ve uyumlu olmasını istersiniz. Minimum yanlış pozitifler istiyorsunuz çünkü kimsenin uyarıları triaşacak zamanı yok. İdeal olarak, kural yazma görevlerini dağıtmak ve başkalarını eğitmeyi kolaylaştırmak istersiniz.
Öte yandan, bir pentester veya güvenlik açığı araştırmacısı yanlış pozitifleri ele alabilir; Daha az yanlış negatif olmayı tercih ediyorsunuz. Hız daha az bir sorundur, çünkü bir CI boru hattında yerine yerel olarak taramayı çalıştırıyorsunuz. Ayrıca daha küçük bir hedef setine, hatta tek bir kod tabanına da odaklanıyor olabilirsiniz. Karmaşık kural sözdizimini öğrenmeye daha fazla zaman ayırabilirsiniz.
Umarım bu, Codeql yazmanın neden SEMGREP kurallarına karşı yazmanın neden bu kadar farklı olduğunu açıklamaya yardımcı olur. Arka uçları hakkında ayrıntılara giren aşağıdaki materyalleri kontrol etmenizi öneririm.