JSRadar (JavaScript敏感信息辅助脚本)

admin 2025年3月26日14:19:30评论11 views字数 18732阅读62分26秒阅读模式

作用原理

通过 _compile_rules 加载YAML规则文件,使用多线程 ThreadPoolExecutor 扫描JS/HTML文件中的敏感模式,最终生成可视化风险报告。

主要优势

✅ 高效扫描 - 多线程处理400+文件/秒

✅ 精准检测 - 支持邮箱/密钥/身份证等20+敏感模式

✅ 风险可视化 - 带星标分级和代码片段展示的 generate_report

✅ 智能缓存 - 基于 _calculate_md5 的增量扫描

当前局限

❌ 误报率依赖正则精度

❌ 仅支持静态代码分析

❌ 未集成动态调试能力

❌ 规则需手动维护更新

渗透测试应用场景

  • 项目源码 敏感信息泄露 审计
  • 前端代码 硬编码凭证 提取
  • 第三方库 供应链风险 检测
  • 自动化报告生成

js_sensitive_scanner.py代码

  1. import os
  2. import re
  3. import json
  4. import yaml
  5. import chardet
  6. from datetime import datetime
  7. import argparse
  8. import hashlib
  9. from concurrent.futures import ThreadPoolExecutor
  10. import regex # 替换标准re库
  11. import html # 新增html模块导入
  12. class SecurityScanner:
  13. def __init__(self, rule_file="security_rules.yaml"):
  14. self.file_hashes = {}
  15. self._load_cache()
  16. self.rules = self._load_rules(rule_file)
  17. self.compiled_rules = self._compile_rules()
  18. def _load_rules(self, rule_file):
  19. with open(rule_file, 'r', encoding='utf-8') as f:
  20. full_config = yaml.safe_load(f) # 整个配置文件
  21. return full_config['rules'] # 明确提取rules字段
  22. # 问题1:Java Deserialization规则缺少color字段(在规则文件中补充)
  23. def _compile_rules(self):
  24. """修复后的规则编译方法"""
  25. compiled = []
  26. for group in self.rules:
  27. if isinstance(group, dict) and 'rule' in group:
  28. for rule in group['rule']:
  29. color = rule.get('color', 'yellow')
  30. try:
  31. # 直接使用原始正则表达式字符串(YAML中应已正确转义)
  32. compiled.append((
  33. re.compile(rule['f_regex']), # 移除多余的字符串格式化
  34. rule['name'],
  35. self._map_color_to_severity(color)
  36. ))
  37. except Exception as e:
  38. print(f"规则编译失败: {rule.get('name')} - {str(e)}")
  39. return compiled
  40. def _load_cache(self):
  41. """加载文件哈希缓存"""
  42. try:
  43. with open('scan_cache.json', 'r') as f:
  44. self.file_hashes = json.load(f)
  45. except FileNotFoundError:
  46. self.file_hashes = {}
  47. def _save_cache(self):
  48. """保存文件哈希缓存"""
  49. with open('scan_cache.json', 'w') as f:
  50. json.dump(self.file_hashes, f)
  51. def _map_color_to_severity(self, color):
  52. """添加缺失的风险等级映射方法"""
  53. color_map = {'red':5, 'orange':4, 'yellow':3, 'cyan':2, 'green':1}
  54. return color_map.get(color.lower(), 2)
  55. # 修复点1:删除重复的 _compile_rules 方法(25行附近)
  56. # 原25行的旧方法定义已被下方的新实现替代
  57. # 删除旧的 _compile_rules 方法(原26行附近)
  58. # def _compile_rules(self):
  59. # """修复后的规则编译方法"""
  60. # ... 旧实现 ...
  61. # 保留下方合并后的新实现(约70行附近)
  62. def _compile_rules(self):
  63. """合并后的正则编译方法"""
  64. compiled = []
  65. for group in self.rules:
  66. if isinstance(group, dict) and 'rule' in group:
  67. for rule in group.get('rule', []):
  68. try:
  69. compiled.append((
  70. regex.compile(rule['f_regex'], flags=regex.VERSION1),
  71. rule['name'],
  72. self._map_color_to_severity(rule.get('color', 'yellow'))
  73. ))
  74. except Exception as e:
  75. print(f"规则编译失败: {rule.get('name')} - {str(e)}")
  76. return compiled
  77. def scan_file(self, file_path):
  78. """修复未定义的seen变量"""
  79. if self._is_file_unchanged(file_path):
  80. return []
  81. findings = []
  82. try:
  83. with open(file_path, 'rb') as f:
  84. raw_data = f.read(4096)
  85. encoding_result = chardet.detect(raw_data)
  86. encoding = encoding_result.get('encoding') if encoding_result else 'utf-8'
  87. seen = set() # 添加变量初始化
  88. with open(file_path, 'r', encoding=encoding, errors='replace') as f:
  89. for line_num, line in enumerate(f, 1): # 流式逐行读取
  90. for pattern, label, severity in self.compiled_rules:
  91. matches = pattern.finditer(line)
  92. for match in matches:
  93. raw_value = match.group()
  94. unique_key = f"{file_path}|{line_num}|{label}|{raw_value}"
  95. if unique_key in seen:
  96. continue
  97. seen.add(unique_key)
  98. # 修复点1:优化敏感标记检测逻辑
  99. is_sensitive = next((
  100. rule.get('sensitive', False)
  101. for group in self.rules
  102. for rule in group.get('rule', [])
  103. if rule.get('name') == label
  104. ), False)
  105. sanitized = self._sanitize(raw_value, is_sensitive)
  106. if is_sensitive and sanitized == raw_value:
  107. print(f"警告:未脱敏的敏感数据 @ {file_path}:{line_num}")
  108. findings.append({
  109. "file": os.path.basename(file_path),
  110. "line": line_num,
  111. "type": label,
  112. "raw": raw_value,
  113. "sanitized": sanitized,
  114. "severity": severity
  115. })
  116. except Exception as e:
  117. print(f"扫描失败: {file_path} - {str(e)}")
  118. return findings
  119. def _is_file_unchanged(self, file_path):
  120. """检查文件是否修改"""
  121. current_hash = self._calculate_md5(file_path)
  122. return self.file_hashes.get(file_path) == current_hash
  123. def _calculate_md5(self, file_path):
  124. """计算文件哈希"""
  125. hasher = hashlib.md5()
  126. with open(file_path, 'rb') as f:
  127. buf = f.read(4096)
  128. hasher.update(buf)
  129. return hasher.hexdigest()
  130. def _update_file_hash(self, file_path):
  131. """更新文件哈希"""
  132. self.file_hashes[file_path] = self._calculate_md5(file_path)
  133. def _sanitize(self, text, is_sensitive):
  134. """增强版脱敏逻辑"""
  135. if not is_sensitive:
  136. return text
  137. # 新增邮箱脱敏:t***@example.com
  138. text = regex.sub(r'(\w{1,3})[\w.-]+@([\w-]+\.[a-z]{2,7})', r'\1***@\2', text)
  139. # 新增密钥脱敏:AKIA***4567
  140. text = regex.sub(r'\b([A-Z0-9]{4})[A-Z0-9]{12,}([A-Z0-9]{4})\b', r'\1***\2', text)
  141. # 保持原有手机号/身份证脱敏...
  142. return text
  143. def _read_file_content(self, file_path):
  144. """提取的公共文件读取方法(唯一实现)"""
  145. try:
  146. with open(file_path, 'rb') as f:
  147. raw_data = f.read(4096)
  148. encoding_result = chardet.detect(raw_data)
  149. encoding = encoding_result.get('encoding') if encoding_result else 'utf-8'
  150. with open(file_path, 'r', encoding=encoding, errors='replace') as f:
  151. return f.read()
  152. except Exception as read_error:
  153. print(f"读取文件失败: {file_path} - {str(read_error)}")
  154. return None
  155. # 修复点2:添加report_path定义(原181行附近)
  156. def generate_report(results, output_dir):
  157. """修复None类型操作问题"""
  158. report_path = os.path.join(output_dir, f"security_report_{datetime.now().strftime('%Y%m%d%H%M')}.html")
  159. risk_levels = {5:0,4:0,3:0,2:0,1:0}
  160. # 修复重复统计问题
  161. for item in results:
  162. severity = item.get('severity', 0) or 0
  163. risk_levels[severity] += 1
  164. with open(report_path, 'w', encoding='utf-8') as f:
  165. f.write(rf"""<html>
  166. <head><title>安全扫描报告</title>
  167. <style>
  168. /* 保持原有样式不变 */
  169. </style>
  170. <script>
  171. // 合并后的切换函数(修复转义问题)
  172. function toggleAllSnippets(btn) {{
  173. const snippets = document.querySelectorAll('.code-snippet');
  174. if(!snippets.length) {{
  175. console.error('未找到代码片段');
  176. return;
  177. }}
  178. const isHidden = window.getComputedStyle(snippets[0]).display === 'none';
  179. snippets.forEach(s => s.style.display = isHidden ? 'block' : 'none');
  180. btn.textContent = isHidden ? '折叠所有代码' : '展开所有代码';
  181. }}
  182. function toggleCodeSnippet(btn) {{
  183. const snippet = btn.nextElementSibling;
  184. const isHidden = window.getComputedStyle(snippet).display === 'none';
  185. snippet.style.display = isHidden ? 'block' : 'none';
  186. btn.textContent = isHidden ? '隐藏代码' : '显示代码';
  187. }}
  188. </script>
  189. </head>
  190. <body>
  191. <h2>安全扫描报告({datetime.now().strftime('%Y-%m-%d %H:%M')})</h2>
  192. <!-- 新增全局展开按钮 -->
  193. <button onclick="toggleAllSnippets(this)"
  194. style="padding:6px 12px;background:#007bff;color:white;border-radius:4px;margin-bottom:16px">
  195. 一键展开所有代码
  196. </button>
  197. <!-- 筛选按钮部分保持不变 -->
  198. <!-- 单一表格结构 -->
  199. <table>
  200. <thead>
  201. <tr>
  202. <th>文件</th>
  203. <th>行号</th>
  204. <th>风险详情</th>
  205. <th>风险等级</th>
  206. </tr>
  207. </thead>
  208. <tbody>
  209. {"".join(
  210. f'''
  211. <tr data-severity="{item['severity']}">
  212. <td>{html.escape(item['file'])}</td>
  213. <td>{item['line']}</td>
  214. <td>
  215. <div class="risk-details">
  216. <span class="risk-type">{html.escape(item['type'])}</span>
  217. <div>
  218. <button onclick='toggleCodeSnippet(this)'
  219. style='padding:2px 8px;margin:2px'>
  220. 显示代码
  221. </button>
  222. <div class='code-snippet' style='display:none'>
  223. {html.escape(item['sanitized']).replace(chr(10), '<br>')}
  224. </div>
  225. </div>
  226. </div>
  227. </td>
  228. <td>{'★'*item['severity']}</td>
  229. </tr>
  230. '''
  231. for item in sorted(results, key=lambda x: (-x['severity'], x['file']))
  232. )}
  233. </tbody>
  234. </table>
  235. <script>
  236. // 新增全局切换函数
  237. // 将两个切换函数合并到同一个script标签中
  238. function toggleAllSnippets(btn) {{
  239. const snippets = document.querySelectorAll('.code-snippet');
  240. if(snippets.length === 0) return;
  241. const isHidden = snippets[0].style.display === 'none';
  242. snippets.forEach(s => s.style.display = isHidden ? 'block' : 'none');
  243. btn.textContent = isHidden ? '折叠所有代码' : '展开所有代码';
  244. }}
  245. function toggleCodeSnippet(btn) {{
  246. const snippet = btn.nextElementSibling;
  247. snippet.style.display = snippet.style.display === 'none' ? 'block' : 'none';
  248. btn.textContent = snippet.style.display === 'none' ? '显示代码' : '隐藏代码';
  249. }}
  250. <\/script>
  251. </body>
  252. </html>
  253. """) # 这是唯一的闭合标签
  254. # 删除下方重复的闭合标签和脚本 ▼▼▼
  255. if __name__ == "__main__":
  256. parser = argparse.ArgumentParser(description='安全信息扫描系统')
  257. parser.add_argument('-d', '--directory', required=True, help='扫描目录路径')
  258. parser.add_argument('-o', '--output', default='reports', help='报告输出目录')
  259. args = parser.parse_args()
  260. scanner = SecurityScanner()
  261. total_results = []
  262. # 修复点:删除重复的线程池执行代码(原281行附近)
  263. # 修正后的线程池配置(添加容错处理)
  264. max_workers = min(os.cpu_count() * 2, 32) if os.cpu_count() else 4
  265. with ThreadPoolExecutor(max_workers=max_workers) as executor:
  266. futures = []
  267. for root, _, files in os.walk(args.directory):
  268. for file in files:
  269. if file.lower().endswith(('.js','.html','.jsx')): # 添加大小写不敏感检查
  270. full_path = os.path.join(root, file)
  271. futures.append(executor.submit(scanner.scan_file, full_path))
  272. # 添加进度跟踪
  273. print(f"正在扫描 {len(futures)} 个文件...")
  274. for i, future in enumerate(futures, 1):
  275. try:
  276. total_results.extend(future.result())
  277. if i % 10 == 0:
  278. print(f"已处理 {i}/{len(futures)} 个文件")
  279. except Exception as e:
  280. print(f"线程执行出错: {str(e)}")
  281. # 修复点3:移除重复的扫描结果处理代码(文件末尾)
  282. # 删除以下重复代码块:
  283. # scanner._save_cache()
  284. # os.makedirs(args.output, exist_ok=True)
  285. # generate_report(...)
  286. # print(...)
  287. # 类型安全检查
  288. for item in total_results:
  289. item['severity'] = item.get('severity', 0) or 0
  290. generate_report(total_results, args.output)
  291. print(f"扫描完成,报告已生成至:{os.path.abspath(args.output)}")

security_rules.yaml代码

  1. rules:
  2. - group: Fingerprint
  3. rule:
  4. - name: Shiro
  5. f_regex: \b(rememberMe=[^;]+|JSESSIONID=)\b # 增加单词边界限制
  6. loaded: true
  7. f_regex: (=deleteMe|rememberMe=)
  8. s_regex: ''
  9. format: '{0}'
  10. color: green
  11. scope: any header
  12. engine: dfa
  13. sensitive: true
  14. - name: JSON Web Token
  15. loaded: true
  16. f_regex: (eyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9._-]{10,}|eyJ[A-Za-z0-9_\/+-]{10,}\.[A-Za-z0-9._\/+-]{10,})
  17. s_regex: ''
  18. format: '{0}'
  19. color: green
  20. scope: any
  21. engine: nfa
  22. sensitive: true
  23. - name: Swagger UI
  24. loaded: true
  25. f_regex: ((swagger-ui.html)|(\"swagger\":)|(Swagger UI)|(swaggerUi)|(swaggerVersion))
  26. s_regex: ''
  27. format: '{0}'
  28. color: red
  29. scope: response body
  30. engine: dfa
  31. sensitive: false
  32. - name: Ueditor
  33. loaded: true
  34. f_regex: (ueditor\.(config|all)\.js)
  35. s_regex: ''
  36. format: '{0}'
  37. color: green
  38. scope: response body
  39. engine: dfa
  40. sensitive: false
  41. - name: Druid
  42. loaded: true
  43. f_regex: (Druid Stat Index)
  44. s_regex: ''
  45. format: '{0}'
  46. color: orange
  47. scope: response body
  48. engine: dfa
  49. sensitive: false
  50. - group: Maybe Vulnerability
  51. rule:
  52. - name: Java Deserialization
  53. loaded: true
  54. f_regex: (\bjavax\.faces\.ViewState\b) # 添加单词边界限制
  55. scope: any # 扩大作用范围到请求和响应
  56. - group: Basic Information
  57. rule:
  58. - name: Email
  59. f_regex: (\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,7}\b) # 简化邮箱正则
  60. s_regex: ''
  61. format: '{0}'
  62. color: yellow
  63. scope: response body
  64. engine: dfa
  65. sensitive: false
  66. - name: Debug Logic Parameters
  67. loaded: true
  68. f_regex: ((access=)|(adm=)|(admin=)|(alter=)|(cfg=)|(clone=)|(config=)|(create=)|(dbg=)|(debug=)|(delete=)|(disable=)|(edit=)|(enable=)|(exec=)|(execute=)|(grant=)|(load=)|(make=)|(modify=)|(rename=)|(reset=)|(root=)|(shell=)|(test=)|(toggl=))
  69. s_regex: ''
  70. format: '{0}'
  71. color: cyan
  72. scope: request
  73. engine: dfa
  74. sensitive: false
  75. - name: URL As A Value
  76. loaded: true
  77. f_regex: (=(https?)(://|%3a%2f%2f))
  78. s_regex: ''
  79. format: '{0}'
  80. color: cyan
  81. scope: any
  82. engine: nfa
  83. sensitive: false
  84. - name: Upload Form
  85. loaded: true
  86. f_regex: (type\=\"file\")
  87. s_regex: ''
  88. format: '{0}'
  89. color: yellow
  90. scope: response body
  91. engine: dfa
  92. sensitive: false
  93. - name: DoS Paramters
  94. loaded: true
  95. f_regex: ((size=)|(page=)|(num=)|(limit=)|(start=)|(end=)|(count=))
  96. s_regex: ''
  97. format: '{0}'
  98. color: cyan
  99. scope: request
  100. engine: dfa
  101. sensitive: false
  102. - group: Basic Information
  103. rule:
  104. - name: Email
  105. loaded: true
  106. f_regex: (([a-z0-9]+[_|\.])*[a-z0-9]+@([a-z0-9]+[-|_|\.])*[a-z0-9]+\.((?!js|css|jpg|jpeg|png|ico)[a-z]{2,5}))
  107. s_regex: ''
  108. format: '{0}'
  109. color: yellow
  110. scope: response
  111. engine: nfa
  112. sensitive: false
  113. - name: Chinese IDCard
  114. loaded: true
  115. f_regex: '[^0-9]((\d{8}(0\d|10|11|12)([0-2]\d|30|31)\d{3}$)|(\d{6}(18|19|20)\d{2}(0[1-9]|10|11|12)([0-2]\d|30|31)\d{3}(\d|X|x)))[^0-9]'
  116. s_regex: ''
  117. format: '{0}'
  118. color: orange
  119. scope: response body
  120. engine: nfa
  121. sensitive: true
  122. - name: Chinese Mobile Number
  123. loaded: true
  124. f_regex: '[^\w]((?:(?:\+|0{0,2})86)?1(?:(?:3[\d])|(?:4[5-79])|(?:5[0-35-9])|(?:6[5-7])|(?:7[0-8])|(?:8[\d])|(?:9[189]))\d{8})[^\w]'
  125. s_regex: ''
  126. format: '{0}'
  127. color: orange
  128. scope: response body
  129. engine: nfa
  130. sensitive: false
  131. - name: Internal IP Address
  132. loaded: true
  133. f_regex: '[^0-9]((127\.0\.0\.1)|(10\.\d{1,3}\.\d{1,3}\.\d{1,3})|(172\.((1[6-9])|(2\d)|(3[01]))\.\d{1,3}\.\d{1,3})|(192\.168\.\d{1,3}\.\d{1,3}))'
  134. s_regex: ''
  135. format: '{0}'
  136. color: cyan
  137. scope: response
  138. engine: nfa
  139. sensitive: true
  140. - name: MAC Address
  141. loaded: true
  142. f_regex: (^([a-fA-F0-9]{2}(:[a-fA-F0-9]{2}){5})|[^a-zA-Z0-9]([a-fA-F0-9]{2}(:[a-fA-F0-9]{2}){5}))
  143. s_regex: ''
  144. format: '{0}'
  145. color: green
  146. scope: response
  147. engine: nfa
  148. sensitive: true
  149. # 重复的 Basic Information 组(合并至单个组)
  150. - group: Basic Information
  151. rule:
  152. # 合并两个 Email 规则(原第41/129行)
  153. - name: Email
  154. f_regex: >-
  155. (?i)(\b[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,7}\b)(?<!\.js)(?<!\.css)(?<!\.png)(?<!\.jpg)
  156. s_regex: ''
  157. format: '{0}'
  158. color: yellow
  159. scope: response body
  160. engine: dfa
  161. sensitive: false
  162. - name: Debug Logic Parameters
  163. loaded: true
  164. f_regex: ((access=)|(adm=)|(admin=)|(alter=)|(cfg=)|(clone=)|(config=)|(create=)|(dbg=)|(debug=)|(delete=)|(disable=)|(edit=)|(enable=)|(exec=)|(execute=)|(grant=)|(load=)|(make=)|(modify=)|(rename=)|(reset=)|(root=)|(shell=)|(test=)|(toggl=))
  165. s_regex: ''
  166. format: '{0}'
  167. color: cyan
  168. scope: request
  169. engine: dfa
  170. sensitive: false
  171. - name: URL As A Value
  172. loaded: true
  173. f_regex: (=(https?)(://|%3a%2f%2f))
  174. s_regex: ''
  175. format: '{0}'
  176. color: cyan
  177. scope: any
  178. engine: nfa
  179. sensitive: false
  180. - name: Upload Form
  181. loaded: true
  182. f_regex: (type\=\"file\")
  183. s_regex: ''
  184. format: '{0}'
  185. color: yellow
  186. scope: response body
  187. engine: dfa
  188. sensitive: false
  189. - name: DoS Paramters
  190. loaded: true
  191. f_regex: ((size=)|(page=)|(num=)|(limit=)|(start=)|(end=)|(count=))
  192. s_regex: ''
  193. format: '{0}'
  194. color: cyan
  195. scope: request
  196. engine: dfa
  197. sensitive: false
  198. # 重复的 Fingerprint 组(合并到原组)
  199. - group: Fingerprint
  200. rule:
  201. - name: Shiro
  202. # 合并两个 f_regex(原第5/7行)
  203. f_regex: \b(rememberMe=[^;]+|JSESSIONID=|deleteMe|rememberMe=)\b
  204. loaded: true
  205. f_regex: (=deleteMe|rememberMe=)
  206. s_regex: ''
  207. format: '{0}'
  208. color: green
  209. scope: any header
  210. engine: dfa
  211. sensitive: true
  212. - name: JSON Web Token
  213. loaded: true
  214. f_regex: (eyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9._-]{10,}|eyJ[A-Za-z0-9_\/+-]{10,}\.[A-Za-z0-9._\/+-]{10,})
  215. s_regex: ''
  216. format: '{0}'
  217. color: green
  218. scope: any
  219. engine: nfa
  220. sensitive: true
  221. - name: Swagger UI
  222. loaded: true
  223. f_regex: ((swagger-ui.html)|(\"swagger\":)|(Swagger UI)|(swaggerUi)|(swaggerVersion))
  224. s_regex: ''
  225. format: '{0}'
  226. color: red
  227. scope: response body
  228. engine: dfa
  229. sensitive: false
  230. - name: Ueditor
  231. loaded: true
  232. f_regex: (ueditor\.(config|all)\.js)
  233. s_regex: ''
  234. format: '{0}'
  235. color: green
  236. scope: response body
  237. engine: dfa
  238. sensitive: false
  239. - name: Druid
  240. loaded: true
  241. f_regex: (Druid Stat Index)
  242. s_regex: ''
  243. format: '{0}'
  244. color: orange
  245. scope: response body
  246. engine: dfa
  247. sensitive: false
  248. - group: Maybe Vulnerability
  249. rule:
  250. - name: Java Deserialization
  251. loaded: true
  252. f_regex: (\bjavax\.faces\.ViewState\b) # 添加单词边界限制
  253. scope: any # 扩大作用范围到请求和响应
  254. - group: Basic Information
  255. rule:
  256. - name: Email
  257. loaded: true
  258. f_regex: (([a-z0-9]+[_|\.])*[a-z0-9]+@([a-z0-9]+[-|_|\.])*[a-z0-9]+\.((?!js|css|jpg|jpeg|png|ico)[a-z]{2,5}))
  259. s_regex: ''
  260. format: '{0}'
  261. color: yellow
  262. scope: response
  263. engine: nfa
  264. sensitive: false
  265. - name: Chinese IDCard
  266. loaded: true
  267. f_regex: '[^0-9]((\d{8}(0\d|10|11|12)([0-2]\d|30|31)\d{3}$)|(\d{6}(18|19|20)\d{2}(0[1-9]|10|11|12)([0-2]\d|30|31)\d{3}(\d|X|x)))[^0-9]'
  268. s_regex: ''
  269. format: '{0}'
  270. color: orange
  271. scope: response body
  272. engine: nfa
  273. sensitive: true
  274. - name: Chinese Mobile Number
  275. loaded: true
  276. f_regex: '[^\w]((?:(?:\+|0{0,2})86)?1(?:(?:3[\d])|(?:4[5-79])|(?:5[0-35-9])|(?:6[5-7])|(?:7[0-8])|(?:8[\d])|(?:9[189]))\d{8})[^\w]'
  277. s_regex: ''
  278. format: '{0}'
  279. color: orange
  280. scope: response body
  281. engine: nfa
  282. sensitive: false
  283. - name: Internal IP Address
  284. loaded: true
  285. f_regex: '[^0-9]((127\.0\.0\.1)|(10\.\d{1,3}\.\d{1,3}\.\d{1,3})|(172\.((1[6-9])|(2\d)|(3[01]))\.\d{1,3}\.\d{1,3})|(192\.168\.\d{1,3}\.\d{1,3}))'
  286. s_regex: ''
  287. format: '{0}'
  288. color: cyan
  289. scope: response
  290. engine: nfa
  291. sensitive: true
  292. - name: MAC Address
  293. loaded: true
  294. f_regex: (^([a-fA-F0-9]{2}(:[a-fA-F0-9]{2}){5})|[^a-zA-Z0-9]([a-fA-F0-9]{2}(:[a-fA-F0-9]{2}){5}))
  295. s_regex: ''
  296. format: '{0}'
  297. color: green
  298. scope: response
  299. engine: nfa
  300. sensitive: true
  301. # 在 Fingerprint 组中新增
  302. - group: Fingerprint
  303. rule:
  304. - name: FTP/SFTP Leak
  305. loaded: true
  306. f_regex: (sftp:\/\/|ftp:\/\/)[^\s]+(:[^\s]+@)
  307. color: red
  308. sensitive: true
  309. # 在 Sensitive Information 组中新增
  310. - group: Sensitive Information
  311. rule:
  312. # 新增企业管理平台密钥检测
  313. - name: Enterprise WeChat Key
  314. f_regex: (\b(corpid|corpsecret)=[a-zA-Z0-9_-]{32}\b)
  315. color: red
  316. sensitive: true
  317. - name: Feishu Credentials
  318. f_regex: (\b(app_id|app_secret)=[a-zA-Z0-9_-]{32}\b)
  319. color: red
  320. sensitive: true
  321. # 增强管理员凭证检测
  322. - name: Admin Credentials
  323. f_regex: (?i)(['"`]?(admin(_?name|_?user)|root)(['"`]?\s*[:=]\s*['"`]?[^'\"]+))
  324. color: red
  325. sensitive: true
  326. # 在 Cloud Key 规则中新增地图密钥检测
  327. - name: Cloud Key
  328. f_regex: >-
  329. (?i)((['"`]?(access_key|map_key|mapsecret)\b['"`]?\s*[:=]\s*['"`]?([A-Z0-9\-_=]{20,})['"`]?)|
  330. (\b(AKIA|AMAP_)[A-Z0-9]{16}\b))
  331. # 补充缺失的规则参数
  332. s_regex: ''
  333. format: '{0}'
  334. color: red
  335. scope: any
  336. engine: nfa
  337. sensitive: true
  338. # 在 Network Infrastructure 组中新增
  339. - group: Network Infrastructure
  340. rule:
  341. - name: Sensitive URL Paths
  342. f_regex: (?i)/(admin|backup|phpmyadmin|\.git|\.svn)/
  343. color: orange
  344. sensitive: false
  345. - name: Dangerous Extensions
  346. f_regex: \.(git|svn|bak|swp|sql)(\?|$)
  347. color: yellow
  348. sensitive: false
  349. - name: Authorization Header
  350. loaded: true
  351. f_regex: ((basic [a-z0-9=:_\+\/-]{5,100})|(bearer [a-z0-9_.=:_\+\/-]{5,100}))
  352. s_regex: ''
  353. format: '{0}'
  354. color: yellow
  355. scope: response body
  356. engine: nfa
  357. sensitive: true
  358. - name: Password Field
  359. loaded: true
  360. f_regex: ((|\\)(|'|")(|[\w]{1,10})(

    (ass|wd|asswd|assword))...

  361. s_regex: ''

  362. format: '{0}'

  363. color: yellow

  364. scope: response body

  365. engine: nfa

  366. sensitive: true

  367. - name: Username Field

  368. loaded: true

  369. f_regex: ((|\\)(|'|")(|[\w]{1,10})(([u](ser|name|sername))|(account)|((((create|update)((d|r)|(by|on|at)))|(creator))))(|[\w]{1,10})(|\\)(|'|")(:|=|\)\.val\()(

  370. |)(|\\)('|")([^'"]+?)(|\\)('|")(|,|\)))

  371. s_regex: ''

  372. format: '{0}'

  373. color: green

  374. scope: response body

  375. engine: nfa

  376. sensitive: false

  377. - name: WeCom Key

  378. loaded: true

  379. f_regex: ((corp)(id|secret))

  380. s_regex: ''

  381. format: '{0}'

  382. color: green

  383. scope: response body

  384. engine: dfa

  385. sensitive: false

  386. - name: JDBC Connection

  387. loaded: true

  388. f_regex: (jdbc:[a-z:]+://[a-z0-9\.\-_:;=/@?,&]+)

  389. s_regex: ''

  390. format: '{0}'

  391. color: yellow

  392. scope: any

  393. engine: nfa

  394. sensitive: false

  395. - name: Authorization Header

  396. loaded: true

  397. f_regex: ((basic [a-z0-9=:_\+\/-]{5,100})|(bearer [a-z0-9_.=:_\+\/-]{5,100}))

  398. s_regex: ''

  399. format: '{0}'

  400. color: yellow

  401. scope: response body

  402. engine: nfa

  403. sensitive: false

  404. - name: Sensitive Field

  405. loaded: true

  406. f_regex: >-

  407. (?i)((['"`]?([\w_]{0,5}((key|secret|token|auth|access|credential|password|config)(s|_id|_key|_store|_name)?|api_?key|private_?key|encryption_?key|admin_?pass))\b['"`]?\s*[:=]\s*['"`]?([A-Z0-9\-_=]{8,64})['"`]?)|

  408. (\b(AKIA|ASIA)[A-Z0-9]{16}\b)|

  409. (\b(ghp|gho|ghu|ghs|ghr)_[A-Za-z0-9_]{36}\b))

  410. s_regex: ''

  411. format: '{0}'

  412. color: red

  413. scope: any

  414. engine: nfa

  415. sensitive: true # 启用脱敏

  416. - name: Mobile Number Field

  417. loaded: true

  418. f_regex: ((|\\)(|'|")(|[\w]{1,10})(mobile|phone|sjh|shoujihao|concat)(|[\w]{1,10})(|\\)(|'|")(:|=|\)\.val\()(

  419. |)(|\\)('|")([^'"]+?)(|\\)('|")(|,|\)))

  420. s_regex: ''

  421. format: '{0}'

  422. color: green

  423. scope: response body

  424. engine: nfa

  425. sensitive: false

  426. - group: Other

  427. rule:

  428. - name: Linkfinder

  429. loaded: true

  430. f_regex: (?:"|')((?:(?:[a-zA-Z]{1,10}://|//)[^"'/]{1,}\.[a-zA-Z]{2,}[^"']{0,})|(?:(?:(?:/|\.\./|\./)?[^"'><,;|*()(%%$^/\\\[\]][^"'><,;|()]{1,}\.[a-zA-Z]{1,4})|(?:(?:/|\.\./|\./)?[^"'><,;|*()(%%$^/\\\[\]][^"'><,;|()]{1,}/[^"'><,;|()]{1,}(?:\.[a-zA-Z]{1,4}|action)?)))(?:[\?|#][^"|']{0,})?(?:"|')

  431. s_regex: ''

  432. format: '{0}'

  433. color: gray

  434. scope: response body

  435. engine: nfa

  436. sensitive: true

  437. - name: Source Map

  438. loaded: true

  439. f_regex: (\.js\.map)

  440. s_regex: ''

  441. format: '{0}'

  442. color: pink

  443. scope: response body

  444. engine: dfa

  445. sensitive: false

  446. - name: Create Script

  447. loaded: true

  448. f_regex: (\{[^{}]*\}\s*\[[^\s]*\]\s*\+\s*"[^\s]*\.js")

  449. s_regex: '"?([\w].*?)"?:"(.*?)"'

  450. format: '{0}.{1}'

  451. color: green

  452. scope: response body

  453. engine: nfa

  454. sensitive: false

  455. - name: URL Schemes

  456. loaded: true

  457. f_regex: (\b(?![\w]{0,10}?https?://)(([-A-Za-z0-9]{1,20})://[-A-Za-z0-9+&@#/%?=~_|!:,.;]+[-A-Za-z0-9+&@#/%=~_|]))

  458. s_regex: ''

  459. format: '{0}'

  460. color: yellow

  461. scope: response body

  462. engine: nfa

  463. sensitive: false

  464. - name: Router Push

  465. loaded: true

  466. f_regex: (\$router\.push)

  467. s_regex: ''

  468. format: '{0}'

  469. color: magenta

  470. scope: response body

  471. engine: dfa

  472. sensitive: false

  473. - name: All URL

  474. loaded: true

  475. f_regex: (https?://[-A-Za-z0-9+&@#/%?=~_|!:,.;\u4E00-\u9FFF]+[-A-Za-z0-9+&@#/%=~_|])

  476. s_regex: ''

  477. format: '{0}'

  478. color: gray

  479. scope: response body

  480. engine: nfa

  481. sensitive: true

  482. - name: Request URI

  483. loaded: true

  484. f_regex: ' ((?!.*\.js(\?.*)?$)(.*?[^.js$])) '

  485. s_regex: ''

  486. format: '{0}'

  487. color: gray

  488. scope: request line

  489. engine: nfa

  490. sensitive: false

  491. - name: 302 Location

  492. loaded: true

  493. f_regex: 'Location: (.*?)\n'

  494. s_regex: ''

  495. format: '{0}'

  496. color: gray

  497. scope: response header

  498. engine: nfa

  499. sensitive: false

使用方法

  1. python3 .js_sensitive_scanner.py -h
JSRadar (JavaScript敏感信息辅助脚本)
  1. python3 .js_sensitive_scanner.py -d 扫描目录路径 -o 报告输出目录
JSRadar (JavaScript敏感信息辅助脚本)

报告如下

JSRadar (JavaScript敏感信息辅助脚本)

原文始发于微信公众号(漏洞谷):JSRadar (JavaScript敏感信息辅助脚本)

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2025年3月26日14:19:30
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   JSRadar (JavaScript敏感信息辅助脚本)https://cn-sec.com/archives/3884729.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息