在打靶场的同时,需要想一下如果你是开发人员你会怎样去防御这种漏洞,而作为攻击方你又怎么去绕过开发人员的防御。
环境搭建
GitHub - j3ers3/Hello-Java-Sec: ☕️ Java Security,安全编码和代码审计
SQL注入
SQLI(SQL Injection), SQL注入是因为程序未能正确对用户的输入进行检查,将用户的输入以拼接的方式带入SQL语句,导致了SQL注入的产生。攻击者可通过SQL注入直接获取数据库信息,造成信息泄漏。
SQL注入之JDBC注入
JDBC有两个方法执行SQL语句,分别是PrepareStatement和Statement。
漏洞代码:
// 采用原始的Statement拼接语句,导致漏洞产生
public String jdbcVul(String id) {
StringBuilder result = new StringBuilder();
try {
Class.forName("com.mysql.cj.jdbc.Driver");
Connection conn = DriverManager.getConnection(db_url, db_user, db_pass);
Statement stmt = conn.createStatement();
// 拼接语句产生SQL注入
String sql = "select * from users where id = '" + id + "'";
ResultSet rs = stmt.executeQuery(sql);
while (rs.next()) {
String res_name = rs.getString("user");
String res_pass = rs.getString("pass");
String info = String.format("查询结果 %s: %s", res_name, res_pass);
result.append(info);
}
漏洞代码二:
// PrepareStatement会对SQL语句进行预编译,但有时开发者为了便利,直接采取拼接的方式构造SQL,此时进行预编译也无用。
Connection conn = DriverManager.getConnection(db_url, db_user, db_pass);
String sql = "select * from users where id = " + id;
PreparedStatement st = conn.prepareStatement(sql);
System.out.println("[*] 执行SQL语句:" + st);
ResultSet rs = st.executeQuery();
SQL注入之MyBatis
MyBatis框架底层已经实现了对SQL注入的防御,但存在使用不当的情况下,仍然存在SQL注入的风险。
漏洞代码:
// 此漏洞出现频率较高并且很严重!
// 为何产生:由于使用 #{} 会将对象转成字符串,形成 order by "user" desc 造成错误,因此很多研发会采用${}来解决,从而造成SQL注入
// 点击运行可通过报错语句获取数据库user
@RequestMapping("/mybatis/vul/order")
public List<User> orderBy(String field, String sort) {
return userMapper.orderBy(field, sort);
}
// mapper.xml语句
<select id="orderBy" resultType="com.best.hello.entity.User">
select * from users order by ${field} ${sort}
</select>
漏洞代码二:
// 模糊搜索时,直接使用'%#{q}%' 会报错,部分研发图方便直接改成'%${q}%'从而造成注入
@Select("select * from users where user like '%${q}%'")
List<User> search(String q);
// 安全代码,采用concat
@Select("select * from users where user like concat('%',#{q},'%')")
List<User> search(String q);
文件上传
文件上传漏洞,是指用户上传了一个可执行的脚本文件(如jsp\php\asp),并通过此脚本文件获得了执行服务器端命令的能力。常见场景是web服务器允许用户上传图片或者普通文本文件保存,这种漏洞属于低成本高杀伤力
漏洞代码:
// 允许上传任意文件导致的安全风险
public String singleFileUpload(@RequestParam("file") MultipartFile file, RedirectAttributes redirectAttributes) {
try {
byte[] bytes = file.getBytes();
Path dir = Paths.get(UPLOADED_FOLDER);
Path path = Paths.get(UPLOADED_FOLDER + file.getOriginalFilename());
Files.write(path, bytes);
redirectAttributes.addFlashAttribute("message","上传文件成功:" + path + "");
} catch (Exception e) {
return e.toString();
}
return "redirect:upload_status";
}
目录遍历
目录遍历, 应用系统在处理下载文件时未对文件进行过滤,系统后台程序程序中如果不能正确地过滤客户端提交的../和./之类的目录跳转符,攻击者可以通过输入../进行目录跳转&#x