thinkgem / jeesite

Java rapid development platform, based (Spring Boot, Spring MVC, Apache Shiro, MyBatis, Beetl, Bootstrap, AdminLTE), online code generation, including modules: Organization, role users, menu and button authorization, data permissions, system parameters, content management, workflow, etc. Loose coupling design is adopted; one key skin switch; account security Settings, password policies; Online scheduled task configuration; Support cluster, support SAAS; Support for multiple data sources
http://jeesite.com
Apache License 2.0
8k stars 5.66k forks source link

There is an SQL injection vulnerability in URL `/jeesite/a/oa/leave/list` #522

Closed LetianYuan closed 6 months ago

LetianYuan commented 6 months ago

Affected Versions

The latest version of jeesite (commit 857cc884991184ae3e4c283f9d8bcea272382415).

Describe the vulnerability

There is an SQL injection vulnerability in URL /jeesite/a/oa/leave/list.

The root cause is at src/main/resources/mappings/modules/oa/LeaveDao.xml.

As the following codes show, parameter ids is wrapped by $ instead of #.

    <select id="findList" resultType="Leave">
        SELECT 
            <include refid="leaveColumns"/>
        FROM oa_leave a
        <include refid="leaveJoins"/>
        WHERE a.del_flag = #{DEL_FLAG_NORMAL} 
        <if test="createDateStart != null">
            AND a.create_date &gt;= #{createDateStart}
        </if>
        <if test="createDateEnd != null">
            AND a.create_date &lt;= #{createDateEnd}
        </if>
        <if test="leaveType != null and leaveType != ''">
            AND a.leave_type = #{leaveType}
        </if>
        <if test="ids != null and ids != ''">
            AND a.id IN (${ids})
        </if>
        ${sqlMap.dsf}
        ORDER BY a.id DESC
    </select>

And the parameter ids is obtained by getIds in src/main/java/com/thinkgem/jeesite/modules/oa/entity/Leave.java.

    public String getIds() {
        List<String> idList = Lists.newArrayList();
        if (StringUtils.isNotBlank(ids)){
            String ss = ids.trim().replace(" ", ",").replace(" ",",").replace(",", ",").replace("'", "");
            for(String s : ss.split(",")) {
//              if(s.matches("\\d*")) {
                    idList.add("'"+s+"'");
//              }
            }
        }
        return StringUtils.join(idList, ",");
    }

If an attacker pass value \,)/**/UNION/**/SELECT/**/......(evil sql)......# to parameter ids, the final SQL will be like SELECT ... FROM ... WHERE ... AND a.id IN ('\',')/**/UNION/**/SELECT/**/......(evil sql)......#') ... ORDER BY ....

So, the attacker escapes from quote ' and parentheses (). Then the attacker can execute any evil SQLs.

To Reproduce (Attacking Vector)

Go to jeesite/a/oa/leave/list, and just type a slash \ in 请假编号 and click button 查询 will cause an MySQLSyntaxErrorException.

1

2

And if you type \,)/**/UNION/**/SELECT/**/......(evil sql)......# in 请假编号 and click button 查询, any evil SQL will be executed.

Note that space and comma are preprocessed in src/main/java/com/thinkgem/jeesite/modules/oa/entity/Leave.java.

Attackers can use comments /**/ to bypass space limitation. That is, write SELECT/**/1 instead of SELECT 1.

And attackers can write SELECT * FROM ((SELECT 1)A JOIN (SELECT 2)B JOIN (SELECT 3)C) instead of SELECT 1,2,3 to bypass comma limitation.

And also note that, in the frontend, there's content length limitation maxlength="50" of input textbox 请假编号. But this limitation does not exist in the backend.

LetianYuan commented 6 months ago

As this vulnerability is confirmed and fixed by you, we're considering report it to CVE MITRE.