第一个脚本
按照步骤开始我们的第一个脚本编写,这里以Naabu 项目为例
新增脚本
工作流管理-脚本列表-新增
,先填写基本信息,包括
- 脚本分类
- 脚本id(可以自定义,只要不重复)
- 脚本类型选择普通脚本
- 脚本语言选择Java
可以参考下图
由于工具需要下载之后才能使用,所以我们需要编写工具下载安装的命令,可以把安装命令分为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
已经安装成功了:
最后回到页面打开这里的需安装,把刚才的命令复制到安装命令里 :
同理,我们继续编写版本检测命令,版本检查命令可以通过正则提取:
naabu -version 2>&1 | grep -oP 'Current Version: \K\d+\.\d+\.\d+'
同样执行一下命令验证是否成功提取到版本号,可以看到已经提取到了:
然后把这个命令放入到版本检查命令中:
这样就完成了工具安装步骤的编写。接下来我们来编写执行工具的代码。
编写代码
查看官方文档可以得知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;
}
}
把代码放到脚本内容里,然后保存:
脚本编排
然后到工作流管理-脚本编排中新增一个:
- 流程名称 任意
- 图标 任意
- 适用资产 因为是扫描IP的端口,所以选择IP
- 结果处理类名 因为是IP扫描结果到端口,所以选择ipOrSubDomainToPortProcessor
- EL表达式填写
THEN(naabu_scan)
这里括号里是上一步定义的id - 默认线程1
- 默认配置 空
恭喜你已经完成了第一个脚本~ 下面我们来测试脚本是否能正常运行。
脚本测试
首先需要测试是否能正常安装,在节点管理-节点工具
找到刚刚新建的naabu端口扫描示例
,然后点击安装:
然后去工作流管理-任务列表
可以看到安装日志:
如果执行成功,在节点管理-节点工具
中状态应该显示已安装
,同时正确获取到了版本号,如果没有成功,请检查新增脚本
步骤中的安装命令
和版本检查命令
然后我们去IP列表中找到我们的脚本进行运行:
同样去工作流管理-任务列表
查看执行日志,如果运行成功说明脚本没有问题,你已经成功创建了自己的第一个脚本~