8 Commits
Author SHA1 Message Date
Li4n0 284db90c16 chore(release): 0.7.0 2023-05-23 23:28:53 +08:00
Li4n0 223c14ab33 feat: add value field to the dns log (#67)
record resolve value of dns log to facilitate the observation of dns rebinding.
2023-05-23 23:27:50 +08:00
Li4n0 c53ec79ccd ci: disable cgo 2023-04-15 19:44:52 +08:00
Li4n0 7dde3936d1 chore: chore(release): 0.6.0 2023-03-24 22:54:44 +08:00
Li4n0 a4ffaa7350 chore(release): 0.6.0 2023-03-24 22:50:39 +08:00
Li4n0 eee9c7be70 docs: introduction to Flag-Filter usage 2023-03-24 22:50:27 +08:00
Li4n0 b76757da33 fix: fix static resource loading failure after modifying admin_path_prefix
#63
2023-03-24 22:50:27 +08:00
whw1sfb b33de11ba8 feat: support for using Flag-Filter request headers to filter the flags that the client expects to receive (#64) 2023-03-24 22:50:20 +08:00
18 changed files with 111 additions and 39 deletions
+4
View File
@@ -23,6 +23,10 @@ jobs:
uses: actions/checkout@v2
- name: create dist directory
run: mkdir frontend/dist && touch frontend/dist/revsuit
- name: Install Go
uses: actions/setup-go@v2
with:
go-version: 1.19.x
- name: Run golangci-lint
uses: golangci/golangci-lint-action@v3
with:
+5 -5
View File
@@ -28,15 +28,15 @@ jobs:
run: echo ::set-output name=VERSION::$(echo $GITHUB_REF | cut -d / -f 3)
- name: compile linux amd64
run: GOARCH="amd64" go build -ldflags="-s -w -X 'github.com/li4n0/revsuit/pkg/server.VERSION=${{ steps.get_version.outputs.VERSION }}'" -tags netgo -trimpath -o "bin/revsuit_linux_amd64" ./cmd/revsuit/revsuit.go
run: CGO_ENABLE=0 GOARCH="amd64" go build -ldflags="-s -w -X 'github.com/li4n0/revsuit/pkg/server.VERSION=${{ steps.get_version.outputs.VERSION }}'" -tags netgo -trimpath -o "bin/revsuit_linux_amd64" ./cmd/revsuit/revsuit.go
- name: compile linux arm64
run: GOARCH="arm64" go build -ldflags="-s -w -X 'github.com/li4n0/revsuit/pkg/server.VERSION=${{ steps.get_version.outputs.VERSION }}'" -tags netgo -trimpath -o "bin/revsuit_linux_arm64" ./cmd/revsuit/revsuit.go
run: CGO_ENABLE=0 GOARCH="arm64" go build -ldflags="-s -w -X 'github.com/li4n0/revsuit/pkg/server.VERSION=${{ steps.get_version.outputs.VERSION }}'" -tags netgo -trimpath -o "bin/revsuit_linux_arm64" ./cmd/revsuit/revsuit.go
- name: compile darwin amd64
run: GOOS="darwin" GOARCH="amd64" go build -ldflags="-s -w -X 'github.com/li4n0/revsuit/pkg/server.VERSION=${{ steps.get_version.outputs.VERSION }}'" -trimpath -o "bin/revsuit_darwin_amd64" ./cmd/revsuit/revsuit.go
run: CGO_ENABLE=0 GOOS="darwin" GOARCH="amd64" go build -ldflags="-s -w -X 'github.com/li4n0/revsuit/pkg/server.VERSION=${{ steps.get_version.outputs.VERSION }}'" -trimpath -o "bin/revsuit_darwin_amd64" ./cmd/revsuit/revsuit.go
- name: compile darwin arm64
run: GOOS="darwin" GOARCH="arm64" go build -ldflags="-s -w -X 'github.com/li4n0/revsuit/pkg/server.VERSION=${{ steps.get_version.outputs.VERSION }}'" -trimpath -o "bin/revsuit_darwin_arm64" ./cmd/revsuit/revsuit.go
run: CGO_ENABLE=0 GOOS="darwin" GOARCH="arm64" go build -ldflags="-s -w -X 'github.com/li4n0/revsuit/pkg/server.VERSION=${{ steps.get_version.outputs.VERSION }}'" -trimpath -o "bin/revsuit_darwin_arm64" ./cmd/revsuit/revsuit.go
- name: compile windows amd64
run: GOOS="windows" GOARCH="amd64" go build -ldflags="-s -w -X 'github.com/li4n0/revsuit/pkg/server.VERSION=${{ steps.get_version.outputs.VERSION }}' " -trimpath -o "bin/revsuit_windows_amd64.exe" ./cmd/revsuit/revsuit.go
run: CGO_ENABLE=0 GOOS="windows" GOARCH="amd64" go build -ldflags="-s -w -X 'github.com/li4n0/revsuit/pkg/server.VERSION=${{ steps.get_version.outputs.VERSION }}' " -trimpath -o "bin/revsuit_windows_amd64.exe" ./cmd/revsuit/revsuit.go
- name: Upload the artifacts
uses: li4n0/upload-release-action@v2
+4 -1
View File
@@ -28,4 +28,7 @@ package-lock.json
node_modules/
## frontend dist
dist/
dist/
## received files
revsuit-files
+19
View File
@@ -2,6 +2,25 @@
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
## [0.7.0](https://github.com/Li4n0/revsuit/compare/v0.6.0...v0.7.0) (2023-05-23)
### Features
* add `value` field to the dns log ([#67](https://github.com/Li4n0/revsuit/issues/67)) ([223c14a](https://github.com/Li4n0/revsuit/commit/223c14ab33757e06b0d8177091982582e08e70c4))
## [0.6.0](https://github.com/Li4n0/revsuit/compare/v0.5.2...v0.6.0) (2023-03-24)
### Features
* support for using `Flag-Filter` request headers to filter the flags that the client expects to receive ([#64](https://github.com/Li4n0/revsuit/issues/64)) ([b33de11](https://github.com/Li4n0/revsuit/commit/b33de11ba8f126b03a45ad15cae69331ad59b865)) (Thanks to @whwlsfb)
### Bug Fixes
* fix static resource loading failure after modifying `admin_path_prefix` ([b76757d](https://github.com/Li4n0/revsuit/commit/b76757da331b56f240ec2a0c69d479f3184bc4c2)), closes [#63](https://github.com/Li4n0/revsuit/issues/63)
### [0.5.2](https://github.com/Li4n0/revsuit/compare/v0.5.1...v0.5.2) (2022-11-16)
+4 -3
View File
@@ -8,9 +8,10 @@ token: # Authentication Token, both the admin pag
domains: [] # The domain names used by the platform
external_ip: # The external IP of the platform, you need to make sure that the target you want to test can access the platform through this IP
admin_path_prefix: "/revsuit" # The http path prefix for the admin page, the page will be located at: /admin_path_prefix/admin
database: revsuit.db # Database connection information, support using Sqlite3, MySQL, Postgres
# database: "mysql://root:password@tcp(127.0.0.1:3306)/revsuit?charset=utf8mb4&parseTime=True&loc=Local"
# Database connection information, support using MySQL, Postgres, Sqlite3
database: "mysql://root:password@tcp(127.0.0.1:3306)/revsuit?charset=utf8mb4&parseTime=True&loc=Local"
# database: "postgres://host=127.0.0.1 user=root password=password dbname=revsuit port=5432 sslmode=disable TimeZone=Asia/Shanghai"
#database: revsuit.db # The use of sqlite databases on some systems may cause `SQLITE BUSY` problems in concurrent scenarios, so it is not recommended for use in a formal environment
log_level: info # Output log levels, divided into: debug, info, warning, error, fatal
check_upgrade: true # Whether to automatically check for updates
@@ -43,4 +44,4 @@ notice:
lark: https://open.feishu.cn/open-apis/bot/v2/hook/{token} # Webhook of Lark Bot
weixin: https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key={key} # Webhook of Weixin Bot
slack: https://hooks.slack.com/services/{id}/{token} # Webhook of Slack Bot
```
```
+4 -3
View File
@@ -7,9 +7,10 @@ token: # 鉴权Token,管理页面和客户端
domains: [] # 反连平台绑定的域名
external_ip: # 反连平台的外部IP,需要确保你想测试的目标能通过该 IP 访问到平台
admin_path_prefix: "/revsuit" # 管理页面的 http path 前缀,管理页面将位于:/admin_path_prefix/admin
database: revsuit.db # 数据库连接信息 支持Sqlite3、MySQL、Postgres
# database: "mysql://root:password@tcp(127.0.0.1:3306)/revsuit?charset=utf8mb4&parseTime=True&loc=Local"
# 数据库连接信息 支持MySQL、Postgres、SQLite3
database: "mysql://root:password@tcp(127.0.0.1:3306)/revsuit?charset=utf8mb4&parseTime=True&loc=Local"
# database: "postgres://host=127.0.0.1 user=root password=password dbname=revsuit port=5432 sslmode=disable TimeZone=Asia/Shanghai"
#database: revsuit.db # 在部分系统上使用 sqlite 数据库时,在并发场景下可能会出现 `SQLITE BUSY` 的问题,因此不推荐在正式环境中使用该类型数据库
log_level: info # 输出日志的级别,分为:debug、info、warning、error、fatal
check_upgrade: false # 是否自动检查更新
@@ -43,4 +44,4 @@ notice:
weixin: https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key={key} # 企业微信机器人webhook地址
slack: https://hooks.slack.com/services/{id}/{token} # slack机器人webhook地址
```
```
+5
View File
@@ -158,6 +158,11 @@ example.
As shown above, RevSuit supports multiple clients, and each client **in the connected state** receives a push of `flag`,
so distributed scanning can be supported.
If you don't want every client to receive all `flag` pushes, you can use the `Flag-Filter` request header when creating an sse connection to set the format(regular expressions) of the `flag` you want that client to receive:
![img.png](./images/flag-filter.gif)
#### Temporary storage queue
RevSuit will store `flag` temporarily in the queue when there is no client connection and send it when the client
+6 -1
View File
@@ -140,6 +140,11 @@ RevSuit
如上一节的图片里所展示的,RevSuit 支持多个客户端,每个在**连接状态**的客户端都会接收到 `flag` 的推送,因此分布式扫描也是支持的。
如果你不希望每个客户端都收到全部的 `flag` 推送,你可以在创建 sse 连接时,使用 `Flag-Filter` 请求头设置希望该客户端接受的 `flag` 的格式(支持正则表达式),例如:
![img.png](./images/flag-filter.gif)
#### 暂存队列
当没有客户端连接的时候,RevSuit 会把 `flag` 暂时存储到队列里,当有客户端连接的时候再进行推送。因此你不必担心因为客户端与 RevSuit 断开连接就错过漏洞。(这对发现延时触发的漏洞尤为有帮助)
@@ -225,4 +230,4 @@ payload,最后被扫描器发出的请求是:`['https://www.testvuln.com?url
## 开源许可协议
@Apache License 2.0
@Apache License 2.0
+2 -2
View File
@@ -2,7 +2,7 @@ import axios from 'axios'
import {store} from "@/main";
const service = axios.create({
baseURL: location.pathname.slice(0, -'/admin/'.length) + "/api", // api的base_url
baseURL: "../api", // api的base_url
timeout: 5000, // request timeout
validateStatus: function (status) {
if (status === 403) {
@@ -12,4 +12,4 @@ const service = axios.create({
}
})
export default service
export default service
+9
View File
@@ -82,6 +82,15 @@ const columns = [
filterIcon: 'filterIcon',
},
},
{
title: 'VALUE',
dataIndex: 'value',
key: 'value',
scopedSlots: {
filterDropdown: 'filterDropdown',
filterIcon: 'filterIcon',
},
},
{
title: 'REMOTE IP',
key: 'remote_ip',
+1 -1
View File
@@ -47,7 +47,7 @@
<a-tag
v-if="file"
color="#f5222d"
><a target="_blank" :href="'/revsuit/api/file/ftp/'+file.id">TRUE</a> </a-tag>
><a target="_blank" :href="'../api/file/ftp/'+file.id">TRUE</a> </a-tag>
<a-tag v-else color="#722ed1">
FALSE
</a-tag>
+1 -1
View File
@@ -10,7 +10,7 @@
>
<div v-if="record.files.length" slot="expandedRowRender" slot-scope="record" style="margin: 0">
<b v-if="record.files.length" style="color: gray">FILES:</b><br>
<a v-for="file in record.files" :key="file.name+record.id" :href="'/revsuit/api/file/mysql/'+file.id"
<a v-for="file in record.files" :key="file.name+record.id" :href="'../api/file/mysql/'+file.id"
target="_blank">{{ file.name }} </a>
</div>
<div slot="selectDropdown"
+2 -2
View File
@@ -3,13 +3,13 @@
<a-space size="middle">
<a-upload
name="rules"
action="/revsuit/api/setting/importRules"
action="../api/setting/importRules"
@change="handleChange"
:showUploadList="false"
>
<a-button type="primary" icon="upload">Import</a-button>
</a-upload>
<a-button type="primary" icon="download" onclick="window.open('/revsuit/api/setting/exportRules')">Export
<a-button type="primary" icon="download" onclick="window.open('../api/setting/exportRules')">Export
</a-button>
</a-space>
<a-result v-if="status"
+2 -5
View File
@@ -10,15 +10,12 @@ module.exports = {
devServer: {
proxy: {
'/api': {
target: 'http://localhost:10000',
pathRewrite: {
'^/api': '/revsuit/api'
}
target: 'http://127.0.0.1:10000/revsuit/',
}
},
},
productionSourceMap: false,
runtimeCompiler: true,
filenameHashing: false,
publicPath: '/revsuit/admin/',
publicPath: '',
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 894 KiB

+16 -12
View File
@@ -126,7 +126,7 @@ func (s *Server) newZone(name string) *newdns.Zone {
"ns2.hostmaster.com.",
"ns3.hostmaster.com.",
},
Handler: func(lookedName, remoteAddr string) ([]newdns.Set, error) {
Handler: func(lookedName, remoteAddr string) (set []newdns.Set, err error) {
ip := strings.Split(remoteAddr, ":")[0]
for _, _rule := range s.getRules() {
@@ -135,12 +135,24 @@ func (s *Server) newZone(name string) *newdns.Zone {
continue
}
r, err := newRecord(_rule, flag, domain, ip, ipinfo.Area(ip))
if _rule.Value != "" {
_type := _rule.Type
if _rule.Type == newdns.REBINDING {
_type = newdns.A
}
set = newSet(_rule, name, rule.CompileTpl(_rule.Value, vars), ip, _type)
}
var value string
if len(set) > 0 && len(set[0].Records) > 0 {
value = set[0].Records[0].Address
}
r, err := newRecord(_rule, flag, domain, value, ip, ipinfo.Area(ip))
if err != nil {
log.Warn("DNS record(rule_id:%s) created failed :%s", _rule.Name, err)
return nil, nil
}
log.Info("DNS record[id:%d rule:%s remote_ip:%s] has been created", r.ID, _rule.Name, ip)
log.Info("DNS record[id:%d rule:%s remote_ip:%s, value:%s] has been created", r.ID, _rule.Name, ip, value)
//only send to client or notify user when this connection recorded first time.
var count int64
@@ -168,15 +180,7 @@ func (s *Server) newZone(name string) *newdns.Zone {
}()
}
}
if _rule.Value != "" {
value := rule.CompileTpl(_rule.Value, vars)
_type := _rule.Type
if _rule.Type == newdns.REBINDING {
_type = newdns.A
}
return newSet(_rule, name, value, ip, _type), nil
}
return set, err
}
return nil, nil
+6 -1
View File
@@ -17,6 +17,7 @@ var _ record.Record = (*Record)(nil)
type Record struct {
Domain string `gorm:"index" form:"domain" json:"domain"`
Value string `form:"value" json:"value"`
record.BaseRecord
Rule Rule `gorm:"foreignKey:RuleName;references:Name;constraint:OnUpdate:CASCADE,OnDelete:SET NULL;" form:"-" json:"-" notice:"-"`
@@ -30,7 +31,7 @@ func (r Record) Notice() {
notice.Notice(r)
}
func newRecord(rule *Rule, flag, domain, remoteIp, ipArea string) (r *Record, err error) {
func newRecord(rule *Rule, flag, domain, value, remoteIp, ipArea string) (r *Record, err error) {
r = &Record{
BaseRecord: record.BaseRecord{
Flag: flag,
@@ -39,6 +40,7 @@ func newRecord(rule *Rule, flag, domain, remoteIp, ipArea string) (r *Record, er
RequestTime: time.Now(),
},
Domain: domain,
Value: value,
Rule: *rule,
}
@@ -89,6 +91,9 @@ func Records(c *gin.Context) {
if dnsRecord.RuleName != "" {
db.Where("rule_name = ?", dnsRecord.RuleName)
}
if dnsRecord.Value != "" {
db.Where("address= ?", dnsRecord.Value)
}
//Delete records
if c.Request.Method == http.MethodDelete {
+21 -2
View File
@@ -1,8 +1,10 @@
package server
import (
"regexp"
"sync"
"github.com/gin-contrib/sse"
"github.com/gin-gonic/gin"
"github.com/li4n0/revsuit/internal/database"
"github.com/li4n0/revsuit/internal/file"
@@ -44,6 +46,8 @@ func (revsuit *Revsuit) addClient(c *gin.Context) int {
revsuit.clientID++
revsuit.clients[revsuit.clientID] = c
sse.Event{}.WriteContentType(c.Writer)
c.Writer.Flush()
revsuit.clientsNum <- struct{}{}
return revsuit.clientID
}
@@ -231,8 +235,23 @@ func (revsuit *Revsuit) Run() {
<-revsuit.clientsNum
revsuit.clientsLock.RLock()
for _, client := range revsuit.clients {
client.SSEvent("message", r.GetFlag())
client.Writer.Flush()
pushIt := false
flag := client.Request.Header.Get("Flag-Filter")
if len(flag) == 0 || flag == "*" {
pushIt = true
} else {
if catcher, err := regexp.Compile(flag); err != nil {
log.Warn("%s[sse flag:%s]", err, flag)
continue
} else {
matched := catcher.FindStringSubmatch(r.GetFlag())
pushIt = len(matched) > 0
}
}
if pushIt {
client.SSEvent("message", r.GetFlag())
client.Writer.Flush()
}
}
revsuit.clientsNum <- struct{}{}
revsuit.clientsLock.RUnlock()