某次渗透中,遇到个jsp的站,弱密码进到后台以后,却发现功能很少,并不好搞,简单排查后并无突破,然而老大给的要求是尽快搞到shell。。。
一番梳理后,我的想法是:要么通过漏洞拿下后台,要么搞到源码直接白盒开冲。白盒的话很香,对审计能力提升也大,所以可以按下面几步来试试:
dirbuster
的字典directory-list-2.3-medium.txt
指定后缀jsp
来扫,工具就随便用个顺手的,dirseach
内心OS:这年头——可不敢乱点。
favicon.ico
,或是用title来搜,准确率都相当惊人
那工具方面,首先是选用了broken5
师傅的https://github.com/broken5/WebAliveScan,1024个线程猛冲之后,却并无发现。。。
考虑是不是字典不够牛,接着使用dirsearch
自带的字典(约17,000条),
# 只要字典大,没有拿不下 python3 dirsearch3.py -e "jsp" -l ip_port.txt -t 50 --plain-text-report=ip_port_DirScan.txt -q
跑目标列表花了一个上午,终于有了收获——web.rar
,香!
天黑了,打开IDEA!天亮了,关闭IDEA。
我发现jsp
的代码虽然不难懂,可基础知识不牢,代码审起来简直让人打脑壳,于是有了下面这第一章。
正常情况下的目录结构,长下面这样
exampleApp └─images └─WEB-INF │ ├─classes # 包含了所有的 Servlet 类和其他类文件【重要】 │ │ └─com │ │ └─example │ │ │ └─lib # 项目依赖包的储存位置(.jar文件) └─web.xml # Servlet的配置文件【重要】
定义路由
路由的定义,可以在这两个地方进行:Servlet注解
、web.xml
, 配置的时候二选一即可。
@WebServlet("/Hello") public class HelloServlet extends HttpServlet{ //处理 GET 方法请求的方法 public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=UTF-8"); //实现的代码 } //处理POST方法请求的方法 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=UTF-8"); //实现的代码 } }
Servlet3.0之前,需要在web.xml中配置,才能够使用Servlet,这一块由于路由跟逻辑并不在一块儿实现,比较陌生,因此我们重点看下它。
web.xml
Java项目中的web.xml
,可以配置web的路由,里面的属性很多,咱们主要关心两条:
<url-pattern>,</url-pattern>路由。为servlet提供一个缺省的URL:http://host/webAppPre fix/servlet/ServletName
<?xml version="1.0" encoding="ISO-8859-1"?> <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd"> <web-app> <servlet> <servlet-name>HelloServlet</servlet-name> <servlet-class>com.example.HelloServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>HelloServlet</servlet-name> <url-pattern>/Hello</url-pattern> </servlet-mapping> </web-app>
## Ⅲ jsp:useBean标签
同时,在jsp
代码的开头,看到大量使用<jsp:useBean...
的代码,见图片中的第2~4行。
这东西,叫**<jsp:useBean>**
标签,它的定义,整理出来是这样的:
<jsp:useBean>
标签可以在JSP中声明一个JavaBean
,然后使用。
- 声明后,
JavaBean
对象就成了脚本变量,可以通过脚本元素或其他自定义标签来访问。<jsp:useBean>
标签的语法格式如下:<jsp:useBean id="HttpSession" scope="session" class="example.HttpSession"/>
- id值,可随意定义,只要跟上下文不重复;在习惯上,跟
class
的最后一级相同(HttpSession
);- scope值,可以是
page
,request
,session
或application
,分别对应不同的作用范围,注意不要将【需要经常变动的bean
】 的scope
设为application
或session
- class值,指定对应的
java
类;一般是WEB-INF/classes/
为起点的一个相对路径(用点作路径分隔符)
而JavaBean
,个人认为就是Java的一种对象,遵循一些规范,有一些特征。
因此,在审计时,只需先在jsp文件中找敏感函数,根据当前文件中的标签定义,找到定义函数的.class
,完成漏洞的确认就好了。用IDEA可以很方便地进行查看。
JSP中取request参数的写法,虽然非常好理解,但对小白来说,也是有一些需要注意的点。
<%@ page contentType="text/html; charset=gb2312" language="java" errorPage="" %> ... <% String id; id = request.getParameter("id"); // 处理中文 String name =new String(request.getParameter("name").getBytes("ISO-8859-1"),"UTF-8"); ...
上面这段代码中,使用request.getParameter
来接受client发送的HTTP参数。但对于id参数,无论你以GET
、还是POST
方法来提交的,都能被server接收。
也就是说:request.getParameter
是兼容POST/GET
参数滴!有点像PHP中的$_REQUEST
方法。
同时,对于中文数据,需要对其转码,才能正常显示。
当然,JSP中还有其它取参数的写法,由于并未在本次渗透中出现,也就不再赘述。感兴趣的师傅可以自行了解。
此外,在项目中还出现了文件包含的写法
<%@ include file="check.jsp"%>
经过一番学习,这个跟PHP中的文件包含有点像
那看看check.jsp
的内容吧,
很明显,下面这段代码一出现,就意味着本页面的功能属于后台功能了。
<%@ include file="check.jsp"%>
不过呢,我还有一点没搞懂,又没看到有exit
函数,为啥include以后的代码,走到out.print
以后就不再执行了呢?估计跟servlet
的生命周期有关。有了解的师傅麻烦在评论区抬一手。
OK,基础知识补充得差不多了,下面开冲,尝试完成前台RCE的挖掘。
轻松找到一处注入,无任何过滤。
不过,考虑到可能需要SQLMAP作自动化利用——删除型的注入点,还是算了。
那么,又重新找到一处拼接表名的注入点。
但问题又来了,这个测试环境的数据库文件,我之前作目录扫描的时候是搞了一份的,找半天咋找不到task_
开头的数据表呢???
没办法,只能FUZZ了,采用SecLists
里面的raft-large-words.txt
来进行FUZZ。哈哈,果然没用!
最后,审计呗,找到一处完美注入点,既不伤害数据库,又不需要花里胡哨地FUZZ。SQLMAP跑的结果如下:
注意到是DBA权限,且通过大小写判断目标是Windows环境。
对我来说,一是想到可以用UNC地址进行带外注入(可以,但在联合注入面前,没必要);
二是写webshell。一般而言,windows通过注入写webshell比linux更难一些,因为路径相对更难猜。不过,由于我手上有系统的部分源码,很快翻找到了web路径,是C:\example
,尝试使用--os-shell
写shell,并不成功;一开始还猜测是当前环境更换了盘符,结果26个字母捋了一遍,都不成功。。。
天无绝人之路啊。我回想起目标环境的Tomcat似乎很拉跨,并未对报错进行屏蔽,经常露源码出来,嘿嘿!
通过让后台备份功能产生报错,成功获得路径d:\exam\bak\
接着通过SQLMAP --os-shell
参数,也是不费工夫就拿到了SQLMAP的shell,允许上传任意文件了。
话又说回来,目前这个目标是拿下来了,可毕竟是弱密码,难免被诟病“不讲武德”。
于是,全局搜索没有包含check.jsp
的代码,发现一处前台SQL注入。。。
好的,前台getshell的方式有了,不过要知道目标环境的web路径才行,但考虑到该产品差不多采用的都是销售OEM服务器的形式,基本不会出太大岔子,所以就到此为止吧。
感谢观看,本文主要是简单的代码审计,有很多思路不到位的地方,请各位师傅不吝指点!