Skip to content

第一个脚本

按照步骤开始我们的第一个脚本编写,这里以Naabu 项目为例

新增脚本

工作流管理-脚本列表-新增,先填写基本信息,包括

  • 脚本分类
  • 脚本id(可以自定义,只要不重复)
  • 脚本类型选择普通脚本
  • 脚本语言选择Java

可以参考下图 picture 10

由于工具需要下载之后才能使用,所以我们需要编写工具下载安装的命令,可以把安装命令分为2步:

# 下载可能网络不通,所以使用代理
export GOPROXY=https://goproxy.cn,direct
# 安装naabu
go install -v github.com/projectdiscovery/naabu/v2/cmd/naabu@latest

那么如何验证这个安装命令是否能成功呢?

首先执行命令进入客户端:

docker exec -it testnet-client /bin/bash

逐条执行命令,可以看到运行完命令之后工具naabu已经安装成功了: picture 11

最后回到页面打开这里的需安装,把刚才的命令复制到安装命令里 : picture 13

同理,我们继续编写版本检测命令,版本检查命令可以通过正则提取:

naabu -version 2>&1 | grep -oP 'Current Version: \K\d+\.\d+\.\d+'

同样执行一下命令验证是否成功提取到版本号,可以看到已经提取到了:

picture 12

然后把这个命令放入到版本检查命令中: picture 14

这样就完成了工具安装步骤的编写。接下来我们来编写执行工具的代码。

编写代码

查看官方文档可以得知naabu工具的命令,我们需要拼接执行命令,如:

naabu -no-stdin -c 200 -json -top-ports 100 -host %s -o %s
  • -no-stdin作用是不等待用户输入
  • -host %s 是要扫描的IP,不能写死,所以要用%s
  • -o %s 是要输出结果的路径,不能写死,所以要用%s

然后处理扫描的结果,参考如下代码:

import com.alibaba.fastjson.JSONObject;
import com.yomahub.liteflow.script.ScriptExecuteWrap;
import com.yomahub.liteflow.script.body.CommonScriptBody;
import com.yomahub.liteflow.spi.holder.ContextAwareHolder;
import testnet.client.service.ILiteFlowMessageSendService;
import testnet.common.dto.IpOrSubDomainToPortDTO;
import testnet.common.entity.liteflow.TaskExecuteMessage;
import testnet.common.utils.CommandUtils;

import java.io.BufferedReader;
import java.io.FileReader;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;


public class NaabuScan implements CommonScriptBody {

    public Void body(ScriptExecuteWrap wrap) {
        TaskExecuteMessage taskExecuteMessage = wrap.cmp.getRequestData();
        try {
            ILiteFlowMessageSendService messageSendService = ContextAwareHolder.loadContextAware().getBean(ILiteFlowMessageSendService.class);
            messageSendService.setTaskId(taskExecuteMessage.getTaskId());
            JSONObject instanceParams = JSONObject.parseObject(taskExecuteMessage.getTaskParams());
            // 随机生成一个结果路径
            String resultPath = taskExecuteMessage.getResultPath() + "naabu_" + UUID.randomUUID() + ".json";
            // 打印结果保存路径到日志
            messageSendService.INFO("结果保存路径:{}", resultPath);
            // 命令
            String command = "naabu -no-stdin -c 200 -json -top-ports 100 -host %s -o %s\n";
            // 从参数读取待扫描的IP
            String asset = instanceParams.getString("ip");
            // 拼接IP和结果路径
            command = String.format(command, asset, resultPath);
            // 打印命令到日志
            messageSendService.INFO("开始执行Nabbu端口扫描,命令是:{}", command);
            // 执行naabu扫描命令
            CommandUtils.CommandResult result = CommandUtils.executeCommand(command);
            // 判断命令是否执行成功
            if (result.getExitCode() == 0) {
                // 读取扫描结果
                BufferedReader reader = new BufferedReader(new FileReader(Paths.get(resultPath).toFile()));
                String line;
                // 创建结果对象
                IpOrSubDomainToPortDTO dto = new IpOrSubDomainToPortDTO();
                // 创建端口列表
                List<IpOrSubDomainToPortDTO.Port> portList = new ArrayList<>();
                // 读取每一行
                while ((line = reader.readLine()) != null) {
                    // 处理每一行内容
                    JSONObject jsonObject = JSONObject.parseObject(line);
                    messageSendService.INFO("Nabbu端口扫描执行结果:{}", jsonObject);
                    if (jsonObject != null) {
                        // 创建端口对象
                        IpOrSubDomainToPortDTO.Port port = new IpOrSubDomainToPortDTO.Port();
                        // 读取结果中的信息
                        port.setPort(jsonObject.getInteger("port"));
                        port.setProtocol(jsonObject.getString("protocol"));
                        port.setIp(jsonObject.getString("ip"));
                        port.setHost(jsonObject.getString("host"));
                        portList.add(port);
                    }
                }
                dto.setPortList(portList);
                // 发送结果
                messageSendService.sendResult(dto);
            } else if (result.getExitCode() == 1) {
                messageSendService.INFO("资产: {} 端口扫描完成,没有端口开放", asset);
            } else {
                messageSendService.ERROR("Nabbu端口扫描执行失败,错误信息是:{}", result.getExitCode());
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return null;
    }
}

把代码放到脚本内容里,然后保存: picture 15

脚本编排

然后到工作流管理-脚本编排中新增一个:

  • 流程名称 任意
  • 图标 任意
  • 适用资产 因为是扫描IP的端口,所以选择IP
  • 结果处理类名 因为是IP扫描结果到端口,所以选择ipOrSubDomainToPortProcessor
  • EL表达式填写 THEN(naabu_scan) 这里括号里是上一步定义的id
  • 默认线程1
  • 默认配置 空

picture 16

恭喜你已经完成了第一个脚本~ 下面我们来测试脚本是否能正常运行。

脚本测试

首先需要测试是否能正常安装,在节点管理-节点工具找到刚刚新建的naabu端口扫描示例,然后点击安装: picture 17

然后去工作流管理-任务列表可以看到安装日志: picture 18

如果执行成功,在节点管理-节点工具中状态应该显示已安装,同时正确获取到了版本号,如果没有成功,请检查新增脚本步骤中的安装命令版本检查命令

然后我们去IP列表中找到我们的脚本进行运行:

picture 19

同样去工作流管理-任务列表查看执行日志,如果运行成功说明脚本没有问题,你已经成功创建了自己的第一个脚本~