自动化Dast扫描+报告输出

admin 2025年2月18日19:57:00评论9 views字数 7267阅读24分13秒阅读模式

加入新公司有一段时间啦,终于有时间来更新更新一下文章了,这篇文章不同于以往的渗透实战哈。阔能没有那么鸡动人心,话不多说,直接上正文。

使用github actions来配置自动化dast扫描(当然也阔以用定时任务的方式,方法是活的),这里就不前置讲github actins了,有不了解的阔以看(https://docs.github.com/en/actions/writing-workflows/workflow-syntax-for-github-actions)。

这里实现主要分成3step,分别是执行dast扫描(这里我选择的是nuclei)、将扫描结果转换成报告、钉钉提醒扫描结束。

执行dast扫描

action代码如下,首先下载nucleiaction的运行环境,然后运行nuclei对目标进行扫描。

- name: Download Nuclei        run: |          # 下载 Nuclei          wget https://github.com/projectdiscovery/nuclei/releases/download/v3.3.5/nuclei_3.3.5_linux_amd64.zip          # 解压缩          unzip nuclei_3.3.5_linux_amd64.zip -/usr/local/bin/          # 赋予执行权限          chmod +/usr/local/bin/nuclei- name: Run Nuclei        run: |          # 使用如下出口 IP 地址执行 Nuclei 扫描          EXTERNAL_IP=$(curl -s https://api.ipify.org)          echo "External IP is: $EXTERNAL_IP"          nuclei -list=urls.txt -je report.json -rl 80

这里有一步,扫描结束后需要将代码upload,不然下一步python转换无法获取到扫描结果,action代码如下。

- name: Upload report.json        uses: actions/upload-artifact@v3with:          name: nuclei-report          path: |            report.json

生成报告

同样的使用action获取python需要的依赖,然后运行python脚本,运行的脚本如下(简单写的一个小脚本,输出有棱有角就行,不要太在意最终的美观性哈)。

import jsonimport refrom datetime import datetimefrom docx import Documentfrom docx.shared import RGBColor# 指定输入和输出文件input_file = 'report.json'          # 输入的 Nuclei JSON 文件url_file = 'urls.txt'   # 扫描的地址output_file = 'vulnerability_report.docx'  # 输出的 DOCX 报告文件now = datetime.now()# 读取 Nuclei 生成的 JSON 文件try:    with open(input_file, 'r', encoding='utf-8'as f:        results = json.load(f)  # 解析 JSON 文件except FileNotFoundError:    print(f"错误: 找不到文件 {input_file}。请确保该文件存在。")    exit(1)except json.JSONDecodeError:    print(f"错误: 文件 {input_file} 不是有效的 JSON 格式。")    exit(1)# 创建 DOCX 文件doc = Document()# 添加标题doc.add_heading('Core Service Application Vulnerability Scan Report'0)# 添加表格:记录测试人员和测试时间doc.add_paragraph(""doc.add_heading('Scanning Plan', level=1)table = doc.add_table(rows=1, cols=2)table.style = 'Table Grid'hdr_cells = table.rows[0].cellshdr_cells[0].text = 'Scan By'hdr_cells[1].text = 'Scan Date'row_cells = table.add_row().cellsrow_cells[0].text = 'Chen Guo'  # 你可以在此处替换为实际测试人员row_cells[1].text = datetime.now().strftime("%Y-%m-%d")doc.add_heading('Scanning Tool', level=1)doc.add_paragraph(f"nuclei")# 读取 URL 文件,获取测试地址try:    with open(url_file, 'r', encoding='utf-8'as f:        urls = [line.strip() for line in f.readlines() if line.strip()]  # 读取并去掉空行except FileNotFoundError:    print(f"错误: 找不到文件 {url_file}。请确保该文件存在。")    exit(1)# 插入URL表格doc.add_heading('Scan Urls', level=1)# 创建一个新表格来显示 URL 地址url_table = doc.add_table(rows=1, cols=1)url_table.style = 'Table Grid'hdr_cells = url_table.rows[0].cellshdr_cells[0].text = 'Scan URL'# 填充 URL 地址for url in urls:    row_cells = url_table.add_row().cells    row_cells[0].text = url# 统计高、中、低风险漏洞数high_risk_count = 0medium_risk_count = 0low_risk_count = 0def extract_header_from_response(response):"""    从响应字符串中提取 HTTP header。    :param response: 包含响应内容的字符串    :return: 提取的header部分    """    # 假设header部分以"HTTP/1.1"开始,直到空行    header_match = re.match(r'^(.*?)(r?nr?n)', response, re.DOTALL)if header_match:return header_match.group(1)  # 返回header部分return'No header found'# 检查是否有结果if not results:    doc.add_paragraph("没有找到漏洞扫描结果。")    doc.save(output_file)    exit(0)# 遍历结果并格式化输出for result in results:    result = json.dumps(result)    result = json.loads(result)    severity = result.get('info', {}).get('severity')if severity != 'info' and severity != 'unknown':        # 更新统计计数if severity == 'high':            high_risk_count += 1        elif severity == 'medium':            medium_risk_count += 1        elif severity == 'low':            low_risk_count += 1# 先输出漏洞统计信息:使用表格展示doc.add_heading('Vulnerability Summary', level=1)# 添加一个表格来展示统计数据vuln_table = doc.add_table(rows=1, cols=3)vuln_table.style = 'Table Grid'hdr_cells = vuln_table.rows[0].cellshdr_cells[0].text = 'Risk Level'hdr_cells[1].text = 'Count'hdr_cells[2].text = 'Description'# 填充表格内容vuln_row = vuln_table.add_row().cellsrun_red = vuln_row[0].paragraphs[0].add_run('High')run_red.font.color.rgb = RGBColor(25500)vuln_row[1].text = str(high_risk_count)vuln_row[2].text = 'High risk vulnerabilities'vuln_row = vuln_table.add_row().cellsrun_yellow =  vuln_row[0].paragraphs[0].add_run('Medium')run_yellow.font.color.rgb = RGBColor(2551650)vuln_row[1].text = str(medium_risk_count)vuln_row[2].text = 'Medium risk vulnerabilities'vuln_row = vuln_table.add_row().cellsrun_green =  vuln_row[0].paragraphs[0].add_run('Low')run_green.font.color.rgb = RGBColor(02550)vuln_row[1].text = str(low_risk_count)vuln_row[2].text = 'Low risk vulnerabilities'doc.add_paragraph("")  # 添加空行分隔统计信息和漏洞详情doc.add_heading('Vulnerability Details', level=1)# 再输出漏洞详细信息num = 1for result in results:    result = json.dumps(result)    result = json.loads(result)    severity = result.get('info', {}).get('severity')    doc.add_heading(f"{num}. {result.get('info', {}).get('name', 'N/A')}", level=2)    host = result.get('host''N/A').replace('n''')    paragraph = doc.add_paragraph(f"Target: {host}")    paragraph.paragraph_format.space_before = 0    paragraph.paragraph_format.space_after = 0    vulnerability_name = result.get('info', {}).get('name''N/A').replace('n''')    paragraph = doc.add_paragraph(f"Vulnerability Name: {vulnerability_name}")    paragraph.paragraph_format.space_before = 0    paragraph.paragraph_format.space_after = 0    p = doc.add_paragraph()  if severity == 'high':        run = p.add_run(f"Severity: high")        run.font.color.rgb = RGBColor(25500)  # 红色    elif severity == 'medium':        run = p.add_run(f"Severity: medium")        run.font.color.rgb = RGBColor(2551650)  # 橙色    elif severity == 'low':        run = p.add_run(f"Severity: low")        run.font.color.rgb = RGBColor(02550)  # 绿色else:        run = p.add_run(f"Severity: info")        run.font.color.rgb = RGBColor(00255)  # 蓝色    p.paragraph_format.space_before = 0    p.paragraph_format.space_after = 0    description = result.get('info', {}).get('description''N/A').replace('n''')    paragraph = doc.add_paragraph(f"Description: {description}")    paragraph.paragraph_format.space_before = 0    paragraph.paragraph_format.space_after = 0    vulnerability_url = result.get('matched-at''N/A').replace('n''')    paragraph = doc.add_paragraph(f"Vulnerability URL: {vulnerability_url}")    paragraph.paragraph_format.space_before = 0    paragraph.paragraph_format.space_after = 0    # 添加请求和响应信息    request = result.get('request''no request')  # 获取原始请求    response = result.get('response''no response') # 获取原始响应if response != 'no response':        response = extract_header_from_response(response)    paragraph = doc.add_paragraph("Request:")    paragraph.paragraph_format.space_before = 0    paragraph.paragraph_format.space_after = 0    paragraph = doc.add_paragraph()for line in request.splitlines():        run = paragraph.add_run(line)        run.add_break()  # 添加换行符    paragraph = doc.add_paragraph("Response:")    paragraph.paragraph_format.space_before = 0    paragraph.paragraph_format.space_after = 0    paragraph = doc.add_paragraph()for line in response.splitlines():        run = paragraph.add_run(line)        run.add_break()  # 添加换行符    num = num + 1# 如果没有找到漏洞if num == 1:    doc.add_paragraph("No risk vulnerabilities have been found, only info information has been found so far")# 保存 DOCX 文件doc.save(output_file)print(f"漏洞报告已生成: {output_file}")

推送报告信息

这里使用的钉钉机器人推送扫描结束通知,github action代码如下。当然也阔以直接将报告发送到邮箱之类的。

- name: dingtalk-bot        uses: leafney/dingtalk-action@v1if: always()env:          DINGTALK_ACCESS_TOKEN:  ${{ secrets.DINGTALK_ACCESS_TOKEN }}        with:          msgtype: link          title: 'Core Service Vulnerability Scan'          text: 'Vulnerability Scan 已经结束:请前往github action下载report。'          msg_url: 'https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}'

查看效果,如下。

自动化Dast扫描+报告输出
自动化Dast扫描+报告输出

原文始发于微信公众号(安全无界):自动化Dast扫描+报告输出

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

发表评论

匿名网友 填写信息