@shriyanss/js-recon 1.0.0 → 1.1.0-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (143) hide show
  1. package/.github/workflows/build-and-prettify.yaml +65 -0
  2. package/.github/workflows/npm-publish.yml +35 -0
  3. package/.prettierignore +2 -0
  4. package/.prettierrc +4 -0
  5. package/CHANGELOG.md +50 -0
  6. package/README.md +35 -139
  7. package/build/api_gateway/checkFeasibility.js +32 -0
  8. package/build/api_gateway/checkFeasibility.js.map +1 -0
  9. package/build/api_gateway/checkFireWallBlocking.js +24 -0
  10. package/build/api_gateway/checkFireWallBlocking.js.map +1 -0
  11. package/build/api_gateway/genReq.js +199 -0
  12. package/build/api_gateway/genReq.js.map +1 -0
  13. package/build/api_gateway/index.js +275 -0
  14. package/build/api_gateway/index.js.map +1 -0
  15. package/build/endpoints/gen_report/gen_json.js +22 -0
  16. package/build/endpoints/gen_report/gen_json.js.map +1 -0
  17. package/build/endpoints/gen_report/gen_markdown.js +66 -0
  18. package/build/endpoints/gen_report/gen_markdown.js.map +1 -0
  19. package/build/endpoints/gen_report/utility/iterate_n_store.js +46 -0
  20. package/build/endpoints/gen_report/utility/iterate_n_store.js.map +1 -0
  21. package/build/endpoints/index.js +89 -0
  22. package/build/endpoints/index.js.map +1 -0
  23. package/build/endpoints/next_js/client_jsFilesHref.js +91 -0
  24. package/build/endpoints/next_js/client_jsFilesHref.js.map +1 -0
  25. package/build/endpoints/next_js/client_jsonParse.js +78 -0
  26. package/build/endpoints/next_js/client_jsonParse.js.map +1 -0
  27. package/build/endpoints/next_js/client_subsequentRequests.js +199 -0
  28. package/build/endpoints/next_js/client_subsequentRequests.js.map +1 -0
  29. package/build/endpoints/next_js/getWebpacks.js +45 -0
  30. package/build/endpoints/next_js/getWebpacks.js.map +1 -0
  31. package/build/globalConfig.js +11 -0
  32. package/build/globalConfig.js.map +1 -0
  33. package/build/index.js +166 -0
  34. package/build/index.js.map +1 -0
  35. package/build/lazyLoad/downloadFilesUtil.js +128 -0
  36. package/build/lazyLoad/downloadFilesUtil.js.map +1 -0
  37. package/build/lazyLoad/downloadLoadedJsUtil.js +51 -0
  38. package/build/lazyLoad/downloadLoadedJsUtil.js.map +1 -0
  39. package/build/lazyLoad/globals.js +22 -0
  40. package/build/lazyLoad/globals.js.map +1 -0
  41. package/build/lazyLoad/index.js +170 -0
  42. package/build/lazyLoad/index.js.map +1 -0
  43. package/build/lazyLoad/next_js/next_GetJSScript.js +94 -0
  44. package/build/lazyLoad/next_js/next_GetJSScript.js.map +1 -0
  45. package/build/lazyLoad/next_js/next_GetLazyResources.js +202 -0
  46. package/build/lazyLoad/next_js/next_GetLazyResources.js.map +1 -0
  47. package/build/lazyLoad/next_js/next_SubsequentRequests.js +120 -0
  48. package/build/lazyLoad/next_js/next_SubsequentRequests.js.map +1 -0
  49. package/build/lazyLoad/nuxt_js/nuxt_astParse.js +188 -0
  50. package/build/lazyLoad/nuxt_js/nuxt_astParse.js.map +1 -0
  51. package/build/lazyLoad/nuxt_js/nuxt_getFromPageSource.js +75 -0
  52. package/build/lazyLoad/nuxt_js/nuxt_getFromPageSource.js.map +1 -0
  53. package/build/lazyLoad/nuxt_js/nuxt_stringAnalysisJSFiles.js +94 -0
  54. package/build/lazyLoad/nuxt_js/nuxt_stringAnalysisJSFiles.js.map +1 -0
  55. package/build/lazyLoad/svelte/svelte_getFromPageSource.js +68 -0
  56. package/build/lazyLoad/svelte/svelte_getFromPageSource.js.map +1 -0
  57. package/build/lazyLoad/svelte/svelte_stringAnalysisJSFiles.js +95 -0
  58. package/build/lazyLoad/svelte/svelte_stringAnalysisJSFiles.js.map +1 -0
  59. package/build/map/index.js +58 -0
  60. package/build/map/index.js.map +1 -0
  61. package/build/map/next_js/getFetchInstances.js +108 -0
  62. package/build/map/next_js/getFetchInstances.js.map +1 -0
  63. package/build/map/next_js/getWebpackConnections.js +227 -0
  64. package/build/map/next_js/getWebpackConnections.js.map +1 -0
  65. package/build/map/next_js/interactive.js +32 -0
  66. package/build/map/next_js/interactive.js.map +1 -0
  67. package/build/map/next_js/interactive_helpers/commandHandler.js +190 -0
  68. package/build/map/next_js/interactive_helpers/commandHandler.js.map +1 -0
  69. package/build/map/next_js/interactive_helpers/commandHelpers.js +91 -0
  70. package/build/map/next_js/interactive_helpers/commandHelpers.js.map +1 -0
  71. package/build/map/next_js/interactive_helpers/helpMenu.js +11 -0
  72. package/build/map/next_js/interactive_helpers/helpMenu.js.map +1 -0
  73. package/build/map/next_js/interactive_helpers/keybindings.js +80 -0
  74. package/build/map/next_js/interactive_helpers/keybindings.js.map +1 -0
  75. package/build/map/next_js/interactive_helpers/printer.js +17 -0
  76. package/build/map/next_js/interactive_helpers/printer.js.map +1 -0
  77. package/build/map/next_js/interactive_helpers/ui.js +81 -0
  78. package/build/map/next_js/interactive_helpers/ui.js.map +1 -0
  79. package/build/map/next_js/resolveFetch.js +201 -0
  80. package/build/map/next_js/resolveFetch.js.map +1 -0
  81. package/build/run/index.js +62 -0
  82. package/build/run/index.js.map +1 -0
  83. package/build/strings/index.js +238 -0
  84. package/build/strings/index.js.map +1 -0
  85. package/build/strings/openapi.js +55 -0
  86. package/build/strings/openapi.js.map +1 -0
  87. package/build/strings/permutate.js +55 -0
  88. package/build/strings/permutate.js.map +1 -0
  89. package/build/strings/secrets.js +89 -0
  90. package/build/strings/secrets.js.map +1 -0
  91. package/build/techDetect/index.js +229 -0
  92. package/build/techDetect/index.js.map +1 -0
  93. package/build/utility/ai.js +69 -0
  94. package/build/utility/ai.js.map +1 -0
  95. package/build/utility/globals.js +84 -0
  96. package/build/utility/globals.js.map +1 -0
  97. package/build/utility/interfaces.js +2 -0
  98. package/build/utility/interfaces.js.map +1 -0
  99. package/build/utility/makeReq.js +265 -0
  100. package/build/utility/makeReq.js.map +1 -0
  101. package/build/utility/resolvePath.js +44 -0
  102. package/build/utility/resolvePath.js.map +1 -0
  103. package/{utility → build/utility}/runSandboxed.js +10 -13
  104. package/build/utility/runSandboxed.js.map +1 -0
  105. package/{utility → build/utility}/urlUtils.js +9 -11
  106. package/build/utility/urlUtils.js.map +1 -0
  107. package/docs/CNAME +1 -0
  108. package/docs/README.md +20 -0
  109. package/docs/api-gateway.md +68 -0
  110. package/docs/endpoints.md +49 -0
  111. package/docs/example-scenario.md +258 -0
  112. package/docs/interactive-mode.md +76 -0
  113. package/docs/lazyload.md +56 -0
  114. package/docs/map.md +53 -0
  115. package/docs/run.md +54 -0
  116. package/docs/strings.md +75 -0
  117. package/package.json +50 -38
  118. package/api_gateway/checkFeasibility.js +0 -25
  119. package/api_gateway/checkFireWallBlocking.js +0 -17
  120. package/api_gateway/genReq.js +0 -214
  121. package/api_gateway/index.js +0 -325
  122. package/endpoints/index.js +0 -7
  123. package/globalConfig.js +0 -12
  124. package/index.js +0 -69
  125. package/lazyLoad/downloadFilesUtil.js +0 -122
  126. package/lazyLoad/downloadLoadedJsUtil.js +0 -54
  127. package/lazyLoad/globals.js +0 -15
  128. package/lazyLoad/index.js +0 -167
  129. package/lazyLoad/next_js/next_GetJSScript.js +0 -99
  130. package/lazyLoad/next_js/next_GetLazyResources.js +0 -201
  131. package/lazyLoad/next_js/next_SubsequentRequests.js +0 -138
  132. package/lazyLoad/nuxt_js/nuxt_astParse.js +0 -194
  133. package/lazyLoad/nuxt_js/nuxt_getFromPageSource.js +0 -77
  134. package/lazyLoad/nuxt_js/nuxt_stringAnalysisJSFiles.js +0 -99
  135. package/research/firewall_bypass.md +0 -38
  136. package/research/next_js.md +0 -116
  137. package/research/nuxt_js.md +0 -125
  138. package/research/vue_js.md +0 -9
  139. package/strings/index.js +0 -145
  140. package/techDetect/index.js +0 -156
  141. package/utility/globals.js +0 -6
  142. package/utility/makeReq.js +0 -179
  143. package/utility/resolvePath.js +0 -43
@@ -1,38 +0,0 @@
1
- # Firewall Bypass
2
- While the development of this tool, the tester came across several websites using firewall, majorly Cloudflare. A technique has to be developed to bypass this blockage, and to download the JS files.
3
-
4
- ## Cloudflare
5
- ### Detection
6
- Whenever the client is restricted by Cloudflare, it returns a HTML page with a JS challenge to be solved. However, the JS is can't be executed by Node.JS. It would need a browser environment. Sample HTML page is shown below:
7
-
8
- ```html
9
- <meta http-equiv="refresh"
10
- content="5; URL='/?bm-verify=--snip--'" />
11
- --snip--
12
- <script> var i = 1749580415; var j = i + Number("7341" + "47171"); </script>
13
- --snip--
14
- <script> var xhr = new XMLHttpRequest(); xhr.withCredentials = true; xhr.addEventListener("loadend", function () { try { var data = JSON.parse(xhr.responseText); if (data.hasOwnProperty('reload')) { if (data["reload"] == true) { window.location.replace(window.location.href.replace(/[&?]bm-verify=[^#]*/, "")); if (window.location.hash) { window.location.reload(); } } } else if (data.hasOwnProperty(--snip </script>
15
- ```
16
-
17
- ### Bypass
18
- #### #1
19
- The most common way to bypass this is to use a browser environment, such as a headless browser.
20
-
21
- To achive this task, a detection mechanism is added in the custom function to make HTTP requests. If CF is detected, it will load the page in a headless browser, and then return the content.
22
-
23
- #### #2
24
- Utilizing a browser plugin to fetch the contents is a more advanced way to bypass this. The user can install the plugin in their testing browser/proxy, and as they navigate the site, the plugin will get the contents and send then to the server for processing (it would be like a caching system).
25
-
26
- #### #3
27
- The `makeRequest()` can be modified to send headers that a browser would send. These include:
28
- - `User-Agent` of a browser
29
- - `Accept`
30
- - `Accept-Language`
31
- - `Sec-Fetch-Site: same-origin`
32
- - `Sec-Fetch-Mode: cors`
33
- - `Sec-Fetch-Dest: empty`
34
- - `Referer`
35
- - `Origin`
36
-
37
- #### #4
38
- Utilizing AWS API Gateway or similar services to rotate IP addresses can help in bypassing the firewall. This, however, could be blocked by the by CF if it is configured to block requests from AWS or similar ISPs.
@@ -1,116 +0,0 @@
1
- # Next.js Research
2
- ## Tech Detection
3
- To detect Next.js, following technique(s) can be used:
4
- - Iterate through all the HTML tags, and find `src`, `srcSet` or `imageSrcSet` attribute with value starting with`/_next/` in the page source
5
-
6
- ## Embedded JS files
7
- A lot of JS files were identified from the page source by inspecting the value of `src` attribute of `script` tags. These included files like `main.js`, `polyfills.js`, `webpack.js` etc.
8
-
9
- ## Lazy Loaded Files
10
- ### Analysis of [Vercel Docs](https://vercel.com/docs)
11
- Upon analysis of page source and HTTP requests, it was found that the webpack filename had a pattern of `webpack-<hash>.js`. So, webpack JS files were identified and fetched.
12
-
13
- Upon inspection of the webpack JS file, it was found that code was distributed into several functions. It was observed that the function responsible for returning the JS path ended with `".js"`. This observation was seen multiple times in the Next.js apps by the developer (aka web researcher), hence it bacame a standard method to get the path of the JS files.
14
-
15
- ### Analysis of [X.ai](https://x.ai)
16
- It was found that most of the things were done in a similar way, however, some extra chars were present after `".js"` in the function responsible for returning JS path in the webpack JS file.
17
-
18
- To handle this, the regex was modified to also include some additional characters at the end.
19
- ```js
20
- .match(/"\.js".{0,15}$/)
21
- ```
22
-
23
- Also, it was found that very less URLs were present in the `webpack.js` file (4 at the time of analysis). Upon further inspection, it was found that the URLs are present in the inline `<script>` tags returned in the page source. For example:
24
- ```
25
- self.__next_f.push([1,"14:I[41498,[\"3867\",\"static/chunks/b6d67c9f-618ea7c61a79562d.js\",\"5017\",\"static/chunks/622eaf3d-350d2142e11f9e13.js\",\"1889\",\"static/chunks/0fd4459a-4e25f772815e6f19.js\",\"4406\",\"static/chunks/4406-fdbbb31c90e98725.js\",\"8627\",\"static/chunks/8627-54829c23d6b1a53f.js\",\"6520\",\"static/chunks/6520-f51ddcfa4e30ebc8.js\",\"1296\",\"static/chunks/1296-b8c2dd03773a40db.js\",\"8922\",\"static/chunks/8922-f01acc4fc5fecfad.js\",\"6929\",\"static/chunks/6929-a636a59ffdb51b17.js\",\"2601\"......snip....../chunks/b6d67c9f-"])
26
- ```
27
-
28
- To handle this, a feature was implemented to get the JS files from the inline `<script>` tags as well.
29
-
30
- Upon researching further, it was found that additional JS files were being returned in the subsequent HTTP requests. For example, the file at `https://x.ai/_next/static/chunks/app/careers/page-9e04dce6fed05790.js` was loaded from a request to `https://x.ai/careers?_rsc=jwl50`.
31
-
32
- Request to `https://x.ai/careers?_rsc=jwl50` should be made with a special header called `RSC: 1` in order to get access to additional JS file paths. This request can be also sent to `/` with the same header to get more files.
33
-
34
- Possible solution: To handle this, the strings can be extracted from the page sources, and then requests to them can be made along with this request header. If it returns a `200 OK`, then it can be also added to the list of JS files.
35
-
36
- ### Analysis of [OpenAI](https://openai.com)
37
- Upon inspection of HTTP requests, a similar behavior of sending the requests with `RSC: 1` header to get additional JS files was found.
38
-
39
- However, a slight difference was found. When sending the request to `/business` with the same header, the server returned a different (`308 Permanent Redirect` to `/business/`) response. This can be handled by sending the request to `/business/` with the same header.
40
-
41
- Additionally, it was noticed that when the requests were sent without the `RSC: 1` header, the request got blocked by Cloudflare, and it resulted in a `403 Forbidden` response with a message `Just a moment...`. This could indicate a potential firewall bypass
42
-
43
- ## Client-Side Paths/URLs
44
- Client-side paths/URLs are web addresses handled by the browser using JavaScript, usually without reloading the page. They are used for navigation, API requests, and loading resources dynamically within the client environment.
45
-
46
- ### Analysis of [X.ai](https://x.ai)
47
- Upon inspection of the client side paths, it was found that they are present in `href` across JS chunks.
48
-
49
- These are a part of a list, which contains objects with keys like `href` (string), `label` (string), `active` (boolean) and `children` (array of objects of the same type).
50
-
51
- For instance, here's a example of such a list:
52
- ```js
53
- let L = [
54
- {
55
- href: "/grok",
56
- label: "Grok",
57
- active: e.startsWith("/grok"),
58
- children: [
59
- { href: "/grok", label: "For Everyone", active: "/grok" == e },
60
- {
61
- href: "/grok/business",
62
- label: "For Business",
63
- active: "/grok/business" == e,
64
- },
65
- ],
66
- },
67
- {
68
- href: "/api",
69
- label: "API",
70
- active: e.startsWith("/api"),
71
- children: [
72
- { href: "/api#capabilities", label: "Overview" },
73
- {
74
- href: "https://docs.x.ai/docs/models?cluster=us-east-1#detailed-pricing-for-all-grok-models",
75
- label: "Pricing",
76
- external: !0,
77
- },
78
- {
79
- href: "https://console.x.ai",
80
- label: "API Console Login",
81
- external: !0,
82
- },
83
- {
84
- href: "https://docs.x.ai",
85
- label: "Documentation",
86
- external: !0,
87
- },
88
- ],
89
- },
90
- { href: "/company", label: "Company", active: "/company" == e },
91
- { href: "/colossus", label: "Colossus", active: "/colossus" == e },
92
- {
93
- href: "/careers",
94
- label: "Careers",
95
- active: e.startsWith("/careers"),
96
- },
97
- { href: "/news", label: "News", active: e.startsWith("/news") },
98
- ]
99
- ```
100
-
101
- Possible methodology: The tool can iterate over all the JS chunks, and find the list of objects with keys like `href` (string), `label` (string), `active` (boolean) and `children` (array of objects of the same type). Then, it can organize them in a report.
102
-
103
- ### Analyis of [1Password](https://1password.com)
104
- It was found that the client-side paths were stored in mostly stored in a way like:
105
- ```js
106
- let s = JSON.parse(
107
- '["/state-of-enterprise-security-report/thank-you/",......"/webinars/1p-quarterly-security-spotlight-and-roadmap-review/thank-you/"]',
108
- )
109
- ```
110
-
111
- Some similar pattern was also observed in [OpenAI](https://openai.com), however, the full analysis of OpenAI's client-side paths is not done at the time of writing this.
112
-
113
- It was also found that some paths were stored directly as a list. For example:
114
- ```js
115
- let n = ["/pricing/xam", "/pricing/password-manager"];
116
- ```
@@ -1,125 +0,0 @@
1
- # Nuxt.js Research
2
- ## Tech Detection
3
- Nuxt.js is a framework based on Vue.js. So, if the Vue.js is detected, then it is essential to detect Nuxt.js for accuracy.
4
-
5
- To detect Nuxt.js, following technique(s) can be used:
6
- - Search for "/_nuxt" in following attributes
7
- - `src`, `href`
8
-
9
- ## Lazy Loaded Files
10
- ### Analysis of [GitLab's About Site](https://about.gitlab.com/)
11
- It was found that all of the JS files were loaded from the `/_nuxt-new` directory instead of `/_nuxt` directory. The path to the JS files were located in the `<link>` tags' `href` attribute. These `<link>` tags had the value of `rel` attribute as `modulepreload`, and the values of `as` attribute as `script`.
12
-
13
- Additionally, there were some `<script>` tags found with `src` attribute as the path to the JS files, which started with `/_nuxt`.
14
-
15
- ### Analysis of [Vue Mastery](https://www.vuemastery.com/)
16
- Similar to Gitlab's About Page, Vue Mastery had `<link>` tags with `rel` attribute as `preload` and `href` attribute as the path to the JS files. These `<link>` tags had the value of `as` attribute as `script`, which is common between two sites.
17
-
18
- Additionally, there were some `<script>` tags found with `src` attribute as the path to the JS files, which started with `/_nuxt`.
19
-
20
- Upon analysis of JS files that can be downloaded with the above two methods, it was found that some of the JS files contained functions to generate dynamic JS files based on the function. One of such function was found in https://www.vuemastery.com/_nuxt/2551e78.js, which was present in a `<script>` tag on the home page source. The function responsible for generating dynamic JS files is:
21
- ```js
22
- f.p = "/_nuxt/",
23
- // --snip--
24
- script.src = function(e) {
25
- return f.p + "" + {
26
- 0: "dad8928",
27
- 1: "45a7974",
28
- 2: "4632233",
29
- 3: "1b5c8a7",
30
- 4: "605bec3",
31
- 5: "b2d6888",
32
- 6: "6f126a6",
33
- 7: "0660b70",
34
- 10: "b2c4841",
35
- 11: "dd7a220",
36
- 12: "f9f7852",
37
- 13: "4204cef",
38
- 14: "6b95651",
39
- 15: "d23fd5a",
40
- 16: "674fd56",
41
- 17: "e43e7d0",
42
- 18: "6745258",
43
- 19: "6ea1659",
44
- 20: "ebdc343",
45
- 21: "b82338f",
46
- 22: "6b6976c",
47
- 23: "3652e0c",
48
- 24: "ab7b2c1",
49
- 25: "4d1b31e",
50
- 26: "4dadfea",
51
- 27: "e3dff7a",
52
- 28: "cc26714",
53
- 29: "5fda719",
54
- 30: "cae7d03",
55
- 31: "23f9ebd",
56
- 32: "8e6c9c2",
57
- 33: "fe28953",
58
- 34: "d31580e",
59
- 35: "da95621",
60
- 36: "edc6dfe",
61
- 37: "5a045a0",
62
- 38: "50dfb9c",
63
- 39: "6ef34b4",
64
- 40: "102f187",
65
- 41: "c1d8d4f",
66
- 42: "4a0b48e",
67
- 43: "635c550",
68
- 44: "0266231",
69
- 45: "8fd697f",
70
- 46: "5107115",
71
- 47: "608af85",
72
- 48: "500d25b",
73
- 49: "da3579b",
74
- 50: "06ee20b",
75
- 51: "43e16e2",
76
- 52: "4c13496",
77
- 53: "a1eb1a8",
78
- 54: "141dbb5",
79
- 55: "c9cbc38",
80
- 56: "7306da6",
81
- 57: "415103c",
82
- 58: "57bbbbd",
83
- 59: "1963258",
84
- 62: "4fca0c9",
85
- 63: "93260d7",
86
- 64: "55a6cb8",
87
- 65: "15afb5c"
88
- }[e] + ".js"
89
- }(e);
90
- ```
91
-
92
- ### Analysis of [Vue.js Amsterdam](https://vuejs.amsterdam/)
93
- Apart from the methods mentioned above, it was found that a lot of JS paths were present in those which are already loaded. They were simple strings like `./sitemap.d7a8ffd7.js`, so they can be extracted on string analysis.
94
-
95
- ## Client-Side Paths/URLs
96
- ### Analysis of [GitLab's About Site](https://about.gitlab.com/)
97
- It was found that the client-side paths/URLs were present in the https://about.gitlab.com/_nuxt-new/builds/meta/2d555104-4dad-4b33-a02f-128a966a0c7b.json file. This file was found in the following tab on the home page's source code:
98
- ```html
99
- <link rel="preload" as="fetch" fetchpriority="low" crossorigin="anonymous" href="/_nuxt-new/builds/meta/2d555104-4dad-4b33-a02f-128a966a0c7b.json">
100
- ```
101
-
102
- Here's a preview of the JSON file:
103
- ```json
104
- {
105
- "id": "2d555104-4dad-4b33-a02f-128a966a0c7b",
106
- "timestamp": 1750133987484,
107
- "matcher": {
108
- "static": {},
109
- "wildcard": {},
110
- "dynamic": {}
111
- },
112
- "prerendered": [
113
- "/de-de/contact-sales",
114
- "/de-de/get-help",
115
- --snip--
116
- "/contact-sales",
117
- "/analysts",
118
- --snip
119
- "/ja-jp",
120
- "/ja-jp/search",
121
- "/",
122
- "/search"
123
- ]
124
- }
125
- ```
@@ -1,9 +0,0 @@
1
- # Vue.js Research
2
- ## Tech Detection
3
- To detect Vue.js, following technique(s) can be used:
4
- - Load the webpage in the browser, and find the `data-v-*` attribute
5
- - Note that this attribute might NOT be present if the webpage is not loaded in the browser, i.e. by directly getting the page source
6
- - However, it was found that most of the Vue.JS sites were using Nuxt. The research for this can be found at [Nuxt.js Research](./nuxt_js.md)
7
-
8
- ## Lazy Loaded Files
9
- ### Analysis of [Vue.JS official site](https://vuejs.org/)
package/strings/index.js DELETED
@@ -1,145 +0,0 @@
1
- import chalk from "chalk";
2
- import fs from "fs";
3
- import path from "path";
4
- import parser from "@babel/parser";
5
- import _traverse from "@babel/traverse";
6
- import prettier from "prettier";
7
-
8
- const traverse = _traverse.default;
9
-
10
- /**
11
- * Extracts all string literals from all .js files in a given directory and its
12
- * subdirectories and writes them to a JSON file.
13
- * @param {string} directory - The directory to scan for .js files
14
- * @param {string} output_file - The file to write the extracted strings to
15
- */
16
- const strings = async (
17
- directory,
18
- output_file,
19
- extract_urls,
20
- extracted_url_path,
21
- ) => {
22
- console.log(chalk.cyan("[i] Loading 'Strings' module"));
23
-
24
- // check if the directory exists
25
- if (!fs.existsSync(directory)) {
26
- console.log(chalk.red("[!] Directory does not exist"));
27
- return;
28
- }
29
-
30
- console.log(chalk.cyan(`[i] Scanning ${directory} directory`));
31
-
32
- // get all files in the directory and sub-directories
33
- const files = fs.readdirSync(directory, { recursive: true });
34
-
35
- // filter out non JS files
36
- const jsFiles = files.filter((file) => file.endsWith(".js"));
37
-
38
- // read all JS files
39
- let js_files_path = [];
40
- for (const file of jsFiles) {
41
- const filePath = path.join(directory, file);
42
- if (!fs.lstatSync(filePath).isDirectory()) {
43
- js_files_path.push(filePath);
44
- }
45
- }
46
-
47
- console.log(chalk.cyan(`[i] Found ${js_files_path.length} JS files`));
48
-
49
- // read all JS files
50
- let all_strings = {};
51
- for (const file of js_files_path) {
52
- const fileContent = fs.readFileSync(file, "utf-8");
53
-
54
- // parse the file contents with babel
55
- const ast = parser.parse(fileContent, {
56
- sourceType: "unambiguous",
57
- plugins: ["jsx", "typescript"],
58
- });
59
-
60
- let strings = [];
61
-
62
- traverse(ast, {
63
- StringLiteral(path) {
64
- strings.push(path.node.value);
65
- },
66
- });
67
-
68
- all_strings[file] = strings;
69
- }
70
-
71
- let strings_count = 0;
72
- for (const file of Object.keys(all_strings)) {
73
- strings_count += all_strings[file].length;
74
- }
75
-
76
- console.log(chalk.cyan(`[i] Extracted ${strings_count} strings`));
77
-
78
- // write to a JSON file
79
- const formatted = await prettier.format(JSON.stringify(all_strings), {
80
- parser: "json",
81
- printWidth: 80,
82
- singleQuote: true,
83
- });
84
- fs.writeFileSync(output_file, formatted);
85
-
86
- console.log(chalk.green(`[✓] Extracted strings to ${output_file}`));
87
-
88
- if (extract_urls) {
89
- console.log(chalk.cyan("[i] Extracting URLs and paths from strings"));
90
-
91
- let urls = [];
92
- let paths = [];
93
-
94
- for (const file of Object.keys(all_strings)) {
95
- for (const string of all_strings[file]) {
96
- if (string.match(/^https?:\/\/[a-zA-Z0-9\.\-_]+\/?.*$/)) {
97
- // like https://site.com
98
- urls.push(string);
99
- }
100
- if (string.match(/^\/.+$/)) {
101
- // like /path/resource
102
- // make sure that the path doesn't start with two special chars except '/_'
103
- if (string.match(/^\/[^a-zA-Z0-9]/) && !string.startsWith("/_")) {
104
- // ignore the path
105
- } else {
106
- paths.push(string);
107
- }
108
- }
109
- if (string.match(/^[a-zA-Z0-9_\-]\/[a-zA-Z0-9_\-].*$/)) {
110
- // like path/to/resource
111
- paths.push(string);
112
- }
113
- if (string.startsWith("./") || string.startsWith("../")) {
114
- // like "./path/to/resource" or "../path/to/resource"
115
- paths.push(string);
116
- }
117
- }
118
- }
119
-
120
- // dedupe the two lists
121
- urls = [...new Set(urls)];
122
- paths = [...new Set(paths)];
123
-
124
- console.log(
125
- chalk.cyan(`[i] Found ${urls.length} URLs and ${paths.length} paths`),
126
- );
127
-
128
- // write to a JSON file
129
- const formatted_urls = await prettier.format(
130
- JSON.stringify({ urls, paths }),
131
- {
132
- parser: "json",
133
- printWidth: 80,
134
- singleQuote: true,
135
- },
136
- );
137
- fs.writeFileSync(extracted_url_path, formatted_urls);
138
-
139
- console.log(
140
- chalk.green(`[✓] Written URLs and paths to ${extracted_url_path}`),
141
- );
142
- }
143
- };
144
-
145
- export default strings;
@@ -1,156 +0,0 @@
1
- import chalk from "chalk";
2
- import * as cheerio from "cheerio";
3
- import makeRequest from "../utility/makeReq.js";
4
- import puppeteer from "puppeteer";
5
-
6
- /**
7
- * Detects if a webpage uses Next.js by checking if any HTML tag has a src,
8
- * srcset, or imageSrcSet attribute that starts with "/_next/".
9
- * @param {CheerioStatic} $ - The Cheerio object containing the parsed HTML.
10
- * @returns {Promise<{detected: boolean, evidence: string}>}
11
- * A promise that resolves to an object with two properties:
12
- * - detected: A boolean indicating whether Next.js was detected.
13
- * - evidence: A string with the evidence of the detection, or an empty string
14
- * if Next.js was not detected.
15
- */
16
- const checkNextJS = async ($) => {
17
- let detected = false;
18
- let evidence = "";
19
- // iterate through each HTML tag, and file tag value that starts with `/_next/`
20
- $("*").each((_, el) => {
21
- const tag = $(el).get(0).tagName;
22
-
23
- // check the value of three attributes
24
- const src = $(el).attr("src");
25
- const srcSet = $(el).attr("srcset");
26
- const imageSrcSet = $(el).attr("imageSrcSet");
27
-
28
- if (src || srcSet || imageSrcSet) {
29
- if (src && src.startsWith("/_next/")) {
30
- detected = true;
31
- evidence = `${tag} :: ${src}`;
32
- } else if (srcSet && srcSet.startsWith("/_next/")) {
33
- detected = true;
34
- evidence = `${tag} :: ${srcSet}`;
35
- } else if (imageSrcSet && imageSrcSet.startsWith("/_next/")) {
36
- detected = true;
37
- evidence = `${tag} :: ${imageSrcSet}`;
38
- }
39
- }
40
- });
41
-
42
- return { detected, evidence };
43
- };
44
-
45
- /**
46
- * Detects if a webpage uses Vue.js by checking if any HTML tag has a data-v-* attribute.
47
- * @param {CheerioStatic} $ - The Cheerio object containing the parsed HTML.
48
- * @returns {Promise<{detected: boolean, evidence: string}>}
49
- * A promise that resolves to an object with two properties:
50
- * - detected: A boolean indicating whether Vue.js was detected.
51
- * - evidence: A string with the evidence of the detection, or an empty string
52
- * if Vue.js was not detected.
53
- */
54
- const checkVueJS = async ($) => {
55
- let detected = false;
56
- let evidence = "";
57
-
58
- $("*").each((_, el) => {
59
- const tag = $(el).get(0).tagName;
60
- const attribs = el.attribs;
61
- if (attribs) {
62
- for (const [attrName, attrValue] of Object.entries(attribs)) {
63
- if (attrName.startsWith("data-v-")) {
64
- detected = true;
65
- evidence = `${tag} :: ${attrName}`;
66
- }
67
- }
68
- }
69
- });
70
-
71
- return { detected, evidence };
72
- };
73
-
74
-
75
- const checkNuxtJS = async ($)=>{
76
- let detected = false;
77
- let evidence = "";
78
-
79
- // go through the page source, and check for "/_nuxt" in the src or href attribute
80
- $("*").each((_, el)=>{
81
- const tag = $(el).get(0).tagName;
82
- const attribs = el.attribs;
83
- if (attribs) {
84
- for (const [attrName, attrValue] of Object.entries(attribs)) {
85
- if (attrName === "src" || attrName === "href") {
86
- if (attrValue.includes("/_nuxt")) {
87
- detected = true;
88
- evidence = `${attrName} :: ${attrValue}`;
89
- }
90
- }
91
- }
92
- }
93
- });
94
-
95
- return { detected, evidence };
96
- }
97
-
98
- /**
99
- * Detects the front-end framework used by a webpage.
100
- * @param {string} url - The URL of the webpage to be detected.
101
- * @returns {Promise<{name: string, evidence: string}> | null}
102
- * A promise that resolves to an object with two properties:
103
- * - name: A string indicating the detected framework, or null if no framework was detected.
104
- * - evidence: A string with the evidence of the detection, or an empty string if no framework was detected.
105
- */
106
- const frameworkDetect = async (url) => {
107
- console.log(chalk.cyan("[i] Detecting front-end framework"));
108
-
109
- // get the page source
110
- const res = await makeRequest(url);
111
-
112
- // get the page source in the browser
113
- const browser = await puppeteer.launch({
114
- headless: true,
115
- args: [
116
- "--disable-gpu",
117
- "--disable-dev-shm-usage",
118
- "--disable-setuid-sandbox",
119
- "--no-sandbox",
120
- ],
121
- });
122
- const page = await browser.newPage();
123
- await page.goto(url);
124
- await new Promise((resolve) => setTimeout(resolve, 5000));
125
- const pageSource = await page.content();
126
- await browser.close();
127
-
128
- // if (res === null || res === undefined) {
129
- // return;
130
- // }
131
-
132
- // const pageSource = await res.text();
133
-
134
- // cheerio to parse the page source
135
- const $ = cheerio.load(pageSource);
136
-
137
- // check all technologies one by one
138
- const result_checkNextJS = await checkNextJS($);
139
- const result_checkVueJS = await checkVueJS($);
140
-
141
- if (result_checkNextJS.detected === true) {
142
- return { name: "next", evidence: result_checkNextJS.evidence };
143
- } else if (result_checkVueJS.detected === true) {
144
- console.log(chalk.green("[✓] Vue.js detected"));
145
- console.log(chalk.cyan(`[i] Checking Nuxt.JS`), chalk.dim("(Nuxt.JS is built on Vue.js)"));
146
- const result_checkNuxtJS = await checkNuxtJS($);
147
- if (result_checkNuxtJS.detected === true) {
148
- return { name: "nuxt", evidence: result_checkNuxtJS.evidence };
149
- }
150
- return { name: "vue", evidence: result_checkVueJS.evidence };
151
- }
152
-
153
- return null;
154
- };
155
-
156
- export default frameworkDetect;
@@ -1,6 +0,0 @@
1
-
2
- export let apiGatewayConfigFile = "";
3
- export let useApiGateway = false;
4
-
5
- export const setApiGatewayConfigFile = (file) => { apiGatewayConfigFile = file; };
6
- export const setUseApiGateway = (value) => { useApiGateway = value; };