📄 mcsrfdetector.java
字号:
package net.jumperz.app.MGuardian.plugin;
import net.jumperz.io.*;
import net.jumperz.net.*;
import net.jumperz.security.*;
import net.jumperz.util.*;
import java.security.NoSuchAlgorithmException;
import java.util.*;
import java.io.*;
import java.util.regex.*;
import java.sql.*;
import net.jumperz.sql.*;
import net.jumperz.app.MGuardian.*;
public class MCSRFDetector
extends MGuardianDBPlugin
implements MObserver1
{
private MTokenGenerator tokenGenerator;
private String tokenName;
private long time = 0;
private long interval;
private int timeout;
private int type;
private boolean oneTime = false;
private boolean block = false;
private String command;
public static final String TABLE_NAME = "tcsrf";
public static final String TOKEN_NAME = "CSRFToken";
public static final String PLUGIN_NAME = "CSRFDetector";
public static final int MAX_SESSIONID_LENGTH = 256;
public static final String DEFAULT_INTERVAL = "5"; //minute
public static final String DEFAULT_TIMEOUT = "30"; //minute
public static final String DEFAULT_ONETIME = "true";
public static final String DEFAULT_BLOCK = "true";
public static final int TYPE_COOKIE = 0;
public static final int TYPE_BASIC = 1;
// --------------------------------------------------------------------------------
protected String getPluginName()
{
return PLUGIN_NAME;
}
// --------------------------------------------------------------------------------
public void update()
{
++time;
if( time >= interval )
{
time = 0;
String queryString = "delete from " + TABLE_NAME + " where t < ?";
MObjectArray args = new MObjectArray( );
args.add( new Timestamp( System.currentTimeMillis() - timeout * 60 * 1000 ) );
try
{
synchronized( this )
{
MSqlUtil.executeUpdate2( connection, queryString, args );
}
}
catch( SQLException e )
{
e.printStackTrace();
}
}
}
// --------------------------------------------------------------------------------
public void startup2()
throws IOException
{
MTimer timer = MGuardianImpl.getInstance().getTimer();
timer.register1( this );
interval = Long.parseLong( control.getProperty( PLUGIN_NAME + ".interval", DEFAULT_INTERVAL ) );
interval = interval * 60 ; // minute -> second
timeout = Integer.parseInt( control.getProperty( PLUGIN_NAME + ".timeout", DEFAULT_TIMEOUT ) );
tokenName = control.getProperty( PLUGIN_NAME + ".tokenName", TOKEN_NAME );
command = control.getProperty( PLUGIN_NAME + ".command", "" );
oneTime = MStringUtil.meansTrue( control.getProperty( PLUGIN_NAME + ".oneTime", DEFAULT_ONETIME ) );
block = MStringUtil.meansTrue( control.getProperty( PLUGIN_NAME + ".block", DEFAULT_BLOCK ) );
try
{
tokenGenerator = new MTokenGenerator();
if( useDefaultDb && !tableExists( TABLE_NAME ) )
{
createTable();
}
}
catch( Exception e )
{
throw new IOException( e.getMessage() );
}
}
// --------------------------------------------------------------------------------
private synchronized void createTable()
throws SQLException
{
String queryString = "create table " + TABLE_NAME + " ( t timestamp, sessionGroupName varchar( 256 ), sessionId varchar( 256 ), token varchar( 128 ) );";
MSqlUtil.executeUpdate( connection, queryString );
}
// --------------------------------------------------------------------------------
public Map execute( Map sessionInfo )
{
try
{
return execute2( sessionInfo );
}
catch( Exception e )
{
e.printStackTrace();
}
return null;
}
//--------------------------------------------------------------------------------
public Map execute2( Map sessionInfo )
throws IOException, SQLException
{
/*
* request cookie jsessionid www.a.com
* request cookie jsessionid
* request basic www.a.com
* request basic
* response cookie jsessionid www.a.com
*/
MHttpRequest request = ( MHttpRequest )sessionInfo.get( "request" );
MHttpResponse response = ( MHttpResponse )sessionInfo.get( "response" );
String arg = ( String )sessionInfo.get( "arg" );
String[] args = arg.split( "[ \t]+" );
String sessionGroupName;
String sessionIdName = null;
String sessionId = null;
if( args.length < 2 )
{
throw new IOException( "Invalid args" );
}
String typeStr = args[ 1 ];
if( typeStr.equalsIgnoreCase( "Cookie" ) )
{
type = TYPE_COOKIE;
if( args.length == 4 )
{
sessionGroupName = args[ 3 ];
}
else if( args.length == 3 )
{
sessionGroupName = "_DEFAULT_";
}
else
{
throw new IOException( "Invalid args" );
}
sessionIdName = args[ 2 ];
int sessionType = MHttpRequest.SESSIONTYPE_COOKIE;
sessionId = request.getSessionId( sessionType, sessionIdName );
}
else if( typeStr.equalsIgnoreCase( "Basic" ) )
{
type = TYPE_BASIC;
if( args.length == 3 )
{
sessionGroupName = args[ 2 ];
}
else if( args.length == 2 )
{
sessionGroupName = "_DEFAULT_";
}
else
{
throw new IOException( "Invalid args" );
}
if( request.headerExists( "Authorization" ) )
{
sessionId = MStringUtil.getMd5Hash( request.getHeaderValue( "Authorization" ) + "S4LT" );
}
}
else
{
throw new IOException( "Invalid args" );
}
if( args[ 0 ].equals( "request" ) )
{
if( sessionId == null )
{
return null;
}
return processRequest( sessionInfo, sessionId, sessionGroupName );
}
else if( args[ 0 ].equals( "response" ) )
{
if( type == TYPE_COOKIE && response.headerExists( "Set-Cookie" ) )
{
List cookieList = response.getHeaderValueList( "Set-Cookie" );
String newSessionId = null;
for( int i = 0; i < cookieList.size(); ++i )
{
String cookie = ( String )cookieList.get( i );
if( cookie.indexOf( sessionIdName ) > -1 )
{
newSessionId = MRegEx.getMatch( sessionIdName + "=([^; ]*)", cookie );
break;
}
}
if( newSessionId != null )
{
if( sessionId != null )
{
changeSessionId( sessionId, newSessionId, sessionGroupName );
}
sessionId = newSessionId;
}
}
return processResponse( sessionInfo, sessionId, sessionGroupName );
}
return null;
}
// --------------------------------------------------------------------------------
private synchronized void changeSessionId( String oldSessionId, String newSessionId, String sessionGroupName )
throws SQLException
{
String queryString = "update " + TABLE_NAME + " set sessionId = ? where sessionGroupName = ? and sessionId = ?";
MObjectArray args = new MObjectArray( );
args.add( newSessionId );
args.add( sessionGroupName );
args.add( oldSessionId );
MSqlUtil.executeUpdate2( connection, queryString, args );
}
// --------------------------------------------------------------------------------
private Map processRequest( Map sessionInfo, String sessionId, String sessionGroupName )
throws IOException, SQLException
{
boolean validTokenFound = false;
if( sessionId != null && sessionId.length() > MAX_SESSIONID_LENGTH )
{
throw new IOException( "sessionId too long." );
}
MHttpRequest request = ( MHttpRequest )sessionInfo.get( "request" );
String token = request.getParameterValue( tokenName );
if( !token.equals( "" ) )
{
String queryString = "select * from " + TABLE_NAME + " where sessionGroupName = ? and sessionId = ? and token = ?";
MObjectArray args = new MObjectArray( );
args.add( sessionGroupName );
args.add( sessionId );
args.add( token );
synchronized( this )
{
ResultSet rs = MSqlUtil.executeQuery2( connection, queryString, args );
if( rs.next() )
{
validTokenFound = true;
if( oneTime )
{
queryString = "delete from " + TABLE_NAME + " where token = ?";
MSqlUtil.executeUpdate2( connection, queryString, token );
}
}
}
}
if( !validTokenFound )
{
Map pluginResult = new HashMap();
pluginResult.put( "block", new Boolean( block ) );
pluginResult.put( "log", new Boolean( true ) );
if( !command.equals( "" ) )
{
pluginResult.put( "command", command );
}
return pluginResult;
}
return null;
}
// --------------------------------------------------------------------------------
private Map processResponse( Map sessionInfo, String sessionId, String sessionGroupName )
throws IOException, SQLException
{
if( sessionId == null )
{
return null;
}
if( sessionId.length() > MAX_SESSIONID_LENGTH )
{
throw new IOException( "sessionId too long." );
}
MHttpResponse response = ( MHttpResponse )sessionInfo.get( "response" );
if( response == null )
{
return null;
}
if( !response.hasBody() )
{
return null;
}
response.chunkToNormal();
String token = null;
MBuffer buffer = new MBuffer();
MLineReader reader = new MAdvancedLineReader();
reader.setInputStream( response.getBodyInputStream() );
while( true )
{
String line = reader.readLine();
if( line == null )
{
break;
}
String formTag = MRegEx.getMatchIgnoreCase( "(</form[^>]*>)", line );
//System.out.println( formTag );
if( formTag.length() > 0 )
{
if( token == null )
{
token = getToken( sessionGroupName, sessionId );
}
String tokenTag = "<input type=\"hidden\" name=\"" + tokenName + "\" value=\"" + token + "\">";
line = MStringUtil.replaceFirst( line, formTag, tokenTag + formTag );
}
buffer.write( MStringUtil.getBytes( line ) );
buffer.write( MStringUtil.getBytes( reader.getLastDelimiterString() ) );
}
if( token != null )
{
response.setBody( buffer );
response.setHeaderValue( "Content-Length", Integer.toString( buffer.getSize() ) );
}
return null;
}
// --------------------------------------------------------------------------------
private String getToken( String sessionGroupName, String sessionId )
throws SQLException
{
String token = tokenGenerator.getToken();
String queryString = "insert into " + TABLE_NAME + " values( ??? )";
MObjectArray args = new MObjectArray( );
args.add( new Timestamp( System.currentTimeMillis() ) );
args.add( sessionGroupName );
args.add( sessionId );
args.add( token );
synchronized( this )
{
MSqlUtil.executeUpdate2( connection, queryString, args );
}
return token;
}
//--------------------------------------------------------------------------------
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -