0x00.前言
協會要舉辦信息安全大賽了,初賽的web+crypto+misc主要由我來出題,注冊、比賽的平台也都要由我來寫
上周日完成了注冊頁面的后端(前端由另一個女生寫的),前天下午大概完成了比賽平台的所有基本功能(前端也是由我寫的...)
獨立寫完比賽平台,有些收獲打算寫在這里,先留個坑,等比賽完了再填坑
后端:PHP
數據庫:MySQL
0x01.登錄頁面
登錄界面的前端是直接找的一個比較簡朴的框架。
后端檢驗用戶的輸入,隊伍名是只允許出現中英文、數字及下划線的,我用的preg_match()進行正則匹配
if(!preg_match('/^(?!_)[A-Za-z0-9_\x{4e00}-\x{9fa5}]+$/u',$_POST['team'])) { echo "<h2 align='center'><font color='#FF00000'>隊名只能包含中英文、數字及下划線!</h2>"; }
驗證合法后,連接MySQL,采用php里mysqli擴展的預編譯執行SQL語句(防注入),查詢隊伍是否存在
1 //數據庫連接 2 $con = new mysqli('localhost',username,password,database); 3 if ($con->connect_error) { 4 die("連接失敗: " . $con->connect_error); 5 } 6 // 預處理及綁定 7 $stmt = $con->prepare("SELECT team,pwd FROM teams WHERE team=? AND pwd=?"); 8 $stmt->bind_param("ss", $team,$pwd); 9 // 執行成功 10 if($stmt->execute()){ 11 $stmt->store_result(); //取回結果 12 if(($stmt->num_rows())==1){ 13 $_SESSION['team'] = $team; //記錄一個Session 14 header("Refresh:0;url=index.php"); //登陸成功跳轉至主頁 15 }else{ 16 echo "<h2 align='center'><font color='#FF00000'>隊名或密碼錯誤!</h1>"; 17 } 18 }
0x02.功能框架
思考:一個CTF平台應該具備些什么基礎的功能?
1.發公告的首頁
2.隊伍得分的排行榜
3.比賽做題的界面(重點)
4.注銷
以上四點是我覺得一個CTF平台應具備的最基礎的功能
另外可擴展的功能有比如:*查看隊伍信息(包括成員、做題情況等),*后台管理頁面等
由於時間較緊迫,初賽比較小型,所以就沒寫那么多,以后有時間再多擴展些功能
平台的前端也是找的一個比較清新的導航界面框架
上面的導航欄可以隨鼠標向下滑動而上移
0x03.數據庫及身份認證
數據庫存了隊伍的隊名、密碼、隊長+成員、得分、各個題是否已做的信息。由於怕自己寫的平台有漏洞,就沒有把flag放在數據庫中。
值得注意的是,得分的那一個字段需要定義為int類型,不能定義為varchar類型,否則后面按得分排名時會出錯
對隊伍的身份認證采用Session會話管理,用session記錄隊名,並且在做題頁面中,會先查詢隊伍做題情況並記入session中。已做的題就會在題旁邊顯示已做,並且不允許再重復提交flag
平台上的每個界面一開始都要檢查用戶是否已登錄
session_start(); if(!isset($_SESSION['team'])){ $login = false; }else{ $login = true; }
在每個功能頁面都包含這段代碼,檢查$login的值就行
若已登錄,導航欄是這樣的
未登錄是這樣的
0x04.排行榜
排行榜比較簡單,查詢數據庫按分數排名,循環打印出來
$sql = "SELECT team,leader,member1,member2,score FROM teams ORDER BY score DESC"; if($res = mysqli_query($con,$sql)){ $num = 1; while($row = mysqli_fetch_assoc($res)){ echo " <tr> <td class='a'>".$num."</td> <td class='b'>".$row['team']."</td> <td class='c'>".$row['leader']." ".$row['member1']." ".$row['member2']."</td> <td class='d'>".$row['score']."</td> </tr>"; $num++; } }
0x05.答題頁面
由於前端不太會..js也不太會,不知道怎么寫出ctfd那樣的效果,只好用table來裝各個題了...
效果是這樣的
因為沒寫后台,所以這些題都是直接在源代碼里添加修改
在題目旁邊會檢查隊伍是否已做出該題
if(@$_SESSION['web1']=='1'){ echo ' <font color="#32CD32">已解決√'; }
驗證flag時,我是將flag以及題目的分值放在一個配置文件里,提交flag時將其包含
檢驗flag代碼如下
if(isset($_POST['web1submit'])){ if(!empty($_POST['web1flag'])){ if($_SESSION['web1']==0){ if(@$_POST['web1flag']===$web1flag){ require("mysqlcon.php"); // 查詢隊伍當前分數 $sql = "SELECT score FROM teams WHERE team='".$_SESSION["team"]."'"; if($res = mysqli_query($con,$sql)){ while($row = mysqli_fetch_assoc($res)){ $score = $row['score']; } } // 加分 $score += $web1score; // 更新分數 $sql = "UPDATE teams SET score='".$score."' WHERE team='".$_SESSION["team"]."'"; if(mysqli_query($con,$sql)){ // 更改web1列記錄已做 $sql = "UPDATE teams SET web1=1 WHERE team='".$_SESSION["team"]."'"; if(mysqli_query($con,$sql)){ echo '<br><font color="#32CD32">正確√'; } } mysqli_close($con); }else{ echo '<br><font color="#FF00000">錯誤×'; } }else{ echo '<br><font color="#FF00000">請勿重復答題!'; } } }
0x06.細節
1.【單雙引號】
通過這次寫這個平台,才了解到php中單雙引號的使用還是有很大區別的,主要區別在於單引號會把【引號內完全當字符解析】,而雙引號會【解析引號內的簡單變量】,更厲害的是花括號{}——可以解析更復雜的變量
0x07.缺陷
缺陷就有很多了,比如,
代碼冗長,無后台管理界面,對隊伍相關信息的操作修改也不方便,出新題也不方便等等,這些也就只有慢慢優化改善這個平台了