问答
发起
提问
文章
攻防
活动
Toggle navigation
首页
(current)
问答
商城
实战攻防技术
漏洞分析与复现
NEW
活动
摸鱼办
搜索
登录
注册
某移动平台代码审计
渗透测试
该套系统是一次地市级hvv中,扫目录扫到备份文件拿到的,因为也是第一次审计.net,前期也没学过,可能也有很多解释的不对的地方望师傅们指出
审计方式是黑盒+白盒的方式 前台SQL注入1: ========= 这个注入是黑盒也能挖出来的 ![1.png](https://shs3.b.qianxin.com/attack_forum/2023/08/attach-ef1118e098ae9fe8fa0c168225efd673b49ebe77.png) 点开这里是发现没有内容可选择的,一开始还以为是系统有问题,输入用户名(用户名最多只能输入4个字符),发现burp里面出现一条数据包 ![2.png](https://shs3.b.qianxin.com/attack_forum/2023/08/attach-c45a44f128c3c3d8d85032f4145b7c4e5fe285a0.png) 这条数据包感觉是在判断该用户名是否存在,因为用户名的表单最多只能输入4个字符,所以这是决定跑一下四位数字 ![图片.png](https://shs3.b.qianxin.com/attack_forum/2023/08/attach-ca4288cbd13980a6438087f618ea2c40310c6a69.png) 跑出两个用户名,来到浏览器输入用户名 ![3.png](https://shs3.b.qianxin.com/attack_forum/2023/08/attach-a54b7298fe2820c8569f09987d66e049617497f7.png) 发现刚刚没有内容的表单此时自己有了内容,根据数据包路径(/Home/UserDepartment?username=8888)找到代码,使用Visual Studio打开,前台的代码位于Controllers\\HomeController.cs 找到UserDepartment方法 ![4.png](https://shs3.b.qianxin.com/attack_forum/2023/08/attach-eb27ccf801ee3d0ee8a2d6fb458aa0700cfe2ae7.png) 根据代码里的注释其实已经很明了了,方法是使用 HTTP GET 方法来获取用户部门信息,并返回 JSON 格式的数据。不过还调用了Account.UserDepartment(),要继续跟进去的,需要反编译dll ![5.png](https://shs3.b.qianxin.com/attack_forum/2023/08/attach-3fe4f45b48fbf2117fbffd73e304f2e0be2539a1.png) 使用Dnspy打开bin目录下对应的dll,反编译后找到UserDepartment方法 ![6.png](https://shs3.b.qianxin.com/attack_forum/2023/08/attach-288db50b5c86ab4b5157543c79a4af7d466f3834.png) 代码解释 通过 \[HttpGet\] 标记指定该方法用于处理 GET 请求。 用户部门获取:调用 Account.UserDepartment(username) 方法,传入用户名 username 作为参数,该方法返回用户的部门信息。 使用 Json 方法将部门信息以 JSON 格式返回,并指定允许 GET 请求访问该结果。 跟进Account.UserDepartment() 方法 ![7.png](https://shs3.b.qianxin.com/attack_forum/2023/08/attach-6548e2de73b55887a977a73c26ae308764f70042.png) 代码创建了一个User类的实例对象user,再调用user 类的GetUserKeShi()方法,传入username参数后返回List对象,继续跟user.GetUserKeShi()方法 ![8.png](https://shs3.b.qianxin.com/attack_forum/2023/08/attach-7d1590e95a00b93e30a7266fba22272bdf0df145.png) 代码大概意思就是 创建了一个 Msg 类的实例对象 msg,用于存储方法执行的结果和消息。构建一个 SQL 查询语句,通过连接 x\_keshi 表和 x\_yonghukeshi 表,根据 yonghuid 字段与传入的 userid 进行匹配筛选用户所属的部门信息。 创建一个 MobileDataEntityDAL 类的实例对象 mobileDataEntityDAL,用于操作数据库并将查询结果转换为 X\_keshi 对象。 使用 DBHelper.SqlHelper 方法执行 SQL 查询语句,将查询结果存储在 DataSet 对象 dataSet 中。同时,将数据库连接字符串指定为 MobileDataBaseLink.Mobile,传入 msg 对象以获取执行结果和错误消息,并使用 CommandType.Text 指定查询类型为文本。 创建一个 List 对象 list,用于存储查询结果的部门信息 可以看到值传进GetUserKeShi()方法之后,未做任何过滤就拼接到SQL语句中执行了 最开始的UserDepartment()方法通过GET方法接受到username之后也未做任何过滤,所以此处是存在SQL注入的 漏洞验证: ----- 数据库为Oracle ![9.png](https://shs3.b.qianxin.com/attack_forum/2023/08/attach-0d20132f14b58411463b3868dc653efa5e178c68.png) 成功执行延时语句 Sqlmap直接跑也是可以的 ![10.png](https://shs3.b.qianxin.com/attack_forum/2023/08/attach-85191209ce1e9a6e37b011461cd116f6c1362098.png) 前台SQL注入2: ========= 这个注入是通过审计发现的,因为上面发现GetUserKeShi()方法存在注入,此处全局搜索GetUserKeShi()方法 ![11.png](https://shs3.b.qianxin.com/attack_forum/2023/08/attach-a47f185503e99b6ca532e1d739afd26f59ffb9c4.png) 发现 Controllers\\HomeController.cs里还有一处,直接利用即可 /home/UserModules?username= ![12.png](https://shs3.b.qianxin.com/attack_forum/2023/08/attach-eb155284d0ed3a7b824721417b8a27b00c726d44.png) 逻辑漏洞: ===== 这里本来是想看看有没有绕过的漏洞,结果发现通过login()方法一直跟 ![13.png](https://shs3.b.qianxin.com/attack_forum/2023/08/attach-2becc7e46f4da3a06de5ff868b2ae8d80c97f496.png) 通过 \[HttpPost\] 标记指定该方法用于处理 POST 请求。 调用 Account.Login(username, password, department, "") 方法,传入用户名、密码、部门和空字符串作为参数进行用户登录验证。该方法返回一个 Msg 对象,用于表示登录结果。 将登录结果的 Result 属性赋值给 result 变量,用来判断用户登录是否成功。 根据登录结果的 Result 值进行不同的处理。 如果登录成功,则判断是否提供了 area 参数。如果有,则在原来的 area 值后添加斜杠,然后重定向到对应的页面(比如 "Home/Index")。 如果登录失败,则使用动态调用的方式设置 ErrorMessage 属性为登录结果的字符串描述,并返回视图。 最后,根据处理结果返回对应的 ActionResult 对象。 \-----继续跟进Account.Login()方法 ![14.png](https://shs3.b.qianxin.com/attack_forum/2023/08/attach-fcaca47d619b9462d57bb51ada8f77343d4d4f65.png) 该方法接受四个字符串类型的参数,分别是 username(用户名)、password(密码)、department(部门)和 yiyuanID(医院ID),其中 yiyuanID 参数有默认值空字符串。 首先创建一个 User 对象,并将其赋值给 user 变量。 调用 user.Login(username, password) 方法执行用户登录操作,并将返回的结果赋值给 msg 变量,msg 是一个 Msg 对象。 从 msg 对象的 Result 属性获取登录结果(布尔值),并将其赋值给 result 变量。 处理登录成功的情况: 如果登录成功,则将 msg 对象的 MsgObjectContent 属性转换为 Res\_Login 类型的对象,并将其赋值给 loginInfo 变量。 判断 department 是否为空或空字符串,如果是,则使用 loginInfo.Depid 作为默认部门。 根据部门ID查找对应的部门信息,将结果赋值给 entity 变量。 如果找不到对应的部门信息,并且 department 不为 null,则设置 msg 对象的 Result 属性为 false,添加一条提示信息,并返回 msg 对象。 如果找到了部门信息,则继续执行后续步骤。 配置医院ID:判断 yiyuanID 是否为空或空字符串,如果是,则从配置文件中获取名为 "yiyuanid" 的设置值,并将其赋值给 yiyuanID 变量。 根据登录信息和部门信息创建一个 UserInfo 对象,并设置其属性值。 使用 SessionHelper.SetInfoCache(info) 方法将用户信息缓存。 使用 SessionHelper.SetUserToolCache(info) 方法将用户工具缓存。 返回 msg 对象。 \-----继续跟进user.Login()方法 ![15.png](https://shs3.b.qianxin.com/attack_forum/2023/08/attach-be4c79b7f960d8ad603659a5a605791a56cec0c6.png) 该方法接受两个字符串类型的参数,分别是 userid(用户ID)和 password(密码)。 首先创建一个空的 Msg 对象,并将其赋值给 msg 变量。 调用 ValidateUser(userid, password) 方法对用户进行验证,并将返回的结果赋值给 msg 对象。 从 msg 对象的 Result 属性获取验证结果(布尔值),并将其赋值给 result 变量。 处理验证成功的情况: 如果验证成功,则将 msg 对象的 MsgObjectContent 属性转换为 X\_yonghu 类型的对象,并将其赋值给 yonghu 变量。 设置 msg 对象的 Result 属性为 true。 调用 InsertLoginLogin(yonghu) 方法插入登录日志,并将返回的结果赋值给 loginlog 变量。 调用 InitLoginInfo(yonghu, loginlog) 方法初始化登录信息,并将返回的结果赋值给 msg 对象的 MsgObjectContent 属性。 处理验证失败的情况: 如果验证失败,则将 msg 对象的 Result 属性设置为 false。 继续返回 msg 对象。 \-----继续跟进ValidateUser()方法 ![16.png](https://shs3.b.qianxin.com/attack_forum/2023/08/attach-f56bde25a5a0183e8b206ba9158d0a27990498bb.png) 跟到最后发现代码中直接将比较的密码值硬编码在代码中,好开发^0^ 使用前期收集到的账号可直接用该密码登陆 ![17.png](https://shs3.b.qianxin.com/attack_forum/2023/08/attach-26299ad840f56f5eef2e849cd402f3af45189676.png) 因为前期发现账号限制最长为4位,所以想收集账号即使并不难,而且也没有验证码做限制 后台文件上传\*5: ========== .net语言找上传点,可以全局搜索关键函数SaveAs() 通过搜索发现有5处 ![18.png](https://shs3.b.qianxin.com/attack_forum/2023/08/attach-8294b9f5d4a731a88050d6376ca9d362d45a83b1.png) 打开\\Areas\\BackStage\\Controllers\\ArtConfigController.cs ![19.png](https://shs3.b.qianxin.com/attack_forum/2023/08/attach-3a9450395ee160d3c711b2745d4fc6deb75181fa.png) 上传文件使用的是UploadImage()方法 ![20.png](https://shs3.b.qianxin.com/attack_forum/2023/08/attach-2d39b6950c178e2b44d83019b2299d16030fcb2e.png) 找到对应的dll进行反编译 ![21.png](https://shs3.b.qianxin.com/attack_forum/2023/08/attach-2dcef32d49779159f4de0d8c6f723a46c6300732.png) 发现代码是没有做任何过滤的 通过Directory.Exists方法检查指定的路径是否存在。如果路径不存在,则通过Directory.CreateDirectory方法创建该路径。 使用base.Request.Files.Count检查是否有文件被上传。如果有文件被上传,则获取上传的文件对象,并将其转换为Image对象。 通过ImageConvert.MakeThumbnail方法,将图像进行缩略处理。 根据用户提供的name参数判断是否为空或null,如果为空,则生成一个唯一的文件名,以GUID和原始文件的扩展名组合而成;如果不为空,则直接使用用户提供的文件名作为保存的文件名。 使用img.Save方法将处理后的图像保存到指定的路径下,路径由Path.Combine方法组合而成。 最后,通过Json方法将保存的文件名以JSON格式返回,并指定允许GET请求访问该结果。 漏洞利用: ----- 根据文件路径,找到对应页面 ![22.png](https://shs3.b.qianxin.com/attack_forum/2023/08/attach-c998ae54c2110380e62a27b935b06283bcd48e72.png) 因为存在该漏洞的代码文件并不是编辑器目录下,所以选择下面上传功能 ![23.png](https://shs3.b.qianxin.com/attack_forum/2023/08/attach-ee70e277dcb5b7692f97014fdbcfa48e0992e72c.png) 看路径可以确定是我们刚刚打开的文件\\Areas\\BackStage\\Controllers\\ArtConfigController.cs里面UploadImage()方法 直接上传即可 ![24.png](https://shs3.b.qianxin.com/attack_forum/2023/08/attach-f58fa018bf807022a9594a5c7c2a2d72c45edab7.png) 经过测试还有其余四个点均可直接上传 巴拉巴拉 ==== 感觉这套源码其实是挺老的,感觉应该还是有其它漏洞,但是水平有限,只能找到这些漏洞,虽然上传点都在后台,不过配合前台的注入和逻辑漏洞组合拳,杀伤力应该还是有的。
发表于 2023-08-30 09:00:02
阅读 ( 5535 )
分类:
代码审计
13 推荐
收藏
1 条评论
嗨嗨害
2023-08-30 11:04
写的很清晰,通俗易懂good!
请先
登录
后评论
请先
登录
后评论
T4nGgggggggggggggggggggggggggggggggg
3 篇文章
×
发送私信
请先
登录
后发送私信
×
举报此文章
垃圾广告信息:
广告、推广、测试等内容
违规内容:
色情、暴力、血腥、敏感信息等内容
不友善内容:
人身攻击、挑衅辱骂、恶意行为
其他原因:
请补充说明
举报原因:
×
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!