# 驗證碼繞過on server
- 驗證碼
- 功用
- 防止登錄暴力破解
- 防止機器惡意註冊
- 流程
- 客戶端request登錄頁面,後台生成驗證碼
- 生成驗證碼
- 後台使用演算法生成圖片,並將圖片response給客戶端
- 同時將算法生成的值全局賦值存到SESSION中
- 校驗驗證碼
- 客戶端將認證信息和驗證碼一同提交
- 後台對提交的驗證碼與SESSION里面的進行比較
- 客戶端重新刷新頁面,再次生成新的驗證碼
- 驗證碼算法中一般包含隨機函數,所以每次刷新都會改變
- 常見問題 (服務端認證不嚴格)
- 驗證碼在後台不過期,導致可以長期被使用
- 驗證碼校驗不嚴格,邏輯出現問題
- 驗證碼設計的太過簡單和有規律,容易被猜解
- 漏洞
- 驗證碼無時效性 沒有被銷毀
- source code分析


```php
<?php
/**
* Created by runner.han
* There is nothing new under the sun
*/
$PIKA_ROOT_DIR = "../../";
include_once $PIKA_ROOT_DIR.'inc/config.inc.php';
include_once $PIKA_ROOT_DIR.'inc/mysql.inc.php';
$SELF_PAGE = substr($_SERVER['PHP_SELF'],strrpos($_SERVER['PHP_SELF'],'/')+1);
if ($SELF_PAGE = "bf_server.php"){
$ACTIVE = array('','active open','','','active',"","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","");
}
include_once $PIKA_ROOT_DIR.'header.php';
$link=connect();
$html="";
if(isset($_POST['submit'])) {
if (empty($_POST['username'])) { //先判斷username是否為空
$html .= "<p class='notice'>用户名不能为空</p>";
} else {
if (empty($_POST['password'])) {//再判斷password是否為空
$html .= "<p class='notice'>密码不能为空</p>";
} else {
if (empty($_POST['vcode'])) {//再判斷驗證碼是否為空
$html .= "<p class='notice'>验证码不能为空哦!</p>";
} else {
// 验证验证码是否正确
if (strtolower($_POST['vcode']) != strtolower($_SESSION['vcode'])) {//驗證碼認證
$html .= "<p class='notice'>验证码输入错误哦!</p>";
//应该在验证完成后,销毁该$_SESSION['vcode'] leak!!!
}else{
$username = $_POST['username']; //再驗證username和password
$password = $_POST['password'];
$vcode = $_POST['vcode'];
$sql = "select * from users where username=? and password=md5(?)";
$line_pre = $link->prepare($sql);
$line_pre->bind_param('ss',$username,$password);
if($line_pre->execute()){
$line_pre->store_result();
//虽然前面做了为空判断,但最后,却没有验证验证码!!!
if($line_pre->num_rows()==1){
$html.='<p> login success</p>';
}else{
$html.= '<p> username or password is not exists~</p>';
}
}else{
$html.= '<p>执行错误:'.$line_pre->errno.'错误信息:'.$line_pre->error.'</p>';
}
}
}
}
}
}
?>
<div class="main-content" xmlns="http://www.w3.org/1999/html">
<div class="main-content-inner">
<div class="breadcrumbs ace-save-state" id="breadcrumbs">
<ul class="breadcrumb">
<li>
<i class="ace-icon fa fa-home home-icon"></i>
<a href="burteforce.php">暴力破解</a>
</li>
<li class="active">验证码绕过(on server)</li>
</ul><!-- /.breadcrumb -->
<a href="#" style="float:right" data-container="body" data-toggle="popover" data-placement="bottom" title="tips(再点一下关闭)"
data-content="这个验证码好像一直有效哎!用户还是那三个默认用户.">
点一下提示~
</a>
</div>
<div class="page-content">
<div class="bf_form">
<div class="bf_form_main">
<h4 class="header blue lighter bigger">
<i class="ace-icon fa fa-coffee green"></i>
Please Enter Your Information
</h4>
<form method="post" action="bf_server.php">
<!-- <fieldset>-->
<label>
<span>
<input type="text" name="username" placeholder="Username" />
<i class="ace-icon fa fa-user"></i>
</span>
</label>
</br>
<label>
<span>
<input type="password" name="password" placeholder="Password" />
<i class="ace-icon fa fa-lock"></i>
</span>
</label>
</br>
<label>
<span>
<input type="text" name="vcode" placeholder="验证码" />
<i class="ace-icon fa fa-lock"></i>
</span>
</label>
</br>
<label>
<img src="../../inc/showvcode.php" onclick="this.src='../../inc/showvcode.php?'+new Date().getTime();" />
</label>
<div class="space"></div>
<div class="clearfix">
<label><input class="submit" name="submit" type="submit" value="Login" /></label>
</div>
</form>
<?php echo $html;?>
</div><!-- /.widget-main -->
</div><!-- /.widget-body -->
</div><!-- /.page-content -->
</div>
</div><!-- /.main-content -->
<?php
include_once $PIKA_ROOT_DIR.'footer.php';
?>
```
- session要設置過期時間 此題無設置

- 驗證碼function.php


- 爆破流程
- 用burp suite抓包
- 傳至repeater進行下一步分析
- 查看source code發現驗證碼由JavaScript隨機生成,藉由點擊一次函數生成相應驗證碼

- 故使用repeater

- 先將驗證碼改成正確的再發送
- 回應 ``username or password is not exist ~``

- 嘗試改username和password 傳送
- 皆傳回``username or password is not exist ~`` ,都沒有回傳驗證碼錯誤
- 可以發現驗證碼並沒有被驗證
- ---> 發現驗證碼不過期漏洞
- 開始爆破
- send to intruder
- 將參數設定在username和password上
- Attack Type選擇Cluster Bomb
id:: 652a5cc8-b255-47ad-82e1-91993768a074
- 設定字典
- 第一個參數username

- 第二個參數password
- 使用numbers

- (optional)設定查看有無輸出``username or password is not exist ~``
- 也可直接查看長度來爆破
- 選擇 options
- Grep - Match
- 在grep-match中刪除原有字符串,添加username or password is not exists, burp就會將所有含有此字符串的數據包flag出來。沒有被flag出的數據包則是我們破解成功的數據包

- Grep - Extract
- 搜尋``username or password is not exist ~``

- 結果

- 點擊username or password is not exists進行排序,沒有勾選的則表明破解成功,有勾選的則表明破解失敗。

- [pikachu靶场通关之暴力破解](https://developer.aliyun.com/article/1044330)
- [Pikachu靶场通关秘籍---暴力破解---验证码绕过(On Server)](https://www.cnblogs.com/redHskb/p/16799610.html)]