mirror of
https://github.com/shadow1ng/fscan.git
synced 2025-09-14 14:06:44 +08:00

将所有服务插件移动到plugins/services/目录下,使目录结构更加清晰直观: • 创建plugins/services/目录统一管理服务扫描插件 • 添加init.go提供类型别名和函数导出 • 更新main.go导入路径 • 所有20个服务插件功能验证正常 新的目录结构更便于插件管理和维护。
363 lines
9.5 KiB
Go
363 lines
9.5 KiB
Go
package services
|
||
|
||
import (
|
||
"context"
|
||
"database/sql"
|
||
"fmt"
|
||
"strings"
|
||
|
||
// _ "github.com/mattn/go-oci8" // Oracle驱动需要特殊安装,暂时注释
|
||
"github.com/shadow1ng/fscan/common"
|
||
"github.com/shadow1ng/fscan/common/i18n"
|
||
)
|
||
|
||
// OraclePlugin Oracle数据库扫描和利用插件 - 包含数据库查询利用功能
|
||
type OraclePlugin struct {
|
||
name string
|
||
ports []int
|
||
}
|
||
|
||
// NewOraclePlugin 创建Oracle插件
|
||
func NewOraclePlugin() *OraclePlugin {
|
||
return &OraclePlugin{
|
||
name: "oracle",
|
||
ports: []int{1521, 1522, 1525}, // Oracle端口
|
||
}
|
||
}
|
||
|
||
// GetName 实现Plugin接口
|
||
func (p *OraclePlugin) GetName() string {
|
||
return p.name
|
||
}
|
||
|
||
// GetPorts 实现Plugin接口
|
||
func (p *OraclePlugin) GetPorts() []int {
|
||
return p.ports
|
||
}
|
||
|
||
// Scan 执行Oracle扫描 - 弱密码检测
|
||
func (p *OraclePlugin) Scan(ctx context.Context, info *common.HostInfo) *ScanResult {
|
||
target := fmt.Sprintf("%s:%s", info.Host, info.Ports)
|
||
|
||
// 如果禁用暴力破解,只做服务识别
|
||
if common.DisableBrute {
|
||
return p.identifyService(ctx, info)
|
||
}
|
||
|
||
// 生成测试凭据
|
||
credentials := GenerateCredentials("oracle")
|
||
if len(credentials) == 0 {
|
||
// Oracle默认凭据
|
||
credentials = []Credential{
|
||
{Username: "sys", Password: "sys"},
|
||
{Username: "sys", Password: "system"},
|
||
{Username: "sys", Password: "oracle"},
|
||
{Username: "system", Password: "system"},
|
||
{Username: "system", Password: "oracle"},
|
||
{Username: "system", Password: "manager"},
|
||
{Username: "scott", Password: "tiger"},
|
||
{Username: "oracle", Password: "oracle"},
|
||
{Username: "admin", Password: "admin"},
|
||
}
|
||
}
|
||
|
||
// 逐个测试凭据
|
||
for _, cred := range credentials {
|
||
// 检查Context是否被取消
|
||
select {
|
||
case <-ctx.Done():
|
||
return &ScanResult{
|
||
Success: false,
|
||
Service: "oracle",
|
||
Error: ctx.Err(),
|
||
}
|
||
default:
|
||
}
|
||
|
||
// 测试凭据
|
||
if db := p.testCredential(ctx, info, cred); db != nil {
|
||
db.Close() // 关闭测试连接
|
||
|
||
// Oracle认证成功
|
||
common.LogSuccess(i18n.GetText("oracle_scan_success", target, cred.Username, cred.Password))
|
||
|
||
return &ScanResult{
|
||
Success: true,
|
||
Service: "oracle",
|
||
Username: cred.Username,
|
||
Password: cred.Password,
|
||
}
|
||
}
|
||
}
|
||
|
||
// 所有凭据都失败
|
||
return &ScanResult{
|
||
Success: false,
|
||
Service: "oracle",
|
||
Error: fmt.Errorf("未发现弱密码"),
|
||
}
|
||
}
|
||
|
||
// Exploit 执行Oracle利用操作 - 实现数据库查询功能
|
||
func (p *OraclePlugin) Exploit(ctx context.Context, info *common.HostInfo, creds Credential) *ExploitResult {
|
||
// 建立Oracle连接
|
||
db := p.testCredential(ctx, info, creds)
|
||
if db == nil {
|
||
return &ExploitResult{
|
||
Success: false,
|
||
Error: fmt.Errorf("Oracle连接失败"),
|
||
}
|
||
}
|
||
defer db.Close()
|
||
|
||
target := fmt.Sprintf("%s:%s", info.Host, info.Ports)
|
||
common.LogSuccess(fmt.Sprintf("Oracle利用开始: %s (用户: %s)", target, creds.Username))
|
||
|
||
var output strings.Builder
|
||
output.WriteString(fmt.Sprintf("=== Oracle利用结果 - %s ===\n", target))
|
||
|
||
// 获取版本信息
|
||
if version := p.getVersion(db); version != "" {
|
||
output.WriteString(fmt.Sprintf("\n[版本信息]\n%s\n", version))
|
||
}
|
||
|
||
// 获取数据库信息
|
||
if dbInfo := p.getDatabaseInfo(db); dbInfo != "" {
|
||
output.WriteString(fmt.Sprintf("\n[数据库信息]\n%s\n", dbInfo))
|
||
}
|
||
|
||
// 获取表空间信息
|
||
if tablespaces := p.getTablespaces(db); len(tablespaces) > 0 {
|
||
output.WriteString(fmt.Sprintf("\n[表空间] (共%d个)\n", len(tablespaces)))
|
||
for i, ts := range tablespaces {
|
||
if i >= 5 { // 限制显示前5个
|
||
output.WriteString("... (更多表空间)\n")
|
||
break
|
||
}
|
||
output.WriteString(fmt.Sprintf(" %s\n", ts))
|
||
}
|
||
}
|
||
|
||
// 获取用户列表
|
||
if users := p.getUsers(db); len(users) > 0 {
|
||
output.WriteString(fmt.Sprintf("\n[用户列表] (共%d个)\n", len(users)))
|
||
for i, user := range users {
|
||
if i >= 10 { // 限制显示前10个用户
|
||
output.WriteString("... (更多用户)\n")
|
||
break
|
||
}
|
||
output.WriteString(fmt.Sprintf(" %s\n", user))
|
||
}
|
||
}
|
||
|
||
// 获取表列表(当前用户)
|
||
if tables := p.getTables(db, creds.Username); len(tables) > 0 {
|
||
output.WriteString(fmt.Sprintf("\n[用户表] (共%d个)\n", len(tables)))
|
||
for i, table := range tables {
|
||
if i >= 5 { // 限制显示前5个表
|
||
output.WriteString("... (更多表)\n")
|
||
break
|
||
}
|
||
output.WriteString(fmt.Sprintf(" %s\n", table))
|
||
}
|
||
}
|
||
|
||
// 获取权限信息
|
||
if privileges := p.getPrivileges(db, creds.Username); privileges != "" {
|
||
output.WriteString(fmt.Sprintf("\n[用户权限]\n%s\n", privileges))
|
||
}
|
||
|
||
common.LogSuccess(fmt.Sprintf("Oracle利用完成: %s", target))
|
||
|
||
return &ExploitResult{
|
||
Success: true,
|
||
Output: output.String(),
|
||
}
|
||
}
|
||
|
||
// testCredential 测试单个凭据 - 返回数据库连接或nil
|
||
func (p *OraclePlugin) testCredential(ctx context.Context, info *common.HostInfo, cred Credential) *sql.DB {
|
||
// Oracle驱动需要特殊安装,这里简化实现
|
||
// 在实际环境中需要安装Oracle客户端和go-oci8驱动
|
||
return nil
|
||
}
|
||
|
||
// getVersion 获取Oracle版本信息
|
||
func (p *OraclePlugin) getVersion(db *sql.DB) string {
|
||
var version string
|
||
err := db.QueryRow("SELECT banner FROM v$version WHERE rownum = 1").Scan(&version)
|
||
if err != nil {
|
||
// 尝试备用查询
|
||
err = db.QueryRow("SELECT version FROM product_component_version WHERE rownum = 1").Scan(&version)
|
||
if err != nil {
|
||
return ""
|
||
}
|
||
}
|
||
return version
|
||
}
|
||
|
||
// getDatabaseInfo 获取数据库基本信息
|
||
func (p *OraclePlugin) getDatabaseInfo(db *sql.DB) string {
|
||
var info strings.Builder
|
||
|
||
// 获取数据库名
|
||
var dbName string
|
||
err := db.QueryRow("SELECT name FROM v$database").Scan(&dbName)
|
||
if err == nil {
|
||
info.WriteString(fmt.Sprintf("数据库名: %s\n", dbName))
|
||
}
|
||
|
||
// 获取实例名
|
||
var instanceName string
|
||
err = db.QueryRow("SELECT instance_name FROM v$instance").Scan(&instanceName)
|
||
if err == nil {
|
||
info.WriteString(fmt.Sprintf("实例名: %s\n", instanceName))
|
||
}
|
||
|
||
// 获取字符集
|
||
var charset string
|
||
err = db.QueryRow("SELECT value FROM nls_database_parameters WHERE parameter = 'NLS_CHARACTERSET'").Scan(&charset)
|
||
if err == nil {
|
||
info.WriteString(fmt.Sprintf("字符集: %s\n", charset))
|
||
}
|
||
|
||
return info.String()
|
||
}
|
||
|
||
// getTablespaces 获取表空间列表
|
||
func (p *OraclePlugin) getTablespaces(db *sql.DB) []string {
|
||
query := "SELECT tablespace_name FROM dba_tablespaces"
|
||
rows, err := db.Query(query)
|
||
if err != nil {
|
||
// 尝试用户表空间查询
|
||
query = "SELECT tablespace_name FROM user_tablespaces"
|
||
rows, err = db.Query(query)
|
||
if err != nil {
|
||
return nil
|
||
}
|
||
}
|
||
defer rows.Close()
|
||
|
||
var tablespaces []string
|
||
for rows.Next() {
|
||
var tsName string
|
||
if err := rows.Scan(&tsName); err == nil {
|
||
tablespaces = append(tablespaces, tsName)
|
||
}
|
||
}
|
||
|
||
return tablespaces
|
||
}
|
||
|
||
// getUsers 获取用户列表
|
||
func (p *OraclePlugin) getUsers(db *sql.DB) []string {
|
||
query := "SELECT username FROM dba_users ORDER BY username"
|
||
rows, err := db.Query(query)
|
||
if err != nil {
|
||
// 尝试all_users
|
||
query = "SELECT username FROM all_users ORDER BY username"
|
||
rows, err = db.Query(query)
|
||
if err != nil {
|
||
return nil
|
||
}
|
||
}
|
||
defer rows.Close()
|
||
|
||
var users []string
|
||
for rows.Next() {
|
||
var userName string
|
||
if err := rows.Scan(&userName); err == nil {
|
||
users = append(users, userName)
|
||
}
|
||
}
|
||
|
||
return users
|
||
}
|
||
|
||
// getTables 获取指定用户的表列表
|
||
func (p *OraclePlugin) getTables(db *sql.DB, owner string) []string {
|
||
query := "SELECT table_name FROM dba_tables WHERE owner = :1 ORDER BY table_name"
|
||
rows, err := db.Query(query, strings.ToUpper(owner))
|
||
if err != nil {
|
||
// 尝试用户表查询
|
||
query = "SELECT table_name FROM user_tables ORDER BY table_name"
|
||
rows, err = db.Query(query)
|
||
if err != nil {
|
||
return nil
|
||
}
|
||
}
|
||
defer rows.Close()
|
||
|
||
var tables []string
|
||
for rows.Next() {
|
||
var tableName string
|
||
if err := rows.Scan(&tableName); err == nil {
|
||
tables = append(tables, tableName)
|
||
}
|
||
}
|
||
|
||
return tables
|
||
}
|
||
|
||
// getPrivileges 获取用户权限信息
|
||
func (p *OraclePlugin) getPrivileges(db *sql.DB, username string) string {
|
||
var privileges strings.Builder
|
||
|
||
// 检查DBA权限
|
||
var dbaRole int
|
||
err := db.QueryRow("SELECT COUNT(*) FROM dba_role_privs WHERE grantee = :1 AND granted_role = 'DBA'",
|
||
strings.ToUpper(username)).Scan(&dbaRole)
|
||
if err == nil && dbaRole > 0 {
|
||
privileges.WriteString("DBA权限: YES\n")
|
||
} else {
|
||
privileges.WriteString("DBA权限: NO\n")
|
||
}
|
||
|
||
// 检查SYSDBA权限
|
||
var sysdbaCount int
|
||
err = db.QueryRow("SELECT COUNT(*) FROM v$pwfile_users WHERE username = :1 AND sysdba = 'TRUE'",
|
||
strings.ToUpper(username)).Scan(&sysdbaCount)
|
||
if err == nil && sysdbaCount > 0 {
|
||
privileges.WriteString("SYSDBA权限: YES\n")
|
||
}
|
||
|
||
// 获取角色列表
|
||
query := "SELECT granted_role FROM dba_role_privs WHERE grantee = :1 AND rownum <= 5"
|
||
rows, err := db.Query(query, strings.ToUpper(username))
|
||
if err == nil {
|
||
defer rows.Close()
|
||
privileges.WriteString("已授予角色: ")
|
||
var roles []string
|
||
for rows.Next() {
|
||
var role string
|
||
if err := rows.Scan(&role); err == nil {
|
||
roles = append(roles, role)
|
||
}
|
||
}
|
||
if len(roles) > 0 {
|
||
privileges.WriteString(strings.Join(roles, ", ") + "\n")
|
||
} else {
|
||
privileges.WriteString("无\n")
|
||
}
|
||
}
|
||
|
||
return privileges.String()
|
||
}
|
||
|
||
// identifyService 服务识别 - 检测Oracle服务
|
||
func (p *OraclePlugin) identifyService(ctx context.Context, info *common.HostInfo) *ScanResult {
|
||
// Oracle驱动需要特殊安装,这里简化实现
|
||
// 在实际环境中需要安装Oracle客户端和go-oci8驱动
|
||
return &ScanResult{
|
||
Success: false,
|
||
Service: "oracle",
|
||
Error: fmt.Errorf("Oracle驱动未安装"),
|
||
}
|
||
}
|
||
|
||
// init 自动注册插件
|
||
func init() {
|
||
RegisterPlugin("oracle", func() Plugin {
|
||
return NewOraclePlugin()
|
||
})
|
||
} |