做一个对妹纸有用的程序员

0x00 背景

  接到妹纸电话,问我会不会使用按键精灵,帮她到一个网站上刷题。
  我会!!!
  妹纸提供的方案是用按键精灵实现每个题都选C,然后提交,但在实际使用过程中出现了以下问题:
  (1)有些题并没有C选项
  (2)选择答案按钮,提交按钮和下一题按钮的位置随题干和解析的长度变换,位置不固定
  (3)该做题系统应该是部署在内网的,妹纸给的外网地址访问奇慢无比,经常掉线
  由于以上原因,我认为无法通过按键精灵的方法达到500分(回答正确一题得0.2分),所有决定采取其他的方法。

0x01 发现漏洞

  首先想到的是在点击提交按钮时抓包,是否能够直接暴力遍历提交。利用Burpsuite抓包,发现了一个惊人的事实,在我拦截了提交答案的post包的情况下,网页依然对我提交的答案进行了判断,而放行post包后的返回包中只包含题目解析,没有答题是否正确的信息。由此判断题目答案已经保存在网页中,不需要再与服务器进行交互。按F12,果然找到了所有题目的答案,如下图:


answer

  再观察提交按钮的post包,如下图:


post

  根据post包的payload信息,只要找到了答案tmAnswer与treeId、treeRoad、tmId的对应关系,就能提供正确答案遍历试题。全程抓包,在点击开始做题时,向服务器请求题目(GetPracticeList)在返回包中包含了tmAnswer、treeId、treeRoad、tmId,post包和返回包如下图所示,根据返回结果,pageSize参数为请求的题目数量,默认为50题,返回包中的TotalCount为剩余的最大题目数。


GetPracticeList


GetPracticeListRe

0x02 利用漏洞刷题

  在获取上述信息之后,就可以利用Burpsuite的Intruder功能刷分了。首先在点击按时做题时抓包,修改pageSize参数为上个返回包中的最大题目数,截取返回包,提取json(其中包含了tmAnswer、treeId、treeRoad、tmId信息),将其保存到txt文件中。利用python解析json,提取tmAnswer、treeId、treeRoad、tmId信息,分别保存在tmAnswer.txt、treeId.txt、treeRoad.txt、tmId.txt中,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
with open(filename) as f:
data = json.load(f)
print len(data)
for i in range(0, len(data)):
tmAnswer.append(data[i]['TmAnswer'])
treeId.append(data[i]['TreeId'])
treeRoad.append(data[i]['TreeRoad'])
tmId.append(data[i]['RegID'])
with open("tmAnswer.txt", 'w') as ftmAnswer:
for i in range(0, len(data)):
ftmAnswer.write(tmAnswer[i] + '\n')
with open("treeId.txt", 'w') as ftreeId:
for i in range(0, len(data)):
ftreeId.write(str(treeId[i]) + '\n')
with open("treeRoad.txt", 'w') as ftreeRoad:
for i in range(0, len(data)):
ftreeRoad.write(str(treeRoad[i]).replace(",", "%2C") + '\n')
with open("tmId.txt", 'w') as ftmId:
for i in range(0, len(data)):
ftmId.write(str(tmId[i]) + '\n')

  在测试过程中,发现返回的json中的TmAnswer有个别出现了格式错误,加入error存储错误的下标,将错误的情况剔除。修改后的代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
def dealJson(filename):
with open(filename) as f:
data = json.load(f)
print len(data)
for i in range(0, len(data)):
tmAnswer.append(data[i]['TmAnswer'])
treeId.append(data[i]['TreeId'])
treeRoad.append(data[i]['TreeRoad'])
tmId.append(data[i]['RegID'])
with open("tmAnswer.txt", 'w') as ftmAnswer:
for i in range(0, len(data)):
try:
ftmAnswer.write(tmAnswer[i] + '\n')
except:
error.append(i)
with open("treeId.txt", 'w') as ftreeId:
for i in range(0, len(data)):
if i in error:
continue
ftreeId.write(str(treeId[i]) + '\n')
with open("treeRoad.txt", 'w') as ftreeRoad:
for i in range(0, len(data)):
if i in error:
continue
ftreeRoad.write(str(treeRoad[i]).replace(",", "%2C") + '\n')
with open("tmId.txt", 'w') as ftmId:
for i in range(0, len(data)):
if i in error:
continue
ftmId.write(str(tmId[i]) + '\n')

  利用Burpsuite中的Intruder功能,选择Pitchfork模式,载入tmAnswer.txt、treeId.txt、treeRoad.txt、tmId.txt,实现遍历答题。


Pitchfork


PitchforkRet

0x03

  妹纸说分不要弄太高,不要太高调!!!