@@ -2,6 +2,7 @@ package webscans
22
33import (
44 "bytes"
5+ "context"
56 "encoding/json"
67 "fmt"
78 "io"
@@ -20,6 +21,7 @@ import (
2021 "oott/lib"
2122
2223 "github.com/PuerkitoBio/goquery"
24+ "github.com/chromedp/chromedp"
2325)
2426
2527type Technology struct {
@@ -358,6 +360,26 @@ func (wp *Wappalyzer) scanWappalyzerScanByUrl(domain string, urlStr string, tech
358360 if err != nil {
359361 return result , err
360362 }
363+
364+ // Check if any technologies have JavaScript patterns to evaluate
365+ jsNeeded := false
366+ for _ , tech := range technologies {
367+ if tech .Js != nil && len (tech .Js ) > 0 {
368+ jsNeeded = true
369+ break
370+ }
371+ }
372+
373+ // Run JavaScript scanning if any technology has Js patterns
374+ if jsNeeded {
375+ helper .InfoPrintf ("[Wappalyzer] JavaScript scanning needed for %s\n " , domain )
376+ jsTechs , jsErr := wp .scanJsExpressions (domain , urlStr , technologies )
377+ if jsErr == nil && len (jsTechs ) > 0 {
378+ result .Technologies = wp .appendDistinct (result .Technologies , jsTechs )
379+ } else if jsErr != nil {
380+ helper .ErrorPrintf ("[!] Error during JavaScript scanning: %v\n " , jsErr )
381+ }
382+ }
361383
362384 // Assign status code to result
363385 result .StatusCode = strconv .Itoa (resp .StatusCode )
@@ -677,7 +699,7 @@ func (wp *Wappalyzer) ScanWebsites(domains []string) ([]WebsiteDetails, error) {
677699
678700 var data []byte
679701 var err error
680- if ! skipDownload {
702+ if ( ! skipDownload ) {
681703 data , err = wp .downloadJSON (url , lib .Config .Tmpfolder + fileName )
682704 if err != nil {
683705 helper .ErrorPrintf ("[!] Error downloading JSON file %s. Read the default files... Error: %v\n " , fileName , err )
@@ -782,3 +804,85 @@ func (wp *Wappalyzer) ScanWebsites(domains []string) ([]WebsiteDetails, error) {
782804
783805 return websiteDetails , nil
784806}
807+
808+ func (wp * Wappalyzer ) scanJsExpressions (domain string , urlStr string , technologies map [string ]Technology ) ([]WebsiteDetailTechnology , error ) {
809+ helper .InfoPrintln ("[Wappalyzer] Starting JavaScript scanning for:" , urlStr )
810+
811+ // Create a lightweight headless browser using chromedp
812+ opts := append (chromedp .DefaultExecAllocatorOptions [:],
813+ chromedp .Flag ("headless" , true ),
814+ chromedp .Flag ("disable-gpu" , true ),
815+ chromedp .Flag ("no-sandbox" , true ),
816+ chromedp .Flag ("disable-dev-shm-usage" , true ),
817+ )
818+
819+ ctx , cancel := chromedp .NewExecAllocator (context .Background (), opts ... )
820+ defer cancel ()
821+
822+ ctx , cancel = chromedp .NewContext (ctx )
823+ defer cancel ()
824+
825+ // Set a reasonable timeout
826+ ctx , cancel = context .WithTimeout (ctx , 15 * time .Second )
827+ defer cancel ()
828+
829+ var detectedTechs []WebsiteDetailTechnology
830+
831+ // Navigate to the URL
832+ if err := chromedp .Run (ctx , chromedp .Navigate (urlStr )); err != nil {
833+ return nil , fmt .Errorf ("failed to navigate to %s: %v" , urlStr , err )
834+ }
835+
836+ // Process technologies with JS patterns
837+ for name , tech := range technologies {
838+ if tech .Js == nil || len (tech .Js ) == 0 {
839+ continue
840+ }
841+
842+ for jsPath , jsPattern := range tech .Js {
843+ var jsResult string
844+
845+ // Build the script to evaluate the JS variable
846+ script := fmt .Sprintf (`
847+ function getVersion() {
848+ try {
849+ const jsVar = %s;
850+ if (jsVar !== undefined) {
851+ return String(jsVar);
852+ }
853+ return null;
854+ } catch (e) {
855+ return null;
856+ }
857+ }
858+ getVersion();
859+ ` , jsPath )
860+
861+ // Execute the script
862+ err := chromedp .Run (ctx , chromedp .Evaluate (script , & jsResult ))
863+ if err != nil {
864+ helper .VerbosePrintf ("[Wappalyzer] Error evaluating JS path %s: %v\n " , jsPath , err )
865+ continue
866+ }
867+
868+ // If we got a result, check if it matches the pattern
869+ if jsResult != "" && jsResult != "null" {
870+ helper .VerbosePrintln ("[-] JS Scan result:" ,jsPath , "->" , jsResult )
871+ matches , err := wp .matchingWithModification (jsPattern , jsResult )
872+ if err != nil {
873+ helper .ErrorPrintf ("[!] Error matching JS pattern for technology %s: %v\n " , name , err )
874+ continue
875+ }
876+
877+ if len (matches ) > 0 {
878+ helper .InfoPrintf ("[Wappalyzer] Domain [%s] JS matched for technology: %s\n " , domain , name )
879+ helper .VerbosePrintln ("[-] JS Match result:" ,jsPattern , "->" , matches )
880+
881+ detectedTechs = wp .appendToTechnology (detectedTechs , name , matches )
882+ }
883+ }
884+ }
885+ }
886+
887+ return detectedTechs , nil
888+ }
0 commit comments