Нема описа
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149
  1. <?php
  2. /**
  3. * 易优CMS
  4. * ============================================================================
  5. * 版权所有 2016-2028 海口快推科技有限公司,并保留所有权利。
  6. * 网站地址: http://www.eyoucms.com
  7. * ----------------------------------------------------------------------------
  8. * 如果商业用途务必到官方购买正版授权, 以免引起不必要的法律纠纷.
  9. * ============================================================================
  10. * Author: 小虎哥 <1105415366@qq.com>
  11. * Date: 2018-4-3
  12. */
  13. namespace app\admin\controller;
  14. use think\Db;
  15. class Security extends Base
  16. {
  17. public $admin_info = array();
  18. /**
  19. * 初始化操作
  20. */
  21. public function _initialize() {
  22. parent::_initialize();
  23. $this->admin_info = session('admin_info');
  24. }
  25. public function index()
  26. {
  27. // if (IS_POST) {
  28. // $this->handleSave();
  29. // }
  30. $is_founder = 0;
  31. if (-1 == $this->admin_info['role_id'] && empty($this->admin_info['parent_id'])) {
  32. $is_founder = 1;
  33. }
  34. $this->admin_info['is_founder'] = $is_founder;
  35. $this->assign('admin_info', $this->admin_info);
  36. //自定义后台路径名
  37. $baseFile = explode('/', $this->request->baseFile());
  38. $web_adminbasefile = end($baseFile);
  39. $adminbasefile = preg_replace('/^(.*)\.([^\.]+)$/i', '$1', $web_adminbasefile);
  40. $this->assign('adminbasefile', $adminbasefile);
  41. // 安全验证配置
  42. $security = tpSetting('security');
  43. if (isset($security['security_verifyfunc'])) {
  44. $security['security_verifyfunc'] = json_decode($security['security_verifyfunc'], true);
  45. }
  46. $security_askanswer_content = '';
  47. if (!empty($security['security_askanswer_list'])) {
  48. $security_askanswer_list = json_decode($security['security_askanswer_list'], true);
  49. $security['security_askanswer_list'] = $security_askanswer_list;
  50. }
  51. if (empty($security_askanswer_list)) {
  52. $security_askanswer_list = config('global.security_askanswer_list');
  53. }
  54. $security_askanswer_content = implode(PHP_EOL, $security_askanswer_list);
  55. $this->assign('security', $security);
  56. $this->assign('security_askanswer_content', $security_askanswer_content);
  57. if (!empty($security['security_ask'])) {
  58. $security_ask = $security['security_ask'];
  59. if (!in_array($security_ask, $security_askanswer_list)) {
  60. $security_askanswer_list[] = $security_ask;
  61. }
  62. }
  63. $this->assign('security_askanswer_list', $security_askanswer_list);
  64. return $this->fetch();
  65. }
  66. /**
  67. * 保存 - 全部(v1.6.2以下版本作废)
  68. * @return [type] [description]
  69. */
  70. // private function handleSave()
  71. // {
  72. // // if (!empty($this->admin_info['parent_id']) || -1 != $this->admin_info['role_id']) {
  73. // // $this->error('该功能仅限于创始人操作!');
  74. // // }
  75. // $post = input('post.');
  76. // $settingData = [];
  77. // /*-------------------后台安全配置 start-------------------*/
  78. // $param = [
  79. // 'web_login_expiretime' => $post['web_login_expiretime'],
  80. // 'login_expiretime_old' => $post['login_expiretime_old'],
  81. // 'web_login_lockopen' => !empty($post['web_login_lockopen']) ? 1 : 0,
  82. // 'web_sqldatapath' => $post['web_sqldatapath'],
  83. // ];
  84. // // 开启锁定才修改相应的配置值
  85. // if (!empty($param['web_login_lockopen'])) {
  86. // $param['web_login_errtotal'] = $post['web_login_errtotal'];
  87. // $param['web_login_errexpire'] = $post['web_login_errexpire'];
  88. // }
  89. // // 自定义后台路径名
  90. // $adminbasefile = preg_replace('/([^\w\_\-])/i', '', trim($post['adminbasefile'])).'.php'; // 新的文件名
  91. // $param['web_adminbasefile'] = $this->root_dir.'/'.$adminbasefile; // 支持子目录
  92. // $adminbasefile_old = preg_replace('/^(.*)\/([^\/]+)$/i', '${2}', tpCache('web.web_adminbasefile')); // 旧的文件名
  93. // if ('index.php' == $adminbasefile) {
  94. // $this->error("后台路径禁止使用index", null, '', 1);
  95. // }
  96. // // 数据库备份目录
  97. // $web_sqldatapath_old = tpCache('global.web_sqldatapath');
  98. // $param['web_sqldatapath'] = '/'.trim($param['web_sqldatapath'], '/');
  99. // // 后台登录超时
  100. // $web_login_expiretime = $param['web_login_expiretime'];
  101. // $login_expiretime_old = $param['login_expiretime_old'];
  102. // unset($param['login_expiretime_old']);
  103. // if ($login_expiretime_old != $web_login_expiretime) {
  104. // $web_login_expiretime = preg_replace('/^(\d{0,})(.*)$/i', '${1}', $web_login_expiretime);
  105. // empty($web_login_expiretime) && $web_login_expiretime = config('login_expire');
  106. // if ($web_login_expiretime > 2592000) {
  107. // $web_login_expiretime = 2592000; // 最多一个月
  108. // }
  109. // $param['web_login_expiretime'] = $web_login_expiretime;
  110. // //前台登录超时时间
  111. // $users_login_expiretime = getUsersConfigData('users.users_login_expiretime');
  112. // //前台和后台谁设置的时间大就用谁的做session过期时间
  113. // $max_login_expiretime = $web_login_expiretime;
  114. // if ($web_login_expiretime < $users_login_expiretime){
  115. // $max_login_expiretime = $users_login_expiretime;
  116. // }
  117. // }
  118. // // 编辑器防注入
  119. // $param['web_xss_filter'] = intval($post['web_xss_filter']);
  120. // /*-------------------后台安全配置 end-------------------*/
  121. // /*-------------------二次安全验证 start-------------------*/
  122. // $this->handleAskData($settingData, $post);
  123. // /*-------------------二次安全验证 end-------------------*/
  124. // /*多语言*/
  125. // if (is_language()) {
  126. // $langRow = \think\Db::name('language')->order('id asc')
  127. // ->cache(true, EYOUCMS_CACHE_TIME, 'language')
  128. // ->select();
  129. // foreach ($langRow as $key => $val) {
  130. // tpCache('web', $param, $val['mark']);
  131. // tpSetting('security', $settingData, $val['mark']);
  132. // }
  133. // } else {
  134. // tpCache('web', $param);
  135. // tpSetting('security', $settingData);
  136. // }
  137. // /*--end*/
  138. // $refresh = false;
  139. // /*-------------------后台安全配置 start-------------------*/
  140. // // 更改session会员设置 - session有效期(后台登录超时)
  141. // if ($login_expiretime_old != $web_login_expiretime) {
  142. // $session_conf = [];
  143. // $session_file = APP_PATH.'admin/conf/session_conf.php';
  144. // if (file_exists($session_file)) {
  145. // require_once($session_file);
  146. // $session_conf_tmp = EY_SESSION_CONF;
  147. // if (!empty($session_conf_tmp)) {
  148. // $session_conf_tmp = json_decode($session_conf_tmp, true);
  149. // if (!empty($session_conf_tmp) && is_array($session_conf_tmp)) {
  150. // $session_conf = $session_conf_tmp;
  151. // }
  152. // }
  153. // }
  154. // $session_conf['expire'] = $max_login_expiretime;
  155. // $str_session_conf = '<?php'.PHP_EOL.'$session_1600593464 = json_encode('.var_export($session_conf,true).');'.PHP_EOL.'define(\'EY_SESSION_CONF\', $session_1600593464);';
  156. // @file_put_contents(APP_PATH . 'admin/conf/session_conf.php', $str_session_conf);
  157. // }
  158. // // 更改自定义后台路径名 - 刷新整个后台
  159. // $gourl = request()->domain().$this->root_dir.'/'.$adminbasefile; // 支持子目录
  160. // if ($adminbasefile_old != $adminbasefile && eyPreventShell($adminbasefile_old)) {
  161. // if (file_exists($adminbasefile_old)) {
  162. // if(rename($adminbasefile_old, $adminbasefile)) {
  163. // $refresh = true;
  164. // }
  165. // } else {
  166. // $this->error("根目录{$adminbasefile_old}文件不存在!", null, '', 2);
  167. // }
  168. // }
  169. // if ($web_sqldatapath_old != $param['web_sqldatapath'] && preg_match('/^\/data\/sqldata([^\/]*)$/i', $param['web_sqldatapath'])) {
  170. // @rename(ROOT_PATH.ltrim($web_sqldatapath_old, '/'), ROOT_PATH.ltrim($param['web_sqldatapath'], '/'));
  171. // }
  172. // /*-------------------后台安全配置 end-------------------*/
  173. // if ($refresh) {
  174. // $this->success('操作成功', $gourl, '', 1, [], '_parent');
  175. // }
  176. // $this->success('操作成功', url('Security/index'));
  177. // }
  178. /**
  179. * 保存 - 后台安全中心
  180. * @return [type] [description]
  181. */
  182. public function handleSave1()
  183. {
  184. if (IS_POST) {
  185. $post = input('post.');
  186. $settingData = [];
  187. /*-------------------后台安全配置 start-------------------*/
  188. $param = [
  189. 'web_login_expiretime' => $post['web_login_expiretime'],
  190. 'login_expiretime_old' => $post['login_expiretime_old'],
  191. 'web_login_lockopen' => !empty($post['web_login_lockopen']) ? 1 : 0,
  192. 'web_sqldatapath' => $post['web_sqldatapath'],
  193. ];
  194. // 开启锁定才修改相应的配置值
  195. if (!empty($param['web_login_lockopen'])) {
  196. $param['web_login_errtotal'] = $post['web_login_errtotal'];
  197. $param['web_login_errexpire'] = $post['web_login_errexpire'];
  198. }
  199. // 自定义后台路径名
  200. $adminbasefile = preg_replace('/([^\w\_\-])/i', '', trim($post['adminbasefile'])).'.php'; // 新的文件名
  201. $param['web_adminbasefile'] = $this->root_dir.'/'.$adminbasefile; // 支持子目录
  202. $baseFile = explode('/', $this->request->baseFile());
  203. $adminbasefile_old = end($baseFile); // 旧的文件名
  204. if ('index.php' == $adminbasefile) {
  205. $this->error("后台路径禁止使用index", null, '', 1);
  206. }
  207. // 数据库备份目录
  208. $web_sqldatapath_old = tpCache('global.web_sqldatapath');
  209. $param['web_sqldatapath'] = '/'.trim($param['web_sqldatapath'], '/');
  210. // 后台登录超时
  211. $web_login_expiretime = $param['web_login_expiretime'];
  212. $login_expiretime_old = $param['login_expiretime_old'];
  213. unset($param['login_expiretime_old']);
  214. if ($login_expiretime_old != $web_login_expiretime) {
  215. $web_login_expiretime = preg_replace('/^(\d{0,})(.*)$/i', '${1}', $web_login_expiretime);
  216. empty($web_login_expiretime) && $web_login_expiretime = config('login_expire');
  217. if ($web_login_expiretime > 2592000) {
  218. $web_login_expiretime = 2592000; // 最多一个月
  219. }
  220. $param['web_login_expiretime'] = $web_login_expiretime;
  221. //前台登录超时时间
  222. $users_login_expiretime = getUsersConfigData('users.users_login_expiretime');
  223. //前台和后台谁设置的时间大就用谁的做session过期时间
  224. $max_login_expiretime = $web_login_expiretime;
  225. if ($web_login_expiretime < $users_login_expiretime){
  226. $max_login_expiretime = $users_login_expiretime;
  227. }
  228. }
  229. // 编辑器防注入
  230. $param['web_xss_filter'] = intval($post['web_xss_filter']);
  231. // 网站防止被刷
  232. $param['web_anti_brushing'] = intval($post['web_anti_brushing']);
  233. /*-------------------后台安全配置 end-------------------*/
  234. /*多语言*/
  235. if (is_language()) {
  236. $langRow = \think\Db::name('language')->order('id asc')
  237. ->cache(true, EYOUCMS_CACHE_TIME, 'language')
  238. ->select();
  239. foreach ($langRow as $key => $val) {
  240. tpCache('web', $param, $val['mark']);
  241. }
  242. } else {
  243. tpCache('web', $param);
  244. }
  245. /*--end*/
  246. $refresh = false;
  247. /*-------------------后台安全配置 start-------------------*/
  248. // 更改session会员设置 - session有效期(后台登录超时)
  249. if ($login_expiretime_old != $web_login_expiretime) {
  250. $session_conf = [];
  251. $session_file = APP_PATH.'admin/conf/session_conf.php';
  252. if (file_exists($session_file)) {
  253. require_once($session_file);
  254. $session_conf_tmp = EY_SESSION_CONF;
  255. if (!empty($session_conf_tmp)) {
  256. $session_conf_tmp = json_decode($session_conf_tmp, true);
  257. if (!empty($session_conf_tmp) && is_array($session_conf_tmp)) {
  258. $session_conf = $session_conf_tmp;
  259. }
  260. }
  261. }
  262. $session_conf['expire'] = $max_login_expiretime;
  263. $str_session_conf = '<?php'.PHP_EOL.'$session_1600593464 = json_encode('.var_export($session_conf,true).');'.PHP_EOL.'define(\'EY_SESSION_CONF\', $session_1600593464);';
  264. @file_put_contents(APP_PATH . 'admin/conf/session_conf.php', $str_session_conf);
  265. }
  266. // 更改自定义后台路径名 - 刷新整个后台
  267. $gourl = request()->domain().$this->root_dir.'/'.$adminbasefile; // 支持子目录
  268. if ($adminbasefile_old != $adminbasefile && eyPreventShell($adminbasefile_old)) {
  269. if (file_exists($adminbasefile_old)) {
  270. if(rename($adminbasefile_old, $adminbasefile)) {
  271. $refresh = true;
  272. }
  273. } else {
  274. $this->error("根目录{$adminbasefile_old}文件不存在!", null, '', 2);
  275. }
  276. }
  277. if ($web_sqldatapath_old != $param['web_sqldatapath'] && preg_match('/^\/data\/sqldata([^\/]*)$/i', $param['web_sqldatapath'])) {
  278. @rename(ROOT_PATH.ltrim($web_sqldatapath_old, '/'), ROOT_PATH.ltrim($param['web_sqldatapath'], '/'));
  279. }
  280. /*-------------------后台安全配置 end-------------------*/
  281. if ($refresh) {
  282. $this->success('操作成功', $gourl, '', 1, [], '_parent');
  283. }
  284. $this->success('操作成功', url('Security/index'));
  285. }
  286. $this->error('操作失败');
  287. }
  288. /**
  289. * 保存 - 安全验证中心
  290. * @return [type] [description]
  291. */
  292. public function handleSave2()
  293. {
  294. if (IS_POST) {
  295. $settingData = [];
  296. $post = input('post.');
  297. if (empty($post['security_ask_open'])) {
  298. $securityOld = tpSetting('security');
  299. if (!empty($securityOld['security_ask'])) {
  300. $answer = empty($post['security_answer_old']) ? '' : trim($post['security_answer_old']);
  301. if (empty($answer)) {
  302. $this->error('请录入密保答案!');
  303. } else {
  304. $security_answer = empty($securityOld['security_answer']) ? '' : trim($securityOld['security_answer']);
  305. $encrypt_answer = func_encrypt($answer, true, pwd_encry_type('bcrypt'));
  306. if ($security_answer != $encrypt_answer) {
  307. $this->error('密保答案不正确!');
  308. }
  309. }
  310. $this->submit_answer_verify();
  311. }
  312. }
  313. /*-------------------二次安全验证 start-------------------*/
  314. $this->handleAskData($settingData, $post);
  315. /*-------------------二次安全验证 end-------------------*/
  316. /*多语言*/
  317. if (is_language()) {
  318. $langRow = \think\Db::name('language')->order('id asc')
  319. ->cache(true, EYOUCMS_CACHE_TIME, 'language')
  320. ->select();
  321. foreach ($langRow as $key => $val) {
  322. tpSetting('security', $settingData, $val['mark']);
  323. }
  324. } else {
  325. tpSetting('security', $settingData);
  326. }
  327. /*--end*/
  328. // 设置问题答案后,自动验证通过
  329. $this->submit_answer_verify();
  330. $msg = "操作成功";
  331. $is_show_answer = 0;
  332. if (!empty($settingData['security_answer']) && !empty($settingData['security_ask_open'])) {
  333. $is_show_answer = 1;
  334. $securityData = tpSetting('security');
  335. $msg = "问题:{$securityData['security_ask']}<br/>答案:".mchStrCode($securityData['security_answer_bright'], 'DECODE');
  336. }
  337. $this->success($msg, url('Security/index'), ['is_show_answer'=>$is_show_answer,'security_ask_open'=>$settingData['security_ask_open']]);
  338. }
  339. $this->error('操作失败');
  340. }
  341. /**
  342. * 保存二次安全验证的数据处理
  343. * @param array &$settingData [description]
  344. * @param array &$post [description]
  345. * @return [type] [description]
  346. */
  347. private function handleAskData(&$settingData = [], &$post = [])
  348. {
  349. $securityOld = tpSetting('security');
  350. $security_ask = intval($post['security_ask']);
  351. $security_answer = trim($post['security_answer']);
  352. $is_ask_add_edit = empty($securityOld['security_ask']) ? 'add' : 'edit';
  353. if ('add' == $is_ask_add_edit) {
  354. if (empty($post['security_ask_open'])) {
  355. $this->success('操作成功', url('Security/index'), ['is_show_answer'=>0,'security_ask_open'=>0]);
  356. }
  357. if (0 > intval($security_ask)) {
  358. $this->error('请选择密保问题!');
  359. } else if ($security_answer === '') {
  360. $this->error('请设置密保答案!');
  361. }
  362. $encrypt_answer = func_encrypt($security_answer, true, pwd_encry_type('bcrypt'));
  363. $row = Db::name('admin')->where([
  364. 'admin_id' => $this->admin_info['admin_id'],
  365. 'password' => $encrypt_answer,
  366. ])->count();
  367. if (!empty($row)) {
  368. $this->error('密保答案不能与登录密码一致!');
  369. }
  370. } else {
  371. $security_answer_old = trim($post['security_answer_old']);
  372. if ($security_answer !== '' || 0 <= intval($security_ask)) {
  373. if ($security_answer_old === '') {
  374. $this->error('密保答案不能为空!');
  375. } else {
  376. if (0 <= intval($security_ask)) {
  377. if ($security_answer === '') {
  378. $this->error('请重置密保答案!');
  379. } else if ($security_answer === $security_answer_old) {
  380. $this->error('重置密保答案不能与原来的一致!');
  381. }
  382. }
  383. }
  384. $encrypt_answer_old = func_encrypt($security_answer_old, true, pwd_encry_type('bcrypt'));
  385. if ($encrypt_answer_old != $securityOld['security_answer']) {
  386. $this->error('密保答案不正确!');
  387. }
  388. $encrypt_answer = func_encrypt($security_answer, true, pwd_encry_type('bcrypt'));
  389. $row = Db::name('admin')->where([
  390. 'admin_id' => $this->admin_info['admin_id'],
  391. 'password' => $encrypt_answer,
  392. ])->count();
  393. if (!empty($row)) {
  394. $this->error('重置密保答案不能与登录密码一致!');
  395. }
  396. } else {
  397. if ($security_answer_old !== '') {
  398. $encrypt_answer_old = func_encrypt($security_answer_old, true, pwd_encry_type('bcrypt'));
  399. if ($encrypt_answer_old != $securityOld['security_answer']) {
  400. $this->error('密保答案不正确!');
  401. }
  402. }
  403. unset($post['security_ask']);
  404. unset($post['security_answer']);
  405. unset($post['security_answer_old']);
  406. }
  407. }
  408. /**
  409. * 如果要关闭二次安全验证,必须要进行答案验证
  410. * 同IP不验证功能也会影响到这里的逻辑
  411. */
  412. // 问题列表
  413. $security_askanswer_list = empty($securityOld['security_askanswer_list']) ? config('global.security_askanswer_list') : json_decode($securityOld['security_askanswer_list'], true);
  414. // 当前管理员二次安全验证过的IP地址
  415. $security_answerverify_ip = !empty($securityOld['security_answerverify_ip']) ? $securityOld['security_answerverify_ip'] : '-1';
  416. // 1、问答要已设置;2、目前是开启;3、当前要关闭;
  417. if (!empty($securityOld['security_ask_open']) && empty($post['security_ask_open']) && !empty($securityOld['security_ask'])) {
  418. $admin_info = Db::name('admin')->field('*')->where(['admin_id'=>$this->admin_info['admin_id']])->find();
  419. // if (!empty($admin_info['parent_id']) || -1 != $admin_info['role_id']) {
  420. // $this->error('创始人才能关闭安全验证功能!');
  421. // }
  422. if ($admin_info['last_ip'] != $security_answerverify_ip) {
  423. $this->error("<span style='display:none;'>__html__</span>出于安全考虑<br/>请勿非法越过密保答案验证", null, '', 3);
  424. }
  425. }
  426. $settingData['security_ask_open'] = intval($post['security_ask_open']);
  427. if (!empty($settingData['security_ask_open'])) {
  428. $post['security_verifyfunc'][] = 'Filemanager@*';
  429. $post['security_verifyfunc'][] = 'Arctype@ajax_newtpl';
  430. $post['security_verifyfunc'][] = 'Archives@ajax_newtpl';
  431. // $post['security_verifyfunc'][] = 'Security@*';
  432. $post['security_verifyfunc'] = array_unique($post['security_verifyfunc']);
  433. $settingData['security_verifyfunc'] = json_encode($post['security_verifyfunc']);
  434. $settingData['security_ask_ip_open'] = !empty($post['security_ask_ip_open']) ? intval($post['security_ask_ip_open']) : 0;
  435. if (isset($post['security_ask'])) {
  436. $settingData['security_ask'] = $security_askanswer_list[$post['security_ask']];
  437. }
  438. if (isset($post['security_answer'])) {
  439. $settingData['security_answer'] = func_encrypt($post['security_answer'], true, pwd_encry_type('bcrypt'));
  440. $settingData['security_answer_bright'] = mchStrCode($post['security_answer']);
  441. }
  442. if (empty($securityOld['security_askanswer_list'])) {
  443. $settingData['security_askanswer_list'] = json_encode($security_askanswer_list);
  444. }
  445. }
  446. }
  447. /*--------------------------------安全验证中心 start--------------------------*/
  448. /**
  449. * 设置二次安全验证的问题、答案
  450. */
  451. public function second_verify_add()
  452. {
  453. $security_askanswer_list = tpSetting('security.security_askanswer_list');
  454. $security_askanswer_list = json_decode($security_askanswer_list, true);
  455. if (empty($security_askanswer_list)) {
  456. $security_askanswer_list = config('global.security_askanswer_list');
  457. }
  458. if (IS_POST) {
  459. // 修补越权的漏洞,在重设答案时,通过抓包改成新设答案
  460. if (!empty($this->globalConfig['security_ask'])) {
  461. $this->error('已设置过密保,请重新设置');
  462. }
  463. $ask = input('post.ask/d');
  464. $answer = input('post.answer/s');
  465. $answer = trim($answer);
  466. if (0 > $ask) {
  467. $this->error('请选择密保问题!');
  468. } else if (empty($answer)) {
  469. $this->error('密保答案不能为空!');
  470. }
  471. $encrypt_answer = func_encrypt($answer, true, pwd_encry_type('bcrypt'));
  472. $row = Db::name('admin')->where([
  473. 'admin_id' => $this->admin_info['admin_id'],
  474. 'password' => $encrypt_answer,
  475. ])->count();
  476. if (!empty($row)) {
  477. $this->error('密保答案不能与登录密码一致!');
  478. }
  479. $data = [
  480. 'security_ask_open' => 1,
  481. 'security_ask' => $security_askanswer_list[$ask],
  482. 'security_answer' => $encrypt_answer,
  483. 'security_answer_bright' => mchStrCode($answer),
  484. 'security_askanswer_list' => json_encode($security_askanswer_list),
  485. ];
  486. /*多语言*/
  487. if (is_language()) {
  488. $langRow = \think\Db::name('language')->order('id asc')
  489. ->cache(true, EYOUCMS_CACHE_TIME, 'language')
  490. ->select();
  491. foreach ($langRow as $key => $val) {
  492. tpSetting('security', $data, $val['mark']);
  493. }
  494. } else {
  495. tpSetting('security', $data);
  496. }
  497. /*--end*/
  498. $this->success('操作成功', url('Security/index'));
  499. }
  500. $this->assign('security_askanswer_list', $security_askanswer_list);
  501. return $this->fetch();
  502. }
  503. /**
  504. * 修改二次安全验证的问题、答案
  505. */
  506. public function second_verify_edit()
  507. {
  508. $security_askanswer_list = tpSetting('security.security_askanswer_list');
  509. $security_askanswer_list = json_decode($security_askanswer_list, true);
  510. if (empty($security_askanswer_list)) {
  511. $security_askanswer_list = config('global.security_askanswer_list');
  512. }
  513. if (IS_POST) {
  514. $post = input('post.');
  515. $answer_old = trim($post['answer_old']);
  516. $ask = intval($post['ask']);
  517. $answer = trim($post['answer']);
  518. if (empty($answer_old)) {
  519. $this->error('密保答案不能为空!');
  520. } else {
  521. if (0 <= $ask) {
  522. if (empty($answer)) {
  523. $this->error('重置密保答案不能为空!');
  524. } else if ($answer == $answer_old) {
  525. $this->error('重置密保答案不能与原来的一致!');
  526. }
  527. }
  528. }
  529. $security = tpSetting('security');
  530. $encrypt_answer_old = func_encrypt($answer_old, true, pwd_encry_type('bcrypt'));
  531. if ($encrypt_answer_old != $security['security_answer']) {
  532. $this->error('密保答案不正确!');
  533. }
  534. $data = [];
  535. if (0 <= $ask) {
  536. $encrypt_answer = func_encrypt($answer, true, pwd_encry_type('bcrypt'));
  537. $row = Db::name('admin')->where([
  538. 'admin_id' => $this->admin_info['admin_id'],
  539. 'password' => $encrypt_answer,
  540. ])->count();
  541. if (!empty($row)) {
  542. $this->error('重置密保答案不能与登录密码一致!');
  543. }
  544. $data['security_ask'] = $security_askanswer_list[$ask];
  545. $data['security_answer'] = $encrypt_answer;
  546. $data['security_answer_bright'] = mchStrCode($answer);
  547. $data['security_askanswer_list'] = json_encode($security_askanswer_list);
  548. }
  549. if (!empty($data)) {
  550. /*多语言*/
  551. if (is_language()) {
  552. $langRow = \think\Db::name('language')->order('id asc')
  553. ->cache(true, EYOUCMS_CACHE_TIME, 'language')
  554. ->select();
  555. foreach ($langRow as $key => $val) {
  556. tpSetting('security', $data, $val['mark']);
  557. }
  558. } else {
  559. tpSetting('security', $data);
  560. }
  561. /*--end*/
  562. }
  563. $this->success('操作成功', url('Security/index'));
  564. }
  565. $security = tpSetting('security');
  566. if (!empty($security)) {
  567. $security_ask = $security['security_ask'];
  568. if (!in_array($security_ask, $security_askanswer_list)) {
  569. $security_askanswer_list[] = $security_ask;
  570. }
  571. }
  572. $this->assign('security', $security);
  573. $this->assign('security_askanswer_list', $security_askanswer_list);
  574. return $this->fetch();
  575. }
  576. /**
  577. * 二次安全验证答案
  578. * @return [type] [description]
  579. */
  580. public function ajax_answer_verify()
  581. {
  582. if (IS_POST) {
  583. $answer = input('param.answer/s');
  584. $answer = trim($answer);
  585. if (empty($answer)) {
  586. $this->error('请录入密保答案!');
  587. } else {
  588. $security_answer = tpSetting('security.security_answer');
  589. $encrypt_answer = func_encrypt($answer, true, pwd_encry_type('bcrypt'));
  590. if ($security_answer != $encrypt_answer) {
  591. $this->error('密保答案不正确!');
  592. }
  593. }
  594. $this->submit_answer_verify();
  595. $this->success('密保验证成功');
  596. }
  597. }
  598. /**
  599. * 二次安全验证答案-提交
  600. * @return [type] [description]
  601. */
  602. private function submit_answer_verify()
  603. {
  604. /*多语言*/
  605. $ip = clientIP();
  606. if (is_language()) {
  607. $langRow = \think\Db::name('language')->order('id asc')
  608. ->cache(true, EYOUCMS_CACHE_TIME, 'language')
  609. ->select();
  610. foreach ($langRow as $key => $val) {
  611. tpSetting('security', ['security_answerverify_ip'=>$ip], $val['mark']);
  612. }
  613. } else {
  614. tpSetting('security', ['security_answerverify_ip'=>$ip]);
  615. }
  616. /*--end*/
  617. // 解决个别用户安装后,登录后台没记录最后登录IP地址,导致一直弹出验证答案
  618. $admin_info = Db::name('admin')->field('admin_id,last_ip')->where(['admin_id'=>$this->admin_info['admin_id']])->find();
  619. Db::name('admin')->where(['admin_id'=>$admin_info['admin_id']])->save(['last_ip'=>$ip, 'update_time'=>getTime()]);
  620. }
  621. /**
  622. * 是否已验证了答案
  623. * @return [type] [description]
  624. */
  625. public function ajax_isverify_answer()
  626. {
  627. if (IS_POST) {
  628. $security = tpSetting('security');
  629. $security_answerverify_ip = !empty($security['security_answerverify_ip']) ? $security['security_answerverify_ip'] : '-1';
  630. $admin_info = Db::name('admin')->field('admin_id,last_ip')->where(['admin_id'=>$this->admin_info['admin_id']])->find();
  631. if ($admin_info['last_ip'] == $security_answerverify_ip) {
  632. $this->success('已验证');
  633. }
  634. }
  635. $this->error('未验证');
  636. }
  637. /**
  638. * 修改问题列表
  639. * @return [type] [description]
  640. */
  641. public function save_ask_list()
  642. {
  643. if (IS_POST) {
  644. $value = input('post.value/s');
  645. $value = str_replace(["\r\n", "\n\r", "\r", "\n"], PHP_EOL, $value);
  646. $arr = explode(PHP_EOL, $value);
  647. foreach ($arr as $key => $val) {
  648. $val = trim($val);
  649. if (empty($val)) {
  650. unset($arr[$key]);
  651. } else {
  652. $arr[$key] = $val;
  653. }
  654. }
  655. if (empty($arr)) {
  656. $this->error('问题列表不能为空!');
  657. }
  658. // 将已设置的问题加入列表中
  659. $security_ask = tpSetting('security.security_ask');
  660. $security_ask = trim($security_ask);
  661. if (!empty($security_ask) && !in_array($security_ask, $arr)) {
  662. $arr[] = $security_ask;
  663. }
  664. if (is_language()) {
  665. $langRow = Db::name('language')->order('id asc')->select();
  666. foreach ($langRow as $key => $val) {
  667. tpSetting('security', ['security_askanswer_list'=>json_encode($arr)], $val['mark']);
  668. }
  669. } else { // 单语言
  670. tpSetting('security', ['security_askanswer_list'=>json_encode($arr)]);
  671. }
  672. $value = implode(PHP_EOL, $arr);
  673. $this->success('操作成功', null, ['value'=>$value, 'security_askanswer_list'=>$arr]);
  674. }
  675. }
  676. /**
  677. * 独立弹窗的安全验证中心(用于点击入口模板管理)
  678. * @return [type] [description]
  679. */
  680. public function second_ask_init()
  681. {
  682. if (IS_POST) {
  683. $settingData = [];
  684. $post = input('post.');
  685. /*-------------------二次安全验证 start-------------------*/
  686. $this->handleAskData($settingData, $post);
  687. /*-------------------二次安全验证 end-------------------*/
  688. /*多语言*/
  689. if (is_language()) {
  690. $langRow = \think\Db::name('language')->order('id asc')
  691. ->cache(true, EYOUCMS_CACHE_TIME, 'language')
  692. ->select();
  693. foreach ($langRow as $key => $val) {
  694. tpSetting('security', $settingData, $val['mark']);
  695. }
  696. } else {
  697. tpSetting('security', $settingData);
  698. }
  699. /*--end*/
  700. // 设置问题答案后,自动验证通过
  701. $this->submit_answer_verify();
  702. $is_show_answer = 0;
  703. if (empty($settingData['security_ask_open'])) {
  704. $gourl = "";
  705. $msg = "操作成功";
  706. } else {
  707. $gourl = input('param.gourl/s', '', null);
  708. if (empty($settingData['security_answer'])) {
  709. $msg = "操作成功";
  710. } else {
  711. $is_show_answer = 1;
  712. $securityData = tpSetting('security');
  713. $msg = "问题:{$securityData['security_ask']}<br/>答案:".mchStrCode($securityData['security_answer_bright'], 'DECODE');
  714. }
  715. }
  716. $this->success($msg, null, ['gourl'=>$gourl,'is_show_answer'=>$is_show_answer]);
  717. }
  718. $is_founder = 0;
  719. if (-1 == $this->admin_info['role_id'] && empty($this->admin_info['parent_id'])) {
  720. $is_founder = 1;
  721. }
  722. $this->admin_info['is_founder'] = $is_founder;
  723. $this->assign('admin_info', $this->admin_info);
  724. // 安全验证配置
  725. $security = tpSetting('security');
  726. if (!isset($security['security_ask_open'])) {
  727. $security['security_ask_open'] = 1;
  728. }
  729. if (isset($security['security_verifyfunc'])) {
  730. $security['security_verifyfunc'] = json_decode($security['security_verifyfunc'], true);
  731. }
  732. $security_askanswer_content = '';
  733. if (!empty($security['security_askanswer_list'])) {
  734. $security_askanswer_list = json_decode($security['security_askanswer_list'], true);
  735. $security['security_askanswer_list'] = $security_askanswer_list;
  736. }
  737. if (empty($security_askanswer_list)) {
  738. $security_askanswer_list = config('global.security_askanswer_list');
  739. }
  740. $security_askanswer_content = implode(PHP_EOL, $security_askanswer_list);
  741. $this->assign('security', $security);
  742. $this->assign('security_askanswer_content', $security_askanswer_content);
  743. if (!empty($security['security_ask'])) {
  744. $security_ask = $security['security_ask'];
  745. if (!in_array($security_ask, $security_askanswer_list)) {
  746. $security_askanswer_list[] = $security_ask;
  747. }
  748. }
  749. $this->assign('security_askanswer_list', $security_askanswer_list);
  750. $gourl = input('param.gourl/s');
  751. $this->assign('gourl', urldecode($gourl));
  752. // 点击来源
  753. $source = input('param.source/s');
  754. $this->assign('source', $source);
  755. return $this->fetch();
  756. }
  757. public function ajax_security_ask_open()
  758. {
  759. $data = tpSetting('security');
  760. $data['security_ask_open'] = empty($data['security_ask_open']) ? 0 : intval($data['security_ask_open']);
  761. $this->success('请求成功', null, $data);
  762. }
  763. /*-----------------------ddos攻击脚本查杀 start-----------------------*/
  764. /**
  765. * DDOS攻击脚本查杀
  766. * @return [type] [description]
  767. */
  768. public function ddos_kill()
  769. {
  770. $Prefix = config('database.prefix');
  771. $isTable = Db::query('SHOW TABLES LIKE \''.$Prefix.'ddos_log\'');
  772. if (empty($isTable)) {
  773. $tableSql = <<<EOF
  774. CREATE TABLE `{$Prefix}ddos_log` (
  775. `id` int(11) NOT NULL AUTO_INCREMENT,
  776. `md5key` varchar(50) DEFAULT '' COMMENT 'md5值',
  777. `file_name` varchar(500) DEFAULT '' COMMENT '文件名',
  778. `file_num` int(10) DEFAULT '0' COMMENT '已扫描数',
  779. `file_total` int(10) DEFAULT '0' COMMENT '总文件数',
  780. `file_num_ky` int(10) DEFAULT '0' COMMENT '可疑恶意文件数',
  781. `is_suspicious` tinyint(1) DEFAULT '0' COMMENT '是否可疑',
  782. `html` text,
  783. `add_time` int(11) DEFAULT '0' COMMENT '新增时间',
  784. `update_time` int(11) DEFAULT '0' COMMENT '更新时间',
  785. PRIMARY KEY (`id`)
  786. ) ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='ddos查杀进度记录表';
  787. EOF;
  788. $r = @Db::execute($tableSql);
  789. if ($r !== false) {
  790. schemaTable('ddos_log');
  791. }
  792. }
  793. $assign = [
  794. 'root_path' => ROOT_PATH,
  795. ];
  796. $this->assign($assign);
  797. return $this->fetch();
  798. }
  799. /**
  800. * 扫描
  801. * @return [type] [description]
  802. */
  803. public function ddos_scan()
  804. {
  805. //防止超时/内存溢出
  806. function_exists('set_time_limit') && set_time_limit(0);
  807. @ini_set('memory_limit','-1');
  808. \think\Session::pause(); // 暂停session,防止session阻塞机制
  809. if (IS_POST) {
  810. Db::name('ddos_log')->where(['id'=>['gt',0]])->delete();
  811. $start=getTime();
  812. $list = [];
  813. $html = '';
  814. $dir = ROOT_PATH;
  815. if (!is_readable($dir)) {
  816. $dir = str_replace('\\', '/', $dir);
  817. $dir = rtrim($dir, '/').'/';
  818. }
  819. $total = $num_ky = $scanned = 0;
  820. $auth_code = tpCache('system.system_auth_code');
  821. $this->ddos_getDirFile($dir, '', $list, $total);
  822. foreach ($list as $key => $value) {
  823. $md5key = md5($value.$auth_code);
  824. $fd = realpath($value);
  825. $fp = fopen($fd, "r");
  826. $scanned +=1;
  827. $i = 0;
  828. $is_suspicious = 0;
  829. while ($buffer = fgets($fp, 4096)) {
  830. $i++;
  831. if ($this->ddos_checkCodeFeatures($buffer)) {
  832. $num_ky += 1;
  833. $j = $num_ky % 2 + 1;
  834. $buffer = htmlspecialchars($this->ddos_cut_str($buffer,120,0));
  835. $is_suspicious = 1;
  836. $html .= <<<EOF
  837. <tr class='alt{$j}' onmouseover='this.className="focus";' onmouseout='this.className="alt{$j}";'>
  838. <td align="center">{$num_ky}</td>
  839. <td>{$fd}</td>
  840. <td>第 {$i} 行</td>
  841. <td>{$buffer}</td>
  842. <td><a href="javascript:void(0);" data-md5key="{$md5key}" onclick="delfile(this);">删除</a></td>
  843. </tr>
  844. EOF;
  845. }
  846. }
  847. fclose($fp);
  848. Db::name('ddos_log')->insert([
  849. 'md5key' => $md5key,
  850. 'file_name' => base64_encode($value),
  851. 'file_num' => $scanned,
  852. 'file_total' => $total,
  853. 'file_num_ky' => $num_ky,
  854. 'is_suspicious'=>$is_suspicious,
  855. 'html' => empty($html) ? '' : htmlspecialchars($html),
  856. 'add_time' => getTime(),
  857. ]);
  858. }
  859. $end = getTime();
  860. $spent = ($end - $start);
  861. $spent_str = '';
  862. $hours = intval($spent/3600);
  863. if (!empty($hours)) {
  864. $spent_str .= $hours."小时";
  865. }
  866. if ($spent >= 60) {
  867. $spent_str .= gmdate('i分', $spent);
  868. }
  869. $spent_str .= gmdate('s秒', $spent);
  870. if (empty($num_ky)) {
  871. $html = <<<EOF
  872. <tr>
  873. <td class="no-data" style="width: auto !important;" align="center" axis="col0" colspan="5">
  874. <i class="fa fa-exclamation-circle"></i>没有发现可疑文件
  875. </td>
  876. </tr>
  877. EOF;
  878. }
  879. $data = [
  880. 'scanned' => $scanned,
  881. 'num_ky' => $num_ky,
  882. 'spent' => $spent_str,
  883. 'html' => $html,
  884. ];
  885. $this->success("扫描完成,请自己排查处理", null, $data);
  886. }
  887. }
  888. /**
  889. * 是否是可疑恶意文件
  890. * @param string $buffer [description]
  891. * @return [type] [description]
  892. */
  893. private function ddos_checkCodeFeatures($buffer = '')
  894. {
  895. $bool = false;
  896. if (!empty($buffer)) {
  897. if (
  898. preg_match('/(pfsoc'.'kopen|fsoc'.'kopen)\("(udp|tcp)/i', $buffer) ||
  899. preg_match('/Php(\s+)(\d+)(\s+)Termi'.'nator/i', $buffer) ||
  900. preg_match('/[\$_G'.'ET|\$_REQU'.'EST]\[\'rat\']/i', $buffer) ||
  901. preg_match('/Tcp3(\s+)CC\.center/i', $buffer) ||
  902. preg_match('/xdos\.s/i', $buffer) ||
  903. preg_match('/儏摓煁'.'晜泟/i', $buffer) ||
  904. preg_match('/((FilemanagerModel\.php)|(\$qaz(\s*)=(\s*)\$qwe)|(include(\s*)\((\s*)([\"\']+)\/tmp\/)|(\$content'.'_mb(\s*)=(\s*))|(file_get_contents(\s*)\((\s*)\$auth_role_admin(\s*)\)))/i', $buffer) ||
  905. preg_match('/function(\s+)httpGetlai\(/i', $buffer)
  906. ) {
  907. $bool = true;
  908. }
  909. }
  910. return $bool;
  911. }
  912. private function ddos_cut_str($string, $sublen, $start = 0, $code = 'UTF-8') {
  913. if ($code == 'UTF-8') {
  914. $pa = "/[\x01-\x7f]|[\xc2-\xdf][\x80-\xbf]|\xe0[\xa0-\xbf][\x80-\xbf]|[\xe1-\xef][\x80-\xbf][\x80-\xbf]|\xf0[\x90-\xbf][\x80-\xbf][\x80-\xbf]|[\xf1-\xf7][\x80-\xbf][\x80-\xbf][\x80-\xbf]/";
  915. preg_match_all($pa, $string, $t_string);
  916. if (count($t_string[0]) - $start > $sublen) {
  917. return join('', array_slice($t_string[0], $start, $sublen)) . "...";
  918. }
  919. return join('', array_slice($t_string[0], $start, $sublen));
  920. } else {
  921. $start = $start * 2;
  922. $sublen = $sublen * 2;
  923. $strlen = strlen($string);
  924. $tmpstr = '';
  925. for($i = 0; $i < $strlen; $i++) {
  926. if ($i >= $start && $i < ($start + $sublen)) {
  927. if (ord(substr($string, $i, 1)) > 129) {
  928. $tmpstr .= substr($string, $i, 2);
  929. } else {
  930. $tmpstr .= substr($string, $i, 1);
  931. }
  932. }
  933. if (ord(substr($string, $i, 1)) > 129) {
  934. $i++;
  935. }
  936. }
  937. if (strlen($tmpstr) < $strlen) {
  938. $tmpstr .= "...";
  939. }
  940. return $tmpstr;
  941. }
  942. }
  943. /**
  944. * 递归读取文件夹文件
  945. */
  946. private function ddos_getDirFile($directory, $dir_name = '', &$arr_file = array(), &$total = 0)
  947. {
  948. $self = '';//'Security.php';
  949. $mydir = dir($directory);
  950. while ($file = $mydir->read()) {
  951. if ((is_dir("$directory/$file")) && !in_array($file, ['.','..','uploads'])) {
  952. if ($dir_name) {
  953. $this->ddos_getDirFile("$directory/$file", "$dir_name/$file", $arr_file, $total);
  954. } else {
  955. $this->ddos_getDirFile("$directory/$file", "$file", $arr_file, $total);
  956. }
  957. } else {
  958. if($file != $self){
  959. if (!in_array($file, ['.','..','uploads']) && preg_match("/\.(php|htm|asp|jsp)$/i", $file)) {
  960. $total +=1;
  961. if ($dir_name) {
  962. $arr_file[] = "$dir_name/$file";
  963. } else {
  964. $arr_file[] = "$file";
  965. }
  966. }
  967. }
  968. }
  969. }
  970. $mydir->close();
  971. return $arr_file;
  972. }
  973. /**
  974. * 扫描进度
  975. * @return [type] [description]
  976. */
  977. public function ddos_progressd()
  978. {
  979. \think\Session::pause(); // 暂停session,防止session阻塞机制
  980. if (IS_AJAX) {
  981. $progress = 0;
  982. $result = [];
  983. $init = input('param.init/d');
  984. if (empty($init)) {
  985. Db::name('ddos_log')->where(['id'=>['gt',0]])->delete();
  986. } else {
  987. $result = Db::name('ddos_log')->field('id, file_num, file_total, file_num_ky, html')->order('id desc')->find();
  988. }
  989. if (!empty($result)) {
  990. $progress = $result['file_num'] / $result['file_total'];
  991. $progress = floor($progress*100)/100;
  992. if ($progress >= 1) {
  993. Db::name('ddos_log')->where(['id'=>['gt',0], 'is_suspicious'=>0])->delete();
  994. }
  995. $progress = strval($progress * 100);
  996. if (empty($result['file_num_ky'])) {
  997. $html = <<<EOF
  998. <tr>
  999. <td class="no-data" style="width: auto !important;" align="center" axis="col0" colspan="5">
  1000. <i class="fa fa-exclamation-circle"></i>正在扫描中
  1001. </td>
  1002. </tr>
  1003. EOF;
  1004. } else {
  1005. $html = htmlspecialchars_decode($result['html']);
  1006. }
  1007. $this->success('请求成功', null, ['progress'=>$progress,'file_num'=>$result['file_num'],'file_num_ky'=>$result['file_num_ky'],'html'=>$html]);
  1008. } else {
  1009. $this->success('请求成功', null, ['progress'=>$progress]);
  1010. }
  1011. }
  1012. }
  1013. /**
  1014. * 删除可疑恶意文件
  1015. * @return [type] [description]
  1016. */
  1017. public function ddos_delfile()
  1018. {
  1019. if (IS_AJAX) {
  1020. $md5key = input('param.md5key/s');
  1021. $result = Db::name('ddos_log')->where(['md5key'=>$md5key, 'is_suspicious'=>1])->find();
  1022. if (empty($result)) {
  1023. $this->success('操作成功');
  1024. }
  1025. $filename = !empty($result['file_name']) ? trim($result['file_name'], '/') : '';
  1026. if (!empty($filename) && is_file($filename)) {
  1027. $filetype = pathinfo($filename, PATHINFO_EXTENSION);
  1028. $phpfile = strtolower(stristr($filename,'.php'));
  1029. if ($phpfile || in_array($filetype, ['php','js','png','gif','jpg','jpeg','ico','bmp','webp','htm','asp','jsp'])) {
  1030. $fd = realpath($filename);
  1031. $fp = fopen($fd, "r");
  1032. $num_ky = 0;
  1033. while ($buffer = fgets($fp, 4096)) {
  1034. if ($this->ddos_checkCodeFeatures($buffer)) {
  1035. $num_ky = 1;
  1036. break;
  1037. }
  1038. }
  1039. fclose($fp);
  1040. if (!empty($num_ky)) {
  1041. @unlink('./'.$filename);
  1042. $this->success('操作成功');
  1043. }
  1044. }
  1045. }
  1046. }
  1047. $this->error('操作失败');
  1048. }
  1049. /*-----------------------ddos攻击脚本查杀 end-----------------------*/
  1050. }