2023-10-28 07:43:15 +00:00
|
|
|
id: js-libraries-detect
|
2023-10-25 23:10:30 +00:00
|
|
|
|
|
|
|
info:
|
2023-10-28 07:43:15 +00:00
|
|
|
name: Common JS Libraries - Detection
|
2023-10-25 23:10:30 +00:00
|
|
|
author: adamparsons,cbadke,ChetGan,ErikOwen,jacalynli
|
|
|
|
severity: info
|
2023-10-28 07:43:15 +00:00
|
|
|
description: Checks a target web app for inclusion of common JavaScript libraries
|
2023-10-25 23:10:30 +00:00
|
|
|
metadata:
|
|
|
|
max-request: 1
|
2023-10-28 07:43:15 +00:00
|
|
|
tags: headless,tech,js
|
2024-01-04 06:27:45 +00:00
|
|
|
|
2023-10-25 23:10:30 +00:00
|
|
|
headless:
|
|
|
|
- steps:
|
|
|
|
- action: navigate
|
|
|
|
args:
|
|
|
|
url: "{{BaseURL}}"
|
|
|
|
|
|
|
|
- action: waitload
|
2023-10-25 23:42:03 +00:00
|
|
|
|
2023-10-25 23:10:30 +00:00
|
|
|
- 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"
|
|
|
|
}
|
2023-10-28 07:43:15 +00:00
|
|
|
|
2023-10-25 23:10:30 +00:00
|
|
|
- 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 ""
|
|
|
|
}
|
2023-10-28 07:43:15 +00:00
|
|
|
|
2023-10-25 23:10:30 +00:00
|
|
|
- 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 "";
|
|
|
|
}
|
2023-10-28 07:43:15 +00:00
|
|
|
|
2023-10-25 23:10:30 +00:00
|
|
|
- action: script
|
|
|
|
name: fingerprintLodash
|
|
|
|
args:
|
|
|
|
code: |
|
|
|
|
() => {
|
|
|
|
try {
|
|
|
|
return _.VERSION || "";
|
|
|
|
} catch (e) {}
|
|
|
|
return "";
|
|
|
|
}
|
2023-10-28 07:43:15 +00:00
|
|
|
|
2023-10-25 23:10:30 +00:00
|
|
|
- action: script
|
|
|
|
name: fingerprintMomentJs
|
|
|
|
args:
|
|
|
|
code: |
|
|
|
|
() => {
|
|
|
|
try {
|
|
|
|
return moment.version || "";
|
|
|
|
} catch (e) {}
|
|
|
|
return "";
|
|
|
|
}
|
2023-10-28 07:43:15 +00:00
|
|
|
|
2023-10-25 23:10:30 +00:00
|
|
|
- action: script
|
|
|
|
name: fingerprintReact
|
|
|
|
args:
|
|
|
|
code: |
|
|
|
|
() => {
|
|
|
|
try {
|
|
|
|
return window.React.version || "";
|
|
|
|
} catch (e) {}
|
|
|
|
return "";
|
|
|
|
}
|
2023-10-28 07:43:15 +00:00
|
|
|
|
2023-10-25 23:10:30 +00:00
|
|
|
- action: script
|
|
|
|
name: fingerprintReactDOM
|
|
|
|
args:
|
|
|
|
code: |
|
|
|
|
() => {
|
|
|
|
try {
|
|
|
|
if (window.ReactDOM) {
|
|
|
|
return window.React.version || "";
|
|
|
|
}
|
|
|
|
} catch (e) {}
|
|
|
|
return "";
|
|
|
|
}
|
2023-10-28 07:43:15 +00:00
|
|
|
|
2023-10-25 23:10:30 +00:00
|
|
|
- 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 ""
|
|
|
|
}
|
2023-10-28 07:43:15 +00:00
|
|
|
|
2023-10-25 23:10:30 +00:00
|
|
|
- action: script
|
|
|
|
name: fingerprintBackboneJs
|
|
|
|
args:
|
|
|
|
code: |
|
|
|
|
() => {
|
|
|
|
|
|
|
|
try {
|
|
|
|
return window.Backbone.VERSION || ""
|
|
|
|
} catch (e) {}
|
|
|
|
return ""
|
|
|
|
}
|
2023-10-28 07:43:15 +00:00
|
|
|
|
2023-10-25 23:10:30 +00:00
|
|
|
- action: script
|
|
|
|
name: fingerprintEmberJs
|
|
|
|
args:
|
|
|
|
code: |
|
|
|
|
() => {
|
|
|
|
try {
|
|
|
|
return Ember.VERSION || ""
|
|
|
|
} catch (e) {}
|
|
|
|
return "";
|
|
|
|
}
|
2023-10-28 07:43:15 +00:00
|
|
|
|
2023-10-25 23:10:30 +00:00
|
|
|
- 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 ""
|
2023-10-25 23:42:03 +00:00
|
|
|
} catch (e) {}
|
2023-10-25 23:10:30 +00:00
|
|
|
return ""
|
|
|
|
}
|
2023-10-28 07:43:15 +00:00
|
|
|
|
2023-10-25 23:10:30 +00:00
|
|
|
- action: script
|
|
|
|
name: fingerprintDojoJs
|
|
|
|
args:
|
|
|
|
code: |
|
|
|
|
() => {
|
|
|
|
try {
|
|
|
|
return ([dojo.version.major, dojo.version.minor, dojo.version.patch].join("."))
|
|
|
|
} catch (e) {}
|
|
|
|
return ""
|
|
|
|
}
|
2023-10-28 07:43:15 +00:00
|
|
|
|
2023-10-25 23:10:30 +00:00
|
|
|
- action: script
|
|
|
|
name: fingerprintDomPurify
|
|
|
|
args:
|
|
|
|
code: |
|
|
|
|
() => {
|
|
|
|
try {
|
|
|
|
return DOMPurify.version || ""
|
|
|
|
} catch (e) {}
|
|
|
|
return ""
|
|
|
|
}
|
2023-10-28 07:43:15 +00:00
|
|
|
|
2023-10-25 23:10:30 +00:00
|
|
|
- action: script
|
|
|
|
name: fingerprintModernizr
|
|
|
|
args:
|
|
|
|
code: |
|
|
|
|
() => {
|
|
|
|
try {
|
|
|
|
return Modernizr._version || ""
|
|
|
|
} catch (e) {}
|
|
|
|
return ""
|
|
|
|
}
|
2023-10-25 23:42:03 +00:00
|
|
|
|
2023-10-25 23:10:30 +00:00
|
|
|
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
|
|
|
|
|
|
|
|
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-]+)*))?$
|
2023-10-28 07:43:15 +00:00
|
|
|
|
2023-10-25 23:10:30 +00:00
|
|
|
- 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-]+)*))?$
|
2023-10-28 07:43:15 +00:00
|
|
|
|
2023-10-25 23:10:30 +00:00
|
|
|
- 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-]+)*))?$
|
2023-10-28 07:43:15 +00:00
|
|
|
|
2023-10-25 23:10:30 +00:00
|
|
|
- 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-]+)*))?$
|
2023-10-28 07:43:15 +00:00
|
|
|
|
2023-10-25 23:10:30 +00:00
|
|
|
- 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-]+)*))?$
|
2023-10-28 07:43:15 +00:00
|
|
|
|
2023-10-25 23:10:30 +00:00
|
|
|
- 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-]+)*))?$
|
2023-10-28 07:43:15 +00:00
|
|
|
|
2023-10-25 23:10:30 +00:00
|
|
|
- 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-]+)*))?$
|
2023-10-28 07:43:15 +00:00
|
|
|
|
2023-10-25 23:10:30 +00:00
|
|
|
- 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-]+)*))?$
|
2023-10-28 07:43:15 +00:00
|
|
|
|
2023-10-25 23:10:30 +00:00
|
|
|
- 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-]+)*))?$
|
2023-10-28 07:43:15 +00:00
|
|
|
|
2023-10-25 23:42:03 +00:00
|
|
|
- name: emberjs
|
2023-10-25 23:10:30 +00:00
|
|
|
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-]+)*))?$
|
2023-10-28 07:43:15 +00:00
|
|
|
|
2023-10-25 23:10:30 +00:00
|
|
|
- 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-]+)*))?$
|
2023-10-28 07:43:15 +00:00
|
|
|
|
2023-10-25 23:10:30 +00:00
|
|
|
- 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-]+)*))?$
|
2023-10-28 07:43:15 +00:00
|
|
|
|
2023-10-25 23:10:30 +00:00
|
|
|
- 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-]+)*))?$
|
2023-10-28 07:43:15 +00:00
|
|
|
|
2023-10-25 23:42:03 +00:00
|
|
|
- name: modernizr
|
2023-10-25 23:10:30 +00:00
|
|
|
type: regex
|
|
|
|
part: fingerprintModernizr
|
|
|
|
regex:
|
2023-10-28 07:43:15 +00:00
|
|
|
- ^(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-]+)*))?$
|
2024-01-04 06:57:22 +00:00
|
|
|
# digest: 490a0046304402204106a779627713aa63ece4bc679f6b08764d94f26d55ca7482a8135cb4a99f89022074e3eff829289082075eb2b6443484212d58cec4ff2a607952e6cd04d73651bc:922c64590222798bb761d5b6d8e72950
|