id: js-libraries-detect info: name: Common JS Libraries - Detection author: adamparsons,cbadke,ChetGan,ErikOwen,jacalynli,geeknik severity: info description: Checks a target web app for inclusion of common JavaScript libraries metadata: max-request: 1 tags: headless,tech,js headless: - steps: - action: navigate args: url: "{{BaseURL}}" - action: waitload - action: script name: fingerprintAxios args: code: | () => { //check for axios if (!window.axios) { return "" } try { // check for version // only works on some websites return window.axios.VERSION } catch (e) {} return "Version not found" } - action: script name: fingerprintBootstrap args: code: | () => { try { // if not using jQuery return bootstrap.Tooltip.VERSION || "" } catch (e) {} try { // if using jQuery return $.fn.tooltip.Constructor.VERSION || "" } catch (e) {} return "" } - action: script name: fingerprintJQuery args: code: | () => { let version = ""; try { if(window.jQuery) { version = jQuery.fn.jquery; } if(window.$) { version = $.fn.jquery; } version = version.replace(".min", ""); version = version.replace(".slim", ""); return version; } catch (e) {} return ""; } - action: script name: fingerprintLodash args: code: | () => { try { return _.VERSION || ""; } catch (e) {} return ""; } - action: script name: fingerprintMomentJs args: code: | () => { try { return moment.version || ""; } catch (e) {} return ""; } - action: script name: fingerprintReact args: code: | () => { try { return window.React.version || ""; } catch (e) {} return ""; } - action: script name: fingerprintReactDOM args: code: | () => { try { if (window.ReactDOM) { return window.React.version || ""; } } catch (e) {} return ""; } - action: script name: fingerprintAngular args: code: | () => { try { // Angular Version 1 return angular.version.full } catch (e) {} try { // Angular Version 2+ return getAllAngularRootElements()[0].attributes["ng-version"].value } catch (e) {} return "" } - action: script name: fingerprintBackboneJs args: code: | () => { try { return window.Backbone.VERSION || "" } catch (e) {} return "" } - action: script name: fingerprintEmberJs args: code: | () => { try { return Ember.VERSION || "" } catch (e) {} return ""; } - action: script name: fingerprintVue args: code: | () => { //method 1 (simple) try { return Vue.version } catch (e) {} //method 2 (checks if Nuxt exists) try { const nuxtDetected = Boolean(window.__NUXT__ || window.$nuxt) if (nuxtDetected) { let Vue } if (window.$nuxt) { Vue = window.$nuxt.$root.constructor } return Vue.version } catch (e) {} //method 3 (go through all elements) try { const all = document.querySelectorAll('*') let flag for (let i = 0; i < all.length; i++) { if (all[i].__vue__) { flag = all[i] break } } if (flag) { let Vue = Object.getPrototypeOf(flag.__vue__).constructor while (Vue.super) { Vue = Vue.super } return Vue.version } return "" } catch (e) {} return "" } - action: script name: fingerprintDojoJs args: code: | () => { try { return ([dojo.version.major, dojo.version.minor, dojo.version.patch].join(".")) } catch (e) {} return "" } - action: script name: fingerprintDomPurify args: code: | () => { try { return DOMPurify.version || "" } catch (e) {} return "" } - action: script name: fingerprintModernizr args: code: | () => { try { return Modernizr._version || "" } catch (e) {} return "" } - action: script name: fingerprintD3 args: code: | () => { try { return d3.version || ""; } catch (e) {} return ""; } - action: script name: fingerprintThreeJs args: code: | () => { try { return THREE.REVISION || ""; } catch (e) {} return ""; } - action: script name: fingerprintChartJs args: code: | () => { try { return Chart.version || ""; } catch (e) {} return ""; } - action: script name: fingerprintSlick args: code: | () => { try { // Assuming Slick Carousel is used as a jQuery plugin return $.fn.slick.version || ""; } catch (e) {} return ""; } - action: script name: fingerprintSelect2 args: code: | () => { try { // Assuming Select2 is used as a jQuery plugin return $.fn.select2.version || ""; } catch (e) {} return ""; } matchers-condition: or matchers: - type: dsl dsl: - len(fingerprintAxios) > 0 - len(fingerprintBootstrap) > 0 - len(fingerprintJQuery) > 0 - len(fingerprintLodash) > 0 - len(fingerprintMomentJs) > 0 - len(fingerprintReact) > 0 - len(fingerprintReactDOM) > 0 - len(fingerprintAngular) > 0 - len(fingerprintBackboneJs) > 0 - len(fingerprintEmberJs) > 0 - len(fingerprintVue) > 0 - len(fingerprintDojoJs) > 0 - len(fingerprintDomPurify) > 0 - len(fingerprintModernizr) > 0 - len(fingerprintD3) > 0 - len(fingerprintThreeJs) > 0 - len(fingerprintChartJs) > 0 - len(fingerprintSlick) > 0 - len(fingerprintSelect2) > 0 extractors: - name: axios type: regex part: fingerprintAxios regex: - ^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$ - name: bootstrap type: regex part: fingerprintBootstrap regex: - ^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$ - name: jquery type: regex part: fingerprintJQuery regex: - ^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$ - name: lodash type: regex part: fingerprintLodash regex: - ^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$ - name: moment type: regex part: fingerprintMomentJs regex: - ^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$ - name: react type: regex part: fingerprintReact regex: - ^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$ - name: reactdom type: regex part: fingerprintReactDOM regex: - ^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$ - name: angular type: regex part: fingerprintAngular regex: - ^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$ - name: backbone type: regex part: fingerprintBackboneJs regex: - ^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$ - name: emberjs type: regex part: fingerprintEmberJs regex: - ^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$ - name: vuejs type: regex part: fingerprintVue regex: - ^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$ - name: dojo type: regex part: fingerprintDojoJs regex: - ^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$ - name: dompurify type: regex part: fingerprintDomPurify regex: - ^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$ - name: modernizr type: regex part: fingerprintModernizr regex: - ^(0|[1-9]\d*)(?:\.(0|[1-9]\d*))?(?:\.(0|[1-9]\d*))?(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$ - name: d3 type: regex part: fingerprintD3 regex: - "^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$" - name: threejs type: regex part: fingerprintThreeJs regex: - "^(0|[1-9]\\d*)$" - name: chartjs type: regex part: fingerprintChartJs regex: - "^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)$" - name: slick type: regex part: fingerprintSlick regex: - "^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)$" - name: select2 type: regex part: fingerprintSelect2 regex: - "^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)$" # digest: 4a0a00473045022079533719529f55f1e51b1f116812923cef7ec5a3a85d88e782a3fcefe130d627022100967c15f1e6ec4fdc6fead7fdbc0944e6e33903ff5827f60a5e3fbf42668a1743:922c64590222798bb761d5b6d8e72950