- 修复RDP协议连接导致的任意文件读取漏洞

- RDP协议增加「域」参数
- 增加安全访问功能
- 优化代码
This commit is contained in:
dushixiang
2021-03-11 21:16:29 +08:00
parent ba5bff1b38
commit 7f7edaa33c
45 changed files with 1020 additions and 158 deletions

View File

@ -0,0 +1,83 @@
package model
import (
"next-terminal/pkg/global"
)
type AccessSecurity struct {
ID string `json:"id"`
Rule string `json:"rule"`
IP string `json:"ip"`
Source string `json:"source"`
Priority int64 `json:"priority"` // 越小优先级越高
}
func (r *AccessSecurity) TableName() string {
return "access_securities"
}
func FindAllAccessSecurities() (o []AccessSecurity, err error) {
db := global.DB
err = db.Order("priority asc").Find(&o).Error
return
}
func FindPageSecurity(pageIndex, pageSize int, ip, rule, order, field string) (o []AccessSecurity, total int64, err error) {
t := AccessSecurity{}
db := global.DB.Table(t.TableName())
dbCounter := global.DB.Table(t.TableName())
if len(ip) > 0 {
db = db.Where("ip like ?", "%"+ip+"%")
dbCounter = dbCounter.Where("ip like ?", "%"+ip+"%")
}
if len(rule) > 0 {
db = db.Where("rule = ?", rule)
dbCounter = dbCounter.Where("rule = ?", rule)
}
err = dbCounter.Count(&total).Error
if err != nil {
return nil, 0, err
}
if order == "descend" {
order = "desc"
} else {
order = "asc"
}
if field == "ip" {
field = "ip"
} else if field == "rule" {
field = "rule"
} else {
field = "priority"
}
err = db.Order(field + " " + order).Find(&o).Offset((pageIndex - 1) * pageSize).Limit(pageSize).Error
if o == nil {
o = make([]AccessSecurity, 0)
}
return
}
func CreateNewSecurity(o *AccessSecurity) error {
return global.DB.Create(o).Error
}
func UpdateSecurityById(o *AccessSecurity, id string) error {
o.ID = id
return global.DB.Updates(o).Error
}
func DeleteSecurityById(id string) error {
return global.DB.Where("id = ?", id).Delete(AccessSecurity{}).Error
}
func FindSecurityById(id string) (o *AccessSecurity, err error) {
err = global.DB.Where("id = ?", id).First(&o).Error
return
}

View File

@ -1,6 +1,7 @@
package model
import (
"next-terminal/pkg/constant"
"next-terminal/pkg/global"
"next-terminal/pkg/utils"
"strings"
@ -66,7 +67,7 @@ func FindAssetByProtocolAndIds(protocol string, assetIds []string) (o []Asset, e
func FindAssetByConditions(protocol string, account User) (o []Asset, err error) {
db := global.DB.Table("assets").Select("assets.id,assets.name,assets.ip,assets.port,assets.protocol,assets.active,assets.owner,assets.created, users.nickname as owner_name,COUNT(resource_sharers.user_id) as sharer_count").Joins("left join users on assets.owner = users.id").Joins("left join resource_sharers on assets.id = resource_sharers.resource_id").Group("assets.id")
if TypeUser == account.Type {
if constant.TypeUser == account.Type {
owner := account.ID
db = db.Where("assets.owner = ? or resource_sharers.user_id = ?", owner, owner)
}
@ -82,7 +83,7 @@ func FindPageAsset(pageIndex, pageSize int, name, protocol, tags string, account
db := global.DB.Table("assets").Select("assets.id,assets.name,assets.ip,assets.port,assets.protocol,assets.active,assets.owner,assets.created,assets.tags, users.nickname as owner_name,COUNT(resource_sharers.user_id) as sharer_count").Joins("left join users on assets.owner = users.id").Joins("left join resource_sharers on assets.id = resource_sharers.resource_id").Group("assets.id")
dbCounter := global.DB.Table("assets").Select("DISTINCT assets.id").Joins("left join resource_sharers on assets.id = resource_sharers.resource_id").Group("assets.id")
if TypeUser == account.Type {
if constant.TypeUser == account.Type {
owner := account.ID
db = db.Where("assets.owner = ? or resource_sharers.user_id = ?", owner, owner)
dbCounter = dbCounter.Where("assets.owner = ? or resource_sharers.user_id = ?", owner, owner)

View File

@ -4,6 +4,7 @@ import (
"fmt"
"github.com/labstack/echo/v4"
"gorm.io/gorm"
"next-terminal/pkg/constant"
"next-terminal/pkg/global"
"next-terminal/pkg/guacd"
"next-terminal/pkg/utils"
@ -20,8 +21,8 @@ func (r *AssetAttribute) TableName() string {
return "asset_attributes"
}
var SSHParameterNames = []string{guacd.FontName, guacd.FontSize, guacd.ColorScheme, guacd.Backspace, guacd.TerminalType, SshMode}
var RDPParameterNames = []string{guacd.RemoteApp, guacd.RemoteAppDir, guacd.RemoteAppArgs}
var SSHParameterNames = []string{guacd.FontName, guacd.FontSize, guacd.ColorScheme, guacd.Backspace, guacd.TerminalType, constant.SshMode}
var RDPParameterNames = []string{guacd.Domain, guacd.RemoteApp, guacd.RemoteAppDir, guacd.RemoteAppArgs}
var VNCParameterNames = []string{guacd.ColorDepth, guacd.Cursor, guacd.SwapRedBlue, guacd.DestHost, guacd.DestPort}
var TelnetParameterNames = []string{guacd.FontName, guacd.FontSize, guacd.ColorScheme, guacd.Backspace, guacd.TerminalType, guacd.UsernameRegex, guacd.PasswordRegex, guacd.LoginSuccessRegex, guacd.LoginFailureRegex}
var KubernetesParameterNames = []string{guacd.FontName, guacd.FontSize, guacd.ColorScheme, guacd.Backspace, guacd.TerminalType, guacd.Namespace, guacd.Pod, guacd.Container, guacd.UesSSL, guacd.ClientCert, guacd.ClientKey, guacd.CaCert, guacd.IgnoreCert}

View File

@ -1,6 +1,7 @@
package model
import (
"next-terminal/pkg/constant"
"next-terminal/pkg/global"
"next-terminal/pkg/utils"
)
@ -32,7 +33,7 @@ func FindPageCommand(pageIndex, pageSize int, name, content, order, field string
db := global.DB.Table("commands").Select("commands.id,commands.name,commands.content,commands.owner,commands.created, users.nickname as owner_name,COUNT(resource_sharers.user_id) as sharer_count").Joins("left join users on commands.owner = users.id").Joins("left join resource_sharers on commands.id = resource_sharers.resource_id").Group("commands.id")
dbCounter := global.DB.Table("commands").Select("DISTINCT commands.id").Joins("left join resource_sharers on commands.id = resource_sharers.resource_id").Group("commands.id")
if TypeUser == account.Type {
if constant.TypeUser == account.Type {
owner := account.ID
db = db.Where("commands.owner = ? or resource_sharers.user_id = ?", owner, owner)
dbCounter = dbCounter.Where("commands.owner = ? or resource_sharers.user_id = ?", owner, owner)

View File

@ -1,16 +1,11 @@
package model
import (
"next-terminal/pkg/constant"
"next-terminal/pkg/global"
"next-terminal/pkg/utils"
)
// 密码
const Custom = "custom"
// 密钥
const PrivateKey = "private-key"
type Credential struct {
ID string `gorm:"primary_key" json:"id"`
Name string `json:"name"`
@ -45,7 +40,7 @@ type CredentialSimpleVo struct {
func FindAllCredential(account User) (o []CredentialSimpleVo, err error) {
db := global.DB.Table("credentials").Select("DISTINCT credentials.id,credentials.name").Joins("left join resource_sharers on credentials.id = resource_sharers.resource_id")
if account.Type == TypeUser {
if account.Type == constant.TypeUser {
db = db.Where("credentials.owner = ? or resource_sharers.user_id = ?", account.ID, account.ID)
}
err = db.Find(&o).Error
@ -56,7 +51,7 @@ func FindPageCredential(pageIndex, pageSize int, name, order, field string, acco
db := global.DB.Table("credentials").Select("credentials.id,credentials.name,credentials.type,credentials.username,credentials.owner,credentials.created,users.nickname as owner_name,COUNT(resource_sharers.user_id) as sharer_count").Joins("left join users on credentials.owner = users.id").Joins("left join resource_sharers on credentials.id = resource_sharers.resource_id").Group("credentials.id")
dbCounter := global.DB.Table("credentials").Select("DISTINCT credentials.id").Joins("left join resource_sharers on credentials.id = resource_sharers.resource_id").Group("credentials.id")
if TypeUser == account.Type {
if constant.TypeUser == account.Type {
owner := account.ID
db = db.Where("credentials.owner = ? or resource_sharers.user_id = ?", owner, owner)
dbCounter = dbCounter.Where("credentials.owner = ? or resource_sharers.user_id = ?", owner, owner)

View File

@ -6,6 +6,7 @@ import (
"fmt"
"github.com/robfig/cron/v3"
"github.com/sirupsen/logrus"
"next-terminal/pkg/constant"
"next-terminal/pkg/global"
"next-terminal/pkg/term"
"next-terminal/pkg/utils"
@ -13,17 +14,6 @@ import (
"time"
)
const (
JobStatusRunning = "running"
JobStatusNotRunning = "not-running"
FuncCheckAssetStatusJob = "check-asset-status-job"
FuncShellJob = "shell-job"
JobModeAll = "all"
JobModeCustom = "custom"
)
type Job struct {
ID string `gorm:"primary_key" json:"id"`
CronJobId int `json:"cronJobId"`
@ -91,7 +81,7 @@ func FindJobByFunc(function string) (o []Job, err error) {
func CreateNewJob(o *Job) (err error) {
if o.Status == JobStatusRunning {
if o.Status == constant.JobStatusRunning {
j, err := getJob(o)
if err != nil {
return err
@ -107,11 +97,12 @@ func CreateNewJob(o *Job) (err error) {
}
func UpdateJobById(o *Job, id string) (err error) {
if o.Status == JobStatusRunning {
if o.Status == constant.JobStatusRunning {
return errors.New("请先停止定时任务后再修改")
}
return global.DB.Where("id = ?", id).Updates(o).Error
o.ID = id
return global.DB.Updates(o).Error
}
func UpdateJonUpdatedById(id string) (err error) {
@ -125,7 +116,7 @@ func ChangeJobStatusById(id, status string) (err error) {
if err != nil {
return err
}
if status == JobStatusRunning {
if status == constant.JobStatusRunning {
j, err := getJob(&job)
if err != nil {
return err
@ -136,11 +127,11 @@ func ChangeJobStatusById(id, status string) (err error) {
}
logrus.Debugf("开启计划任务「%v」,运行中计划任务数量「%v」", job.Name, len(global.Cron.Entries()))
return global.DB.Updates(Job{ID: id, Status: JobStatusRunning, CronJobId: int(entryID)}).Error
return global.DB.Updates(Job{ID: id, Status: constant.JobStatusRunning, CronJobId: int(entryID)}).Error
} else {
global.Cron.Remove(cron.EntryID(job.CronJobId))
logrus.Debugf("关闭计划任务「%v」,运行中计划任务数量「%v」", job.Name, len(global.Cron.Entries()))
return global.DB.Updates(Job{ID: id, Status: JobStatusNotRunning}).Error
return global.DB.Updates(Job{ID: id, Status: constant.JobStatusNotRunning}).Error
}
}
@ -167,8 +158,8 @@ func DeleteJobById(id string) error {
if err != nil {
return err
}
if job.Status == JobStatusRunning {
if err := ChangeJobStatusById(id, JobStatusNotRunning); err != nil {
if job.Status == constant.JobStatusRunning {
if err := ChangeJobStatusById(id, constant.JobStatusNotRunning); err != nil {
return err
}
}
@ -177,9 +168,9 @@ func DeleteJobById(id string) error {
func getJob(j *Job) (job cron.Job, err error) {
switch j.Func {
case FuncCheckAssetStatusJob:
case constant.FuncCheckAssetStatusJob:
job = CheckAssetStatusJob{ID: j.ID, Mode: j.Mode, ResourceIds: j.ResourceIds, Metadata: j.Metadata}
case FuncShellJob:
case constant.FuncShellJob:
job = ShellJob{ID: j.ID, Mode: j.Mode, ResourceIds: j.ResourceIds, Metadata: j.Metadata}
default:
return nil, errors.New("未识别的任务")
@ -200,7 +191,7 @@ func (r CheckAssetStatusJob) Run() {
}
var assets []Asset
if r.Mode == JobModeAll {
if r.Mode == constant.JobModeAll {
assets, _ = FindAllAsset()
} else {
assets, _ = FindAssetByIds(strings.Split(r.ResourceIds, ","))
@ -258,7 +249,7 @@ func (r ShellJob) Run() {
}
var assets []Asset
if r.Mode == JobModeAll {
if r.Mode == constant.JobModeAll {
assets, _ = FindAssetByProtocol("ssh")
} else {
assets, _ = FindAssetByProtocolAndIds("ssh", strings.Split(r.ResourceIds, ","))
@ -299,7 +290,7 @@ func (r ShellJob) Run() {
return
}
if credential.Type == Custom {
if credential.Type == constant.Custom {
username = credential.Username
password = credential.Password
} else {

View File

@ -4,18 +4,11 @@ import (
"github.com/jordan-wright/email"
"github.com/sirupsen/logrus"
"net/smtp"
"next-terminal/pkg/constant"
"next-terminal/pkg/global"
"next-terminal/pkg/guacd"
)
const (
SshMode = "ssh-mode"
MailHost = "mail-host"
MailPort = "mail-port"
MailUsername = "mail-username"
MailPassword = "mail-password"
)
type Property struct {
Name string `gorm:"primary_key" json:"name"`
Value string `json:"value"`
@ -74,10 +67,10 @@ func GetRecordingPath() (string, error) {
func SendMail(to, subject, text string) {
propertiesMap := FindAllPropertiesMap()
host := propertiesMap[MailHost]
port := propertiesMap[MailPort]
username := propertiesMap[MailUsername]
password := propertiesMap[MailPassword]
host := propertiesMap[constant.MailHost]
port := propertiesMap[constant.MailPort]
username := propertiesMap[constant.MailUsername]
password := propertiesMap[constant.MailPassword]
if host == "" || port == "" || username == "" || password == "" {
logrus.Debugf("邮箱信息不完整,跳过发送邮件。")

View File

@ -1,6 +1,7 @@
package model
import (
"next-terminal/pkg/constant"
"next-terminal/pkg/global"
"next-terminal/pkg/utils"
"os"
@ -8,18 +9,6 @@ import (
"time"
)
const (
NoConnect = "no_connect"
Connecting = "connecting"
Connected = "connected"
Disconnected = "disconnected"
)
const (
Guacd = "guacd"
Naive = "naive"
)
type Session struct {
ID string `gorm:"primary_key" json:"id"`
Protocol string `json:"protocol"`
@ -130,7 +119,7 @@ func FindSessionByStatusIn(statuses []string) (o []Session, err error) {
func FindOutTimeSessions(dayLimit int) (o []Session, err error) {
limitTime := time.Now().Add(time.Duration(-dayLimit*24) * time.Hour)
err = global.DB.Where("status = ? and connected_time < ?", Disconnected, limitTime).Find(&o).Error
err = global.DB.Where("status = ? and connected_time < ?", constant.Disconnected, limitTime).Find(&o).Error
return
}
@ -187,7 +176,7 @@ func DeleteSessionByStatus(status string) {
}
func CountOnlineSession() (total int64, err error) {
err = global.DB.Where("status = ?", Connected).Find(&Session{}).Count(&total).Error
err = global.DB.Where("status = ?", constant.Connected).Find(&Session{}).Count(&total).Error
return
}

View File

@ -2,10 +2,6 @@ package model
import "next-terminal/pkg/global"
const (
FontSize = "font-size"
)
type UserAttribute struct {
Id string `gorm:"index" json:"id"`
UserId string `gorm:"index" json:"userId"`

View File

@ -6,11 +6,6 @@ import (
"reflect"
)
const (
TypeUser = "user"
TypeAdmin = "admin"
)
type User struct {
ID string `gorm:"primary_key" json:"id"`
Username string `gorm:"index" json:"username"`