首页 > 代码库 > Tomcat Server Configuration Automation Reinforcement(undone)

Tomcat Server Configuration Automation Reinforcement(undone)

目录

0. 引言1. 黑客针对WEB Server会有那些攻击面2. 针对Tomcat Server可以做的安全加固3. Managing Security Realms with JMX4. 实现对TOMCAT配置信息的动态修改(hot dynamic edit)5. Tomcat后台manager页面禁用

 

0. 引言

WEB容器(WEB Server)是运行在操作系统上的一个应用级软件,对服务器的配置(config文件)进行加固处理是防御WEB相关漏洞的一个有效的手段。对于实现WEB服务器的配置加固,我们需要达到如下几个目标

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

 

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白名单、黑名单限制

Relevant Link:

http://www.searchsecurity.com.cn/showcontent_11382.htmhttp://www.searchsecurity.com.cn/guide/webseversetting.htm

 

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

1. 后台管理页面(manager管理界面)basic authentication登录弱口令强化帮助用户解决弱口令问题2. 禁用后台管理页面(manager管理界面)在大多数生产情况下,manager页面是不需要的3. 禁用tomcat manager管理界面的WAR Remote Deploy远程部署通过后台管理界面的WAR部署接口进行GETSHELL是黑客常用的手段4. 禁止列目录(index travel)

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

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

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

0x2: 禁用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.xml2. JDBCRealm//className="org.apache.catalina.realm.JDBCRealmJDBCRealm 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. MemoryRealmMemoryRealm 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 UserDatabaseRealmextends 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-guiallows access to the HTML GUI and the status pages也就是我们常用到的http://localhost:8080/manager/html2. manager-scriptallows access to the text interface and the status pages3. manager-jmxallows access to the JMX proxy and the status pages4. manager-statusallows 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的后台管理界面已经被禁用

Relevant Link:

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

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

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

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

 

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 LevelThe 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 shortMBeans 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 MBeans2. the Agent LevelThere 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 JMXs 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 roleIn 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 providers3. 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 realm2. 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 AuthorizerMBean2. 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. AuthenticationProviderMBeanThe 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. AuthenticatorMBeanThe 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. IdentityAsserterMBeanThe 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. ServletAuthenticationFilterMBeanThe 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 users2. 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 Proxy2. 使用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 MBeans 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=used3. 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=104. JMX Invoke commandThe 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.htmlhttp://docs.oracle.com/cd/E11035_01/wls100/jmx/accessWLS.html#wp1112969http://tomcat.apache.org/tomcat-8.0-doc/manager-howto.html#Using_the_JMX_Proxy_Servlethttp://tomcat.apache.org/tomcat-8.0-doc/manager-howto.htmlhttp://tomcat.apache.org/tomcat-8.0-doc/realm-howto.html#MemoryRealmhttp://docs.oracle.com/cd/E11035_01/wls100/jmx/editsecurity.htmlhttp://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=stateNameresult:OK - Attribute get Catalina:type=Valve,host=localhost,context=/host-manager,name=BasicAuthenticator - stateName = STARTED

Relevant Link:

http://whitesock.iteye.com/blog/246186http://www.programcreek.com/java-api-examples/index.php?api=javax.management.MBeanServerConnectionhttp://pic.dhe.ibm.com/infocenter/wxsinfo/v8r6/index.jsp?topic=%2Fcom.ibm.websphere.extremescale.doc%2Ftxsmbeanprog.htmlhttp://blog.csdn.net/airobot008/article/details/3951524http://sharpspeed.iteye.com/blog/2009770http://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页面禁用

结合以上我们所了解的知识,我们该如何解决因为tomcat后台manager页面被弱口令、或者暴力破解导致的入侵呢?我们可以作如下思考

1. 直接删除manager页面对应的jsp文件、manager目录2. 研究一下tomcat的第三方监听器模块编写,向tomcat动态注册一个监听暴力破解事件的模块来阻断对后台manager页面的暴力破解3. 对磁盘上的tomcat-users.xml文件的修复还是要的,尽管这需要等到用户自己下次重启的时候才会生效    1) 将若密码修改为强密码    2) 取消用户的manager-gui,即降权,达到禁止用户访问manager页面的目的 5. 仅仅修改tomcat下的manager应用的web.xml文件,达到禁用basic authentication、或者禁止登录效果后,重启这个应用(manager)即可

我们来逐一对这些思路进行可行性验证

0x1: 针对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 URLs -->         <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.xmlhttp://fangyunfeng.iteye.com/blog/1862251

0x2: 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>

 

Copyright (c) 2014 LittleHann All rights reserved

 

Tomcat Server Configuration Automation Reinforcement(undone)