Tomcat Server Configuration Automation Reinforcement

目录

0. 引言
1. 黑客针对WEB Server会有那些攻击面
2. 针对Tomcat Server可以做的安全加固
3. Managing Security Realms with JMX
4. 实现对TOMCAT配置信息的动态修改(hot dynamic edit)
5. Tomcat manager弱口令入侵部署WEBSHELL防御 
6. Tomcat远程war包部署攻防

 

0. 引言

most weaknesses in Apache Tomcat come from incorrect or inappropriate configuration. It is nearly always possible to make Tomcat more secure than the default out of the box installation.
WEB容器(WEB Server)是运行在操作系统上的一个应用级软件,对服务器的配置(config文件)进行加固处理是防御WEB相关漏洞的一个有效的手段。对于实现WEB服务器的配置加固,我们需要达到如下几个目标

1. 使用加固后的标准版的配置文件(config file)对原始文件进行替换
2. 对配置文件替换操作需要实现回滚操作
3. 对配置文件进行加固后,需要能立刻生效,并对当前服务器的业务运行产生尽量少的影响
    1) 配置文件热加载(hot reload)
    2) 重启web server

Relevant Link:

https://www.owasp.org/index.php/Securing_tomcat

 

1. 黑客针对WEB Server会有那些攻击面

黑客攻击网站时,有一个简单的杀手锏,即寻找常见的漏洞,例如

1. 使用WEB Server默认的账户
    1) tomcat默认安装后,后台管理界面的登录采用basic authentication的身份验证方式,而这个默认的账户是系统默认设置的tomcat、tomcat(在tomcat-users.xml文件中)

2. 帐户密码很弱或者没有  
    1) IIS使用内置或默认帐户。黑客一般会寻找这些帐户。如果这些账户没有从系统中删除的话,就会被发现并被更改
    2) 用户为了方便管理,常常在tomcat的后台管理界面的basic authentication登录中使用弱口令,很容易遭到黑客的暴力破解

3. 大量的开放端口 
每一位访问者,无论是善意还是恶意,都可以通过开放端口连接到站点和系统。在默认情况下,Windows与IIS的开放端口远远多于为了正常运行所需的端口。保持系统的开放端口应该保持最少数量,这一点很重要。所有其他的端口都需要关闭。
    1) Windows License Logging Service溢出 
      通过发送一条经过特殊格式化的信息到运行License Logging Service的Web服务器,黑客能够对未检查的缓冲区进行攻击。这可以导致服务失效,为黑客打开一个开放端口,从而使用“System”权限在服务器上执行代码。  
      2) 微软服务器信息块(SMB)漏洞
      服务器信息块协议被Windows用于文件和打印机的共享以及计算机之间的通信。黑客的SMB服务器可以利用这项功能来使用"System"权限,对客户机执行任意代码。
  
4. 服务器扩展、模块的漏洞
    1) ISAPI扩展缓冲区溢出
      IIS安装后,就会自动安装多个Internet ISAPI服务器扩展。ISAPI服务器扩展实际上是动态链接库(DLL),是用来增强IIS服务器的功能的。一些动态链接库,比如idq.dll ,包含编程错误,可让黑客发送数据到ISAPI服务器扩展,这就是"缓冲区溢出"攻击 因此,攻                
 
5. WEB脚本漏洞
针对WEB脚本(asp、php、jsp)的攻击原则上来说是代码层的攻击,但是从纵深防御的原则上来看,我们在服务器的代码执行层面也是可以部署一些限制的
    1) 利用执行路径限制,将当前web路径强制限定在某个路径下
    2) API白名单、黑名单限制

0x1: Tomcat默认配置

1. tomcat-users.xml
Tomcat默认配置了2个角色: tomcat、role1
tomcat默认配置了3个帐号: both、tomcat、role1的默认密码都是tomcat
/* 
<user username="tomcat" password="tomcat" roles="tomcat"/>
<user username="both" password="tomcat" roles="tomcat,role1"/>
<user username="role1" password="tomcat" roles="role1"/>
*/
但是这些帐号都不具备直接部署应用的权限,默认需要有manager权限才能够直接部署war包,Tomcat默认需要安装Administration Web Application。Tomcat默认没有配置任何用户以及角色,没办法用默认帐号登录,在正常情况下,如果管理员需要登录manager页面使用管理以及远程部署功能,需要新增一个manager角色,并将指定帐号赋予这个角色,之后管理员才可以使用这个帐号登录manager页面

2. context.xml
Tomcat的上下文,一般情况下如果用Tomcat的自身的数据源多在这里配置。找到数据源即可用对应的帐号密码去连接数据库 
/*
<Context>
    <WatchedResource>WEB-INF/web.xml</WatchedResource>
    <Resource name="jdbc/u3" auth="Container" type="javax.sql.DataSource"
              maxActive="100" maxIdle="30" maxWait="10000"
              username="xxxxx" password="xxxx" driverClassName="com.mysql.jdbc.Driver"
              url="jdbc:mysql://192.168.0.xxx:3306/xxx?autoReconnect=true"/>
</Context>
*/

3. server.xml
Server这个配置文件价值非常高,通常的访问端口、域名绑定和数据源可以在这里找到,如果想知道找到域名对应的目录可以读取这个配置文件。如果有用Https,其配置也在这里面能够找到 

4. web.xml
项目初始化的时候会去调用这个配置文件 

0x2: manager页面部署WAR Getshell

1. 查看部署情况。从"tomcat-users.xml"文件中、或者直接通过猜解默认密码获取的具有管理员权限的用户名和密码,验证通过后进入部署管理页面
2. 部署管理页面中可以"Start"(启动)、"Stop"(停止)、"Reload"(重载)、"Undeploy"(删除部署)已经部署的项目,单击"Undeploy"会对文件进行物理删除
3. 部署的文件夹是以*.war文件的名称,例如上传的文件是job.war,则在Tomcat目录中会对应生成一个"job"文件夹 
4. 部署JSP WebShell后门程序。在部署管理页面的下方有一个"WAR file to deploy",单击浏览选择一个已经设置好的后门war文件,在本例中的后门程序为job.war,单击“deploy”将该文件部署到服务器上
5. 上传文件后,tomcat会自动进行部署并运行 
http://127.0.0.1:8080/job/job.jsp[/url] 

Relevant Link:

http://www.searchsecurity.com.cn/showcontent_11382.htm
http://www.searchsecurity.com.cn/guide/webseversetting.htm
http://blog.csdn.net/ablipan/article/details/7840103 
http://drops.wooyun.org/tips/604
http://oss.org.cn/ossdocs/apache/tomcat/l-tomcat.htm

 

2. 针对Tomcat Server可以做的安全加固

0x1:  升级到官方最新版

The first step is to make sure you are running the latest stable releases of software

1. Java Runtime Environment (JRE) or SDK
2. Tomcat
3. Third-party libraries

Many software projects, including Tomcat and Java, maintain multiple branches. New features are added to more recent branches, the older branches receive only bug-fixes and security updates. This allows developers to advance the software without disrupting production environments. Be aware of which branch you have deployed, and track new releases within that branch.
For example, if you are running Tomcat 5.5.26, you should watch for new versions within the 5.5 branch (e.g. 5.5.27) and upgrade to this bug-fix version. If you are content to stick with the Tomcat 5.5 branch then it is not necessary to upgrade to a new 6.0.18 version.

0x2: 最小权限默认安装

1. UNIX
    1) Create a tomcat user/group
    2) Download and unpack the core distribution (referenced as CATALINA_HOME from now on)
    3) Change CATALINA_HOME ownership to tomcat user and tomcat group
    4) Change files in CATALINA_HOME/conf to be readonly (400)
    5) Make sure tomcat user has read/write access to /tmp and write (300 - yes, only write/execute) access to CATALINA_HOME/logs
//值得注意的是,在LINUX/UNIX系统上,tomcat可以实现降权运行

2. Windows
    1) Download the core windows service installer
    2) Start the installation, click Next and Agree to the licence
    3) Untick native, documentation, examples and webapps then click Next
    4) Choose an installation directory (referenced as CATALINA_HOME from now on), preferably on a different drive to the OS.
    5) Choose an administrator username (NOT admin) and a secure password that complies with your organisations password policy.
    6) Complete tomcat installation, but do not start service.

3. Common
    1) Remove everything from CATALINA_HOME/webapps (ROOT, balancer, jsp-examples, servlet-examples, tomcat-docs, webdav)
    2) Remove everything from CATALINA_HOME/server/webapps (host-manager, manager). Note that it can be useful to keep the manager webapp installed if you need the ability to redeploy without restarting Tomcat. If you choose to keep it please read the section on Securing the Manager WebApp.
    3) Remove CATALINA_HOME/conf/Catalina/localhost/host-manager.xml and CATALINA_HOME/conf/Catalina/localhost/manager.xml (again, if you are keeping the manager application, do not remove this).
    4) Make sure the default servlet is configured not to serve index pages when a welcome file is not present. In CATALINA_HOME/conf/web.xml
/*
<servlet>
   <servlet-name>default</servlet-name>
   <servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
   <init-param>
     <param-name>debug</param-name>
     <param-value>0</param-value>
   </init-param>
   <init-param>
     <param-name>listings</param-name>
     <param-value>false</param-value>  <!-- make sure this is false -->
   </init-param>
   <load-on-startup>1</load-on-startup>
 </servlet>
*/
    5) Remove version string from HTTP error messages by repacking CATALINA_HOME/server/lib/catalina.jar with an updated ServerInfo.properties file.
    6) ename CATALINA_HOME/conf/server.xml to CATALINA_HOME/conf/server-original.xml and rename CATALINA_HOME/conf/server-minimal.xml to CATALINA_HOME/conf/server.xml. The minimal configuration provides the same basic configuration, but without the nested comments is much easier to maintain and understand. Do not delete the original file as the comments make it useful for reference if you ever need to make changes - e.g. enable SSL.
    7) Replace the server version string from HTTP headers in server responses, by adding the server keyword in your Connectors in CATALINA_HOME/conf/server.xml
/*
 <Connector port="8080" ...
            server="Apache" />  <!-- server header is now Apache -->
*/

0x3: 错误页面版本隐藏

Remove version string from HTTP error messages by repacking CATALINA_HOME/server/lib/catalina.jar with an updated ServerInfo.properties file. Note that making this change may prevent Lambda Probe (popular Tomcat monitoring webapp) to initialise as it cannot determine the Tomcat version.

1. unpack catalina.jar
cd CATALINA_HOME/server/lib
jar xf catalina.jar org/apache/catalina/util/ServerInfo.properties

2. update ServerInfo.properties by changing server.info line to server.info=Apache Tomcat

3. repackage catalina.jar
jar uf catalina.jar org/apache/catalina/util/ServerInfo.properties

4. remove CATALINA_HOME/server/lib/org (created when extracting the ServerInfo.properties file)

0x4: HTTP响应版本隐藏

Replace the server version string from HTTP headers in server responses, by adding the server keyword in your Connectors in CATALINA_HOME/conf/server.xml

 <Connector port="8080" ...
            server="Apache" />  <!-- server header is now Apache -->

0x5: Protecting the Shutdown Port

Tomcat uses a port (defaults to 8005) as a shutdown port. What this means is that to stop all webapps and stop Tomcat cleanly the shutdown scripts make a connection to this port and send the shutdown command. This is not as huge a security problem as it may sound considering the connection to the port must be made from the machine running tomcat(必须从本机发起这个关闭请求,无法通过RCE完成) and the shutdown command can be changed to something other than the string SHUTDOWN. However, it's wise to take the following precautions

1. if you are running a publicly accessible server make sure you prevent external access to the shutdown port by using a suitable firewall.
2. change the shutdown command in CATALINA_HOME/conf/server.xml and make sure that file is only readable by the tomcat user.
/*
 <Server port="8005" shutdown="ReallyComplexWord">
*/

0x6: Securing Manager WebApp

1. By default there are no users with the manager role. To make use of the manager webapp you need to add a new role and user into the CATALINA_HOME/conf/tomcat-users.xml file.

<role rolename="manager"/>
<user username="darren" password="ReallyComplexPassword" roles="manager"/>

2. When you access the password-protected manager webapp, the password you enter will be sent over the network in (nearly) plain text, ripe for interception. By using an SSL connection instead, you can transport the password securely

Fortunately, this is simple to accomplish. After configuring an SSL Connector in server.xml (see your Tomcat documentation), simply add the following to CATALINA_HOME/webapps/manager/WEB-INF/web.xml inside of the <security-constraint></security-constraint> tags.

<user-data-constraint>
     <transport-guarantee>CONFIDENTIAL</transport-guarantee>
  </user-data-constraint>

This will force an SSL connection to be used when accessing the manager webapp. Plus, with a little more work, the SSL Connector can be configured to require a client certificate.

3. Using a valve to filter by IP or hostname to only allow a subset of machines to connect (i.e. LAN machines). Add one of the following within the Context tag in CATALINA_HOME/conf/Catalina/localhost/manager.xml

<!-- allow only LAN IPs to connect to the manager webapp -->
<!-- contrary to the current Tomcat 5.5 documation the value for allow is not a regular expression -->
<!-- future versions may have to be specified as 192\.168\.1\.* -->
<Valve className="org.apache.catalina.valves.RemoteAddrValve" allow="192.168.1.*" />

<!-- allow only LAN hosts to connect to the manager webapp -->
<!-- contrary to the current Tomcat 5.5 documation the value for allow is not a regular expression -->
<!-- future versions may have to be specified as *\.localdomain\.com -->
<Valve className="org.apache.catalina.valves.RemoteHostValve" allow="*.localdomain.com" />

4. Rename the manager webapp

This is 'security through obscurity'. Although widely maligned, obscurity is a useful adjunct security measure on a one-off basis. A would-be attacker seeking to gain access to the manager webapp will look for it in its usual location. By renaming it, you force the attacker to guess URLs or assume that it is not installed. It is important to note that you are not relying upon this obscurity for security, but rather using it as a backup measure in case someone finds a way around the remote valve filter you have configured as described above.
To rename the manager webapp, decide on the new name (we'll use foobar in this example), and:

1. Move CATALINA_HOME/conf/Catalina/localhost/manager.xml to CATALINA_HOME/conf/Catalina/localhost/foobar.xml
2. Update the docBase attribute within CATALINA_HOME/conf/Catalina/localhost/foobar.xml to ${catalina.home}/server/webapps/foobar
3. Move CATALINA_HOME/server/webapps/manager to CATALINA_HOME/server/webapps/foobar

0x7: Logging

As of tomcat 5.5 logging is now handled by the commons-logging framework allowing you to choose your preferred logging implementation - log4j or standard JDK logging. By default the standard JDK logging is used (or a compatible extension called juli to be more precise), storing daily log files in CATALINA_HOME/logs.
By default additional webapp log entries are added to CATALINA_HOME/logs/catalina.YYYY-MM-DD.log and System.out/System.err are redirected to CATALINA_HOME/logs/catalina.out. To place webapp log entries in individual log files create a logging.properties file similar to the following within CATALINA_HOME/webapps/APP_NAME/WEB-INF/classes (change the APP_NAME value to create a unique file for each webapp)

handlers = org.apache.juli.FileHandler, java.util.logging.ConsoleHandler
org.apache.juli.FileHandler.level = ALL
org.apache.juli.FileHandler.directory = ${catalina.base}/logs
org.apache.juli.FileHandler.prefix = APP_NAME.

0x8: Java Security

1. Running Tomcat with a Security Manager
The default Tomcat configuration provides good protection for most requirements, but does not prevent a malicious application from compromising the security of other applications running in the same instance. To prevent this sort of attack, Tomcat can be run with a Security Manager enabled which strictly controls access to server resources. Tomcat documentation has a good section on enabling the Security Manager.
It's always a good idea to start tomcat with the "-security" parameter. This also makes sure (among other things), that a webapplication isn't able to read/write/execute any file on the local filesystem without enabling it in the catalina.policy file. This effectively stops web shells like described here from working.

0x9: 后台管理界面登录密码强化

这个问题属于口令安全的范畴,我在其他的文章中涉及到了这方面的知识

http://www.cnblogs.com/LittleHann/p/3567908.html
http://www.cnblogs.com/LittleHann/p/3541989.html
http://www.cnblogs.com/LittleHann/p/3543681.html

0x10: 禁用tomcat manage管理页面

禁用Tomcat Manage的后台管理页面,可以通过修改tomcat-users.xml配置文件中和角色,账户身份有关的配置来实现,在研究如何禁用管理界面之前,我们先来学习一下tomcat的身份验证机制

1. tomcat中的Reaml身份验证、管理

1. UserDatabaseRealm
//className="org.apache.catalina.realm.UserDatabaseRealm"
UserDatabaseRealm is an implementation of the Tomcat Realm interface that uses a JNDI resource to store user information. By default, the JNDI resource is backed by an XML file. It is not designed for large-scale production use. At startup time, the UserDatabaseRealm loads information about all users, and their corresponding roles, from an XML document (by default, this document is loaded from $CATALINA_BASE/conf/tomcat-users.xml). The users, their passwords and their roles may all be editing dynamically, typically via JMX. Changes may be saved and will be reflected in the XML file.
对于使用 的身份验证,可以使用JMX API接口动态的修改tomcat的身份认证配置,并自动映射到磁盘上的配置文件tomcat-users.xml

2. JDBCRealm
//className="org.apache.catalina.realm.JDBCRealm
JDBCRealm is an implementation of the Tomcat Realm interface that looks up users in a relational database accessed via a JDBC driver. There is substantial configuration flexibility that lets you adapt to existing table and column names, as long as your database structure conforms to the following requirements:
    1) There must be a table, referenced below as the users table, that contains one row for every valid user that this Realm should recognize.
    2) The users table must contain at least two columns (it may contain more if your existing applications required it):
    3) Username to be recognized by Tomcat when the user logs in. Password to be recognized by Tomcat when the user logs in. This value may in cleartext or digested 
    4) The user roles table must contain at least two columns (it may contain more if your existing applications required it):
        4.1) Username to be recognized by Tomcat ( 
        4.2) 2014/10/27Role name of a valid role associated with this user.
    /*
    create table users (
      user_name         varchar(15) not null primary key,
      user_pass         varchar(15) not null
    );

    create table user_roles (
      user_name         varchar(15) not null,
      role_name         varchar(15) not null,
      primary key (user_name, role_name)
    );
    */
When a user attempts to access a protected resource for the first time, Tomcat will call the authenticate() method of this Realm. Thus, any changes you have made to the database directly (new users, changed passwords or roles, etc.) will be immediately reflected.
对于JDBCRealm来说,对保存账户信息的数据库的修改,会实时的映射到tomcat中
      
3. DataSourceRealm
//className="org.apache.catalina.realm.DataSourceRealm"
DataSourceRealm is an implementation of the Tomcat Realm interface that looks up users in a relational database accessed via a JNDI(JNDI(Java Naming and Directory Interface,Java命名和目录接口) named JDBC DataSource. 
本质上和JDBCRealm认证原理类似,差别在于使用JNDI接口进行数据源数据获取

4. JNDIRealm
//className="org.apache.catalina.realm.JNDIRealm"
JNDIRealm is an implementation of the Tomcat Realm interface that looks up users in an LDAP directory server accessed by a JNDI provider (typically, the standard LDAP provider that is available with the JNDI API classes). The realm supports a variety of approaches to using a directory for authentication.

5. MemoryRealm
MemoryRealm is a simple demonstration implementation of the Tomcat Realm interface. It is not designed for production use. At startup time, MemoryRealm loads information about all users, and their corresponding roles, from an XML document (by default, this document is loaded from $CATALINA_BASE/conf/tomcat-users.xml). Changes to the data in this file are not recognized until Tomcat is restarted.

6. JAASRealm
//className="org.apache.catalina.realm.JAASRealm"
JAASRealm is an implementation of the Tomcat Realm interface that authenticates users through the Java Authentication & Authorization Service (JAAS) framework which is now provided as part of the standard Java SE API.

7. CombinedRealm
//className="org.apache.catalina.realm.CombinedRealm"
CombinedRealm is an implementation of the Tomcat Realm interface that authenticates users through one or more sub-Realms.
Using CombinedRealm gives the developer the ability to combine multiple Realms of the same or different types. This can be used to authenticate against different sources, provide fall back in case one Realm fails or for any other purpose that requires multiple Realms.
Sub-realms are defined by nesting Realm elements inside the Realm element that defines the CombinedRealm. Authentication will be attempted against each Realm in the order they are listed. Authentication against any Realm will be sufficient to authenticate the user.

8. LockOutRealm
//className="org.apache.catalina.realm.LockOutRealm"
LockOutRealm is an implementation of the Tomcat Realm interface that extends the CombinedRealm to provide lock out functionality to provide a user lock out mechanism if there are too many failed authentication attempts in a given period of time.
To ensure correct operation, there is a reasonable degree of synchronisation in this Realm.
This Realm does not require modification to the underlying Realms or the associated user storage mechanisms. It achieves this by recording all failed logins, including those for users that do not exist. To prevent a DOS by deliberating making requests with invalid users (and hence causing this cache to grow) the size of the list of users that have failed authentication is limited.
Sub-realms are defined by nesting Realm elements inside the Realm element that defines the LockOutRealm. Authentication will be attempted against each Realm in the order they are listed. Authentication against any Realm will be sufficient to authenticate the user.

我们重点来研究一下tomcat默认的身份验证方式,UserDatabaseRealm的相关知识

...
<Realm className="org.apache.catalina.realm.LockOutRealm">
    <!-- This Realm uses the UserDatabase configured in the global JNDI
         resources under the key "UserDatabase".  Any edits
         that are performed against this UserDatabase are immediately
         available for use by the Realm.  -->
    <Realm className="org.apache.catalina.realm.UserDatabaseRealm" resourceName="UserDatabase"/>
</Realm>
...

UserDatabaseRealm类接口

public class UserDatabaseRealm
extends RealmBase
//Implementation of Realm that is based on an implementation of UserDatabase made available through the global JNDI resources configured for this instance of Catalina. Set the resourceName parameter to the global JNDI resources name for the configured instance of UserDatabase that we should consult.

UserDatabaseRealm is an implementation of the Tomcat Realm interface that uses a JNDI resource to store user information. By default, the JNDI resource is backed by an XML file. It is not designed for large-scale production use. At startup time, the UserDatabaseRealm loads information about all users, and their corresponding roles, from an XML document (by default, this document is loaded from $CATALINA_BASE/conf/tomcat-users.xml). The users, their passwords and their roles may all be editing dynamically, typically via JMX. Changes may be saved and will be reflected in the XML file.

2. tomcat中用户角色

tomcat采用"用户角色"的方式对用户的访问权限进行管理,每个用户都被划分到了一个"用户角色"中,toncat的默认预设角色有

1. manager-gui
allows access to the HTML GUI and the status pages
也就是我们常用到的
http://localhost:8080/manager/html

2. manager-script
allows access to the text interface and the status pages

3. manager-jmx
allows access to the JMX proxy and the status pages

4. manager-status
allows access to the status pages only

结合以上知识,我们可以得出如果需要对tomcat manager页面进行禁用,可以采取如下的方法

1. 将tomcat-users.xml中的<user .../>节点中,设置为"manager-gui"的账户全部修改为"tomcat"
因为只有manager-gui这个role才具有访问tomcat web后台界面的权限,因此,这样实现对tomcat后台页面的禁用

2. 修改403.jsp页面
对tomcat-users.xml文件进行修改后,管理员在使用原始的帐号密码登录后台的时候,会被Realm验证模块拒绝,显示403.jsp页面。我们需要在这个页面显示我们的修复动作和可能产生的后果,并告知修改回滚的接口地址

3. 修复消息通知推送
通过手机短信的方式通知到管理员tomcat的后台管理界面已经被禁用

3. 删除\webapps\manager\WEB-INF\web.xml文件

Relevant Link:

http://tomcat.apache.org/tomcat-8.0-doc/index.html
http://tomcat.apache.org/tomcat-8.0-doc/realm-howto.html
http://www.cnblogs.com/lanhuahua/archive/2011/08/10/2133685.html
http://blog.csdn.net/feng88724/article/details/7164983
https://tomcat.apache.org/tomcat-7.0-doc/api/org/apache/catalina/realm/UserDatabaseRealm.html

011: 禁用tomcat manager管理界面的WAR Remote Deploy远程部署

0x12: 禁止列目录(index travel)

<init-param>
    <param-name>listings</param-name>
    <param-value>false</param-value>
</init-param>

Relevant Link:

https://www.owasp.org/index.php/Securing_tomcat
http://tomcat.apache.org/tomcat-7.0-doc/security-howto.htm
http://media.techtarget.com/tss/static/articles/content/TomcatSecurity/TomcatSecurity.pdf
https://www.mulesoft.com/tcat/tomcat-security

 

3. Managing Security Realms with JMX(java management extensions)

和IIS的自动化API操作类似,tomcat同样提供了对外暴露的安全配置接口

//IIS API automatic config相关知识请参阅
http://www.cnblogs.com/LittleHann/p/3988923.html

Java Management Extensions, or JMX, is a Java technology designed for remote administration and monitoring of Java components.  All versions of Tomcat 5.x or later natively support the JMX protocol.

整个tomcat的安全配置体系架构可以分为一个三层的结构

1. the Instrumentation Level
The Instrumentation Level contains the components and resources that you would like to manage.  These resources are represented by one or more specialized JavaBeans known as Managed Beans, or MBeans for short
MBeans are Java Beans that implement additional components which allow them to be managed and monitored via the JMX framework.  Each MBean represents a single resource running on the JVM, which is exposed for remote management using JMX.
在这一层就是所谓的providers MBeans

2. the Agent Level
There are a few different types of MBeans, each with different functionalities, which offer a greater degree flexibility when designing your administrative framework.  Any MBean that you wish to expose is registered with the MBeanServer, which makes up JMX's Agent Level.
The Agent Level is composed of an intermediate agent called MBeanServer.  The job of this layer is to receive requests or commands from the Remote Management Level, and relay them to the appropriate MBean.  It also can receive notifications from its MBeans, such as state changes, and forward them to the Remote Management Layer.
在这一层就是所谓的security service(APIS)

3. the Remote Management Level    
The Remote Management Layer is made up of client programs, connectors, and adaptors, and allows the user to send requests to the Agent layer for relay and receive the results of these requests.  Users can connect to the MBeanServer either 
    1) through a connector, using a client program such as JConsole and a protocol such as RMI or IIOP
    对应于tomcat-users.xml中的manager-jmx role

    2) or through an adaptor, which adapts the MBeanServer API to another protocol, such as HTTP, allowing JMX to be used with custom web-based GUIs.
    对应于tomcat-users.xml中的manager-gui role
In summary, a user at the Remote Management Level sends a request or command to the Agent Level, which contacts the appropriate MBean at the Instrumentation Level, and relays the response back to the user. 

This distributed system allows users to build highly customized administrative frameworks from scratch.

0x1: Security Realms

A security realm comprises mechanisms for protecting WebLogic resources. Each security realm consists of a set of configured security providers, which are modular components that handle specific aspects of security. You can

1. create a JMX client that uses the providers in a realm to add or remove security data such as users and groups. 
2. You can also create a client that adds or removes providers
3. makes other changes to the realm configuration.

0x2: Understanding the Hierarchy of Security MBeans

Like other subsystems, the "WebLogic Server security framework" organizes its MBeans in a hierarchy that JMX clients can navigate without constructing JMX object names. However

1. the set of MBean types that are available in a security realm depends on which security providers you have installed in the realm
2. the set of services that each security provider enables depends on how the provider was created.

tomcat使用层次结构的MBeans对安全域进行组织管理,每个Mbeans对应于不同方面的安全配置,程序员可以通过JMX Clients连接这些Mbeans,对tomcat的对应的安全配置进行动态的读写

security providers -> security realm(一个realm可以包含多个providers) -> MBean Proxy -> security service(APIS) 

而之所以说tomcat的Mbeans是层次结构的,是由它的类继承关系决定的

Each security provider must extend a base provider type. For example

1. DefaultAuthorizerMBean extends AuthorizerMBean
2. any custom or third-party authorization provider also extends AuthorizerMBean. 
//If a JMX client gets the value of the RealmMBean Authorizers attribute, the MBean server returns all MBeans in the realm that extend AuthorizerMBean. The JMX client can iterate through the list of providers and select one based on the value of its Name attribute or other criteria.

Base provider types can be enhanced by extending a set of optional mix-in interfaces. For example

1. if an authentication provider extends the UserEditorMBean, then the provider can add users to the realm.

0x3: Security Providers(the Instrumentation Level)

我们知道,对tomcat中某个MBeans的操作实质上就是在对MBeans后面的Provider的操作,在tomcat的providers中,和安全身份认证有关的providers有

1. AuthenticationProviderMBean
The base MBean for all MBean implementations that manage Authentication providers. If your Authentication provider uses the WebLogic Security SSPI to provide login services, then your MBean must extend weblogic.management.security.authentication.Authenticator. If your Authentication provider uses the WebLogic Security SPI to provide identity-assertion services, then your MBean must extend weblogic.management.security.authentication.IdentityAsserter.
 
2. AuthenticatorMBean
The SSPI MBean that all Authentication providers with login services must extend. This MBean provides a ControlFlag to determine whether the Authentication provider is a REQUIRED, REQUISITE, SUFFICENT, or OPTIONAL part of the login sequence.

3. IdentityAsserterMBean
The SSPI MBean that all Identity Assertion providers must extend. This MBean enables an Identity Assertion provider to specify the token types for which it is capable of asserting identity.

4. ServletAuthenticationFilterMBean
The SSPI MBean that all Servlet Authentication Filter providers must extend. This MBean is just a marker interface. It has no methods on it.

0x4: MBean Mixin Interfaces for Security Providers

在tomcat中,providers模块是数据提供者,而MBeans则提供了对外访问的接口,用来对tomcat的配置进行动态地修改

....
1. UserEditorMBean:Provides a set of methods for creating, editing, and removing users
2. UserReaderMBean:Provides a set of methods for reading data about users.
3. RoleEditorMBean:Provides a set of methods for creating, editing, and removing roles.  
4. RoleReaderMBean:Provides a set of methods for reading roles.
...

0x5: 通过JMX操作tomcat配置信息编程示例

连接tomcat的JMX Proxy有2种方法

1. HTTP URL方式:tomcat manager内置了一个轻量级的JMP HTTP Proxy
2. 使用java编写client connector/adaptor客户端程序

1. HTTP方式

The JMX Proxy Servlet is a lightweight proxy to get and set the tomcat internals

JXMProxy HTTP有以下几种操作方式

1. JMX Query command
    1) look for a specific MBean by the given name
    http://localhost:8080/manager/jmxproxy/?qry=Catalina%3Atype%3DEnvironment%2Cresourcetype%3DGlobal%2Cname%3DsimpleValue 
    2) locate all workers which can process requests and report their state
    http://localhost:8080/manager/jmxproxy/?qry=*%3Atype%3DRequestProcessor%2C* 
    3) return all loaded servlets
    http://localhost:8080/manager/jmxproxy/?qry=*%3Aj2eeType=Servlet%2c*

2. JMX Get command
    1) fetch the value of a specific MBean's attribute
    http://localhost:8080/manager/jmxproxy/?get=BEANNAME&att=MYATTRIBUTE&key=MYKEY
    2) fetch the current heap memory data:
    http://localhost:8080/manager/jmxproxy/?get=java.lang:type=Memory&att=HeapMemoryUsage
    3) fetch the current heap memory data and only want the "used" key
    http://localhost:8080/manager/jmxproxy/?get=java.lang:type=Memory&att=HeapMemoryUsage&key=used

3. JMX Set command
    1) general format
    http://localhost:8080/manager/jmxproxy/?set=BEANNAME&att=MYATTRIBUTE&val=NEWVALUE
    2) turn up debugging on the fly for the ErrorReportValve
    http://localhost:8080/manager/jmxproxy/?set=Catalina%3Atype%3DValve%2Cname%3DErrorReportValve%2Chost%3Dlocalhost&att=debug&val=10

4. JMX Invoke command
The invoke command enables methods to be called on MBeans
    1) general format
    http://localhost:8080/manager/jmxproxy/?invoke=BEANNAME&op=METHODNAME&ps=COMMASEPARATEDPARAMETERS
    2) call the findConnectors() method of the Service use
    http://localhost:8080/manager/jmxproxy/?invoke=Catalina%3Atype%3DService&op=findConnectors&ps=
    3) 修改指定用户的密码
    http://localhost:8080/manager/jmxproxy/?set=Users:type=User,username="test",database=UserDatabase&att=password&val=hello
    //将test这个账户的密码修改为hello

Relevant Link:

http://docs.oracle.com/cd/E11035_01/wls100/secintro/index.html
http://docs.oracle.com/cd/E11035_01/wls100/jmx/accessWLS.html#wp1112969
http://tomcat.apache.org/tomcat-8.0-doc/manager-howto.html#Using_the_JMX_Proxy_Servlet
http://tomcat.apache.org/tomcat-8.0-doc/manager-howto.html
http://tomcat.apache.org/tomcat-8.0-doc/realm-howto.html#MemoryRealm
http://docs.oracle.com/cd/E11035_01/wls100/jmx/editsecurity.html
http://www.360doc.com/content/10/1005/14/39755_58581727.shtml

2. JAVA Client Connector/adaptor方式:Creating WebLogic users programmatically from a standalone Java client

使用java编写client connector/adaptor这种方式要求服务端的tomcat服务器要开启"JMX_REMOTE_CONFIG",即tomcat需要监听一个JMX Proxy端口,默认情况下,tomcat是不会开启这个接口的,所以要进行这个实验,我们还需要对tomcat的启动脚本增加一些额外的配置

1. 先修改Tomcat的启动脚本
    1) windows下为bin/catalina.bat
    2) linux下为catalina.sh
添加以下内容
set JMX_REMOTE_CONFIG=-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=8999 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false  
set CATALINA_OPTS=%CATALINA_OPTS% %JMX_REMOTE_CONFIG%  
/*
1. 8999是jmxremote使用的端口号
2. 第二个false表示不需要鉴权
*/

2. 要注意以上语句的位置不能太后面
大概在200行左右这个位置就可以了,太前面也不行

3. 启动/重启tomcat
    1) D:\tomcat\apache-tomcat-8.0.14\bin
    2) catalina.bat run

我们配置了无鉴权模式的8999端口jmxproxy监听服务,现在可以开始编写java代码,通过jmx api连接到jmxproxy上了,从而对tomcat的MBeans进行动态的读写

import java.util.HashMap;
import java.util.Map;
import javax.management.MBeanServerConnection;
import javax.management.ObjectName;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;

public class JMXTest 
{ 
    public static void main(String[] args)
    {
        try 
        {
           String jmxURL = "service:jmx:rmi:///jndi/rmi://127.0.0.1:8999/jmxrmi";//tomcat jmx url
           /*
             * JMXServiceURL用于标识JMXConnectorServer,它是采用以下形式的字符串
             * service:jmx:<protocol>://[[[ <host>]: <port>]/ <path>]
                    1. "protocol" 
                    指定了协议,例如
                        1) rmi
                        2) iiop
                        3) jmxmp
                        4) soap
                    2. "host"(可选)
                    3. "port"(可选)
                    4. "path"(可选)
            */
           JMXServiceURL serviceURL = new JMXServiceURL(jmxURL);
           
           Map<String, String[]> map = new HashMap<String, String[]>();
           String[] credentials = new String[] { "monitorRole" , "QED" };
           map.put("jmx.remote.credentials", credentials);
           /*
             * The client end of a JMX API connector. An object of this type can be used to establish a connection to a connector server.
             * A newly-created object of this type is unconnected. Its connect method must be called before it can be used. However, objects created by JMXConnectorFactory.connect are already connected.
           */
           JMXConnector conneactor = JMXConnectorFactory.connect(serviceURL, map);
           MBeanServerConnection  mbsc = conneactor.getMBeanServerConnection();
           
           /*
           ObjectName threadObjNameSet = new ObjectName("Catalina:type=Valve,host=localhost,context=/host-manager,name=BasicAuthenticator");
           Attribute attrVal = new Attribute("stateName", "STOPED");
           mbsc.setAttribute(threadObjNameSet, attrVal);
           */
           
           /*
            * 填写需要获取的ObjectName对象名,即MBeans Idntifier
           */
           ObjectName threadObjName = new ObjectName("Catalina:type=Valve,host=localhost,context=/host-manager,name=BasicAuthenticator");
           String attrName = "stateName";  
           //通过MBeans的getter方法获取对应的属性值
           System.out.println("password: " + mbsc.getAttribute(threadObjName, attrName));            
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    } 
}

可以通过URL的jmxproxy方式验证我们获得的结果

http://localhost:8080/manager/jmxproxy/?get=Catalina:type=Valve,host=localhost,context=/host-manager,name=BasicAuthenticator&att=stateName
result:
OK - Attribute get 'Catalina:type=Valve,host=localhost,context=/host-manager,name=BasicAuthenticator' - stateName = STARTED

Relevant Link:

http://whitesock.iteye.com/blog/246186
http://www.programcreek.com/java-api-examples/index.php?api=javax.management.MBeanServerConnection
http://pic.dhe.ibm.com/infocenter/wxsinfo/v8r6/index.jsp?topic=%2Fcom.ibm.websphere.extremescale.doc%2Ftxsmbeanprog.html
http://blog.csdn.net/airobot008/article/details/3951524
http://sharpspeed.iteye.com/blog/2009770
http://www.blogjava.net/japper/archive/2012/09/05/387092.html

 

4. 实现对TOMCAT配置信息的动态修改(hot dynamic edit)

了解了tomcat jmx api编程之后,我们回到我们本文的中心,就是自动化的tomcat配置加固,即动态的修改内存中的tomcat配置,实现对tomcat的MBeans(保存tomcat所有维度信息的基本单位)配置信息的动态修改

1. HTTP URL JMXPROXY 
通过这种方式对tomcat的配置进行动态修改存在如下几个条件、限制
    1) 调用URL接口的用户必须本身是具有"manager-jmx"的角色,并且需要处于登录后的状态才可以调用这个接口
    2) tomcat的MBeans大多数不提供setter接口,而只提供getter接口,很多的设置是不能修改的,例如
        2.1) 取消basic认证
        2.2) 修改账户的role角色

2. JAVA CLIENT JXMPROXY API
通过这种方式对tomcat的配置进行动态修改存在如下几个条件、限制
    1) 需要tomcat服务端开启了JMXPROXY端口监听服务,而tomcat默认是不开启这个端口监听的,需要手动设置并重启
    2) tomcat的MBeans大多数不提供setter接口,而只提供getter接口,很多的设置是不能修改的,例如
        2.1) 取消basic认证
        2.2) 修改账户的role角色

需要注意的是,tomcat的jmx自动化操作方式是针对需要对tomcat进行实时性能监控而产生的,所以我们会发现jmx接口中大多数是getter方法,而且不管是ur方式、还是java client方式,在默认情况下tomcat都不支持,需要额外的配置才能启用,所以,我们想要通过tomcat jmx方式对tomcat进行配置加固是有困难的

 

5. Tomcat manager弱口令入侵部署WEBSHELL防御

0x1: 直接删除manager页面对应的jsp文件、manager目录

或者直接删除\webapps\manager\WEB-INF\web.xml文件,同样得到禁用manager页面的效果

0x2: 修改tomcat-users.xml文件配置

1. 将弱密码修改为强密码
2. 取消用户的manager-gui,即降权,达到禁止用户访问manager页面的目的 
//需要重启tomcat才能使新配置生效

0x3: 针对web应用的轻量级重启:修改应用中的web.xml的和身份认证、禁止登录、POST WAR的相关配置

在开始研究tomcat应用程序的web.xml配置之前,我们先针对这个思路和apache的配置进行一个类比

http://man.chinaunix.net/newsoft/Apache2.2_chinese_manual/howto/htaccess.html

在apache架构的网站应用中.htaccess文件(或者"分布式配置文件")提供了针对每个目录(web应用)改变配置的方法,即在一个特定的目录中放置一个包含指令的文件,其中的指令作用于此目录及其所有子目录

对于tomcat,我们也可以采取相同的思路,从本质上来说,manager这个后台管理界面属于一个J2EE的应用,我们可以直接修改manager目录下的web.xml文件,对其配置项进行修改禁止管理员访问,然后直接重启manager这个应用即可

1. tomcat web.xml配置

The web.xml Deployment Descriptor file describes how to deploy a web application in a servlet container such as Tomcat.
The location of the file is always the same: application root/WEB-INF/web.xml

<?xml version="1.0" encoding="UTF-8"?> 
<web-app xmlns="http://java.sun.com/xml/ns/j2ee" 
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
        xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" 
        version="2.4"> 

        <!-- ========================================================== --> 
        <!-- General --> 
        <!-- ========================================================== --> 

        <!-- Name the application --> 
        <display-name>Example App</display-name> 
        <description>An example application which is used to play with some of the features of Tomcat</description> 

        <!-- This app is cluster-ready --> 
        <distributable /> 

        <!-- Set timeout to 120 minutes --> 
        <session-config> 
                <session-timeout>120</session-timeout> 
        </session-config> 


        <!-- ========================================================== --> 
        <!-- Custom Tag Libraries --> 
        <!-- ========================================================== --> 

        <!-- Taglib declarations are no longer required since JSP 2.0, see Removing taglib from web.xml --> 
        <!-- The <taglib> did not need to be a child of <jsp-config> in earlier versions but is required as of Tomcat 7 --> 
        <!-- Note that you can only have one <jsp-config> element per web.xml --> 
        <!-- 
        <jsp-config> 
                <taglib> 
                        <taglib-uri>mytags</taglib-uri> 
                        <taglib-location>/WEB-INF/jsp/mytaglib.tld</taglib-location> 
                </taglib> 
        </jsp-config> 
        --> 


        <!-- ========================================================== --> 
        <!-- JSP Configuration --> 
        <!-- ========================================================== --> 

        <jsp-config> 
                <jsp-property-group> 
                        <url-pattern>*.jsp</url-pattern> 
                        <include-prelude>/WEB-INF/jspf/prelude1.jspf</include-prelude> 
                        <include-coda>/WEB-INF/jspf/coda1.jspf</include-coda> 
                </jsp-property-group> 
        </jsp-config> 


        <!-- ========================================================== --> 
        <!-- Context Parameters --> 
        <!-- ========================================================== --> 

        <context-param> 
                <description>Enable debugging for the application</description> 
                <param-name>debug</param-name> 
                <param-value>true</param-value> 
        </context-param> 
        <context-param> 
                <description>The email address of the administrator, used to send error reports.</description> 
                <param-name>webmaster</param-name> 
                <param-value>address@somedomain.com</param-value> 
        </context-param> 


        <!-- ========================================================== --> 
        <!-- JNDI Environment Variables --> 
        <!-- ========================================================== --> 

        <env-entry> 
                <env-entry-name>webmasterName</env-entry-name> 
                <env-entry-value>Ms. W. Master</env-entry-value> 
                <env-entry-type>java.lang.String</env-entry-type> 
        </env-entry> 
        <env-entry> 
                <env-entry-name>cms/defaultUserSettings/recordsPerPage</env-entry-name> 
                <env-entry-value>30</env-entry-value> 
                <env-entry-type>java.lang.Integer</env-entry-type> 
        </env-entry> 
        <env-entry> 
                <env-entry-name>cms/enableXMLExport</env-entry-name> 
                <env-entry-value>false</env-entry-value> 
                <env-entry-type>java.lang.Boolean</env-entry-type> 
        </env-entry> 
        <env-entry> 
                <env-entry-name>cms/enableEmailNotifications</env-entry-name> 
                <env-entry-value>true</env-entry-value> 
                <env-entry-type>java.lang.Boolean</env-entry-type> 
        </env-entry> 


        <!-- ========================================================== --> 
        <!-- Servlets --> 
        <!-- ========================================================== --> 

        <!-- Simple Servlet, provide a name, class, description and map to URL /servlet/SimpleServlet --> 
        <servlet> 
                <servlet-name>Simple</servlet-name> 
                <servlet-class>SimpleServlet</servlet-class> 
                <description>This is a simple Hello World servlet</description> 
        </servlet> 
        <servlet-mapping> 
                <servlet-name>Simple</servlet-name> 
                <url-pattern>/servlet/SimpleServlet</url-pattern> 
        </servlet-mapping> 

        <!-- CMS Servlet, responds to *.cms URL's --> 
        <servlet> 
                <!-- Identification --> 
                <servlet-name>cms</servlet-name> 
                <servlet-class>com.metawerx.servlets.ContentManagementSystem</servlet-class> 
                <description>This servlet handles requests for the CMS (it is a controller in an MVC architecture)</description> 

                <!-- This servlet has two parameters --> 
                <init-param> 
                        <param-name>debug</param-name> 
                        <param-value>true</param-value> 
                </init-param> 
                <init-param> 
                        <param-name>detail</param-name> 
                        <param-value>2</param-value> 
                </init-param> 

                <!-- Load this servlet when the application starts (call the init() method of the servlet) --> 
                <load-on-startup>5</load-on-startup> 
                <!-- <run-at>0:00, 6:00, 12:00, 18:00</run-at> This tag is only valid for Resin --> 
        </servlet> 

        <!-- Map some URLs to the cms servlet (demonstrates *.extension mapping) --> 
        <servlet-mapping> 
                <!-- For any URL ending in .cms, the cms servlet will be called --> 
                <servlet-name>cms</servlet-name> 
                <url-pattern>*.cms</url-pattern> 
        </servlet-mapping> 

        <!-- Rewriter Servlet, responds to /content/* and /admin/RewriterStatistics URL's --> 
        <!-- Define a servlet to respond to /content/* URL's --> 
        <servlet> 
                <servlet-name>rewriter</servlet-name> 
                <servlet-class>com.metawerx.servlets.URLRewriter</servlet-class> 
        </servlet> 

        <!-- Map some URL's to the rewriter servlet (demonstrates /path/* and specific URL mapping) --> 
        <servlet-mapping> 
                <!-- For any URL starting with /content/, the rewriter servlet will be called --> 
                <servlet-name>rewriter</servlet-name> 
                <url-pattern>/content/*</url-pattern> 
        </servlet-mapping> 
        <servlet-mapping> 
                <!-- The rewriter servlet can also be called directly as /admin/RewriterStatistics, to return stats --> 
                <servlet-name>rewriter</servlet-name> 
                <url-pattern>/admin/RewriterStatistics</url-pattern> 
        </servlet-mapping> 

        <!-- PathJSP Servlet, maps /shop/item/* URL's to a JSP file --> 
        <!-- Define a JSP file to respond to /shop/item/* URL's --> 
        <servlet> 
                <servlet-name>pathjsp</servlet-name> 
                <jsp-file>pathfinder.jsp</jsp-file> 
        </servlet> 

        <!-- Map some URL's to the pathjsp servlet (demonstrates /long/path/* URL mapping) --> 
        <servlet-mapping> 
                <!-- For any URL starting with /shop/item/, the pathjsp servlet will be called --> 
                <servlet-name>pathjsp</servlet-name> 
                <url-pattern>/shop/item/*</url-pattern> 
        </servlet-mapping> 


        <!-- ========================================================== --> 
        <!-- Filters --> 
        <!-- ========================================================== --> 

        <!-- Example filter to set character encoding on each request (from Tomcat servlets-examples context) --> 
        <filter> 
                <filter-name>Set Character Encoding</filter-name> 
                <filter-class>filters.SetCharacterEncodingFilter</filter-class> 
                <init-param> 
                        <param-name>encoding</param-name> 
                        <param-value>EUC_JP</param-value> 
                </init-param> 
        </filter> 
        <filter-mapping> 
                <filter-name>Set Character Encoding</filter-name> 
                <url-pattern>/*</url-pattern> 
        </filter-mapping> 

        <!-- Example filter to dump the HTTP request at the top of each page (from Tomcat servlets-examples context) --> 
        <filter> 
                <filter-name>Request Dumper Filter</filter-name> 
                <filter-class>filters.RequestDumperFilter</filter-class> 
        </filter> 
        <filter-mapping> 
                <filter-name>Request Dumper Filter</filter-name> 
                <url-pattern>/*</url-pattern> 
        </filter-mapping> 


        <!-- ========================================================== --> 
        <!-- Listeners --> 
        <!-- ========================================================== --> 

        <!-- Define example application events listeners --> 
        <listener> 
                <listener-class>com.metawerx.listener.ContextListener</listener-class> 
        </listener> 
        <listener> 
                <listener-class>com.metawerx.listener.SessionListener</listener-class> 
        </listener> 


        <!-- ========================================================== --> 
        <!-- Security --> 
        <!-- ========================================================== --> 

        <!-- Define roles --> 
        <security-role> 
                <role-name>admin</role-name> 
        </security-role> 
        <security-role> 
                <role-name>cms_editors</role-name> 
        </security-role> 
         
        <!-- Define a constraint to restrict access to /private/* --> 
        <security-constraint> 

                <display-name>Security constraint for the /private folder</display-name> 

                <web-resource-collection> 
                         
                        <web-resource-name>Protected Area</web-resource-name> 
                        <url-pattern>/private/*</url-pattern> 
                         
                        <!-- If you list http methods, only those methods are protected. --> 
                        <!-- Leave this commented out to protect all access --> 
                        <!-- 
                        <http-method>DELETE</http-method> 
                        <http-method>GET</http-method> 
                        <http-method>POST</http-method> 
                        <http-method>PUT</http-method> 
                        --> 

                </web-resource-collection> 

                <auth-constraint> 
                        <!-- Only only administrator and CMS editors to access this area --> 
                        <role-name>admin</role-name> 
                        <role-name>cms_editors</role-name> 
                </auth-constraint> 

        </security-constraint> 

        <!-- FORM based authentication --> 
        <!-- Leave this commented out, we will use BASIC (HTTP) authentication instead --> 
        <!-- 
        <login-config> 
                <auth-method>FORM</auth-method> 
                <form-login-config> 
                        <form-login-page>/login.jsp</form-login-page> 
                        <form-error-page>/error.jsp</form-error-page> 
                </form-login-config> 
        </login-config> 
        --> 
        <!-- This application uses BASIC authentication --> 
        <login-config> 
                <auth-method>BASIC</auth-method> 
                <realm-name>Editor Login</realm-name> 
        </login-config> 

        <!-- Define a constraint to force SSL on all pages in the application --> 
        <security-constraint> 

                <web-resource-collection> 
                        <web-resource-name>Entire Application</web-resource-name> 
                        <url-pattern>/*</url-pattern> 
                </web-resource-collection> 

                <user-data-constraint> 
                        <transport-guarantee>CONFIDENTIAL</transport-guarantee> 
                </user-data-constraint> 

        </security-constraint> 


        <!-- ========================================================== --> 
        <!-- Error Handler --> 
        <!-- ========================================================== --> 

        <!-- Define an error handler for 404 pages --> 
        <error-page> 
                <error-code>404</error-code> 
                <location>/error404.jsp</location> 
        </error-page> 

        <!-- Define an error handler for java.lang.Throwable --> 
        <error-page> 
                <exception-type>java.lang.Throwable</exception-type> 
                <location>/errorThrowable.jsp</location> 
        </error-page> 


        <!-- ========================================================== --> 
        <!-- Extra MIME types --> 
        <!-- ========================================================== --> 

        <!-- Set XML mime-mapping so spreadsheets open properly instead of being sent as an octet/stream --> 
        <mime-mapping> 
                <extension>xls</extension> 
                <mime-type>application/vnd.ms-excel</mime-type> 
        </mime-mapping> 


        <!-- ========================================================== --> 
        <!-- Locale --> 
        <!-- ========================================================== --> 

        <!-- Set Locale Encoding --> 
        <locale-encoding-mapping-list> 
                <locale-encoding-mapping> 
                        <locale>ja</locale> 
                        <encoding>Shift_JIS</encoding> 
                </locale-encoding-mapping> 
        </locale-encoding-mapping-list> 


        <!-- ========================================================== --> 
        <!-- Welcome Files --> 
        <!-- ========================================================== --> 

        <!-- Define, in order of preference, which file to show when no filename is defined in the path --> 
        <!-- eg: when user goes to http://yoursite.com/ or http://yoursite.com/somefolder --> 
        <!-- Defaults are provided in the server-wide web.xml file, such as index.jsp, index.htm --> 
        <!-- Note: using this tag overrides the defaults, so don't forget to add them here --> 
        <welcome-file-list> 
                <!-- Use index.swf if present, or splash.jsp, otherwise just look for the normal defaults --> 
                <welcome-file>index.swf</welcome-file> 
                <welcome-file>splash.jsp</welcome-file> 
                <welcome-file>index.html</welcome-file> 
                <welcome-file>index.htm</welcome-file> 
                <welcome-file>index.jsp</welcome-file> 
        </welcome-file-list> 

</web-app>

关于jsp和web.xml配置的相关知识,请参阅

http://www.cnblogs.com/LittleHann/p/3725886.html
搜索:2. web.xml基础语法

2. 配置web.xml禁用管理登录manager后台页面

要达到禁用后台登录的目的,我们可以通过对web.xml作如下修改达到目的

1. <security-constraint>(fro html) -> <auth-constraint> ->  <role-name>  
2. 将"/html/*"(web-gui)的身份鉴权角色限制修改为一个自定义的角色名,例如"just4fun",这个名字要保证tomcat的默认角色配置不会覆盖到,即达到对管理员的角色降权,禁止管理员
3. 针对web.xml的配置修改是立刻在tomcat中生效的,tomcat会对web.xml的修改自动做reload操作
4. manager页面会立刻禁止管理员登录

D:\tomcat\apache-tomcat-8.0.14\webapps\manager\WEB-INF\web.xml

修改后,立即生效

回滚后也立即生效

Relevant Link:

http://wiki.metawerx.net/wiki/Web.xml
http://fangyunfeng.iteye.com/blog/1862251

0x4: Make A Brustattack Blocking Filter Or Listener Within Tomcat:向tomcat注册一个用于阻断后台manager页面的暴力破解阻断模块

filter、listener是tomcat中对http数据流进行pre(前置劫持)、after(后置处理)的一直机制,简单来说,tomcat在整个http数据流的流程中给程序员暴露出了一些串行的hook点,允许程序员对http数据流进行修改

web.xml 的加载顺序是:context-param -> listener -> filter -> servlet ,而相同类型节点之间的程序调用的顺序是根据对应的mapping的顺序进行调用的

所以我们可以选择编写tomcat filter,实现暴力破解阻断的功能

1. Tomcat Filter

关于tomcat filter的相关知识,请参阅另一篇文章

http://www.cnblogs.com/LittleHann/p/3725886.html
搜索:0x3: Filter介绍

2. Code Example

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

/**
 * @author Administrator
 *
 */
public class LogFilter implements Filter {
    private FilterConfig filterConfig;

    public FilterConfig getFilterConfig() {
        System.err.println("...getFilterConfig...");
        return filterConfig;
    }

    public void setFilterConfig(FilterConfig filterConfig) {
        System.err.println("...setFilterConfig...");
        this.filterConfig = filterConfig;
    }

    /* (non-Javadoc)
     * @see javax.servlet.Filter#destroy()
     */
    @Override
    public void destroy() {
        System.err.println("...filter destroy...");
    }

    /* (non-Javadoc)
     * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain)
     */
    @Override
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
        System.err.println("...doFilter...");
        //传递下一个Filter
        chain.doFilter(request, response);
    }

    /* (non-Javadoc)
     * @see javax.servlet.Filter#init(javax.servlet.FilterConfig)
     */
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.err.println("...init Filter...");
        this.filterConfig = filterConfig;
    }

}

2. 配置web.xml,向web应用注册一个Filter

<filter>
    <filter-name>LogFilter</filter-name>
    <filter-class>com.ee.filter.LogFilter</filter-class>
</filter>

<filter-mapping>
    <filter-name>LogFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

0x5: 通过classloader反射动态修改容器内类的配置实现修复配置修复

0x6: 通过java attach api实现远程代码注入,修复应用内存配置漏洞

0x7: Use LockOutRealm To Prevents Brute Force Attacks(org.apache.catalina.realm.LockOutRealm)

LockOutRealm is an implementation of the Tomcat Realm interface that extends the CombinedRealm to provide lock out functionality to provide a user lock out mechanism if there are too many failed authentication attempts in a given period of time.
To ensure correct operation, there is a reasonable degree of synchronization in this Realm.
This Realm does not require modification to the underlying Realms or the associated user storage mechanisms. It achieves this by recording all failed logins, including those for users that do not exist. To prevent a DOS by deliberating making requests with invalid users (and hence causing this cache to grow) the size of the list of users that have failed authentication is limited.
Sub-realms are defined by nesting Realm elements inside the Realm element that defines the LockOutRealm. Authentication will be attempted against each Realm in the order they are listed. Authentication against any Realm will be sufficient to authenticate the user.
The LockOutRealm implementation supports the following additional attributes.

1. allRolesMode    
This attribute controls how the special role name * is handled when processing authorization constraints in web.xml. By default, the specification compliant value of strict is used which means that the user must be assigned one of the roles defined in web.xml. The alternative values are authOnly which means that the user must be authenticated but no check is made for assigned roles and strictAuthOnly which means that the user must be authenticated and no check will be made for assigned roles unless roles are defined in web.xml in which case the user must be assigned at least one of those roles.

2. cacheRemovalWarningTime    
If a failed user is removed from the cache because the cache is too big before it has been in the cache for at least this period of time (in seconds) a warning message will be logged. Defaults to 3600 (1 hour).

3. cacheSize    
Number of users that have failed authentication to keep in cache. Over time the cache will grow to this size and may not shrink. Defaults to 1000.

4. failureCount    
The number of times in a row a user has to fail authentication to be locked out. Defaults to 5.

5. lockOutTime    
The time (in seconds) a user is locked out for after too many authentication failures. Defaults to 300 (5 minutes).

为了配置 CombinedRealm,需要创建一个 <Realm> 元素,并将其内嵌在 <Engine> 或 <Host> 元素中的 $CATALINA_BASE/conf/server.xml 文件内。同样,你也可以将其内嵌到 context.xml 文件下的 <Context> 节点

<Engine name="Catalina" defaultHost="localhost">  
    <Realm className="org.apache.catalina.realm.LockOutRealm"> 
        <Realm className="org.apache.catalina.realm.UserDatabaseRealm" resourceName="UserDatabase"/>
    </Realm>

    <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 &quot;%r&quot; %s %b" />
    </Host>
</Engine>

0x8: 修改\conf\tomcat-users.xml中的弱密码

缺点在于,需要重启Tomcat

Relevant Link:

http://docs.oracle.com/javase/7/docs/technotes/guides/attach/index.html
https://tomcat.apache.org/tomcat-7.0-doc/security-howto.html#Securing_Management_Applications
https://tomcat.apache.org/tomcat-7.0-doc/config/realm.html#LockOut_Realm_-_org.apache.catalina.realm.LockOutRealm
https://tomcat.apache.org/tomcat-7.0-doc/realm-howto.html
http://wiki.jikexueyuan.com/project/tomcat/realms-aaa.html

0x9: 调用attach api动态修复JVM内存中配置

1. 列出当前主机上所有运行中JVM实例
2. 通过枚举进程列表、及其参数,找到tomcat进程PID
3. attach到目标JVM进程
4. 执行指定agent,注入指令,修改JVM的内存配置,关闭redirect、debug开关

 

6. Tomcat远程war包部署攻防

在windows环境下,tomcat的启动参数如下

D:\Java\bin\java.exe -Djava.util.logging.config.file="D:\Apache_Tomcat\conf\logging.properties" -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager   -Djava.endorsed.dirs="D:\Apache_Tomcat\endorsed" -classpath "D:\Apache_Tomcat\bin\bootstrap.jar;D:\Apache_Tomcat\bin\tomcat-juli.jar" -Dcatalina.base="D:\Apache_Tomcat" -Dcatalina.home="D:\Apache_Tomcat" -Djava.io.tmpdir="D:\Apache_Tomcat\temp" org.apache.catalina.startup.Bootstrap  start

规则

proc:path:blurry:java:cmd:"Tomcat\conf" write file:path:blurry:/webapps/*.war deny
//tomcat manager远程部署只会像webapps目录下写后缀为war的文件

Relevant Link:

Copyright (c) 2014 LittleHann All rights reserved

 

转载于:https://www.cnblogs.com/LittleHann/p/4054162.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值