这篇文章上次修改于 1484 天前,可能其部分内容已经发生变化,如有疑问可询问作者。
自学了一段时间Golang,写了一些练习demo, 想想还是写点小东西出来总和练习下比较好, 通过本次练习能够串联起学习的知识点.
Nessus已经提供了API接口,无论是接入其他系统还是自己自动化扫描都特别方便. 官方提供了Python和Java的SDK方便用户调用,但没有提供Golang的SDK, 所以用Golang写一个简易版的吧.
环境
Go: 1.15.5
Nessus: Nessus Professional Version 8.13.1
Nessus也已经提供了完备的API文档,查阅地址是https://<Nessus_IP>:8834/api#/overview
认证
Nessus有两种认证方式,第一种是常规的登录获取token,API如下:
POST /session
{
"username":{string},
"password":{string}
}
输入正确用户名和密码后会响应一个token
{
"token": {string}
}
伪代码实现如下:
package nessus_request
import (
"crypto/tls"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"strings"
"time"
)
func GetToken(username, password string) (token string) {
var url string = "https://10.211.55.54:8834/session"
timeout := time.Duration(10 * time.Second) //超时时间50ms
bodyString := "{\"username\":" + username + "+,\"password\":" + password + "}"
req, err := http.NewRequest("POST", url, strings.NewReader(bodyString))
if err != nil {
panic(err)
}
if req != nil {
req.Header.Add("Content-Type", "application/json")
// 使用AK进行登录,添加下面一行即可
// req.Header.Add("X-ApiKeys", "accessKey={accessKey}; secretKey={secretKey};")
}
client := &http.Client{
Timeout: timeout,
Transport: &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, // 忽略证书检测
}}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
var tokens struct {
Token string `json:"token"`
}
json.Unmarshal(body, &tokens)
fmt.Println(tokens.Token)
return tokens.Token
}
TIPS: 我们需要为响应创建与之匹配的结构体, 可以使用在线网站自动生成:https://mholt.github.io/json-to-go/
第二种使用AK方式登录,即可直接进行操作,只要在每次请求时在HTTP请求头中添加"X-ApiKeys", "accessKey={accessKey}; secretKey={secretKey};”
即可.示例代码参考上面示例即可.
任务
添加任务
添加任务的数据格式如下,其中必填的字段有:uuid,settings.name,settings.enabled,settings.text_targets,settings.agent_group_id
POST /scans
{
"uuid": {template_uuid}, // 模板UUID
"settings": {
"name": {string}, // 扫描任务的名称
"description": {string},
"emails": {string},
"enabled": "true",
"launch": {string}, // 是否马上运行,建议设置为"true"
"folder_id": {integer}, // folder_id 需要抓包看下
"policy_id": {integer}, //策略可以不填
"scanner_id": {integer}, // 为1
"text_targets": {string}, //扫描的目标
"agent_group_id": []
}
}
uuid是扫描模板的id为必填项.
这里值得注意的是launch参数我们最好填上并设置为true,这样添加完任务后能够自动扫描.
代码片段:
// NewScan 新建扫描
func (n *nessusImpl) NewScan(
TmplUUID string,
Name string,
TextTargets string,
) (*Scan, error) {
data := NewScanRequest{
UUID: TmplUUID,
Settings: Settings{
Name: Name,
Description: "",
LaunchNow: true,
FolderID: 3, // 请自行替换为自己的folder_id
Enabled: false,
ScannerID: "1",
TextTargets: TextTargets,
},
}
return n.CreateScan(data)
}
func (n *nessusImpl) CreateScan(newScanRequest NewScanRequest) (*Scan, error) {
if n.verbose {
log.Println("Creating a new scan...")
}
resp, err := n.Request("POST", "/scans", newScanRequest, []int{http.StatusOK})
if err != nil {
return nil, err
}
defer resp.Body.Close()
reply := struct {
Scan Scan `json:"scan"`
}{}
if err = json.NewDecoder(resp.Body).Decode(&reply); err != nil {
return nil, err
}
return &reply.Scan, nil
}
暂停任务数据格式
POST /scans/{scan_id}/pause
停止任务数据格式
POST /scans/{scan_id}/stop
恢复任务数据格式
POST /scans/{scan_id}/resume
添加任务,暂停任务,恢复任务均为POST请求方式,body字段为空
获取任务扫描结果
GET /scans/{scan_id}
# 响应如下
{
"info": {
"acls": [
permission Resource
],
"edit_allowed": {boolean},
"status": {string},
"policy": {string},
"pci-can-upload": {boolean},
"hasaudittrail": {boolean},
"scan_start": {string},
"folder_id": {integer},
"targets": {string},
"timestamp": {integer},
"object_id": {integer},
"scanner_name": {string},
"haskb": {boolean},
"uuid": {string},
"hostcount": {integer},
"scan_end": {string},
"name": {string},
"user_permissions": {integer},
"control": {boolean}
},
"hosts": [
host Resource
],
"comphosts": [
host Resource
],
"notes": [
note Resource
],
"remediations": {
"remediations": [
remediation Resource
],
"num_hosts": {integer},
"num_cves": {integer},
"num_impacted_hosts": {integer},
"num_remediated_cves": {integer}
},
"vulnerabilities": [
vulnerability Resource
],
"compliance": [
vulnerability Resource
],
"history": [
history Resource
],
"filters": [
filter Resource
]
}
go实例代码
func (n *nessusImpl) ScanDetails(scanID int64) (*ScanDetailsResp, error) {
if n.verbose {
log.Println("获取扫描明细...")
}
resp, err := n.Request("GET", fmt.Sprintf("/scans/%d", scanID), nil, []int{http.StatusOK})
if err != nil {
return nil, err
}
defer resp.Body.Close()
reply := &ScanDetailsResp{}
if err = json.NewDecoder(resp.Body).Decode(&reply); err != nil {
return nil, err
}
return reply, nil
}
小结
这篇文章我们主要介绍了nessus API从登录到扫描任务创建、启动、停止、以及结果的获取的内容.当然nessus的api不止这些,目前还是个半成品,后面继续完善吧.
完整代码 https://github.com/ucstone/go-nessus/tree/master
没有评论