鍵盤上的"整蠱專家",如何防止簡訊轟炸機
"簡訊轟炸機",是別人通過爬蟲或者其他抓取手段在網路上收集那些公司平臺簡訊業務介面的一個整合程式,可能只需要輸入一個手機號,對方一整天都會收到各大平臺的註冊或提醒簡訊,就是手機在那裡響個不停。因為現在手機只能對單方的多條簡訊進行遮蔽,而這種是多平臺同時進行傳送,很難攔截。
而被他們收集介面的乙方公司,可能一天簡訊的消耗量就比過一週的量,造成公司財產損失。其實相比以前我們遇到的被刷“提現”介面可以直接獲取金錢,刷簡訊介面的行為,開始我很是想不通,就單純為了消耗別人公司的簡訊費,他也得不到什麼好處,為什麼要這樣做。當時也沒想對方是出於什麼理由,只是先把簡訊介面重新整改,防止的手法在下面介紹。
這種行為我也是最近才瞭解,原來網上也存在像周星馳電影"整蠱專家"的人,收取別人的錢開展對自己客戶提供的人進行騷擾等業務,而簡訊就是其中一種,網上還有通過輸入手機號,對方手機一天全部是陌生人來電的“呼死你”軟體,心理承受力差的可能就抑鬱,好點的話至少一天的心情都不好。
我們公司現在簡訊的用處主要還是註冊/登陸驗證碼,找回密碼,綁銀行卡,修改支付密碼,所以一天的量並不大。但那一天充了錢,不出幾分鐘,直接刷到沒有,還好發現的早,解決的也早。
解決方法,在PC端可以在發簡訊驗證碼時,加上圖形驗證碼校驗,最好是要能和使用者互動的,比如拖動或算術的,因為如果是靜態的圖形驗證也不是很安全,畢竟現在的圖片識別介面也很多。而在移動端,加圖形驗證體驗不是很好,可以和前端通過約定金鑰實現,而在H5上,就很尷尬了,而且還遇到一個只有必須繞彎路的事情。
一,APP端
1.IP和手機號黑名單(ip的例子)
<?php
$Ip = $request->ip();
$Iplist = ['180.137.97.10'];
if (in_array($Ip, $Iplist)) {
return $this->sendError(1, '業務限流', 200);
}
2.限制指定的user_agent
<?php
$string = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:27.0) Gecko/20100101 Firefox/27.0";
if ($Agent == $string) {
return $this->sendError(1, '業務限流', 200);
}
3.限制多久後才能發
(1).獲取指定鍵的一個快取是否存在,存在則返回
$is_msgtime = cache($mobile.'_msgtimes');
if (!empty($is_mesgtime)) {
return $this->sendError(1, '60秒後才能繼續發', 200);
}
(2).在簡訊傳送成功時,存下該鍵名,並快取60秒(按需求指定時間)
cache($mobile.'_msgtimes', 1, 60);
4.限制單號單日傳送的個數限制
(1)獲取快取指定鍵名的值為多少(number),並與最大限制比較
$Daytimes = intval(cache($mobile.'_daytimes')) ? intval(cache($mobile.'_daytimes')) : 0;
if(Daytimes>3) {
return ^^^^^^^^^
}
(2)簡訊傳送成功記錄並累加該號該日傳送量
if ($Daytimes > 0) {
$nextday = strtotime("today") + 24 * 60 * 60;
$expires = $nextday - time();
Cache::set($mobile.'_daytimes', $Daytimes + 1, $expires);
} else {
$nextday = strtotime("today") + 24 * 60 * 60;
$expires = $nextday - time();
Cache::set($mobile.'_daytimes', 1, $expires);
}
以上部分是沒用,因為ip和手機號,user_agent都可以通過特殊手段偽造,並且上面只是對單號碼進行攔截,所以問題就是別人通過很多號碼對介面請求,這樣一樣的可以刷。
5.介面新增複雜性,增加簽名請求等方式
(1).請求介面時,除了手機號引數,還需帶上簽名(一個不可逆加密方式處理的字串,前後端約定一個key),和時間戳.
(2).後端根據約定的key和手機號也做相應的加密與傳過來的簽名匹配,並和時間戳和當前伺服器時間做比較,時間戳最好也作為簽名加密,加密方式多種,不管是DES,RSA還是MD5看個人。
$timestamp = input('get.timestamp') ? input('get.timestamp') : 0; // 時間戳
$sign = input('get.app_sign') ? input('get.app_sign') : ''; // 請求籤名
$terminal = input('get.term') ? input('get.term') : ''; // 終端標識 1.app 2.web
$veryify_code = mt_rand(100000, 999999); // 6位數的驗證碼
$priKey = "paobuqianjinzhf..20181029"; // 加密祕鑰
// 判斷終端
if(!empty($terminal) && ($terminal == 'app')) {
$signAuth = md5($priKey.$mobile.$timestamp);
if($timestamp > time()+10 || $timestamp<time()-60*10) {
return $this->sendError(1, '請求已過期', 200);
}
if($sign != $signAuth) {
return $this->sendError(1, '簽名匹配失敗', 200);
}
短語簡訊傳送,最好用一張表記錄一下,不管成功與否,以後查起來也方便,到底這介面發了哪些號碼,什麼時候發的等等
二,H5端
在h5上,上面的通過key撒鹽的方式傳參就行不通了,因為網頁可以檢視程式碼,如果把key放在前端傳上來,可以看的很清楚。但是可以在後端生成一個串分配到網頁請求的時候傳上來就可以啊,就想表單令牌一樣。但是我們這個H5是純靜態,沒有後臺程式,介面都只是跨域ajax請求。所以分配字串到頁面行不通,通過介面請求籤名也行不通,因為別人抓到了這些介面,還是一樣的可以通過一樣的方式實現一遍。無奈只能通過圖形驗證碼。
<?php
/**
* Created by PhpStorm.
* User: Administrator
* Date: 2018/10/29 0029
* Time: 16:15
*/
namespace Admin\Controller;
use Think\Controller;
use Think\Verify; // 驗證碼類
use Admin\Model;
class RegisterController extends Controller // 控制器:使用者登入
{
// 登陸控制器的入口函式
public function index()
{
$this->redirect('Admin/Register/userRegister');
}
// 使用者註冊介面
public function userRegister()
{
// $parm=I('get.');
$ajax = new AjaxController();
$this->assign('loginurl', $ajax->getAjaxUrl('ajaxuserloginexe'));
$token=md5('paobuqianjinzhf..20181029'.time());
$this->assign('token',$token);
$this->display('user_register');
}
// 生成登陸驗證碼
public function verfyCode() {
$config = array(
'fontSize' => 50, // 驗證碼字型大小
'length' => 4, // 驗證碼位數
//'useNoise' => false, // 關閉驗證碼雜點
);
$Verify = new \Think\Verify($config);
$Verify->entry();
}
// 檢測驗證碼
public function checkVerifyCode() {
$code = I('code');
$mobile = I('mobile');
$term = 'app';
$timestamp =time();
$prikey='paobuqianjinzhf..20181029';
$app_sign = md5($prikey.$mobile.$timestamp);
if (empty($mobile)){
$result_data['state'] = 0;
$result_data['string'] = '手機號必填寫';
returnjsontojs($result_data);
}
if(!check_verify($code,false)) {
$result_data['state'] = 0;
$result_data['string'] = '驗證碼不正確';
returnjsontojs($result_data);
}
$Agent = $_SERVER['HTTP_USER_AGENT'];
// $url ="http://www.api.com/v1/ThirdParty/sendMsg?mobile=".$mobile.'&term='.$term.'&app_sign='.$app_sign.'×tamp='.$timestamp;
$url ="https://api.runmoneyin.com/v1/ThirdParty/sendMsg?mobile=".$mobile.'&term='.$term.'&app_sign='.$app_sign.'×tamp='.$timestamp;
// $url ="https://api.runmoneyin.com/v1/ThirdParty/sendMsg?mobile=".$mobile;
$curl = curl_init();
//設定抓取的url
curl_setopt($curl, CURLOPT_URL, $url);
//設定標頭檔案的資訊作為資料流輸出
curl_setopt($curl, CURLOPT_HEADER, 1);
//設定獲取的資訊以檔案流的形式返回,而不是直接輸出。
//
curl_setopt($curl,CURLOPT_USERAGENT,$Agent);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
//執行命令
$data = curl_exec($curl);
$body='';
$result_data['state'] = false;
if (curl_getinfo($curl, CURLINFO_HTTP_CODE) == '200') {
$headerSize = curl_getinfo($curl, CURLINFO_HEADER_SIZE);
$header = substr($data, 0, $headerSize);
$body = json_decode(substr($data, $headerSize),true);
}
//關閉URL請求
curl_close($curl);
if ($body['error']==0){
$result_data['state'] = true;
}
$result_data['string']=$body['message'];
returnjsontojs($result_data);
}
}
以上我是在另一個系統下放了那個H5頁面,因為靜態頁面也無法做圖形驗證碼,獲取驗證碼時先判斷圖形驗證碼是否正確,正確再通過CURL請求真正的簡訊介面,跟APP一樣的請求方式傳參。
但是這個進行到後面卻發現,我們那個H5頁面的地址已經做了固定域名二維碼並列印了上萬張,現在把H5的地址換掉的話,也就是域名變了,也就意味著那些列印的二維碼全都沒用了,於是想到一個辦法: 在原來靜態H5的地址,加上一個訪問a.html會預設訪問a.php,然後在a.php做一個跳轉,跳轉到我們修改圖形驗證碼的域名就可以了,這樣還是訪問原來的地址,但是會重定向到新系統的地址。因為我們只是對a.html起效,其他同目錄的b.html不做處理,如果是在伺服器上做重定向,整個域名下的都會被重定向,
1.在a.html目錄下新建a.php,並新建一個.htaccess檔案
2.對a.html的伺服器能支援支援.htaccess
開啟apache安裝目錄下的httpd.conf檔案,把
AllowOverride None 改為AllowOverride All ,如圖
去掉下面的註釋 #
LoadModule rewrite_module modules/mod_rewrite.so,如圖
3.htaccess檔案修改為
<IFMODULE mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule (.*)\a.html$ $1\a.php [QSA,PT,L]
</IFMODULE>
個人公眾號:ZERO開發