0x01 关于Tomcat,更多详情大家可直接参考百科说明
1
| https://zh.wikipedia.org/wiki/Apache_Tomcat
|
此次演示环境
1 2
| CentOS7 x86_64 ip: 192.168.3.64 Apache Tomcat/8.5.24 建议大家使用较新版的稳定版本
|
0x02 首先,在正式部署Tomcat之前,需要先来准备好jdk环境,因为毕竟底层还是在靠java来处理,所以必须要先得有java的运行环境才行,其实,在实际生产环境中,也可以单独使用jre
,不过个人觉得这和安全的关系并不大,试想,如果你手里都已经拿到了一个可以运行java的环境了,我在本地用对应版本的jdk编译好了再丢上运行也是一样,防不住啥,太泛泛
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| # tar xf jdk-8u151-linux-x64.tar.gz # mv jdk1.8.0_151/ /usr/local/ # ln -s /usr/local/jdk1.8.0_151/ /usr/local/jdk # tar xf apache-tomcat-8.5.24.tar.gz # mv apache-tomcat-8.5.24 /usr/local/ # ln -s /usr/local/apache-tomcat-8.5.24/ /usr/local/tomcat # ll /usr/local/ # vi /etc/profile export JAVA_HOME=/usr/local/jdk/ export PATH=$JAVA_HOME/bin:$JAVA_HOME/jre/bin:$PATH export CLASSPATH=.$CLASSPATH:$JAVA_HOME/lib:$JAVA_HOME/jre/lib:$JAVA_HOME/lib/tools.jar export TOMCAT_HOME=/usr/local/tomcat # source /etc/profile # java -version # javac
|
0x03 务必专门创建一个普通用户来运行tomcat服务,防止入侵者直接拿到root权限的webshell
,极度建议大家实际应用中在满足当前及拓展业务需求的前提下,尽量把tomcat压缩在一个极小的系统权限下,最好,除了指定的事儿,其它的让它啥也干不了
1 2 3 4 5 6 7 8 9
| # useradd -u 301 tomcat # passwd tomcat # chown -R tomcat:tomcat /usr/local/tomcat/ # chown -R tomcat:tomcat /usr/local/jdk/ # ll /usr/local/jdk/ /usr/local/tomcat/ # su - tomcat $ /usr/local/tomcat/bin/catalina.sh start $ netstat -tulnp $ cat /usr/local/tomcat/logs/catalina.out 启动过程中如果有什么问题可以去该日志
|
0x04 理解Tomcat的基本目录结构
1 2 3 4 5 6 7 8 9 10 11 12 13
| /usr/local/tomcat/ ├── bin 主要用来放置各种tomcat服务管理脚本 ├── conf 用于存放Tomcat服务的各类配置文件 ├── lib 此目录用于存放Tomcat的核心类库文件 ├── LICENSE ├── logs 主要用于放置Tomcat的启动和访问日志文件 ├── NOTICE ├── RELEASE-NOTES ├── RUNNING.txt ├── temp 存放一些缓存临时数据的目录 ├── webapps 默认的站点根目录 └── work 把jsp代码转换为java代码[class]文件时的存放目录,这就是为什么访问速度极快的原因之一,只需编译一次,后续直接访问`缓存`
|
0x05 理解Tomcat各个配置文件的主要功用
1 2 3 4 5 6 7 8 9 10 11 12 13
| /usr/local/tomcat/conf/ ├── Catalina ├── catalina.policy 当带上-security选项启动tomcat时,会自动读取并应用该文件中的策略配置 ├── catalina.properties 有关Tomcat内部各种类加载器的一些配置 ├── context.xml 此处的context.xml是作用于域全局的,一般情况下,每个站点目录下都应有一个context.xml文件,用于定义会话管理器,JDBC等 ├── jaspic-providers.xml ├── jaspic-providers.xsd ├── logging.properties 指定不同类日志的格式 ├── server.xml tomcat主配置文件 ├── tomcat-users.xml 用于tomcat web管理端认证的配置文件 ├── tomcat-users.xsd └── web.xml 站点被部署时使用的默认部署配置项
|
0x05 深入理解tomcat的运作细节及常用组件
简单回顾Tomcat的基本运作细节
1 2 3 4 5 6 7 8 9
| -> 此处,以请求 http://www.rootkit.org:8080/demo/index.jsp 为例 -> 首先,客户端来请求www.rootkit.org的8080端口,正好被监听于此的Http Connector所捕获 -> 随后,Connector会把该请求交给它所在的Service中的Engine去处理并等待Engine回应 -> 当Engine拿到这个请求后,会自动根据请求中的www.rootkit.org这个域名来匹配到它内部属于哪个Host,然后直接丢给那个Host -> 当请求到达指定的Host时,Host会自动匹配出Path为/demo所在的Context -> 之后,对应Context会拿到/index.jsp请求,再到映射表中找出对应的Servlet类去处理,如,构造HttpServletRequest和HttpServletResponse对象 -> Context会把处理好之后的HttpServletResponse对象返回给Host -> Host再把HttpServletResponse对象返回给Engine -> 最后,Engine把HttpServletResponse对象返回对应的Connector,至此,一次相对完整的Tomcat请求响应过程就基本完成了
|
关于上述提到的各个组件功用简介
1 2 3 4 5 6 7 8
| Server 一个Server即对应一个Tomcat实例,实际中机器性能好的情况下,建议直接分成多实例,不建议用它自带的虚拟主机,虚拟主机之间对性能影响较大 Service 通常由一个Engine以及一个或多个Connector组成 Connector 主要就是用来监听指定端口,然后把指定端口的请求都交给Engine Engine 其实就是实际的处理引擎,下面可以同时配置多个虚拟主机,它自身会根据域名来匹配到对应的虚拟主机 Host 即虚拟主机,一个Host即一个虚拟主机 Context Context在创建的时候会根据配置文件$CATALINA_HOME/conf/web.xml 和$WEBAPP_HOME/WEB-INF/web.xml载入Servlet类,当Context收到请求时 将到自己的映射表 [mapping table]中寻找相匹配的Servlet类,如果找到,则执行该类,并回应该请求
|
tomcat 主配置文件结构大致如下
1 2 3 4 5 6 7 8 9 10 11 12 13
| <Server> <Service> <Connector/> <Engine> <Host> <Context></Context> </Host> </Engine> </Service> <Service> ... </Service> </Server>
|
0x06 一个标准的 Java web
目录结构,如下
0x07 如何快速纯手工在Tomcat中自定义一个基于域名的虚拟主机,还是那句话,实际中机器性能够的情况下,建议用tomcat多实例,不建议用虚拟主机
先准备好站点所需的各种目录,务必要严格按照上面的java web标准来
1 2 3 4 5 6 7 8 9 10 11 12 13
| # mkdir /data/{javaweb,logs} -p # chown -R tomcat:tomcat /data/ $ su - tomcat $ cd /data/javaweb/ $ mkdir secapp/{lib,classes,WEB-INF,META-INF} -p $ vi secapp/index.jsp <html> <body> <br> <center><h1>This is a Tomcat Server 8.x </h1> <br><h2>Now time is: <%=new java.util.Date()%></h2></center> </body> </html>
|
再到tomcat主配置文件中添加Host标签段,记得禁用自动部署和自动解war包
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| $ vi /usr/local/tomcat/conf/server.xml <Host name="www.sec.org" appBase="/data/javaweb/secapp" autoDeploy="false" unpackWARs="true"> <Context path="" docBase="." debug="0" /> <Valve className="org.apache.catalina.valves.AccessLogValve" directory="/data/logs" prefix="www.sec.org_access_log" suffix=".txt" pattern="%h %l %u %t "%r" %s %b" /> </Host>
$ /usr/local/tomcat/bin/catalina.sh stop $ cd /usr/local/tomcat/ 重启前最好把下面两个目录中的内容清空,防止缓存作祟 $ rm -fr ./temp/* $ rm -fr ./work/* $ /usr/local/tomcat/bin/catalina.sh start $ cat /usr/local/tomcat/logs/catalina.out 查看tomcat启动日志,一般来这儿都是为了看报错 $ tail -f /data/logs/www.sec.org_access_log.2017-12-17.txt $ tree /usr/local/tomcat/work/
|
0x08 配置Tomcat的web端管理功能,此功能比较危险,容易被人跑到管理账号密码,直接进来即可部署webshell,如非必须,建议删除
1 2 3 4 5 6 7
| $ vi /usr/local/tomcat/conf/tomcat-users.xml <role rolename="manager-gui"/> <role rolename="admin-gui"/> <user username="tomcat" password="tomcat" roles="manager-gui,admin-gui"/> 让tomcat同时应用于两个角色 $ /usr/local/tomcat/bin/catalina.sh start 修改完配置后重启tomcat $ /usr/local/tomcat/bin/catalina.sh stop
|
0x09 修改管理端口及用于关闭服务的字符串,默认为8005,SHUTDOWN
,实际中,一般也不会用这种方式来关闭tomcat,所以,可以把关闭字符串设的更长更随机一些,不过,好在最新版本tomcat默认只监听在127.0.0.1,所以对此项不必太过紧张
1 2
| $ vi /usr/local/tomcat/conf/server.xml <Server port="9301" shutdown="a8HelEd45fm43LseDF">
|
0x10 修改AJP协议通信端口,其实你可以直接把该项注释掉,因为绝大多数情况下我们都只会使用http协议进行反向代理,而不会用AJP协议
1 2
| $ vi /usr/local/tomcat/conf/server.xml
|
0x11 禁止tomcat目录遍历,将param-value
标签中的值改为false,其实默认就是禁止的,只不过为了保险,还是需要再确认一下
1 2 3 4 5 6 7 8 9 10 11 12
| $ vi /usr/local/tomcat/conf/web.xml <init-param> <param-name>listings</param-name> <param-value>false</param-value> </init-param> <welcome-file-list> <welcome-file>index.html</welcome-file> <welcome-file>index.htm</welcome-file> <welcome-file>index.jsp</welcome-file> <welcome-file>demo.jsp</welcome-file> </welcome-file-list>
|
0x12 隐藏服务器版本信息,为了能一定程度上防止被人用0day批量打,我们需要将tomcat的详细版本稍微隐藏下,比如,在出现403,404,500这样的状态码时,就很容易会暴露我们web服务器的详细版本,当然,你也可以直接把指定的状态码重定向到指定的页面上
1 2 3 4 5 6 7 8 9 10 11
| $ cd /usr/local/tomcat/lib/ $ unzip catalina.jar $ cd org/apache/catalina/util/ $ vi ServerInfo.properties server.info=Microsoft-IIS/7.5 server.number=7.5 server.built=Nov 27 2017 13:05:30 UTC $ cd /usr/local/tomcat/lib/ $ jar uvf catalina.jar org/apache/catalina/util/ServerInfo.properties $ /usr/local/tomcat/bin/catalina.sh stop $ /usr/local/tomcat/bin/catalina.sh start
|
0x13 修改http响应头中的server字段名称,只需要在http连接器中添加指定的server属性即可
1 2 3 4
| $ vi /usr/local/tomcat/conf/server.xml <Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" server="Microsoft-IIS/7.5" />
|
0x14 最好把所有Host组件中的自动部署选项全部关掉
1 2
| $ vi /usr/local/tomcat/conf/server.xml <Host name="www.sec.org" appBase="/data/javaweb/secapp" autoDeploy="false" unpackWARs="true">
|
0x15 如果我们是在前面使用apache或者nginx做的反向代理,也可通过限制特定ip的方式来访问,如下,表示仅允许192.168.3.0/24
这个内网段来访问
1 2 3 4 5 6 7
| $ vi /usr/local/tomcat/conf/server.xml <Host> ... <Context path="" docBase="." debug="0" /> <Valve className="org.apache.catalina.valves.RemoteAddrValve" allow="192.168.4.*" deny="*.*.*.*" /> ... </Host>
|
0x16 限制其他用户对tomcat各类服务管理工具的使用
1
| $ chmod -R 744 /usr/local/tomcat/bin/*
|
0x17 配置更加详细的访问日志格式,方便后续做入侵审查,如添加记录 user-agent,referer 字段数据
1 2 3 4
| $ vi /usr/local/tomcat/conf/server.xml <Valve className="org.apache.catalina.valves.AccessLogValve" directory="/data/logs" prefix="www.sec.org_access_log" suffix=".txt" pattern="%h %l %u %t "%r" %s %b %{Referer}i %{User-Agent}i %D" resolveHosts="false" />
|
0x18 关于Tomcat 7.x 版本,你可能还需要手工去禁用一些危险请求方法,将readonly
的值设为true
,即禁止DELETE
及PUT
方法,如下,不过在新版中,默认就处于禁用状态,无需关心
1 2 3 4 5
| $ vi /usr/local/tomcat/conf/web.xml <init-param> <param-name>readonly</param-name> <param-value>true</param-value> </init-param>
|
0x19 必要情况下,可直接禁用tomcat提供的默认web管理端,防止入侵者用此方式部署webshell,此处采用的禁用方式只是把原来web管理端的文件都重新放到别的目录中,而后再到主配置文件中去注释掉默认的locahost所对应的host组件,最后重启tomcat即可,话说回来,status可以留着,因为可能后续还要靠此来监控jvm的一些性能参数,大家还是酌情而定吧
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| $ cd /usr/local/tomcat/webapps/ $ mkdir tmp $ mv docs/ examples/ host-manager/ manager/ ROOT/ ./tmp/ <Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true"> --> <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" prefix="localhost_access_log" suffix=".txt" pattern="%h %l %u %t "%r" %s %b" /> </Host> -->
|
0x20 最后,时常去关注tomcat官方发布的一些高危漏洞补丁,tomcat 8.x 已经相对比较稳定了,所以也建议大家,务必在稳定的前提下使用更新一点的版本
后话:
因为关注的点不同,所以肯定有所偏颇,此处还是旨在防入侵,至于针对jvm的各种性能优化
,后续有机会我们再单独说明,因为tomcat几乎都不会直接面向用户,大多都是通过反向代理的方式来提供服务的,另外,java自身的安全性和性能采用编译的方式来运行
都要优于php,所以,针对tomcat的安全并没有像nginx或者apache压力那么大,而且由于tomcat是在后端,也相对比较好控制,虽然它到现在对java的一些类库支持的还不是很完整,但那些对我们而言暂时无需关心,以上部署仅供参考,并不完整,后续还会不断更新,大家可根据自己的实际业务需求再做进更进一步调整,关于java对渗透的功用,比如,免杀…想必大家也都非常熟悉了,这里就不多说了,更多其它内容,也非常欢迎大家来一起私信交流 ^_^