欢迎关注我的微信公众号《壳中之魂》,查看更多网安文章
敏感信息一般分为系统敏感信息和应用敏感信息两大类,其中,系统敏感信息一般为业务系统本身的基础环境信息,例如系统信息、中间件版本、代码信息;应用敏感信息又可以分为个人敏感信息和非个人敏感信息,个人敏感信息包括身份证、姓名、电话号码、邮箱等,非个人敏感信息则可能是企事业单位甚至国家层面的敏感信息。系统敏感信息的泄露可能为攻击者提供更多的攻击途径与方法,而应用敏感信息的泄露造成的危害就因信息内容而定。
TurboMail邮件系统是某面向企事业单位通信需求而研发的电子邮件服务器系统。该系统的5.2.0版本没有进行充分的权限验证,使每个用户都可以通过访问接口获知“当前已经登录过的用户的邮箱地址”。由于在邮箱的登录页面没有设置验证码,如果用户的密码强度不够,攻击者可能进行爆破登录。
通过查看TurboMail的安装路径,可以发现TurboMail是Java EE工程,通过审计web.xml,可以发现url-pattern“mailmain”对应servlet-name“mailmaini”
<servlet-mapping>
<servlet-name>mailmaini</servlet-name>
<url-pattern>/mailmain</url-pattern>
</servlet-mapping>
审计servlet-name“mailmaini”所对应的类servlet-class,可以发现它对应类
<servlet-name>mailmaini</servlet-name>
<servlet-class>turbomail.web.MailMain</servlet-class>
通过搜索turbomail,找到一个名字相同的jar包
使用JD-gui反编译,可以发现“MailMain”位于该Jar包中,路径为turbomail\web\mailmain,查看MailMain方法,发现其继承自httpservlet类,且会接受一个名为type的请求参数
String type = request.getParameter("type");
当出现“type.equals("pm")”时,会调用PMAdmin的show方法
else if (type.equals("pm")) {
/* 636 */ PMAdmin.show(false, request, response);
/* 637 */ }
对PMAdmin的show方法进行审计,可以发现如下代码在输出数据前并没有进行权限验证,即任何人都可以发送请求
public static void show(boolean bAjax, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
/* 38 */ PMInterface pm = null;
/* */
/* 40 */ StringBuffer sb = new StringBuffer();
/* */
/* 42 */ for (int i = 0; i < alPM.size(); i++) {
/* 43 */ pm = alPM.get(i);
/* 44 */ sb.append(pm.PM());
/* */
/* 46 */ sb.append("\r\n");
/* */ }
/* */
/* */
/* 50 */ String str = sb.toString();
/* 51 */ response.getOutputStream().write(str.getBytes(SysConts.New_InCharSet));
/* */ }
/* */ }
访问地址http://169.254.109.87:8080/mailmain?type=pm可以发现显示出了登陆过的用户信息,造成了敏感信息泄露
若开发人员未做好自定义错误页面,则容易将网站的一些开发组件信息暴露,报错信息中可能会包含服务器代码信息、数据库连接信息、SQL语句或者敏感文件的路径,为攻击者收集信息提供了方便。
参考网站:公司项目被安全公司扫描出“报错页面敏感信息泄露”,问题如下?-H5W3
可以看到已经获取到了此网站的tomcat版本,因此可以轻易地在网上搜索相关版本的漏洞信息
在例子中,开发者已经配置了错误错误路径,然而没有配置405错误码,而此次报错正好是405错误码,所以没有被引导到error.jsp
<error-page>
<error-code>404</error-code>
<location>/error.jsp</location>
</error-page>
<error-page>
<error-code>500</error-code>
<location>/error.jsp</location>
</error-page>
<error-page>
<exception-type>java.lang.Exception</exception-type>
<location>/error.jsp</location>
</error-page>
<welcome-file-list>
<welcome-file>pc/index.html</welcome-file>
</welcome-file-list>
一般错误界面不仅会暴露出使用的中间件,如果是在数据库查询功能页面,还会暴露出SQL语句、使用的数据库及版本以及使用的框架等
修复建议:
1、编码时增加异常处理模块,对错误页面做统一的自定义返回界面,隐藏服务器版本信息;
2、不对外输出程序运行时产生的异常错误信息详情。
在java开发中,异常抛出一般有两种,一个是try...catch,另一种就是使用throw,伴随着try catch的还有e.printStackTrace()方法,当发生错误时,e.printStackTrace()方法就会把错误信息输出
try (Connection connection = dataSource.getConnection()) {
} catch (Exception e) {
e.printStackTrace();
}
然而输出错误信息的同时还会输出一些开发组件信息,如
SQL语句:
hibernate框架
strust2
修复建议:
1、将错误代码输出到后台的日志文件中
2、不把错误异常对外抛出
参考文章:如何在Java源代码中隐藏硬编码密码 | 码农家园 (codenong.com)
假设在一个登录中,以这种方式保存账号密码
String username ="username";
String password ="password";
login(username, password);
当我把源码开源后,亦或者是报错把源码输出时,这种硬编码方式就会泄露用户密码
修复建议:
将用户名和密码放在与程序分开的配置文件中大致如下:
Properties login = new Properties();
try (FileReader in = new FileReader("login.properties")) {
login.load(in);
}
String username = login.getProperty("username");
String password = login.getProperty("password");
并创建一个文件login.properties,其中包含:
username=your_username_here
password=your_password_here
从其他文件读取密码与账号,就在一定程度避免了硬编码导致的信息泄露
目录穿越漏洞往往出现在需要用户提供路径或文件名时,如文件下载,造成目录穿越漏洞的原因是开发者没有对路径进行检验,判断是否存在../等特殊字符,没有对访问的文件进行限制导致目录穿越,读取到本不应该读取到的内容
假如正常功能下允许用户访问filename=file.txt文件,路径为/www/file/file.txt,但是如果没有控制好传入的filename参数,就有可能通过../../../etc/passwd的方式读取密码文件,此时的路径为/www/file/../../../etc/passwd
目录穿越漏洞产生的本质是路径可控,一旦涉及文件的读取问题便会涉及java.io.File类,因此在审计这类漏洞时可以优先查找java.io.File引用,并根据经验来判断Paths、path、System.getProperty("user.dir")等各类可能会用来构造路径的关键字,若项目采用Spring MVC这类框架也可以先查看一下路由,判断是否存在如path之类的路由
以下代码模拟网站业务,需要用户输入文件名,根据文件名显示内容,当前设置的目录路径为C:\Users\HHY\Desktop\Upload\File,在此文件夹下有一个名为world.txt的文件,在C:\Users\HHY\Desktop\Upload文件夹(也就是上一级文件夹下)存在hello.txt文件
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String path = "C:\\Users\\HHY\\Desktop\\Upload\\File\\";
System.out.println("请输入要浏览的文件名(当前目录下有world.txt,上一目录有hello.txt)");
String filename = sc.nextLine();
try {
BufferedReader in = new BufferedReader(new FileReader(path + filename + ".txt"));
String str;
while ((str = in.readLine()) != null) {
System.out.println(str);
}
// System.out.println(str);
} catch (IOException e) {
e.printStackTrace();
}
}
正常情况下只允许用户读取当前路径的然而没有对路径进行过滤,导致可以通过../等字符遍历其他文件
修复建议:
1、传入的路径(文件名)不允许./或者../
if(filename.indexOf("..") != -1 || temp.charAt(0) == '/')
if(filename.indexOf("/.//") == -1 && filename.indexOf("/././/") == -1){
exit();
} else {
//do
}
2、白名单ID索引(针对于下载业务)
通过建立数据库的方式,当一个文件上传时就把它的文件名添加到白名单里面,当下载文件时则去查询此文件名是否存在此白名单内,因此防止此漏洞不仅要在读取文件时进行路径的过滤,还要在上传文件时对文件名、路径进行一定程度的过滤才能达到效果
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。