.NET ORM 注入 审计-FreeSql中直接使用 SQL 片段的问题

admin 2024年2月1日21:00:09评论9 views字数 4162阅读13分52秒阅读模式

.NET ORM 注入 审计-FreeSql中直接使用 SQL 片段的问题

采用项目 ASP.NET Core Web Application 模板创建项目的demo

.NET ORM 注入 审计-FreeSql中直接使用 SQL 片段的问题

搞定。环境OK了。看看注入的地方。

ORM 工具通过将 SQL 语句中的变量部分(例如查询条件中的参数)与代码分离,来防止 SQL 注入攻击。

但是在官网上,有提示:动态操作 | FreeSql 官方文档

FreeSql 提供 Where(sql)、GroupBy(sql)、OrderBy(sql)、ToList(sql) 等直接使用 SQL 片段的 API。使用这些 API 时请务必注意SQL注入安全问题。不建议前端直接 POST SQL 到后端使用它们,而应该在后端做一层映射。

  • • POC= 1' and 1=(select @@version)) a --

.NET ORM 注入 审计-FreeSql中直接使用 SQL 片段的问题

image-20240130171100041

此时是存在的。

写一个Demo(改动的dotnetcore-examples/ORM/FreeSql),搞定了。

using System;
using System.Collections.Generic;
using System.Xml.Linq;
using AutoMapper;
using Microsoft.AspNetCore.Mvc;
using OvOv.Core.Domain;
using OvOv.Core.Models.Blogs;
using OvOv.Core.Web;

namespace OvOv.FreeSql.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class BlogController : ControllerBase
    {
        // GET api/Blog

        private readonly IFreeSql _fsql;
        private readonly IMapper _mapper;
        public BlogController(IFreeSql fsql, IMapper mapper)
        {
            _fsql = fsql;
            _mapper = mapper;
        }

        /// <summary>
        /// 博客列表页 
        /// </summary>
        /// <param name="pageDto">分页参数</param>
        /// <returns></returns>
        [HttpGet]
        public ActionResult<PagedResultDto<Blog>> Get([FromQuery] PageDto pageDto)
        {
            List<Blog> blogs = _fsql.Select<Blog>().OrderByDescending(r => r.CreateTime).Page(pageDto.PageNumber, pageDto.PageSize).ToList();
            long count = _fsql.Select<Blog>().Count();
            return new PagedResultDto<Blog>(count, blogs);
        }

        // GET api/blog/5
        [HttpGet("{id}")]
        public ActionResult<Blog> Get(String id)
        {
            var blogs = _fsql.Select<Blog>()
                 .WithSql($"SELECT * FROM Blog WHERE id LIKE '%{id}%'")
                 .ToList();
            return Ok(blogs + "wulala");
            
        }


        // POST api/blog
        [HttpPost]
        public void Post([FromBody] CreateBlogDto createBlogDto)
        {
            Blog blog = _mapper.Map<Blog>(createBlogDto);
            blog.CreateTime = DateTime.Now;
            _fsql.Insert<Blog>(blog).ExecuteAffrows();
        }

        // PUT api/blog
        [HttpPut]
        public void Put([FromBody] UpdateBlogDto updateBlogDto)
        {

            //eg.1 更新指定列
            //_fsql.Update<Blog>(updateBlogDto.BlogId).Set(a => new Blog()
            //{
            //    Title = updateBlogDto.Title,
            //    Content = updateBlogDto.Content
            //}).ExecuteAffrows();

            //eg.2将这个实体更新到数据库中。当更新时,会把其他列的值,如CreateTime也更新掉。
            //使用IgnoreColumns可忽略某一些列。

            Blog blog = _mapper.Map<Blog>(updateBlogDto);
            _fsql.Update<Blog>().SetSource(blog).IgnoreColumns(r => r.CreateTime).ExecuteAffrows();
        }

        // DELETE api/blog/5
        [HttpDelete("{id}")]
        public void Delete(int id)
        {
            _fsql.Delete<Blog>(new { BlogId = id }).ExecuteAffrows();
        }

        private void Test()
        {
            CreateBlogDto createBlogDto = new CreateBlogDto()
            {
                Title = "我是title",
                Content = "我是content"
            };

            Blog newBlog = new Blog()
            {
                Title = createBlogDto.Title,
                Content = createBlogDto.Content
            };

        }
    }
}

.NET ORM 注入 审计-FreeSql中直接使用 SQL 片段的问题

image-20240131144351988

这个时候就造成了注入。(打包了,放到了目录下,需要的时候整体替换到github的那个项目里面就行了。)

审计的点:正常FreeSql肯定是不建议这么写的,如果碰到了这种的话,看一下用没用参数化,比如@id占位。

从CODE上修复的话:

参数化查询使用 .WithSql 方法,并通过参数传递值:

csharpCopy codevar blogs = _fsql.Select<Blog>()
                 .WithSql("SELECT * FROM Blog WHERE id LIKE @id", new { id = $"%{id}%" })
                 .ToList();

用Lambda表达式进行条件查询,使用ORM提供的Lambda表达式进行条件查询,因为这些查询自然是参数化的,从而减少了SQL注入的风险。例如:

csharpCopy codevar keyword = $"%{id}%";
var blogs = _fsql.Select<Blog>()
                 .Where(a => a.Id.ToString().Contains(keyword))
                 .ToList();

这种方式下,你不需要担心SQL注入,因为FreeSql内部会处理参数化。

使用FreeSql的高级功能,FreeSql还提供了更高级的查询功能,比如表达式树转换和动态LINQ,这些都内建了参数化查询的支持,从而确保了查询的安全性。

  • • 当 id 是数值类型时,直接使用 ToString() 和 Contains() 可能不适用。你需要根据实际情况调整查询逻辑。

  • • 对于复杂的查询逻辑,考虑使用FreeSql提供的高级查询功能,如动态LINQ和表达式树,这些都可以帮助你构建既灵活又安全的查询。

考虑到安全性时,应优先使用ORM的内建方法来构建查询,这样自然包含了参数化查询的实现。只有在确实需要执行原生SQL语句时,才考虑使用参数化的原生SQL查询。

原文始发于微信公众号(wulala520):.NET ORM 注入 审计-FreeSql中直接使用 SQL 片段的问题

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年2月1日21:00:09
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   .NET ORM 注入 审计-FreeSql中直接使用 SQL 片段的问题https://cn-sec.com/archives/2452387.html

发表评论

匿名网友 填写信息