summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShulhan <ms@kilabit.info>2021-03-21 22:23:27 +0700
committerShulhan <ms@kilabit.info>2021-03-21 22:26:05 +0700
commit360bf84d2af244c7926c2aa7c1f23d0c280b8238 (patch)
tree2bcf39d2c6425980abdfe4a310f31eaf0f11b9a1
parent5828835bcd18eff070789fd82401480c244bbc27 (diff)
downloadgorankusu-360bf84d2af244c7926c2aa7c1f23d0c280b8238.tar.xz
all: implement interface and API to delete attack result
When user clicking the "Delete" button on attack result item, it will send request to API to delete the selected item. Server will check if the requested result file name exist and delete them from file system if its exist, otherwise it will return 404 Not found.
-rw-r--r--_www/index.css27
-rw-r--r--_www/index.html3
-rw-r--r--_www/index.js124
-rw-r--r--http_target.go7
-rw-r--r--trunks.go79
5 files changed, 182 insertions, 58 deletions
diff --git a/_www/index.css b/_www/index.css
index ef43f5b..f80f449 100644
--- a/_www/index.css
+++ b/_www/index.css
@@ -3,6 +3,28 @@ body {
margin: 0;
padding: 0;
}
+
+#notif,
+#notif-error {
+ position: absolute;
+ top: 1em;
+ left: 10%;
+ width: 80%;
+}
+
+#notif > div {
+ background-color: white;
+ border: 1px solid lightgrey;
+ margin: 1em auto;
+ padding: 1em;
+}
+
+#notif-error > div {
+ background-color: salmon;
+ margin: 1em auto;
+ padding: 1em;
+}
+
.nav {
height: calc(100% - 2em);
padding: 1em;
@@ -41,8 +63,11 @@ body {
}
.mono {
background-color: cornsilk;
- border-radius: 1em;
font-family: monospace;
padding: 1em;
overflow: auto;
}
+
+.results > .result-name {
+ margin-bottom: 1em;
+}
diff --git a/_www/index.html b/_www/index.html
index 97ac64d..56754af 100644
--- a/_www/index.html
+++ b/_www/index.html
@@ -26,5 +26,8 @@
<div class="main">
<div id="main-content"></div>
</div>
+
+ <div id="notif"></div>
+ <div id="notif-error"></div>
</body>
</html>
diff --git a/_www/index.js b/_www/index.js
index 642a7bc..044bd57 100644
--- a/_www/index.js
+++ b/_www/index.js
@@ -127,7 +127,7 @@ function renderTarget(targetID) {
let http = target.HttpTargets[x]
w += `
- <div>
+ <div id="${http.ID}" class="HttpTarget">
<h3>
${http.Name}
<button onclick="run('${target.ID}', '${http.ID}')">
@@ -137,42 +137,49 @@ function renderTarget(targetID) {
Attack
</button>
</h3>
- <div class="mono">
+
+ <div id="${http.ID}_preview" class="preview mono">
${_requestMethods[http.Method]} ${http.Path} <br/>
Content-Type: ${_requestTypes[http.RequestType]}
</div>
+
+ <h4>Headers</h4>
+ <div id="${http.ID}_headers" class="headers"></div>
+
+ <h4>Parameters</h4>
+ <div id="${http.ID}_params" class="params"></div>
+
+ <h4>Run response</h4>
+ <pre id="${http.ID}_response" class="response mono"></pre>
+
+ <h4>Attack results</h4>
+ <div id="${http.ID}_results" class="results"></div>
+ </div>
`
+ }
+ w += "</div>"
+
+ document.getElementById("main-content").innerHTML = w
+
+ for (let x = 0; x < target.HttpTargets.length; x++) {
+ let http = target.HttpTargets[x]
if (Object.keys(http.Headers).length > 0) {
- w += "<h4>Headers</h4>"
- w += renderHttpTargetHeaders(target, http)
+ renderHttpTargetHeaders(target, http)
}
if (Object.keys(http.Params).length > 0) {
- w += "<h4>Parameters</h4>"
- w += renderHttpTargetParams(target, http)
+ renderHttpTargetParams(target, http)
}
- w += `
- <h4>Run response</h4>
- <pre id="${http.ID}_response" class="mono">
- </pre>
- `
-
if (http.Results && Object.keys(http.Results).length > 0) {
- w += "<h4>Attack results</h4>"
- w += renderHttpAttackResults(target, http)
+ renderHttpAttackResults(target, http)
}
-
- w += "</div>"
}
- w += "</div>"
-
- document.getElementById("main-content").innerHTML = w
}
function renderHttpTargetHeaders(target, http) {
- let w = `<div id="${http.ID}_headers">`
+ let w = ""
for (const k in http.Headers) {
w += `
<div class="input">
@@ -184,12 +191,11 @@ function renderHttpTargetHeaders(target, http) {
</div>
`
}
- w += "</div>"
- return w
+ document.getElementById(`${http.ID}_headers`).innerHTML = w
}
function renderHttpTargetParams(target, http) {
- let w = `<div id="${http.ID}_params">`
+ let w = ""
for (const k in http.Params) {
w += `
<div class="input">
@@ -201,30 +207,33 @@ function renderHttpTargetParams(target, http) {
</div>
`
}
- w += "</div>"
- return w
+ document.getElementById(`${http.ID}_params`).innerHTML = w
}
function renderHttpAttackResults(target, http) {
- let w = `<div id="${http.ID}_results">`
+ let w = ""
for (let x = 0; x < http.Results.length; x++) {
let result = http.Results[x]
w += `
- <div>
- <button onclick="getAttackResult(this, '${result.Name}')">
+ <div class="result-name">
+ <button onclick="attackResultGet(this, '${result.Name}')">
Show
</button>
&nbsp;
--
&nbsp;
${result.Name}
+ &nbsp;
+ <button onclick="attackResultDelete('${result.Name}')">
+ Delete
+ </button>
+
</div>
<div class="result" id="${result.Name}" style="display: none;">
</div>
`
}
- w += "</div>"
- return w
+ document.getElementById(`${http.ID}_results`).innerHTML = w
}
async function run(targetID, httpTargetID) {
@@ -273,7 +282,38 @@ async function attack(targetID, httpTargetID) {
let res = await fres.json()
}
-async function getAttackResult(button, name) {
+async function attackResultDelete(name) {
+ let url = "/_trunks/api/target/attack/result?name=" + name
+ let fres = await fetch(url, {
+ method: "DELETE",
+ })
+ let res = await fres.json()
+ if (res.code != 200) {
+ console.log("attackResultDelete: ", res)
+ notifError(res.message)
+ return
+ }
+
+ let ids = name.split(".")
+ let target = _targets[ids[0]]
+ if (!target) {
+ return
+ }
+ let httpTarget = getHttpTargetByID(target, ids[1])
+ if (!httpTarget) {
+ return
+ }
+ for (let x = 0; x < httpTarget.Results.length; x++) {
+ let result = httpTarget.Results[x]
+ if (result.Name == name) {
+ httpTarget.Results.splice(x, 1)
+ renderHttpAttackResults(target, httpTarget)
+ return
+ }
+ }
+}
+
+async function attackResultGet(button, name) {
let el = document.getElementById(name)
if (el.style.display === "block") {
@@ -320,3 +360,25 @@ function onChangeHttpParam(targetID, httpTargetID, key, val) {
let httpTarget = getHttpTargetByID(target, httpTargetID)
httpTarget.Params[key] = val
}
+
+function notif(msg) {
+ let root = document.getElementById("notif")
+ let item = document.createElement("div");
+ item.innerHTML = msg
+ root.appendChild(item)
+
+ setTimeout(function() {
+ root.removeChild(item)
+ }, 5000)
+}
+
+function notifError(msg) {
+ let root = document.getElementById("notif-error")
+ let item = document.createElement("div");
+ item.innerHTML = msg
+ root.appendChild(item)
+
+ setTimeout(function() {
+ root.removeChild(item)
+ }, 5000)
+}
diff --git a/http_target.go b/http_target.go
index 03c05b1..5652df3 100644
--- a/http_target.go
+++ b/http_target.go
@@ -5,10 +5,12 @@
package trunks
import (
+ "os"
"path/filepath"
"sync"
libhttp "github.com/shuLhan/share/lib/http"
+ "github.com/shuLhan/share/lib/mlog"
vegeta "github.com/tsenart/vegeta/v12/lib"
)
@@ -87,6 +89,11 @@ func (ht *HttpTarget) deleteResult(result *AttackResult) {
copy(ht.Results[x:], ht.Results[x+1:])
ht.Results[len(ht.Results)-1] = nil
ht.Results = ht.Results[:len(ht.Results)-1]
+
+ err := os.Remove(result.fullpath)
+ if err != nil {
+ mlog.Errf("deleteResult: %q: %s\n", result.fullpath, err)
+ }
}
func (ht *HttpTarget) addResult(dir, name string) (err error) {
diff --git a/trunks.go b/trunks.go
index df6f2c0..9b700e9 100644
--- a/trunks.go
+++ b/trunks.go
@@ -200,7 +200,7 @@ func (trunks *Trunks) registerHttpApis() (err error) {
Path: apiTargetAttackResult,
RequestType: libhttp.RequestTypeJSON,
ResponseType: libhttp.ResponseTypeJSON,
- Call: trunks.apiTargetAttackResultsDelete,
+ Call: trunks.apiTargetAttackResultDelete,
})
if err != nil {
return err
@@ -302,32 +302,14 @@ func (trunks *Trunks) apiTargetAttackCancel(epr *libhttp.EndpointRequest) (resbo
}
func (trunks *Trunks) apiTargetAttackResultGet(epr *libhttp.EndpointRequest) (resbody []byte, err error) {
- res := &libhttp.EndpointResponse{
- E: liberrors.E{
- Code: http.StatusNotFound,
- Name: "ERR_ATTACK_RESULT_NOT_FOUND",
- },
- }
-
name := epr.HttpRequest.Form.Get(paramNameName)
if len(name) == 0 {
return nil, errInvalidParameter(paramNameName, name)
}
- t, ht := trunks.getTargetByResultFilename(name)
- if t == nil {
- res.Message = "Target ID not found"
- return nil, res
- }
- if ht == nil {
- res.Message = "HttpTarget ID not found"
- return nil, res
- }
-
- result := ht.getResultByName(name)
- if result == nil {
- res.Message = "Result file not found"
- return nil, res
+ _, _, result, err := trunks.getAttackResultByName(name)
+ if err != nil {
+ return nil, err
}
err = result.load()
@@ -335,15 +317,33 @@ func (trunks *Trunks) apiTargetAttackResultGet(epr *libhttp.EndpointRequest) (re
return nil, err
}
+ res := libhttp.EndpointResponse{}
res.Code = http.StatusOK
- res.Name = "OK_TARGET_ATTACK_RESULT"
+ res.Name = "OK_TARGET_ATTACK_RESULT_GET"
res.Data = result
- return json.Marshal(res)
+ return json.Marshal(&res)
}
-func (trunks *Trunks) apiTargetAttackResultsDelete(epr *libhttp.EndpointRequest) (resbody []byte, err error) {
- return resbody, nil
+func (trunks *Trunks) apiTargetAttackResultDelete(epr *libhttp.EndpointRequest) (resbody []byte, err error) {
+ name := epr.HttpRequest.Form.Get(paramNameName)
+ if len(name) == 0 {
+ return nil, errInvalidParameter(paramNameName, name)
+ }
+
+ _, ht, result, err := trunks.getAttackResultByName(name)
+ if err != nil {
+ return nil, err
+ }
+
+ ht.deleteResult(result)
+
+ res := libhttp.EndpointResponse{}
+ res.Code = http.StatusOK
+ res.Name = "OK_TARGET_ATTACK_RESULT_GET"
+ res.Data = result
+
+ return json.Marshal(&res)
}
func (trunks *Trunks) apiTargetRun(epr *libhttp.EndpointRequest) ([]byte, error) {
@@ -391,6 +391,33 @@ func (trunks *Trunks) getTargetByID(id string) *Target {
return nil
}
+func (trunks *Trunks) getAttackResultByName(name string) (t *Target, ht *HttpTarget, result *AttackResult, err error) {
+ res := &libhttp.EndpointResponse{
+ E: liberrors.E{
+ Code: http.StatusNotFound,
+ Name: "ERR_ATTACK_RESULT_NOT_FOUND",
+ },
+ }
+
+ t, ht = trunks.getTargetByResultFilename(name)
+ if t == nil {
+ res.Message = "Target ID not found"
+ return nil, nil, nil, res
+ }
+ if ht == nil {
+ res.Message = "HttpTarget ID not found"
+ return nil, nil, nil, res
+ }
+
+ result = ht.getResultByName(name)
+ if result == nil {
+ res.Message = "Result file not found"
+ return nil, nil, nil, res
+ }
+
+ return t, ht, result, nil
+}
+
func (trunks *Trunks) getTargetByResultFilename(name string) (t *Target, ht *HttpTarget) {
names := strings.Split(name, ".")