Mybatils 中使用$代码逃避扫描漏洞

这篇具有很好参考价值的文章主要介绍了Mybatils 中使用$代码逃避扫描漏洞。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

解决$在mybatis中权限注入导致的安全问题


@Slf4j
@Component
public class MybatisSecureProcessor implements BeanPostProcessor {

//自定义的符号
private char customToken = '@';

//Mybatis的配置变量
private Properties mybatisVariables;

@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
//拦截SqlSessionFactory
if (! (bean instanceof SqlSessionFactory)) {
return bean;
}
SqlSessionFactory sqlSessionFactory = (SqlSessionFactory) bean;
Configuration configuration = sqlSessionFactory.getConfiguration();
//获取所有sql片段,这里不能是Collection<MappedStatement>, 因为里面可能有Ambiguity
Collection<?> mappedStatements = configuration.getMappedStatements();
//获取所有配置的变量
Properties variables = configuration.getVariables();
if (variables != null && variables.size() != 0) {
this.mybatisVariables = variables;
}

//这里面会有Ambiguity
for (Object item : mappedStatements) {

if (! (item instanceof MappedStatement)) {
continue;
}
MappedStatement mappedStatement = (MappedStatement) item;
try {
SqlSource sqlSource = mappedStatement.getSqlSource();
//我们只处理动态sql
if (sqlSource instanceof DynamicSqlSource) {
handleDynamicSqlSource((DynamicSqlSource) sqlSource);
} else if (sqlSource instanceof RawSqlSource) {
handleRawSqlSource(mappedStatement,(RawSqlSource) sqlSource);
} else {
log.error("不支持的mapper" + sqlSource.getClass().getSimpleName() + " unhandled");
}
} catch (Exception e) {
e.printStackTrace();
}

}

return bean;
}

private void handleDynamicSqlSource(DynamicSqlSource sqlSource) {
try {
Field rootSqlNodeField = DynamicSqlSource.class.getDeclaredField("rootSqlNode");
rootSqlNodeField.setAccessible(true);
SqlNode rootSqlNode = (SqlNode) rootSqlNodeField.get(sqlSource);
iterateSqlNode(rootSqlNode, sqlSource, rootSqlNodeField);
} catch (Exception e) {
e.printStackTrace();
}
}

private void handleRawSqlSource(MappedStatement mappedStatement,RawSqlSource sqlSource) throws NoSuchFieldException, IllegalAccessException {
//有兴趣可以实现一下
//改造方法:1、获取 sqlsource StaticSqlSource;
Field sqlSource1 = sqlSource.getClass().getDeclaredField("sqlSource");
sqlSource1.setAccessible(true);
Object o = sqlSource1.get(sqlSource);
Field sql1 = o.getClass().getDeclaredField("sql");
sql1.setAccessible(true);

BoundSql boundSql = sqlSource.getBoundSql(mappedStatement);
String sql = boundSql.getSql();
if (sql.contains(customToken+"{")) {
String newSql = tryParseCustomToken(sql);
sql1.set(o, newSql);

//将存放此sqlNode的地方换成TextSqlNode
TextSqlNode textSqlNode = new TextSqlNode(newSql);
DynamicSqlSource dynamicSqlSource = new DynamicSqlSource(mappedStatement.getConfiguration(),textSqlNode);
Field sqlSourceAsp = mappedStatement.getClass().getDeclaredField("sqlSource");
sqlSourceAsp.setAccessible(true);

//替换数据源
sqlSourceAsp.set(mappedStatement,dynamicSqlSource);

}

}

*
* 遍历所有sqlNode。
* @param sqlNode 需要被遍历的sqlNode。
* @param target 需要被遍历的sqlNode所在的对象。
* @param field 需要被遍历的sqlNode所在的字段。
* @throws Exception



@SuppressWarnings("unchecked")
private void iterateSqlNode(SqlNode sqlNode, Object target, Field field) throws Exception {
if (sqlNode instanceof MixedSqlNode) {
Field contentsField = MixedSqlNode.class.getDeclaredField("contents");
contentsField.setAccessible(true);
List<SqlNode> contents = (List<SqlNode>) contentsField.get(sqlNode);
for (SqlNode n : contents) {
iterateSqlNode(n, sqlNode, contentsField);
}
} else if (sqlNode instanceof StaticTextSqlNode) {
Field textField = StaticTextSqlNode.class.getDeclaredField("text");
textField.setAccessible(true);
String text = (String) textField.get(sqlNode);
String afterParsed = tryParseCustomToken(text);
if (afterParsed == null) {
return;
}
//将存放此sqlNode的地方换成TextSqlNode
TextSqlNode textSqlNode = new TextSqlNode(afterParsed);
saveNewNode(textSqlNode, sqlNode, target, field);
} else if (sqlNode instanceof ForEachSqlNode) {
Field contentsField = ForEachSqlNode.class.getDeclaredField("contents");
contentsField.setAccessible(true);
SqlNode contents = (SqlNode) contentsField.get(sqlNode);
iterateSqlNode(contents, sqlNode, contentsField);
} else if (sqlNode instanceof IfSqlNode) {
Field contentsField = IfSqlNode.class.getDeclaredField("contents");
contentsField.setAccessible(true);
SqlNode contents = (SqlNode) contentsField.get(sqlNode);
iterateSqlNode(contents, sqlNode, contentsField);
}
//TODO ...处理其他你需要处理的类型
}

//寻找自定义占位符
private String tryParseCustomToken(String text) {
List<TokenRecord> records = new LinkedList<>();
int strLength = text.length();
findCustom: for (int i = 0; i < strLength; i++) {
if (text.charAt(i) == this.customToken && text.charAt(i + 1) == '{') {
for (int j = i + 2; j < strLength; j++) {
if (text.charAt(j) == '}') {
TokenRecord record = new TokenRecord(i, i + 1, j);
String placeholderName = text.substring(i + 2, j);
record.placeholderName = placeholderName;
//注意,Mybatis会在首次加载Mapper的时候,把配置变量中存在的占位符先替换掉,而不是等到SQL执行的时候再替换
//例如,配置文件中有mybatis.configuration.variables.abc=xxx
//那么,Mybatis初始化的时候会把Mapper中的所有${abc}替换为xxx
//我们使用了自定义占位符,所以要替Mybatis完成这一步
if (this.mybatisVariables != null) {
record.placeholderValue = this.mybatisVariables.getProperty(placeholderName);
}
records.add(record);
continue findCustom;
}
}
throw new IllegalStateException("token not match");
}
}
if (records.isEmpty()) {
return null;
}
//生成替换后的sql字符串
StringBuilder builder = new StringBuilder();
//原text中将要被拼接的字符索引
int appendIndex = 0;
for (TokenRecord tr : records) {
builder.append(text, appendIndex, tr.customTokenIndex);
if (tr.placeholderValue != null) {
builder.append(tr.placeholderValue);
} else {
builder.append('$').append('{');
builder.append(tr.placeholderName);
builder.append('}');
}
appendIndex = tr.endBracketIndex + 1;
}
builder.append(text, appendIndex, text.length() - 1);

return builder.toString();
}

//把替换后的sqlNode保存到对应字段
@SuppressWarnings("unchecked")
public void saveNewNode(TextSqlNode newNode, SqlNode oldNode, Object targetObject, Field field) throws Exception {
Class<?> fieldType = field.getType();
if (List.class.isAssignableFrom(fieldType)) {
List<Object> list = (List<Object>) field.get(targetObject);
for (int i = 0; i < list.size(); i++) {
if (list.get(i) == oldNode) {
list.set(i, newNode);
return;
}
}
} else if (SqlNode.class.isAssignableFrom(fieldType)) {
field.set(targetObject, newNode);
}
}

//记录占位符替换信息的结构体
private static class TokenRecord {
int customTokenIndex;
int startBracketIndex;
int endBracketIndex;
String placeholderName;
String placeholderValue;

TokenRecord(int customTokenIndex, int startBracketIndex, int endBracketIndex) {
this.customTokenIndex = customTokenIndex;
this.startBracketIndex = startBracketIndex;
this.endBracketIndex = endBracketIndex;
}
}

}
 文章来源地址https://www.toymoban.com/news/detail-667098.html

到了这里,关于Mybatils 中使用$代码逃避扫描漏洞的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 使用kali系统中的nmap工具扫描漏洞

    1.我们打开kali在终端输入 nmap 可以看到nmap工具的所有参数如下图 2.现在我们来使用nmap工具中的这个 nmap www.xxx.com 命令来扫描网站开了那些端口如下图 如图我们知道了网站开了那些端口现在我们运行这个 nmap -sv -p端口 --script=vulners(或者vuln)www.xxx.com 如图 如上图我们知道了这

    2024年02月11日
    浏览(35)
  • 网络安全——漏洞扫描工具(AWVS的使用)

    一、安全漏洞产生的原因    二、什么是0day漏洞 在安全漏洞生命周期内,从安全漏洞被发现到厂商发布补丁程序用于修复该漏洞之前。 三、什么是安全漏洞生命周期 一共分为7个阶段    四、安全漏洞管理 1、    2、安全漏洞等级 (1)、微软设置了4个等级:低危、中危、

    2024年02月08日
    浏览(59)
  • 漏洞扫描工具AWVS的安装及配置使用过程

    Acunetix Web Vulnerability Scanner(AWVS)可以扫描任何通过Web浏览器访问和遵循HTTP/HTTPS规则的Web站点。适用于任何中小型和大型企业的内联网、外延网和面向客户、雇员、厂商和其它人员的Web网站。 AWVS可以通过检查SQL注入攻击漏洞、XSS跨站脚本攻击漏洞等漏洞来审核Web应用程序的

    2023年04月16日
    浏览(53)
  • 漏洞扫描工具OWASP ZAP的下载、安装、使用教程

    开放式Web应用程序安全项目(OWASP,Open Web Application Security Project)是一个组织,它提供有关计算机和互联网应用程序的公正、实际、有成本效益的信息。ZAP则是OWASP里的工具类项目,也是旗舰项目,全称是OWASP Zed attack proxy,是一款web application 集成渗透测试和漏洞工具,同样是

    2024年02月07日
    浏览(81)
  • 常见漏洞扫描工具AWVS、AppScan、Nessus的使用

    AWVS(Acunetix Web Vulnerability Scanner)是一款知名的网络漏洞扫描工具,通过网络爬虫测试网站安全,检测流行的 Web应用攻击 ,如跨站脚本、sql 注入等。 Windows安装没有什么难度,这里主要记录Kali环境下的安装与部署。 准备 acunetix_trial.sh 和激活包 pathc_awvs 。 下载地址: 修改

    2024年02月03日
    浏览(53)
  • 自动化漏洞扫描工具Goby介绍、下载、使用、插件、功能

    介绍 Goby 是一款新的网络安全测试工具,它能够针对一个目标企业梳理最全的攻击面信息,同时能进行高效、实战化漏洞扫描,并快速地从一个验证入口点,切换到横向。我们希望能够输出更具生命力的工具,能够对标黑客的实际能力,帮助企业来有效地理解和应对网络攻击

    2024年02月17日
    浏览(61)
  • 【漏洞名称】终端服务未使用网络级别身份验证 (NLA) 【原理扫描】

    1丶漏洞报告描述如下图: 2丶漏洞修复流程如下 : (1)丶选择【我的电脑】右键选择【属性】 (2)丶选择【远程】把如下图箭头勾上

    2024年02月12日
    浏览(42)
  • Web安全漏洞扫描神器-AWVS下载、安装及使用教程

    目录 一、AWVS介绍 二、网站漏洞扫描 三、漏洞扫描结果 四、漏洞告警分析利用 五、根据漏洞信息进行验证、利用 六、网络爬虫 七、主机发现(c段探测) 八、子域名探测 九、SQL注入 十、HTTP头编辑 十一、HTTP监听拦截 AWVS为Acunetix Web Vulnarability Scanner的简称,是一种web网站漏

    2024年02月08日
    浏览(61)
  • 解决 远程 服务器--Microsoft Windows CredSSP 远程执行代码漏洞(CVE-2018-0886)【原理扫描】(KB4103725 或 KB4103715)

    系统: windows server 2012 R2 standard 扫描出漏洞: Microsoft Windows CredSSP 远程执行代码漏洞(CVE-2018-0886)【原理扫描】 按照微软官方给的答案: https://portal.msrc.microsoft.com/zh-CN/security-guidance/advisory/CVE-2018-0886,对应下载安装包是 KB4103725 或 KB4103715 但是下载后安装 报错: 此更新不适用此

    2024年02月06日
    浏览(68)
  • 渗透测试——安全漏洞扫描工具APPScan的安装与基本使用步骤

            HCL AppScan Standard是安全专家和渗透测试者设计的动态应用程序安全测试工具,AppScan使用强大的扫描引擎,会自动检索目标应用程序并测试漏洞。测试结果按优先级排列,允许操作员快速分类问题、发现最关键的漏洞。每个检测到的问题都可以根据清晰且可操作的修

    2024年02月09日
    浏览(45)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包