Merhabalar,

Saldırı vektörlerinin tespitinde WAF uygulamaları blacklist/whitelist tabanlı çalışmakta. Bu yaklaşımları WAF’ın öğrenme moduyla birlikte kullandığımızda otomatik olarak atak vektörü eklememiz mümkün olabiliyor. Bu bağlamda Rus güvenlik araştırmacıları Denis Kolegov ve Arseny Reutov WAF’ların öğrenme moduna katkı sağlayacak bir yapıyı client-side fazında nasıl geliştiririz sorusunun cevabını aramışlar ve AST dediğimiz yapı ile buna bir çözüm üretmişler.

Özetle, tespit aşamasının özünde AST yapısı yatıyor. Bu kısmı biraz anlamaya çalışalım. Bu konuda uzman değilim fakat referanslarda belirttiğim kaynakları incelemeye çalıştım.

AST (Abstract Syntax Tree) nedir?

Programla dillerinde yazılan komutların anlaşılması için ilk olarak parsing işleminin gerçekleşmesi gerekmektedir. Bir kodun anlamlı küçük parçalara ayrılmasında lexer görev alır. Bu aşamada kod token haline getirilir ve sonraki aşamada ise parser’a geçerek lexer’dan aldığı tokenlar ile gramer yapısını doğrular ve sonucunda AST kodunu ortaya çıkartır. Bu yapının anlaşılması adına bir örnekle devam edelim.

var x= 34; kod parçası doğru bir gramere sahiptir. İlgili değişken için bir Online bir araçla AST analizi yaptığımızda aşağıdaki gibi bir sonuca ulaşmaktayız.

Token Yapısı şu şekilde: Keyword(var) Identifier(x) Punctuator(=) Numeric(34) Punctuator(;)

ast1
AST Grafiği (http://resources.jointjs.com/demos/javascript-ast)

Görüldüğü gibi boşluklar dışındaki değerler token olarak belirlendi. Eğer JavaScript’in syntaxını doğru bir şekilde yazmazsak hata verecekti. İlk olarak basit bir JavaScript kodu denedik. Şimdi bir tane XSS atak vektörü kullanarak AST çıktısını incelemeye çalışalım.

Kaynak kodumuzdaki taslağımızda var a = "BURAYAPAYLOADGELECEK"; şeklinde bir Js kodu olduğunu varsayalım ve bu değişkene kullanıcıdan değer gönderilebildiğini varsayalım.Saldırgandan gelen isteği öyle bir yazmalıyız ki mevcut syntax’i bozmayacak şekilde olmalı.

Mesela şu şekilde var a = " BURAYAPAYLOADGELECEK" "; bir istek attığımızı düşünelim. “Unexpected token ILLEGAL” gibi bir hata alacağız ve JavaScript çalışmayacak. Saldırgan kodu şu şekilde yazsın. var a = "";alert(1)//"; Bu tasklaktaki atak vektörü de şu şekilde ";alert(1)//

Atak vektörünü böyle yazdığımızda AST çıktısını alabildik. Bu şu demek oluyor; Saldırgan anlamlı bir kod yapısı oluşturabildiği için alert() fonksiyonunu çalıştırabildi.

Peki bu atak vektörünün AST çıktısı nasıl, online bir AST aracıyla inceleyelim.

ast2
AST Grafiği (http://resources.jointjs.com/demos/javascript-ast)

Ağaç yapısına baktığımızda bir önceki ağaç yapısından farklı olarak ExpressionStatement kısmı ilgimizi çekiyor. Callexpression node değerinde alert fonksiyonunu görebiliyorsunuz. Callexpression bize davranışsal analiz aşaması için yol gösteriyor. Bunun dışında aşağıdaki durumları da bilmekte fayda var.

Bu noktalar başka bir blog yazısının konusu diyelim ve devam edelim.

Şu an elimizde şöyle bir bilgi var. Eğer saldırgan belirtilen JavaScript kodunun gramerini doğru bir şekilde oluşturursa AST çıktısı alabiliriz..

Bu noktada tespit aşaması için Esprima parserı kullanarak neler yapabileceğimizi inceleyelim. Aşağıdaki kod parçasında mevcut taslak için Esprima parserını kullandık.

var esprima =  require('esprima');

var buf = new Buffer(process.argv[2], 'base64').toString('ascii');
console.log("Payload: " + buf); 
var b = "var x =\"" + buf + "\"";
console.log("Template: " + b);


esprima.parseScript(b, { comment: true }, function (node) {
    if (node.type === 'CallExpression') {
    console.log("XSS tespit edildi");
    }   
});

Kodun şu kısmında, ilgili node CallExpression ile eşleşirse XSS atak vektörünü tespit edebiliyoruz.

esprima.parseScript(b, { comment: true }, function (node) {
    if (node.type === 'CallExpression') {
    console.log("XSS tespit edildi");
    }   
});

Saldırgan popup çıkartmak için alert dışında başka fonksiyonlarda kullanabilir. Mesela console.log atak vektörü. Yine aynı taslak için deneyelim.

ast3
AST Grafiği (http://resources.jointjs.com/demos/javascript-ast)

Evet görüldüğü gibi bu çıktıyla da CallExpression’ı gözlemledik. Bunun dışında, bazı evasion’lar için yine CallExpression node bilgisine ulaşabiliyoruz.

$.globalEval("al"+"ert()");

ama aşağıdaki gibi bir evasion için NewExpression kullanıldığını görüyoruz.

new Function`al\ert\`1\``

Başka bir evasion örneği için TaggedTemplateExpression kullanılmış

setTimeout`\x64ocument.write\x28\x64ocument.\x63ookie\x29`

Bunun gibi çok sayıda atak vektörü denemesi yapılabilir. Sonuç olarak AST yaklaşımı ile;

  • 0dayclient-side ataklarını tespit edebilmek
  • Katmanlı güvenlik mimarisi oluşturabilmek

mümkün olabilir.

Faydalı olması dileğiyle.

Bu yazıda emeği geçen @A_Burak_Gokalp ‘a teşekkürler.


Referanslar :

https://speakerdeck.com/dnkolegov/waf-dot-js-how-to-protect-web-applications-using-javascript

https://medium.com/basecs/leveling-up-ones-parsing-game-with-asts-d7a6fc2400ff

https://www.slideshare.net/JarrodOverson/javascript-asts-transformations-analysis-and-transpiling

https://developer.mozilla.org/en-US/docs/Mozilla/Projects/SpiderMonkey/Parser_API

https://www.slideshare.net/JamundFerguson/ui-40829744

https://jotadeveloper.com/blog/2016/03/19/abstract-syntax-trees-on-javascript/

https://zhuanlan.zhihu.com/p/32189701

https://itnext.io/ast-for-javascript-developers-3e79aeb08343

http://tobyho.com/2013/12/02/fun-with-esprima/

https://ariya.io/2016/12/on-the-fly-javascript-syntax-node-inspection

https://stackoverflow.com/questions/47972903/difference-between-callexpression-and-memberexpression

http://www.ecma-international.org/ecma-262/5.1/

https://esprima.org/demo/parse.html?code=

https://tomnomnom.com/talks/advxss.pdf

https://github.com/0xInfection/Awesome-WAF

https://medium.com/basecs/leveling-up-ones-parsing-game-with-asts-d7a6fc2400ff

https://gist.github.com/myshov/05800f083a0afce56e0f782314a103eb#file-function_invocation-js

https://yehudakatz.com/2011/08/11/understanding-javascript-function-invocation-and-this/

http://resources.jointjs.com/demos/javascript-ast

https://blog.sessionstack.com/how-javascript-works-parsing-abstract-syntax-trees-asts-5-tips-on-how-to-minimize-parse-time-abfcf7e8a0c8

https://blog.buildo.io/a-tour-of-abstract-syntax-trees-906c0574a067

https://twitter.com/c0mr3x/status/1149284940028272640?s=19

https://ysar.net/python/parsing-parser-topdown-operator-precedence.html

https://medium.com/@sddkal/python-ile-python-lexer-yazal%C4%B1m-1447d0b23dc3