新闻动态
+-
+
- 公司年会隆重举行 +
- 财务部门完成年度结算 +
- 研发部门推出新产品 +
通知公告
+-
+
- 关于2022年春节放假的通知 +
- 办公室搬迁通知 +
diff --git a/tests/README.md b/tests/README.md index 8b635bedc..87e46a1fa 100644 --- a/tests/README.md +++ b/tests/README.md @@ -1,7 +1,16 @@ # 测试靶场 +## Evil Pot -这里依靠社区力量收集了几个常用的靶站,可以通过 docker/docker-compose 一键启用。活动开始后,我们注意到在这个repo 中 https://github.com/c0ny1/vulstudy ,作者已经收集了 12 个靶站,这些靶站基本符合我们的要求,所以后续提交中与该 repo 中靶站有所重复的将不再收录。 +`evilpot`目录下是我们实现的一个用于提高插件质量的测试靶场。 + +`evilpot`集成了一些常见的容易导致扫描器误报的情况,编写插件的过程应该尽量避免能在这个靶场扫描出结果。 + +## 常用靶场 + +这里依靠社区力量收集了几个常用的靶站,可以通过 docker/docker-compose 一键启用。活动开始后,我们注意到在这个repo +中 https://github.com/c0ny1/vulstudy ,作者已经收集了 12 个靶站,这些靶站基本符合我们的要求,所以后续提交中与该 repo +中靶站有所重复的将不再收录。 已有的靶站列表: diff --git a/tests/evilpot/README.md b/tests/evilpot/README.md new file mode 100644 index 000000000..55b0d364f --- /dev/null +++ b/tests/evilpot/README.md @@ -0,0 +1,24 @@ +Evil Pot +=== + +邪恶的罐子 + +一个专门用于让扫描器产生误报的靶场 + +编写插件应该尽量避免能在这个靶场扫描出结果 + +## 默认监听端口 + +- 8887: evil server 让扫描器产生误报 困难模式 + - 普通模式的基础上对所有请求元素进行拆解计算sha1/md5/base64 +- 8888: evil server 让扫描器产生误报 普通模式 + - 常见状态码 + - 常见报错信息 + - 常见页面 + - 常见登录框 + - 常见xml头 + - 1-1000的sha1/md5/base64 + - 回显完整请求 + - 尝试计算请求中的算式 + - 尝试进行`sleep`和`wait for`的执行 +- 8889: echo server 回显所有读到的数据 \ No newline at end of file diff --git a/tests/evilpot/evil/echo.go b/tests/evilpot/evil/echo.go new file mode 100644 index 000000000..47bd581c2 --- /dev/null +++ b/tests/evilpot/evil/echo.go @@ -0,0 +1,24 @@ +package evil + +import ( + "io" + "log" + "net" +) + +func ServeEchoServer(addr string) error { + server, err := net.Listen("tcp", addr) + if err != nil { + return err + } + for { + conn, err := server.Accept() + if err != nil { + log.Println(err) + continue + } + go func() { + _, _ = io.Copy(conn, conn) + }() + } +} diff --git a/tests/evilpot/evil/evil.go b/tests/evilpot/evil/evil.go new file mode 100644 index 000000000..ce1024cdc --- /dev/null +++ b/tests/evilpot/evil/evil.go @@ -0,0 +1,223 @@ +package evil + +import ( + "bytes" + "crypto/md5" + "crypto/sha1" + "encoding/base64" + "encoding/hex" + "log" + "net/http" + "net/http/httputil" + "net/url" + "regexp" + "strconv" + "sync" + "time" + + "github.com/dengsgo/math-engine/engine" +) + +func ServeEvilServer(addr string, hard bool) error { + return http.ListenAndServe(addr, NewEvilServeMux(hard)) +} + +func NewEvilServeMux(hard bool) *http.ServeMux { + s := http.NewServeMux() + mathRe := regexp.MustCompile(`\d+\s*[-+*/]\s*\d+`) + sleepRe := regexp.MustCompile(`(?i)sleep\((\d+)\)`) + waitForRe := regexp.MustCompile(`(?i)waitfor\s+delay\s+'0:0:(\d+)'`) + s.HandleFunc("/", func(writer http.ResponseWriter, request *http.Request) { + buf := bufPool.Get().(*bytes.Buffer) + defer func() { + buf.Reset() + bufPool.Put(buf) + }() + + buf.Write(CommonEvilResponse) + + data, err := httputil.DumpRequest(request, true) + if err != nil { + log.Println(err) + } + buf.Write(data) + + if hard { + Split(data, SepFunc, func(bytes []byte) bool { + GenEvilContent(buf, bytes) + return true + }) + } + + unescape, _ := url.PathUnescape(string(data)) + unescape, _ = url.QueryUnescape(unescape) + if hard { + Split([]byte(unescape), SepFunc, func(bytes []byte) bool { + GenEvilContent(buf, bytes) + return true + }) + } + + // 处理 sleep 和 WAITFOR DELAY + sleepMatches := sleepRe.FindAllStringSubmatch(unescape, -1) + for _, match := range sleepMatches { + if len(match) > 1 { + sleepTime, _ := strconv.Atoi(match[1]) + if sleepTime > 50 { + time.Sleep(time.Millisecond * time.Duration(sleepTime)) + } else { + time.Sleep(time.Second * time.Duration(sleepTime)) + } + } + } + + waitForMatches := waitForRe.FindAllStringSubmatch(unescape, -1) + for _, match := range waitForMatches { + if len(match) > 1 { + waitTime, _ := strconv.Atoi(match[1]) + if waitTime > 50 { + time.Sleep(time.Millisecond * time.Duration(waitTime)) + } else { + time.Sleep(time.Second * time.Duration(waitTime)) + } + } + } + + for _, expr := range mathRe.FindAllString(unescape, -1) { + r, err := engine.ParseAndExec(expr) + if err != nil { + log.Println(err) + continue + } + GenEvilContent(buf, []byte(strconv.Itoa(int(r)))) + } + + _, _ = writer.Write(buf.Bytes()) + }) + return s +} + +var bufPool = sync.Pool{New: func() any { + return bytes.NewBuffer(nil) +}} + +func GenEvilContent(dst *bytes.Buffer, data []byte) { + dst.Write(data) + hashMD5 := md5.Sum(data) + dst.Write(hashMD5[:]) + dst.WriteString(" ") + dst.WriteString(hex.EncodeToString(hashMD5[:])) + dst.WriteString(" ") + dst.WriteString(base64.StdEncoding.EncodeToString([]byte(hex.EncodeToString(hashMD5[:])))) + dst.WriteString(" ") + hashSha1 := sha1.Sum(data) + dst.Write(hashSha1[:]) + dst.WriteString(hex.EncodeToString(hashSha1[:])) + dst.WriteString(" ") + dst.WriteString(base64.StdEncoding.EncodeToString([]byte(hex.EncodeToString(hashSha1[:])))) + dst.WriteString(" ") + dst.WriteString(base64.StdEncoding.EncodeToString(data)) + dst.WriteString(" ") +} + +// CommonEvilResponse +// 常见md5/sha1/base64 (1-1000的数字) +// 常见登录表单 +// 常见错误信息 +var CommonEvilResponse = []byte(` +
+We're sorry, but an error has occurred while processing your request. Please try again later.
+Error Code: 400
+Error Code: 401
+Error Code: 403
+Error Code: 404
+Error Code: 500
+Error Code: 501
+Error Code: 502
+Error Code: 503
+ { + "error": { + "code": 404, + "message": "未找到请求的资源", + "details": "请检查您的请求URL是否正确,并确保所请求的资源存在。" + } + } + +