您的位置:首页 > 运维架构

【web安全】监控文件目录变化 , 防篡改系统的简易实现

2016-07-16 14:36 447 查看
web应用开发时我们从开发的角度处理了XSS,CSRF,SQL注入等安全问题后,系统仍然是不安全的,想想看如果有人通过某种手段直接篡改了应用下的jsp文件会如何?或者上传了一个恶意的文档,常见的就是把你的主页给黑了,挂上某国国旗之类的。所以单纯从应用开发的角度解决web安全问题还是不够的,防篡改系统的引入就是从部署的角度解决上述问题。市面上有很多的防篡改系统 ,这Guard,那Guard,统称为X-Guard 了,如果项目中可以采购的话最好直接采购,价钱也不贵。如果确实没有项目预算了,可以自己实现一个简易的防篡改系统。

防篡改系统首要的一点是要能监控到文件目录的变化,现在比较好的一种实现技术是对文件目录进行监控,JDK提供了一种便捷的目录监控api,下面的例子参照官方文档略微做了封装,使用起来比较方便:

事件处理接口类:

import java.nio.file.Path;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;
import java.util.Map;

//定义用来处理各类事件的接口类
public interface IEventHandler {

public void processEvents(WatchService watcher,Map<WatchKey, Path> kes);
}


事件处理接口实现类:

import java.nio.file.Path;
import java.nio.file.StandardWatchEventKinds;
import java.nio.file.WatchEvent;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;
import java.util.Map;

public class MyEventHandler implements IEventHandler {

public void processEvents(WatchService watcher, Map<WatchKey, Path> keyMap) {

int count = 0;
WatchKey watchKey = null;
for(;;){

try {
watchKey = watcher.take();
} catch (Exception e) {
return;
}
Path path = keyMap.get(watchKey);

System.out.println("Loop count: " + count);
for (WatchEvent<?> event : watchKey.pollEvents()) {
if(StandardWatchEventKinds.ENTRY_CREATE.equals(event.kind())){
System.out.println("创建了文件: "+ path.resolve(event.context().toString()));
}
if(StandardWatchEventKinds.ENTRY_DELETE.equals(event.kind())){
System.out.println("删除了文件: "+ path.resolve(event.context().toString()));
}
if(StandardWatchEventKinds.ENTRY_MODIFY.equals(event.kind())){
Path p = path.resolve(event.context().toString());
if(p.toFile().isDirectory()){
System.out.println("目录 "+p+" 下文件发生了变化.....");
}else {
System.out.println("修改了文件: "+ p);
}
}
count++;
}
watchKey.reset();
}
}
}


用来注册要监控目录的类:
import java.io.IOException;
import java.nio.file.FileSystems;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.StandardWatchEventKinds;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.HashMap;
import java.util.Map;

/**
* 用来注册要监控的文件目录
*/
public class WatchDirService {

/**
*
* @param startDir 起始目录
* @param recursive 是否要监控子目录
* @param handler 事件处理类
* @throws IOException
*/
public static void registerWatch(Path startDir,boolean recursive,IEventHandler handler) throws IOException{

final WatchService watcher = FileSystems.getDefault().newWatchService();
final Map<WatchKey, Path> keyMap = new HashMap<>();

WatchKey watchkey=startDir.register(watcher,
StandardWatchEventKinds.ENTRY_MODIFY,
StandardWatchEventKinds.ENTRY_CREATE,
StandardWatchEventKinds.ENTRY_DELETE);
keyMap.put(watchkey, startDir);

//为所有的子目录注册监听
if(recursive){
Files.walkFileTree(startDir, new SimpleFileVisitor<Path>() {

@Override
public FileVisitResult preVisitDirectory(Path dir,
BasicFileAttributes attrs) throws IOException {

WatchKey watchkey=dir.register(watcher
,StandardWatchEventKinds.ENTRY_MODIFY
,StandardWatchEventKinds.ENTRY_CREATE
,StandardWatchEventKinds.ENTRY_DELETE);
keyMap.put(watchkey, dir);
return FileVisitResult.CONTINUE;
}

});
}

handler.processEvents(watcher, keyMap);
}
}


最后再写个测试类:

import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;

public class Test {
public static void main(String[] args) throws IOException {
Path startDir = Paths.get("d:\\temp\\");
WatchDirService.registerWatch(startDir, true, new MyEventHandler());
}
}


可以测试一下修改d:\\temp目录下的文件,看看是不是在监控台显示监控到文件修改了? 



防篡改系统监测到文件目录的变化只是第一步,还需要能够防止篡改行为产生实际的影响。这个可以根据自己的实现思路编写上面的 IEventHandler  的实现类即可,一般更新系统时可以把应用系统的文件同时放到一个备份目录下,比如可以放到E:\\backup,然后对应用系统的每个文件(包含js,img,jsp等等)生成hash值并存储到数据库或缓存中,当监测到文件变化时就和数据库中的值或者缓存值进行比较,通过比较的结果来判定监测到的文件变化是合法的操作还是恶意的篡改行为,这样一个最简易的防篡改系统就完成了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息