Version Description
- Added API service failback mechanism
- Added core integrity email on force scan
- Slight interface redesign
- Various bugfixes and improvements
Download this release
Release Info
Developer | akresic |
Plugin | Sucuri Security – Auditing, Malware Scanner and Security Hardening |
Version | 1.7.17 |
Comparing to | |
See all releases |
Code changes from version 1.7.16 to 1.7.17
- .htaccess +2 -8
- inc/css/sucuri-scanner.min.css +1 -1
- inc/images/blank.png +0 -0
- inc/images/flags.sprite.png +0 -0
- inc/js/sucuri-scanner.min.js +1 -1
- inc/tpl/base.html.tpl +8 -9
- inc/tpl/bsidebar.html.tpl +2 -2
- inc/tpl/{notification-corefiles.html.tpl → corefiles-notification.html.tpl} +1 -1
- inc/tpl/corefiles-page.html.tpl +39 -0
- inc/tpl/corefiles.html.tpl +82 -0
- inc/tpl/{integrity-corefiles.snippet.tpl → corefiles.snippet.tpl} +3 -3
- inc/tpl/firewall-auditlogs.html.tpl +73 -0
- inc/tpl/firewall-auditlogs.snippet.tpl +43 -0
- inc/tpl/firewall-clearcache.html.tpl +59 -0
- inc/tpl/firewall-settings.html.tpl +65 -0
- inc/tpl/firewall-settings.snippet.tpl +5 -0
- inc/tpl/firewall.html.tpl +28 -0
- inc/tpl/hardening-panel.html.tpl +14 -14
- inc/tpl/hardening-whitelist.html.tpl +1 -1
- inc/tpl/hardening.html.tpl +4 -4
- inc/tpl/hardening.snippet.tpl +3 -3
- inc/tpl/infosys-cronjobs.html.tpl +1 -1
- inc/tpl/infosys-errorlogs.html.tpl +2 -2
- inc/tpl/infosys-htaccess.html.tpl +18 -3
- inc/tpl/infosys-serverinfo.html.tpl +1 -1
- inc/tpl/infosys-wpconfig.html.tpl +1 -1
- inc/tpl/infosys.html.tpl +10 -10
- inc/tpl/integrity-auditlogs.html.tpl +3 -3
- inc/tpl/integrity-auditlogs.snippet.tpl +1 -1
- inc/tpl/integrity-auditreport.html.tpl +15 -14
- inc/tpl/integrity-corefiles.html.tpl +0 -97
- inc/tpl/integrity-modifiedfiles.html.tpl +56 -37
- inc/tpl/integrity-modifiedfiles.snippet.tpl +2 -2
- inc/tpl/integrity.html.tpl +4 -4
- inc/tpl/lastlogins-admins.html.tpl +1 -1
- inc/tpl/lastlogins-admins.snippet.tpl +3 -3
- inc/tpl/lastlogins-all.html.tpl +1 -1
- inc/tpl/lastlogins-failedlogins.html.tpl +6 -8
- inc/tpl/lastlogins-failedlogins.snippet.tpl +2 -2
- inc/tpl/lastlogins-loggedin.html.tpl +1 -1
- inc/tpl/lastlogins.html.tpl +8 -8
- inc/tpl/malwarescan-resblacklist.html.tpl +1 -5
- inc/tpl/malwarescan-resmalware.html.tpl +9 -15
- inc/tpl/malwarescan-resmalware.snippet.tpl +0 -2
- inc/tpl/malwarescan-results.html.tpl +12 -15
- inc/tpl/malwarescan-reswebdetails.html.tpl +5 -11
- inc/tpl/malwarescan-resweblinks.html.tpl +1 -4
- inc/tpl/malwarescan-weblinktitle.snippet.tpl +1 -1
- inc/tpl/malwarescan.html.tpl +3 -3
- inc/tpl/modalwindow.html.tpl +1 -2
- inc/tpl/monitoring-logs.html.tpl +0 -73
- inc/tpl/monitoring-logs.snippet.tpl +0 -71
- inc/tpl/monitoring-settings.html.tpl +0 -28
- inc/tpl/monitoring-settings.snippet.tpl +0 -5
- inc/tpl/monitoring.html.tpl +0 -58
- inc/tpl/notification-admin.html.tpl +5 -0
- inc/tpl/notification-pretty.html.tpl +2 -2
- inc/tpl/notification-resetpwd.html.tpl +1 -0
- inc/tpl/posthack-resetpassword.html.tpl +2 -2
- inc/tpl/posthack-resetplugins.html.tpl +1 -9
- inc/tpl/posthack-updatesecretkeys.html.tpl +1 -1
- inc/tpl/posthack.html.tpl +6 -6
- inc/tpl/settings-alert-bruteforce.html.tpl +35 -0
- inc/tpl/settings-alert-events.html.tpl +46 -0
- inc/tpl/settings-alert-events.snippet.tpl +10 -0
- inc/tpl/settings-alert-perhour.html.tpl +35 -0
- inc/tpl/settings-alert-recipients.html.tpl +58 -0
- inc/tpl/settings-alert-recipients.snippet.tpl +9 -0
- inc/tpl/settings-alert-subject.html.tpl +34 -0
- inc/tpl/settings-alert-subject.snippet.tpl +8 -0
- inc/tpl/settings-alert.html.tpl +12 -0
- inc/tpl/{settings-general-apiproxy.html.tpl → settings-apiservice-proxy.html.tpl} +1 -1
- inc/tpl/{settings-general-apissl.html.tpl → settings-apiservice-ssl.html.tpl} +2 -2
- inc/tpl/settings-apiservice-status.html.tpl +44 -0
- inc/tpl/{settings-general-apitimeout.html.tpl → settings-apiservice-timeout.html.tpl} +12 -6
- inc/tpl/settings-apiservice.html.tpl +10 -0
- inc/tpl/settings-emailsubject.snippet.tpl +0 -7
- inc/tpl/settings-general-apikey.html.tpl +3 -3
- inc/tpl/settings-general-auditlogstats.html.tpl +40 -0
- inc/tpl/settings-general-datastorage.html.tpl +2 -2
- inc/tpl/settings-general-datetime.html.tpl +21 -0
- inc/tpl/settings-general-ipdiscoverer.html.tpl +21 -0
- inc/tpl/settings-general-xhrmonitor.html.tpl +1 -1
- inc/tpl/settings-general.html.tpl +10 -106
- inc/tpl/settings-heartbeat.html.tpl +7 -7
- inc/tpl/settings-ignorerules.html.tpl +2 -2
- inc/tpl/settings-ignorerules.snippet.tpl +1 -1
- inc/tpl/settings-ignorescanning.html.tpl +4 -4
- inc/tpl/settings-notifications.html.tpl +0 -75
- inc/tpl/settings-notifications.snippet.tpl +0 -12
- inc/tpl/settings-scanner.html.tpl +15 -27
- inc/tpl/settings-selfhosting-monitor.html.tpl +56 -0
- inc/tpl/settings-selfhosting.html.tpl +4 -0
- inc/tpl/settings-trustip.html.tpl +3 -3
- inc/tpl/settings.html.tpl +35 -21
- inc/tpl/setup-form.html.tpl +1 -1
- inc/tpl/setup-notice.html.tpl +1 -1
- readme.txt +20 -12
- sucuri.php +5181 -4420
- uninstall.php +24 -22
.htaccess
CHANGED
@@ -1,14 +1,8 @@
|
|
1 |
|
2 |
Order Deny,Allow
|
3 |
Deny from all
|
4 |
-
Allow from 127.0.0.1
|
5 |
-
|
6 |
-
<Files index.php>
|
7 |
-
Order Allow,Deny
|
8 |
-
Allow from all
|
9 |
-
</Files>
|
10 |
|
11 |
<FilesMatch "\.(gif|jpe?g|png|css|js)$">
|
12 |
-
|
13 |
-
|
14 |
</FilesMatch>
|
1 |
|
2 |
Order Deny,Allow
|
3 |
Deny from all
|
|
|
|
|
|
|
|
|
|
|
|
|
4 |
|
5 |
<FilesMatch "\.(gif|jpe?g|png|css|js)$">
|
6 |
+
Order Allow,Deny
|
7 |
+
Allow from all
|
8 |
</FilesMatch>
|
inc/css/sucuri-scanner.min.css
CHANGED
@@ -1 +1 @@
|
|
1 |
-
.sucuriscan-wrap *,.sucuriscan-wrap *:before,.sucuriscan-wrap *:after{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.sucuriscan-clearfix:before,.sucuriscan-clearfix:after{display:table;content:' '}.sucuriscan-clearfix:after{clear:both}.sucuriscan-hidden{display:none !important}.sucuriscan-opacity{opacity:.6}.sucuriscan-monospace{font-family:Menlo,Monaco,monospace,courier}.sucuriscan-ellipsis{overflow:hidden;display:inline-block;white-space:nowrap;text-overflow:ellipsis}.sucuriscan-wraptext{word-break:break-all}.sucuriscan-pull-left{float:left}.sucuriscan-pull-right{float:right}.sucuriscan-list li{list-style:disc;margin:0 0 5px 15px}.sucuriscan-gradient,.sucuriscan-modal-header,.sucuriscan-maincontent .sucuriscan-table tr>th,.sucuriscan-leftside #poststuff h3{background-color:#f1f1f1;background-image:-webkit-gradient(linear,left top,left bottom,from(#f9f9f9),to(#ececec));background-image:-webkit-linear-gradient(top,#f9f9f9,#ececec);background-image:-moz-linear-gradient(top,#f9f9f9,#ececec);background-image:-ms-linear-gradient(top,#f9f9f9,#ececec);background-image:-o-linear-gradient(top,#f9f9f9,#ececec);background-image:linear-gradient(top,#f9f9f9,#ececec);filter:"progid: DXImageTransform.Microsoft.Gradient(startColorstr=#f9f9f9, endColorstr=#ececec)";-ms-filter:"progid: DXImageTransform.Microsoft.Gradient(startColorstr=#f9f9f9, endColorstr=#ececec)"}.wp-core-ui .button-success,.wp-core-ui .button-success.focus,.wp-core-ui .button-success.hover,.wp-core-ui .button-success:focus,.wp-core-ui .button-success:hover{background:#8dcd5a;border-color:#48a325;box-shadow:inset 0 1px 0 rgba(195,230,180,0.6)}.wp-core-ui .button-success.focus,.wp-core-ui .button-success.hover,.wp-core-ui .button-success:focus,.wp-core-ui .button-success:hover{background:#69be48}.wp-core-ui .button-success.focus,.wp-core-ui .button-success:focus{border-color:#23500e}.wp-core-ui .button-success.active,.wp-core-ui .button-success.active:focus,.wp-core-ui .button-success.active:hover,.wp-core-ui .button-success:active{background:#47a61b;border-color:#358400}.wp-core-ui .button-success-disabled,.wp-core-ui .button-success.disabled,.wp-core-ui .button-success:disabled,.wp-core-ui .button-success[disabled]{color:#b2e794 !important;background:#74ba29 !important;border-color:#3f7f1b !important}.wp-core-ui .button-danger,.wp-core-ui .button-danger.focus,.wp-core-ui .button-danger.hover,.wp-core-ui .button-danger:focus,.wp-core-ui .button-danger:hover{background:#cd5050;border-color:#a52121;box-shadow:inset 0 1px 0 rgba(230,170,170,0.6)}.wp-core-ui .button-danger.focus,.wp-core-ui .button-danger.hover,.wp-core-ui .button-danger:focus,.wp-core-ui .button-danger:hover{background:#be4242}.wp-core-ui .button-danger.focus,.wp-core-ui .button-danger:focus{border-color:#500e0e}.wp-core-ui .button-danger.active,.wp-core-ui .button-danger.active:focus,.wp-core-ui .button-danger.active:hover,.wp-core-ui .button-danger:active{background:#a61b1b;border-color:#840000}.wp-core-ui .button-danger-disabled,.wp-core-ui .button-danger.disabled,.wp-core-ui .button-danger:disabled,.wp-core-ui .button-danger[disabled]{color:#e79494 !important;background:#ba2929 !important;border-color:#7f1b1b !important}.wp-core-ui .sucuriscan-btnblock{display:block;width:100%;text-align:center}.sucuriscan-overlay{position:fixed;top:0;left:0;bottom:0;right:0;z-index:9990;background:rgba(0,0,0,0.5)}.sucuriscan-modal{position:absolute;top:25px;left:15%;z-index:9990;width:55%}.sucuriscan-modal-outside{position:relative;left:0;border:1px solid #ddd}.sucuriscan-modal-inside{background:#fff;padding:20px}.sucuriscan-modal-header{padding:0;border-bottom:1px solid #ddd}#poststuff h3.sucuriscan-modal-title,.sucuriscan-leftside #poststuff h3.sucuriscan-modal-title,.sucuriscan-modal-header .sucuriscan-modal-title{margin:0;padding:0;float:left;line-height:38px;margin-left:10px;border-bottom:0}.sucuriscan-modal-header .sucuriscan-modal-logo{display:inline-block;float:left;margin-top:8px;margin-left:18px}.sucuriscan-modal-header .sucuriscan-modal-logo img{height:22px}.sucuriscan-modal-close{display:inline-block;position:absolute;top:0;right:0;font-size:16px;font-weight:bold;text-decoration:none;line-height:38px;padding:0 15px;border-left:1px solid #ddd}.sucuriscan-modal-inside p:first-child{margin-top:0}.sucuriscan-modal-inside p:last-child{margin-bottom:0}.sucuriscan-label,.sucuriscan-label-default,.sucuriscan-label-unknown,.sucuriscan-label-primary,.sucuriscan-label-success,.sucuriscan-label-info,.sucuriscan-label-notice,.sucuriscan-label-warning,.sucuriscan-label-danger,.sucuriscan-label-error{display:inline;font-size:75%;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;padding:.2em .6em .3em;border-radius:.25em}.sucuriscan-label-default,.sucuriscan-label-unknown{background:#777}.sucuriscan-label-danger,.sucuriscan-label-error{background:#d9534f}.sucuriscan-label-info,.sucuriscan-label-notice{background:#5bc0de}.sucuriscan-label-warning{background:#f0ad4e}.sucuriscan-label-success{background:#5cb85c}.sucuriscan-label-primary{background:#428bca}.sucuriscan-wrap{margin-top:20px}.sucuriscan-wrap .sucuriscan-maincontent{margin:20px 0}.sucuriscan-wrap .sucuriscan-leftside{width:73.5%;float:left}.sucuriscan-wrap .sucuriscan-onecolumn{width:100%}.sucuriscan-wrap .sucuriscan-sidebar{width:25%;float:right}.sucuriscan-wrap #warnings_hook{line-height:initial;padding:0}.sucuriscan-wrap .sucuriscan-navbar{padding-top:20px;padding-left:6px}.sucuriscan-wrap .sucuriscan-navbar .nav-tab{margin-right:0}.sucuriscan-header,.sucuriscan-footer{position:relative;min-width:255px;background:#333;margin:0;padding:10px;border-radius:4px}.sucuriscan-footer .sucuriscan-help{color:#fff;float:right;text-align:right}.sucuriscan-footer .sucuriscan-help p{line-height:38px;margin:0 10px 0 0;padding:0}.sucuriscan-wrap .sucuriscan-logo,.sucuriscan-wrap .sucuriscan-header h2,.sucuriscan-wrap .sucuriscan-footer h2{float:left;margin:0;padding:0}.sucuriscan-wrap .sucuriscan-logo{display:inline-block}.sucuriscan-wrap .sucuriscan-logo img{display:block}.sucuriscan-wrap .sucuriscan-header h2,.sucuriscan-wrap .sucuriscan-footer h2{color:#fff;line-height:38px;margin-left:10px;text-shadow:#000 0 1px 0}.sucuriscan-leftside #poststuff .postbox:last-child{margin-bottom:0}.sucuriscan-leftside #poststuff .postbox h3{border-bottom:1px solid #ddd}.sucuriscan-maincontent abbr{text-decoration:underline;cursor:help}.wrap div.sucuriscan-setup-notice{background:#bbe8f5;margin:0 0 20px 0;padding:0;border:1px solid #bbb;border-radius:3px;-webkit-box-shadow:none;box-shadow:none}.wrap div.sucuriscan-setup-notice .sucuriscan-setup-image,.wrap div.sucuriscan-setup-notice .sucuriscan-setup-image img{border-radius:3px 0 0 3px}.wrap div.sucuriscan-setup-notice .sucuriscan-setup-image{background:#333;margin:-1px 0 -1px -1px;padding:7px 10px;border-right:1px solid transparent}.wrap div.sucuriscan-setup-notice .sucuriscan-setup-form{padding:4px;padding-left:0}.wrap div.sucuriscan-setup-notice p{font-size:14px;line-height:20px;margin:0 0 0 10px;padding:7px 0}.wrap div.sucuriscan-setup-notice,.wrap div.sucuriscan-setup-notice .sucuriscan-setup-image{border-color:#4393ac}.wp-core-ui .sucuriscan-review-hero,.wp-core-ui .button.sucuriscan-review-hero{position:relative;top:-2px;right:-15px;height:initial;line-height:30px;float:right;padding:0 20px}.sucuriscan-input-group>label{display:inline-block;border:1px solid #ddd;border-right:0;line-height:26px;float:left;padding:0 10px;background:#eee}.sucuriscan-input-group>input[type=text]{margin:0;padding-bottom:4px}.sucuriscan-input-group>select{vertical-align:initial;margin:0}.sucuriscan-table-setup td{vertical-align:top}.sucuriscan-table-setup .sucuriscan-description{font-size:12px;margin-top:10px}.sucuriscan-dismiss-setup{font-size:10px;line-height:28px}.sucuriscan-maincontent .sucuriscan-table{margin-top:12px}.sucuriscan-maincontent .sucuriscan-table tr>th{border-top:1px solid #e5e5e5;border-bottom:1px solid #e5e5e5}.sucuriscan-maincontent .sucuriscan-table tr:first-child th{border-top:0}.sucuriscan-maincontent .sucuriscan-table td.check-column{padding:8px 10px}.sucuriscan-maincontent .sucuriscan-striped-table tr:nth-child(even){background:#f5f5f5}.sucuriscan-table-double-title tr:first-child th{border-bottom:0}.sucuriscan-table-triple-title tr:first-child th,.sucuriscan-table-triple-title tr:first-child+tr th{border-bottom:0}.sucuriscan-table-quad-title tr:first-child th,.sucuriscan-table-quad-title tr:first-child+tr th,.sucuriscan-table-quad-title tr:first-child+tr+tr th{border-bottom:0}.sucuriscan-table-description{border-left-width:1px !important;box-shadow:none}.sucuriscan-table-description .inside{border-bottom:0 !important}.widefat td.td-with-button{text-align:right;padding:3px 10px}.widefat td.td-with-button button{min-width:90px}.widefat td.td-with-button select{height:initial;line-height:initial;vertical-align:top;margin:0;padding:2px 0 3px 0}.widefat th.check-column{line-height:36px;padding:0}.widefat th.check-column input[type=checkbox]{margin:1px 0 0 10px}.sucuriscan-list-as-table{background:#fff;border:1px solid #e5e5e5}.sucuriscan-list-as-table li{line-height:30px;word-break:break-all;margin:0;padding:0 10px}.sucuriscan-list-as-table li:nth-child(odd){background:#f5f5f5}.sucuriscan-list-as-table-scrollable{height:300px;overflow:hidden;overflow-y:scroll}.sucuriscan-maincontent .thead-with-button{padding:5px 5px 5px 10px}.sucuriscan-maincontent .thead-with-button>span{display:inline-block;line-height:28px}.sucuriscan-maincontent .thead-with-button .input-text{line-height:26px}.sucuriscan-maincontent .thead-with-button select{margin:0;padding:0}.sucuriscan-maincontent .thead-topright-action{display:inline-block;float:right}.sucuriscan-ad{color:#fff;padding:20px;margin-bottom:20px}.sucuriscan-ad h3,.sucuriscan-ad h4,.sucuriscan-ad .sucuriscan-ad-btn{font-family:Arial,Helvetica,sans-serif;color:#fff;margin:0}.sucuriscan-ad h3{font-size:18px;font-weight:300}.sucuriscan-ad h4{font-size:22px;font-weight:bold;margin-top:10px}.sucuriscan-ad .sucuriscan-ad-btn{display:block;font-size:13px;font-weight:bold;text-align:center;text-decoration:none;text-transform:uppercase;margin-top:20px;padding:5px;border-radius:20px}.sucuriscan-ad .sucuriscan-ad-footer{margin-top:20px;margin-bottom:0}.sucuriscan-ad .sucuriscan-ad-footer ul{margin:0}.sucuriscan-ad .sucuriscan-ad-footer li{font-size:12px;color:#fff;list-style:disc;margin:0 0 0 16px}.sucuriscan-ad .sucuriscan-ad-footer li.featured{color:#fde44c}.sucuriscan-scanner-video{width:100%;background:#fff;border:1px solid #ddd}.sucuriscan-sidebar .sucuriscan-supportbtn{width:100%;height:initial;text-align:center;line-height:36px;margin-top:15px;padding:0}.wp-core-ui .sucuriscan-hide-ads{display:block;color:#666;font-size:11px;text-decoration:underline;margin-top:15px;padding:0}.wp-core-ui .sucuriscan-hide-ads:focus{color:#000;box-shadow:none}.sucuriscan-ad-firewall{background:#606e77}.sucuriscan-ad-firewall .sucuriscan-ad-btn{background:#606e77;border:1px solid #fff}.sucuriscan-ad-firewall .sucuriscan-ad-btn:hover{background:#85929b}.sucuriscan-ad-antivirus{background:#04833e;padding-bottom:0}.sucuriscan-ad-antivirus .sucuriscan-ad-website{display:block;text-decoration:none;margin-top:20px}.sucuriscan-ad-antivirus .sucuriscan-ad-website img{display:block;max-width:100%}.sucuriscan-ad-antivirus .sucuriscan-ad-btn{background-color:#e8840a;background-image:-webkit-gradient(linear,left top,left bottom,from(#e8840a),to(#ef7f02));background-image:-webkit-linear-gradient(top,#e8840a,#ef7f02);background-image:-moz-linear-gradient(top,#e8840a,#ef7f02);background-image:-ms-linear-gradient(top,#e8840a,#ef7f02);background-image:-o-linear-gradient(top,#e8840a,#ef7f02);background-image:linear-gradient(top,#e8840a,#ef7f02);filter:"progid: DXImageTransform.Microsoft.Gradient(startColorstr=#e8840a, endColorstr=#ef7f02)";-ms-filter:"progid: DXImageTransform.Microsoft.Gradient(startColorstr=#e8840a, endColorstr=#ef7f02)";box-shadow:inset 0 1px 1px #eaac3a;border:1px solid #d17301}div.sucuriscan-alert{position:relative;margin:0 0 20px 0}div.sucuriscan-alert>a.close{position:absolute;top:10px;right:10px;font-size:18px;font-weight:bold;text-decoration:none}.sucuriscan-inline-alert,.sucuriscan-inline-alert-updated,.sucuriscan-inline-alert-error,.sucuriscan-inline-alert-warning,.sucuriscan-inline-alert-info{background:#fff;box-shadow:0 1px 1px 0 rgba(0,0,0,0.1);padding:0;border-left:4px solid #ddd}.sucuriscan-inline-alert>p,.sucuriscan-inline-alert-updated>p,.sucuriscan-inline-alert-error>p,.sucuriscan-inline-alert-warning>p,.sucuriscan-inline-alert-info>p{margin:0;padding:8px 12px;border:1px solid #ddd;border-left:0}.sucuriscan-inline-alert-updated,.sucuriscan-inline-alert-warning,.sucuriscan-inline-alert-error,.sucuriscan-inline-alert-info{margin-bottom:10px}.sucuriscan-inline-alert-updated{border-left-color:#7ad03a}.sucuriscan-inline-alert-warning{border-left-color:#ffba00}.sucuriscan-inline-alert-error{border-left-color:#dd3d36}.sucuriscan-inline-alert-info{border-left-color:#2ea2cc}.sucuriscan-tabs>ul{margin:0}.sucuriscan-tabs>ul li,.sucuriscan-tabs>ul li>a{display:inline-block}.sucuriscan-tabs>ul li{margin-bottom:0}.sucuriscan-tabs>ul li>a{background:#e5e5e5;font-size:13px;font-weight:bold;color:#333;line-height:38px;text-decoration:none;padding:0 10px}.sucuriscan-tabs>ul li>a.sucuriscan-tab-active{background:#fff;border:1px solid #e1e1e1;border-bottom:0}.sucuriscan-tabs>ul li.sucuriscan-red-tab a{background:#ff8a83;color:#fff}.sucuriscan-tabs>ul li.sucuriscan-red-tab a.sucuriscan-tab-active{background:#dd3d36;border-color:#dd3d36}.sucuriscan-maincontent .sucuriscan-tab-containers>div>table{margin-top:0}.sucuriscan-maincontent .sucuriscan-tab-containers>div>#poststuff{margin-top:0}.sucuriscan-getapi-div{background:#fff;margin:0 0 20px 0;border:1px solid #e5e5e5;border-radius:3px}.sucuriscan-getapi-div p{margin:0;padding:10px}.sucuriscan-getapi-form button.button-primary{width:100%;height:initial;line-height:30px;margin:0 0 -1px 0;padding:0;border-radius:0 0 3px 3px}.sucuriscan-malwarescan-message{margin-bottom:20px !important}.sucuriscan-loading{background:#fff;text-align:center;padding:30px;padding-bottom:15px;border:1px solid #ddd;border-radius:4px}.sucuriscan-loading p,.sucuriscan-loading h3{margin:0;padding:0}.sucuriscan-loading .title{font-size:28px;margin-bottom:10px}.sucuriscan-loading .description{font-size:16px}.sucuriscan-sitelogo{width:190px;height:100px;background:url('http://sitecheck.sucuri.net/images/sucuri-sprite.png') no-repeat;margin:0 auto}.sucuriscan-sitecheck-form{margin:20px 0 0 0}.sucuriscan-sitecheck-form .button.button-hero{padding:0 46px}.sucuriscan-loading .sucuriscan-sitecheck-disclaimer{text-align:justify;padding-top:20px;border-top:1px solid #ddd}.sucuriscan-loading .sucuriscan-sitecheck-disclaimer p{font-size:10px}.sucuriscan-maincontent .sucuriscan-border{border:0;border-left:4px solid #ddd}.sucuriscan-maincontent .sucuriscan-border>h3,.sucuriscan-maincontent .sucuriscan-border>.inside{border-top:1px solid #e5e5e5;border-right:1px solid #e5e5e5}.sucuriscan-maincontent .sucuriscan-border>h3{border-bottom:0}.sucuriscan-maincontent .sucuriscan-border>.inside{margin-top:0 !important;border-bottom:1px solid #ddd}.sucuriscan-maincontent .sucuriscan-border-good,.sucuriscan-maincontent .sucuriscan-border-success{border-left-color:#7ad03a}.sucuriscan-maincontent .sucuriscan-border-bad,.sucuriscan-maincontent .sucuriscan-border-danger{border-left-color:#dd3d36}.sucuriscan-maincontent .sucuriscan-border-info{border-left-color:#2ea2cc}.sucuriscan-maincontent .sucuriscan-cleanup-btn{margin:20px 0 0 0}.sucuriscan-scanner-results .sucuriscan-scanner-details tr:nth-child(even),.sucuriscan-scanner-results .sucuriscan-scanner-links tr:nth-child(even){background:#f5f5f5}.sucuriscan-scanner-results td.sucuriscan-border-bad{border-left-width:4px;border-left-style:solid}.sucuriscan-scanner-results .sucuriscan-malware-link{text-align:right}.sucuriscan-scanner-results .sucuriscan-malware-link a:hover{color:#fff}.sucuriscan-malware-payload{background:#f5f5f5;word-break:break-all;margin:-2px -15px -15px -15px;padding:15px}.sucuriscan-maincontent .sucuriscan-corefiles,.sucuriscan-maincontent .sucuriscan-integrity-message,.sucuriscan-maincontent .sucuriscan-wordpress-outdated,.sucuriscan-maincontent .sucuriscan-auditlogs{margin-top:0;margin-bottom:20px}.sucuriscan-maincontent .sucuriscan-auditlogs{margin-bottom:0}.sucuriscan-auditlogs .sucuriscan-list-as-table{margin-bottom:0}.sucuriscan-auditlogs .sucuriscan-maxper-page{text-align:right}.sucuriscan-auditlogs .sucuriscan-label{display:inline-block;width:18px;text-transform:uppercase;line-height:13px;cursor:pointer;border-radius:50%}.sucuriscan-auditlogs .sucuriscan-auditlog-success,.sucuriscan-label-added{background:#5cb85c}.sucuriscan-auditlogs .sucuriscan-auditlog-debug{background:#c690ec}.sucuriscan-auditlogs .sucuriscan-auditlog-info{background:#5bc0de}.sucuriscan-auditlogs .sucuriscan-auditlog-notice{background:#428bca}.sucuriscan-auditlogs .sucuriscan-auditlog-warning,.sucuriscan-label-modified{background:#f0ad4e}.sucuriscan-auditlogs .sucuriscan-auditlog-error,.sucuriscan-label-removed{background:#f27d7d}.sucuriscan-auditlogs .sucuriscan-auditlog-critical{background:#000}.sucuriscan-maincontent .sucuriscan-audit-report{border-left-width:1px}.sucuriscan-audit-report .sucuriscan-report-row{margin-bottom:10px}.sucuriscan-audit-report .sucuriscan-report-row:last-child{margin-bottom:0}.sucuriscan-audit-report .sucuriscan-report-chart{width:49%;border:1px solid #ddd}.sucuriscan-audit-report .sucuriscan-report-chart h4,.sucuriscan-audit-report .sucuriscan-report-chart h5{font-weight:normal;text-align:center;margin:0}.sucuriscan-audit-report .sucuriscan-report-chart h4{font-size:18px;margin-top:10px}.sucuriscan-audit-report .sucuriscan-report-chart h5{font-size:12px;margin-top:5px}.sucuriscan-maincontent .sucuriscan-audit-report .sucuriscan-inline-alert-info{margin-top:10px}.sucuriscan-status-type{display:inline-block;width:20px;background:#ddd;text-align:center;text-transform:uppercase;margin-right:10px;padding:0 3px;border:1px solid transparent;border-radius:3px}td.sucuriscan-corefiles-warning>div{background:#f2dede;color:#a94442;border-color:#ebccd1}.sucuriscan-maincontent .sucuriscan-corefiles .sucuriscan-label{text-transform:capitalize}.sucuriscan-maincontent td.sucuriscan-corefiles-warning,.sucuriscan-maincontent td.sucuriscan-corefiles-warning p{margin:0;padding:0}.sucuriscan-maincontent td.sucuriscan-corefiles-warning div{padding:10px;border-width:1px;border-style:solid}.sucuriscan-maincontent td.sucuriscan-corefiles-warning code{font-size:12px;padding:0 5px}.sucuriscan-maincontent .sucuriscan-integrity-message{position:relative}.sucuriscan-maincontent .sucuriscan-integrity-message .sucuriscan-integrity-mark,.sucuriscan-maincontent .sucuriscan-integrity-message .sucuriscan-integrity-failure{position:absolute;top:1px;right:1px;background:#ddd;font-weight:bold;color:#fff;line-height:35px;padding:0 10px;border-left:1px solid #ddd}.sucuriscan-maincontent .sucuriscan-integrity-message .sucuriscan-integrity-mark{background:#7ad03a}.sucuriscan-maincontent .sucuriscan-integrity-message .sucuriscan-integrity-failure{background:#dd3d36;border-left:0}.sucuriscan-maincontent .sucuriscan-ignoredfiles{margin-top:0}.sucuriscan-ignore-file form{padding:10px;padding-top:0;border-bottom:1px solid #ddd;border-right:1px solid #ddd}.sucuriscan-ignore-file p{border-bottom:0}.sucuriscan-ignore-file-input{width:80%}.sucuriscan-ignore-file-button{width:18%}.sucuriscan-maincontent .sucuriscan-modifiedfiles .sucuriscan-ellipsis{width:100px}.sucuriscan-monitoring-settings{margin-bottom:20px}.sucuriscan-monitoring-settings td.td-with-button{text-align:left}.sucuriscan-monitoring-settings .sucuriscan-list-as-table{margin:0}.sucuriscan-monitoring-apikey-form .input-text{width:85%}.sucuriscan-monitoring-logs .thead-with-button .button{width:65px}.sucuriscan-monitoring-logs .thead-with-button .input-text,.sucuriscan-monitoring-logs .thead-with-button select{width:250px}.sucuriscan-monitoring-logs .sucuriscan-monitoring-date-form select{width:70px}.sucuriscan-monitoring-logs .sucuriscan-monitoring-date-form select+select{width:112px}.sucuriscan-monitoring-logs .sucuriscan-monitoring-date-form select+select+select{width:60px}.sucuriscan-monitoring-logs .sucuriscan-target-date{font-size:12px;color:#999;margin-right:5px}.sucuriscan-monitoring-logs .sucuriscan-denial-type{font-size:14px}.sucuriscan-monitoring-logs .sucuriscan-denial-type-date{font-style:italic;color:#999}.sucuriscan-request-summary{margin:-15px;margin-top:-3px}.sucuriscan-request-summary td{font-size:14px}.sucuriscan-request-summary tr td:first-child{font-weight:bold}.sucuriscan-request-summary td+td{word-break:break-all}.sucuriscan-hstatus{position:relative;margin:0 -12px;padding:10px 12px;border:1px solid transparent}.sucuriscan-hstatus-0{background-color:#f2dede;color:#a94442;border-color:#ebccd1}.sucuriscan-hstatus-1{background-color:#dff0d8;color:#3c763d;border-color:#d6e9c6}.sucuriscan-hstatus-2{background-color:#dee4f2;color:#4263a9;border-color:#ccd0eb}.sucuriscan-hstatus .button-primary,.sucuriscan-hstatus .button-secondary{position:absolute;top:5px;right:5px}.sucuriscan-hardening .postbox .inside pre{background:#eaeaea;padding:10px}.sucuriscan-hardening-whitelist form{margin-top:15px}.sucuriscan-hardening-whitelist form label{line-height:29px;font-size:12px;background-color:#eee;padding:0 10px;display:inline-block;border:1px solid #ddd;border-right:0}.sucuriscan-hardening-whitelist form input[type=text]{margin:0;padding:5px}.sucuriscan-hardening-whitelist form select{height:initial;padding:4px;margin:0}.sucuriscan-hardening-whitelist form select,.sucuriscan-hardening-whitelist form input[type=text],.sucuriscan-hardening-whitelist form .button{margin-right:5px}.sucuriscan-maincontent .sucuriscan-table.sucuriscan-hardening-whitelist-table{margin-top:0}.sucuriscan-lastlogin-outof{font-style:italic;color:#999;margin-right:10px}.sucuriscan-admins-lastlogins .sucuriscan-ellipsis{width:170px}.sucuriscan-admins-lastlogins td{padding:4px 8px}.sucuriscan-pattern-search-inputbox{margin-top:12px}.sucuriscan-pattern-search-inputbox .input-text{width:84.7777%;line-height:30px;margin:0;margin-right:6px}.sucuriscan-pattern-search-inputbox .input-button{width:14%;height:initial;line-height:35px}.sucuriscan-pattern-search .sucuriscan-cleanup-btn{margin-top:12px}.sucuriscan-pattern-search table label{color:#999}.sucuriscan-pattern-search .sucuriscan-grep-text em{color:#ea3838}.sucuriscan-about ul{margin-left:20px}.sucuriscan-about ul li{list-style:initial}.sucuriscan-about li label{font-weight:bold;vertical-align:initial}.sucuriscan-apikey-registered .sucuriscan-pull-right{width:400px}.sucuriscan-apikey-registered .sucuriscan-sitelogo{background-position:0 -17px;height:83px}.sucuriscan-setup-instructions .form-table{margin-top:15px}.sucuriscan-setup-instructions .form-table td{padding:0;padding-bottom:12px}.sucuriscan-setup-instructions .form-table select{max-width:400px}.sucuriscan-pagination{display:inline-block;margin:0;padding:0;border-radius:4px}.sucuriscan-pagination>li{display:inline}.sucuriscan-pagination>li>a,.sucuriscan-pagination>li>span{position:relative;background:#fff;color:#428bca;line-height:1.42857143;text-decoration:none;float:left;margin-left:-1px;padding:6px 12px;border:1px solid #ddd}.sucuriscan-pagination>li:first-child>a,.sucuriscan-pagination>li:first-child>span{margin-left:0;border-radius:4px 0 0 4px}.sucuriscan-pagination>li:last-child>a,.sucuriscan-pagination>li:last-child>span{border-radius:0 4px 4px 0}.sucuriscan-pagination>li>a.sucuriscan-pagination-active,.sucuriscan-pagination>li>a:hover{background:#0074a2;color:#fff}.sucuriscan_wpconfig_keys_updated textarea{width:100%;height:250px;background:#f5f5f5;font-size:12px;resize:vertical;margin:20px 0 0 0}.sucuriscan-maincontent .sucuriscan-last-logins{margin-top:0}.sucuriscan-maincontent .sucuriscan-last-logins .sucuriscan-ellipsis{width:150px;line-height:inherit}.sucuriscan-maincontent .sucuriscan-full-textarea{width:100%;height:400px;line-height:normal;resize:vertical;padding:10px}.sucuriscan-maincontent .sucuriscan-settings{margin-top:0}.sucuriscan-maincontent .sucuriscan-settings form{display:inline-block}.sucuriscan-maincontent .sucuriscan-settings select,.sucuriscan-maincontent .sucuriscan-settings .input-text{width:220px;margin:0}.sucuriscan-maincontent .sucuriscan-settings-notifications{margin-top:0}.sucuriscan-maincontent .sucuriscan-settings-notifications .dashicons-before:before{margin-right:5px}.sucuriscan-maincontent .sucuriscan-settings-ignorescanning{margin-top:0}.sucuriscan-maincontent .sucuriscan-settings-trustip{margin-top:0}.sucuriscan-maincontent .sucuriscan-wpcron-list{margin-top:0}.sucuriscan-maincontent .sucuriscan-infosys-htaccess .inside{border-bottom:1px solid #ddd !important}.sucuriscan-maincontent .sucuriscan-infosys-htaccess .inside .sucuriscan-inline-alert-updated{margin-bottom:10px}.sucuriscan-maincontent .sucuriscan-errorlogs .inside .sucuriscan-inline-alert-error{margin-top:10px}.sucuriscan-maincontent .sucuriscan-subject-formats{margin:0}.sucuriscan-maincontent .sucuriscan-subject-formats input[type=text]{width:40%;margin-left:10px}.c3 svg{font:10px sans-serif}.c3 line,.c3 path{fill:none;stroke:#000}.c3 text{-webkit-user-select:none;-moz-user-select:none;user-select:none}.c3-bars path,.c3-event-rect,.c3-legend-item-tile,.c3-xgrid-focus,.c3-ygrid{shape-rendering:crispEdges}.c3-chart-arc path{stroke:#fff}.c3-chart-arc text{fill:#fff;font-size:13px}.c3-grid line{stroke:#aaa}.c3-grid text{fill:#aaa}.c3-xgrid,.c3-ygrid{stroke-dasharray:3 3}.c3-text.c3-empty{fill:gray;font-size:2em}.c3-line{stroke-width:1px}.c3-circle._expanded_{stroke-width:1px;stroke:#fff}.c3-selected-circle{fill:#fff;stroke-width:2px}.c3-bar{stroke-width:0}.c3-bar._expanded_{fill-opacity:.75}.c3-chart-arcs-title{dominant-baseline:middle;font-size:1.3em}.c3-target.c3-focused{opacity:1}.c3-target.c3-focused path.c3-line,.c3-target.c3-focused path.c3-step{stroke-width:2px}.c3-target.c3-defocused{opacity:.3 !important}.c3-region{fill:#4682b4;fill-opacity:.1}.c3-brush .extent{fill-opacity:.1}.c3-legend-item{font-size:12px}.c3-legend-item-hidden{opacity:.15}.c3-legend-background{opacity:.75;fill:#fff;stroke:#d3d3d3;stroke-width:1}.c3-tooltip-container{z-index:10}.c3-tooltip{border-collapse:collapse;border-spacing:0;background-color:#fff;empty-cells:show;-webkit-box-shadow:7px 7px 12px -9px #777;-moz-box-shadow:7px 7px 12px -9px #777;box-shadow:7px 7px 12px -9px #777}.c3-tooltip tr{border:1px solid #CCC}.c3-tooltip th{background-color:#aaa;font-size:14px;padding:2px 5px;text-align:left;color:#FFF}.c3-tooltip td{font-size:13px;padding:3px 6px;background-color:#fff;border-left:1px dotted #999}.c3-tooltip td>span{display:inline-block;width:10px;height:10px;margin-right:6px}.c3-tooltip td.value{text-align:right}.c3-area{stroke-width:0;opacity:.2}.c3-chart-arcs .c3-chart-arcs-background{fill:#e0e0e0;stroke:none}.c3-chart-arcs .c3-chart-arcs-gauge-unit{fill:#000;font-size:16px}.c3-chart-arcs .c3-chart-arcs-gauge-max,.c3-chart-arcs .c3-chart-arcs-gauge-min{fill:#777}.c3-chart-arc .c3-gauge-value{fill:#000}@media(max-width:620px){.sucuriscan-tabs>ul li,.sucuriscan-tabs>ul li>a{display:block}.sucuriscan-getapi-form button.button-primary{line-height:40px}}@media(max-width:768px){.sucuriscan-wrap .sucuriscan-leftside,.sucuriscan-wrap .sucuriscan-sidebar,.sucuriscan-wrap .sucuriscan-footer .sucuriscan-logo,.sucuriscan-wrap .sucuriscan-footer .sucuriscan-help{float:none}.sucuriscan-wrap .sucuriscan-leftside,.sucuriscan-wrap .sucuriscan-sidebar{width:100%}.sucuriscan-wrap .sucuriscan-sidebar{margin-top:20px}.sucuriscan-wrap .sucuriscan-footer .sucuriscan-logo{display:table;margin:0 auto}}@media(max-width:920px){.sucuriscan-wrap .sucuriscan-navbar{padding-left:0;padding-right:0}.sucuriscan-wrap .sucuriscan-navbar .nav-tab{display:block;line-height:20px;margin:0}.sucuriscan-wrap .sucuriscan-navbar .nav-tab:last-child{border-bottom:1px solid #ccc}.wp-core-ui .sucuriscan-review-hero,.wp-core-ui .button.sucuriscan-review-hero{top:0;right:0;display:block;width:100%;margin:10px 0}}.sucuriscan-maincontent #poststuff{min-width:initial;padding-top:0}.sucuriscan-maincontent .widefat tbody th.check-column{padding:6px 0 3px 0}.sucuriscan-maincontent .hardening-box .primary-secondary{margin:0 0 0 10px}.sucuriscan-maincontent hr{border:0;border-top:1px solid #999}.sucuriscan-maincontent table td>table{background:#fff}.sucuriscan-maincontent table td>table th{padding:4px 8px}
|
1 |
+
.sucuriscan-malware-payload,.sucuriscan-request-summary td+td,.sucuriscan-wraptext{word-break:break-all}.sucuriscan-wrap *,.sucuriscan-wrap :after,.sucuriscan-wrap :before{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.sucuriscan-clearfix:after,.sucuriscan-clearfix:before{display:table;content:' '}.sucuriscan-clearfix:after{clear:both}.sucuriscan-hidden{display:none!important}.sucuriscan-opacity{opacity:.6}.sucuriscan-monospace{font-family:Menlo,Monaco,monospace,courier}.sucuriscan-ellipsis{overflow:hidden;display:inline-block;white-space:nowrap;text-overflow:ellipsis}.sucuriscan-pull-left{float:left}.sucuriscan-pull-right{float:right}.sucuriscan-list li{list-style:disc;margin:0 0 5px 15px}.sucuriscan-gradient,.sucuriscan-leftside #poststuff h3,.sucuriscan-maincontent .sucuriscan-table tr>th,.sucuriscan-modal-header{background-color:#f1f1f1;background-image:-webkit-gradient(linear,left top,left bottom,from(#f9f9f9),to(#ececec));background-image:-webkit-linear-gradient(top,#f9f9f9,#ececec);background-image:-moz-linear-gradient(top,#f9f9f9,#ececec);background-image:-ms-linear-gradient(top,#f9f9f9,#ececec);background-image:-o-linear-gradient(top,#f9f9f9,#ececec);background-image:linear-gradient(top,#f9f9f9,#ececec);filter:"progid: DXImageTransform.Microsoft.Gradient(startColorstr=#f9f9f9, endColorstr=#ececec)";-ms-filter:"progid: DXImageTransform.Microsoft.Gradient(startColorstr=#f9f9f9, endColorstr=#ececec)"}.wp-core-ui .button-success,.wp-core-ui .button-success.focus,.wp-core-ui .button-success.hover,.wp-core-ui .button-success:focus,.wp-core-ui .button-success:hover,.wp-core-ui .button.button-success.button-hero{-webkit-box-shadow:0 1px 0 #109900;-moz-box-shadow:0 1px 0 #109900;box-shadow:0 1px 0 #109900}.wp-core-ui .button-success,.wp-core-ui .button-success.focus,.wp-core-ui .button-success.hover,.wp-core-ui .button-success:focus,.wp-core-ui .button-success:hover{background:#8dcd5a;border-color:#48a325;box-shadow:0 1px 0 #109900;text-shadow:0 -1px 1px #109900,1px 0 1px #109900,0 1px 1px #109900,-1px 0 1px #109900}.wp-core-ui .button-success.focus,.wp-core-ui .button-success.hover,.wp-core-ui .button-success:focus,.wp-core-ui .button-success:hover{background:#69be48}.wp-core-ui .button-success.focus,.wp-core-ui .button-success:focus{border-color:#23500e}.wp-core-ui .button-success.active,.wp-core-ui .button-success.active:focus,.wp-core-ui .button-success.active:hover,.wp-core-ui .button-success:active{background:#47a61b;border-color:#358400}.wp-core-ui .button-success-disabled,.wp-core-ui .button-success.disabled,.wp-core-ui .button-success:disabled,.wp-core-ui .button-success[disabled]{color:#b2e794!important;background:#74ba29!important;border-color:#3f7f1b!important}.wp-core-ui .button-danger,.wp-core-ui .button-danger.focus,.wp-core-ui .button-danger.hover,.wp-core-ui .button-danger:focus,.wp-core-ui .button-danger:hover,.wp-core-ui .button.button-danger.button-hero{-webkit-box-shadow:0 1px 0 #99000e;-moz-box-shadow:0 1px 0 #99000e;box-shadow:0 1px 0 #99000e}.wp-core-ui .button-danger,.wp-core-ui .button-danger.focus,.wp-core-ui .button-danger.hover,.wp-core-ui .button-danger:focus,.wp-core-ui .button-danger:hover{background:#cd5050;border-color:#a52121;text-shadow:0 -1px 1px #99000e,1px 0 1px #99000e,0 1px 1px #99000e,-1px 0 1px #99000e}.wp-core-ui .button-danger.focus,.wp-core-ui .button-danger.hover,.wp-core-ui .button-danger:focus,.wp-core-ui .button-danger:hover{background:#be4242}.wp-core-ui .button-danger.focus,.wp-core-ui .button-danger:focus{border-color:#500e0e}.wp-core-ui .button-danger.active,.wp-core-ui .button-danger.active:focus,.wp-core-ui .button-danger.active:hover,.wp-core-ui .button-danger:active{background:#a61b1b;border-color:#840000}.wp-core-ui .button-danger-disabled,.wp-core-ui .button-danger.disabled,.wp-core-ui .button-danger:disabled,.wp-core-ui .button-danger[disabled]{color:#e79494!important;background:#ba2929!important;border-color:#7f1b1b!important}.wp-core-ui .sucuriscan-btnblock{display:block;width:100%;text-align:center}.sucuriscan-overlay{position:fixed;top:0;left:0;bottom:0;right:0;z-index:9990;background:#666;background:rgba(0,0,0,.5)}.sucuriscan-modal{position:absolute;top:25px;left:15%;z-index:9990;width:55%}.sucuriscan-modal-outside{position:relative;left:0;border:1px solid #ddd}.sucuriscan-modal-inside{background:#fff;padding:20px}.sucuriscan-modal-header{padding:0;border-bottom:1px solid #ddd}#poststuff h3.sucuriscan-modal-title,.sucuriscan-leftside #poststuff h3.sucuriscan-modal-title,.sucuriscan-modal-header .sucuriscan-modal-title{margin:0 0 0 10px;padding:0;float:left;line-height:38px;border-bottom:0}.sucuriscan-modal-header .sucuriscan-modal-logo{display:inline-block;float:left;margin-top:8px;margin-left:18px}.sucuriscan-modal-header .sucuriscan-modal-logo img{height:22px}.sucuriscan-modal-close{display:inline-block;position:absolute;top:0;right:0;font-size:16px;font-weight:700;text-decoration:none;line-height:38px;padding:0 15px;border-left:1px solid #ddd}.sucuriscan-modal-inside p:first-child{margin-top:0}.postbox .inside p:last-child,.sucuriscan-modal-inside p:last-child{margin-bottom:0}.sucuriscan-label,.sucuriscan-label-danger,.sucuriscan-label-default,.sucuriscan-label-error,.sucuriscan-label-info,.sucuriscan-label-notice,.sucuriscan-label-primary,.sucuriscan-label-success,.sucuriscan-label-unknown,.sucuriscan-label-warning{display:inline;font-size:75%;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;padding:.2em .6em .3em;border-radius:.25em}.sucuriscan-label-default,.sucuriscan-label-unknown{background:#777}.sucuriscan-label-danger,.sucuriscan-label-error{background:#d9534f}.sucuriscan-label-info,.sucuriscan-label-notice{background:#5bc0de}.sucuriscan-label-warning{background:#f0ad4e}.sucuriscan-label-success{background:#5cb85c}.sucuriscan-label-primary{background:#428bca}.sucuriscan-wrap{margin-top:20px}.sucuriscan-wrap .sucuriscan-maincontent{margin:20px 0}.sucuriscan-wrap .sucuriscan-leftside{width:73.5%;float:left}.sucuriscan-wrap .sucuriscan-onecolumn{width:100%}.sucuriscan-wrap .sucuriscan-sidebar{width:25%;float:right}.sucuriscan-wrap #warnings_hook{line-height:normal;padding:0}.sucuriscan-wrap .sucuriscan-navbar{padding-top:20px;padding-left:6px}.sucuriscan-wrap .sucuriscan-navbar .nav-tab{margin-right:0}.sucuriscan-footer,.sucuriscan-header{position:relative;min-width:255px;background:#333;margin:0;padding:10px;border-radius:4px}.sucuriscan-footer .sucuriscan-help{color:#fff;float:right;text-align:right}.sucuriscan-footer .sucuriscan-help p{line-height:38px;margin:0 10px 0 0;padding:0}.sucuriscan-wrap .sucuriscan-footer h2,.sucuriscan-wrap .sucuriscan-header h2,.sucuriscan-wrap .sucuriscan-logo{float:left;margin:0;padding:0}.sucuriscan-wrap .sucuriscan-logo{display:inline-block}.sucuriscan-wrap .sucuriscan-logo img{display:block}.sucuriscan-wrap .sucuriscan-footer h2,.sucuriscan-wrap .sucuriscan-header h2{color:#fff;line-height:38px;margin-left:10px;text-shadow:#000 0 1px 0}.sucuriscan-leftside #poststuff .postbox:last-child{margin-bottom:0}.sucuriscan-leftside #poststuff .postbox h3{margin:0;padding:10px;border-bottom:1px solid #ddd}.sucuriscan-maincontent abbr{text-decoration:underline;cursor:help}.wrap div.sucuriscan-setup-notice{background:#bbe8f5;margin:0 0 20px;padding:0;border:1px solid #bbb;border-radius:3px;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.wrap div.sucuriscan-setup-notice .sucuriscan-setup-image,.wrap div.sucuriscan-setup-notice .sucuriscan-setup-image img{border-radius:3px 0 0 3px}.wrap div.sucuriscan-setup-notice .sucuriscan-setup-image{background:#333;margin:-1px 0 -1px -1px;padding:7px 10px;border-right:1px solid transparent}.wrap div.sucuriscan-setup-notice .sucuriscan-setup-form{padding:4px 4px 4px 0}.wrap div.sucuriscan-setup-notice p{font-size:14px;line-height:20px;margin:0 0 0 10px;padding:7px 0}.wrap div.sucuriscan-setup-notice,.wrap div.sucuriscan-setup-notice .sucuriscan-setup-image{border-color:#4393ac}.wp-core-ui .button.sucuriscan-review-hero,.wp-core-ui .sucuriscan-review-hero{height:initial;line-height:36px;float:right;padding:0 20px}.sucuriscan-input-group>label{display:inline-block;border:1px solid #ddd;border-right:0;line-height:26px;float:left;padding:0 10px;background:#eee}.sucuriscan-input-group>input[type=text]{margin:0;padding-bottom:4px}.sucuriscan-input-group>select{vertical-align:initial;margin:0}.sucuriscan-table-setup td{vertical-align:top}.sucuriscan-table-setup .sucuriscan-description{font-size:12px;margin-top:10px}.sucuriscan-dismiss-setup{font-size:10px;line-height:28px}.sucuriscan-maincontent .sucuriscan-table{margin-top:12px}.sucuriscan-maincontent .sucuriscan-table tr>th{border-top:1px solid #e5e5e5;border-bottom:1px solid #e5e5e5}.sucuriscan-maincontent .sucuriscan-table tr:first-child th{border-top:0}.sucuriscan-maincontent .sucuriscan-table td.check-column{padding:8px 10px}.sucuriscan-maincontent .sucuriscan-striped-table tr:nth-child(even){background:#f5f5f5}.sucuriscan-table-double-title tr:first-child th,.sucuriscan-table-quad-title tr:first-child th,.sucuriscan-table-quad-title tr:first-child+tr th,.sucuriscan-table-quad-title tr:first-child+tr+tr th,.sucuriscan-table-triple-title tr:first-child th,.sucuriscan-table-triple-title tr:first-child+tr th{border-bottom:0}.sucuriscan-table-description{border-left-width:1px!important;box-shadow:none}.sucuriscan-table-description .inside{border-bottom:0!important}.widefat td.td-with-button{text-align:right;padding:3px 10px}.widefat td.td-with-button button{min-width:90px}.widefat td.td-with-button select{height:initial;line-height:initial;vertical-align:top;margin:0;padding:2px 0 3px}.widefat th.check-column{line-height:36px;padding:0}.widefat th.check-column input[type=checkbox]{margin:1px 0 0 10px}.sucuriscan-list-as-table{background:#fff;border:1px solid #e5e5e5}.sucuriscan-list-as-table li{line-height:30px;word-break:break-all;margin:0;padding:0 10px}.sucuriscan-list-as-table li:nth-child(odd){background:#f5f5f5}.sucuriscan-list-as-table-scrollable{height:300px;overflow:hidden;overflow-y:scroll}.sucuriscan-maincontent .thead-with-button{padding:5px 5px 5px 10px}.sucuriscan-maincontent .thead-with-button>span{display:inline-block;line-height:28px}.sucuriscan-maincontent .thead-with-button .input-text{line-height:26px}.sucuriscan-maincontent .thead-with-button select{margin:0;padding:0}.sucuriscan-maincontent .thead-topright-action{display:inline-block;float:right}.sucuriscan-ad{color:#fff;padding:20px;margin-bottom:20px}.sucuriscan-ad .sucuriscan-ad-btn,.sucuriscan-ad h3,.sucuriscan-ad h4{font-family:Arial,Helvetica,sans-serif;color:#fff;margin:0}.sucuriscan-ad h3{font-size:18px;font-weight:300}.sucuriscan-ad h4{font-size:22px;font-weight:700;margin-top:10px}.sucuriscan-ad .sucuriscan-ad-btn{display:block;font-size:13px;font-weight:700;text-align:center;text-decoration:none;text-transform:uppercase;margin-top:20px;padding:5px;border-radius:20px}.sucuriscan-ad .sucuriscan-ad-footer{margin-top:20px;margin-bottom:0}.sucuriscan-ad .sucuriscan-ad-footer ul{margin:0}.sucuriscan-ad .sucuriscan-ad-footer li{font-size:12px;color:#fff;list-style:disc;margin:0 0 0 16px}.sucuriscan-ad .sucuriscan-ad-footer li.featured{color:#fde44c}.sucuriscan-scanner-video{width:100%;background:#fff;border:1px solid #ddd}.sucuriscan-sidebar .sucuriscan-supportbtn{width:100%;height:initial;text-align:center;line-height:36px;margin-top:15px;padding:0}.wp-core-ui .sucuriscan-hide-ads{display:block;color:#666;font-size:11px;text-decoration:underline;margin-top:15px;padding:0}.wp-core-ui .sucuriscan-hide-ads:focus{color:#000;box-shadow:none}.sucuriscan-ad-firewall{background:#606e77}.sucuriscan-ad-firewall .sucuriscan-ad-btn{background:#606e77;border:1px solid #fff}.sucuriscan-ad-firewall .sucuriscan-ad-btn:hover{background:#85929b}.sucuriscan-ad-antivirus{background:#04833e;padding-bottom:0}.sucuriscan-ad-antivirus .sucuriscan-ad-website{display:block;text-decoration:none;margin-top:20px}.sucuriscan-ad-antivirus .sucuriscan-ad-website img{display:block;max-width:100%}.sucuriscan-ad-antivirus .sucuriscan-ad-btn{background-color:#e8840a;background-image:-webkit-gradient(linear,left top,left bottom,from(#e8840a),to(#ef7f02));background-image:-webkit-linear-gradient(top,#e8840a,#ef7f02);background-image:-moz-linear-gradient(top,#e8840a,#ef7f02);background-image:-ms-linear-gradient(top,#e8840a,#ef7f02);background-image:-o-linear-gradient(top,#e8840a,#ef7f02);background-image:linear-gradient(top,#e8840a,#ef7f02);filter:"progid: DXImageTransform.Microsoft.Gradient(startColorstr=#e8840a, endColorstr=#ef7f02)";-ms-filter:"progid: DXImageTransform.Microsoft.Gradient(startColorstr=#e8840a, endColorstr=#ef7f02)";box-shadow:inset 0 1px 1px #eaac3a;border:1px solid #d17301}div.sucuriscan-alert{position:relative;margin:0 0 20px}div.sucuriscan-alert>a.close{position:absolute;top:10px;right:10px;font-size:18px;font-weight:700;text-decoration:none}.sucuriscan-inline-alert,.sucuriscan-inline-alert-error,.sucuriscan-inline-alert-info,.sucuriscan-inline-alert-updated,.sucuriscan-inline-alert-warning{background:#fff;box-shadow:0 1px 1px 0 rgba(0,0,0,.1);padding:0;border-left:4px solid #ddd}.sucuriscan-inline-alert-error>p,.sucuriscan-inline-alert-info>p,.sucuriscan-inline-alert-updated>p,.sucuriscan-inline-alert-warning>p,.sucuriscan-inline-alert>p{margin:0;padding:8px 12px;border:1px solid #ddd;border-left:0}.sucuriscan-inline-alert,.sucuriscan-inline-alert-error,.sucuriscan-inline-alert-info,.sucuriscan-inline-alert-updated,.sucuriscan-inline-alert-warning{margin-bottom:10px}.postbox .inside .sucuriscan-inline-alert-error:last-child,.postbox .inside .sucuriscan-inline-alert-info:last-child,.postbox .inside .sucuriscan-inline-alert-updated:last-child,.postbox .inside .sucuriscan-inline-alert-warning:last-child,.postbox .inside .sucuriscan-inline-alert:last-child,.sucuriscan-tabs>ul li{margin-bottom:0}.sucuriscan-inline-alert-updated{border-left-color:#7ad03a}.sucuriscan-inline-alert-warning{border-left-color:#ffba00}.sucuriscan-inline-alert-error{border-left-color:#dd3d36}.sucuriscan-inline-alert-info{border-left-color:#2ea2cc}.sucuriscan-tabs>ul{margin:0}.sucuriscan-tabs>ul li,.sucuriscan-tabs>ul li>a{display:inline-block}.sucuriscan-tabs>ul li>a{background:#e5e5e5;font-size:13px;font-weight:700;color:#333;line-height:38px;text-decoration:none;padding:0 10px}.sucuriscan-tabs>ul li>a.sucuriscan-tab-active{background:#fff;border:1px solid #e1e1e1;border-bottom:0}.sucuriscan-tabs>ul li.sucuriscan-red-tab a{background:#ff8a83;color:#fff}.sucuriscan-tabs>ul li.sucuriscan-red-tab a.sucuriscan-tab-active{background:#dd3d36;border-color:#dd3d36}.sucuriscan-maincontent .sucuriscan-tab-containers>div>#poststuff,.sucuriscan-maincontent .sucuriscan-tab-containers>div>table{margin-top:0}.sucuriscan-getapi-div{background:#fff;margin:0 0 20px;border:1px solid #e5e5e5;border-radius:3px}.sucuriscan-getapi-div p{margin:0;padding:10px}.sucuriscan-getapi-form button.button-primary{width:100%;height:initial;line-height:30px;margin:0 0 -1px;padding:0;border-radius:0 0 3px 3px}.sucuriscan-malwarescan-message{margin-bottom:20px!important}.sucuriscan-loading{background:#fff;text-align:center;padding:30px 30px 15px;border:1px solid #ddd;border-radius:4px}.sucuriscan-loading h3,.sucuriscan-loading p{margin:0;padding:0}.sucuriscan-loading .title{font-size:28px;margin-bottom:10px}.sucuriscan-loading .description{font-size:16px}.sucuriscan-sitelogo{width:190px;height:100px;background:url(https://sitecheck.sucuri.net/images/sucuri-sprite.png) no-repeat;margin:0 auto}.sucuriscan-sitecheck-form{margin:20px 0 0}.sucuriscan-sitecheck-form .button.button-hero{padding:0 46px}.sucuriscan-loading .sucuriscan-sitecheck-disclaimer{text-align:justify;padding-top:20px;border-top:1px solid #ddd}.sucuriscan-auditlogs .sucuriscan-maxper-page,.sucuriscan-scanner-results .sucuriscan-malware-link{text-align:right}.sucuriscan-loading .sucuriscan-sitecheck-disclaimer p{font-size:10px}.sucuriscan-maincontent .sucuriscan-border{border:0;border-left:4px solid #ddd}.sucuriscan-maincontent .sucuriscan-border>.inside,.sucuriscan-maincontent .sucuriscan-border>h3{border-top:1px solid #e5e5e5;border-right:1px solid #e5e5e5}.sucuriscan-maincontent .sucuriscan-border>h3{border-bottom:0}.sucuriscan-maincontent .sucuriscan-border>.inside{margin-top:0!important;border-bottom:1px solid #ddd}.sucuriscan-maincontent .sucuriscan-border-good,.sucuriscan-maincontent .sucuriscan-border-success{border-left-color:#7ad03a}.sucuriscan-maincontent .sucuriscan-border-bad,.sucuriscan-maincontent .sucuriscan-border-danger{border-left-color:#dd3d36}.sucuriscan-maincontent .sucuriscan-border-info{border-left-color:#2ea2cc}.sucuriscan-maincontent .sucuriscan-cleanup-btn{margin:20px 0 0}.sucuriscan-scanner-results .sucuriscan-scanner-details tr:nth-child(even),.sucuriscan-scanner-results .sucuriscan-scanner-links tr:nth-child(even){background:#f5f5f5}.sucuriscan-scanner-results td.sucuriscan-border-bad{border-left-width:4px;border-left-style:solid}.sucuriscan-scanner-results .sucuriscan-malware-link a:hover{color:#fff}.sucuriscan-malware-payload{background:#f5f5f5;margin:-2px -15px -15px;padding:15px}.sucuriscan-maincontent .sucuriscan-auditlogs,.sucuriscan-maincontent .sucuriscan-corefiles,.sucuriscan-maincontent .sucuriscan-wordpress-outdated{margin-top:0;margin-bottom:20px}.sucuriscan-auditlogs .sucuriscan-list-as-table,.sucuriscan-maincontent .sucuriscan-auditlogs{margin-bottom:0}.sucuriscan-auditlogs .sucuriscan-label{display:inline-block;width:18px;text-transform:uppercase;line-height:13px;cursor:pointer;border-radius:50%}.sucuriscan-auditlogs .sucuriscan-auditlog-success,.sucuriscan-label-added{background:#5cb85c}.sucuriscan-auditlogs .sucuriscan-auditlog-debug{background:#c690ec}.sucuriscan-auditlogs .sucuriscan-auditlog-info{background:#5bc0de}.sucuriscan-auditlogs .sucuriscan-auditlog-notice{background:#428bca}.sucuriscan-auditlogs .sucuriscan-auditlog-warning,.sucuriscan-label-modified{background:#f0ad4e}.sucuriscan-auditlogs .sucuriscan-auditlog-error,.sucuriscan-label-removed{background:#f27d7d}.sucuriscan-auditlogs .sucuriscan-auditlog-critical{background:#000}.sucuriscan-maincontent .sucuriscan-audit-report{border-left-width:1px}.sucuriscan-audit-report .sucuriscan-report-row{margin-bottom:10px}.sucuriscan-audit-report .sucuriscan-report-row:last-child,.sucuriscan-maincontent .sucuriscan-corefiles{margin-bottom:0}.sucuriscan-audit-report .sucuriscan-report-chart{width:49%;border:1px solid #ddd}.sucuriscan-audit-report .sucuriscan-report-chart h4,.sucuriscan-audit-report .sucuriscan-report-chart h5{font-weight:400;text-align:center;margin:0}.sucuriscan-firewall-accesslog .sucuriscan-accesslog-label,.sucuriscan-request-summary tr td:first-child{font-weight:700}.sucuriscan-audit-report .sucuriscan-report-chart h4{font-size:18px;margin-top:10px}.sucuriscan-audit-report .sucuriscan-report-chart h5{font-size:12px;margin-top:5px}.sucuriscan-firewall-auditlogs .sucuriscan-denial-type,.sucuriscan-request-summary td{font-size:14px}.sucuriscan-maincontent .sucuriscan-audit-report .sucuriscan-inline-alert-info{margin-top:10px}.sucuriscan-status-type{display:inline-block;width:20px;background:#ddd;text-align:center;text-transform:uppercase;margin-right:10px;padding:0 3px;border:1px solid transparent;border-radius:3px}.sucuriscan-maincontent .sucuriscan-corefiles .sucuriscan-label{text-transform:capitalize}.sucuriscan-maincontent .sucuriscan-ignoredfiles{margin-top:0}.sucuriscan-ignore-file form{padding:0 10px 10px;border-bottom:1px solid #ddd;border-right:1px solid #ddd}.sucuriscan-ignore-file p{border-bottom:none}.sucuriscan-ignore-file-input{width:80%}.sucuriscan-ignore-file-button{width:18%}.sucuriscan-maincontent .sucuriscan-modifiedfiles .sucuriscan-ellipsis{width:100px}.sucuriscan-maincontent .sucuriscan-firewall-apikey{margin-bottom:10px}.sucuriscan-firewall-settings .sucuriscan-list-as-table{margin-top:4px;margin-bottom:4px}.sucuriscan-firewall-auditlogs .thead-with-button .button{width:65px}.sucuriscan-firewall-auditlogs .thead-with-button .input-text,.sucuriscan-firewall-auditlogs .thead-with-button select{width:250px}.sucuriscan-firewall-auditlogs .sucuriscan-denial-type-date{font-style:italic;color:#999}.sucuriscan-firewall-auditlogs .sucuriscan-alert,.wrap .sucuriscan-firewall-auditlogs .error,.wrap .sucuriscan-firewall-auditlogs .updated{background:#eee;border:1px solid #ddd;border-left-width:4px;margin:10px}.sucuriscan-firewall-accesslog .sucuriscan-accesslog-origin img{margin-right:6px}.sucuriscan-firewall-accesslog .sucuriscan-accesslog-datetime,.sucuriscan-firewall-accesslog .sucuriscan-accesslog-origin,.sucuriscan-firewall-accesslog .sucuriscan-accesslog-referer,.sucuriscan-firewall-accesslog .sucuriscan-accesslog-request,.sucuriscan-firewall-accesslog .sucuriscan-accesslog-signature,.sucuriscan-firewall-accesslog .sucuriscan-accesslog-target,.sucuriscan-firewall-accesslog .sucuriscan-accesslog-useragent{display:block;padding-left:30px}.sucuriscan-firewall-accesslog .sucuriscan-accesslog-origin{padding-left:0}.sucuriscan-request-summary{margin:-3px -15px -15px}.sucuriscan-hstatus{position:relative;margin:0 -12px;padding:10px 12px;border:1px solid transparent}.sucuriscan-hstatus-0{background-color:#f2dede;color:#a94442;border-color:#ebccd1}.sucuriscan-hstatus-1{background-color:#dff0d8;color:#3c763d;border-color:#d6e9c6}.sucuriscan-hstatus-2{background-color:#dee4f2;color:#4263a9;border-color:#ccd0eb}.sucuriscan-hstatus .button-primary,.sucuriscan-hstatus .button-secondary{position:absolute;top:5px;right:5px}.sucuriscan-hardening .postbox .inside pre{background:#eaeaea;padding:10px}.sucuriscan-hardening-whitelist form{margin-top:15px}.sucuriscan-hardening-whitelist form label{line-height:29px;font-size:12px;background-color:#eee;padding:0 10px;display:inline-block;border:1px solid #ddd;border-right:0}.sucuriscan-hardening-whitelist form input[type=text]{margin:0;padding:5px}.sucuriscan-hardening-whitelist form select{height:initial;padding:4px;margin:0}.sucuriscan-hardening-whitelist form .button,.sucuriscan-hardening-whitelist form input[type=text],.sucuriscan-hardening-whitelist form select{margin-right:5px}.sucuriscan-maincontent .sucuriscan-table.sucuriscan-hardening-whitelist-table{margin-top:0}.sucuriscan-lastlogin-outof{font-style:italic;color:#999;margin-right:10px}.sucuriscan-admins-lastlogins .sucuriscan-ellipsis{width:170px}.sucuriscan-admins-lastlogins td{padding:4px 8px}.sucuriscan-pattern-search-inputbox{margin-top:12px}.sucuriscan-pattern-search-inputbox .input-text{width:84.7777%;line-height:30px;margin:0 6px 0 0}.sucuriscan-pattern-search-inputbox .input-button{width:14%;height:initial;line-height:35px}.sucuriscan-pattern-search .sucuriscan-cleanup-btn{margin-top:12px}.sucuriscan-pattern-search table label{color:#999}.sucuriscan-pattern-search .sucuriscan-grep-text em{color:#ea3838}.sucuriscan-about ul{margin-left:20px}.sucuriscan-about ul li{list-style:outside}.sucuriscan-about li label{font-weight:700;vertical-align:initial}.sucuriscan-apikey-registered .sucuriscan-pull-right{width:400px}.sucuriscan-apikey-registered .sucuriscan-sitelogo{background-position:0 -17px;height:83px}.sucuriscan-setup-instructions .form-table{margin-top:15px}.sucuriscan-setup-instructions .form-table td{padding:0 0 12px}.sucuriscan-setup-instructions .form-table select{max-width:400px}.sucuriscan-pagination{display:inline-block;margin:0;padding:0;border-radius:4px}.sucuriscan-pagination>li{display:inline}.c3-tooltip td>span,.sucuriscan-maincontent .sucuriscan-settings form{display:inline-block}.sucuriscan-pagination>li>a,.sucuriscan-pagination>li>span{position:relative;background:#fff;color:#428bca;line-height:1.42857143;text-decoration:none;float:left;margin-left:-1px;padding:6px 12px;border:1px solid #ddd}.sucuriscan-pagination>li:first-child>a,.sucuriscan-pagination>li:first-child>span{margin-left:0;border-radius:4px 0 0 4px}.sucuriscan-pagination>li:last-child>a,.sucuriscan-pagination>li:last-child>span{border-radius:0 4px 4px 0}.sucuriscan-pagination>li>a.sucuriscan-pagination-active,.sucuriscan-pagination>li>a:hover{background:#0074a2;color:#fff}.sucuriscan_wpconfig_keys_updated textarea{width:100%;height:250px;background:#f5f5f5;font-size:12px;resize:vertical;margin:20px 0 0}.sucuriscan-maincontent .sucuriscan-last-logins,.sucuriscan-maincontent .sucuriscan-settings{margin-top:0}.sucuriscan-maincontent .sucuriscan-last-logins .sucuriscan-ellipsis{width:150px;line-height:inherit}.sucuriscan-maincontent .sucuriscan-full-textarea{width:100%;height:400px;line-height:normal;resize:vertical;padding:10px}.sucuriscan-maincontent .sucuriscan-settings .input-text,.sucuriscan-maincontent .sucuriscan-settings select{width:220px;margin:0}.sucuriscan-maincontent .sucuriscan-infosys-htaccess .inside .sucuriscan-inline-alert-updated,.sucuriscan-maincontent .sucuriscan-monitor-fpath{margin-bottom:10px}.sucuriscan-maincontent .sucuriscan-recipient-form{margin-top:10px}.sucuriscan-maincontent .sucuriscan-settings-ignorescanning,.sucuriscan-maincontent .sucuriscan-settings-notifications,.sucuriscan-maincontent .sucuriscan-settings-trustip,.sucuriscan-maincontent .sucuriscan-wpcron-list{margin-top:0}.sucuriscan-maincontent .sucuriscan-settings-notifications .dashicons-before:before{margin-right:5px}.sucuriscan-maincontent .sucuriscan-infosys-htaccess .inside{border-bottom:1px solid #ddd!important}.sucuriscan-maincontent .sucuriscan-errorlogs .inside .sucuriscan-inline-alert-error{margin-top:10px}.sucuriscan-maincontent .sucuriscan-subject-formats{margin:0}.sucuriscan-maincontent .sucuriscan-subject-formats input[type=text]{width:40%;margin-left:10px}.sucuriscan-flag{width:16px;height:11px;background:url(../images/flags.sprite.png) no-repeat}.sucuriscan-flag-ad{background-position:-16px 0}.sucuriscan-flag-ae{background-position:-32px 0}.sucuriscan-flag-af{background-position:-48px 0}.sucuriscan-flag-ag{background-position:-64px 0}.sucuriscan-flag-ai{background-position:-80px 0}.sucuriscan-flag-al{background-position:-96px 0}.sucuriscan-flag-am{background-position:-112px 0}.sucuriscan-flag-an{background-position:-128px 0}.sucuriscan-flag-ao{background-position:-144px 0}.sucuriscan-flag-ar{background-position:-160px 0}.sucuriscan-flag-as{background-position:-176px 0}.sucuriscan-flag-at{background-position:-192px 0}.sucuriscan-flag-au{background-position:-208px 0}.sucuriscan-flag-aw{background-position:-224px 0}.sucuriscan-flag-az{background-position:-240px 0}.sucuriscan-flag-ba{background-position:0 -11px}.sucuriscan-flag-bb{background-position:-16px -11px}.sucuriscan-flag-bd{background-position:-32px -11px}.sucuriscan-flag-be{background-position:-48px -11px}.sucuriscan-flag-bf{background-position:-64px -11px}.sucuriscan-flag-bg{background-position:-80px -11px}.sucuriscan-flag-bh{background-position:-96px -11px}.sucuriscan-flag-bi{background-position:-112px -11px}.sucuriscan-flag-bj{background-position:-128px -11px}.sucuriscan-flag-bm{background-position:-144px -11px}.sucuriscan-flag-bn{background-position:-160px -11px}.sucuriscan-flag-bo{background-position:-176px -11px}.sucuriscan-flag-br{background-position:-192px -11px}.sucuriscan-flag-bs{background-position:-208px -11px}.sucuriscan-flag-bt{background-position:-224px -11px}.sucuriscan-flag-bv{background-position:-240px -11px}.sucuriscan-flag-bw{background-position:0 -22px}.sucuriscan-flag-by{background-position:-16px -22px}.sucuriscan-flag-bz{background-position:-32px -22px}.sucuriscan-flag-ca{background-position:-48px -22px}.sucuriscan-flag-catalonia{background-position:-64px -22px}.sucuriscan-flag-cd{background-position:-80px -22px}.sucuriscan-flag-cf{background-position:-96px -22px}.sucuriscan-flag-cg{background-position:-112px -22px}.sucuriscan-flag-ch{background-position:-128px -22px}.sucuriscan-flag-ci{background-position:-144px -22px}.sucuriscan-flag-ck{background-position:-160px -22px}.sucuriscan-flag-cl{background-position:-176px -22px}.sucuriscan-flag-cm{background-position:-192px -22px}.sucuriscan-flag-cn{background-position:-208px -22px}.sucuriscan-flag-co{background-position:-224px -22px}.sucuriscan-flag-cr{background-position:-240px -22px}.sucuriscan-flag-cu{background-position:0 -33px}.sucuriscan-flag-cv{background-position:-16px -33px}.sucuriscan-flag-cw{background-position:-32px -33px}.sucuriscan-flag-cy{background-position:-48px -33px}.sucuriscan-flag-cz{background-position:-64px -33px}.sucuriscan-flag-de{background-position:-80px -33px}.sucuriscan-flag-dj{background-position:-96px -33px}.sucuriscan-flag-dk{background-position:-112px -33px}.sucuriscan-flag-dm{background-position:-128px -33px}.sucuriscan-flag-do{background-position:-144px -33px}.sucuriscan-flag-dz{background-position:-160px -33px}.sucuriscan-flag-ec{background-position:-176px -33px}.sucuriscan-flag-ee{background-position:-192px -33px}.sucuriscan-flag-eg{background-position:-208px -33px}.sucuriscan-flag-eh{background-position:-224px -33px}.sucuriscan-flag-england{background-position:-240px -33px}.sucuriscan-flag-er{background-position:0 -44px}.sucuriscan-flag-es{background-position:-16px -44px}.sucuriscan-flag-et{background-position:-32px -44px}.sucuriscan-flag-eu{background-position:-48px -44px}.sucuriscan-flag-fi{background-position:-64px -44px}.sucuriscan-flag-fj{background-position:-80px -44px}.sucuriscan-flag-fk{background-position:-96px -44px}.sucuriscan-flag-fm{background-position:-112px -44px}.sucuriscan-flag-fo{background-position:-128px -44px}.sucuriscan-flag-fr{background-position:-144px -44px}.sucuriscan-flag-ga{background-position:-160px -44px}.sucuriscan-flag-gb{background-position:-176px -44px}.sucuriscan-flag-gd{background-position:-192px -44px}.sucuriscan-flag-ge{background-position:-208px -44px}.sucuriscan-flag-gf{background-position:-224px -44px}.sucuriscan-flag-gg{background-position:-240px -44px}.sucuriscan-flag-gh{background-position:0 -55px}.sucuriscan-flag-gi{background-position:-16px -55px}.sucuriscan-flag-gl{background-position:-32px -55px}.sucuriscan-flag-gm{background-position:-48px -55px}.sucuriscan-flag-gn{background-position:-64px -55px}.sucuriscan-flag-gp{background-position:-80px -55px}.sucuriscan-flag-gq{background-position:-96px -55px}.sucuriscan-flag-gr{background-position:-112px -55px}.sucuriscan-flag-gs{background-position:-128px -55px}.sucuriscan-flag-gt{background-position:-144px -55px}.sucuriscan-flag-gu{background-position:-160px -55px}.sucuriscan-flag-gw{background-position:-176px -55px}.sucuriscan-flag-gy{background-position:-192px -55px}.sucuriscan-flag-hk{background-position:-208px -55px}.sucuriscan-flag-hm{background-position:-224px -55px}.sucuriscan-flag-hn{background-position:-240px -55px}.sucuriscan-flag-hr{background-position:0 -66px}.sucuriscan-flag-ht{background-position:-16px -66px}.sucuriscan-flag-hu{background-position:-32px -66px}.sucuriscan-flag-ic{background-position:-48px -66px}.sucuriscan-flag-id{background-position:-64px -66px}.sucuriscan-flag-ie{background-position:-80px -66px}.sucuriscan-flag-il{background-position:-96px -66px}.sucuriscan-flag-im{background-position:-112px -66px}.sucuriscan-flag-in{background-position:-128px -66px}.sucuriscan-flag-io{background-position:-144px -66px}.sucuriscan-flag-iq{background-position:-160px -66px}.sucuriscan-flag-ir{background-position:-176px -66px}.sucuriscan-flag-is{background-position:-192px -66px}.sucuriscan-flag-it{background-position:-208px -66px}.sucuriscan-flag-je{background-position:-224px -66px}.sucuriscan-flag-jm{background-position:-240px -66px}.sucuriscan-flag-jo{background-position:0 -77px}.sucuriscan-flag-jp{background-position:-16px -77px}.sucuriscan-flag-ke{background-position:-32px -77px}.sucuriscan-flag-kg{background-position:-48px -77px}.sucuriscan-flag-kh{background-position:-64px -77px}.sucuriscan-flag-ki{background-position:-80px -77px}.sucuriscan-flag-km{background-position:-96px -77px}.sucuriscan-flag-kn{background-position:-112px -77px}.sucuriscan-flag-kp{background-position:-128px -77px}.sucuriscan-flag-kr{background-position:-144px -77px}.sucuriscan-flag-kurdistan{background-position:-160px -77px}.sucuriscan-flag-kw{background-position:-176px -77px}.sucuriscan-flag-ky{background-position:-192px -77px}.sucuriscan-flag-kz{background-position:-208px -77px}.sucuriscan-flag-la{background-position:-224px -77px}.sucuriscan-flag-lb{background-position:-240px -77px}.sucuriscan-flag-lc{background-position:0 -88px}.sucuriscan-flag-li{background-position:-16px -88px}.sucuriscan-flag-lk{background-position:-32px -88px}.sucuriscan-flag-lr{background-position:-48px -88px}.sucuriscan-flag-ls{background-position:-64px -88px}.sucuriscan-flag-lt{background-position:-80px -88px}.sucuriscan-flag-lu{background-position:-96px -88px}.sucuriscan-flag-lv{background-position:-112px -88px}.sucuriscan-flag-ly{background-position:-128px -88px}.sucuriscan-flag-ma{background-position:-144px -88px}.sucuriscan-flag-mc{background-position:-160px -88px}.sucuriscan-flag-md{background-position:-176px -88px}.sucuriscan-flag-me{background-position:-192px -88px}.sucuriscan-flag-mg{background-position:-208px -88px}.sucuriscan-flag-mh{background-position:-224px -88px}.sucuriscan-flag-mk{background-position:-240px -88px}.sucuriscan-flag-ml{background-position:0 -99px}.sucuriscan-flag-mm{background-position:-16px -99px}.sucuriscan-flag-mn{background-position:-32px -99px}.sucuriscan-flag-mo{background-position:-48px -99px}.sucuriscan-flag-mp{background-position:-64px -99px}.sucuriscan-flag-mq{background-position:-80px -99px}.sucuriscan-flag-mr{background-position:-96px -99px}.sucuriscan-flag-ms{background-position:-112px -99px}.sucuriscan-flag-mt{background-position:-128px -99px}.sucuriscan-flag-mu{background-position:-144px -99px}.sucuriscan-flag-mv{background-position:-160px -99px}.sucuriscan-flag-mw{background-position:-176px -99px}.sucuriscan-flag-mx{background-position:-192px -99px}.sucuriscan-flag-my{background-position:-208px -99px}.sucuriscan-flag-mz{background-position:-224px -99px}.sucuriscan-flag-na{background-position:-240px -99px}.sucuriscan-flag-nc{background-position:0 -110px}.sucuriscan-flag-ne{background-position:-16px -110px}.sucuriscan-flag-nf{background-position:-32px -110px}.sucuriscan-flag-ng{background-position:-48px -110px}.sucuriscan-flag-ni{background-position:-64px -110px}.sucuriscan-flag-nl{background-position:-80px -110px}.sucuriscan-flag-no{background-position:-96px -110px}.sucuriscan-flag-np{background-position:-112px -110px}.sucuriscan-flag-nr{background-position:-128px -110px}.sucuriscan-flag-nu{background-position:-144px -110px}.sucuriscan-flag-nz{background-position:-160px -110px}.sucuriscan-flag-om{background-position:-176px -110px}.sucuriscan-flag-pa{background-position:-192px -110px}.sucuriscan-flag-pe{background-position:-208px -110px}.sucuriscan-flag-pf{background-position:-224px -110px}.sucuriscan-flag-pg{background-position:-240px -110px}.sucuriscan-flag-ph{background-position:0 -121px}.sucuriscan-flag-pk{background-position:-16px -121px}.sucuriscan-flag-pl{background-position:-32px -121px}.sucuriscan-flag-pm{background-position:-48px -121px}.sucuriscan-flag-pn{background-position:-64px -121px}.sucuriscan-flag-pr{background-position:-80px -121px}.sucuriscan-flag-ps{background-position:-96px -121px}.sucuriscan-flag-pt{background-position:-112px -121px}.sucuriscan-flag-pw{background-position:-128px -121px}.sucuriscan-flag-py{background-position:-144px -121px}.sucuriscan-flag-qa{background-position:-160px -121px}.sucuriscan-flag-re{background-position:-176px -121px}.sucuriscan-flag-ro{background-position:-192px -121px}.sucuriscan-flag-rs{background-position:-208px -121px}.sucuriscan-flag-ru{background-position:-224px -121px}.sucuriscan-flag-rw{background-position:-240px -121px}.sucuriscan-flag-sa{background-position:0 -132px}.sucuriscan-flag-sb{background-position:-16px -132px}.sucuriscan-flag-sc{background-position:-32px -132px}.sucuriscan-flag-scotland{background-position:-48px -132px}.sucuriscan-flag-sd{background-position:-64px -132px}.sucuriscan-flag-se{background-position:-80px -132px}.sucuriscan-flag-sg{background-position:-96px -132px}.sucuriscan-flag-sh{background-position:-112px -132px}.sucuriscan-flag-si{background-position:-128px -132px}.sucuriscan-flag-sk{background-position:-144px -132px}.sucuriscan-flag-sl{background-position:-160px -132px}.sucuriscan-flag-sm{background-position:-176px -132px}.sucuriscan-flag-sn{background-position:-192px -132px}.sucuriscan-flag-so{background-position:-208px -132px}.sucuriscan-flag-somaliland{background-position:-224px -132px}.sucuriscan-flag-sr{background-position:-240px -132px}.sucuriscan-flag-ss{background-position:0 -143px}.sucuriscan-flag-st{background-position:-16px -143px}.sucuriscan-flag-sv{background-position:-32px -143px}.sucuriscan-flag-sx{background-position:-48px -143px}.sucuriscan-flag-sy{background-position:-64px -143px}.sucuriscan-flag-sz{background-position:-80px -143px}.sucuriscan-flag-tc{background-position:-96px -143px}.sucuriscan-flag-td{background-position:-112px -143px}.sucuriscan-flag-tf{background-position:-128px -143px}.sucuriscan-flag-tg{background-position:-144px -143px}.sucuriscan-flag-th{background-position:-160px -143px}.sucuriscan-flag-tj{background-position:-176px -143px}.sucuriscan-flag-tk{background-position:-192px -143px}.sucuriscan-flag-tl{background-position:-208px -143px}.sucuriscan-flag-tm{background-position:-224px -143px}.sucuriscan-flag-tn{background-position:-240px -143px}.sucuriscan-flag-to{background-position:0 -154px}.sucuriscan-flag-tr{background-position:-16px -154px}.sucuriscan-flag-tt{background-position:-32px -154px}.sucuriscan-flag-tv{background-position:-48px -154px}.sucuriscan-flag-tw{background-position:-64px -154px}.sucuriscan-flag-tz{background-position:-80px -154px}.sucuriscan-flag-ua{background-position:-96px -154px}.sucuriscan-flag-ug{background-position:-112px -154px}.sucuriscan-flag-um{background-position:-128px -154px}.sucuriscan-flag-us{background-position:-144px -154px}.sucuriscan-flag-uy{background-position:-160px -154px}.sucuriscan-flag-uz{background-position:-176px -154px}.sucuriscan-flag-va{background-position:-192px -154px}.sucuriscan-flag-vc{background-position:-208px -154px}.sucuriscan-flag-ve{background-position:-224px -154px}.sucuriscan-flag-vg{background-position:-240px -154px}.sucuriscan-flag-vi{background-position:0 -165px}.sucuriscan-flag-vn{background-position:-16px -165px}.sucuriscan-flag-vu{background-position:-32px -165px}.sucuriscan-flag-wales{background-position:-48px -165px}.sucuriscan-flag-wf{background-position:-64px -165px}.sucuriscan-flag-ws{background-position:-80px -165px}.sucuriscan-flag-ye{background-position:-96px -165px}.sucuriscan-flag-yt{background-position:-112px -165px}.sucuriscan-flag-za{background-position:-128px -165px}.sucuriscan-flag-zanzibar{background-position:-144px -165px}.sucuriscan-flag-zm{background-position:-160px -165px}.sucuriscan-flag-zw{background-position:-176px -165px}.c3 svg{font:10px sans-serif}.c3 line,.c3 path{fill:none;stroke:#000}.c3 text{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.c3-bars path,.c3-event-rect,.c3-legend-item-tile,.c3-xgrid-focus,.c3-ygrid{shape-rendering:crispEdges}.c3-chart-arc path{stroke:#fff}.c3-chart-arc text{fill:#fff;font-size:13px}.c3-grid line{stroke:#aaa}.c3-grid text{fill:#aaa}.c3-xgrid,.c3-ygrid{stroke-dasharray:3 3}.c3-text.c3-empty{fill:gray;font-size:2em}.c3-line{stroke-width:1px}.c3-circle._expanded_{stroke-width:1px;stroke:#fff}.c3-selected-circle{fill:#fff;stroke-width:2px}.c3-bar{stroke-width:0}.c3-bar._expanded_{fill-opacity:.75}.c3-chart-arcs-title{dominant-baseline:middle;font-size:1.3em}.c3-target.c3-focused{opacity:1}.c3-target.c3-focused path.c3-line,.c3-target.c3-focused path.c3-step{stroke-width:2px}.c3-target.c3-defocused{opacity:.3!important}.c3-region{fill:#4682b4;fill-opacity:.1}.c3-brush .extent{fill-opacity:.1}.c3-legend-item{font-size:12px}.c3-legend-item-hidden{opacity:.15}.c3-legend-background{opacity:.75;fill:#fff;stroke:#d3d3d3;stroke-width:1}.c3-tooltip-container{z-index:10}.c3-tooltip{border-collapse:collapse;border-spacing:0;background-color:#fff;empty-cells:show;-webkit-box-shadow:7px 7px 12px -9px #777;-moz-box-shadow:7px 7px 12px -9px #777;box-shadow:7px 7px 12px -9px #777}.c3-tooltip tr{border:1px solid #CCC}.c3-tooltip th{background-color:#aaa;font-size:14px;padding:2px 5px;text-align:left;color:#FFF}.c3-tooltip td{font-size:13px;padding:3px 6px;background-color:#fff;border-left:1px dotted #999}.c3-tooltip td>span{width:10px;height:10px;margin-right:6px}.c3-tooltip td.value{text-align:right}.c3-area{stroke-width:0;opacity:.2}.c3-chart-arcs .c3-chart-arcs-background{fill:#e0e0e0;stroke:none}.c3-chart-arcs .c3-chart-arcs-gauge-unit{fill:#000;font-size:16px}.c3-chart-arcs .c3-chart-arcs-gauge-max,.c3-chart-arcs .c3-chart-arcs-gauge-min{fill:#777}.c3-chart-arc .c3-gauge-value{fill:#000}@media (max-width:510px){.wp-core-ui .button.sucuriscan-review-hero,.wp-core-ui .sucuriscan-review-hero{display:none}}@media (max-width:620px){.sucuriscan-tabs>ul li,.sucuriscan-tabs>ul li>a{display:block}.sucuriscan-getapi-form button.button-primary{line-height:40px}}@media (max-width:768px){.sucuriscan-wrap .sucuriscan-footer .sucuriscan-help,.sucuriscan-wrap .sucuriscan-footer .sucuriscan-logo,.sucuriscan-wrap .sucuriscan-leftside,.sucuriscan-wrap .sucuriscan-sidebar{float:none}.sucuriscan-wrap .sucuriscan-leftside,.sucuriscan-wrap .sucuriscan-sidebar{width:100%}.sucuriscan-wrap .sucuriscan-sidebar{margin-top:20px}.sucuriscan-wrap .sucuriscan-footer .sucuriscan-logo{display:table;margin:0 auto}}@media (max-width:920px){.sucuriscan-wrap .sucuriscan-navbar{padding-left:0;padding-right:0}.sucuriscan-wrap .sucuriscan-navbar .nav-tab{display:block;line-height:20px;margin:0}.sucuriscan-wrap .sucuriscan-navbar .nav-tab:last-child{border-bottom:1px solid #ccc}}@media (min-width:600px) and (max-width:1060px){.sucuriscan-wrap .sucuriscan-leftside,.sucuriscan-wrap .sucuriscan-sidebar{width:initial;float:none}.sucuriscan-wrap .sucuriscan-sidebar{margin-top:20px}.sucuriscan-wrap .sucuriscan-sidebar>div{width:49%;float:left;min-height:339px}.sucuriscan-wrap .sucuriscan-sidebar .sucuriscan-ad-antivirus{margin-left:2%}.sucuriscan-wrap .sucuriscan-scanner-video{height:450px}}.sucuriscan-maincontent #poststuff{min-width:initial;padding-top:0}.sucuriscan-maincontent .widefat tbody th.check-column{padding:6px 0 3px}.sucuriscan-maincontent .hardening-box .primary-secondary{margin:0 0 0 10px}.sucuriscan-maincontent hr{border:none;border-top:1px solid #999}.sucuriscan-maincontent table td>table{background:#fff}.sucuriscan-maincontent table td>table th{padding:4px 8px}
|
inc/images/blank.png
ADDED
Binary file
|
inc/images/flags.sprite.png
ADDED
Binary file
|
inc/js/sucuri-scanner.min.js
CHANGED
@@ -1 +1 @@
|
|
1 |
-
function sucuriscan_alert_close(b){var a=document.getElementById("sucuriscan-alert-"+b);a.parentNode.removeChild(a)}jQuery(document).ready(function(c){c(".sucuriscan-modal-btn").on("click",function(e){e.preventDefault();var f=c(this).data("modalid");c("div."+f).removeClass("sucuriscan-hidden")});c(".sucuriscan-overlay, .sucuriscan-modal-close").on("click",function(e){e.preventDefault();c(".sucuriscan-overlay").addClass("sucuriscan-hidden");c(".sucuriscan-modal").addClass("sucuriscan-hidden")});if(c(".sucuriscan-tabs").length){var d="sucuriscan-hidden";var b="sucuriscan-tab-active";var a=location.href.split("#")[1];c(".sucuriscan-tabs > ul a").on("click",function(k){k.preventDefault();var h=c(this);var j=h.data("tabname");var f=c(".sucuriscan-tab-containers > #sucuriscan-"+j);if(f.length){var g=location.href.replace(location.hash,"");var i=g+"#"+j;window.history.pushState({},document.title,i);c(".sucuriscan-tabs > ul a").removeClass(b);c(".sucuriscan-tab-containers > div").addClass(d);h.addClass(b);f.removeClass(d)}});c(".sucuriscan-tab-containers > div").addClass(d);if(a
|
1 |
+
function sucuriscan_alert_close(b){var a=document.getElementById("sucuriscan-alert-"+b);a.parentNode.removeChild(a)}jQuery(document).ready(function(c){c(".sucuriscan-modal-btn").on("click",function(e){e.preventDefault();var f=c(this).data("modalid");c("div."+f).removeClass("sucuriscan-hidden")});c(".sucuriscan-overlay, .sucuriscan-modal-close").on("click",function(e){e.preventDefault();c(".sucuriscan-overlay").addClass("sucuriscan-hidden");c(".sucuriscan-modal").addClass("sucuriscan-hidden")});if(c(".sucuriscan-tabs").length){var d="sucuriscan-hidden";var b="sucuriscan-tab-active";var a=location.href.split("#")[1];c(".sucuriscan-tabs > ul a").on("click",function(k){k.preventDefault();var h=c(this);var j=h.data("tabname");var f=c(".sucuriscan-tab-containers > #sucuriscan-"+j);if(f.length){var g=location.href.replace(location.hash,"");var i=g+"#"+j;window.history.pushState({},document.title,i);c(".sucuriscan-tabs > ul a").removeClass(b);c(".sucuriscan-tab-containers > div").addClass(d);h.addClass(b);f.removeClass(d)}});c(".sucuriscan-tab-containers > div").addClass(d);if(a!==undefined){c(".sucuriscan-tabs > ul li a").each(function(e,f){if(c(f).data("tabname")===a){c(f).trigger("click")}})}else{c(".sucuriscan-tabs > ul li:first-child a").trigger("click")}}c("body").on("click",".sucuriscan-corefiles .manage-column :checkbox",function(e){c(".sucuriscan-corefiles tbody :checkbox").each(function(g,h){var f=c(h).is(":checked");c(h).attr("checked",!f)})})});
|
inc/tpl/base.html.tpl
CHANGED
@@ -4,40 +4,39 @@
|
|
4 |
<h2 id="warnings_hook"></h2>
|
5 |
|
6 |
<div class="sucuriscan-header sucuriscan-clearfix">
|
7 |
-
<a href="
|
8 |
<img src="%%SUCURI.SucuriURL%%/inc/images/logo.png" alt="Sucuri Security" />
|
9 |
</a>
|
10 |
<h2>Sucuri Security %%SUCURI.PageTitle%%</h2>
|
|
|
|
|
11 |
</div>
|
12 |
|
13 |
<h2 class="nav-tab-wrapper sucuriscan-navbar">
|
14 |
-
|
15 |
-
|
16 |
-
<a class="button button-hero button-primary sucuriscan-review-hero"
|
17 |
-
href="http://goo.gl/aByqP5" target="_blank">Review Plugin</a>
|
18 |
</h2>
|
19 |
|
20 |
<div class="sucuriscan-maincontent sucuriscan-clearfix">
|
21 |
|
22 |
<div class="sucuriscan-leftside sucuriscan-%%SUCURI.LayoutType%% sucuriscan-%%SUCURI.PageStyleClass%%">
|
23 |
|
24 |
-
|
25 |
|
26 |
</div>
|
27 |
|
28 |
-
|
29 |
|
30 |
</div>
|
31 |
|
32 |
<div class="sucuriscan-footer sucuriscan-clearfix">
|
33 |
-
<a href="
|
34 |
<img src="%%SUCURI.SucuriURL%%/inc/images/logo.png" alt="Sucuri Security" />
|
35 |
</a>
|
36 |
<div class="sucuriscan-help">
|
37 |
<p>
|
38 |
If you have any questions about these checks or this plugin, contact us at
|
39 |
<a href="mailto:info@sucuri.net">info@sucuri.net</a> or visit
|
40 |
-
<a href="
|
41 |
</p>
|
42 |
</div>
|
43 |
</div>
|
4 |
<h2 id="warnings_hook"></h2>
|
5 |
|
6 |
<div class="sucuriscan-header sucuriscan-clearfix">
|
7 |
+
<a href="https://sucuri.net/signup" target="_blank" title="Sucuri Security" class="sucuriscan-logo">
|
8 |
<img src="%%SUCURI.SucuriURL%%/inc/images/logo.png" alt="Sucuri Security" />
|
9 |
</a>
|
10 |
<h2>Sucuri Security %%SUCURI.PageTitle%%</h2>
|
11 |
+
<a class="button button-hero button-primary sucuriscan-review-hero"
|
12 |
+
href="https://goo.gl/aByqP5" target="_blank">Review Plugin</a>
|
13 |
</div>
|
14 |
|
15 |
<h2 class="nav-tab-wrapper sucuriscan-navbar">
|
16 |
+
%%%SUCURI.Navbar%%%
|
|
|
|
|
|
|
17 |
</h2>
|
18 |
|
19 |
<div class="sucuriscan-maincontent sucuriscan-clearfix">
|
20 |
|
21 |
<div class="sucuriscan-leftside sucuriscan-%%SUCURI.LayoutType%% sucuriscan-%%SUCURI.PageStyleClass%%">
|
22 |
|
23 |
+
%%%SUCURI.PageContent%%%
|
24 |
|
25 |
</div>
|
26 |
|
27 |
+
%%%SUCURI.PageSidebarContent%%%
|
28 |
|
29 |
</div>
|
30 |
|
31 |
<div class="sucuriscan-footer sucuriscan-clearfix">
|
32 |
+
<a href="https://sucuri.net/signup" target="_blank" title="Sucuri Security" class="sucuriscan-logo">
|
33 |
<img src="%%SUCURI.SucuriURL%%/inc/images/logo.png" alt="Sucuri Security" />
|
34 |
</a>
|
35 |
<div class="sucuriscan-help">
|
36 |
<p>
|
37 |
If you have any questions about these checks or this plugin, contact us at
|
38 |
<a href="mailto:info@sucuri.net">info@sucuri.net</a> or visit
|
39 |
+
<a href="https://sucuri.net/" target="_blank">sucuri.net</a>
|
40 |
</p>
|
41 |
</div>
|
42 |
</div>
|
inc/tpl/bsidebar.html.tpl
CHANGED
@@ -12,7 +12,7 @@
|
|
12 |
</div>
|
13 |
</div>
|
14 |
|
15 |
-
<a href="
|
16 |
|
17 |
<div class="sucuriscan-ad-footer">
|
18 |
<ul>
|
@@ -33,7 +33,7 @@
|
|
33 |
<h4>Blacklisted by Google?</h4>
|
34 |
</div>
|
35 |
|
36 |
-
<a href="
|
37 |
|
38 |
<div class="sucuriscan-ad-footer sucuriscan-clearfix">
|
39 |
<div class="sucuriscan-pull-left">
|
12 |
</div>
|
13 |
</div>
|
14 |
|
15 |
+
<a href="https://goo.gl/9sD2sh" target="_blank" class="sucuriscan-ad-btn">Protect Your Website Today</a>
|
16 |
|
17 |
<div class="sucuriscan-ad-footer">
|
18 |
<ul>
|
33 |
<h4>Blacklisted by Google?</h4>
|
34 |
</div>
|
35 |
|
36 |
+
<a href="https://goo.gl/vEwZq6" target="_blank" class="sucuriscan-ad-btn">Get Clean Today</a>
|
37 |
|
38 |
<div class="sucuriscan-ad-footer sucuriscan-clearfix">
|
39 |
<div class="sucuriscan-pull-left">
|
inc/tpl/{notification-corefiles.html.tpl → corefiles-notification.html.tpl}
RENAMED
@@ -26,7 +26,7 @@
|
|
26 |
</thead>
|
27 |
|
28 |
<tbody>
|
29 |
-
|
30 |
</tbody>
|
31 |
|
32 |
<tfoot>
|
26 |
</thead>
|
27 |
|
28 |
<tbody>
|
29 |
+
%%%SUCURI.CoreFiles.List%%%
|
30 |
</tbody>
|
31 |
|
32 |
<tfoot>
|
inc/tpl/corefiles-page.html.tpl
ADDED
@@ -0,0 +1,39 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
<div class="postbox">
|
3 |
+
<h3>Core Integrity</h3>
|
4 |
+
|
5 |
+
<div class="inside">
|
6 |
+
<p>
|
7 |
+
Every WordPress release comes with a set of files that are part of the standard
|
8 |
+
installation process of each version, none of these files should be modified as
|
9 |
+
they are overwritten on each upgrade, it is not advised that web developers
|
10 |
+
modify the core files and instead extend the base functionality with themes or
|
11 |
+
plugins. Only three directories are scanned: admin, includes, and the document
|
12 |
+
root where the configuration and startup files are located.
|
13 |
+
</p>
|
14 |
+
|
15 |
+
<div class="sucuriscan-inline-alert-info">
|
16 |
+
<p>
|
17 |
+
Use a <a href="https://sucuri.net/website-antivirus/" target="_blank"> server
|
18 |
+
side scanner</a> or a <a href="https://sitecheck.sucuri.net/" target="_blank">
|
19 |
+
web scanner</a> to find the source of the infection and broken pages respectively.
|
20 |
+
</p>
|
21 |
+
</div>
|
22 |
+
|
23 |
+
<div id="sucuriscan-corefiles-response">
|
24 |
+
<em>Loading...</em>
|
25 |
+
</div>
|
26 |
+
|
27 |
+
<script type="text/javascript">
|
28 |
+
jQuery(function($){
|
29 |
+
$.post('%%SUCURI.AjaxURL.Home%%', {
|
30 |
+
action: 'sucuriscan_ajax',
|
31 |
+
sucuriscan_page_nonce: '%%SUCURI.PageNonce%%',
|
32 |
+
form_action: 'get_core_files',
|
33 |
+
}, function(data){
|
34 |
+
$('#sucuriscan-corefiles-response').html(data);
|
35 |
+
});
|
36 |
+
});
|
37 |
+
</script>
|
38 |
+
</div>
|
39 |
+
</div>
|
inc/tpl/corefiles.html.tpl
ADDED
@@ -0,0 +1,82 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
<div class="sucuriscan-inline-alert-updated sucuriscan-%%SUCURI.CoreFiles.GoodVisibility%%">
|
3 |
+
<p>
|
4 |
+
Your WordPress core files are clean and were not modified.
|
5 |
+
</p>
|
6 |
+
</div>
|
7 |
+
|
8 |
+
<div class="sucuriscan-inline-alert-warning sucuriscan-%%SUCURI.CoreFiles.NotFixableVisibility%%">
|
9 |
+
<p>
|
10 |
+
Files marked with the text <em>"not fixable"</em> are files without write
|
11 |
+
permissions, you have to fix them manually.
|
12 |
+
</p>
|
13 |
+
</div>
|
14 |
+
|
15 |
+
<div class="sucuriscan-inline-alert-error sucuriscan-%%SUCURI.CoreFiles.FailureVisibility%%">
|
16 |
+
<p>
|
17 |
+
Error retrieving the <a href="%%SUCURI.CoreFiles.RemoteChecksumsURL%%" target="_blank">
|
18 |
+
WordPress core hashes</a>. The information used by the plugin to determine the
|
19 |
+
integrity of the core files is retrieved and controlled by WordPress. Any error
|
20 |
+
message related with this tool is likely related with a modification in their
|
21 |
+
API service that is not supported yet. It is also possible that your website is
|
22 |
+
not able to communicate with this server due to a missing HTTP transport tool.
|
23 |
+
</p>
|
24 |
+
</div>
|
25 |
+
|
26 |
+
<form action="%%SUCURI.URL.Home%%" method="post">
|
27 |
+
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
28 |
+
|
29 |
+
<table class="wp-list-table widefat sucuriscan-table sucuriscan-corefiles sucuriscan-%%SUCURI.CoreFiles.BadVisibility%%">
|
30 |
+
<thead>
|
31 |
+
<tr>
|
32 |
+
<th colspan="5">Core Integrity (%%SUCURI.CoreFiles.ListCount%% files)</th>
|
33 |
+
</tr>
|
34 |
+
|
35 |
+
<tr>
|
36 |
+
<th class="manage-column column-cb check-column">
|
37 |
+
<label class="screen-reader-text" for="cb-select-all-1">Select All</label>
|
38 |
+
<input id="cb-select-all-1" type="checkbox">
|
39 |
+
</th>
|
40 |
+
<th width="80" class="manage-column">Status</th>
|
41 |
+
<th width="100" class="manage-column">File Size</th>
|
42 |
+
<th width="200" class="manage-column">Modified At</th>
|
43 |
+
<th class="manage-column">File Path</th>
|
44 |
+
</tr>
|
45 |
+
</thead>
|
46 |
+
|
47 |
+
<tbody>
|
48 |
+
%%%SUCURI.CoreFiles.List%%%
|
49 |
+
</tbody>
|
50 |
+
</table>
|
51 |
+
|
52 |
+
<div class="sucuriscan-%%SUCURI.CoreFiles.BadVisibility%%">
|
53 |
+
<p>
|
54 |
+
Marking one or more files as fixed will force the plugin to ignore them during
|
55 |
+
the next scan, very useful when you find false positives. Additionally you can
|
56 |
+
restore the original content of the core files that appear as modified or deleted,
|
57 |
+
this will tell the plugin to download a copy of the original files from the official
|
58 |
+
<a href="https://core.svn.wordpress.org/tags/" target="_blank">WordPress repository</a>.
|
59 |
+
Deleting a file is an irreversible action, be careful.
|
60 |
+
</p>
|
61 |
+
|
62 |
+
<div class="sucuriscan-recipient-form">
|
63 |
+
<p>
|
64 |
+
<label>
|
65 |
+
<input type="hidden" name="sucuriscan_process_form" value="0" />
|
66 |
+
<input type="checkbox" name="sucuriscan_process_form" value="1" />
|
67 |
+
<span>I understand that this operation can not be reverted.</span>
|
68 |
+
</label>
|
69 |
+
</p>
|
70 |
+
|
71 |
+
<span class="sucuriscan-input-group">
|
72 |
+
<label>Choose Action:</label>
|
73 |
+
<select name="sucuriscan_integrity_action">
|
74 |
+
<option value="fixed">Mark as fixed</option>
|
75 |
+
<option value="restore">Restore source</option>
|
76 |
+
<option value="delete">Delete file</option>
|
77 |
+
</select>
|
78 |
+
</span>
|
79 |
+
<button type="submit" class="button button-primary">Proceed</button>
|
80 |
+
</div>
|
81 |
+
</div>
|
82 |
+
</form>
|
inc/tpl/{integrity-corefiles.snippet.tpl → corefiles.snippet.tpl}
RENAMED
@@ -1,8 +1,8 @@
|
|
1 |
|
2 |
-
<tr class="%%SUCURI.CoreFiles.CssClass%%
|
3 |
<td class="check-column">
|
4 |
-
<input type="checkbox" name="
|
5 |
-
|
6 |
</td>
|
7 |
<td><span class="sucuriscan-label sucuriscan-label-%%SUCURI.CoreFiles.StatusType%%">%%SUCURI.CoreFiles.StatusType%%</span></td>
|
8 |
<td><em title="%%SUCURI.CoreFiles.FileSizeNumber%% bytes">~%%SUCURI.CoreFiles.FileSizeHuman%%</em></td>
|
1 |
|
2 |
+
<tr class="%%SUCURI.CoreFiles.CssClass%%">
|
3 |
<td class="check-column">
|
4 |
+
<input type="checkbox" name="sucuriscan_corefiles[]"
|
5 |
+
value="%%SUCURI.CoreFiles.StatusType%%@%%SUCURI.CoreFiles.FilePath%%" />
|
6 |
</td>
|
7 |
<td><span class="sucuriscan-label sucuriscan-label-%%SUCURI.CoreFiles.StatusType%%">%%SUCURI.CoreFiles.StatusType%%</span></td>
|
8 |
<td><em title="%%SUCURI.CoreFiles.FileSizeNumber%% bytes">~%%SUCURI.CoreFiles.FileSizeHuman%%</em></td>
|
inc/tpl/firewall-auditlogs.html.tpl
ADDED
@@ -0,0 +1,73 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
<div id="poststuff">
|
3 |
+
<div class="postbox">
|
4 |
+
<h3>Firewall Audit Logs</h3>
|
5 |
+
|
6 |
+
<div class="inside">
|
7 |
+
<p>
|
8 |
+
CloudProxy logs every request involved in an attack and separates them from the
|
9 |
+
legitimate requests. You can analyze the data from the latest entries in the
|
10 |
+
logs using this tool and take action either enabling the advanced features of
|
11 |
+
the IDS <em>(Intrusion Detection System)</em> from the <a target="_blank"
|
12 |
+
href="https://waf.sucuri.net/?settings">CloudProxy Dashboard</a> and/or blocking
|
13 |
+
IP addresses and URL paths directly from the <a href="https://waf.sucuri.net/?audit"
|
14 |
+
target="_blank">CloudProxy Audit Trails</a> page.
|
15 |
+
</p>
|
16 |
+
|
17 |
+
<div class="sucuriscan-inline-alert-info">
|
18 |
+
<p>Note that non-blocked requests are hidden from the logs, this is intentional.</p>
|
19 |
+
</div>
|
20 |
+
|
21 |
+
<div>
|
22 |
+
<form action="%%SUCURI.URL.Firewall%%#auditlogs" method="post">
|
23 |
+
<span class="sucuriscan-input-group">
|
24 |
+
<label>Query:</label>
|
25 |
+
<input type="text" id="sucuriscan_firewall_query" class="input-text" />
|
26 |
+
<select id="sucuriscan_firewall_day">%%%SUCURI.AuditLogs.DateDays%%%</select>
|
27 |
+
<select id="sucuriscan_firewall_month">%%%SUCURI.AuditLogs.DateMonths%%%</select>
|
28 |
+
<select id="sucuriscan_firewall_year">%%%SUCURI.AuditLogs.DateYears%%%</select>
|
29 |
+
</span>
|
30 |
+
<button id="sucuriscan-firewall-auditlogs-button" class="button button-primary">Retrieve Logs</button>
|
31 |
+
</form>
|
32 |
+
</div>
|
33 |
+
|
34 |
+
<script type="text/javascript">
|
35 |
+
jQuery(function($){
|
36 |
+
$('#sucuriscan-firewall-auditlogs-button').on('click', function(ev){
|
37 |
+
ev.preventDefault();
|
38 |
+
$('.sucuriscan-firewall-auditlogs tbody').html(
|
39 |
+
'<tr><td><em>Loading...</em></td></tr>'
|
40 |
+
);
|
41 |
+
var params = {
|
42 |
+
action: 'sucuriscan_firewall_ajax',
|
43 |
+
sucuriscan_page_nonce: '%%SUCURI.PageNonce%%',
|
44 |
+
form_action: 'get_audit_logs',
|
45 |
+
};
|
46 |
+
params.sucuriscan_query = $('#sucuriscan_firewall_query').val();
|
47 |
+
params.sucuriscan_month = $('#sucuriscan_firewall_month').val();
|
48 |
+
params.sucuriscan_year = $('#sucuriscan_firewall_year').val();
|
49 |
+
params.sucuriscan_day = $('#sucuriscan_firewall_day').val();
|
50 |
+
$.post('%%SUCURI.AjaxURL.Firewall%%', params, function(data){
|
51 |
+
$('.sucuriscan-firewall-auditlogs tbody').html(data);
|
52 |
+
});
|
53 |
+
});
|
54 |
+
$('#sucuriscan-firewall-auditlogs-button').click();
|
55 |
+
});
|
56 |
+
</script>
|
57 |
+
|
58 |
+
<table class="wp-list-table widefat sucuriscan-table sucuriscan-firewall-auditlogs">
|
59 |
+
<thead>
|
60 |
+
<tr>
|
61 |
+
<th>Audit Logs</th>
|
62 |
+
</tr>
|
63 |
+
</thead>
|
64 |
+
|
65 |
+
<tbody>
|
66 |
+
<tr>
|
67 |
+
<td><em>Loading...</em></td>
|
68 |
+
</tr>
|
69 |
+
</tbody>
|
70 |
+
</table>
|
71 |
+
</div>
|
72 |
+
</div>
|
73 |
+
</div>
|
inc/tpl/firewall-auditlogs.snippet.tpl
ADDED
@@ -0,0 +1,43 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
<tr class="%%SUCURI.AccessLog.CssClass%%">
|
3 |
+
<td>
|
4 |
+
<div class="sucuriscan-firewall-accesslog sucuriscan-monospace">
|
5 |
+
<div class="sucuriscan-accesslog-origin">
|
6 |
+
<img src="%%SUCURI.SucuriURL%%/inc/images/blank.png"
|
7 |
+
class="sucuriscan-flag sucuriscan-flag-%%SUCURI.AccessLog.RequestCountryCode%%" />
|
8 |
+
<span>%%SUCURI.AccessLog.RemoteAddr%%</span>
|
9 |
+
<span>(%%SUCURI.AccessLog.RequestCountryName%%)</span>
|
10 |
+
</div>
|
11 |
+
<div class="sucuriscan-accesslog-datetime">
|
12 |
+
<span class="sucuriscan-accesslog-label">Date/Time:</span>
|
13 |
+
<span>%%SUCURI.AccessLog.RequestDate%%</span>
|
14 |
+
<span>%%SUCURI.AccessLog.RequestTime%%</span>
|
15 |
+
<span>%%SUCURI.AccessLog.RequestTimezone%%</span>
|
16 |
+
</div>
|
17 |
+
<div class="sucuriscan-accesslog-signature">
|
18 |
+
<span class="sucuriscan-accesslog-label">Signature:</span>
|
19 |
+
<span>%%SUCURI.AccessLog.SucuriBlockCode%%</span>
|
20 |
+
<span>(%%SUCURI.AccessLog.SucuriBlockReason%%)</span>
|
21 |
+
</div>
|
22 |
+
<div class="sucuriscan-accesslog-request">
|
23 |
+
<span class="sucuriscan-accesslog-label">Request:</span>
|
24 |
+
<span>%%SUCURI.AccessLog.HttpProtocol%%</span>
|
25 |
+
<span>%%SUCURI.AccessLog.RequestMethod%%</span>
|
26 |
+
<span>%%SUCURI.AccessLog.HttpStatus%%</span>
|
27 |
+
<span>%%SUCURI.AccessLog.HttpStatusTitle%%</span>
|
28 |
+
</div>
|
29 |
+
<div class="sucuriscan-accesslog-useragent">
|
30 |
+
<span class="sucuriscan-accesslog-label">U-Agent:</span>
|
31 |
+
<span>%%SUCURI.AccessLog.HttpUserAgent%%</span>
|
32 |
+
</div>
|
33 |
+
<div class="sucuriscan-accesslog-target">
|
34 |
+
<span class="sucuriscan-accesslog-label">Target.:</span>
|
35 |
+
<span>%%SUCURI.AccessLog.ResourcePath%%</span>
|
36 |
+
</div>
|
37 |
+
<div class="sucuriscan-accesslog-referer">
|
38 |
+
<span class="sucuriscan-accesslog-label">Referer:</span>
|
39 |
+
<span>%%SUCURI.AccessLog.HttpReferer%%</span>
|
40 |
+
</div>
|
41 |
+
</span>
|
42 |
+
</td>
|
43 |
+
</tr>
|
inc/tpl/firewall-clearcache.html.tpl
ADDED
@@ -0,0 +1,59 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
<div id="poststuff">
|
3 |
+
<div class="postbox">
|
4 |
+
<h3>Clear Cache</h3>
|
5 |
+
|
6 |
+
<div class="inside">
|
7 |
+
<p>
|
8 |
+
CloudProxy offers multiple options to configure the cache level applied to your
|
9 |
+
website. You can either enable the full cache functionality which is the
|
10 |
+
recommended setting, or you can set the cache level to minimal which will keep
|
11 |
+
the pages static for a couple of minutes, or force the usage of the website
|
12 |
+
headers <em>(only for advanced users)</em>, or in extreme cases where you do not
|
13 |
+
need the cache you can simply disable it. You can find more information about it
|
14 |
+
in the <a href="https://kb.sucuri.net/cloudproxy/Performance/caching-options"
|
15 |
+
target="_blank">Sucuri Knowledge Base</a> website.
|
16 |
+
</p>
|
17 |
+
|
18 |
+
<div class="sucuriscan-inline-alert-info">
|
19 |
+
<p>
|
20 |
+
Note that CloudProxy has <a href="https://kb.sucuri.net/cloudproxy/Performance/cache-exceptions"
|
21 |
+
target="_blank">special caching rules</a> for Images, Cascading Style Sheets,
|
22 |
+
JavaScript, PDF, TXT, media files and a few more extensions that are stored on
|
23 |
+
our <a href="https://en.wikipedia.org/wiki/Edge_device" target="_blank">edge</a>.
|
24 |
+
The only way to flush the cache for these files is by clearing CloudProxy's cache
|
25 |
+
completely <em>(for the whole website)</em>.
|
26 |
+
</p>
|
27 |
+
</div>
|
28 |
+
|
29 |
+
<div class="sucuriscan-inline-alert-warning">
|
30 |
+
<p>
|
31 |
+
Due to our caching of JavaScript and CSS files, often, as is best practice, the
|
32 |
+
use of versioning during development will ensure updates going live as expected.
|
33 |
+
This is done by adding a query string such as <code>?ver=1.2.3</code> and
|
34 |
+
incrementing on each update.
|
35 |
+
</p>
|
36 |
+
</div>
|
37 |
+
|
38 |
+
<p>
|
39 |
+
A web cache (or HTTP cache) is an information technology for the temporary
|
40 |
+
storage (caching) of web documents, such as HTML pages and images, to reduce
|
41 |
+
bandwidth usage, server load, and perceived lag. A web cache system stores
|
42 |
+
copies of documents passing through it; subsequent requests may be satisfied
|
43 |
+
from the cache if certain conditions are met. A web cache system can refer
|
44 |
+
either to an appliance, or to a computer program.
|
45 |
+
</p>
|
46 |
+
|
47 |
+
<p>
|
48 |
+
More info at <a href="https://en.wikipedia.org/wiki/Web_cache" target="_blank">
|
49 |
+
WikiPedia - Web Cache</a>
|
50 |
+
</p>
|
51 |
+
|
52 |
+
<form action="%%SUCURI.URL.Firewall%%#clearcache" method="post">
|
53 |
+
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
54 |
+
<input type="hidden" name="sucuriscan_clear_cache" value="1" />
|
55 |
+
<input type="submit" value="Clear Cache" class="button button-primary" />
|
56 |
+
</form>
|
57 |
+
</div>
|
58 |
+
</div>
|
59 |
+
</div>
|
inc/tpl/firewall-settings.html.tpl
ADDED
@@ -0,0 +1,65 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
<div id="poststuff">
|
3 |
+
<div class="postbox">
|
4 |
+
<h3>Firewall Settings</h3>
|
5 |
+
|
6 |
+
<div class="inside">
|
7 |
+
<p>
|
8 |
+
A powerful <b>WAF</b> <em>(Web Application Firewall)</em> and <b>Intrusion
|
9 |
+
Prevention</b> system for any WordPress user and many other platforms. This page
|
10 |
+
will help you to configure and monitor your site through <strong>Sucuri
|
11 |
+
CloudProxy</strong>. Once enabled, our firewall will act as a shield, protecting
|
12 |
+
your site from attacks and preventing malware infections and reinfections. It
|
13 |
+
will block SQL injection attempts, brute force attacks, XSS, RFI, backdoors and
|
14 |
+
many other threats against your site.
|
15 |
+
</p>
|
16 |
+
|
17 |
+
<div class="sucuriscan-inline-alert-info">
|
18 |
+
<p>
|
19 |
+
Add your <a href="https://waf.sucuri.net/?settings&panel=api" target="_blank">
|
20 |
+
CloudProxy API key</a> in the form below to start communicating with the firewall
|
21 |
+
API service.
|
22 |
+
</p>
|
23 |
+
</div>
|
24 |
+
|
25 |
+
<div class="sucuriscan-hstatus sucuriscan-hstatus-2 sucuriscan-firewall-apikey sucuriscan-%%SUCURI.Firewall.APIKeyVisibility%%">
|
26 |
+
<span class="sucuriscan-monospace">%%SUCURI.Firewall.APIKey%%</span>
|
27 |
+
<form action="%%SUCURI.URL.Firewall%%" method="post">
|
28 |
+
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
29 |
+
<button type="submit" name="sucuriscan_delete_wafkey" class="button-primary button-danger">Delete</button>
|
30 |
+
</form>
|
31 |
+
</div>
|
32 |
+
|
33 |
+
<form action="%%SUCURI.URL.Firewall%%" method="post" class="sucuriscan-%%SUCURI.Firewall.APIKeyFormVisibility%%">
|
34 |
+
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
35 |
+
<span class="sucuriscan-input-group">
|
36 |
+
<label>CloudProxy API Key:</label>
|
37 |
+
<input type="text" name="sucuriscan_cloudproxy_apikey" class="input-text" />
|
38 |
+
</span>
|
39 |
+
<button type="submit" class="button-primary">Save</button>
|
40 |
+
</form>
|
41 |
+
|
42 |
+
<table class="wp-list-table widefat sucuriscan-table sucuriscan-firewall-settings sucuriscan-%%SUCURI.Firewall.SettingsVisibility%%">
|
43 |
+
<thead>
|
44 |
+
<tr>
|
45 |
+
<th>Setting Name</th>
|
46 |
+
<th>Setting Value</th>
|
47 |
+
</tr>
|
48 |
+
</thead>
|
49 |
+
|
50 |
+
<tbody>
|
51 |
+
%%%SUCURI.Firewall.SettingOptions%%%
|
52 |
+
</tbody>
|
53 |
+
</table>
|
54 |
+
|
55 |
+
<p>
|
56 |
+
<em>[1]</em> More information about <a href="https://sucuri.net/website-firewall/"
|
57 |
+
target="_blank">CloudProxy</a>, features and pricing.<br>
|
58 |
+
<em>[2]</em> Instructions and videos in the official <a href="https://kb.sucuri.net/cloudproxy"
|
59 |
+
target="_blank">Knowledge Base</a> site.<br>
|
60 |
+
<em>[3]</em> <a href="https://login.sucuri.net/signup2/create?CloudProxy" target="_blank">
|
61 |
+
Sign up</a> for a new account and start protecting your site with CloudProxy.
|
62 |
+
</p>
|
63 |
+
</div>
|
64 |
+
</div>
|
65 |
+
</div>
|
inc/tpl/firewall-settings.snippet.tpl
ADDED
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
<tr class="%%SUCURI.Firewall.OptionCssClass%%">
|
3 |
+
<td><label>%%SUCURI.Firewall.OptionName%%</label></td>
|
4 |
+
<td><span class="sucuriscan-monospace">%%%SUCURI.Firewall.OptionValue%%%</span></td>
|
5 |
+
</tr>
|
inc/tpl/firewall.html.tpl
ADDED
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
<div class="sucuriscan-tabs">
|
3 |
+
<ul>
|
4 |
+
<li>
|
5 |
+
<a href="#settings" data-tabname="settings">Settings</a>
|
6 |
+
</li>
|
7 |
+
<li>
|
8 |
+
<a href="#auditlogs" data-tabname="auditlogs">Audit Logs</a>
|
9 |
+
</li>
|
10 |
+
<li>
|
11 |
+
<a href="#clearcache" data-tabname="clearcache">Clear Cache</a>
|
12 |
+
</li>
|
13 |
+
</ul>
|
14 |
+
|
15 |
+
<div class="sucuriscan-tab-containers">
|
16 |
+
<div id="sucuriscan-settings">
|
17 |
+
%%%SUCURI.Firewall.Settings%%%
|
18 |
+
</div>
|
19 |
+
|
20 |
+
<div id="sucuriscan-auditlogs">
|
21 |
+
%%%SUCURI.Firewall.AuditLogs%%%
|
22 |
+
</div>
|
23 |
+
|
24 |
+
<div id="sucuriscan-clearcache">
|
25 |
+
%%%SUCURI.Firewall.ClearCache%%%
|
26 |
+
</div>
|
27 |
+
</div>
|
28 |
+
</div>
|
inc/tpl/hardening-panel.html.tpl
CHANGED
@@ -4,32 +4,32 @@
|
|
4 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
5 |
<input type="hidden" name="sucuriscan_run_hardening" value="1" />
|
6 |
|
7 |
-
|
8 |
|
9 |
-
|
10 |
|
11 |
-
|
12 |
|
13 |
-
|
14 |
|
15 |
-
|
16 |
|
17 |
-
|
18 |
|
19 |
-
|
20 |
|
21 |
-
|
22 |
|
23 |
-
|
24 |
|
25 |
-
|
26 |
|
27 |
-
|
28 |
|
29 |
-
|
30 |
|
31 |
-
|
32 |
|
33 |
-
|
34 |
</form>
|
35 |
</div>
|
4 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
5 |
<input type="hidden" name="sucuriscan_run_hardening" value="1" />
|
6 |
|
7 |
+
%%%SUCURI.Hardening.Version%%%
|
8 |
|
9 |
+
%%%SUCURI.Hardening.CloudProxy%%%
|
10 |
|
11 |
+
%%%SUCURI.Hardening.RemoveGenerator%%%
|
12 |
|
13 |
+
%%%SUCURI.Hardening.NginxPhpFpm%%%
|
14 |
|
15 |
+
%%%SUCURI.Hardening.Upload%%%
|
16 |
|
17 |
+
%%%SUCURI.Hardening.WpContent%%%
|
18 |
|
19 |
+
%%%SUCURI.Hardening.WpIncludes%%%
|
20 |
|
21 |
+
%%%SUCURI.Hardening.PhpVersion%%%
|
22 |
|
23 |
+
%%%SUCURI.Hardening.SecretKeys%%%
|
24 |
|
25 |
+
%%%SUCURI.Hardening.Readme%%%
|
26 |
|
27 |
+
%%%SUCURI.Hardening.AdminUser%%%
|
28 |
|
29 |
+
%%%SUCURI.Hardening.FileEditor%%%
|
30 |
|
31 |
+
%%%SUCURI.Hardening.DBTables%%%
|
32 |
|
33 |
+
%%%SUCURI.Hardening.ErrorLog%%%
|
34 |
</form>
|
35 |
</div>
|
inc/tpl/hardening-whitelist.html.tpl
CHANGED
@@ -76,7 +76,7 @@
|
|
76 |
</thead>
|
77 |
|
78 |
<tbody>
|
79 |
-
|
80 |
|
81 |
<tr class="sucuriscan-%%SUCURI.HardeningWhitelist.NoItemsVisibility%%">
|
82 |
<td colspan="4">
|
76 |
</thead>
|
77 |
|
78 |
<tbody>
|
79 |
+
%%%SUCURI.HardeningWhitelist.List%%%
|
80 |
|
81 |
<tr class="sucuriscan-%%SUCURI.HardeningWhitelist.NoItemsVisibility%%">
|
82 |
<td colspan="4">
|
inc/tpl/hardening.html.tpl
CHANGED
@@ -2,20 +2,20 @@
|
|
2 |
<div class="sucuriscan-tabs">
|
3 |
<ul>
|
4 |
<li>
|
5 |
-
<a href="#" data-tabname="hardening">Hardening Options</a>
|
6 |
</li>
|
7 |
<li>
|
8 |
-
<a href="#" data-tabname="whitelist">Whitelist Blocked PHP Files</a>
|
9 |
</li>
|
10 |
</ul>
|
11 |
|
12 |
<div class="sucuriscan-tab-containers">
|
13 |
<div id="sucuriscan-hardening">
|
14 |
-
|
15 |
</div>
|
16 |
|
17 |
<div id="sucuriscan-whitelist">
|
18 |
-
|
19 |
</div>
|
20 |
</div>
|
21 |
</div>
|
2 |
<div class="sucuriscan-tabs">
|
3 |
<ul>
|
4 |
<li>
|
5 |
+
<a href="#hardening" data-tabname="hardening">Hardening Options</a>
|
6 |
</li>
|
7 |
<li>
|
8 |
+
<a href="#whitelist" data-tabname="whitelist">Whitelist Blocked PHP Files</a>
|
9 |
</li>
|
10 |
</ul>
|
11 |
|
12 |
<div class="sucuriscan-tab-containers">
|
13 |
<div id="sucuriscan-hardening">
|
14 |
+
%%%SUCURI.Hardening.Panel%%%
|
15 |
</div>
|
16 |
|
17 |
<div id="sucuriscan-whitelist">
|
18 |
+
%%%SUCURI.Hardening.Whitelist%%%
|
19 |
</div>
|
20 |
</div>
|
21 |
</div>
|
inc/tpl/hardening.snippet.tpl
CHANGED
@@ -3,7 +3,7 @@
|
|
3 |
<h3>%%SUCURI.Hardening.Title%%</h3>
|
4 |
|
5 |
<div class="inside">
|
6 |
-
|
7 |
|
8 |
<div class="sucuriscan-hstatus sucuriscan-hstatus-%%SUCURI.Hardening.Status%%">
|
9 |
<input type="submit" name="%%SUCURI.Hardening.FieldName%%"
|
@@ -11,9 +11,9 @@
|
|
11 |
%%SUCURI.Hardening.FieldAttributes%%
|
12 |
class="button-secondary" />
|
13 |
|
14 |
-
<span
|
15 |
</div>
|
16 |
|
17 |
-
|
18 |
</div>
|
19 |
</div>
|
3 |
<h3>%%SUCURI.Hardening.Title%%</h3>
|
4 |
|
5 |
<div class="inside">
|
6 |
+
%%%SUCURI.Hardening.Description%%%
|
7 |
|
8 |
<div class="sucuriscan-hstatus sucuriscan-hstatus-%%SUCURI.Hardening.Status%%">
|
9 |
<input type="submit" name="%%SUCURI.Hardening.FieldName%%"
|
11 |
%%SUCURI.Hardening.FieldAttributes%%
|
12 |
class="button-secondary" />
|
13 |
|
14 |
+
<span>%%%SUCURI.Hardening.Information%%%</span>
|
15 |
</div>
|
16 |
|
17 |
+
%%%SUCURI.Hardening.UpdateMessage%%%
|
18 |
</div>
|
19 |
</div>
|
inc/tpl/infosys-cronjobs.html.tpl
CHANGED
@@ -42,7 +42,7 @@
|
|
42 |
</thead>
|
43 |
|
44 |
<tbody>
|
45 |
-
|
46 |
</tbody>
|
47 |
|
48 |
<tfoot>
|
42 |
</thead>
|
43 |
|
44 |
<tbody>
|
45 |
+
%%%SUCURI.Cronjobs.List%%%
|
46 |
</tbody>
|
47 |
|
48 |
<tfoot>
|
inc/tpl/infosys-errorlogs.html.tpl
CHANGED
@@ -36,7 +36,7 @@
|
|
36 |
Note that if the log file is not empty but the table is, it means that the
|
37 |
format of the logs used by the web server is not supported by the scanner,
|
38 |
you can try to increase the number of lines processed though from
|
39 |
-
<a href="%%SUCURI.URL.Settings%%#
|
40 |
other lines have a different format which is very common on servers with
|
41 |
mixed configurations.
|
42 |
</p>
|
@@ -71,7 +71,7 @@
|
|
71 |
</thead>
|
72 |
|
73 |
<tbody>
|
74 |
-
|
75 |
|
76 |
<tr class="sucuriscan-%%SUCURI.ErrorLog.InvalidFormatVisibility%%">
|
77 |
<td colspan="5">
|
36 |
Note that if the log file is not empty but the table is, it means that the
|
37 |
format of the logs used by the web server is not supported by the scanner,
|
38 |
you can try to increase the number of lines processed though from
|
39 |
+
<a href="%%SUCURI.URL.Settings%%#scanner">here</a> in case that
|
40 |
other lines have a different format which is very common on servers with
|
41 |
mixed configurations.
|
42 |
</p>
|
71 |
</thead>
|
72 |
|
73 |
<tbody>
|
74 |
+
%%%SUCURI.ErrorLog.List%%%
|
75 |
|
76 |
<tr class="sucuriscan-%%SUCURI.ErrorLog.InvalidFormatVisibility%%">
|
77 |
<td colspan="5">
|
inc/tpl/infosys-htaccess.html.tpl
CHANGED
@@ -12,14 +12,29 @@
|
|
12 |
able to handle pretty permalinks.
|
13 |
</p>
|
14 |
|
15 |
-
<div class="sucuriscan-inline-alert
|
16 |
-
<p>%%SUCURI.HTAccess.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
17 |
</div>
|
18 |
|
19 |
<textarea class="sucuriscan-full-textarea sucuriscan-monospace %%SUCURI.HTAccess.TextareaVisible%%">%%SUCURI.HTAccess.Content%%</textarea>
|
20 |
|
21 |
<p>
|
22 |
-
<small>Source <a href="
|
23 |
</p>
|
24 |
</div>
|
25 |
</div>
|
12 |
able to handle pretty permalinks.
|
13 |
</p>
|
14 |
|
15 |
+
<div class="sucuriscan-inline-alert-updated sucuriscan-%%SUCURI.HTAccess.FoundVisible%%">
|
16 |
+
<p>HTAccess file found in this path <code>%%SUCURI.HTAccess.Fpath%%</code></p>
|
17 |
+
</div>
|
18 |
+
|
19 |
+
<div class="sucuriscan-inline-alert-error sucuriscan-%%SUCURI.HTAccess.NotFoundVisible%%">
|
20 |
+
<p>Your website has no <code>.htaccess</code> file or it was not found in the default location.</p>
|
21 |
+
</div>
|
22 |
+
|
23 |
+
<div class="sucuriscan-inline-alert-info sucuriscan-%%SUCURI.HTAccess.StandardVisible%%">
|
24 |
+
<p>
|
25 |
+
The main <code>.htaccess</code> file in your site has the standard rules for a
|
26 |
+
WordPress installation. You can customize it to improve the performance and
|
27 |
+
change the behaviour of the redirections for pages and posts in your site. To
|
28 |
+
get more information visit the official documentation at <a target="_blank"
|
29 |
+
href="https://codex.wordpress.org/Using_Permalinks#Creating_and_editing_.28.htaccess.29">
|
30 |
+
Codex WordPrexx - Creating and editing (.htaccess)</a>
|
31 |
+
</p>
|
32 |
</div>
|
33 |
|
34 |
<textarea class="sucuriscan-full-textarea sucuriscan-monospace %%SUCURI.HTAccess.TextareaVisible%%">%%SUCURI.HTAccess.Content%%</textarea>
|
35 |
|
36 |
<p>
|
37 |
+
<small>Source <a href="https://codex.wordpress.org/htaccess" target="_blank">Codex WordPress HTAccess</a></small>
|
38 |
</p>
|
39 |
</div>
|
40 |
</div>
|
inc/tpl/infosys-serverinfo.html.tpl
CHANGED
@@ -1,6 +1,6 @@
|
|
1 |
|
2 |
<table class="wp-list-table widefat sucuriscan-server-info">
|
3 |
<tbody>
|
4 |
-
|
5 |
</tbody>
|
6 |
</table>
|
1 |
|
2 |
<table class="wp-list-table widefat sucuriscan-server-info">
|
3 |
<tbody>
|
4 |
+
%%%SUCURI.ServerInfo.Variables%%%
|
5 |
</tbody>
|
6 |
</table>
|
inc/tpl/infosys-wpconfig.html.tpl
CHANGED
@@ -8,6 +8,6 @@
|
|
8 |
</thead>
|
9 |
|
10 |
<tbody>
|
11 |
-
|
12 |
</tbody>
|
13 |
</table>
|
8 |
</thead>
|
9 |
|
10 |
<tbody>
|
11 |
+
%%%SUCURI.WordpressConfig.Rules%%%
|
12 |
</tbody>
|
13 |
</table>
|
inc/tpl/infosys.html.tpl
CHANGED
@@ -2,41 +2,41 @@
|
|
2 |
<div class="sucuriscan-tabs">
|
3 |
<ul>
|
4 |
<li>
|
5 |
-
<a href="#" data-tabname="server-info">Plugin & Server Info</a>
|
6 |
</li>
|
7 |
<li>
|
8 |
-
<a href="#" data-tabname="wordpress-cronjobs">Scheduled Tasks</a>
|
9 |
</li>
|
10 |
<li>
|
11 |
-
<a href="#" data-tabname="htaccess-integrity">Access File Integrity</a>
|
12 |
</li>
|
13 |
<li>
|
14 |
-
<a href="#" data-tabname="wpconfig-vars">Config. Variables</a>
|
15 |
</li>
|
16 |
<li>
|
17 |
-
<a href="#" data-tabname="error-logs">Error Logs</a>
|
18 |
</li>
|
19 |
</ul>
|
20 |
|
21 |
<div class="sucuriscan-tab-containers">
|
22 |
<div id="sucuriscan-server-info">
|
23 |
-
|
24 |
</div>
|
25 |
|
26 |
<div id="sucuriscan-wordpress-cronjobs">
|
27 |
-
|
28 |
</div>
|
29 |
|
30 |
<div id="sucuriscan-htaccess-integrity">
|
31 |
-
|
32 |
</div>
|
33 |
|
34 |
<div id="sucuriscan-wpconfig-vars">
|
35 |
-
|
36 |
</div>
|
37 |
|
38 |
<div id="sucuriscan-error-logs">
|
39 |
-
|
40 |
</div>
|
41 |
</div>
|
42 |
</div>
|
2 |
<div class="sucuriscan-tabs">
|
3 |
<ul>
|
4 |
<li>
|
5 |
+
<a href="#server-info" data-tabname="server-info">Plugin & Server Info</a>
|
6 |
</li>
|
7 |
<li>
|
8 |
+
<a href="#wordpress-cronjobs" data-tabname="wordpress-cronjobs">Scheduled Tasks</a>
|
9 |
</li>
|
10 |
<li>
|
11 |
+
<a href="#htaccess-integrity" data-tabname="htaccess-integrity">Access File Integrity</a>
|
12 |
</li>
|
13 |
<li>
|
14 |
+
<a href="#wpconfig-vars" data-tabname="wpconfig-vars">Config. Variables</a>
|
15 |
</li>
|
16 |
<li>
|
17 |
+
<a href="#error-logs" data-tabname="error-logs">Error Logs</a>
|
18 |
</li>
|
19 |
</ul>
|
20 |
|
21 |
<div class="sucuriscan-tab-containers">
|
22 |
<div id="sucuriscan-server-info">
|
23 |
+
%%%SUCURI.ServerInfo%%%
|
24 |
</div>
|
25 |
|
26 |
<div id="sucuriscan-wordpress-cronjobs">
|
27 |
+
%%%SUCURI.Cronjobs%%%
|
28 |
</div>
|
29 |
|
30 |
<div id="sucuriscan-htaccess-integrity">
|
31 |
+
%%%SUCURI.HTAccessIntegrity%%%
|
32 |
</div>
|
33 |
|
34 |
<div id="sucuriscan-wpconfig-vars">
|
35 |
+
%%%SUCURI.WordpressConfig%%%
|
36 |
</div>
|
37 |
|
38 |
<div id="sucuriscan-error-logs">
|
39 |
+
%%%SUCURI.ErrorLogs%%%
|
40 |
</div>
|
41 |
</div>
|
42 |
</div>
|
inc/tpl/integrity-auditlogs.html.tpl
CHANGED
@@ -15,7 +15,7 @@
|
|
15 |
|
16 |
<tr>
|
17 |
<th> </th>
|
18 |
-
<th width="
|
19 |
<th>Username</th>
|
20 |
<th>IP Address</th>
|
21 |
<th>Event Message</th>
|
@@ -23,7 +23,7 @@
|
|
23 |
</thead>
|
24 |
|
25 |
<tbody>
|
26 |
-
|
27 |
|
28 |
<tr class="sucuriscan-%%SUCURI.AuditLogs.NoItemsVisibility%%">
|
29 |
<td colspan="5">
|
@@ -34,7 +34,7 @@
|
|
34 |
<tr class="sucuriscan-%%SUCURI.AuditLogs.PaginationVisibility%%">
|
35 |
<td colspan="5">
|
36 |
<ul class="sucuriscan-pagination">
|
37 |
-
|
38 |
</ul>
|
39 |
</td>
|
40 |
</tr>
|
15 |
|
16 |
<tr>
|
17 |
<th> </th>
|
18 |
+
<th width="200">Date</th>
|
19 |
<th>Username</th>
|
20 |
<th>IP Address</th>
|
21 |
<th>Event Message</th>
|
23 |
</thead>
|
24 |
|
25 |
<tbody>
|
26 |
+
%%%SUCURI.AuditLogs.List%%%
|
27 |
|
28 |
<tr class="sucuriscan-%%SUCURI.AuditLogs.NoItemsVisibility%%">
|
29 |
<td colspan="5">
|
34 |
<tr class="sucuriscan-%%SUCURI.AuditLogs.PaginationVisibility%%">
|
35 |
<td colspan="5">
|
36 |
<ul class="sucuriscan-pagination">
|
37 |
+
%%%SUCURI.AuditLogs.PaginationLinks%%%
|
38 |
</ul>
|
39 |
</td>
|
40 |
</tr>
|
inc/tpl/integrity-auditlogs.snippet.tpl
CHANGED
@@ -10,6 +10,6 @@
|
|
10 |
<td>
|
11 |
<span>%%SUCURI.AuditLog.Message%%</span>
|
12 |
|
13 |
-
|
14 |
</td>
|
15 |
</tr>
|
10 |
<td>
|
11 |
<span>%%SUCURI.AuditLog.Message%%</span>
|
12 |
|
13 |
+
%%%SUCURI.AuditLog.Extra%%%
|
14 |
</td>
|
15 |
</tr>
|
inc/tpl/integrity-auditreport.html.tpl
CHANGED
@@ -6,9 +6,10 @@
|
|
6 |
|
7 |
<div class="sucuriscan-inline-alert-info">
|
8 |
<p>
|
9 |
-
The data used to generate these charts comes from the last
|
10 |
-
audit logs</strong>, you can
|
11 |
-
|
|
|
12 |
</p>
|
13 |
</div>
|
14 |
|
@@ -16,13 +17,13 @@
|
|
16 |
|
17 |
<div class="sucuriscan-pull-left sucuriscan-report-chart">
|
18 |
<h4>Audit Logs per Event</h4>
|
19 |
-
<h5>source
|
20 |
<div id="sucuriscan-report-events-per-type"></div>
|
21 |
</div>
|
22 |
|
23 |
<div class="sucuriscan-pull-right sucuriscan-report-chart">
|
24 |
<h4>Successful/Failed Logins</h4>
|
25 |
-
<h5>source
|
26 |
<div id="sucuriscan-report-events-per-login"></div>
|
27 |
</div>
|
28 |
|
@@ -32,13 +33,13 @@
|
|
32 |
|
33 |
<div class="sucuriscan-pull-left sucuriscan-report-chart">
|
34 |
<h4>Audit Logs per User</h4>
|
35 |
-
<h5>source
|
36 |
<div id="sucuriscan-report-events-per-user"></div>
|
37 |
</div>
|
38 |
|
39 |
<div class="sucuriscan-pull-right sucuriscan-report-chart">
|
40 |
<h4>Audit Logs per IP Address</h4>
|
41 |
-
<h5>source
|
42 |
<div id="sucuriscan-report-events-per-ipaddress"></div>
|
43 |
</div>
|
44 |
|
@@ -79,29 +80,29 @@ jQuery(document).ready(function($){
|
|
79 |
/* Pie-chart with number of audit logs per event type. */
|
80 |
sucuriscan_pie_chart(
|
81 |
'#sucuriscan-report-events-per-type',
|
82 |
-
[
|
83 |
-
[
|
84 |
);
|
85 |
|
86 |
/* Column-chart with number of audit logs per event login. */
|
87 |
sucuriscan_pie_chart(
|
88 |
'#sucuriscan-report-events-per-login',
|
89 |
-
[
|
90 |
[ '#5cb85c', '#f27d7d' ]
|
91 |
);
|
92 |
|
93 |
/* Bar-chart with number of audit logs per user account. */
|
94 |
sucuriscan_bar_chart(
|
95 |
'#sucuriscan-report-events-per-user',
|
96 |
-
[
|
97 |
-
[ 'data',
|
98 |
);
|
99 |
|
100 |
/* Bar-chart with number of audit logs per remote address. */
|
101 |
sucuriscan_bar_chart(
|
102 |
'#sucuriscan-report-events-per-ipaddress',
|
103 |
-
[
|
104 |
-
[ 'data',
|
105 |
);
|
106 |
|
107 |
});
|
6 |
|
7 |
<div class="sucuriscan-inline-alert-info">
|
8 |
<p>
|
9 |
+
The data used to generate these charts comes from the last
|
10 |
+
<strong>%%SUCURI.AuditReport.Logs4Report%% audit logs</strong>, you can
|
11 |
+
configure this number from the plugin settings page, you can also disable
|
12 |
+
and enable this panel from there at any time.
|
13 |
</p>
|
14 |
</div>
|
15 |
|
17 |
|
18 |
<div class="sucuriscan-pull-left sucuriscan-report-chart">
|
19 |
<h4>Audit Logs per Event</h4>
|
20 |
+
<h5>source https://sucuri.net/</h5>
|
21 |
<div id="sucuriscan-report-events-per-type"></div>
|
22 |
</div>
|
23 |
|
24 |
<div class="sucuriscan-pull-right sucuriscan-report-chart">
|
25 |
<h4>Successful/Failed Logins</h4>
|
26 |
+
<h5>source https://sucuri.net/</h5>
|
27 |
<div id="sucuriscan-report-events-per-login"></div>
|
28 |
</div>
|
29 |
|
33 |
|
34 |
<div class="sucuriscan-pull-left sucuriscan-report-chart">
|
35 |
<h4>Audit Logs per User</h4>
|
36 |
+
<h5>source https://sucuri.net/</h5>
|
37 |
<div id="sucuriscan-report-events-per-user"></div>
|
38 |
</div>
|
39 |
|
40 |
<div class="sucuriscan-pull-right sucuriscan-report-chart">
|
41 |
<h4>Audit Logs per IP Address</h4>
|
42 |
+
<h5>source https://sucuri.net/</h5>
|
43 |
<div id="sucuriscan-report-events-per-ipaddress"></div>
|
44 |
</div>
|
45 |
|
80 |
/* Pie-chart with number of audit logs per event type. */
|
81 |
sucuriscan_pie_chart(
|
82 |
'#sucuriscan-report-events-per-type',
|
83 |
+
[ %%%SUCURI.AuditReport.EventsPerType%%% ],
|
84 |
+
[ %%%SUCURI.AuditReport.EventColors%%% ]
|
85 |
);
|
86 |
|
87 |
/* Column-chart with number of audit logs per event login. */
|
88 |
sucuriscan_pie_chart(
|
89 |
'#sucuriscan-report-events-per-login',
|
90 |
+
[ %%%SUCURI.AuditReport.EventsPerLogin%%% ],
|
91 |
[ '#5cb85c', '#f27d7d' ]
|
92 |
);
|
93 |
|
94 |
/* Bar-chart with number of audit logs per user account. */
|
95 |
sucuriscan_bar_chart(
|
96 |
'#sucuriscan-report-events-per-user',
|
97 |
+
[ %%%SUCURI.AuditReport.EventsPerUserCategories%%% ],
|
98 |
+
[ 'data', %%%SUCURI.AuditReport.EventsPerUserSeries%%% ]
|
99 |
);
|
100 |
|
101 |
/* Bar-chart with number of audit logs per remote address. */
|
102 |
sucuriscan_bar_chart(
|
103 |
'#sucuriscan-report-events-per-ipaddress',
|
104 |
+
[ %%%SUCURI.AuditReport.EventsPerIPAddressCategories%%% ],
|
105 |
+
[ 'data', %%%SUCURI.AuditReport.EventsPerIPAddressSeries%%% ]
|
106 |
);
|
107 |
|
108 |
});
|
inc/tpl/integrity-corefiles.html.tpl
DELETED
@@ -1,97 +0,0 @@
|
|
1 |
-
|
2 |
-
<div class="postbox sucuriscan-border sucuriscan-border-good sucuriscan-integrity-message sucuriscan-%%SUCURI.CoreFiles.GoodVisibility%%">
|
3 |
-
<span class="sucuriscan-integrity-mark">OK</span>
|
4 |
-
<h3>Core integrity</h3>
|
5 |
-
|
6 |
-
<div class="inside">
|
7 |
-
<p>Your WordPress core files are clean and were not modified.</p>
|
8 |
-
</div>
|
9 |
-
</div>
|
10 |
-
|
11 |
-
<div class="postbox sucuriscan-border sucuriscan-border-bad sucuriscan-integrity-message sucuriscan-%%SUCURI.CoreFiles.FailureVisibility%%">
|
12 |
-
<span class="sucuriscan-integrity-failure">FAILURE</span>
|
13 |
-
<h3>Core integrity</h3>
|
14 |
-
|
15 |
-
<div class="inside">
|
16 |
-
<p>
|
17 |
-
Error retrieving the <a href="%%SUCURI.CoreFiles.RemoteChecksumsURL%%" target="_blank">
|
18 |
-
WordPress core hashes</a>. The information used by the plugin to determine the
|
19 |
-
integrity of the core files is retrieved and controlled by WordPress. Any error
|
20 |
-
message related with this tool is likely related with a modification in their
|
21 |
-
API service that is not supported yet. It is also possible that your website is
|
22 |
-
not able to communicate with this server due to a missing HTTP transport tool.
|
23 |
-
</p>
|
24 |
-
</div>
|
25 |
-
</div>
|
26 |
-
|
27 |
-
<form action="%%SUCURI.URL.Home%%" method="post">
|
28 |
-
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
29 |
-
|
30 |
-
<table class="wp-list-table widefat sucuriscan-table sucuriscan-corefiles sucuriscan-%%SUCURI.CoreFiles.BadVisibility%%">
|
31 |
-
<thead>
|
32 |
-
<tr>
|
33 |
-
<th colspan="5" class="sucuriscan-clearfix thead-with-button">
|
34 |
-
<span>Core integrity (%%SUCURI.CoreFiles.ListCount%% files)</span>
|
35 |
-
<button id="sucuriscan-corefiles-show" class="button button-primary thead-topright-action" data-action="show">Show files</button>
|
36 |
-
</th>
|
37 |
-
</tr>
|
38 |
-
|
39 |
-
<tr>
|
40 |
-
<td colspan="5" class="sucuriscan-corefiles-warning">
|
41 |
-
<div>
|
42 |
-
<p>
|
43 |
-
Changes in the integrity of your core files were detected, you may want to check
|
44 |
-
each file to determine if they were infected with malicious code. The WordPress
|
45 |
-
core directories <code>/<root></code>, <code>/wp-admin</code> and <code>
|
46 |
-
/wp-includes</code> are the only ones being scanned; the content, uploads, and
|
47 |
-
custom directories are not part of the official archives so you have to check
|
48 |
-
them manually.
|
49 |
-
</p>
|
50 |
-
</div>
|
51 |
-
</td>
|
52 |
-
</tr>
|
53 |
-
|
54 |
-
<tr class="sucuriscan-hidden">
|
55 |
-
<th class="manage-column column-cb check-column">
|
56 |
-
<label class="screen-reader-text" for="cb-select-all-1">Select All</label>
|
57 |
-
<input id="cb-select-all-1" type="checkbox">
|
58 |
-
</th>
|
59 |
-
<th width="80" class="manage-column">Status</th>
|
60 |
-
<th width="100" class="manage-column">File Size</th>
|
61 |
-
<th width="180" class="manage-column">Modified At</th>
|
62 |
-
<th class="manage-column">File Path</th>
|
63 |
-
</tr>
|
64 |
-
</thead>
|
65 |
-
|
66 |
-
<tbody>
|
67 |
-
%%SUCURI.CoreFiles.List%%
|
68 |
-
</tbody>
|
69 |
-
|
70 |
-
<tfoot>
|
71 |
-
<tr>
|
72 |
-
<td colspan="5">
|
73 |
-
<p>
|
74 |
-
<strong>Note.</strong> This is not a malware scanner but an integrity checker
|
75 |
-
which is a completely different thing, if you want to check if your site is
|
76 |
-
generating malicious code then use the <a href="%%SUCURI.URL.Scanner%%">malware
|
77 |
-
scan</a> tool. If you see the text <em>"must be fixed manually"</em> in any of
|
78 |
-
these files that means that they do not have write permissions so you can not
|
79 |
-
fix them using this tool.
|
80 |
-
</p>
|
81 |
-
|
82 |
-
<label>
|
83 |
-
<select name="sucuriscan_integrity_action">
|
84 |
-
<option value="">Choose action</option>
|
85 |
-
<option value="restore">Restore file(s) content</option>
|
86 |
-
<option value="delete">Delete file(s)</option>
|
87 |
-
<option value="fixed">Mark as fixed</option>
|
88 |
-
</select>
|
89 |
-
</label>
|
90 |
-
|
91 |
-
<button type="submit" class="button button-primary">Send action</button>
|
92 |
-
</td>
|
93 |
-
</tr>
|
94 |
-
</tfoot>
|
95 |
-
</table>
|
96 |
-
|
97 |
-
</form>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
inc/tpl/integrity-modifiedfiles.html.tpl
CHANGED
@@ -4,66 +4,85 @@
|
|
4 |
<h3>Modified Files</h3>
|
5 |
|
6 |
<div class="inside">
|
7 |
-
|
8 |
<p>
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
|
|
|
|
|
|
13 |
</p>
|
14 |
|
15 |
-
<div class="sucuriscan-inline-alert-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
16 |
<p>
|
17 |
-
|
18 |
-
|
19 |
-
of the PHP
|
20 |
-
|
21 |
-
|
22 |
-
experience issues like <em>"Internal Server Error"</em> messages or blank pages
|
23 |
-
just disable the scanner again.
|
24 |
</p>
|
25 |
</div>
|
26 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
27 |
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
28 |
</div>
|
29 |
</div>
|
30 |
|
31 |
<table class="wp-list-table widefat sucuriscan-table sucuriscan-table-double-title sucuriscan-modifiedfiles">
|
32 |
<thead>
|
33 |
<tr>
|
34 |
-
<th colspan="3" class="thead-with-button">
|
35 |
<span>Modified files <em>(inside the content directory)</em></span>
|
36 |
-
|
37 |
-
<form action="%%SUCURI.CurrentURL%%#modified-files" method="post" class="thead-topright-action">
|
38 |
-
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
39 |
-
<label>
|
40 |
-
Modified in the last
|
41 |
-
<select name="sucuriscan_last_days" id="sucuriscan_last_days">
|
42 |
-
%%SUCURI.ModifiedFiles.SelectOptions%%
|
43 |
-
</select>
|
44 |
-
days
|
45 |
-
</label>
|
46 |
-
|
47 |
-
<!-- This field was added to give backward compatibility with the SiteCheck form. -->
|
48 |
-
<input type="hidden" name="sucuriscan_malware_scan" value="1" />
|
49 |
-
</form>
|
50 |
</th>
|
51 |
</tr>
|
52 |
|
53 |
<tr>
|
54 |
-
<th>
|
55 |
<th width="100">File Size</th>
|
56 |
-
<th
|
57 |
</tr>
|
58 |
</thead>
|
59 |
|
60 |
<tbody>
|
61 |
-
%%SUCURI.ModifiedFiles.List%%
|
62 |
-
|
63 |
-
<tr class="sucuriscan-%%SUCURI.ModifiedFiles.NoFilesVisibility%%">
|
64 |
-
<td colspan="3">
|
65 |
-
<em>No files modified in the last %%SUCURI.ModifiedFiles.Days%% days</em>
|
66 |
-
</td>
|
67 |
-
</tr>
|
68 |
</tbody>
|
69 |
</table>
|
4 |
<h3>Modified Files</h3>
|
5 |
|
6 |
<div class="inside">
|
|
|
7 |
<p>
|
8 |
+
The scanner searches the WordPress content directory for files that were
|
9 |
+
modified during the number of days specified by the user in the request. If your
|
10 |
+
site was recently attacked, you can see which files were modified to assist with
|
11 |
+
any investigation. Other WordPress core directories are scanned automatically
|
12 |
+
with the core integrity checker, if you want to scan other directories that are
|
13 |
+
not part of the official WordPress packages you have to ask for assistance to
|
14 |
+
your hosting provider.
|
15 |
</p>
|
16 |
|
17 |
+
<div class="sucuriscan-inline-alert-info">
|
18 |
+
<p>
|
19 |
+
Note that in most Unix file systems, a file is considered modified when its
|
20 |
+
inode data is changed; that is, when the permissions, owner, group, or other
|
21 |
+
metadata from the inode is updated. Considering this it may be possible to have
|
22 |
+
false-positives in the result.
|
23 |
+
</p>
|
24 |
+
</div>
|
25 |
+
|
26 |
+
<div class="sucuriscan-inline-alert-warning">
|
27 |
<p>
|
28 |
+
Depending on the number of files stored in your website this operation may fail
|
29 |
+
due to limitations set by your hosting provider to keep the memory assignation
|
30 |
+
of the PHP scripts in certain numbers. If you have issues executing this tool
|
31 |
+
ask your hosting provider to assist you in the configuration of your website to
|
32 |
+
allow the execution of this script.
|
|
|
|
|
33 |
</p>
|
34 |
</div>
|
35 |
|
36 |
+
<form action="%%SUCURI.URL.Scanner%%" method="post" id="sucuriscan-modfiles-form">
|
37 |
+
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
38 |
+
<span class="sucuriscan-input-group">
|
39 |
+
<label>Search Files Modified</label>
|
40 |
+
<select id="sucuriscan_back_days">
|
41 |
+
%%%SUCURI.ModifiedFiles.SelectOptions%%%
|
42 |
+
</select>
|
43 |
+
</span>
|
44 |
+
<button id="sucuriscan-modfiles-button" class="button-primary">Proceed</button>
|
45 |
+
</form>
|
46 |
</div>
|
47 |
+
|
48 |
+
<script type="text/javascript">
|
49 |
+
jQuery(function($){
|
50 |
+
$('#sucuriscan-modfiles-button').on('click', function(ev){
|
51 |
+
ev.preventDefault();
|
52 |
+
$('.sucuriscan-modifiedfiles tbody').html(
|
53 |
+
'<tr><td colspan="3"><span>Loading <em>(may take '
|
54 |
+
+ 'several seconds)</em>...</span></td></tr>'
|
55 |
+
);
|
56 |
+
$.post('%%SUCURI.AjaxURL.Scanner%%', {
|
57 |
+
action: 'sucuriscan_scanner_ajax',
|
58 |
+
sucuriscan_page_nonce: '%%SUCURI.PageNonce%%',
|
59 |
+
form_action: 'get_modfiles',
|
60 |
+
}, function(data){
|
61 |
+
$('.sucuriscan-modifiedfiles tbody').html(data);
|
62 |
+
});
|
63 |
+
});
|
64 |
+
$('#sucuriscan-modfiles-button').click();
|
65 |
+
});
|
66 |
+
</script>
|
67 |
</div>
|
68 |
</div>
|
69 |
|
70 |
<table class="wp-list-table widefat sucuriscan-table sucuriscan-table-double-title sucuriscan-modifiedfiles">
|
71 |
<thead>
|
72 |
<tr>
|
73 |
+
<th colspan="3" class="sucuriscan-clearfix thead-with-button">
|
74 |
<span>Modified files <em>(inside the content directory)</em></span>
|
75 |
+
<span class="thead-topright-action"> </span>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
76 |
</th>
|
77 |
</tr>
|
78 |
|
79 |
<tr>
|
80 |
+
<th width="200">Modification</th>
|
81 |
<th width="100">File Size</th>
|
82 |
+
<th>File Path</th>
|
83 |
</tr>
|
84 |
</thead>
|
85 |
|
86 |
<tbody>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
87 |
</tbody>
|
88 |
</table>
|
inc/tpl/integrity-modifiedfiles.snippet.tpl
CHANGED
@@ -1,6 +1,6 @@
|
|
1 |
|
2 |
<tr class="sucuriscan-wraptext %%SUCURI.ModifiedFiles.CssClass%%">
|
3 |
-
<td><span class="sucuriscan-monospace">%%SUCURI.ModifiedFiles.FilePath%%</span></td>
|
4 |
-
<td><em title="%%SUCURI.ModifiedFiles.FileSizeNumber%% bytes">~%%SUCURI.ModifiedFiles.FileSizeHuman%%</em></td>
|
5 |
<td>%%SUCURI.ModifiedFiles.DateTime%%</td>
|
|
|
|
|
6 |
</tr>
|
1 |
|
2 |
<tr class="sucuriscan-wraptext %%SUCURI.ModifiedFiles.CssClass%%">
|
|
|
|
|
3 |
<td>%%SUCURI.ModifiedFiles.DateTime%%</td>
|
4 |
+
<td><em title="%%SUCURI.ModifiedFiles.FileSizeNumber%% bytes">~%%SUCURI.ModifiedFiles.FileSizeHuman%%</em></td>
|
5 |
+
<td><span class="sucuriscan-monospace">%%SUCURI.ModifiedFiles.FilePath%%</span></td>
|
6 |
</tr>
|
inc/tpl/integrity.html.tpl
CHANGED
@@ -1,10 +1,10 @@
|
|
1 |
|
2 |
<div id="poststuff">
|
3 |
-
|
4 |
|
5 |
-
|
6 |
|
7 |
-
|
8 |
|
9 |
-
|
10 |
</div>
|
1 |
|
2 |
<div id="poststuff">
|
3 |
+
%%%SUCURI.WordpressVersion%%%
|
4 |
|
5 |
+
%%%SUCURI.CoreFiles%%%
|
6 |
|
7 |
+
%%%SUCURI.AuditReports%%%
|
8 |
|
9 |
+
%%%SUCURI.AuditLogs%%%
|
10 |
</div>
|
inc/tpl/lastlogins-admins.html.tpl
CHANGED
@@ -10,6 +10,6 @@
|
|
10 |
</thead>
|
11 |
|
12 |
<tbody>
|
13 |
-
|
14 |
</tbody>
|
15 |
</table>
|
10 |
</thead>
|
11 |
|
12 |
<tbody>
|
13 |
+
%%%SUCURI.AdminUsers.List%%%
|
14 |
</tbody>
|
15 |
</table>
|
inc/tpl/lastlogins-admins.snippet.tpl
CHANGED
@@ -4,18 +4,18 @@
|
|
4 |
<td>%%SUCURI.AdminUsers.RegisteredAt%%</td>
|
5 |
<td class="adminusers-lastlogin">
|
6 |
<div class="sucuriscan-%%SUCURI.AdminUsers.NoLastLogins%%">
|
7 |
-
<i>No data available
|
8 |
</div>
|
9 |
|
10 |
<table class="widefat sucuriscan-admins-lastlogins sucuriscan-%%SUCURI.AdminUsers.NoLastLoginsTable%%">
|
11 |
<thead>
|
12 |
<tr>
|
13 |
<th>IP Address</th>
|
14 |
-
<th>Date & Time</th>
|
15 |
</tr>
|
16 |
</thead>
|
17 |
<tbody>
|
18 |
-
|
19 |
</tbody>
|
20 |
</table>
|
21 |
</td>
|
4 |
<td>%%SUCURI.AdminUsers.RegisteredAt%%</td>
|
5 |
<td class="adminusers-lastlogin">
|
6 |
<div class="sucuriscan-%%SUCURI.AdminUsers.NoLastLogins%%">
|
7 |
+
<i>No data available.</i>
|
8 |
</div>
|
9 |
|
10 |
<table class="widefat sucuriscan-admins-lastlogins sucuriscan-%%SUCURI.AdminUsers.NoLastLoginsTable%%">
|
11 |
<thead>
|
12 |
<tr>
|
13 |
<th>IP Address</th>
|
14 |
+
<th>Date & Time</th>
|
15 |
</tr>
|
16 |
</thead>
|
17 |
<tbody>
|
18 |
+
%%%SUCURI.AdminUsers.LastLogins%%%
|
19 |
</tbody>
|
20 |
</table>
|
21 |
</td>
|
inc/tpl/lastlogins-all.html.tpl
CHANGED
@@ -23,7 +23,7 @@
|
|
23 |
</thead>
|
24 |
|
25 |
<tbody>
|
26 |
-
|
27 |
|
28 |
<tr class="sucuriscan-%%SUCURI.UserList.NoItemsVisibility%%">
|
29 |
<td colspan="6">
|
23 |
</thead>
|
24 |
|
25 |
<tbody>
|
26 |
+
%%%SUCURI.UserList%%%
|
27 |
|
28 |
<tr class="sucuriscan-%%SUCURI.UserList.NoItemsVisibility%%">
|
29 |
<td colspan="6">
|
inc/tpl/lastlogins-failedlogins.html.tpl
CHANGED
@@ -6,11 +6,11 @@
|
|
6 |
<div class="inside">
|
7 |
<p>
|
8 |
This information will be used to determine if your site is being victim of
|
9 |
-
<a href="
|
10 |
target="_blank">Password Guessing Brute Force Attacks</a>. These logs will be
|
11 |
accumulated and the plugin will send a report via email if there are more than
|
12 |
<code>%%SUCURI.FailedLogins.MaxFailedLogins%%</code> failed login attempts during
|
13 |
-
the same hour, you can change this number from <a href="%%SUCURI.URL.Settings%%#
|
14 |
<strong>Note.</strong> Some <em>"Two-Factor Authentication"</em> plugins do not
|
15 |
follow the same rules that WordPress have to report failed login attempts, so
|
16 |
you may not see all the attempts in this panel if you have one of these plugins
|
@@ -19,11 +19,11 @@
|
|
19 |
|
20 |
<div class="sucuriscan-inline-alert-warning sucuriscan-%%SUCURI.FailedLogins.WarningVisibility%%">
|
21 |
<p>
|
22 |
-
The option to alert possible <a href="
|
23 |
target="_blank">Password Guessing Brute Force Attacks</a> is disabled, you will
|
24 |
not receive email reports with the attempts collected during the attacks, but
|
25 |
you will continue receiving the alerts of failed logins if you have enabled that
|
26 |
-
option. Go to the <a href="%%SUCURI.URL.Settings%%#
|
27 |
settings</a> panel to change this configuration.
|
28 |
</p>
|
29 |
</div>
|
@@ -34,7 +34,7 @@
|
|
34 |
the security logs. If someone get access to your API key, or your server fails
|
35 |
to process the PHP files (which is not usual but may happen) then an attacker
|
36 |
may steal your credentials and get access to your site. Change this from the <a
|
37 |
-
href="%%SUCURI.URL.Settings%%#
|
38 |
</p>
|
39 |
</div>
|
40 |
</div>
|
@@ -54,8 +54,7 @@
|
|
54 |
</thead>
|
55 |
|
56 |
<tbody>
|
57 |
-
|
58 |
-
%%SUCURI.FailedLogins.List%%
|
59 |
|
60 |
<tr class="sucuriscan-%%SUCURI.FailedLogins.NoItemsVisibility%%">
|
61 |
<td colspan="6">
|
@@ -70,6 +69,5 @@
|
|
70 |
</ul>
|
71 |
</td>
|
72 |
</tr>
|
73 |
-
|
74 |
</tbody>
|
75 |
</table>
|
6 |
<div class="inside">
|
7 |
<p>
|
8 |
This information will be used to determine if your site is being victim of
|
9 |
+
<a href="https://kb.sucuri.net/definitions/attacks/brute-force/password-guessing"
|
10 |
target="_blank">Password Guessing Brute Force Attacks</a>. These logs will be
|
11 |
accumulated and the plugin will send a report via email if there are more than
|
12 |
<code>%%SUCURI.FailedLogins.MaxFailedLogins%%</code> failed login attempts during
|
13 |
+
the same hour, you can change this number from <a href="%%SUCURI.URL.Settings%%#general">here</a>.
|
14 |
<strong>Note.</strong> Some <em>"Two-Factor Authentication"</em> plugins do not
|
15 |
follow the same rules that WordPress have to report failed login attempts, so
|
16 |
you may not see all the attempts in this panel if you have one of these plugins
|
19 |
|
20 |
<div class="sucuriscan-inline-alert-warning sucuriscan-%%SUCURI.FailedLogins.WarningVisibility%%">
|
21 |
<p>
|
22 |
+
The option to alert possible <a href="https://kb.sucuri.net/definitions/attacks/brute-force/password-guessing"
|
23 |
target="_blank">Password Guessing Brute Force Attacks</a> is disabled, you will
|
24 |
not receive email reports with the attempts collected during the attacks, but
|
25 |
you will continue receiving the alerts of failed logins if you have enabled that
|
26 |
+
option. Go to the <a href="%%SUCURI.URL.Settings%%#notifications">alert
|
27 |
settings</a> panel to change this configuration.
|
28 |
</p>
|
29 |
</div>
|
34 |
the security logs. If someone get access to your API key, or your server fails
|
35 |
to process the PHP files (which is not usual but may happen) then an attacker
|
36 |
may steal your credentials and get access to your site. Change this from the <a
|
37 |
+
href="%%SUCURI.URL.Settings%%#general">general settings</a>
|
38 |
</p>
|
39 |
</div>
|
40 |
</div>
|
54 |
</thead>
|
55 |
|
56 |
<tbody>
|
57 |
+
%%%SUCURI.FailedLogins.List%%%
|
|
|
58 |
|
59 |
<tr class="sucuriscan-%%SUCURI.FailedLogins.NoItemsVisibility%%">
|
60 |
<td colspan="6">
|
69 |
</ul>
|
70 |
</td>
|
71 |
</tr>
|
|
|
72 |
</tbody>
|
73 |
</table>
|
inc/tpl/lastlogins-failedlogins.snippet.tpl
CHANGED
@@ -1,8 +1,8 @@
|
|
1 |
|
2 |
<tr class="%%SUCURI.FailedLogins.CssClass%%">
|
3 |
<td>%%SUCURI.FailedLogins.Num%%</td>
|
4 |
-
<td>%%SUCURI.FailedLogins.Username%%</td>
|
5 |
-
<td>%%SUCURI.FailedLogins.Password%%</td>
|
6 |
<td><span class="sucuriscan-monospace">%%SUCURI.FailedLogins.RemoteAddr%%</span></td>
|
7 |
<td><em>%%SUCURI.FailedLogins.Datetime%%</em></td>
|
8 |
<td><div class="sucuriscan-wraptext">%%SUCURI.FailedLogins.UserAgent%%</div></td>
|
1 |
|
2 |
<tr class="%%SUCURI.FailedLogins.CssClass%%">
|
3 |
<td>%%SUCURI.FailedLogins.Num%%</td>
|
4 |
+
<td><span class="sucuriscan-monospace">%%SUCURI.FailedLogins.Username%%</span></td>
|
5 |
+
<td><span class="sucuriscan-label-%%SUCURI.FailedLogins.PasswordColor%%">%%SUCURI.FailedLogins.Password%%</span></td>
|
6 |
<td><span class="sucuriscan-monospace">%%SUCURI.FailedLogins.RemoteAddr%%</span></td>
|
7 |
<td><em>%%SUCURI.FailedLogins.Datetime%%</em></td>
|
8 |
<td><div class="sucuriscan-wraptext">%%SUCURI.FailedLogins.UserAgent%%</div></td>
|
inc/tpl/lastlogins-loggedin.html.tpl
CHANGED
@@ -15,6 +15,6 @@
|
|
15 |
</thead>
|
16 |
|
17 |
<tbody>
|
18 |
-
|
19 |
</tbody>
|
20 |
</table>
|
15 |
</thead>
|
16 |
|
17 |
<tbody>
|
18 |
+
%%%SUCURI.LoggedInUsers.List%%%
|
19 |
</tbody>
|
20 |
</table>
|
inc/tpl/lastlogins.html.tpl
CHANGED
@@ -2,34 +2,34 @@
|
|
2 |
<div class="sucuriscan-tabs">
|
3 |
<ul>
|
4 |
<li>
|
5 |
-
<a href="#" data-tabname="lastlogins-allusers">All Users</a>
|
6 |
</li>
|
7 |
<li>
|
8 |
-
<a href="#" data-tabname="lastlogins-admins">Admin Users</a>
|
9 |
</li>
|
10 |
<li>
|
11 |
-
<a href="#" data-tabname="loggedin-users">Logged In Users</a>
|
12 |
</li>
|
13 |
<li>
|
14 |
-
<a href="#" data-tabname="failed-logins">Failed Logins</a>
|
15 |
</li>
|
16 |
</ul>
|
17 |
|
18 |
<div class="sucuriscan-tab-containers">
|
19 |
<div id="sucuriscan-lastlogins-allusers">
|
20 |
-
|
21 |
</div>
|
22 |
|
23 |
<div id="sucuriscan-lastlogins-admins">
|
24 |
-
|
25 |
</div>
|
26 |
|
27 |
<div id="sucuriscan-loggedin-users">
|
28 |
-
|
29 |
</div>
|
30 |
|
31 |
<div id="sucuriscan-failed-logins">
|
32 |
-
|
33 |
</div>
|
34 |
</div>
|
35 |
</div>
|
2 |
<div class="sucuriscan-tabs">
|
3 |
<ul>
|
4 |
<li>
|
5 |
+
<a href="#lastlogins-allusers" data-tabname="lastlogins-allusers">All Users</a>
|
6 |
</li>
|
7 |
<li>
|
8 |
+
<a href="#lastlogins-admins" data-tabname="lastlogins-admins">Admin Users</a>
|
9 |
</li>
|
10 |
<li>
|
11 |
+
<a href="#loggedin-users" data-tabname="loggedin-users">Logged In Users</a>
|
12 |
</li>
|
13 |
<li>
|
14 |
+
<a href="#failed-logins" data-tabname="failed-logins">Failed Logins</a>
|
15 |
</li>
|
16 |
</ul>
|
17 |
|
18 |
<div class="sucuriscan-tab-containers">
|
19 |
<div id="sucuriscan-lastlogins-allusers">
|
20 |
+
%%%SUCURI.LastLogins.AllUsers%%%
|
21 |
</div>
|
22 |
|
23 |
<div id="sucuriscan-lastlogins-admins">
|
24 |
+
%%%SUCURI.LastLogins.Admins%%%
|
25 |
</div>
|
26 |
|
27 |
<div id="sucuriscan-loggedin-users">
|
28 |
+
%%%SUCURI.LoggedInUsers%%%
|
29 |
</div>
|
30 |
|
31 |
<div id="sucuriscan-failed-logins">
|
32 |
+
%%%SUCURI.FailedLogins%%%
|
33 |
</div>
|
34 |
</div>
|
35 |
</div>
|
inc/tpl/malwarescan-resblacklist.html.tpl
CHANGED
@@ -1,6 +1,5 @@
|
|
1 |
|
2 |
<table class="wp-list-table widefat sucuriscan-table sucuriscan-scanner-details">
|
3 |
-
|
4 |
<thead>
|
5 |
<tr>
|
6 |
<th colspan="3" class="thead-with-button">
|
@@ -10,9 +9,6 @@
|
|
10 |
</thead>
|
11 |
|
12 |
<tbody>
|
13 |
-
|
14 |
-
%%SUCURI.BlacklistStatusList%%
|
15 |
-
|
16 |
</tbody>
|
17 |
-
|
18 |
</table>
|
1 |
|
2 |
<table class="wp-list-table widefat sucuriscan-table sucuriscan-scanner-details">
|
|
|
3 |
<thead>
|
4 |
<tr>
|
5 |
<th colspan="3" class="thead-with-button">
|
9 |
</thead>
|
10 |
|
11 |
<tbody>
|
12 |
+
%%%SUCURI.BlacklistStatusList%%%
|
|
|
|
|
13 |
</tbody>
|
|
|
14 |
</table>
|
inc/tpl/malwarescan-resmalware.html.tpl
CHANGED
@@ -1,21 +1,17 @@
|
|
1 |
|
2 |
<table class="wp-list-table widefat sucuriscan-table sucuriscan-scanner-details">
|
3 |
-
|
4 |
<thead>
|
5 |
-
|
6 |
<tr>
|
7 |
<th colspan="3" class="thead-with-button">
|
8 |
<span>%%SUCURI.WebsiteStatus%%</span>
|
9 |
-
<a href="
|
10 |
class="thead-topright-action button-primary sucuriscan-%%SUCURI.FixButtonVisibility%%">
|
11 |
Request Malware Cleanup</a>
|
12 |
</th>
|
13 |
</tr>
|
14 |
-
|
15 |
</thead>
|
16 |
|
17 |
<tbody>
|
18 |
-
|
19 |
<tr>
|
20 |
<td colspan="3">
|
21 |
<p>
|
@@ -23,7 +19,7 @@
|
|
23 |
website to the SiteCheck API service this plugin will cache the results of every
|
24 |
scan for <strong>%%SUCURI.CacheLifeTime%% seconds</strong>. If you want to get
|
25 |
fresh results after modifications suggested by the scanner then go to the <a
|
26 |
-
href="%%SUCURI.URL.Settings%%#
|
27 |
click the button in front of the label <em>"Reset sitecheck logs"</em>, then
|
28 |
come back to this page and run a new malware scan. Note that SiteCheck may cache
|
29 |
the results of the scan as well in its own server and there is no way you can
|
@@ -32,7 +28,7 @@
|
|
32 |
</td>
|
33 |
</tr>
|
34 |
|
35 |
-
|
36 |
|
37 |
<tr class="sucuriscan-%%SUCURI.NoMalwareRowVisibility%%">
|
38 |
<td><span class="sucuriscan-label sucuriscan-label-success">CLEAN</span></td>
|
@@ -42,7 +38,7 @@
|
|
42 |
<tr class="sucuriscan-%%SUCURI.NoMalwareRowVisibility%%">
|
43 |
<td><span class="sucuriscan-label sucuriscan-label-success">CLEAN</span></td>
|
44 |
<td width="220">
|
45 |
-
<a href="
|
46 |
Malicious javascript
|
47 |
</a>
|
48 |
</td>
|
@@ -59,7 +55,7 @@
|
|
59 |
<tr class="sucuriscan-%%SUCURI.NoMalwareRowVisibility%%">
|
60 |
<td><span class="sucuriscan-label sucuriscan-label-success">CLEAN</span></td>
|
61 |
<td width="220">
|
62 |
-
<a href="
|
63 |
Malicious iframes
|
64 |
</a>
|
65 |
</td>
|
@@ -77,7 +73,7 @@
|
|
77 |
<tr class="sucuriscan-%%SUCURI.NoMalwareRowVisibility%%">
|
78 |
<td><span class="sucuriscan-label sucuriscan-label-success">CLEAN</span></td>
|
79 |
<td width="220">
|
80 |
-
<a href="
|
81 |
Suspicious redirections (htaccess)
|
82 |
</a>
|
83 |
</td>
|
@@ -103,18 +99,16 @@
|
|
103 |
|
104 |
<tr>
|
105 |
<td colspan="3">
|
106 |
-
<hr
|
107 |
<em>
|
108 |
-
More details at <a href="
|
109 |
target="_blank">SiteCheck/%%SUCURI.ScannedDomainName%%</a>. If our free scanner
|
110 |
did not detect any issue, you may have a more complicated and hidden problem.
|
111 |
-
You can <a href="
|
112 |
Sucuri for a complete and in depth scan+cleanup <strong>(not included in the
|
113 |
free checks)</strong>.
|
114 |
</em>
|
115 |
</td>
|
116 |
</tr>
|
117 |
-
|
118 |
</tbody>
|
119 |
-
|
120 |
</table>
|
1 |
|
2 |
<table class="wp-list-table widefat sucuriscan-table sucuriscan-scanner-details">
|
|
|
3 |
<thead>
|
|
|
4 |
<tr>
|
5 |
<th colspan="3" class="thead-with-button">
|
6 |
<span>%%SUCURI.WebsiteStatus%%</span>
|
7 |
+
<a href="https://sucuri.net/website-antivirus/" target="_blank"
|
8 |
class="thead-topright-action button-primary sucuriscan-%%SUCURI.FixButtonVisibility%%">
|
9 |
Request Malware Cleanup</a>
|
10 |
</th>
|
11 |
</tr>
|
|
|
12 |
</thead>
|
13 |
|
14 |
<tbody>
|
|
|
15 |
<tr>
|
16 |
<td colspan="3">
|
17 |
<p>
|
19 |
website to the SiteCheck API service this plugin will cache the results of every
|
20 |
scan for <strong>%%SUCURI.CacheLifeTime%% seconds</strong>. If you want to get
|
21 |
fresh results after modifications suggested by the scanner then go to the <a
|
22 |
+
href="%%SUCURI.URL.Settings%%#scanner">scanner settings</a> page and
|
23 |
click the button in front of the label <em>"Reset sitecheck logs"</em>, then
|
24 |
come back to this page and run a new malware scan. Note that SiteCheck may cache
|
25 |
the results of the scan as well in its own server and there is no way you can
|
28 |
</td>
|
29 |
</tr>
|
30 |
|
31 |
+
%%%SUCURI.MalwarePayloadList%%%
|
32 |
|
33 |
<tr class="sucuriscan-%%SUCURI.NoMalwareRowVisibility%%">
|
34 |
<td><span class="sucuriscan-label sucuriscan-label-success">CLEAN</span></td>
|
38 |
<tr class="sucuriscan-%%SUCURI.NoMalwareRowVisibility%%">
|
39 |
<td><span class="sucuriscan-label sucuriscan-label-success">CLEAN</span></td>
|
40 |
<td width="220">
|
41 |
+
<a href="https://kb.sucuri.net/malware/encoded-javascript" target="_blank">
|
42 |
Malicious javascript
|
43 |
</a>
|
44 |
</td>
|
55 |
<tr class="sucuriscan-%%SUCURI.NoMalwareRowVisibility%%">
|
56 |
<td><span class="sucuriscan-label sucuriscan-label-success">CLEAN</span></td>
|
57 |
<td width="220">
|
58 |
+
<a href="https://kb.sucuri.net/malware/malicious-iframes" target="_blank">
|
59 |
Malicious iframes
|
60 |
</a>
|
61 |
</td>
|
73 |
<tr class="sucuriscan-%%SUCURI.NoMalwareRowVisibility%%">
|
74 |
<td><span class="sucuriscan-label sucuriscan-label-success">CLEAN</span></td>
|
75 |
<td width="220">
|
76 |
+
<a href="https://kb.sucuri.net/malware/conditional-redirections" target="_blank">
|
77 |
Suspicious redirections (htaccess)
|
78 |
</a>
|
79 |
</td>
|
99 |
|
100 |
<tr>
|
101 |
<td colspan="3">
|
102 |
+
<hr>
|
103 |
<em>
|
104 |
+
More details at <a href="https://sitecheck.sucuri.net/results/%%SUCURI.ScannedDomainName%%"
|
105 |
target="_blank">SiteCheck/%%SUCURI.ScannedDomainName%%</a>. If our free scanner
|
106 |
did not detect any issue, you may have a more complicated and hidden problem.
|
107 |
+
You can <a href="https://sucuri.net/signup" target="_blank">sign up</a> with
|
108 |
Sucuri for a complete and in depth scan+cleanup <strong>(not included in the
|
109 |
free checks)</strong>.
|
110 |
</em>
|
111 |
</td>
|
112 |
</tr>
|
|
|
113 |
</tbody>
|
|
|
114 |
</table>
|
inc/tpl/malwarescan-resmalware.snippet.tpl
CHANGED
@@ -1,6 +1,5 @@
|
|
1 |
|
2 |
<tr>
|
3 |
-
|
4 |
<td>
|
5 |
<a href="%%SUCURI.MalwareDocs%%" target="_blank">%%SUCURI.AlertMessage%%</a>
|
6 |
</td>
|
@@ -23,5 +22,4 @@
|
|
23 |
<div class="sucuriscan-malware-payload sucuriscan-monospace">%%SUCURI.MalwarePayload%%</div>
|
24 |
</div>
|
25 |
</td>
|
26 |
-
|
27 |
</tr>
|
1 |
|
2 |
<tr>
|
|
|
3 |
<td>
|
4 |
<a href="%%SUCURI.MalwareDocs%%" target="_blank">%%SUCURI.AlertMessage%%</a>
|
5 |
</td>
|
22 |
<div class="sucuriscan-malware-payload sucuriscan-monospace">%%SUCURI.MalwarePayload%%</div>
|
23 |
</div>
|
24 |
</td>
|
|
|
25 |
</tr>
|
inc/tpl/malwarescan-results.html.tpl
CHANGED
@@ -1,51 +1,48 @@
|
|
1 |
-
<div class="sucuriscan-tabs">
|
2 |
|
|
|
3 |
<ul>
|
4 |
<li class="%%SUCURI.ScannerResults.CssClass%%">
|
5 |
-
<a href="#" data-tabname="sitecheck-results">Remote Scanner Results</a>
|
6 |
</li>
|
7 |
<li class="%%SUCURI.WebsiteDetails.CssClass%%">
|
8 |
-
<a href="#" data-tabname="website-details">Website Details</a>
|
9 |
</li>
|
10 |
<li class="%%SUCURI.WebsiteLinks.CssClass%%">
|
11 |
-
<a href="#" data-tabname="website-links">IFrames / Links / Scripts</a>
|
12 |
</li>
|
13 |
<li class="%%SUCURI.BlacklistStatus.CssClass%%">
|
14 |
-
<a href="#" data-tabname="blacklist-status">Blacklist Status</a>
|
15 |
</li>
|
16 |
<li class="%%SUCURI.ModifiedFiles.CssClass%%">
|
17 |
-
<a href="#" data-tabname="modified-files">Modified Files</a>
|
18 |
</li>
|
19 |
</ul>
|
20 |
|
21 |
<div class="sucuriscan-tab-containers">
|
22 |
-
|
23 |
<div id="sucuriscan-sitecheck-results">
|
24 |
-
|
25 |
</div>
|
26 |
|
27 |
<div id="sucuriscan-website-details">
|
28 |
-
|
29 |
</div>
|
30 |
|
31 |
<div id="sucuriscan-website-links">
|
32 |
-
|
33 |
</div>
|
34 |
|
35 |
<div id="sucuriscan-blacklist-status">
|
36 |
-
|
37 |
</div>
|
38 |
|
39 |
<div id="sucuriscan-modified-files">
|
40 |
-
|
41 |
</div>
|
42 |
-
|
43 |
</div>
|
44 |
-
|
45 |
</div>
|
46 |
|
47 |
<div>
|
48 |
-
<a href="
|
49 |
class="button button-primary button-hero sucuriscan-cleanup-btn
|
50 |
sucuriscan-btnblock sucuriscan-%%SUCURI.SignupButtonVisibility%%">
|
51 |
Get your site protected with Sucuri</a>
|
|
|
1 |
|
2 |
+
<div class="sucuriscan-tabs">
|
3 |
<ul>
|
4 |
<li class="%%SUCURI.ScannerResults.CssClass%%">
|
5 |
+
<a href="#sitecheck-results" data-tabname="sitecheck-results">Remote Scanner Results</a>
|
6 |
</li>
|
7 |
<li class="%%SUCURI.WebsiteDetails.CssClass%%">
|
8 |
+
<a href="#website-details" data-tabname="website-details">Website Details</a>
|
9 |
</li>
|
10 |
<li class="%%SUCURI.WebsiteLinks.CssClass%%">
|
11 |
+
<a href="#website-links" data-tabname="website-links">IFrames / Links / Scripts</a>
|
12 |
</li>
|
13 |
<li class="%%SUCURI.BlacklistStatus.CssClass%%">
|
14 |
+
<a href="#blacklist-status" data-tabname="blacklist-status">Blacklist Status</a>
|
15 |
</li>
|
16 |
<li class="%%SUCURI.ModifiedFiles.CssClass%%">
|
17 |
+
<a href="#modified-files" data-tabname="modified-files">Modified Files</a>
|
18 |
</li>
|
19 |
</ul>
|
20 |
|
21 |
<div class="sucuriscan-tab-containers">
|
|
|
22 |
<div id="sucuriscan-sitecheck-results">
|
23 |
+
%%%SUCURI.ScannerResults.Content%%%
|
24 |
</div>
|
25 |
|
26 |
<div id="sucuriscan-website-details">
|
27 |
+
%%%SUCURI.WebsiteDetails.Content%%%
|
28 |
</div>
|
29 |
|
30 |
<div id="sucuriscan-website-links">
|
31 |
+
%%%SUCURI.WebsiteLinks.Content%%%
|
32 |
</div>
|
33 |
|
34 |
<div id="sucuriscan-blacklist-status">
|
35 |
+
%%%SUCURI.BlacklistStatus.Content%%%
|
36 |
</div>
|
37 |
|
38 |
<div id="sucuriscan-modified-files">
|
39 |
+
%%%SUCURI.ModifiedFiles.Content%%%
|
40 |
</div>
|
|
|
41 |
</div>
|
|
|
42 |
</div>
|
43 |
|
44 |
<div>
|
45 |
+
<a href="https://sucuri.net/signup/" target="_blank"
|
46 |
class="button button-primary button-hero sucuriscan-cleanup-btn
|
47 |
sucuriscan-btnblock sucuriscan-%%SUCURI.SignupButtonVisibility%%">
|
48 |
Get your site protected with Sucuri</a>
|
inc/tpl/malwarescan-reswebdetails.html.tpl
CHANGED
@@ -1,8 +1,6 @@
|
|
1 |
|
2 |
<table class="wp-list-table widefat sucuriscan-table sucuriscan-scanner-details">
|
3 |
-
|
4 |
<thead>
|
5 |
-
|
6 |
<tr>
|
7 |
<th colspan="2" class="thead-with-button">
|
8 |
<span>System information</span>
|
@@ -14,22 +12,20 @@
|
|
14 |
</a>
|
15 |
</th>
|
16 |
</tr>
|
17 |
-
|
18 |
</thead>
|
19 |
|
20 |
<tbody>
|
21 |
-
|
22 |
<!-- List of generic information from the site. -->
|
23 |
-
|
24 |
|
25 |
<!-- List of application details from the site. -->
|
26 |
<tr>
|
27 |
<th colspan="2">Web application details</th>
|
28 |
</tr>
|
29 |
|
30 |
-
|
31 |
|
32 |
-
|
33 |
|
34 |
<tr class="sucuriscan-%%SUCURI.NoAppDetailsVisibility%%">
|
35 |
<td colspan="2"><em>No more information was found.</em></td>
|
@@ -41,11 +37,9 @@
|
|
41 |
</tr>
|
42 |
|
43 |
<!-- Possible outdated software on the site. -->
|
44 |
-
|
45 |
|
46 |
<!-- Possible recommendations for the site. -->
|
47 |
-
|
48 |
-
|
49 |
</tbody>
|
50 |
-
|
51 |
</table>
|
1 |
|
2 |
<table class="wp-list-table widefat sucuriscan-table sucuriscan-scanner-details">
|
|
|
3 |
<thead>
|
|
|
4 |
<tr>
|
5 |
<th colspan="2" class="thead-with-button">
|
6 |
<span>System information</span>
|
12 |
</a>
|
13 |
</th>
|
14 |
</tr>
|
|
|
15 |
</thead>
|
16 |
|
17 |
<tbody>
|
|
|
18 |
<!-- List of generic information from the site. -->
|
19 |
+
%%%SUCURI.GenericInformationList%%%
|
20 |
|
21 |
<!-- List of application details from the site. -->
|
22 |
<tr>
|
23 |
<th colspan="2">Web application details</th>
|
24 |
</tr>
|
25 |
|
26 |
+
%%%SUCURI.ApplicationDetailsList%%%
|
27 |
|
28 |
+
%%%SUCURI.SystemNoticeList%%%
|
29 |
|
30 |
<tr class="sucuriscan-%%SUCURI.NoAppDetailsVisibility%%">
|
31 |
<td colspan="2"><em>No more information was found.</em></td>
|
37 |
</tr>
|
38 |
|
39 |
<!-- Possible outdated software on the site. -->
|
40 |
+
%%%SUCURI.OutdatedSoftwareList%%%
|
41 |
|
42 |
<!-- Possible recommendations for the site. -->
|
43 |
+
%%%SUCURI.SecurityRecomendationList%%%
|
|
|
44 |
</tbody>
|
|
|
45 |
</table>
|
inc/tpl/malwarescan-resweblinks.html.tpl
CHANGED
@@ -1,13 +1,10 @@
|
|
1 |
|
2 |
<table class="wp-list-table widefat sucuriscan-table sucuriscan-scanner-links">
|
3 |
<tbody>
|
4 |
-
|
5 |
-
%%SUCURI.WebsiteLinksAllList%%
|
6 |
|
7 |
<tr class="sucuriscan-%%SUCURI.NoLinksVisibility%%">
|
8 |
<td><em>No iFrames, links, or script files were found.</em></td>
|
9 |
</tr>
|
10 |
-
|
11 |
</tbody>
|
12 |
-
|
13 |
</table>
|
1 |
|
2 |
<table class="wp-list-table widefat sucuriscan-table sucuriscan-scanner-links">
|
3 |
<tbody>
|
4 |
+
%%%SUCURI.WebsiteLinksAllList%%%
|
|
|
5 |
|
6 |
<tr class="sucuriscan-%%SUCURI.NoLinksVisibility%%">
|
7 |
<td><em>No iFrames, links, or script files were found.</em></td>
|
8 |
</tr>
|
|
|
9 |
</tbody>
|
|
|
10 |
</table>
|
inc/tpl/malwarescan-weblinktitle.snippet.tpl
CHANGED
@@ -6,4 +6,4 @@
|
|
6 |
</th>
|
7 |
</tr>
|
8 |
|
9 |
-
|
6 |
</th>
|
7 |
</tr>
|
8 |
|
9 |
+
%%%SUCURI.WebsiteLinksSectionItems%%%
|
inc/tpl/malwarescan.html.tpl
CHANGED
@@ -2,7 +2,7 @@
|
|
2 |
<div class="sucuriscan-loading">
|
3 |
<h3 class="title">Website Security Scans by Sucuri Sitecheck</h3>
|
4 |
|
5 |
-
<p class="description">Visit our <a href="
|
6 |
|
7 |
<form action="%%SUCURI.URL.Scanner%%" method="post" class="sucuriscan-sitecheck-form">
|
8 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
@@ -24,11 +24,11 @@
|
|
24 |
|
25 |
<div class="sucuriscan-sitecheck-disclaimer">
|
26 |
<p>
|
27 |
-
The malware scanner is a free tool powered by <a href="
|
28 |
Sucuri SiteCheck</a>, it will check your website for known malware, blacklisting
|
29 |
status, website errors, and out-of-date software. Although we do our best to
|
30 |
provide the best results, 100% accuracy is not realistic, and not guaranteed.
|
31 |
-
You can also <a href="%%SUCURI.URL.Settings%%#
|
32 |
feature</a> from the settings page if you do not want to allow any of your
|
33 |
registered users to use it.
|
34 |
</p>
|
2 |
<div class="sucuriscan-loading">
|
3 |
<h3 class="title">Website Security Scans by Sucuri Sitecheck</h3>
|
4 |
|
5 |
+
<p class="description">Visit our <a href="https://sucuri.net/signup?fromloader" target="_blank">coverage & pricing</a> page for details on how sucuri can help you.</p>
|
6 |
|
7 |
<form action="%%SUCURI.URL.Scanner%%" method="post" class="sucuriscan-sitecheck-form">
|
8 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
24 |
|
25 |
<div class="sucuriscan-sitecheck-disclaimer">
|
26 |
<p>
|
27 |
+
The malware scanner is a free tool powered by <a href="https://sitecheck.sucuri.net/" target="_blank">
|
28 |
Sucuri SiteCheck</a>, it will check your website for known malware, blacklisting
|
29 |
status, website errors, and out-of-date software. Although we do our best to
|
30 |
provide the best results, 100% accuracy is not realistic, and not guaranteed.
|
31 |
+
You can also <a href="%%SUCURI.URL.Settings%%#scanner">disable this
|
32 |
feature</a> from the settings page if you do not want to allow any of your
|
33 |
registered users to use it.
|
34 |
</p>
|
inc/tpl/modalwindow.html.tpl
CHANGED
@@ -13,8 +13,7 @@
|
|
13 |
</div>
|
14 |
|
15 |
<div class="sucuriscan-modal-inside">
|
16 |
-
|
17 |
</div>
|
18 |
-
|
19 |
</div>
|
20 |
</div>
|
13 |
</div>
|
14 |
|
15 |
<div class="sucuriscan-modal-inside">
|
16 |
+
%%%SUCURI.Content%%%
|
17 |
</div>
|
|
|
18 |
</div>
|
19 |
</div>
|
inc/tpl/monitoring-logs.html.tpl
DELETED
@@ -1,73 +0,0 @@
|
|
1 |
-
|
2 |
-
<table class="wp-list-table widefat sucuriscan-table sucuriscan-table-quad-title sucuriscan-monitoring-logs">
|
3 |
-
<thead>
|
4 |
-
<tr>
|
5 |
-
<th colspan="4" class="thead-with-button">
|
6 |
-
<span>Search among the logs:</span>
|
7 |
-
<div class="thead-topright-action">
|
8 |
-
<form action="%%SUCURI.URL.Monitoring%%#monitoring-logs" method="post" class="sucuriscan-monitoring-search-form">
|
9 |
-
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
10 |
-
<input type="text" name="sucuriscan_monitoring_log_filter" class="input-text" />
|
11 |
-
<input type="submit" value="Search" class="button button-primary" />
|
12 |
-
</form>
|
13 |
-
</div>
|
14 |
-
</th>
|
15 |
-
</tr>
|
16 |
-
|
17 |
-
<tr>
|
18 |
-
<th colspan="4" class="thead-with-button">
|
19 |
-
<span>Filter by the denial type:</span>
|
20 |
-
<div class="thead-topright-action">
|
21 |
-
<form action="%%SUCURI.URL.Monitoring%%#monitoring-logs" method="post" class="sucuriscan-monitoring-denial-types-form">
|
22 |
-
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
23 |
-
<select name="sucuriscan_monitoring_denial_type">%%SUCURI.AuditLogs.DenialTypeOptions%%</select>
|
24 |
-
<input type="submit" value="Filter" class="button button-primary" />
|
25 |
-
</form>
|
26 |
-
</div>
|
27 |
-
</th>
|
28 |
-
</tr>
|
29 |
-
|
30 |
-
<tr>
|
31 |
-
<th colspan="4" class="thead-with-button">
|
32 |
-
<span>Filter by date:</span>
|
33 |
-
<div class="thead-topright-action">
|
34 |
-
<form action="%%SUCURI.URL.Monitoring%%#monitoring-logs" method="post" class="sucuriscan-monitoring-date-form">
|
35 |
-
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
36 |
-
<input type="hidden" name="sucuriscan_monitoring_date" value="1" />
|
37 |
-
<em class="sucuriscan-target-date">(%%SUCURI.AuditLogs.TargetDate%%)</em>
|
38 |
-
<select name="sucuriscan_year">%%SUCURI.AuditLogs.DateYears%%</select>
|
39 |
-
<select name="sucuriscan_month">%%SUCURI.AuditLogs.DateMonths%%</select>
|
40 |
-
<select name="sucuriscan_day">%%SUCURI.AuditLogs.DateDays%%</select>
|
41 |
-
<input type="submit" value="Filter" class="button button-primary" />
|
42 |
-
</form>
|
43 |
-
</div>
|
44 |
-
</th>
|
45 |
-
</tr>
|
46 |
-
|
47 |
-
<tr>
|
48 |
-
<th width="250">Denial Type</th>
|
49 |
-
<th width="120">Remote Address</th>
|
50 |
-
<th>Request Path</th>
|
51 |
-
</tr>
|
52 |
-
</thead>
|
53 |
-
|
54 |
-
<tbody>
|
55 |
-
%%SUCURI.AuditLogs.List%%
|
56 |
-
|
57 |
-
<tr class="sucuriscan-%%SUCURI.AuditLogs.NoItemsVisibility%%">
|
58 |
-
<td colspan="4">
|
59 |
-
<em>Audit trails is empty.</em>
|
60 |
-
</td>
|
61 |
-
</tr>
|
62 |
-
</tbody>
|
63 |
-
|
64 |
-
<tfoot>
|
65 |
-
<tr class="sucuriscan-%%SUCURI.AuditLogs.PaginationVisibility%%">
|
66 |
-
<td colspan="4">
|
67 |
-
<div class='pagination' style="float:right;">
|
68 |
-
%%SUCURI.AuditLogs.AuditPagination%%
|
69 |
-
</div>
|
70 |
-
</td>
|
71 |
-
</tr>
|
72 |
-
</tfoot>
|
73 |
-
</table>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
inc/tpl/monitoring-logs.snippet.tpl
DELETED
@@ -1,71 +0,0 @@
|
|
1 |
-
|
2 |
-
<tr class="%%SUCURI.AuditLog.CssClass%%">
|
3 |
-
<td>
|
4 |
-
<span class="sucuriscan-denial-type">%%SUCURI.AuditLog.SucuriBlockReason%%</span><br>
|
5 |
-
<span class="sucuriscan-denial-type-date">Date/Time: %%SUCURI.AuditLog.LocalRequestTime%%</span>
|
6 |
-
</td>
|
7 |
-
<td><span class="sucuriscan-monospace">%%SUCURI.AuditLog.RemoteAddr%%</span></td>
|
8 |
-
<td>
|
9 |
-
<div class="sucuriscan-wraptext">
|
10 |
-
<a href="#TB_inline?width=600&height=300&inlineId=sucuriscan-reqsummary-%%SUCURI.AuditLog.Id%%" title="Access Log Summary" class="thickbox">
|
11 |
-
<span class="sucuriscan-monospace">%%SUCURI.AuditLog.ResourcePath%%</span>
|
12 |
-
</a>
|
13 |
-
</div>
|
14 |
-
|
15 |
-
<div id="sucuriscan-reqsummary-%%SUCURI.AuditLog.Id%%" style="display:none">
|
16 |
-
<div class="sucuriscan-request-summary">
|
17 |
-
<table class="wp-list-table widefat">
|
18 |
-
<thead>
|
19 |
-
<tr>
|
20 |
-
<th width="200">Information</th>
|
21 |
-
<th> </th>
|
22 |
-
</tr>
|
23 |
-
</thead>
|
24 |
-
|
25 |
-
<tbody>
|
26 |
-
<tr class="alternate">
|
27 |
-
<td>Blocked Reason</td>
|
28 |
-
<td class="sucuriscan-monospace">%%SUCURI.AuditLog.SucuriBlockReason%%</td>
|
29 |
-
</tr>
|
30 |
-
<tr>
|
31 |
-
<td>Remote Address</td>
|
32 |
-
<td class="sucuriscan-monospace">%%SUCURI.AuditLog.RemoteAddr%%</td>
|
33 |
-
</tr>
|
34 |
-
<tr class="alternate">
|
35 |
-
<td>Date & Time (Local Time)</td>
|
36 |
-
<td class="sucuriscan-monospace">%%SUCURI.AuditLog.LocalRequestTime%%</td>
|
37 |
-
</tr>
|
38 |
-
<tr>
|
39 |
-
<td>Resource Path</td>
|
40 |
-
<td class="sucuriscan-monospace">%%SUCURI.AuditLog.ResourcePath%%</td>
|
41 |
-
</tr>
|
42 |
-
<tr class="alternate">
|
43 |
-
<td>Request Method</td>
|
44 |
-
<td class="sucuriscan-monospace">%%SUCURI.AuditLog.RequestMethod%%</td>
|
45 |
-
</tr>
|
46 |
-
<tr>
|
47 |
-
<td>HTTP Protocol</td>
|
48 |
-
<td class="sucuriscan-monospace">%%SUCURI.AuditLog.HttpProtocol%%</td>
|
49 |
-
</tr>
|
50 |
-
<tr class="alternate">
|
51 |
-
<td>HTTP Status</td>
|
52 |
-
<td class="sucuriscan-monospace">%%SUCURI.AuditLog.HttpStatus%% %%SUCURI.AuditLog.HttpStatusTitle%%</td>
|
53 |
-
</tr>
|
54 |
-
<tr>
|
55 |
-
<td>HTTP Bytes Sent</td>
|
56 |
-
<td class="sucuriscan-monospace">%%SUCURI.AuditLog.HttpBytesSent%%</td>
|
57 |
-
</tr>
|
58 |
-
<tr class="alternate">
|
59 |
-
<td>HTTP Referer</td>
|
60 |
-
<td class="sucuriscan-monospace">%%SUCURI.AuditLog.HttpReferer%%</td>
|
61 |
-
</tr>
|
62 |
-
<tr>
|
63 |
-
<td>HTTP User Agent</td>
|
64 |
-
<td class="sucuriscan-monospace">%%SUCURI.AuditLog.HttpUserAgent%%</td>
|
65 |
-
</tr>
|
66 |
-
</tbody>
|
67 |
-
</table>
|
68 |
-
</div>
|
69 |
-
</div>
|
70 |
-
</td>
|
71 |
-
</tr>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
inc/tpl/monitoring-settings.html.tpl
DELETED
@@ -1,28 +0,0 @@
|
|
1 |
-
|
2 |
-
<table class="wp-list-table widefat sucuriscan-table sucuriscan-monitoring-settings">
|
3 |
-
<tbody>
|
4 |
-
<tr>
|
5 |
-
<td width="200"><label>CloudProxy API key</label></td>
|
6 |
-
<td class="td-with-button">
|
7 |
-
<form action="%%SUCURI.URL.Monitoring%%#monitoring-settings" method="post" class="sucuriscan-monitoring-apikey-form">
|
8 |
-
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
9 |
-
<input type="text" name="sucuriscan_cloudproxy_apikey" value="%%SUCURI.Monitoring.APIKey%%" class="input-text" />
|
10 |
-
<input type="submit" value="Save" class="button button-primary" />
|
11 |
-
</form>
|
12 |
-
</td>
|
13 |
-
</tr>
|
14 |
-
|
15 |
-
%%SUCURI.Monitoring.SettingOptions%%
|
16 |
-
|
17 |
-
<tr class="alternate sucuriscan-%%SUCURI.Monitoring.SettingsVisibility%%">
|
18 |
-
<td><label>Clear cache</label></td>
|
19 |
-
<td class="td-with-button">
|
20 |
-
<form action="%%SUCURI.URL.Monitoring%%#monitoring-settings" method="post" class="sucuriscan-monitoring-clear-cache-form">
|
21 |
-
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
22 |
-
<input type="hidden" name="sucuriscan_clear_cache" value="1" />
|
23 |
-
<input type="submit" value="Clear Cache" class="button button-primary" />
|
24 |
-
</form>
|
25 |
-
</td>
|
26 |
-
</tr>
|
27 |
-
</tbody>
|
28 |
-
</table>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
inc/tpl/monitoring-settings.snippet.tpl
DELETED
@@ -1,5 +0,0 @@
|
|
1 |
-
|
2 |
-
<tr class="%%SUCURI.Monitoring.OptionCssClass%%">
|
3 |
-
<td><label>%%SUCURI.Monitoring.OptionName%%</label></td>
|
4 |
-
<td><span class="sucuriscan-monospace">%%SUCURI.Monitoring.OptionValue%%</span></td>
|
5 |
-
</tr>
|
|
|
|
|
|
|
|
|
|
inc/tpl/monitoring.html.tpl
DELETED
@@ -1,58 +0,0 @@
|
|
1 |
-
|
2 |
-
<div id="poststuff">
|
3 |
-
|
4 |
-
<div class="postbox sucuriscan-border sucuriscan-border-info sucuriscan-%%SUCURI.Monitoring.InstructionsVisibility%%">
|
5 |
-
<h3>Activation instructions</h3>
|
6 |
-
|
7 |
-
<div class="inside">
|
8 |
-
<p>
|
9 |
-
A powerful <b>WAF</b> <em>(Web Application Firewall)</em> and <b>Intrusion
|
10 |
-
Prevention</b> system for any WordPress user and many other platforms. This page
|
11 |
-
will help you to configure and monitor your site through <strong>Sucuri
|
12 |
-
CloudProxy</strong>. Once enabled, our firewall will act as a shield, protecting
|
13 |
-
your site from attacks and preventing malware infections and reinfections. It
|
14 |
-
will block SQL injection attempts, brute force attacks, XSS, RFI, backdoors and
|
15 |
-
many other threats against your site.
|
16 |
-
</p>
|
17 |
-
|
18 |
-
<p>
|
19 |
-
Add your <strong>API key</strong> in the form bellow, click in the
|
20 |
-
<em>activate</em> button and after that your site will start communicating with
|
21 |
-
the official CloudProxy API service. Your account settings, whitelisted IP
|
22 |
-
addresses, audit logs, and the cache status will be displayed when the API key
|
23 |
-
is validated.
|
24 |
-
</p>
|
25 |
-
|
26 |
-
<p>
|
27 |
-
<em>[1]</em> More information about <a href="http://cloudproxy.sucuri.net/" target="_blank">CloudProxy</a>.<br>
|
28 |
-
<em>[2]</em> Configuration instructions and videos in the official <a href="http://kb.sucuri.net/cloudproxy"
|
29 |
-
target="_blank">Knowledge Base</a> site.<br>
|
30 |
-
<em>[3]</em> <a href="https://login.sucuri.net/signup2/create?CloudProxy" target="_blank">Sign up</a> for a new
|
31 |
-
account and start protecting your site with CloudProxy.
|
32 |
-
</p>
|
33 |
-
</div>
|
34 |
-
</div>
|
35 |
-
|
36 |
-
|
37 |
-
<div class="sucuriscan-tabs">
|
38 |
-
<ul>
|
39 |
-
<li>
|
40 |
-
<a href="#" data-tabname="monitoring-settings">Firewall (WAF) Settings</a>
|
41 |
-
</li>
|
42 |
-
<li>
|
43 |
-
<a href="#" data-tabname="monitoring-logs">Firewall (WAF) Logs</a>
|
44 |
-
</li>
|
45 |
-
</ul>
|
46 |
-
|
47 |
-
<div class="sucuriscan-tab-containers">
|
48 |
-
<div id="sucuriscan-monitoring-settings">
|
49 |
-
%%SUCURI.Monitoring.Settings%%
|
50 |
-
</div>
|
51 |
-
|
52 |
-
<div id="sucuriscan-monitoring-logs">
|
53 |
-
%%SUCURI.Monitoring.Logs%%
|
54 |
-
</div>
|
55 |
-
</div>
|
56 |
-
</div>
|
57 |
-
|
58 |
-
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
inc/tpl/notification-admin.html.tpl
ADDED
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
<div id="sucuriscan-alert-%%SUCURI.AlertUnique%%" class="%%SUCURI.AlertType%% sucuriscan-alert sucuriscan-alert-%%SUCURI.AlertType%%">
|
3 |
+
<a href="javascript:void(0)" class="close" onclick="sucuriscan_alert_close('%%SUCURI.AlertUnique%%')">×</a>
|
4 |
+
<p>%%%SUCURI.AlertMessage%%%</p>
|
5 |
+
</div>
|
inc/tpl/notification-pretty.html.tpl
CHANGED
@@ -3,7 +3,7 @@
|
|
3 |
<thead sytle="border-bottom:1px solid #ccc">
|
4 |
<tr style="background-color:#4b4b4b;background-image:-moz-linear-gradient(top, #555555, #3b3b3b);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#555555), to(#3b3b3b));background-image:-webkit-linear-gradient(top, #555555, #3b3b3b);background-image:-o-linear-gradient(top, #555555, #3b3b3b);background-image:linear-gradient(to bottom, #555555, #3b3b3b);background-repeat:repeat-x">
|
5 |
<td sytle="font-size:20px;font-weight:normal;color:#ffffff;padding:10px;border-right:1px solid #2f2f2f;border-left:1px solid #6f6f6f;-webkit-box-shadow:inset 0 1px 0 #888888;-moz-box-shadow:inset 0 1px 0 #888888;box-shadow:inset 0 1px 0 #888888;text-shadow:1px 1px 2px rgba(0, 0, 0, 0.5)">
|
6 |
-
<a href="
|
7 |
<img src="%%SUCURI.SucuriURL%%/inc/images/main-logo.png" alt="Sucuri, Inc." style="border:none" />
|
8 |
</a>
|
9 |
<span style="display:inline-block;line-height:46px;margin:0 20px 0 0;float:right;color:#ffffff">%%SUCURI.TemplateTitle%%</span>
|
@@ -24,7 +24,7 @@
|
|
24 |
IP Address: %%SUCURI.RemoteAddress%%<br>
|
25 |
</p>
|
26 |
<h4 style="text-transform:uppercase;margin:0">Notification Message:</h4>
|
27 |
-
<p style="margin:0 0 10px 0"
|
28 |
</td>
|
29 |
</tr>
|
30 |
</tbody>
|
3 |
<thead sytle="border-bottom:1px solid #ccc">
|
4 |
<tr style="background-color:#4b4b4b;background-image:-moz-linear-gradient(top, #555555, #3b3b3b);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#555555), to(#3b3b3b));background-image:-webkit-linear-gradient(top, #555555, #3b3b3b);background-image:-o-linear-gradient(top, #555555, #3b3b3b);background-image:linear-gradient(to bottom, #555555, #3b3b3b);background-repeat:repeat-x">
|
5 |
<td sytle="font-size:20px;font-weight:normal;color:#ffffff;padding:10px;border-right:1px solid #2f2f2f;border-left:1px solid #6f6f6f;-webkit-box-shadow:inset 0 1px 0 #888888;-moz-box-shadow:inset 0 1px 0 #888888;box-shadow:inset 0 1px 0 #888888;text-shadow:1px 1px 2px rgba(0, 0, 0, 0.5)">
|
6 |
+
<a href="https://sucuri.net/" style="text-decoration:none;display:inline-block;margin:8px 0 5px 20px">
|
7 |
<img src="%%SUCURI.SucuriURL%%/inc/images/main-logo.png" alt="Sucuri, Inc." style="border:none" />
|
8 |
</a>
|
9 |
<span style="display:inline-block;line-height:46px;margin:0 20px 0 0;float:right;color:#ffffff">%%SUCURI.TemplateTitle%%</span>
|
24 |
IP Address: %%SUCURI.RemoteAddress%%<br>
|
25 |
</p>
|
26 |
<h4 style="text-transform:uppercase;margin:0">Notification Message:</h4>
|
27 |
+
<p style="margin:0 0 10px 0">%%%SUCURI.Message%%%</p>
|
28 |
</td>
|
29 |
</tr>
|
30 |
</tbody>
|
inc/tpl/notification-resetpwd.html.tpl
CHANGED
@@ -3,6 +3,7 @@ Your password for <strong>%%SUCURI.ResetPassword.UserName%%</strong>
|
|
3 |
<em>(%%SUCURI.ResetPassword.DisplayName%%)</em> at <a target="_blank"
|
4 |
href="http://%%SUCURI.ResetPassword.Website%%">%%SUCURI.ResetPassword.Website%%</a>
|
5 |
has been reset for security reasons.<br>
|
|
|
6 |
You can use this temporary password to log in:
|
7 |
<span style="display:inline-block;background:#f5f5f5;padding:2px 6px;
|
8 |
font-family:Menlo, Monaco, monospace, serif;border:1px solid #ddd">
|
3 |
<em>(%%SUCURI.ResetPassword.DisplayName%%)</em> at <a target="_blank"
|
4 |
href="http://%%SUCURI.ResetPassword.Website%%">%%SUCURI.ResetPassword.Website%%</a>
|
5 |
has been reset for security reasons.<br>
|
6 |
+
|
7 |
You can use this temporary password to log in:
|
8 |
<span style="display:inline-block;background:#f5f5f5;padding:2px 6px;
|
9 |
font-family:Menlo, Monaco, monospace, serif;border:1px solid #ddd">
|
inc/tpl/posthack-resetpassword.html.tpl
CHANGED
@@ -36,12 +36,12 @@
|
|
36 |
</thead>
|
37 |
|
38 |
<tbody>
|
39 |
-
|
40 |
|
41 |
<tr class="sucuriscan-%%SUCURI.ResetPassword.PaginationVisibility%%">
|
42 |
<td colspan="4">
|
43 |
<ul class="sucuriscan-pagination">
|
44 |
-
|
45 |
</ul>
|
46 |
</td>
|
47 |
</tr>
|
36 |
</thead>
|
37 |
|
38 |
<tbody>
|
39 |
+
%%%SUCURI.ResetPassword.UserList%%%
|
40 |
|
41 |
<tr class="sucuriscan-%%SUCURI.ResetPassword.PaginationVisibility%%">
|
42 |
<td colspan="4">
|
43 |
<ul class="sucuriscan-pagination">
|
44 |
+
%%%SUCURI.ResetPassword.PaginationLinks%%%
|
45 |
</ul>
|
46 |
</td>
|
47 |
</tr>
|
inc/tpl/posthack-resetplugins.html.tpl
CHANGED
@@ -1,12 +1,8 @@
|
|
1 |
|
2 |
<div id="poststuff" class="sucuriscan-reset-plugins">
|
3 |
-
|
4 |
<div class="postbox">
|
5 |
-
|
6 |
<div class="inside">
|
7 |
-
|
8 |
<form action="%%SUCURI.URL.Posthack%%#reset-plugins" method="post">
|
9 |
-
|
10 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
11 |
<input type="hidden" name="sucuriscan_reset_plugins" value="1" />
|
12 |
|
@@ -60,12 +56,11 @@
|
|
60 |
</p>
|
61 |
|
62 |
<input type="submit" value="Process selected items" class="button button-primary" />
|
63 |
-
|
64 |
</form>
|
65 |
|
66 |
<script type="text/javascript">
|
67 |
jQuery(function($){
|
68 |
-
$.post(
|
69 |
action: 'sucuriscan_posthack_ajax',
|
70 |
sucuriscan_page_nonce: '%%SUCURI.PageNonce%%',
|
71 |
form_action: 'get_plugins_data',
|
@@ -74,9 +69,6 @@
|
|
74 |
});
|
75 |
});
|
76 |
</script>
|
77 |
-
|
78 |
</div>
|
79 |
-
|
80 |
</div>
|
81 |
-
|
82 |
</div>
|
1 |
|
2 |
<div id="poststuff" class="sucuriscan-reset-plugins">
|
|
|
3 |
<div class="postbox">
|
|
|
4 |
<div class="inside">
|
|
|
5 |
<form action="%%SUCURI.URL.Posthack%%#reset-plugins" method="post">
|
|
|
6 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
7 |
<input type="hidden" name="sucuriscan_reset_plugins" value="1" />
|
8 |
|
56 |
</p>
|
57 |
|
58 |
<input type="submit" value="Process selected items" class="button button-primary" />
|
|
|
59 |
</form>
|
60 |
|
61 |
<script type="text/javascript">
|
62 |
jQuery(function($){
|
63 |
+
$.post('%%SUCURI.AjaxURL.Posthack%%', {
|
64 |
action: 'sucuriscan_posthack_ajax',
|
65 |
sucuriscan_page_nonce: '%%SUCURI.PageNonce%%',
|
66 |
form_action: 'get_plugins_data',
|
69 |
});
|
70 |
});
|
71 |
</script>
|
|
|
72 |
</div>
|
|
|
73 |
</div>
|
|
|
74 |
</div>
|
inc/tpl/posthack-updatesecretkeys.html.tpl
CHANGED
@@ -26,7 +26,7 @@
|
|
26 |
</thead>
|
27 |
|
28 |
<tbody>
|
29 |
-
|
30 |
</tbody>
|
31 |
</table>
|
32 |
|
26 |
</thead>
|
27 |
|
28 |
<tbody>
|
29 |
+
%%%SUCURI.SecurityKeys.List%%%
|
30 |
</tbody>
|
31 |
</table>
|
32 |
|
inc/tpl/posthack.html.tpl
CHANGED
@@ -2,27 +2,27 @@
|
|
2 |
<div class="sucuriscan-tabs">
|
3 |
<ul>
|
4 |
<li>
|
5 |
-
<a href="#" data-tabname="update-security-keys">Security Keys</a>
|
6 |
</li>
|
7 |
<li>
|
8 |
-
<a href="#" data-tabname="reset-users-password">Reset User's Password</a>
|
9 |
</li>
|
10 |
<li>
|
11 |
-
<a href="#" data-tabname="reset-plugins">Reset Plugins</a>
|
12 |
</li>
|
13 |
</ul>
|
14 |
|
15 |
<div class="sucuriscan-tab-containers">
|
16 |
<div id="sucuriscan-update-security-keys">
|
17 |
-
|
18 |
</div>
|
19 |
|
20 |
<div id="sucuriscan-reset-users-password">
|
21 |
-
|
22 |
</div>
|
23 |
|
24 |
<div id="sucuriscan-reset-plugins">
|
25 |
-
|
26 |
</div>
|
27 |
</div>
|
28 |
</div>
|
2 |
<div class="sucuriscan-tabs">
|
3 |
<ul>
|
4 |
<li>
|
5 |
+
<a href="#update-security-keys" data-tabname="update-security-keys">Security Keys</a>
|
6 |
</li>
|
7 |
<li>
|
8 |
+
<a href="#reset-users-password" data-tabname="reset-users-password">Reset User's Password</a>
|
9 |
</li>
|
10 |
<li>
|
11 |
+
<a href="#reset-plugins" data-tabname="reset-plugins">Reset Plugins</a>
|
12 |
</li>
|
13 |
</ul>
|
14 |
|
15 |
<div class="sucuriscan-tab-containers">
|
16 |
<div id="sucuriscan-update-security-keys">
|
17 |
+
%%%SUCURI.UpdateSecretKeys%%%
|
18 |
</div>
|
19 |
|
20 |
<div id="sucuriscan-reset-users-password">
|
21 |
+
%%%SUCURI.ResetPassword%%%
|
22 |
</div>
|
23 |
|
24 |
<div id="sucuriscan-reset-plugins">
|
25 |
+
%%%SUCURI.ResetPlugins%%%
|
26 |
</div>
|
27 |
</div>
|
28 |
</div>
|
inc/tpl/settings-alert-bruteforce.html.tpl
ADDED
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
<div class="postbox">
|
3 |
+
<h3>Password Guessing Brute Force Attacks</h3>
|
4 |
+
|
5 |
+
<div class="inside">
|
6 |
+
<p>
|
7 |
+
Password guessing brute force attacks are very common against web sites and web
|
8 |
+
servers. They are one of the most common vectors used to compromise web sites.
|
9 |
+
The process is very simple and the attackers basically try multiple combinations
|
10 |
+
of usernames and passwords until they find one that works. Once they get in,
|
11 |
+
they can compromise the web site with malware, spam , phishing or anything else
|
12 |
+
they want.
|
13 |
+
</p>
|
14 |
+
|
15 |
+
<div class="sucuriscan-inline-alert-warning">
|
16 |
+
<p>This option overrides the <em>"Alerts Per Hour"</em> setting.</p>
|
17 |
+
</div>
|
18 |
+
|
19 |
+
<form action="%%SUCURI.URL.Settings%%#notifications" method="post">
|
20 |
+
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
21 |
+
<span class="sucuriscan-input-group">
|
22 |
+
<label>Consider Brute-Force Attack After:</label>
|
23 |
+
<select name="sucuriscan_maximum_failed_logins">
|
24 |
+
%%%SUCURI.AlertSettings.BruteForce%%%
|
25 |
+
</select>
|
26 |
+
</span>
|
27 |
+
<button type="submit" class="button-primary">Save</button>
|
28 |
+
</form>
|
29 |
+
|
30 |
+
<p>
|
31 |
+
More info at <a href="https://kb.sucuri.net/definitions/attacks/brute-force/password-guessing"
|
32 |
+
target="_blank">Sucuri KB - Password Guessing Brute Force Attacks</a>.
|
33 |
+
</p>
|
34 |
+
</div>
|
35 |
+
</div>
|
inc/tpl/settings-alert-events.html.tpl
ADDED
@@ -0,0 +1,46 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
<div class="postbox">
|
3 |
+
<h3>Alert Events</h3>
|
4 |
+
|
5 |
+
<div class="inside">
|
6 |
+
<p>
|
7 |
+
Configure the alert settings to your needs, and make sure to read the purpose of
|
8 |
+
each option below otherwise you will end up enabling and/or disabling things
|
9 |
+
that will affect your personal inbox. If you experience issues with one or more
|
10 |
+
of these options revert them to their original state.
|
11 |
+
</p>
|
12 |
+
|
13 |
+
<div class="sucuriscan-inline-alert-warning">
|
14 |
+
<p>
|
15 |
+
Enabling the alerts for failed login attempts may become an indirect mail spam
|
16 |
+
attack as you will receive tons of emails if your website is victim of a brute
|
17 |
+
force attack. Disable this option and enable the brute force attack reports to
|
18 |
+
get a summary of all the failed logins detected each hour.
|
19 |
+
</p>
|
20 |
+
</div>
|
21 |
+
|
22 |
+
<form action="%%SUCURI.URL.Settings%%#notifications" method="post">
|
23 |
+
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
24 |
+
|
25 |
+
<table class="wp-list-table widefat sucuriscan-table sucuriscan-settings-notifications">
|
26 |
+
<thead>
|
27 |
+
<tr>
|
28 |
+
<th class="manage-column column-cb check-column">
|
29 |
+
<label class="screen-reader-text" for="cb-select-all-1">Select All</label>
|
30 |
+
<input id="cb-select-all-1" type="checkbox">
|
31 |
+
</th>
|
32 |
+
<th class="manage-column">Event Description</th>
|
33 |
+
</tr>
|
34 |
+
</thead>
|
35 |
+
|
36 |
+
<tbody>
|
37 |
+
%%%SUCURI.AlertSettings.Events%%%
|
38 |
+
</tbody>
|
39 |
+
</table>
|
40 |
+
|
41 |
+
<div class="sucuriscan-recipient-form">
|
42 |
+
<button type="submit" name="sucuriscan_save_alert_events" class="button-primary">Save</button>
|
43 |
+
</div>
|
44 |
+
</form>
|
45 |
+
</div>
|
46 |
+
</div>
|
inc/tpl/settings-alert-events.snippet.tpl
ADDED
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
<tr class="%%SUCURI.Event.CssClass%%">
|
3 |
+
<td class="check-column">
|
4 |
+
<input type="hidden" name="%%SUCURI.Event.Name%%" value="0" />
|
5 |
+
<input type="checkbox" name="%%SUCURI.Event.Name%%" value="1" %%SUCURI.Event.Checked%% />
|
6 |
+
</td>
|
7 |
+
<td>
|
8 |
+
<span class="%%SUCURI.Event.LabelIcon%%">%%%SUCURI.Event.Label%%%</span>
|
9 |
+
</td>
|
10 |
+
</tr>
|
inc/tpl/settings-alert-perhour.html.tpl
ADDED
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
<div class="postbox">
|
3 |
+
<h3>Alerts Per Hour</h3>
|
4 |
+
|
5 |
+
<div class="inside">
|
6 |
+
<p>
|
7 |
+
Depending on the number of yours registered in your website or the number of
|
8 |
+
actions performed by these users the recipients of the alerts sent when the site
|
9 |
+
triggers an action that the plugin monitors may become annoying or irrelevant
|
10 |
+
after some time. You can use this option to configure the maximum number of
|
11 |
+
alerts to receive during the same hour.
|
12 |
+
</p>
|
13 |
+
|
14 |
+
<div class="sucuriscan-inline-alert-warning">
|
15 |
+
<p>
|
16 |
+
If you have enabled the alerts for <a href="https://kb.sucuri.net/definitions/attacks/brute-force/password-guessing"
|
17 |
+
target="_blank">password guessing brute force attacks</a> and lowered the number
|
18 |
+
of alerts sent during the hour has reached its limit, the plugin will force the
|
19 |
+
sending of the alert; you can consider the limit for alerts per hour a
|
20 |
+
<em>"limit + one"</em> if the brute force attack summary is generated.
|
21 |
+
</p>
|
22 |
+
</div>
|
23 |
+
|
24 |
+
<form action="%%SUCURI.URL.Settings%%#notifications" method="post">
|
25 |
+
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
26 |
+
<span class="sucuriscan-input-group">
|
27 |
+
<label>Maximum Alerts Per Hour:</label>
|
28 |
+
<select name="sucuriscan_emails_per_hour">
|
29 |
+
%%%SUCURI.AlertSettings.PerHour%%%
|
30 |
+
</select>
|
31 |
+
</span>
|
32 |
+
<button type="submit" class="button-primary">Save</button>
|
33 |
+
</form>
|
34 |
+
</div>
|
35 |
+
</div>
|
inc/tpl/settings-alert-recipients.html.tpl
ADDED
@@ -0,0 +1,58 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
<div class="postbox">
|
3 |
+
<h3>Alert Recipients</h3>
|
4 |
+
|
5 |
+
<div class="inside">
|
6 |
+
<p>
|
7 |
+
By default the plugin will send email alerts to the email address of the
|
8 |
+
original user account created during the installation process of your website,
|
9 |
+
you can change this adding a new address below and then deleting the old entry.
|
10 |
+
Additionally, you are allowed to send a copy of the same alerts to other email
|
11 |
+
addresses.
|
12 |
+
</p>
|
13 |
+
|
14 |
+
<div class="sucuriscan-inline-alert-info">
|
15 |
+
<p>
|
16 |
+
Make sure to check your spam folder if you do not see the alerts in your inbox,
|
17 |
+
if at least one of the recipients listed below receives the alert it means that
|
18 |
+
the message was delivered correctly, if you or one of the other recipients is
|
19 |
+
not receiving the alerts is probably because of a filter in your email service.
|
20 |
+
This is because the plugin only sends one single message per alert, so either
|
21 |
+
everyone gets the message or no one gets it.
|
22 |
+
</p>
|
23 |
+
</div>
|
24 |
+
|
25 |
+
<form action="%%SUCURI.URL.Settings%%#notifications" method="post">
|
26 |
+
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
27 |
+
|
28 |
+
<table class="wp-list-table widefat sucuriscan-table">
|
29 |
+
<thead>
|
30 |
+
<tr>
|
31 |
+
<th class="manage-column column-cb check-column">
|
32 |
+
<label class="screen-reader-text" for="cb-select-all-1">Select All</label>
|
33 |
+
<input id="cb-select-all-1" type="checkbox">
|
34 |
+
</th>
|
35 |
+
<th class="manage-column">E-mail Address</th>
|
36 |
+
</tr>
|
37 |
+
</thead>
|
38 |
+
|
39 |
+
<tbody>
|
40 |
+
%%%SUCURI.AlertSettings.Recipients%%%
|
41 |
+
</tbody>
|
42 |
+
</table>
|
43 |
+
|
44 |
+
<div class="sucuriscan-recipient-form">
|
45 |
+
<span class="sucuriscan-input-group">
|
46 |
+
<label>E-mail Address:</label>
|
47 |
+
<input type="text" name="sucuriscan_recipient" class="input-text" placeholder="e.g. user@example.com" />
|
48 |
+
</span>
|
49 |
+
<button type="submit" name="sucuriscan_save_recipient" class="button-primary">Add Recipient</button>
|
50 |
+
</div>
|
51 |
+
|
52 |
+
<div class="sucuriscan-recipient-form">
|
53 |
+
<button type="submit" name="sucuriscan_delete_recipients" class="button-primary button-danger">Delete Selected</button>
|
54 |
+
<button type="submit" name="sucuriscan_debug_email" value="1" class="button-primary">Test Alert Delivery</button>
|
55 |
+
</div>
|
56 |
+
</form>
|
57 |
+
</div>
|
58 |
+
</div>
|
inc/tpl/settings-alert-recipients.snippet.tpl
ADDED
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
<tr class="%%SUCURI.Recipient.CssClass%%">
|
3 |
+
<td class="check-column">
|
4 |
+
<input type="checkbox" name="sucuriscan_recipients[]" value="%%SUCURI.Recipient.Email%%" />
|
5 |
+
</td>
|
6 |
+
<td>
|
7 |
+
<a href="mailto:%%SUCURI.Recipient.Email%%">%%SUCURI.Recipient.Email%%</a>
|
8 |
+
</td>
|
9 |
+
</tr>
|
inc/tpl/settings-alert-subject.html.tpl
ADDED
@@ -0,0 +1,34 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
<div class="postbox">
|
3 |
+
<h3>Alert Subject</h3>
|
4 |
+
|
5 |
+
<div class="inside">
|
6 |
+
<p>
|
7 |
+
Format of the subject for the email alerts, by default the plugin will use the
|
8 |
+
website name and the event identifier that is being reported, you can use this
|
9 |
+
panel to include the IP address of that user that triggered the event and some
|
10 |
+
additional data. You can create filters in your email client creating a custom
|
11 |
+
email subject using the pseudo-tags shown below.
|
12 |
+
</p>
|
13 |
+
|
14 |
+
<form action="%%SUCURI.URL.Settings%%#notifications" method="post">
|
15 |
+
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
16 |
+
|
17 |
+
<ul class="sucuriscan-subject-formats">
|
18 |
+
%%%SUCURI.AlertSettings.Subject%%%
|
19 |
+
|
20 |
+
<li>
|
21 |
+
<label>
|
22 |
+
<input type="radio" name="sucuriscan_email_subject" value="custom" %%SUCURI.AlertSettings.CustomChecked%% />
|
23 |
+
<span>Custom format</span>
|
24 |
+
<input type="text" name="sucuriscan_custom_email_subject" value="%%SUCURI.AlertSettings.CustomValue%%" />
|
25 |
+
</label>
|
26 |
+
</li>
|
27 |
+
</ul>
|
28 |
+
|
29 |
+
<div class="sucuriscan-recipient-form">
|
30 |
+
<button type="submit" class="button-primary">Save</button>
|
31 |
+
</div>
|
32 |
+
</form>
|
33 |
+
</div>
|
34 |
+
</div>
|
inc/tpl/settings-alert-subject.snippet.tpl
ADDED
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
<li>
|
3 |
+
<label>
|
4 |
+
<input type="radio" name="sucuriscan_email_subject"
|
5 |
+
value="%%SUCURI.EmailSubject.Value%%" %%SUCURI.EmailSubject.Checked%% />
|
6 |
+
<span>%%SUCURI.EmailSubject.Name%%</span>
|
7 |
+
</label>
|
8 |
+
</li>
|
inc/tpl/settings-alert.html.tpl
ADDED
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
<div id="poststuff">
|
3 |
+
%%%SUCURI.AlertSettings.Recipients%%%
|
4 |
+
|
5 |
+
%%%SUCURI.AlertSettings.Subject%%%
|
6 |
+
|
7 |
+
%%%SUCURI.AlertSettings.PerHour%%%
|
8 |
+
|
9 |
+
%%%SUCURI.AlertSettings.BruteForce%%%
|
10 |
+
|
11 |
+
%%%SUCURI.AlertSettings.Events%%%
|
12 |
+
</div>
|
inc/tpl/{settings-general-apiproxy.html.tpl → settings-apiservice-proxy.html.tpl}
RENAMED
@@ -7,7 +7,7 @@
|
|
7 |
All the HTTP requests used to communicate with the API service are being sent
|
8 |
using the WordPress built-in functions, so <em>(almost)</em> all its official
|
9 |
features are inherited, this is useful if you need to pass these HTTP requests
|
10 |
-
through a proxy. According to the <a href="
|
11 |
target="_blank">official documentation</a> you have to add some constants to the
|
12 |
main configuration file: <em>WP_PROXY_HOST, WP_PROXY_PORT, WP_PROXY_USERNAME,
|
13 |
WP_PROXY_PASSWORD</em>.
|
7 |
All the HTTP requests used to communicate with the API service are being sent
|
8 |
using the WordPress built-in functions, so <em>(almost)</em> all its official
|
9 |
features are inherited, this is useful if you need to pass these HTTP requests
|
10 |
+
through a proxy. According to the <a href="https://codex.wordpress.org/HTTP_API"
|
11 |
target="_blank">official documentation</a> you have to add some constants to the
|
12 |
main configuration file: <em>WP_PROXY_HOST, WP_PROXY_PORT, WP_PROXY_USERNAME,
|
13 |
WP_PROXY_PASSWORD</em>.
|
inc/tpl/{settings-general-apissl.html.tpl → settings-apiservice-ssl.html.tpl}
RENAMED
@@ -24,12 +24,12 @@
|
|
24 |
can take advantage of this to steal information from your website.
|
25 |
</p>
|
26 |
|
27 |
-
<form action="%%SUCURI.URL.Settings
|
28 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
29 |
<span class="sucuriscan-input-group">
|
30 |
<label>SSL Certificate Verification:</label>
|
31 |
<select name="sucuriscan_verify_ssl_cert">
|
32 |
-
|
33 |
</select>
|
34 |
</span>
|
35 |
<button type="submit" class="button-primary">Proceed</button>
|
24 |
can take advantage of this to steal information from your website.
|
25 |
</p>
|
26 |
|
27 |
+
<form action="%%SUCURI.URL.Settings%%#apiservice" method="post">
|
28 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
29 |
<span class="sucuriscan-input-group">
|
30 |
<label>SSL Certificate Verification:</label>
|
31 |
<select name="sucuriscan_verify_ssl_cert">
|
32 |
+
%%%SUCURI.VerifySSLCertOptions%%%
|
33 |
</select>
|
34 |
</span>
|
35 |
<button type="submit" class="button-primary">Proceed</button>
|
inc/tpl/settings-apiservice-status.html.tpl
ADDED
@@ -0,0 +1,44 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
<div class="postbox">
|
3 |
+
<h3>API Service Communication</h3>
|
4 |
+
|
5 |
+
<div class="inside">
|
6 |
+
<p>
|
7 |
+
Once the API key is generate the plugin will communicate with a remote API
|
8 |
+
service that will act as a safe data storage for the audit logs generated when
|
9 |
+
the website triggers certain events that the plugin monitors. If the website is
|
10 |
+
hacked the attacker will not have access to these logs and that way you can
|
11 |
+
investigate what was modified <em>(for malware infaction)</em> and/or how the
|
12 |
+
malicious person was able to gain access to the website.
|
13 |
+
</p>
|
14 |
+
|
15 |
+
<div class="sucuriscan-inline-alert-warning sucuriscan-%%SUCURI.ApiStatus.WarningVisibility%%">
|
16 |
+
<p>
|
17 |
+
The latency of the HTTP requests may slow down the website depending on the
|
18 |
+
location of the server that is hosting it. Additionally, if the API goes down
|
19 |
+
the plugin will throw warnings that may affect your workflow, in this case you
|
20 |
+
may want to stop the communication with the API service to keep the latency at
|
21 |
+
zero and be able to continue working in the website without interruptions.
|
22 |
+
</p>
|
23 |
+
</div>
|
24 |
+
|
25 |
+
<div class="sucuriscan-inline-alert-error sucuriscan-%%SUCURI.ApiStatus.ErrorVisibility%%">
|
26 |
+
<p>
|
27 |
+
Disabling the API service communication will stop the event monitoring, consider
|
28 |
+
to enable the <a href="%%SUCURI.URL.Settings%%#selfhosting">Log Exporter</a> to
|
29 |
+
keep the monitoring working while the HTTP requests are ignored, otherwise an
|
30 |
+
attacker may execute an action that will not be registered in the security logs
|
31 |
+
and you will not have a way to investigate the attack in the future.
|
32 |
+
</p>
|
33 |
+
</div>
|
34 |
+
|
35 |
+
<div class="sucuriscan-hstatus sucuriscan-hstatus-%%SUCURI.ApiStatus.StatusNum%%">
|
36 |
+
<span>API Service Communication is %%SUCURI.ApiStatus.Status%%</span>
|
37 |
+
<form action="%%SUCURI.URL.Settings%%#apiservice" method="post">
|
38 |
+
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
39 |
+
<input type="hidden" name="sucuriscan_api_service" value="%%SUCURI.ApiStatus.SwitchValue%%" />
|
40 |
+
<button type="submit" class="button-primary %%SUCURI.ApiStatus.SwitchCssClass%%">%%SUCURI.ApiStatus.SwitchText%%</button>
|
41 |
+
</form>
|
42 |
+
</div>
|
43 |
+
</div>
|
44 |
+
</div>
|
inc/tpl/{settings-general-apitimeout.html.tpl → settings-apiservice-timeout.html.tpl}
RENAMED
@@ -4,13 +4,19 @@
|
|
4 |
|
5 |
<div class="inside">
|
6 |
<p>
|
7 |
-
The plugin sends the data
|
8 |
-
the action is suspicious, it sends this information via HTTP requests
|
9 |
-
<a
|
10 |
-
|
11 |
-
|
12 |
</p>
|
13 |
|
|
|
|
|
|
|
|
|
|
|
|
|
14 |
<div class="sucuriscan-hstatus sucuriscan-hstatus-2">
|
15 |
<span>Wait <b>%%SUCURI.RequestTimeout%%</b> before timeout</span>
|
16 |
</div>
|
@@ -22,7 +28,7 @@
|
|
22 |
something in the server blocking the connection.
|
23 |
</p>
|
24 |
|
25 |
-
<form action="%%SUCURI.URL.Settings
|
26 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
27 |
<span class="sucuriscan-input-group">
|
28 |
<label>HTTP Request Timeout (in secs)</label>
|
4 |
|
5 |
<div class="inside">
|
6 |
<p>
|
7 |
+
The plugin sends the data associated to the events triggered by WordPress when
|
8 |
+
it considers the action is suspicious, it sends this information via HTTP requests
|
9 |
+
using the HTTP transport protocol available in the system and the <a target="_blank"
|
10 |
+
href="https://developer.wordpress.org/reference/functions/wp_remote_post/">built-in
|
11 |
+
functions</a> provided by WordPress, then it waits for the response.
|
12 |
</p>
|
13 |
|
14 |
+
<div class="sucuriscan-inline-alert-info">
|
15 |
+
<p>
|
16 |
+
You can set up to %%SUCURI.MaxRequestTimeout%% seconds for the timeout, more than that is not allowed.
|
17 |
+
</p>
|
18 |
+
</div>
|
19 |
+
|
20 |
<div class="sucuriscan-hstatus sucuriscan-hstatus-2">
|
21 |
<span>Wait <b>%%SUCURI.RequestTimeout%%</b> before timeout</span>
|
22 |
</div>
|
28 |
something in the server blocking the connection.
|
29 |
</p>
|
30 |
|
31 |
+
<form action="%%SUCURI.URL.Settings%%#apiservice" method="post">
|
32 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
33 |
<span class="sucuriscan-input-group">
|
34 |
<label>HTTP Request Timeout (in secs)</label>
|
inc/tpl/settings-apiservice.html.tpl
ADDED
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
<div id="poststuff" class="sucuriscan-general-apiservice">
|
3 |
+
%%%SUCURI.SettingsSection.ApiStatus%%%
|
4 |
+
|
5 |
+
%%%SUCURI.SettingsSection.ApiProxy%%%
|
6 |
+
|
7 |
+
%%%SUCURI.SettingsSection.ApiSSL%%%
|
8 |
+
|
9 |
+
%%%SUCURI.SettingsSection.ApiTimeout%%%
|
10 |
+
</div>
|
inc/tpl/settings-emailsubject.snippet.tpl
DELETED
@@ -1,7 +0,0 @@
|
|
1 |
-
|
2 |
-
<li>
|
3 |
-
<label>
|
4 |
-
<input type="radio" name="sucuriscan_email_subject" value="%%SUCURI.EmailSubject.Value%%" %%SUCURI.EmailSubject.Checked%% />
|
5 |
-
<span>%%SUCURI.EmailSubject.Name%%</span>
|
6 |
-
</label>
|
7 |
-
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
inc/tpl/settings-general-apikey.html.tpl
CHANGED
@@ -1,7 +1,7 @@
|
|
1 |
|
2 |
-
|
3 |
|
4 |
-
|
5 |
|
6 |
<div class="postbox">
|
7 |
<h3>Plugin API Key</h3>
|
@@ -49,7 +49,7 @@
|
|
49 |
</div>
|
50 |
|
51 |
<div class="sucuriscan-hstatus sucuriscan-hstatus-1 sucuriscan-%%SUCURI.APIKey.RemoveVisibility%%">
|
52 |
-
<div class="sucuriscan-monospace">Plugin API Key:
|
53 |
<form action="%%SUCURI.URL.Settings%%" method="post">
|
54 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
55 |
<button type="submit" name="sucuriscan_remove_api_key" class="button-primary button-danger">Remove</button>
|
1 |
|
2 |
+
%%%SUCURI.ModalWhenAPIRegistered%%%
|
3 |
|
4 |
+
%%%SUCURI.ModalForApiKeyRecovery%%%
|
5 |
|
6 |
<div class="postbox">
|
7 |
<h3>Plugin API Key</h3>
|
49 |
</div>
|
50 |
|
51 |
<div class="sucuriscan-hstatus sucuriscan-hstatus-1 sucuriscan-%%SUCURI.APIKey.RemoveVisibility%%">
|
52 |
+
<div class="sucuriscan-monospace">Plugin API Key: %%SUCURI.APIKey%%</div>
|
53 |
<form action="%%SUCURI.URL.Settings%%" method="post">
|
54 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
55 |
<button type="submit" name="sucuriscan_remove_api_key" class="button-primary button-danger">Remove</button>
|
inc/tpl/settings-general-auditlogstats.html.tpl
ADDED
@@ -0,0 +1,40 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
<div class="postbox">
|
3 |
+
<h3>Audit Log Statistics</h3>
|
4 |
+
|
5 |
+
<div class="inside">
|
6 |
+
<p>
|
7 |
+
Enabling this option allows you to have a quick view of the range of the
|
8 |
+
activity of your users and/or the attacks directed against your website. By
|
9 |
+
default, the plugin uses the <strong>latest %%SUCURI.AuditLogStats.Limit%%
|
10 |
+
entries</strong> in the audit logs and uses that information to draw bar and
|
11 |
+
pie charts in the dashboard.
|
12 |
+
</p>
|
13 |
+
|
14 |
+
<div class="sucuriscan-hstatus sucuriscan-hstatus-%%SUCURI.AuditLogStats.StatusNum%%">
|
15 |
+
<span>Audit Log Statistics are %%SUCURI.AuditLogStats.Status%%</span>
|
16 |
+
<form action="%%SUCURI.URL.Settings%%" method="post">
|
17 |
+
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
18 |
+
<input type="hidden" name="sucuriscan_audit_report" value="%%SUCURI.AuditLogStats.SwitchValue%%" />
|
19 |
+
<button type="submit" class="button-primary %%SUCURI.AuditLogStats.SwitchCssClass%%">%%SUCURI.AuditLogStats.SwitchText%%</button>
|
20 |
+
</form>
|
21 |
+
</div>
|
22 |
+
|
23 |
+
<p>
|
24 |
+
The statistic charts are generated with a limited number of logs stored in the
|
25 |
+
remote API server, you can increase the number to draw the charts with more data
|
26 |
+
and represent the activity during a wider range of days, but you must consider
|
27 |
+
that the bigger the number the slower the plugin dashboard will be because it
|
28 |
+
will take more time to read more logs.
|
29 |
+
</p>
|
30 |
+
|
31 |
+
<form action="%%SUCURI.URL.Settings%%" method="post">
|
32 |
+
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
33 |
+
<span class="sucuriscan-input-group">
|
34 |
+
<label>Audit Logs Limit:</label>
|
35 |
+
<input type="text" name="sucuriscan_logs4report" class="input-text" placeholder="e.g. 500" />
|
36 |
+
</span>
|
37 |
+
<button type="submit" class="button-primary">Save</button>
|
38 |
+
</form>
|
39 |
+
</div>
|
40 |
+
</div>
|
inc/tpl/settings-general-datastorage.html.tpl
CHANGED
@@ -1,6 +1,6 @@
|
|
1 |
|
2 |
<div class="postbox">
|
3 |
-
<h3>
|
4 |
|
5 |
<div class="inside">
|
6 |
<p>
|
@@ -45,7 +45,7 @@
|
|
45 |
<form action="%%SUCURI.URL.Settings%%" method="post">
|
46 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
47 |
<span class="sucuriscan-input-group">
|
48 |
-
<label>Data
|
49 |
<input type="text" name="sucuriscan_datastore_path" class="input-text" />
|
50 |
</span>
|
51 |
<button type="submit" class="button-primary">Proceed</button>
|
1 |
|
2 |
<div class="postbox">
|
3 |
+
<h3>Data Storage Path</h3>
|
4 |
|
5 |
<div class="inside">
|
6 |
<p>
|
45 |
<form action="%%SUCURI.URL.Settings%%" method="post">
|
46 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
47 |
<span class="sucuriscan-input-group">
|
48 |
+
<label>Data Storage Path:</label>
|
49 |
<input type="text" name="sucuriscan_datastore_path" class="input-text" />
|
50 |
</span>
|
51 |
<button type="submit" class="button-primary">Proceed</button>
|
inc/tpl/settings-general-datetime.html.tpl
ADDED
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
<div class="postbox">
|
3 |
+
<h3>Date & Time</h3>
|
4 |
+
|
5 |
+
<div class="inside">
|
6 |
+
<p>
|
7 |
+
The plugin uses built-in WordPress functions to retrieve the current date and
|
8 |
+
time, as well to translate timestamps to human readable text. Below is shown the
|
9 |
+
data returned by the main three functions used by this plugin to get the date
|
10 |
+
for the logs and email alerts, if you notice an inconsistency with any of these
|
11 |
+
values please change the timezone settings.
|
12 |
+
</p>
|
13 |
+
|
14 |
+
<div class="sucuriscan-hstatus sucuriscan-hstatus-2">
|
15 |
+
<span>Current Date & Time is</span>
|
16 |
+
<strong>%%SUCURI.Datetime.HumanReadable%%</strong>
|
17 |
+
<em>(%%SUCURI.Datetime.Timezone%% - %%SUCURI.Datetime.Timestamp%%)</em>
|
18 |
+
<a href="%%SUCURI.Datetime.AdminURL%%" target="_blank" class="button-primary">Change</a>
|
19 |
+
</div>
|
20 |
+
</div>
|
21 |
+
</div>
|
inc/tpl/settings-general-ipdiscoverer.html.tpl
CHANGED
@@ -31,6 +31,27 @@
|
|
31 |
</form>
|
32 |
</div>
|
33 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
34 |
<p>
|
35 |
If you are experiencing issues with the automatic detection of IP address of
|
36 |
your visitors, with the security logs, or with the response time of your website
|
31 |
</form>
|
32 |
</div>
|
33 |
|
34 |
+
<p>
|
35 |
+
Once the feature is enabled you may choose the HTTP header that will be used by
|
36 |
+
default to retrieve the real IP address of each HTTP request, generally you do
|
37 |
+
not need to set this but in rare cases your hosting provider may have a load
|
38 |
+
balancer that can interfere in the process, in which case you will have to
|
39 |
+
explicitly specify the main HTTP header. Note that if you select a HTTP header
|
40 |
+
that is not being set by the server the plugin will fallback to the default
|
41 |
+
<em>Remote-Addr</em>.
|
42 |
+
</p>
|
43 |
+
|
44 |
+
<form action="%%SUCURI.URL.Settings%%" method="post">
|
45 |
+
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
46 |
+
<span class="sucuriscan-input-group">
|
47 |
+
<label>Main IP HTTP Header:</label>
|
48 |
+
<select name="sucuriscan_addr_header">
|
49 |
+
%%%SUCURI.AddrHeaderOptions%%%
|
50 |
+
</select>
|
51 |
+
</span>
|
52 |
+
<button type="submit" class="button-primary">Proceed</button>
|
53 |
+
</form>
|
54 |
+
|
55 |
<p>
|
56 |
If you are experiencing issues with the automatic detection of IP address of
|
57 |
your visitors, with the security logs, or with the response time of your website
|
inc/tpl/settings-general-xhrmonitor.html.tpl
CHANGED
@@ -31,7 +31,7 @@
|
|
31 |
</div>
|
32 |
|
33 |
<div class="sucuriscan-hstatus sucuriscan-hstatus-2">
|
34 |
-
<span>
|
35 |
|
36 |
<form action="%%SUCURI.URL.Settings%%" method="post">
|
37 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
31 |
</div>
|
32 |
|
33 |
<div class="sucuriscan-hstatus sucuriscan-hstatus-2">
|
34 |
+
<span>XML HTTP Request Monitor is %%SUCURI.XhrMonitorStatus%%</span>
|
35 |
|
36 |
<form action="%%SUCURI.URL.Settings%%" method="post">
|
37 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
inc/tpl/settings-general.html.tpl
CHANGED
@@ -1,118 +1,22 @@
|
|
1 |
|
2 |
<div id="poststuff" class="sucuriscan-general-settings">
|
3 |
-
|
4 |
|
5 |
-
|
6 |
|
7 |
-
|
8 |
|
9 |
-
|
10 |
|
11 |
-
|
12 |
|
13 |
-
|
14 |
|
15 |
-
|
16 |
|
17 |
-
|
18 |
|
19 |
-
|
20 |
|
21 |
-
|
22 |
-
|
23 |
-
%%SUCURI.SettingsSection.ResetOptions%%
|
24 |
</div>
|
25 |
-
|
26 |
-
<table class="wp-list-table widefat sucuriscan-table sucuriscan-striped-table sucuriscan-settings">
|
27 |
-
<tbody>
|
28 |
-
<tr>
|
29 |
-
<td>Test email alerts</td>
|
30 |
-
<td><em>(Test ability to send email alerts)</em></td>
|
31 |
-
<td class="td-with-button">
|
32 |
-
<form action="%%SUCURI.URL.Settings%%" method="post">
|
33 |
-
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
34 |
-
<input type="hidden" name="sucuriscan_debug_email" value="1" />
|
35 |
-
<button type="submit" class="button-primary">Proceed</button>
|
36 |
-
</form>
|
37 |
-
</td>
|
38 |
-
</tr>
|
39 |
-
|
40 |
-
<tr>
|
41 |
-
<td>Send plugin alerts to</td>
|
42 |
-
<td>%%SUCURI.NotifyTo%%</td>
|
43 |
-
<td class="td-with-button">
|
44 |
-
<form action="%%SUCURI.URL.Settings%%" method="post">
|
45 |
-
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
46 |
-
<input type="text" name="sucuriscan_notify_to" class="input-text" placeholder="Separated by commas" />
|
47 |
-
<button type="submit" class="button-primary">Change</button>
|
48 |
-
</form>
|
49 |
-
</td>
|
50 |
-
</tr>
|
51 |
-
|
52 |
-
<tr>
|
53 |
-
<td>Maximum alerts per hour</td>
|
54 |
-
<td>%%SUCURI.EmailsPerHour%%</td>
|
55 |
-
<td class="td-with-button">
|
56 |
-
<form action="%%SUCURI.URL.Settings%%" method="post">
|
57 |
-
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
58 |
-
<select name="sucuriscan_emails_per_hour">
|
59 |
-
%%SUCURI.EmailsPerHourOptions%%
|
60 |
-
</select>
|
61 |
-
<button type="submit" class="button-primary">Change</button>
|
62 |
-
</form>
|
63 |
-
</td>
|
64 |
-
</tr>
|
65 |
-
|
66 |
-
<tr>
|
67 |
-
<td>Consider brute-force after</td>
|
68 |
-
<td>%%SUCURI.MaximumFailedLogins%%</td>
|
69 |
-
<td class="td-with-button">
|
70 |
-
<form action="%%SUCURI.URL.Settings%%" method="post">
|
71 |
-
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
72 |
-
<select name="sucuriscan_maximum_failed_logins">
|
73 |
-
%%SUCURI.MaximumFailedLoginsOptions%%
|
74 |
-
</select>
|
75 |
-
<button type="submit" class="button-primary">Change</button>
|
76 |
-
</form>
|
77 |
-
</td>
|
78 |
-
</tr>
|
79 |
-
|
80 |
-
<tr>
|
81 |
-
<td>Display audit report</td>
|
82 |
-
<td>%%SUCURI.AuditReportStatus%%</td>
|
83 |
-
<td class="td-with-button">
|
84 |
-
<form action="%%SUCURI.URL.Settings%%" method="post">
|
85 |
-
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
86 |
-
<input type="hidden" name="sucuriscan_audit_report" value="%%SUCURI.AuditReportSwitchValue%%" />
|
87 |
-
<button type="submit" class="button-primary %%SUCURI.AuditReportSwitchCssClass%%">%%SUCURI.AuditReportSwitchText%%</button>
|
88 |
-
</form>
|
89 |
-
</td>
|
90 |
-
</tr>
|
91 |
-
|
92 |
-
<tr>
|
93 |
-
<td>Audit report limit</td>
|
94 |
-
<td>Process latest %%SUCURI.AuditReportLimit%% logs</td>
|
95 |
-
<td class="td-with-button">
|
96 |
-
<form action="%%SUCURI.URL.Settings%%" method="post">
|
97 |
-
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
98 |
-
<input type="text" name="sucuriscan_logs4report" class="input-text" placeholder="e.g. 500" />
|
99 |
-
<button type="submit" class="button-primary">Change</button>
|
100 |
-
</form>
|
101 |
-
</td>
|
102 |
-
</tr>
|
103 |
-
|
104 |
-
<tr>
|
105 |
-
<td>Current Timezone</td>
|
106 |
-
<td>%%SUCURI.CustomTimezone%% <em>(%%SUCURI.CurrentDatetime%%)</em></td>
|
107 |
-
<td class="td-with-button">
|
108 |
-
<form action="%%SUCURI.URL.Settings%%" method="post">
|
109 |
-
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
110 |
-
<a href="options-general.php" target="_blank" class="button">
|
111 |
-
<span>Change Timezone from the Settings/General page</span>
|
112 |
-
</a>
|
113 |
-
</form>
|
114 |
-
</td>
|
115 |
-
</tr>
|
116 |
-
|
117 |
-
</tbody>
|
118 |
-
</table>
|
1 |
|
2 |
<div id="poststuff" class="sucuriscan-general-settings">
|
3 |
+
%%%SUCURI.SettingsSection.ApiKey%%%
|
4 |
|
5 |
+
%%%SUCURI.SettingsSection.DataStorage%%%
|
6 |
|
7 |
+
%%%SUCURI.SettingsSection.ReverseProxy%%%
|
8 |
|
9 |
+
%%%SUCURI.SettingsSection.IPDiscoverer%%%
|
10 |
|
11 |
+
%%%SUCURI.SettingsSection.PasswordCollector%%%
|
12 |
|
13 |
+
%%%SUCURI.SettingsSection.CommentMonitor%%%
|
14 |
|
15 |
+
%%%SUCURI.SettingsSection.XhrMonitor%%%
|
16 |
|
17 |
+
%%%SUCURI.SettingsSection.AuditLogStats%%%
|
18 |
|
19 |
+
%%%SUCURI.SettingsSection.Datetime%%%
|
20 |
|
21 |
+
%%%SUCURI.SettingsSection.ResetOptions%%%
|
|
|
|
|
22 |
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
inc/tpl/settings-heartbeat.html.tpl
CHANGED
@@ -31,10 +31,10 @@
|
|
31 |
<td>Heartbeat status</td>
|
32 |
<td>%%SUCURI.HeartbeatStatus%%</td>
|
33 |
<td class="td-with-button">
|
34 |
-
<form action="%%SUCURI.URL.Settings%%#
|
35 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
36 |
<select name="sucuriscan_heartbeat_status">
|
37 |
-
|
38 |
</select>
|
39 |
<button type="submit" class="button-primary">Change</button>
|
40 |
</form>
|
@@ -45,10 +45,10 @@
|
|
45 |
<td>Pulse interval</td>
|
46 |
<td>%%SUCURI.HeartbeatPulse%%</td>
|
47 |
<td class="td-with-button">
|
48 |
-
<form action="%%SUCURI.URL.Settings%%#
|
49 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
50 |
<select name="sucuriscan_heartbeat_pulse">
|
51 |
-
|
52 |
</select>
|
53 |
<button type="submit" class="button-primary">Change</button>
|
54 |
</form>
|
@@ -59,10 +59,10 @@
|
|
59 |
<td>Interval speed</td>
|
60 |
<td>%%SUCURI.HeartbeatInterval%%</td>
|
61 |
<td class="td-with-button">
|
62 |
-
<form action="%%SUCURI.URL.Settings%%#
|
63 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
64 |
<select name="sucuriscan_heartbeat_interval">
|
65 |
-
|
66 |
</select>
|
67 |
<button type="submit" class="button-primary">Change</button>
|
68 |
</form>
|
@@ -73,7 +73,7 @@
|
|
73 |
<td>Auto-start</td>
|
74 |
<td>%%SUCURI.HeartbeatAutostart%%</td>
|
75 |
<td class="td-with-button">
|
76 |
-
<form action="%%SUCURI.URL.Settings%%#
|
77 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
78 |
<input type="hidden" name="sucuriscan_heartbeat_autostart" value="%%SUCURI.HeartbeatAutostartSwitchValue%%" />
|
79 |
<button type="submit" class="button-primary %%SUCURI.HeartbeatAutostartSwitchCssClass%%">%%SUCURI.HeartbeatAutostartSwitchText%%</button>
|
31 |
<td>Heartbeat status</td>
|
32 |
<td>%%SUCURI.HeartbeatStatus%%</td>
|
33 |
<td class="td-with-button">
|
34 |
+
<form action="%%SUCURI.URL.Settings%%#heartbeat" method="post">
|
35 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
36 |
<select name="sucuriscan_heartbeat_status">
|
37 |
+
%%%SUCURI.HeartbeatStatusOptions%%%
|
38 |
</select>
|
39 |
<button type="submit" class="button-primary">Change</button>
|
40 |
</form>
|
45 |
<td>Pulse interval</td>
|
46 |
<td>%%SUCURI.HeartbeatPulse%%</td>
|
47 |
<td class="td-with-button">
|
48 |
+
<form action="%%SUCURI.URL.Settings%%#heartbeat" method="post">
|
49 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
50 |
<select name="sucuriscan_heartbeat_pulse">
|
51 |
+
%%%SUCURI.HeartbeatPulseOptions%%%
|
52 |
</select>
|
53 |
<button type="submit" class="button-primary">Change</button>
|
54 |
</form>
|
59 |
<td>Interval speed</td>
|
60 |
<td>%%SUCURI.HeartbeatInterval%%</td>
|
61 |
<td class="td-with-button">
|
62 |
+
<form action="%%SUCURI.URL.Settings%%#heartbeat" method="post">
|
63 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
64 |
<select name="sucuriscan_heartbeat_interval">
|
65 |
+
%%%SUCURI.HeartbeatIntervalOptions%%%
|
66 |
</select>
|
67 |
<button type="submit" class="button-primary">Change</button>
|
68 |
</form>
|
73 |
<td>Auto-start</td>
|
74 |
<td>%%SUCURI.HeartbeatAutostart%%</td>
|
75 |
<td class="td-with-button">
|
76 |
+
<form action="%%SUCURI.URL.Settings%%#heartbeat" method="post">
|
77 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
78 |
<input type="hidden" name="sucuriscan_heartbeat_autostart" value="%%SUCURI.HeartbeatAutostartSwitchValue%%" />
|
79 |
<button type="submit" class="button-primary %%SUCURI.HeartbeatAutostartSwitchCssClass%%">%%SUCURI.HeartbeatAutostartSwitchText%%</button>
|
inc/tpl/settings-ignorerules.html.tpl
CHANGED
@@ -21,7 +21,7 @@
|
|
21 |
|
22 |
<div class="inside">
|
23 |
<p>
|
24 |
-
This is a list of registered <a href="
|
25 |
target="_blank">Post Types</a>, since you have enabled the <strong>email alerts
|
26 |
for new or modified content</strong>, we will send you an alert if any of these
|
27 |
<code>post-types</code> are created and/or updated. You may want to ignore some
|
@@ -44,6 +44,6 @@
|
|
44 |
</thead>
|
45 |
|
46 |
<tbody>
|
47 |
-
|
48 |
</tbody>
|
49 |
</table>
|
21 |
|
22 |
<div class="inside">
|
23 |
<p>
|
24 |
+
This is a list of registered <a href="https://codex.wordpress.org/Post_Types"
|
25 |
target="_blank">Post Types</a>, since you have enabled the <strong>email alerts
|
26 |
for new or modified content</strong>, we will send you an alert if any of these
|
27 |
<code>post-types</code> are created and/or updated. You may want to ignore some
|
44 |
</thead>
|
45 |
|
46 |
<tbody>
|
47 |
+
%%%SUCURI.IgnoreRules.PostTypes%%%
|
48 |
</tbody>
|
49 |
</table>
|
inc/tpl/settings-ignorerules.snippet.tpl
CHANGED
@@ -5,7 +5,7 @@
|
|
5 |
<td><span class="sucuriscan-label-%%SUCURI.IgnoreRules.IsIgnoredClass%%">%%SUCURI.IgnoreRules.IsIgnored%%</span></td>
|
6 |
<td><em class="sucuriscan-monospace">%%SUCURI.IgnoreRules.WasIgnoredAt%%</em></td>
|
7 |
<td class="td-with-button">
|
8 |
-
<form action="%%SUCURI.URL.Settings%%#
|
9 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
10 |
<input type="hidden" name="sucuriscan_ignorerule" value="%%SUCURI.IgnoreRules.PostType%%" />
|
11 |
<input type="hidden" name="sucuriscan_ignorerule_action" value="%%SUCURI.IgnoreRules.Action%%" />
|
5 |
<td><span class="sucuriscan-label-%%SUCURI.IgnoreRules.IsIgnoredClass%%">%%SUCURI.IgnoreRules.IsIgnored%%</span></td>
|
6 |
<td><em class="sucuriscan-monospace">%%SUCURI.IgnoreRules.WasIgnoredAt%%</em></td>
|
7 |
<td class="td-with-button">
|
8 |
+
<form action="%%SUCURI.URL.Settings%%#ignorerules" method="post">
|
9 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
10 |
<input type="hidden" name="sucuriscan_ignorerule" value="%%SUCURI.IgnoreRules.PostType%%" />
|
11 |
<input type="hidden" name="sucuriscan_ignorerule_action" value="%%SUCURI.IgnoreRules.Action%%" />
|
inc/tpl/settings-ignorescanning.html.tpl
CHANGED
@@ -30,7 +30,7 @@
|
|
30 |
prevent the misuse of this tool.
|
31 |
</p>
|
32 |
|
33 |
-
<form action="%%SUCURI.URL.Settings%%#
|
34 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
35 |
<input type="hidden" name="sucuriscan_ignorescanning_action" value="ignore" />
|
36 |
<input type="text" name="sucuriscan_ignorescanning_file"
|
@@ -44,7 +44,7 @@
|
|
44 |
</div>
|
45 |
</div>
|
46 |
|
47 |
-
<form action="%%SUCURI.URL.Settings%%#
|
48 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
49 |
|
50 |
<table class="wp-list-table widefat sucuriscan-table sucuriscan-settings-ignorescanning">
|
@@ -55,11 +55,11 @@
|
|
55 |
</th>
|
56 |
<th class="manage-column"> </th>
|
57 |
<th class="manage-column">Directory</th>
|
58 |
-
<th class="manage-column" width="
|
59 |
</thead>
|
60 |
|
61 |
<tbody>
|
62 |
-
|
63 |
|
64 |
<tr class="sucuriscan-%%SUCURI.IgnoreScanning.NoItemsVisibility%%">
|
65 |
<td colspan="4">
|
30 |
prevent the misuse of this tool.
|
31 |
</p>
|
32 |
|
33 |
+
<form action="%%SUCURI.URL.Settings%%#ignorescanning" method="post">
|
34 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
35 |
<input type="hidden" name="sucuriscan_ignorescanning_action" value="ignore" />
|
36 |
<input type="text" name="sucuriscan_ignorescanning_file"
|
44 |
</div>
|
45 |
</div>
|
46 |
|
47 |
+
<form action="%%SUCURI.URL.Settings%%#ignorescanning" method="post">
|
48 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
49 |
|
50 |
<table class="wp-list-table widefat sucuriscan-table sucuriscan-settings-ignorescanning">
|
55 |
</th>
|
56 |
<th class="manage-column"> </th>
|
57 |
<th class="manage-column">Directory</th>
|
58 |
+
<th class="manage-column" width="200">Ignored At</th>
|
59 |
</thead>
|
60 |
|
61 |
<tbody>
|
62 |
+
%%%SUCURI.IgnoreScanning.ResourceList%%%
|
63 |
|
64 |
<tr class="sucuriscan-%%SUCURI.IgnoreScanning.NoItemsVisibility%%">
|
65 |
<td colspan="4">
|
inc/tpl/settings-notifications.html.tpl
DELETED
@@ -1,75 +0,0 @@
|
|
1 |
-
|
2 |
-
<div id="poststuff">
|
3 |
-
<div class="postbox sucuriscan-border sucuriscan-table-description">
|
4 |
-
<h3>Alert Settings</h3>
|
5 |
-
|
6 |
-
<div class="inside">
|
7 |
-
<p>
|
8 |
-
Check the boxes bellow to receive alerts via email of the events explained in
|
9 |
-
the table, by the default the notifications will be sent to the address
|
10 |
-
configured during the installation of your site, you can change this in the
|
11 |
-
<em>General Settings</em> panel. You can specify multiple recipients separating
|
12 |
-
each address with a comma.
|
13 |
-
</p>
|
14 |
-
|
15 |
-
<div class="sucuriscan-inline-alert-warning sucuriscan-%%SUCURI.PrettifyMailsWarningVisibility%%">
|
16 |
-
<p>
|
17 |
-
Some emails sent by this plugin will be rejected outright by some popular email
|
18 |
-
services. To fix this you will need to use a third-party email service, or use a
|
19 |
-
plugin to force the site to use SMTP <em>(Simple Mail Transfer Protocol)</em>
|
20 |
-
for sending emails, and then configure your SMTP server to properly handle
|
21 |
-
messages. You can also <strong>disable HTML alerts</strong> to get notifications
|
22 |
-
in <em>text/plain</em> format.
|
23 |
-
</p>
|
24 |
-
</div>
|
25 |
-
</div>
|
26 |
-
</div>
|
27 |
-
</div>
|
28 |
-
|
29 |
-
<form action="%%SUCURI.URL.Settings%%#settings-notifications" method="post">
|
30 |
-
<table class="wp-list-table widefat sucuriscan-table sucuriscan-settings-notifications">
|
31 |
-
<thead>
|
32 |
-
<tr>
|
33 |
-
<th class="thead-with-button">
|
34 |
-
<span>Alert Settings</span>
|
35 |
-
<div class="thead-topright-action">
|
36 |
-
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
37 |
-
<button type="submit" name="sucuriscan_save_notification_settings" class="button-primary">Save</button>
|
38 |
-
</div>
|
39 |
-
</th>
|
40 |
-
</tr>
|
41 |
-
</thead>
|
42 |
-
|
43 |
-
<tbody>
|
44 |
-
|
45 |
-
<tr>
|
46 |
-
<td>
|
47 |
-
<p>
|
48 |
-
Format of the subject for the email alerts, by default the plugin will use the
|
49 |
-
domain of the site, and the event that is going to be reported, you can change
|
50 |
-
this to also report the remote address of the user involved in the operation
|
51 |
-
that is being reported to quickly determine if the event is valid or not reading
|
52 |
-
the subject of the email.
|
53 |
-
</p>
|
54 |
-
|
55 |
-
<ul class="sucuriscan-subject-formats">
|
56 |
-
|
57 |
-
%%SUCURI.EmailSubjectOptions%%
|
58 |
-
|
59 |
-
<li>
|
60 |
-
<label>
|
61 |
-
<input type="radio" name="sucuriscan_email_subject" value="custom" %%SUCURI.EmailSubjectCustom.Checked%% />
|
62 |
-
<span>Custom format</span>
|
63 |
-
<input type="text" name="sucuriscan_custom_email_subject" value="%%SUCURI.EmailSubjectCustom.Value%%" />
|
64 |
-
</label>
|
65 |
-
</li>
|
66 |
-
|
67 |
-
</ul>
|
68 |
-
</td>
|
69 |
-
</tr>
|
70 |
-
|
71 |
-
%%SUCURI.NotificationOptions%%
|
72 |
-
|
73 |
-
</tbody>
|
74 |
-
</table>
|
75 |
-
</form>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
inc/tpl/settings-notifications.snippet.tpl
DELETED
@@ -1,12 +0,0 @@
|
|
1 |
-
|
2 |
-
<tr class="%%SUCURI.Notification.CssClass%%">
|
3 |
-
<td>
|
4 |
-
<div>
|
5 |
-
<label>
|
6 |
-
<input type="hidden" name="%%SUCURI.Notification.Name%%" value="0" />
|
7 |
-
<input type="checkbox" name="%%SUCURI.Notification.Name%%" value="1" %%SUCURI.Notification.Checked%% />
|
8 |
-
<span class="%%SUCURI.Notification.LabelIcon%%">%%SUCURI.Notification.Label%%</span>
|
9 |
-
</label>
|
10 |
-
</div>
|
11 |
-
</td>
|
12 |
-
</tr>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
inc/tpl/settings-scanner.html.tpl
CHANGED
@@ -55,10 +55,10 @@
|
|
55 |
<td>Scanning algorithm</td>
|
56 |
<td>%%SUCURI.ScanningInterface%%</td>
|
57 |
<td class="td-with-button">
|
58 |
-
<form action="%%SUCURI.URL.Settings%%#
|
59 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
60 |
<select name="sucuriscan_scan_interface">
|
61 |
-
|
62 |
</select>
|
63 |
<button type="submit" class="button-primary">Change</button>
|
64 |
</form>
|
@@ -69,10 +69,10 @@
|
|
69 |
<td>Scanning frequency</td>
|
70 |
<td>%%SUCURI.ScanningFrequency%%</td>
|
71 |
<td class="td-with-button">
|
72 |
-
<form action="%%SUCURI.URL.Settings%%#
|
73 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
74 |
<select name="sucuriscan_scan_frequency">
|
75 |
-
|
76 |
</select>
|
77 |
<button type="submit" class="button-primary">Change</button>
|
78 |
</form>
|
@@ -83,7 +83,7 @@
|
|
83 |
<td>Main <abbr title="File System Scanner">FS Scanner</abbr></td>
|
84 |
<td>%%SUCURI.FsScannerStatus%%</td>
|
85 |
<td class="td-with-button">
|
86 |
-
<form action="%%SUCURI.URL.Settings%%#
|
87 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
88 |
<input type="hidden" name="sucuriscan_fs_scanner" value="%%SUCURI.FsScannerSwitchValue%%" />
|
89 |
<button type="submit" class="button-primary %%SUCURI.FsScannerSwitchCssClass%%">%%SUCURI.FsScannerSwitchText%%</button>
|
@@ -91,23 +91,11 @@
|
|
91 |
</td>
|
92 |
</tr>
|
93 |
|
94 |
-
<tr>
|
95 |
-
<td>FS Scanner, Modified files</td>
|
96 |
-
<td>%%SUCURI.ScanModfilesStatus%%</td>
|
97 |
-
<td class="td-with-button">
|
98 |
-
<form action="%%SUCURI.URL.Settings%%#settings-scanner" method="post">
|
99 |
-
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
100 |
-
<input type="hidden" name="sucuriscan_scan_modfiles" value="%%SUCURI.ScanModfilesSwitchValue%%" />
|
101 |
-
<button type="submit" class="button-primary %%SUCURI.ScanModfilesSwitchCssClass%%">%%SUCURI.ScanModfilesSwitchText%%</button>
|
102 |
-
</form>
|
103 |
-
</td>
|
104 |
-
</tr>
|
105 |
-
|
106 |
<tr class="alternate">
|
107 |
<td>FS Scanner, Core integrity checks</td>
|
108 |
<td>%%SUCURI.ScanChecksumsStatus%%</td>
|
109 |
<td class="td-with-button">
|
110 |
-
<form action="%%SUCURI.URL.Settings%%#
|
111 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
112 |
<input type="hidden" name="sucuriscan_scan_checksums" value="%%SUCURI.ScanChecksumsSwitchValue%%" />
|
113 |
<button type="submit" class="button-primary %%SUCURI.ScanChecksumsSwitchCssClass%%">%%SUCURI.ScanChecksumsSwitchText%%</button>
|
@@ -119,7 +107,7 @@
|
|
119 |
<td>FS Scanner, Ignore scanning</td>
|
120 |
<td>%%SUCURI.IgnoreScanningStatus%%</td>
|
121 |
<td class="td-with-button">
|
122 |
-
<form action="%%SUCURI.URL.Settings%%#
|
123 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
124 |
<input type="hidden" name="sucuriscan_ignore_scanning" value="%%SUCURI.IgnoreScanningSwitchValue%%" />
|
125 |
<button type="submit" class="button-primary %%SUCURI.IgnoreScanningSwitchCssClass%%">%%SUCURI.IgnoreScanningSwitchText%%</button>
|
@@ -131,7 +119,7 @@
|
|
131 |
<td>FS Scanner, Error log files</td>
|
132 |
<td>%%SUCURI.ScanErrorlogsStatus%%</td>
|
133 |
<td class="td-with-button">
|
134 |
-
<form action="%%SUCURI.URL.Settings%%#
|
135 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
136 |
<input type="hidden" name="sucuriscan_scan_errorlogs" value="%%SUCURI.ScanErrorlogsSwitchValue%%" />
|
137 |
<button type="submit" class="button-primary %%SUCURI.ScanErrorlogsSwitchCssClass%%">%%SUCURI.ScanErrorlogsSwitchText%%</button>
|
@@ -143,7 +131,7 @@
|
|
143 |
<td>SiteCheck scanner</td>
|
144 |
<td>%%SUCURI.SiteCheckScannerStatus%%</td>
|
145 |
<td class="td-with-button">
|
146 |
-
<form action="%%SUCURI.URL.Settings%%#
|
147 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
148 |
<input type="hidden" name="sucuriscan_sitecheck_scanner" value="%%SUCURI.SiteCheckScannerSwitchValue%%" />
|
149 |
<button type="submit" class="button-primary %%SUCURI.SiteCheckScannerSwitchCssClass%%">%%SUCURI.SiteCheckScannerSwitchText%%</button>
|
@@ -167,7 +155,7 @@
|
|
167 |
<td>Analyze error logs</td>
|
168 |
<td>%%SUCURI.ParseErrorLogsStatus%%</td>
|
169 |
<td class="td-with-button">
|
170 |
-
<form action="%%SUCURI.URL.Settings%%#
|
171 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
172 |
<input type="hidden" name="sucuriscan_parse_errorlogs" value="%%SUCURI.ParseErrorLogsSwitchValue%%" />
|
173 |
<button type="submit" class="button-primary %%SUCURI.ParseErrorLogsSwitchCssClass%%">%%SUCURI.ParseErrorLogsSwitchText%%</button>
|
@@ -179,7 +167,7 @@
|
|
179 |
<td>Error logs limit</td>
|
180 |
<td>Analyze last %%SUCURI.ErrorLogsLimit%% logs</td>
|
181 |
<td class="td-with-button">
|
182 |
-
<form action="%%SUCURI.URL.Settings%%#
|
183 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
184 |
<input type="text" name="sucuriscan_errorlogs_limit" placeholder="Number of lines to analyze" class="input-text" />
|
185 |
<button type="submit" class="button-primary">Change</button>
|
@@ -191,7 +179,7 @@
|
|
191 |
<td>Reset core integrity logs</td>
|
192 |
<td><span class="sucuriscan-monospace">%%SUCURI.IntegrityLogLife%% of data</span></td>
|
193 |
<td class="td-with-button">
|
194 |
-
<form action="%%SUCURI.URL.Settings%%#
|
195 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
196 |
<input type="hidden" name="sucuriscan_reset_logfile" value="integrity" />
|
197 |
<button type="submit" class="button-primary">Reset logs</button>
|
@@ -203,7 +191,7 @@
|
|
203 |
<td>Reset last login logs</td>
|
204 |
<td><span class="sucuriscan-monospace">%%SUCURI.LastLoginLogLife%% of data</span></td>
|
205 |
<td class="td-with-button">
|
206 |
-
<form action="%%SUCURI.URL.Settings%%#
|
207 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
208 |
<input type="hidden" name="sucuriscan_reset_logfile" value="lastlogins" />
|
209 |
<button type="submit" class="button-primary">Reset logs</button>
|
@@ -215,7 +203,7 @@
|
|
215 |
<td>Reset failed login logs</td>
|
216 |
<td><span class="sucuriscan-monospace">%%SUCURI.FailedLoginLogLife%% of data</span></td>
|
217 |
<td class="td-with-button">
|
218 |
-
<form action="%%SUCURI.URL.Settings%%#
|
219 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
220 |
<input type="hidden" name="sucuriscan_reset_logfile" value="failedlogins" />
|
221 |
<button type="submit" class="button-primary">Reset logs</button>
|
@@ -227,7 +215,7 @@
|
|
227 |
<td>Reset sitecheck logs</td>
|
228 |
<td><span class="sucuriscan-monospace">%%SUCURI.SiteCheckLogLife%% of data</span></td>
|
229 |
<td class="td-with-button">
|
230 |
-
<form action="%%SUCURI.URL.Settings%%#
|
231 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
232 |
<input type="hidden" name="sucuriscan_reset_logfile" value="sitecheck" />
|
233 |
<button type="submit" class="button-primary">Reset logs</button>
|
55 |
<td>Scanning algorithm</td>
|
56 |
<td>%%SUCURI.ScanningInterface%%</td>
|
57 |
<td class="td-with-button">
|
58 |
+
<form action="%%SUCURI.URL.Settings%%#scanner" method="post">
|
59 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
60 |
<select name="sucuriscan_scan_interface">
|
61 |
+
%%%SUCURI.ScanningInterfaceOptions%%%
|
62 |
</select>
|
63 |
<button type="submit" class="button-primary">Change</button>
|
64 |
</form>
|
69 |
<td>Scanning frequency</td>
|
70 |
<td>%%SUCURI.ScanningFrequency%%</td>
|
71 |
<td class="td-with-button">
|
72 |
+
<form action="%%SUCURI.URL.Settings%%#scanner" method="post">
|
73 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
74 |
<select name="sucuriscan_scan_frequency">
|
75 |
+
%%%SUCURI.ScanningFrequencyOptions%%%
|
76 |
</select>
|
77 |
<button type="submit" class="button-primary">Change</button>
|
78 |
</form>
|
83 |
<td>Main <abbr title="File System Scanner">FS Scanner</abbr></td>
|
84 |
<td>%%SUCURI.FsScannerStatus%%</td>
|
85 |
<td class="td-with-button">
|
86 |
+
<form action="%%SUCURI.URL.Settings%%#scanner" method="post">
|
87 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
88 |
<input type="hidden" name="sucuriscan_fs_scanner" value="%%SUCURI.FsScannerSwitchValue%%" />
|
89 |
<button type="submit" class="button-primary %%SUCURI.FsScannerSwitchCssClass%%">%%SUCURI.FsScannerSwitchText%%</button>
|
91 |
</td>
|
92 |
</tr>
|
93 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
94 |
<tr class="alternate">
|
95 |
<td>FS Scanner, Core integrity checks</td>
|
96 |
<td>%%SUCURI.ScanChecksumsStatus%%</td>
|
97 |
<td class="td-with-button">
|
98 |
+
<form action="%%SUCURI.URL.Settings%%#scanner" method="post">
|
99 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
100 |
<input type="hidden" name="sucuriscan_scan_checksums" value="%%SUCURI.ScanChecksumsSwitchValue%%" />
|
101 |
<button type="submit" class="button-primary %%SUCURI.ScanChecksumsSwitchCssClass%%">%%SUCURI.ScanChecksumsSwitchText%%</button>
|
107 |
<td>FS Scanner, Ignore scanning</td>
|
108 |
<td>%%SUCURI.IgnoreScanningStatus%%</td>
|
109 |
<td class="td-with-button">
|
110 |
+
<form action="%%SUCURI.URL.Settings%%#scanner" method="post">
|
111 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
112 |
<input type="hidden" name="sucuriscan_ignore_scanning" value="%%SUCURI.IgnoreScanningSwitchValue%%" />
|
113 |
<button type="submit" class="button-primary %%SUCURI.IgnoreScanningSwitchCssClass%%">%%SUCURI.IgnoreScanningSwitchText%%</button>
|
119 |
<td>FS Scanner, Error log files</td>
|
120 |
<td>%%SUCURI.ScanErrorlogsStatus%%</td>
|
121 |
<td class="td-with-button">
|
122 |
+
<form action="%%SUCURI.URL.Settings%%#scanner" method="post">
|
123 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
124 |
<input type="hidden" name="sucuriscan_scan_errorlogs" value="%%SUCURI.ScanErrorlogsSwitchValue%%" />
|
125 |
<button type="submit" class="button-primary %%SUCURI.ScanErrorlogsSwitchCssClass%%">%%SUCURI.ScanErrorlogsSwitchText%%</button>
|
131 |
<td>SiteCheck scanner</td>
|
132 |
<td>%%SUCURI.SiteCheckScannerStatus%%</td>
|
133 |
<td class="td-with-button">
|
134 |
+
<form action="%%SUCURI.URL.Settings%%#scanner" method="post">
|
135 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
136 |
<input type="hidden" name="sucuriscan_sitecheck_scanner" value="%%SUCURI.SiteCheckScannerSwitchValue%%" />
|
137 |
<button type="submit" class="button-primary %%SUCURI.SiteCheckScannerSwitchCssClass%%">%%SUCURI.SiteCheckScannerSwitchText%%</button>
|
155 |
<td>Analyze error logs</td>
|
156 |
<td>%%SUCURI.ParseErrorLogsStatus%%</td>
|
157 |
<td class="td-with-button">
|
158 |
+
<form action="%%SUCURI.URL.Settings%%#scanner" method="post">
|
159 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
160 |
<input type="hidden" name="sucuriscan_parse_errorlogs" value="%%SUCURI.ParseErrorLogsSwitchValue%%" />
|
161 |
<button type="submit" class="button-primary %%SUCURI.ParseErrorLogsSwitchCssClass%%">%%SUCURI.ParseErrorLogsSwitchText%%</button>
|
167 |
<td>Error logs limit</td>
|
168 |
<td>Analyze last %%SUCURI.ErrorLogsLimit%% logs</td>
|
169 |
<td class="td-with-button">
|
170 |
+
<form action="%%SUCURI.URL.Settings%%#scanner" method="post">
|
171 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
172 |
<input type="text" name="sucuriscan_errorlogs_limit" placeholder="Number of lines to analyze" class="input-text" />
|
173 |
<button type="submit" class="button-primary">Change</button>
|
179 |
<td>Reset core integrity logs</td>
|
180 |
<td><span class="sucuriscan-monospace">%%SUCURI.IntegrityLogLife%% of data</span></td>
|
181 |
<td class="td-with-button">
|
182 |
+
<form action="%%SUCURI.URL.Settings%%#scanner" method="post">
|
183 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
184 |
<input type="hidden" name="sucuriscan_reset_logfile" value="integrity" />
|
185 |
<button type="submit" class="button-primary">Reset logs</button>
|
191 |
<td>Reset last login logs</td>
|
192 |
<td><span class="sucuriscan-monospace">%%SUCURI.LastLoginLogLife%% of data</span></td>
|
193 |
<td class="td-with-button">
|
194 |
+
<form action="%%SUCURI.URL.Settings%%#scanner" method="post">
|
195 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
196 |
<input type="hidden" name="sucuriscan_reset_logfile" value="lastlogins" />
|
197 |
<button type="submit" class="button-primary">Reset logs</button>
|
203 |
<td>Reset failed login logs</td>
|
204 |
<td><span class="sucuriscan-monospace">%%SUCURI.FailedLoginLogLife%% of data</span></td>
|
205 |
<td class="td-with-button">
|
206 |
+
<form action="%%SUCURI.URL.Settings%%#scanner" method="post">
|
207 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
208 |
<input type="hidden" name="sucuriscan_reset_logfile" value="failedlogins" />
|
209 |
<button type="submit" class="button-primary">Reset logs</button>
|
215 |
<td>Reset sitecheck logs</td>
|
216 |
<td><span class="sucuriscan-monospace">%%SUCURI.SiteCheckLogLife%% of data</span></td>
|
217 |
<td class="td-with-button">
|
218 |
+
<form action="%%SUCURI.URL.Settings%%#scanner" method="post">
|
219 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
220 |
<input type="hidden" name="sucuriscan_reset_logfile" value="sitecheck" />
|
221 |
<button type="submit" class="button-primary">Reset logs</button>
|
inc/tpl/settings-selfhosting-monitor.html.tpl
ADDED
@@ -0,0 +1,56 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
<div class="postbox">
|
3 |
+
<h3>Log Exporter</h3>
|
4 |
+
|
5 |
+
<div class="inside">
|
6 |
+
<p>
|
7 |
+
This option allows you to export the WordPress audit logs to a local log file
|
8 |
+
that can be read by a SIEM or any log analysis software <em>(we recommend OSSEC)
|
9 |
+
</em>. That will give visibility from within WordPress to complement your log
|
10 |
+
monitoring infrastructure.
|
11 |
+
</p>
|
12 |
+
|
13 |
+
<div class="sucuriscan-hstatus sucuriscan-hstatus-2 sucuriscan-%%SUCURI.SelfHostingMonitor.DisabledVisibility%%">
|
14 |
+
<span>Log Exporter is %%SUCURI.SelfHostingMonitor.Status%%</span>
|
15 |
+
</div>
|
16 |
+
|
17 |
+
<div class="sucuriscan-hstatus sucuriscan-hstatus-2 sucuriscan-monitor-fpath sucuriscan-%%SUCURI.SelfHostingMonitor.FpathVisibility%%">
|
18 |
+
<span class="sucuriscan-monospace">%%SUCURI.SelfHostingMonitor.Fpath%%</span>
|
19 |
+
<form action="%%SUCURI.URL.Settings%%#selfhosting" method="post">
|
20 |
+
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
21 |
+
<input type="hidden" name="sucuriscan_selfhosting_fpath" class="input-text" />
|
22 |
+
<button type="submit" class="button-primary %%SUCURI.SelfHostingMonitor.SwitchCssClass%%">
|
23 |
+
%%SUCURI.SelfHostingMonitor.SwitchText%%</button>
|
24 |
+
</form>
|
25 |
+
</div>
|
26 |
+
|
27 |
+
<p>
|
28 |
+
Specify the absolute location of the file <em>(including the extension)</em>
|
29 |
+
that you want to use to store a copy of the events that are being monitored by
|
30 |
+
the plugin. The file must exists and be writable by the PHP interpreter. Note
|
31 |
+
that the events that are being triggered when this option is disabled will not
|
32 |
+
be copied to this file even if you have enabled this feature before, you must
|
33 |
+
consider this when you give access to other administrator users to change the
|
34 |
+
settings of your website.
|
35 |
+
</p>
|
36 |
+
|
37 |
+
<div class="sucuriscan-inline-alert-warning">
|
38 |
+
<p>
|
39 |
+
Do not use a public location to store the logs, you will end up leaking
|
40 |
+
sensitive information about your website and the activity of your users. If you
|
41 |
+
decide to use a file located in the public directory for any particular reason
|
42 |
+
we recommend you to name it with a random-unique string so malicious users can
|
43 |
+
not easily access it.
|
44 |
+
</p>
|
45 |
+
</div>
|
46 |
+
|
47 |
+
<form action="%%SUCURI.URL.Settings%%#selfhosting" method="post" class="sucuriscan-%%SUCURI.SelfHostingMonitor.DisabledVisibility%%">
|
48 |
+
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
49 |
+
<span class="sucuriscan-input-group">
|
50 |
+
<label>Absolute File Path:</label>
|
51 |
+
<input type="text" name="sucuriscan_selfhosting_fpath" class="input-text" />
|
52 |
+
</span>
|
53 |
+
<button type="submit" class="button-primary">Save</button>
|
54 |
+
</form>
|
55 |
+
</div>
|
56 |
+
</div>
|
inc/tpl/settings-selfhosting.html.tpl
ADDED
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
<div id="poststuff">
|
3 |
+
%%%SUCURI.SelfHosting.Monitor%%%
|
4 |
+
</div>
|
inc/tpl/settings-trustip.html.tpl
CHANGED
@@ -12,7 +12,7 @@
|
|
12 |
specify ranges of IP addresses <em>(only 8, 16, and 24)</em>.
|
13 |
</p>
|
14 |
|
15 |
-
<form action="%%SUCURI.URL.Settings%%#
|
16 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
17 |
<input type="text" name="sucuriscan_trust_ip" placeholder="e.g. 182.120.56.0/24" />
|
18 |
<input type="submit" value="Add Entry" class="button button-primary" />
|
@@ -21,7 +21,7 @@
|
|
21 |
</div>
|
22 |
</div>
|
23 |
|
24 |
-
<form action="%%SUCURI.URL.Settings%%#
|
25 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
26 |
|
27 |
<table class="wp-list-table widefat sucuriscan-table sucuriscan-settings-trustip">
|
@@ -38,7 +38,7 @@
|
|
38 |
</thead>
|
39 |
|
40 |
<tbody>
|
41 |
-
|
42 |
|
43 |
<tr class="sucuriscan-%%SUCURI.TrustedIPs.NoItems.Visibility%%">
|
44 |
<td colspan="4">
|
12 |
specify ranges of IP addresses <em>(only 8, 16, and 24)</em>.
|
13 |
</p>
|
14 |
|
15 |
+
<form action="%%SUCURI.URL.Settings%%#trustip" method="POST">
|
16 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
17 |
<input type="text" name="sucuriscan_trust_ip" placeholder="e.g. 182.120.56.0/24" />
|
18 |
<input type="submit" value="Add Entry" class="button button-primary" />
|
21 |
</div>
|
22 |
</div>
|
23 |
|
24 |
+
<form action="%%SUCURI.URL.Settings%%#trustip" method="post">
|
25 |
<input type="hidden" name="sucuriscan_page_nonce" value="%%SUCURI.PageNonce%%" />
|
26 |
|
27 |
<table class="wp-list-table widefat sucuriscan-table sucuriscan-settings-trustip">
|
38 |
</thead>
|
39 |
|
40 |
<tbody>
|
41 |
+
%%%SUCURI.TrustedIPs.List%%%
|
42 |
|
43 |
<tr class="sucuriscan-%%SUCURI.TrustedIPs.NoItems.Visibility%%">
|
44 |
<td colspan="4">
|
inc/tpl/settings.html.tpl
CHANGED
@@ -2,55 +2,69 @@
|
|
2 |
<div class="sucuriscan-tabs">
|
3 |
<ul>
|
4 |
<li>
|
5 |
-
<a href="#" data-tabname="
|
6 |
</li>
|
7 |
<li>
|
8 |
-
<a href="#" data-tabname="
|
9 |
</li>
|
10 |
<li>
|
11 |
-
<a href="#" data-tabname="
|
12 |
</li>
|
13 |
<li>
|
14 |
-
<a href="#" data-tabname="
|
15 |
</li>
|
16 |
<li>
|
17 |
-
<a href="#" data-tabname="
|
18 |
</li>
|
19 |
<li>
|
20 |
-
<a href="#" data-tabname="
|
21 |
</li>
|
22 |
<li>
|
23 |
-
<a href="#" data-tabname="
|
|
|
|
|
|
|
|
|
|
|
|
|
24 |
</li>
|
25 |
</ul>
|
26 |
|
27 |
<div class="sucuriscan-tab-containers">
|
28 |
-
<div id="sucuriscan-
|
29 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
30 |
</div>
|
31 |
|
32 |
-
<div id="sucuriscan-
|
33 |
-
|
34 |
</div>
|
35 |
|
36 |
-
<div id="sucuriscan-
|
37 |
-
|
38 |
</div>
|
39 |
|
40 |
-
<div id="sucuriscan-
|
41 |
-
|
42 |
</div>
|
43 |
|
44 |
-
<div id="sucuriscan-
|
45 |
-
|
46 |
</div>
|
47 |
|
48 |
-
<div id="sucuriscan-
|
49 |
-
|
50 |
</div>
|
51 |
|
52 |
-
<div id="sucuriscan-
|
53 |
-
|
54 |
</div>
|
55 |
</div>
|
56 |
</div>
|
2 |
<div class="sucuriscan-tabs">
|
3 |
<ul>
|
4 |
<li>
|
5 |
+
<a href="#general" data-tabname="general">General</a>
|
6 |
</li>
|
7 |
<li>
|
8 |
+
<a href="#scanner" data-tabname="scanner">Scanner</a>
|
9 |
</li>
|
10 |
<li>
|
11 |
+
<a href="#notifications" data-tabname="notifications">Alerts</a>
|
12 |
</li>
|
13 |
<li>
|
14 |
+
<a href="#apiservice" data-tabname="apiservice">API Service</a>
|
15 |
</li>
|
16 |
<li>
|
17 |
+
<a href="#selfhosting" data-tabname="selfhosting">Log Exporter</a>
|
18 |
</li>
|
19 |
<li>
|
20 |
+
<a href="#ignorescanning" data-tabname="ignorescanning">Ignore Scanning</a>
|
21 |
</li>
|
22 |
<li>
|
23 |
+
<a href="#ignorerules" data-tabname="ignorerules">Ignore Alerts</a>
|
24 |
+
</li>
|
25 |
+
<li>
|
26 |
+
<a href="#trustip" data-tabname="trustip">Trust IP</a>
|
27 |
+
</li>
|
28 |
+
<li>
|
29 |
+
<a href="#heartbeat" data-tabname="heartbeat">Heartbeat</a>
|
30 |
</li>
|
31 |
</ul>
|
32 |
|
33 |
<div class="sucuriscan-tab-containers">
|
34 |
+
<div id="sucuriscan-general">
|
35 |
+
%%%SUCURI.Settings.General%%%
|
36 |
+
</div>
|
37 |
+
|
38 |
+
<div id="sucuriscan-scanner">
|
39 |
+
%%%SUCURI.Settings.Scanner%%%
|
40 |
+
</div>
|
41 |
+
|
42 |
+
<div id="sucuriscan-notifications">
|
43 |
+
%%%SUCURI.Settings.Alerts%%%
|
44 |
</div>
|
45 |
|
46 |
+
<div id="sucuriscan-apiservice">
|
47 |
+
%%%SUCURI.Settings.ApiService%%%
|
48 |
</div>
|
49 |
|
50 |
+
<div id="sucuriscan-selfhosting">
|
51 |
+
%%%SUCURI.Settings.SelfHosting%%%
|
52 |
</div>
|
53 |
|
54 |
+
<div id="sucuriscan-ignorescanning">
|
55 |
+
%%%SUCURI.Settings.IgnoreScanning%%%
|
56 |
</div>
|
57 |
|
58 |
+
<div id="sucuriscan-ignorerules">
|
59 |
+
%%%SUCURI.Settings.IgnoreRules%%%
|
60 |
</div>
|
61 |
|
62 |
+
<div id="sucuriscan-trustip">
|
63 |
+
%%%SUCURI.Settings.TrustIP%%%
|
64 |
</div>
|
65 |
|
66 |
+
<div id="sucuriscan-heartbeat">
|
67 |
+
%%%SUCURI.Settings.Heartbeat%%%
|
68 |
</div>
|
69 |
</div>
|
70 |
</div>
|
inc/tpl/setup-form.html.tpl
CHANGED
@@ -32,7 +32,7 @@
|
|
32 |
<td>E-mail Address:</td>
|
33 |
<td>
|
34 |
<select name="sucuriscan_setup_user">
|
35 |
-
|
36 |
</select>
|
37 |
</td>
|
38 |
</tr>
|
32 |
<td>E-mail Address:</td>
|
33 |
<td>
|
34 |
<select name="sucuriscan_setup_user">
|
35 |
+
%%%SUCURI.AdminEmails%%%
|
36 |
</select>
|
37 |
</td>
|
38 |
</tr>
|
inc/tpl/setup-notice.html.tpl
CHANGED
@@ -1,6 +1,6 @@
|
|
1 |
|
2 |
<div class="updated sucuriscan-setup-notice sucuriscan-clearfix">
|
3 |
-
<a href="
|
4 |
<img src="%%SUCURI.SucuriURL%%/inc/images/logo.png" alt="Sucuri Scanner" />
|
5 |
</a>
|
6 |
|
1 |
|
2 |
<div class="updated sucuriscan-setup-notice sucuriscan-clearfix">
|
3 |
+
<a href="https://sucuri.net/" target="_blank" class="sucuriscan-pull-left sucuriscan-setup-image">
|
4 |
<img src="%%SUCURI.SucuriURL%%/inc/images/logo.png" alt="Sucuri Scanner" />
|
5 |
</a>
|
6 |
|
readme.txt
CHANGED
@@ -1,10 +1,10 @@
|
|
1 |
=== Sucuri Security - Auditing, Malware Scanner and Security Hardening ===
|
2 |
Contributors: dd@sucuri.net
|
3 |
-
Donate Link:
|
4 |
Tags: malware, security, firewall, scan, spam, virus, sucuri, protection,WordPress Security, Login Security,Security Auditing,File Integrity,htaccess,phishing,backdoors,SQL Injection, RFI, LFI, XSS, CSRF, website firewall, Website Security, Performance Optimization, Zero Day, Software Vulnerability, Exploits, Hacks, Attackers, Bad Actors, Reverse Proxy, Two Factor Security, Two Factor Authentication, Security Logs, HeatBleed Vulnerability, Website Protection, Bash Vulnerability, RevSlider Vulnerability, MailPoet Vulnerability, Malware Prevention, Website Firewall, Website AntiVirus, Security Response, Security Detection, Security Prevention
|
5 |
Requires at least:3.2
|
6 |
-
Stable tag: 1.7.
|
7 |
-
Tested up to: 4.
|
8 |
|
9 |
The Sucuri WordPress Security plugin is a security toolset for security integrity monitoring, malware detection and security hardening.
|
10 |
|
@@ -79,10 +79,9 @@ Here is a video of the Security File Integrity Monitoring feature:
|
|
79 |
= Remote Security Malware Scanning =
|
80 |
|
81 |
This feature is powered by our very powerful scanning engine, found on our
|
82 |
-
free security scanner - <a href="
|
83 |
-
important to take some time to <a
|
84 |
-
|
85 |
-
how this scanner works</a>.
|
86 |
|
87 |
Here is a video of the Remote Security Malware Scanning feature:
|
88 |
|
@@ -178,8 +177,11 @@ This is coupled with a number of features like:
|
|
178 |
<li>Failover and Redundancy</li>
|
179 |
</ol>
|
180 |
|
181 |
-
This is not included as a
|
182 |
-
integrated so that if purchased you are able to activate. If you prefer to
|
|
|
|
|
|
|
183 |
|
184 |
Here is a video of the Sucuri Security Website Firewall (Add On Security Service) feature:
|
185 |
|
@@ -208,7 +210,7 @@ To install Sucuri Security and complement your Security posture:
|
|
208 |
|
209 |
|
210 |
1. You will want to log into your WordPress administration panel - (e.g.,
|
211 |
-
|
212 |
|
213 |
2. Navigate to <strong>Plugins Menu</strong> option in your WordPress
|
214 |
administration panel
|
@@ -253,7 +255,7 @@ security needs as you see fit.
|
|
253 |
== FAQ ==
|
254 |
|
255 |
More information can be found on the the Sucuri Security WordPress Security
|
256 |
-
plugin via our free [Knowledge Base](
|
257 |
|
258 |
= What does this plugin do that other WordPress security plugins don't do? =
|
259 |
|
@@ -352,6 +354,12 @@ service from the WordPress dashboard.
|
|
352 |
|
353 |
== Changelog ==
|
354 |
|
|
|
|
|
|
|
|
|
|
|
|
|
355 |
= 1.7.16 =
|
356 |
* Fixing a low severity XSS (needs admin access to create it)
|
357 |
|
@@ -587,5 +595,5 @@ service from the WordPress dashboard.
|
|
587 |
|
588 |
== Credits ==
|
589 |
|
590 |
-
* <a href="
|
591 |
|
1 |
=== Sucuri Security - Auditing, Malware Scanner and Security Hardening ===
|
2 |
Contributors: dd@sucuri.net
|
3 |
+
Donate Link: https://sucuri.net/
|
4 |
Tags: malware, security, firewall, scan, spam, virus, sucuri, protection,WordPress Security, Login Security,Security Auditing,File Integrity,htaccess,phishing,backdoors,SQL Injection, RFI, LFI, XSS, CSRF, website firewall, Website Security, Performance Optimization, Zero Day, Software Vulnerability, Exploits, Hacks, Attackers, Bad Actors, Reverse Proxy, Two Factor Security, Two Factor Authentication, Security Logs, HeatBleed Vulnerability, Website Protection, Bash Vulnerability, RevSlider Vulnerability, MailPoet Vulnerability, Malware Prevention, Website Firewall, Website AntiVirus, Security Response, Security Detection, Security Prevention
|
5 |
Requires at least:3.2
|
6 |
+
Stable tag: 1.7.17
|
7 |
+
Tested up to: 4.4.1
|
8 |
|
9 |
The Sucuri WordPress Security plugin is a security toolset for security integrity monitoring, malware detection and security hardening.
|
10 |
|
79 |
= Remote Security Malware Scanning =
|
80 |
|
81 |
This feature is powered by our very powerful scanning engine, found on our
|
82 |
+
free security scanner - <a href="https://sitecheck.sucuri.net">SiteCheck</a>. It’s
|
83 |
+
important to take some time to <a href="https://blog.sucuri.net/2012/10/ask-sucuri-how-does-sitecheck-work.html">
|
84 |
+
understand how this scanner works</a>.
|
|
|
85 |
|
86 |
Here is a video of the Remote Security Malware Scanning feature:
|
87 |
|
177 |
<li>Failover and Redundancy</li>
|
178 |
</ol>
|
179 |
|
180 |
+
This is <strong>not included as a free</strong> option to the plugin, but is
|
181 |
+
integrated so that if purchased you are able to activate. If you prefer to
|
182 |
+
leverage the Sucuri Security Website Firewall (CloudProxy) product by itself,
|
183 |
+
you have the option to operate the <a href="https://wordpress.org/plugins/sucuri-cloudproxy-waf/">
|
184 |
+
Website Firewall WordPress Security</a> plugin in standalone mode.
|
185 |
|
186 |
Here is a video of the Sucuri Security Website Firewall (Add On Security Service) feature:
|
187 |
|
210 |
|
211 |
|
212 |
1. You will want to log into your WordPress administration panel - (e.g.,
|
213 |
+
https://yourdomain/wp-admin)
|
214 |
|
215 |
2. Navigate to <strong>Plugins Menu</strong> option in your WordPress
|
216 |
administration panel
|
255 |
== FAQ ==
|
256 |
|
257 |
More information can be found on the the Sucuri Security WordPress Security
|
258 |
+
plugin via our free [Knowledge Base](https://kb.sucuri.net/plugins/WordPress+Plugin/index).
|
259 |
|
260 |
= What does this plugin do that other WordPress security plugins don't do? =
|
261 |
|
354 |
|
355 |
== Changelog ==
|
356 |
|
357 |
+
= 1.7.17 =
|
358 |
+
* Added API service failback mechanism
|
359 |
+
* Added core integrity email on force scan
|
360 |
+
* Slight interface redesign
|
361 |
+
* Various bugfixes and improvements
|
362 |
+
|
363 |
= 1.7.16 =
|
364 |
* Fixing a low severity XSS (needs admin access to create it)
|
365 |
|
595 |
|
596 |
== Credits ==
|
597 |
|
598 |
+
* <a href="https://sucuri.net">Sucuri Security</a>
|
599 |
|
sucuri.php
CHANGED
@@ -1,11 +1,11 @@
|
|
1 |
<?php
|
2 |
/*
|
3 |
Plugin Name: Sucuri Security - Auditing, Malware Scanner and Hardening
|
4 |
-
Plugin URI:
|
5 |
-
Description: The <a href="
|
6 |
Author: Sucuri, INC
|
7 |
-
Version: 1.7.
|
8 |
-
Author URI:
|
9 |
*/
|
10 |
|
11 |
|
@@ -42,8 +42,8 @@ $sucuriscan_dependencies = array(
|
|
42 |
);
|
43 |
|
44 |
// Terminate execution if any of the functions mentioned above is not defined.
|
45 |
-
foreach (
|
46 |
-
if (
|
47 |
exit(0);
|
48 |
}
|
49 |
}
|
@@ -61,92 +61,97 @@ foreach ( $sucuriscan_dependencies as $dependency ) {
|
|
61 |
/**
|
62 |
* Unique name of the plugin through out all the code.
|
63 |
*/
|
64 |
-
define(
|
65 |
|
66 |
/**
|
67 |
* Current version of the plugin's code.
|
68 |
*/
|
69 |
-
define(
|
70 |
|
71 |
/**
|
72 |
* The name of the Sucuri plugin main file.
|
73 |
*/
|
74 |
-
define(
|
75 |
|
76 |
/**
|
77 |
* The name of the folder where the plugin's files will be located.
|
78 |
*/
|
79 |
-
define(
|
80 |
|
81 |
/**
|
82 |
* The fullpath where the plugin's files will be located.
|
83 |
*/
|
84 |
-
define(
|
85 |
|
86 |
/**
|
87 |
* The fullpath of the main plugin file.
|
88 |
*/
|
89 |
-
define(
|
90 |
|
91 |
/**
|
92 |
* The local URL where the plugin's files and assets are served.
|
93 |
*/
|
94 |
-
define(
|
95 |
|
96 |
/**
|
97 |
* Checksum of this file to check the integrity of the plugin.
|
98 |
*/
|
99 |
-
define(
|
100 |
|
101 |
/**
|
102 |
* Remote URL where the public Sucuri API service is running.
|
103 |
*/
|
104 |
-
define(
|
105 |
|
106 |
/**
|
107 |
* Latest version of the public Sucuri API.
|
108 |
*/
|
109 |
-
define(
|
110 |
|
111 |
/**
|
112 |
* Remote URL where the CloudProxy API service is running.
|
113 |
*/
|
114 |
-
define(
|
115 |
|
116 |
/**
|
117 |
* Latest version of the CloudProxy API.
|
118 |
*/
|
119 |
-
define(
|
120 |
|
121 |
/**
|
122 |
* The maximum quantity of entries that will be displayed in the last login page.
|
123 |
*/
|
124 |
-
define(
|
125 |
|
126 |
/**
|
127 |
* The maximum quantity of entries that will be displayed in the audit logs page.
|
128 |
*/
|
129 |
-
define(
|
130 |
|
131 |
/**
|
132 |
* The maximum quantity of buttons in the paginations.
|
133 |
*/
|
134 |
-
define(
|
135 |
|
136 |
/**
|
137 |
* The minimum quantity of seconds to wait before each filesystem scan.
|
138 |
*/
|
139 |
-
define(
|
140 |
|
141 |
/**
|
142 |
* The life time of the cache for the results of the SiteCheck scans.
|
143 |
*/
|
144 |
-
define(
|
145 |
|
146 |
/**
|
147 |
* The life time of the cache for the results of the get_plugins function.
|
148 |
*/
|
149 |
-
define(
|
|
|
|
|
|
|
|
|
|
|
150 |
|
151 |
/**
|
152 |
* Plugin's global variables.
|
@@ -156,7 +161,7 @@ define( 'SUCURISCAN_GET_PLUGINS_LIFETIME', 1800 );
|
|
156 |
* conditional will act as a container helping in the readability of the code
|
157 |
* considering the total number of lines that this file will have.
|
158 |
*/
|
159 |
-
if (
|
160 |
/**
|
161 |
* Define the prefix for some actions and filters that rely in the
|
162 |
* differentiation of the type of site where the extension is being used. There
|
@@ -176,7 +181,7 @@ if ( defined( 'SUCURISCAN' ) ) {
|
|
176 |
$sucuriscan_pages = array(
|
177 |
'sucuriscan' => 'Dashboard',
|
178 |
'sucuriscan_scanner' => 'Malware Scan',
|
179 |
-
'
|
180 |
'sucuriscan_hardening' => 'Hardening',
|
181 |
'sucuriscan_posthack' => 'Post-Hack',
|
182 |
'sucuriscan_lastlogins' => 'Last Logins',
|
@@ -197,30 +202,30 @@ if ( defined( 'SUCURISCAN' ) ) {
|
|
197 |
*/
|
198 |
|
199 |
$sucuriscan_notify_options = array(
|
200 |
-
'sucuriscan_notify_plugin_change' => 'Receive email alerts for <
|
201 |
'sucuriscan_prettify_mails' => 'Receive email alerts in HTML <em>(there may be issues with some mail services)</em>',
|
202 |
'sucuriscan_use_wpmail' => 'Use WordPress functions to send mails <em>(uncheck to use native PHP functions)</em>',
|
203 |
'sucuriscan_lastlogin_redirection' => 'Allow redirection after login to report the last-login information',
|
204 |
'sucuriscan_notify_scan_checksums' => 'Receive email alerts for core integrity checks',
|
205 |
'sucuriscan_notify_user_registration' => 'user:Receive email alerts for new user registration',
|
206 |
'sucuriscan_notify_success_login' => 'user:Receive email alerts for successful login attempts',
|
207 |
-
'sucuriscan_notify_failed_login' => 'user:Receive email alerts for failed login attempts',
|
208 |
-
'sucuriscan_notify_bruteforce_attack' => 'user:Receive email alerts for password guessing
|
209 |
'sucuriscan_notify_post_publication' => 'Receive email alerts for Post-Type changes <em>(configure from Ignore Alerts)</em>',
|
210 |
'sucuriscan_notify_website_updated' => 'Receive email alerts when the WordPress version is updated',
|
211 |
'sucuriscan_notify_settings_updated' => 'Receive email alerts when your website settings are updated',
|
212 |
'sucuriscan_notify_theme_editor' => 'Receive email alerts when a file is modified with theme/plugin editor',
|
213 |
-
'sucuriscan_notify_plugin_installed' => 'plugin:Receive email alerts when a <
|
214 |
-
'sucuriscan_notify_plugin_activated' => 'plugin:Receive email alerts when a <
|
215 |
-
'sucuriscan_notify_plugin_deactivated' => 'plugin:Receive email alerts when a <
|
216 |
-
'sucuriscan_notify_plugin_updated' => 'plugin:Receive email alerts when a <
|
217 |
-
'sucuriscan_notify_plugin_deleted' => 'plugin:Receive email alerts when a <
|
218 |
-
'sucuriscan_notify_widget_added' => 'widget:Receive email alerts when a <
|
219 |
-
'sucuriscan_notify_widget_deleted' => 'widget:Receive email alerts when a <
|
220 |
-
'sucuriscan_notify_theme_installed' => 'theme:Receive email alerts when a <
|
221 |
-
'sucuriscan_notify_theme_activated' => 'theme:Receive email alerts when a <
|
222 |
-
'sucuriscan_notify_theme_updated' => 'theme:Receive email alerts when a <
|
223 |
-
'sucuriscan_notify_theme_deleted' => 'theme:Receive email alerts when a <
|
224 |
);
|
225 |
|
226 |
$sucuriscan_schedule_allowed = array(
|
@@ -275,7 +280,7 @@ if ( defined( 'SUCURISCAN' ) ) {
|
|
275 |
/**
|
276 |
* Remove the WordPress generator meta-tag from the source code.
|
277 |
*/
|
278 |
-
remove_action(
|
279 |
|
280 |
/**
|
281 |
* Run a specific function defined in the plugin's code to locate every
|
@@ -283,7 +288,7 @@ if ( defined( 'SUCURISCAN' ) ) {
|
|
283 |
* information to the Sucuri API service where a security and integrity scan
|
284 |
* will be performed against the hashes provided and the official versions.
|
285 |
*/
|
286 |
-
add_action(
|
287 |
|
288 |
/**
|
289 |
* Initialize the execute of the main plugin's functions.
|
@@ -291,10 +296,10 @@ if ( defined( 'SUCURISCAN' ) ) {
|
|
291 |
* This will load the menu options in the WordPress administrator panel, and
|
292 |
* execute the bootstrap function of the plugin.
|
293 |
*/
|
294 |
-
add_action(
|
295 |
-
add_action(
|
296 |
-
add_action(
|
297 |
-
add_action(
|
298 |
|
299 |
/**
|
300 |
* Display extension menu and submenu items in the correct interface. For single
|
@@ -302,16 +307,16 @@ if ( defined( 'SUCURISCAN' ) ) {
|
|
302 |
* multisite installations the menu items must be available only in the network
|
303 |
* panel and hidden in the administration panel of the subsites.
|
304 |
*/
|
305 |
-
add_action(
|
306 |
|
307 |
/**
|
308 |
* Attach Ajax requests to a custom page handler.
|
309 |
*/
|
310 |
-
foreach (
|
311 |
$ajax_func = $page_func . '_ajax';
|
312 |
|
313 |
-
if (
|
314 |
-
add_action(
|
315 |
}
|
316 |
}
|
317 |
|
@@ -325,7 +330,7 @@ if ( defined( 'SUCURISCAN' ) ) {
|
|
325 |
*
|
326 |
* @see Class SucuriScanHook
|
327 |
*/
|
328 |
-
if (
|
329 |
$sucuriscan_hooks = array(
|
330 |
'add_attachment',
|
331 |
'add_link',
|
@@ -347,19 +352,19 @@ if ( defined( 'SUCURISCAN' ) ) {
|
|
347 |
'xmlrpc_publish_post',
|
348 |
);
|
349 |
|
350 |
-
if (
|
351 |
$sucuriscan_hooks[] = 'all';
|
352 |
}
|
353 |
|
354 |
-
foreach (
|
355 |
$hook_func = 'SucuriScanHook::hook_' . $hook_name;
|
356 |
-
add_action(
|
357 |
}
|
358 |
|
359 |
-
add_action(
|
360 |
-
add_action(
|
361 |
} else {
|
362 |
-
SucuriScanInterface::error(
|
363 |
}
|
364 |
|
365 |
/**
|
@@ -371,7 +376,7 @@ if ( defined( 'SUCURISCAN' ) ) {
|
|
371 |
* the plugin to execute the filesystem scans, the project integrity, and the
|
372 |
* email notifications.
|
373 |
*/
|
374 |
-
add_action(
|
375 |
|
376 |
/**
|
377 |
* Heartbeat API
|
@@ -382,12 +387,12 @@ if ( defined( 'SUCURISCAN' ) ) {
|
|
382 |
* cases it may improve the performance of the site by reducing the quantity of
|
383 |
* requests sent to the server per session.
|
384 |
*/
|
385 |
-
add_filter(
|
386 |
-
add_filter(
|
387 |
-
add_filter(
|
388 |
-
add_filter(
|
389 |
-
add_filter(
|
390 |
-
add_filter(
|
391 |
}
|
392 |
|
393 |
/**
|
@@ -397,12 +402,13 @@ if ( defined( 'SUCURISCAN' ) ) {
|
|
397 |
* other libraries extending from this and functions defined in other files, be
|
398 |
* aware of the hierarchy and check the other libraries for duplicated methods.
|
399 |
*/
|
400 |
-
class SucuriScan
|
401 |
-
|
402 |
/**
|
403 |
* Class constructor.
|
404 |
*/
|
405 |
-
public function __construct()
|
|
|
406 |
}
|
407 |
|
408 |
/**
|
@@ -416,9 +422,14 @@ class SucuriScan {
|
|
416 |
* @param string $var_name Name of a variable with an optional colon at the beginning.
|
417 |
* @return string Full name of the variable with the extra characters (if needed).
|
418 |
*/
|
419 |
-
public static function variable_prefix(
|
420 |
-
|
421 |
-
|
|
|
|
|
|
|
|
|
|
|
422 |
}
|
423 |
|
424 |
return $var_name;
|
@@ -430,27 +441,31 @@ class SucuriScan {
|
|
430 |
* @param string $property The configuration option name.
|
431 |
* @return string Value of the configuration option as a string on success.
|
432 |
*/
|
433 |
-
public static function ini_get(
|
434 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
435 |
|
436 |
-
if (
|
437 |
$ini_value = 'Undefined';
|
438 |
-
} elseif (
|
439 |
-
$
|
440 |
-
|
441 |
-
|
442 |
-
|
443 |
-
case 'safe_mode': $ini_value = 'Off'; break;
|
444 |
-
case 'memory_limit': $ini_value = '128M'; break;
|
445 |
-
case 'upload_max_filesize': $ini_value = '2M'; break;
|
446 |
-
case 'post_max_size': $ini_value = '8M'; break;
|
447 |
-
case 'max_execution_time': $ini_value = '30'; break;
|
448 |
-
case 'max_input_time': $ini_value = '-1'; break;
|
449 |
}
|
450 |
}
|
451 |
|
452 |
-
if (
|
453 |
-
$ini_value = basename(
|
454 |
}
|
455 |
|
456 |
return $ini_value;
|
@@ -463,12 +478,13 @@ class SucuriScan {
|
|
463 |
* @param string $text The text which is to be encoded.
|
464 |
* @return string The encoded text with HTML entities.
|
465 |
*/
|
466 |
-
public static function escape(
|
|
|
467 |
// Escape the value of the variable using a built-in function if possible.
|
468 |
-
if (
|
469 |
-
$text = esc_attr(
|
470 |
} else {
|
471 |
-
$text = htmlspecialchars(
|
472 |
}
|
473 |
|
474 |
return $text;
|
@@ -480,12 +496,18 @@ class SucuriScan {
|
|
480 |
* @param integer $length Length of the string that will be generated.
|
481 |
* @return string The random string generated.
|
482 |
*/
|
483 |
-
public static function random_char(
|
|
|
484 |
$string = '';
|
485 |
-
$
|
|
|
|
|
|
|
|
|
486 |
|
487 |
-
for (
|
488 |
-
$
|
|
|
489 |
}
|
490 |
|
491 |
return $string;
|
@@ -495,15 +517,16 @@ class SucuriScan {
|
|
495 |
* Translate a given number in bytes to a human readable file size using the
|
496 |
* a approximate value in Kylo, Mega, Giga, etc.
|
497 |
*
|
498 |
-
* @link
|
499 |
* @param integer $bytes An integer representing a file size in bytes.
|
500 |
* @param integer $decimals How many decimals should be returned after the translation.
|
501 |
* @return string Human readable representation of the given number in Kylo, Mega, Giga, etc.
|
502 |
*/
|
503 |
-
public static function human_filesize(
|
|
|
504 |
$sz = 'BKMGTP';
|
505 |
-
$factor = floor(
|
506 |
-
return sprintf(
|
507 |
}
|
508 |
|
509 |
/**
|
@@ -513,38 +536,37 @@ class SucuriScan {
|
|
513 |
* @param string $path The relative path that needs to be completed to get the absolute path.
|
514 |
* @return string The full filesystem path including the directory specified.
|
515 |
*/
|
516 |
-
public static function datastore_folder_path(
|
517 |
-
|
518 |
-
$
|
|
|
519 |
|
520 |
// Use the uploads folder by default.
|
521 |
-
if (
|
522 |
$uploads_path = false;
|
523 |
|
524 |
// Multisite installations may have different paths.
|
525 |
-
if (
|
526 |
$upload_dir = wp_upload_dir();
|
527 |
|
528 |
-
if (
|
529 |
-
$uploads_path = rtrim(
|
530 |
}
|
531 |
}
|
532 |
|
533 |
-
if (
|
534 |
-
if (
|
535 |
-
$uploads_path =
|
536 |
} else {
|
537 |
-
$uploads_path =
|
538 |
}
|
539 |
}
|
540 |
|
541 |
-
$
|
542 |
-
SucuriScanOption::update_option(
|
543 |
}
|
544 |
|
545 |
-
|
546 |
-
|
547 |
-
return $wp_filepath;
|
548 |
}
|
549 |
|
550 |
/**
|
@@ -552,15 +574,18 @@ class SucuriScan {
|
|
552 |
*
|
553 |
* @return boolean Either TRUE or FALSE in case WordPress is being used as a multi-site instance.
|
554 |
*/
|
555 |
-
public static function is_multisite()
|
556 |
-
|
557 |
-
|
558 |
-
|
559 |
-
) {
|
560 |
-
return true;
|
561 |
-
}
|
562 |
|
563 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
564 |
}
|
565 |
|
566 |
/**
|
@@ -568,22 +593,23 @@ class SucuriScan {
|
|
568 |
*
|
569 |
* @return string The version number of Wordpress installed.
|
570 |
*/
|
571 |
-
public static function site_version()
|
|
|
572 |
global $wp_version;
|
573 |
|
574 |
-
if (
|
575 |
$wp_version_path = ABSPATH . WPINC . '/version.php';
|
576 |
|
577 |
-
if (
|
578 |
include($wp_version_path);
|
579 |
$wp_version = isset($wp_version) ? $wp_version : '0.0';
|
580 |
} else {
|
581 |
-
$option_version = get_option(
|
582 |
$wp_version = $option_version ? $option_version : '0.0';
|
583 |
}
|
584 |
}
|
585 |
|
586 |
-
$wp_version = self::escape(
|
587 |
|
588 |
return $wp_version;
|
589 |
}
|
@@ -593,19 +619,20 @@ class SucuriScan {
|
|
593 |
*
|
594 |
* @return string Absolute path of the WordPress configuration file.
|
595 |
*/
|
596 |
-
public static function get_wpconfig_path()
|
597 |
-
|
|
|
598 |
$file_path = ABSPATH . '/wp-config.php';
|
599 |
|
600 |
// if wp-config.php doesn't exist, or is not readable check one directory up.
|
601 |
-
if (
|
602 |
$file_path = ABSPATH . '/../wp-config.php';
|
603 |
}
|
604 |
|
605 |
// Remove duplicated double slashes.
|
606 |
-
$file_path = @realpath(
|
607 |
|
608 |
-
if (
|
609 |
return $file_path;
|
610 |
}
|
611 |
}
|
@@ -618,18 +645,19 @@ class SucuriScan {
|
|
618 |
*
|
619 |
* @return string Absolute path of the main WordPress htaccess file.
|
620 |
*/
|
621 |
-
public static function get_htaccess_path()
|
622 |
-
|
|
|
623 |
$base_dirs = array(
|
624 |
-
rtrim(
|
625 |
-
dirname(
|
626 |
-
dirname(
|
627 |
);
|
628 |
|
629 |
-
foreach (
|
630 |
-
$htaccess_path = sprintf(
|
631 |
|
632 |
-
if (
|
633 |
return $htaccess_path;
|
634 |
}
|
635 |
}
|
@@ -643,7 +671,8 @@ class SucuriScan {
|
|
643 |
*
|
644 |
* @return string Secret key definition pattern.
|
645 |
*/
|
646 |
-
public static function secret_key_pattern()
|
|
|
647 |
return '/define\(\s*\'([A-Z_]+)\',(\s*)\'(.+)\'\s*\);/';
|
648 |
}
|
649 |
|
@@ -652,57 +681,106 @@ class SucuriScan {
|
|
652 |
*
|
653 |
* @return void
|
654 |
*/
|
655 |
-
public static function run_scheduled_task()
|
|
|
656 |
SucuriScanEvent::filesystem_scan();
|
657 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
658 |
}
|
659 |
|
660 |
/**
|
661 |
* Retrieve the real ip address of the user in the current request.
|
662 |
*
|
663 |
-
* @param boolean $
|
664 |
-
* @return string
|
665 |
*/
|
666 |
-
public static function get_remote_addr(
|
667 |
-
|
|
|
668 |
$header_used = 'unknown';
|
|
|
669 |
|
670 |
-
|
671 |
-
|
672 |
-
|
673 |
-
|
674 |
-
|
675 |
-
|
676 |
-
|
677 |
-
'HTTP_CLIENT_IP',
|
678 |
-
'HTTP_X_FORWARDED_FOR',
|
679 |
-
'HTTP_X_FORWARDED',
|
680 |
-
'HTTP_FORWARDED_FOR',
|
681 |
-
'HTTP_FORWARDED',
|
682 |
-
'SUCURI_RIP',
|
683 |
-
'REMOTE_ADDR',
|
684 |
-
);
|
685 |
-
|
686 |
-
foreach ( $alternatives as $alternative ) {
|
687 |
-
if (
|
688 |
-
isset($_SERVER[ $alternative ])
|
689 |
-
&& self::is_valid_ip( $_SERVER[ $alternative ] )
|
690 |
-
) {
|
691 |
-
$remote_addr = $_SERVER[ $alternative ];
|
692 |
-
$header_used = $alternative;
|
693 |
-
break;
|
694 |
-
}
|
695 |
}
|
696 |
-
} elseif ( isset($_SERVER['REMOTE_ADDR']) ) {
|
697 |
-
$remote_addr = $_SERVER['REMOTE_ADDR'];
|
698 |
-
$header_used = 'REMOTE_ADDR';
|
699 |
}
|
700 |
|
701 |
-
if ( $remote_addr
|
702 |
$remote_addr = '127.0.0.1';
|
703 |
}
|
704 |
|
705 |
-
if (
|
706 |
return $header_used;
|
707 |
}
|
708 |
|
@@ -714,8 +792,9 @@ class SucuriScan {
|
|
714 |
*
|
715 |
* @return string The HTTP header used to retrieve the remote address.
|
716 |
*/
|
717 |
-
public static function get_remote_addr_header()
|
718 |
-
|
|
|
719 |
}
|
720 |
|
721 |
/**
|
@@ -723,9 +802,10 @@ class SucuriScan {
|
|
723 |
*
|
724 |
* @return string The user-agent from the current request.
|
725 |
*/
|
726 |
-
public static function get_user_agent()
|
727 |
-
|
728 |
-
|
|
|
729 |
}
|
730 |
|
731 |
return false;
|
@@ -736,12 +816,13 @@ class SucuriScan {
|
|
736 |
*
|
737 |
* @return string The domain of the current site.
|
738 |
*/
|
739 |
-
public static function get_domain(
|
740 |
-
|
|
|
741 |
$site_url = get_site_url();
|
742 |
$pattern = '/([fhtps]+:\/\/)?([^:\/]+)(:[0-9:]+)?(\/.*)?/';
|
743 |
$replacement = ( $return_tld === true ) ? '$2' : '$2$3$4';
|
744 |
-
$domain_name = @preg_replace(
|
745 |
|
746 |
return $domain_name;
|
747 |
}
|
@@ -754,8 +835,9 @@ class SucuriScan {
|
|
754 |
*
|
755 |
* @return string Top-level domain (TLD) of the website.
|
756 |
*/
|
757 |
-
public static function get_top_level_domain()
|
758 |
-
|
|
|
759 |
}
|
760 |
|
761 |
/**
|
@@ -763,8 +845,9 @@ class SucuriScan {
|
|
763 |
*
|
764 |
* @return boolean TRUE if reverse proxies must be supported, FALSE otherwise.
|
765 |
*/
|
766 |
-
public static function support_reverse_proxy()
|
767 |
-
|
|
|
768 |
}
|
769 |
|
770 |
/**
|
@@ -778,10 +861,10 @@ class SucuriScan {
|
|
778 |
*
|
779 |
* @return boolean True if the DNS lookups should be executed, false otherwise.
|
780 |
*/
|
781 |
-
public static function execute_dns_lookups()
|
782 |
-
|
783 |
-
|
784 |
-
|| SucuriScanOption::is_disabled(
|
785 |
) {
|
786 |
return false;
|
787 |
}
|
@@ -795,13 +878,14 @@ class SucuriScan {
|
|
795 |
* @param boolean $verbose Return an array with the hostname, address, and status, or not.
|
796 |
* @return boolean Either TRUE or FALSE if the site is behind CloudProxy.
|
797 |
*/
|
798 |
-
public static function is_behind_cloudproxy(
|
|
|
799 |
$http_host = self::get_top_level_domain();
|
800 |
|
801 |
-
if (
|
802 |
-
$host_by_addr = @gethostbyname(
|
803 |
-
$host_by_name = @gethostbyaddr(
|
804 |
-
$status = (bool) preg_match(
|
805 |
} else {
|
806 |
$status = false;
|
807 |
$host_by_addr = '::1';
|
@@ -813,14 +897,13 @@ class SucuriScan {
|
|
813 |
* the site as protected by a firewall. A fake key can be used to bypass the DNS
|
814 |
* checking, but that is not something that will affect us, only the client.
|
815 |
*/
|
816 |
-
if (
|
817 |
-
|
818 |
-
&& SucuriScanAPI::get_cloudproxy_key()
|
819 |
) {
|
820 |
$status = true;
|
821 |
}
|
822 |
|
823 |
-
if (
|
824 |
return array(
|
825 |
'http_host' => $http_host,
|
826 |
'host_name' => $host_by_name,
|
@@ -839,10 +922,11 @@ class SucuriScan {
|
|
839 |
*
|
840 |
* @return string The administrator email address.
|
841 |
*/
|
842 |
-
public static function get_site_email()
|
843 |
-
|
|
|
844 |
|
845 |
-
if (
|
846 |
return $email;
|
847 |
}
|
848 |
|
@@ -855,11 +939,12 @@ class SucuriScan {
|
|
855 |
* @param integer $identifier User account identifier.
|
856 |
* @return object WordPress user object with data.
|
857 |
*/
|
858 |
-
public static function get_user_by_id(
|
859 |
-
|
860 |
-
|
|
|
861 |
|
862 |
-
if (
|
863 |
return $user;
|
864 |
}
|
865 |
}
|
@@ -872,11 +957,12 @@ class SucuriScan {
|
|
872 |
*
|
873 |
* @return array List of admin users, false otherwise.
|
874 |
*/
|
875 |
-
public static function get_admin_users()
|
876 |
-
|
|
|
877 |
$args = array( 'role' => 'administrator' );
|
878 |
|
879 |
-
return get_users(
|
880 |
}
|
881 |
|
882 |
return false;
|
@@ -892,13 +978,14 @@ class SucuriScan {
|
|
892 |
*
|
893 |
* @return array List of user identifiers and email addresses.
|
894 |
*/
|
895 |
-
public static function get_users_for_api_key()
|
|
|
896 |
$valid_users = array();
|
897 |
$users = self::get_admin_users();
|
898 |
|
899 |
-
if (
|
900 |
-
foreach (
|
901 |
-
if (
|
902 |
$valid_users[ $user->ID ] = sprintf(
|
903 |
'%s - %s',
|
904 |
$user->user_login,
|
@@ -916,9 +1003,10 @@ class SucuriScan {
|
|
916 |
*
|
917 |
* @return integer Return current Unix timestamp.
|
918 |
*/
|
919 |
-
public static function local_time()
|
920 |
-
|
921 |
-
|
|
|
922 |
} else {
|
923 |
return time();
|
924 |
}
|
@@ -934,7 +1022,8 @@ class SucuriScan {
|
|
934 |
* @param integer $timestamp Unix timestamp.
|
935 |
* @return string The date, translated if locale specifies it.
|
936 |
*/
|
937 |
-
public static function datetime($timestamp = null)
|
|
|
938 |
$date_format = get_option('date_format');
|
939 |
$time_format = get_option('time_format');
|
940 |
$tz_format = sprintf('%s %s', $date_format, $time_format);
|
@@ -951,7 +1040,8 @@ class SucuriScan {
|
|
951 |
*
|
952 |
* @return string The date, translated if locale specifies it.
|
953 |
*/
|
954 |
-
public static function current_datetime()
|
|
|
955 |
return self::datetime();
|
956 |
}
|
957 |
|
@@ -961,15 +1051,16 @@ class SucuriScan {
|
|
961 |
* @param integer $timestamp The Unix time number of the date/time before now.
|
962 |
* @return string The time passed since the timestamp specified.
|
963 |
*/
|
964 |
-
public static function time_ago(
|
965 |
-
|
966 |
-
|
|
|
967 |
}
|
968 |
|
969 |
$local_time = self::local_time();
|
970 |
-
$diff = abs(
|
971 |
|
972 |
-
if (
|
973 |
return 'just now';
|
974 |
}
|
975 |
|
@@ -983,7 +1074,7 @@ class SucuriScan {
|
|
983 |
$diff < 60 => array( 'second', 1, ),
|
984 |
);
|
985 |
|
986 |
-
$value = floor(
|
987 |
$time_ago = sprintf(
|
988 |
'%s %s%s ago',
|
989 |
$value,
|
@@ -997,15 +1088,16 @@ class SucuriScan {
|
|
997 |
/**
|
998 |
* Convert an string of characters into a valid variable name.
|
999 |
*
|
1000 |
-
* @see
|
1001 |
*
|
1002 |
* @param string $text A text containing alpha-numeric and special characters.
|
1003 |
* @return string A valid variable name.
|
1004 |
*/
|
1005 |
-
public static function human2var(
|
1006 |
-
|
|
|
1007 |
$pattern = '/[^a-z0-9_]/';
|
1008 |
-
$var_name = preg_replace(
|
1009 |
|
1010 |
return $var_name;
|
1011 |
}
|
@@ -1016,8 +1108,9 @@ class SucuriScan {
|
|
1016 |
* @param string $data The data that will be checked.
|
1017 |
* @return boolean TRUE if the data was serialized, FALSE otherwise.
|
1018 |
*/
|
1019 |
-
public static function is_serialized(
|
1020 |
-
|
|
|
1021 |
}
|
1022 |
|
1023 |
/**
|
@@ -1026,15 +1119,16 @@ class SucuriScan {
|
|
1026 |
* @param string $remote_addr The host IP address.
|
1027 |
* @return boolean Whether the IP address specified is valid or not.
|
1028 |
*/
|
1029 |
-
public static function is_valid_ip(
|
1030 |
-
|
1031 |
-
|
1032 |
-
|
|
|
1033 |
$pattern = '/^([0-9]{1,3}\.) {3}[0-9]{1,3}$/';
|
1034 |
|
1035 |
-
if (
|
1036 |
-
for (
|
1037 |
-
if (
|
1038 |
return false;
|
1039 |
}
|
1040 |
}
|
@@ -1053,9 +1147,10 @@ class SucuriScan {
|
|
1053 |
* @param string $remote_addr The supposed ip address that will be checked.
|
1054 |
* @return boolean Either TRUE or FALSE if the ip address specified is valid or not.
|
1055 |
*/
|
1056 |
-
public static function is_valid_cidr(
|
1057 |
-
|
1058 |
-
|
|
|
1059 |
return true;
|
1060 |
}
|
1061 |
}
|
@@ -1069,13 +1164,13 @@ class SucuriScan {
|
|
1069 |
* @param string $remote_addr The supposed ip address that will be formatted.
|
1070 |
* @return array Clean address, CIDR range, and CIDR format; FALSE otherwise.
|
1071 |
*/
|
1072 |
-
public static function get_ip_info(
|
1073 |
-
|
1074 |
-
|
|
|
1075 |
|
1076 |
-
if (
|
1077 |
-
|
1078 |
-
&& self::is_valid_ip( $ip_parts[0] )
|
1079 |
) {
|
1080 |
$addr_info = array();
|
1081 |
$addr_info['remote_addr'] = $ip_parts[0];
|
@@ -1096,17 +1191,18 @@ class SucuriScan {
|
|
1096 |
* 5.2.0 if it is not found in the interpreter this function will sue regular
|
1097 |
* expressions to check whether the email address passed is valid or not.
|
1098 |
*
|
1099 |
-
* @see
|
1100 |
*
|
1101 |
* @param string $email The string that will be validated as an email address.
|
1102 |
* @return boolean TRUE if the email address passed to the function is valid, FALSE if not.
|
1103 |
*/
|
1104 |
-
public static function is_valid_email(
|
1105 |
-
|
1106 |
-
|
|
|
1107 |
} else {
|
1108 |
$pattern = '/^([a-z0-9\+_\-]+)(\.[a-z0-9\+_\-]+)*@([a-z0-9\-]+\.)+[a-z]{2,6}$/ix';
|
1109 |
-
return (bool) preg_match(
|
1110 |
}
|
1111 |
}
|
1112 |
|
@@ -1116,58 +1212,15 @@ class SucuriScan {
|
|
1116 |
* @param string $pattern The regular expression to check.
|
1117 |
* @return boolean True if the regular expression is valid, false otherwise.
|
1118 |
*/
|
1119 |
-
public static function is_valid_pattern(
|
|
|
1120 |
return (bool) (
|
1121 |
-
is_string(
|
1122 |
-
&& !
|
1123 |
-
&& @preg_match(
|
1124 |
);
|
1125 |
}
|
1126 |
|
1127 |
-
/**
|
1128 |
-
* Return a string with all the valid email addresses.
|
1129 |
-
*
|
1130 |
-
* @param string $email The string that will be validated as an email address.
|
1131 |
-
* @param boolean $as_array TRUE to return the list of valid email addresses as an array.
|
1132 |
-
* @return string All the valid email addresses separated by a comma.
|
1133 |
-
*/
|
1134 |
-
public static function get_valid_email( $email = '', $as_array = false ){
|
1135 |
-
$valid_emails = array();
|
1136 |
-
$is_valid_string = (bool) ( is_string( $email ) && ! empty($email) );
|
1137 |
-
|
1138 |
-
if (
|
1139 |
-
$is_valid_string === true
|
1140 |
-
&& strpos( $email, ',' ) !== false
|
1141 |
-
) {
|
1142 |
-
$addresses = explode( ',', $email );
|
1143 |
-
|
1144 |
-
foreach ( $addresses as $address ) {
|
1145 |
-
$address = trim( $address );
|
1146 |
-
|
1147 |
-
if ( self::is_valid_email( $address ) ) {
|
1148 |
-
$valid_emails[] = $address;
|
1149 |
-
}
|
1150 |
-
}
|
1151 |
-
} elseif (
|
1152 |
-
$is_valid_string === true
|
1153 |
-
&& self::is_valid_email( $email )
|
1154 |
-
) {
|
1155 |
-
$valid_emails[] = $email;
|
1156 |
-
}
|
1157 |
-
|
1158 |
-
if ( ! empty($valid_emails) ) {
|
1159 |
-
$valid_emails = array_unique( $valid_emails );
|
1160 |
-
|
1161 |
-
if ( $as_array === true ) {
|
1162 |
-
return $valid_emails;
|
1163 |
-
}
|
1164 |
-
|
1165 |
-
return self::implode( ', ', $valid_emails );
|
1166 |
-
}
|
1167 |
-
|
1168 |
-
return false;
|
1169 |
-
}
|
1170 |
-
|
1171 |
/**
|
1172 |
* Cut a long text to the length specified, and append suspensive points at the end.
|
1173 |
*
|
@@ -1175,11 +1228,12 @@ class SucuriScan {
|
|
1175 |
* @param integer $length Maximum length of the returned string, default is 10.
|
1176 |
* @return string Short version of the text specified.
|
1177 |
*/
|
1178 |
-
public static function excerpt(
|
1179 |
-
|
|
|
1180 |
|
1181 |
-
if (
|
1182 |
-
return substr(
|
1183 |
}
|
1184 |
|
1185 |
return $text;
|
@@ -1192,10 +1246,11 @@ class SucuriScan {
|
|
1192 |
* @param integer $length Maximum length of the returned string, default is 10.
|
1193 |
* @return string Short version of the text specified.
|
1194 |
*/
|
1195 |
-
public static function excerpt_rev(
|
1196 |
-
|
1197 |
-
$
|
1198 |
-
$
|
|
|
1199 |
|
1200 |
return $text_transformed;
|
1201 |
}
|
@@ -1206,10 +1261,11 @@ class SucuriScan {
|
|
1206 |
* @param array $list An array or multidimensional array of different values.
|
1207 |
* @return boolean TRUE if the list is multidimensional, FALSE otherwise.
|
1208 |
*/
|
1209 |
-
public static function is_multi_list(
|
1210 |
-
|
1211 |
-
|
1212 |
-
|
|
|
1213 |
return true;
|
1214 |
}
|
1215 |
}
|
@@ -1225,19 +1281,20 @@ class SucuriScan {
|
|
1225 |
* @param array $list The array of strings to implode.
|
1226 |
* @return string String of all the items in the list, with the separator between them.
|
1227 |
*/
|
1228 |
-
public static function implode(
|
1229 |
-
|
|
|
1230 |
$pieces = array();
|
1231 |
|
1232 |
-
foreach (
|
1233 |
-
$pieces[] = @implode(
|
1234 |
}
|
1235 |
|
1236 |
-
$joined_pieces = '(' . implode(
|
1237 |
|
1238 |
return $joined_pieces;
|
1239 |
} else {
|
1240 |
-
return implode(
|
1241 |
}
|
1242 |
}
|
1243 |
|
@@ -1247,19 +1304,19 @@ class SucuriScan {
|
|
1247 |
* @param string $current_page Identifier of the current page.
|
1248 |
* @return boolean TRUE if the current page must not have noticies.
|
1249 |
*/
|
1250 |
-
public static function no_notices_here(
|
|
|
1251 |
global $sucuriscan_no_notices_in;
|
1252 |
|
1253 |
-
if (
|
1254 |
-
$current_page = SucuriScanRequest::get(
|
1255 |
}
|
1256 |
|
1257 |
-
if (
|
1258 |
-
|
1259 |
-
&&
|
1260 |
-
&& ! empty($sucuriscan_no_notices_in)
|
1261 |
) {
|
1262 |
-
return (bool) in_array(
|
1263 |
}
|
1264 |
|
1265 |
return false;
|
@@ -1270,8 +1327,9 @@ class SucuriScan {
|
|
1270 |
*
|
1271 |
* @return boolean TRUE if the site is running over Nginx, FALSE otherwise.
|
1272 |
*/
|
1273 |
-
public static function is_nginx_server()
|
1274 |
-
|
|
|
1275 |
}
|
1276 |
|
1277 |
/**
|
@@ -1279,10 +1337,10 @@ class SucuriScan {
|
|
1279 |
*
|
1280 |
* @return boolean TRUE if the site is running over Nginx, FALSE otherwise.
|
1281 |
*/
|
1282 |
-
public static function is_iis_server()
|
1283 |
-
|
|
|
1284 |
}
|
1285 |
-
|
1286 |
}
|
1287 |
|
1288 |
/**
|
@@ -1293,7 +1351,8 @@ class SucuriScan {
|
|
1293 |
* these methods at most instead of accessing an index in the global PHP
|
1294 |
* variables _POST, _GET, _REQUEST since they may come with insecure data.
|
1295 |
*/
|
1296 |
-
class SucuriScanRequest extends SucuriScan
|
|
|
1297 |
|
1298 |
/**
|
1299 |
* Returns the value stored in a specific index in the global _GET, _POST or
|
@@ -1305,38 +1364,48 @@ class SucuriScanRequest extends SucuriScan {
|
|
1305 |
* @param string $pattern Optional pattern to match allowed values in the requested key.
|
1306 |
* @return string The value stored in the specified key inside the global _GET variable.
|
1307 |
*/
|
1308 |
-
public static function request(
|
1309 |
-
|
|
|
1310 |
|
1311 |
-
if (
|
1312 |
-
|
1313 |
-
&& is_string( $key )
|
1314 |
&& isset($list[ $key ])
|
1315 |
) {
|
1316 |
// Select the key from the list and escape its content.
|
1317 |
$key_value = $list[ $key ];
|
1318 |
|
1319 |
// Define regular expressions for specific value types.
|
1320 |
-
if (
|
1321 |
$pattern = '/.*/';
|
1322 |
} else {
|
1323 |
-
switch (
|
1324 |
-
case '_nonce':
|
1325 |
-
|
1326 |
-
|
1327 |
-
case '
|
1328 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1329 |
}
|
1330 |
}
|
1331 |
|
1332 |
// If the request data is an array, then only cast the value.
|
1333 |
-
if (
|
1334 |
return (array) $key_value;
|
1335 |
}
|
1336 |
|
1337 |
// Check the format of the request data with a regex defined above.
|
1338 |
-
if (
|
1339 |
-
return self::escape(
|
1340 |
}
|
1341 |
}
|
1342 |
|
@@ -1351,8 +1420,9 @@ class SucuriScanRequest extends SucuriScan {
|
|
1351 |
* @param string $pattern Optional pattern to match allowed values in the requested key.
|
1352 |
* @return string The value stored in the specified key inside the global _GET variable.
|
1353 |
*/
|
1354 |
-
public static function get(
|
1355 |
-
|
|
|
1356 |
}
|
1357 |
|
1358 |
/**
|
@@ -1363,8 +1433,9 @@ class SucuriScanRequest extends SucuriScan {
|
|
1363 |
* @param string $pattern Optional pattern to match allowed values in the requested key.
|
1364 |
* @return string The value stored in the specified key inside the global _POST variable.
|
1365 |
*/
|
1366 |
-
public static function post(
|
1367 |
-
|
|
|
1368 |
}
|
1369 |
|
1370 |
/**
|
@@ -1375,10 +1446,10 @@ class SucuriScanRequest extends SucuriScan {
|
|
1375 |
* @param string $pattern Optional pattern to match allowed values in the requested key.
|
1376 |
* @return string The value stored in the specified key inside the global _POST variable.
|
1377 |
*/
|
1378 |
-
public static function get_or_post(
|
1379 |
-
|
|
|
1380 |
}
|
1381 |
-
|
1382 |
}
|
1383 |
|
1384 |
/**
|
@@ -1389,7 +1460,8 @@ class SucuriScanRequest extends SucuriScan {
|
|
1389 |
* offers a high-level object oriented interface to information for an individual
|
1390 |
* file.
|
1391 |
*/
|
1392 |
-
class SucuriScanFileInfo extends SucuriScan
|
|
|
1393 |
|
1394 |
/**
|
1395 |
* Define the interface that will be used to execute the file system scans, the
|
@@ -1451,7 +1523,8 @@ class SucuriScanFileInfo extends SucuriScan {
|
|
1451 |
/**
|
1452 |
* Class constructor.
|
1453 |
*/
|
1454 |
-
public function __construct()
|
|
|
1455 |
}
|
1456 |
|
1457 |
/**
|
@@ -1464,38 +1537,39 @@ class SucuriScanFileInfo extends SucuriScan {
|
|
1464 |
* @param boolean $as_array Whether the result of the operation will be returned as an array or string.
|
1465 |
* @return array List of files in the main and subdirectories of the folder specified.
|
1466 |
*/
|
1467 |
-
public function get_directory_tree_md5(
|
|
|
1468 |
$project_signatures = '';
|
1469 |
-
$abs_path = rtrim(
|
1470 |
-
$files = $this->get_directory_tree(
|
1471 |
|
1472 |
-
if (
|
1473 |
$project_signatures = array();
|
1474 |
}
|
1475 |
|
1476 |
-
if (
|
1477 |
-
sort(
|
1478 |
|
1479 |
-
foreach (
|
1480 |
-
$file_checksum = @md5_file(
|
1481 |
-
$filesize = @filesize(
|
1482 |
|
1483 |
-
if (
|
1484 |
-
$basename = str_replace(
|
1485 |
$project_signatures[ $basename ] = array(
|
1486 |
'filepath' => $filepath,
|
1487 |
'checksum' => $file_checksum,
|
1488 |
'filesize' => $filesize,
|
1489 |
-
'created_at' => @filectime(
|
1490 |
-
'modified_at' => @filemtime(
|
1491 |
);
|
1492 |
} else {
|
1493 |
-
$filepath = str_replace(
|
1494 |
$project_signatures .= sprintf(
|
1495 |
"%s%s%s%s\n",
|
1496 |
$file_checksum,
|
1497 |
$filesize,
|
1498 |
-
chr(
|
1499 |
$filepath
|
1500 |
);
|
1501 |
}
|
@@ -1513,37 +1587,38 @@ class SucuriScanFileInfo extends SucuriScan {
|
|
1513 |
* @param string $directory Parent directory where the filesystem scan will start.
|
1514 |
* @return array List of files in the main and subdirectories of the folder specified.
|
1515 |
*/
|
1516 |
-
public function get_directory_tree(
|
1517 |
-
|
|
|
1518 |
$tree = array();
|
1519 |
|
1520 |
// Check whether the ignore scanning feature is enabled or not.
|
1521 |
-
if (
|
1522 |
$this->ignored_directories = SucuriScanFSScanner::get_ignored_directories();
|
1523 |
}
|
1524 |
|
1525 |
-
switch (
|
1526 |
case 'spl':
|
1527 |
-
if (
|
1528 |
-
$tree = $this->get_directory_tree_with_spl(
|
1529 |
} else {
|
1530 |
$this->scan_interface = 'opendir';
|
1531 |
-
SucuriScanOption::update_option(
|
1532 |
-
$tree = $this->get_directory_tree(
|
1533 |
}
|
1534 |
break;
|
1535 |
|
1536 |
case 'glob':
|
1537 |
-
$tree = $this->get_directory_tree_with_glob(
|
1538 |
break;
|
1539 |
|
1540 |
case 'opendir':
|
1541 |
-
$tree = $this->get_directory_tree_with_opendir(
|
1542 |
break;
|
1543 |
|
1544 |
default:
|
1545 |
$this->scan_interface = 'spl';
|
1546 |
-
$tree = $this->get_directory_tree(
|
1547 |
break;
|
1548 |
}
|
1549 |
|
@@ -1560,21 +1635,21 @@ class SucuriScanFileInfo extends SucuriScan {
|
|
1560 |
* @param string $directory Directory where the scanner is located at the moment.
|
1561 |
* @return array List of file paths where the file was found.
|
1562 |
*/
|
1563 |
-
public function find_file(
|
|
|
1564 |
$file_paths = array();
|
1565 |
|
1566 |
-
if (
|
1567 |
-
|
1568 |
-
&& defined( 'ABSPATH' )
|
1569 |
) {
|
1570 |
$directory = ABSPATH;
|
1571 |
}
|
1572 |
|
1573 |
-
if (
|
1574 |
-
$dir_tree = $this->get_directory_tree(
|
1575 |
|
1576 |
-
foreach (
|
1577 |
-
if (
|
1578 |
$file_paths[] = $filepath;
|
1579 |
}
|
1580 |
}
|
@@ -1588,12 +1663,13 @@ class SucuriScanFileInfo extends SucuriScan {
|
|
1588 |
* or not, it is required to have PHP >= 5.1.0. The SplFileObject class offers
|
1589 |
* an object oriented interface for a file.
|
1590 |
*
|
1591 |
-
* @link
|
1592 |
*
|
1593 |
* @return boolean Whether the PHP class "SplFileObject" is available or not.
|
1594 |
*/
|
1595 |
-
public static function is_spl_available()
|
1596 |
-
|
|
|
1597 |
}
|
1598 |
|
1599 |
/**
|
@@ -1601,7 +1677,7 @@ class SucuriScanFileInfo extends SucuriScan {
|
|
1601 |
* of the folder specified. Some folders and files will be ignored depending
|
1602 |
* on some rules defined by the developer.
|
1603 |
*
|
1604 |
-
* @link
|
1605 |
* @see RecursiveDirectoryIterator extends FilesystemIterator
|
1606 |
* @see FilesystemIterator extends DirectoryIterator
|
1607 |
* @see DirectoryIterator extends SplFileInfo
|
@@ -1610,47 +1686,47 @@ class SucuriScanFileInfo extends SucuriScan {
|
|
1610 |
* @param string $directory Parent directory where the filesystem scan will start.
|
1611 |
* @return array List of files in the main and subdirectories of the folder specified.
|
1612 |
*/
|
1613 |
-
private function get_directory_tree_with_spl(
|
|
|
1614 |
$files = array();
|
1615 |
-
$filepath = @realpath(
|
1616 |
$objects = array();
|
1617 |
|
1618 |
// Exception for directory name must not be empty.
|
1619 |
-
if (
|
1620 |
return $files;
|
1621 |
}
|
1622 |
|
1623 |
-
if (
|
1624 |
$this->scan_interface = 'opendir';
|
1625 |
-
SucuriScanOption::update_option(
|
1626 |
-
$alternative_tree = $this->get_directory_tree(
|
1627 |
|
1628 |
return $alternative_tree;
|
1629 |
}
|
1630 |
|
1631 |
try {
|
1632 |
-
if (
|
1633 |
$flags = FilesystemIterator::KEY_AS_PATHNAME
|
1634 |
| FilesystemIterator::CURRENT_AS_FILEINFO
|
1635 |
| FilesystemIterator::SKIP_DOTS
|
1636 |
| FilesystemIterator::UNIX_PATHS;
|
1637 |
$objects = new RecursiveIteratorIterator(
|
1638 |
-
new RecursiveDirectoryIterator(
|
1639 |
RecursiveIteratorIterator::SELF_FIRST,
|
1640 |
RecursiveIteratorIterator::CATCH_GET_CHILD
|
1641 |
);
|
1642 |
} else {
|
1643 |
-
$objects = new DirectoryIterator(
|
1644 |
}
|
1645 |
-
} catch (
|
1646 |
-
SucuriScanEvent::report_exception(
|
1647 |
}
|
1648 |
|
1649 |
-
foreach (
|
1650 |
$filename = $fileinfo->getFilename();
|
1651 |
|
1652 |
-
if (
|
1653 |
-
$this->ignore_folderpath( null, $filename )
|
1654 |
|| (
|
1655 |
$this->skip_directories === true
|
1656 |
&& $fileinfo->isDir()
|
@@ -1659,16 +1735,15 @@ class SucuriScanFileInfo extends SucuriScan {
|
|
1659 |
continue;
|
1660 |
}
|
1661 |
|
1662 |
-
if (
|
1663 |
-
$directory = dirname(
|
1664 |
} else {
|
1665 |
$directory = $fileinfo->getPath();
|
1666 |
$filepath = $directory . '/' . $filename;
|
1667 |
}
|
1668 |
|
1669 |
-
if (
|
1670 |
-
$this->
|
1671 |
-
|| $this->ignore_filepath( $filename )
|
1672 |
) {
|
1673 |
continue;
|
1674 |
}
|
@@ -1687,31 +1762,32 @@ class SucuriScanFileInfo extends SucuriScan {
|
|
1687 |
* @param string $directory Parent directory where the filesystem scan will start.
|
1688 |
* @return array List of files in the main and subdirectories of the folder specified.
|
1689 |
*/
|
1690 |
-
private function get_directory_tree_with_glob(
|
|
|
1691 |
$files = array();
|
1692 |
-
$directory_pattern = sprintf(
|
1693 |
-
$files_found = @glob(
|
1694 |
-
|
1695 |
-
if (
|
1696 |
-
foreach (
|
1697 |
-
$filepath = @realpath(
|
1698 |
-
$directory = dirname(
|
1699 |
-
$filepath_parts = explode(
|
1700 |
-
$filename = array_pop(
|
1701 |
-
|
1702 |
-
if (
|
1703 |
-
if (
|
1704 |
continue;
|
1705 |
}
|
1706 |
|
1707 |
-
if (
|
1708 |
-
$sub_files = $this->get_directory_tree_with_glob(
|
1709 |
|
1710 |
-
if (
|
1711 |
-
$files = array_merge(
|
1712 |
}
|
1713 |
}
|
1714 |
-
} elseif (
|
1715 |
continue;
|
1716 |
} else {
|
1717 |
$files[] = $filepath;
|
@@ -1730,40 +1806,41 @@ class SucuriScanFileInfo extends SucuriScan {
|
|
1730 |
* @param string $directory Parent directory where the filesystem scan will start.
|
1731 |
* @return array List of files in the main and subdirectories of the folder specified.
|
1732 |
*/
|
1733 |
-
private function get_directory_tree_with_opendir(
|
|
|
1734 |
$files = array();
|
1735 |
-
$dh = @opendir(
|
1736 |
|
1737 |
-
if (
|
1738 |
return false;
|
1739 |
}
|
1740 |
|
1741 |
-
while (
|
1742 |
-
$filepath = @realpath(
|
1743 |
|
1744 |
-
if (
|
1745 |
continue;
|
1746 |
-
} elseif (
|
1747 |
-
if (
|
1748 |
continue;
|
1749 |
}
|
1750 |
|
1751 |
-
if (
|
1752 |
-
$sub_files = $this->get_directory_tree_with_opendir(
|
1753 |
|
1754 |
-
if (
|
1755 |
-
$files = array_merge(
|
1756 |
}
|
1757 |
}
|
1758 |
} else {
|
1759 |
-
if (
|
1760 |
continue;
|
1761 |
}
|
1762 |
$files[] = $filepath;
|
1763 |
}
|
1764 |
}
|
1765 |
|
1766 |
-
closedir(
|
1767 |
return $files;
|
1768 |
}
|
1769 |
|
@@ -1774,27 +1851,27 @@ class SucuriScanFileInfo extends SucuriScan {
|
|
1774 |
* @param string $filename Name of the folder or file being scanned at the moment.
|
1775 |
* @return boolean Either TRUE or FALSE representing that the scan should ignore this folder or not.
|
1776 |
*/
|
1777 |
-
private function ignore_folderpath(
|
|
|
1778 |
// Ignoring current and parent folders.
|
1779 |
-
if (
|
1780 |
return true;
|
1781 |
}
|
1782 |
|
1783 |
-
if (
|
1784 |
// Ignore directories based on a common regular expression.
|
1785 |
-
$filepath = @realpath(
|
1786 |
$pattern = '/\/wp-content\/(uploads|cache|backup|w3tc)/';
|
1787 |
|
1788 |
-
if (
|
1789 |
return true;
|
1790 |
}
|
1791 |
|
1792 |
// Ignore directories specified by the administrator.
|
1793 |
-
if (
|
1794 |
-
foreach (
|
1795 |
-
if (
|
1796 |
-
strpos(
|
1797 |
-
|| strpos( $filepath, $ignored_dir ) !== false
|
1798 |
) {
|
1799 |
return true;
|
1800 |
}
|
@@ -1811,32 +1888,32 @@ class SucuriScanFileInfo extends SucuriScan {
|
|
1811 |
* @param string $filename Name of the folder or file being scanned at the moment.
|
1812 |
* @return boolean Either TRUE or FALSE representing that the scan should ignore this filename or not.
|
1813 |
*/
|
1814 |
-
private function ignore_filepath(
|
1815 |
-
|
|
|
1816 |
return false;
|
1817 |
}
|
1818 |
|
1819 |
// Ignoring backup files from our clean ups.
|
1820 |
-
if (
|
1821 |
return true;
|
1822 |
}
|
1823 |
|
1824 |
// Ignore files specified by the administrator.
|
1825 |
-
if (
|
1826 |
-
foreach (
|
1827 |
-
if (
|
1828 |
return true;
|
1829 |
}
|
1830 |
}
|
1831 |
}
|
1832 |
|
1833 |
// Any file maching one of these rules WILL NOT be ignored.
|
1834 |
-
if (
|
1835 |
-
( strpos(
|
1836 |
-
( strpos(
|
1837 |
-
(
|
1838 |
-
( strcmp(
|
1839 |
-
( strcmp( $filename, 'php.ini' ) == 0 )
|
1840 |
) {
|
1841 |
return false;
|
1842 |
}
|
@@ -1850,20 +1927,23 @@ class SucuriScanFileInfo extends SucuriScan {
|
|
1850 |
* @param array $dir_tree A list of files under a directory.
|
1851 |
* @return array A list of unique directory paths.
|
1852 |
*/
|
1853 |
-
public function get_diretories_only(
|
|
|
1854 |
$dirs = array();
|
1855 |
|
1856 |
-
if (
|
1857 |
-
$dir_tree = $this->get_directory_tree(
|
1858 |
}
|
1859 |
|
1860 |
-
if (
|
1861 |
-
foreach (
|
1862 |
-
$dir_path = dirname(
|
1863 |
|
1864 |
-
if (
|
1865 |
-
!
|
1866 |
-
&&
|
|
|
|
|
1867 |
) {
|
1868 |
$dirs[] = $dir_path;
|
1869 |
}
|
@@ -1883,26 +1963,26 @@ class SucuriScanFileInfo extends SucuriScan {
|
|
1883 |
* @param string $pattern Text that will be searched inside each file.
|
1884 |
* @return array Associative list with the file path and line number of the match.
|
1885 |
*/
|
1886 |
-
public function grep_pattern(
|
1887 |
-
|
1888 |
-
$
|
|
|
1889 |
$results = array();
|
1890 |
|
1891 |
-
if (
|
1892 |
-
class_exists(
|
1893 |
-
&&
|
1894 |
-
&& SucuriScan::is_valid_pattern( $pattern )
|
1895 |
) {
|
1896 |
-
foreach (
|
1897 |
try {
|
1898 |
-
$fobject = new SplFileObject(
|
1899 |
-
$fstream = new RegexIterator(
|
1900 |
|
1901 |
-
foreach (
|
1902 |
$lnumber = ( $key + 1 );
|
1903 |
-
$ltext = str_replace(
|
1904 |
-
$fpath = str_replace(
|
1905 |
-
$loutput = sprintf(
|
1906 |
$results[] = array(
|
1907 |
'file_path' => $file_path,
|
1908 |
'relative_path' => $fpath,
|
@@ -1911,8 +1991,8 @@ class SucuriScanFileInfo extends SucuriScan {
|
|
1911 |
'output' => $loutput,
|
1912 |
);
|
1913 |
}
|
1914 |
-
} catch (
|
1915 |
-
SucuriScanEvent::report_exception(
|
1916 |
}
|
1917 |
}
|
1918 |
}
|
@@ -1926,10 +2006,11 @@ class SucuriScanFileInfo extends SucuriScan {
|
|
1926 |
* @param string $directory Path of the existing directory that will be removed.
|
1927 |
* @return boolean TRUE if all the files and folder inside the directory were removed.
|
1928 |
*/
|
1929 |
-
public function remove_directory_tree(
|
1930 |
-
|
|
|
1931 |
|
1932 |
-
if (
|
1933 |
$dirs_only = array();
|
1934 |
|
1935 |
// Include the parent directory as the first entry.
|
@@ -1941,15 +2022,15 @@ class SucuriScanFileInfo extends SucuriScan {
|
|
1941 |
* were successfully deleted, this is because PHP does not allows to delete non-
|
1942 |
* empty folders.
|
1943 |
*/
|
1944 |
-
foreach (
|
1945 |
-
if (
|
1946 |
$dirs_only[] = $filepath;
|
1947 |
} else {
|
1948 |
-
@unlink(
|
1949 |
}
|
1950 |
}
|
1951 |
|
1952 |
-
if (
|
1953 |
/**
|
1954 |
* Evaluates the difference between the length of two strings.
|
1955 |
*
|
@@ -1957,18 +2038,19 @@ class SucuriScanFileInfo extends SucuriScan {
|
|
1957 |
* @param string $b Second string of characters that will be measured.
|
1958 |
* @return integer The difference in length between the two strings.
|
1959 |
*/
|
1960 |
-
function sucuriscan_strlen_diff(
|
1961 |
-
|
|
|
1962 |
}
|
1963 |
}
|
1964 |
|
1965 |
// Sort the directories by deep level in ascendant order.
|
1966 |
-
$dirs_only = array_unique(
|
1967 |
-
usort(
|
1968 |
|
1969 |
// Delete all the directories starting from the deepest level.
|
1970 |
-
foreach (
|
1971 |
-
@rmdir(
|
1972 |
}
|
1973 |
|
1974 |
return true;
|
@@ -1985,8 +2067,9 @@ class SucuriScanFileInfo extends SucuriScan {
|
|
1985 |
* @param string $filepath Path to the file.
|
1986 |
* @return array An array where each element is a line in the file.
|
1987 |
*/
|
1988 |
-
public static function file_lines(
|
1989 |
-
|
|
|
1990 |
}
|
1991 |
|
1992 |
/**
|
@@ -1999,42 +2082,43 @@ class SucuriScanFileInfo extends SucuriScan {
|
|
1999 |
* @param boolean $adaptive Whether the buffer will adapt to a specific number of bytes or not.
|
2000 |
* @return string Text contained at the end of the file.
|
2001 |
*/
|
2002 |
-
public static function tail_file(
|
2003 |
-
|
|
|
2004 |
$limit = $lines;
|
2005 |
|
2006 |
-
if (
|
2007 |
-
fseek(
|
2008 |
|
2009 |
-
if (
|
2010 |
$buffer = 64;
|
2011 |
-
} elseif (
|
2012 |
$buffer = 512;
|
2013 |
} else {
|
2014 |
$buffer = 4096;
|
2015 |
}
|
2016 |
|
2017 |
-
if (
|
2018 |
$lines -= 1;
|
2019 |
}
|
2020 |
|
2021 |
$output = '';
|
2022 |
$chunk = '';
|
2023 |
|
2024 |
-
while (
|
2025 |
-
$seek = min(
|
2026 |
-
fseek(
|
2027 |
-
$chunk = fread(
|
2028 |
$output = $chunk . $output;
|
2029 |
-
fseek(
|
2030 |
-
$lines -= substr_count(
|
2031 |
}
|
2032 |
|
2033 |
-
fclose(
|
2034 |
|
2035 |
-
$lines_arr = explode(
|
2036 |
-
$lines_count = count(
|
2037 |
-
$result = array_slice(
|
2038 |
|
2039 |
return $result;
|
2040 |
}
|
@@ -2048,10 +2132,11 @@ class SucuriScanFileInfo extends SucuriScan {
|
|
2048 |
* @param string $file_path Path to the file.
|
2049 |
* @return integer Time the file was last changed.
|
2050 |
*/
|
2051 |
-
public static function creation_time(
|
2052 |
-
|
2053 |
-
|
2054 |
-
|
|
|
2055 |
}
|
2056 |
|
2057 |
return 0;
|
@@ -2063,10 +2148,11 @@ class SucuriScanFileInfo extends SucuriScan {
|
|
2063 |
* @param string $file_path Path to the file.
|
2064 |
* @return integer Time the file was last modified.
|
2065 |
*/
|
2066 |
-
public static function modification_time(
|
2067 |
-
|
2068 |
-
|
2069 |
-
|
|
|
2070 |
}
|
2071 |
|
2072 |
return 0;
|
@@ -2078,18 +2164,18 @@ class SucuriScanFileInfo extends SucuriScan {
|
|
2078 |
* @param string $path Path to the file.
|
2079 |
* @return string Type of resource: dir, link, file.
|
2080 |
*/
|
2081 |
-
public static function get_resource_type(
|
2082 |
-
|
|
|
2083 |
return 'dir';
|
2084 |
-
} elseif (
|
2085 |
return 'link';
|
2086 |
-
} elseif (
|
2087 |
return 'file';
|
2088 |
} else {
|
2089 |
return 'unknown';
|
2090 |
}
|
2091 |
}
|
2092 |
-
|
2093 |
}
|
2094 |
|
2095 |
/**
|
@@ -2102,11 +2188,11 @@ class SucuriScanFileInfo extends SucuriScan {
|
|
2102 |
* the request. Cached data will not be stored persistently across page loads
|
2103 |
* unless of the installation of a 3party persistent caching plugin [2].
|
2104 |
*
|
2105 |
-
* [1]
|
2106 |
-
* [2]
|
2107 |
*/
|
2108 |
-
class SucuriScanCache extends SucuriScan
|
2109 |
-
|
2110 |
/**
|
2111 |
* The unique name (or identifier) of the file with the data.
|
2112 |
*
|
@@ -2145,9 +2231,10 @@ class SucuriScanCache extends SucuriScan {
|
|
2145 |
* @param string $datastore Unique name (or identifier) of the file with the data.
|
2146 |
* @return void
|
2147 |
*/
|
2148 |
-
public function __construct(
|
|
|
2149 |
$this->datastore = $datastore;
|
2150 |
-
$this->datastore_path = $this->
|
2151 |
$this->usable_datastore = (bool) $this->datastore_path;
|
2152 |
}
|
2153 |
|
@@ -2156,7 +2243,8 @@ class SucuriScanCache extends SucuriScan {
|
|
2156 |
*
|
2157 |
* @return string Default attributes for every datastore file.
|
2158 |
*/
|
2159 |
-
private function
|
|
|
2160 |
$attrs = array(
|
2161 |
'datastore' => $this->datastore,
|
2162 |
'created_on' => time(),
|
@@ -2172,21 +2260,21 @@ class SucuriScanCache extends SucuriScan {
|
|
2172 |
* @param array $finfo Rainbow table with the key names and decoded values.
|
2173 |
* @return string Default content of every datastore file.
|
2174 |
*/
|
2175 |
-
private function
|
2176 |
-
|
|
|
2177 |
$info_is_available = (bool) isset($finfo['info']);
|
2178 |
$info = "<?php\n";
|
2179 |
|
2180 |
-
foreach (
|
2181 |
-
if (
|
2182 |
-
$info_is_available
|
2183 |
&& $attr_name != 'updated_on'
|
2184 |
-
&& isset($finfo['info'][
|
2185 |
) {
|
2186 |
-
$attr_value = $finfo['info'][
|
2187 |
}
|
2188 |
|
2189 |
-
$info .= sprintf(
|
2190 |
}
|
2191 |
|
2192 |
$info .= "exit(0);\n";
|
@@ -2203,30 +2291,29 @@ class SucuriScanCache extends SucuriScan {
|
|
2203 |
* @param boolean $auto_create Automatically create the file if not exists or not.
|
2204 |
* @return string The full path where the datastore file is located, FALSE otherwise.
|
2205 |
*/
|
2206 |
-
private function
|
2207 |
-
|
|
|
2208 |
$folder_path = $this->datastore_folder_path();
|
2209 |
$file_path = $folder_path . 'sucuri-' . $this->datastore . '.php';
|
2210 |
|
2211 |
// Create the datastore parent directory.
|
2212 |
-
if (
|
2213 |
-
@mkdir(
|
2214 |
}
|
2215 |
|
2216 |
// Create the datastore file is it does not exists and the folder is writable.
|
2217 |
-
if (
|
2218 |
-
|
2219 |
-
&& is_writable( $folder_path )
|
2220 |
&& $auto_create === true
|
2221 |
) {
|
2222 |
-
@file_put_contents(
|
2223 |
}
|
2224 |
|
2225 |
// Continue the operation after an attemp to create the datastore file.
|
2226 |
-
if (
|
2227 |
-
|
2228 |
-
&&
|
2229 |
-
&& is_readable( $file_path )
|
2230 |
) {
|
2231 |
return $file_path;
|
2232 |
}
|
@@ -2243,16 +2330,13 @@ class SucuriScanCache extends SucuriScan {
|
|
2243 |
* @param string $action Either "valid", "content", or "header".
|
2244 |
* @return string Cache key pattern.
|
2245 |
*/
|
2246 |
-
private function
|
2247 |
-
|
|
|
2248 |
return '/^([0-9a-zA-Z_]+)$/';
|
2249 |
-
}
|
2250 |
-
|
2251 |
-
if ( $action == 'content' ) {
|
2252 |
return '/^([0-9a-zA-Z_]+):(.+)/';
|
2253 |
-
}
|
2254 |
-
|
2255 |
-
if ( $action == 'header' ) {
|
2256 |
return '/^\/\/ ([a-z_]+)=(.*);$/';
|
2257 |
}
|
2258 |
|
@@ -2265,8 +2349,9 @@ class SucuriScanCache extends SucuriScan {
|
|
2265 |
* @param string $key Unique name to identify the data in the datastore file.
|
2266 |
* @return boolean TRUE if the format of the key name is valid, FALSE otherwise.
|
2267 |
*/
|
2268 |
-
private function
|
2269 |
-
|
|
|
2270 |
}
|
2271 |
|
2272 |
/**
|
@@ -2275,21 +2360,20 @@ class SucuriScanCache extends SucuriScan {
|
|
2275 |
* @param array $finfo Rainbow table with the key names and decoded values.
|
2276 |
* @return boolean TRUE if the operation finished successfully, FALSE otherwise.
|
2277 |
*/
|
2278 |
-
private function
|
2279 |
-
|
|
|
2280 |
|
2281 |
-
if (
|
2282 |
-
foreach (
|
2283 |
-
if (
|
2284 |
-
$data = json_encode(
|
2285 |
-
$data_string .= sprintf(
|
2286 |
}
|
2287 |
}
|
2288 |
}
|
2289 |
|
2290 |
-
|
2291 |
-
|
2292 |
-
return (bool) $saved;
|
2293 |
}
|
2294 |
|
2295 |
/**
|
@@ -2301,25 +2385,25 @@ class SucuriScanCache extends SucuriScan {
|
|
2301 |
* @param boolean $assoc When TRUE returned objects will be converted into associative arrays.
|
2302 |
* @return array Rainbow table with the key names and decoded values.
|
2303 |
*/
|
2304 |
-
private function
|
|
|
2305 |
$data_object = array(
|
2306 |
'info' => array(),
|
2307 |
'entries' => array(),
|
2308 |
);
|
2309 |
|
2310 |
-
if (
|
2311 |
-
$data_lines = SucuriScanFileInfo::file_lines(
|
2312 |
|
2313 |
-
if (
|
2314 |
-
foreach (
|
2315 |
-
if (
|
2316 |
$data_object['info'][ $match[1] ] = $match[2];
|
2317 |
-
} elseif (
|
2318 |
-
if (
|
2319 |
-
|
2320 |
-
&& ! array_key_exists( $match[1], $data_object )
|
2321 |
) {
|
2322 |
-
$data_object['entries'][
|
2323 |
}
|
2324 |
}
|
2325 |
}
|
@@ -2337,14 +2421,15 @@ class SucuriScanCache extends SucuriScan {
|
|
2337 |
* functionality of these headers please refer to the function that contains the
|
2338 |
* default attributes and their values [1].
|
2339 |
*
|
2340 |
-
* [1] SucuriScanCache::
|
2341 |
*
|
2342 |
* @return array Default content of every datastore file.
|
2343 |
*/
|
2344 |
-
public function
|
2345 |
-
|
|
|
2346 |
|
2347 |
-
if (
|
2348 |
return $finfo['info'];
|
2349 |
}
|
2350 |
|
@@ -2357,12 +2442,13 @@ class SucuriScanCache extends SucuriScan {
|
|
2357 |
* @param array $finfo Rainbow table with the key names and decoded values.
|
2358 |
* @return integer Total number of unique entries found in the datastore file.
|
2359 |
*/
|
2360 |
-
public function
|
2361 |
-
|
2362 |
-
|
|
|
2363 |
}
|
2364 |
|
2365 |
-
return count(
|
2366 |
}
|
2367 |
|
2368 |
/**
|
@@ -2375,15 +2461,16 @@ class SucuriScanCache extends SucuriScan {
|
|
2375 |
* @param array $finfo Rainbow table with the key names and decoded values.
|
2376 |
* @return boolean TRUE if the life time of the data has expired, FALSE otherwise.
|
2377 |
*/
|
2378 |
-
public function
|
2379 |
-
|
2380 |
-
|
|
|
2381 |
}
|
2382 |
|
2383 |
-
if (
|
2384 |
-
$diff_time = time() - intval(
|
2385 |
|
2386 |
-
if (
|
2387 |
return true;
|
2388 |
}
|
2389 |
}
|
@@ -2401,45 +2488,37 @@ class SucuriScanCache extends SucuriScan {
|
|
2401 |
* @param boolean $assoc When TRUE returned objects will be converted into associative arrays.
|
2402 |
* @return boolean TRUE if the operation finished successfully, FALSE otherwise.
|
2403 |
*/
|
2404 |
-
private function
|
2405 |
-
|
2406 |
-
|
2407 |
-
|
2408 |
-
|
2409 |
-
)
|
2410 |
-
$finfo = $this->get_datastore_content( $assoc );
|
2411 |
|
2412 |
-
|
2413 |
-
|
2414 |
-
|
2415 |
-
|
2416 |
-
|
2417 |
-
|
2418 |
-
|
2419 |
-
|
2420 |
-
|
2421 |
-
|
2422 |
-
|
2423 |
-
|
2424 |
-
|
2425 |
-
break;
|
2426 |
-
case 'get_all': /* no_break */
|
2427 |
-
if ( ! $this->data_has_expired( $lifetime, $finfo ) ) {
|
2428 |
-
return $finfo['entries'];
|
2429 |
-
}
|
2430 |
-
case 'exists':
|
2431 |
-
if (
|
2432 |
-
! $this->data_has_expired( $lifetime, $finfo )
|
2433 |
-
&& array_key_exists( $key, $finfo['entries'] )
|
2434 |
-
) {
|
2435 |
-
return true;
|
2436 |
-
}
|
2437 |
-
break;
|
2438 |
-
case 'delete':
|
2439 |
-
unset($finfo['entries'][ $key ]);
|
2440 |
-
return $this->save_new_entries( $finfo );
|
2441 |
-
break;
|
2442 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2443 |
}
|
2444 |
}
|
2445 |
|
@@ -2456,8 +2535,9 @@ class SucuriScanCache extends SucuriScan {
|
|
2456 |
* @param string $data Mixed data stored in the datastore file following the unique key name.
|
2457 |
* @return boolean TRUE if the data was stored successfully, FALSE otherwise.
|
2458 |
*/
|
2459 |
-
public function add(
|
2460 |
-
|
|
|
2461 |
}
|
2462 |
|
2463 |
/**
|
@@ -2467,8 +2547,9 @@ class SucuriScanCache extends SucuriScan {
|
|
2467 |
* @param string $data Mixed data stored in the datastore file following the unique key name.
|
2468 |
* @return boolean TRUE if the data was stored successfully, FALSE otherwise.
|
2469 |
*/
|
2470 |
-
public function set(
|
2471 |
-
|
|
|
2472 |
}
|
2473 |
|
2474 |
/**
|
@@ -2479,10 +2560,11 @@ class SucuriScanCache extends SucuriScan {
|
|
2479 |
* @param boolean $assoc When TRUE returned objects will be converted into associative arrays.
|
2480 |
* @return string Mixed data stored in the datastore file following the unique key name.
|
2481 |
*/
|
2482 |
-
public function get(
|
2483 |
-
|
|
|
2484 |
|
2485 |
-
return $this->
|
2486 |
}
|
2487 |
|
2488 |
/**
|
@@ -2492,10 +2574,11 @@ class SucuriScanCache extends SucuriScan {
|
|
2492 |
* @param boolean $assoc When TRUE returned objects will be converted into associative arrays.
|
2493 |
* @return string Mixed data stored in the datastore file following the unique key name.
|
2494 |
*/
|
2495 |
-
public function
|
2496 |
-
|
|
|
2497 |
|
2498 |
-
return $this->
|
2499 |
}
|
2500 |
|
2501 |
/**
|
@@ -2504,8 +2587,9 @@ class SucuriScanCache extends SucuriScan {
|
|
2504 |
* @param string $key Unique name to identify the data in the datastore file.
|
2505 |
* @return boolean TRUE if the key exists in the datastore file, FALSE otherwise.
|
2506 |
*/
|
2507 |
-
public function exists(
|
2508 |
-
|
|
|
2509 |
}
|
2510 |
|
2511 |
/**
|
@@ -2514,8 +2598,9 @@ class SucuriScanCache extends SucuriScan {
|
|
2514 |
* @param string $key Unique name to identify the data in the datastore file.
|
2515 |
* @return boolean TRUE if the entries were removed, FALSE otherwise.
|
2516 |
*/
|
2517 |
-
public function delete(
|
2518 |
-
|
|
|
2519 |
}
|
2520 |
|
2521 |
/**
|
@@ -2523,12 +2608,12 @@ class SucuriScanCache extends SucuriScan {
|
|
2523 |
*
|
2524 |
* @return boolean Always TRUE unless the datastore file is not writable.
|
2525 |
*/
|
2526 |
-
public function flush()
|
2527 |
-
|
|
|
2528 |
|
2529 |
-
return $this->
|
2530 |
}
|
2531 |
-
|
2532 |
}
|
2533 |
|
2534 |
/**
|
@@ -2551,21 +2636,25 @@ class SucuriScanCache extends SucuriScan {
|
|
2551 |
* apply network-wide and the data is stored in the wp_sitemeta table under the
|
2552 |
* given custom name.
|
2553 |
*
|
2554 |
-
* @see
|
2555 |
-
* @see
|
2556 |
*/
|
2557 |
-
class SucuriScanOption extends SucuriScanRequest
|
|
|
2558 |
|
2559 |
/**
|
2560 |
* Default values for all the plugin's options.
|
2561 |
*
|
2562 |
* @return array Default values for all the plugin's options.
|
2563 |
*/
|
2564 |
-
public static function get_default_option_values()
|
|
|
2565 |
$defaults = array(
|
2566 |
'sucuriscan_account' => '',
|
|
|
2567 |
'sucuriscan_ads_visibility' => 'enabled',
|
2568 |
'sucuriscan_api_key' => false,
|
|
|
2569 |
'sucuriscan_audit_report' => 'disabled',
|
2570 |
'sucuriscan_cloudproxy_apikey' => '',
|
2571 |
'sucuriscan_collect_wrong_passwords' => 'disabled',
|
@@ -2612,14 +2701,15 @@ class SucuriScanOption extends SucuriScanRequest {
|
|
2612 |
'sucuriscan_notify_widget_deleted' => 'disabled',
|
2613 |
'sucuriscan_parse_errorlogs' => 'enabled',
|
2614 |
'sucuriscan_prettify_mails' => 'disabled',
|
2615 |
-
'sucuriscan_request_timeout' =>
|
2616 |
'sucuriscan_revproxy' => 'disabled',
|
2617 |
'sucuriscan_runtime' => 0,
|
2618 |
'sucuriscan_scan_checksums' => 'enabled',
|
2619 |
'sucuriscan_scan_errorlogs' => 'disabled',
|
2620 |
'sucuriscan_scan_frequency' => 'twicedaily',
|
2621 |
'sucuriscan_scan_interface' => 'spl',
|
2622 |
-
'
|
|
|
2623 |
'sucuriscan_site_version' => '0.0',
|
2624 |
'sucuriscan_sitecheck_counter' => 0,
|
2625 |
'sucuriscan_sitecheck_scanner' => 'enabled',
|
@@ -2636,9 +2726,10 @@ class SucuriScanOption extends SucuriScanRequest {
|
|
2636 |
*
|
2637 |
* @return array Name of all valid plugin's options.
|
2638 |
*/
|
2639 |
-
public static function get_default_option_names()
|
|
|
2640 |
$options = self::get_default_option_values();
|
2641 |
-
$names = array_keys(
|
2642 |
|
2643 |
return $names;
|
2644 |
}
|
@@ -2649,9 +2740,10 @@ class SucuriScanOption extends SucuriScanRequest {
|
|
2649 |
* @param string $option_name Name of the option that will be checked.
|
2650 |
* @return boolean True if the option is part of the plugin, False otherwise.
|
2651 |
*/
|
2652 |
-
public static function is_valid_plugin_option(
|
|
|
2653 |
$valid_options = self::get_default_option_names();
|
2654 |
-
$is_valid_option = (bool) array_key_exists(
|
2655 |
|
2656 |
return $is_valid_option;
|
2657 |
}
|
@@ -2662,19 +2754,20 @@ class SucuriScanOption extends SucuriScanRequest {
|
|
2662 |
* @param string|array $settings Either an array that will be complemented or a string with the name of the option.
|
2663 |
* @return string|array The default values for the specified options.
|
2664 |
*/
|
2665 |
-
public static function get_default_options(
|
|
|
2666 |
$default_options = self::get_default_option_values();
|
2667 |
|
2668 |
// Use framework built-in function.
|
2669 |
-
if (
|
2670 |
-
$admin_email = get_option(
|
2671 |
$default_options['sucuriscan_account'] = $admin_email;
|
2672 |
$default_options['sucuriscan_notify_to'] = $admin_email;
|
2673 |
}
|
2674 |
|
2675 |
-
if (
|
2676 |
-
foreach (
|
2677 |
-
if (
|
2678 |
$settings[ $option_name ] = $option_value;
|
2679 |
}
|
2680 |
}
|
@@ -2682,10 +2775,9 @@ class SucuriScanOption extends SucuriScanRequest {
|
|
2682 |
return $settings;
|
2683 |
}
|
2684 |
|
2685 |
-
if (
|
2686 |
-
|
2687 |
-
&&
|
2688 |
-
&& array_key_exists( $settings, $default_options )
|
2689 |
) {
|
2690 |
return $default_options[ $settings ];
|
2691 |
}
|
@@ -2705,18 +2797,19 @@ class SucuriScanOption extends SucuriScanRequest {
|
|
2705 |
* automatically replace that character with the unique identifier of the
|
2706 |
* plugin.
|
2707 |
*
|
2708 |
-
* @see
|
2709 |
*
|
2710 |
* @param string $option_name Optional parameter that you can use to filter the results to one option.
|
2711 |
* @return string The value (or default value) of the option specified.
|
2712 |
*/
|
2713 |
-
public static function get_option(
|
2714 |
-
|
2715 |
-
|
2716 |
-
$
|
|
|
2717 |
|
2718 |
-
if (
|
2719 |
-
$option_value = self::get_default_options(
|
2720 |
}
|
2721 |
|
2722 |
return $option_value;
|
@@ -2733,17 +2826,18 @@ class SucuriScanOption extends SucuriScanRequest {
|
|
2733 |
* the insert SQL statement but not the option value, this value should always
|
2734 |
* be properly sanitized.
|
2735 |
*
|
2736 |
-
* @see
|
2737 |
*
|
2738 |
* @param string $option_name Name of the option to update which must not exceed 64 characters.
|
2739 |
* @param string $option_value The new value for the option, can be an integer, string, array, or object.
|
2740 |
* @return boolean True if option value has changed, false if not or if update failed.
|
2741 |
*/
|
2742 |
-
public static function update_option(
|
2743 |
-
|
2744 |
-
|
|
|
2745 |
|
2746 |
-
return update_option(
|
2747 |
}
|
2748 |
|
2749 |
return false;
|
@@ -2754,16 +2848,17 @@ class SucuriScanOption extends SucuriScanRequest {
|
|
2754 |
*
|
2755 |
* A safe way of removing a named option/value pair from the options database table.
|
2756 |
*
|
2757 |
-
* @see
|
2758 |
*
|
2759 |
* @param string $option_name Name of the option to be deleted.
|
2760 |
* @return boolean True, if option is successfully deleted. False on failure, or option does not exist.
|
2761 |
*/
|
2762 |
-
public static function delete_option(
|
2763 |
-
|
2764 |
-
|
|
|
2765 |
|
2766 |
-
return delete_option(
|
2767 |
}
|
2768 |
|
2769 |
return false;
|
@@ -2775,8 +2870,9 @@ class SucuriScanOption extends SucuriScanRequest {
|
|
2775 |
* @param string $option Name of the option to be deleted.
|
2776 |
* @return boolean True if the option is enabled, false otherwise.
|
2777 |
*/
|
2778 |
-
public static function is_enabled(
|
2779 |
-
|
|
|
2780 |
}
|
2781 |
|
2782 |
/**
|
@@ -2785,8 +2881,9 @@ class SucuriScanOption extends SucuriScanRequest {
|
|
2785 |
* @param string $option Name of the option to be deleted.
|
2786 |
* @return boolean True if the option is disabled, false otherwise.
|
2787 |
*/
|
2788 |
-
public static function is_disabled(
|
2789 |
-
|
|
|
2790 |
}
|
2791 |
|
2792 |
/**
|
@@ -2794,7 +2891,8 @@ class SucuriScanOption extends SucuriScanRequest {
|
|
2794 |
*
|
2795 |
* @return void
|
2796 |
*/
|
2797 |
-
public static function delete_plugin_options()
|
|
|
2798 |
global $wpdb;
|
2799 |
|
2800 |
$options = $wpdb->get_results(
|
@@ -2803,8 +2901,8 @@ class SucuriScanOption extends SucuriScanRequest {
|
|
2803 |
ORDER BY option_id ASC"
|
2804 |
);
|
2805 |
|
2806 |
-
foreach (
|
2807 |
-
self::delete_option(
|
2808 |
}
|
2809 |
}
|
2810 |
|
@@ -2815,7 +2913,8 @@ class SucuriScanOption extends SucuriScanRequest {
|
|
2815 |
*
|
2816 |
* @return array All the options stored by Wordpress in the database, except the transient options.
|
2817 |
*/
|
2818 |
-
public static function get_site_options()
|
|
|
2819 |
global $wpdb;
|
2820 |
|
2821 |
$settings = array();
|
@@ -2825,7 +2924,7 @@ class SucuriScanOption extends SucuriScanRequest {
|
|
2825 |
ORDER BY option_id ASC"
|
2826 |
);
|
2827 |
|
2828 |
-
foreach (
|
2829 |
$settings[ $row->option_name ] = $row->option_value;
|
2830 |
}
|
2831 |
|
@@ -2839,7 +2938,8 @@ class SucuriScanOption extends SucuriScanRequest {
|
|
2839 |
* @param array $request The content of the global variable GET or POST considering SERVER[REQUEST_METHOD].
|
2840 |
* @return array A list of all the options that were changes through this request.
|
2841 |
*/
|
2842 |
-
public static function what_options_were_changed(
|
|
|
2843 |
$options_changed = array(
|
2844 |
'original' => array(),
|
2845 |
'changed' => array()
|
@@ -2847,9 +2947,8 @@ class SucuriScanOption extends SucuriScanRequest {
|
|
2847 |
|
2848 |
$site_options = self::get_site_options();
|
2849 |
|
2850 |
-
foreach (
|
2851 |
-
if (
|
2852 |
-
array_key_exists( $req_name, $site_options )
|
2853 |
&& $site_options[ $req_name ] != $req_value
|
2854 |
) {
|
2855 |
$options_changed['original'][ $req_name ] = $site_options[ $req_name ];
|
@@ -2865,21 +2964,21 @@ class SucuriScanOption extends SucuriScanRequest {
|
|
2865 |
*
|
2866 |
* @return boolean TRUE if the nonce is valid, FALSE otherwise.
|
2867 |
*/
|
2868 |
-
public static function check_options_nonce()
|
|
|
2869 |
// Create the option_page value if permalink submission.
|
2870 |
-
if (
|
2871 |
-
! isset($_POST['option_page'])
|
2872 |
&& isset($_POST['permalink_structure'])
|
2873 |
) {
|
2874 |
$_POST['option_page'] = 'permalink';
|
2875 |
}
|
2876 |
|
2877 |
// Check if the option_page has an allowed value.
|
2878 |
-
if (
|
2879 |
$nonce = '_wpnonce';
|
2880 |
$action = '';
|
2881 |
|
2882 |
-
switch (
|
2883 |
case 'general': /* no_break */
|
2884 |
case 'writing': /* no_break */
|
2885 |
case 'reading': /* no_break */
|
@@ -2894,10 +2993,9 @@ class SucuriScanOption extends SucuriScanRequest {
|
|
2894 |
}
|
2895 |
|
2896 |
// Check the nonce validity.
|
2897 |
-
if (
|
2898 |
-
! empty($action)
|
2899 |
&& isset($_REQUEST[ $nonce ])
|
2900 |
-
&& wp_verify_nonce(
|
2901 |
) {
|
2902 |
return true;
|
2903 |
}
|
@@ -2912,25 +3010,24 @@ class SucuriScanOption extends SucuriScanRequest {
|
|
2912 |
*
|
2913 |
* @return array List of ignored posts-types to send notifications.
|
2914 |
*/
|
2915 |
-
public static function get_ignored_events()
|
2916 |
-
|
|
|
2917 |
$post_types_arr = false;
|
2918 |
|
2919 |
// Encode (old) serialized data into JSON.
|
2920 |
-
if (
|
2921 |
-
$post_types_arr = @unserialize(
|
2922 |
-
$post_types_fix = json_encode(
|
2923 |
-
self::update_option(
|
2924 |
|
2925 |
return $post_types_arr;
|
|
|
|
|
|
|
2926 |
}
|
2927 |
|
2928 |
-
|
2929 |
-
elseif ( preg_match( '/^\{.+\}$/', $post_types ) ) {
|
2930 |
-
$post_types_arr = @json_decode( $post_types, true );
|
2931 |
-
}
|
2932 |
-
|
2933 |
-
if ( ! is_array( $post_types_arr ) ) {
|
2934 |
$post_types_arr = array();
|
2935 |
}
|
2936 |
|
@@ -2943,18 +3040,19 @@ class SucuriScanOption extends SucuriScanRequest {
|
|
2943 |
* @param string $event_name Unique post-type name.
|
2944 |
* @return boolean Whether the event was ignored or not.
|
2945 |
*/
|
2946 |
-
public static function add_ignored_event(
|
2947 |
-
|
|
|
2948 |
$post_types = get_post_types();
|
2949 |
|
2950 |
// Check if the event is a registered post-type.
|
2951 |
-
if (
|
2952 |
$ignored_events = self::get_ignored_events();
|
2953 |
|
2954 |
// Check if the event is not ignored already.
|
2955 |
-
if (
|
2956 |
$ignored_events[ $event_name ] = time();
|
2957 |
-
$saved = self::update_option(
|
2958 |
|
2959 |
return $saved;
|
2960 |
}
|
@@ -2970,12 +3068,13 @@ class SucuriScanOption extends SucuriScanRequest {
|
|
2970 |
* @param string $event_name Unique post-type name.
|
2971 |
* @return boolean Whether the event was removed from the list or not.
|
2972 |
*/
|
2973 |
-
public static function remove_ignored_event(
|
|
|
2974 |
$ignored_events = self::get_ignored_events();
|
2975 |
|
2976 |
-
if (
|
2977 |
-
unset(
|
2978 |
-
$saved = self::update_option(
|
2979 |
|
2980 |
return $saved;
|
2981 |
}
|
@@ -2989,11 +3088,12 @@ class SucuriScanOption extends SucuriScanRequest {
|
|
2989 |
* @param string $event_name Unique post-type name.
|
2990 |
* @return boolean Whether an event is being ignored or not.
|
2991 |
*/
|
2992 |
-
public static function is_ignored_event(
|
2993 |
-
|
|
|
2994 |
$ignored_events = self::get_ignored_events();
|
2995 |
|
2996 |
-
if (
|
2997 |
return true;
|
2998 |
}
|
2999 |
|
@@ -3006,7 +3106,8 @@ class SucuriScanOption extends SucuriScanRequest {
|
|
3006 |
*
|
3007 |
* @return array Array with three keys: good, missing, bad.
|
3008 |
*/
|
3009 |
-
public static function get_security_keys()
|
|
|
3010 |
$response = array(
|
3011 |
'good' => array(),
|
3012 |
'missing' => array(),
|
@@ -3023,11 +3124,11 @@ class SucuriScanOption extends SucuriScanRequest {
|
|
3023 |
'SECURE_AUTH_SALT',
|
3024 |
);
|
3025 |
|
3026 |
-
foreach (
|
3027 |
-
if (
|
3028 |
-
$key_value = constant(
|
3029 |
|
3030 |
-
if (
|
3031 |
$response['bad'][ $key_name ] = $key_value;
|
3032 |
} else {
|
3033 |
$response['good'][ $key_name ] = $key_value;
|
@@ -3040,6 +3141,51 @@ class SucuriScanOption extends SucuriScanRequest {
|
|
3040 |
return $response;
|
3041 |
}
|
3042 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3043 |
}
|
3044 |
|
3045 |
/**
|
@@ -3055,23 +3201,25 @@ class SucuriScanOption extends SucuriScanRequest {
|
|
3055 |
* response to events is said to be event-driven, often with the goal of being
|
3056 |
* interactive.
|
3057 |
*
|
3058 |
-
* @see
|
3059 |
*/
|
3060 |
-
class SucuriScanEvent extends SucuriScan
|
|
|
3061 |
|
3062 |
/**
|
3063 |
* Schedule the task to run the first filesystem scan.
|
3064 |
*
|
3065 |
* @return void
|
3066 |
*/
|
3067 |
-
public static function schedule_task()
|
|
|
3068 |
$task_name = 'sucuriscan_scheduled_scan';
|
3069 |
|
3070 |
-
if (
|
3071 |
-
wp_schedule_event(
|
3072 |
}
|
3073 |
|
3074 |
-
wp_schedule_single_event(
|
3075 |
}
|
3076 |
|
3077 |
/**
|
@@ -3081,29 +3229,29 @@ class SucuriScanEvent extends SucuriScan {
|
|
3081 |
* @param boolean $force_scan Whether the filesystem scan was forced by an administrator user or not.
|
3082 |
* @return boolean Either TRUE or FALSE representing the success or fail of the operation respectively.
|
3083 |
*/
|
3084 |
-
private static function verify_run(
|
|
|
3085 |
$option_name = ':runtime';
|
3086 |
-
$last_run = SucuriScanOption::get_option(
|
3087 |
$current_time = time();
|
3088 |
|
3089 |
// The filesystem scanner can be disabled from the settings page.
|
3090 |
-
if (
|
3091 |
-
SucuriScanOption::is_disabled( ':fs_scanner' )
|
3092 |
&& $force_scan === false
|
3093 |
) {
|
3094 |
return false;
|
3095 |
}
|
3096 |
|
3097 |
// Check if the last runtime is too near the current time.
|
3098 |
-
if (
|
3099 |
$runtime_diff = $current_time - $runtime;
|
3100 |
|
3101 |
-
if (
|
3102 |
return false;
|
3103 |
}
|
3104 |
}
|
3105 |
|
3106 |
-
SucuriScanOption::update_option(
|
3107 |
|
3108 |
return true;
|
3109 |
}
|
@@ -3114,14 +3262,15 @@ class SucuriScanEvent extends SucuriScan {
|
|
3114 |
*
|
3115 |
* @return boolean TRUE if the current WordPress version must be reported, FALSE otherwise.
|
3116 |
*/
|
3117 |
-
private static function report_site_version()
|
|
|
3118 |
$option_name = ':site_version';
|
3119 |
-
$reported_version = SucuriScanOption::get_option(
|
3120 |
$wp_version = self::site_version();
|
3121 |
|
3122 |
-
if (
|
3123 |
-
SucuriScanEvent::report_info_event(
|
3124 |
-
SucuriScanOption::update_option(
|
3125 |
|
3126 |
return true;
|
3127 |
}
|
@@ -3137,31 +3286,31 @@ class SucuriScanEvent extends SucuriScan {
|
|
3137 |
* @param boolean $force_scan Whether the filesystem scan was forced by an administrator user or not.
|
3138 |
* @return boolean TRUE if the filesystem scan was successful, FALSE otherwise.
|
3139 |
*/
|
3140 |
-
public static function filesystem_scan(
|
|
|
3141 |
$minimum_runtime = SUCURISCAN_MINIMUM_RUNTIME;
|
3142 |
|
3143 |
-
if (
|
3144 |
-
|
3145 |
-
&&
|
3146 |
-
&& SucuriScanAPI::get_plugin_key()
|
3147 |
) {
|
3148 |
self::report_site_version();
|
3149 |
|
3150 |
$file_info = new SucuriScanFileInfo();
|
3151 |
-
$file_info->scan_interface = SucuriScanOption::get_option(
|
3152 |
-
$signatures = $file_info->get_directory_tree_md5(
|
3153 |
|
3154 |
-
if (
|
3155 |
-
$hashes_sent = SucuriScanAPI::
|
3156 |
|
3157 |
-
if (
|
3158 |
-
SucuriScanOption::update_option(
|
3159 |
return true;
|
3160 |
} else {
|
3161 |
-
SucuriScanInterface::error(
|
3162 |
}
|
3163 |
} else {
|
3164 |
-
SucuriScanInterface::error(
|
3165 |
}
|
3166 |
}
|
3167 |
|
@@ -3177,22 +3326,22 @@ class SucuriScanEvent extends SucuriScan {
|
|
3177 |
* @param boolean $internal Whether the event will be publicly visible or not.
|
3178 |
* @return boolean TRUE if the event was logged in the monitoring service, FALSE otherwise.
|
3179 |
*/
|
3180 |
-
private static function report_event(
|
|
|
3181 |
$user = wp_get_current_user();
|
3182 |
$username = false;
|
3183 |
-
$current_time = date(
|
3184 |
$remote_ip = self::get_remote_addr();
|
3185 |
|
3186 |
// Identify current user in session.
|
3187 |
-
if (
|
3188 |
-
$user instanceof WP_User
|
3189 |
&& isset($user->user_login)
|
3190 |
-
&& !
|
3191 |
) {
|
3192 |
-
if (
|
3193 |
-
$username = sprintf(
|
3194 |
} else {
|
3195 |
-
$username = sprintf(
|
3196 |
}
|
3197 |
}
|
3198 |
|
@@ -3200,26 +3349,40 @@ class SucuriScanEvent extends SucuriScan {
|
|
3200 |
$severity = (int) $severity;
|
3201 |
|
3202 |
// Convert the severity number into a readable string.
|
3203 |
-
switch (
|
3204 |
-
case 0:
|
3205 |
-
|
3206 |
-
|
3207 |
-
case
|
3208 |
-
|
3209 |
-
|
3210 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3211 |
}
|
3212 |
|
3213 |
// Mark the event as internal if necessary.
|
3214 |
-
if (
|
3215 |
$severity_name = '@' . $severity_name;
|
3216 |
}
|
3217 |
|
3218 |
// Clear event message.
|
3219 |
-
$message = strip_tags(
|
3220 |
-
$message = str_replace(
|
3221 |
-
$message = str_replace(
|
3222 |
-
$message = str_replace(
|
3223 |
|
3224 |
$event_message = sprintf(
|
3225 |
'%s:%s %s; %s',
|
@@ -3229,19 +3392,58 @@ class SucuriScanEvent extends SucuriScan {
|
|
3229 |
$message
|
3230 |
);
|
3231 |
|
3232 |
-
return
|
3233 |
}
|
3234 |
|
3235 |
-
|
3236 |
-
|
3237 |
-
|
3238 |
-
|
3239 |
-
|
3240 |
-
|
3241 |
-
|
3242 |
-
|
3243 |
-
|
3244 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3245 |
|
3246 |
/**
|
3247 |
* Reports a notice event on the website.
|
@@ -3250,8 +3452,9 @@ class SucuriScanEvent extends SucuriScan {
|
|
3250 |
* @param boolean $internal Whether the event will be publicly visible or not.
|
3251 |
* @return boolean Either true or false depending on the success of the operation.
|
3252 |
*/
|
3253 |
-
public static function report_notice_event(
|
3254 |
-
|
|
|
3255 |
}
|
3256 |
|
3257 |
/**
|
@@ -3261,8 +3464,9 @@ class SucuriScanEvent extends SucuriScan {
|
|
3261 |
* @param boolean $internal Whether the event will be publicly visible or not.
|
3262 |
* @return boolean Either true or false depending on the success of the operation.
|
3263 |
*/
|
3264 |
-
public static function report_info_event(
|
3265 |
-
|
|
|
3266 |
}
|
3267 |
|
3268 |
/**
|
@@ -3272,8 +3476,9 @@ class SucuriScanEvent extends SucuriScan {
|
|
3272 |
* @param boolean $internal Whether the event will be publicly visible or not.
|
3273 |
* @return boolean Either true or false depending on the success of the operation.
|
3274 |
*/
|
3275 |
-
public static function report_warning_event(
|
3276 |
-
|
|
|
3277 |
}
|
3278 |
|
3279 |
/**
|
@@ -3283,8 +3488,9 @@ class SucuriScanEvent extends SucuriScan {
|
|
3283 |
* @param boolean $internal Whether the event will be publicly visible or not.
|
3284 |
* @return boolean Either true or false depending on the success of the operation.
|
3285 |
*/
|
3286 |
-
public static function report_error_event(
|
3287 |
-
|
|
|
3288 |
}
|
3289 |
|
3290 |
/**
|
@@ -3294,8 +3500,9 @@ class SucuriScanEvent extends SucuriScan {
|
|
3294 |
* @param boolean $internal Whether the event will be publicly visible or not.
|
3295 |
* @return boolean Either true or false depending on the success of the operation.
|
3296 |
*/
|
3297 |
-
public static function report_critical_event(
|
3298 |
-
|
|
|
3299 |
}
|
3300 |
|
3301 |
/**
|
@@ -3306,21 +3513,22 @@ class SucuriScanEvent extends SucuriScan {
|
|
3306 |
* @param boolean $internal Whether the event will be publicly visible or not.
|
3307 |
* @return boolean Either true or false depending on the success of the operation.
|
3308 |
*/
|
3309 |
-
public static function report_auto_event(
|
3310 |
-
|
|
|
3311 |
|
3312 |
// Auto-detect the action performed, either enabled or disabled.
|
3313 |
-
if (
|
3314 |
$action = $match[2];
|
3315 |
}
|
3316 |
|
3317 |
// Report the correct event for the action performed.
|
3318 |
-
if (
|
3319 |
-
return self::report_notice_event(
|
3320 |
-
} elseif (
|
3321 |
-
return self::report_error_event(
|
3322 |
} else {
|
3323 |
-
return self::report_info_event(
|
3324 |
}
|
3325 |
}
|
3326 |
|
@@ -3330,19 +3538,20 @@ class SucuriScanEvent extends SucuriScan {
|
|
3330 |
* @param Exception $exception A valid exception object of any type.
|
3331 |
* @return boolean Whether the report was filled correctly or not.
|
3332 |
*/
|
3333 |
-
public static function report_exception(
|
3334 |
-
|
|
|
3335 |
$e_trace = $exception->getTrace();
|
3336 |
$multiple_entries = array();
|
3337 |
|
3338 |
-
foreach (
|
3339 |
-
$e_file = array_key_exists(
|
3340 |
-
? basename(
|
3341 |
: '[internal function]';
|
3342 |
-
$e_line = array_key_exists(
|
3343 |
-
? basename(
|
3344 |
: '0';
|
3345 |
-
$e_function = array_key_exists(
|
3346 |
? $e_child['class'] . $e_child['type'] . $e_child['function']
|
3347 |
: $e_child['function'];
|
3348 |
$multiple_entries[] = sprintf(
|
@@ -3356,10 +3565,10 @@ class SucuriScanEvent extends SucuriScan {
|
|
3356 |
$report_message = sprintf(
|
3357 |
'%s: (multiple entries): %s',
|
3358 |
$exception->getMessage(),
|
3359 |
-
@implode(
|
3360 |
);
|
3361 |
|
3362 |
-
return self::report_debug_event(
|
3363 |
}
|
3364 |
|
3365 |
return false;
|
@@ -3373,34 +3582,42 @@ class SucuriScanEvent extends SucuriScan {
|
|
3373 |
* @param string $content Body of the email that will be sent to the administrator.
|
3374 |
* @return void
|
3375 |
*/
|
3376 |
-
public static function notify_event(
|
3377 |
-
|
3378 |
-
$
|
|
|
3379 |
$email_params = array();
|
3380 |
|
3381 |
-
if (
|
3382 |
$notify = 'disabled';
|
3383 |
}
|
3384 |
|
3385 |
-
if (
|
3386 |
-
if (
|
3387 |
$event = 'post_update';
|
3388 |
-
} elseif (
|
3389 |
-
$
|
3390 |
-
$content .=
|
3391 |
-
|
3392 |
-
|
3393 |
-
|
3394 |
-
|
3395 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3396 |
// Send a notification even if the limit of emails per hour was reached.
|
3397 |
$email_params['Force'] = true;
|
3398 |
-
} elseif (
|
3399 |
$event = 'core_integrity_checks';
|
3400 |
$email_params['Force'] = true;
|
3401 |
}
|
3402 |
|
3403 |
-
$title = str_replace(
|
3404 |
$mail_sent = SucuriScanMail::send_mail(
|
3405 |
$email,
|
3406 |
$title,
|
@@ -3420,44 +3637,44 @@ class SucuriScanEvent extends SucuriScan {
|
|
3420 |
* @param string $remote_addr The supposed ip address that will be checked.
|
3421 |
* @return boolean TRUE if the IP address of the user is trusted, FALSE otherwise.
|
3422 |
*/
|
3423 |
-
private static function is_trusted_ip(
|
3424 |
-
|
3425 |
-
$
|
|
|
3426 |
|
3427 |
-
if (
|
3428 |
$remote_addr = SucuriScan::get_remote_addr();
|
3429 |
}
|
3430 |
|
3431 |
-
$addr_md5 = md5(
|
3432 |
|
3433 |
// Check if the CIDR in range 32 of this IP is trusted.
|
3434 |
-
if (
|
3435 |
-
|
3436 |
-
&&
|
3437 |
-
&& array_key_exists( $addr_md5, $trusted_ips )
|
3438 |
) {
|
3439 |
return true;
|
3440 |
}
|
3441 |
|
3442 |
-
if (
|
3443 |
-
foreach (
|
3444 |
-
$ip_parts = explode(
|
3445 |
$ip_pattern = false;
|
3446 |
|
3447 |
// Generate the regular expression for a specific CIDR range.
|
3448 |
-
switch (
|
3449 |
case 24:
|
3450 |
-
$ip_pattern = sprintf(
|
3451 |
break;
|
3452 |
case 16:
|
3453 |
-
$ip_pattern = sprintf(
|
3454 |
break;
|
3455 |
case 8:
|
3456 |
-
$ip_pattern = sprintf(
|
3457 |
break;
|
3458 |
}
|
3459 |
|
3460 |
-
if (
|
3461 |
return true;
|
3462 |
}
|
3463 |
}
|
@@ -3472,29 +3689,30 @@ class SucuriScanEvent extends SucuriScan {
|
|
3472 |
* @param integer $user_id The user identifier that will be changed, this must be different than the user in session.
|
3473 |
* @return boolean Either TRUE or FALSE in case of success or error respectively.
|
3474 |
*/
|
3475 |
-
public static function set_new_password(
|
3476 |
-
|
|
|
3477 |
|
3478 |
-
if (
|
3479 |
-
$user = get_userdata(
|
3480 |
|
3481 |
-
if (
|
3482 |
$website = SucuriScan::get_domain();
|
3483 |
$user_login = $user->user_login;
|
3484 |
$display_name = $user->display_name;
|
3485 |
-
$new_password = wp_generate_password(
|
3486 |
|
3487 |
-
$message = SucuriScanTemplate::
|
3488 |
'ResetPassword.UserName' => $user_login,
|
3489 |
'ResetPassword.DisplayName' => $display_name,
|
3490 |
'ResetPassword.Password' => $new_password,
|
3491 |
'ResetPassword.Website' => $website,
|
3492 |
-
)
|
3493 |
|
3494 |
$data_set = array( 'Force' => true ); // Skip limit for emails per hour.
|
3495 |
-
SucuriScanMail::send_mail(
|
3496 |
|
3497 |
-
wp_set_password(
|
3498 |
|
3499 |
return true;
|
3500 |
}
|
@@ -3512,28 +3730,29 @@ class SucuriScanEvent extends SucuriScan {
|
|
3512 |
*
|
3513 |
* @return false|array Either FALSE in case of error, or an array with the old and new keys.
|
3514 |
*/
|
3515 |
-
public static function set_new_config_keys()
|
|
|
3516 |
$new_wpconfig = '';
|
3517 |
$config_path = self::get_wpconfig_path();
|
3518 |
|
3519 |
-
if (
|
3520 |
$pattern = self::secret_key_pattern();
|
3521 |
$define_tpl = "define('%s',%s'%s');";
|
3522 |
-
$config_lines = SucuriScanFileInfo::file_lines(
|
3523 |
-
$new_keys = SucuriScanAPI::
|
3524 |
$old_keys = array();
|
3525 |
$old_keys_string = '';
|
3526 |
$new_keys_string = '';
|
3527 |
|
3528 |
-
foreach (
|
3529 |
-
if (
|
3530 |
$key_name = $match[1];
|
3531 |
|
3532 |
-
if (
|
3533 |
$white_spaces = $match[2];
|
3534 |
$old_keys[ $key_name ] = $match[3];
|
3535 |
-
$config_line = sprintf(
|
3536 |
-
$old_keys_string .= sprintf(
|
3537 |
$new_keys_string .= $config_line . "\n";
|
3538 |
}
|
3539 |
}
|
@@ -3542,7 +3761,7 @@ class SucuriScanEvent extends SucuriScan {
|
|
3542 |
}
|
3543 |
|
3544 |
$response = array(
|
3545 |
-
'updated' => is_writable(
|
3546 |
'old_keys' => $old_keys,
|
3547 |
'old_keys_string' => $old_keys_string,
|
3548 |
'new_keys' => $new_keys,
|
@@ -3550,8 +3769,8 @@ class SucuriScanEvent extends SucuriScan {
|
|
3550 |
'new_wpconfig' => $new_wpconfig,
|
3551 |
);
|
3552 |
|
3553 |
-
if (
|
3554 |
-
file_put_contents(
|
3555 |
}
|
3556 |
|
3557 |
return $response;
|
@@ -3559,7 +3778,6 @@ class SucuriScanEvent extends SucuriScan {
|
|
3559 |
|
3560 |
return false;
|
3561 |
}
|
3562 |
-
|
3563 |
}
|
3564 |
|
3565 |
/**
|
@@ -3577,7 +3795,8 @@ class SucuriScanEvent extends SucuriScan {
|
|
3577 |
* calls in order to monitor behavior or modify the function of an application
|
3578 |
* or other component; it is also widely used in benchmarking programs.
|
3579 |
*/
|
3580 |
-
class SucuriScanHook extends SucuriScanEvent
|
|
|
3581 |
|
3582 |
/**
|
3583 |
* Send to Sucuri servers an alert notifying that an attachment was added to a post.
|
@@ -3585,8 +3804,9 @@ class SucuriScanHook extends SucuriScanEvent {
|
|
3585 |
* @param integer $id The post identifier.
|
3586 |
* @return void
|
3587 |
*/
|
3588 |
-
public static function hook_add_attachment(
|
3589 |
-
|
|
|
3590 |
$id = $data->ID;
|
3591 |
$title = $data->post_title;
|
3592 |
$mime_type = $data->post_mime_type;
|
@@ -3595,9 +3815,9 @@ class SucuriScanHook extends SucuriScanEvent {
|
|
3595 |
$mime_type = 'unknown';
|
3596 |
}
|
3597 |
|
3598 |
-
$message = sprintf(
|
3599 |
-
self::report_notice_event(
|
3600 |
-
self::notify_event(
|
3601 |
}
|
3602 |
|
3603 |
/**
|
@@ -3606,8 +3826,9 @@ class SucuriScanHook extends SucuriScanEvent {
|
|
3606 |
* @param integer $id Identifier of the new link created;
|
3607 |
* @return void
|
3608 |
*/
|
3609 |
-
public static function hook_add_link(
|
3610 |
-
|
|
|
3611 |
$id = $data->link_id;
|
3612 |
$title = $data->link_name;
|
3613 |
$url = $data->link_url;
|
@@ -3620,10 +3841,13 @@ class SucuriScanHook extends SucuriScanEvent {
|
|
3620 |
|
3621 |
$message = sprintf(
|
3622 |
'Bookmark link added; identifier: %s; name: %s; url: %s; target: %s',
|
3623 |
-
$id,
|
|
|
|
|
|
|
3624 |
);
|
3625 |
-
self::report_warning_event(
|
3626 |
-
self::notify_event(
|
3627 |
}
|
3628 |
|
3629 |
/**
|
@@ -3632,12 +3856,13 @@ class SucuriScanHook extends SucuriScanEvent {
|
|
3632 |
* @param integer $id The identifier of the category created.
|
3633 |
* @return void
|
3634 |
*/
|
3635 |
-
public static function hook_create_category(
|
3636 |
-
|
|
|
3637 |
|
3638 |
-
$message = sprintf(
|
3639 |
-
self::report_notice_event(
|
3640 |
-
self::notify_event(
|
3641 |
}
|
3642 |
|
3643 |
/**
|
@@ -3646,8 +3871,9 @@ class SucuriScanHook extends SucuriScanEvent {
|
|
3646 |
* @param integer $id The identifier of the post deleted.
|
3647 |
* @return void
|
3648 |
*/
|
3649 |
-
public static function hook_delete_post(
|
3650 |
-
|
|
|
3651 |
}
|
3652 |
|
3653 |
/**
|
@@ -3656,8 +3882,9 @@ class SucuriScanHook extends SucuriScanEvent {
|
|
3656 |
* @param integer $id The identifier of the trashed post.
|
3657 |
* @return void
|
3658 |
*/
|
3659 |
-
public static function hook_wp_trash_post(
|
3660 |
-
|
|
|
3661 |
$title = $data->post_title;
|
3662 |
$status = $data->post_status;
|
3663 |
} else {
|
@@ -3667,9 +3894,11 @@ class SucuriScanHook extends SucuriScanEvent {
|
|
3667 |
|
3668 |
$message = sprintf(
|
3669 |
'Post moved to trash; identifier: %s; name: %s; status: %s',
|
3670 |
-
$id,
|
|
|
|
|
3671 |
);
|
3672 |
-
self::report_warning_event(
|
3673 |
}
|
3674 |
|
3675 |
/**
|
@@ -3678,8 +3907,9 @@ class SucuriScanHook extends SucuriScanEvent {
|
|
3678 |
* @param integer $id The identifier of the user account deleted.
|
3679 |
* @return void
|
3680 |
*/
|
3681 |
-
public static function hook_delete_user(
|
3682 |
-
|
|
|
3683 |
}
|
3684 |
|
3685 |
/**
|
@@ -3688,10 +3918,11 @@ class SucuriScanHook extends SucuriScanEvent {
|
|
3688 |
*
|
3689 |
* @return void
|
3690 |
*/
|
3691 |
-
public static function hook_login_form_resetpass()
|
|
|
3692 |
// Detecting WordPress 2.8.3 vulnerability - $key is array.
|
3693 |
-
if (
|
3694 |
-
self::report_critical_event(
|
3695 |
}
|
3696 |
}
|
3697 |
|
@@ -3702,23 +3933,26 @@ class SucuriScanHook extends SucuriScanEvent {
|
|
3702 |
* @param integer $id The identifier of the post changed.
|
3703 |
* @return void
|
3704 |
*/
|
3705 |
-
public static function hook_private_to_published(
|
3706 |
-
|
|
|
3707 |
$title = $data->post_title;
|
3708 |
-
$p_type = ucwords(
|
3709 |
} else {
|
3710 |
$title = 'Unknown';
|
3711 |
$p_type = 'Publication';
|
3712 |
}
|
3713 |
|
3714 |
// Check whether the post-type is being ignored to send notifications.
|
3715 |
-
if (
|
3716 |
$message = sprintf(
|
3717 |
'%s (private to published); identifier: %s; name: %s',
|
3718 |
-
$p_type,
|
|
|
|
|
3719 |
);
|
3720 |
-
self::report_notice_event(
|
3721 |
-
self::notify_event(
|
3722 |
}
|
3723 |
}
|
3724 |
|
@@ -3728,10 +3962,11 @@ class SucuriScanHook extends SucuriScanEvent {
|
|
3728 |
* @param integer $id The identifier of the post or page published.
|
3729 |
* @return void
|
3730 |
*/
|
3731 |
-
public static function hook_publish(
|
3732 |
-
|
|
|
3733 |
$title = $data->post_title;
|
3734 |
-
$p_type = ucwords(
|
3735 |
$action = ( $data->post_date == $data->post_modified ? 'created' : 'updated' );
|
3736 |
} else {
|
3737 |
$title = 'Unknown';
|
@@ -3741,10 +3976,13 @@ class SucuriScanHook extends SucuriScanEvent {
|
|
3741 |
|
3742 |
$message = sprintf(
|
3743 |
'%s was %s; identifier: %s; name: %s',
|
3744 |
-
$p_type,
|
|
|
|
|
|
|
3745 |
);
|
3746 |
-
self::report_notice_event(
|
3747 |
-
self::notify_event(
|
3748 |
}
|
3749 |
|
3750 |
/**
|
@@ -3753,8 +3991,9 @@ class SucuriScanHook extends SucuriScanEvent {
|
|
3753 |
* @param integer $id The identifier of the post or page published.
|
3754 |
* @return void
|
3755 |
*/
|
3756 |
-
public static function hook_publish_page(
|
3757 |
-
|
|
|
3758 |
}
|
3759 |
|
3760 |
/**
|
@@ -3763,8 +4002,9 @@ class SucuriScanHook extends SucuriScanEvent {
|
|
3763 |
* @param integer $id The identifier of the post or page published.
|
3764 |
* @return void
|
3765 |
*/
|
3766 |
-
public static function hook_publish_post(
|
3767 |
-
|
|
|
3768 |
}
|
3769 |
|
3770 |
/**
|
@@ -3773,8 +4013,9 @@ class SucuriScanHook extends SucuriScanEvent {
|
|
3773 |
* @param integer $id The identifier of the post or page published.
|
3774 |
* @return void
|
3775 |
*/
|
3776 |
-
public static function hook_publish_phone(
|
3777 |
-
|
|
|
3778 |
}
|
3779 |
|
3780 |
/**
|
@@ -3783,8 +4024,9 @@ class SucuriScanHook extends SucuriScanEvent {
|
|
3783 |
* @param integer $id The identifier of the post or page published.
|
3784 |
* @return void
|
3785 |
*/
|
3786 |
-
public static function hook_xmlrpc_publish_post(
|
3787 |
-
|
|
|
3788 |
}
|
3789 |
|
3790 |
/**
|
@@ -3794,12 +4036,13 @@ class SucuriScanHook extends SucuriScanEvent {
|
|
3794 |
* @param string $title The name of the user account involved in the trasaction.
|
3795 |
* @return void
|
3796 |
*/
|
3797 |
-
public static function hook_retrieve_password(
|
3798 |
-
|
|
|
3799 |
$title = 'unknown';
|
3800 |
}
|
3801 |
|
3802 |
-
self::report_error_event(
|
3803 |
}
|
3804 |
|
3805 |
/**
|
@@ -3808,14 +4051,15 @@ class SucuriScanHook extends SucuriScanEvent {
|
|
3808 |
* @param string $title The name of the new theme selected to used through out the site.
|
3809 |
* @return void
|
3810 |
*/
|
3811 |
-
public static function hook_switch_theme(
|
3812 |
-
|
|
|
3813 |
$title = 'unknown';
|
3814 |
}
|
3815 |
|
3816 |
$message = 'Theme activated: ' . $title;
|
3817 |
-
self::report_warning_event(
|
3818 |
-
self::notify_event(
|
3819 |
}
|
3820 |
|
3821 |
/**
|
@@ -3824,11 +4068,12 @@ class SucuriScanHook extends SucuriScanEvent {
|
|
3824 |
* @param integer $id The identifier of the new user account created.
|
3825 |
* @return void
|
3826 |
*/
|
3827 |
-
public static function hook_user_register(
|
3828 |
-
|
|
|
3829 |
$title = $data->user_login;
|
3830 |
$email = $data->user_email;
|
3831 |
-
$roles = @implode(
|
3832 |
} else {
|
3833 |
$title = 'unknown';
|
3834 |
$email = 'user@domain.com';
|
@@ -3837,10 +4082,13 @@ class SucuriScanHook extends SucuriScanEvent {
|
|
3837 |
|
3838 |
$message = sprintf(
|
3839 |
'User account created; identifier: %s; name: %s; email: %s; roles: %s',
|
3840 |
-
$id,
|
|
|
|
|
|
|
3841 |
);
|
3842 |
-
self::report_warning_event(
|
3843 |
-
self::notify_event(
|
3844 |
}
|
3845 |
|
3846 |
/**
|
@@ -3850,14 +4098,15 @@ class SucuriScanHook extends SucuriScanEvent {
|
|
3850 |
* @param string $title The name of the user account involved in the transaction.
|
3851 |
* @return void
|
3852 |
*/
|
3853 |
-
public static function hook_wp_login(
|
3854 |
-
|
|
|
3855 |
$title = 'Unknown';
|
3856 |
}
|
3857 |
|
3858 |
$message = 'User authentication succeeded: ' . $title;
|
3859 |
-
self::report_notice_event(
|
3860 |
-
self::notify_event(
|
3861 |
}
|
3862 |
|
3863 |
/**
|
@@ -3867,33 +4116,34 @@ class SucuriScanHook extends SucuriScanEvent {
|
|
3867 |
* @param string $title The name of the user account involved in the transaction.
|
3868 |
* @return void
|
3869 |
*/
|
3870 |
-
public static function hook_wp_login_failed(
|
3871 |
-
|
|
|
3872 |
$title = 'Unknown';
|
3873 |
}
|
3874 |
|
3875 |
-
$title = sanitize_user(
|
3876 |
-
$password = SucuriScanRequest::post(
|
3877 |
$message = 'User authentication failed: ' . $title;
|
3878 |
|
3879 |
-
self::report_error_event(
|
3880 |
|
3881 |
-
if (
|
3882 |
$message .= "<br>\nUser wrong password: " . $password;
|
3883 |
}
|
3884 |
|
3885 |
-
self::notify_event(
|
3886 |
|
3887 |
// Log the failed login in the internal datastore for future reports.
|
3888 |
-
$logged = sucuriscan_log_failed_login(
|
3889 |
|
3890 |
// Check if the quantity of failed logins will be considered as a brute-force attack.
|
3891 |
-
if (
|
3892 |
$failed_logins = sucuriscan_get_failed_logins();
|
3893 |
|
3894 |
-
if (
|
3895 |
$max_time = 3600;
|
3896 |
-
$maximum_failed_logins = SucuriScanOption::get_option(
|
3897 |
|
3898 |
/**
|
3899 |
* If the time passed is within the hour, and the quantity of failed logins
|
@@ -3902,14 +4152,11 @@ class SucuriScanHook extends SucuriScanEvent {
|
|
3902 |
* settings page), then send an email notification reporting the event and
|
3903 |
* specifying that it may be a brute-force attack against the login page.
|
3904 |
*/
|
3905 |
-
if (
|
3906 |
-
$failed_logins['diff_time'] <= $max_time
|
3907 |
&& $failed_logins['count'] >= $maximum_failed_logins
|
3908 |
) {
|
3909 |
-
sucuriscan_report_failed_logins(
|
3910 |
-
}
|
3911 |
-
|
3912 |
-
/**
|
3913 |
* If there time passed is superior to the hour, then reset the content of the
|
3914 |
* datastore file containing the failed logins so far, any entry in that file
|
3915 |
* will not be considered as part of a brute-force attack (if it exists) because
|
@@ -3918,9 +4165,9 @@ class SucuriScanHook extends SucuriScanEvent {
|
|
3918 |
* first entry of that file in case of future attempts during the next sixty
|
3919 |
* minutes.
|
3920 |
*/
|
3921 |
-
elseif (
|
3922 |
sucuriscan_reset_failed_logins();
|
3923 |
-
sucuriscan_log_failed_login(
|
3924 |
}
|
3925 |
}
|
3926 |
}
|
@@ -3942,13 +4189,13 @@ class SucuriScanHook extends SucuriScanEvent {
|
|
3942 |
* @param object $comment The comment object.
|
3943 |
* @return void
|
3944 |
*/
|
3945 |
-
public static function hook_wp_insert_comment(
|
3946 |
-
|
3947 |
-
|
3948 |
-
&& property_exists(
|
3949 |
-
&& property_exists(
|
3950 |
-
&& property_exists(
|
3951 |
-
&& SucuriScanOption::is_enabled(
|
3952 |
) {
|
3953 |
$data_set = array(
|
3954 |
'id' => $comment->comment_ID,
|
@@ -3962,8 +4209,8 @@ class SucuriScanHook extends SucuriScanEvent {
|
|
3962 |
'content' => $comment->comment_content,
|
3963 |
'user_agent' => $comment->comment_agent,
|
3964 |
);
|
3965 |
-
$message = base64_encode(
|
3966 |
-
self::report_notice_event(
|
3967 |
}
|
3968 |
}
|
3969 |
|
@@ -3979,22 +4226,22 @@ class SucuriScanHook extends SucuriScanEvent {
|
|
3979 |
*
|
3980 |
* @return void
|
3981 |
*/
|
3982 |
-
public static function hook_all(
|
|
|
3983 |
global $wp_filter, $wp_actions;
|
3984 |
|
3985 |
-
if (
|
3986 |
-
is_array(
|
3987 |
-
&&
|
3988 |
-
&& array_key_exists(
|
3989 |
-
&& ! array_key_exists( $action, $wp_filter )
|
3990 |
&& (
|
3991 |
-
substr(
|
3992 |
-
|| substr(
|
3993 |
)
|
3994 |
) {
|
3995 |
-
$message = sprintf(
|
3996 |
-
self::report_error_event(
|
3997 |
-
header(
|
3998 |
exit(1);
|
3999 |
}
|
4000 |
}
|
@@ -4006,313 +4253,272 @@ class SucuriScanHook extends SucuriScanEvent {
|
|
4006 |
*
|
4007 |
* @return integer Either one or zero representing the success or fail of the operation.
|
4008 |
*/
|
4009 |
-
public static function hook_undefined_actions()
|
|
|
4010 |
|
4011 |
$plugin_activate_actions = '(activate|deactivate)(\-selected)?';
|
4012 |
$plugin_update_actions = '(upgrade-plugin|do-plugin-upgrade|update-selected)';
|
4013 |
|
4014 |
// Plugin activation and/or deactivation.
|
4015 |
-
if (
|
4016 |
-
current_user_can( 'activate_plugins' )
|
4017 |
&& (
|
4018 |
-
SucuriScanRequest::get_or_post(
|
4019 |
-
|| SucuriScanRequest::get_or_post(
|
4020 |
)
|
4021 |
) {
|
4022 |
$plugin_list = array();
|
4023 |
$items_affected = array();
|
4024 |
|
4025 |
// Get the action performed through action or action2 params.
|
4026 |
-
$action_d = SucuriScanRequest::get_or_post(
|
4027 |
-
if (
|
4028 |
-
$action_d = SucuriScanRequest::get_or_post(
|
4029 |
}
|
4030 |
$action_d .= 'd';
|
4031 |
|
4032 |
-
if (
|
4033 |
-
|
4034 |
-
&& strpos( $_SERVER['REQUEST_URI'], 'plugins.php' ) !== false
|
4035 |
) {
|
4036 |
-
$plugin_list[] = SucuriScanRequest::get(
|
4037 |
-
}
|
4038 |
-
|
4039 |
-
|
4040 |
-
isset($_POST['checked'])
|
4041 |
-
&& is_array( $_POST['checked'] )
|
4042 |
-
&& ! empty($_POST['checked'])
|
4043 |
) {
|
4044 |
-
$plugin_list = SucuriScanRequest::post(
|
4045 |
-
$action_d = str_replace(
|
4046 |
}
|
4047 |
|
4048 |
-
foreach (
|
4049 |
-
$plugin_info = get_plugin_data(
|
4050 |
|
4051 |
-
if (
|
4052 |
-
!
|
4053 |
-
&& ! empty($plugin_info['Version'])
|
4054 |
) {
|
4055 |
$items_affected[] = sprintf(
|
4056 |
'%s (v%s; %s)',
|
4057 |
-
self::escape(
|
4058 |
-
self::escape(
|
4059 |
-
self::escape(
|
4060 |
);
|
4061 |
}
|
4062 |
}
|
4063 |
|
4064 |
// Report activated/deactivated plugins at once.
|
4065 |
-
if (
|
4066 |
-
$message_tpl = ( count(
|
4067 |
? 'Plugins %s: (multiple entries): %s'
|
4068 |
: 'Plugin %s: %s';
|
4069 |
$message = sprintf(
|
4070 |
$message_tpl,
|
4071 |
$action_d,
|
4072 |
-
@implode(
|
4073 |
);
|
4074 |
-
self::report_warning_event(
|
4075 |
-
self::notify_event(
|
4076 |
}
|
4077 |
-
}
|
4078 |
-
|
4079 |
-
// Plugin update request.
|
4080 |
-
elseif (
|
4081 |
-
current_user_can( 'update_plugins' )
|
4082 |
&& (
|
4083 |
-
SucuriScanRequest::get_or_post(
|
4084 |
-
|| SucuriScanRequest::get_or_post(
|
4085 |
)
|
4086 |
) {
|
4087 |
$plugin_list = array();
|
4088 |
$items_affected = array();
|
4089 |
|
4090 |
-
if (
|
4091 |
-
|
4092 |
-
&& strpos( $_SERVER['REQUEST_URI'], 'wp-admin/update.php' ) !== false
|
4093 |
) {
|
4094 |
-
$plugin_list[] = SucuriScanRequest::get(
|
4095 |
-
}
|
4096 |
-
|
4097 |
-
|
4098 |
-
isset($_POST['checked'])
|
4099 |
-
&& is_array( $_POST['checked'] )
|
4100 |
-
&& ! empty($_POST['checked'])
|
4101 |
) {
|
4102 |
-
$plugin_list = SucuriScanRequest::post(
|
4103 |
}
|
4104 |
|
4105 |
-
foreach (
|
4106 |
-
$plugin_info = get_plugin_data(
|
4107 |
|
4108 |
-
if (
|
4109 |
-
!
|
4110 |
-
&& ! empty($plugin_info['Version'])
|
4111 |
) {
|
4112 |
$items_affected[] = sprintf(
|
4113 |
'%s (v%s; %s)',
|
4114 |
-
self::escape(
|
4115 |
-
self::escape(
|
4116 |
-
self::escape(
|
4117 |
);
|
4118 |
}
|
4119 |
}
|
4120 |
|
4121 |
// Report updated plugins at once.
|
4122 |
-
if (
|
4123 |
-
$message_tpl = ( count(
|
4124 |
? 'Plugins updated: (multiple entries): %s'
|
4125 |
: 'Plugin updated: %s';
|
4126 |
$message = sprintf(
|
4127 |
$message_tpl,
|
4128 |
-
@implode(
|
4129 |
);
|
4130 |
-
self::report_warning_event(
|
4131 |
-
self::notify_event(
|
4132 |
}
|
4133 |
-
}
|
4134 |
-
|
4135 |
-
|
4136 |
-
elseif (
|
4137 |
-
current_user_can( 'install_plugins' )
|
4138 |
-
&& SucuriScanRequest::get( 'action', '(install|upload)-plugin' )
|
4139 |
) {
|
4140 |
-
if (
|
4141 |
-
$plugin = self::escape(
|
4142 |
} else {
|
4143 |
-
$plugin = SucuriScanRequest::get(
|
4144 |
|
4145 |
-
if (
|
4146 |
$plugin = 'Unknown';
|
4147 |
}
|
4148 |
}
|
4149 |
|
4150 |
-
$message = 'Plugin installed: ' . self::escape(
|
4151 |
-
SucuriScanEvent::report_warning_event(
|
4152 |
-
self::notify_event(
|
4153 |
-
}
|
4154 |
-
|
4155 |
-
|
4156 |
-
|
4157 |
-
current_user_can( 'delete_plugins' )
|
4158 |
-
&& SucuriScanRequest::post( 'action', 'delete-selected' )
|
4159 |
-
&& SucuriScanRequest::post( 'verify-delete', '1' )
|
4160 |
) {
|
4161 |
-
$plugin_list = SucuriScanRequest::post(
|
4162 |
$items_affected = array();
|
4163 |
|
4164 |
-
foreach (
|
4165 |
-
$plugin_info = get_plugin_data(
|
4166 |
|
4167 |
-
if (
|
4168 |
-
!
|
4169 |
-
&& ! empty($plugin_info['Version'])
|
4170 |
) {
|
4171 |
$items_affected[] = sprintf(
|
4172 |
'%s (v%s; %s)',
|
4173 |
-
self::escape(
|
4174 |
-
self::escape(
|
4175 |
-
self::escape(
|
4176 |
);
|
4177 |
}
|
4178 |
}
|
4179 |
|
4180 |
// Report deleted plugins at once.
|
4181 |
-
if (
|
4182 |
-
$message_tpl = ( count(
|
4183 |
? 'Plugins deleted: (multiple entries): %s'
|
4184 |
: 'Plugin deleted: %s';
|
4185 |
$message = sprintf(
|
4186 |
$message_tpl,
|
4187 |
-
@implode(
|
4188 |
);
|
4189 |
-
self::report_warning_event(
|
4190 |
-
self::notify_event(
|
4191 |
-
}
|
4192 |
-
}
|
4193 |
-
|
4194 |
-
|
4195 |
-
|
4196 |
-
|
4197 |
-
&&
|
4198 |
-
&& SucuriScanRequest::post( 'plugin', '.+' )
|
4199 |
-
&& SucuriScanRequest::post( 'file', '.+' )
|
4200 |
-
&& strpos( $_SERVER['REQUEST_URI'], 'plugin-editor.php' ) !== false
|
4201 |
) {
|
4202 |
-
$filename = SucuriScanRequest::post(
|
4203 |
-
$message = 'Plugin editor used in: ' . SucuriScan::escape(
|
4204 |
-
self::report_error_event(
|
4205 |
-
self::notify_event(
|
4206 |
-
}
|
4207 |
-
|
4208 |
-
|
4209 |
-
|
4210 |
-
|
4211 |
-
&&
|
4212 |
-
&& SucuriScanRequest::post( 'theme', '.+' )
|
4213 |
-
&& SucuriScanRequest::post( 'file', '.+' )
|
4214 |
-
&& strpos( $_SERVER['REQUEST_URI'], 'theme-editor.php' ) !== false
|
4215 |
) {
|
4216 |
-
$theme_name = SucuriScanRequest::post(
|
4217 |
-
$filename = SucuriScanRequest::post(
|
4218 |
-
$message = 'Theme editor used in: ' . SucuriScan::escape(
|
4219 |
-
self::report_error_event(
|
4220 |
-
self::notify_event(
|
4221 |
-
}
|
4222 |
-
|
4223 |
-
|
4224 |
-
elseif (
|
4225 |
-
current_user_can( 'install_themes' )
|
4226 |
-
&& SucuriScanRequest::get( 'action', 'install-theme' )
|
4227 |
) {
|
4228 |
-
$theme = SucuriScanRequest::get(
|
4229 |
|
4230 |
-
if (
|
4231 |
$theme = 'Unknown';
|
4232 |
}
|
4233 |
|
4234 |
-
$message = 'Theme installed: ' . self::escape(
|
4235 |
-
SucuriScanEvent::report_warning_event(
|
4236 |
-
self::notify_event(
|
4237 |
-
}
|
4238 |
-
|
4239 |
-
|
4240 |
-
|
4241 |
-
current_user_can( 'delete_themes' )
|
4242 |
-
&& SucuriScanRequest::get_or_post( 'action', 'delete' )
|
4243 |
-
&& SucuriScanRequest::get_or_post( 'stylesheet', '.+' )
|
4244 |
) {
|
4245 |
-
$theme = SucuriScanRequest::get(
|
4246 |
|
4247 |
-
if (
|
4248 |
$theme = 'Unknown';
|
4249 |
}
|
4250 |
|
4251 |
-
$message = 'Theme deleted: ' . self::escape(
|
4252 |
-
SucuriScanEvent::report_warning_event(
|
4253 |
-
self::notify_event(
|
4254 |
-
}
|
4255 |
-
|
4256 |
-
|
4257 |
-
|
4258 |
-
current_user_can( 'update_themes' )
|
4259 |
-
&& SucuriScanRequest::get( 'action', '(upgrade-theme|do-theme-upgrade)' )
|
4260 |
-
&& SucuriScanRequest::post( 'checked', '_array' )
|
4261 |
) {
|
4262 |
-
$themes = SucuriScanRequest::post(
|
4263 |
$items_affected = array();
|
4264 |
|
4265 |
-
foreach (
|
4266 |
-
$theme_info = wp_get_theme(
|
4267 |
-
$theme_name = ucwords(
|
4268 |
$theme_version = '0.0';
|
4269 |
|
4270 |
-
if (
|
4271 |
-
$theme_name = $theme_info->get(
|
4272 |
-
$theme_version = $theme_info->get(
|
4273 |
}
|
4274 |
|
4275 |
$items_affected[] = sprintf(
|
4276 |
'%s (v%s; %s)',
|
4277 |
-
self::escape(
|
4278 |
-
self::escape(
|
4279 |
-
self::escape(
|
4280 |
);
|
4281 |
}
|
4282 |
|
4283 |
// Report updated themes at once.
|
4284 |
-
if (
|
4285 |
-
$message_tpl = ( count(
|
4286 |
? 'Themes updated: (multiple entries): %s'
|
4287 |
: 'Theme updated: %s';
|
4288 |
$message = sprintf(
|
4289 |
$message_tpl,
|
4290 |
-
@implode(
|
4291 |
);
|
4292 |
-
self::report_warning_event(
|
4293 |
-
self::notify_event(
|
4294 |
}
|
4295 |
-
}
|
4296 |
-
|
4297 |
-
|
4298 |
-
|
4299 |
-
current_user_can( 'update_core' )
|
4300 |
-
&& SucuriScanRequest::get( 'action', '(do-core-upgrade|do-core-reinstall)' )
|
4301 |
-
&& SucuriScanRequest::post( 'upgrade' )
|
4302 |
) {
|
4303 |
-
$message = 'WordPress updated to version: ' . SucuriScanRequest::post(
|
4304 |
-
self::report_critical_event(
|
4305 |
-
self::notify_event(
|
4306 |
-
}
|
4307 |
-
|
4308 |
-
|
4309 |
-
|
4310 |
-
|
4311 |
-
&& SucuriScanRequest::post( 'action', 'save-widget' )
|
4312 |
-
&& SucuriScanRequest::post( 'id_base' ) !== false
|
4313 |
-
&& SucuriScanRequest::post( 'sidebar' ) !== false
|
4314 |
) {
|
4315 |
-
if (
|
4316 |
$action_d = 'deleted';
|
4317 |
$action_text = 'deleted from';
|
4318 |
} else {
|
@@ -4322,44 +4528,41 @@ class SucuriScanHook extends SucuriScanEvent {
|
|
4322 |
|
4323 |
$message = sprintf(
|
4324 |
'Widget %s (%s) %s %s (#%d; size %dx%d)',
|
4325 |
-
SucuriScanRequest::post(
|
4326 |
-
SucuriScanRequest::post(
|
4327 |
$action_text,
|
4328 |
-
SucuriScanRequest::post(
|
4329 |
-
SucuriScanRequest::post(
|
4330 |
-
SucuriScanRequest::post(
|
4331 |
-
SucuriScanRequest::post(
|
4332 |
);
|
4333 |
|
4334 |
-
self::report_warning_event(
|
4335 |
-
self::notify_event(
|
4336 |
-
}
|
4337 |
-
|
4338 |
-
// Detect any Wordpress settings modification.
|
4339 |
-
elseif (
|
4340 |
-
current_user_can( 'manage_options' )
|
4341 |
&& SucuriScanOption::check_options_nonce()
|
4342 |
) {
|
4343 |
// Get the settings available in the database and compare them with the submission.
|
4344 |
-
$options_changed = SucuriScanOption::what_options_were_changed(
|
4345 |
$options_changed_str = '';
|
4346 |
$options_changed_simple = '';
|
4347 |
$options_changed_count = 0;
|
4348 |
|
4349 |
// Generate the list of options changed.
|
4350 |
-
foreach (
|
4351 |
$options_changed_count += 1;
|
4352 |
$options_changed_str .= sprintf(
|
4353 |
"The value of the option <b>%s</b> was changed from <b>'%s'</b> to <b>'%s'</b>.<br>\n",
|
4354 |
-
self::escape(
|
4355 |
-
self::escape(
|
4356 |
-
self::escape(
|
4357 |
);
|
4358 |
$options_changed_simple .= sprintf(
|
4359 |
"%s: from '%s' to '%s',",
|
4360 |
-
self::escape(
|
4361 |
-
self::escape(
|
4362 |
-
self::escape(
|
4363 |
);
|
4364 |
}
|
4365 |
|
@@ -4368,7 +4571,7 @@ class SucuriScanHook extends SucuriScanEvent {
|
|
4368 |
$page_referer = false;
|
4369 |
|
4370 |
// Check which of these option groups where modified.
|
4371 |
-
switch (
|
4372 |
case 'options':
|
4373 |
$page_referer = 'Global';
|
4374 |
break;
|
@@ -4378,26 +4581,25 @@ class SucuriScanHook extends SucuriScanEvent {
|
|
4378 |
case 'discussion': /* no_break */
|
4379 |
case 'media': /* no_break */
|
4380 |
case 'permalink':
|
4381 |
-
$page_referer = ucwords(
|
4382 |
break;
|
4383 |
default:
|
4384 |
$page_referer = 'Common';
|
4385 |
break;
|
4386 |
}
|
4387 |
|
4388 |
-
if (
|
4389 |
$message = $page_referer . ' settings changed';
|
4390 |
-
SucuriScanEvent::report_error_event(
|
4391 |
'%s: (multiple entries): %s',
|
4392 |
$message,
|
4393 |
-
rtrim(
|
4394 |
-
)
|
4395 |
-
self::notify_event(
|
4396 |
}
|
4397 |
}
|
4398 |
|
4399 |
}
|
4400 |
-
|
4401 |
}
|
4402 |
|
4403 |
/**
|
@@ -4417,10 +4619,10 @@ class SucuriScanHook extends SucuriScanEvent {
|
|
4417 |
* APIs allow the combination of multiple APIs into new applications known as
|
4418 |
* mashups.
|
4419 |
*
|
4420 |
-
* @see
|
4421 |
*/
|
4422 |
-
class SucuriScanAPI extends SucuriScanOption
|
4423 |
-
|
4424 |
/**
|
4425 |
* Check whether the SSL certificates will be verified while executing a HTTP
|
4426 |
* request or not. This is only for customization of the administrator, in fact
|
@@ -4428,17 +4630,34 @@ class SucuriScanAPI extends SucuriScanOption {
|
|
4428 |
*
|
4429 |
* @return boolean Whether the SSL certs will be verified while sending a request.
|
4430 |
*/
|
4431 |
-
public static function
|
4432 |
-
|
|
|
4433 |
}
|
4434 |
|
4435 |
/**
|
4436 |
* Seconds before consider a HTTP request as timeout.
|
4437 |
*
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4438 |
* @return integer Seconds to consider a HTTP request timeout.
|
4439 |
*/
|
4440 |
-
public static function
|
4441 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4442 |
}
|
4443 |
|
4444 |
/**
|
@@ -4446,22 +4665,21 @@ class SucuriScanAPI extends SucuriScanOption {
|
|
4446 |
*
|
4447 |
* @return string An user-agent for the HTTP requests.
|
4448 |
*/
|
4449 |
-
private static function
|
4450 |
-
|
|
|
4451 |
'WordPress/%s; %s',
|
4452 |
self::site_version(),
|
4453 |
self::get_domain()
|
4454 |
);
|
4455 |
-
|
4456 |
-
return $user_agent;
|
4457 |
}
|
4458 |
|
4459 |
/**
|
4460 |
* Retrieves a URL using a changeable HTTP method, returning results in an
|
4461 |
* array. Results include HTTP headers and content.
|
4462 |
*
|
4463 |
-
* @see
|
4464 |
-
* @see
|
4465 |
*
|
4466 |
* @param string $url The target URL where the request will be sent.
|
4467 |
* @param string $method HTTP method that will be used to send the request.
|
@@ -4469,52 +4687,53 @@ class SucuriScanAPI extends SucuriScanOption {
|
|
4469 |
* @param array $args Request arguments like the timeout, redirections, headers, cookies, etc.
|
4470 |
* @return array Response object after the HTTP request is executed.
|
4471 |
*/
|
4472 |
-
private static function
|
4473 |
-
|
|
|
4474 |
return false;
|
4475 |
}
|
4476 |
|
4477 |
$req_args = array(
|
4478 |
'method' => $method,
|
4479 |
-
'timeout' => self::
|
4480 |
'redirection' => 2,
|
4481 |
'httpversion' => '1.0',
|
4482 |
-
'user-agent' => self::
|
4483 |
'blocking' => true,
|
4484 |
'headers' => array(),
|
4485 |
'cookies' => array(),
|
4486 |
'compress' => false,
|
4487 |
'decompress' => false,
|
4488 |
-
'sslverify' => self::
|
4489 |
);
|
4490 |
|
4491 |
// Update the request arguments with the values passed tot he function.
|
4492 |
-
foreach (
|
4493 |
-
if (
|
4494 |
-
$req_args[
|
4495 |
}
|
4496 |
}
|
4497 |
|
4498 |
// Add random request parameter to avoid request reset.
|
4499 |
-
if (
|
4500 |
$params['time'] = time();
|
4501 |
}
|
4502 |
|
4503 |
-
if (
|
4504 |
-
if (
|
4505 |
-
$url = sprintf(
|
4506 |
}
|
4507 |
|
4508 |
-
$response = wp_remote_get(
|
4509 |
-
} elseif (
|
4510 |
$req_args['body'] = $params;
|
4511 |
-
$response = wp_remote_post(
|
4512 |
} else {
|
4513 |
$response = false;
|
4514 |
-
SucuriScanInterface::error(
|
4515 |
}
|
4516 |
|
4517 |
-
return self::
|
4518 |
}
|
4519 |
|
4520 |
/**
|
@@ -4523,10 +4742,9 @@ class SucuriScanAPI extends SucuriScanOption {
|
|
4523 |
* @param string $api_key An unique string to identify this installation.
|
4524 |
* @return boolean True if the API key is valid, false otherwise.
|
4525 |
*/
|
4526 |
-
private static function
|
4527 |
-
|
4528 |
-
|
4529 |
-
return (bool) ( @preg_match( $pattern, $api_key ) );
|
4530 |
}
|
4531 |
|
4532 |
/**
|
@@ -4536,19 +4754,20 @@ class SucuriScanAPI extends SucuriScanOption {
|
|
4536 |
* @param boolean $validate Whether the format of the key should be validated before store it.
|
4537 |
* @return boolean Either true or false if the key was saved successfully or not respectively.
|
4538 |
*/
|
4539 |
-
public static function
|
4540 |
-
|
4541 |
-
|
4542 |
-
|
|
|
4543 |
return false;
|
4544 |
}
|
4545 |
}
|
4546 |
|
4547 |
-
if (
|
4548 |
-
SucuriScanEvent::notify_event(
|
4549 |
}
|
4550 |
|
4551 |
-
return self::update_option(
|
4552 |
}
|
4553 |
|
4554 |
/**
|
@@ -4556,12 +4775,12 @@ class SucuriScanAPI extends SucuriScanOption {
|
|
4556 |
*
|
4557 |
* @return string|boolean The API key or false if it does not exists.
|
4558 |
*/
|
4559 |
-
public static function
|
4560 |
-
|
|
|
4561 |
|
4562 |
-
if (
|
4563 |
-
|
4564 |
-
&& self::is_valid_key( $api_key )
|
4565 |
) {
|
4566 |
return $api_key;
|
4567 |
}
|
@@ -4578,24 +4797,25 @@ class SucuriScanAPI extends SucuriScanOption {
|
|
4578 |
*
|
4579 |
* @return array|boolean false if the key is invalid or not present, an array otherwise.
|
4580 |
*/
|
4581 |
-
public static function
|
|
|
4582 |
$option_name = ':cloudproxy_apikey';
|
4583 |
-
$api_key = self::get_option(
|
4584 |
|
4585 |
// Check if the cloudproxy-waf plugin was previously installed.
|
4586 |
-
if (
|
4587 |
-
$api_key = self::get_option(
|
4588 |
|
4589 |
-
if (
|
4590 |
-
self::update_option(
|
4591 |
-
self::delete_option(
|
4592 |
}
|
4593 |
}
|
4594 |
|
4595 |
// Check the validity of the API key.
|
4596 |
-
$match = self::
|
4597 |
|
4598 |
-
if (
|
4599 |
return array(
|
4600 |
'string' => $match[1].'/'.$match[2],
|
4601 |
'k' => $match[1],
|
@@ -4613,11 +4833,12 @@ class SucuriScanAPI extends SucuriScanOption {
|
|
4613 |
* @param boolean $return_match Whether the parts of the API key must be returned or not.
|
4614 |
* @return boolean true if the API key specified is valid, false otherwise.
|
4615 |
*/
|
4616 |
-
public static function
|
|
|
4617 |
$pattern = '/^([a-z0-9]{32})\/([a-z0-9]{32})$/';
|
4618 |
|
4619 |
-
if (
|
4620 |
-
if (
|
4621 |
return $match;
|
4622 |
}
|
4623 |
|
@@ -4636,24 +4857,23 @@ class SucuriScanAPI extends SucuriScanOption {
|
|
4636 |
* @param array $args Request arguments like the timeout, redirections, headers, cookies, etc.
|
4637 |
* @return array Response object after the HTTP request is executed.
|
4638 |
*/
|
4639 |
-
public static function
|
|
|
4640 |
$url = SUCURISCAN_API;
|
4641 |
$params[ SUCURISCAN_API_VERSION ] = 1;
|
4642 |
$params['p'] = 'wordpress';
|
4643 |
|
4644 |
-
if (
|
4645 |
-
$api_key = self::
|
4646 |
|
4647 |
-
if (
|
4648 |
return false;
|
4649 |
}
|
4650 |
|
4651 |
$params['k'] = $api_key;
|
4652 |
}
|
4653 |
|
4654 |
-
|
4655 |
-
|
4656 |
-
return $response;
|
4657 |
}
|
4658 |
|
4659 |
/**
|
@@ -4663,29 +4883,28 @@ class SucuriScanAPI extends SucuriScanOption {
|
|
4663 |
* @param array $params Parameters for the request defined in an associative array of key-value.
|
4664 |
* @return array Response object after the HTTP request is executed.
|
4665 |
*/
|
4666 |
-
public static function
|
|
|
4667 |
$send_request = false;
|
4668 |
|
4669 |
-
if (
|
4670 |
$send_request = true;
|
4671 |
} else {
|
4672 |
-
$api_key = self::
|
4673 |
|
4674 |
-
if (
|
4675 |
$send_request = true;
|
4676 |
$params['k'] = $api_key['k'];
|
4677 |
$params['s'] = $api_key['s'];
|
4678 |
}
|
4679 |
}
|
4680 |
|
4681 |
-
if (
|
4682 |
$url = SUCURISCAN_CLOUDPROXY_API;
|
4683 |
$params[ SUCURISCAN_CLOUDPROXY_API_VERSION ] = 1;
|
4684 |
-
unset(
|
4685 |
-
|
4686 |
-
$response = self::api_call( $url, $method, $params );
|
4687 |
|
4688 |
-
return $
|
4689 |
}
|
4690 |
|
4691 |
return false;
|
@@ -4699,16 +4918,17 @@ class SucuriScanAPI extends SucuriScanOption {
|
|
4699 |
* @param array $args Request arguments like the timeout, redirections, headers, cookies, etc.
|
4700 |
* @return array Response object with some modifications.
|
4701 |
*/
|
4702 |
-
private static function
|
|
|
4703 |
/**
|
4704 |
* Convert the error message generated by the code base functions after the HTTP
|
4705 |
* request is executed to a valid response object that will allow this code
|
4706 |
* process the data according to the specified standards.
|
4707 |
*/
|
4708 |
-
if (
|
4709 |
// Extract information from the error object.
|
4710 |
$error_message = $response->get_error_message();
|
4711 |
-
$request_action = isset(
|
4712 |
|
4713 |
// Build a fake request response with custom data.
|
4714 |
$data_set = array(
|
@@ -4722,11 +4942,11 @@ class SucuriScanAPI extends SucuriScanOption {
|
|
4722 |
|
4723 |
// Build the response object and encode data.
|
4724 |
$response = array();
|
4725 |
-
$response['body'] = json_encode(
|
4726 |
-
$response['headers']['date'] = date(
|
4727 |
$response['headers']['connection'] = 'close';
|
4728 |
$response['headers']['content-type'] = 'application/json';
|
4729 |
-
$response['headers']['content-length'] = strlen(
|
4730 |
$response['response']['code'] = 500;
|
4731 |
$response['response']['message'] = 'ERROR';
|
4732 |
}
|
@@ -4742,23 +4962,33 @@ class SucuriScanAPI extends SucuriScanOption {
|
|
4742 |
* they will see extra information explaining the response and how to proceed
|
4743 |
* with it.
|
4744 |
*/
|
4745 |
-
if (
|
4746 |
-
|
4747 |
-
&& array_key_exists(
|
4748 |
-
&& array_key_exists(
|
4749 |
-
&& array_key_exists( 'response', $response )
|
4750 |
) {
|
|
|
4751 |
$response['body_raw'] = $response['body'];
|
4752 |
|
4753 |
-
//
|
4754 |
-
|
4755 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4756 |
&& $response['headers']['content-type'] == 'application/json'
|
4757 |
) {
|
4758 |
-
$assoc = (
|
4759 |
-
$response['body'] = @json_decode(
|
4760 |
-
|
4761 |
-
|
4762 |
$response['body_raw'] = null;
|
4763 |
$response['body'] = 'ERROR:Serialized data is not supported.';
|
4764 |
}
|
@@ -4774,129 +5004,179 @@ class SucuriScanAPI extends SucuriScanOption {
|
|
4774 |
* generic variables and types, in case of an error a notification will appears
|
4775 |
* in the administrator panel explaining the result of the operation.
|
4776 |
*
|
4777 |
-
* @param array $response
|
4778 |
-
* @
|
|
|
4779 |
*/
|
4780 |
-
private static function
|
4781 |
-
|
4782 |
-
|
4783 |
-
|
4784 |
-
|
|
|
|
|
|
|
4785 |
return true;
|
4786 |
} else {
|
4787 |
-
$
|
4788 |
-
|
4789 |
-
// Check whether the message list is empty or not.
|
4790 |
-
if ( isset($response['body']->messages[0]) ) {
|
4791 |
-
$action_message = $response['body']->messages[0] . '.';
|
4792 |
-
}
|
4793 |
-
|
4794 |
-
// Keep a copy of the original API response message.
|
4795 |
-
$raw_message = $action_message;
|
4796 |
-
|
4797 |
-
// Special response for invalid API keys.
|
4798 |
-
if ( stripos( $raw_message, 'log file not found' ) !== false ) {
|
4799 |
-
SucuriScanOption::delete_option( ':api_key' );
|
4800 |
-
|
4801 |
-
$action_message .= ' This generally happens when you add an invalid API key, the'
|
4802 |
-
. ' key will be deleted automatically to hide these warnings, if you want to'
|
4803 |
-
. ' recover it go to the settings page and use the recover button to send the'
|
4804 |
-
. ' key to your email address.';
|
4805 |
-
}
|
4806 |
-
|
4807 |
-
// Special response for invalid CloudProxy API keys.
|
4808 |
-
if ( stripos( $raw_message, 'wrong api key' ) !== false ) {
|
4809 |
-
SucuriScanOption::delete_option( ':cloudproxy_apikey' );
|
4810 |
-
SucuriScanOption::delete_option( ':revproxy' );
|
4811 |
-
|
4812 |
-
$action_message .= ' The CloudProxy API key does not seems to be valid.';
|
4813 |
-
}
|
4814 |
-
|
4815 |
-
// Special response for connection time outs.
|
4816 |
-
if ( stripos( $raw_message, 'timed out' ) !== false ) {
|
4817 |
-
$current_timeout = SucuriScanOption::get_option( ':request_timeout' );
|
4818 |
-
|
4819 |
-
if ( $current_timeout < 300 ) {
|
4820 |
-
SucuriScanOption::update_option( ':request_timeout', 300 );
|
4821 |
-
}
|
4822 |
-
|
4823 |
-
$action_message .= ' This generally happens when the API service fails to respond'
|
4824 |
-
. ' in time, you currently have configured the plugin to discard the network'
|
4825 |
-
. ' connection after ' . $current_timeout . ' seconds. Wait a few minutes until'
|
4826 |
-
. ' the issue is resolved by itself, or change the timeout limit from the general'
|
4827 |
-
. ' settings page of the plugin, the option is named "API request timeout".';
|
4828 |
-
}
|
4829 |
-
|
4830 |
-
// Stop SSL peer verification on connection failures.
|
4831 |
-
if (
|
4832 |
-
stripos( $raw_message, 'no alternative certificate' )
|
4833 |
-
|| stripos( $raw_message, 'error setting certificate' )
|
4834 |
-
) {
|
4835 |
-
SucuriScanOption::update_option( ':verify_ssl_cert', 'false' );
|
4836 |
-
|
4837 |
-
$action_message .= 'There were some issues with the SSL certificate either in this'
|
4838 |
-
. ' server or with the remote API service. The automatic verification of the'
|
4839 |
-
. ' certificates has been deactivated to reduce the noise during the execution'
|
4840 |
-
. ' of the HTTP requests.';
|
4841 |
-
}
|
4842 |
-
|
4843 |
-
SucuriScanInterface::error(
|
4844 |
-
sprintf(
|
4845 |
-
'(%d) %s: %s',
|
4846 |
-
SucuriScan::local_time(),
|
4847 |
-
ucwords( $response['body']->action ),
|
4848 |
-
$action_message
|
4849 |
-
)
|
4850 |
-
);
|
4851 |
}
|
4852 |
} else {
|
4853 |
-
|
4854 |
}
|
4855 |
} else {
|
4856 |
-
$
|
4857 |
|
4858 |
-
if (
|
4859 |
-
isset($response['response'])
|
4860 |
&& isset($response['response']['message'])
|
4861 |
&& isset($response['response']['code'])
|
4862 |
&& $response['response']['code'] !== 200
|
4863 |
) {
|
4864 |
-
$
|
4865 |
'(%s) %s',
|
4866 |
$response['response']['code'],
|
4867 |
$response['response']['message']
|
4868 |
);
|
4869 |
}
|
4870 |
|
4871 |
-
|
4872 |
}
|
4873 |
}
|
4874 |
|
|
|
|
|
|
|
|
|
4875 |
return false;
|
4876 |
}
|
4877 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4878 |
/**
|
4879 |
* Send a request to the API to register this site.
|
4880 |
*
|
4881 |
* @param string $email Optional email address for the registration.
|
4882 |
* @return boolean True if the API key was generated, false otherwise.
|
4883 |
*/
|
4884 |
-
public static function
|
4885 |
-
|
|
|
4886 |
$email = self::get_site_email();
|
4887 |
}
|
4888 |
|
4889 |
-
$response = self::
|
4890 |
'e' => $email,
|
4891 |
's' => self::get_domain(),
|
4892 |
'a' => 'register_site',
|
4893 |
-
), false
|
4894 |
|
4895 |
-
if (
|
4896 |
-
self::
|
4897 |
SucuriScanEvent::schedule_task();
|
4898 |
-
SucuriScanEvent::notify_event(
|
4899 |
-
SucuriScanInterface::info(
|
4900 |
|
4901 |
return true;
|
4902 |
}
|
@@ -4909,18 +5189,19 @@ class SucuriScanAPI extends SucuriScanOption {
|
|
4909 |
*
|
4910 |
* @return boolean true if the API key was sent to the administrator email, false otherwise.
|
4911 |
*/
|
4912 |
-
public static function
|
|
|
4913 |
$clean_domain = self::get_domain();
|
4914 |
|
4915 |
-
$response = self::
|
4916 |
'e' => self::get_site_email(),
|
4917 |
's' => $clean_domain,
|
4918 |
'a' => 'recover_key',
|
4919 |
-
), false
|
4920 |
|
4921 |
-
if (
|
4922 |
-
SucuriScanEvent::notify_event(
|
4923 |
-
SucuriScanInterface::info(
|
4924 |
|
4925 |
return true;
|
4926 |
}
|
@@ -4934,17 +5215,25 @@ class SucuriScanAPI extends SucuriScanOption {
|
|
4934 |
* settings or files in the administrator panel, or a notification generated by
|
4935 |
* this plugin.
|
4936 |
*
|
4937 |
-
* @param string $event
|
4938 |
-
* @
|
|
|
|
|
4939 |
*/
|
4940 |
-
public static function
|
4941 |
-
|
4942 |
-
|
4943 |
-
|
4944 |
-
|
4945 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
4946 |
|
4947 |
-
if (
|
4948 |
return true;
|
4949 |
}
|
4950 |
}
|
@@ -4952,21 +5241,63 @@ class SucuriScanAPI extends SucuriScanOption {
|
|
4952 |
return false;
|
4953 |
}
|
4954 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4955 |
/**
|
4956 |
* Retrieve all the event logs registered by the API service.
|
4957 |
*
|
4958 |
* @return array The object with the data returned from the API service.
|
4959 |
*/
|
4960 |
-
public static function
|
|
|
4961 |
// Get the total number of lines in the logs.
|
4962 |
-
$response = self::
|
4963 |
'a' => 'get_logs',
|
4964 |
'l' => 0,
|
4965 |
-
)
|
4966 |
|
4967 |
// If success continue with the retrieval of the logs data.
|
4968 |
-
if (
|
4969 |
-
return self::
|
4970 |
}
|
4971 |
|
4972 |
return false;
|
@@ -4978,21 +5309,22 @@ class SucuriScanAPI extends SucuriScanOption {
|
|
4978 |
* @param integer $lines How many lines from the log file will be retrieved.
|
4979 |
* @return string The response of the API service.
|
4980 |
*/
|
4981 |
-
public static function
|
4982 |
-
|
|
|
4983 |
'a' => 'get_logs',
|
4984 |
'l' => $lines,
|
4985 |
-
)
|
4986 |
|
4987 |
-
if (
|
4988 |
$response['body']->output_data = array();
|
4989 |
$log_pattern = '/^([0-9\-]+) ([0-9:]+) (\S+) : (.+)/';
|
4990 |
$extra_pattern = '/(.+ \(multiple entries\):) (.+)/';
|
4991 |
-
$generic_pattern = '/^@?([A-Z][a-z]{3,7}): ([
|
4992 |
$auth_pattern = '/^User authentication (succeeded|failed): ([^<;]+)/';
|
4993 |
|
4994 |
-
foreach (
|
4995 |
-
if (
|
4996 |
$log_data = array(
|
4997 |
'event' => 'notice',
|
4998 |
'date' => '',
|
@@ -5001,37 +5333,37 @@ class SucuriScanAPI extends SucuriScanOption {
|
|
5001 |
'timestamp' => 0,
|
5002 |
'account' => $log_match[3],
|
5003 |
'username' => 'system',
|
5004 |
-
'remote_addr' => '
|
5005 |
'message' => $log_match[4],
|
5006 |
'file_list' => false,
|
5007 |
'file_list_count' => 0,
|
5008 |
);
|
5009 |
|
5010 |
// Extract and fix the date and time using the Eastern time zone.
|
5011 |
-
$datetime = sprintf(
|
5012 |
-
$log_data['timestamp'] = strtotime(
|
5013 |
-
$log_data['datetime'] = date(
|
5014 |
-
$log_data['date'] = date(
|
5015 |
-
$log_data['time'] = date(
|
5016 |
|
5017 |
// Extract more information from the generic audit logs.
|
5018 |
-
$log_data['message'] = str_replace(
|
5019 |
|
5020 |
-
if (
|
5021 |
-
$log_data['event'] = strtolower(
|
5022 |
-
$log_data['message'] = trim(
|
5023 |
|
5024 |
// Extract the username and remote address from the log.
|
5025 |
-
if (
|
5026 |
-
$username_address = rtrim(
|
5027 |
|
5028 |
// Separate the username from the remote address.
|
5029 |
-
if (
|
5030 |
-
$usip_parts = explode(
|
5031 |
|
5032 |
-
if (
|
5033 |
// Separate the username from the display name.
|
5034 |
-
$log_data['username'] = preg_replace(
|
5035 |
$log_data['remote_addr'] = $usip_parts[1];
|
5036 |
}
|
5037 |
} else {
|
@@ -5046,18 +5378,18 @@ class SucuriScanAPI extends SucuriScanOption {
|
|
5046 |
$log_data['message']
|
5047 |
);
|
5048 |
|
5049 |
-
if (
|
5050 |
$log_data['username'] = $user_match[2];
|
5051 |
}
|
5052 |
}
|
5053 |
|
5054 |
// Extract more information from the special formatted logs.
|
5055 |
-
if (
|
5056 |
$log_data['message'] = $log_extra[1];
|
5057 |
-
$log_extra[2] = str_replace(
|
5058 |
-
$log_extra[2] = str_replace(
|
5059 |
-
$log_data['file_list'] = explode(
|
5060 |
-
$log_data['file_list_count'] = count(
|
5061 |
}
|
5062 |
|
5063 |
$response['body']->output_data[] = $log_data;
|
@@ -5075,8 +5407,9 @@ class SucuriScanAPI extends SucuriScanOption {
|
|
5075 |
*
|
5076 |
* @return array Valid audit event types with their colors.
|
5077 |
*/
|
5078 |
-
public static function
|
5079 |
-
|
|
|
5080 |
'critical' => '#000000',
|
5081 |
'debug' => '#c690ec',
|
5082 |
'error' => '#f27d7d',
|
@@ -5084,8 +5417,6 @@ class SucuriScanAPI extends SucuriScanOption {
|
|
5084 |
'notice' => '#428bca',
|
5085 |
'warning' => '#f0ad4e',
|
5086 |
);
|
5087 |
-
|
5088 |
-
return $event_types;
|
5089 |
}
|
5090 |
|
5091 |
/**
|
@@ -5094,12 +5425,13 @@ class SucuriScanAPI extends SucuriScanOption {
|
|
5094 |
* @param string $event_log Event log that will be processed.
|
5095 |
* @return array List of parts of the event log.
|
5096 |
*/
|
5097 |
-
public static function
|
5098 |
-
|
|
|
5099 |
$event_log = array();
|
5100 |
-
$event_log[] = trim(
|
5101 |
-
$grouped_items = @explode(
|
5102 |
-
$event_log = array_merge(
|
5103 |
}
|
5104 |
|
5105 |
return $event_log;
|
@@ -5111,14 +5443,14 @@ class SucuriScanAPI extends SucuriScanOption {
|
|
5111 |
* @param integer $lines How many lines from the log file will be retrieved.
|
5112 |
* @return array All the information necessary to display the audit logs report.
|
5113 |
*/
|
5114 |
-
public static function
|
5115 |
-
|
|
|
5116 |
|
5117 |
-
if (
|
5118 |
-
$audit_logs
|
5119 |
-
&& property_exists(
|
5120 |
-
&&
|
5121 |
-
&& ! empty($audit_logs->output_data)
|
5122 |
) {
|
5123 |
// Data structure that will be returned.
|
5124 |
$report = array(
|
@@ -5136,66 +5468,67 @@ class SucuriScanAPI extends SucuriScanOption {
|
|
5136 |
);
|
5137 |
|
5138 |
// Get a list of valid audit event types.
|
5139 |
-
$event_types = self::
|
5140 |
-
foreach (
|
5141 |
-
$report['events_per_type'][
|
5142 |
-
$report['event_colors'][] = sprintf(
|
5143 |
}
|
5144 |
|
5145 |
// Collect information for each report chart.
|
5146 |
-
foreach (
|
5147 |
$report['total_events'] += 1;
|
5148 |
|
5149 |
// Increment the number of events for this event type.
|
5150 |
-
if (
|
5151 |
$report['events_per_type'][ $event['event'] ] += 1;
|
5152 |
} else {
|
5153 |
$report['events_per_type'][ $event['event'] ] = 1;
|
5154 |
}
|
5155 |
|
5156 |
// Find the lowest datetime among the filtered events.
|
5157 |
-
if (
|
5158 |
-
$event['timestamp'] <= $report['start_timestamp']
|
5159 |
|| $report['start_timestamp'] === 0
|
5160 |
) {
|
5161 |
$report['start_timestamp'] = $event['timestamp'];
|
5162 |
}
|
5163 |
|
5164 |
// Find the highest datetime among the filtered events.
|
5165 |
-
if (
|
5166 |
$report['end_timestamp'] = $event['timestamp'];
|
5167 |
}
|
5168 |
|
5169 |
// Increment the number of events generated by this user account.
|
5170 |
-
|
5171 |
-
|
|
|
5172 |
} else {
|
5173 |
-
$report['events_per_user'][
|
5174 |
}
|
5175 |
|
5176 |
// Increment the number of events generated from this remote address.
|
5177 |
-
|
5178 |
-
|
|
|
5179 |
} else {
|
5180 |
-
$report['events_per_ipaddress'][
|
5181 |
}
|
5182 |
|
5183 |
// Detect successful and failed user authentications.
|
5184 |
$auth_pattern = '/^User authentication (succeeded|failed):/';
|
5185 |
|
5186 |
-
if (
|
5187 |
-
if (
|
5188 |
$report['events_per_login']['successful'] += 1;
|
5189 |
} else {
|
5190 |
$report['events_per_login']['failed'] += 1;
|
5191 |
}
|
5192 |
-
} elseif (
|
5193 |
// Backward compatibility for previous user login messages.
|
5194 |
$report['events_per_login']['successful'] += 1;
|
5195 |
}
|
5196 |
}
|
5197 |
|
5198 |
-
if (
|
5199 |
return $report;
|
5200 |
}
|
5201 |
}
|
@@ -5212,14 +5545,15 @@ class SucuriScanAPI extends SucuriScanOption {
|
|
5212 |
* @param string $hashes The information gathered after the scanning of the site's files.
|
5213 |
* @return boolean true if the hashes were stored, false otherwise.
|
5214 |
*/
|
5215 |
-
public static function
|
5216 |
-
|
5217 |
-
|
|
|
5218 |
'a' => 'send_hashes',
|
5219 |
'h' => $hashes,
|
5220 |
-
)
|
5221 |
|
5222 |
-
if (
|
5223 |
return true;
|
5224 |
}
|
5225 |
}
|
@@ -5236,16 +5570,17 @@ class SucuriScanAPI extends SucuriScanOption {
|
|
5236 |
* @param boolean $api_key The CloudProxy API key.
|
5237 |
* @return array A hash with the settings of a CloudProxy account.
|
5238 |
*/
|
5239 |
-
public static function
|
5240 |
-
|
|
|
5241 |
|
5242 |
-
if (
|
5243 |
-
$params = array_merge(
|
5244 |
}
|
5245 |
|
5246 |
-
$response = self::
|
5247 |
|
5248 |
-
if (
|
5249 |
return $response['body']->output;
|
5250 |
}
|
5251 |
|
@@ -5258,16 +5593,17 @@ class SucuriScanAPI extends SucuriScanOption {
|
|
5258 |
* @param boolean $api_key The CloudProxy API key.
|
5259 |
* @return string Message explaining the result of the operation.
|
5260 |
*/
|
5261 |
-
public static function
|
|
|
5262 |
$params = array( 'a' => 'clear_cache' );
|
5263 |
|
5264 |
-
if (
|
5265 |
-
$params = array_merge(
|
5266 |
}
|
5267 |
|
5268 |
-
$response = self::
|
5269 |
|
5270 |
-
if (
|
5271 |
return $response['body'];
|
5272 |
}
|
5273 |
|
@@ -5285,28 +5621,31 @@ class SucuriScanAPI extends SucuriScanOption {
|
|
5285 |
* the logs of previous days you will need to add a new parameter to the request
|
5286 |
* URL named "date" with format yyyy-mm-dd.
|
5287 |
*
|
5288 |
-
* @param
|
5289 |
-
* @param string $date
|
5290 |
-
* @
|
|
|
|
|
|
|
5291 |
*/
|
5292 |
-
public static function
|
|
|
5293 |
$params = array(
|
5294 |
'a' => 'audit_trails',
|
5295 |
-
'date' => date
|
|
|
|
|
|
|
5296 |
);
|
5297 |
|
5298 |
-
if (
|
5299 |
-
$params
|
5300 |
-
}
|
5301 |
-
|
5302 |
-
if ( $api_key ) {
|
5303 |
-
$params = array_merge( $params, $api_key );
|
5304 |
}
|
5305 |
|
5306 |
-
$response = self::
|
5307 |
|
5308 |
-
if (
|
5309 |
-
return $response['
|
5310 |
}
|
5311 |
|
5312 |
return false;
|
@@ -5316,15 +5655,16 @@ class SucuriScanAPI extends SucuriScanOption {
|
|
5316 |
* Scan a website through the public SiteCheck API [1] for known malware,
|
5317 |
* blacklisting status, website errors, and out-of-date software.
|
5318 |
*
|
5319 |
-
* [1]
|
5320 |
*
|
5321 |
* @param string $domain The clean version of the website's domain.
|
5322 |
* @return object Serialized data of the scanning results for the site specified.
|
5323 |
*/
|
5324 |
-
public static function
|
5325 |
-
|
5326 |
-
|
5327 |
-
$
|
|
|
5328 |
$url,
|
5329 |
'GET',
|
5330 |
array(
|
@@ -5338,7 +5678,7 @@ class SucuriScanAPI extends SucuriScanOption {
|
|
5338 |
)
|
5339 |
);
|
5340 |
|
5341 |
-
if (
|
5342 |
return $response['body'];
|
5343 |
}
|
5344 |
}
|
@@ -5352,8 +5692,9 @@ class SucuriScanAPI extends SucuriScanOption {
|
|
5352 |
* @param array $malware Array with two entries with basic malware information.
|
5353 |
* @return array Detailed information of the malware found by SiteCheck.
|
5354 |
*/
|
5355 |
-
public static function
|
5356 |
-
|
|
|
5357 |
$data_set = array(
|
5358 |
'alert_message' => '',
|
5359 |
'infected_url' => '',
|
@@ -5363,27 +5704,27 @@ class SucuriScanAPI extends SucuriScanOption {
|
|
5363 |
);
|
5364 |
|
5365 |
// Extract the information from the alert message.
|
5366 |
-
$alert_parts = explode(
|
5367 |
|
5368 |
-
if (
|
5369 |
$data_set['alert_message'] = $alert_parts[0];
|
5370 |
$data_set['infected_url'] = $alert_parts[1];
|
5371 |
}
|
5372 |
|
5373 |
// Extract the information from the malware message.
|
5374 |
-
$malware_parts = explode(
|
5375 |
|
5376 |
-
if (
|
5377 |
-
if (
|
5378 |
$data_set['malware_type'] = $match[1];
|
5379 |
$data_set['malware_docs'] = $match[2];
|
5380 |
}
|
5381 |
|
5382 |
-
$payload = trim(
|
5383 |
-
$payload = html_entity_decode(
|
5384 |
|
5385 |
-
if (
|
5386 |
-
$data_set['malware_payload'] = trim(
|
5387 |
}
|
5388 |
}
|
5389 |
|
@@ -5399,15 +5740,16 @@ class SucuriScanAPI extends SucuriScanOption {
|
|
5399 |
*
|
5400 |
* @return array A list of the new set of keys generated by WordPress API.
|
5401 |
*/
|
5402 |
-
public static function
|
|
|
5403 |
$pattern = self::secret_key_pattern();
|
5404 |
-
$response = self::
|
5405 |
|
5406 |
-
if (
|
5407 |
$new_keys = array();
|
5408 |
|
5409 |
-
foreach (
|
5410 |
-
$new_keys[
|
5411 |
}
|
5412 |
|
5413 |
return $new_keys;
|
@@ -5419,33 +5761,32 @@ class SucuriScanAPI extends SucuriScanOption {
|
|
5419 |
/**
|
5420 |
* Retrieve a list with the checksums of the files in a specific version of WordPress.
|
5421 |
*
|
5422 |
-
* @see Release Archive
|
5423 |
*
|
5424 |
* @param integer $version Valid version number of the WordPress project.
|
5425 |
* @return object Associative object with the relative filepath and the checksums of the project files.
|
5426 |
*/
|
5427 |
-
public static function
|
5428 |
-
|
|
|
5429 |
$language = 'en_US'; /* WPLANG does not works. */
|
5430 |
-
$response = self::
|
5431 |
'version' => $version,
|
5432 |
'locale' => $language,
|
5433 |
));
|
5434 |
|
5435 |
-
if (
|
5436 |
-
if (
|
5437 |
$json_data = $response['body'];
|
5438 |
} else {
|
5439 |
-
$json_data = @json_decode(
|
5440 |
}
|
5441 |
|
5442 |
-
if (
|
5443 |
-
|
5444 |
-
&& ! empty($json_data->checksums)
|
5445 |
) {
|
5446 |
-
if (
|
5447 |
-
|
5448 |
-
&& property_exists( $json_data->checksums, $version )
|
5449 |
) {
|
5450 |
$checksums = $json_data->checksums->{$version};
|
5451 |
} else {
|
@@ -5453,7 +5794,7 @@ class SucuriScanAPI extends SucuriScanOption {
|
|
5453 |
}
|
5454 |
|
5455 |
// Check whether the list of file is an object.
|
5456 |
-
if (
|
5457 |
return (array) $checksums;
|
5458 |
}
|
5459 |
}
|
@@ -5469,16 +5810,17 @@ class SucuriScanAPI extends SucuriScanOption {
|
|
5469 |
*
|
5470 |
* @return array Key is the plugin file path and the value is an array of the plugin data.
|
5471 |
*/
|
5472 |
-
public static function
|
|
|
5473 |
// Check if the cache library was loaded.
|
5474 |
-
$can_cache = class_exists(
|
5475 |
|
5476 |
-
if (
|
5477 |
-
$cache = new SucuriScanCache(
|
5478 |
-
$cached_data = $cache->get(
|
5479 |
|
5480 |
// Return the previously cached results of this function.
|
5481 |
-
if (
|
5482 |
return $cached_data;
|
5483 |
}
|
5484 |
}
|
@@ -5489,7 +5831,7 @@ class SucuriScanAPI extends SucuriScanOption {
|
|
5489 |
$wp_market = 'https://wordpress.org/plugins/%s/';
|
5490 |
|
5491 |
// Loop through each plugin data and complement its information with more attributes.
|
5492 |
-
foreach (
|
5493 |
// Default values for the plugin extra attributes.
|
5494 |
$repository = '';
|
5495 |
$repository_name = '';
|
@@ -5502,26 +5844,24 @@ class SucuriScanAPI extends SucuriScanOption {
|
|
5502 |
* official WordPress server it means that it is premium and is being
|
5503 |
* distributed by an independent developer.
|
5504 |
*/
|
5505 |
-
if (
|
5506 |
-
|
5507 |
-
&& preg_match( $pattern, $plugin_data['PluginURI'], $match )
|
5508 |
) {
|
5509 |
$repository = $match[0];
|
5510 |
$repository_name = $match[2];
|
5511 |
$is_free_plugin = true;
|
5512 |
} else {
|
5513 |
-
if (
|
5514 |
-
$plugin_path_parts = explode(
|
5515 |
} else {
|
5516 |
-
$plugin_path_parts = explode(
|
5517 |
}
|
5518 |
|
5519 |
-
if (
|
5520 |
-
$possible_repository = sprintf(
|
5521 |
-
$resp = wp_remote_head(
|
5522 |
|
5523 |
-
if (
|
5524 |
-
! is_wp_error( $resp )
|
5525 |
&& $resp['response']['code'] == 200
|
5526 |
) {
|
5527 |
$repository = $possible_repository;
|
@@ -5532,26 +5872,26 @@ class SucuriScanAPI extends SucuriScanOption {
|
|
5532 |
}
|
5533 |
|
5534 |
// Complement the plugin's information with these attributes.
|
5535 |
-
$plugins[
|
5536 |
-
$plugins[
|
5537 |
-
$plugins[
|
5538 |
-
$plugins[
|
5539 |
-
$plugins[
|
5540 |
-
$plugins[
|
5541 |
-
$plugins[
|
5542 |
|
5543 |
-
if (
|
5544 |
-
$plugins[
|
5545 |
}
|
5546 |
|
5547 |
-
if (
|
5548 |
-
$plugins[
|
5549 |
}
|
5550 |
}
|
5551 |
|
5552 |
-
if (
|
5553 |
// Add the information of the plugins to the file-based cache.
|
5554 |
-
$cache->add(
|
5555 |
}
|
5556 |
|
5557 |
return $plugins;
|
@@ -5574,13 +5914,14 @@ class SucuriScanAPI extends SucuriScanOption {
|
|
5574 |
* @param string $plugin Frienly name of the plugin.
|
5575 |
* @return object Object on success, WP_Error on failure.
|
5576 |
*/
|
5577 |
-
public static function
|
5578 |
-
|
5579 |
-
|
5580 |
-
$
|
|
|
5581 |
|
5582 |
-
if (
|
5583 |
-
if (
|
5584 |
return $response['body'];
|
5585 |
}
|
5586 |
}
|
@@ -5594,28 +5935,28 @@ class SucuriScanAPI extends SucuriScanOption {
|
|
5594 |
* the content of the file is determined by the tags defined using the site
|
5595 |
* version specified. Only official core files are allowed to fetch.
|
5596 |
*
|
5597 |
-
* @see
|
5598 |
-
* @see
|
5599 |
-
* @see
|
5600 |
*
|
5601 |
* @param string $filepath Relative file path of a project core file.
|
5602 |
* @param string $version Optional site version, default will be the global version number.
|
5603 |
* @return string Full content of the official file retrieved, false if the file was not found.
|
5604 |
*/
|
5605 |
-
public static function
|
5606 |
-
|
5607 |
-
|
|
|
5608 |
$version = self::site_version();
|
5609 |
}
|
5610 |
|
5611 |
-
$url = sprintf(
|
5612 |
-
$response = self::
|
5613 |
|
5614 |
-
if (
|
5615 |
-
if (
|
5616 |
-
isset($response['headers']['content-length'])
|
5617 |
&& $response['headers']['content-length'] > 0
|
5618 |
-
&& is_string(
|
5619 |
) {
|
5620 |
return $response['body'];
|
5621 |
}
|
@@ -5624,7 +5965,6 @@ class SucuriScanAPI extends SucuriScanOption {
|
|
5624 |
|
5625 |
return false;
|
5626 |
}
|
5627 |
-
|
5628 |
}
|
5629 |
|
5630 |
/**
|
@@ -5635,15 +5975,17 @@ class SucuriScanAPI extends SucuriScanOption {
|
|
5635 |
* will be sent to the site email address (an address that can be configured in
|
5636 |
* the settings page).
|
5637 |
*/
|
5638 |
-
class SucuriScanMail extends SucuriScanOption
|
|
|
5639 |
|
5640 |
/**
|
5641 |
* Check whether the email notifications will be sent in HTML or Plain/Text.
|
5642 |
*
|
5643 |
* @return boolean Whether the emails will be in HTML or Plain/Text.
|
5644 |
*/
|
5645 |
-
public static function prettify_mails()
|
5646 |
-
|
|
|
5647 |
}
|
5648 |
|
5649 |
/**
|
@@ -5655,15 +5997,15 @@ class SucuriScanMail extends SucuriScanOption {
|
|
5655 |
* @param array $data_set Optional parameter to add more information to the notification.
|
5656 |
* @return boolean Whether the email contents were sent successfully.
|
5657 |
*/
|
5658 |
-
public static function send_mail(
|
|
|
5659 |
$headers = array();
|
5660 |
-
$subject = ucwords(
|
5661 |
$force = false;
|
5662 |
$debug = false;
|
5663 |
|
5664 |
// Check whether the mail will be printed in the site instead of sent.
|
5665 |
-
if (
|
5666 |
-
isset($data_set['Debug'])
|
5667 |
&& $data_set['Debug'] == true
|
5668 |
) {
|
5669 |
$debug = true;
|
@@ -5671,8 +6013,7 @@ class SucuriScanMail extends SucuriScanOption {
|
|
5671 |
}
|
5672 |
|
5673 |
// Check whether the mail will be even if the limit per hour was reached or not.
|
5674 |
-
if (
|
5675 |
-
isset($data_set['Force'])
|
5676 |
&& $data_set['Force'] == true
|
5677 |
) {
|
5678 |
$force = true;
|
@@ -5680,21 +6021,21 @@ class SucuriScanMail extends SucuriScanOption {
|
|
5680 |
}
|
5681 |
|
5682 |
// Check whether the email notifications will be sent in HTML or Plain/Text.
|
5683 |
-
if (
|
5684 |
$headers = array( 'content-type: text/html' );
|
5685 |
$data_set['PrettifyType'] = 'pretty';
|
5686 |
} else {
|
5687 |
-
$message = strip_tags(
|
5688 |
}
|
5689 |
|
5690 |
-
if (
|
5691 |
-
$message = self::prettify_mail(
|
5692 |
|
5693 |
-
if (
|
5694 |
die($message);
|
5695 |
}
|
5696 |
|
5697 |
-
$subject = self::get_email_subject(
|
5698 |
|
5699 |
/**
|
5700 |
* WordPress uses a library named PHPMailer [1] to send emails through the
|
@@ -5710,17 +6051,17 @@ class SucuriScanMail extends SucuriScanOption {
|
|
5710 |
*
|
5711 |
* @var boolean
|
5712 |
*/
|
5713 |
-
if (
|
5714 |
-
$mail_sent = wp_mail(
|
5715 |
} else {
|
5716 |
-
$headers = implode(
|
5717 |
-
$mail_sent = @mail(
|
5718 |
}
|
5719 |
|
5720 |
-
if (
|
5721 |
-
$emails_sent_num = (int) self::get_option(
|
5722 |
-
self::update_option(
|
5723 |
-
self::update_option(
|
5724 |
|
5725 |
return true;
|
5726 |
}
|
@@ -5735,24 +6076,25 @@ class SucuriScanMail extends SucuriScanOption {
|
|
5735 |
* @param string $event The reason of the message that will be sent.
|
5736 |
* @return string A text with the subject for the email alert.
|
5737 |
*/
|
5738 |
-
private static function get_email_subject(
|
5739 |
-
|
|
|
5740 |
|
5741 |
/**
|
5742 |
* Probably a bad value in the options table. Delete the entry from the database
|
5743 |
* and call this function to try again, it will probably fall in an infinite
|
5744 |
* loop, but this is the easiest way to control this procedure.
|
5745 |
*/
|
5746 |
-
if (
|
5747 |
-
self::delete_option(
|
5748 |
|
5749 |
-
return self::get_email_subject(
|
5750 |
}
|
5751 |
|
5752 |
-
$subject = strip_tags(
|
5753 |
-
$subject = str_replace(
|
5754 |
-
$subject = str_replace(
|
5755 |
-
$subject = str_replace(
|
5756 |
|
5757 |
/**
|
5758 |
* Extract user data from the current session.
|
@@ -5761,22 +6103,21 @@ class SucuriScanMail extends SucuriScanOption {
|
|
5761 |
* the username and/or email address are necessary to build the email subject,
|
5762 |
* otherwise this operation may delay the sending of the alerts.
|
5763 |
*/
|
5764 |
-
if (
|
5765 |
$user = wp_get_current_user();
|
5766 |
$username = 'unknown';
|
5767 |
$eaddress = 'unknown';
|
5768 |
|
5769 |
-
if (
|
5770 |
-
$user
|
5771 |
-
&& isset(
|
5772 |
-
&& isset( $user->user_email )
|
5773 |
) {
|
5774 |
$username = $user->user_login;
|
5775 |
$eaddress = $user->user_email;
|
5776 |
}
|
5777 |
|
5778 |
-
$subject = str_replace(
|
5779 |
-
$subject = str_replace(
|
5780 |
}
|
5781 |
|
5782 |
return $subject;
|
@@ -5790,33 +6131,33 @@ class SucuriScanMail extends SucuriScanOption {
|
|
5790 |
* @param array $data_set Optional parameter to add more information to the notification.
|
5791 |
* @return string The message formatted in a HTML template.
|
5792 |
*/
|
5793 |
-
private static function prettify_mail(
|
|
|
5794 |
$prettify_type = isset($data_set['PrettifyType']) ? $data_set['PrettifyType'] : 'simple';
|
5795 |
$template_name = 'notification-' . $prettify_type;
|
5796 |
$user = wp_get_current_user();
|
5797 |
$display_name = '';
|
5798 |
|
5799 |
-
if (
|
5800 |
-
$user instanceof WP_User
|
5801 |
&& isset($user->user_login)
|
5802 |
-
&& !
|
5803 |
) {
|
5804 |
-
$display_name = sprintf(
|
5805 |
}
|
5806 |
|
5807 |
// Format list of items when the event has multiple entries.
|
5808 |
-
if (
|
5809 |
-
$message_parts = SucuriScanAPI::
|
5810 |
|
5811 |
-
if (
|
5812 |
$message = ( $prettify_type == 'pretty' ) ? $message_parts[0] . '<ul>' : $message_parts[0];
|
5813 |
unset($message_parts[0]);
|
5814 |
|
5815 |
-
foreach (
|
5816 |
-
if (
|
5817 |
-
$message .= sprintf(
|
5818 |
} else {
|
5819 |
-
$message .= sprintf(
|
5820 |
}
|
5821 |
}
|
5822 |
|
@@ -5827,18 +6168,18 @@ class SucuriScanMail extends SucuriScanOption {
|
|
5827 |
$mail_variables = array(
|
5828 |
'TemplateTitle' => 'Sucuri Alert',
|
5829 |
'Subject' => $subject,
|
5830 |
-
'Website' => self::get_option(
|
5831 |
'RemoteAddress' => self::get_remote_addr(),
|
5832 |
'Message' => $message,
|
5833 |
'User' => $display_name,
|
5834 |
'Time' => SucuriScan::current_datetime(),
|
5835 |
);
|
5836 |
|
5837 |
-
foreach (
|
5838 |
$mail_variables[ $var_key ] = $var_value;
|
5839 |
}
|
5840 |
|
5841 |
-
return SucuriScanTemplate::
|
5842 |
}
|
5843 |
|
5844 |
/**
|
@@ -5846,32 +6187,32 @@ class SucuriScanMail extends SucuriScanOption {
|
|
5846 |
*
|
5847 |
* @return boolean Whether the quota emails per hour was reached.
|
5848 |
*/
|
5849 |
-
private static function emails_per_hour_reached()
|
5850 |
-
|
|
|
5851 |
|
5852 |
-
if (
|
5853 |
// Check if we are still in that sixty minutes.
|
5854 |
$current_time = time();
|
5855 |
-
$last_email_at = self::get_option(
|
5856 |
-
$diff_time = abs(
|
5857 |
|
5858 |
-
if (
|
5859 |
// Check if the quantity of emails sent is bigger than the configured.
|
5860 |
-
$emails_sent = (int) self::get_option(
|
5861 |
-
$max_per_hour = intval(
|
5862 |
|
5863 |
-
if (
|
5864 |
return true;
|
5865 |
}
|
5866 |
} else {
|
5867 |
// Reset the counter of emails sent.
|
5868 |
-
self::update_option(
|
5869 |
}
|
5870 |
}
|
5871 |
|
5872 |
return false;
|
5873 |
}
|
5874 |
-
|
5875 |
}
|
5876 |
|
5877 |
/**
|
@@ -5887,8 +6228,8 @@ class SucuriScanMail extends SucuriScanOption {
|
|
5887 |
* generate a large number of "static" (unchanging) web pages in advance, or to
|
5888 |
* produce "dynamic" web pages on demand.
|
5889 |
*/
|
5890 |
-
class SucuriScanTemplate extends SucuriScanRequest
|
5891 |
-
|
5892 |
/**
|
5893 |
* Replace all pseudo-variables from a string of characters.
|
5894 |
*
|
@@ -5896,11 +6237,20 @@ class SucuriScanTemplate extends SucuriScanRequest {
|
|
5896 |
* @param array $params List of pseudo-variables that will be replaced in the template.
|
5897 |
* @return string The content of the template with the pseudo-variables replated.
|
5898 |
*/
|
5899 |
-
private static function
|
5900 |
-
|
5901 |
-
|
5902 |
-
|
5903 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
5904 |
}
|
5905 |
|
5906 |
return $content;
|
@@ -5912,26 +6262,27 @@ class SucuriScanTemplate extends SucuriScanRequest {
|
|
5912 |
/**
|
5913 |
* Gather and generate the information required globally by all the template files.
|
5914 |
*
|
5915 |
-
* @param array $params
|
5916 |
* @return array A complementary list of pseudo-variables for the template files.
|
5917 |
*/
|
5918 |
-
private static function
|
5919 |
-
|
|
|
5920 |
|
5921 |
// Base parameters, required to render all the pages.
|
5922 |
-
$params = self::
|
5923 |
|
5924 |
// Global parameters, used through out all the pages.
|
5925 |
$params['PageTitle'] = isset($params['PageTitle']) ? '('.$params['PageTitle'].')' : '';
|
5926 |
-
$params['PageNonce'] = wp_create_nonce(
|
5927 |
$params['PageStyleClass'] = isset($params['PageStyleClass']) ? $params['PageStyleClass'] : 'base';
|
5928 |
$params['CleanDomain'] = self::get_domain();
|
5929 |
$params['AdminEmails'] = '';
|
5930 |
|
5931 |
// Get a list of admin users for the API key generation.
|
5932 |
-
if (
|
5933 |
$admin_users = SucuriScan::get_users_for_api_key();
|
5934 |
-
$params['AdminEmails'] = self::
|
5935 |
}
|
5936 |
|
5937 |
// Hide the advertisements from the layout.
|
@@ -5944,7 +6295,7 @@ class SucuriScanTemplate extends SucuriScanRequest {
|
|
5944 |
$params['LayoutType'] = 'twocolumns';
|
5945 |
$params['AdsVisibility'] = 'visible';
|
5946 |
$params['ReviewNavbarButton'] = 'hidden';
|
5947 |
-
$params['PageSidebarContent'] = self::
|
5948 |
}
|
5949 |
|
5950 |
return $params;
|
@@ -5956,22 +6307,26 @@ class SucuriScanTemplate extends SucuriScanRequest {
|
|
5956 |
* @param boolean $visible Whether the condition executed returned a positive value or not.
|
5957 |
* @return string A string indicating the visibility of a HTML component.
|
5958 |
*/
|
5959 |
-
public static function visibility(
|
5960 |
-
|
|
|
5961 |
}
|
5962 |
|
5963 |
/**
|
5964 |
* Generate an URL pointing to the page indicated in the function and that must
|
5965 |
* be loaded through the administrator panel.
|
5966 |
*
|
5967 |
-
* @param string
|
5968 |
-
* @
|
|
|
5969 |
*/
|
5970 |
-
public static function
|
5971 |
-
|
|
|
|
|
5972 |
|
5973 |
-
if (
|
5974 |
-
$url_path .= '_' . strtolower(
|
5975 |
}
|
5976 |
|
5977 |
return $url_path;
|
@@ -5984,14 +6339,9 @@ class SucuriScanTemplate extends SucuriScanRequest {
|
|
5984 |
* @param string $page Short name of the page that will be generated.
|
5985 |
* @return string Full string containing the link of the page.
|
5986 |
*/
|
5987 |
-
public static function
|
5988 |
-
|
5989 |
-
|
5990 |
-
if ( ! empty($page) ) {
|
5991 |
-
$url_path .= '_' . strtolower( $page );
|
5992 |
-
}
|
5993 |
-
|
5994 |
-
return $url_path;
|
5995 |
}
|
5996 |
|
5997 |
/**
|
@@ -5999,56 +6349,56 @@ class SucuriScanTemplate extends SucuriScanRequest {
|
|
5999 |
* template files, this will also generate the navigation bar and detect which
|
6000 |
* items in it are selected by the current page.
|
6001 |
*
|
6002 |
-
* @param array $params
|
6003 |
* @return array A complementary list of pseudo-variables for the template files.
|
6004 |
*/
|
6005 |
-
private static function
|
|
|
6006 |
global $sucuriscan_pages;
|
6007 |
|
6008 |
-
$params = is_array(
|
6009 |
-
$sub_pages = is_array(
|
6010 |
|
6011 |
$params['Navbar'] = '';
|
6012 |
$params['CurrentPageFunc'] = '';
|
6013 |
|
6014 |
-
if (
|
6015 |
$params['CurrentPageFunc'] = $_page;
|
6016 |
}
|
6017 |
|
6018 |
-
foreach (
|
6019 |
-
if (
|
6020 |
-
|
6021 |
-
&& SucuriScanOption::is_disabled( ':sitecheck_scanner' )
|
6022 |
) {
|
6023 |
continue;
|
6024 |
}
|
6025 |
|
6026 |
-
$func_parts = explode(
|
6027 |
|
6028 |
-
if (
|
6029 |
$unique_name = $func_parts[1];
|
6030 |
-
$pseudo_var = 'URL.' . ucwords(
|
6031 |
} else {
|
6032 |
$unique_name = '';
|
6033 |
$pseudo_var = 'URL.Home';
|
6034 |
}
|
6035 |
|
6036 |
-
$params[
|
6037 |
|
6038 |
// Copy URL variable and create an Ajax handler.
|
6039 |
$pseudo_var_ajax = 'Ajax' . $pseudo_var;
|
6040 |
-
$params[
|
6041 |
|
6042 |
$navbar_item_css_class = 'nav-tab';
|
6043 |
|
6044 |
-
if (
|
6045 |
-
$navbar_item_css_class .=
|
6046 |
}
|
6047 |
|
6048 |
$params['Navbar'] .= sprintf(
|
6049 |
-
|
6050 |
$navbar_item_css_class,
|
6051 |
-
$params[
|
6052 |
$sub_page_title
|
6053 |
);
|
6054 |
}
|
@@ -6062,16 +6412,17 @@ class SucuriScanTemplate extends SucuriScanRequest {
|
|
6062 |
* of the function.
|
6063 |
*
|
6064 |
* @param string $html The HTML content of a template file with its pseudo-variables parsed.
|
6065 |
-
* @param array $params
|
6066 |
* @return string The formatted HTML content of the base template.
|
6067 |
*/
|
6068 |
-
public static function
|
6069 |
-
|
|
|
6070 |
|
6071 |
-
$params = self::
|
6072 |
$params['PageContent'] = $html;
|
6073 |
|
6074 |
-
return self::
|
6075 |
}
|
6076 |
|
6077 |
/**
|
@@ -6080,54 +6431,59 @@ class SucuriScanTemplate extends SucuriScanRequest {
|
|
6080 |
* of the function.
|
6081 |
*
|
6082 |
* @param string $template Filename of the template that will be used to generate the page.
|
6083 |
-
* @param array $params
|
6084 |
-
* @param boolean $type
|
6085 |
-
* @return string
|
6086 |
-
*/
|
6087 |
-
public static function
|
6088 |
-
|
6089 |
-
|
6090 |
-
|
6091 |
-
$template_path_pattern = '%s/%s/inc/tpl/%s.html.tpl';
|
6092 |
-
break;
|
6093 |
-
case 'snippet':
|
6094 |
-
$template_path_pattern = '%s/%s/inc/tpl/%s.snippet.tpl';
|
6095 |
-
break;
|
6096 |
}
|
6097 |
|
6098 |
-
$
|
6099 |
-
|
6100 |
-
|
|
|
|
|
|
|
|
|
6101 |
|
6102 |
-
if (
|
6103 |
-
$
|
|
|
6104 |
|
6105 |
-
$
|
|
|
6106 |
|
6107 |
-
|
6108 |
-
if ( $_page = self::get( 'page', '_page' ) ) {
|
6109 |
-
$params['CurrentURL'] = admin_url( 'admin.php?page=' . $_page );
|
6110 |
-
} else {
|
6111 |
-
$params['CurrentURL'] = admin_url();
|
6112 |
-
}
|
6113 |
|
6114 |
-
|
6115 |
-
|
6116 |
-
|
6117 |
-
|
6118 |
-
|
6119 |
-
|
6120 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
6121 |
}
|
6122 |
|
6123 |
-
$
|
6124 |
-
|
|
|
6125 |
|
6126 |
-
|
6127 |
-
return $template_content;
|
6128 |
}
|
6129 |
|
6130 |
-
return
|
6131 |
}
|
6132 |
|
6133 |
/**
|
@@ -6136,13 +6492,14 @@ class SucuriScanTemplate extends SucuriScanRequest {
|
|
6136 |
* of the function.
|
6137 |
*
|
6138 |
* @param string $template Filename of the template that will be used to generate the page.
|
6139 |
-
* @param array $params
|
6140 |
* @return string The formatted HTML page after replace all the pseudo-variables.
|
6141 |
*/
|
6142 |
-
public static function
|
6143 |
-
|
|
|
6144 |
|
6145 |
-
return self::
|
6146 |
}
|
6147 |
|
6148 |
/**
|
@@ -6151,10 +6508,11 @@ class SucuriScanTemplate extends SucuriScanRequest {
|
|
6151 |
* of the function.
|
6152 |
*
|
6153 |
* @param string $template Filename of the template that will be used to generate the page.
|
6154 |
-
* @param array $params
|
6155 |
* @return string The formatted HTML page after replace all the pseudo-variables.
|
6156 |
*/
|
6157 |
-
public static function
|
|
|
6158 |
$required = array(
|
6159 |
'Title' => 'Lorem ipsum dolor sit amet',
|
6160 |
'Visibility' => 'visible',
|
@@ -6168,21 +6526,21 @@ class SucuriScanTemplate extends SucuriScanRequest {
|
|
6168 |
proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>',
|
6169 |
);
|
6170 |
|
6171 |
-
if (
|
6172 |
-
$params['Content'] = self::
|
6173 |
}
|
6174 |
|
6175 |
-
foreach (
|
6176 |
-
if (
|
6177 |
-
$params[
|
6178 |
}
|
6179 |
}
|
6180 |
|
6181 |
$params['Visibility'] = 'sucuriscan-' . $params['Visibility'];
|
6182 |
$params['Identifier'] = 'sucuriscan-' . $template . '-modal';
|
6183 |
-
$params = self::
|
6184 |
|
6185 |
-
return self::
|
6186 |
}
|
6187 |
|
6188 |
/**
|
@@ -6191,11 +6549,12 @@ class SucuriScanTemplate extends SucuriScanRequest {
|
|
6191 |
* of the function.
|
6192 |
*
|
6193 |
* @param string $template Filename of the template that will be used to generate the page.
|
6194 |
-
* @param array $params
|
6195 |
* @return string The formatted HTML page after replace all the pseudo-variables.
|
6196 |
*/
|
6197 |
-
public static function
|
6198 |
-
|
|
|
6199 |
}
|
6200 |
|
6201 |
/**
|
@@ -6205,21 +6564,16 @@ class SucuriScanTemplate extends SucuriScanRequest {
|
|
6205 |
* @param string $selected_val Value of the option that will be selected by default.
|
6206 |
* @return string Option list for a select form field.
|
6207 |
*/
|
6208 |
-
public static function
|
|
|
6209 |
$options = '';
|
6210 |
|
6211 |
-
foreach (
|
6212 |
-
$selected_str = '';
|
6213 |
-
|
6214 |
-
if ( $option_name == $selected_val ) {
|
6215 |
-
$selected_str = 'selected="selected"';
|
6216 |
-
}
|
6217 |
-
|
6218 |
$options .= sprintf(
|
6219 |
-
"<option
|
6220 |
-
|
6221 |
-
SucuriScan::escape(
|
6222 |
-
SucuriScan::escape(
|
6223 |
);
|
6224 |
}
|
6225 |
|
@@ -6231,10 +6585,11 @@ class SucuriScanTemplate extends SucuriScanRequest {
|
|
6231 |
*
|
6232 |
* @return integer Page number of the link clicked in a pagination.
|
6233 |
*/
|
6234 |
-
public static function
|
6235 |
-
|
|
|
6236 |
|
6237 |
-
return (
|
6238 |
}
|
6239 |
|
6240 |
/**
|
@@ -6245,36 +6600,40 @@ class SucuriScanTemplate extends SucuriScanRequest {
|
|
6245 |
* @param integer $max_per_page Maximum number of items that will be shown per page.
|
6246 |
* @return string HTML code for a pagination generated using the provided data.
|
6247 |
*/
|
6248 |
-
public static function
|
|
|
6249 |
// Calculate the number of links for the pagination.
|
6250 |
$html_links = '';
|
6251 |
-
$page_number = self::
|
6252 |
-
$max_pages = ceil(
|
6253 |
$extra_url = '';
|
6254 |
|
6255 |
// Fix for inline anchor URLs.
|
6256 |
-
if (
|
6257 |
$base_url = $match[1];
|
6258 |
$extra_url = $match[2];
|
6259 |
}
|
6260 |
|
6261 |
// Generate the HTML links for the pagination.
|
6262 |
-
for (
|
6263 |
$link_class = 'sucuriscan-pagination-link';
|
6264 |
|
6265 |
-
if (
|
6266 |
-
$link_class .=
|
6267 |
}
|
6268 |
|
6269 |
$html_links .= sprintf(
|
6270 |
'<li><a href="%s&paged=%d%s" class="%s">%s</a></li>',
|
6271 |
-
$base_url,
|
|
|
|
|
|
|
|
|
6272 |
);
|
6273 |
}
|
6274 |
|
6275 |
return $html_links;
|
6276 |
}
|
6277 |
-
|
6278 |
}
|
6279 |
|
6280 |
/**
|
@@ -6286,7 +6645,8 @@ class SucuriScanTemplate extends SucuriScanRequest {
|
|
6286 |
* content is then submitted to the remote server and it is stored for future
|
6287 |
* analysis.
|
6288 |
*/
|
6289 |
-
class SucuriScanFSScanner extends SucuriScan
|
|
|
6290 |
|
6291 |
/**
|
6292 |
* Retrieve the last time when the filesystem scan was ran.
|
@@ -6294,19 +6654,20 @@ class SucuriScanFSScanner extends SucuriScan {
|
|
6294 |
* @param boolean $format Whether the timestamp must be formatted as date/time or not.
|
6295 |
* @return string The timestamp of the runtime, or an string with the date/time.
|
6296 |
*/
|
6297 |
-
public static function get_filesystem_runtime(
|
6298 |
-
|
|
|
6299 |
|
6300 |
-
if (
|
6301 |
-
if (
|
6302 |
-
return SucuriScan::datetime(
|
6303 |
}
|
6304 |
|
6305 |
return $runtime;
|
6306 |
}
|
6307 |
|
6308 |
-
if (
|
6309 |
-
return '
|
6310 |
}
|
6311 |
|
6312 |
return false;
|
@@ -6320,8 +6681,9 @@ class SucuriScanFSScanner extends SucuriScan {
|
|
6320 |
*
|
6321 |
* @return boolean Whether the feature to ignore files is enabled or not.
|
6322 |
*/
|
6323 |
-
public static function will_ignore_scanning()
|
6324 |
-
|
|
|
6325 |
}
|
6326 |
|
6327 |
/**
|
@@ -6330,18 +6692,19 @@ class SucuriScanFSScanner extends SucuriScan {
|
|
6330 |
* @param string $directory_path The (full) absolute path of a directory.
|
6331 |
* @return boolean TRUE if the directory path was added to the list, FALSE otherwise.
|
6332 |
*/
|
6333 |
-
public static function ignore_directory(
|
6334 |
-
|
|
|
6335 |
|
6336 |
// Use the checksum of the directory path as the cache key.
|
6337 |
-
$cache_key = md5(
|
6338 |
-
$resource_type = SucuriScanFileInfo::get_resource_type(
|
6339 |
$cache_value = array(
|
6340 |
'directory_path' => $directory_path,
|
6341 |
'ignored_at' => self::local_time(),
|
6342 |
'resource_type' => $resource_type,
|
6343 |
);
|
6344 |
-
$cached = $cache->add(
|
6345 |
|
6346 |
return $cached;
|
6347 |
}
|
@@ -6352,12 +6715,13 @@ class SucuriScanFSScanner extends SucuriScan {
|
|
6352 |
* @param string $directory_path The (full) absolute path of a directory.
|
6353 |
* @return boolean TRUE if the directory path was removed to the list, FALSE otherwise.
|
6354 |
*/
|
6355 |
-
public static function unignore_directory(
|
6356 |
-
|
|
|
6357 |
|
6358 |
// Use the checksum of the directory path as the cache key.
|
6359 |
-
$cache_key = md5(
|
6360 |
-
$removed = $cache->delete(
|
6361 |
|
6362 |
return $removed;
|
6363 |
}
|
@@ -6383,7 +6747,8 @@ class SucuriScanFSScanner extends SucuriScan {
|
|
6383 |
*
|
6384 |
* @return array List of ignored directory paths.
|
6385 |
*/
|
6386 |
-
public static function get_ignored_directories()
|
|
|
6387 |
$response = array(
|
6388 |
'raw' => array(),
|
6389 |
'checksums' => array(),
|
@@ -6391,17 +6756,16 @@ class SucuriScanFSScanner extends SucuriScan {
|
|
6391 |
'ignored_at_list' => array(),
|
6392 |
);
|
6393 |
|
6394 |
-
$cache = new SucuriScanCache(
|
6395 |
$cache_lifetime = 0; // It is not necessary to expire this cache.
|
6396 |
-
$ignored_directories = $cache->
|
6397 |
|
6398 |
-
if (
|
6399 |
$response['raw'] = $ignored_directories;
|
6400 |
|
6401 |
-
foreach (
|
6402 |
-
if (
|
6403 |
-
array_key_exists(
|
6404 |
-
&& array_key_exists( 'ignored_at', $data )
|
6405 |
) {
|
6406 |
$response['checksums'][] = $checksum;
|
6407 |
$response['directories'][] = $data['directory_path'];
|
@@ -6423,7 +6787,8 @@ class SucuriScanFSScanner extends SucuriScan {
|
|
6423 |
*
|
6424 |
* @return array List of ignored and not ignored directories.
|
6425 |
*/
|
6426 |
-
public static function get_ignored_directories_live()
|
|
|
6427 |
$response = array(
|
6428 |
'is_ignored' => array(),
|
6429 |
'is_not_ignored' => array(),
|
@@ -6432,7 +6797,7 @@ class SucuriScanFSScanner extends SucuriScan {
|
|
6432 |
// Get the ignored directories from the cache.
|
6433 |
$ignored_directories = self::get_ignored_directories();
|
6434 |
|
6435 |
-
if (
|
6436 |
$response['is_ignored'] = $ignored_directories['raw'];
|
6437 |
}
|
6438 |
|
@@ -6440,10 +6805,10 @@ class SucuriScanFSScanner extends SucuriScan {
|
|
6440 |
$file_info = new SucuriScanFileInfo();
|
6441 |
$file_info->ignore_files = true;
|
6442 |
$file_info->ignore_directories = true;
|
6443 |
-
$file_info->scan_interface = SucuriScanOption::get_option(
|
6444 |
-
$directory_list = $file_info->get_diretories_only(
|
6445 |
|
6446 |
-
if (
|
6447 |
$response['is_not_ignored'] = $directory_list;
|
6448 |
}
|
6449 |
|
@@ -6456,7 +6821,8 @@ class SucuriScanFSScanner extends SucuriScan {
|
|
6456 |
* @param array $error_logs The content of an error log file, or an array with the lines.
|
6457 |
* @return array List of valid error logs with their attributes separated.
|
6458 |
*/
|
6459 |
-
public static function parse_error_logs(
|
|
|
6460 |
$logs_arr = array();
|
6461 |
$pattern = '/^'
|
6462 |
. '(\[(\S+) ([0-9:]{5,8})( \S+)?\] )?' // Detect date, time, and timezone.
|
@@ -6465,16 +6831,16 @@ class SucuriScanFSScanner extends SucuriScan {
|
|
6465 |
. '(:| on line )([0-9]+)' // Detect line number.
|
6466 |
. '$/';
|
6467 |
|
6468 |
-
if (
|
6469 |
-
$error_logs = explode(
|
6470 |
}
|
6471 |
|
6472 |
-
foreach (
|
6473 |
-
if (
|
6474 |
continue;
|
6475 |
}
|
6476 |
|
6477 |
-
if (
|
6478 |
$data_set = array(
|
6479 |
'date' => '',
|
6480 |
'time' => '',
|
@@ -6491,25 +6857,25 @@ class SucuriScanFSScanner extends SucuriScan {
|
|
6491 |
// Basic attributes from the scrapping.
|
6492 |
$data_set['date'] = $match[2];
|
6493 |
$data_set['time'] = $match[3];
|
6494 |
-
$data_set['time_zone'] = trim(
|
6495 |
-
$data_set['error_type'] = trim(
|
6496 |
-
$data_set['error_message'] = trim(
|
6497 |
-
$data_set['file_path'] = trim(
|
6498 |
$data_set['line_number'] = (int) $match[10];
|
6499 |
|
6500 |
// Additional data from the attributes.
|
6501 |
-
if (
|
6502 |
$data_set['date_time'] = $data_set['date']
|
6503 |
. "\x20" . $data_set['time']
|
6504 |
. "\x20" . $data_set['time_zone'];
|
6505 |
-
$data_set['timestamp'] = strtotime(
|
6506 |
}
|
6507 |
|
6508 |
-
if (
|
6509 |
$valid_types = array( 'warning', 'notice', 'error' );
|
6510 |
|
6511 |
-
foreach (
|
6512 |
-
if (
|
6513 |
$data_set['error_code'] = $valid_type;
|
6514 |
break;
|
6515 |
}
|
@@ -6522,7 +6888,6 @@ class SucuriScanFSScanner extends SucuriScan {
|
|
6522 |
|
6523 |
return $logs_arr;
|
6524 |
}
|
6525 |
-
|
6526 |
}
|
6527 |
|
6528 |
/**
|
@@ -6537,43 +6902,37 @@ class SucuriScanFSScanner extends SucuriScan {
|
|
6537 |
*
|
6538 |
* @see https://core.trac.wordpress.org/ticket/23216
|
6539 |
*/
|
6540 |
-
class SucuriScanHeartbeat extends SucuriScanOption
|
|
|
6541 |
|
6542 |
/**
|
6543 |
* Stop execution of the heartbeat API in certain parts of the site.
|
6544 |
*
|
6545 |
* @return void
|
6546 |
*/
|
6547 |
-
public static function register_script()
|
|
|
6548 |
global $pagenow;
|
6549 |
|
6550 |
-
$status = SucuriScanOption::get_option(
|
6551 |
|
6552 |
// Enable heartbeat everywhere.
|
6553 |
-
if (
|
6554 |
/* Do nothing */
|
6555 |
-
}
|
6556 |
-
|
6557 |
-
|
6558 |
-
|
6559 |
-
|
6560 |
-
}
|
6561 |
-
|
6562 |
-
// Disable heartbeat only on the dashboard and home pages.
|
6563 |
-
elseif (
|
6564 |
-
$status == 'dashboard'
|
6565 |
&& $pagenow == 'index.php'
|
6566 |
) {
|
6567 |
-
wp_deregister_script(
|
6568 |
-
}
|
6569 |
-
|
6570 |
-
// Disable heartbeat everywhere except in post edition.
|
6571 |
-
elseif (
|
6572 |
-
$status == 'addpost'
|
6573 |
&& $pagenow != 'post.php'
|
6574 |
&& $pagenow != 'post-new.php'
|
6575 |
) {
|
6576 |
-
wp_deregister_script(
|
6577 |
}
|
6578 |
}
|
6579 |
|
@@ -6587,12 +6946,13 @@ class SucuriScanHeartbeat extends SucuriScanOption {
|
|
6587 |
* @param array $settings Heartbeat settings.
|
6588 |
* @return array Updated version of the heartbeat settings.
|
6589 |
*/
|
6590 |
-
public static function update_settings(
|
6591 |
-
|
6592 |
-
$
|
|
|
6593 |
|
6594 |
-
if (
|
6595 |
-
SucuriScanOption::delete_option(
|
6596 |
$pulse = 15;
|
6597 |
}
|
6598 |
|
@@ -6610,17 +6970,17 @@ class SucuriScanHeartbeat extends SucuriScanOption {
|
|
6610 |
* @param string $screen_id Identifier of the screen the heartbeat occurred on.
|
6611 |
* @return array Response with new data.
|
6612 |
*/
|
6613 |
-
public static function respond_to_received(
|
6614 |
-
|
|
|
6615 |
|
6616 |
-
if (
|
6617 |
-
$interval == 'slow'
|
6618 |
|| $interval == 'fast'
|
6619 |
|| $interval == 'standard'
|
6620 |
) {
|
6621 |
$response['heartbeat_interval'] = $interval;
|
6622 |
} else {
|
6623 |
-
SucuriScanOption::delete_option(
|
6624 |
}
|
6625 |
|
6626 |
return $response;
|
@@ -6633,7 +6993,8 @@ class SucuriScanHeartbeat extends SucuriScanOption {
|
|
6633 |
* @param string $screen_id Identifier of the screen the heartbeat occurred on.
|
6634 |
* @return array Response with new data.
|
6635 |
*/
|
6636 |
-
public static function respond_to_send(
|
|
|
6637 |
return $response;
|
6638 |
}
|
6639 |
|
@@ -6642,7 +7003,8 @@ class SucuriScanHeartbeat extends SucuriScanOption {
|
|
6642 |
*
|
6643 |
* @return array Allowed values for the heartbeat status.
|
6644 |
*/
|
6645 |
-
public static function statuses_allowed()
|
|
|
6646 |
return array(
|
6647 |
'enabled' => 'Enable everywhere',
|
6648 |
'disabled' => 'Disable everywhere',
|
@@ -6656,7 +7018,8 @@ class SucuriScanHeartbeat extends SucuriScanOption {
|
|
6656 |
*
|
6657 |
* @return array Allowed values for the heartbeat intervals.
|
6658 |
*/
|
6659 |
-
public static function intervals_allowed()
|
|
|
6660 |
return array(
|
6661 |
'slow' => 'Slow interval',
|
6662 |
'fast' => 'Fast interval',
|
@@ -6669,16 +7032,16 @@ class SucuriScanHeartbeat extends SucuriScanOption {
|
|
6669 |
*
|
6670 |
* @return array Allowed values for the heartbeat pulses.
|
6671 |
*/
|
6672 |
-
public static function pulses_allowed()
|
|
|
6673 |
$pulses = array();
|
6674 |
|
6675 |
-
for (
|
6676 |
-
$pulses[ $i ] = sprintf(
|
6677 |
}
|
6678 |
|
6679 |
return $pulses;
|
6680 |
}
|
6681 |
-
|
6682 |
}
|
6683 |
|
6684 |
/**
|
@@ -6690,8 +7053,8 @@ class SucuriScanHeartbeat extends SucuriScanOption {
|
|
6690 |
* sites with old versions of the premium plugin (that was deprecated at
|
6691 |
* July/2014).
|
6692 |
*/
|
6693 |
-
class SucuriScanInterface
|
6694 |
-
|
6695 |
/**
|
6696 |
* Initialization code for the plugin.
|
6697 |
*
|
@@ -6702,8 +7065,11 @@ class SucuriScanInterface {
|
|
6702 |
*
|
6703 |
* @return void
|
6704 |
*/
|
6705 |
-
public static function initialize()
|
6706 |
-
|
|
|
|
|
|
|
6707 |
$_SERVER['SUCURIREAL_REMOTE_ADDR'] = $_SERVER['REMOTE_ADDR'];
|
6708 |
$_SERVER['REMOTE_ADDR'] = SucuriScan::get_remote_addr();
|
6709 |
}
|
@@ -6715,23 +7081,24 @@ class SucuriScanInterface {
|
|
6715 |
*
|
6716 |
* @return void
|
6717 |
*/
|
6718 |
-
public static function enqueue_scripts()
|
|
|
6719 |
$asset_version = '';
|
6720 |
|
6721 |
-
if (
|
6722 |
-
$asset_version = substr(
|
6723 |
}
|
6724 |
|
6725 |
-
wp_register_style(
|
6726 |
-
wp_register_script(
|
6727 |
-
wp_enqueue_style(
|
6728 |
-
wp_enqueue_script(
|
6729 |
|
6730 |
-
if (
|
6731 |
-
wp_register_script(
|
6732 |
-
wp_register_script(
|
6733 |
-
wp_enqueue_script(
|
6734 |
-
wp_enqueue_script(
|
6735 |
}
|
6736 |
}
|
6737 |
|
@@ -6740,14 +7107,14 @@ class SucuriScanInterface {
|
|
6740 |
*
|
6741 |
* @return void
|
6742 |
*/
|
6743 |
-
public static function add_interface_menu()
|
|
|
6744 |
global $sucuriscan_pages;
|
6745 |
|
6746 |
-
if (
|
6747 |
-
function_exists( 'add_menu_page' )
|
6748 |
&& $sucuriscan_pages
|
6749 |
-
&& is_array(
|
6750 |
-
&& array_key_exists(
|
6751 |
) {
|
6752 |
// Add main menu link.
|
6753 |
add_menu_page(
|
@@ -6759,10 +7126,9 @@ class SucuriScanInterface {
|
|
6759 |
SUCURISCAN_URL . '/inc/images/menu-icon.png'
|
6760 |
);
|
6761 |
|
6762 |
-
foreach (
|
6763 |
-
if (
|
6764 |
-
|
6765 |
-
&& SucuriScanOption::is_disabled( ':sitecheck_scanner' )
|
6766 |
) {
|
6767 |
continue;
|
6768 |
}
|
@@ -6789,8 +7155,9 @@ class SucuriScanInterface {
|
|
6789 |
*
|
6790 |
* @return void
|
6791 |
*/
|
6792 |
-
public static function handle_old_plugins()
|
6793 |
-
|
|
|
6794 |
$file_info = new SucuriScanFileInfo();
|
6795 |
$file_info->ignore_files = false;
|
6796 |
$file_info->ignore_directories = false;
|
@@ -6800,15 +7167,15 @@ class SucuriScanInterface {
|
|
6800 |
'sucuri-cloudproxy-waf/cloudproxy.php',
|
6801 |
);
|
6802 |
|
6803 |
-
foreach (
|
6804 |
-
$plugin_directory = dirname(
|
6805 |
|
6806 |
-
if (
|
6807 |
-
if (
|
6808 |
-
deactivate_plugins(
|
6809 |
}
|
6810 |
|
6811 |
-
$plugin_removed = $file_info->remove_directory_tree(
|
6812 |
}
|
6813 |
}
|
6814 |
}
|
@@ -6820,14 +7187,18 @@ class SucuriScanInterface {
|
|
6820 |
*
|
6821 |
* @return void
|
6822 |
*/
|
6823 |
-
public static function create_datastore_folder()
|
|
|
6824 |
$directory = SucuriScan::datastore_folder_path();
|
6825 |
|
6826 |
if (!file_exists($directory)) {
|
6827 |
@mkdir($directory, 0755, true);
|
6828 |
}
|
6829 |
|
6830 |
-
if (
|
|
|
|
|
|
|
6831 |
// Create last-logins datastore file.
|
6832 |
sucuriscan_lastlogins_datastore_exists();
|
6833 |
|
@@ -6848,7 +7219,7 @@ class SucuriScanInterface {
|
|
6848 |
SucuriScanOption::delete_option(':datastore_path');
|
6849 |
SucuriScanInterface::error(
|
6850 |
'Data folder does not exists and could not be created. Try to <a href="' .
|
6851 |
-
SucuriScanTemplate::
|
6852 |
if the plugin is able to fix this error automatically, if this message
|
6853 |
reappears you will need to either change the location of the directory from
|
6854 |
the plugin general settings page or create this directory manually and give
|
@@ -6862,13 +7233,14 @@ class SucuriScanInterface {
|
|
6862 |
*
|
6863 |
* @return void
|
6864 |
*/
|
6865 |
-
public static function check_permissions()
|
6866 |
-
|
6867 |
-
|
6868 |
-
|| !
|
6869 |
) {
|
6870 |
-
$page = SucuriScanRequest::get(
|
6871 |
-
|
|
|
6872 |
}
|
6873 |
}
|
6874 |
|
@@ -6879,13 +7251,14 @@ class SucuriScanInterface {
|
|
6879 |
*
|
6880 |
* @return boolean Either TRUE or FALSE if the nonce is valid or not respectively.
|
6881 |
*/
|
6882 |
-
public static function check_nonce()
|
6883 |
-
|
|
|
6884 |
$nonce_name = 'sucuriscan_page_nonce';
|
6885 |
-
$nonce_value = SucuriScanRequest::post(
|
6886 |
|
6887 |
-
if (
|
6888 |
-
wp_die(
|
6889 |
|
6890 |
return false;
|
6891 |
}
|
@@ -6901,7 +7274,8 @@ class SucuriScanInterface {
|
|
6901 |
* @param string $message The message that will be printed in the alert.
|
6902 |
* @return void
|
6903 |
*/
|
6904 |
-
private static function admin_notice(
|
|
|
6905 |
$display_notice = true;
|
6906 |
|
6907 |
/**
|
@@ -6913,24 +7287,24 @@ class SucuriScanInterface {
|
|
6913 |
* user authentication process is executed may cause a "headers already sent"
|
6914 |
* error.
|
6915 |
*/
|
6916 |
-
if (
|
6917 |
-
|
6918 |
-
&& SucuriScanRequest::post(
|
6919 |
-
&& SucuriScanRequest::post(
|
6920 |
-
&& SucuriScanRequest::post( 'wp-submit' )
|
6921 |
) {
|
6922 |
$display_notice = false;
|
6923 |
}
|
6924 |
|
6925 |
// Display the HTML notice to the current user.
|
6926 |
-
if (
|
6927 |
-
|
6928 |
-
|
6929 |
-
|
6930 |
-
|
6931 |
-
|
6932 |
-
|
6933 |
-
|
|
|
6934 |
}
|
6935 |
}
|
6936 |
|
@@ -6940,8 +7314,9 @@ class SucuriScanInterface {
|
|
6940 |
* @param string $error_msg The message that will be printed in the alert.
|
6941 |
* @return void
|
6942 |
*/
|
6943 |
-
public static function error(
|
6944 |
-
|
|
|
6945 |
}
|
6946 |
|
6947 |
/**
|
@@ -6950,8 +7325,9 @@ class SucuriScanInterface {
|
|
6950 |
* @param string $info_msg The message that will be printed in the alert.
|
6951 |
* @return void
|
6952 |
*/
|
6953 |
-
public static function info(
|
6954 |
-
|
|
|
6955 |
}
|
6956 |
|
6957 |
/**
|
@@ -6961,22 +7337,22 @@ class SucuriScanInterface {
|
|
6961 |
*
|
6962 |
* @return void
|
6963 |
*/
|
6964 |
-
public static function setup_notice()
|
6965 |
-
|
6966 |
-
|
6967 |
&& SucuriScan::no_notices_here() === false
|
6968 |
-
&& !
|
6969 |
-
&& SucuriScanRequest::post(
|
6970 |
-
&& SucuriScanRequest::post(
|
6971 |
-
&& !
|
6972 |
) {
|
6973 |
if (SucuriScanRequest::get(':dismiss_setup') !== false) {
|
6974 |
SucuriScanOption::update_option(':dismiss_setup', 'enabled');
|
6975 |
} elseif (SucuriScanOption::is_enabled(':dismiss_setup')) {
|
6976 |
/* Do not display API key generation form. */
|
6977 |
} else {
|
6978 |
-
echo SucuriScanTemplate::
|
6979 |
-
echo SucuriScanTemplate::
|
6980 |
'Visibility' => 'hidden',
|
6981 |
'Title' => 'Sucuri API key generation',
|
6982 |
'CssClass' => 'sucuriscan-setup-instructions',
|
@@ -6984,7 +7360,102 @@ class SucuriScanInterface {
|
|
6984 |
}
|
6985 |
}
|
6986 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
6987 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
6988 |
}
|
6989 |
|
6990 |
/**
|
@@ -6994,33 +7465,49 @@ class SucuriScanInterface {
|
|
6994 |
*
|
6995 |
* @return void
|
6996 |
*/
|
6997 |
-
function sucuriscan_scanner_page()
|
|
|
6998 |
SucuriScanInterface::check_permissions();
|
6999 |
|
7000 |
-
$
|
7001 |
-
$cache = new SucuriScanCache(
|
7002 |
-
$scan_results = $cache->get(
|
7003 |
-
$report_results = (bool) (
|
7004 |
|
7005 |
-
if (
|
7006 |
-
|
7007 |
-
&& SucuriScanRequest::post( ':malware_scan', '1' )
|
7008 |
) {
|
7009 |
$report_results = true;
|
7010 |
}
|
7011 |
|
7012 |
-
if (
|
7013 |
$template_name = 'malwarescan-results';
|
7014 |
-
$
|
7015 |
-
$
|
7016 |
-
$
|
7017 |
} else {
|
7018 |
$template_name = 'malwarescan';
|
7019 |
-
$
|
7020 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
7021 |
}
|
7022 |
|
7023 |
-
|
7024 |
}
|
7025 |
|
7026 |
/**
|
@@ -7029,9 +7516,10 @@ function sucuriscan_scanner_page(){
|
|
7029 |
* @param array $scan_results Array with information of the scanning.
|
7030 |
* @return array Array with psuedo-variables to build the template.
|
7031 |
*/
|
7032 |
-
function sucuriscan_sitecheck_info(
|
|
|
7033 |
$clean_domain = SucuriScan::get_domain();
|
7034 |
-
$
|
7035 |
'ScannedDomainName' => $clean_domain,
|
7036 |
'ScannerResults.CssClass' => '',
|
7037 |
'ScannerResults.Content' => '',
|
@@ -7047,47 +7535,49 @@ function sucuriscan_sitecheck_info( $scan_results = array() ){
|
|
7047 |
);
|
7048 |
|
7049 |
// If the results are not cached, then request a new scan and store in cache.
|
7050 |
-
if (
|
7051 |
-
$scan_results = SucuriScanAPI::
|
7052 |
|
7053 |
// Check for error messages in the request's response.
|
7054 |
-
if (
|
7055 |
-
if (
|
7056 |
-
SucuriScanInterface::error(
|
|
|
|
|
|
|
7057 |
} else {
|
7058 |
-
SucuriScanInterface::error(
|
7059 |
}
|
7060 |
} else {
|
7061 |
-
$cache = new SucuriScanCache(
|
7062 |
-
$results_were_cached = $cache->add(
|
7063 |
|
7064 |
-
if (
|
7065 |
-
SucuriScanInterface::error(
|
7066 |
}
|
7067 |
}
|
7068 |
}
|
7069 |
|
7070 |
-
if (
|
7071 |
// Increase the malware scan counter.
|
7072 |
-
$sitecheck_counter = (int) SucuriScanOption::get_option(
|
7073 |
-
SucuriScanOption::update_option(
|
7074 |
add_thickbox();
|
7075 |
|
7076 |
-
$
|
7077 |
-
$
|
7078 |
-
$
|
7079 |
-
$
|
7080 |
-
$
|
7081 |
|
7082 |
-
if (
|
7083 |
-
isset($scan_results['MALWARE']['WARN'])
|
7084 |
|| isset($scan_results['BLACKLIST']['WARN'])
|
7085 |
) {
|
7086 |
-
$
|
7087 |
}
|
7088 |
}
|
7089 |
|
7090 |
-
return $
|
7091 |
}
|
7092 |
|
7093 |
/**
|
@@ -7095,11 +7585,12 @@ function sucuriscan_sitecheck_info( $scan_results = array() ){
|
|
7095 |
* the HTML code to display the information in the malware scan page inside the
|
7096 |
* remote scanner results tab.
|
7097 |
*
|
7098 |
-
* @param array $scan_results
|
7099 |
-
* @param array $
|
7100 |
-
* @return array
|
7101 |
*/
|
7102 |
-
function sucuriscan_sitecheck_scanner_results(
|
|
|
7103 |
$secvars = array(
|
7104 |
'CacheLifeTime' => SUCURISCAN_SITECHECK_LIFETIME,
|
7105 |
'WebsiteStatus' => 'Site status unknown',
|
@@ -7108,33 +7599,36 @@ function sucuriscan_sitecheck_scanner_results( $scan_results = false, $template_
|
|
7108 |
'MalwarePayloadList' => '',
|
7109 |
);
|
7110 |
|
7111 |
-
if (
|
7112 |
-
$
|
7113 |
$secvars['WebsiteStatus'] = 'Site compromised (malware was identified)';
|
7114 |
$secvars['NoMalwareRowVisibility'] = 'hidden';
|
7115 |
$secvars['FixButtonVisibility'] = 'visible';
|
7116 |
|
7117 |
-
foreach (
|
7118 |
-
$malres = SucuriScanAPI::
|
7119 |
-
|
7120 |
-
if (
|
7121 |
-
$secvars['MalwarePayloadList'] .= SucuriScanTemplate::
|
7122 |
-
'
|
7123 |
-
|
7124 |
-
|
7125 |
-
|
7126 |
-
|
7127 |
-
|
7128 |
-
|
|
|
|
|
|
|
7129 |
}
|
7130 |
}
|
7131 |
} else {
|
7132 |
$secvars['WebsiteStatus'] = 'Site clean (no malware was identified)';
|
7133 |
}
|
7134 |
|
7135 |
-
$
|
7136 |
|
7137 |
-
return $
|
7138 |
}
|
7139 |
|
7140 |
/**
|
@@ -7142,15 +7636,16 @@ function sucuriscan_sitecheck_scanner_results( $scan_results = false, $template_
|
|
7142 |
* the HTML code to display the information in the malware scan page inside the
|
7143 |
* website details tab.
|
7144 |
*
|
7145 |
-
* @param array $scan_results
|
7146 |
-
* @param array $
|
7147 |
-
* @return array
|
7148 |
*/
|
7149 |
-
function sucuriscan_sitecheck_website_details(
|
|
|
7150 |
$secvars = array(
|
7151 |
'UpdateWebsiteButtonVisibility' => 'hidden',
|
7152 |
'VersionNumberOfTheUpdate' => '0.0',
|
7153 |
-
'AdminUrlForUpdates' => admin_url(
|
7154 |
'GenericInformationList' => '',
|
7155 |
'NoAppDetailsVisibility' => 'visible',
|
7156 |
'ApplicationDetailsList' => '',
|
@@ -7161,11 +7656,10 @@ function sucuriscan_sitecheck_website_details( $scan_results = false, $template_
|
|
7161 |
);
|
7162 |
|
7163 |
// Check whether this WordPress installation needs an update.
|
7164 |
-
if (
|
7165 |
$site_updates = get_core_updates();
|
7166 |
|
7167 |
-
if (
|
7168 |
-
! is_array( $site_updates )
|
7169 |
|| empty($site_updates)
|
7170 |
|| $site_updates[0]->response == 'latest'
|
7171 |
) {
|
@@ -7173,22 +7667,21 @@ function sucuriscan_sitecheck_website_details( $scan_results = false, $template_
|
|
7173 |
}
|
7174 |
}
|
7175 |
|
7176 |
-
if (
|
7177 |
-
isset($scan_results['OUTDATEDSCAN'])
|
7178 |
|| isset($scan_results['RECOMMENDATIONS'])
|
7179 |
) {
|
7180 |
-
$
|
7181 |
}
|
7182 |
|
7183 |
-
$secvars = sucuriscan_sitecheck_general_information(
|
7184 |
-
$secvars = sucuriscan_sitecheck_application_details(
|
7185 |
-
$secvars = sucuriscan_sitecheck_system_notices(
|
7186 |
-
$secvars = sucuriscan_sitecheck_outdated_software(
|
7187 |
-
$secvars = sucuriscan_sitecheck_recommendations(
|
7188 |
|
7189 |
-
$
|
7190 |
|
7191 |
-
return $
|
7192 |
}
|
7193 |
|
7194 |
/**
|
@@ -7196,11 +7689,12 @@ function sucuriscan_sitecheck_website_details( $scan_results = false, $template_
|
|
7196 |
* the HTML code to display the information in the malware scan page inside the
|
7197 |
* website details tab and specifically in the general information panel.
|
7198 |
*
|
7199 |
-
* @param array $scan_results
|
7200 |
-
* @param array $
|
7201 |
-
* @return array
|
7202 |
*/
|
7203 |
-
function sucuriscan_sitecheck_general_information(
|
|
|
7204 |
$possible_keys = array(
|
7205 |
'DOMAIN' => 'Domain Scanned',
|
7206 |
'IP' => 'Site IP Address',
|
@@ -7210,18 +7704,25 @@ function sucuriscan_sitecheck_general_information( $scan_results = false, $secva
|
|
7210 |
'PHP_VERSION' => 'PHP Version',
|
7211 |
);
|
7212 |
|
7213 |
-
if (
|
7214 |
-
$scan_results['SCAN']['WP_VERSION'] = array(
|
7215 |
-
$scan_results['SCAN']['PHP_VERSION'] = array(
|
7216 |
|
7217 |
-
foreach (
|
7218 |
-
if (
|
7219 |
-
|
|
|
|
|
|
|
|
|
7220 |
|
7221 |
-
$secvars['GenericInformationList'] .= SucuriScanTemplate::
|
7222 |
-
'
|
7223 |
-
|
7224 |
-
|
|
|
|
|
|
|
7225 |
}
|
7226 |
}
|
7227 |
}
|
@@ -7234,29 +7735,33 @@ function sucuriscan_sitecheck_general_information( $scan_results = false, $secva
|
|
7234 |
* the HTML code to display the information in the malware scan page inside the
|
7235 |
* website details tab and specifically in the application details panel.
|
7236 |
*
|
7237 |
-
* @param array $scan_results
|
7238 |
-
* @param array $
|
7239 |
-
* @return array
|
7240 |
*/
|
7241 |
-
function sucuriscan_sitecheck_application_details(
|
7242 |
-
|
7243 |
-
|
7244 |
-
|
7245 |
-
|
|
|
7246 |
$secvars['NoAppDetailsVisibility'] = 'hidden';
|
7247 |
|
7248 |
-
if (
|
7249 |
$details = isset($details[0]) ? $details[0] : '';
|
7250 |
}
|
7251 |
|
7252 |
-
$details_parts = explode(
|
7253 |
-
$result_title = isset($details_parts[0]) ? trim(
|
7254 |
-
$result_value = isset($details_parts[1]) ? trim(
|
7255 |
|
7256 |
-
$secvars['ApplicationDetailsList'] .= SucuriScanTemplate::
|
7257 |
-
'
|
7258 |
-
|
7259 |
-
|
|
|
|
|
|
|
7260 |
}
|
7261 |
}
|
7262 |
}
|
@@ -7270,22 +7775,26 @@ function sucuriscan_sitecheck_application_details( $scan_results = false, $secva
|
|
7270 |
* the HTML code to display the information in the malware scan page inside the
|
7271 |
* website details tab and specifically in the system notices panel.
|
7272 |
*
|
7273 |
-
* @param array $scan_results
|
7274 |
-
* @param array $
|
7275 |
-
* @return array
|
7276 |
*/
|
7277 |
-
function sucuriscan_sitecheck_system_notices(
|
7278 |
-
|
7279 |
-
|
|
|
7280 |
$secvars['NoAppDetailsVisibility'] = 'hidden';
|
7281 |
|
7282 |
-
if (
|
7283 |
-
$notice = implode(
|
7284 |
}
|
7285 |
|
7286 |
-
$secvars['SystemNoticeList'] .= SucuriScanTemplate::
|
7287 |
-
'
|
7288 |
-
|
|
|
|
|
|
|
7289 |
}
|
7290 |
}
|
7291 |
|
@@ -7297,20 +7806,24 @@ function sucuriscan_sitecheck_system_notices( $scan_results = false, $secvars =
|
|
7297 |
* the HTML code to display the information in the malware scan page inside the
|
7298 |
* website details tab and specifically in the outdated software panel.
|
7299 |
*
|
7300 |
-
* @param array $scan_results
|
7301 |
-
* @param array $
|
7302 |
-
* @return array
|
7303 |
*/
|
7304 |
-
function sucuriscan_sitecheck_outdated_software(
|
7305 |
-
|
7306 |
-
|
7307 |
-
|
|
|
7308 |
$secvars['HasRecommendationsVisibility'] = 'visible';
|
7309 |
-
$secvars['OutdatedSoftwareList'] .= SucuriScanTemplate::
|
7310 |
-
'
|
7311 |
-
|
7312 |
-
|
7313 |
-
|
|
|
|
|
|
|
7314 |
}
|
7315 |
}
|
7316 |
}
|
@@ -7323,21 +7836,25 @@ function sucuriscan_sitecheck_outdated_software( $scan_results = false, $secvars
|
|
7323 |
* the HTML code to display the information in the malware scan page inside the
|
7324 |
* website details tab and specifically in the security recommendations panel.
|
7325 |
*
|
7326 |
-
* @param array $scan_results
|
7327 |
-
* @param array $
|
7328 |
-
* @return array
|
7329 |
*/
|
7330 |
-
function sucuriscan_sitecheck_recommendations(
|
7331 |
-
|
7332 |
-
|
7333 |
-
|
|
|
7334 |
$secvars['HasRecommendationsVisibility'] = 'visible';
|
7335 |
-
$secvars['SecurityRecomendationList'] .= SucuriScanTemplate::
|
7336 |
-
'
|
7337 |
-
|
7338 |
-
|
7339 |
-
|
7340 |
-
|
|
|
|
|
|
|
7341 |
}
|
7342 |
}
|
7343 |
}
|
@@ -7350,11 +7867,12 @@ function sucuriscan_sitecheck_recommendations( $scan_results = false, $secvars =
|
|
7350 |
* the HTML code to display the information in the malware scan page inside the
|
7351 |
* website links tab.
|
7352 |
*
|
7353 |
-
* @param array $scan_results
|
7354 |
-
* @param array $
|
7355 |
-
* @return array
|
7356 |
*/
|
7357 |
-
function sucuriscan_sitecheck_website_links(
|
|
|
7358 |
$possible_url_keys = array(
|
7359 |
'IFRAME' => 'List of iframes found',
|
7360 |
'JSEXTERNAL' => 'List of external scripts included',
|
@@ -7366,33 +7884,39 @@ function sucuriscan_sitecheck_website_links( $scan_results = false, $template_va
|
|
7366 |
'NoLinksVisibility' => 'hidden',
|
7367 |
);
|
7368 |
|
7369 |
-
if (
|
7370 |
-
foreach (
|
7371 |
-
if (
|
7372 |
$result_value = 0;
|
7373 |
$result_items = '';
|
7374 |
|
7375 |
-
foreach (
|
7376 |
$result_value += 1;
|
7377 |
-
$result_items .= SucuriScanTemplate::
|
7378 |
-
'
|
7379 |
-
|
|
|
|
|
|
|
7380 |
}
|
7381 |
|
7382 |
-
$secvars['WebsiteLinksAllList'] .= SucuriScanTemplate::
|
7383 |
-
'
|
7384 |
-
|
7385 |
-
|
7386 |
-
|
|
|
|
|
|
|
7387 |
}
|
7388 |
}
|
7389 |
} else {
|
7390 |
$secvars['NoLinksVisibility'] = 'visible';
|
7391 |
}
|
7392 |
|
7393 |
-
$
|
7394 |
|
7395 |
-
return $
|
7396 |
}
|
7397 |
|
7398 |
/**
|
@@ -7400,11 +7924,12 @@ function sucuriscan_sitecheck_website_links( $scan_results = false, $template_va
|
|
7400 |
* the HTML code to display the information in the malware scan page inside the
|
7401 |
* blacklist status tab.
|
7402 |
*
|
7403 |
-
* @param array $scan_results
|
7404 |
-
* @param array $
|
7405 |
-
* @return array
|
7406 |
*/
|
7407 |
-
function sucuriscan_sitecheck_blacklist_status(
|
|
|
7408 |
$blacklist_types = array(
|
7409 |
'INFO' => 'CLEAN',
|
7410 |
'WARN' => 'WARNING',
|
@@ -7414,29 +7939,32 @@ function sucuriscan_sitecheck_blacklist_status( $scan_results = false, $template
|
|
7414 |
'BlacklistStatusList' => '',
|
7415 |
);
|
7416 |
|
7417 |
-
if (
|
7418 |
-
$
|
7419 |
-
$
|
7420 |
}
|
7421 |
|
7422 |
-
foreach (
|
7423 |
-
if (
|
7424 |
-
foreach (
|
7425 |
-
$css_blacklist = (
|
7426 |
|
7427 |
-
$secvars['BlacklistStatusList'] .= SucuriScanTemplate::
|
7428 |
-
'
|
7429 |
-
|
7430 |
-
|
7431 |
-
|
7432 |
-
|
|
|
|
|
|
|
7433 |
}
|
7434 |
}
|
7435 |
}
|
7436 |
|
7437 |
-
$
|
7438 |
|
7439 |
-
return $
|
7440 |
}
|
7441 |
|
7442 |
/**
|
@@ -7444,424 +7972,236 @@ function sucuriscan_sitecheck_blacklist_status( $scan_results = false, $template
|
|
7444 |
* the HTML code to display the information in the malware scan page inside the
|
7445 |
* modified files tab.
|
7446 |
*
|
7447 |
-
* @param array $scan_results
|
7448 |
-
* @param array $
|
7449 |
-
* @return array
|
7450 |
-
*/
|
7451 |
-
function sucuriscan_sitecheck_modified_files( $scan_results = false, $template_variables = array() ){
|
7452 |
-
$template_variables['ModifiedFiles.Content'] = sucuriscan_modified_files();
|
7453 |
-
|
7454 |
-
return $template_variables;
|
7455 |
-
}
|
7456 |
-
|
7457 |
-
/**
|
7458 |
-
* CloudProxy monitoring page.
|
7459 |
-
*
|
7460 |
-
* It checks whether the WordPress core files are the original ones, and the state
|
7461 |
-
* of the themes and plugins reporting the availability of updates. It also checks
|
7462 |
-
* the user accounts under the administrator group.
|
7463 |
-
*
|
7464 |
-
* @return void
|
7465 |
-
*/
|
7466 |
-
function sucuriscan_monitoring_page(){
|
7467 |
-
SucuriScanInterface::check_permissions();
|
7468 |
-
|
7469 |
-
// Process all form submissions.
|
7470 |
-
sucuriscan_monitoring_form_submissions();
|
7471 |
-
|
7472 |
-
// Get the dynamic values for the template variables.
|
7473 |
-
$api_key = SucuriScanAPI::get_cloudproxy_key();
|
7474 |
-
|
7475 |
-
// Page pseudo-variables initialization.
|
7476 |
-
$template_variables = array(
|
7477 |
-
'PageTitle' => 'Firewall WAF',
|
7478 |
-
'Monitoring.InstructionsVisibility' => 'visible',
|
7479 |
-
'Monitoring.Settings' => sucuriscan_monitoring_settings( $api_key ),
|
7480 |
-
'Monitoring.Logs' => sucuriscan_monitoring_logs( $api_key ),
|
7481 |
-
|
7482 |
-
/* Pseudo-variables for the monitoring logs. */
|
7483 |
-
'AuditLogs.List' => '',
|
7484 |
-
'AuditLogs.CountText' => '',
|
7485 |
-
'AuditLogs.DenialTypeOptions' => '',
|
7486 |
-
'AuditLogs.NoItemsVisibility' => '',
|
7487 |
-
'AuditLogs.PaginationVisibility' => '',
|
7488 |
-
'AuditLogs.AuditPagination' => '',
|
7489 |
-
);
|
7490 |
-
|
7491 |
-
if ( $api_key ) {
|
7492 |
-
$template_variables['Monitoring.InstructionsVisibility'] = 'hidden';
|
7493 |
-
}
|
7494 |
-
|
7495 |
-
echo SucuriScanTemplate::get_template( 'monitoring', $template_variables );
|
7496 |
-
}
|
7497 |
-
|
7498 |
-
/**
|
7499 |
-
* Process the requests sent by the form submissions originated in the monitoring
|
7500 |
-
* page, all forms must have a nonce field that will be checked against the one
|
7501 |
-
* generated in the template render function.
|
7502 |
-
*
|
7503 |
-
* @return void
|
7504 |
*/
|
7505 |
-
function
|
7506 |
-
|
7507 |
-
|
7508 |
-
// Add and/or Update the Sucuri WAF API Key (do it before anything else).
|
7509 |
-
$option_name = ':cloudproxy_apikey';
|
7510 |
-
$api_key = SucuriScanRequest::post( $option_name );
|
7511 |
-
|
7512 |
-
if ( $api_key !== false ) {
|
7513 |
-
if ( SucuriScanAPI::is_valid_cloudproxy_key( $api_key ) ) {
|
7514 |
-
SucuriScanOption::update_option( $option_name, $api_key );
|
7515 |
-
SucuriScanOption::update_option( ':revproxy', 'enabled' );
|
7516 |
-
SucuriScanInterface::info( 'CloudProxy API key saved successfully' );
|
7517 |
-
} elseif ( empty($api_key) ) {
|
7518 |
-
SucuriScanOption::delete_option( $option_name );
|
7519 |
-
SucuriScanOption::update_option( ':revproxy', 'disabled' );
|
7520 |
-
SucuriScanInterface::info( 'CloudProxy API key removed successfully' );
|
7521 |
-
} else {
|
7522 |
-
SucuriScanInterface::error( 'Invalid CloudProxy API key, check your settings and try again.' );
|
7523 |
-
}
|
7524 |
-
}
|
7525 |
-
|
7526 |
-
// Flush the cache of the site(s) associated with the API key.
|
7527 |
-
if ( SucuriScanRequest::post( ':clear_cache', '1' ) ) {
|
7528 |
-
$clear_cache_resp = SucuriScanAPI::clear_cloudproxy_cache();
|
7529 |
-
|
7530 |
-
if ( $clear_cache_resp ) {
|
7531 |
-
if ( isset($clear_cache_resp->messages[0]) ) {
|
7532 |
-
// Clear W3 Total Cache if it is installed.
|
7533 |
-
if ( function_exists( 'w3tc_flush_all' ) ) {
|
7534 |
-
w3tc_flush_all();
|
7535 |
-
}
|
7536 |
-
|
7537 |
-
SucuriScanInterface::info( $clear_cache_resp->messages[0] );
|
7538 |
-
} else {
|
7539 |
-
SucuriScanInterface::error( 'Could not clear the cache of your site, try later again.' );
|
7540 |
-
}
|
7541 |
-
} else {
|
7542 |
-
SucuriScanInterface::error( 'CloudProxy is not enabled on your site, or your API key is invalid.' );
|
7543 |
-
}
|
7544 |
-
}
|
7545 |
-
}
|
7546 |
|
|
|
7547 |
}
|
7548 |
|
7549 |
/**
|
7550 |
-
* Generate the HTML code for the
|
7551 |
*
|
7552 |
* @param string $api_key The CloudProxy API key.
|
7553 |
-
* @return string The parsed-content of the
|
7554 |
*/
|
7555 |
-
function
|
7556 |
-
|
7557 |
-
|
7558 |
-
'
|
7559 |
-
'
|
|
|
|
|
|
|
7560 |
);
|
7561 |
|
7562 |
-
if ( $api_key
|
7563 |
-
$settings = SucuriScanAPI::
|
7564 |
|
7565 |
-
$
|
|
|
|
|
7566 |
|
7567 |
-
if (
|
7568 |
$counter = 0;
|
7569 |
-
$
|
7570 |
-
$settings =
|
7571 |
-
|
7572 |
-
foreach ( $settings as $option_name => $option_value ) {
|
7573 |
-
// Change the name of some options.
|
7574 |
-
if ( $option_name == 'internal_ip' ) {
|
7575 |
-
$option_name = 'hosting_ip';
|
7576 |
-
}
|
7577 |
|
7578 |
-
|
7579 |
-
$
|
|
|
7580 |
|
7581 |
// Generate a HTML list when the option's value is an array.
|
7582 |
-
if (
|
7583 |
-
$css_scrollable = count(
|
7584 |
$html_list = '<ul class="sucuriscan-list-as-table ' . $css_scrollable . '">';
|
7585 |
|
7586 |
-
foreach (
|
7587 |
-
$html_list .= '<li>' . $single_value . '</li>';
|
7588 |
}
|
7589 |
|
7590 |
$html_list .= '</ul>';
|
7591 |
$option_value = $html_list;
|
|
|
|
|
7592 |
}
|
7593 |
|
7594 |
// Parse the snippet template and replace the pseudo-variables.
|
7595 |
-
$
|
7596 |
-
'
|
7597 |
-
|
7598 |
-
|
7599 |
-
|
7600 |
-
|
|
|
|
|
|
|
7601 |
}
|
7602 |
}
|
7603 |
}
|
7604 |
|
7605 |
-
return SucuriScanTemplate::
|
7606 |
}
|
7607 |
|
7608 |
/**
|
7609 |
-
* Converts the value of some of the
|
7610 |
* text, for example changing numbers or variable names into a more explicit
|
7611 |
* text so the administrator can understand the meaning of these settings.
|
7612 |
*
|
7613 |
* @param array $settings A hash with the settings of a CloudProxy account.
|
7614 |
* @return array The explained version of the CloudProxy settings.
|
7615 |
*/
|
7616 |
-
function
|
7617 |
-
|
7618 |
-
|
7619 |
-
|
7620 |
-
|
7621 |
-
|
7622 |
-
|
7623 |
-
|
7624 |
-
$new_value = ( $option_value == 1 ) ? 'Active' : 'not active';
|
7625 |
-
break;
|
7626 |
-
case 'cache_mode':
|
7627 |
-
$new_value = sucuriscan_cache_mode_title( $option_value );
|
7628 |
-
break;
|
7629 |
-
}
|
7630 |
|
7631 |
-
|
7632 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
7633 |
}
|
7634 |
}
|
7635 |
-
|
7636 |
-
return $settings;
|
7637 |
}
|
7638 |
|
7639 |
-
return
|
7640 |
}
|
7641 |
|
7642 |
/**
|
7643 |
-
*
|
7644 |
*
|
7645 |
-
* @param string $
|
7646 |
-
* @return string
|
7647 |
*/
|
7648 |
-
function
|
7649 |
-
|
|
|
|
|
7650 |
|
7651 |
-
|
7652 |
-
|
7653 |
-
|
7654 |
-
case 'nocache': $title = 'Minimal (only for a few minutes)'; break;
|
7655 |
-
case 'nocacheatall': $title = 'Caching disabled (use with caution)'; break;
|
7656 |
-
default: $title = 'Unknown'; break;
|
7657 |
-
}
|
7658 |
|
7659 |
-
return $
|
7660 |
}
|
7661 |
|
7662 |
-
|
7663 |
-
|
7664 |
-
|
7665 |
-
|
7666 |
-
|
7667 |
-
|
7668 |
-
|
7669 |
-
|
7670 |
-
|
7671 |
-
|
7672 |
-
|
7673 |
-
|
7674 |
-
|
7675 |
-
|
7676 |
-
|
7677 |
-
|
7678 |
-
|
7679 |
-
|
7680 |
-
|
7681 |
-
|
7682 |
-
$date = date( 'Y-m-d' );
|
7683 |
|
7684 |
-
|
7685 |
-
|
7686 |
-
|
7687 |
-
|
7688 |
-
|
|
|
|
|
7689 |
|
7690 |
-
|
7691 |
-
|
7692 |
-
$month = SucuriScanRequest::post( ':month' );
|
7693 |
-
$day = SucuriScanRequest::post( ':day' );
|
7694 |
|
7695 |
-
|
7696 |
-
|
|
|
|
|
|
|
|
|
7697 |
}
|
7698 |
|
7699 |
-
|
7700 |
-
|
7701 |
-
if ( $logs_data ) {
|
7702 |
-
add_thickbox(); /* Include the Thickbox library. */
|
7703 |
-
$template_variables['AuditLogs.NoItemsVisibility'] = 'hidden';
|
7704 |
-
$template_variables['AuditLogs.CountText'] = $logs_data->limit . '/' . $logs_data->total_lines;
|
7705 |
-
$template_variables['AuditLogs.List'] = sucuriscan_monitoring_access_logs( $logs_data->access_logs );
|
7706 |
-
$template_variables['AuditLogs.DenialTypeOptions'] = sucuriscan_monitoring_denial_types( $logs_data->access_logs );
|
7707 |
-
}
|
7708 |
}
|
7709 |
-
|
7710 |
-
$template_variables['AuditLogs.TargetDate'] = SucuriScan::escape( $date );
|
7711 |
-
$template_variables['AuditLogs.DateYears'] = sucuriscan_monitoring_dates( 'years', $date );
|
7712 |
-
$template_variables['AuditLogs.DateMonths'] = sucuriscan_monitoring_dates( 'months', $date );
|
7713 |
-
$template_variables['AuditLogs.DateDays'] = sucuriscan_monitoring_dates( 'days', $date );
|
7714 |
-
|
7715 |
-
return SucuriScanTemplate::get_section( 'monitoring-logs', $template_variables );
|
7716 |
}
|
7717 |
|
7718 |
-
|
7719 |
-
|
7720 |
-
|
7721 |
-
|
7722 |
-
|
7723 |
-
|
7724 |
-
|
7725 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
7726 |
|
7727 |
-
if (
|
7728 |
$counter = 0;
|
7729 |
-
$needed_attrs = array(
|
7730 |
-
'request_date',
|
7731 |
-
'request_time',
|
7732 |
-
'request_timezone',
|
7733 |
-
'request_timestamp',
|
7734 |
-
'local_request_time',
|
7735 |
-
'remote_addr',
|
7736 |
-
'sucuri_block_reason',
|
7737 |
-
'resource_path',
|
7738 |
-
'request_method',
|
7739 |
-
'http_protocol',
|
7740 |
-
'http_status',
|
7741 |
-
'http_status_title',
|
7742 |
-
'http_bytes_sent',
|
7743 |
-
'http_referer',
|
7744 |
-
'http_user_agent',
|
7745 |
-
);
|
7746 |
-
|
7747 |
-
$filter_by_denial_type = false;
|
7748 |
-
$filter_by_keyword = false;
|
7749 |
-
$filter_query = false;
|
7750 |
-
|
7751 |
-
if ( $q = SucuriScanRequest::post( ':monitoring_denial_type' ) ) {
|
7752 |
-
$filter_by_denial_type = true;
|
7753 |
-
$filter_query = $q;
|
7754 |
-
}
|
7755 |
-
|
7756 |
-
if ( $q = SucuriScanRequest::post( ':monitoring_log_filter' ) ) {
|
7757 |
-
$filter_by_keyword = true;
|
7758 |
-
$filter_query = $q;
|
7759 |
-
}
|
7760 |
-
|
7761 |
-
foreach ( $access_logs as $access_log ) {
|
7762 |
-
$css_class = ( $counter % 2 == 0 ) ? '' : 'alternate';
|
7763 |
-
$audit_log_snippet = array(
|
7764 |
-
'AuditLog.Id' => $counter,
|
7765 |
-
'AuditLog.CssClass' => $css_class,
|
7766 |
-
);
|
7767 |
-
|
7768 |
-
// If there is a filter, check the access_log data and break the operation if needed.
|
7769 |
-
if ( $filter_query ) {
|
7770 |
-
if ( $filter_by_denial_type ) {
|
7771 |
-
$denial_type_slug = SucuriScan::human2var( $access_log->sucuri_block_reason );
|
7772 |
-
|
7773 |
-
if ( $denial_type_slug != $filter_query ) {
|
7774 |
-
continue;
|
7775 |
-
}
|
7776 |
-
}
|
7777 |
-
|
7778 |
-
if (
|
7779 |
-
$filter_by_keyword
|
7780 |
-
&& strpos( $access_log->remote_addr, $filter_query ) === false
|
7781 |
-
&& strpos( $access_log->resource_path, $filter_query ) === false
|
7782 |
-
) {
|
7783 |
-
continue;
|
7784 |
-
}
|
7785 |
-
}
|
7786 |
-
|
7787 |
-
// Generate (dynamically) the pseudo-variables for the template.
|
7788 |
-
foreach ( $needed_attrs as $attr_name ) {
|
7789 |
-
$attr_value = '';
|
7790 |
|
7791 |
-
|
7792 |
-
|
7793 |
-
|
7794 |
-
$attr_title = 'AuditLog.' . $attr_title;
|
7795 |
|
7796 |
-
|
7797 |
-
|
|
|
|
|
|
|
|
|
7798 |
|
7799 |
-
|
7800 |
-
|
7801 |
-
|
7802 |
-
|
7803 |
-
|
7804 |
-
}
|
7805 |
-
} elseif ( $attr_name == 'local_request_time' ) {
|
7806 |
-
$attr_value = SucuriScan::datetime( $access_log->request_timestamp );
|
7807 |
}
|
7808 |
|
7809 |
-
|
7810 |
-
|
7811 |
-
|
7812 |
-
|
7813 |
-
|
7814 |
-
|
7815 |
-
|
7816 |
-
|
7817 |
-
return $logs_html;
|
7818 |
-
}
|
7819 |
-
|
7820 |
-
/**
|
7821 |
-
* Get a list of denial types using the reason of the blocking of a request from
|
7822 |
-
* the from the audit logs. Examples of denial types can be: "Bad bot access
|
7823 |
-
* denied", "Access to restricted folder", "Blocked by IDS", etc.
|
7824 |
-
*
|
7825 |
-
* @param array $access_logs A list of objects with the detailed version of each request blocked by our service.
|
7826 |
-
* @param boolean $in_html Whether the list should be converted to a HTML select options or not.
|
7827 |
-
* @return array Either a list of unique blocking types, or a HTML code.
|
7828 |
-
*/
|
7829 |
-
function sucuriscan_monitoring_denial_types( $access_logs = array(), $in_html = true ){
|
7830 |
-
$types = array();
|
7831 |
-
|
7832 |
-
if ( $access_logs && ! empty($access_logs) ) {
|
7833 |
-
foreach ( $access_logs as $access_log ) {
|
7834 |
-
if ( ! array_key_exists( $access_log->sucuri_block_reason, $types ) ) {
|
7835 |
-
$denial_type_k = SucuriScan::human2var( $access_log->sucuri_block_reason );
|
7836 |
-
$denial_type_v = $access_log->sucuri_block_reason;
|
7837 |
-
|
7838 |
-
if ( empty($denial_type_v) ) {
|
7839 |
-
$denial_type_v = 'Unknown';
|
7840 |
}
|
7841 |
-
|
7842 |
-
$types[ $denial_type_k ] = $denial_type_v;
|
7843 |
}
|
7844 |
-
}
|
7845 |
-
}
|
7846 |
-
|
7847 |
-
if ( $in_html ) {
|
7848 |
-
$html_types = '<option value="">Filter</option>';
|
7849 |
-
$selected = SucuriScanRequest::post( ':monitoring_denial_type', '.+' );
|
7850 |
|
7851 |
-
|
7852 |
-
$
|
7853 |
-
$html_types .= sprintf(
|
7854 |
-
'<option value="%s" %s>%s</option>',
|
7855 |
-
SucuriScan::escape( $type_key ),
|
7856 |
-
$selected_tag,
|
7857 |
-
SucuriScan::escape( $type_value )
|
7858 |
-
);
|
7859 |
}
|
7860 |
-
|
7861 |
-
return $html_types;
|
7862 |
}
|
7863 |
|
7864 |
-
return $
|
7865 |
}
|
7866 |
|
7867 |
/**
|
@@ -7872,26 +8212,27 @@ function sucuriscan_monitoring_denial_types( $access_logs = array(), $in_html =
|
|
7872 |
* @param boolean $in_html Whether the list should be converted to a HTML select options or not.
|
7873 |
* @return array Either an array with the expected values, or a HTML code.
|
7874 |
*/
|
7875 |
-
function
|
|
|
7876 |
$options = array();
|
7877 |
$selected = '';
|
|
|
|
|
|
|
|
|
7878 |
|
7879 |
-
if (
|
7880 |
$s_year = $date_m[1];
|
7881 |
$s_month = $date_m[2];
|
7882 |
$s_day = $date_m[3];
|
7883 |
-
} else {
|
7884 |
-
$s_year = '';
|
7885 |
-
$s_month = '';
|
7886 |
-
$s_day = '';
|
7887 |
}
|
7888 |
|
7889 |
-
switch (
|
7890 |
case 'years':
|
7891 |
$selected = $s_year;
|
7892 |
-
$current_year = (int) date(
|
7893 |
$max_years = 5; /* Maximum number of years to keep the logs. */
|
7894 |
-
$options = range(
|
7895 |
break;
|
7896 |
case 'months':
|
7897 |
$selected = $s_month;
|
@@ -7911,25 +8252,25 @@ function sucuriscan_monitoring_dates( $type = '', $date = '', $in_html = true ){
|
|
7911 |
);
|
7912 |
break;
|
7913 |
case 'days':
|
7914 |
-
$options = range(
|
7915 |
$selected = $s_day;
|
7916 |
break;
|
7917 |
}
|
7918 |
|
7919 |
-
if (
|
7920 |
$html_options = '';
|
7921 |
|
7922 |
-
foreach (
|
7923 |
-
if (
|
7924 |
-
$value = str_pad(
|
7925 |
}
|
7926 |
|
7927 |
-
if (
|
7928 |
$key = $value;
|
7929 |
}
|
7930 |
|
7931 |
$selected_tag = ( $key == $selected ) ? 'selected="selected"' : '';
|
7932 |
-
$html_options .= sprintf(
|
7933 |
}
|
7934 |
|
7935 |
return $html_options;
|
@@ -7938,6 +8279,125 @@ function sucuriscan_monitoring_dates( $type = '', $date = '', $in_html = true ){
|
|
7938 |
return $options;
|
7939 |
}
|
7940 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
7941 |
/**
|
7942 |
* Project hardening library.
|
7943 |
*
|
@@ -7956,7 +8416,8 @@ function sucuriscan_monitoring_dates( $type = '', $date = '', $in_html = true ){
|
|
7956 |
* Apache/PHP Hardener that can, for example, deactivate unneeded features in
|
7957 |
* configuration files or perform various other protective measures.
|
7958 |
*/
|
7959 |
-
class SucuriScanHardening extends SucuriScan
|
|
|
7960 |
|
7961 |
/**
|
7962 |
* Returns a list of access control rules for the Apache web server that can be
|
@@ -8170,7 +8631,8 @@ class SucuriScanHardening extends SucuriScan {
|
|
8170 |
*
|
8171 |
* @return void
|
8172 |
*/
|
8173 |
-
function sucuriscan_hardening_page()
|
|
|
8174 |
SucuriScanInterface::check_permissions();
|
8175 |
|
8176 |
$template_variables = array(
|
@@ -8178,12 +8640,13 @@ function sucuriscan_hardening_page(){
|
|
8178 |
'Hardening.Whitelist' => sucuriscan_hardening_whitelist(),
|
8179 |
);
|
8180 |
|
8181 |
-
echo SucuriScanTemplate::
|
8182 |
}
|
8183 |
|
8184 |
-
function sucuriscan_hardening_panel()
|
|
|
8185 |
if (SucuriScanRequest::post(':run_hardening')
|
8186 |
-
&& !
|
8187 |
) {
|
8188 |
unset($_POST['sucuriscan_run_hardening']);
|
8189 |
}
|
@@ -8216,10 +8679,11 @@ function sucuriscan_hardening_panel(){
|
|
8216 |
$template_variables['Hardening.WpIncludes'] = sucuriscan_harden_wpincludes();
|
8217 |
}
|
8218 |
|
8219 |
-
return SucuriScanTemplate::
|
8220 |
}
|
8221 |
|
8222 |
-
function sucuriscan_hardening_whitelist()
|
|
|
8223 |
$template_variables = array(
|
8224 |
'HardeningWhitelist.List' => '',
|
8225 |
'HardeningWhitelist.NoItemsVisibility' => 'visible',
|
@@ -8268,19 +8732,22 @@ function sucuriscan_hardening_whitelist(){
|
|
8268 |
foreach ($files as $file) {
|
8269 |
$css_class = ($counter % 2 === 0) ? '' : 'alternate';
|
8270 |
$fregexp = sprintf('%s/.*/%s', $folder, $file);
|
8271 |
-
$html = SucuriScanTemplate::
|
8272 |
-
'
|
8273 |
-
|
8274 |
-
|
8275 |
-
|
8276 |
-
|
|
|
|
|
|
|
8277 |
$template_variables['HardeningWhitelist.List'] .= $html;
|
8278 |
$counter++;
|
8279 |
}
|
8280 |
}
|
8281 |
}
|
8282 |
|
8283 |
-
return SucuriScanTemplate::
|
8284 |
}
|
8285 |
|
8286 |
/**
|
@@ -8297,9 +8764,10 @@ function sucuriscan_hardening_whitelist(){
|
|
8297 |
* @param string $updatemsg Optional explanation of the hardening after the submission of the form.
|
8298 |
* @return void
|
8299 |
*/
|
8300 |
-
function sucuriscan_harden_status(
|
|
|
8301 |
$template_variables = array(
|
8302 |
-
'Hardening.Title' =>
|
8303 |
'Hardening.Description' => '',
|
8304 |
'Hardening.Status' => 'unknown',
|
8305 |
'Hardening.FieldName' => '',
|
@@ -8309,18 +8777,18 @@ function sucuriscan_harden_status( $title = '', $status = 0, $type = '', $messag
|
|
8309 |
'Hardening.UpdateMessage' => '',
|
8310 |
);
|
8311 |
|
8312 |
-
if (
|
8313 |
$type = 'unknown';
|
8314 |
$template_variables['Hardening.FieldAttributes'] = 'disabled="disabled"';
|
8315 |
}
|
8316 |
|
8317 |
$template_variables['Hardening.Status'] = (string) $status;
|
8318 |
|
8319 |
-
if (
|
8320 |
$template_variables['Hardening.FieldName'] = $type . '_unharden';
|
8321 |
$template_variables['Hardening.FieldValue'] = 'Revert hardening';
|
8322 |
$template_variables['Hardening.Information'] = $messageok;
|
8323 |
-
} elseif (
|
8324 |
$template_variables['Hardening.FieldName'] = $type;
|
8325 |
$template_variables['Hardening.FieldValue'] = 'Harden';
|
8326 |
$template_variables['Hardening.Information'] = $messagewarn;
|
@@ -8331,15 +8799,15 @@ function sucuriscan_harden_status( $title = '', $status = 0, $type = '', $messag
|
|
8331 |
$template_variables['Hardening.FieldAttributes'] = 'disabled="disabled"';
|
8332 |
}
|
8333 |
|
8334 |
-
if (
|
8335 |
$template_variables['Hardening.Description'] = '<p>' . $desc . '</p>';
|
8336 |
}
|
8337 |
|
8338 |
-
if (
|
8339 |
$template_variables['Hardening.UpdateMessage'] = '<p>' . $updatemsg . '</p>';
|
8340 |
}
|
8341 |
|
8342 |
-
return SucuriScanTemplate::
|
8343 |
}
|
8344 |
|
8345 |
/**
|
@@ -8348,21 +8816,21 @@ function sucuriscan_harden_status( $title = '', $status = 0, $type = '', $messag
|
|
8348 |
*
|
8349 |
* @return void
|
8350 |
*/
|
8351 |
-
function sucuriscan_harden_version()
|
|
|
8352 |
$site_version = SucuriScan::site_version();
|
8353 |
$updates = get_core_updates();
|
8354 |
-
$cp = (
|
8355 |
|
8356 |
-
if (
|
8357 |
-
if (
|
8358 |
-
$updates[0]->response == 'latest'
|
8359 |
|| $updates[0]->response == 'development'
|
8360 |
) {
|
8361 |
$cp = 1;
|
8362 |
}
|
8363 |
}
|
8364 |
|
8365 |
-
if (
|
8366 |
$cp = 0;
|
8367 |
}
|
8368 |
|
@@ -8371,14 +8839,14 @@ function sucuriscan_harden_version(){
|
|
8371 |
to the source code are made public, if there were security fixes then
|
8372 |
someone with malicious intent can use this information to attack any site
|
8373 |
that has not been upgraded.';
|
8374 |
-
$messageok = sprintf(
|
8375 |
$messagewarn = sprintf(
|
8376 |
'Your current version (%s) is not current.<br>
|
8377 |
<a href="update-core.php" class="button-primary">Update now!</a>',
|
8378 |
$site_version
|
8379 |
);
|
8380 |
|
8381 |
-
return sucuriscan_harden_status(
|
8382 |
}
|
8383 |
|
8384 |
/**
|
@@ -8388,7 +8856,8 @@ function sucuriscan_harden_version(){
|
|
8388 |
*
|
8389 |
* @return void
|
8390 |
*/
|
8391 |
-
function sucuriscan_harden_removegenerator()
|
|
|
8392 |
return sucuriscan_harden_status(
|
8393 |
'Remove WordPress version',
|
8394 |
1,
|
@@ -8400,14 +8869,15 @@ function sucuriscan_harden_removegenerator(){
|
|
8400 |
);
|
8401 |
}
|
8402 |
|
8403 |
-
function sucuriscan_harden_nginx_phpfpm()
|
|
|
8404 |
$description = 'It seems that you are using the Nginx web server, if that is
|
8405 |
the case then you will need to add the following code into the global
|
8406 |
<code>nginx.conf</code> file or the virtualhost associated with this
|
8407 |
website. Choose the correct rules for the directories that you want to
|
8408 |
protect. If you encounter errors after restart the web server then revert
|
8409 |
the changes and contact the support team of your hosting company, or read
|
8410 |
-
the official article about <a href="
|
8411 |
WordPress on Nginx</a>.</p>';
|
8412 |
|
8413 |
$description .= "<pre class='code'># Block PHP files in uploads directory.\nlocation ~* /(?:uploads|files)/.*\.php$ {\n\x20\x20deny all;\n}</pre>";
|
@@ -8441,35 +8911,36 @@ function sucuriscan_harden_nginx_phpfpm(){
|
|
8441 |
*
|
8442 |
* @return void
|
8443 |
*/
|
8444 |
-
function sucuriscan_harden_upload()
|
|
|
8445 |
$dpath = WP_CONTENT_DIR . '/uploads';
|
8446 |
|
8447 |
-
if (
|
8448 |
-
if (
|
8449 |
-
$result = SucuriScanHardening::harden_directory(
|
8450 |
|
8451 |
-
if (
|
8452 |
$message = 'Hardening applied to the uploads directory';
|
8453 |
-
SucuriScanEvent::report_notice_event(
|
8454 |
-
SucuriScanInterface::info(
|
8455 |
} else {
|
8456 |
-
SucuriScanInterface::error(
|
8457 |
}
|
8458 |
-
} elseif (
|
8459 |
-
$result = SucuriScanHardening::unharden_directory(
|
8460 |
|
8461 |
-
if (
|
8462 |
$message = 'Hardening reverted in the uploads directory';
|
8463 |
-
SucuriScanEvent::report_error_event(
|
8464 |
-
SucuriScanInterface::info(
|
8465 |
} else {
|
8466 |
-
SucuriScanInterface::info(
|
8467 |
}
|
8468 |
}
|
8469 |
}
|
8470 |
|
8471 |
// Check whether the directory is already hardened or not.
|
8472 |
-
$is_hardened = SucuriScanHardening::is_hardened(
|
8473 |
$cp = ( $is_hardened === true ) ? 1 : 0;
|
8474 |
|
8475 |
$description = 'It checks if the uploads directory of this site allows the direct execution'
|
@@ -8501,33 +8972,34 @@ function sucuriscan_harden_upload(){
|
|
8501 |
*
|
8502 |
* @return void
|
8503 |
*/
|
8504 |
-
function sucuriscan_harden_wpcontent()
|
8505 |
-
|
8506 |
-
|
8507 |
-
|
|
|
8508 |
|
8509 |
-
if (
|
8510 |
$message = 'Hardening applied to the content directory';
|
8511 |
-
SucuriScanEvent::report_notice_event(
|
8512 |
-
SucuriScanInterface::info(
|
8513 |
} else {
|
8514 |
-
SucuriScanInterface::error(
|
8515 |
}
|
8516 |
-
} elseif (
|
8517 |
-
$result = SucuriScanHardening::unharden_directory(
|
8518 |
|
8519 |
-
if (
|
8520 |
$message = 'Hardening reverted in the content directory';
|
8521 |
-
SucuriScanEvent::report_error_event(
|
8522 |
-
SucuriScanInterface::info(
|
8523 |
} else {
|
8524 |
-
SucuriScanInterface::info(
|
8525 |
}
|
8526 |
}
|
8527 |
}
|
8528 |
|
8529 |
// Check whether the directory is already hardened or not.
|
8530 |
-
$is_hardened = SucuriScanHardening::is_hardened(
|
8531 |
$cp = ( $is_hardened === true ) ? 1 : 0;
|
8532 |
|
8533 |
$description = 'This option blocks direct access to any PHP file located under the content'
|
@@ -8558,39 +9030,40 @@ function sucuriscan_harden_wpcontent(){
|
|
8558 |
*
|
8559 |
* @return void
|
8560 |
*/
|
8561 |
-
function sucuriscan_harden_wpincludes()
|
|
|
8562 |
$dpath = ABSPATH . '/wp-includes';
|
8563 |
|
8564 |
-
if (
|
8565 |
-
if (
|
8566 |
-
$result = SucuriScanHardening::harden_directory(
|
8567 |
|
8568 |
-
if (
|
8569 |
$message = 'Hardening applied to the library directory';
|
8570 |
SucuriScanHardening::whitelist('wp-tinymce.php', 'wp-includes');
|
8571 |
SucuriScanHardening::whitelist('ms-files.php', 'wp-includes');
|
8572 |
-
SucuriScanEvent::report_notice_event(
|
8573 |
-
SucuriScanInterface::info(
|
8574 |
} else {
|
8575 |
-
SucuriScanInterface::error(
|
8576 |
}
|
8577 |
-
} elseif (
|
8578 |
-
$result = SucuriScanHardening::unharden_directory(
|
8579 |
|
8580 |
-
if (
|
8581 |
$message = 'Hardening reverted in the library directory';
|
8582 |
SucuriScanHardening::dewhitelist('wp-tinymce.php', 'wp-includes');
|
8583 |
SucuriScanHardening::dewhitelist('ms-files.php', 'wp-includes');
|
8584 |
-
SucuriScanEvent::report_error_event(
|
8585 |
-
SucuriScanInterface::info(
|
8586 |
} else {
|
8587 |
-
SucuriScanInterface::info(
|
8588 |
}
|
8589 |
}
|
8590 |
}
|
8591 |
|
8592 |
// Check whether the directory is already hardened or not.
|
8593 |
-
$is_hardened = SucuriScanHardening::is_hardened(
|
8594 |
$cp = ( $is_hardened === true ) ? 1 : 0;
|
8595 |
|
8596 |
return sucuriscan_harden_status(
|
@@ -8610,9 +9083,10 @@ function sucuriscan_harden_wpincludes(){
|
|
8610 |
*
|
8611 |
* @return void
|
8612 |
*/
|
8613 |
-
function sucuriscan_harden_phpversion()
|
|
|
8614 |
$phpv = phpversion();
|
8615 |
-
$cp = ( strncmp(
|
8616 |
|
8617 |
return sucuriscan_harden_status(
|
8618 |
'Verify PHP version',
|
@@ -8630,18 +9104,19 @@ function sucuriscan_harden_phpversion(){
|
|
8630 |
*
|
8631 |
* @return void
|
8632 |
*/
|
8633 |
-
function sucuriscan_cloudproxy_enabled()
|
|
|
8634 |
$btn_string = '';
|
8635 |
$proxy_info = SucuriScan::is_behind_cloudproxy();
|
8636 |
$status = 1;
|
8637 |
|
8638 |
$description = 'A WAF is a protection layer for your web site, blocking all sort of attacks (brute force attempts, '
|
8639 |
. 'DDoS, SQL injections, etc) and helping it remain malware and blacklist free. This test checks if your site is '
|
8640 |
-
. 'using <a href="
|
8641 |
|
8642 |
-
if (
|
8643 |
$status = 0;
|
8644 |
-
$btn_string = '<a href="
|
8645 |
}
|
8646 |
|
8647 |
return sucuriscan_harden_status(
|
@@ -8665,18 +9140,17 @@ function sucuriscan_cloudproxy_enabled(){
|
|
8665 |
*
|
8666 |
* @return void
|
8667 |
*/
|
8668 |
-
function sucuriscan_harden_secretkeys()
|
|
|
8669 |
$wp_config_path = SucuriScan::get_wpconfig_path();
|
8670 |
$current_keys = SucuriScanOption::get_security_keys();
|
8671 |
|
8672 |
-
if (
|
8673 |
$cp = 1;
|
8674 |
-
$
|
|
|
8675 |
|
8676 |
-
if (
|
8677 |
-
! empty($current_keys['bad'])
|
8678 |
-
|| ! empty($current_keys['missing'])
|
8679 |
-
) {
|
8680 |
$cp = 0;
|
8681 |
}
|
8682 |
} else {
|
@@ -8685,13 +9159,13 @@ function sucuriscan_harden_secretkeys(){
|
|
8685 |
}
|
8686 |
|
8687 |
$message .= '<br>It checks whether you have proper random keys/salts created for WordPress. A
|
8688 |
-
<a href="
|
8689 |
secret key</a> makes your site harder to hack and access harder to crack by adding
|
8690 |
random elements to the password. In simple terms, a secret key is a password with
|
8691 |
elements that make it harder to generate enough options to break through your
|
8692 |
security barriers.';
|
8693 |
$messageok = 'Security keys and salts not set, we recommend to create them for security reasons'
|
8694 |
-
. '<a href="' . SucuriScanTemplate::
|
8695 |
. 'Harden</a>';
|
8696 |
|
8697 |
return sucuriscan_harden_status(
|
@@ -8712,23 +9186,24 @@ function sucuriscan_harden_secretkeys(){
|
|
8712 |
*
|
8713 |
* @return void
|
8714 |
*/
|
8715 |
-
function sucuriscan_harden_readme()
|
|
|
8716 |
$upmsg = null;
|
8717 |
-
$cp = is_readable(
|
8718 |
|
8719 |
// TODO: After hardening create an option to automatically remove this after WP upgrade.
|
8720 |
-
if (
|
8721 |
-
if (
|
8722 |
-
if (
|
8723 |
-
$upmsg = SucuriScanInterface::error(
|
8724 |
} else {
|
8725 |
$cp = 1;
|
8726 |
$message = 'Hardening applied to the <code>readme.html</code> file';
|
8727 |
-
SucuriScanEvent::report_notice_event(
|
8728 |
-
SucuriScanInterface::info(
|
8729 |
}
|
8730 |
-
} elseif (
|
8731 |
-
SucuriScanInterface::error(
|
8732 |
}
|
8733 |
}
|
8734 |
|
@@ -8749,7 +9224,8 @@ function sucuriscan_harden_readme(){
|
|
8749 |
*
|
8750 |
* @return void
|
8751 |
*/
|
8752 |
-
function sucuriscan_harden_adminuser()
|
|
|
8753 |
global $wpdb;
|
8754 |
|
8755 |
$upmsg = null;
|
@@ -8759,12 +9235,12 @@ function sucuriscan_harden_adminuser(){
|
|
8759 |
'search_columns' => array( 'user_login' ),
|
8760 |
));
|
8761 |
$results = $user_query->get_results();
|
8762 |
-
$account_removed = ( count(
|
8763 |
|
8764 |
-
if (
|
8765 |
$upmsg = '<i><strong>Notice.</strong> We do not offer an option to automatically change the user name.
|
8766 |
-
Go to the <a href="'.admin_url(
|
8767 |
-
administrator user. Once created, log in as that user and remove the default <code>admin</code>
|
8768 |
(make sure to assign all the admin posts to the new user too).</i>';
|
8769 |
}
|
8770 |
|
@@ -8784,49 +9260,50 @@ function sucuriscan_harden_adminuser(){
|
|
8784 |
*
|
8785 |
* @return void
|
8786 |
*/
|
8787 |
-
function sucuriscan_harden_fileeditor()
|
8788 |
-
|
|
|
8789 |
|
8790 |
-
if (
|
8791 |
-
$current_time = date(
|
8792 |
$wp_config_path = SucuriScan::get_wpconfig_path();
|
8793 |
|
8794 |
-
$wp_config_writable = ( file_exists(
|
8795 |
-
$new_wpconfig = $wp_config_writable ? @file_get_contents(
|
8796 |
|
8797 |
-
if (
|
8798 |
-
if (
|
8799 |
-
if (
|
8800 |
$disallow_fileedit_definition = "\n\ndefine('DISALLOW_FILE_EDIT', TRUE); // Sucuri Security: {$current_time}\n";
|
8801 |
-
$new_wpconfig = str_replace(
|
8802 |
}
|
8803 |
|
8804 |
$file_editor_disabled = true;
|
8805 |
-
@file_put_contents(
|
8806 |
$message = 'Hardening applied to the plugin and theme editor';
|
8807 |
-
SucuriScanEvent::report_notice_event(
|
8808 |
-
SucuriScanInterface::info(
|
8809 |
} else {
|
8810 |
-
SucuriScanInterface::error(
|
8811 |
or is not writable, you will need to put the following code manually there:
|
8812 |
-
<code>define("DISALLOW_FILE_EDIT", TRUE);</code>'
|
8813 |
}
|
8814 |
-
} elseif (
|
8815 |
-
if (
|
8816 |
-
if (
|
8817 |
-
$new_wpconfig = str_replace(
|
8818 |
-
file_put_contents(
|
8819 |
$file_editor_disabled = false;
|
8820 |
$message = 'Hardening reverted in the plugin and theme editor';
|
8821 |
-
SucuriScanEvent::report_error_event(
|
8822 |
-
SucuriScanInterface::info(
|
8823 |
} else {
|
8824 |
-
SucuriScanInterface::error(
|
8825 |
or is not writable, you will need to remove the following code manually from there:
|
8826 |
-
<code>define("DISALLOW_FILE_EDIT", TRUE);</code>'
|
8827 |
}
|
8828 |
} else {
|
8829 |
-
SucuriScanInterface::error(
|
8830 |
}
|
8831 |
}
|
8832 |
}
|
@@ -8854,7 +9331,8 @@ function sucuriscan_harden_fileeditor(){
|
|
8854 |
*
|
8855 |
* @return void
|
8856 |
*/
|
8857 |
-
function sucuriscan_harden_dbtables()
|
|
|
8858 |
global $table_prefix;
|
8859 |
|
8860 |
$hardened = ( $table_prefix == 'wp_' ? 0 : 1 );
|
@@ -8875,10 +9353,11 @@ function sucuriscan_harden_dbtables(){
|
|
8875 |
*
|
8876 |
* @return void
|
8877 |
*/
|
8878 |
-
function sucuriscan_harden_errorlog()
|
|
|
8879 |
$hardened = 1;
|
8880 |
-
$log_filename = SucuriScan::ini_get(
|
8881 |
-
$scan_errorlogs = SucuriScanOption::get_option(
|
8882 |
|
8883 |
$description = 'PHP uses files named as <code>' . $log_filename . '</code> to log errors found in '
|
8884 |
. 'the code, these files may leak sensitive information of your project allowing an attacker '
|
@@ -8886,12 +9365,12 @@ function sucuriscan_harden_errorlog(){
|
|
8886 |
. 'a development environment, and remove them in production mode.';
|
8887 |
|
8888 |
// Search error log files in the project.
|
8889 |
-
if (
|
8890 |
$file_info = new SucuriScanFileInfo();
|
8891 |
$file_info->ignore_files = false;
|
8892 |
$file_info->ignore_directories = false;
|
8893 |
-
$error_logs = $file_info->find_file(
|
8894 |
-
$total_log_files = count(
|
8895 |
} else {
|
8896 |
$hardened = 2;
|
8897 |
$error_logs = array();
|
@@ -8903,33 +9382,33 @@ function sucuriscan_harden_errorlog(){
|
|
8903 |
}
|
8904 |
|
8905 |
// Remove every error log file found in the filesystem scan.
|
8906 |
-
if (
|
8907 |
-
if (
|
8908 |
$removed_logs = 0;
|
8909 |
-
SucuriScanEvent::report_notice_event(
|
8910 |
'Error log files deleted: (multiple entries): %s',
|
8911 |
-
@implode(
|
8912 |
-
)
|
8913 |
|
8914 |
-
foreach (
|
8915 |
-
if (
|
8916 |
unset($error_logs[ $i ]);
|
8917 |
$removed_logs += 1;
|
8918 |
}
|
8919 |
}
|
8920 |
|
8921 |
-
SucuriScanInterface::info(
|
8922 |
}
|
8923 |
}
|
8924 |
|
8925 |
// List the error log files in a HTML table.
|
8926 |
-
if (
|
8927 |
$hardened = 0;
|
8928 |
$description .= '</p><ul class="sucuriscan-list-as-table">';
|
8929 |
|
8930 |
-
foreach (
|
8931 |
-
$error_log_path = str_replace(
|
8932 |
-
$description .= '<li>' . $error_log_path . '</li>';
|
8933 |
}
|
8934 |
|
8935 |
$description .= '</ul><p>';
|
@@ -8962,141 +9441,30 @@ function sucuriscan_page()
|
|
8962 |
// Process all form submissions.
|
8963 |
sucuriscan_integrity_form_submissions();
|
8964 |
|
8965 |
-
$
|
8966 |
'WordpressVersion' => sucuriscan_wordpress_outdated(),
|
8967 |
'CoreFiles' => sucuriscan_core_files(),
|
8968 |
'AuditReports' => sucuriscan_auditreport(),
|
8969 |
'AuditLogs' => sucuriscan_auditlogs(),
|
8970 |
);
|
8971 |
|
8972 |
-
echo SucuriScanTemplate::
|
8973 |
-
}
|
8974 |
-
|
8975 |
-
/**
|
8976 |
-
* Process the requests sent by the form submissions originated in the integrity
|
8977 |
-
* page, all forms must have a nonce field that will be checked against the one
|
8978 |
-
* generated in the template render function.
|
8979 |
-
*
|
8980 |
-
* @return void
|
8981 |
-
*/
|
8982 |
-
function sucuriscan_integrity_form_submissions()
|
8983 |
-
{
|
8984 |
-
if (SucuriScanInterface::check_nonce()) {
|
8985 |
-
// Force the execution of the filesystem scanner.
|
8986 |
-
if (SucuriScanRequest::post(':force_scan') !== false) {
|
8987 |
-
SucuriScanEvent::notify_event('plugin_change', 'Filesystem scan forced at: ' . date('r'));
|
8988 |
-
SucuriScanEvent::filesystem_scan(true);
|
8989 |
-
}
|
8990 |
-
|
8991 |
-
// Restore, Remove, Mark as fixed the core files.
|
8992 |
-
$allowed_actions = '(restore|delete|fixed)';
|
8993 |
-
$integrity_action = SucuriScanRequest::post(':integrity_action', $allowed_actions);
|
8994 |
-
|
8995 |
-
if ($integrity_action !== false) {
|
8996 |
-
$cache = new SucuriScanCache('integrity');
|
8997 |
-
$integrity_files = SucuriScanRequest::post(':integrity_files', '_array');
|
8998 |
-
$integrity_types = SucuriScanRequest::post(':integrity_types', '_array');
|
8999 |
-
$files_selected = count($integrity_files);
|
9000 |
-
$files_affected = array();
|
9001 |
-
$files_processed = 0;
|
9002 |
-
$action_titles = array(
|
9003 |
-
'restore' => 'Core file restored',
|
9004 |
-
'delete' => 'Non-core file deleted',
|
9005 |
-
'fixed' => 'Core file marked as fixed',
|
9006 |
-
);
|
9007 |
-
|
9008 |
-
if ($integrity_files) {
|
9009 |
-
foreach ((array) $integrity_files as $i => $file_path) {
|
9010 |
-
$full_path = ABSPATH . $file_path;
|
9011 |
-
$status_type = $integrity_types[ $i ];
|
9012 |
-
|
9013 |
-
switch ($integrity_action) {
|
9014 |
-
case 'restore':
|
9015 |
-
$file_content = SucuriScanAPI::get_original_core_file($file_path);
|
9016 |
-
if ($file_content) {
|
9017 |
-
$restored = @file_put_contents($full_path, $file_content, LOCK_EX);
|
9018 |
-
$files_processed += ( $restored ? 1 : 0 );
|
9019 |
-
$files_affected[] = $full_path;
|
9020 |
-
}
|
9021 |
-
break;
|
9022 |
-
case 'delete':
|
9023 |
-
if (@unlink($full_path)) {
|
9024 |
-
$files_processed += 1;
|
9025 |
-
$files_affected[] = $full_path;
|
9026 |
-
}
|
9027 |
-
break;
|
9028 |
-
case 'fixed':
|
9029 |
-
$cache_key = md5($file_path);
|
9030 |
-
$cache_value = array(
|
9031 |
-
'file_path' => $file_path,
|
9032 |
-
'file_status' => $status_type,
|
9033 |
-
'ignored_at' => time(),
|
9034 |
-
);
|
9035 |
-
$cached = $cache->add($cache_key, $cache_value);
|
9036 |
-
$files_processed += ( $cached ? 1 : 0 );
|
9037 |
-
$files_affected[] = $full_path;
|
9038 |
-
break;
|
9039 |
-
}
|
9040 |
-
}
|
9041 |
-
|
9042 |
-
// Report files affected as a single event.
|
9043 |
-
if (! empty($files_affected)) {
|
9044 |
-
$message_tpl = ( count($files_affected) > 1 )
|
9045 |
-
? '%s: (multiple entries): %s'
|
9046 |
-
: '%s: %s';
|
9047 |
-
$message = sprintf(
|
9048 |
-
$message_tpl,
|
9049 |
-
$action_titles[ $integrity_action ],
|
9050 |
-
@implode(',', $files_affected)
|
9051 |
-
);
|
9052 |
-
|
9053 |
-
switch ($integrity_action) {
|
9054 |
-
case 'restore':
|
9055 |
-
SucuriScanEvent::report_info_event($message);
|
9056 |
-
break;
|
9057 |
-
case 'delete':
|
9058 |
-
SucuriScanEvent::report_notice_event($message);
|
9059 |
-
break;
|
9060 |
-
case 'fixed':
|
9061 |
-
SucuriScanEvent::report_warning_event($message);
|
9062 |
-
break;
|
9063 |
-
}
|
9064 |
-
}
|
9065 |
-
|
9066 |
-
SucuriScanInterface::info(sprintf(
|
9067 |
-
'<code>%d</code> out of <code>%d</code> files were successfully processed.',
|
9068 |
-
$files_selected,
|
9069 |
-
$files_processed
|
9070 |
-
));
|
9071 |
-
}
|
9072 |
-
}
|
9073 |
-
}
|
9074 |
}
|
9075 |
|
9076 |
/**
|
9077 |
-
*
|
9078 |
-
* folder specified. This is a recursive function.
|
9079 |
*
|
9080 |
-
* @
|
9081 |
-
* @param boolean $recursive Either TRUE or FALSE if the scan should be performed recursively.
|
9082 |
-
* @return array List of arrays containing the md5sum and last modification time of the files found.
|
9083 |
*/
|
9084 |
-
function
|
9085 |
{
|
9086 |
-
|
9087 |
-
|
9088 |
-
$file_info = new SucuriScanFileInfo();
|
9089 |
-
$file_info->ignore_files = false;
|
9090 |
-
$file_info->ignore_directories = false;
|
9091 |
-
$file_info->run_recursively = $recursive;
|
9092 |
-
$file_info->scan_interface = SucuriScanOption::get_option(':scan_interface');
|
9093 |
-
$integrity_tree = $file_info->get_directory_tree_md5($dir, true);
|
9094 |
|
9095 |
-
if (
|
9096 |
-
|
9097 |
}
|
9098 |
|
9099 |
-
|
9100 |
}
|
9101 |
|
9102 |
/**
|
@@ -9109,11 +9477,11 @@ function sucuriscan_auditlogs()
|
|
9109 |
{
|
9110 |
// Initialize the values for the pagination.
|
9111 |
$max_per_page = SUCURISCAN_AUDITLOGS_PER_PAGE;
|
9112 |
-
$page_number = SucuriScanTemplate::
|
9113 |
$logs_limit = $page_number * $max_per_page;
|
9114 |
-
$audit_logs = SucuriScanAPI::
|
9115 |
|
9116 |
-
$
|
9117 |
'PageTitle' => 'Audit Logs',
|
9118 |
'AuditLogs.List' => '',
|
9119 |
'AuditLogs.Count' => 0,
|
@@ -9133,7 +9501,7 @@ function sucuriscan_auditlogs()
|
|
9133 |
if ($audit_logs->total_entries >= $max_per_page
|
9134 |
&& SucuriScanOption::is_disabled(':audit_report')
|
9135 |
) {
|
9136 |
-
$
|
9137 |
}
|
9138 |
|
9139 |
for ($i = $iterator_start; $i < $total_items; $i++) {
|
@@ -9147,13 +9515,14 @@ function sucuriscan_auditlogs()
|
|
9147 |
$css_class = ( $counter_i % 2 == 0 ) ? '' : 'alternate';
|
9148 |
$snippet_data = array(
|
9149 |
'AuditLog.CssClass' => $css_class,
|
9150 |
-
'AuditLog.Event' =>
|
9151 |
-
'AuditLog.EventTitle' =>
|
|
|
9152 |
'AuditLog.DateTime' => SucuriScan::datetime($audit_log['timestamp']),
|
9153 |
-
'AuditLog.Account' =>
|
9154 |
-
'AuditLog.Username' =>
|
9155 |
-
'AuditLog.RemoteAddress' =>
|
9156 |
-
'AuditLog.Message' =>
|
9157 |
'AuditLog.Extra' => '',
|
9158 |
);
|
9159 |
|
@@ -9167,13 +9536,13 @@ function sucuriscan_auditlogs()
|
|
9167 |
$snippet_data['AuditLog.Extra'] .= '</ul>';
|
9168 |
}
|
9169 |
|
9170 |
-
$
|
9171 |
$counter_i += 1;
|
9172 |
}
|
9173 |
}
|
9174 |
|
9175 |
-
$
|
9176 |
-
$
|
9177 |
|
9178 |
if ($total_items > 1) {
|
9179 |
$max_pages = ceil($audit_logs->total_entries / $max_per_page);
|
@@ -9183,8 +9552,8 @@ function sucuriscan_auditlogs()
|
|
9183 |
}
|
9184 |
|
9185 |
if ($max_pages > 1) {
|
9186 |
-
$
|
9187 |
-
$
|
9188 |
'%%SUCURI.URL.Home%%',
|
9189 |
$max_per_page * $max_pages,
|
9190 |
$max_per_page
|
@@ -9193,8 +9562,9 @@ function sucuriscan_auditlogs()
|
|
9193 |
}
|
9194 |
}
|
9195 |
|
9196 |
-
return SucuriScanTemplate::
|
9197 |
}
|
|
|
9198 |
/**
|
9199 |
* Print a HTML code with the content of the logs audited by the remote Sucuri
|
9200 |
* API service, this page is part of the monitoring tool.
|
@@ -9207,10 +9577,10 @@ function sucuriscan_auditreport()
|
|
9207 |
$logs4report = SucuriScanOption::get_option(':logs4report');
|
9208 |
|
9209 |
if (SucuriScanOption::is_enabled(':audit_report')) {
|
9210 |
-
$audit_report = SucuriScanAPI::
|
9211 |
}
|
9212 |
|
9213 |
-
$
|
9214 |
'PageTitle' => 'Audit Reports',
|
9215 |
'AuditReport.EventColors' => '',
|
9216 |
'AuditReport.EventsPerType' => '',
|
@@ -9223,11 +9593,11 @@ function sucuriscan_auditreport()
|
|
9223 |
);
|
9224 |
|
9225 |
if ($audit_report) {
|
9226 |
-
$
|
9227 |
|
9228 |
// Generate report chart data for the events per type.
|
9229 |
foreach ($audit_report['events_per_type'] as $event => $times) {
|
9230 |
-
$
|
9231 |
"[ '%s', %d ],\n",
|
9232 |
ucwords($event . "\x20events"),
|
9233 |
$times
|
@@ -9236,7 +9606,7 @@ function sucuriscan_auditreport()
|
|
9236 |
|
9237 |
// Generate report chart data for the events per login.
|
9238 |
foreach ($audit_report['events_per_login'] as $event => $times) {
|
9239 |
-
$
|
9240 |
"[ '%s', %d ],\n",
|
9241 |
ucwords($event . "\x20logins"),
|
9242 |
$times
|
@@ -9245,17 +9615,17 @@ function sucuriscan_auditreport()
|
|
9245 |
|
9246 |
// Generate report chart data for the events per user.
|
9247 |
foreach ($audit_report['events_per_user'] as $event => $times) {
|
9248 |
-
$
|
9249 |
-
$
|
9250 |
}
|
9251 |
|
9252 |
// Generate report chart data for the events per remote address.
|
9253 |
foreach ($audit_report['events_per_ipaddress'] as $event => $times) {
|
9254 |
-
$
|
9255 |
-
$
|
9256 |
}
|
9257 |
|
9258 |
-
return SucuriScanTemplate::
|
9259 |
}
|
9260 |
|
9261 |
return '';
|
@@ -9270,13 +9640,13 @@ function sucuriscan_wordpress_outdated()
|
|
9270 |
{
|
9271 |
$site_version = SucuriScan::site_version();
|
9272 |
$updates = get_core_updates();
|
9273 |
-
$cp = (
|
9274 |
|
9275 |
-
$
|
9276 |
'WordPress.Version' => $site_version,
|
9277 |
'WordPress.NewVersion' => '0.0.0',
|
9278 |
'WordPress.NewLocale' => 'default',
|
9279 |
-
'WordPress.UpdateURL' => admin_url('update-core.php'),
|
9280 |
'WordPress.DownloadURL' => '#',
|
9281 |
'WordPress.UpdateVisibility' => 'hidden',
|
9282 |
);
|
@@ -9286,11 +9656,11 @@ function sucuriscan_wordpress_outdated()
|
|
9286 |
&& property_exists($updates[0], 'version')
|
9287 |
&& property_exists($updates[0], 'download')
|
9288 |
) {
|
9289 |
-
$
|
9290 |
-
$
|
9291 |
|
9292 |
if (property_exists($updates[0], 'locale')) {
|
9293 |
-
$
|
9294 |
}
|
9295 |
|
9296 |
if ($updates[0]->response == 'latest'
|
@@ -9302,10 +9672,10 @@ function sucuriscan_wordpress_outdated()
|
|
9302 |
}
|
9303 |
|
9304 |
if ($cp == 0) {
|
9305 |
-
$
|
9306 |
}
|
9307 |
|
9308 |
-
return SucuriScanTemplate::
|
9309 |
}
|
9310 |
|
9311 |
/**
|
@@ -9315,39 +9685,54 @@ function sucuriscan_wordpress_outdated()
|
|
9315 |
* send a notification to the administrator with a list of files that were added,
|
9316 |
* modified and/or deleted so far.
|
9317 |
*
|
9318 |
-
* @
|
9319 |
-
* @return string HTML code with a list of files that were affected.
|
9320 |
*/
|
9321 |
-
function sucuriscan_core_files(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
9322 |
{
|
9323 |
-
$site_version = SucuriScan::site_version();
|
9324 |
$affected_files = 0;
|
|
|
9325 |
|
9326 |
-
$
|
9327 |
'CoreFiles.List' => '',
|
9328 |
'CoreFiles.ListCount' => 0,
|
9329 |
-
'CoreFiles.
|
9330 |
'CoreFiles.BadVisibility' => 'hidden',
|
|
|
9331 |
'CoreFiles.FailureVisibility' => 'hidden',
|
9332 |
-
'CoreFiles.
|
9333 |
);
|
9334 |
|
9335 |
if ($site_version && SucuriScanOption::is_enabled(':scan_checksums')) {
|
9336 |
// Check if there are added, removed, or modified files.
|
9337 |
$latest_hashes = sucuriscan_check_core_integrity($site_version);
|
9338 |
-
$
|
9339 |
-
'
|
9340 |
. '?version=' . $site_version . '&locale=en_US';
|
9341 |
|
9342 |
if ($latest_hashes) {
|
9343 |
$cache = new SucuriScanCache('integrity');
|
9344 |
-
$ignored_files = $cache->
|
9345 |
$counter = 0;
|
9346 |
|
9347 |
foreach ($latest_hashes as $list_type => $file_list) {
|
9348 |
-
if ($list_type == 'stable'
|
9349 |
-
|| empty($file_list)
|
9350 |
-
) {
|
9351 |
continue;
|
9352 |
}
|
9353 |
|
@@ -9368,49 +9753,50 @@ function sucuriscan_core_files($send_email = false)
|
|
9368 |
// Add extra information to the file list.
|
9369 |
$css_class = ( $counter % 2 == 0 ) ? '' : 'alternate';
|
9370 |
$file_size = @filesize($full_filepath);
|
9371 |
-
$is_fixable_html = '';
|
9372 |
$is_fixable_text = '';
|
9373 |
|
9374 |
// Check whether the file can be fixed automatically or not.
|
9375 |
if ($file_info['is_fixable'] !== true) {
|
9376 |
$css_class .= ' sucuriscan-opacity';
|
9377 |
-
$
|
9378 |
-
$
|
9379 |
}
|
9380 |
|
9381 |
// Generate the HTML code from the snippet template for this file.
|
9382 |
-
$
|
9383 |
-
'
|
9384 |
-
|
9385 |
-
|
9386 |
-
|
9387 |
-
|
9388 |
-
|
9389 |
-
|
9390 |
-
|
9391 |
-
|
9392 |
-
|
|
|
|
|
9393 |
$counter += 1;
|
9394 |
$affected_files += 1;
|
9395 |
}
|
9396 |
}
|
9397 |
|
9398 |
if ($counter > 0) {
|
9399 |
-
$
|
9400 |
-
$
|
9401 |
-
$
|
9402 |
}
|
9403 |
} else {
|
9404 |
-
$
|
9405 |
-
$
|
9406 |
-
$
|
9407 |
}
|
9408 |
}
|
9409 |
|
9410 |
// Send an email notification with the affected files.
|
9411 |
if ($send_email === true) {
|
9412 |
if ($affected_files > 0) {
|
9413 |
-
$content = SucuriScanTemplate::
|
9414 |
$sent = SucuriScanEvent::notify_event('scan_checksums', $content);
|
9415 |
|
9416 |
return $sent;
|
@@ -9419,7 +9805,158 @@ function sucuriscan_core_files($send_email = false)
|
|
9419 |
return false;
|
9420 |
}
|
9421 |
|
9422 |
-
return SucuriScanTemplate::
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
9423 |
}
|
9424 |
|
9425 |
/**
|
@@ -9428,7 +9965,7 @@ function sucuriscan_core_files($send_email = false)
|
|
9428 |
* these keys:
|
9429 |
*
|
9430 |
* <ul>
|
9431 |
-
* <li>modified: Files with a different checksum according to the official
|
9432 |
* <li>stable: Files with the same checksums than the official files,</li>
|
9433 |
* <li>removed: Official files which are not present in the local project,</li>
|
9434 |
* <li>added: Files present in the local project but not in the official WordPress packages.</li>
|
@@ -9439,12 +9976,12 @@ function sucuriscan_core_files($send_email = false)
|
|
9439 |
*/
|
9440 |
function sucuriscan_check_core_integrity($version = 0)
|
9441 |
{
|
9442 |
-
$latest_hashes = SucuriScanAPI::
|
9443 |
$base_content_dir = defined('WP_CONTENT_DIR')
|
9444 |
? basename(rtrim(WP_CONTENT_DIR, '/'))
|
9445 |
: '';
|
9446 |
|
9447 |
-
if (
|
9448 |
return false;
|
9449 |
}
|
9450 |
|
@@ -9470,7 +10007,7 @@ function sucuriscan_check_core_integrity($version = 0)
|
|
9470 |
$full_filepath = sprintf('%s/%s', ABSPATH, $file_path);
|
9471 |
|
9472 |
// Patch for custom content directory path.
|
9473 |
-
if (!
|
9474 |
&& strpos($file_path, 'wp-content') !== false
|
9475 |
&& defined('WP_CONTENT_DIR')
|
9476 |
) {
|
@@ -9513,13 +10050,13 @@ function sucuriscan_check_core_integrity($version = 0)
|
|
9513 |
// Search added files (files not common in a normal wordpress installation).
|
9514 |
foreach ($wp_core_hashes as $file_path => $extra_info) {
|
9515 |
$file_path = str_replace(DIRECTORY_SEPARATOR, '/', $file_path);
|
9516 |
-
$file_path = preg_replace('/^\.\/(.*)/', '$1', $file_path);
|
9517 |
|
9518 |
if (sucuriscan_ignore_integrity_filepath($file_path)) {
|
9519 |
continue;
|
9520 |
}
|
9521 |
|
9522 |
-
if (!
|
9523 |
$full_filepath = ABSPATH . '/' . $file_path;
|
9524 |
$modified_at = @filemtime($full_filepath);
|
9525 |
$is_fixable = (bool) is_writable($full_filepath);
|
@@ -9546,7 +10083,8 @@ function sucuriscan_ignore_integrity_filepath($file_path = '')
|
|
9546 |
|
9547 |
// List of files that will be ignored from the integrity checking.
|
9548 |
$ignore_files = array(
|
9549 |
-
'^sucuri-[0-9a-z]+\.php$',
|
|
|
9550 |
'^favicon\.ico$',
|
9551 |
'^php\.ini$',
|
9552 |
'^\.htaccess$',
|
@@ -9581,7 +10119,7 @@ function sucuriscan_ignore_integrity_filepath($file_path = '')
|
|
9581 |
|
9582 |
// Determine whether a file must be ignored from the integrity checks or not.
|
9583 |
foreach ($ignore_files as $ignore_pattern) {
|
9584 |
-
if (preg_match('/'.$ignore_pattern.'/', $file_path)) {
|
9585 |
return true;
|
9586 |
}
|
9587 |
}
|
@@ -9589,109 +10127,26 @@ function sucuriscan_ignore_integrity_filepath($file_path = '')
|
|
9589 |
return false;
|
9590 |
}
|
9591 |
|
9592 |
-
/**
|
9593 |
-
* List all files inside wp-content that have been modified in the last days.
|
9594 |
-
*
|
9595 |
-
* @return void
|
9596 |
-
*/
|
9597 |
-
function sucuriscan_modified_files()
|
9598 |
-
{
|
9599 |
-
$valid_day_ranges = array( 1, 3, 7, 30, 60 );
|
9600 |
-
$template_variables = array(
|
9601 |
-
'ModifiedFiles.List' => '',
|
9602 |
-
'ModifiedFiles.SelectOptions' => '',
|
9603 |
-
'ModifiedFiles.NoFilesVisibility' => 'visible',
|
9604 |
-
'ModifiedFiles.DisabledVisibility' => 'hidden',
|
9605 |
-
'ModifiedFiles.Days' => 0,
|
9606 |
-
);
|
9607 |
-
|
9608 |
-
// Find files modified in the last days.
|
9609 |
-
$back_days = SucuriScanRequest::post(':last_days', '[0-9]+');
|
9610 |
-
|
9611 |
-
if ($back_days !== false) {
|
9612 |
-
if ($back_days <= 0) {
|
9613 |
-
$back_days = 1;
|
9614 |
-
} elseif ($back_days >= 60) {
|
9615 |
-
$back_days = 60;
|
9616 |
-
}
|
9617 |
-
} else {
|
9618 |
-
$back_days = 7;
|
9619 |
-
}
|
9620 |
-
|
9621 |
-
// Fix data type for the back days variable.
|
9622 |
-
$back_days = intval($back_days);
|
9623 |
-
$template_variables['ModifiedFiles.Days'] = $back_days;
|
9624 |
-
|
9625 |
-
// Generate the options for the select field of the page form.
|
9626 |
-
foreach ($valid_day_ranges as $day) {
|
9627 |
-
$selected_option = ($back_days == $day) ? 'selected="selected"' : '';
|
9628 |
-
$template_variables['ModifiedFiles.SelectOptions'] .= sprintf(
|
9629 |
-
'<option value="%d" %s>%d</option>',
|
9630 |
-
$day,
|
9631 |
-
$selected_option,
|
9632 |
-
$day
|
9633 |
-
);
|
9634 |
-
}
|
9635 |
-
|
9636 |
-
// The scanner for modified files can be disabled from the settings page.
|
9637 |
-
if (SucuriScanOption::is_enabled(':scan_modfiles')) {
|
9638 |
-
// Search modified files among the project's files.
|
9639 |
-
$content_hashes = sucuriscan_get_integrity_tree(WP_CONTENT_DIR, true);
|
9640 |
-
|
9641 |
-
if (! empty($content_hashes)) {
|
9642 |
-
$back_days = current_time('timestamp') - ( $back_days * 86400);
|
9643 |
-
$counter = 0;
|
9644 |
-
|
9645 |
-
foreach ($content_hashes as $file_path => $file_info) {
|
9646 |
-
if (isset($file_info['modified_at'])
|
9647 |
-
&& $file_info['modified_at'] >= $back_days
|
9648 |
-
) {
|
9649 |
-
$css_class = ( $counter % 2 == 0 ) ? '' : 'alternate';
|
9650 |
-
$mod_date = SucuriScan::datetime($file_info['modified_at']);
|
9651 |
-
|
9652 |
-
$template_variables['ModifiedFiles.List'] .= SucuriScanTemplate::get_snippet('integrity-modifiedfiles', array(
|
9653 |
-
'ModifiedFiles.CssClass' => $css_class,
|
9654 |
-
'ModifiedFiles.CheckSum' => $file_info['checksum'],
|
9655 |
-
'ModifiedFiles.FilePath' => SucuriScan::escape($file_path),
|
9656 |
-
'ModifiedFiles.DateTime' => $mod_date,
|
9657 |
-
'ModifiedFiles.FileSize' => $file_info['filesize'],
|
9658 |
-
'ModifiedFiles.FileSizeHuman' => SucuriScan::human_filesize($file_info['filesize']),
|
9659 |
-
'ModifiedFiles.FileSizeNumber' => number_format($file_info['filesize']),
|
9660 |
-
));
|
9661 |
-
$counter += 1;
|
9662 |
-
}
|
9663 |
-
}
|
9664 |
-
|
9665 |
-
if ($counter > 0) {
|
9666 |
-
$template_variables['ModifiedFiles.NoFilesVisibility'] = 'hidden';
|
9667 |
-
}
|
9668 |
-
}
|
9669 |
-
} else {
|
9670 |
-
$template_variables['ModifiedFiles.DisabledVisibility'] = 'visible';
|
9671 |
-
}
|
9672 |
-
|
9673 |
-
return SucuriScanTemplate::get_section('integrity-modifiedfiles', $template_variables);
|
9674 |
-
}
|
9675 |
-
|
9676 |
/**
|
9677 |
* Generate and print the HTML code for the Post-Hack page.
|
9678 |
*
|
9679 |
* @return void
|
9680 |
*/
|
9681 |
-
function sucuriscan_posthack_page()
|
|
|
9682 |
SucuriScanInterface::check_permissions();
|
9683 |
|
9684 |
$process_form = sucuriscan_posthack_process_form();
|
9685 |
|
9686 |
// Page pseudo-variables initialization.
|
9687 |
-
$
|
9688 |
'PageTitle' => 'Post-Hack',
|
9689 |
-
'UpdateSecretKeys' => sucuriscan_update_secret_keys(
|
9690 |
-
'ResetPassword' => sucuriscan_posthack_users(
|
9691 |
-
'ResetPlugins' => sucuriscan_posthack_plugins(
|
9692 |
);
|
9693 |
|
9694 |
-
echo SucuriScanTemplate::
|
9695 |
}
|
9696 |
|
9697 |
/**
|
@@ -9699,10 +10154,11 @@ function sucuriscan_posthack_page(){
|
|
9699 |
*
|
9700 |
* @return mixed.
|
9701 |
*/
|
9702 |
-
function sucuriscan_posthack_ajax()
|
|
|
9703 |
SucuriScanInterface::check_permissions();
|
9704 |
|
9705 |
-
if (
|
9706 |
sucuriscan_posthack_plugins_ajax();
|
9707 |
}
|
9708 |
|
@@ -9714,17 +10170,17 @@ function sucuriscan_posthack_ajax(){
|
|
9714 |
*
|
9715 |
* @return boolean TRUE if a form submission should be processed, FALSE otherwise.
|
9716 |
*/
|
9717 |
-
function sucuriscan_posthack_process_form()
|
9718 |
-
|
|
|
9719 |
|
9720 |
-
if (
|
9721 |
-
SucuriScanInterface::check_nonce()
|
9722 |
&& $process_form !== false
|
9723 |
) {
|
9724 |
-
if (
|
9725 |
return true;
|
9726 |
} else {
|
9727 |
-
SucuriScanInterface::error(
|
9728 |
}
|
9729 |
}
|
9730 |
|
@@ -9737,37 +10193,38 @@ function sucuriscan_posthack_process_form(){
|
|
9737 |
* @param $process_form Whether a form was submitted or not.
|
9738 |
* @return string HTML code with the information of the process.
|
9739 |
*/
|
9740 |
-
function sucuriscan_update_secret_keys(
|
9741 |
-
|
|
|
9742 |
'WPConfigUpdate.Visibility' => 'hidden',
|
9743 |
'WPConfigUpdate.NewConfig' => '',
|
9744 |
'SecurityKeys.List' => '',
|
9745 |
);
|
9746 |
|
9747 |
// Update all WordPress secret keys.
|
9748 |
-
if (
|
9749 |
$wpconfig_process = SucuriScanEvent::set_new_config_keys();
|
9750 |
|
9751 |
-
if (
|
9752 |
-
$
|
9753 |
-
SucuriScanEvent::report_notice_event(
|
9754 |
-
|
9755 |
-
if (
|
9756 |
-
SucuriScanInterface::info(
|
9757 |
-
$
|
9758 |
-
$
|
9759 |
-
$
|
9760 |
-
$
|
9761 |
-
$
|
9762 |
} else {
|
9763 |
SucuriScanInterface::error(
|
9764 |
'<code>wp-config.php</code> file is not writable, replace the '
|
9765 |
. 'old configuration file with the new values shown bellow.'
|
9766 |
);
|
9767 |
-
$
|
9768 |
}
|
9769 |
} else {
|
9770 |
-
SucuriScanInterface::error(
|
9771 |
}
|
9772 |
}
|
9773 |
|
@@ -9775,12 +10232,12 @@ function sucuriscan_update_secret_keys( $process_form = false ){
|
|
9775 |
$current_keys = SucuriScanOption::get_security_keys();
|
9776 |
$counter = 0;
|
9777 |
|
9778 |
-
foreach (
|
9779 |
-
foreach (
|
9780 |
$css_class = ( $counter % 2 == 0 ) ? '' : 'alternate';
|
9781 |
-
$key_value = SucuriScan::excerpt(
|
9782 |
|
9783 |
-
switch (
|
9784 |
case 'good':
|
9785 |
$key_status_text = 'good';
|
9786 |
$key_status_css_class = 'success';
|
@@ -9796,20 +10253,23 @@ function sucuriscan_update_secret_keys( $process_form = false ){
|
|
9796 |
break;
|
9797 |
}
|
9798 |
|
9799 |
-
if (
|
9800 |
-
$
|
9801 |
-
'
|
9802 |
-
|
9803 |
-
|
9804 |
-
|
9805 |
-
|
9806 |
-
|
9807 |
-
|
|
|
|
|
|
|
9808 |
}
|
9809 |
}
|
9810 |
}
|
9811 |
|
9812 |
-
return SucuriScanTemplate::
|
9813 |
}
|
9814 |
|
9815 |
/**
|
@@ -9819,70 +10279,73 @@ function sucuriscan_update_secret_keys( $process_form = false ){
|
|
9819 |
* @param $process_form Whether a form was submitted or not.
|
9820 |
* @return string HTML code for a table where a list of user accounts will be shown.
|
9821 |
*/
|
9822 |
-
function sucuriscan_posthack_users(
|
9823 |
-
|
|
|
9824 |
'ResetPassword.UserList' => '',
|
9825 |
'ResetPassword.PaginationLinks' => '',
|
9826 |
'ResetPassword.PaginationVisibility' => 'hidden',
|
9827 |
);
|
9828 |
|
9829 |
// Process the form submission (if any).
|
9830 |
-
sucuriscan_reset_user_password(
|
9831 |
|
9832 |
// Fill the user list for ResetPassword action.
|
9833 |
$user_list = false;
|
9834 |
-
$page_number = SucuriScanTemplate::
|
9835 |
$max_per_page = SUCURISCAN_MAX_PAGINATION_BUTTONS;
|
9836 |
-
$dbquery = new WP_User_Query(
|
9837 |
'number' => $max_per_page,
|
9838 |
-
'offset' => (
|
9839 |
'fields' => 'all_with_meta',
|
9840 |
'orderby' => 'ID',
|
9841 |
-
)
|
9842 |
|
9843 |
// Retrieve the results and build the pagination links.
|
9844 |
-
if (
|
9845 |
$total_items = $dbquery->get_total();
|
9846 |
$user_list = $dbquery->get_results();
|
9847 |
|
9848 |
-
$
|
9849 |
'%%SUCURI.URL.Posthack%%#reset-users-password',
|
9850 |
$total_items,
|
9851 |
$max_per_page
|
9852 |
);
|
9853 |
|
9854 |
-
if (
|
9855 |
-
$
|
9856 |
}
|
9857 |
}
|
9858 |
|
9859 |
-
if (
|
9860 |
$counter = 0;
|
9861 |
|
9862 |
-
foreach (
|
9863 |
-
$user->user_registered_timestamp = strtotime(
|
9864 |
-
$user->user_registered_formatted = SucuriScan::datetime(
|
9865 |
$css_class = ( $counter % 2 == 0 ) ? '' : 'alternate';
|
9866 |
$display_username = ( $user->user_login != $user->display_name )
|
9867 |
-
? sprintf(
|
9868 |
: $user->user_login;
|
9869 |
|
9870 |
-
$
|
9871 |
-
'
|
9872 |
-
|
9873 |
-
|
9874 |
-
|
9875 |
-
|
9876 |
-
|
9877 |
-
|
9878 |
-
|
9879 |
-
|
9880 |
-
|
9881 |
-
|
|
|
|
|
9882 |
}
|
9883 |
}
|
9884 |
|
9885 |
-
return SucuriScanTemplate::
|
9886 |
}
|
9887 |
|
9888 |
/**
|
@@ -9891,37 +10354,38 @@ function sucuriscan_posthack_users( $process_form = false ){
|
|
9891 |
* @param $process_form Whether a form was submitted or not.
|
9892 |
* @return void
|
9893 |
*/
|
9894 |
-
function sucuriscan_reset_user_password(
|
9895 |
-
|
9896 |
-
|
|
|
9897 |
$pwd_changed = array();
|
9898 |
$pwd_not_changed = array();
|
9899 |
|
9900 |
-
if (
|
9901 |
-
arsort(
|
9902 |
|
9903 |
-
foreach (
|
9904 |
-
$user_id = intval(
|
9905 |
|
9906 |
-
if (
|
9907 |
$pwd_changed[] = $user_id;
|
9908 |
} else {
|
9909 |
$pwd_not_changed[] = $user_id;
|
9910 |
}
|
9911 |
}
|
9912 |
|
9913 |
-
if (
|
9914 |
-
$message = 'Password changed for user identifiers <code>' . @implode(
|
9915 |
|
9916 |
-
SucuriScanEvent::report_notice_event(
|
9917 |
-
SucuriScanInterface::info(
|
9918 |
}
|
9919 |
|
9920 |
-
if (
|
9921 |
-
SucuriScanInterface::error(
|
9922 |
}
|
9923 |
} else {
|
9924 |
-
SucuriScanInterface::error(
|
9925 |
}
|
9926 |
}
|
9927 |
}
|
@@ -9932,19 +10396,20 @@ function sucuriscan_reset_user_password( $process_form = false ){
|
|
9932 |
* @param boolean $process_form Whether a form was submitted or not.
|
9933 |
* @return void
|
9934 |
*/
|
9935 |
-
function sucuriscan_posthack_plugins(
|
9936 |
-
|
|
|
9937 |
'ResetPlugin.PluginList' => '',
|
9938 |
'ResetPlugin.CacheLifeTime' => 'unknown',
|
9939 |
);
|
9940 |
|
9941 |
-
if (
|
9942 |
-
$
|
9943 |
}
|
9944 |
|
9945 |
-
sucuriscan_posthack_reinstall_plugins(
|
9946 |
|
9947 |
-
return SucuriScanTemplate::
|
9948 |
}
|
9949 |
|
9950 |
/**
|
@@ -9952,32 +10417,35 @@ function sucuriscan_posthack_plugins( $process_form = false ){
|
|
9952 |
*
|
9953 |
* @return string HTML code for a table with the plugins metadata.
|
9954 |
*/
|
9955 |
-
function sucuriscan_posthack_plugins_ajax()
|
9956 |
-
|
9957 |
-
|
|
|
9958 |
$response = '';
|
9959 |
$counter = 0;
|
9960 |
|
9961 |
-
foreach (
|
9962 |
$css_class = ( $counter % 2 == 0 ) ? '' : 'alternate';
|
9963 |
$plugin_type_class = ( $plugin_data['PluginType'] == 'free' ) ? 'primary' : 'warning';
|
9964 |
$input_disabled = ( $plugin_data['PluginType'] == 'free' ) ? '' : 'disabled="disabled"';
|
9965 |
$plugin_status = $plugin_data['IsPluginActive'] ? 'active' : 'not active';
|
9966 |
$plugin_status_class = $plugin_data['IsPluginActive'] ? 'success' : 'default';
|
9967 |
|
9968 |
-
$response .= SucuriScanTemplate::
|
9969 |
-
'
|
9970 |
-
|
9971 |
-
|
9972 |
-
|
9973 |
-
|
9974 |
-
|
9975 |
-
|
9976 |
-
|
9977 |
-
|
9978 |
-
|
9979 |
-
|
9980 |
-
|
|
|
|
|
9981 |
}
|
9982 |
|
9983 |
print( $response );
|
@@ -9994,12 +10462,13 @@ function sucuriscan_posthack_plugins_ajax(){
|
|
9994 |
* @param boolean $process_form Whether a form was submitted or not.
|
9995 |
* @return void
|
9996 |
*/
|
9997 |
-
function sucuriscan_posthack_reinstall_plugins(
|
9998 |
-
|
9999 |
-
|
10000 |
-
include_once(
|
|
|
10001 |
|
10002 |
-
if (
|
10003 |
// Create an instance of the FileInfo interface.
|
10004 |
$file_info = new SucuriScanFileInfo();
|
10005 |
$file_info->ignore_files = false;
|
@@ -10007,37 +10476,37 @@ function sucuriscan_posthack_reinstall_plugins( $process_form = false ){
|
|
10007 |
$file_info->skip_directories = false;
|
10008 |
|
10009 |
// Get (possible) cached information from the installed plugins.
|
10010 |
-
$all_plugins = SucuriScanAPI::
|
10011 |
|
10012 |
// Loop through all the installed plugins.
|
10013 |
-
foreach (
|
10014 |
-
if (
|
10015 |
$plugin_data = $all_plugins[ $plugin_path ];
|
10016 |
|
10017 |
// Check if the plugin can be downloaded from the free market.
|
10018 |
-
if (
|
10019 |
-
$plugin_info = SucuriScanAPI::
|
10020 |
|
10021 |
-
if (
|
10022 |
// First, remove all files/sub-folders from the plugin's directory.
|
10023 |
-
if (
|
10024 |
-
$plugin_directory = dirname(
|
10025 |
-
$file_info->remove_directory_tree(
|
10026 |
}
|
10027 |
|
10028 |
// Install a fresh copy of the plugin's files.
|
10029 |
$upgrader_skin = new Plugin_Installer_Skin();
|
10030 |
-
$upgrader = new Plugin_Upgrader(
|
10031 |
-
$upgrader->install(
|
10032 |
-
SucuriScanEvent::report_notice_event(
|
10033 |
} else {
|
10034 |
-
SucuriScanInterface::error(
|
10035 |
}
|
10036 |
}
|
10037 |
}
|
10038 |
}
|
10039 |
} else {
|
10040 |
-
SucuriScanInterface::error(
|
10041 |
}
|
10042 |
}
|
10043 |
}
|
@@ -10049,26 +10518,26 @@ function sucuriscan_posthack_reinstall_plugins( $process_form = false ){
|
|
10049 |
*
|
10050 |
* @return string Last-logings for the administrator accounts.
|
10051 |
*/
|
10052 |
-
function sucuriscan_lastlogins_page()
|
|
|
10053 |
SucuriScanInterface::check_permissions();
|
10054 |
|
10055 |
// Reset the file with the last-logins logs.
|
10056 |
-
if (
|
10057 |
-
|
10058 |
-
&& SucuriScanRequest::post( ':reset_lastlogins' ) !== false
|
10059 |
) {
|
10060 |
$file_path = sucuriscan_lastlogins_datastore_filepath();
|
10061 |
|
10062 |
-
if (
|
10063 |
sucuriscan_lastlogins_datastore_exists();
|
10064 |
-
SucuriScanInterface::info(
|
10065 |
} else {
|
10066 |
-
SucuriScanInterface::error(
|
10067 |
}
|
10068 |
}
|
10069 |
|
10070 |
// Page pseudo-variables initialization.
|
10071 |
-
$
|
10072 |
'PageTitle' => 'Last Logins',
|
10073 |
'LastLogins.Admins' => sucuriscan_lastlogins_admins(),
|
10074 |
'LastLogins.AllUsers' => sucuriscan_lastlogins_all(),
|
@@ -10076,64 +10545,70 @@ function sucuriscan_lastlogins_page(){
|
|
10076 |
'FailedLogins' => sucuriscan_failed_logins_panel(),
|
10077 |
);
|
10078 |
|
10079 |
-
echo SucuriScanTemplate::
|
10080 |
}
|
10081 |
|
10082 |
/**
|
10083 |
* List all the user administrator accounts.
|
10084 |
*
|
10085 |
-
* @see
|
10086 |
*
|
10087 |
* @return void
|
10088 |
*/
|
10089 |
-
function sucuriscan_lastlogins_admins()
|
|
|
10090 |
// Page pseudo-variables initialization.
|
10091 |
-
$
|
10092 |
'AdminUsers.List' => '',
|
10093 |
);
|
10094 |
|
10095 |
-
$user_query = new WP_User_Query(
|
10096 |
$admins = $user_query->get_results();
|
10097 |
|
10098 |
-
foreach (
|
10099 |
-
$last_logins = sucuriscan_get_logins(
|
10100 |
$admin->lastlogins = $last_logins['entries'];
|
10101 |
|
10102 |
$user_snippet = array(
|
10103 |
-
'AdminUsers.Username' =>
|
10104 |
-
'AdminUsers.Email' =>
|
10105 |
'AdminUsers.LastLogins' => '',
|
10106 |
-
'AdminUsers.RegisteredAt' => '
|
10107 |
-
'AdminUsers.UserURL' => admin_url(
|
10108 |
'AdminUsers.NoLastLogins' => 'visible',
|
10109 |
'AdminUsers.NoLastLoginsTable' => 'hidden',
|
10110 |
);
|
10111 |
|
10112 |
-
if (
|
10113 |
$user_snippet['AdminUsers.NoLastLogins'] = 'hidden';
|
10114 |
$user_snippet['AdminUsers.NoLastLoginsTable'] = 'visible';
|
10115 |
$user_snippet['AdminUsers.RegisteredAt'] = 'Unknown';
|
10116 |
$counter = 0;
|
10117 |
|
10118 |
-
foreach (
|
10119 |
-
if (
|
10120 |
-
$user_snippet['AdminUsers.RegisteredAt'] = SucuriScan::datetime(
|
|
|
|
|
10121 |
}
|
10122 |
|
10123 |
-
$css_class = (
|
10124 |
-
$user_snippet['AdminUsers.LastLogins'] .= SucuriScanTemplate::
|
10125 |
-
'
|
10126 |
-
|
10127 |
-
|
10128 |
-
|
10129 |
-
|
|
|
|
|
|
|
10130 |
}
|
10131 |
}
|
10132 |
|
10133 |
-
$
|
10134 |
}
|
10135 |
|
10136 |
-
return SucuriScanTemplate::
|
10137 |
}
|
10138 |
|
10139 |
/**
|
@@ -10143,12 +10618,13 @@ function sucuriscan_lastlogins_admins(){
|
|
10143 |
*
|
10144 |
* @return string Last-logings for all user accounts.
|
10145 |
*/
|
10146 |
-
function sucuriscan_lastlogins_all()
|
|
|
10147 |
$max_per_page = SUCURISCAN_LASTLOGINS_USERSLIMIT;
|
10148 |
-
$page_number = SucuriScanTemplate::
|
10149 |
$offset = ($max_per_page * $page_number) - $max_per_page;
|
10150 |
|
10151 |
-
$
|
10152 |
'UserList' => '',
|
10153 |
'UserList.Limit' => $max_per_page,
|
10154 |
'UserList.Total' => 0,
|
@@ -10157,59 +10633,60 @@ function sucuriscan_lastlogins_all(){
|
|
10157 |
'UserList.NoItemsVisibility' => 'visible',
|
10158 |
);
|
10159 |
|
10160 |
-
if (
|
10161 |
-
|
|
|
10162 |
}
|
10163 |
|
10164 |
$counter = 0;
|
10165 |
-
$last_logins = sucuriscan_get_logins(
|
10166 |
-
$
|
10167 |
|
10168 |
-
if (
|
10169 |
-
$
|
10170 |
}
|
10171 |
|
10172 |
-
if (
|
10173 |
-
$
|
10174 |
}
|
10175 |
|
10176 |
-
foreach (
|
10177 |
-
$counter
|
10178 |
-
$css_class = ( $counter % 2 == 0 ) ? 'alternate' : '';
|
10179 |
|
10180 |
$user_dataset = array(
|
10181 |
'UserList.Number' => $user->line_num,
|
10182 |
'UserList.UserId' => $user->user_id,
|
10183 |
-
'UserList.Username' => '
|
10184 |
'UserList.Displayname' => '',
|
10185 |
'UserList.Email' => '',
|
10186 |
'UserList.Registered' => '',
|
10187 |
-
'UserList.RemoteAddr' =>
|
10188 |
-
'UserList.Hostname' =>
|
10189 |
-
'UserList.Datetime' =>
|
10190 |
-
'UserList.TimeAgo' => SucuriScan::time_ago(
|
10191 |
-
'UserList.UserURL' => admin_url(
|
10192 |
'UserList.CssClass' => $css_class,
|
10193 |
);
|
10194 |
|
10195 |
-
if (
|
10196 |
-
$user_dataset['UserList.Username'] =
|
10197 |
-
$user_dataset['UserList.Displayname'] =
|
10198 |
-
$user_dataset['UserList.Email'] =
|
10199 |
-
$user_dataset['UserList.Registered'] =
|
10200 |
}
|
10201 |
|
10202 |
-
$
|
|
|
10203 |
}
|
10204 |
|
10205 |
// Generate the pagination for the list.
|
10206 |
-
$
|
10207 |
'%%SUCURI.URL.Lastlogins%%',
|
10208 |
$last_logins['total'],
|
10209 |
$max_per_page
|
10210 |
);
|
10211 |
|
10212 |
-
return SucuriScanTemplate::
|
10213 |
}
|
10214 |
|
10215 |
/**
|
@@ -10217,8 +10694,9 @@ function sucuriscan_lastlogins_all(){
|
|
10217 |
*
|
10218 |
* @return string Absolute filepath where the user's last login information is stored.
|
10219 |
*/
|
10220 |
-
function sucuriscan_lastlogins_datastore_filepath()
|
10221 |
-
|
|
|
10222 |
}
|
10223 |
|
10224 |
/**
|
@@ -10227,7 +10705,8 @@ function sucuriscan_lastlogins_datastore_filepath(){
|
|
10227 |
*
|
10228 |
* @return string Absolute filepath where the user's last login information is stored.
|
10229 |
*/
|
10230 |
-
function sucuriscan_lastlogins_datastore_exists()
|
|
|
10231 |
$fpath = sucuriscan_lastlogins_datastore_filepath();
|
10232 |
|
10233 |
if (!file_exists($fpath)) {
|
@@ -10247,15 +10726,16 @@ function sucuriscan_lastlogins_datastore_exists(){
|
|
10247 |
*
|
10248 |
* @return boolean Whether the user's last login datastore file is writable or not.
|
10249 |
*/
|
10250 |
-
function sucuriscan_lastlogins_datastore_is_writable()
|
|
|
10251 |
$datastore_filepath = sucuriscan_lastlogins_datastore_exists();
|
10252 |
|
10253 |
-
if (
|
10254 |
-
if (
|
10255 |
-
@chmod(
|
10256 |
}
|
10257 |
|
10258 |
-
if (
|
10259 |
return $datastore_filepath;
|
10260 |
}
|
10261 |
}
|
@@ -10269,42 +10749,44 @@ function sucuriscan_lastlogins_datastore_is_writable(){
|
|
10269 |
*
|
10270 |
* @return boolean Whether the user's last login datastore file is readable or not.
|
10271 |
*/
|
10272 |
-
function sucuriscan_lastlogins_datastore_is_readable()
|
|
|
10273 |
$datastore_filepath = sucuriscan_lastlogins_datastore_exists();
|
10274 |
|
10275 |
-
if (
|
10276 |
return $datastore_filepath;
|
10277 |
}
|
10278 |
|
10279 |
return false;
|
10280 |
}
|
10281 |
|
10282 |
-
if (
|
10283 |
/**
|
10284 |
* Add a new user session to the list of last user logins.
|
10285 |
*
|
10286 |
* @param string $user_login The name of the user account involved in the operation.
|
10287 |
* @return void
|
10288 |
*/
|
10289 |
-
function sucuriscan_set_lastlogin(
|
|
|
10290 |
$datastore_filepath = sucuriscan_lastlogins_datastore_is_writable();
|
10291 |
|
10292 |
-
if (
|
10293 |
-
$current_user = get_user_by(
|
10294 |
$remote_addr = SucuriScan::get_remote_addr();
|
10295 |
|
10296 |
$login_info = array(
|
10297 |
'user_id' => $current_user->ID,
|
10298 |
'user_login' => $current_user->user_login,
|
10299 |
'user_remoteaddr' => $remote_addr,
|
10300 |
-
'user_hostname' => @gethostbyaddr(
|
10301 |
-
'user_lastlogin' => current_time(
|
10302 |
);
|
10303 |
|
10304 |
-
@file_put_contents(
|
10305 |
}
|
10306 |
}
|
10307 |
-
add_action(
|
10308 |
}
|
10309 |
|
10310 |
/**
|
@@ -10318,18 +10800,19 @@ if ( ! function_exists( 'sucuri_set_lastlogin' ) ) {
|
|
10318 |
* @param integer $user_id Optional user identifier to filter the results.
|
10319 |
* @return array The list of all the user logins, and total of entries registered.
|
10320 |
*/
|
10321 |
-
function sucuriscan_get_logins(
|
|
|
10322 |
$datastore_filepath = sucuriscan_lastlogins_datastore_is_readable();
|
10323 |
$last_logins = array(
|
10324 |
'total' => 0,
|
10325 |
'entries' => array(),
|
10326 |
);
|
10327 |
|
10328 |
-
if (
|
10329 |
$parsed_lines = 0;
|
10330 |
-
$data_lines = SucuriScanFileInfo::file_lines(
|
10331 |
|
10332 |
-
if (
|
10333 |
/**
|
10334 |
* This count will not be 100% accurate considering that we are checking the
|
10335 |
* syntax of each line in the loop bellow, there may be some lines without the
|
@@ -10338,11 +10821,11 @@ function sucuriscan_get_logins( $limit = 10, $offset = 0, $user_id = 0 ){
|
|
10338 |
*
|
10339 |
* @var integer
|
10340 |
*/
|
10341 |
-
$total_lines = count(
|
10342 |
$last_logins['total'] = $total_lines;
|
10343 |
|
10344 |
// Get a list with the latest entries in the first positions.
|
10345 |
-
$reversed_lines = array_reverse(
|
10346 |
|
10347 |
/**
|
10348 |
* Only the user accounts with administrative privileges can see the logs of all
|
@@ -10351,44 +10834,44 @@ function sucuriscan_get_logins( $limit = 10, $offset = 0, $user_id = 0 ){
|
|
10351 |
* @var object
|
10352 |
*/
|
10353 |
$current_user = wp_get_current_user();
|
10354 |
-
$is_admin_user = (bool) current_user_can(
|
10355 |
|
10356 |
-
for (
|
10357 |
-
$line = $reversed_lines[
|
10358 |
|
10359 |
// Check if the data is serialized (which we will consider as insecure).
|
10360 |
-
if (
|
10361 |
-
$last_login =
|
10362 |
} else {
|
10363 |
-
$last_login = @json_decode(
|
10364 |
}
|
10365 |
|
10366 |
-
if (
|
10367 |
-
$last_login['user_lastlogin_timestamp'] = strtotime(
|
10368 |
$last_login['user_registered_timestamp'] = 0;
|
10369 |
|
10370 |
// Only administrators can see all login stats.
|
10371 |
-
if (
|
10372 |
continue;
|
10373 |
}
|
10374 |
|
10375 |
// Filter the user identifiers using the value passed tot his function.
|
10376 |
-
if (
|
10377 |
continue;
|
10378 |
}
|
10379 |
|
10380 |
// Get the WP_User object and add extra information from the last-login data.
|
10381 |
$last_login['user_exists'] = false;
|
10382 |
-
$user_account = get_userdata(
|
10383 |
|
10384 |
-
if (
|
10385 |
$last_login['user_exists'] = true;
|
10386 |
|
10387 |
-
foreach (
|
10388 |
$last_login[ $var_name ] = $var_value;
|
10389 |
|
10390 |
-
if (
|
10391 |
-
$last_login['user_registered_timestamp'] = strtotime(
|
10392 |
}
|
10393 |
}
|
10394 |
}
|
@@ -10400,8 +10883,8 @@ function sucuriscan_get_logins( $limit = 10, $offset = 0, $user_id = 0 ){
|
|
10400 |
$last_logins['total'] -= 1;
|
10401 |
}
|
10402 |
|
10403 |
-
if (
|
10404 |
-
if (
|
10405 |
break;
|
10406 |
}
|
10407 |
}
|
@@ -10412,7 +10895,7 @@ function sucuriscan_get_logins( $limit = 10, $offset = 0, $user_id = 0 ){
|
|
10412 |
return $last_logins;
|
10413 |
}
|
10414 |
|
10415 |
-
if (
|
10416 |
/**
|
10417 |
* Hook for the wp-login action to redirect the user to a specific URL after
|
10418 |
* his successfully login to the administrator interface.
|
@@ -10422,57 +10905,57 @@ if ( ! function_exists( 'sucuri_login_redirect' ) ) {
|
|
10422 |
* @param boolean $user WordPress user object with the information of the account involved in the operation.
|
10423 |
* @return string URL where the browser must be redirected to.
|
10424 |
*/
|
10425 |
-
function sucuriscan_login_redirect(
|
10426 |
-
|
|
|
10427 |
|
10428 |
-
if (
|
10429 |
-
$user
|
10430 |
-
&&
|
10431 |
-
&& SucuriScanOption::is_enabled( ':lastlogin_redirection' )
|
10432 |
) {
|
10433 |
-
$login_url = add_query_arg(
|
10434 |
}
|
10435 |
|
10436 |
return $login_url;
|
10437 |
}
|
10438 |
|
10439 |
-
if (
|
10440 |
-
add_filter(
|
10441 |
}
|
10442 |
}
|
10443 |
|
10444 |
-
if (
|
10445 |
/**
|
10446 |
* Display the last user login at the top of the admin interface.
|
10447 |
*
|
10448 |
* @return void
|
10449 |
*/
|
10450 |
-
function sucuriscan_get_user_lastlogin()
|
10451 |
-
|
10452 |
-
|
10453 |
-
&& SucuriScanRequest::get(
|
10454 |
) {
|
10455 |
$current_user = wp_get_current_user();
|
10456 |
|
10457 |
// Select the penultimate entry, not the last one.
|
10458 |
-
$last_logins = sucuriscan_get_logins(
|
10459 |
|
10460 |
-
if (
|
10461 |
$row = $last_logins['entries'][1];
|
10462 |
-
|
10463 |
-
$
|
10464 |
-
'Last
|
10465 |
-
SucuriScan::datetime(
|
10466 |
-
$row->user_remoteaddr,
|
10467 |
-
$row->user_hostname
|
10468 |
);
|
10469 |
-
$
|
10470 |
-
SucuriScanInterface::info(
|
10471 |
}
|
10472 |
}
|
10473 |
}
|
10474 |
|
10475 |
-
add_action(
|
10476 |
}
|
10477 |
|
10478 |
/**
|
@@ -10480,38 +10963,42 @@ if ( ! function_exists( 'sucuri_get_user_lastlogin' ) ) {
|
|
10480 |
*
|
10481 |
* @return string The HTML code displaying a list of all the users logged in at the moment.
|
10482 |
*/
|
10483 |
-
function sucuriscan_loggedin_users_panel()
|
|
|
10484 |
// Get user logged in list.
|
10485 |
-
$
|
10486 |
'LoggedInUsers.List' => '',
|
10487 |
'LoggedInUsers.Total' => 0,
|
10488 |
);
|
10489 |
|
10490 |
-
$logged_in_users = sucuriscan_get_online_users(
|
10491 |
|
10492 |
-
if (
|
10493 |
-
$
|
10494 |
$counter = 0;
|
10495 |
|
10496 |
-
foreach (
|
10497 |
-
$counter
|
10498 |
-
$logged_in_user['last_activity_datetime'] = SucuriScan::datetime(
|
10499 |
-
$logged_in_user['user_registered_datetime'] = SucuriScan::datetime(
|
10500 |
-
|
10501 |
-
$
|
10502 |
-
'
|
10503 |
-
|
10504 |
-
|
10505 |
-
|
10506 |
-
|
10507 |
-
|
10508 |
-
|
10509 |
-
|
10510 |
-
|
|
|
|
|
|
|
10511 |
}
|
10512 |
}
|
10513 |
|
10514 |
-
return SucuriScanTemplate::
|
10515 |
}
|
10516 |
|
10517 |
/**
|
@@ -10520,21 +11007,22 @@ function sucuriscan_loggedin_users_panel(){
|
|
10520 |
* @param boolean $add_current_user Whether the current user should be added to the list or not.
|
10521 |
* @return array List of registered users currently in session.
|
10522 |
*/
|
10523 |
-
function sucuriscan_get_online_users(
|
|
|
10524 |
$users = array();
|
10525 |
|
10526 |
-
if (
|
10527 |
-
$users = get_site_transient(
|
10528 |
} else {
|
10529 |
-
$users = get_transient(
|
10530 |
}
|
10531 |
|
10532 |
// If not online users but current user is logged in, add it to the list.
|
10533 |
-
if (
|
10534 |
$current_user = wp_get_current_user();
|
10535 |
|
10536 |
-
if (
|
10537 |
-
sucuriscan_set_online_user(
|
10538 |
|
10539 |
return sucuriscan_get_online_users();
|
10540 |
}
|
@@ -10551,32 +11039,34 @@ function sucuriscan_get_online_users( $add_current_user = false ){
|
|
10551 |
* @param array $logged_in_users List of registered users currently in session.
|
10552 |
* @return boolean Either TRUE or FALSE representing the success or fail of the operation.
|
10553 |
*/
|
10554 |
-
function sucuriscan_save_online_users(
|
|
|
10555 |
$expiration = 30 * 60;
|
10556 |
|
10557 |
-
if (
|
10558 |
-
return set_site_transient(
|
10559 |
} else {
|
10560 |
-
return set_transient(
|
10561 |
}
|
10562 |
}
|
10563 |
|
10564 |
-
if (
|
10565 |
/**
|
10566 |
* Remove a logged in user from the list of registered users in session when
|
10567 |
* the logout page is requested.
|
10568 |
*
|
10569 |
* @return void
|
10570 |
*/
|
10571 |
-
function sucuriscan_unset_online_user_on_logout()
|
|
|
10572 |
$remote_addr = SucuriScan::get_remote_addr();
|
10573 |
$current_user = wp_get_current_user();
|
10574 |
$user_id = $current_user->ID;
|
10575 |
|
10576 |
-
sucuriscan_unset_online_user(
|
10577 |
}
|
10578 |
|
10579 |
-
add_action(
|
10580 |
}
|
10581 |
|
10582 |
/**
|
@@ -10587,15 +11077,15 @@ if ( ! function_exists( 'sucuriscan_unset_online_user_on_logout' ) ) {
|
|
10587 |
* @param integer $remote_addr IP address of the computer where the user logged in.
|
10588 |
* @return boolean Either TRUE or FALSE representing the success or fail of the operation.
|
10589 |
*/
|
10590 |
-
function sucuriscan_unset_online_user(
|
|
|
10591 |
$logged_in_users = sucuriscan_get_online_users();
|
10592 |
|
10593 |
// Remove the specified user identifier from the list.
|
10594 |
-
if (
|
10595 |
-
foreach (
|
10596 |
-
if (
|
10597 |
-
$user['
|
10598 |
-
&& strcmp( $user['remote_addr'], $remote_addr ) == 0
|
10599 |
) {
|
10600 |
unset($logged_in_users[ $i ]);
|
10601 |
break;
|
@@ -10603,10 +11093,10 @@ function sucuriscan_unset_online_user( $user_id = 0, $remote_addr = 0 ){
|
|
10603 |
}
|
10604 |
}
|
10605 |
|
10606 |
-
return sucuriscan_save_online_users(
|
10607 |
}
|
10608 |
|
10609 |
-
if (
|
10610 |
/**
|
10611 |
* Add an user account to the list of registered users in session.
|
10612 |
*
|
@@ -10614,13 +11104,14 @@ if ( ! function_exists( 'sucuriscan_set_online_user' ) ) {
|
|
10614 |
* @param boolean $user The WordPress object containing all the information associated to the user.
|
10615 |
* @return void
|
10616 |
*/
|
10617 |
-
function sucuriscan_set_online_user(
|
10618 |
-
|
|
|
10619 |
// Get logged in user information.
|
10620 |
$current_user = ($user instanceof WP_User) ? $user : wp_get_current_user();
|
10621 |
$current_user_id = $current_user->ID;
|
10622 |
$remote_addr = SucuriScan::get_remote_addr();
|
10623 |
-
$current_time = current_time(
|
10624 |
$logged_in_users = sucuriscan_get_online_users();
|
10625 |
|
10626 |
// Build the dataset array that will be stored in the transient variable.
|
@@ -10633,21 +11124,20 @@ if ( ! function_exists( 'sucuriscan_set_online_user' ) ) {
|
|
10633 |
'remote_addr' => $remote_addr,
|
10634 |
);
|
10635 |
|
10636 |
-
if (
|
10637 |
$logged_in_users = array( $current_user_info );
|
10638 |
-
sucuriscan_save_online_users(
|
10639 |
} else {
|
10640 |
$do_nothing = false;
|
10641 |
$update_existing = false;
|
10642 |
$item_index = 0;
|
10643 |
|
10644 |
// Check if the user is already in the logged-in-user list and update it if is necessary.
|
10645 |
-
foreach (
|
10646 |
-
if (
|
10647 |
-
$user['
|
10648 |
-
&& strcmp( $user['remote_addr'], $remote_addr ) == 0
|
10649 |
) {
|
10650 |
-
if (
|
10651 |
$update_existing = true;
|
10652 |
$item_index = $i;
|
10653 |
break;
|
@@ -10658,20 +11148,20 @@ if ( ! function_exists( 'sucuriscan_set_online_user' ) ) {
|
|
10658 |
}
|
10659 |
}
|
10660 |
|
10661 |
-
if (
|
10662 |
$logged_in_users[ $item_index ] = $current_user_info;
|
10663 |
-
sucuriscan_save_online_users(
|
10664 |
-
} elseif (
|
10665 |
// Do nothing.
|
10666 |
} else {
|
10667 |
$logged_in_users[] = $current_user_info;
|
10668 |
-
sucuriscan_save_online_users(
|
10669 |
}
|
10670 |
}
|
10671 |
}
|
10672 |
}
|
10673 |
|
10674 |
-
add_action(
|
10675 |
}
|
10676 |
|
10677 |
/**
|
@@ -10679,7 +11169,8 @@ if ( ! function_exists( 'sucuriscan_set_online_user' ) ) {
|
|
10679 |
*
|
10680 |
* @return string A list with the failed logins occurred during the last hour.
|
10681 |
*/
|
10682 |
-
function sucuriscan_failed_logins_panel()
|
|
|
10683 |
$template_variables = array(
|
10684 |
'FailedLogins.List' => '',
|
10685 |
'FailedLogins.Total' => '',
|
@@ -10692,91 +11183,88 @@ function sucuriscan_failed_logins_panel(){
|
|
10692 |
);
|
10693 |
|
10694 |
// Define variables for the pagination.
|
10695 |
-
$page_number = SucuriScanTemplate::
|
10696 |
$max_per_page = SUCURISCAN_MAX_PAGINATION_BUTTONS;
|
10697 |
-
$page_offset = (
|
10698 |
-
$page_limit = (
|
10699 |
|
10700 |
-
$max_failed_logins = SucuriScanOption::get_option(
|
10701 |
-
$notify_bruteforce_attack = SucuriScanOption::get_option(
|
10702 |
$failed_logins = sucuriscan_get_failed_logins();
|
10703 |
-
$old_failed_logins = sucuriscan_get_failed_logins(
|
10704 |
|
10705 |
// Merge the new and old failed logins.
|
10706 |
-
if (
|
10707 |
-
is_array( $
|
10708 |
-
|
10709 |
-
) {
|
10710 |
-
if (
|
10711 |
-
is_array( $failed_logins )
|
10712 |
-
&& ! empty($failed_logins)
|
10713 |
-
) {
|
10714 |
-
$failed_logins = array_merge( $failed_logins, $old_failed_logins );
|
10715 |
} else {
|
10716 |
$failed_logins = $old_failed_logins;
|
10717 |
}
|
10718 |
}
|
10719 |
|
10720 |
-
if (
|
10721 |
$counter = 0;
|
10722 |
|
10723 |
-
for (
|
10724 |
-
if (
|
10725 |
$login_data = $failed_logins['entries'][ $key ];
|
10726 |
$css_class = ( $counter % 2 == 0 ) ? '' : 'alternate';
|
10727 |
-
$wrong_user_password = '
|
|
|
10728 |
|
10729 |
-
if (
|
10730 |
-
if (
|
10731 |
-
|
10732 |
-
|
10733 |
-
) {
|
10734 |
-
$wrong_user_password = SucuriScan::escape( $login_data['user_password'] );
|
10735 |
} else {
|
10736 |
-
$wrong_user_password = '
|
|
|
10737 |
}
|
10738 |
}
|
10739 |
|
10740 |
-
$template_variables['FailedLogins.List'] .= SucuriScanTemplate::
|
10741 |
-
'
|
10742 |
-
|
10743 |
-
|
10744 |
-
|
10745 |
-
|
10746 |
-
|
10747 |
-
|
10748 |
-
|
10749 |
-
|
10750 |
-
|
|
|
|
|
|
|
10751 |
}
|
10752 |
}
|
10753 |
|
10754 |
-
if (
|
10755 |
$template_variables['FailedLogins.NoItemsVisibility'] = 'hidden';
|
10756 |
}
|
10757 |
|
10758 |
-
$template_variables['FailedLogins.PaginationLinks'] = SucuriScanTemplate::
|
10759 |
'%%SUCURI.URL.Lastlogins%%#failed-logins',
|
10760 |
$failed_logins['count'],
|
10761 |
$max_per_page
|
10762 |
);
|
10763 |
|
10764 |
-
if (
|
10765 |
$template_variables['FailedLogins.PaginationVisibility'] = 'visible';
|
10766 |
}
|
10767 |
}
|
10768 |
|
10769 |
$template_variables['FailedLogins.MaxFailedLogins'] = $max_failed_logins;
|
10770 |
|
10771 |
-
if (
|
10772 |
$template_variables['FailedLogins.WarningVisibility'] = 'hidden';
|
10773 |
}
|
10774 |
|
10775 |
-
if (
|
10776 |
$template_variables['FailedLogins.CollectPasswordsVisibility'] = 'hidden';
|
10777 |
}
|
10778 |
|
10779 |
-
return SucuriScanTemplate::
|
10780 |
}
|
10781 |
|
10782 |
/**
|
@@ -10784,8 +11272,9 @@ function sucuriscan_failed_logins_panel(){
|
|
10784 |
*
|
10785 |
* @return boolean TRUE if the password must be collected, FALSE otherwise.
|
10786 |
*/
|
10787 |
-
function sucuriscan_collect_wrong_passwords()
|
10788 |
-
|
|
|
10789 |
}
|
10790 |
|
10791 |
/**
|
@@ -10800,21 +11289,19 @@ function sucuriscan_collect_wrong_passwords(){
|
|
10800 |
* @param boolean $reset Whether the file will be resetted or not.
|
10801 |
* @return string The full (relative) path where the file is located.
|
10802 |
*/
|
10803 |
-
function sucuriscan_failed_logins_datastore_path(
|
|
|
10804 |
$file_name = $get_old_logs ? 'sucuri-oldfailedlogins.php' : 'sucuri-failedlogins.php';
|
10805 |
-
$datastore_path = SucuriScan::datastore_folder_path(
|
10806 |
$default_content = sucuriscan_failed_logins_default_content();
|
10807 |
|
10808 |
// Create the file if it does not exists.
|
10809 |
-
if (
|
10810 |
-
@file_put_contents(
|
10811 |
}
|
10812 |
|
10813 |
// Return the datastore path if the file exists (or was created).
|
10814 |
-
if (
|
10815 |
-
file_exists( $datastore_path )
|
10816 |
-
&& is_readable( $datastore_path )
|
10817 |
-
) {
|
10818 |
return $datastore_path;
|
10819 |
}
|
10820 |
|
@@ -10826,7 +11313,8 @@ function sucuriscan_failed_logins_datastore_path( $get_old_logs = false, $reset
|
|
10826 |
*
|
10827 |
* @return string Default content of the file.
|
10828 |
*/
|
10829 |
-
function sucuriscan_failed_logins_default_content()
|
|
|
10830 |
$default_content = "<?php exit(0); ?>\n";
|
10831 |
|
10832 |
return $default_content;
|
@@ -10843,15 +11331,16 @@ function sucuriscan_failed_logins_default_content(){
|
|
10843 |
* @param boolean $get_old_logs Whether the old logs will be retrieved or not.
|
10844 |
* @return array Information and entries gathered from the failed logins datastore file.
|
10845 |
*/
|
10846 |
-
function sucuriscan_get_failed_logins(
|
10847 |
-
|
|
|
10848 |
$default_content = sucuriscan_failed_logins_default_content();
|
10849 |
-
$default_content_n = substr_count(
|
10850 |
|
10851 |
-
if (
|
10852 |
-
$lines = SucuriScanFileInfo::file_lines(
|
10853 |
|
10854 |
-
if (
|
10855 |
$failed_logins = array(
|
10856 |
'count' => 0,
|
10857 |
'first_attempt' => 0,
|
@@ -10861,21 +11350,21 @@ function sucuriscan_get_failed_logins( $get_old_logs = false ){
|
|
10861 |
);
|
10862 |
|
10863 |
// Read and parse all the entries found in the datastore file.
|
10864 |
-
$offset = count(
|
10865 |
|
10866 |
-
for (
|
10867 |
-
$line = trim(
|
10868 |
-
$login_data = @json_decode(
|
10869 |
|
10870 |
-
if (
|
10871 |
-
$login_data['attempt_date'] = date(
|
10872 |
$login_data['attempt_count'] = ( $key + 1 );
|
10873 |
|
10874 |
-
if (
|
10875 |
$login_data['user_agent'] = 'Unknown';
|
10876 |
}
|
10877 |
|
10878 |
-
if (
|
10879 |
$login_data['user_password'] = '';
|
10880 |
}
|
10881 |
|
@@ -10885,11 +11374,11 @@ function sucuriscan_get_failed_logins( $get_old_logs = false ){
|
|
10885 |
}
|
10886 |
|
10887 |
// Calculate the different time between the first and last attempt.
|
10888 |
-
if (
|
10889 |
-
$z = abs(
|
10890 |
$failed_logins['last_attempt'] = $failed_logins['entries'][ $z ]['attempt_time'];
|
10891 |
$failed_logins['first_attempt'] = $failed_logins['entries'][0]['attempt_time'];
|
10892 |
-
$failed_logins['diff_time'] = abs(
|
10893 |
|
10894 |
return $failed_logins;
|
10895 |
}
|
@@ -10909,15 +11398,16 @@ function sucuriscan_get_failed_logins( $get_old_logs = false ){
|
|
10909 |
* @param string $wrong_password Wrong password used during the supposed attack.
|
10910 |
* @return boolean Whether the information of the current failed login event was stored or not.
|
10911 |
*/
|
10912 |
-
function sucuriscan_log_failed_login(
|
|
|
10913 |
$datastore_path = sucuriscan_failed_logins_datastore_path();
|
10914 |
|
10915 |
// Do not collect wrong passwords if it is not necessary.
|
10916 |
-
if (
|
10917 |
$wrong_password = '';
|
10918 |
}
|
10919 |
|
10920 |
-
if (
|
10921 |
$login_data = json_encode(array(
|
10922 |
'user_login' => $user_login,
|
10923 |
'user_password' => $wrong_password,
|
@@ -10926,9 +11416,15 @@ function sucuriscan_log_failed_login( $user_login = '', $wrong_password = '' ){
|
|
10926 |
'user_agent' => SucuriScan::get_user_agent(),
|
10927 |
));
|
10928 |
|
10929 |
-
$
|
|
|
|
|
|
|
|
|
10930 |
|
10931 |
-
|
|
|
|
|
10932 |
}
|
10933 |
|
10934 |
return false;
|
@@ -10943,13 +11439,14 @@ function sucuriscan_log_failed_login( $user_login = '', $wrong_password = '' ){
|
|
10943 |
* @param array $failed_logins Information and entries gathered from the failed logins datastore file.
|
10944 |
* @return boolean Whether the report was sent via email or not.
|
10945 |
*/
|
10946 |
-
function sucuriscan_report_failed_logins(
|
10947 |
-
|
|
|
10948 |
$prettify_mails = SucuriScanMail::prettify_mails();
|
10949 |
$collect_wrong_passwords = sucuriscan_collect_wrong_passwords();
|
10950 |
$mail_content = '';
|
10951 |
|
10952 |
-
if (
|
10953 |
$table_html = '<table border="1" cellspacing="0" cellpadding="0">';
|
10954 |
|
10955 |
// Add the table headers.
|
@@ -10957,7 +11454,7 @@ function sucuriscan_report_failed_logins( $failed_logins = array() ){
|
|
10957 |
$table_html .= '<tr>';
|
10958 |
$table_html .= '<th>Username</th>';
|
10959 |
|
10960 |
-
if (
|
10961 |
$table_html .= '<th>Password</th>';
|
10962 |
}
|
10963 |
|
@@ -10970,16 +11467,16 @@ function sucuriscan_report_failed_logins( $failed_logins = array() ){
|
|
10970 |
$table_html .= '<tbody>';
|
10971 |
}
|
10972 |
|
10973 |
-
foreach (
|
10974 |
-
if (
|
10975 |
$table_html .= '<tr>';
|
10976 |
-
$table_html .= '<td>' . esc_attr(
|
10977 |
|
10978 |
-
if (
|
10979 |
-
$table_html .= '<td>' . esc_attr(
|
10980 |
}
|
10981 |
|
10982 |
-
$table_html .= '<td>' . esc_attr(
|
10983 |
$table_html .= '<td>' . $login_data['attempt_time'] . '</td>';
|
10984 |
$table_html .= '<td>' . $login_data['attempt_date'] . '</td>';
|
10985 |
$table_html .= '</tr>';
|
@@ -10987,7 +11484,7 @@ function sucuriscan_report_failed_logins( $failed_logins = array() ){
|
|
10987 |
$mail_content .= "\n";
|
10988 |
$mail_content .= 'Username: ' . $login_data['user_login'] . "\n";
|
10989 |
|
10990 |
-
if (
|
10991 |
$mail_content .= 'Password: ' . $login_data['user_password'] . "\n";
|
10992 |
}
|
10993 |
|
@@ -10997,13 +11494,13 @@ function sucuriscan_report_failed_logins( $failed_logins = array() ){
|
|
10997 |
}
|
10998 |
}
|
10999 |
|
11000 |
-
if (
|
11001 |
$table_html .= '</tbody>';
|
11002 |
$table_html .= '</table>';
|
11003 |
$mail_content = $table_html;
|
11004 |
}
|
11005 |
|
11006 |
-
if (
|
11007 |
sucuriscan_reset_failed_logins();
|
11008 |
|
11009 |
return true;
|
@@ -11021,12 +11518,13 @@ function sucuriscan_report_failed_logins( $failed_logins = array() ){
|
|
11021 |
*
|
11022 |
* @return boolean Whether the datastore file was resetted or not.
|
11023 |
*/
|
11024 |
-
function sucuriscan_reset_failed_logins()
|
11025 |
-
|
11026 |
-
$
|
|
|
11027 |
$default_content = sucuriscan_failed_logins_default_content();
|
11028 |
-
$current_content = @file_get_contents(
|
11029 |
-
$current_content = str_replace(
|
11030 |
|
11031 |
@file_put_contents(
|
11032 |
$datastore_backup_path,
|
@@ -11034,7 +11532,7 @@ function sucuriscan_reset_failed_logins(){
|
|
11034 |
FILE_APPEND
|
11035 |
);
|
11036 |
|
11037 |
-
return (bool) sucuriscan_failed_logins_datastore_path(
|
11038 |
}
|
11039 |
|
11040 |
/**
|
@@ -11045,596 +11543,396 @@ function sucuriscan_reset_failed_logins(){
|
|
11045 |
* @param boolean $page_nonce True if the nonce is valid, False otherwise.
|
11046 |
* @return void
|
11047 |
*/
|
11048 |
-
function sucuriscan_settings_form_submissions(
|
|
|
11049 |
global $sucuriscan_schedule_allowed,
|
11050 |
$sucuriscan_interface_allowed,
|
11051 |
$sucuriscan_notify_options,
|
11052 |
-
$sucuriscan_emails_per_hour,
|
11053 |
-
$sucuriscan_maximum_failed_logins,
|
11054 |
$sucuriscan_email_subjects;
|
11055 |
|
11056 |
// Use this conditional to avoid double checking.
|
11057 |
-
if (
|
11058 |
$page_nonce = SucuriScanInterface::check_nonce();
|
11059 |
}
|
11060 |
|
11061 |
-
if (
|
11062 |
// Save API key after it was recovered by the administrator.
|
11063 |
-
if (
|
11064 |
-
SucuriScanAPI::
|
11065 |
SucuriScanEvent::schedule_task();
|
11066 |
-
SucuriScanEvent::report_info_event(
|
11067 |
}
|
11068 |
|
11069 |
// Remove API key from the local storage.
|
11070 |
-
if (
|
11071 |
-
SucuriScanAPI::
|
11072 |
-
wp_clear_scheduled_hook(
|
11073 |
-
SucuriScanEvent::report_critical_event(
|
11074 |
-
SucuriScanEvent::notify_event(
|
11075 |
}
|
11076 |
|
11077 |
// Enable or disable the filesystem scanner.
|
11078 |
-
if (
|
11079 |
$action_d = $fs_scanner . 'd';
|
11080 |
$message = 'Main file system scanner was <code>' . $action_d . '</code>';
|
11081 |
|
11082 |
-
SucuriScanOption::update_option(
|
11083 |
-
SucuriScanEvent::report_auto_event(
|
11084 |
-
SucuriScanEvent::notify_event(
|
11085 |
-
SucuriScanInterface::info(
|
11086 |
-
}
|
11087 |
-
|
11088 |
-
// Enable or disable the filesystem scanner for modified files.
|
11089 |
-
if ( $scan_modfiles = SucuriScanRequest::post( ':scan_modfiles', '(en|dis)able' ) ) {
|
11090 |
-
$action_d = $scan_modfiles . 'd';
|
11091 |
-
$message = 'File system scanner for modified files was <code>' . $action_d . '</code>';
|
11092 |
-
|
11093 |
-
SucuriScanOption::update_option( ':scan_modfiles', $action_d );
|
11094 |
-
SucuriScanEvent::report_auto_event( $message );
|
11095 |
-
SucuriScanEvent::notify_event( 'plugin_change', $message );
|
11096 |
-
SucuriScanInterface::info( $message );
|
11097 |
}
|
11098 |
|
11099 |
// Enable or disable the filesystem scanner for file integrity.
|
11100 |
-
if (
|
11101 |
$action_d = $scan_checksums . 'd';
|
11102 |
$message = 'File system scanner for file integrity was <code>' . $action_d . '</code>';
|
11103 |
|
11104 |
-
SucuriScanOption::update_option(
|
11105 |
-
SucuriScanEvent::report_auto_event(
|
11106 |
-
SucuriScanEvent::notify_event(
|
11107 |
-
SucuriScanInterface::info(
|
11108 |
}
|
11109 |
|
11110 |
// Enable or disable the filesystem scanner for error logs.
|
11111 |
-
if (
|
11112 |
$action_d = $ignore_scanning . 'd';
|
11113 |
$message = 'File system scanner rules to ignore directories was <code>' . $action_d . '</code>';
|
11114 |
|
11115 |
-
SucuriScanOption::update_option(
|
11116 |
-
SucuriScanEvent::report_auto_event(
|
11117 |
-
SucuriScanEvent::notify_event(
|
11118 |
-
SucuriScanInterface::info(
|
11119 |
}
|
11120 |
|
11121 |
// Enable or disable the filesystem scanner for error logs.
|
11122 |
-
if (
|
11123 |
$action_d = $scan_errorlogs . 'd';
|
11124 |
$message = 'File system scanner for error logs was <code>' . $action_d . '</code>';
|
11125 |
|
11126 |
-
SucuriScanOption::update_option(
|
11127 |
-
SucuriScanEvent::report_auto_event(
|
11128 |
-
SucuriScanEvent::notify_event(
|
11129 |
-
SucuriScanInterface::info(
|
11130 |
}
|
11131 |
|
11132 |
// Enable or disable the error logs parsing.
|
11133 |
-
if (
|
11134 |
$action_d = $parse_errorlogs . 'd';
|
11135 |
$message = 'Analysis of main error log file was <code>' . $action_d . '</code>';
|
11136 |
|
11137 |
-
SucuriScanOption::update_option(
|
11138 |
-
SucuriScanEvent::report_auto_event(
|
11139 |
-
SucuriScanEvent::notify_event(
|
11140 |
-
SucuriScanInterface::info(
|
11141 |
}
|
11142 |
|
11143 |
// Enable or disable the SiteCheck scanner and the malware scan page.
|
11144 |
-
if (
|
11145 |
$action_d = $sitecheck_scanner . 'd';
|
11146 |
$message = 'SiteCheck malware and blacklist scanner was <code>' . $action_d . '</code>';
|
11147 |
|
11148 |
-
SucuriScanOption::update_option(
|
11149 |
-
SucuriScanEvent::report_auto_event(
|
11150 |
-
SucuriScanEvent::notify_event(
|
11151 |
-
SucuriScanInterface::info(
|
11152 |
}
|
11153 |
|
11154 |
// Modify the schedule of the filesystem scanner.
|
11155 |
-
if (
|
11156 |
-
if (
|
11157 |
-
SucuriScanOption::update_option(
|
11158 |
-
wp_clear_scheduled_hook(
|
11159 |
|
11160 |
-
if (
|
11161 |
-
wp_schedule_event(
|
11162 |
}
|
11163 |
|
11164 |
-
$frequency_title = strtolower(
|
11165 |
$message = 'File system scanning frequency set to <code>' . $frequency_title . '</code>';
|
11166 |
|
11167 |
-
SucuriScanEvent::report_info_event(
|
11168 |
-
SucuriScanEvent::notify_event(
|
11169 |
-
SucuriScanInterface::info(
|
11170 |
}
|
11171 |
}
|
11172 |
|
11173 |
// Set the method (aka. interface) that will be used to scan the site.
|
11174 |
-
if (
|
11175 |
-
$allowed_values = array_keys(
|
11176 |
|
11177 |
-
if (
|
11178 |
$message = 'File system scanning interface set to <code>' . $interface . '</code>';
|
11179 |
|
11180 |
-
SucuriScanOption::update_option(
|
11181 |
-
SucuriScanEvent::report_info_event(
|
11182 |
-
SucuriScanEvent::notify_event(
|
11183 |
-
SucuriScanInterface::info(
|
11184 |
}
|
11185 |
}
|
11186 |
|
11187 |
// Update the limit of error log lines to parse.
|
11188 |
-
if (
|
11189 |
-
if (
|
11190 |
-
SucuriScanInterface::error(
|
11191 |
} else {
|
11192 |
-
SucuriScanOption::update_option(
|
11193 |
-
SucuriScanInterface::info(
|
11194 |
|
11195 |
-
if (
|
11196 |
-
SucuriScanOption::update_option(
|
11197 |
}
|
11198 |
}
|
11199 |
}
|
11200 |
|
11201 |
// Reset the plugin security logs.
|
11202 |
$allowed_log_files = '(integrity|lastlogins|failedlogins|sitecheck)';
|
11203 |
-
if (
|
11204 |
$files_to_delete = array(
|
11205 |
'sucuri-' . $reset_logfile . '.php',
|
11206 |
'sucuri-old' . $reset_logfile . '.php',
|
11207 |
);
|
11208 |
|
11209 |
-
foreach (
|
11210 |
-
$log_filepath = SucuriScan::datastore_folder_path(
|
11211 |
|
11212 |
-
if (
|
11213 |
-
$log_filename_simple = str_replace(
|
11214 |
$message = 'Deleted security log <code>' . $log_filename_simple . '</code>';
|
11215 |
|
11216 |
-
SucuriScanEvent::report_debug_event(
|
11217 |
-
SucuriScanInterface::info(
|
11218 |
-
}
|
11219 |
-
}
|
11220 |
-
}
|
11221 |
-
|
11222 |
-
// Update the value for the maximum emails per hour.
|
11223 |
-
if ( $per_hour = SucuriScanRequest::post( ':emails_per_hour' ) ) {
|
11224 |
-
if ( array_key_exists( $per_hour, $sucuriscan_emails_per_hour ) ) {
|
11225 |
-
$per_hour_label = strtolower( $sucuriscan_emails_per_hour[ $per_hour ] );
|
11226 |
-
$message = 'Maximum email alerts per hour set to <code>' . $per_hour_label . '</code>';
|
11227 |
-
|
11228 |
-
SucuriScanOption::update_option( ':emails_per_hour', $per_hour );
|
11229 |
-
SucuriScanEvent::report_info_event( $message );
|
11230 |
-
SucuriScanEvent::notify_event( 'plugin_change', $message );
|
11231 |
-
SucuriScanInterface::info( $message );
|
11232 |
-
} else {
|
11233 |
-
SucuriScanInterface::error( 'Invalid value for the maximum emails per hour.' );
|
11234 |
-
}
|
11235 |
-
}
|
11236 |
-
|
11237 |
-
// Update the email where the event notifications will be sent.
|
11238 |
-
if ( $new_email = SucuriScanRequest::post( ':notify_to' ) ) {
|
11239 |
-
$valid_email = SucuriScan::get_valid_email( $new_email );
|
11240 |
-
|
11241 |
-
if ( $valid_email ) {
|
11242 |
-
$message = 'Sucuri alerts will be sent to this email: <code>' . $valid_email . '</code>';
|
11243 |
-
|
11244 |
-
SucuriScanOption::update_option( ':notify_to', $valid_email );
|
11245 |
-
SucuriScanEvent::report_info_event( $message );
|
11246 |
-
SucuriScanEvent::notify_event( 'plugin_change', $message );
|
11247 |
-
SucuriScanInterface::info( $message );
|
11248 |
-
} else {
|
11249 |
-
SucuriScanInterface::error( 'Email format not supported.' );
|
11250 |
-
}
|
11251 |
-
}
|
11252 |
-
|
11253 |
-
// Update the maximum failed logins per hour before consider it a brute-force attack.
|
11254 |
-
if ( $failed_logins = SucuriScanRequest::post( ':maximum_failed_logins' ) ) {
|
11255 |
-
if ( array_key_exists( $failed_logins, $sucuriscan_maximum_failed_logins ) ) {
|
11256 |
-
$message = 'Consider brute-force attack after <code>' . $failed_logins . '</code> failed logins per hour';
|
11257 |
-
|
11258 |
-
SucuriScanOption::update_option( ':maximum_failed_logins', $failed_logins );
|
11259 |
-
SucuriScanEvent::report_info_event( $message );
|
11260 |
-
SucuriScanEvent::notify_event( 'plugin_change', $message );
|
11261 |
-
SucuriScanInterface::info( $message );
|
11262 |
-
} else {
|
11263 |
-
SucuriScanInterface::error( 'Invalid value for the maximum failed logins per hour before consider it a brute-force attack.' );
|
11264 |
-
}
|
11265 |
-
}
|
11266 |
-
|
11267 |
-
// Enable or disable the audit logs report.
|
11268 |
-
if ( $audit_report = SucuriScanRequest::post( ':audit_report', '(en|dis)able' ) ) {
|
11269 |
-
$action_d = $audit_report . 'd';
|
11270 |
-
$message = 'Audit logs report was <code>' . $action_d . '</code>';
|
11271 |
-
|
11272 |
-
SucuriScanOption::update_option( ':audit_report', $action_d );
|
11273 |
-
SucuriScanEvent::report_info_event( $message );
|
11274 |
-
SucuriScanEvent::notify_event( 'plugin_change', $message );
|
11275 |
-
SucuriScanInterface::info( $message );
|
11276 |
-
}
|
11277 |
-
|
11278 |
-
// Update the limit for audit logs report.
|
11279 |
-
if ( $logs4report = SucuriScanRequest::post( ':logs4report', '[0-9]{1,4}' ) ) {
|
11280 |
-
$message = 'Limit for audit logs report set to <code>' . $logs4report . '</code>';
|
11281 |
-
|
11282 |
-
SucuriScanOption::update_option( ':logs4report', $logs4report );
|
11283 |
-
SucuriScanEvent::report_info_event( $message );
|
11284 |
-
SucuriScanEvent::notify_event( 'plugin_change', $message );
|
11285 |
-
SucuriScanInterface::info( $message );
|
11286 |
-
}
|
11287 |
-
|
11288 |
-
// Update the notification settings.
|
11289 |
-
if ( SucuriScanRequest::post( ':save_notification_settings' ) !== false ) {
|
11290 |
-
$options_updated_counter = 0;
|
11291 |
-
|
11292 |
-
if ( SucuriScanRequest::post( ':notify_scan_checksums', '1' ) ) {
|
11293 |
-
$_POST['sucuriscan_prettify_mails'] = '1';
|
11294 |
-
}
|
11295 |
-
|
11296 |
-
foreach ( $sucuriscan_notify_options as $alert_type => $alert_label ) {
|
11297 |
-
$option_value = SucuriScanRequest::post( $alert_type, '(1|0)' );
|
11298 |
-
|
11299 |
-
if ( $option_value !== false ) {
|
11300 |
-
$current_value = SucuriScanOption::get_option( $alert_type );
|
11301 |
-
$option_value = ( $option_value == '1' ) ? 'enabled' : 'disabled';
|
11302 |
-
|
11303 |
-
// Check that the option value was actually changed.
|
11304 |
-
if ( $current_value !== $option_value ) {
|
11305 |
-
SucuriScanOption::update_option( $alert_type, $option_value );
|
11306 |
-
$options_updated_counter += 1;
|
11307 |
-
}
|
11308 |
-
}
|
11309 |
-
}
|
11310 |
-
|
11311 |
-
if ( $options_updated_counter > 0 ) {
|
11312 |
-
$message = 'Alert settings were changed <code>' . $options_updated_counter . ' options</code>';
|
11313 |
-
|
11314 |
-
SucuriScanEvent::report_info_event( $message );
|
11315 |
-
SucuriScanEvent::notify_event( 'plugin_change', $message );
|
11316 |
-
SucuriScanInterface::info( $message );
|
11317 |
-
}
|
11318 |
-
}
|
11319 |
-
|
11320 |
-
// Update the subject format for the email alerts.
|
11321 |
-
if ( $email_subject = SucuriScanRequest::post( ':email_subject' ) ) {
|
11322 |
-
$new_email_subject = false;
|
11323 |
-
$current_value = SucuriScanOption::get_option( ':email_subject' );
|
11324 |
-
|
11325 |
-
/**
|
11326 |
-
* Validate the format of the email subject format.
|
11327 |
-
*
|
11328 |
-
* If the user chooses the option to build the subject of the email alerts
|
11329 |
-
* manually we will need to validate the characters. Otherwise we will need to
|
11330 |
-
* check if the pseudo-tags selected by the user are allowed and supported.
|
11331 |
-
*/
|
11332 |
-
if ( $email_subject == 'custom' ) {
|
11333 |
-
$format_pattern = '/^[0-9a-zA-Z:,\s]+$/';
|
11334 |
-
$custom_email_subject = SucuriScanRequest::post( ':custom_email_subject' );
|
11335 |
-
|
11336 |
-
if (
|
11337 |
-
$custom_email_subject !== false
|
11338 |
-
&& ! empty($custom_email_subject)
|
11339 |
-
&& preg_match( $format_pattern, $custom_email_subject )
|
11340 |
-
) {
|
11341 |
-
$new_email_subject = trim( $custom_email_subject );
|
11342 |
-
} else {
|
11343 |
-
SucuriScanInterface::error( 'Invalid characters found in the email alert subject format.' );
|
11344 |
}
|
11345 |
-
} elseif (
|
11346 |
-
is_array( $sucuriscan_email_subjects )
|
11347 |
-
&& in_array( $email_subject, $sucuriscan_email_subjects )
|
11348 |
-
) {
|
11349 |
-
$new_email_subject = trim( $email_subject );
|
11350 |
-
}
|
11351 |
-
|
11352 |
-
// Proceed with the operation saving the new subject.
|
11353 |
-
if (
|
11354 |
-
$new_email_subject !== false
|
11355 |
-
&& $current_value !== $new_email_subject
|
11356 |
-
) {
|
11357 |
-
$message = 'Alert subject format set to <code>' . $new_email_subject . '</code>';
|
11358 |
-
|
11359 |
-
SucuriScanOption::update_option( ':email_subject', $new_email_subject );
|
11360 |
-
SucuriScanEvent::report_info_event( $message );
|
11361 |
-
SucuriScanEvent::notify_event( 'plugin_change', $message );
|
11362 |
-
SucuriScanInterface::info( $message );
|
11363 |
}
|
11364 |
}
|
11365 |
|
11366 |
// Ignore a new event for email notifications.
|
11367 |
-
if (
|
11368 |
-
$ignore_rule = SucuriScanRequest::post(
|
11369 |
|
11370 |
-
if (
|
11371 |
-
if (
|
11372 |
-
SucuriScanInterface::info(
|
11373 |
-
SucuriScanEvent::report_warning_event(
|
11374 |
} else {
|
11375 |
-
SucuriScanInterface::error(
|
11376 |
}
|
11377 |
-
} elseif (
|
11378 |
-
SucuriScanOption::remove_ignored_event(
|
11379 |
-
SucuriScanInterface::info(
|
11380 |
-
SucuriScanEvent::report_notice_event(
|
11381 |
}
|
11382 |
}
|
11383 |
|
11384 |
// Ignore a new directory path for the file system scans.
|
11385 |
-
if (
|
11386 |
-
$ignore_directories = SucuriScanRequest::post(
|
11387 |
-
$ignore_file = SucuriScanRequest::post(
|
11388 |
|
11389 |
-
if (
|
11390 |
// Target a single file path to be ignored.
|
11391 |
-
if (
|
11392 |
$ignore_directories = array( $ignore_file );
|
11393 |
}
|
11394 |
|
11395 |
// Target a list of directories to be ignored.
|
11396 |
-
if (
|
11397 |
$were_ignored = array();
|
11398 |
|
11399 |
-
foreach (
|
11400 |
-
if (
|
11401 |
-
|
11402 |
-
&& SucuriScanFSScanner::ignore_directory( $resource_path )
|
11403 |
) {
|
11404 |
$were_ignored[] = $resource_path;
|
11405 |
}
|
11406 |
}
|
11407 |
|
11408 |
-
if (
|
11409 |
-
SucuriScanInterface::info(
|
11410 |
-
SucuriScanEvent::report_warning_event(
|
11411 |
'Resources will not be scanned: (multiple entries): %s',
|
11412 |
-
@implode(
|
11413 |
-
)
|
11414 |
}
|
11415 |
}
|
11416 |
-
} elseif (
|
11417 |
-
foreach (
|
11418 |
-
SucuriScanFSScanner::unignore_directory(
|
11419 |
}
|
11420 |
|
11421 |
-
SucuriScanInterface::info(
|
11422 |
-
SucuriScanEvent::report_notice_event(
|
11423 |
'Resources will be scanned: (multiple entries): %s',
|
11424 |
-
@implode(
|
11425 |
-
)
|
11426 |
}
|
11427 |
}
|
11428 |
|
11429 |
// Trust and IP address to ignore notifications for a subnet.
|
11430 |
-
if (
|
11431 |
-
if (
|
11432 |
-
SucuriScan::
|
11433 |
-
|| SucuriScan::is_valid_cidr( $trust_ip )
|
11434 |
) {
|
11435 |
-
$cache = new SucuriScanCache(
|
11436 |
-
$ip_info = SucuriScan::get_ip_info(
|
11437 |
$ip_info['added_at'] = SucuriScan::local_time();
|
11438 |
-
$cache_key = md5(
|
11439 |
|
11440 |
-
if (
|
11441 |
-
SucuriScanInterface::error(
|
11442 |
-
} elseif (
|
11443 |
$message = 'Changes from <code>' . $trust_ip . '</code> will be ignored';
|
11444 |
|
11445 |
-
SucuriScanEvent::report_warning_event(
|
11446 |
-
SucuriScanInterface::info(
|
11447 |
} else {
|
11448 |
-
SucuriScanInterface::error(
|
11449 |
}
|
11450 |
}
|
11451 |
}
|
11452 |
|
11453 |
// Trust and IP address to ignore notifications for a subnet.
|
11454 |
-
if (
|
11455 |
-
$cache = new SucuriScanCache(
|
11456 |
|
11457 |
-
foreach (
|
11458 |
-
$cache->delete(
|
11459 |
}
|
11460 |
|
11461 |
-
SucuriScanInterface::info(
|
11462 |
}
|
11463 |
|
11464 |
// Update the settings for the heartbeat API.
|
11465 |
-
if (
|
11466 |
$statuses_allowed = SucuriScanHeartbeat::statuses_allowed();
|
11467 |
|
11468 |
-
if (
|
11469 |
$message = 'Heartbeat status set to <code>' . $heartbeat_status . '</code>';
|
11470 |
|
11471 |
-
SucuriScanOption::update_option(
|
11472 |
-
SucuriScanEvent::report_info_event(
|
11473 |
-
SucuriScanInterface::info(
|
11474 |
} else {
|
11475 |
-
SucuriScanInterface::error(
|
11476 |
}
|
11477 |
}
|
11478 |
|
11479 |
// Update the value of the heartbeat pulse.
|
11480 |
-
if (
|
11481 |
$pulses_allowed = SucuriScanHeartbeat::pulses_allowed();
|
11482 |
|
11483 |
-
if (
|
11484 |
$message = 'Heartbeat pulse set to <code>' . $heartbeat_pulse . '</code> seconds.';
|
11485 |
|
11486 |
-
SucuriScanOption::update_option(
|
11487 |
-
SucuriScanEvent::report_info_event(
|
11488 |
-
SucuriScanInterface::info(
|
11489 |
} else {
|
11490 |
-
SucuriScanInterface::error(
|
11491 |
}
|
11492 |
}
|
11493 |
|
11494 |
// Update the value of the heartbeat interval.
|
11495 |
-
if (
|
11496 |
$intervals_allowed = SucuriScanHeartbeat::intervals_allowed();
|
11497 |
|
11498 |
-
if (
|
11499 |
$message = 'Heartbeat interval set to <code>' . $heartbeat_interval . '</code>';
|
11500 |
|
11501 |
-
SucuriScanOption::update_option(
|
11502 |
-
SucuriScanEvent::report_info_event(
|
11503 |
-
SucuriScanInterface::info(
|
11504 |
} else {
|
11505 |
-
SucuriScanInterface::error(
|
11506 |
}
|
11507 |
}
|
11508 |
|
11509 |
// Enable or disable the auto-start execution of heartbeat.
|
11510 |
-
if (
|
11511 |
$action_d = $heartbeat_autostart . 'd';
|
11512 |
$message = 'Heartbeat auto-start was <code>' . $action_d . '</code>';
|
11513 |
|
11514 |
-
SucuriScanOption::update_option(
|
11515 |
-
SucuriScanEvent::report_info_event(
|
11516 |
-
SucuriScanInterface::info(
|
11517 |
-
}
|
11518 |
-
|
11519 |
-
// Debug ability of the plugin to send email alerts correctly.
|
11520 |
-
if ( SucuriScanRequest::post( ':debug_email' ) ) {
|
11521 |
-
$recipient = SucuriScanOption::get_option( ':notify_to' );
|
11522 |
-
$mail_sent = SucuriScanMail::send_mail(
|
11523 |
-
$recipient,
|
11524 |
-
'Test email alert',
|
11525 |
-
sprintf( 'Test email alert sent at %s', date('r') ),
|
11526 |
-
array( 'Force' => true )
|
11527 |
-
);
|
11528 |
-
SucuriScanInterface::info( 'Test email alert sent, check your inbox.' );
|
11529 |
}
|
11530 |
}
|
11531 |
}
|
11532 |
|
11533 |
-
/**
|
11534 |
-
* Print a HTML code with the settings of the plugin.
|
11535 |
-
*
|
11536 |
-
* @return void
|
11537 |
-
*/
|
11538 |
-
function sucuriscan_settings_page(){
|
11539 |
-
SucuriScanInterface::check_permissions();
|
11540 |
-
|
11541 |
-
$template_variables = array(
|
11542 |
-
'PageTitle' => 'Settings',
|
11543 |
-
'Settings.General' => sucuriscan_settings_general(),
|
11544 |
-
'Settings.Scanner' => sucuriscan_settings_scanner(),
|
11545 |
-
'Settings.IgnoreScanning' => sucuriscan_settings_ignorescanning(),
|
11546 |
-
'Settings.Notifications' => sucuriscan_settings_notifications(),
|
11547 |
-
'Settings.IgnoreRules' => sucuriscan_settings_ignore_rules(),
|
11548 |
-
'Settings.TrustIP' => sucuriscan_settings_trust_ip(),
|
11549 |
-
'Settings.Heartbeat' => sucuriscan_settings_heartbeat(),
|
11550 |
-
);
|
11551 |
-
|
11552 |
-
echo SucuriScanTemplate::get_template( 'settings', $template_variables );
|
11553 |
-
}
|
11554 |
-
|
11555 |
/**
|
11556 |
* Read and parse the content of the general settings template.
|
11557 |
*
|
11558 |
* @return string Parsed HTML code for the general settings panel.
|
11559 |
*/
|
11560 |
-
function sucuriscan_settings_general()
|
11561 |
-
|
11562 |
-
|
11563 |
-
|
11564 |
|
11565 |
-
|
11566 |
-
$page_nonce = SucuriScanInterface::check_nonce();
|
11567 |
|
11568 |
-
//
|
11569 |
-
|
11570 |
|
11571 |
-
//
|
11572 |
-
$
|
11573 |
-
$
|
11574 |
-
$
|
11575 |
-
$
|
|
|
|
|
|
|
|
|
|
|
11576 |
|
11577 |
-
|
11578 |
-
$emails_per_hour_options = SucuriScanTemplate::get_select_options( $sucuriscan_emails_per_hour, $emails_per_hour );
|
11579 |
-
$maximum_failed_logins_options = SucuriScanTemplate::get_select_options( $sucuriscan_maximum_failed_logins, $maximum_failed_logins );
|
11580 |
|
11581 |
-
|
11582 |
-
|
11583 |
-
'EmailsPerHour' => 'Undefined',
|
11584 |
-
'EmailsPerHourOptions' => $emails_per_hour_options,
|
11585 |
-
'MaximumFailedLogins' => 'Undefined',
|
11586 |
-
'MaximumFailedLoginsOptions' => $maximum_failed_logins_options,
|
11587 |
-
/* Audit Logs Report */
|
11588 |
-
'AuditReportStatus' => 'Enabled',
|
11589 |
-
'AuditReportSwitchText' => 'Disable',
|
11590 |
-
'AuditReportSwitchValue' => 'disable',
|
11591 |
-
'AuditReportSwitchCssClass' => 'button-danger',
|
11592 |
-
'AuditReportLimit' => $logs4report,
|
11593 |
-
/* Timezone Settings */
|
11594 |
-
'CustomTimezone' => '',
|
11595 |
-
'CurrentDatetime' => '',
|
11596 |
-
);
|
11597 |
|
11598 |
-
|
11599 |
-
|
|
|
|
|
|
|
11600 |
|
11601 |
-
|
11602 |
-
|
11603 |
-
|
11604 |
-
|
11605 |
-
|
11606 |
-
$template_variables['SettingsSection.ApiTimeout'] = sucuriscan_settings_general_apitimeout($page_nonce);
|
11607 |
-
$template_variables['SettingsSection.ReverseProxy'] = sucuriscan_settings_general_reverseproxy($page_nonce);
|
11608 |
-
$template_variables['SettingsSection.PasswordCollector'] = sucuriscan_settings_general_pwdcollector($page_nonce);
|
11609 |
-
$template_variables['SettingsSection.IPDiscoverer'] = sucuriscan_settings_general_ipdiscoverer($page_nonce);
|
11610 |
-
$template_variables['SettingsSection.CommentMonitor'] = sucuriscan_settings_general_commentmonitor($page_nonce);
|
11611 |
-
$template_variables['SettingsSection.XhrMonitor'] = sucuriscan_settings_general_xhrmonitor($page_nonce);
|
11612 |
|
11613 |
-
|
|
|
11614 |
|
11615 |
-
|
11616 |
-
|
11617 |
-
}
|
11618 |
|
11619 |
-
|
11620 |
-
|
11621 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
11622 |
|
11623 |
-
|
11624 |
-
|
11625 |
-
|
11626 |
-
|
11627 |
-
|
11628 |
-
|
11629 |
|
11630 |
-
|
11631 |
-
|
11632 |
-
|
11633 |
-
|
11634 |
-
$template_variables['CustomTimezone'] = empty( $tzstring ) ? 'UTC' . $gmt_offset : $tzstring;
|
11635 |
}
|
11636 |
|
11637 |
-
return SucuriScanTemplate::
|
11638 |
}
|
11639 |
|
11640 |
function sucuriscan_settings_general_apikey($nonce)
|
@@ -11654,8 +11952,8 @@ function sucuriscan_settings_general_apikey($nonce)
|
|
11654 |
|
11655 |
if ($user_obj !== false && user_can($user_obj, 'administrator')) {
|
11656 |
// Send request to generate new API key or display form to set manually.
|
11657 |
-
if (SucuriScanAPI::
|
11658 |
-
$api_registered_modal = SucuriScanTemplate::
|
11659 |
'settings-apiregistered',
|
11660 |
array(
|
11661 |
'Title' => 'Site registered successfully',
|
@@ -11670,9 +11968,9 @@ function sucuriscan_settings_general_apikey($nonce)
|
|
11670 |
|
11671 |
// Recover API key through the email registered previously.
|
11672 |
if (SucuriScanRequest::post(':recover_key') !== false) {
|
11673 |
-
SucuriScanAPI::
|
11674 |
SucuriScanEvent::report_info_event('Recovery of the Sucuri API key was requested.');
|
11675 |
-
$api_recovery_modal = SucuriScanTemplate::
|
11676 |
'settings-apirecovery',
|
11677 |
array(
|
11678 |
'Title' => 'Plugin API Key Recovery',
|
@@ -11682,7 +11980,7 @@ function sucuriscan_settings_general_apikey($nonce)
|
|
11682 |
}
|
11683 |
}
|
11684 |
|
11685 |
-
$api_key = SucuriScanAPI::
|
11686 |
|
11687 |
// Check whether the domain name is valid or not.
|
11688 |
if (!$api_key) {
|
@@ -11691,7 +11989,7 @@ function sucuriscan_settings_general_apikey($nonce)
|
|
11691 |
$invalid_domain = (bool) ($domain_address === $clean_domain);
|
11692 |
}
|
11693 |
|
11694 |
-
$params['APIKey'] = (!$api_key ? '
|
11695 |
$params['APIKey.RecoverVisibility'] = SucuriScanTemplate::visibility(!$api_key && !$display_manual_key_form);
|
11696 |
$params['APIKey.ManualKeyFormVisibility'] = SucuriScanTemplate::visibility($display_manual_key_form);
|
11697 |
$params['APIKey.RemoveVisibility'] = SucuriScanTemplate::visibility((bool) $api_key);
|
@@ -11699,40 +11997,7 @@ function sucuriscan_settings_general_apikey($nonce)
|
|
11699 |
$params['ModalWhenAPIRegistered'] = $api_registered_modal;
|
11700 |
$params['ModalForApiKeyRecovery'] = $api_recovery_modal;
|
11701 |
|
11702 |
-
return SucuriScanTemplate::
|
11703 |
-
}
|
11704 |
-
|
11705 |
-
function sucuriscan_settings_general_apiproxy()
|
11706 |
-
{
|
11707 |
-
$params = array(
|
11708 |
-
'APIProxy.Host' => 'no_proxy_host',
|
11709 |
-
'APIProxy.Port' => 'no_proxy_port',
|
11710 |
-
'APIProxy.Username' => 'no_proxy_username',
|
11711 |
-
'APIProxy.Password' => 'no_proxy_password',
|
11712 |
-
'APIProxy.PasswordType' => 'default',
|
11713 |
-
'APIProxy.PasswordText' => 'empty',
|
11714 |
-
);
|
11715 |
-
|
11716 |
-
if (class_exists('WP_HTTP_Proxy')) {
|
11717 |
-
$wp_http_proxy = new WP_HTTP_Proxy();
|
11718 |
-
|
11719 |
-
if ($wp_http_proxy->is_enabled()) {
|
11720 |
-
$proxy_host = SucuriScan::escape($wp_http_proxy->host());
|
11721 |
-
$proxy_port = SucuriScan::escape($wp_http_proxy->port());
|
11722 |
-
$proxy_username = SucuriScan::escape($wp_http_proxy->username());
|
11723 |
-
$proxy_password = SucuriScan::escape($wp_http_proxy->password());
|
11724 |
-
|
11725 |
-
$template_variables['APIProxy.Host'] = $proxy_host;
|
11726 |
-
$template_variables['APIProxy.Port'] = $proxy_port;
|
11727 |
-
$template_variables['APIProxy.Username'] = $proxy_username;
|
11728 |
-
$template_variables['APIProxy.Password'] = $proxy_password;
|
11729 |
-
$template_variables['APIProxy.PasswordType'] = 'info';
|
11730 |
-
$template_variables['APIProxy.PasswordText'] = 'hidden';
|
11731 |
-
|
11732 |
-
}
|
11733 |
-
}
|
11734 |
-
|
11735 |
-
return SucuriScanTemplate::get_section('settings-general-apiproxy', $params);
|
11736 |
}
|
11737 |
|
11738 |
function sucuriscan_settings_general_datastorage($nonce)
|
@@ -11780,75 +12045,7 @@ function sucuriscan_settings_general_datastorage($nonce)
|
|
11780 |
|
11781 |
$params['DatastorePath'] = SucuriScanOption::get_option(':datastore_path');
|
11782 |
|
11783 |
-
return SucuriScanTemplate::
|
11784 |
-
}
|
11785 |
-
|
11786 |
-
function sucuriscan_settings_general_apissl($nonce)
|
11787 |
-
{
|
11788 |
-
global $sucuriscan_verify_ssl_cert;
|
11789 |
-
|
11790 |
-
$params = array(
|
11791 |
-
'VerifySSLCert' => 'Undefined',
|
11792 |
-
'VerifySSLCertCssClass' => 0,
|
11793 |
-
'VerifySSLCertOptions' => '',
|
11794 |
-
);
|
11795 |
-
|
11796 |
-
// Update the configuration for the SSL certificate verification.
|
11797 |
-
if ($nonce) {
|
11798 |
-
$verify_ssl_cert = SucuriScanRequest::post(':verify_ssl_cert');
|
11799 |
-
|
11800 |
-
if ($verify_ssl_cert) {
|
11801 |
-
if (array_key_exists($verify_ssl_cert, $sucuriscan_verify_ssl_cert)) {
|
11802 |
-
$message = 'SSL certificate verification for API calls set to <code>' . $verify_ssl_cert . '</code>';
|
11803 |
-
|
11804 |
-
SucuriScanOption::update_option(':verify_ssl_cert', $verify_ssl_cert);
|
11805 |
-
SucuriScanEvent::report_warning_event($message);
|
11806 |
-
SucuriScanEvent::notify_event('plugin_change', $message);
|
11807 |
-
SucuriScanInterface::info($message);
|
11808 |
-
} else {
|
11809 |
-
SucuriScanInterface::error('Invalid value for the SSL certificate verification.');
|
11810 |
-
}
|
11811 |
-
}
|
11812 |
-
}
|
11813 |
-
|
11814 |
-
$verify_ssl_cert = SucuriScanOption::get_option(':verify_ssl_cert');
|
11815 |
-
$params['VerifySSLCertOptions'] = SucuriScanTemplate::get_select_options(
|
11816 |
-
$sucuriscan_verify_ssl_cert,
|
11817 |
-
$verify_ssl_cert
|
11818 |
-
);
|
11819 |
-
|
11820 |
-
if (array_key_exists($verify_ssl_cert, $sucuriscan_verify_ssl_cert)) {
|
11821 |
-
$params['VerifySSLCert'] = $sucuriscan_verify_ssl_cert[$verify_ssl_cert];
|
11822 |
-
|
11823 |
-
if ($verify_ssl_cert === 'true') {
|
11824 |
-
$params['VerifySSLCertCssClass'] = 1;
|
11825 |
-
}
|
11826 |
-
}
|
11827 |
-
|
11828 |
-
return SucuriScanTemplate::get_section('settings-general-apissl', $params);
|
11829 |
-
}
|
11830 |
-
|
11831 |
-
function sucuriscan_settings_general_apitimeout($nonce)
|
11832 |
-
{
|
11833 |
-
$params = array();
|
11834 |
-
|
11835 |
-
// Update the API request timeout.
|
11836 |
-
if ($nonce) {
|
11837 |
-
$timeout = SucuriScanRequest::post(':request_timeout', '[0-9]+');
|
11838 |
-
|
11839 |
-
if ($timeout !== false) {
|
11840 |
-
$message = 'API request timeout set to <code>' . $timeout . '</code> seconds.';
|
11841 |
-
|
11842 |
-
SucuriScanOption::update_option(':request_timeout', $timeout);
|
11843 |
-
SucuriScanEvent::report_info_event($message);
|
11844 |
-
SucuriScanEvent::notify_event('plugin_change', $message);
|
11845 |
-
SucuriScanInterface::info($message);
|
11846 |
-
}
|
11847 |
-
}
|
11848 |
-
|
11849 |
-
$params['RequestTimeout'] = SucuriScanOption::get_option(':request_timeout') . ' seconds';
|
11850 |
-
|
11851 |
-
return SucuriScanTemplate::get_section('settings-general-apitimeout', $params);
|
11852 |
}
|
11853 |
|
11854 |
function sucuriscan_settings_general_reverseproxy($nonce)
|
@@ -11865,13 +12062,13 @@ function sucuriscan_settings_general_reverseproxy($nonce)
|
|
11865 |
$revproxy = SucuriScanRequest::post(':revproxy', '(en|dis)able');
|
11866 |
|
11867 |
if ($revproxy) {
|
11868 |
-
|
11869 |
-
|
11870 |
-
|
11871 |
-
|
11872 |
-
|
11873 |
-
|
11874 |
-
|
11875 |
}
|
11876 |
}
|
11877 |
|
@@ -11882,7 +12079,7 @@ function sucuriscan_settings_general_reverseproxy($nonce)
|
|
11882 |
$params['ReverseProxySwitchCssClass'] = 'button-success';
|
11883 |
}
|
11884 |
|
11885 |
-
return SucuriScanTemplate::
|
11886 |
}
|
11887 |
|
11888 |
function sucuriscan_settings_general_pwdcollector($nonce)
|
@@ -11925,7 +12122,7 @@ function sucuriscan_settings_general_pwdcollector($nonce)
|
|
11925 |
$params['PwdCollectorSwitchCssClass'] = 'button-danger';
|
11926 |
}
|
11927 |
|
11928 |
-
return SucuriScanTemplate::
|
11929 |
}
|
11930 |
|
11931 |
function sucuriscan_settings_general_ipdiscoverer($nonce)
|
@@ -11938,6 +12135,7 @@ function sucuriscan_settings_general_ipdiscoverer($nonce)
|
|
11938 |
'WebsiteURL' => 'Unknown',
|
11939 |
'RemoteAddress' => '127.0.0.1',
|
11940 |
'RemoteAddressHeader' => 'INVALID',
|
|
|
11941 |
/* Switch form information. */
|
11942 |
'DnsLookupsStatus' => 'Enabled',
|
11943 |
'DnsLookupsSwitchText' => 'Disable',
|
@@ -11945,9 +12143,13 @@ function sucuriscan_settings_general_ipdiscoverer($nonce)
|
|
11945 |
'DnsLookupsSwitchCssClass' => 'button-danger',
|
11946 |
);
|
11947 |
|
|
|
|
|
|
|
11948 |
// Configure the DNS lookups option for reverse proxy detection.
|
11949 |
if ($nonce) {
|
11950 |
$dns_lookups = SucuriScanRequest::post(':dns_lookups', '(en|dis)able');
|
|
|
11951 |
|
11952 |
if ($dns_lookups) {
|
11953 |
$action_d = $dns_lookups . 'd';
|
@@ -11958,6 +12160,16 @@ function sucuriscan_settings_general_ipdiscoverer($nonce)
|
|
11958 |
SucuriScanEvent::notify_event('plugin_change', $message);
|
11959 |
SucuriScanInterface::info($message);
|
11960 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
11961 |
}
|
11962 |
|
11963 |
if (SucuriScanOption::is_disabled(':dns_lookups')) {
|
@@ -11977,12 +12189,16 @@ function sucuriscan_settings_general_ipdiscoverer($nonce)
|
|
11977 |
$params['RemoteAddressHeader'] = SucuriScan::get_remote_addr_header();
|
11978 |
$params['RemoteAddress'] = SucuriScan::get_remote_addr();
|
11979 |
$params['WebsiteURL'] = SucuriScan::get_domain();
|
|
|
|
|
|
|
|
|
11980 |
|
11981 |
if ($base_domain !== $proxy_info['http_host']) {
|
11982 |
$params['TopLevelDomain'] = sprintf('%s (%s)', $params['TopLevelDomain'], $base_domain);
|
11983 |
}
|
11984 |
|
11985 |
-
return SucuriScanTemplate::
|
11986 |
}
|
11987 |
|
11988 |
function sucuriscan_settings_general_commentmonitor($nonce)
|
@@ -12016,7 +12232,7 @@ function sucuriscan_settings_general_commentmonitor($nonce)
|
|
12016 |
$params['CommentMonitorSwitchCssClass'] = 'button-success';
|
12017 |
}
|
12018 |
|
12019 |
-
return SucuriScanTemplate::
|
12020 |
}
|
12021 |
|
12022 |
function sucuriscan_settings_general_xhrmonitor($nonce)
|
@@ -12050,70 +12266,91 @@ function sucuriscan_settings_general_xhrmonitor($nonce)
|
|
12050 |
$params['XhrMonitorSwitchCssClass'] = 'button-success';
|
12051 |
}
|
12052 |
|
12053 |
-
return SucuriScanTemplate::
|
12054 |
}
|
12055 |
|
12056 |
-
function
|
12057 |
{
|
12058 |
-
|
12059 |
-
|
12060 |
-
|
|
|
|
|
|
|
|
|
12061 |
|
12062 |
-
|
12063 |
-
|
12064 |
-
|
|
|
|
|
12065 |
|
12066 |
-
SucuriScanOption::update_option(':
|
12067 |
SucuriScanEvent::report_info_event($message);
|
|
|
12068 |
SucuriScanInterface::info($message);
|
12069 |
}
|
12070 |
-
}
|
12071 |
-
}
|
12072 |
|
12073 |
-
|
12074 |
-
{
|
12075 |
-
|
12076 |
-
|
12077 |
-
$process = SucuriScanRequest::post(':process_form');
|
12078 |
|
12079 |
-
|
12080 |
-
|
12081 |
-
$message = 'Sucuri plugin options were reset';
|
12082 |
-
SucuriScanEvent::report_critical_event($message);
|
12083 |
SucuriScanEvent::notify_event('plugin_change', $message);
|
|
|
|
|
|
|
12084 |
|
12085 |
-
|
12086 |
-
|
|
|
12087 |
|
12088 |
-
|
12089 |
-
|
|
|
|
|
|
|
|
|
|
|
12090 |
|
12091 |
-
|
12092 |
-
|
12093 |
-
@unlink(SucuriScan::datastore_folder_path('index.html'));
|
12094 |
-
@unlink(SucuriScan::datastore_folder_path('sucuri-failedlogins.php'));
|
12095 |
-
@unlink(SucuriScan::datastore_folder_path('sucuri-integrity.php'));
|
12096 |
-
@unlink(SucuriScan::datastore_folder_path('sucuri-lastlogins.php'));
|
12097 |
-
@unlink(SucuriScan::datastore_folder_path('sucuri-oldfailedlogins.php'));
|
12098 |
-
@unlink(SucuriScan::datastore_folder_path('sucuri-plugindata.php'));
|
12099 |
-
@unlink(SucuriScan::datastore_folder_path('sucuri-sitecheck.php'));
|
12100 |
-
@unlink(SucuriScan::datastore_folder_path('sucuri-trustip.php'));
|
12101 |
-
@rmdir(SucuriScan::datastore_folder_path());
|
12102 |
|
12103 |
-
|
12104 |
-
|
12105 |
-
|
12106 |
-
|
12107 |
-
|
12108 |
-
|
|
|
12109 |
|
12110 |
-
|
12111 |
-
|
12112 |
-
|
12113 |
-
|
|
|
12114 |
}
|
12115 |
|
12116 |
-
return SucuriScanTemplate::
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
12117 |
}
|
12118 |
|
12119 |
/**
|
@@ -12121,46 +12358,40 @@ function sucuriscan_settings_general_resetoptions($nonce)
|
|
12121 |
*
|
12122 |
* @return string Parsed HTML code for the scanner settings panel.
|
12123 |
*/
|
12124 |
-
function sucuriscan_settings_scanner()
|
12125 |
-
|
12126 |
global $sucuriscan_schedule_allowed,
|
12127 |
$sucuriscan_interface_allowed;
|
12128 |
|
12129 |
// Get initial variables to decide some things bellow.
|
12130 |
-
$fs_scanner = SucuriScanOption::get_option(
|
12131 |
-
$scan_freq = SucuriScanOption::get_option(
|
12132 |
-
$scan_interface = SucuriScanOption::get_option(
|
12133 |
-
$
|
12134 |
-
$
|
12135 |
-
$
|
12136 |
-
$
|
12137 |
-
$
|
12138 |
-
$
|
12139 |
-
$
|
12140 |
-
$
|
12141 |
-
$runtime_scan_human = SucuriScanFSScanner::get_filesystem_runtime( true );
|
12142 |
|
12143 |
// Get the file path of the security logs.
|
12144 |
-
$integrity_log_path = SucuriScan::datastore_folder_path(
|
12145 |
-
$lastlogins_log_path = SucuriScan::datastore_folder_path(
|
12146 |
-
$failedlogins_log_path = SucuriScan::datastore_folder_path(
|
12147 |
-
$sitecheck_log_path = SucuriScan::datastore_folder_path(
|
12148 |
|
12149 |
// Generate the HTML code for the option list in the form select fields.
|
12150 |
-
$scan_freq_options = SucuriScanTemplate::
|
12151 |
-
$scan_interface_options = SucuriScanTemplate::
|
12152 |
|
12153 |
-
$
|
12154 |
/* Filesystem scanner */
|
12155 |
'FsScannerStatus' => 'Enabled',
|
12156 |
'FsScannerSwitchText' => 'Disable',
|
12157 |
'FsScannerSwitchValue' => 'disable',
|
12158 |
'FsScannerSwitchCssClass' => 'button-danger',
|
12159 |
-
/* Scan modified files. */
|
12160 |
-
'ScanModfilesStatus' => 'Enabled',
|
12161 |
-
'ScanModfilesSwitchText' => 'Disable',
|
12162 |
-
'ScanModfilesSwitchValue' => 'disable',
|
12163 |
-
'ScanModfilesSwitchCssClass' => 'button-danger',
|
12164 |
/* Scan files checksum. */
|
12165 |
'ScanChecksumsStatus' => 'Enabled',
|
12166 |
'ScanChecksumsSwitchText' => 'Disable',
|
@@ -12201,324 +12432,840 @@ function sucuriscan_settings_scanner(){
|
|
12201 |
'SiteCheckLogLife' => '0B',
|
12202 |
);
|
12203 |
|
12204 |
-
if (
|
12205 |
-
$
|
12206 |
-
$
|
12207 |
-
$
|
12208 |
-
$
|
12209 |
}
|
12210 |
|
12211 |
-
if (
|
12212 |
-
$
|
12213 |
-
$
|
12214 |
-
$
|
12215 |
-
$
|
12216 |
}
|
12217 |
|
12218 |
-
if (
|
12219 |
-
$
|
12220 |
-
$
|
12221 |
-
$
|
12222 |
-
$
|
12223 |
}
|
12224 |
|
12225 |
-
if (
|
12226 |
-
$
|
12227 |
-
$
|
12228 |
-
$
|
12229 |
-
$
|
12230 |
}
|
12231 |
|
12232 |
-
if (
|
12233 |
-
$
|
12234 |
-
$
|
12235 |
-
$
|
12236 |
-
$
|
12237 |
}
|
12238 |
|
12239 |
-
if (
|
12240 |
-
$
|
12241 |
-
$
|
12242 |
-
$
|
12243 |
-
$
|
12244 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
12245 |
|
12246 |
-
|
12247 |
-
|
12248 |
-
|
12249 |
-
|
12250 |
-
|
12251 |
-
|
12252 |
|
12253 |
-
|
12254 |
-
$template_variables['ScanningFrequency'] = $sucuriscan_schedule_allowed[ $scan_freq ];
|
12255 |
}
|
12256 |
|
12257 |
-
|
12258 |
-
$template_variables['IntegrityLogLife'] = SucuriScan::human_filesize( @filesize( $integrity_log_path ) );
|
12259 |
-
$template_variables['LastLoginLogLife'] = SucuriScan::human_filesize( @filesize( $lastlogins_log_path ) );
|
12260 |
-
$template_variables['FailedLoginLogLife'] = SucuriScan::human_filesize( @filesize( $failedlogins_log_path ) );
|
12261 |
-
$template_variables['SiteCheckLogLife'] = SucuriScan::human_filesize( @filesize( $sitecheck_log_path ) );
|
12262 |
-
|
12263 |
-
return SucuriScanTemplate::get_section( 'settings-scanner', $template_variables );
|
12264 |
}
|
12265 |
|
12266 |
-
|
12267 |
-
|
12268 |
-
|
12269 |
-
* @return string Parsed HTML code for the notification settings panel.
|
12270 |
-
*/
|
12271 |
-
function sucuriscan_settings_notifications(){
|
12272 |
-
global $sucuriscan_notify_options,
|
12273 |
-
$sucuriscan_email_subjects;
|
12274 |
|
12275 |
-
$
|
12276 |
-
'
|
12277 |
-
'
|
12278 |
-
'
|
12279 |
-
'EmailSubjectCustom.Value' => '',
|
12280 |
-
'PrettifyMailsWarningVisibility' => SucuriScanTemplate::visibility( SucuriScanMail::prettify_mails() ),
|
12281 |
);
|
12282 |
|
12283 |
-
|
12284 |
-
|
12285 |
-
$
|
12286 |
|
12287 |
-
|
12288 |
-
if (
|
12289 |
-
$
|
12290 |
-
|
|
|
|
|
|
|
|
|
12291 |
} else {
|
12292 |
-
|
12293 |
}
|
12294 |
-
|
12295 |
-
$template_variables['EmailSubjectOptions'] .= SucuriScanTemplate::get_snippet('settings-emailsubject', array(
|
12296 |
-
'EmailSubject.Name' => $subject_format,
|
12297 |
-
'EmailSubject.Value' => $subject_format,
|
12298 |
-
'EmailSubject.Checked' => $checked,
|
12299 |
-
));
|
12300 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
12301 |
|
12302 |
-
|
12303 |
-
|
12304 |
-
|
|
|
|
|
12305 |
}
|
12306 |
}
|
12307 |
|
12308 |
-
|
12309 |
-
|
|
|
|
|
|
|
|
|
12310 |
|
12311 |
-
|
12312 |
-
|
12313 |
-
$
|
12314 |
-
$css_class = ( $counter % 2 == 0 ) ? 'alternate' : '';
|
12315 |
-
$alert_icon = '';
|
12316 |
|
12317 |
-
if (
|
12318 |
-
|
12319 |
-
|
12320 |
|
12321 |
-
|
12322 |
-
|
12323 |
-
|
12324 |
-
|
|
|
|
|
12325 |
}
|
12326 |
}
|
12327 |
-
|
12328 |
-
$template_variables['NotificationOptions'] .= SucuriScanTemplate::get_snippet('settings-notifications', array(
|
12329 |
-
'Notification.CssClass' => $css_class,
|
12330 |
-
'Notification.Name' => $alert_type,
|
12331 |
-
'Notification.Checked' => $checked,
|
12332 |
-
'Notification.Label' => $alert_label,
|
12333 |
-
'Notification.LabelIcon' => $alert_icon,
|
12334 |
-
));
|
12335 |
-
$counter += 1;
|
12336 |
}
|
12337 |
|
12338 |
-
|
|
|
|
|
|
|
12339 |
}
|
12340 |
|
12341 |
/**
|
12342 |
-
* Read and parse the content of the
|
12343 |
*
|
12344 |
-
* @return string Parsed HTML code for the
|
12345 |
*/
|
12346 |
-
function
|
12347 |
-
|
12348 |
-
|
12349 |
-
$template_variables = array(
|
12350 |
-
'IgnoreRules.MessageVisibility' => 'visible',
|
12351 |
-
'IgnoreRules.TableVisibility' => 'hidden',
|
12352 |
-
'IgnoreRules.PostTypes' => '',
|
12353 |
-
);
|
12354 |
-
|
12355 |
-
if ( $notify_new_site_content == 'enabled' ) {
|
12356 |
-
$post_types = get_post_types();
|
12357 |
-
$ignored_events = SucuriScanOption::get_ignored_events();
|
12358 |
|
12359 |
-
|
12360 |
-
$template_variables['IgnoreRules.TableVisibility'] = 'visible';
|
12361 |
-
$counter = 0;
|
12362 |
|
12363 |
-
|
12364 |
-
|
12365 |
-
$css_class = ( $counter % 2 == 0 ) ? 'alternate' : '';
|
12366 |
-
$post_type_title = ucwords( str_replace( '_', chr( 32 ), $post_type ) );
|
12367 |
|
12368 |
-
|
12369 |
-
|
12370 |
-
|
12371 |
-
|
12372 |
-
$button_action = 'remove';
|
12373 |
-
$button_class = 'button-primary';
|
12374 |
-
$button_text = 'Allow';
|
12375 |
-
} else {
|
12376 |
-
$is_ignored_text = 'NO';
|
12377 |
-
$was_ignored_at = 'Not ignored';
|
12378 |
-
$is_ignored_class = 'success';
|
12379 |
-
$button_action = 'add';
|
12380 |
-
$button_class = 'button-primary button-danger';
|
12381 |
-
$button_text = 'Ignore';
|
12382 |
-
}
|
12383 |
|
12384 |
-
|
12385 |
-
|
12386 |
-
|
12387 |
-
|
12388 |
-
|
12389 |
-
|
12390 |
-
'IgnoreRules.IsIgnoredClass' => $is_ignored_class,
|
12391 |
-
'IgnoreRules.PostType' => $post_type,
|
12392 |
-
'IgnoreRules.Action' => $button_action,
|
12393 |
-
'IgnoreRules.ButtonClass' => 'button ' . $button_class,
|
12394 |
-
'IgnoreRules.ButtonText' => $button_text,
|
12395 |
-
));
|
12396 |
-
}
|
12397 |
}
|
12398 |
|
12399 |
-
return
|
12400 |
}
|
12401 |
|
12402 |
-
|
12403 |
-
|
12404 |
-
|
12405 |
-
* @return string Parsed HTML code for the trust-ip settings panel.
|
12406 |
-
*/
|
12407 |
-
function sucuriscan_settings_trust_ip(){
|
12408 |
-
$template_variables = array(
|
12409 |
-
'TrustedIPs.List' => '',
|
12410 |
-
'TrustedIPs.NoItems.Visibility' => 'visible',
|
12411 |
-
);
|
12412 |
|
12413 |
-
$
|
12414 |
-
$
|
|
|
|
|
|
|
|
|
|
|
12415 |
|
12416 |
-
if (
|
12417 |
-
|
|
|
12418 |
|
12419 |
-
|
12420 |
-
|
|
|
12421 |
|
12422 |
-
|
12423 |
-
|
12424 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
12425 |
|
12426 |
-
|
12427 |
-
'
|
12428 |
-
'
|
12429 |
-
'
|
12430 |
-
|
12431 |
-
|
12432 |
-
));
|
12433 |
-
$counter += 1;
|
12434 |
}
|
|
|
12435 |
|
12436 |
-
|
12437 |
-
|
12438 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
12439 |
}
|
12440 |
|
12441 |
-
return SucuriScanTemplate::
|
12442 |
}
|
12443 |
|
12444 |
/**
|
12445 |
-
* Read and parse the content of the
|
12446 |
*
|
12447 |
-
* @return string Parsed HTML code for the
|
12448 |
*/
|
12449 |
-
function
|
12450 |
-
|
12451 |
-
|
12452 |
-
|
12453 |
-
|
12454 |
-
);
|
12455 |
-
|
12456 |
-
$ignore_scanning = SucuriScanFSScanner::will_ignore_scanning();
|
12457 |
|
12458 |
-
|
12459 |
-
|
12460 |
-
$ignore_scanning = false;
|
12461 |
-
}
|
12462 |
|
12463 |
-
|
12464 |
-
if ( $ignore_scanning === true ) {
|
12465 |
$counter = 0;
|
12466 |
-
$template_variables['IgnoreScanning.DisabledVisibility'] = 'hidden';
|
12467 |
-
$dir_list_list = SucuriScanFSScanner::get_ignored_directories_live();
|
12468 |
-
|
12469 |
-
foreach ( $dir_list_list as $group => $dir_list ) {
|
12470 |
-
foreach ( $dir_list as $dir_data ) {
|
12471 |
-
$valid_entry = false;
|
12472 |
-
$snippet_data = array(
|
12473 |
-
'IgnoreScanning.CssClass' => '',
|
12474 |
-
'IgnoreScanning.Directory' => '',
|
12475 |
-
'IgnoreScanning.DirectoryPath' => '',
|
12476 |
-
'IgnoreScanning.IgnoredAt' => '',
|
12477 |
-
'IgnoreScanning.IgnoredAtText' => 'ok',
|
12478 |
-
'IgnoreScanning.IgnoredCssClass' => 'success',
|
12479 |
-
);
|
12480 |
|
12481 |
-
|
12482 |
-
|
12483 |
-
$snippet_data['IgnoreScanning.Directory'] = urlencode( $dir_data['directory_path'] );
|
12484 |
-
$snippet_data['IgnoreScanning.DirectoryPath'] = SucuriScan::escape( $dir_data['directory_path'] );
|
12485 |
-
$snippet_data['IgnoreScanning.IgnoredAt'] = SucuriScan::datetime( $dir_data['ignored_at'] );
|
12486 |
-
$snippet_data['IgnoreScanning.IgnoredAtText'] = 'ignored';
|
12487 |
-
$snippet_data['IgnoreScanning.IgnoredCssClass'] = 'warning';
|
12488 |
-
} elseif ( $group == 'is_not_ignored' ) {
|
12489 |
-
$valid_entry = true;
|
12490 |
-
$snippet_data['IgnoreScanning.Directory'] = urlencode( $dir_data );
|
12491 |
-
$snippet_data['IgnoreScanning.DirectoryPath'] = SucuriScan::escape( $dir_data );
|
12492 |
-
}
|
12493 |
|
12494 |
-
|
12495 |
-
|
12496 |
-
$snippet_data['IgnoreScanning.CssClass'] = $css_class;
|
12497 |
-
$template_variables['IgnoreScanning.ResourceList'] .= SucuriScanTemplate::get_snippet( 'settings-ignorescanning', $snippet_data );
|
12498 |
-
$counter += 1;
|
12499 |
-
}
|
12500 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
12501 |
}
|
12502 |
|
12503 |
-
if (
|
12504 |
-
$
|
12505 |
}
|
12506 |
}
|
12507 |
|
12508 |
-
return SucuriScanTemplate::
|
12509 |
}
|
12510 |
|
|
|
12511 |
/**
|
12512 |
* Read and parse the content of the heartbeat settings template.
|
12513 |
*
|
12514 |
* @return string Parsed HTML code for the heartbeat settings panel.
|
12515 |
*/
|
12516 |
-
function sucuriscan_settings_heartbeat()
|
|
|
12517 |
// Current values set in the options table.
|
12518 |
-
$heartbeat_status = SucuriScanOption::get_option(
|
12519 |
-
$heartbeat_pulse = SucuriScanOption::get_option(
|
12520 |
-
$heartbeat_interval = SucuriScanOption::get_option(
|
12521 |
-
$heartbeat_autostart = SucuriScanOption::get_option(
|
12522 |
|
12523 |
// Allowed values for each setting.
|
12524 |
$statuses_allowed = SucuriScanHeartbeat::statuses_allowed();
|
@@ -12526,11 +13273,11 @@ function sucuriscan_settings_heartbeat(){
|
|
12526 |
$intervals_allowed = SucuriScanHeartbeat::intervals_allowed();
|
12527 |
|
12528 |
// HTML select form fields.
|
12529 |
-
$heartbeat_options = SucuriScanTemplate::
|
12530 |
-
$heartbeat_pulse_options = SucuriScanTemplate::
|
12531 |
-
$heartbeat_interval_options = SucuriScanTemplate::
|
12532 |
|
12533 |
-
$
|
12534 |
'HeartbeatStatus' => 'Undefined',
|
12535 |
'HeartbeatPulse' => 'Undefined',
|
12536 |
'HeartbeatInterval' => 'Undefined',
|
@@ -12545,26 +13292,52 @@ function sucuriscan_settings_heartbeat(){
|
|
12545 |
'HeartbeatAutostartSwitchCssClass' => 'button-danger',
|
12546 |
);
|
12547 |
|
12548 |
-
if (
|
12549 |
-
$
|
12550 |
}
|
12551 |
|
12552 |
-
if (
|
12553 |
-
$
|
12554 |
}
|
12555 |
|
12556 |
-
if (
|
12557 |
-
$
|
12558 |
}
|
12559 |
|
12560 |
-
if (
|
12561 |
-
$
|
12562 |
-
$
|
12563 |
-
$
|
12564 |
-
$
|
12565 |
}
|
12566 |
|
12567 |
-
return SucuriScanTemplate::
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
12568 |
}
|
12569 |
|
12570 |
/**
|
@@ -12576,14 +13349,15 @@ function sucuriscan_settings_heartbeat(){
|
|
12576 |
*
|
12577 |
* @return void
|
12578 |
*/
|
12579 |
-
function sucuriscan_infosys_page()
|
|
|
12580 |
SucuriScanInterface::check_permissions();
|
12581 |
|
12582 |
// Process all form submissions.
|
12583 |
sucuriscan_infosys_form_submissions();
|
12584 |
|
12585 |
// Page pseudo-variables initialization.
|
12586 |
-
$
|
12587 |
'PageTitle' => 'Site Info',
|
12588 |
'ServerInfo' => sucuriscan_server_info(),
|
12589 |
'Cronjobs' => sucuriscan_show_cronjobs(),
|
@@ -12592,7 +13366,7 @@ function sucuriscan_infosys_page(){
|
|
12592 |
'ErrorLogs' => sucuriscan_infosys_errorlogs(),
|
12593 |
);
|
12594 |
|
12595 |
-
echo SucuriScanTemplate::
|
12596 |
}
|
12597 |
|
12598 |
/**
|
@@ -12601,87 +13375,64 @@ function sucuriscan_infosys_page(){
|
|
12601 |
*
|
12602 |
* @return string The HTML code displaying the information about the HTAccess rules.
|
12603 |
*/
|
12604 |
-
function sucuriscan_infosys_htaccess()
|
|
|
12605 |
$htaccess_path = SucuriScan::get_htaccess_path();
|
12606 |
-
|
12607 |
-
$template_variables = array(
|
12608 |
'HTAccess.Content' => '',
|
12609 |
-
'HTAccess.Message' => '',
|
12610 |
-
'HTAccess.MessageType' => '',
|
12611 |
-
'HTAccess.MessageVisible' => 'hidden',
|
12612 |
'HTAccess.TextareaVisible' => 'hidden',
|
|
|
|
|
|
|
|
|
12613 |
);
|
12614 |
|
12615 |
-
if (
|
12616 |
-
$htaccess_rules = file_get_contents(
|
12617 |
|
12618 |
-
$
|
12619 |
-
$
|
12620 |
-
$
|
12621 |
-
$
|
12622 |
-
$template_variables['HTAccess.Message'] .= 'HTAccess file found in this path <code>'.$htaccess_path.'</code>';
|
12623 |
|
12624 |
-
if (
|
12625 |
-
$
|
12626 |
-
$template_variables['HTAccess.Message'] .= '</p><p>The HTAccess file found is completely empty.';
|
12627 |
-
}
|
12628 |
-
if ( sucuriscan_htaccess_is_standard( $htaccess_rules ) ) {
|
12629 |
-
$template_variables['HTAccess.Message'] .= '</p><p>
|
12630 |
-
The main <code>.htaccess</code> file in your site has the standard rules for a WordPress installation. You can customize it to improve the
|
12631 |
-
performance and change the behaviour of the redirections for pages and posts in your site. To get more information visit the official documentation at
|
12632 |
-
<a href="http://codex.wordpress.org/Using_Permalinks#Creating_and_editing_.28.htaccess.29" target="_blank">Codex WordPrexx - Creating and editing (.htaccess)</a>';
|
12633 |
}
|
12634 |
} else {
|
12635 |
-
$
|
12636 |
-
$template_variables['HTAccess.MessageType'] = 'error';
|
12637 |
-
$template_variables['HTAccess.MessageVisible'] = 'visible';
|
12638 |
}
|
12639 |
|
12640 |
-
return SucuriScanTemplate::
|
12641 |
}
|
12642 |
|
12643 |
/**
|
12644 |
-
* Check
|
12645 |
-
*
|
|
|
|
|
|
|
12646 |
*
|
12647 |
-
* @param string $rules
|
12648 |
-
* @return boolean
|
12649 |
*/
|
12650 |
-
function sucuriscan_htaccess_is_standard(
|
12651 |
-
|
|
|
|
|
12652 |
$htaccess_path = SucuriScan::get_htaccess_path();
|
12653 |
-
$rules = $htaccess_path ? file_get_contents( $htaccess_path ) : '';
|
12654 |
-
}
|
12655 |
-
|
12656 |
-
if ( ! empty($rules) ) {
|
12657 |
-
$standard_lines = array(
|
12658 |
-
'# BEGIN WordPress',
|
12659 |
-
'<IfModule mod_rewrite\.c>',
|
12660 |
-
'RewriteEngine On',
|
12661 |
-
'RewriteBase \/',
|
12662 |
-
'RewriteRule .index.\.php. - \[L\]',
|
12663 |
-
'RewriteCond %\{REQUEST_FILENAME\} \!-f',
|
12664 |
-
'RewriteCond %\{REQUEST_FILENAME\} \!-d',
|
12665 |
-
'RewriteRule \. \/index\.php \[L\]',
|
12666 |
-
'<\/IfModule>',
|
12667 |
-
'# END WordPress',
|
12668 |
-
);
|
12669 |
-
$pattern = '';
|
12670 |
-
$standard_lines_total = count( $standard_lines );
|
12671 |
-
foreach ( $standard_lines as $i => $line ) {
|
12672 |
-
if ( $i < ($standard_lines_total -1) ) {
|
12673 |
-
$end_of_line = "\n";
|
12674 |
-
} else {
|
12675 |
-
$end_of_line = '';
|
12676 |
-
}
|
12677 |
-
$pattern .= sprintf( '%s%s', $line, $end_of_line );
|
12678 |
-
}
|
12679 |
|
12680 |
-
if (
|
12681 |
-
|
12682 |
}
|
12683 |
}
|
12684 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
12685 |
return false;
|
12686 |
}
|
12687 |
|
@@ -12692,65 +13443,64 @@ function sucuriscan_htaccess_is_standard( $rules = false ){
|
|
12692 |
*
|
12693 |
* @return string The HTML code displaying the constants and variables found in the wp-config file.
|
12694 |
*/
|
12695 |
-
function sucuriscan_infosys_wpconfig()
|
12696 |
-
|
|
|
12697 |
'WordpressConfig.Rules' => '',
|
12698 |
'WordpressConfig.Total' => 0,
|
12699 |
);
|
12700 |
|
12701 |
-
$ignore_wp_rules = array(
|
12702 |
$wp_config_path = SucuriScan::get_wpconfig_path();
|
12703 |
|
12704 |
-
if (
|
12705 |
$wp_config_rules = array();
|
12706 |
-
$wp_config_content = SucuriScanFileInfo::file_lines(
|
12707 |
|
12708 |
// Parse the main configuration file and look for constants and global variables.
|
12709 |
-
foreach (
|
12710 |
-
if (
|
12711 |
-
|
12712 |
-
|
12713 |
-
} elseif ( preg_match( '/define\(/', $line ) ) {
|
12714 |
// Detect PHP constants even if the line if indented.
|
12715 |
-
$line = preg_replace(
|
12716 |
-
$line_parts = explode(
|
12717 |
-
} elseif (
|
12718 |
// Detect global variables like the database table prefix.
|
12719 |
-
$line = preg_replace(
|
12720 |
-
$line_parts = explode(
|
12721 |
} else {
|
12722 |
-
|
12723 |
-
continue;
|
12724 |
}
|
12725 |
|
12726 |
// Clean and append the rule to the wp_config_rules variable.
|
12727 |
-
if (
|
12728 |
$key_name = '';
|
12729 |
$key_value = '';
|
12730 |
|
12731 |
// TODO: A foreach loop is not really necessary, find a better way.
|
12732 |
-
foreach (
|
12733 |
-
$line_part = trim(
|
12734 |
-
$line_part = ltrim(
|
12735 |
-
$line_part = rtrim(
|
12736 |
|
12737 |
// Remove single/double quotes at the beginning and end of the string.
|
12738 |
-
$line_part = ltrim(
|
12739 |
-
$line_part = rtrim(
|
12740 |
-
$line_part = ltrim(
|
12741 |
-
$line_part = rtrim(
|
12742 |
|
12743 |
// Assign the clean strings to specific variables.
|
12744 |
-
if (
|
12745 |
$key_name = $line_part;
|
12746 |
}
|
12747 |
|
12748 |
-
if (
|
12749 |
-
if (
|
12750 |
-
$key_value = constant(
|
12751 |
|
12752 |
-
if (
|
12753 |
-
$key_value = (
|
12754 |
}
|
12755 |
} else {
|
12756 |
$key_value = $line_part;
|
@@ -12759,40 +13509,43 @@ function sucuriscan_infosys_wpconfig(){
|
|
12759 |
}
|
12760 |
|
12761 |
// Remove the value of sensitive variables like the database password.
|
12762 |
-
if (
|
12763 |
$key_value = 'hidden';
|
12764 |
}
|
12765 |
|
12766 |
// Append the value to the configuration rules.
|
12767 |
-
$wp_config_rules[
|
12768 |
}
|
12769 |
}
|
12770 |
|
12771 |
// Pass the WordPress configuration rules to the template and show them.
|
12772 |
$counter = 0;
|
12773 |
-
foreach (
|
12774 |
-
$css_class = (
|
12775 |
$label_css = 'sucuriscan-monospace';
|
12776 |
|
12777 |
-
if (
|
12778 |
$var_value = 'empty';
|
12779 |
$label_css = 'sucuriscan-label-default';
|
12780 |
-
} elseif (
|
12781 |
$label_css = 'sucuriscan-label-info';
|
12782 |
}
|
12783 |
|
12784 |
-
$
|
12785 |
-
$
|
12786 |
-
'
|
12787 |
-
|
12788 |
-
|
12789 |
-
|
12790 |
-
|
12791 |
-
|
|
|
|
|
|
|
12792 |
}
|
12793 |
}
|
12794 |
|
12795 |
-
return SucuriScanTemplate::
|
12796 |
}
|
12797 |
|
12798 |
/**
|
@@ -12800,8 +13553,9 @@ function sucuriscan_infosys_wpconfig(){
|
|
12800 |
*
|
12801 |
* @return array A list of pseudo-variables and values that will replace them in the HTML template.
|
12802 |
*/
|
12803 |
-
function sucuriscan_show_cronjobs()
|
12804 |
-
|
|
|
12805 |
'Cronjobs.List' => '',
|
12806 |
'Cronjobs.Total' => 0,
|
12807 |
);
|
@@ -12810,27 +13564,30 @@ function sucuriscan_show_cronjobs(){
|
|
12810 |
$schedules = wp_get_schedules();
|
12811 |
$counter = 0;
|
12812 |
|
12813 |
-
foreach (
|
12814 |
-
foreach (
|
12815 |
-
foreach (
|
12816 |
-
if (
|
12817 |
-
$event['args'] = array(
|
12818 |
}
|
12819 |
|
12820 |
-
$
|
12821 |
-
$
|
12822 |
-
'
|
12823 |
-
|
12824 |
-
|
12825 |
-
|
12826 |
-
|
12827 |
-
|
12828 |
-
|
|
|
|
|
|
|
12829 |
}
|
12830 |
}
|
12831 |
}
|
12832 |
|
12833 |
-
return SucuriScanTemplate::
|
12834 |
}
|
12835 |
|
12836 |
/**
|
@@ -12841,64 +13598,60 @@ function sucuriscan_show_cronjobs(){
|
|
12841 |
* @param boolean $page_nonce True if the nonce is valid, False otherwise.
|
12842 |
* @return void
|
12843 |
*/
|
12844 |
-
function sucuriscan_infosys_form_submissions()
|
12845 |
-
|
|
|
12846 |
// Modify the scheduled tasks (run now, remove, re-schedule).
|
12847 |
$allowed_actions = '(runnow|hourly|twicedaily|daily|remove)';
|
12848 |
|
12849 |
-
if (
|
12850 |
-
$cronjobs = SucuriScanRequest::post(
|
12851 |
|
12852 |
-
if (
|
12853 |
-
$total_tasks = count(
|
12854 |
|
12855 |
// Force execution of the selected scheduled tasks.
|
12856 |
-
if (
|
12857 |
-
SucuriScanInterface::info(
|
12858 |
-
SucuriScanEvent::report_notice_event(
|
12859 |
'Force execution of scheduled tasks: (multiple entries): %s',
|
12860 |
-
@implode(
|
12861 |
-
)
|
12862 |
|
12863 |
-
foreach (
|
12864 |
-
wp_schedule_single_event(
|
12865 |
}
|
12866 |
-
}
|
12867 |
-
|
12868 |
-
|
12869 |
-
|
12870 |
-
SucuriScanInterface::info( $total_tasks . ' scheduled tasks were removed.' );
|
12871 |
-
SucuriScanEvent::report_notice_event( sprintf(
|
12872 |
'Delete scheduled tasks: (multiple entries): %s',
|
12873 |
-
@implode(
|
12874 |
-
)
|
12875 |
|
12876 |
-
foreach (
|
12877 |
-
wp_clear_scheduled_hook(
|
12878 |
}
|
12879 |
-
}
|
12880 |
-
|
12881 |
-
// Re-schedule the selected scheduled tasks.
|
12882 |
-
elseif (
|
12883 |
-
$cronjob_action == 'hourly'
|
12884 |
|| $cronjob_action == 'twicedaily'
|
12885 |
|| $cronjob_action == 'daily'
|
12886 |
) {
|
12887 |
-
SucuriScanInterface::info(
|
12888 |
-
SucuriScanEvent::report_notice_event(
|
12889 |
'Re-configure scheduled tasks %s: (multiple entries): %s',
|
12890 |
$cronjob_action,
|
12891 |
-
@implode(
|
12892 |
-
)
|
12893 |
|
12894 |
-
foreach (
|
12895 |
-
wp_clear_scheduled_hook(
|
12896 |
-
$next_due = wp_next_scheduled(
|
12897 |
-
wp_schedule_event(
|
12898 |
}
|
12899 |
}
|
12900 |
} else {
|
12901 |
-
SucuriScanInterface::error(
|
12902 |
}
|
12903 |
}
|
12904 |
}
|
@@ -12909,8 +13662,9 @@ function sucuriscan_infosys_form_submissions(){
|
|
12909 |
*
|
12910 |
* @return array A list of pseudo-variables and values that will replace them in the HTML template.
|
12911 |
*/
|
12912 |
-
function sucuriscan_infosys_errorlogs()
|
12913 |
-
|
|
|
12914 |
'ErrorLog.Path' => '',
|
12915 |
'ErrorLog.Exists' => 'No',
|
12916 |
'ErrorLog.NoItemsVisibility' => 'hidden',
|
@@ -12922,52 +13676,55 @@ function sucuriscan_infosys_errorlogs(){
|
|
12922 |
);
|
12923 |
|
12924 |
$error_log_path = false;
|
12925 |
-
$log_filename = SucuriScan::ini_get(
|
12926 |
-
$errorlogs_limit = SucuriScanOption::get_option(
|
12927 |
-
$
|
12928 |
-
$
|
12929 |
-
|
12930 |
-
if (
|
12931 |
-
$error_log_path = @realpath(
|
12932 |
-
}
|
12933 |
-
|
12934 |
-
if (
|
12935 |
-
$
|
12936 |
-
}
|
12937 |
-
|
12938 |
-
if (
|
12939 |
-
$
|
12940 |
-
$
|
12941 |
-
$
|
12942 |
-
|
12943 |
-
$last_lines = SucuriScanFileInfo::tail_file(
|
12944 |
-
$error_logs = SucuriScanFSScanner::parse_error_logs(
|
12945 |
-
$error_logs = array_reverse(
|
12946 |
-
$
|
12947 |
-
|
12948 |
-
foreach (
|
12949 |
-
$css_class = ( $
|
12950 |
-
$
|
12951 |
-
'
|
12952 |
-
|
12953 |
-
|
12954 |
-
|
12955 |
-
|
12956 |
-
|
12957 |
-
|
12958 |
-
|
12959 |
-
|
12960 |
-
|
|
|
|
|
|
|
12961 |
}
|
12962 |
|
12963 |
-
if (
|
12964 |
-
$
|
12965 |
}
|
12966 |
} else {
|
12967 |
-
$
|
12968 |
}
|
12969 |
|
12970 |
-
return SucuriScanTemplate::
|
12971 |
}
|
12972 |
|
12973 |
/**
|
@@ -12975,19 +13732,20 @@ function sucuriscan_infosys_errorlogs(){
|
|
12975 |
*
|
12976 |
* @return array A list of pseudo-variables and values that will replace them in the HTML template.
|
12977 |
*/
|
12978 |
-
function sucuriscan_server_info()
|
|
|
12979 |
global $wpdb;
|
12980 |
|
12981 |
-
$
|
12982 |
'ServerInfo.Variables' => '',
|
12983 |
);
|
12984 |
|
12985 |
$info_vars = array(
|
12986 |
'Plugin_version' => SUCURISCAN_VERSION,
|
12987 |
'Plugin_checksum' => SUCURISCAN_PLUGIN_CHECKSUM,
|
12988 |
-
'Last_filesystem_scan' => SucuriScanFSScanner::get_filesystem_runtime(
|
12989 |
'Datetime_and_Timezone' => '',
|
12990 |
-
'Operating_system' => sprintf(
|
12991 |
'Server' => 'Unknown',
|
12992 |
'Developer_mode' => 'OFF',
|
12993 |
'Memory_usage' => 'N/A',
|
@@ -12999,26 +13757,26 @@ function sucuriscan_server_info(){
|
|
12999 |
$info_vars['Datetime_and_Timezone'] = sprintf(
|
13000 |
'%s (GMT %s)',
|
13001 |
SucuriScan::current_datetime(),
|
13002 |
-
get_option(
|
13003 |
);
|
13004 |
|
13005 |
-
if (
|
13006 |
$info_vars['Developer_mode'] = 'ON';
|
13007 |
}
|
13008 |
|
13009 |
-
if (
|
13010 |
-
$info_vars['Memory_usage'] = round(
|
13011 |
}
|
13012 |
|
13013 |
-
if (
|
13014 |
-
$info_vars['Server'] =
|
13015 |
}
|
13016 |
|
13017 |
-
if (
|
13018 |
-
$info_vars['MySQL_version'] = $wpdb->get_var(
|
13019 |
|
13020 |
-
$mysql_info = $wpdb->get_results(
|
13021 |
-
if (
|
13022 |
$info_vars['SQL_mode'] = $mysql_info[0]->Value;
|
13023 |
}
|
13024 |
}
|
@@ -13034,26 +13792,29 @@ function sucuriscan_server_info(){
|
|
13034 |
'max_input_time',
|
13035 |
);
|
13036 |
|
13037 |
-
foreach (
|
13038 |
-
$php_flag_value = SucuriScan::ini_get(
|
13039 |
$php_flag_name = 'PHP_' . $php_flag;
|
13040 |
-
$info_vars[
|
13041 |
}
|
13042 |
|
13043 |
$counter = 0;
|
13044 |
|
13045 |
-
foreach (
|
13046 |
-
$css_class = (
|
13047 |
-
$var_name = str_replace(
|
13048 |
|
13049 |
-
$
|
13050 |
-
'
|
13051 |
-
|
13052 |
-
|
13053 |
-
|
|
|
|
|
|
|
13054 |
$counter += 1;
|
13055 |
}
|
13056 |
|
13057 |
-
return SucuriScanTemplate::
|
13058 |
}
|
13059 |
|
1 |
<?php
|
2 |
/*
|
3 |
Plugin Name: Sucuri Security - Auditing, Malware Scanner and Hardening
|
4 |
+
Plugin URI: https://wordpress.sucuri.net/
|
5 |
+
Description: The <a href="https://sucuri.net/" target="_blank">Sucuri</a> plugin provides the website owner the best Activity Auditing, SiteCheck Remote Malware Scanning, Effective Security Hardening and Post-Hack features. SiteCheck will check for malware, spam, blacklisting and other security issues like .htaccess redirects, hidden eval code, etc. The best thing about it is it's completely free.
|
6 |
Author: Sucuri, INC
|
7 |
+
Version: 1.7.17
|
8 |
+
Author URI: https://sucuri.net
|
9 |
*/
|
10 |
|
11 |
|
42 |
);
|
43 |
|
44 |
// Terminate execution if any of the functions mentioned above is not defined.
|
45 |
+
foreach ($sucuriscan_dependencies as $dependency) {
|
46 |
+
if (!function_exists($dependency)) {
|
47 |
exit(0);
|
48 |
}
|
49 |
}
|
61 |
/**
|
62 |
* Unique name of the plugin through out all the code.
|
63 |
*/
|
64 |
+
define('SUCURISCAN', 'sucuriscan');
|
65 |
|
66 |
/**
|
67 |
* Current version of the plugin's code.
|
68 |
*/
|
69 |
+
define('SUCURISCAN_VERSION', '1.7.17');
|
70 |
|
71 |
/**
|
72 |
* The name of the Sucuri plugin main file.
|
73 |
*/
|
74 |
+
define('SUCURISCAN_PLUGIN_FILE', 'sucuri.php');
|
75 |
|
76 |
/**
|
77 |
* The name of the folder where the plugin's files will be located.
|
78 |
*/
|
79 |
+
define('SUCURISCAN_PLUGIN_FOLDER', 'sucuri-scanner');
|
80 |
|
81 |
/**
|
82 |
* The fullpath where the plugin's files will be located.
|
83 |
*/
|
84 |
+
define('SUCURISCAN_PLUGIN_PATH', WP_PLUGIN_DIR.'/'.SUCURISCAN_PLUGIN_FOLDER);
|
85 |
|
86 |
/**
|
87 |
* The fullpath of the main plugin file.
|
88 |
*/
|
89 |
+
define('SUCURISCAN_PLUGIN_FILEPATH', SUCURISCAN_PLUGIN_PATH.'/'.SUCURISCAN_PLUGIN_FILE);
|
90 |
|
91 |
/**
|
92 |
* The local URL where the plugin's files and assets are served.
|
93 |
*/
|
94 |
+
define('SUCURISCAN_URL', rtrim(plugin_dir_url(SUCURISCAN_PLUGIN_FILEPATH), '/'));
|
95 |
|
96 |
/**
|
97 |
* Checksum of this file to check the integrity of the plugin.
|
98 |
*/
|
99 |
+
define('SUCURISCAN_PLUGIN_CHECKSUM', @md5_file(SUCURISCAN_PLUGIN_FILEPATH));
|
100 |
|
101 |
/**
|
102 |
* Remote URL where the public Sucuri API service is running.
|
103 |
*/
|
104 |
+
define('SUCURISCAN_API', 'https://wordpress.sucuri.net/api/');
|
105 |
|
106 |
/**
|
107 |
* Latest version of the public Sucuri API.
|
108 |
*/
|
109 |
+
define('SUCURISCAN_API_VERSION', 'v1');
|
110 |
|
111 |
/**
|
112 |
* Remote URL where the CloudProxy API service is running.
|
113 |
*/
|
114 |
+
define('SUCURISCAN_CLOUDPROXY_API', 'https://waf.sucuri.net/api');
|
115 |
|
116 |
/**
|
117 |
* Latest version of the CloudProxy API.
|
118 |
*/
|
119 |
+
define('SUCURISCAN_CLOUDPROXY_API_VERSION', 'v2');
|
120 |
|
121 |
/**
|
122 |
* The maximum quantity of entries that will be displayed in the last login page.
|
123 |
*/
|
124 |
+
define('SUCURISCAN_LASTLOGINS_USERSLIMIT', 25);
|
125 |
|
126 |
/**
|
127 |
* The maximum quantity of entries that will be displayed in the audit logs page.
|
128 |
*/
|
129 |
+
define('SUCURISCAN_AUDITLOGS_PER_PAGE', 50);
|
130 |
|
131 |
/**
|
132 |
* The maximum quantity of buttons in the paginations.
|
133 |
*/
|
134 |
+
define('SUCURISCAN_MAX_PAGINATION_BUTTONS', 20);
|
135 |
|
136 |
/**
|
137 |
* The minimum quantity of seconds to wait before each filesystem scan.
|
138 |
*/
|
139 |
+
define('SUCURISCAN_MINIMUM_RUNTIME', 10800);
|
140 |
|
141 |
/**
|
142 |
* The life time of the cache for the results of the SiteCheck scans.
|
143 |
*/
|
144 |
+
define('SUCURISCAN_SITECHECK_LIFETIME', 1200);
|
145 |
|
146 |
/**
|
147 |
* The life time of the cache for the results of the get_plugins function.
|
148 |
*/
|
149 |
+
define('SUCURISCAN_GET_PLUGINS_LIFETIME', 1800);
|
150 |
+
|
151 |
+
/**
|
152 |
+
* The maximum execution time of a HTTP request before timeout.
|
153 |
+
*/
|
154 |
+
define('SUCURISCAN_MAX_REQUEST_TIMEOUT', 15);
|
155 |
|
156 |
/**
|
157 |
* Plugin's global variables.
|
161 |
* conditional will act as a container helping in the readability of the code
|
162 |
* considering the total number of lines that this file will have.
|
163 |
*/
|
164 |
+
if (defined('SUCURISCAN')) {
|
165 |
/**
|
166 |
* Define the prefix for some actions and filters that rely in the
|
167 |
* differentiation of the type of site where the extension is being used. There
|
181 |
$sucuriscan_pages = array(
|
182 |
'sucuriscan' => 'Dashboard',
|
183 |
'sucuriscan_scanner' => 'Malware Scan',
|
184 |
+
'sucuriscan_firewall' => 'Firewall (WAF)',
|
185 |
'sucuriscan_hardening' => 'Hardening',
|
186 |
'sucuriscan_posthack' => 'Post-Hack',
|
187 |
'sucuriscan_lastlogins' => 'Last Logins',
|
202 |
*/
|
203 |
|
204 |
$sucuriscan_notify_options = array(
|
205 |
+
'sucuriscan_notify_plugin_change' => 'Receive email alerts for <b>Sucuri</b> plugin changes',
|
206 |
'sucuriscan_prettify_mails' => 'Receive email alerts in HTML <em>(there may be issues with some mail services)</em>',
|
207 |
'sucuriscan_use_wpmail' => 'Use WordPress functions to send mails <em>(uncheck to use native PHP functions)</em>',
|
208 |
'sucuriscan_lastlogin_redirection' => 'Allow redirection after login to report the last-login information',
|
209 |
'sucuriscan_notify_scan_checksums' => 'Receive email alerts for core integrity checks',
|
210 |
'sucuriscan_notify_user_registration' => 'user:Receive email alerts for new user registration',
|
211 |
'sucuriscan_notify_success_login' => 'user:Receive email alerts for successful login attempts',
|
212 |
+
'sucuriscan_notify_failed_login' => 'user:Receive email alerts for failed login attempts <em>(you may receive tons of emails)</em>',
|
213 |
+
'sucuriscan_notify_bruteforce_attack' => 'user:Receive email alerts for password guessing attacks <em>(summary of failed logins per hour)</em>',
|
214 |
'sucuriscan_notify_post_publication' => 'Receive email alerts for Post-Type changes <em>(configure from Ignore Alerts)</em>',
|
215 |
'sucuriscan_notify_website_updated' => 'Receive email alerts when the WordPress version is updated',
|
216 |
'sucuriscan_notify_settings_updated' => 'Receive email alerts when your website settings are updated',
|
217 |
'sucuriscan_notify_theme_editor' => 'Receive email alerts when a file is modified with theme/plugin editor',
|
218 |
+
'sucuriscan_notify_plugin_installed' => 'plugin:Receive email alerts when a <b>plugin is installed</b>',
|
219 |
+
'sucuriscan_notify_plugin_activated' => 'plugin:Receive email alerts when a <b>plugin is activated</b>',
|
220 |
+
'sucuriscan_notify_plugin_deactivated' => 'plugin:Receive email alerts when a <b>plugin is deactivated</b>',
|
221 |
+
'sucuriscan_notify_plugin_updated' => 'plugin:Receive email alerts when a <b>plugin is updated</b>',
|
222 |
+
'sucuriscan_notify_plugin_deleted' => 'plugin:Receive email alerts when a <b>plugin is deleted</b>',
|
223 |
+
'sucuriscan_notify_widget_added' => 'widget:Receive email alerts when a <b>widget is added</b> to a sidebar',
|
224 |
+
'sucuriscan_notify_widget_deleted' => 'widget:Receive email alerts when a <b>widget is deleted</b> from a sidebar',
|
225 |
+
'sucuriscan_notify_theme_installed' => 'theme:Receive email alerts when a <b>theme is installed</b>',
|
226 |
+
'sucuriscan_notify_theme_activated' => 'theme:Receive email alerts when a <b>theme is activated</b>',
|
227 |
+
'sucuriscan_notify_theme_updated' => 'theme:Receive email alerts when a <b>theme is updated</b>',
|
228 |
+
'sucuriscan_notify_theme_deleted' => 'theme:Receive email alerts when a <b>theme is deleted</b>',
|
229 |
);
|
230 |
|
231 |
$sucuriscan_schedule_allowed = array(
|
280 |
/**
|
281 |
* Remove the WordPress generator meta-tag from the source code.
|
282 |
*/
|
283 |
+
remove_action('wp_head', 'wp_generator');
|
284 |
|
285 |
/**
|
286 |
* Run a specific function defined in the plugin's code to locate every
|
288 |
* information to the Sucuri API service where a security and integrity scan
|
289 |
* will be performed against the hashes provided and the official versions.
|
290 |
*/
|
291 |
+
add_action('sucuriscan_scheduled_scan', 'SucuriScan::run_scheduled_task');
|
292 |
|
293 |
/**
|
294 |
* Initialize the execute of the main plugin's functions.
|
296 |
* This will load the menu options in the WordPress administrator panel, and
|
297 |
* execute the bootstrap function of the plugin.
|
298 |
*/
|
299 |
+
add_action('init', 'SucuriScanInterface::initialize', 1);
|
300 |
+
add_action('admin_init', 'SucuriScanInterface::create_datastore_folder');
|
301 |
+
add_action('admin_init', 'SucuriScanInterface::handle_old_plugins');
|
302 |
+
add_action('admin_enqueue_scripts', 'SucuriScanInterface::enqueue_scripts', 1);
|
303 |
|
304 |
/**
|
305 |
* Display extension menu and submenu items in the correct interface. For single
|
307 |
* multisite installations the menu items must be available only in the network
|
308 |
* panel and hidden in the administration panel of the subsites.
|
309 |
*/
|
310 |
+
add_action($sucuriscan_action_prefix . 'admin_menu', 'SucuriScanInterface::add_interface_menu');
|
311 |
|
312 |
/**
|
313 |
* Attach Ajax requests to a custom page handler.
|
314 |
*/
|
315 |
+
foreach ($sucuriscan_pages as $page_func => $page_title) {
|
316 |
$ajax_func = $page_func . '_ajax';
|
317 |
|
318 |
+
if (function_exists($ajax_func)) {
|
319 |
+
add_action('wp_ajax_' . $ajax_func, $ajax_func);
|
320 |
}
|
321 |
}
|
322 |
|
330 |
*
|
331 |
* @see Class SucuriScanHook
|
332 |
*/
|
333 |
+
if (class_exists('SucuriScanHook')) {
|
334 |
$sucuriscan_hooks = array(
|
335 |
'add_attachment',
|
336 |
'add_link',
|
352 |
'xmlrpc_publish_post',
|
353 |
);
|
354 |
|
355 |
+
if (SucuriScanOption::is_enabled(':xhr_monitor')) {
|
356 |
$sucuriscan_hooks[] = 'all';
|
357 |
}
|
358 |
|
359 |
+
foreach ($sucuriscan_hooks as $hook_name) {
|
360 |
$hook_func = 'SucuriScanHook::hook_' . $hook_name;
|
361 |
+
add_action($hook_name, $hook_func, 50, 5);
|
362 |
}
|
363 |
|
364 |
+
add_action('admin_init', 'SucuriScanHook::hook_undefined_actions');
|
365 |
+
add_action('login_form', 'SucuriScanHook::hook_undefined_actions');
|
366 |
} else {
|
367 |
+
SucuriScanInterface::error('Function call interceptors are not working properly.');
|
368 |
}
|
369 |
|
370 |
/**
|
376 |
* the plugin to execute the filesystem scans, the project integrity, and the
|
377 |
* email notifications.
|
378 |
*/
|
379 |
+
add_action($sucuriscan_action_prefix . 'admin_notices', 'SucuriScanInterface::setup_notice');
|
380 |
|
381 |
/**
|
382 |
* Heartbeat API
|
387 |
* cases it may improve the performance of the site by reducing the quantity of
|
388 |
* requests sent to the server per session.
|
389 |
*/
|
390 |
+
add_filter('init', 'SucuriScanHeartbeat::register_script', 1);
|
391 |
+
add_filter('heartbeat_settings', 'SucuriScanHeartbeat::update_settings');
|
392 |
+
add_filter('heartbeat_send', 'SucuriScanHeartbeat::respond_to_send', 10, 3);
|
393 |
+
add_filter('heartbeat_received', 'SucuriScanHeartbeat::respond_to_received', 10, 3);
|
394 |
+
add_filter('heartbeat_nopriv_send', 'SucuriScanHeartbeat::respond_to_send', 10, 3);
|
395 |
+
add_filter('heartbeat_nopriv_received', 'SucuriScanHeartbeat::respond_to_received', 10, 3);
|
396 |
}
|
397 |
|
398 |
/**
|
402 |
* other libraries extending from this and functions defined in other files, be
|
403 |
* aware of the hierarchy and check the other libraries for duplicated methods.
|
404 |
*/
|
405 |
+
class SucuriScan
|
406 |
+
{
|
407 |
/**
|
408 |
* Class constructor.
|
409 |
*/
|
410 |
+
public function __construct()
|
411 |
+
{
|
412 |
}
|
413 |
|
414 |
/**
|
422 |
* @param string $var_name Name of a variable with an optional colon at the beginning.
|
423 |
* @return string Full name of the variable with the extra characters (if needed).
|
424 |
*/
|
425 |
+
public static function variable_prefix($var_name = '')
|
426 |
+
{
|
427 |
+
if (!empty($var_name) && $var_name[0] === ':') {
|
428 |
+
$var_name = sprintf(
|
429 |
+
'%s_%s',
|
430 |
+
SUCURISCAN,
|
431 |
+
substr($var_name, 1)
|
432 |
+
);
|
433 |
}
|
434 |
|
435 |
return $var_name;
|
441 |
* @param string $property The configuration option name.
|
442 |
* @return string Value of the configuration option as a string on success.
|
443 |
*/
|
444 |
+
public static function ini_get($property = '')
|
445 |
+
{
|
446 |
+
$ini_value = ini_get($property);
|
447 |
+
$default = array(
|
448 |
+
'error_log' => 'error_log',
|
449 |
+
'safe_mode' => 'Off',
|
450 |
+
'memory_limit' => '128M',
|
451 |
+
'upload_max_filesize' => '2M',
|
452 |
+
'post_max_size' => '8M',
|
453 |
+
'max_execution_time' => '30',
|
454 |
+
'max_input_time' => '-1',
|
455 |
+
);
|
456 |
|
457 |
+
if ($ini_value === false) {
|
458 |
$ini_value = 'Undefined';
|
459 |
+
} elseif (empty($ini_value) || $ini_value === null) {
|
460 |
+
if (array_key_exists($property, $default)) {
|
461 |
+
$ini_value = $default[$property];
|
462 |
+
} else {
|
463 |
+
$ini_value = 'Off';
|
|
|
|
|
|
|
|
|
|
|
|
|
464 |
}
|
465 |
}
|
466 |
|
467 |
+
if ($property == 'error_log') {
|
468 |
+
$ini_value = basename($ini_value);
|
469 |
}
|
470 |
|
471 |
return $ini_value;
|
478 |
* @param string $text The text which is to be encoded.
|
479 |
* @return string The encoded text with HTML entities.
|
480 |
*/
|
481 |
+
public static function escape($text = '')
|
482 |
+
{
|
483 |
// Escape the value of the variable using a built-in function if possible.
|
484 |
+
if (function_exists('esc_attr')) {
|
485 |
+
$text = esc_attr($text);
|
486 |
} else {
|
487 |
+
$text = htmlspecialchars($text);
|
488 |
}
|
489 |
|
490 |
return $text;
|
496 |
* @param integer $length Length of the string that will be generated.
|
497 |
* @return string The random string generated.
|
498 |
*/
|
499 |
+
public static function random_char($length = 4)
|
500 |
+
{
|
501 |
$string = '';
|
502 |
+
$offset = 25;
|
503 |
+
$chars = array(
|
504 |
+
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
|
505 |
+
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
|
506 |
+
);
|
507 |
|
508 |
+
for ($i = 0; $i < $length; $i++) {
|
509 |
+
$index = rand(0, $offset);
|
510 |
+
$string .= $chars[$index];
|
511 |
}
|
512 |
|
513 |
return $string;
|
517 |
* Translate a given number in bytes to a human readable file size using the
|
518 |
* a approximate value in Kylo, Mega, Giga, etc.
|
519 |
*
|
520 |
+
* @link https://www.php.net/manual/en/function.filesize.php#106569
|
521 |
* @param integer $bytes An integer representing a file size in bytes.
|
522 |
* @param integer $decimals How many decimals should be returned after the translation.
|
523 |
* @return string Human readable representation of the given number in Kylo, Mega, Giga, etc.
|
524 |
*/
|
525 |
+
public static function human_filesize($bytes = 0, $decimals = 2)
|
526 |
+
{
|
527 |
$sz = 'BKMGTP';
|
528 |
+
$factor = floor((strlen($bytes) - 1) / 3);
|
529 |
+
return sprintf("%.{$decimals}f", $bytes / pow(1024, $factor)) . @$sz[ $factor ];
|
530 |
}
|
531 |
|
532 |
/**
|
536 |
* @param string $path The relative path that needs to be completed to get the absolute path.
|
537 |
* @return string The full filesystem path including the directory specified.
|
538 |
*/
|
539 |
+
public static function datastore_folder_path($path = '')
|
540 |
+
{
|
541 |
+
$default_dir = 'sucuri';
|
542 |
+
$datastore = SucuriScanOption::get_option(':datastore_path');
|
543 |
|
544 |
// Use the uploads folder by default.
|
545 |
+
if (empty($datastore)) {
|
546 |
$uploads_path = false;
|
547 |
|
548 |
// Multisite installations may have different paths.
|
549 |
+
if (function_exists('wp_upload_dir')) {
|
550 |
$upload_dir = wp_upload_dir();
|
551 |
|
552 |
+
if (isset($upload_dir['basedir'])) {
|
553 |
+
$uploads_path = rtrim($upload_dir['basedir'], '/');
|
554 |
}
|
555 |
}
|
556 |
|
557 |
+
if ($uploads_path === false) {
|
558 |
+
if (defined('WP_CONTENT_DIR')) {
|
559 |
+
$uploads_path = WP_CONTENT_DIR . '/uploads';
|
560 |
} else {
|
561 |
+
$uploads_path = ABSPATH . '/wp-content/uploads';
|
562 |
}
|
563 |
}
|
564 |
|
565 |
+
$datastore = $uploads_path . '/' . $default_dir;
|
566 |
+
SucuriScanOption::update_option(':datastore_path', $datastore);
|
567 |
}
|
568 |
|
569 |
+
return $datastore . '/' . $path;
|
|
|
|
|
570 |
}
|
571 |
|
572 |
/**
|
574 |
*
|
575 |
* @return boolean Either TRUE or FALSE in case WordPress is being used as a multi-site instance.
|
576 |
*/
|
577 |
+
public static function is_multisite()
|
578 |
+
{
|
579 |
+
return (bool) (function_exists('is_multisite') && is_multisite());
|
580 |
+
}
|
|
|
|
|
|
|
581 |
|
582 |
+
public static function admin_url($url = '')
|
583 |
+
{
|
584 |
+
if (self::is_multisite()) {
|
585 |
+
return network_admin_url($url);
|
586 |
+
} else {
|
587 |
+
return admin_url($url);
|
588 |
+
}
|
589 |
}
|
590 |
|
591 |
/**
|
593 |
*
|
594 |
* @return string The version number of Wordpress installed.
|
595 |
*/
|
596 |
+
public static function site_version()
|
597 |
+
{
|
598 |
global $wp_version;
|
599 |
|
600 |
+
if ($wp_version === null) {
|
601 |
$wp_version_path = ABSPATH . WPINC . '/version.php';
|
602 |
|
603 |
+
if (file_exists($wp_version_path)) {
|
604 |
include($wp_version_path);
|
605 |
$wp_version = isset($wp_version) ? $wp_version : '0.0';
|
606 |
} else {
|
607 |
+
$option_version = get_option('version');
|
608 |
$wp_version = $option_version ? $option_version : '0.0';
|
609 |
}
|
610 |
}
|
611 |
|
612 |
+
$wp_version = self::escape($wp_version);
|
613 |
|
614 |
return $wp_version;
|
615 |
}
|
619 |
*
|
620 |
* @return string Absolute path of the WordPress configuration file.
|
621 |
*/
|
622 |
+
public static function get_wpconfig_path()
|
623 |
+
{
|
624 |
+
if (defined('ABSPATH')) {
|
625 |
$file_path = ABSPATH . '/wp-config.php';
|
626 |
|
627 |
// if wp-config.php doesn't exist, or is not readable check one directory up.
|
628 |
+
if (!file_exists($file_path)) {
|
629 |
$file_path = ABSPATH . '/../wp-config.php';
|
630 |
}
|
631 |
|
632 |
// Remove duplicated double slashes.
|
633 |
+
$file_path = @realpath($file_path);
|
634 |
|
635 |
+
if ($file_path) {
|
636 |
return $file_path;
|
637 |
}
|
638 |
}
|
645 |
*
|
646 |
* @return string Absolute path of the main WordPress htaccess file.
|
647 |
*/
|
648 |
+
public static function get_htaccess_path()
|
649 |
+
{
|
650 |
+
if (defined('ABSPATH')) {
|
651 |
$base_dirs = array(
|
652 |
+
rtrim(ABSPATH, '/'),
|
653 |
+
dirname(ABSPATH),
|
654 |
+
dirname(dirname(ABSPATH)),
|
655 |
);
|
656 |
|
657 |
+
foreach ($base_dirs as $base_dir) {
|
658 |
+
$htaccess_path = sprintf('%s/.htaccess', $base_dir);
|
659 |
|
660 |
+
if (file_exists($htaccess_path)) {
|
661 |
return $htaccess_path;
|
662 |
}
|
663 |
}
|
671 |
*
|
672 |
* @return string Secret key definition pattern.
|
673 |
*/
|
674 |
+
public static function secret_key_pattern()
|
675 |
+
{
|
676 |
return '/define\(\s*\'([A-Z_]+)\',(\s*)\'(.+)\'\s*\);/';
|
677 |
}
|
678 |
|
681 |
*
|
682 |
* @return void
|
683 |
*/
|
684 |
+
public static function run_scheduled_task()
|
685 |
+
{
|
686 |
SucuriScanEvent::filesystem_scan();
|
687 |
+
sucuriscan_core_files_data(true);
|
688 |
+
}
|
689 |
+
|
690 |
+
/**
|
691 |
+
* List of allowed HTTP headers to retrieve the real IP.
|
692 |
+
*
|
693 |
+
* Once the DNS lookups are enabled to discover the real IP address of the
|
694 |
+
* visitors the user may choose the HTTP header that will be used by default to
|
695 |
+
* retrieve the real IP address of each HTTP request, generally they do not need
|
696 |
+
* to set this but in rare cases the hosting provider may have a load balancer
|
697 |
+
* that can interfere in the process, in which case they will have to explicitly
|
698 |
+
* specify the main HTTP header. This is a list of the allowed headers that the
|
699 |
+
* user can choose.
|
700 |
+
*
|
701 |
+
* @param boolean $with_keys Return the array with its values are keys.
|
702 |
+
* @return array Allowed HTTP headers to retrieve real IP.
|
703 |
+
*/
|
704 |
+
public static function allowedHttpHeaders($with_keys = false)
|
705 |
+
{
|
706 |
+
$allowed = array(
|
707 |
+
'HTTP_X_SUCURI_CLIENTIP',
|
708 |
+
'HTTP_X_REAL_IP',
|
709 |
+
'HTTP_CLIENT_IP',
|
710 |
+
'HTTP_X_FORWARDED_FOR',
|
711 |
+
'HTTP_X_FORWARDED',
|
712 |
+
'HTTP_FORWARDED_FOR',
|
713 |
+
'HTTP_FORWARDED',
|
714 |
+
'SUCURI_RIP',
|
715 |
+
'REMOTE_ADDR',
|
716 |
+
);
|
717 |
+
|
718 |
+
if ($with_keys === true) {
|
719 |
+
$verbose = array();
|
720 |
+
|
721 |
+
foreach ($allowed as $header) {
|
722 |
+
$verbose[$header] = $header;
|
723 |
+
}
|
724 |
+
|
725 |
+
return $verbose;
|
726 |
+
}
|
727 |
+
|
728 |
+
return $allowed;
|
729 |
+
}
|
730 |
+
|
731 |
+
/**
|
732 |
+
* List HTTP headers ordered.
|
733 |
+
*
|
734 |
+
* The list of HTTP headers is ordered per relevancy, and having the main HTTP
|
735 |
+
* header as the first entry, this guarantees that the IP address of the
|
736 |
+
* visitors will be retrieved from the HTTP header chosen by the user first and
|
737 |
+
* fallback to the other alternatives if available.
|
738 |
+
*
|
739 |
+
* @return array Ordered allowed HTTP headers.
|
740 |
+
*/
|
741 |
+
private static function orderedHttpHeaders()
|
742 |
+
{
|
743 |
+
$ordered = array();
|
744 |
+
$allowed = self::allowedHttpHeaders();
|
745 |
+
$addr_header = SucuriScanOption::get_option(':addr_header');
|
746 |
+
$ordered[] = $addr_header;
|
747 |
+
|
748 |
+
foreach ($allowed as $header) {
|
749 |
+
if (!in_array($header, $ordered)) {
|
750 |
+
$ordered[] = $header;
|
751 |
+
}
|
752 |
+
}
|
753 |
+
|
754 |
+
return $ordered;
|
755 |
}
|
756 |
|
757 |
/**
|
758 |
* Retrieve the real ip address of the user in the current request.
|
759 |
*
|
760 |
+
* @param boolean $with_header Return HTTP header where the IP address was found.
|
761 |
+
* @return string Real IP address of the user in the current request.
|
762 |
*/
|
763 |
+
public static function get_remote_addr($with_header = false)
|
764 |
+
{
|
765 |
+
$remote_addr = false;
|
766 |
$header_used = 'unknown';
|
767 |
+
$headers = self::orderedHttpHeaders();
|
768 |
|
769 |
+
foreach ($headers as $header) {
|
770 |
+
if (array_key_exists($header, $_SERVER)
|
771 |
+
&& self::is_valid_ip($_SERVER[$header])
|
772 |
+
) {
|
773 |
+
$remote_addr = $_SERVER[$header];
|
774 |
+
$header_used = $header;
|
775 |
+
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
776 |
}
|
|
|
|
|
|
|
777 |
}
|
778 |
|
779 |
+
if (!$remote_addr || $remote_addr === '::1') {
|
780 |
$remote_addr = '127.0.0.1';
|
781 |
}
|
782 |
|
783 |
+
if ($with_header) {
|
784 |
return $header_used;
|
785 |
}
|
786 |
|
792 |
*
|
793 |
* @return string The HTTP header used to retrieve the remote address.
|
794 |
*/
|
795 |
+
public static function get_remote_addr_header()
|
796 |
+
{
|
797 |
+
return self::get_remote_addr(true);
|
798 |
}
|
799 |
|
800 |
/**
|
802 |
*
|
803 |
* @return string The user-agent from the current request.
|
804 |
*/
|
805 |
+
public static function get_user_agent()
|
806 |
+
{
|
807 |
+
if (isset($_SERVER['HTTP_USER_AGENT'])) {
|
808 |
+
return self::escape($_SERVER['HTTP_USER_AGENT']);
|
809 |
}
|
810 |
|
811 |
return false;
|
816 |
*
|
817 |
* @return string The domain of the current site.
|
818 |
*/
|
819 |
+
public static function get_domain($return_tld = false)
|
820 |
+
{
|
821 |
+
if (function_exists('get_site_url')) {
|
822 |
$site_url = get_site_url();
|
823 |
$pattern = '/([fhtps]+:\/\/)?([^:\/]+)(:[0-9:]+)?(\/.*)?/';
|
824 |
$replacement = ( $return_tld === true ) ? '$2' : '$2$3$4';
|
825 |
+
$domain_name = @preg_replace($pattern, $replacement, $site_url);
|
826 |
|
827 |
return $domain_name;
|
828 |
}
|
835 |
*
|
836 |
* @return string Top-level domain (TLD) of the website.
|
837 |
*/
|
838 |
+
public static function get_top_level_domain()
|
839 |
+
{
|
840 |
+
return self::get_domain(true);
|
841 |
}
|
842 |
|
843 |
/**
|
845 |
*
|
846 |
* @return boolean TRUE if reverse proxies must be supported, FALSE otherwise.
|
847 |
*/
|
848 |
+
public static function support_reverse_proxy()
|
849 |
+
{
|
850 |
+
return SucuriScanOption::is_enabled(':revproxy');
|
851 |
}
|
852 |
|
853 |
/**
|
861 |
*
|
862 |
* @return boolean True if the DNS lookups should be executed, false otherwise.
|
863 |
*/
|
864 |
+
public static function execute_dns_lookups()
|
865 |
+
{
|
866 |
+
if (( defined('NOT_USING_CLOUDPROXY') && NOT_USING_CLOUDPROXY === true )
|
867 |
+
|| SucuriScanOption::is_disabled(':dns_lookups')
|
868 |
) {
|
869 |
return false;
|
870 |
}
|
878 |
* @param boolean $verbose Return an array with the hostname, address, and status, or not.
|
879 |
* @return boolean Either TRUE or FALSE if the site is behind CloudProxy.
|
880 |
*/
|
881 |
+
public static function is_behind_cloudproxy($verbose = false)
|
882 |
+
{
|
883 |
$http_host = self::get_top_level_domain();
|
884 |
|
885 |
+
if (self::execute_dns_lookups()) {
|
886 |
+
$host_by_addr = @gethostbyname($http_host);
|
887 |
+
$host_by_name = @gethostbyaddr($host_by_addr);
|
888 |
+
$status = (bool) preg_match('/^cloudproxy[0-9]+\.sucuri\.net$/', $host_by_name);
|
889 |
} else {
|
890 |
$status = false;
|
891 |
$host_by_addr = '::1';
|
897 |
* the site as protected by a firewall. A fake key can be used to bypass the DNS
|
898 |
* checking, but that is not something that will affect us, only the client.
|
899 |
*/
|
900 |
+
if ($status === false
|
901 |
+
&& SucuriScanAPI::getCloudproxyKey()
|
|
|
902 |
) {
|
903 |
$status = true;
|
904 |
}
|
905 |
|
906 |
+
if ($verbose) {
|
907 |
return array(
|
908 |
'http_host' => $http_host,
|
909 |
'host_name' => $host_by_name,
|
922 |
*
|
923 |
* @return string The administrator email address.
|
924 |
*/
|
925 |
+
public static function get_site_email()
|
926 |
+
{
|
927 |
+
$email = get_option('admin_email');
|
928 |
|
929 |
+
if (self::is_valid_email($email)) {
|
930 |
return $email;
|
931 |
}
|
932 |
|
939 |
* @param integer $identifier User account identifier.
|
940 |
* @return object WordPress user object with data.
|
941 |
*/
|
942 |
+
public static function get_user_by_id($identifier = 0)
|
943 |
+
{
|
944 |
+
if (function_exists('get_user_by')) {
|
945 |
+
$user = get_user_by('id', $identifier);
|
946 |
|
947 |
+
if ($user instanceof WP_User) {
|
948 |
return $user;
|
949 |
}
|
950 |
}
|
957 |
*
|
958 |
* @return array List of admin users, false otherwise.
|
959 |
*/
|
960 |
+
public static function get_admin_users()
|
961 |
+
{
|
962 |
+
if (function_exists('get_users')) {
|
963 |
$args = array( 'role' => 'administrator' );
|
964 |
|
965 |
+
return get_users($args);
|
966 |
}
|
967 |
|
968 |
return false;
|
978 |
*
|
979 |
* @return array List of user identifiers and email addresses.
|
980 |
*/
|
981 |
+
public static function get_users_for_api_key()
|
982 |
+
{
|
983 |
$valid_users = array();
|
984 |
$users = self::get_admin_users();
|
985 |
|
986 |
+
if ($users !== false) {
|
987 |
+
foreach ($users as $user) {
|
988 |
+
if ($user->user_status === '0') {
|
989 |
$valid_users[ $user->ID ] = sprintf(
|
990 |
'%s - %s',
|
991 |
$user->user_login,
|
1003 |
*
|
1004 |
* @return integer Return current Unix timestamp.
|
1005 |
*/
|
1006 |
+
public static function local_time()
|
1007 |
+
{
|
1008 |
+
if (function_exists('current_time')) {
|
1009 |
+
return current_time('timestamp');
|
1010 |
} else {
|
1011 |
return time();
|
1012 |
}
|
1022 |
* @param integer $timestamp Unix timestamp.
|
1023 |
* @return string The date, translated if locale specifies it.
|
1024 |
*/
|
1025 |
+
public static function datetime($timestamp = null)
|
1026 |
+
{
|
1027 |
$date_format = get_option('date_format');
|
1028 |
$time_format = get_option('time_format');
|
1029 |
$tz_format = sprintf('%s %s', $date_format, $time_format);
|
1040 |
*
|
1041 |
* @return string The date, translated if locale specifies it.
|
1042 |
*/
|
1043 |
+
public static function current_datetime()
|
1044 |
+
{
|
1045 |
return self::datetime();
|
1046 |
}
|
1047 |
|
1051 |
* @param integer $timestamp The Unix time number of the date/time before now.
|
1052 |
* @return string The time passed since the timestamp specified.
|
1053 |
*/
|
1054 |
+
public static function time_ago($timestamp = 0)
|
1055 |
+
{
|
1056 |
+
if (!is_numeric($timestamp)) {
|
1057 |
+
$timestamp = strtotime($timestamp);
|
1058 |
}
|
1059 |
|
1060 |
$local_time = self::local_time();
|
1061 |
+
$diff = abs($local_time - intval($timestamp));
|
1062 |
|
1063 |
+
if ($diff == 0) {
|
1064 |
return 'just now';
|
1065 |
}
|
1066 |
|
1074 |
$diff < 60 => array( 'second', 1, ),
|
1075 |
);
|
1076 |
|
1077 |
+
$value = floor($diff / $intervals[1][1]);
|
1078 |
$time_ago = sprintf(
|
1079 |
'%s %s%s ago',
|
1080 |
$value,
|
1088 |
/**
|
1089 |
* Convert an string of characters into a valid variable name.
|
1090 |
*
|
1091 |
+
* @see https://www.php.net/manual/en/language.variables.basics.php
|
1092 |
*
|
1093 |
* @param string $text A text containing alpha-numeric and special characters.
|
1094 |
* @return string A valid variable name.
|
1095 |
*/
|
1096 |
+
public static function human2var($text = '')
|
1097 |
+
{
|
1098 |
+
$text = strtolower($text);
|
1099 |
$pattern = '/[^a-z0-9_]/';
|
1100 |
+
$var_name = preg_replace($pattern, '_', $text);
|
1101 |
|
1102 |
return $var_name;
|
1103 |
}
|
1108 |
* @param string $data The data that will be checked.
|
1109 |
* @return boolean TRUE if the data was serialized, FALSE otherwise.
|
1110 |
*/
|
1111 |
+
public static function is_serialized($data = '')
|
1112 |
+
{
|
1113 |
+
return ( is_string($data) && preg_match('/^(a|O):[0-9]+:.+/', $data) );
|
1114 |
}
|
1115 |
|
1116 |
/**
|
1119 |
* @param string $remote_addr The host IP address.
|
1120 |
* @return boolean Whether the IP address specified is valid or not.
|
1121 |
*/
|
1122 |
+
public static function is_valid_ip($remote_addr = '')
|
1123 |
+
{
|
1124 |
+
if (function_exists('filter_var')) {
|
1125 |
+
return (bool) filter_var($remote_addr, FILTER_VALIDATE_IP);
|
1126 |
+
} elseif (strlen($remote_addr) >= 7) {
|
1127 |
$pattern = '/^([0-9]{1,3}\.) {3}[0-9]{1,3}$/';
|
1128 |
|
1129 |
+
if (preg_match($pattern, $remote_addr, $match)) {
|
1130 |
+
for ($i = 0; $i < 4; $i++) {
|
1131 |
+
if ($match[ $i ] > 255) {
|
1132 |
return false;
|
1133 |
}
|
1134 |
}
|
1147 |
* @param string $remote_addr The supposed ip address that will be checked.
|
1148 |
* @return boolean Either TRUE or FALSE if the ip address specified is valid or not.
|
1149 |
*/
|
1150 |
+
public static function is_valid_cidr($remote_addr = '')
|
1151 |
+
{
|
1152 |
+
if (preg_match('/^([0-9\.]{7,15})\/(8|16|24)$/', $remote_addr, $match)) {
|
1153 |
+
if (self::is_valid_ip($match[1])) {
|
1154 |
return true;
|
1155 |
}
|
1156 |
}
|
1164 |
* @param string $remote_addr The supposed ip address that will be formatted.
|
1165 |
* @return array Clean address, CIDR range, and CIDR format; FALSE otherwise.
|
1166 |
*/
|
1167 |
+
public static function get_ip_info($remote_addr = '')
|
1168 |
+
{
|
1169 |
+
if ($remote_addr) {
|
1170 |
+
$ip_parts = explode('/', $remote_addr);
|
1171 |
|
1172 |
+
if (array_key_exists(0, $ip_parts)
|
1173 |
+
&& self::is_valid_ip($ip_parts[0])
|
|
|
1174 |
) {
|
1175 |
$addr_info = array();
|
1176 |
$addr_info['remote_addr'] = $ip_parts[0];
|
1191 |
* 5.2.0 if it is not found in the interpreter this function will sue regular
|
1192 |
* expressions to check whether the email address passed is valid or not.
|
1193 |
*
|
1194 |
+
* @see https://www.php.net/manual/en/function.filter-var.php
|
1195 |
*
|
1196 |
* @param string $email The string that will be validated as an email address.
|
1197 |
* @return boolean TRUE if the email address passed to the function is valid, FALSE if not.
|
1198 |
*/
|
1199 |
+
public static function is_valid_email($email = '')
|
1200 |
+
{
|
1201 |
+
if (function_exists('filter_var')) {
|
1202 |
+
return (bool) filter_var($email, FILTER_VALIDATE_EMAIL);
|
1203 |
} else {
|
1204 |
$pattern = '/^([a-z0-9\+_\-]+)(\.[a-z0-9\+_\-]+)*@([a-z0-9\-]+\.)+[a-z]{2,6}$/ix';
|
1205 |
+
return (bool) preg_match($pattern, $email);
|
1206 |
}
|
1207 |
}
|
1208 |
|
1212 |
* @param string $pattern The regular expression to check.
|
1213 |
* @return boolean True if the regular expression is valid, false otherwise.
|
1214 |
*/
|
1215 |
+
public static function is_valid_pattern($pattern = '')
|
1216 |
+
{
|
1217 |
return (bool) (
|
1218 |
+
is_string($pattern)
|
1219 |
+
&& !empty($pattern)
|
1220 |
+
&& @preg_match($pattern, null) !== false
|
1221 |
);
|
1222 |
}
|
1223 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1224 |
/**
|
1225 |
* Cut a long text to the length specified, and append suspensive points at the end.
|
1226 |
*
|
1228 |
* @param integer $length Maximum length of the returned string, default is 10.
|
1229 |
* @return string Short version of the text specified.
|
1230 |
*/
|
1231 |
+
public static function excerpt($text = '', $length = 10)
|
1232 |
+
{
|
1233 |
+
$text_length = strlen($text);
|
1234 |
|
1235 |
+
if ($text_length > $length) {
|
1236 |
+
return substr($text, 0, $length) . '...';
|
1237 |
}
|
1238 |
|
1239 |
return $text;
|
1246 |
* @param integer $length Maximum length of the returned string, default is 10.
|
1247 |
* @return string Short version of the text specified.
|
1248 |
*/
|
1249 |
+
public static function excerpt_rev($text = '', $length = 10)
|
1250 |
+
{
|
1251 |
+
$str_reversed = strrev($text);
|
1252 |
+
$str_excerpt = self::excerpt($str_reversed, $length);
|
1253 |
+
$text_transformed = strrev($str_excerpt);
|
1254 |
|
1255 |
return $text_transformed;
|
1256 |
}
|
1261 |
* @param array $list An array or multidimensional array of different values.
|
1262 |
* @return boolean TRUE if the list is multidimensional, FALSE otherwise.
|
1263 |
*/
|
1264 |
+
public static function is_multi_list($list = array())
|
1265 |
+
{
|
1266 |
+
if (!empty($list)) {
|
1267 |
+
foreach ((array) $list as $item) {
|
1268 |
+
if (is_array($item)) {
|
1269 |
return true;
|
1270 |
}
|
1271 |
}
|
1281 |
* @param array $list The array of strings to implode.
|
1282 |
* @return string String of all the items in the list, with the separator between them.
|
1283 |
*/
|
1284 |
+
public static function implode($separator = '', $list = array())
|
1285 |
+
{
|
1286 |
+
if (self::is_multi_list($list)) {
|
1287 |
$pieces = array();
|
1288 |
|
1289 |
+
foreach ($list as $items) {
|
1290 |
+
$pieces[] = @implode($separator, $items);
|
1291 |
}
|
1292 |
|
1293 |
+
$joined_pieces = '(' . implode('), (', $pieces) . ')';
|
1294 |
|
1295 |
return $joined_pieces;
|
1296 |
} else {
|
1297 |
+
return implode($separator, $list);
|
1298 |
}
|
1299 |
}
|
1300 |
|
1304 |
* @param string $current_page Identifier of the current page.
|
1305 |
* @return boolean TRUE if the current page must not have noticies.
|
1306 |
*/
|
1307 |
+
public static function no_notices_here($current_page = false)
|
1308 |
+
{
|
1309 |
global $sucuriscan_no_notices_in;
|
1310 |
|
1311 |
+
if ($current_page === false) {
|
1312 |
+
$current_page = SucuriScanRequest::get('page');
|
1313 |
}
|
1314 |
|
1315 |
+
if (isset($sucuriscan_no_notices_in)
|
1316 |
+
&& is_array($sucuriscan_no_notices_in)
|
1317 |
+
&& !empty($sucuriscan_no_notices_in)
|
|
|
1318 |
) {
|
1319 |
+
return (bool) in_array($current_page, $sucuriscan_no_notices_in);
|
1320 |
}
|
1321 |
|
1322 |
return false;
|
1327 |
*
|
1328 |
* @return boolean TRUE if the site is running over Nginx, FALSE otherwise.
|
1329 |
*/
|
1330 |
+
public static function is_nginx_server()
|
1331 |
+
{
|
1332 |
+
return (bool) preg_match('/^nginx(\/[0-9\.]+)?$/', @$_SERVER['SERVER_SOFTWARE']);
|
1333 |
}
|
1334 |
|
1335 |
/**
|
1337 |
*
|
1338 |
* @return boolean TRUE if the site is running over Nginx, FALSE otherwise.
|
1339 |
*/
|
1340 |
+
public static function is_iis_server()
|
1341 |
+
{
|
1342 |
+
return (bool) preg_match('/Microsoft-IIS/i', @$_SERVER['SERVER_SOFTWARE']);
|
1343 |
}
|
|
|
1344 |
}
|
1345 |
|
1346 |
/**
|
1351 |
* these methods at most instead of accessing an index in the global PHP
|
1352 |
* variables _POST, _GET, _REQUEST since they may come with insecure data.
|
1353 |
*/
|
1354 |
+
class SucuriScanRequest extends SucuriScan
|
1355 |
+
{
|
1356 |
|
1357 |
/**
|
1358 |
* Returns the value stored in a specific index in the global _GET, _POST or
|
1364 |
* @param string $pattern Optional pattern to match allowed values in the requested key.
|
1365 |
* @return string The value stored in the specified key inside the global _GET variable.
|
1366 |
*/
|
1367 |
+
public static function request($list = array(), $key = '', $pattern = '')
|
1368 |
+
{
|
1369 |
+
$key = self::variable_prefix($key);
|
1370 |
|
1371 |
+
if (is_array($list)
|
1372 |
+
&& is_string($key)
|
|
|
1373 |
&& isset($list[ $key ])
|
1374 |
) {
|
1375 |
// Select the key from the list and escape its content.
|
1376 |
$key_value = $list[ $key ];
|
1377 |
|
1378 |
// Define regular expressions for specific value types.
|
1379 |
+
if ($pattern === '') {
|
1380 |
$pattern = '/.*/';
|
1381 |
} else {
|
1382 |
+
switch ($pattern) {
|
1383 |
+
case '_nonce':
|
1384 |
+
$pattern = '/^[a-z0-9]{10}$/';
|
1385 |
+
break;
|
1386 |
+
case '_page':
|
1387 |
+
$pattern = '/^[a-z_]+$/';
|
1388 |
+
break;
|
1389 |
+
case '_array':
|
1390 |
+
$pattern = '_array';
|
1391 |
+
break;
|
1392 |
+
case '_yyyymmdd':
|
1393 |
+
$pattern = '/^[0-9]{4}(\-[0-9]{2}) {2}$/';
|
1394 |
+
break;
|
1395 |
+
default:
|
1396 |
+
$pattern = '/^'.$pattern.'$/';
|
1397 |
+
break;
|
1398 |
}
|
1399 |
}
|
1400 |
|
1401 |
// If the request data is an array, then only cast the value.
|
1402 |
+
if ($pattern == '_array' && is_array($key_value)) {
|
1403 |
return (array) $key_value;
|
1404 |
}
|
1405 |
|
1406 |
// Check the format of the request data with a regex defined above.
|
1407 |
+
if (@preg_match($pattern, $key_value)) {
|
1408 |
+
return self::escape($key_value);
|
1409 |
}
|
1410 |
}
|
1411 |
|
1420 |
* @param string $pattern Optional pattern to match allowed values in the requested key.
|
1421 |
* @return string The value stored in the specified key inside the global _GET variable.
|
1422 |
*/
|
1423 |
+
public static function get($key = '', $pattern = '')
|
1424 |
+
{
|
1425 |
+
return self::request($_GET, $key, $pattern);
|
1426 |
}
|
1427 |
|
1428 |
/**
|
1433 |
* @param string $pattern Optional pattern to match allowed values in the requested key.
|
1434 |
* @return string The value stored in the specified key inside the global _POST variable.
|
1435 |
*/
|
1436 |
+
public static function post($key = '', $pattern = '')
|
1437 |
+
{
|
1438 |
+
return self::request($_POST, $key, $pattern);
|
1439 |
}
|
1440 |
|
1441 |
/**
|
1446 |
* @param string $pattern Optional pattern to match allowed values in the requested key.
|
1447 |
* @return string The value stored in the specified key inside the global _POST variable.
|
1448 |
*/
|
1449 |
+
public static function get_or_post($key = '', $pattern = '')
|
1450 |
+
{
|
1451 |
+
return self::request($_REQUEST, $key, $pattern);
|
1452 |
}
|
|
|
1453 |
}
|
1454 |
|
1455 |
/**
|
1460 |
* offers a high-level object oriented interface to information for an individual
|
1461 |
* file.
|
1462 |
*/
|
1463 |
+
class SucuriScanFileInfo extends SucuriScan
|
1464 |
+
{
|
1465 |
|
1466 |
/**
|
1467 |
* Define the interface that will be used to execute the file system scans, the
|
1523 |
/**
|
1524 |
* Class constructor.
|
1525 |
*/
|
1526 |
+
public function __construct()
|
1527 |
+
{
|
1528 |
}
|
1529 |
|
1530 |
/**
|
1537 |
* @param boolean $as_array Whether the result of the operation will be returned as an array or string.
|
1538 |
* @return array List of files in the main and subdirectories of the folder specified.
|
1539 |
*/
|
1540 |
+
public function get_directory_tree_md5($directory = '', $as_array = false)
|
1541 |
+
{
|
1542 |
$project_signatures = '';
|
1543 |
+
$abs_path = rtrim(ABSPATH, DIRECTORY_SEPARATOR);
|
1544 |
+
$files = $this->get_directory_tree($directory);
|
1545 |
|
1546 |
+
if ($as_array) {
|
1547 |
$project_signatures = array();
|
1548 |
}
|
1549 |
|
1550 |
+
if ($files) {
|
1551 |
+
sort($files);
|
1552 |
|
1553 |
+
foreach ($files as $filepath) {
|
1554 |
+
$file_checksum = @md5_file($filepath);
|
1555 |
+
$filesize = @filesize($filepath);
|
1556 |
|
1557 |
+
if ($as_array) {
|
1558 |
+
$basename = str_replace($abs_path . DIRECTORY_SEPARATOR, '', $filepath);
|
1559 |
$project_signatures[ $basename ] = array(
|
1560 |
'filepath' => $filepath,
|
1561 |
'checksum' => $file_checksum,
|
1562 |
'filesize' => $filesize,
|
1563 |
+
'created_at' => @filectime($filepath),
|
1564 |
+
'modified_at' => @filemtime($filepath),
|
1565 |
);
|
1566 |
} else {
|
1567 |
+
$filepath = str_replace($abs_path, $abs_path . DIRECTORY_SEPARATOR, $filepath);
|
1568 |
$project_signatures .= sprintf(
|
1569 |
"%s%s%s%s\n",
|
1570 |
$file_checksum,
|
1571 |
$filesize,
|
1572 |
+
chr(32),
|
1573 |
$filepath
|
1574 |
);
|
1575 |
}
|
1587 |
* @param string $directory Parent directory where the filesystem scan will start.
|
1588 |
* @return array List of files in the main and subdirectories of the folder specified.
|
1589 |
*/
|
1590 |
+
public function get_directory_tree($directory = '')
|
1591 |
+
{
|
1592 |
+
if (file_exists($directory) && is_dir($directory)) {
|
1593 |
$tree = array();
|
1594 |
|
1595 |
// Check whether the ignore scanning feature is enabled or not.
|
1596 |
+
if (SucuriScanFSScanner::will_ignore_scanning()) {
|
1597 |
$this->ignored_directories = SucuriScanFSScanner::get_ignored_directories();
|
1598 |
}
|
1599 |
|
1600 |
+
switch ($this->scan_interface) {
|
1601 |
case 'spl':
|
1602 |
+
if ($this->is_spl_available()) {
|
1603 |
+
$tree = $this->get_directory_tree_with_spl($directory);
|
1604 |
} else {
|
1605 |
$this->scan_interface = 'opendir';
|
1606 |
+
SucuriScanOption::update_option(':scan_interface', $this->scan_interface);
|
1607 |
+
$tree = $this->get_directory_tree($directory);
|
1608 |
}
|
1609 |
break;
|
1610 |
|
1611 |
case 'glob':
|
1612 |
+
$tree = $this->get_directory_tree_with_glob($directory);
|
1613 |
break;
|
1614 |
|
1615 |
case 'opendir':
|
1616 |
+
$tree = $this->get_directory_tree_with_opendir($directory);
|
1617 |
break;
|
1618 |
|
1619 |
default:
|
1620 |
$this->scan_interface = 'spl';
|
1621 |
+
$tree = $this->get_directory_tree($directory);
|
1622 |
break;
|
1623 |
}
|
1624 |
|
1635 |
* @param string $directory Directory where the scanner is located at the moment.
|
1636 |
* @return array List of file paths where the file was found.
|
1637 |
*/
|
1638 |
+
public function find_file($filename = '', $directory = null)
|
1639 |
+
{
|
1640 |
$file_paths = array();
|
1641 |
|
1642 |
+
if (is_null($directory)
|
1643 |
+
&& defined('ABSPATH')
|
|
|
1644 |
) {
|
1645 |
$directory = ABSPATH;
|
1646 |
}
|
1647 |
|
1648 |
+
if (is_dir($directory)) {
|
1649 |
+
$dir_tree = $this->get_directory_tree($directory);
|
1650 |
|
1651 |
+
foreach ($dir_tree as $filepath) {
|
1652 |
+
if (stripos($filepath, $filename) !== false) {
|
1653 |
$file_paths[] = $filepath;
|
1654 |
}
|
1655 |
}
|
1663 |
* or not, it is required to have PHP >= 5.1.0. The SplFileObject class offers
|
1664 |
* an object oriented interface for a file.
|
1665 |
*
|
1666 |
+
* @link https://www.php.net/manual/en/class.splfileobject.php
|
1667 |
*
|
1668 |
* @return boolean Whether the PHP class "SplFileObject" is available or not.
|
1669 |
*/
|
1670 |
+
public static function is_spl_available()
|
1671 |
+
{
|
1672 |
+
return (bool) class_exists('SplFileObject');
|
1673 |
}
|
1674 |
|
1675 |
/**
|
1677 |
* of the folder specified. Some folders and files will be ignored depending
|
1678 |
* on some rules defined by the developer.
|
1679 |
*
|
1680 |
+
* @link https://www.php.net/manual/en/class.recursivedirectoryiterator.php
|
1681 |
* @see RecursiveDirectoryIterator extends FilesystemIterator
|
1682 |
* @see FilesystemIterator extends DirectoryIterator
|
1683 |
* @see DirectoryIterator extends SplFileInfo
|
1686 |
* @param string $directory Parent directory where the filesystem scan will start.
|
1687 |
* @return array List of files in the main and subdirectories of the folder specified.
|
1688 |
*/
|
1689 |
+
private function get_directory_tree_with_spl($directory = '')
|
1690 |
+
{
|
1691 |
$files = array();
|
1692 |
+
$filepath = @realpath($directory);
|
1693 |
$objects = array();
|
1694 |
|
1695 |
// Exception for directory name must not be empty.
|
1696 |
+
if ($filepath === false) {
|
1697 |
return $files;
|
1698 |
}
|
1699 |
|
1700 |
+
if (!class_exists('FilesystemIterator')) {
|
1701 |
$this->scan_interface = 'opendir';
|
1702 |
+
SucuriScanOption::update_option(':scan_interface', $this->scan_interface);
|
1703 |
+
$alternative_tree = $this->get_directory_tree($directory);
|
1704 |
|
1705 |
return $alternative_tree;
|
1706 |
}
|
1707 |
|
1708 |
try {
|
1709 |
+
if ($this->run_recursively) {
|
1710 |
$flags = FilesystemIterator::KEY_AS_PATHNAME
|
1711 |
| FilesystemIterator::CURRENT_AS_FILEINFO
|
1712 |
| FilesystemIterator::SKIP_DOTS
|
1713 |
| FilesystemIterator::UNIX_PATHS;
|
1714 |
$objects = new RecursiveIteratorIterator(
|
1715 |
+
new RecursiveDirectoryIterator($filepath, $flags),
|
1716 |
RecursiveIteratorIterator::SELF_FIRST,
|
1717 |
RecursiveIteratorIterator::CATCH_GET_CHILD
|
1718 |
);
|
1719 |
} else {
|
1720 |
+
$objects = new DirectoryIterator($filepath);
|
1721 |
}
|
1722 |
+
} catch (RuntimeException $exception) {
|
1723 |
+
SucuriScanEvent::report_exception($exception);
|
1724 |
}
|
1725 |
|
1726 |
+
foreach ($objects as $filepath => $fileinfo) {
|
1727 |
$filename = $fileinfo->getFilename();
|
1728 |
|
1729 |
+
if ($this->ignore_folderpath(null, $filename)
|
|
|
1730 |
|| (
|
1731 |
$this->skip_directories === true
|
1732 |
&& $fileinfo->isDir()
|
1735 |
continue;
|
1736 |
}
|
1737 |
|
1738 |
+
if ($this->run_recursively) {
|
1739 |
+
$directory = dirname($filepath);
|
1740 |
} else {
|
1741 |
$directory = $fileinfo->getPath();
|
1742 |
$filepath = $directory . '/' . $filename;
|
1743 |
}
|
1744 |
|
1745 |
+
if ($this->ignore_folderpath($directory, $filename)
|
1746 |
+
|| $this->ignore_filepath($filename)
|
|
|
1747 |
) {
|
1748 |
continue;
|
1749 |
}
|
1762 |
* @param string $directory Parent directory where the filesystem scan will start.
|
1763 |
* @return array List of files in the main and subdirectories of the folder specified.
|
1764 |
*/
|
1765 |
+
private function get_directory_tree_with_glob($directory = '')
|
1766 |
+
{
|
1767 |
$files = array();
|
1768 |
+
$directory_pattern = sprintf('%s/*', rtrim($directory, '/'));
|
1769 |
+
$files_found = @glob($directory_pattern);
|
1770 |
+
|
1771 |
+
if (is_array($files_found)) {
|
1772 |
+
foreach ($files_found as $filepath) {
|
1773 |
+
$filepath = @realpath($filepath);
|
1774 |
+
$directory = dirname($filepath);
|
1775 |
+
$filepath_parts = explode('/', $filepath);
|
1776 |
+
$filename = array_pop($filepath_parts);
|
1777 |
+
|
1778 |
+
if (is_dir($filepath)) {
|
1779 |
+
if ($this->ignore_folderpath($directory, $filename)) {
|
1780 |
continue;
|
1781 |
}
|
1782 |
|
1783 |
+
if ($this->run_recursively) {
|
1784 |
+
$sub_files = $this->get_directory_tree_with_glob($filepath);
|
1785 |
|
1786 |
+
if ($sub_files) {
|
1787 |
+
$files = array_merge($files, $sub_files);
|
1788 |
}
|
1789 |
}
|
1790 |
+
} elseif ($this->ignore_filepath($filename)) {
|
1791 |
continue;
|
1792 |
} else {
|
1793 |
$files[] = $filepath;
|
1806 |
* @param string $directory Parent directory where the filesystem scan will start.
|
1807 |
* @return array List of files in the main and subdirectories of the folder specified.
|
1808 |
*/
|
1809 |
+
private function get_directory_tree_with_opendir($directory = '')
|
1810 |
+
{
|
1811 |
$files = array();
|
1812 |
+
$dh = @opendir($directory);
|
1813 |
|
1814 |
+
if (!$dh) {
|
1815 |
return false;
|
1816 |
}
|
1817 |
|
1818 |
+
while (($filename = readdir($dh)) !== false) {
|
1819 |
+
$filepath = @realpath($directory . '/' . $filename);
|
1820 |
|
1821 |
+
if ($filepath === false) {
|
1822 |
continue;
|
1823 |
+
} elseif (is_dir($filepath)) {
|
1824 |
+
if ($this->ignore_folderpath($directory, $filename)) {
|
1825 |
continue;
|
1826 |
}
|
1827 |
|
1828 |
+
if ($this->run_recursively) {
|
1829 |
+
$sub_files = $this->get_directory_tree_with_opendir($filepath);
|
1830 |
|
1831 |
+
if ($sub_files) {
|
1832 |
+
$files = array_merge($files, $sub_files);
|
1833 |
}
|
1834 |
}
|
1835 |
} else {
|
1836 |
+
if ($this->ignore_filepath($filename)) {
|
1837 |
continue;
|
1838 |
}
|
1839 |
$files[] = $filepath;
|
1840 |
}
|
1841 |
}
|
1842 |
|
1843 |
+
closedir($dh);
|
1844 |
return $files;
|
1845 |
}
|
1846 |
|
1851 |
* @param string $filename Name of the folder or file being scanned at the moment.
|
1852 |
* @return boolean Either TRUE or FALSE representing that the scan should ignore this folder or not.
|
1853 |
*/
|
1854 |
+
private function ignore_folderpath($directory = '', $filename = '')
|
1855 |
+
{
|
1856 |
// Ignoring current and parent folders.
|
1857 |
+
if ($filename == '.' || $filename == '..') {
|
1858 |
return true;
|
1859 |
}
|
1860 |
|
1861 |
+
if ($this->ignore_directories) {
|
1862 |
// Ignore directories based on a common regular expression.
|
1863 |
+
$filepath = @realpath($directory . '/' . $filename);
|
1864 |
$pattern = '/\/wp-content\/(uploads|cache|backup|w3tc)/';
|
1865 |
|
1866 |
+
if (preg_match($pattern, $filepath)) {
|
1867 |
return true;
|
1868 |
}
|
1869 |
|
1870 |
// Ignore directories specified by the administrator.
|
1871 |
+
if (!empty($this->ignored_directories)) {
|
1872 |
+
foreach ($this->ignored_directories['directories'] as $ignored_dir) {
|
1873 |
+
if (strpos($directory, $ignored_dir) !== false
|
1874 |
+
|| strpos($filepath, $ignored_dir) !== false
|
|
|
1875 |
) {
|
1876 |
return true;
|
1877 |
}
|
1888 |
* @param string $filename Name of the folder or file being scanned at the moment.
|
1889 |
* @return boolean Either TRUE or FALSE representing that the scan should ignore this filename or not.
|
1890 |
*/
|
1891 |
+
private function ignore_filepath($filename = '')
|
1892 |
+
{
|
1893 |
+
if (!$this->ignore_files) {
|
1894 |
return false;
|
1895 |
}
|
1896 |
|
1897 |
// Ignoring backup files from our clean ups.
|
1898 |
+
if (strpos($filename, '_sucuribackup.') !== false) {
|
1899 |
return true;
|
1900 |
}
|
1901 |
|
1902 |
// Ignore files specified by the administrator.
|
1903 |
+
if (!empty($this->ignored_directories)) {
|
1904 |
+
foreach ($this->ignored_directories['directories'] as $ignored_dir) {
|
1905 |
+
if (strpos($ignored_dir, $filename) !== false) {
|
1906 |
return true;
|
1907 |
}
|
1908 |
}
|
1909 |
}
|
1910 |
|
1911 |
// Any file maching one of these rules WILL NOT be ignored.
|
1912 |
+
if (( strpos($filename, '.php') !== false) ||
|
1913 |
+
( strpos($filename, '.htm') !== false) ||
|
1914 |
+
( strpos($filename, '.js') !== false) ||
|
1915 |
+
( strcmp($filename, '.htaccess') == 0 ) ||
|
1916 |
+
( strcmp($filename, 'php.ini') == 0 )
|
|
|
1917 |
) {
|
1918 |
return false;
|
1919 |
}
|
1927 |
* @param array $dir_tree A list of files under a directory.
|
1928 |
* @return array A list of unique directory paths.
|
1929 |
*/
|
1930 |
+
public function get_diretories_only($dir_tree = array())
|
1931 |
+
{
|
1932 |
$dirs = array();
|
1933 |
|
1934 |
+
if (is_string($dir_tree)) {
|
1935 |
+
$dir_tree = $this->get_directory_tree($dir_tree);
|
1936 |
}
|
1937 |
|
1938 |
+
if (is_array($dir_tree) && !empty($dir_tree)) {
|
1939 |
+
foreach ($dir_tree as $filepath) {
|
1940 |
+
$dir_path = dirname($filepath);
|
1941 |
|
1942 |
+
if (is_array($dirs)
|
1943 |
+
&& !in_array($dir_path, $dirs)
|
1944 |
+
&& array_key_exists('directories', $this->ignored_directories)
|
1945 |
+
&& is_array($this->ignored_directories['directories'])
|
1946 |
+
&& !in_array($dir_path, $this->ignored_directories['directories'])
|
1947 |
) {
|
1948 |
$dirs[] = $dir_path;
|
1949 |
}
|
1963 |
* @param string $pattern Text that will be searched inside each file.
|
1964 |
* @return array Associative list with the file path and line number of the match.
|
1965 |
*/
|
1966 |
+
public function grep_pattern($directory = '', $pattern = '')
|
1967 |
+
{
|
1968 |
+
$dir_tree = $this->get_directory_tree($directory);
|
1969 |
+
$pattern = '/.*' . str_replace('/', '\/', $pattern) . '.*/';
|
1970 |
$results = array();
|
1971 |
|
1972 |
+
if (class_exists('SplFileObject')
|
1973 |
+
&& class_exists('RegexIterator')
|
1974 |
+
&& SucuriScan::is_valid_pattern($pattern)
|
|
|
1975 |
) {
|
1976 |
+
foreach ($dir_tree as $file_path) {
|
1977 |
try {
|
1978 |
+
$fobject = new SplFileObject($file_path);
|
1979 |
+
$fstream = new RegexIterator($fobject, $pattern, RegexIterator::MATCH);
|
1980 |
|
1981 |
+
foreach ($fstream as $key => $ltext) {
|
1982 |
$lnumber = ( $key + 1 );
|
1983 |
+
$ltext = str_replace("\n", '', $ltext);
|
1984 |
+
$fpath = str_replace($directory, '', $file_path);
|
1985 |
+
$loutput = sprintf('%s:%d:%s', $fpath, $lnumber, $ltext);
|
1986 |
$results[] = array(
|
1987 |
'file_path' => $file_path,
|
1988 |
'relative_path' => $fpath,
|
1991 |
'output' => $loutput,
|
1992 |
);
|
1993 |
}
|
1994 |
+
} catch (RuntimeException $exception) {
|
1995 |
+
SucuriScanEvent::report_exception($exception);
|
1996 |
}
|
1997 |
}
|
1998 |
}
|
2006 |
* @param string $directory Path of the existing directory that will be removed.
|
2007 |
* @return boolean TRUE if all the files and folder inside the directory were removed.
|
2008 |
*/
|
2009 |
+
public function remove_directory_tree($directory = '')
|
2010 |
+
{
|
2011 |
+
$dir_tree = $this->get_directory_tree($directory);
|
2012 |
|
2013 |
+
if ($dir_tree) {
|
2014 |
$dirs_only = array();
|
2015 |
|
2016 |
// Include the parent directory as the first entry.
|
2022 |
* were successfully deleted, this is because PHP does not allows to delete non-
|
2023 |
* empty folders.
|
2024 |
*/
|
2025 |
+
foreach ($dir_tree as $filepath) {
|
2026 |
+
if (is_dir($filepath)) {
|
2027 |
$dirs_only[] = $filepath;
|
2028 |
} else {
|
2029 |
+
@unlink($filepath);
|
2030 |
}
|
2031 |
}
|
2032 |
|
2033 |
+
if (!function_exists('sucuriscan_strlen_diff')) {
|
2034 |
/**
|
2035 |
* Evaluates the difference between the length of two strings.
|
2036 |
*
|
2038 |
* @param string $b Second string of characters that will be measured.
|
2039 |
* @return integer The difference in length between the two strings.
|
2040 |
*/
|
2041 |
+
function sucuriscan_strlen_diff($a = '', $b = '')
|
2042 |
+
{
|
2043 |
+
return strlen($b) - strlen($a);
|
2044 |
}
|
2045 |
}
|
2046 |
|
2047 |
// Sort the directories by deep level in ascendant order.
|
2048 |
+
$dirs_only = array_unique($dirs_only);
|
2049 |
+
usort($dirs_only, 'sucuriscan_strlen_diff');
|
2050 |
|
2051 |
// Delete all the directories starting from the deepest level.
|
2052 |
+
foreach ($dirs_only as $dir_path) {
|
2053 |
+
@rmdir($dir_path);
|
2054 |
}
|
2055 |
|
2056 |
return true;
|
2067 |
* @param string $filepath Path to the file.
|
2068 |
* @return array An array where each element is a line in the file.
|
2069 |
*/
|
2070 |
+
public static function file_lines($filepath = '')
|
2071 |
+
{
|
2072 |
+
return @file($filepath, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
|
2073 |
}
|
2074 |
|
2075 |
/**
|
2082 |
* @param boolean $adaptive Whether the buffer will adapt to a specific number of bytes or not.
|
2083 |
* @return string Text contained at the end of the file.
|
2084 |
*/
|
2085 |
+
public static function tail_file($file_path = '', $lines = 1, $adaptive = true)
|
2086 |
+
{
|
2087 |
+
$file = @fopen($file_path, 'rb');
|
2088 |
$limit = $lines;
|
2089 |
|
2090 |
+
if ($file) {
|
2091 |
+
fseek($file, -1, SEEK_END);
|
2092 |
|
2093 |
+
if ($adaptive && $lines < 2) {
|
2094 |
$buffer = 64;
|
2095 |
+
} elseif ($adaptive && $lines < 10) {
|
2096 |
$buffer = 512;
|
2097 |
} else {
|
2098 |
$buffer = 4096;
|
2099 |
}
|
2100 |
|
2101 |
+
if (fread($file, 1) != "\n") {
|
2102 |
$lines -= 1;
|
2103 |
}
|
2104 |
|
2105 |
$output = '';
|
2106 |
$chunk = '';
|
2107 |
|
2108 |
+
while (ftell($file) > 0 && $lines >= 0) {
|
2109 |
+
$seek = min(ftell($file), $buffer);
|
2110 |
+
fseek($file, -$seek, SEEK_CUR);
|
2111 |
+
$chunk = fread($file, $seek);
|
2112 |
$output = $chunk . $output;
|
2113 |
+
fseek($file, -mb_strlen($chunk, '8bit'), SEEK_CUR);
|
2114 |
+
$lines -= substr_count($chunk, "\n");
|
2115 |
}
|
2116 |
|
2117 |
+
fclose($file);
|
2118 |
|
2119 |
+
$lines_arr = explode("\n", $output);
|
2120 |
+
$lines_count = count($lines_arr);
|
2121 |
+
$result = array_slice($lines_arr, ($lines_count - $limit));
|
2122 |
|
2123 |
return $result;
|
2124 |
}
|
2132 |
* @param string $file_path Path to the file.
|
2133 |
* @return integer Time the file was last changed.
|
2134 |
*/
|
2135 |
+
public static function creation_time($file_path = '')
|
2136 |
+
{
|
2137 |
+
if (file_exists($file_path)) {
|
2138 |
+
clearstatcache($file_path);
|
2139 |
+
return filectime($file_path);
|
2140 |
}
|
2141 |
|
2142 |
return 0;
|
2148 |
* @param string $file_path Path to the file.
|
2149 |
* @return integer Time the file was last modified.
|
2150 |
*/
|
2151 |
+
public static function modification_time($file_path = '')
|
2152 |
+
{
|
2153 |
+
if (file_exists($file_path)) {
|
2154 |
+
clearstatcache($file_path);
|
2155 |
+
return filemtime($file_path);
|
2156 |
}
|
2157 |
|
2158 |
return 0;
|
2164 |
* @param string $path Path to the file.
|
2165 |
* @return string Type of resource: dir, link, file.
|
2166 |
*/
|
2167 |
+
public static function get_resource_type($path = '')
|
2168 |
+
{
|
2169 |
+
if (is_dir($path)) {
|
2170 |
return 'dir';
|
2171 |
+
} elseif (is_link($path)) {
|
2172 |
return 'link';
|
2173 |
+
} elseif (is_file($path)) {
|
2174 |
return 'file';
|
2175 |
} else {
|
2176 |
return 'unknown';
|
2177 |
}
|
2178 |
}
|
|
|
2179 |
}
|
2180 |
|
2181 |
/**
|
2188 |
* the request. Cached data will not be stored persistently across page loads
|
2189 |
* unless of the installation of a 3party persistent caching plugin [2].
|
2190 |
*
|
2191 |
+
* [1] https://codex.wordpress.org/Class_Reference/WP_Object_Cache
|
2192 |
+
* [2] https://codex.wordpress.org/Class_Reference/WP_Object_Cache#Persistent_Caching
|
2193 |
*/
|
2194 |
+
class SucuriScanCache extends SucuriScan
|
2195 |
+
{
|
2196 |
/**
|
2197 |
* The unique name (or identifier) of the file with the data.
|
2198 |
*
|
2231 |
* @param string $datastore Unique name (or identifier) of the file with the data.
|
2232 |
* @return void
|
2233 |
*/
|
2234 |
+
public function __construct($datastore = '', $auto_create = true)
|
2235 |
+
{
|
2236 |
$this->datastore = $datastore;
|
2237 |
+
$this->datastore_path = $this->datastoreFilePath($auto_create);
|
2238 |
$this->usable_datastore = (bool) $this->datastore_path;
|
2239 |
}
|
2240 |
|
2243 |
*
|
2244 |
* @return string Default attributes for every datastore file.
|
2245 |
*/
|
2246 |
+
private function datastoreDefaultInfo()
|
2247 |
+
{
|
2248 |
$attrs = array(
|
2249 |
'datastore' => $this->datastore,
|
2250 |
'created_on' => time(),
|
2260 |
* @param array $finfo Rainbow table with the key names and decoded values.
|
2261 |
* @return string Default content of every datastore file.
|
2262 |
*/
|
2263 |
+
private function datastoreInfo($finfo = array())
|
2264 |
+
{
|
2265 |
+
$attrs = $this->datastoreDefaultInfo();
|
2266 |
$info_is_available = (bool) isset($finfo['info']);
|
2267 |
$info = "<?php\n";
|
2268 |
|
2269 |
+
foreach ($attrs as $attr_name => $attr_value) {
|
2270 |
+
if ($info_is_available
|
|
|
2271 |
&& $attr_name != 'updated_on'
|
2272 |
+
&& isset($finfo['info'][$attr_name])
|
2273 |
) {
|
2274 |
+
$attr_value = $finfo['info'][$attr_name];
|
2275 |
}
|
2276 |
|
2277 |
+
$info .= sprintf("// %s=%s;\n", $attr_name, $attr_value);
|
2278 |
}
|
2279 |
|
2280 |
$info .= "exit(0);\n";
|
2291 |
* @param boolean $auto_create Automatically create the file if not exists or not.
|
2292 |
* @return string The full path where the datastore file is located, FALSE otherwise.
|
2293 |
*/
|
2294 |
+
private function datastoreFilePath($auto_create = false)
|
2295 |
+
{
|
2296 |
+
if (!is_null($this->datastore)) {
|
2297 |
$folder_path = $this->datastore_folder_path();
|
2298 |
$file_path = $folder_path . 'sucuri-' . $this->datastore . '.php';
|
2299 |
|
2300 |
// Create the datastore parent directory.
|
2301 |
+
if (!file_exists($folder_path)) {
|
2302 |
+
@mkdir($folder_path, 0755, true);
|
2303 |
}
|
2304 |
|
2305 |
// Create the datastore file is it does not exists and the folder is writable.
|
2306 |
+
if (!file_exists($file_path)
|
2307 |
+
&& is_writable($folder_path)
|
|
|
2308 |
&& $auto_create === true
|
2309 |
) {
|
2310 |
+
@file_put_contents($file_path, $this->datastoreInfo());
|
2311 |
}
|
2312 |
|
2313 |
// Continue the operation after an attemp to create the datastore file.
|
2314 |
+
if (file_exists($file_path)
|
2315 |
+
&& is_writable($file_path)
|
2316 |
+
&& is_readable($file_path)
|
|
|
2317 |
) {
|
2318 |
return $file_path;
|
2319 |
}
|
2330 |
* @param string $action Either "valid", "content", or "header".
|
2331 |
* @return string Cache key pattern.
|
2332 |
*/
|
2333 |
+
private function keyPattern($action = 'valid')
|
2334 |
+
{
|
2335 |
+
if ($action == 'valid') {
|
2336 |
return '/^([0-9a-zA-Z_]+)$/';
|
2337 |
+
} elseif ($action == 'content') {
|
|
|
|
|
2338 |
return '/^([0-9a-zA-Z_]+):(.+)/';
|
2339 |
+
} elseif ($action == 'header') {
|
|
|
|
|
2340 |
return '/^\/\/ ([a-z_]+)=(.*);$/';
|
2341 |
}
|
2342 |
|
2349 |
* @param string $key Unique name to identify the data in the datastore file.
|
2350 |
* @return boolean TRUE if the format of the key name is valid, FALSE otherwise.
|
2351 |
*/
|
2352 |
+
private function validKeyName($key = '')
|
2353 |
+
{
|
2354 |
+
return (bool) @preg_match($this->keyPattern('valid'), $key);
|
2355 |
}
|
2356 |
|
2357 |
/**
|
2360 |
* @param array $finfo Rainbow table with the key names and decoded values.
|
2361 |
* @return boolean TRUE if the operation finished successfully, FALSE otherwise.
|
2362 |
*/
|
2363 |
+
private function saveNewEntries($finfo = array())
|
2364 |
+
{
|
2365 |
+
$data_string = $this->datastoreInfo($finfo);
|
2366 |
|
2367 |
+
if (!empty($finfo)) {
|
2368 |
+
foreach ($finfo['entries'] as $key => $data) {
|
2369 |
+
if ($this->validKeyName($key)) {
|
2370 |
+
$data = json_encode($data);
|
2371 |
+
$data_string .= sprintf("%s:%s\n", $key, $data);
|
2372 |
}
|
2373 |
}
|
2374 |
}
|
2375 |
|
2376 |
+
return (bool) @file_put_contents($this->datastore_path, $data_string);
|
|
|
|
|
2377 |
}
|
2378 |
|
2379 |
/**
|
2385 |
* @param boolean $assoc When TRUE returned objects will be converted into associative arrays.
|
2386 |
* @return array Rainbow table with the key names and decoded values.
|
2387 |
*/
|
2388 |
+
private function getDatastoreContent($assoc = false)
|
2389 |
+
{
|
2390 |
$data_object = array(
|
2391 |
'info' => array(),
|
2392 |
'entries' => array(),
|
2393 |
);
|
2394 |
|
2395 |
+
if ($this->usable_datastore) {
|
2396 |
+
$data_lines = SucuriScanFileInfo::file_lines($this->datastore_path);
|
2397 |
|
2398 |
+
if (!empty($data_lines)) {
|
2399 |
+
foreach ($data_lines as $line) {
|
2400 |
+
if (preg_match($this->keyPattern('header'), $line, $match)) {
|
2401 |
$data_object['info'][ $match[1] ] = $match[2];
|
2402 |
+
} elseif (preg_match($this->keyPattern('content'), $line, $match)) {
|
2403 |
+
if ($this->validKeyName($match[1])
|
2404 |
+
&& !array_key_exists($match[1], $data_object)
|
|
|
2405 |
) {
|
2406 |
+
$data_object['entries'][$match[1]] = @json_decode($match[2], $assoc);
|
2407 |
}
|
2408 |
}
|
2409 |
}
|
2421 |
* functionality of these headers please refer to the function that contains the
|
2422 |
* default attributes and their values [1].
|
2423 |
*
|
2424 |
+
* [1] SucuriScanCache::datastoreDefaultInfo()
|
2425 |
*
|
2426 |
* @return array Default content of every datastore file.
|
2427 |
*/
|
2428 |
+
public function getDatastoreInfo()
|
2429 |
+
{
|
2430 |
+
$finfo = $this->getDatastoreContent();
|
2431 |
|
2432 |
+
if (!empty($finfo['info'])) {
|
2433 |
return $finfo['info'];
|
2434 |
}
|
2435 |
|
2442 |
* @param array $finfo Rainbow table with the key names and decoded values.
|
2443 |
* @return integer Total number of unique entries found in the datastore file.
|
2444 |
*/
|
2445 |
+
public function getCount($finfo = null)
|
2446 |
+
{
|
2447 |
+
if (!is_array($finfo)) {
|
2448 |
+
$finfo = $this->getDatastoreContent();
|
2449 |
}
|
2450 |
|
2451 |
+
return count($finfo['entries']);
|
2452 |
}
|
2453 |
|
2454 |
/**
|
2461 |
* @param array $finfo Rainbow table with the key names and decoded values.
|
2462 |
* @return boolean TRUE if the life time of the data has expired, FALSE otherwise.
|
2463 |
*/
|
2464 |
+
public function dataHasExpired($lifetime = 0, $finfo = null)
|
2465 |
+
{
|
2466 |
+
if (is_null($finfo)) {
|
2467 |
+
$finfo = $this->getDatastoreContent();
|
2468 |
}
|
2469 |
|
2470 |
+
if ($lifetime > 0 && !empty($finfo['info'])) {
|
2471 |
+
$diff_time = time() - intval($finfo['info']['updated_on']);
|
2472 |
|
2473 |
+
if ($diff_time >= $lifetime) {
|
2474 |
return true;
|
2475 |
}
|
2476 |
}
|
2488 |
* @param boolean $assoc When TRUE returned objects will be converted into associative arrays.
|
2489 |
* @return boolean TRUE if the operation finished successfully, FALSE otherwise.
|
2490 |
*/
|
2491 |
+
private function handleKeyData($key = '', $data = null, $action = '', $lifetime = 0, $assoc = false)
|
2492 |
+
{
|
2493 |
+
if ($this->validKeyName($key)
|
2494 |
+
&& $this->usable_datastore
|
2495 |
+
) {
|
2496 |
+
$finfo = $this->getDatastoreContent($assoc);
|
|
|
2497 |
|
2498 |
+
if ($action == 'set' || $action == 'add') {
|
2499 |
+
$finfo['entries'][$key] = $data;
|
2500 |
+
|
2501 |
+
return $this->saveNewEntries($finfo);
|
2502 |
+
} elseif ($action == 'get') {
|
2503 |
+
if (!$this->dataHasExpired($lifetime, $finfo)
|
2504 |
+
&& array_key_exists($key, $finfo['entries'])
|
2505 |
+
) {
|
2506 |
+
return $finfo['entries'][$key];
|
2507 |
+
}
|
2508 |
+
} elseif ($action == 'get_all') {
|
2509 |
+
if (!$this->dataHasExpired($lifetime, $finfo)) {
|
2510 |
+
return $finfo['entries'];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2511 |
}
|
2512 |
+
} elseif ($action == 'exists') {
|
2513 |
+
if (!$this->dataHasExpired($lifetime, $finfo)
|
2514 |
+
&& array_key_exists($key, $finfo['entries'])
|
2515 |
+
) {
|
2516 |
+
return true;
|
2517 |
+
}
|
2518 |
+
} elseif ($action == 'delete') {
|
2519 |
+
unset($finfo['entries'][$key]);
|
2520 |
+
|
2521 |
+
return $this->saveNewEntries($finfo);
|
2522 |
}
|
2523 |
}
|
2524 |
|
2535 |
* @param string $data Mixed data stored in the datastore file following the unique key name.
|
2536 |
* @return boolean TRUE if the data was stored successfully, FALSE otherwise.
|
2537 |
*/
|
2538 |
+
public function add($key = '', $data = '')
|
2539 |
+
{
|
2540 |
+
return $this->handleKeyData($key, $data, 'add');
|
2541 |
}
|
2542 |
|
2543 |
/**
|
2547 |
* @param string $data Mixed data stored in the datastore file following the unique key name.
|
2548 |
* @return boolean TRUE if the data was stored successfully, FALSE otherwise.
|
2549 |
*/
|
2550 |
+
public function set($key = '', $data = '')
|
2551 |
+
{
|
2552 |
+
return $this->handleKeyData($key, $data, 'set');
|
2553 |
}
|
2554 |
|
2555 |
/**
|
2560 |
* @param boolean $assoc When TRUE returned objects will be converted into associative arrays.
|
2561 |
* @return string Mixed data stored in the datastore file following the unique key name.
|
2562 |
*/
|
2563 |
+
public function get($key = '', $lifetime = 0, $assoc = false)
|
2564 |
+
{
|
2565 |
+
$assoc = ($assoc == 'array' ? true : $assoc);
|
2566 |
|
2567 |
+
return $this->handleKeyData($key, null, 'get', $lifetime, $assoc);
|
2568 |
}
|
2569 |
|
2570 |
/**
|
2574 |
* @param boolean $assoc When TRUE returned objects will be converted into associative arrays.
|
2575 |
* @return string Mixed data stored in the datastore file following the unique key name.
|
2576 |
*/
|
2577 |
+
public function getAll($lifetime = 0, $assoc = false)
|
2578 |
+
{
|
2579 |
+
$assoc = ($assoc == 'array' ? true : $assoc);
|
2580 |
|
2581 |
+
return $this->handleKeyData('temp', null, 'get_all', $lifetime, $assoc);
|
2582 |
}
|
2583 |
|
2584 |
/**
|
2587 |
* @param string $key Unique name to identify the data in the datastore file.
|
2588 |
* @return boolean TRUE if the key exists in the datastore file, FALSE otherwise.
|
2589 |
*/
|
2590 |
+
public function exists($key = '')
|
2591 |
+
{
|
2592 |
+
return $this->handleKeyData($key, null, 'exists');
|
2593 |
}
|
2594 |
|
2595 |
/**
|
2598 |
* @param string $key Unique name to identify the data in the datastore file.
|
2599 |
* @return boolean TRUE if the entries were removed, FALSE otherwise.
|
2600 |
*/
|
2601 |
+
public function delete($key = '')
|
2602 |
+
{
|
2603 |
+
return $this->handleKeyData($key, null, 'delete');
|
2604 |
}
|
2605 |
|
2606 |
/**
|
2608 |
*
|
2609 |
* @return boolean Always TRUE unless the datastore file is not writable.
|
2610 |
*/
|
2611 |
+
public function flush()
|
2612 |
+
{
|
2613 |
+
$finfo = $this->getDatastoreContent();
|
2614 |
|
2615 |
+
return $this->saveNewEntries($finfo);
|
2616 |
}
|
|
|
2617 |
}
|
2618 |
|
2619 |
/**
|
2636 |
* apply network-wide and the data is stored in the wp_sitemeta table under the
|
2637 |
* given custom name.
|
2638 |
*
|
2639 |
+
* @see https://codex.wordpress.org/Option_Reference
|
2640 |
+
* @see https://codex.wordpress.org/Options_API
|
2641 |
*/
|
2642 |
+
class SucuriScanOption extends SucuriScanRequest
|
2643 |
+
{
|
2644 |
|
2645 |
/**
|
2646 |
* Default values for all the plugin's options.
|
2647 |
*
|
2648 |
* @return array Default values for all the plugin's options.
|
2649 |
*/
|
2650 |
+
public static function get_default_option_values()
|
2651 |
+
{
|
2652 |
$defaults = array(
|
2653 |
'sucuriscan_account' => '',
|
2654 |
+
'sucuriscan_addr_header' => 'HTTP_X_SUCURI_CLIENTIP',
|
2655 |
'sucuriscan_ads_visibility' => 'enabled',
|
2656 |
'sucuriscan_api_key' => false,
|
2657 |
+
'sucuriscan_api_service' => 'enabled',
|
2658 |
'sucuriscan_audit_report' => 'disabled',
|
2659 |
'sucuriscan_cloudproxy_apikey' => '',
|
2660 |
'sucuriscan_collect_wrong_passwords' => 'disabled',
|
2701 |
'sucuriscan_notify_widget_deleted' => 'disabled',
|
2702 |
'sucuriscan_parse_errorlogs' => 'enabled',
|
2703 |
'sucuriscan_prettify_mails' => 'disabled',
|
2704 |
+
'sucuriscan_request_timeout' => 5,
|
2705 |
'sucuriscan_revproxy' => 'disabled',
|
2706 |
'sucuriscan_runtime' => 0,
|
2707 |
'sucuriscan_scan_checksums' => 'enabled',
|
2708 |
'sucuriscan_scan_errorlogs' => 'disabled',
|
2709 |
'sucuriscan_scan_frequency' => 'twicedaily',
|
2710 |
'sucuriscan_scan_interface' => 'spl',
|
2711 |
+
'sucuriscan_selfhosting_fpath' => '',
|
2712 |
+
'sucuriscan_selfhosting_monitor' => 'disabled',
|
2713 |
'sucuriscan_site_version' => '0.0',
|
2714 |
'sucuriscan_sitecheck_counter' => 0,
|
2715 |
'sucuriscan_sitecheck_scanner' => 'enabled',
|
2726 |
*
|
2727 |
* @return array Name of all valid plugin's options.
|
2728 |
*/
|
2729 |
+
public static function get_default_option_names()
|
2730 |
+
{
|
2731 |
$options = self::get_default_option_values();
|
2732 |
+
$names = array_keys($options);
|
2733 |
|
2734 |
return $names;
|
2735 |
}
|
2740 |
* @param string $option_name Name of the option that will be checked.
|
2741 |
* @return boolean True if the option is part of the plugin, False otherwise.
|
2742 |
*/
|
2743 |
+
public static function is_valid_plugin_option($option_name = '')
|
2744 |
+
{
|
2745 |
$valid_options = self::get_default_option_names();
|
2746 |
+
$is_valid_option = (bool) array_key_exists($option_name, $valid_options);
|
2747 |
|
2748 |
return $is_valid_option;
|
2749 |
}
|
2754 |
* @param string|array $settings Either an array that will be complemented or a string with the name of the option.
|
2755 |
* @return string|array The default values for the specified options.
|
2756 |
*/
|
2757 |
+
public static function get_default_options($settings = '')
|
2758 |
+
{
|
2759 |
$default_options = self::get_default_option_values();
|
2760 |
|
2761 |
// Use framework built-in function.
|
2762 |
+
if (function_exists('get_option')) {
|
2763 |
+
$admin_email = get_option('admin_email');
|
2764 |
$default_options['sucuriscan_account'] = $admin_email;
|
2765 |
$default_options['sucuriscan_notify_to'] = $admin_email;
|
2766 |
}
|
2767 |
|
2768 |
+
if (is_array($settings)) {
|
2769 |
+
foreach ($default_options as $option_name => $option_value) {
|
2770 |
+
if (!isset($settings[ $option_name ])) {
|
2771 |
$settings[ $option_name ] = $option_value;
|
2772 |
}
|
2773 |
}
|
2775 |
return $settings;
|
2776 |
}
|
2777 |
|
2778 |
+
if (is_string($settings)
|
2779 |
+
&& !empty($settings)
|
2780 |
+
&& array_key_exists($settings, $default_options)
|
|
|
2781 |
) {
|
2782 |
return $default_options[ $settings ];
|
2783 |
}
|
2797 |
* automatically replace that character with the unique identifier of the
|
2798 |
* plugin.
|
2799 |
*
|
2800 |
+
* @see https://codex.wordpress.org/Function_Reference/get_option
|
2801 |
*
|
2802 |
* @param string $option_name Optional parameter that you can use to filter the results to one option.
|
2803 |
* @return string The value (or default value) of the option specified.
|
2804 |
*/
|
2805 |
+
public static function get_option($option_name = '')
|
2806 |
+
{
|
2807 |
+
if (function_exists('update_option')) {
|
2808 |
+
$option_name = self::variable_prefix($option_name);
|
2809 |
+
$option_value = get_option($option_name);
|
2810 |
|
2811 |
+
if ($option_value === false && preg_match('/^sucuriscan_/', $option_name)) {
|
2812 |
+
$option_value = self::get_default_options($option_name);
|
2813 |
}
|
2814 |
|
2815 |
return $option_value;
|
2826 |
* the insert SQL statement but not the option value, this value should always
|
2827 |
* be properly sanitized.
|
2828 |
*
|
2829 |
+
* @see https://codex.wordpress.org/Function_Reference/update_option
|
2830 |
*
|
2831 |
* @param string $option_name Name of the option to update which must not exceed 64 characters.
|
2832 |
* @param string $option_value The new value for the option, can be an integer, string, array, or object.
|
2833 |
* @return boolean True if option value has changed, false if not or if update failed.
|
2834 |
*/
|
2835 |
+
public static function update_option($option_name = '', $option_value = '')
|
2836 |
+
{
|
2837 |
+
if (function_exists('update_option')) {
|
2838 |
+
$option_name = self::variable_prefix($option_name);
|
2839 |
|
2840 |
+
return update_option($option_name, $option_value);
|
2841 |
}
|
2842 |
|
2843 |
return false;
|
2848 |
*
|
2849 |
* A safe way of removing a named option/value pair from the options database table.
|
2850 |
*
|
2851 |
+
* @see https://codex.wordpress.org/Function_Reference/delete_option
|
2852 |
*
|
2853 |
* @param string $option_name Name of the option to be deleted.
|
2854 |
* @return boolean True, if option is successfully deleted. False on failure, or option does not exist.
|
2855 |
*/
|
2856 |
+
public static function delete_option($option_name = '')
|
2857 |
+
{
|
2858 |
+
if (function_exists('delete_option')) {
|
2859 |
+
$option_name = self::variable_prefix($option_name);
|
2860 |
|
2861 |
+
return delete_option($option_name);
|
2862 |
}
|
2863 |
|
2864 |
return false;
|
2870 |
* @param string $option Name of the option to be deleted.
|
2871 |
* @return boolean True if the option is enabled, false otherwise.
|
2872 |
*/
|
2873 |
+
public static function is_enabled($option = '')
|
2874 |
+
{
|
2875 |
+
return (bool) ( self::get_option($option) === 'enabled' );
|
2876 |
}
|
2877 |
|
2878 |
/**
|
2881 |
* @param string $option Name of the option to be deleted.
|
2882 |
* @return boolean True if the option is disabled, false otherwise.
|
2883 |
*/
|
2884 |
+
public static function is_disabled($option = '')
|
2885 |
+
{
|
2886 |
+
return (bool) ( self::get_option($option) === 'disabled' );
|
2887 |
}
|
2888 |
|
2889 |
/**
|
2891 |
*
|
2892 |
* @return void
|
2893 |
*/
|
2894 |
+
public static function delete_plugin_options()
|
2895 |
+
{
|
2896 |
global $wpdb;
|
2897 |
|
2898 |
$options = $wpdb->get_results(
|
2901 |
ORDER BY option_id ASC"
|
2902 |
);
|
2903 |
|
2904 |
+
foreach ($options as $option) {
|
2905 |
+
self::delete_option($option->option_name);
|
2906 |
}
|
2907 |
}
|
2908 |
|
2913 |
*
|
2914 |
* @return array All the options stored by Wordpress in the database, except the transient options.
|
2915 |
*/
|
2916 |
+
public static function get_site_options()
|
2917 |
+
{
|
2918 |
global $wpdb;
|
2919 |
|
2920 |
$settings = array();
|
2924 |
ORDER BY option_id ASC"
|
2925 |
);
|
2926 |
|
2927 |
+
foreach ($results as $row) {
|
2928 |
$settings[ $row->option_name ] = $row->option_value;
|
2929 |
}
|
2930 |
|
2938 |
* @param array $request The content of the global variable GET or POST considering SERVER[REQUEST_METHOD].
|
2939 |
* @return array A list of all the options that were changes through this request.
|
2940 |
*/
|
2941 |
+
public static function what_options_were_changed($request = array())
|
2942 |
+
{
|
2943 |
$options_changed = array(
|
2944 |
'original' => array(),
|
2945 |
'changed' => array()
|
2947 |
|
2948 |
$site_options = self::get_site_options();
|
2949 |
|
2950 |
+
foreach ($request as $req_name => $req_value) {
|
2951 |
+
if (array_key_exists($req_name, $site_options)
|
|
|
2952 |
&& $site_options[ $req_name ] != $req_value
|
2953 |
) {
|
2954 |
$options_changed['original'][ $req_name ] = $site_options[ $req_name ];
|
2964 |
*
|
2965 |
* @return boolean TRUE if the nonce is valid, FALSE otherwise.
|
2966 |
*/
|
2967 |
+
public static function check_options_nonce()
|
2968 |
+
{
|
2969 |
// Create the option_page value if permalink submission.
|
2970 |
+
if (!isset($_POST['option_page'])
|
|
|
2971 |
&& isset($_POST['permalink_structure'])
|
2972 |
) {
|
2973 |
$_POST['option_page'] = 'permalink';
|
2974 |
}
|
2975 |
|
2976 |
// Check if the option_page has an allowed value.
|
2977 |
+
if ($option_page = SucuriScanRequest::post('option_page')) {
|
2978 |
$nonce = '_wpnonce';
|
2979 |
$action = '';
|
2980 |
|
2981 |
+
switch ($option_page) {
|
2982 |
case 'general': /* no_break */
|
2983 |
case 'writing': /* no_break */
|
2984 |
case 'reading': /* no_break */
|
2993 |
}
|
2994 |
|
2995 |
// Check the nonce validity.
|
2996 |
+
if (!empty($action)
|
|
|
2997 |
&& isset($_REQUEST[ $nonce ])
|
2998 |
+
&& wp_verify_nonce($_REQUEST[ $nonce ], $action)
|
2999 |
) {
|
3000 |
return true;
|
3001 |
}
|
3010 |
*
|
3011 |
* @return array List of ignored posts-types to send notifications.
|
3012 |
*/
|
3013 |
+
public static function get_ignored_events()
|
3014 |
+
{
|
3015 |
+
$post_types = self::get_option(':ignored_events');
|
3016 |
$post_types_arr = false;
|
3017 |
|
3018 |
// Encode (old) serialized data into JSON.
|
3019 |
+
if (self::is_serialized($post_types)) {
|
3020 |
+
$post_types_arr = @unserialize($post_types);
|
3021 |
+
$post_types_fix = json_encode($post_types_arr);
|
3022 |
+
self::update_option(':ignored_events', $post_types_fix);
|
3023 |
|
3024 |
return $post_types_arr;
|
3025 |
+
} // Decode JSON-encoded data as an array.
|
3026 |
+
elseif (preg_match('/^\{.+\}$/', $post_types)) {
|
3027 |
+
$post_types_arr = @json_decode($post_types, true);
|
3028 |
}
|
3029 |
|
3030 |
+
if (!is_array($post_types_arr)) {
|
|
|
|
|
|
|
|
|
|
|
3031 |
$post_types_arr = array();
|
3032 |
}
|
3033 |
|
3040 |
* @param string $event_name Unique post-type name.
|
3041 |
* @return boolean Whether the event was ignored or not.
|
3042 |
*/
|
3043 |
+
public static function add_ignored_event($event_name = '')
|
3044 |
+
{
|
3045 |
+
if (function_exists('get_post_types')) {
|
3046 |
$post_types = get_post_types();
|
3047 |
|
3048 |
// Check if the event is a registered post-type.
|
3049 |
+
if (array_key_exists($event_name, $post_types)) {
|
3050 |
$ignored_events = self::get_ignored_events();
|
3051 |
|
3052 |
// Check if the event is not ignored already.
|
3053 |
+
if (!array_key_exists($event_name, $ignored_events)) {
|
3054 |
$ignored_events[ $event_name ] = time();
|
3055 |
+
$saved = self::update_option(':ignored_events', json_encode($ignored_events));
|
3056 |
|
3057 |
return $saved;
|
3058 |
}
|
3068 |
* @param string $event_name Unique post-type name.
|
3069 |
* @return boolean Whether the event was removed from the list or not.
|
3070 |
*/
|
3071 |
+
public static function remove_ignored_event($event_name = '')
|
3072 |
+
{
|
3073 |
$ignored_events = self::get_ignored_events();
|
3074 |
|
3075 |
+
if (array_key_exists($event_name, $ignored_events)) {
|
3076 |
+
unset($ignored_events[ $event_name ]);
|
3077 |
+
$saved = self::update_option(':ignored_events', json_encode($ignored_events));
|
3078 |
|
3079 |
return $saved;
|
3080 |
}
|
3088 |
* @param string $event_name Unique post-type name.
|
3089 |
* @return boolean Whether an event is being ignored or not.
|
3090 |
*/
|
3091 |
+
public static function is_ignored_event($event_name = '')
|
3092 |
+
{
|
3093 |
+
$event_name = strtolower($event_name);
|
3094 |
$ignored_events = self::get_ignored_events();
|
3095 |
|
3096 |
+
if (array_key_exists($event_name, $ignored_events)) {
|
3097 |
return true;
|
3098 |
}
|
3099 |
|
3106 |
*
|
3107 |
* @return array Array with three keys: good, missing, bad.
|
3108 |
*/
|
3109 |
+
public static function get_security_keys()
|
3110 |
+
{
|
3111 |
$response = array(
|
3112 |
'good' => array(),
|
3113 |
'missing' => array(),
|
3124 |
'SECURE_AUTH_SALT',
|
3125 |
);
|
3126 |
|
3127 |
+
foreach ($key_names as $key_name) {
|
3128 |
+
if (defined($key_name)) {
|
3129 |
+
$key_value = constant($key_name);
|
3130 |
|
3131 |
+
if (stripos($key_value, 'unique phrase') !== false) {
|
3132 |
$response['bad'][ $key_name ] = $key_value;
|
3133 |
} else {
|
3134 |
$response['good'][ $key_name ] = $key_value;
|
3141 |
return $response;
|
3142 |
}
|
3143 |
|
3144 |
+
/**
|
3145 |
+
* Change the reverse proxy setting.
|
3146 |
+
*
|
3147 |
+
* When enabled this option forces the plugin to override the value of the
|
3148 |
+
* global IP address variable from the HTTP header selected by the user from the
|
3149 |
+
* settings. Note that this may also be automatically enabled when the firewall
|
3150 |
+
* page is activated as it assumes that the proxy is creating a custom HTTP
|
3151 |
+
* header for the real IP.
|
3152 |
+
*
|
3153 |
+
* @param string $header Valid HTTP header name.
|
3154 |
+
* @return void
|
3155 |
+
*/
|
3156 |
+
public static function setRevProxy($action = 'disable')
|
3157 |
+
{
|
3158 |
+
$action_d = $action . 'd';
|
3159 |
+
$message = 'Reverse proxy support was <code>' . $action_d . '</code>';
|
3160 |
+
|
3161 |
+
self::update_option(':revproxy', $action_d);
|
3162 |
+
SucuriScanEvent::report_info_event($message);
|
3163 |
+
SucuriScanEvent::notify_event('plugin_change', $message);
|
3164 |
+
SucuriScanInterface::info($message);
|
3165 |
+
}
|
3166 |
+
|
3167 |
+
/**
|
3168 |
+
* Change the HTTP header to retrieve the real IP address.
|
3169 |
+
*
|
3170 |
+
* @param string $header Valid HTTP header name.
|
3171 |
+
* @return void
|
3172 |
+
*/
|
3173 |
+
public static function setAddrHeader($header = 'REMOTE_ADDR')
|
3174 |
+
{
|
3175 |
+
$header = strtoupper($header);
|
3176 |
+
$allowed = SucuriScan::allowedHttpHeaders(true);
|
3177 |
+
|
3178 |
+
if (array_key_exists($header, $allowed)) {
|
3179 |
+
$message = 'HTTP header was set to <code>' . $header . '</code>';
|
3180 |
+
|
3181 |
+
self::update_option(':addr_header', $header);
|
3182 |
+
SucuriScanEvent::report_info_event($message);
|
3183 |
+
SucuriScanEvent::notify_event('plugin_change', $message);
|
3184 |
+
SucuriScanInterface::info($message);
|
3185 |
+
} else {
|
3186 |
+
SucuriScanInterface::error('HTTP header is not in the allowed list');
|
3187 |
+
}
|
3188 |
+
}
|
3189 |
}
|
3190 |
|
3191 |
/**
|
3201 |
* response to events is said to be event-driven, often with the goal of being
|
3202 |
* interactive.
|
3203 |
*
|
3204 |
+
* @see https://en.wikipedia.org/wiki/Event_(computing)
|
3205 |
*/
|
3206 |
+
class SucuriScanEvent extends SucuriScan
|
3207 |
+
{
|
3208 |
|
3209 |
/**
|
3210 |
* Schedule the task to run the first filesystem scan.
|
3211 |
*
|
3212 |
* @return void
|
3213 |
*/
|
3214 |
+
public static function schedule_task()
|
3215 |
+
{
|
3216 |
$task_name = 'sucuriscan_scheduled_scan';
|
3217 |
|
3218 |
+
if (!wp_next_scheduled($task_name)) {
|
3219 |
+
wp_schedule_event(time() + 10, 'twicedaily', $task_name);
|
3220 |
}
|
3221 |
|
3222 |
+
wp_schedule_single_event(time() + 300, $task_name);
|
3223 |
}
|
3224 |
|
3225 |
/**
|
3229 |
* @param boolean $force_scan Whether the filesystem scan was forced by an administrator user or not.
|
3230 |
* @return boolean Either TRUE or FALSE representing the success or fail of the operation respectively.
|
3231 |
*/
|
3232 |
+
private static function verify_run($runtime = 0, $force_scan = false)
|
3233 |
+
{
|
3234 |
$option_name = ':runtime';
|
3235 |
+
$last_run = SucuriScanOption::get_option($option_name);
|
3236 |
$current_time = time();
|
3237 |
|
3238 |
// The filesystem scanner can be disabled from the settings page.
|
3239 |
+
if (SucuriScanOption::is_disabled(':fs_scanner')
|
|
|
3240 |
&& $force_scan === false
|
3241 |
) {
|
3242 |
return false;
|
3243 |
}
|
3244 |
|
3245 |
// Check if the last runtime is too near the current time.
|
3246 |
+
if ($last_run && !$force_scan) {
|
3247 |
$runtime_diff = $current_time - $runtime;
|
3248 |
|
3249 |
+
if ($last_run >= $runtime_diff) {
|
3250 |
return false;
|
3251 |
}
|
3252 |
}
|
3253 |
|
3254 |
+
SucuriScanOption::update_option($option_name, $current_time);
|
3255 |
|
3256 |
return true;
|
3257 |
}
|
3262 |
*
|
3263 |
* @return boolean TRUE if the current WordPress version must be reported, FALSE otherwise.
|
3264 |
*/
|
3265 |
+
private static function report_site_version()
|
3266 |
+
{
|
3267 |
$option_name = ':site_version';
|
3268 |
+
$reported_version = SucuriScanOption::get_option($option_name);
|
3269 |
$wp_version = self::site_version();
|
3270 |
|
3271 |
+
if ($reported_version != $wp_version) {
|
3272 |
+
SucuriScanEvent::report_info_event('WordPress version detected ' . $wp_version);
|
3273 |
+
SucuriScanOption::update_option($option_name, $wp_version);
|
3274 |
|
3275 |
return true;
|
3276 |
}
|
3286 |
* @param boolean $force_scan Whether the filesystem scan was forced by an administrator user or not.
|
3287 |
* @return boolean TRUE if the filesystem scan was successful, FALSE otherwise.
|
3288 |
*/
|
3289 |
+
public static function filesystem_scan($force_scan = false)
|
3290 |
+
{
|
3291 |
$minimum_runtime = SUCURISCAN_MINIMUM_RUNTIME;
|
3292 |
|
3293 |
+
if (self::verify_run($minimum_runtime, $force_scan)
|
3294 |
+
&& class_exists('SucuriScanFileInfo')
|
3295 |
+
&& SucuriScanAPI::getPluginKey()
|
|
|
3296 |
) {
|
3297 |
self::report_site_version();
|
3298 |
|
3299 |
$file_info = new SucuriScanFileInfo();
|
3300 |
+
$file_info->scan_interface = SucuriScanOption::get_option(':scan_interface');
|
3301 |
+
$signatures = $file_info->get_directory_tree_md5(ABSPATH);
|
3302 |
|
3303 |
+
if ($signatures) {
|
3304 |
+
$hashes_sent = SucuriScanAPI::sendHashes($signatures);
|
3305 |
|
3306 |
+
if ($hashes_sent) {
|
3307 |
+
SucuriScanOption::update_option(':runtime', time());
|
3308 |
return true;
|
3309 |
} else {
|
3310 |
+
SucuriScanInterface::error('The file hashes could not be stored.');
|
3311 |
}
|
3312 |
} else {
|
3313 |
+
SucuriScanInterface::error('The file hashes could not be retrieved, the filesystem scan failed.');
|
3314 |
}
|
3315 |
}
|
3316 |
|
3326 |
* @param boolean $internal Whether the event will be publicly visible or not.
|
3327 |
* @return boolean TRUE if the event was logged in the monitoring service, FALSE otherwise.
|
3328 |
*/
|
3329 |
+
private static function report_event($severity = 0, $location = '', $message = '', $internal = false)
|
3330 |
+
{
|
3331 |
$user = wp_get_current_user();
|
3332 |
$username = false;
|
3333 |
+
$current_time = date('Y-m-d H:i:s');
|
3334 |
$remote_ip = self::get_remote_addr();
|
3335 |
|
3336 |
// Identify current user in session.
|
3337 |
+
if ($user instanceof WP_User
|
|
|
3338 |
&& isset($user->user_login)
|
3339 |
+
&& !empty($user->user_login)
|
3340 |
) {
|
3341 |
+
if ($user->user_login != $user->display_name) {
|
3342 |
+
$username = sprintf("\x20%s (%s),", $user->display_name, $user->user_login);
|
3343 |
} else {
|
3344 |
+
$username = sprintf("\x20%s,", $user->user_login);
|
3345 |
}
|
3346 |
}
|
3347 |
|
3349 |
$severity = (int) $severity;
|
3350 |
|
3351 |
// Convert the severity number into a readable string.
|
3352 |
+
switch ($severity) {
|
3353 |
+
case 0:
|
3354 |
+
$severity_name = 'Debug';
|
3355 |
+
break;
|
3356 |
+
case 1:
|
3357 |
+
$severity_name = 'Notice';
|
3358 |
+
break;
|
3359 |
+
case 2:
|
3360 |
+
$severity_name = 'Info';
|
3361 |
+
break;
|
3362 |
+
case 3:
|
3363 |
+
$severity_name = 'Warning';
|
3364 |
+
break;
|
3365 |
+
case 4:
|
3366 |
+
$severity_name = 'Error';
|
3367 |
+
break;
|
3368 |
+
case 5:
|
3369 |
+
$severity_name = 'Critical';
|
3370 |
+
break;
|
3371 |
+
default:
|
3372 |
+
$severity_name = 'Info';
|
3373 |
+
break;
|
3374 |
}
|
3375 |
|
3376 |
// Mark the event as internal if necessary.
|
3377 |
+
if ($internal === true) {
|
3378 |
$severity_name = '@' . $severity_name;
|
3379 |
}
|
3380 |
|
3381 |
// Clear event message.
|
3382 |
+
$message = strip_tags($message);
|
3383 |
+
$message = str_replace("\r", '', $message);
|
3384 |
+
$message = str_replace("\n", '', $message);
|
3385 |
+
$message = str_replace("\t", '', $message);
|
3386 |
|
3387 |
$event_message = sprintf(
|
3388 |
'%s:%s %s; %s',
|
3392 |
$message
|
3393 |
);
|
3394 |
|
3395 |
+
return self::sendEventLog($event_message);
|
3396 |
}
|
3397 |
|
3398 |
+
public static function sendEventLog($event_message = '')
|
3399 |
+
{
|
3400 |
+
/**
|
3401 |
+
* Self-hosted Monitor.
|
3402 |
+
*
|
3403 |
+
* Send a copy of the event log to a local file, this will allow the
|
3404 |
+
* administrator of the server to integrate the events monitored by the plugin
|
3405 |
+
* with a 3rd-party service like OSSEC or similar. More information in the Self-
|
3406 |
+
* Hosting panel located in the plugin' settings page.
|
3407 |
+
*/
|
3408 |
+
if (function_exists('sucuriscan_selfhosting_fpath')) {
|
3409 |
+
$monitor_fpath = sucuriscan_selfhosting_fpath();
|
3410 |
+
|
3411 |
+
if ($monitor_fpath !== false) {
|
3412 |
+
$local_event = sprintf(
|
3413 |
+
"%s WordPressAudit %s %s : %s\n",
|
3414 |
+
date('Y-m-d H:i:s'),
|
3415 |
+
SucuriScan::get_top_level_domain(),
|
3416 |
+
SucuriScanOption::get_option(':account'),
|
3417 |
+
$event_message
|
3418 |
+
);
|
3419 |
+
@file_put_contents(
|
3420 |
+
$monitor_fpath,
|
3421 |
+
$local_event,
|
3422 |
+
FILE_APPEND
|
3423 |
+
);
|
3424 |
+
}
|
3425 |
+
}
|
3426 |
+
|
3427 |
+
if (SucuriScanOption::is_enabled(':api_service')) {
|
3428 |
+
SucuriScanAPI::sendLogsFromQueue();
|
3429 |
+
|
3430 |
+
return SucuriScanAPI::sendLog($event_message);
|
3431 |
+
}
|
3432 |
+
|
3433 |
+
return true;
|
3434 |
+
}
|
3435 |
+
|
3436 |
+
/**
|
3437 |
+
* Reports a debug event on the website.
|
3438 |
+
*
|
3439 |
+
* @param string $message Text witht the explanation of the event or action performed.
|
3440 |
+
* @param boolean $internal Whether the event will be publicly visible or not.
|
3441 |
+
* @return boolean Either true or false depending on the success of the operation.
|
3442 |
+
*/
|
3443 |
+
public static function report_debug_event($message = '', $internal = false)
|
3444 |
+
{
|
3445 |
+
return self::report_event(0, 'core', $message, $internal);
|
3446 |
+
}
|
3447 |
|
3448 |
/**
|
3449 |
* Reports a notice event on the website.
|
3452 |
* @param boolean $internal Whether the event will be publicly visible or not.
|
3453 |
* @return boolean Either true or false depending on the success of the operation.
|
3454 |
*/
|
3455 |
+
public static function report_notice_event($message = '', $internal = false)
|
3456 |
+
{
|
3457 |
+
return self::report_event(1, 'core', $message, $internal);
|
3458 |
}
|
3459 |
|
3460 |
/**
|
3464 |
* @param boolean $internal Whether the event will be publicly visible or not.
|
3465 |
* @return boolean Either true or false depending on the success of the operation.
|
3466 |
*/
|
3467 |
+
public static function report_info_event($message = '', $internal = false)
|
3468 |
+
{
|
3469 |
+
return self::report_event(2, 'core', $message, $internal);
|
3470 |
}
|
3471 |
|
3472 |
/**
|
3476 |
* @param boolean $internal Whether the event will be publicly visible or not.
|
3477 |
* @return boolean Either true or false depending on the success of the operation.
|
3478 |
*/
|
3479 |
+
public static function report_warning_event($message = '', $internal = false)
|
3480 |
+
{
|
3481 |
+
return self::report_event(3, 'core', $message, $internal);
|
3482 |
}
|
3483 |
|
3484 |
/**
|
3488 |
* @param boolean $internal Whether the event will be publicly visible or not.
|
3489 |
* @return boolean Either true or false depending on the success of the operation.
|
3490 |
*/
|
3491 |
+
public static function report_error_event($message = '', $internal = false)
|
3492 |
+
{
|
3493 |
+
return self::report_event(4, 'core', $message, $internal);
|
3494 |
}
|
3495 |
|
3496 |
/**
|
3500 |
* @param boolean $internal Whether the event will be publicly visible or not.
|
3501 |
* @return boolean Either true or false depending on the success of the operation.
|
3502 |
*/
|
3503 |
+
public static function report_critical_event($message = '', $internal = false)
|
3504 |
+
{
|
3505 |
+
return self::report_event(5, 'core', $message, $internal);
|
3506 |
}
|
3507 |
|
3508 |
/**
|
3513 |
* @param boolean $internal Whether the event will be publicly visible or not.
|
3514 |
* @return boolean Either true or false depending on the success of the operation.
|
3515 |
*/
|
3516 |
+
public static function report_auto_event($message = '', $action = '', $internal = false)
|
3517 |
+
{
|
3518 |
+
$message = strip_tags($message);
|
3519 |
|
3520 |
// Auto-detect the action performed, either enabled or disabled.
|
3521 |
+
if (preg_match('/( was )?(enabled|disabled)$/', $message, $match)) {
|
3522 |
$action = $match[2];
|
3523 |
}
|
3524 |
|
3525 |
// Report the correct event for the action performed.
|
3526 |
+
if ($action == 'enabled') {
|
3527 |
+
return self::report_notice_event($message, $internal);
|
3528 |
+
} elseif ($action == 'disabled') {
|
3529 |
+
return self::report_error_event($message, $internal);
|
3530 |
} else {
|
3531 |
+
return self::report_info_event($message, $internal);
|
3532 |
}
|
3533 |
}
|
3534 |
|
3538 |
* @param Exception $exception A valid exception object of any type.
|
3539 |
* @return boolean Whether the report was filled correctly or not.
|
3540 |
*/
|
3541 |
+
public static function report_exception($exception = false)
|
3542 |
+
{
|
3543 |
+
if ($exception) {
|
3544 |
$e_trace = $exception->getTrace();
|
3545 |
$multiple_entries = array();
|
3546 |
|
3547 |
+
foreach ($e_trace as $e_child) {
|
3548 |
+
$e_file = array_key_exists('file', $e_child)
|
3549 |
+
? basename($e_child['file'])
|
3550 |
: '[internal function]';
|
3551 |
+
$e_line = array_key_exists('line', $e_child)
|
3552 |
+
? basename($e_child['line'])
|
3553 |
: '0';
|
3554 |
+
$e_function = array_key_exists('class', $e_child)
|
3555 |
? $e_child['class'] . $e_child['type'] . $e_child['function']
|
3556 |
: $e_child['function'];
|
3557 |
$multiple_entries[] = sprintf(
|
3565 |
$report_message = sprintf(
|
3566 |
'%s: (multiple entries): %s',
|
3567 |
$exception->getMessage(),
|
3568 |
+
@implode(',', $multiple_entries)
|
3569 |
);
|
3570 |
|
3571 |
+
return self::report_debug_event($report_message);
|
3572 |
}
|
3573 |
|
3574 |
return false;
|
3582 |
* @param string $content Body of the email that will be sent to the administrator.
|
3583 |
* @return void
|
3584 |
*/
|
3585 |
+
public static function notify_event($event = '', $content = '')
|
3586 |
+
{
|
3587 |
+
$notify = SucuriScanOption::get_option(':notify_' . $event);
|
3588 |
+
$email = SucuriScanOption::get_option(':notify_to');
|
3589 |
$email_params = array();
|
3590 |
|
3591 |
+
if (self::is_trusted_ip()) {
|
3592 |
$notify = 'disabled';
|
3593 |
}
|
3594 |
|
3595 |
+
if ($notify == 'enabled') {
|
3596 |
+
if ($event == 'post_publication') {
|
3597 |
$event = 'post_update';
|
3598 |
+
} elseif ($event == 'failed_login') {
|
3599 |
+
$settings_url = SucuriScanTemplate::getUrl('settings');
|
3600 |
+
$content .= "<br>\n<br>\n<em>Explanation: Someone failed to login to your "
|
3601 |
+
. "site. If you are getting too many of these messages, it is likely your "
|
3602 |
+
. "site is under a password guessing brute-force attack [1]. You can disable "
|
3603 |
+
. "the failed login alerts from here [2]. Alternatively, you can consider "
|
3604 |
+
. "to install a firewall between your website and your visitors to filter "
|
3605 |
+
. "out these and other attacks, take a look at Sucuri CloudProxy [3].</em>"
|
3606 |
+
. "<br>\n<br>\n"
|
3607 |
+
. "[1] <a href='https://kb.sucuri.net/definitions/attacks/brute-force/password-guessing'>"
|
3608 |
+
. "https://kb.sucuri.net/definitions/attacks/brute-force/password-guessing</a><br>\n"
|
3609 |
+
. "[2] <a href='" . $settings_url . "'>" . $settings_url . "</a> <br>\n"
|
3610 |
+
. "[3] <a href='https://sucuri.net/website-firewall/?wpalert'>"
|
3611 |
+
. "https://sucuri.net/website-firewall/</a> <br>\n";
|
3612 |
+
} elseif ($event == 'bruteforce_attack') {
|
3613 |
// Send a notification even if the limit of emails per hour was reached.
|
3614 |
$email_params['Force'] = true;
|
3615 |
+
} elseif ($event == 'scan_checksums') {
|
3616 |
$event = 'core_integrity_checks';
|
3617 |
$email_params['Force'] = true;
|
3618 |
}
|
3619 |
|
3620 |
+
$title = str_replace('_', "\x20", $event);
|
3621 |
$mail_sent = SucuriScanMail::send_mail(
|
3622 |
$email,
|
3623 |
$title,
|
3637 |
* @param string $remote_addr The supposed ip address that will be checked.
|
3638 |
* @return boolean TRUE if the IP address of the user is trusted, FALSE otherwise.
|
3639 |
*/
|
3640 |
+
private static function is_trusted_ip($remote_addr = '')
|
3641 |
+
{
|
3642 |
+
$cache = new SucuriScanCache('trustip', false);
|
3643 |
+
$trusted_ips = $cache->getAll();
|
3644 |
|
3645 |
+
if (!$remote_addr) {
|
3646 |
$remote_addr = SucuriScan::get_remote_addr();
|
3647 |
}
|
3648 |
|
3649 |
+
$addr_md5 = md5($remote_addr);
|
3650 |
|
3651 |
// Check if the CIDR in range 32 of this IP is trusted.
|
3652 |
+
if (is_array($trusted_ips)
|
3653 |
+
&& !empty($trusted_ips)
|
3654 |
+
&& array_key_exists($addr_md5, $trusted_ips)
|
|
|
3655 |
) {
|
3656 |
return true;
|
3657 |
}
|
3658 |
|
3659 |
+
if ($trusted_ips) {
|
3660 |
+
foreach ($trusted_ips as $cache_key => $ip_info) {
|
3661 |
+
$ip_parts = explode('.', $ip_info->remote_addr);
|
3662 |
$ip_pattern = false;
|
3663 |
|
3664 |
// Generate the regular expression for a specific CIDR range.
|
3665 |
+
switch ($ip_info->cidr_range) {
|
3666 |
case 24:
|
3667 |
+
$ip_pattern = sprintf('/^%d\.%d\.%d\.[0-9]{1,3}$/', $ip_parts[0], $ip_parts[1], $ip_parts[2]);
|
3668 |
break;
|
3669 |
case 16:
|
3670 |
+
$ip_pattern = sprintf('/^%d\.%d(\.[0-9]{1,3}) {2}$/', $ip_parts[0], $ip_parts[1]);
|
3671 |
break;
|
3672 |
case 8:
|
3673 |
+
$ip_pattern = sprintf('/^%d(\.[0-9]{1,3}) {3}$/', $ip_parts[0]);
|
3674 |
break;
|
3675 |
}
|
3676 |
|
3677 |
+
if ($ip_pattern && preg_match($ip_pattern, $remote_addr)) {
|
3678 |
return true;
|
3679 |
}
|
3680 |
}
|
3689 |
* @param integer $user_id The user identifier that will be changed, this must be different than the user in session.
|
3690 |
* @return boolean Either TRUE or FALSE in case of success or error respectively.
|
3691 |
*/
|
3692 |
+
public static function set_new_password($user_id = 0)
|
3693 |
+
{
|
3694 |
+
$user_id = intval($user_id);
|
3695 |
|
3696 |
+
if ($user_id > 0 && function_exists('wp_generate_password')) {
|
3697 |
+
$user = get_userdata($user_id);
|
3698 |
|
3699 |
+
if ($user instanceof WP_User) {
|
3700 |
$website = SucuriScan::get_domain();
|
3701 |
$user_login = $user->user_login;
|
3702 |
$display_name = $user->display_name;
|
3703 |
+
$new_password = wp_generate_password(15, true, false);
|
3704 |
|
3705 |
+
$message = SucuriScanTemplate::getSection('notification-resetpwd', array(
|
3706 |
'ResetPassword.UserName' => $user_login,
|
3707 |
'ResetPassword.DisplayName' => $display_name,
|
3708 |
'ResetPassword.Password' => $new_password,
|
3709 |
'ResetPassword.Website' => $website,
|
3710 |
+
));
|
3711 |
|
3712 |
$data_set = array( 'Force' => true ); // Skip limit for emails per hour.
|
3713 |
+
SucuriScanMail::send_mail($user->user_email, 'Password changed', $message, $data_set);
|
3714 |
|
3715 |
+
wp_set_password($new_password, $user_id);
|
3716 |
|
3717 |
return true;
|
3718 |
}
|
3730 |
*
|
3731 |
* @return false|array Either FALSE in case of error, or an array with the old and new keys.
|
3732 |
*/
|
3733 |
+
public static function set_new_config_keys()
|
3734 |
+
{
|
3735 |
$new_wpconfig = '';
|
3736 |
$config_path = self::get_wpconfig_path();
|
3737 |
|
3738 |
+
if ($config_path) {
|
3739 |
$pattern = self::secret_key_pattern();
|
3740 |
$define_tpl = "define('%s',%s'%s');";
|
3741 |
+
$config_lines = SucuriScanFileInfo::file_lines($config_path);
|
3742 |
+
$new_keys = SucuriScanAPI::getNewSecretKeys();
|
3743 |
$old_keys = array();
|
3744 |
$old_keys_string = '';
|
3745 |
$new_keys_string = '';
|
3746 |
|
3747 |
+
foreach ((array) $config_lines as $config_line) {
|
3748 |
+
if (preg_match($pattern, $config_line, $match)) {
|
3749 |
$key_name = $match[1];
|
3750 |
|
3751 |
+
if (array_key_exists($key_name, $new_keys)) {
|
3752 |
$white_spaces = $match[2];
|
3753 |
$old_keys[ $key_name ] = $match[3];
|
3754 |
+
$config_line = sprintf($define_tpl, $key_name, $white_spaces, $new_keys[ $key_name ]);
|
3755 |
+
$old_keys_string .= sprintf($define_tpl, $key_name, $white_spaces, $old_keys[ $key_name ]) . "\n";
|
3756 |
$new_keys_string .= $config_line . "\n";
|
3757 |
}
|
3758 |
}
|
3761 |
}
|
3762 |
|
3763 |
$response = array(
|
3764 |
+
'updated' => is_writable($config_path),
|
3765 |
'old_keys' => $old_keys,
|
3766 |
'old_keys_string' => $old_keys_string,
|
3767 |
'new_keys' => $new_keys,
|
3769 |
'new_wpconfig' => $new_wpconfig,
|
3770 |
);
|
3771 |
|
3772 |
+
if ($response['updated']) {
|
3773 |
+
file_put_contents($config_path, $new_wpconfig, LOCK_EX);
|
3774 |
}
|
3775 |
|
3776 |
return $response;
|
3778 |
|
3779 |
return false;
|
3780 |
}
|
|
|
3781 |
}
|
3782 |
|
3783 |
/**
|
3795 |
* calls in order to monitor behavior or modify the function of an application
|
3796 |
* or other component; it is also widely used in benchmarking programs.
|
3797 |
*/
|
3798 |
+
class SucuriScanHook extends SucuriScanEvent
|
3799 |
+
{
|
3800 |
|
3801 |
/**
|
3802 |
* Send to Sucuri servers an alert notifying that an attachment was added to a post.
|
3804 |
* @param integer $id The post identifier.
|
3805 |
* @return void
|
3806 |
*/
|
3807 |
+
public static function hook_add_attachment($id = 0)
|
3808 |
+
{
|
3809 |
+
if ($data = get_post($id)) {
|
3810 |
$id = $data->ID;
|
3811 |
$title = $data->post_title;
|
3812 |
$mime_type = $data->post_mime_type;
|
3815 |
$mime_type = 'unknown';
|
3816 |
}
|
3817 |
|
3818 |
+
$message = sprintf('Media file added; identifier: %s; name: %s; type: %s', $id, $title, $mime_type);
|
3819 |
+
self::report_notice_event($message);
|
3820 |
+
self::notify_event('post_publication', $message);
|
3821 |
}
|
3822 |
|
3823 |
/**
|
3826 |
* @param integer $id Identifier of the new link created;
|
3827 |
* @return void
|
3828 |
*/
|
3829 |
+
public static function hook_add_link($id = 0)
|
3830 |
+
{
|
3831 |
+
if ($data = get_bookmark($id)) {
|
3832 |
$id = $data->link_id;
|
3833 |
$title = $data->link_name;
|
3834 |
$url = $data->link_url;
|
3841 |
|
3842 |
$message = sprintf(
|
3843 |
'Bookmark link added; identifier: %s; name: %s; url: %s; target: %s',
|
3844 |
+
$id,
|
3845 |
+
$title,
|
3846 |
+
$url,
|
3847 |
+
$target
|
3848 |
);
|
3849 |
+
self::report_warning_event($message);
|
3850 |
+
self::notify_event('post_publication', $message);
|
3851 |
}
|
3852 |
|
3853 |
/**
|
3856 |
* @param integer $id The identifier of the category created.
|
3857 |
* @return void
|
3858 |
*/
|
3859 |
+
public static function hook_create_category($id = 0)
|
3860 |
+
{
|
3861 |
+
$title = ( is_int($id) ? get_cat_name($id) : 'Unknown' );
|
3862 |
|
3863 |
+
$message = sprintf('Category created; identifier: %s; name: %s', $id, $title);
|
3864 |
+
self::report_notice_event($message);
|
3865 |
+
self::notify_event('post_publication', $message);
|
3866 |
}
|
3867 |
|
3868 |
/**
|
3871 |
* @param integer $id The identifier of the post deleted.
|
3872 |
* @return void
|
3873 |
*/
|
3874 |
+
public static function hook_delete_post($id = 0)
|
3875 |
+
{
|
3876 |
+
self::report_warning_event('Post deleted; identifier: ' . $id);
|
3877 |
}
|
3878 |
|
3879 |
/**
|
3882 |
* @param integer $id The identifier of the trashed post.
|
3883 |
* @return void
|
3884 |
*/
|
3885 |
+
public static function hook_wp_trash_post($id = 0)
|
3886 |
+
{
|
3887 |
+
if ($data = get_post($id)) {
|
3888 |
$title = $data->post_title;
|
3889 |
$status = $data->post_status;
|
3890 |
} else {
|
3894 |
|
3895 |
$message = sprintf(
|
3896 |
'Post moved to trash; identifier: %s; name: %s; status: %s',
|
3897 |
+
$id,
|
3898 |
+
$title,
|
3899 |
+
$status
|
3900 |
);
|
3901 |
+
self::report_warning_event($message);
|
3902 |
}
|
3903 |
|
3904 |
/**
|
3907 |
* @param integer $id The identifier of the user account deleted.
|
3908 |
* @return void
|
3909 |
*/
|
3910 |
+
public static function hook_delete_user($id = 0)
|
3911 |
+
{
|
3912 |
+
self::report_warning_event('User account deleted; identifier: ' . $id);
|
3913 |
}
|
3914 |
|
3915 |
/**
|
3918 |
*
|
3919 |
* @return void
|
3920 |
*/
|
3921 |
+
public static function hook_login_form_resetpass()
|
3922 |
+
{
|
3923 |
// Detecting WordPress 2.8.3 vulnerability - $key is array.
|
3924 |
+
if (isset($_GET['key']) && is_array($_GET['key'])) {
|
3925 |
+
self::report_critical_event('Attempt to reset password by attacking WP/2.8.3 bug');
|
3926 |
}
|
3927 |
}
|
3928 |
|
3933 |
* @param integer $id The identifier of the post changed.
|
3934 |
* @return void
|
3935 |
*/
|
3936 |
+
public static function hook_private_to_published($id = 0)
|
3937 |
+
{
|
3938 |
+
if ($data = get_post($id)) {
|
3939 |
$title = $data->post_title;
|
3940 |
+
$p_type = ucwords($data->post_type);
|
3941 |
} else {
|
3942 |
$title = 'Unknown';
|
3943 |
$p_type = 'Publication';
|
3944 |
}
|
3945 |
|
3946 |
// Check whether the post-type is being ignored to send notifications.
|
3947 |
+
if (!SucuriScanOption::is_ignored_event($p_type)) {
|
3948 |
$message = sprintf(
|
3949 |
'%s (private to published); identifier: %s; name: %s',
|
3950 |
+
$p_type,
|
3951 |
+
$id,
|
3952 |
+
$title
|
3953 |
);
|
3954 |
+
self::report_notice_event($message);
|
3955 |
+
self::notify_event('post_publication', $message);
|
3956 |
}
|
3957 |
}
|
3958 |
|
3962 |
* @param integer $id The identifier of the post or page published.
|
3963 |
* @return void
|
3964 |
*/
|
3965 |
+
public static function hook_publish($id = 0)
|
3966 |
+
{
|
3967 |
+
if ($data = get_post($id)) {
|
3968 |
$title = $data->post_title;
|
3969 |
+
$p_type = ucwords($data->post_type);
|
3970 |
$action = ( $data->post_date == $data->post_modified ? 'created' : 'updated' );
|
3971 |
} else {
|
3972 |
$title = 'Unknown';
|
3976 |
|
3977 |
$message = sprintf(
|
3978 |
'%s was %s; identifier: %s; name: %s',
|
3979 |
+
$p_type,
|
3980 |
+
$action,
|
3981 |
+
$id,
|
3982 |
+
$title
|
3983 |
);
|
3984 |
+
self::report_notice_event($message);
|
3985 |
+
self::notify_event('post_publication', $message);
|
3986 |
}
|
3987 |
|
3988 |
/**
|
3991 |
* @param integer $id The identifier of the post or page published.
|
3992 |
* @return void
|
3993 |
*/
|
3994 |
+
public static function hook_publish_page($id = 0)
|
3995 |
+
{
|
3996 |
+
self::hook_publish($id);
|
3997 |
}
|
3998 |
|
3999 |
/**
|
4002 |
* @param integer $id The identifier of the post or page published.
|
4003 |
* @return void
|
4004 |
*/
|
4005 |
+
public static function hook_publish_post($id = 0)
|
4006 |
+
{
|
4007 |
+
self::hook_publish($id);
|
4008 |
}
|
4009 |
|
4010 |
/**
|
4013 |
* @param integer $id The identifier of the post or page published.
|
4014 |
* @return void
|
4015 |
*/
|
4016 |
+
public static function hook_publish_phone($id = 0)
|
4017 |
+
{
|
4018 |
+
self::hook_publish($id);
|
4019 |
}
|
4020 |
|
4021 |
/**
|
4024 |
* @param integer $id The identifier of the post or page published.
|
4025 |
* @return void
|
4026 |
*/
|
4027 |
+
public static function hook_xmlrpc_publish_post($id = 0)
|
4028 |
+
{
|
4029 |
+
self::hook_publish($id);
|
4030 |
}
|
4031 |
|
4032 |
/**
|
4036 |
* @param string $title The name of the user account involved in the trasaction.
|
4037 |
* @return void
|
4038 |
*/
|
4039 |
+
public static function hook_retrieve_password($title = '')
|
4040 |
+
{
|
4041 |
+
if (empty($title)) {
|
4042 |
$title = 'unknown';
|
4043 |
}
|
4044 |
|
4045 |
+
self::report_error_event('Password retrieval attempt: ' . $title);
|
4046 |
}
|
4047 |
|
4048 |
/**
|
4051 |
* @param string $title The name of the new theme selected to used through out the site.
|
4052 |
* @return void
|
4053 |
*/
|
4054 |
+
public static function hook_switch_theme($title = '')
|
4055 |
+
{
|
4056 |
+
if (empty($title)) {
|
4057 |
$title = 'unknown';
|
4058 |
}
|
4059 |
|
4060 |
$message = 'Theme activated: ' . $title;
|
4061 |
+
self::report_warning_event($message);
|
4062 |
+
self::notify_event('theme_activated', $message);
|
4063 |
}
|
4064 |
|
4065 |
/**
|
4068 |
* @param integer $id The identifier of the new user account created.
|
4069 |
* @return void
|
4070 |
*/
|
4071 |
+
public static function hook_user_register($id = 0)
|
4072 |
+
{
|
4073 |
+
if ($data = get_userdata($id)) {
|
4074 |
$title = $data->user_login;
|
4075 |
$email = $data->user_email;
|
4076 |
+
$roles = @implode(', ', $data->roles);
|
4077 |
} else {
|
4078 |
$title = 'unknown';
|
4079 |
$email = 'user@domain.com';
|
4082 |
|
4083 |
$message = sprintf(
|
4084 |
'User account created; identifier: %s; name: %s; email: %s; roles: %s',
|
4085 |
+
$id,
|
4086 |
+
$title,
|
4087 |
+
$email,
|
4088 |
+
$roles
|
4089 |
);
|
4090 |
+
self::report_warning_event($message);
|
4091 |
+
self::notify_event('user_registration', $message);
|
4092 |
}
|
4093 |
|
4094 |
/**
|
4098 |
* @param string $title The name of the user account involved in the transaction.
|
4099 |
* @return void
|
4100 |
*/
|
4101 |
+
public static function hook_wp_login($title = '')
|
4102 |
+
{
|
4103 |
+
if (empty($title)) {
|
4104 |
$title = 'Unknown';
|
4105 |
}
|
4106 |
|
4107 |
$message = 'User authentication succeeded: ' . $title;
|
4108 |
+
self::report_notice_event($message);
|
4109 |
+
self::notify_event('success_login', $message);
|
4110 |
}
|
4111 |
|
4112 |
/**
|
4116 |
* @param string $title The name of the user account involved in the transaction.
|
4117 |
* @return void
|
4118 |
*/
|
4119 |
+
public static function hook_wp_login_failed($title = '')
|
4120 |
+
{
|
4121 |
+
if (empty($title)) {
|
4122 |
$title = 'Unknown';
|
4123 |
}
|
4124 |
|
4125 |
+
$title = sanitize_user($title, true);
|
4126 |
+
$password = SucuriScanRequest::post('pwd');
|
4127 |
$message = 'User authentication failed: ' . $title;
|
4128 |
|
4129 |
+
self::report_error_event($message);
|
4130 |
|
4131 |
+
if (sucuriscan_collect_wrong_passwords() === true) {
|
4132 |
$message .= "<br>\nUser wrong password: " . $password;
|
4133 |
}
|
4134 |
|
4135 |
+
self::notify_event('failed_login', $message);
|
4136 |
|
4137 |
// Log the failed login in the internal datastore for future reports.
|
4138 |
+
$logged = sucuriscan_log_failed_login($title, $password);
|
4139 |
|
4140 |
// Check if the quantity of failed logins will be considered as a brute-force attack.
|
4141 |
+
if ($logged) {
|
4142 |
$failed_logins = sucuriscan_get_failed_logins();
|
4143 |
|
4144 |
+
if ($failed_logins) {
|
4145 |
$max_time = 3600;
|
4146 |
+
$maximum_failed_logins = SucuriScanOption::get_option('sucuriscan_maximum_failed_logins');
|
4147 |
|
4148 |
/**
|
4149 |
* If the time passed is within the hour, and the quantity of failed logins
|
4152 |
* settings page), then send an email notification reporting the event and
|
4153 |
* specifying that it may be a brute-force attack against the login page.
|
4154 |
*/
|
4155 |
+
if ($failed_logins['diff_time'] <= $max_time
|
|
|
4156 |
&& $failed_logins['count'] >= $maximum_failed_logins
|
4157 |
) {
|
4158 |
+
sucuriscan_report_failed_logins($failed_logins);
|
4159 |
+
} /**
|
|
|
|
|
4160 |
* If there time passed is superior to the hour, then reset the content of the
|
4161 |
* datastore file containing the failed logins so far, any entry in that file
|
4162 |
* will not be considered as part of a brute-force attack (if it exists) because
|
4165 |
* first entry of that file in case of future attempts during the next sixty
|
4166 |
* minutes.
|
4167 |
*/
|
4168 |
+
elseif ($failed_logins['diff_time'] > $max_time) {
|
4169 |
sucuriscan_reset_failed_logins();
|
4170 |
+
sucuriscan_log_failed_login($title);
|
4171 |
}
|
4172 |
}
|
4173 |
}
|
4189 |
* @param object $comment The comment object.
|
4190 |
* @return void
|
4191 |
*/
|
4192 |
+
public static function hook_wp_insert_comment($id = 0, $comment = false)
|
4193 |
+
{
|
4194 |
+
if ($comment instanceof stdClass
|
4195 |
+
&& property_exists($comment, 'comment_ID')
|
4196 |
+
&& property_exists($comment, 'comment_agent')
|
4197 |
+
&& property_exists($comment, 'comment_author_IP')
|
4198 |
+
&& SucuriScanOption::is_enabled(':comment_monitor')
|
4199 |
) {
|
4200 |
$data_set = array(
|
4201 |
'id' => $comment->comment_ID,
|
4209 |
'content' => $comment->comment_content,
|
4210 |
'user_agent' => $comment->comment_agent,
|
4211 |
);
|
4212 |
+
$message = base64_encode(json_encode($data_set));
|
4213 |
+
self::report_notice_event('Base64:' . $message, true);
|
4214 |
}
|
4215 |
}
|
4216 |
|
4226 |
*
|
4227 |
* @return void
|
4228 |
*/
|
4229 |
+
public static function hook_all($action = null, $data = false)
|
4230 |
+
{
|
4231 |
global $wp_filter, $wp_actions;
|
4232 |
|
4233 |
+
if (is_array($wp_filter)
|
4234 |
+
&& is_array($wp_actions)
|
4235 |
+
&& array_key_exists($action, $wp_actions)
|
4236 |
+
&& !array_key_exists($action, $wp_filter)
|
|
|
4237 |
&& (
|
4238 |
+
substr($action, 0, 11) === 'admin_post_'
|
4239 |
+
|| substr($action, 0, 8) === 'wp_ajax_'
|
4240 |
)
|
4241 |
) {
|
4242 |
+
$message = sprintf('Undefined XHR action %s', $action);
|
4243 |
+
self::report_error_event($message);
|
4244 |
+
header('HTTP/1.1 400 Bad Request');
|
4245 |
exit(1);
|
4246 |
}
|
4247 |
}
|
4253 |
*
|
4254 |
* @return integer Either one or zero representing the success or fail of the operation.
|
4255 |
*/
|
4256 |
+
public static function hook_undefined_actions()
|
4257 |
+
{
|
4258 |
|
4259 |
$plugin_activate_actions = '(activate|deactivate)(\-selected)?';
|
4260 |
$plugin_update_actions = '(upgrade-plugin|do-plugin-upgrade|update-selected)';
|
4261 |
|
4262 |
// Plugin activation and/or deactivation.
|
4263 |
+
if (current_user_can('activate_plugins')
|
|
|
4264 |
&& (
|
4265 |
+
SucuriScanRequest::get_or_post('action', $plugin_activate_actions)
|
4266 |
+
|| SucuriScanRequest::get_or_post('action2', $plugin_activate_actions)
|
4267 |
)
|
4268 |
) {
|
4269 |
$plugin_list = array();
|
4270 |
$items_affected = array();
|
4271 |
|
4272 |
// Get the action performed through action or action2 params.
|
4273 |
+
$action_d = SucuriScanRequest::get_or_post('action');
|
4274 |
+
if ($action_d == '-1') {
|
4275 |
+
$action_d = SucuriScanRequest::get_or_post('action2');
|
4276 |
}
|
4277 |
$action_d .= 'd';
|
4278 |
|
4279 |
+
if (SucuriScanRequest::get('plugin', '.+')
|
4280 |
+
&& strpos($_SERVER['REQUEST_URI'], 'plugins.php') !== false
|
|
|
4281 |
) {
|
4282 |
+
$plugin_list[] = SucuriScanRequest::get('plugin');
|
4283 |
+
} elseif (isset($_POST['checked'])
|
4284 |
+
&& is_array($_POST['checked'])
|
4285 |
+
&& !empty($_POST['checked'])
|
|
|
|
|
|
|
4286 |
) {
|
4287 |
+
$plugin_list = SucuriScanRequest::post('checked', '_array');
|
4288 |
+
$action_d = str_replace('-selected', '', $action_d);
|
4289 |
}
|
4290 |
|
4291 |
+
foreach ($plugin_list as $plugin) {
|
4292 |
+
$plugin_info = get_plugin_data(WP_PLUGIN_DIR . '/' . $plugin);
|
4293 |
|
4294 |
+
if (!empty($plugin_info['Name'])
|
4295 |
+
&& !empty($plugin_info['Version'])
|
|
|
4296 |
) {
|
4297 |
$items_affected[] = sprintf(
|
4298 |
'%s (v%s; %s)',
|
4299 |
+
self::escape($plugin_info['Name']),
|
4300 |
+
self::escape($plugin_info['Version']),
|
4301 |
+
self::escape($plugin)
|
4302 |
);
|
4303 |
}
|
4304 |
}
|
4305 |
|
4306 |
// Report activated/deactivated plugins at once.
|
4307 |
+
if (!empty($items_affected)) {
|
4308 |
+
$message_tpl = ( count($items_affected) > 1 )
|
4309 |
? 'Plugins %s: (multiple entries): %s'
|
4310 |
: 'Plugin %s: %s';
|
4311 |
$message = sprintf(
|
4312 |
$message_tpl,
|
4313 |
$action_d,
|
4314 |
+
@implode(',', $items_affected)
|
4315 |
);
|
4316 |
+
self::report_warning_event($message);
|
4317 |
+
self::notify_event('plugin_' . $action_d, $message);
|
4318 |
}
|
4319 |
+
} // Plugin update request.
|
4320 |
+
elseif (current_user_can('update_plugins')
|
|
|
|
|
|
|
4321 |
&& (
|
4322 |
+
SucuriScanRequest::get_or_post('action', $plugin_update_actions)
|
4323 |
+
|| SucuriScanRequest::get_or_post('action2', $plugin_update_actions)
|
4324 |
)
|
4325 |
) {
|
4326 |
$plugin_list = array();
|
4327 |
$items_affected = array();
|
4328 |
|
4329 |
+
if (SucuriScanRequest::get('plugin', '.+')
|
4330 |
+
&& strpos($_SERVER['REQUEST_URI'], 'wp-admin/update.php') !== false
|
|
|
4331 |
) {
|
4332 |
+
$plugin_list[] = SucuriScanRequest::get('plugin', '.+');
|
4333 |
+
} elseif (isset($_POST['checked'])
|
4334 |
+
&& is_array($_POST['checked'])
|
4335 |
+
&& !empty($_POST['checked'])
|
|
|
|
|
|
|
4336 |
) {
|
4337 |
+
$plugin_list = SucuriScanRequest::post('checked', '_array');
|
4338 |
}
|
4339 |
|
4340 |
+
foreach ($plugin_list as $plugin) {
|
4341 |
+
$plugin_info = get_plugin_data(WP_PLUGIN_DIR . '/' . $plugin);
|
4342 |
|
4343 |
+
if (!empty($plugin_info['Name'])
|
4344 |
+
&& !empty($plugin_info['Version'])
|
|
|
4345 |
) {
|
4346 |
$items_affected[] = sprintf(
|
4347 |
'%s (v%s; %s)',
|
4348 |
+
self::escape($plugin_info['Name']),
|
4349 |
+
self::escape($plugin_info['Version']),
|
4350 |
+
self::escape($plugin)
|
4351 |
);
|
4352 |
}
|
4353 |
}
|
4354 |
|
4355 |
// Report updated plugins at once.
|
4356 |
+
if (!empty($items_affected)) {
|
4357 |
+
$message_tpl = ( count($items_affected) > 1 )
|
4358 |
? 'Plugins updated: (multiple entries): %s'
|
4359 |
: 'Plugin updated: %s';
|
4360 |
$message = sprintf(
|
4361 |
$message_tpl,
|
4362 |
+
@implode(',', $items_affected)
|
4363 |
);
|
4364 |
+
self::report_warning_event($message);
|
4365 |
+
self::notify_event('plugin_updated', $message);
|
4366 |
}
|
4367 |
+
} // Plugin installation request.
|
4368 |
+
elseif (current_user_can('install_plugins')
|
4369 |
+
&& SucuriScanRequest::get('action', '(install|upload)-plugin')
|
|
|
|
|
|
|
4370 |
) {
|
4371 |
+
if (isset($_FILES['pluginzip'])) {
|
4372 |
+
$plugin = self::escape($_FILES['pluginzip']['name']);
|
4373 |
} else {
|
4374 |
+
$plugin = SucuriScanRequest::get('plugin', '.+');
|
4375 |
|
4376 |
+
if (!$plugin) {
|
4377 |
$plugin = 'Unknown';
|
4378 |
}
|
4379 |
}
|
4380 |
|
4381 |
+
$message = 'Plugin installed: ' . self::escape($plugin);
|
4382 |
+
SucuriScanEvent::report_warning_event($message);
|
4383 |
+
self::notify_event('plugin_installed', $message);
|
4384 |
+
} // Plugin deletion request.
|
4385 |
+
elseif (current_user_can('delete_plugins')
|
4386 |
+
&& SucuriScanRequest::post('action', 'delete-selected')
|
4387 |
+
&& SucuriScanRequest::post('verify-delete', '1')
|
|
|
|
|
|
|
4388 |
) {
|
4389 |
+
$plugin_list = SucuriScanRequest::post('checked', '_array');
|
4390 |
$items_affected = array();
|
4391 |
|
4392 |
+
foreach ((array) $plugin_list as $plugin) {
|
4393 |
+
$plugin_info = get_plugin_data(WP_PLUGIN_DIR . '/' . $plugin);
|
4394 |
|
4395 |
+
if (!empty($plugin_info['Name'])
|
4396 |
+
&& !empty($plugin_info['Version'])
|
|
|
4397 |
) {
|
4398 |
$items_affected[] = sprintf(
|
4399 |
'%s (v%s; %s)',
|
4400 |
+
self::escape($plugin_info['Name']),
|
4401 |
+
self::escape($plugin_info['Version']),
|
4402 |
+
self::escape($plugin)
|
4403 |
);
|
4404 |
}
|
4405 |
}
|
4406 |
|
4407 |
// Report deleted plugins at once.
|
4408 |
+
if (!empty($items_affected)) {
|
4409 |
+
$message_tpl = ( count($items_affected) > 1 )
|
4410 |
? 'Plugins deleted: (multiple entries): %s'
|
4411 |
: 'Plugin deleted: %s';
|
4412 |
$message = sprintf(
|
4413 |
$message_tpl,
|
4414 |
+
@implode(',', $items_affected)
|
4415 |
);
|
4416 |
+
self::report_warning_event($message);
|
4417 |
+
self::notify_event('plugin_deleted', $message);
|
4418 |
+
}
|
4419 |
+
} // Plugin editor request.
|
4420 |
+
elseif (current_user_can('edit_plugins')
|
4421 |
+
&& SucuriScanRequest::post('action', 'update')
|
4422 |
+
&& SucuriScanRequest::post('plugin', '.+')
|
4423 |
+
&& SucuriScanRequest::post('file', '.+')
|
4424 |
+
&& strpos($_SERVER['REQUEST_URI'], 'plugin-editor.php') !== false
|
|
|
|
|
|
|
4425 |
) {
|
4426 |
+
$filename = SucuriScanRequest::post('file');
|
4427 |
+
$message = 'Plugin editor used in: ' . SucuriScan::escape($filename);
|
4428 |
+
self::report_error_event($message);
|
4429 |
+
self::notify_event('theme_editor', $message);
|
4430 |
+
} // Theme editor request.
|
4431 |
+
elseif (current_user_can('edit_themes')
|
4432 |
+
&& SucuriScanRequest::post('action', 'update')
|
4433 |
+
&& SucuriScanRequest::post('theme', '.+')
|
4434 |
+
&& SucuriScanRequest::post('file', '.+')
|
4435 |
+
&& strpos($_SERVER['REQUEST_URI'], 'theme-editor.php') !== false
|
|
|
|
|
|
|
4436 |
) {
|
4437 |
+
$theme_name = SucuriScanRequest::post('theme');
|
4438 |
+
$filename = SucuriScanRequest::post('file');
|
4439 |
+
$message = 'Theme editor used in: ' . SucuriScan::escape($theme_name) . '/' . SucuriScan::escape($filename);
|
4440 |
+
self::report_error_event($message);
|
4441 |
+
self::notify_event('theme_editor', $message);
|
4442 |
+
} // Theme installation request.
|
4443 |
+
elseif (current_user_can('install_themes')
|
4444 |
+
&& SucuriScanRequest::get('action', 'install-theme')
|
|
|
|
|
|
|
4445 |
) {
|
4446 |
+
$theme = SucuriScanRequest::get('theme', '.+');
|
4447 |
|
4448 |
+
if (!$theme) {
|
4449 |
$theme = 'Unknown';
|
4450 |
}
|
4451 |
|
4452 |
+
$message = 'Theme installed: ' . self::escape($theme);
|
4453 |
+
SucuriScanEvent::report_warning_event($message);
|
4454 |
+
self::notify_event('theme_installed', $message);
|
4455 |
+
} // Theme deletion request.
|
4456 |
+
elseif (current_user_can('delete_themes')
|
4457 |
+
&& SucuriScanRequest::get_or_post('action', 'delete')
|
4458 |
+
&& SucuriScanRequest::get_or_post('stylesheet', '.+')
|
|
|
|
|
|
|
4459 |
) {
|
4460 |
+
$theme = SucuriScanRequest::get('stylesheet', '.+');
|
4461 |
|
4462 |
+
if (!$theme) {
|
4463 |
$theme = 'Unknown';
|
4464 |
}
|
4465 |
|
4466 |
+
$message = 'Theme deleted: ' . self::escape($theme);
|
4467 |
+
SucuriScanEvent::report_warning_event($message);
|
4468 |
+
self::notify_event('theme_deleted', $message);
|
4469 |
+
} // Theme update request.
|
4470 |
+
elseif (current_user_can('update_themes')
|
4471 |
+
&& SucuriScanRequest::get('action', '(upgrade-theme|do-theme-upgrade)')
|
4472 |
+
&& SucuriScanRequest::post('checked', '_array')
|
|
|
|
|
|
|
4473 |
) {
|
4474 |
+
$themes = SucuriScanRequest::post('checked', '_array');
|
4475 |
$items_affected = array();
|
4476 |
|
4477 |
+
foreach ((array) $themes as $theme) {
|
4478 |
+
$theme_info = wp_get_theme($theme);
|
4479 |
+
$theme_name = ucwords($theme);
|
4480 |
$theme_version = '0.0';
|
4481 |
|
4482 |
+
if ($theme_info->exists()) {
|
4483 |
+
$theme_name = $theme_info->get('Name');
|
4484 |
+
$theme_version = $theme_info->get('Version');
|
4485 |
}
|
4486 |
|
4487 |
$items_affected[] = sprintf(
|
4488 |
'%s (v%s; %s)',
|
4489 |
+
self::escape($theme_name),
|
4490 |
+
self::escape($theme_version),
|
4491 |
+
self::escape($theme)
|
4492 |
);
|
4493 |
}
|
4494 |
|
4495 |
// Report updated themes at once.
|
4496 |
+
if (!empty($items_affected)) {
|
4497 |
+
$message_tpl = ( count($items_affected) > 1 )
|
4498 |
? 'Themes updated: (multiple entries): %s'
|
4499 |
: 'Theme updated: %s';
|
4500 |
$message = sprintf(
|
4501 |
$message_tpl,
|
4502 |
+
@implode(',', $items_affected)
|
4503 |
);
|
4504 |
+
self::report_warning_event($message);
|
4505 |
+
self::notify_event('theme_updated', $message);
|
4506 |
}
|
4507 |
+
} // WordPress update request.
|
4508 |
+
elseif (current_user_can('update_core')
|
4509 |
+
&& SucuriScanRequest::get('action', '(do-core-upgrade|do-core-reinstall)')
|
4510 |
+
&& SucuriScanRequest::post('upgrade')
|
|
|
|
|
|
|
4511 |
) {
|
4512 |
+
$message = 'WordPress updated to version: ' . SucuriScanRequest::post('version');
|
4513 |
+
self::report_critical_event($message);
|
4514 |
+
self::notify_event('website_updated', $message);
|
4515 |
+
} // Widget addition or deletion.
|
4516 |
+
elseif (current_user_can('edit_theme_options')
|
4517 |
+
&& SucuriScanRequest::post('action', 'save-widget')
|
4518 |
+
&& SucuriScanRequest::post('id_base') !== false
|
4519 |
+
&& SucuriScanRequest::post('sidebar') !== false
|
|
|
|
|
|
|
4520 |
) {
|
4521 |
+
if (SucuriScanRequest::post('delete_widget', '1')) {
|
4522 |
$action_d = 'deleted';
|
4523 |
$action_text = 'deleted from';
|
4524 |
} else {
|
4528 |
|
4529 |
$message = sprintf(
|
4530 |
'Widget %s (%s) %s %s (#%d; size %dx%d)',
|
4531 |
+
SucuriScanRequest::post('id_base'),
|
4532 |
+
SucuriScanRequest::post('widget-id'),
|
4533 |
$action_text,
|
4534 |
+
SucuriScanRequest::post('sidebar'),
|
4535 |
+
SucuriScanRequest::post('widget_number'),
|
4536 |
+
SucuriScanRequest::post('widget-width'),
|
4537 |
+
SucuriScanRequest::post('widget-height')
|
4538 |
);
|
4539 |
|
4540 |
+
self::report_warning_event($message);
|
4541 |
+
self::notify_event('widget_' . $action_d, $message);
|
4542 |
+
} // Detect any Wordpress settings modification.
|
4543 |
+
elseif (current_user_can('manage_options')
|
|
|
|
|
|
|
4544 |
&& SucuriScanOption::check_options_nonce()
|
4545 |
) {
|
4546 |
// Get the settings available in the database and compare them with the submission.
|
4547 |
+
$options_changed = SucuriScanOption::what_options_were_changed($_POST);
|
4548 |
$options_changed_str = '';
|
4549 |
$options_changed_simple = '';
|
4550 |
$options_changed_count = 0;
|
4551 |
|
4552 |
// Generate the list of options changed.
|
4553 |
+
foreach ($options_changed['original'] as $option_name => $option_value) {
|
4554 |
$options_changed_count += 1;
|
4555 |
$options_changed_str .= sprintf(
|
4556 |
"The value of the option <b>%s</b> was changed from <b>'%s'</b> to <b>'%s'</b>.<br>\n",
|
4557 |
+
self::escape($option_name),
|
4558 |
+
self::escape($option_value),
|
4559 |
+
self::escape($options_changed['changed'][ $option_name ])
|
4560 |
);
|
4561 |
$options_changed_simple .= sprintf(
|
4562 |
"%s: from '%s' to '%s',",
|
4563 |
+
self::escape($option_name),
|
4564 |
+
self::escape($option_value),
|
4565 |
+
self::escape($options_changed['changed'][ $option_name ])
|
4566 |
);
|
4567 |
}
|
4568 |
|
4571 |
$page_referer = false;
|
4572 |
|
4573 |
// Check which of these option groups where modified.
|
4574 |
+
switch ($option_page) {
|
4575 |
case 'options':
|
4576 |
$page_referer = 'Global';
|
4577 |
break;
|
4581 |
case 'discussion': /* no_break */
|
4582 |
case 'media': /* no_break */
|
4583 |
case 'permalink':
|
4584 |
+
$page_referer = ucwords($option_page);
|
4585 |
break;
|
4586 |
default:
|
4587 |
$page_referer = 'Common';
|
4588 |
break;
|
4589 |
}
|
4590 |
|
4591 |
+
if ($page_referer && $options_changed_count > 0) {
|
4592 |
$message = $page_referer . ' settings changed';
|
4593 |
+
SucuriScanEvent::report_error_event(sprintf(
|
4594 |
'%s: (multiple entries): %s',
|
4595 |
$message,
|
4596 |
+
rtrim($options_changed_simple, ',')
|
4597 |
+
));
|
4598 |
+
self::notify_event('settings_updated', $message . "<br>\n" . $options_changed_str);
|
4599 |
}
|
4600 |
}
|
4601 |
|
4602 |
}
|
|
|
4603 |
}
|
4604 |
|
4605 |
/**
|
4619 |
* APIs allow the combination of multiple APIs into new applications known as
|
4620 |
* mashups.
|
4621 |
*
|
4622 |
+
* @see https://en.wikipedia.org/wiki/Application_programming_interface#Web_APIs
|
4623 |
*/
|
4624 |
+
class SucuriScanAPI extends SucuriScanOption
|
4625 |
+
{
|
4626 |
/**
|
4627 |
* Check whether the SSL certificates will be verified while executing a HTTP
|
4628 |
* request or not. This is only for customization of the administrator, in fact
|
4630 |
*
|
4631 |
* @return boolean Whether the SSL certs will be verified while sending a request.
|
4632 |
*/
|
4633 |
+
public static function verifySslCert()
|
4634 |
+
{
|
4635 |
+
return (self::get_option(':verify_ssl_cert') === 'true');
|
4636 |
}
|
4637 |
|
4638 |
/**
|
4639 |
* Seconds before consider a HTTP request as timeout.
|
4640 |
*
|
4641 |
+
* As for the 01/Jan/2016 if the number of seconds before a timeout is greater
|
4642 |
+
* than sixty (which is one minute) the function will reset the option to its
|
4643 |
+
* default value to keep the latency of the HTTP requests in a minimum to
|
4644 |
+
* minimize the interruptions in the admins workflow. The normal connection
|
4645 |
+
* timeout should be in the range of ten seconds, or fifteen if the DNS lookups
|
4646 |
+
* are slow.
|
4647 |
+
*
|
4648 |
* @return integer Seconds to consider a HTTP request timeout.
|
4649 |
*/
|
4650 |
+
public static function requestTimeout()
|
4651 |
+
{
|
4652 |
+
$timeout = (int) self::get_option(':request_timeout');
|
4653 |
+
|
4654 |
+
if ($timeout > SUCURISCAN_MAX_REQUEST_TIMEOUT) {
|
4655 |
+
self::delete_option(':request_timeout');
|
4656 |
+
|
4657 |
+
return self::requestTimeout();
|
4658 |
+
}
|
4659 |
+
|
4660 |
+
return $timeout;
|
4661 |
}
|
4662 |
|
4663 |
/**
|
4665 |
*
|
4666 |
* @return string An user-agent for the HTTP requests.
|
4667 |
*/
|
4668 |
+
private static function userAgent()
|
4669 |
+
{
|
4670 |
+
return sprintf(
|
4671 |
'WordPress/%s; %s',
|
4672 |
self::site_version(),
|
4673 |
self::get_domain()
|
4674 |
);
|
|
|
|
|
4675 |
}
|
4676 |
|
4677 |
/**
|
4678 |
* Retrieves a URL using a changeable HTTP method, returning results in an
|
4679 |
* array. Results include HTTP headers and content.
|
4680 |
*
|
4681 |
+
* @see https://codex.wordpress.org/Function_Reference/wp_remote_post
|
4682 |
+
* @see https://codex.wordpress.org/Function_Reference/wp_remote_get
|
4683 |
*
|
4684 |
* @param string $url The target URL where the request will be sent.
|
4685 |
* @param string $method HTTP method that will be used to send the request.
|
4687 |
* @param array $args Request arguments like the timeout, redirections, headers, cookies, etc.
|
4688 |
* @return array Response object after the HTTP request is executed.
|
4689 |
*/
|
4690 |
+
private static function apiCall($url = '', $method = 'GET', $params = array(), $args = array())
|
4691 |
+
{
|
4692 |
+
if (!$url) {
|
4693 |
return false;
|
4694 |
}
|
4695 |
|
4696 |
$req_args = array(
|
4697 |
'method' => $method,
|
4698 |
+
'timeout' => self::requestTimeout(),
|
4699 |
'redirection' => 2,
|
4700 |
'httpversion' => '1.0',
|
4701 |
+
'user-agent' => self::userAgent(),
|
4702 |
'blocking' => true,
|
4703 |
'headers' => array(),
|
4704 |
'cookies' => array(),
|
4705 |
'compress' => false,
|
4706 |
'decompress' => false,
|
4707 |
+
'sslverify' => self::verifySslCert(),
|
4708 |
);
|
4709 |
|
4710 |
// Update the request arguments with the values passed tot he function.
|
4711 |
+
foreach ($args as $arg_name => $arg_value) {
|
4712 |
+
if (array_key_exists($arg_name, $req_args)) {
|
4713 |
+
$req_args[$arg_name] = $arg_value;
|
4714 |
}
|
4715 |
}
|
4716 |
|
4717 |
// Add random request parameter to avoid request reset.
|
4718 |
+
if (!empty($params) && !array_key_exists('time', $params)) {
|
4719 |
$params['time'] = time();
|
4720 |
}
|
4721 |
|
4722 |
+
if ($method == 'GET') {
|
4723 |
+
if (!empty($params)) {
|
4724 |
+
$url = sprintf('%s?%s', $url, http_build_query($params));
|
4725 |
}
|
4726 |
|
4727 |
+
$response = wp_remote_get($url, $req_args);
|
4728 |
+
} elseif ($method == 'POST') {
|
4729 |
$req_args['body'] = $params;
|
4730 |
+
$response = wp_remote_post($url, $req_args);
|
4731 |
} else {
|
4732 |
$response = false;
|
4733 |
+
SucuriScanInterface::error('HTTP method not allowed: ' . $method);
|
4734 |
}
|
4735 |
|
4736 |
+
return self::processResponse($response, $params, $args);
|
4737 |
}
|
4738 |
|
4739 |
/**
|
4742 |
* @param string $api_key An unique string to identify this installation.
|
4743 |
* @return boolean True if the API key is valid, false otherwise.
|
4744 |
*/
|
4745 |
+
private static function isValidKey($api_key = '')
|
4746 |
+
{
|
4747 |
+
return (bool) @preg_match('/^[a-z0-9]{32}$/', $api_key);
|
|
|
4748 |
}
|
4749 |
|
4750 |
/**
|
4754 |
* @param boolean $validate Whether the format of the key should be validated before store it.
|
4755 |
* @return boolean Either true or false if the key was saved successfully or not respectively.
|
4756 |
*/
|
4757 |
+
public static function setPluginKey($api_key = '', $validate = false)
|
4758 |
+
{
|
4759 |
+
if ($validate) {
|
4760 |
+
if (!self::isValidKey($api_key)) {
|
4761 |
+
SucuriScanInterface::error('Invalid API key format');
|
4762 |
return false;
|
4763 |
}
|
4764 |
}
|
4765 |
|
4766 |
+
if (!empty($api_key)) {
|
4767 |
+
SucuriScanEvent::notify_event('plugin_change', 'API key updated successfully: ' . $api_key);
|
4768 |
}
|
4769 |
|
4770 |
+
return self::update_option(':api_key', $api_key);
|
4771 |
}
|
4772 |
|
4773 |
/**
|
4775 |
*
|
4776 |
* @return string|boolean The API key or false if it does not exists.
|
4777 |
*/
|
4778 |
+
public static function getPluginKey()
|
4779 |
+
{
|
4780 |
+
$api_key = self::get_option(':api_key');
|
4781 |
|
4782 |
+
if (is_string($api_key)
|
4783 |
+
&& self::isValidKey($api_key)
|
|
|
4784 |
) {
|
4785 |
return $api_key;
|
4786 |
}
|
4797 |
*
|
4798 |
* @return array|boolean false if the key is invalid or not present, an array otherwise.
|
4799 |
*/
|
4800 |
+
public static function getCloudproxyKey()
|
4801 |
+
{
|
4802 |
$option_name = ':cloudproxy_apikey';
|
4803 |
+
$api_key = self::get_option($option_name);
|
4804 |
|
4805 |
// Check if the cloudproxy-waf plugin was previously installed.
|
4806 |
+
if (!$api_key) {
|
4807 |
+
$api_key = self::get_option('sucuriwaf_apikey');
|
4808 |
|
4809 |
+
if ($api_key) {
|
4810 |
+
self::update_option($option_name, $api_key);
|
4811 |
+
self::delete_option('sucuriwaf_apikey');
|
4812 |
}
|
4813 |
}
|
4814 |
|
4815 |
// Check the validity of the API key.
|
4816 |
+
$match = self::isValidCloudproxyKey($api_key, true);
|
4817 |
|
4818 |
+
if ($match) {
|
4819 |
return array(
|
4820 |
'string' => $match[1].'/'.$match[2],
|
4821 |
'k' => $match[1],
|
4833 |
* @param boolean $return_match Whether the parts of the API key must be returned or not.
|
4834 |
* @return boolean true if the API key specified is valid, false otherwise.
|
4835 |
*/
|
4836 |
+
public static function isValidCloudproxyKey($api_key = '', $return_match = false)
|
4837 |
+
{
|
4838 |
$pattern = '/^([a-z0-9]{32})\/([a-z0-9]{32})$/';
|
4839 |
|
4840 |
+
if ($api_key && preg_match($pattern, $api_key, $match)) {
|
4841 |
+
if ($return_match) {
|
4842 |
return $match;
|
4843 |
}
|
4844 |
|
4857 |
* @param array $args Request arguments like the timeout, redirections, headers, cookies, etc.
|
4858 |
* @return array Response object after the HTTP request is executed.
|
4859 |
*/
|
4860 |
+
public static function apiCallWordpress($method = 'GET', $params = array(), $send_api_key = true, $args = array())
|
4861 |
+
{
|
4862 |
$url = SUCURISCAN_API;
|
4863 |
$params[ SUCURISCAN_API_VERSION ] = 1;
|
4864 |
$params['p'] = 'wordpress';
|
4865 |
|
4866 |
+
if ($send_api_key) {
|
4867 |
+
$api_key = self::getPluginKey();
|
4868 |
|
4869 |
+
if (!$api_key) {
|
4870 |
return false;
|
4871 |
}
|
4872 |
|
4873 |
$params['k'] = $api_key;
|
4874 |
}
|
4875 |
|
4876 |
+
return self::apiCall($url, $method, $params, $args);
|
|
|
|
|
4877 |
}
|
4878 |
|
4879 |
/**
|
4883 |
* @param array $params Parameters for the request defined in an associative array of key-value.
|
4884 |
* @return array Response object after the HTTP request is executed.
|
4885 |
*/
|
4886 |
+
public static function apiCallCloudproxy($method = 'GET', $params = array())
|
4887 |
+
{
|
4888 |
$send_request = false;
|
4889 |
|
4890 |
+
if (isset($params['k']) && isset($params['s'])) {
|
4891 |
$send_request = true;
|
4892 |
} else {
|
4893 |
+
$api_key = self::getCloudproxyKey();
|
4894 |
|
4895 |
+
if ($api_key) {
|
4896 |
$send_request = true;
|
4897 |
$params['k'] = $api_key['k'];
|
4898 |
$params['s'] = $api_key['s'];
|
4899 |
}
|
4900 |
}
|
4901 |
|
4902 |
+
if ($send_request) {
|
4903 |
$url = SUCURISCAN_CLOUDPROXY_API;
|
4904 |
$params[ SUCURISCAN_CLOUDPROXY_API_VERSION ] = 1;
|
4905 |
+
unset($params['string']);
|
|
|
|
|
4906 |
|
4907 |
+
return self::apiCall($url, $method, $params);
|
4908 |
}
|
4909 |
|
4910 |
return false;
|
4918 |
* @param array $args Request arguments like the timeout, redirections, headers, cookies, etc.
|
4919 |
* @return array Response object with some modifications.
|
4920 |
*/
|
4921 |
+
private static function processResponse($response = array(), $params = array(), $args = array())
|
4922 |
+
{
|
4923 |
/**
|
4924 |
* Convert the error message generated by the code base functions after the HTTP
|
4925 |
* request is executed to a valid response object that will allow this code
|
4926 |
* process the data according to the specified standards.
|
4927 |
*/
|
4928 |
+
if (is_wp_error($response)) {
|
4929 |
// Extract information from the error object.
|
4930 |
$error_message = $response->get_error_message();
|
4931 |
+
$request_action = isset($params['a']) ? $params['a'] : 'unknown';
|
4932 |
|
4933 |
// Build a fake request response with custom data.
|
4934 |
$data_set = array(
|
4942 |
|
4943 |
// Build the response object and encode data.
|
4944 |
$response = array();
|
4945 |
+
$response['body'] = json_encode($data_set);
|
4946 |
+
$response['headers']['date'] = date('r');
|
4947 |
$response['headers']['connection'] = 'close';
|
4948 |
$response['headers']['content-type'] = 'application/json';
|
4949 |
+
$response['headers']['content-length'] = strlen($response['body']);
|
4950 |
$response['response']['code'] = 500;
|
4951 |
$response['response']['message'] = 'ERROR';
|
4952 |
}
|
4962 |
* they will see extra information explaining the response and how to proceed
|
4963 |
* with it.
|
4964 |
*/
|
4965 |
+
if (is_array($response)
|
4966 |
+
&& array_key_exists('body', $response)
|
4967 |
+
&& array_key_exists('headers', $response)
|
4968 |
+
&& array_key_exists('response', $response)
|
|
|
4969 |
) {
|
4970 |
+
// Keep a copy of the raw HTTP response.
|
4971 |
$response['body_raw'] = $response['body'];
|
4972 |
|
4973 |
+
// Append the non-private HTTP request parameters.
|
4974 |
+
$response['params'] = $params;
|
4975 |
+
unset($response['params']['k']);
|
4976 |
+
|
4977 |
+
/**
|
4978 |
+
* Check and decode the API response.
|
4979 |
+
*
|
4980 |
+
* Note that serialized data is going to be ignored, the old API service used to
|
4981 |
+
* respond to all endpoints with serialized data and considering the risk that
|
4982 |
+
* it poses to unserialize in PHP it was decided to drop that option and stick
|
4983 |
+
* to JSON which is a bit safer.
|
4984 |
+
*/
|
4985 |
+
if (isset($response['headers']['content-type'])
|
4986 |
&& $response['headers']['content-type'] == 'application/json'
|
4987 |
) {
|
4988 |
+
$assoc = (isset($args['assoc']) && $args['assoc'] === true) ? true : false;
|
4989 |
+
$response['body'] = @json_decode($response['body_raw'], $assoc);
|
4990 |
+
$response['body_arr'] = @json_decode($response['body_raw'], true);
|
4991 |
+
} elseif (self::is_serialized($response['body'])) {
|
4992 |
$response['body_raw'] = null;
|
4993 |
$response['body'] = 'ERROR:Serialized data is not supported.';
|
4994 |
}
|
5004 |
* generic variables and types, in case of an error a notification will appears
|
5005 |
* in the administrator panel explaining the result of the operation.
|
5006 |
*
|
5007 |
+
* @param array $response HTTP response after API endpoint execution.
|
5008 |
+
* @param boolean $enqueue Add the log to the local queue on a failure.
|
5009 |
+
* @return boolean False if the API call failed, true otherwise.
|
5010 |
*/
|
5011 |
+
private static function handleResponse($response = array(), $enqueue = true)
|
5012 |
+
{
|
5013 |
+
$error_msg = '';
|
5014 |
+
|
5015 |
+
if ($response) {
|
5016 |
+
if ($response['body'] instanceof stdClass) {
|
5017 |
+
if (isset($response['body']->status)) {
|
5018 |
+
if ($response['body']->status == 1) {
|
5019 |
return true;
|
5020 |
} else {
|
5021 |
+
return self::handleErrorResponse($response, $enqueue);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
5022 |
}
|
5023 |
} else {
|
5024 |
+
$error_msg = 'Could not determine the status of an API call.';
|
5025 |
}
|
5026 |
} else {
|
5027 |
+
$message = 'non JSON-encoded response.';
|
5028 |
|
5029 |
+
if (isset($response['response'])
|
|
|
5030 |
&& isset($response['response']['message'])
|
5031 |
&& isset($response['response']['code'])
|
5032 |
&& $response['response']['code'] !== 200
|
5033 |
) {
|
5034 |
+
$message = sprintf(
|
5035 |
'(%s) %s',
|
5036 |
$response['response']['code'],
|
5037 |
$response['response']['message']
|
5038 |
);
|
5039 |
}
|
5040 |
|
5041 |
+
$error_msg = 'Malformed API response: ' . $message;
|
5042 |
}
|
5043 |
}
|
5044 |
|
5045 |
+
if (!empty($error_msg) && $enqueue) {
|
5046 |
+
SucuriScanInterface::error($error_msg);
|
5047 |
+
}
|
5048 |
+
|
5049 |
return false;
|
5050 |
}
|
5051 |
|
5052 |
+
/**
|
5053 |
+
* Process failures in the HTTP response.
|
5054 |
+
*
|
5055 |
+
* Log file not found: means that the API key used to execute the request is
|
5056 |
+
* not associated to the website, this may indicate that either the key was
|
5057 |
+
* invalidated by an administrator of the service or that the API key was
|
5058 |
+
* custom generated with invalid data.
|
5059 |
+
*
|
5060 |
+
* Wrong API key: means that the TLD of the origin of the request is not the
|
5061 |
+
* domain used to generate the API key in the first place, or that the email
|
5062 |
+
* address of the site administrator was changed so the data is not valid
|
5063 |
+
* anymore.
|
5064 |
+
*
|
5065 |
+
* Connection timeout: means that the API service is down either because the
|
5066 |
+
* hosting provider has connectivity issues or because the code is being
|
5067 |
+
* deployed. There is an option in the settings page that allows to temporarily
|
5068 |
+
* disable the communication with the API service while the server is down, this
|
5069 |
+
* allows the admins to keep the latency at zero and continue working in their
|
5070 |
+
* websites without interruptions.
|
5071 |
+
*
|
5072 |
+
* SSL issues: depending on the options used to compile the OpenSSL library
|
5073 |
+
* built by each hosting provider, the connection with the HTTPs version of the
|
5074 |
+
* API service may be rejected because of a failure in the SSL algorithm check.
|
5075 |
+
* There is an option in the settings page that allows to disable the SSL pair
|
5076 |
+
* verification, this option it disable automatically when the error is detected
|
5077 |
+
* for the first time.
|
5078 |
+
*
|
5079 |
+
* @param array $response HTTP response after API endpoint execution.
|
5080 |
+
* @param boolean $enqueue Add the log to the local queue on a failure.
|
5081 |
+
* @return boolean False if the API call failed, true otherwise.
|
5082 |
+
*/
|
5083 |
+
private static function handleErrorResponse($response = array(), $enqueue = true)
|
5084 |
+
{
|
5085 |
+
$action_message = 'Unknown error, there is no more information.';
|
5086 |
+
|
5087 |
+
// Check whether the message list is empty or not.
|
5088 |
+
if (isset($response['body']->messages[0])) {
|
5089 |
+
$action_message = $response['body']->messages[0] . '.';
|
5090 |
+
}
|
5091 |
+
|
5092 |
+
// Keep a copy of the original API response message.
|
5093 |
+
$raw_message = $action_message;
|
5094 |
+
|
5095 |
+
// Special response for invalid API keys.
|
5096 |
+
if (stripos($raw_message, 'log file not found') !== false) {
|
5097 |
+
SucuriScanOption::delete_option(':api_key');
|
5098 |
+
|
5099 |
+
$action_message .= ' This generally happens when you add an invalid API key, the'
|
5100 |
+
. ' key will be deleted automatically to hide these warnings, if you want to'
|
5101 |
+
. ' recover it go to the settings page and use the recover button to send the'
|
5102 |
+
. ' key to your email address.';
|
5103 |
+
}
|
5104 |
+
|
5105 |
+
// Special response for invalid CloudProxy API keys.
|
5106 |
+
if (stripos($raw_message, 'wrong api key') !== false) {
|
5107 |
+
SucuriScanOption::delete_option(':cloudproxy_apikey');
|
5108 |
+
SucuriScanOption::setRevProxy('disable');
|
5109 |
+
SucuriScanOption::setAddrHeader('REMOTE_ADDR');
|
5110 |
+
|
5111 |
+
$action_message .= ' The CloudProxy API key does not seems to be valid.';
|
5112 |
+
}
|
5113 |
+
|
5114 |
+
// Special response for connection timeouts.
|
5115 |
+
if ($enqueue && @preg_match('/time(d\s)?out/', $raw_message)) {
|
5116 |
+
$action_message = ''; /* Empty the error message. */
|
5117 |
+
$cache = new SucuriScanCache('auditqueue');
|
5118 |
+
$cache_key = md5($response['params']['time']);
|
5119 |
+
$cache_value = array(
|
5120 |
+
'created_at' => $response['params']['time'],
|
5121 |
+
'message' => $response['params']['m'],
|
5122 |
+
);
|
5123 |
+
$cache->add($cache_key, $cache_value);
|
5124 |
+
}
|
5125 |
+
|
5126 |
+
// Stop SSL peer verification on connection failures.
|
5127 |
+
if (stripos($raw_message, 'no alternative certificate')
|
5128 |
+
|| stripos($raw_message, 'error setting certificate')
|
5129 |
+
|| stripos($raw_message, 'SSL connect error')
|
5130 |
+
) {
|
5131 |
+
SucuriScanOption::update_option(':verify_ssl_cert', 'false');
|
5132 |
+
|
5133 |
+
$action_message .= 'There were some issues with the SSL certificate either in this'
|
5134 |
+
. ' server or with the remote API service. The automatic verification of the'
|
5135 |
+
. ' certificates has been deactivated to reduce the noise during the execution'
|
5136 |
+
. ' of the HTTP requests.';
|
5137 |
+
}
|
5138 |
+
|
5139 |
+
if (!empty($action_message)) {
|
5140 |
+
if ($enqueue) {
|
5141 |
+
SucuriScanInterface::error(
|
5142 |
+
sprintf(
|
5143 |
+
'(%d) %s: %s',
|
5144 |
+
SucuriScan::local_time(),
|
5145 |
+
ucwords($response['body']->action),
|
5146 |
+
$action_message
|
5147 |
+
)
|
5148 |
+
);
|
5149 |
+
}
|
5150 |
+
|
5151 |
+
return false;
|
5152 |
+
}
|
5153 |
+
|
5154 |
+
return true;
|
5155 |
+
}
|
5156 |
+
|
5157 |
/**
|
5158 |
* Send a request to the API to register this site.
|
5159 |
*
|
5160 |
* @param string $email Optional email address for the registration.
|
5161 |
* @return boolean True if the API key was generated, false otherwise.
|
5162 |
*/
|
5163 |
+
public static function registerSite($email = '')
|
5164 |
+
{
|
5165 |
+
if (!is_string($email) || empty($email)) {
|
5166 |
$email = self::get_site_email();
|
5167 |
}
|
5168 |
|
5169 |
+
$response = self::apiCallWordpress('POST', array(
|
5170 |
'e' => $email,
|
5171 |
's' => self::get_domain(),
|
5172 |
'a' => 'register_site',
|
5173 |
+
), false);
|
5174 |
|
5175 |
+
if (self::handleResponse($response)) {
|
5176 |
+
self::setPluginKey($response['body']->output->api_key);
|
5177 |
SucuriScanEvent::schedule_task();
|
5178 |
+
SucuriScanEvent::notify_event('plugin_change', 'Site registered and API key generated');
|
5179 |
+
SucuriScanInterface::info('The API key for your site was successfully generated and saved.');
|
5180 |
|
5181 |
return true;
|
5182 |
}
|
5189 |
*
|
5190 |
* @return boolean true if the API key was sent to the administrator email, false otherwise.
|
5191 |
*/
|
5192 |
+
public static function recoverKey()
|
5193 |
+
{
|
5194 |
$clean_domain = self::get_domain();
|
5195 |
|
5196 |
+
$response = self::apiCallWordpress('GET', array(
|
5197 |
'e' => self::get_site_email(),
|
5198 |
's' => $clean_domain,
|
5199 |
'a' => 'recover_key',
|
5200 |
+
), false);
|
5201 |
|
5202 |
+
if (self::handleResponse($response)) {
|
5203 |
+
SucuriScanEvent::notify_event('plugin_change', 'API key recovered for domain: ' . $clean_domain);
|
5204 |
+
SucuriScanInterface::info($response['body']->output->message);
|
5205 |
|
5206 |
return true;
|
5207 |
}
|
5215 |
* settings or files in the administrator panel, or a notification generated by
|
5216 |
* this plugin.
|
5217 |
*
|
5218 |
+
* @param string $event Event triggered by the core system functions.
|
5219 |
+
* @param integer $time Timestamp when the event was originally triggered.
|
5220 |
+
* @param boolean $enqueue Add the log to the local queue on a failure.
|
5221 |
+
* @return boolean True if the event was logged, false otherwise.
|
5222 |
*/
|
5223 |
+
public static function sendLog($event = '', $time = 0, $enqueue = true)
|
5224 |
+
{
|
5225 |
+
if (!empty($event)) {
|
5226 |
+
$params = array();
|
5227 |
+
$params['a'] = 'send_log';
|
5228 |
+
$params['m'] = $event;
|
5229 |
+
|
5230 |
+
if (intval($time) > 0) {
|
5231 |
+
$params['time'] = (int) $time;
|
5232 |
+
}
|
5233 |
+
|
5234 |
+
$response = self::apiCallWordpress('POST', $params, true);
|
5235 |
|
5236 |
+
if (self::handleResponse($response, $enqueue)) {
|
5237 |
return true;
|
5238 |
}
|
5239 |
}
|
5241 |
return false;
|
5242 |
}
|
5243 |
|
5244 |
+
/**
|
5245 |
+
* Send all logs from the queue.
|
5246 |
+
*
|
5247 |
+
* Retry the HTTP calls for the logs that were not sent to the API service
|
5248 |
+
* because of a connection failure or misconfiguration. Each successful call
|
5249 |
+
* will remove the log from the queue and the failures will keep them until the
|
5250 |
+
* next function call is executed.
|
5251 |
+
*
|
5252 |
+
* @return void
|
5253 |
+
*/
|
5254 |
+
public static function sendLogsFromQueue()
|
5255 |
+
{
|
5256 |
+
$cache = new SucuriScanCache('auditqueue');
|
5257 |
+
$entries = $cache->getAll();
|
5258 |
+
|
5259 |
+
if (is_array($entries) && !empty($entries)) {
|
5260 |
+
foreach ($entries as $key => $entry) {
|
5261 |
+
$result = self::sendLog(
|
5262 |
+
$entry->message,
|
5263 |
+
$entry->created_at,
|
5264 |
+
false
|
5265 |
+
);
|
5266 |
+
|
5267 |
+
if ($result === true) {
|
5268 |
+
$cache->delete($key);
|
5269 |
+
} else {
|
5270 |
+
/**
|
5271 |
+
* Stop loop on failures.
|
5272 |
+
*
|
5273 |
+
* If the log was successfully sent to the API service then we can continue
|
5274 |
+
* sending the other logs in the queue, otherwise the operation must be stopped
|
5275 |
+
* so it can be executed next time when the service is online, not stopping the
|
5276 |
+
* operation when one or more of the API calls fails will cause a very long
|
5277 |
+
* delay in the load of the page that is being requested.
|
5278 |
+
*/
|
5279 |
+
break;
|
5280 |
+
}
|
5281 |
+
}
|
5282 |
+
}
|
5283 |
+
}
|
5284 |
+
|
5285 |
/**
|
5286 |
* Retrieve all the event logs registered by the API service.
|
5287 |
*
|
5288 |
* @return array The object with the data returned from the API service.
|
5289 |
*/
|
5290 |
+
public static function getAllLogs()
|
5291 |
+
{
|
5292 |
// Get the total number of lines in the logs.
|
5293 |
+
$response = self::apiCallWordpress('GET', array(
|
5294 |
'a' => 'get_logs',
|
5295 |
'l' => 0,
|
5296 |
+
));
|
5297 |
|
5298 |
// If success continue with the retrieval of the logs data.
|
5299 |
+
if (self::handleResponse($response)) {
|
5300 |
+
return self::getLogs($response['body']->total_entries);
|
5301 |
}
|
5302 |
|
5303 |
return false;
|
5309 |
* @param integer $lines How many lines from the log file will be retrieved.
|
5310 |
* @return string The response of the API service.
|
5311 |
*/
|
5312 |
+
public static function getLogs($lines = 50)
|
5313 |
+
{
|
5314 |
+
$response = self::apiCallWordpress('GET', array(
|
5315 |
'a' => 'get_logs',
|
5316 |
'l' => $lines,
|
5317 |
+
));
|
5318 |
|
5319 |
+
if (self::handleResponse($response)) {
|
5320 |
$response['body']->output_data = array();
|
5321 |
$log_pattern = '/^([0-9\-]+) ([0-9:]+) (\S+) : (.+)/';
|
5322 |
$extra_pattern = '/(.+ \(multiple entries\):) (.+)/';
|
5323 |
+
$generic_pattern = '/^@?([A-Z][a-z]{3,7}): ([^;]+; )?(.+)/';
|
5324 |
$auth_pattern = '/^User authentication (succeeded|failed): ([^<;]+)/';
|
5325 |
|
5326 |
+
foreach ($response['body']->output as $log) {
|
5327 |
+
if (@preg_match($log_pattern, $log, $log_match)) {
|
5328 |
$log_data = array(
|
5329 |
'event' => 'notice',
|
5330 |
'date' => '',
|
5333 |
'timestamp' => 0,
|
5334 |
'account' => $log_match[3],
|
5335 |
'username' => 'system',
|
5336 |
+
'remote_addr' => '127.0.0.1',
|
5337 |
'message' => $log_match[4],
|
5338 |
'file_list' => false,
|
5339 |
'file_list_count' => 0,
|
5340 |
);
|
5341 |
|
5342 |
// Extract and fix the date and time using the Eastern time zone.
|
5343 |
+
$datetime = sprintf('%s %s EDT', $log_match[1], $log_match[2]);
|
5344 |
+
$log_data['timestamp'] = strtotime($datetime);
|
5345 |
+
$log_data['datetime'] = date('Y-m-d H:i:s', $log_data['timestamp']);
|
5346 |
+
$log_data['date'] = date('Y-m-d', $log_data['timestamp']);
|
5347 |
+
$log_data['time'] = date('H:i:s', $log_data['timestamp']);
|
5348 |
|
5349 |
// Extract more information from the generic audit logs.
|
5350 |
+
$log_data['message'] = str_replace('<br>', '; ', $log_data['message']);
|
5351 |
|
5352 |
+
if (@preg_match($generic_pattern, $log_data['message'], $log_extra)) {
|
5353 |
+
$log_data['event'] = strtolower($log_extra[1]);
|
5354 |
+
$log_data['message'] = trim($log_extra[3]);
|
5355 |
|
5356 |
// Extract the username and remote address from the log.
|
5357 |
+
if (!empty($log_extra[2])) {
|
5358 |
+
$username_address = rtrim($log_extra[2], ";\x20");
|
5359 |
|
5360 |
// Separate the username from the remote address.
|
5361 |
+
if (strpos($username_address, ",\x20") !== false) {
|
5362 |
+
$usip_parts = explode(",\x20", $username_address, 2);
|
5363 |
|
5364 |
+
if (count($usip_parts) == 2) {
|
5365 |
// Separate the username from the display name.
|
5366 |
+
$log_data['username'] = @preg_replace('/^.+ \((.+)\)$/', '$1', $usip_parts[0]);
|
5367 |
$log_data['remote_addr'] = $usip_parts[1];
|
5368 |
}
|
5369 |
} else {
|
5378 |
$log_data['message']
|
5379 |
);
|
5380 |
|
5381 |
+
if (@preg_match($auth_pattern, $log_data['message'], $user_match)) {
|
5382 |
$log_data['username'] = $user_match[2];
|
5383 |
}
|
5384 |
}
|
5385 |
|
5386 |
// Extract more information from the special formatted logs.
|
5387 |
+
if (@preg_match($extra_pattern, $log_data['message'], $log_extra)) {
|
5388 |
$log_data['message'] = $log_extra[1];
|
5389 |
+
$log_extra[2] = str_replace(', new size', '; new size', $log_extra[2]);
|
5390 |
+
$log_extra[2] = str_replace(",\x20", ";\x20", $log_extra[2]);
|
5391 |
+
$log_data['file_list'] = explode(',', $log_extra[2]);
|
5392 |
+
$log_data['file_list_count'] = count($log_data['file_list']);
|
5393 |
}
|
5394 |
|
5395 |
$response['body']->output_data[] = $log_data;
|
5407 |
*
|
5408 |
* @return array Valid audit event types with their colors.
|
5409 |
*/
|
5410 |
+
public static function getAuditEventTypes()
|
5411 |
+
{
|
5412 |
+
return array(
|
5413 |
'critical' => '#000000',
|
5414 |
'debug' => '#c690ec',
|
5415 |
'error' => '#f27d7d',
|
5417 |
'notice' => '#428bca',
|
5418 |
'warning' => '#f0ad4e',
|
5419 |
);
|
|
|
|
|
5420 |
}
|
5421 |
|
5422 |
/**
|
5425 |
* @param string $event_log Event log that will be processed.
|
5426 |
* @return array List of parts of the event log.
|
5427 |
*/
|
5428 |
+
public static function parseMultipleEntries($event_log = '')
|
5429 |
+
{
|
5430 |
+
if (@preg_match('/^(.*:\s)\(multiple entries\):\s(.+)/', $event_log, $match)) {
|
5431 |
$event_log = array();
|
5432 |
+
$event_log[] = trim($match[1]);
|
5433 |
+
$grouped_items = @explode(',', $match[2]);
|
5434 |
+
$event_log = array_merge($event_log, $grouped_items);
|
5435 |
}
|
5436 |
|
5437 |
return $event_log;
|
5443 |
* @param integer $lines How many lines from the log file will be retrieved.
|
5444 |
* @return array All the information necessary to display the audit logs report.
|
5445 |
*/
|
5446 |
+
public static function getAuditReport($lines = 50)
|
5447 |
+
{
|
5448 |
+
$audit_logs = self::getLogs($lines);
|
5449 |
|
5450 |
+
if ($audit_logs instanceof stdClass
|
5451 |
+
&& property_exists($audit_logs, 'total_entries')
|
5452 |
+
&& property_exists($audit_logs, 'output_data')
|
5453 |
+
&& !empty($audit_logs->output_data)
|
|
|
5454 |
) {
|
5455 |
// Data structure that will be returned.
|
5456 |
$report = array(
|
5468 |
);
|
5469 |
|
5470 |
// Get a list of valid audit event types.
|
5471 |
+
$event_types = self::getAuditEventTypes();
|
5472 |
+
foreach ($event_types as $event => $event_color) {
|
5473 |
+
$report['events_per_type'][$event] = 0;
|
5474 |
+
$report['event_colors'][] = sprintf("'%s'", $event_color);
|
5475 |
}
|
5476 |
|
5477 |
// Collect information for each report chart.
|
5478 |
+
foreach ($audit_logs->output_data as $event) {
|
5479 |
$report['total_events'] += 1;
|
5480 |
|
5481 |
// Increment the number of events for this event type.
|
5482 |
+
if (array_key_exists($event['event'], $report['events_per_type'])) {
|
5483 |
$report['events_per_type'][ $event['event'] ] += 1;
|
5484 |
} else {
|
5485 |
$report['events_per_type'][ $event['event'] ] = 1;
|
5486 |
}
|
5487 |
|
5488 |
// Find the lowest datetime among the filtered events.
|
5489 |
+
if ($event['timestamp'] <= $report['start_timestamp']
|
|
|
5490 |
|| $report['start_timestamp'] === 0
|
5491 |
) {
|
5492 |
$report['start_timestamp'] = $event['timestamp'];
|
5493 |
}
|
5494 |
|
5495 |
// Find the highest datetime among the filtered events.
|
5496 |
+
if ($event['timestamp'] >= $report['end_timestamp']) {
|
5497 |
$report['end_timestamp'] = $event['timestamp'];
|
5498 |
}
|
5499 |
|
5500 |
// Increment the number of events generated by this user account.
|
5501 |
+
$_username = SucuriScan::escape($event['username']);
|
5502 |
+
if (array_key_exists($_username, $report['events_per_user'])) {
|
5503 |
+
$report['events_per_user'][$_username] += 1;
|
5504 |
} else {
|
5505 |
+
$report['events_per_user'][$_username] = 1;
|
5506 |
}
|
5507 |
|
5508 |
// Increment the number of events generated from this remote address.
|
5509 |
+
$_remote_addr = SucuriScan::escape($event['remote_addr']);
|
5510 |
+
if (array_key_exists($_remote_addr, $report['events_per_ipaddress'])) {
|
5511 |
+
$report['events_per_ipaddress'][$_remote_addr] += 1;
|
5512 |
} else {
|
5513 |
+
$report['events_per_ipaddress'][$_remote_addr] = 1;
|
5514 |
}
|
5515 |
|
5516 |
// Detect successful and failed user authentications.
|
5517 |
$auth_pattern = '/^User authentication (succeeded|failed):/';
|
5518 |
|
5519 |
+
if (@preg_match($auth_pattern, $event['message'], $match)) {
|
5520 |
+
if ($match[1] == 'succeeded') {
|
5521 |
$report['events_per_login']['successful'] += 1;
|
5522 |
} else {
|
5523 |
$report['events_per_login']['failed'] += 1;
|
5524 |
}
|
5525 |
+
} elseif (@preg_match('/^User logged in:/', $event['message'])) {
|
5526 |
// Backward compatibility for previous user login messages.
|
5527 |
$report['events_per_login']['successful'] += 1;
|
5528 |
}
|
5529 |
}
|
5530 |
|
5531 |
+
if ($report['total_events'] > 0) {
|
5532 |
return $report;
|
5533 |
}
|
5534 |
}
|
5545 |
* @param string $hashes The information gathered after the scanning of the site's files.
|
5546 |
* @return boolean true if the hashes were stored, false otherwise.
|
5547 |
*/
|
5548 |
+
public static function sendHashes($hashes = '')
|
5549 |
+
{
|
5550 |
+
if (!empty($hashes)) {
|
5551 |
+
$response = self::apiCallWordpress('POST', array(
|
5552 |
'a' => 'send_hashes',
|
5553 |
'h' => $hashes,
|
5554 |
+
));
|
5555 |
|
5556 |
+
if (self::handleResponse($response)) {
|
5557 |
return true;
|
5558 |
}
|
5559 |
}
|
5570 |
* @param boolean $api_key The CloudProxy API key.
|
5571 |
* @return array A hash with the settings of a CloudProxy account.
|
5572 |
*/
|
5573 |
+
public static function getCloudproxySettings($api_key = false)
|
5574 |
+
{
|
5575 |
+
$params = array('a' => 'show_settings');
|
5576 |
|
5577 |
+
if ($api_key) {
|
5578 |
+
$params = array_merge($params, $api_key);
|
5579 |
}
|
5580 |
|
5581 |
+
$response = self::apiCallCloudproxy('GET', $params);
|
5582 |
|
5583 |
+
if (self::handleResponse($response)) {
|
5584 |
return $response['body']->output;
|
5585 |
}
|
5586 |
|
5593 |
* @param boolean $api_key The CloudProxy API key.
|
5594 |
* @return string Message explaining the result of the operation.
|
5595 |
*/
|
5596 |
+
public static function clearCloudproxyCache($api_key = false)
|
5597 |
+
{
|
5598 |
$params = array( 'a' => 'clear_cache' );
|
5599 |
|
5600 |
+
if ($api_key) {
|
5601 |
+
$params = array_merge($params, $api_key);
|
5602 |
}
|
5603 |
|
5604 |
+
$response = self::apiCallCloudproxy('GET', $params);
|
5605 |
|
5606 |
+
if (self::handleResponse($response)) {
|
5607 |
return $response['body'];
|
5608 |
}
|
5609 |
|
5621 |
* the logs of previous days you will need to add a new parameter to the request
|
5622 |
* URL named "date" with format yyyy-mm-dd.
|
5623 |
*
|
5624 |
+
* @param string $api_key The CloudProxy API key.
|
5625 |
+
* @param string $date Retrieve the data from this date.
|
5626 |
+
* @param string $query Filter the data to match this query.
|
5627 |
+
* @param integer $limit Retrieve this maximum of data.
|
5628 |
+
* @param integer $offset Retrieve the data from this point.
|
5629 |
+
* @return array Objects with details of each blocked request.
|
5630 |
*/
|
5631 |
+
public static function firewallAuditLogs($api_key, $date = '', $query = '', $limit = 10, $offset = 0)
|
5632 |
+
{
|
5633 |
$params = array(
|
5634 |
'a' => 'audit_trails',
|
5635 |
+
'date' => $date,
|
5636 |
+
'query' => $query,
|
5637 |
+
'limit' => $limit,
|
5638 |
+
'offset' => $offset,
|
5639 |
);
|
5640 |
|
5641 |
+
if (is_array($api_key) && !empty($api_key)) {
|
5642 |
+
$params = array_merge($params, $api_key);
|
|
|
|
|
|
|
|
|
5643 |
}
|
5644 |
|
5645 |
+
$response = self::apiCallCloudproxy('GET', $params);
|
5646 |
|
5647 |
+
if (self::handleResponse($response)) {
|
5648 |
+
return $response['body_arr']['output'];
|
5649 |
}
|
5650 |
|
5651 |
return false;
|
5655 |
* Scan a website through the public SiteCheck API [1] for known malware,
|
5656 |
* blacklisting status, website errors, and out-of-date software.
|
5657 |
*
|
5658 |
+
* [1] https://sitecheck.sucuri.net/
|
5659 |
*
|
5660 |
* @param string $domain The clean version of the website's domain.
|
5661 |
* @return object Serialized data of the scanning results for the site specified.
|
5662 |
*/
|
5663 |
+
public static function getSitecheckResults($domain = '')
|
5664 |
+
{
|
5665 |
+
if (!empty($domain)) {
|
5666 |
+
$url = 'https://sitecheck.sucuri.net/';
|
5667 |
+
$response = self::apiCall(
|
5668 |
$url,
|
5669 |
'GET',
|
5670 |
array(
|
5678 |
)
|
5679 |
);
|
5680 |
|
5681 |
+
if ($response) {
|
5682 |
return $response['body'];
|
5683 |
}
|
5684 |
}
|
5692 |
* @param array $malware Array with two entries with basic malware information.
|
5693 |
* @return array Detailed information of the malware found by SiteCheck.
|
5694 |
*/
|
5695 |
+
public static function getSitecheckMalware($malware = array())
|
5696 |
+
{
|
5697 |
+
if (count($malware) >= 2) {
|
5698 |
$data_set = array(
|
5699 |
'alert_message' => '',
|
5700 |
'infected_url' => '',
|
5704 |
);
|
5705 |
|
5706 |
// Extract the information from the alert message.
|
5707 |
+
$alert_parts = explode(':', $malware[0], 2);
|
5708 |
|
5709 |
+
if (isset($alert_parts[1])) {
|
5710 |
$data_set['alert_message'] = $alert_parts[0];
|
5711 |
$data_set['infected_url'] = $alert_parts[1];
|
5712 |
}
|
5713 |
|
5714 |
// Extract the information from the malware message.
|
5715 |
+
$malware_parts = explode("\n", $malware[1]);
|
5716 |
|
5717 |
+
if (isset($malware_parts[1])) {
|
5718 |
+
if (@preg_match('/(.+)\. Details: (.+)/', $malware_parts[0], $match)) {
|
5719 |
$data_set['malware_type'] = $match[1];
|
5720 |
$data_set['malware_docs'] = $match[2];
|
5721 |
}
|
5722 |
|
5723 |
+
$payload = trim($malware_parts[1]);
|
5724 |
+
$payload = html_entity_decode($payload);
|
5725 |
|
5726 |
+
if (@preg_match('/<div id=\'HiddenDiv\'>(.+)<\/div>/', $payload, $match)) {
|
5727 |
+
$data_set['malware_payload'] = trim($match[1]);
|
5728 |
}
|
5729 |
}
|
5730 |
|
5740 |
*
|
5741 |
* @return array A list of the new set of keys generated by WordPress API.
|
5742 |
*/
|
5743 |
+
public static function getNewSecretKeys()
|
5744 |
+
{
|
5745 |
$pattern = self::secret_key_pattern();
|
5746 |
+
$response = self::apiCall('https://api.wordpress.org/secret-key/1.1/salt/', 'GET');
|
5747 |
|
5748 |
+
if ($response && @preg_match_all($pattern, $response['body'], $match)) {
|
5749 |
$new_keys = array();
|
5750 |
|
5751 |
+
foreach ($match[1] as $i => $value) {
|
5752 |
+
$new_keys[$value] = $match[3][$i];
|
5753 |
}
|
5754 |
|
5755 |
return $new_keys;
|
5761 |
/**
|
5762 |
* Retrieve a list with the checksums of the files in a specific version of WordPress.
|
5763 |
*
|
5764 |
+
* @see Release Archive https://wordpress.org/download/release-archive/
|
5765 |
*
|
5766 |
* @param integer $version Valid version number of the WordPress project.
|
5767 |
* @return object Associative object with the relative filepath and the checksums of the project files.
|
5768 |
*/
|
5769 |
+
public static function getOfficialChecksums($version = 0)
|
5770 |
+
{
|
5771 |
+
$url = 'https://api.wordpress.org/core/checksums/1.0/';
|
5772 |
$language = 'en_US'; /* WPLANG does not works. */
|
5773 |
+
$response = self::apiCall($url, 'GET', array(
|
5774 |
'version' => $version,
|
5775 |
'locale' => $language,
|
5776 |
));
|
5777 |
|
5778 |
+
if ($response) {
|
5779 |
+
if ($response['body'] instanceof stdClass) {
|
5780 |
$json_data = $response['body'];
|
5781 |
} else {
|
5782 |
+
$json_data = @json_decode($response['body']);
|
5783 |
}
|
5784 |
|
5785 |
+
if (isset($json_data->checksums)
|
5786 |
+
&& !empty($json_data->checksums)
|
|
|
5787 |
) {
|
5788 |
+
if (count((array) $json_data->checksums) <= 1
|
5789 |
+
&& property_exists($json_data->checksums, $version)
|
|
|
5790 |
) {
|
5791 |
$checksums = $json_data->checksums->{$version};
|
5792 |
} else {
|
5794 |
}
|
5795 |
|
5796 |
// Check whether the list of file is an object.
|
5797 |
+
if ($checksums instanceof stdClass) {
|
5798 |
return (array) $checksums;
|
5799 |
}
|
5800 |
}
|
5810 |
*
|
5811 |
* @return array Key is the plugin file path and the value is an array of the plugin data.
|
5812 |
*/
|
5813 |
+
public static function getPlugins()
|
5814 |
+
{
|
5815 |
// Check if the cache library was loaded.
|
5816 |
+
$can_cache = class_exists('SucuriScanCache');
|
5817 |
|
5818 |
+
if ($can_cache) {
|
5819 |
+
$cache = new SucuriScanCache('plugindata');
|
5820 |
+
$cached_data = $cache->get('plugins', SUCURISCAN_GET_PLUGINS_LIFETIME, 'array');
|
5821 |
|
5822 |
// Return the previously cached results of this function.
|
5823 |
+
if ($cached_data !== false) {
|
5824 |
return $cached_data;
|
5825 |
}
|
5826 |
}
|
5831 |
$wp_market = 'https://wordpress.org/plugins/%s/';
|
5832 |
|
5833 |
// Loop through each plugin data and complement its information with more attributes.
|
5834 |
+
foreach ($plugins as $plugin_path => $plugin_data) {
|
5835 |
// Default values for the plugin extra attributes.
|
5836 |
$repository = '';
|
5837 |
$repository_name = '';
|
5844 |
* official WordPress server it means that it is premium and is being
|
5845 |
* distributed by an independent developer.
|
5846 |
*/
|
5847 |
+
if (isset($plugin_data['PluginURI'])
|
5848 |
+
&& preg_match($pattern, $plugin_data['PluginURI'], $match)
|
|
|
5849 |
) {
|
5850 |
$repository = $match[0];
|
5851 |
$repository_name = $match[2];
|
5852 |
$is_free_plugin = true;
|
5853 |
} else {
|
5854 |
+
if (strpos($plugin_path, '/') !== false) {
|
5855 |
+
$plugin_path_parts = explode('/', $plugin_path, 2);
|
5856 |
} else {
|
5857 |
+
$plugin_path_parts = explode('.', $plugin_path, 2);
|
5858 |
}
|
5859 |
|
5860 |
+
if (isset($plugin_path_parts[0])) {
|
5861 |
+
$possible_repository = sprintf($wp_market, $plugin_path_parts[0]);
|
5862 |
+
$resp = wp_remote_head($possible_repository);
|
5863 |
|
5864 |
+
if (!is_wp_error($resp)
|
|
|
5865 |
&& $resp['response']['code'] == 200
|
5866 |
) {
|
5867 |
$repository = $possible_repository;
|
5872 |
}
|
5873 |
|
5874 |
// Complement the plugin's information with these attributes.
|
5875 |
+
$plugins[$plugin_path]['Repository'] = $repository;
|
5876 |
+
$plugins[$plugin_path]['RepositoryName'] = $repository_name;
|
5877 |
+
$plugins[$plugin_path]['InstallationPath'] = sprintf('%s/%s', WP_PLUGIN_DIR, $repository_name);
|
5878 |
+
$plugins[$plugin_path]['IsFreePlugin'] = $is_free_plugin;
|
5879 |
+
$plugins[$plugin_path]['PluginType'] = ( $is_free_plugin ? 'free' : 'premium' );
|
5880 |
+
$plugins[$plugin_path]['IsPluginActive'] = false;
|
5881 |
+
$plugins[$plugin_path]['IsPluginInstalled'] = false;
|
5882 |
|
5883 |
+
if (is_plugin_active($plugin_path)) {
|
5884 |
+
$plugins[$plugin_path]['IsPluginActive'] = true;
|
5885 |
}
|
5886 |
|
5887 |
+
if (is_dir($plugins[$plugin_path]['InstallationPath'])) {
|
5888 |
+
$plugins[$plugin_path]['IsPluginInstalled'] = true;
|
5889 |
}
|
5890 |
}
|
5891 |
|
5892 |
+
if ($can_cache) {
|
5893 |
// Add the information of the plugins to the file-based cache.
|
5894 |
+
$cache->add('plugins', $plugins);
|
5895 |
}
|
5896 |
|
5897 |
return $plugins;
|
5914 |
* @param string $plugin Frienly name of the plugin.
|
5915 |
* @return object Object on success, WP_Error on failure.
|
5916 |
*/
|
5917 |
+
public static function getRemotePluginData($plugin = '')
|
5918 |
+
{
|
5919 |
+
if (!empty($plugin)) {
|
5920 |
+
$url = sprintf('https://api.wordpress.org/plugins/info/1.0/%s.json', $plugin);
|
5921 |
+
$response = self::apiCall($url, 'GET');
|
5922 |
|
5923 |
+
if ($response) {
|
5924 |
+
if ($response['body'] instanceof stdClass) {
|
5925 |
return $response['body'];
|
5926 |
}
|
5927 |
}
|
5935 |
* the content of the file is determined by the tags defined using the site
|
5936 |
* version specified. Only official core files are allowed to fetch.
|
5937 |
*
|
5938 |
+
* @see https://core.svn.wordpress.org/
|
5939 |
+
* @see https://i18n.svn.wordpress.org/
|
5940 |
+
* @see https://core.svn.wordpress.org/tags/VERSION_NUMBER/
|
5941 |
*
|
5942 |
* @param string $filepath Relative file path of a project core file.
|
5943 |
* @param string $version Optional site version, default will be the global version number.
|
5944 |
* @return string Full content of the official file retrieved, false if the file was not found.
|
5945 |
*/
|
5946 |
+
public static function getOriginalCoreFile($filepath = '', $version = 0)
|
5947 |
+
{
|
5948 |
+
if (!empty($filepath)) {
|
5949 |
+
if ($version == 0) {
|
5950 |
$version = self::site_version();
|
5951 |
}
|
5952 |
|
5953 |
+
$url = sprintf('https://core.svn.wordpress.org/tags/%s/%s', $version, $filepath);
|
5954 |
+
$response = self::apiCall($url, 'GET');
|
5955 |
|
5956 |
+
if ($response) {
|
5957 |
+
if (isset($response['headers']['content-length'])
|
|
|
5958 |
&& $response['headers']['content-length'] > 0
|
5959 |
+
&& is_string($response['body'])
|
5960 |
) {
|
5961 |
return $response['body'];
|
5962 |
}
|
5965 |
|
5966 |
return false;
|
5967 |
}
|
|
|
5968 |
}
|
5969 |
|
5970 |
/**
|
5975 |
* will be sent to the site email address (an address that can be configured in
|
5976 |
* the settings page).
|
5977 |
*/
|
5978 |
+
class SucuriScanMail extends SucuriScanOption
|
5979 |
+
{
|
5980 |
|
5981 |
/**
|
5982 |
* Check whether the email notifications will be sent in HTML or Plain/Text.
|
5983 |
*
|
5984 |
* @return boolean Whether the emails will be in HTML or Plain/Text.
|
5985 |
*/
|
5986 |
+
public static function prettify_mails()
|
5987 |
+
{
|
5988 |
+
return self::is_enabled(':prettify_mails');
|
5989 |
}
|
5990 |
|
5991 |
/**
|
5997 |
* @param array $data_set Optional parameter to add more information to the notification.
|
5998 |
* @return boolean Whether the email contents were sent successfully.
|
5999 |
*/
|
6000 |
+
public static function send_mail($email = '', $subject = '', $message = '', $data_set = array())
|
6001 |
+
{
|
6002 |
$headers = array();
|
6003 |
+
$subject = ucwords(strtolower($subject));
|
6004 |
$force = false;
|
6005 |
$debug = false;
|
6006 |
|
6007 |
// Check whether the mail will be printed in the site instead of sent.
|
6008 |
+
if (isset($data_set['Debug'])
|
|
|
6009 |
&& $data_set['Debug'] == true
|
6010 |
) {
|
6011 |
$debug = true;
|
6013 |
}
|
6014 |
|
6015 |
// Check whether the mail will be even if the limit per hour was reached or not.
|
6016 |
+
if (isset($data_set['Force'])
|
|
|
6017 |
&& $data_set['Force'] == true
|
6018 |
) {
|
6019 |
$force = true;
|
6021 |
}
|
6022 |
|
6023 |
// Check whether the email notifications will be sent in HTML or Plain/Text.
|
6024 |
+
if (self::prettify_mails()) {
|
6025 |
$headers = array( 'content-type: text/html' );
|
6026 |
$data_set['PrettifyType'] = 'pretty';
|
6027 |
} else {
|
6028 |
+
$message = strip_tags($message);
|
6029 |
}
|
6030 |
|
6031 |
+
if (!self::emails_per_hour_reached() || $force || $debug) {
|
6032 |
+
$message = self::prettify_mail($subject, $message, $data_set);
|
6033 |
|
6034 |
+
if ($debug) {
|
6035 |
die($message);
|
6036 |
}
|
6037 |
|
6038 |
+
$subject = self::get_email_subject($subject);
|
6039 |
|
6040 |
/**
|
6041 |
* WordPress uses a library named PHPMailer [1] to send emails through the
|
6051 |
*
|
6052 |
* @var boolean
|
6053 |
*/
|
6054 |
+
if (SucuriScanOption::is_enabled(':use_wpmail')) {
|
6055 |
+
$mail_sent = wp_mail($email, $subject, $message, $headers);
|
6056 |
} else {
|
6057 |
+
$headers = implode("\r\n", $headers);
|
6058 |
+
$mail_sent = @mail($email, $subject, $message, $headers);
|
6059 |
}
|
6060 |
|
6061 |
+
if ($mail_sent) {
|
6062 |
+
$emails_sent_num = (int) self::get_option(':emails_sent');
|
6063 |
+
self::update_option(':emails_sent', $emails_sent_num + 1);
|
6064 |
+
self::update_option(':last_email_at', time());
|
6065 |
|
6066 |
return true;
|
6067 |
}
|
6076 |
* @param string $event The reason of the message that will be sent.
|
6077 |
* @return string A text with the subject for the email alert.
|
6078 |
*/
|
6079 |
+
private static function get_email_subject($event = '')
|
6080 |
+
{
|
6081 |
+
$subject = self::get_option(':email_subject');
|
6082 |
|
6083 |
/**
|
6084 |
* Probably a bad value in the options table. Delete the entry from the database
|
6085 |
* and call this function to try again, it will probably fall in an infinite
|
6086 |
* loop, but this is the easiest way to control this procedure.
|
6087 |
*/
|
6088 |
+
if (!$subject) {
|
6089 |
+
self::delete_option(':email_subject');
|
6090 |
|
6091 |
+
return self::get_email_subject($event);
|
6092 |
}
|
6093 |
|
6094 |
+
$subject = strip_tags($subject);
|
6095 |
+
$subject = str_replace(':event', $event, $subject);
|
6096 |
+
$subject = str_replace(':domain', self::get_domain(), $subject);
|
6097 |
+
$subject = str_replace(':remoteaddr', self::get_remote_addr(), $subject);
|
6098 |
|
6099 |
/**
|
6100 |
* Extract user data from the current session.
|
6103 |
* the username and/or email address are necessary to build the email subject,
|
6104 |
* otherwise this operation may delay the sending of the alerts.
|
6105 |
*/
|
6106 |
+
if (preg_match('/:(username|email)/', $subject)) {
|
6107 |
$user = wp_get_current_user();
|
6108 |
$username = 'unknown';
|
6109 |
$eaddress = 'unknown';
|
6110 |
|
6111 |
+
if ($user instanceof WP_User
|
6112 |
+
&& isset($user->user_login)
|
6113 |
+
&& isset($user->user_email)
|
|
|
6114 |
) {
|
6115 |
$username = $user->user_login;
|
6116 |
$eaddress = $user->user_email;
|
6117 |
}
|
6118 |
|
6119 |
+
$subject = str_replace(':username', $user->user_login, $subject);
|
6120 |
+
$subject = str_replace(':email', $user->user_email, $subject);
|
6121 |
}
|
6122 |
|
6123 |
return $subject;
|
6131 |
* @param array $data_set Optional parameter to add more information to the notification.
|
6132 |
* @return string The message formatted in a HTML template.
|
6133 |
*/
|
6134 |
+
private static function prettify_mail($subject = '', $message = '', $data_set = array())
|
6135 |
+
{
|
6136 |
$prettify_type = isset($data_set['PrettifyType']) ? $data_set['PrettifyType'] : 'simple';
|
6137 |
$template_name = 'notification-' . $prettify_type;
|
6138 |
$user = wp_get_current_user();
|
6139 |
$display_name = '';
|
6140 |
|
6141 |
+
if ($user instanceof WP_User
|
|
|
6142 |
&& isset($user->user_login)
|
6143 |
+
&& !empty($user->user_login)
|
6144 |
) {
|
6145 |
+
$display_name = sprintf('User: %s (%s)', $user->display_name, $user->user_login);
|
6146 |
}
|
6147 |
|
6148 |
// Format list of items when the event has multiple entries.
|
6149 |
+
if (strpos($message, 'multiple') !== false) {
|
6150 |
+
$message_parts = SucuriScanAPI::parseMultipleEntries($message);
|
6151 |
|
6152 |
+
if (is_array($message_parts)) {
|
6153 |
$message = ( $prettify_type == 'pretty' ) ? $message_parts[0] . '<ul>' : $message_parts[0];
|
6154 |
unset($message_parts[0]);
|
6155 |
|
6156 |
+
foreach ($message_parts as $msg_part) {
|
6157 |
+
if ($prettify_type == 'pretty') {
|
6158 |
+
$message .= sprintf("<li>%s</li>\n", $msg_part);
|
6159 |
} else {
|
6160 |
+
$message .= sprintf("- %s\n", $msg_part);
|
6161 |
}
|
6162 |
}
|
6163 |
|
6168 |
$mail_variables = array(
|
6169 |
'TemplateTitle' => 'Sucuri Alert',
|
6170 |
'Subject' => $subject,
|
6171 |
+
'Website' => self::get_option('siteurl'),
|
6172 |
'RemoteAddress' => self::get_remote_addr(),
|
6173 |
'Message' => $message,
|
6174 |
'User' => $display_name,
|
6175 |
'Time' => SucuriScan::current_datetime(),
|
6176 |
);
|
6177 |
|
6178 |
+
foreach ($data_set as $var_key => $var_value) {
|
6179 |
$mail_variables[ $var_key ] = $var_value;
|
6180 |
}
|
6181 |
|
6182 |
+
return SucuriScanTemplate::getSection($template_name, $mail_variables);
|
6183 |
}
|
6184 |
|
6185 |
/**
|
6187 |
*
|
6188 |
* @return boolean Whether the quota emails per hour was reached.
|
6189 |
*/
|
6190 |
+
private static function emails_per_hour_reached()
|
6191 |
+
{
|
6192 |
+
$max_per_hour = self::get_option(':emails_per_hour');
|
6193 |
|
6194 |
+
if ($max_per_hour != 'unlimited') {
|
6195 |
// Check if we are still in that sixty minutes.
|
6196 |
$current_time = time();
|
6197 |
+
$last_email_at = self::get_option(':last_email_at');
|
6198 |
+
$diff_time = abs($current_time - $last_email_at);
|
6199 |
|
6200 |
+
if ($diff_time <= 3600) {
|
6201 |
// Check if the quantity of emails sent is bigger than the configured.
|
6202 |
+
$emails_sent = (int) self::get_option(':emails_sent');
|
6203 |
+
$max_per_hour = intval($max_per_hour);
|
6204 |
|
6205 |
+
if ($emails_sent >= $max_per_hour) {
|
6206 |
return true;
|
6207 |
}
|
6208 |
} else {
|
6209 |
// Reset the counter of emails sent.
|
6210 |
+
self::update_option(':emails_sent', 0);
|
6211 |
}
|
6212 |
}
|
6213 |
|
6214 |
return false;
|
6215 |
}
|
|
|
6216 |
}
|
6217 |
|
6218 |
/**
|
6228 |
* generate a large number of "static" (unchanging) web pages in advance, or to
|
6229 |
* produce "dynamic" web pages on demand.
|
6230 |
*/
|
6231 |
+
class SucuriScanTemplate extends SucuriScanRequest
|
6232 |
+
{
|
6233 |
/**
|
6234 |
* Replace all pseudo-variables from a string of characters.
|
6235 |
*
|
6237 |
* @param array $params List of pseudo-variables that will be replaced in the template.
|
6238 |
* @return string The content of the template with the pseudo-variables replated.
|
6239 |
*/
|
6240 |
+
private static function replacePseudoVars($content = '', $params = array())
|
6241 |
+
{
|
6242 |
+
if (is_array($params)) {
|
6243 |
+
foreach ($params as $keyname => $kvalue) {
|
6244 |
+
$tplkey = 'SUCURI.' . $keyname;
|
6245 |
+
$with_escape = '%%' . $tplkey . '%%';
|
6246 |
+
$wout_escape = '%%%' . $tplkey . '%%%';
|
6247 |
+
|
6248 |
+
if (strpos($content, $wout_escape) !== false) {
|
6249 |
+
$content = str_replace($wout_escape, $kvalue, $content);
|
6250 |
+
} elseif (strpos($content, $with_escape) !== false) {
|
6251 |
+
$kvalue = SucuriScan::escape($kvalue);
|
6252 |
+
$content = str_replace($with_escape, $kvalue, $content);
|
6253 |
+
}
|
6254 |
}
|
6255 |
|
6256 |
return $content;
|
6262 |
/**
|
6263 |
* Gather and generate the information required globally by all the template files.
|
6264 |
*
|
6265 |
+
* @param array $params Key-value array with pseudo-variables shared with the template.
|
6266 |
* @return array A complementary list of pseudo-variables for the template files.
|
6267 |
*/
|
6268 |
+
private static function sharedParams($params = array())
|
6269 |
+
{
|
6270 |
+
$params = is_array($params) ? $params : array();
|
6271 |
|
6272 |
// Base parameters, required to render all the pages.
|
6273 |
+
$params = self::linksAndNavbar($params);
|
6274 |
|
6275 |
// Global parameters, used through out all the pages.
|
6276 |
$params['PageTitle'] = isset($params['PageTitle']) ? '('.$params['PageTitle'].')' : '';
|
6277 |
+
$params['PageNonce'] = wp_create_nonce('sucuriscan_page_nonce');
|
6278 |
$params['PageStyleClass'] = isset($params['PageStyleClass']) ? $params['PageStyleClass'] : 'base';
|
6279 |
$params['CleanDomain'] = self::get_domain();
|
6280 |
$params['AdminEmails'] = '';
|
6281 |
|
6282 |
// Get a list of admin users for the API key generation.
|
6283 |
+
if (SucuriScanAPI::getPluginKey() === false) {
|
6284 |
$admin_users = SucuriScan::get_users_for_api_key();
|
6285 |
+
$params['AdminEmails'] = self::selectOptions($admin_users);
|
6286 |
}
|
6287 |
|
6288 |
// Hide the advertisements from the layout.
|
6295 |
$params['LayoutType'] = 'twocolumns';
|
6296 |
$params['AdsVisibility'] = 'visible';
|
6297 |
$params['ReviewNavbarButton'] = 'hidden';
|
6298 |
+
$params['PageSidebarContent'] = self::getTemplate('bsidebar', $params, 'section');
|
6299 |
}
|
6300 |
|
6301 |
return $params;
|
6307 |
* @param boolean $visible Whether the condition executed returned a positive value or not.
|
6308 |
* @return string A string indicating the visibility of a HTML component.
|
6309 |
*/
|
6310 |
+
public static function visibility($visible = false)
|
6311 |
+
{
|
6312 |
+
return ($visible === true ? 'visible' : 'hidden');
|
6313 |
}
|
6314 |
|
6315 |
/**
|
6316 |
* Generate an URL pointing to the page indicated in the function and that must
|
6317 |
* be loaded through the administrator panel.
|
6318 |
*
|
6319 |
+
* @param string $page Short name of the page that will be generated.
|
6320 |
+
* @param boolean $ajax True if the URL should point to the Ajax handler.
|
6321 |
+
* @return string Full string containing the link of the page.
|
6322 |
*/
|
6323 |
+
public static function getUrl($page = '', $ajax = false)
|
6324 |
+
{
|
6325 |
+
$suffix = ($ajax === true) ? 'admin-ajax' : 'admin';
|
6326 |
+
$url_path = SucuriScan::admin_url($suffix . '.php?page=sucuriscan');
|
6327 |
|
6328 |
+
if (!empty($page)) {
|
6329 |
+
$url_path .= '_' . strtolower($page);
|
6330 |
}
|
6331 |
|
6332 |
return $url_path;
|
6339 |
* @param string $page Short name of the page that will be generated.
|
6340 |
* @return string Full string containing the link of the page.
|
6341 |
*/
|
6342 |
+
public static function getAjaxUrl($page = '')
|
6343 |
+
{
|
6344 |
+
return self::getUrl($page, true);
|
|
|
|
|
|
|
|
|
|
|
6345 |
}
|
6346 |
|
6347 |
/**
|
6349 |
* template files, this will also generate the navigation bar and detect which
|
6350 |
* items in it are selected by the current page.
|
6351 |
*
|
6352 |
+
* @param array $params Key-value array with pseudo-variables shared with the template.
|
6353 |
* @return array A complementary list of pseudo-variables for the template files.
|
6354 |
*/
|
6355 |
+
private static function linksAndNavbar($params = array())
|
6356 |
+
{
|
6357 |
global $sucuriscan_pages;
|
6358 |
|
6359 |
+
$params = is_array($params) ? $params : array();
|
6360 |
+
$sub_pages = is_array($sucuriscan_pages) ? $sucuriscan_pages : array();
|
6361 |
|
6362 |
$params['Navbar'] = '';
|
6363 |
$params['CurrentPageFunc'] = '';
|
6364 |
|
6365 |
+
if ($_page = self::get('page', '_page')) {
|
6366 |
$params['CurrentPageFunc'] = $_page;
|
6367 |
}
|
6368 |
|
6369 |
+
foreach ($sub_pages as $sub_page_func => $sub_page_title) {
|
6370 |
+
if ($sub_page_func == 'sucuriscan_scanner'
|
6371 |
+
&& SucuriScanOption::is_disabled(':sitecheck_scanner')
|
|
|
6372 |
) {
|
6373 |
continue;
|
6374 |
}
|
6375 |
|
6376 |
+
$func_parts = explode('_', $sub_page_func, 2);
|
6377 |
|
6378 |
+
if (isset($func_parts[1])) {
|
6379 |
$unique_name = $func_parts[1];
|
6380 |
+
$pseudo_var = 'URL.' . ucwords($unique_name);
|
6381 |
} else {
|
6382 |
$unique_name = '';
|
6383 |
$pseudo_var = 'URL.Home';
|
6384 |
}
|
6385 |
|
6386 |
+
$params[$pseudo_var] = self::getUrl($unique_name);
|
6387 |
|
6388 |
// Copy URL variable and create an Ajax handler.
|
6389 |
$pseudo_var_ajax = 'Ajax' . $pseudo_var;
|
6390 |
+
$params[$pseudo_var_ajax] = self::getAjaxUrl($unique_name);
|
6391 |
|
6392 |
$navbar_item_css_class = 'nav-tab';
|
6393 |
|
6394 |
+
if ($params['CurrentPageFunc'] == $sub_page_func) {
|
6395 |
+
$navbar_item_css_class .= "\x20nav-tab-active";
|
6396 |
}
|
6397 |
|
6398 |
$params['Navbar'] .= sprintf(
|
6399 |
+
"<a class='%s' href='%s'>%s</a>\n",
|
6400 |
$navbar_item_css_class,
|
6401 |
+
$params[$pseudo_var],
|
6402 |
$sub_page_title
|
6403 |
);
|
6404 |
}
|
6412 |
* of the function.
|
6413 |
*
|
6414 |
* @param string $html The HTML content of a template file with its pseudo-variables parsed.
|
6415 |
+
* @param array $params Key-value array with pseudo-variables shared with the template.
|
6416 |
* @return string The formatted HTML content of the base template.
|
6417 |
*/
|
6418 |
+
public static function getBaseTemplate($html = '', $params = array())
|
6419 |
+
{
|
6420 |
+
$params = is_array($params) ? $params : array();
|
6421 |
|
6422 |
+
$params = self::sharedParams($params);
|
6423 |
$params['PageContent'] = $html;
|
6424 |
|
6425 |
+
return self::getTemplate('base', $params);
|
6426 |
}
|
6427 |
|
6428 |
/**
|
6431 |
* of the function.
|
6432 |
*
|
6433 |
* @param string $template Filename of the template that will be used to generate the page.
|
6434 |
+
* @param array $params Key-value array with pseudo-variables shared with the template.
|
6435 |
+
* @param boolean $type Template type; either page, section or snippet.
|
6436 |
+
* @return string Formatted HTML code after pseudo-variables replacement.
|
6437 |
+
*/
|
6438 |
+
public static function getTemplate($template = '', $params = array(), $type = 'page')
|
6439 |
+
{
|
6440 |
+
if (!is_array($params)) {
|
6441 |
+
$params = array();
|
|
|
|
|
|
|
|
|
|
|
6442 |
}
|
6443 |
|
6444 |
+
if ($type == 'page' || $type == 'section') {
|
6445 |
+
$fpath_pattern = '%s/%s/inc/tpl/%s.html.tpl';
|
6446 |
+
} elseif ($type == 'snippet') {
|
6447 |
+
$fpath_pattern = '%s/%s/inc/tpl/%s.snippet.tpl';
|
6448 |
+
} else {
|
6449 |
+
$fpath_pattern = null;
|
6450 |
+
}
|
6451 |
|
6452 |
+
if ($fpath_pattern !== null) {
|
6453 |
+
$output = '';
|
6454 |
+
$fpath = sprintf($fpath_pattern, WP_PLUGIN_DIR, SUCURISCAN_PLUGIN_FOLDER, $template);
|
6455 |
|
6456 |
+
if (file_exists($fpath) && is_readable($fpath)) {
|
6457 |
+
$output = @file_get_contents($fpath);
|
6458 |
|
6459 |
+
$params['SucuriURL'] = SUCURISCAN_URL;
|
|
|
|
|
|
|
|
|
|
|
6460 |
|
6461 |
+
// Detect the current page URL.
|
6462 |
+
if ($_page = self::get('page', '_page')) {
|
6463 |
+
$params['CurrentURL'] = SucuriScan::admin_url('admin.php?page=' . $_page);
|
6464 |
+
} else {
|
6465 |
+
$params['CurrentURL'] = SucuriScan::admin_url();
|
6466 |
+
}
|
6467 |
+
|
6468 |
+
// Replace the global pseudo-variables in the section/snippets templates.
|
6469 |
+
if ($template == 'base'
|
6470 |
+
&& array_key_exists('PageContent', $params)
|
6471 |
+
&& @preg_match('/%%SUCURI\.(.+)%%/', $params['PageContent'])
|
6472 |
+
) {
|
6473 |
+
$params['PageContent'] = self::replacePseudoVars($params['PageContent'], $params);
|
6474 |
+
}
|
6475 |
+
|
6476 |
+
$output = self::replacePseudoVars($output, $params);
|
6477 |
}
|
6478 |
|
6479 |
+
if ($template == 'base' || $type != 'page') {
|
6480 |
+
return $output;
|
6481 |
+
}
|
6482 |
|
6483 |
+
return self::getBaseTemplate($output, $params);
|
|
|
6484 |
}
|
6485 |
|
6486 |
+
return '';
|
6487 |
}
|
6488 |
|
6489 |
/**
|
6492 |
* of the function.
|
6493 |
*
|
6494 |
* @param string $template Filename of the template that will be used to generate the page.
|
6495 |
+
* @param array $params Key-value array with pseudo-variables shared with the template.
|
6496 |
* @return string The formatted HTML page after replace all the pseudo-variables.
|
6497 |
*/
|
6498 |
+
public static function getSection($template = '', $params = array())
|
6499 |
+
{
|
6500 |
+
$params = self::sharedParams($params);
|
6501 |
|
6502 |
+
return self::getTemplate($template, $params, 'section');
|
6503 |
}
|
6504 |
|
6505 |
/**
|
6508 |
* of the function.
|
6509 |
*
|
6510 |
* @param string $template Filename of the template that will be used to generate the page.
|
6511 |
+
* @param array $params Key-value array with pseudo-variables shared with the template.
|
6512 |
* @return string The formatted HTML page after replace all the pseudo-variables.
|
6513 |
*/
|
6514 |
+
public static function getModal($template = '', $params = array())
|
6515 |
+
{
|
6516 |
$required = array(
|
6517 |
'Title' => 'Lorem ipsum dolor sit amet',
|
6518 |
'Visibility' => 'visible',
|
6526 |
proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>',
|
6527 |
);
|
6528 |
|
6529 |
+
if (!empty($template) && $template != 'none') {
|
6530 |
+
$params['Content'] = self::getSection($template);
|
6531 |
}
|
6532 |
|
6533 |
+
foreach ($required as $param_name => $param_value) {
|
6534 |
+
if (!isset($params[$param_name])) {
|
6535 |
+
$params[$param_name] = $param_value;
|
6536 |
}
|
6537 |
}
|
6538 |
|
6539 |
$params['Visibility'] = 'sucuriscan-' . $params['Visibility'];
|
6540 |
$params['Identifier'] = 'sucuriscan-' . $template . '-modal';
|
6541 |
+
$params = self::sharedParams($params);
|
6542 |
|
6543 |
+
return self::getTemplate('modalwindow', $params, 'section');
|
6544 |
}
|
6545 |
|
6546 |
/**
|
6549 |
* of the function.
|
6550 |
*
|
6551 |
* @param string $template Filename of the template that will be used to generate the page.
|
6552 |
+
* @param array $params Key-value array with pseudo-variables shared with the template.
|
6553 |
* @return string The formatted HTML page after replace all the pseudo-variables.
|
6554 |
*/
|
6555 |
+
public static function getSnippet($template = '', $params = array())
|
6556 |
+
{
|
6557 |
+
return self::getTemplate($template, $params, 'snippet');
|
6558 |
}
|
6559 |
|
6560 |
/**
|
6564 |
* @param string $selected_val Value of the option that will be selected by default.
|
6565 |
* @return string Option list for a select form field.
|
6566 |
*/
|
6567 |
+
public static function selectOptions($allowed_values = array(), $selected_val = '')
|
6568 |
+
{
|
6569 |
$options = '';
|
6570 |
|
6571 |
+
foreach ($allowed_values as $option_name => $option_label) {
|
|
|
|
|
|
|
|
|
|
|
|
|
6572 |
$options .= sprintf(
|
6573 |
+
"<option %s value='%s'>%s</option>\n",
|
6574 |
+
($option_name === $selected_val ? 'selected="selected"' : ''),
|
6575 |
+
SucuriScan::escape($option_name),
|
6576 |
+
SucuriScan::escape($option_label)
|
6577 |
);
|
6578 |
}
|
6579 |
|
6585 |
*
|
6586 |
* @return integer Page number of the link clicked in a pagination.
|
6587 |
*/
|
6588 |
+
public static function pageNumber()
|
6589 |
+
{
|
6590 |
+
$paged = self::get('paged', '[0-9]{1,5}');
|
6591 |
|
6592 |
+
return ($paged ? intval($paged) : 1);
|
6593 |
}
|
6594 |
|
6595 |
/**
|
6600 |
* @param integer $max_per_page Maximum number of items that will be shown per page.
|
6601 |
* @return string HTML code for a pagination generated using the provided data.
|
6602 |
*/
|
6603 |
+
public static function pagination($base_url = '', $total_items = 0, $max_per_page = 1)
|
6604 |
+
{
|
6605 |
// Calculate the number of links for the pagination.
|
6606 |
$html_links = '';
|
6607 |
+
$page_number = self::pageNumber();
|
6608 |
+
$max_pages = ceil($total_items / $max_per_page);
|
6609 |
$extra_url = '';
|
6610 |
|
6611 |
// Fix for inline anchor URLs.
|
6612 |
+
if (@preg_match('/^(.+)(#.+)$/', $base_url, $match)) {
|
6613 |
$base_url = $match[1];
|
6614 |
$extra_url = $match[2];
|
6615 |
}
|
6616 |
|
6617 |
// Generate the HTML links for the pagination.
|
6618 |
+
for ($j = 1; $j <= $max_pages; $j++) {
|
6619 |
$link_class = 'sucuriscan-pagination-link';
|
6620 |
|
6621 |
+
if ($page_number == $j) {
|
6622 |
+
$link_class .= "\x20sucuriscan-pagination-active";
|
6623 |
}
|
6624 |
|
6625 |
$html_links .= sprintf(
|
6626 |
'<li><a href="%s&paged=%d%s" class="%s">%s</a></li>',
|
6627 |
+
$base_url,
|
6628 |
+
$j,
|
6629 |
+
$extra_url,
|
6630 |
+
$link_class,
|
6631 |
+
$j
|
6632 |
);
|
6633 |
}
|
6634 |
|
6635 |
return $html_links;
|
6636 |
}
|
|
|
6637 |
}
|
6638 |
|
6639 |
/**
|
6645 |
* content is then submitted to the remote server and it is stored for future
|
6646 |
* analysis.
|
6647 |
*/
|
6648 |
+
class SucuriScanFSScanner extends SucuriScan
|
6649 |
+
{
|
6650 |
|
6651 |
/**
|
6652 |
* Retrieve the last time when the filesystem scan was ran.
|
6654 |
* @param boolean $format Whether the timestamp must be formatted as date/time or not.
|
6655 |
* @return string The timestamp of the runtime, or an string with the date/time.
|
6656 |
*/
|
6657 |
+
public static function get_filesystem_runtime($format = false)
|
6658 |
+
{
|
6659 |
+
$runtime = SucuriScanOption::get_option(':runtime');
|
6660 |
|
6661 |
+
if ($runtime > 0) {
|
6662 |
+
if ($format) {
|
6663 |
+
return SucuriScan::datetime($runtime);
|
6664 |
}
|
6665 |
|
6666 |
return $runtime;
|
6667 |
}
|
6668 |
|
6669 |
+
if ($format) {
|
6670 |
+
return 'Unknown';
|
6671 |
}
|
6672 |
|
6673 |
return false;
|
6681 |
*
|
6682 |
* @return boolean Whether the feature to ignore files is enabled or not.
|
6683 |
*/
|
6684 |
+
public static function will_ignore_scanning()
|
6685 |
+
{
|
6686 |
+
return SucuriScanOption::is_enabled(':ignore_scanning');
|
6687 |
}
|
6688 |
|
6689 |
/**
|
6692 |
* @param string $directory_path The (full) absolute path of a directory.
|
6693 |
* @return boolean TRUE if the directory path was added to the list, FALSE otherwise.
|
6694 |
*/
|
6695 |
+
public static function ignore_directory($directory_path = '')
|
6696 |
+
{
|
6697 |
+
$cache = new SucuriScanCache('ignorescanning');
|
6698 |
|
6699 |
// Use the checksum of the directory path as the cache key.
|
6700 |
+
$cache_key = md5($directory_path);
|
6701 |
+
$resource_type = SucuriScanFileInfo::get_resource_type($directory_path);
|
6702 |
$cache_value = array(
|
6703 |
'directory_path' => $directory_path,
|
6704 |
'ignored_at' => self::local_time(),
|
6705 |
'resource_type' => $resource_type,
|
6706 |
);
|
6707 |
+
$cached = $cache->add($cache_key, $cache_value);
|
6708 |
|
6709 |
return $cached;
|
6710 |
}
|
6715 |
* @param string $directory_path The (full) absolute path of a directory.
|
6716 |
* @return boolean TRUE if the directory path was removed to the list, FALSE otherwise.
|
6717 |
*/
|
6718 |
+
public static function unignore_directory($directory_path = '')
|
6719 |
+
{
|
6720 |
+
$cache = new SucuriScanCache('ignorescanning');
|
6721 |
|
6722 |
// Use the checksum of the directory path as the cache key.
|
6723 |
+
$cache_key = md5($directory_path);
|
6724 |
+
$removed = $cache->delete($cache_key);
|
6725 |
|
6726 |
return $removed;
|
6727 |
}
|
6747 |
*
|
6748 |
* @return array List of ignored directory paths.
|
6749 |
*/
|
6750 |
+
public static function get_ignored_directories()
|
6751 |
+
{
|
6752 |
$response = array(
|
6753 |
'raw' => array(),
|
6754 |
'checksums' => array(),
|
6756 |
'ignored_at_list' => array(),
|
6757 |
);
|
6758 |
|
6759 |
+
$cache = new SucuriScanCache('ignorescanning');
|
6760 |
$cache_lifetime = 0; // It is not necessary to expire this cache.
|
6761 |
+
$ignored_directories = $cache->getAll($cache_lifetime, 'array');
|
6762 |
|
6763 |
+
if ($ignored_directories) {
|
6764 |
$response['raw'] = $ignored_directories;
|
6765 |
|
6766 |
+
foreach ($ignored_directories as $checksum => $data) {
|
6767 |
+
if (array_key_exists('directory_path', $data)
|
6768 |
+
&& array_key_exists('ignored_at', $data)
|
|
|
6769 |
) {
|
6770 |
$response['checksums'][] = $checksum;
|
6771 |
$response['directories'][] = $data['directory_path'];
|
6787 |
*
|
6788 |
* @return array List of ignored and not ignored directories.
|
6789 |
*/
|
6790 |
+
public static function get_ignored_directories_live()
|
6791 |
+
{
|
6792 |
$response = array(
|
6793 |
'is_ignored' => array(),
|
6794 |
'is_not_ignored' => array(),
|
6797 |
// Get the ignored directories from the cache.
|
6798 |
$ignored_directories = self::get_ignored_directories();
|
6799 |
|
6800 |
+
if ($ignored_directories) {
|
6801 |
$response['is_ignored'] = $ignored_directories['raw'];
|
6802 |
}
|
6803 |
|
6805 |
$file_info = new SucuriScanFileInfo();
|
6806 |
$file_info->ignore_files = true;
|
6807 |
$file_info->ignore_directories = true;
|
6808 |
+
$file_info->scan_interface = SucuriScanOption::get_option(':scan_interface');
|
6809 |
+
$directory_list = $file_info->get_diretories_only(ABSPATH);
|
6810 |
|
6811 |
+
if ($directory_list) {
|
6812 |
$response['is_not_ignored'] = $directory_list;
|
6813 |
}
|
6814 |
|
6821 |
* @param array $error_logs The content of an error log file, or an array with the lines.
|
6822 |
* @return array List of valid error logs with their attributes separated.
|
6823 |
*/
|
6824 |
+
public static function parse_error_logs($error_logs = array())
|
6825 |
+
{
|
6826 |
$logs_arr = array();
|
6827 |
$pattern = '/^'
|
6828 |
. '(\[(\S+) ([0-9:]{5,8})( \S+)?\] )?' // Detect date, time, and timezone.
|
6831 |
. '(:| on line )([0-9]+)' // Detect line number.
|
6832 |
. '$/';
|
6833 |
|
6834 |
+
if (is_string($error_logs)) {
|
6835 |
+
$error_logs = explode("\n", $error_logs);
|
6836 |
}
|
6837 |
|
6838 |
+
foreach ((array) $error_logs as $line) {
|
6839 |
+
if (!is_string($line) || empty($line)) {
|
6840 |
continue;
|
6841 |
}
|
6842 |
|
6843 |
+
if (preg_match($pattern, $line, $match)) {
|
6844 |
$data_set = array(
|
6845 |
'date' => '',
|
6846 |
'time' => '',
|
6857 |
// Basic attributes from the scrapping.
|
6858 |
$data_set['date'] = $match[2];
|
6859 |
$data_set['time'] = $match[3];
|
6860 |
+
$data_set['time_zone'] = trim($match[4]);
|
6861 |
+
$data_set['error_type'] = trim($match[6]);
|
6862 |
+
$data_set['error_message'] = trim($match[7]);
|
6863 |
+
$data_set['file_path'] = trim($match[8]);
|
6864 |
$data_set['line_number'] = (int) $match[10];
|
6865 |
|
6866 |
// Additional data from the attributes.
|
6867 |
+
if ($data_set['date']) {
|
6868 |
$data_set['date_time'] = $data_set['date']
|
6869 |
. "\x20" . $data_set['time']
|
6870 |
. "\x20" . $data_set['time_zone'];
|
6871 |
+
$data_set['timestamp'] = strtotime($data_set['date_time']);
|
6872 |
}
|
6873 |
|
6874 |
+
if ($data_set['error_type']) {
|
6875 |
$valid_types = array( 'warning', 'notice', 'error' );
|
6876 |
|
6877 |
+
foreach ($valid_types as $valid_type) {
|
6878 |
+
if (stripos($data_set['error_type'], $valid_type) !== false) {
|
6879 |
$data_set['error_code'] = $valid_type;
|
6880 |
break;
|
6881 |
}
|
6888 |
|
6889 |
return $logs_arr;
|
6890 |
}
|
|
|
6891 |
}
|
6892 |
|
6893 |
/**
|
6902 |
*
|
6903 |
* @see https://core.trac.wordpress.org/ticket/23216
|
6904 |
*/
|
6905 |
+
class SucuriScanHeartbeat extends SucuriScanOption
|
6906 |
+
{
|
6907 |
|
6908 |
/**
|
6909 |
* Stop execution of the heartbeat API in certain parts of the site.
|
6910 |
*
|
6911 |
* @return void
|
6912 |
*/
|
6913 |
+
public static function register_script()
|
6914 |
+
{
|
6915 |
global $pagenow;
|
6916 |
|
6917 |
+
$status = SucuriScanOption::get_option(':heartbeat');
|
6918 |
|
6919 |
// Enable heartbeat everywhere.
|
6920 |
+
if ($status == 'enabled') {
|
6921 |
/* Do nothing */
|
6922 |
+
} // Disable heartbeat everywhere.
|
6923 |
+
elseif ($status == 'disabled') {
|
6924 |
+
wp_deregister_script('heartbeat');
|
6925 |
+
} // Disable heartbeat only on the dashboard and home pages.
|
6926 |
+
elseif ($status == 'dashboard'
|
|
|
|
|
|
|
|
|
|
|
6927 |
&& $pagenow == 'index.php'
|
6928 |
) {
|
6929 |
+
wp_deregister_script('heartbeat');
|
6930 |
+
} // Disable heartbeat everywhere except in post edition.
|
6931 |
+
elseif ($status == 'addpost'
|
|
|
|
|
|
|
6932 |
&& $pagenow != 'post.php'
|
6933 |
&& $pagenow != 'post-new.php'
|
6934 |
) {
|
6935 |
+
wp_deregister_script('heartbeat');
|
6936 |
}
|
6937 |
}
|
6938 |
|
6946 |
* @param array $settings Heartbeat settings.
|
6947 |
* @return array Updated version of the heartbeat settings.
|
6948 |
*/
|
6949 |
+
public static function update_settings($settings = array())
|
6950 |
+
{
|
6951 |
+
$pulse = SucuriScanOption::get_option(':heartbeat_pulse');
|
6952 |
+
$autostart = SucuriScanOption::get_option(':heartbeat_autostart');
|
6953 |
|
6954 |
+
if ($pulse < 15 || $pulse > 60) {
|
6955 |
+
SucuriScanOption::delete_option(':heartbeat_pulse');
|
6956 |
$pulse = 15;
|
6957 |
}
|
6958 |
|
6970 |
* @param string $screen_id Identifier of the screen the heartbeat occurred on.
|
6971 |
* @return array Response with new data.
|
6972 |
*/
|
6973 |
+
public static function respond_to_received($response = array(), $data = array(), $screen_id = '')
|
6974 |
+
{
|
6975 |
+
$interval = SucuriScanOption::get_option(':heartbeat_interval');
|
6976 |
|
6977 |
+
if ($interval == 'slow'
|
|
|
6978 |
|| $interval == 'fast'
|
6979 |
|| $interval == 'standard'
|
6980 |
) {
|
6981 |
$response['heartbeat_interval'] = $interval;
|
6982 |
} else {
|
6983 |
+
SucuriScanOption::delete_option(':heartbeat_interval');
|
6984 |
}
|
6985 |
|
6986 |
return $response;
|
6993 |
* @param string $screen_id Identifier of the screen the heartbeat occurred on.
|
6994 |
* @return array Response with new data.
|
6995 |
*/
|
6996 |
+
public static function respond_to_send($response = array(), $screen_id = '')
|
6997 |
+
{
|
6998 |
return $response;
|
6999 |
}
|
7000 |
|
7003 |
*
|
7004 |
* @return array Allowed values for the heartbeat status.
|
7005 |
*/
|
7006 |
+
public static function statuses_allowed()
|
7007 |
+
{
|
7008 |
return array(
|
7009 |
'enabled' => 'Enable everywhere',
|
7010 |
'disabled' => 'Disable everywhere',
|
7018 |
*
|
7019 |
* @return array Allowed values for the heartbeat intervals.
|
7020 |
*/
|
7021 |
+
public static function intervals_allowed()
|
7022 |
+
{
|
7023 |
return array(
|
7024 |
'slow' => 'Slow interval',
|
7025 |
'fast' => 'Fast interval',
|
7032 |
*
|
7033 |
* @return array Allowed values for the heartbeat pulses.
|
7034 |
*/
|
7035 |
+
public static function pulses_allowed()
|
7036 |
+
{
|
7037 |
$pulses = array();
|
7038 |
|
7039 |
+
for ($i = 15; $i <= 60; $i++) {
|
7040 |
+
$pulses[ $i ] = sprintf('Run every %d seconds', $i);
|
7041 |
}
|
7042 |
|
7043 |
return $pulses;
|
7044 |
}
|
|
|
7045 |
}
|
7046 |
|
7047 |
/**
|
7053 |
* sites with old versions of the premium plugin (that was deprecated at
|
7054 |
* July/2014).
|
7055 |
*/
|
7056 |
+
class SucuriScanInterface
|
7057 |
+
{
|
7058 |
/**
|
7059 |
* Initialization code for the plugin.
|
7060 |
*
|
7065 |
*
|
7066 |
* @return void
|
7067 |
*/
|
7068 |
+
public static function initialize()
|
7069 |
+
{
|
7070 |
+
if (SucuriScan::support_reverse_proxy()
|
7071 |
+
|| SucuriScan::is_behind_cloudproxy()
|
7072 |
+
) {
|
7073 |
$_SERVER['SUCURIREAL_REMOTE_ADDR'] = $_SERVER['REMOTE_ADDR'];
|
7074 |
$_SERVER['REMOTE_ADDR'] = SucuriScan::get_remote_addr();
|
7075 |
}
|
7081 |
*
|
7082 |
* @return void
|
7083 |
*/
|
7084 |
+
public static function enqueue_scripts()
|
7085 |
+
{
|
7086 |
$asset_version = '';
|
7087 |
|
7088 |
+
if (strlen(SUCURISCAN_PLUGIN_CHECKSUM) >= 7) {
|
7089 |
+
$asset_version = substr(SUCURISCAN_PLUGIN_CHECKSUM, 0, 7);
|
7090 |
}
|
7091 |
|
7092 |
+
wp_register_style('sucuriscan', SUCURISCAN_URL . '/inc/css/sucuri-scanner.min.css', array(), $asset_version);
|
7093 |
+
wp_register_script('sucuriscan', SUCURISCAN_URL . '/inc/js/sucuri-scanner.min.js', array(), $asset_version);
|
7094 |
+
wp_enqueue_style('sucuriscan');
|
7095 |
+
wp_enqueue_script('sucuriscan');
|
7096 |
|
7097 |
+
if (SucuriScanRequest::get('page', 'sucuriscan') !== false) {
|
7098 |
+
wp_register_script('sucuriscan2', SUCURISCAN_URL . '/inc/js/d3.min.js', array(), $asset_version);
|
7099 |
+
wp_register_script('sucuriscan3', SUCURISCAN_URL . '/inc/js/c3.min.js', array(), $asset_version);
|
7100 |
+
wp_enqueue_script('sucuriscan2');
|
7101 |
+
wp_enqueue_script('sucuriscan3');
|
7102 |
}
|
7103 |
}
|
7104 |
|
7107 |
*
|
7108 |
* @return void
|
7109 |
*/
|
7110 |
+
public static function add_interface_menu()
|
7111 |
+
{
|
7112 |
global $sucuriscan_pages;
|
7113 |
|
7114 |
+
if (function_exists('add_menu_page')
|
|
|
7115 |
&& $sucuriscan_pages
|
7116 |
+
&& is_array($sucuriscan_pages)
|
7117 |
+
&& array_key_exists('sucuriscan', $sucuriscan_pages)
|
7118 |
) {
|
7119 |
// Add main menu link.
|
7120 |
add_menu_page(
|
7126 |
SUCURISCAN_URL . '/inc/images/menu-icon.png'
|
7127 |
);
|
7128 |
|
7129 |
+
foreach ($sucuriscan_pages as $sub_page_func => $sub_page_title) {
|
7130 |
+
if ($sub_page_func == 'sucuriscan_scanner'
|
7131 |
+
&& SucuriScanOption::is_disabled(':sitecheck_scanner')
|
|
|
7132 |
) {
|
7133 |
continue;
|
7134 |
}
|
7155 |
*
|
7156 |
* @return void
|
7157 |
*/
|
7158 |
+
public static function handle_old_plugins()
|
7159 |
+
{
|
7160 |
+
if (class_exists('SucuriScanFileInfo')) {
|
7161 |
$file_info = new SucuriScanFileInfo();
|
7162 |
$file_info->ignore_files = false;
|
7163 |
$file_info->ignore_directories = false;
|
7167 |
'sucuri-cloudproxy-waf/cloudproxy.php',
|
7168 |
);
|
7169 |
|
7170 |
+
foreach ($plugins as $plugin) {
|
7171 |
+
$plugin_directory = dirname(WP_PLUGIN_DIR . '/' . $plugin);
|
7172 |
|
7173 |
+
if (file_exists($plugin_directory)) {
|
7174 |
+
if (is_plugin_active($plugin)) {
|
7175 |
+
deactivate_plugins($plugin);
|
7176 |
}
|
7177 |
|
7178 |
+
$plugin_removed = $file_info->remove_directory_tree($plugin_directory);
|
7179 |
}
|
7180 |
}
|
7181 |
}
|
7187 |
*
|
7188 |
* @return void
|
7189 |
*/
|
7190 |
+
public static function create_datastore_folder()
|
7191 |
+
{
|
7192 |
$directory = SucuriScan::datastore_folder_path();
|
7193 |
|
7194 |
if (!file_exists($directory)) {
|
7195 |
@mkdir($directory, 0755, true);
|
7196 |
}
|
7197 |
|
7198 |
+
if (@preg_match(';/uploads/$;', $directory)) {
|
7199 |
+
SucuriScanOption::delete_option(':datastore_path');
|
7200 |
+
SucuriScanInterface::error('Uploads directory must not be used as the data store path.');
|
7201 |
+
} elseif (file_exists($directory)) {
|
7202 |
// Create last-logins datastore file.
|
7203 |
sucuriscan_lastlogins_datastore_exists();
|
7204 |
|
7219 |
SucuriScanOption::delete_option(':datastore_path');
|
7220 |
SucuriScanInterface::error(
|
7221 |
'Data folder does not exists and could not be created. Try to <a href="' .
|
7222 |
+
SucuriScanTemplate::getUrl('settings') . '">click this link</a> to see
|
7223 |
if the plugin is able to fix this error automatically, if this message
|
7224 |
reappears you will need to either change the location of the directory from
|
7225 |
the plugin general settings page or create this directory manually and give
|
7233 |
*
|
7234 |
* @return void
|
7235 |
*/
|
7236 |
+
public static function check_permissions()
|
7237 |
+
{
|
7238 |
+
if (!function_exists('current_user_can')
|
7239 |
+
|| !current_user_can('manage_options')
|
7240 |
) {
|
7241 |
+
$page = SucuriScanRequest::get('page', '_page');
|
7242 |
+
$page = SucuriScan::escape($page);
|
7243 |
+
wp_die(__('Access denied by <b>Sucuri</b> to see <code>' . $page . '</code>'));
|
7244 |
}
|
7245 |
}
|
7246 |
|
7251 |
*
|
7252 |
* @return boolean Either TRUE or FALSE if the nonce is valid or not respectively.
|
7253 |
*/
|
7254 |
+
public static function check_nonce()
|
7255 |
+
{
|
7256 |
+
if (!empty($_POST)) {
|
7257 |
$nonce_name = 'sucuriscan_page_nonce';
|
7258 |
+
$nonce_value = SucuriScanRequest::post($nonce_name, '_nonce');
|
7259 |
|
7260 |
+
if (!$nonce_value || !wp_verify_nonce($nonce_value, $nonce_name)) {
|
7261 |
+
wp_die(__('WordPress Nonce verification failed, try again going back and checking the form.'));
|
7262 |
|
7263 |
return false;
|
7264 |
}
|
7274 |
* @param string $message The message that will be printed in the alert.
|
7275 |
* @return void
|
7276 |
*/
|
7277 |
+
private static function admin_notice($type = 'updated', $message = '')
|
7278 |
+
{
|
7279 |
$display_notice = true;
|
7280 |
|
7281 |
/**
|
7287 |
* user authentication process is executed may cause a "headers already sent"
|
7288 |
* error.
|
7289 |
*/
|
7290 |
+
if (!empty($_POST)
|
7291 |
+
&& SucuriScanRequest::post('log')
|
7292 |
+
&& SucuriScanRequest::post('pwd')
|
7293 |
+
&& SucuriScanRequest::post('wp-submit')
|
|
|
7294 |
) {
|
7295 |
$display_notice = false;
|
7296 |
}
|
7297 |
|
7298 |
// Display the HTML notice to the current user.
|
7299 |
+
if ($display_notice === true && !empty($message)) {
|
7300 |
+
echo SucuriScanTemplate::getSection(
|
7301 |
+
'notification-admin',
|
7302 |
+
array(
|
7303 |
+
'AlertType' => $type,
|
7304 |
+
'AlertUnique' => rand(100, 999),
|
7305 |
+
'AlertMessage' => $message,
|
7306 |
+
)
|
7307 |
+
);
|
7308 |
}
|
7309 |
}
|
7310 |
|
7314 |
* @param string $error_msg The message that will be printed in the alert.
|
7315 |
* @return void
|
7316 |
*/
|
7317 |
+
public static function error($error_msg = '')
|
7318 |
+
{
|
7319 |
+
self::admin_notice('error', '<b>Sucuri:</b> ' . $error_msg);
|
7320 |
}
|
7321 |
|
7322 |
/**
|
7325 |
* @param string $info_msg The message that will be printed in the alert.
|
7326 |
* @return void
|
7327 |
*/
|
7328 |
+
public static function info($info_msg = '')
|
7329 |
+
{
|
7330 |
+
self::admin_notice('updated', '<b>Sucuri:</b> ' . $info_msg);
|
7331 |
}
|
7332 |
|
7333 |
/**
|
7337 |
*
|
7338 |
* @return void
|
7339 |
*/
|
7340 |
+
public static function setup_notice()
|
7341 |
+
{
|
7342 |
+
if (current_user_can('manage_options')
|
7343 |
&& SucuriScan::no_notices_here() === false
|
7344 |
+
&& !SucuriScanAPI::getPluginKey()
|
7345 |
+
&& SucuriScanRequest::post(':plugin_api_key') === false
|
7346 |
+
&& SucuriScanRequest::post(':recover_key') === false
|
7347 |
+
&& !SucuriScanRequest::post(':manual_api_key')
|
7348 |
) {
|
7349 |
if (SucuriScanRequest::get(':dismiss_setup') !== false) {
|
7350 |
SucuriScanOption::update_option(':dismiss_setup', 'enabled');
|
7351 |
} elseif (SucuriScanOption::is_enabled(':dismiss_setup')) {
|
7352 |
/* Do not display API key generation form. */
|
7353 |
} else {
|
7354 |
+
echo SucuriScanTemplate::getSection('setup-notice');
|
7355 |
+
echo SucuriScanTemplate::getModal('setup-form', array(
|
7356 |
'Visibility' => 'hidden',
|
7357 |
'Title' => 'Sucuri API key generation',
|
7358 |
'CssClass' => 'sucuriscan-setup-instructions',
|
7360 |
}
|
7361 |
}
|
7362 |
}
|
7363 |
+
}
|
7364 |
+
|
7365 |
+
/**
|
7366 |
+
* Scan the content directory for files that were modified during the last seven
|
7367 |
+
* days (by default) or during the number of days specified by the user in the
|
7368 |
+
* request. Note that this operation may fail with an internal server error if
|
7369 |
+
* the project contains too many files that the PHP interpreter can check in a
|
7370 |
+
* single run.
|
7371 |
+
*
|
7372 |
+
* @return void
|
7373 |
+
*/
|
7374 |
+
function sucuriscan_modified_files()
|
7375 |
+
{
|
7376 |
+
// TODO: Keep the array values hardcoded for now.
|
7377 |
+
$valid_day_ranges = array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20, 30, 60);
|
7378 |
+
$template_variables = array(
|
7379 |
+
'ModifiedFiles.List' => '',
|
7380 |
+
'ModifiedFiles.SelectOptions' => '',
|
7381 |
+
'ModifiedFiles.Days' => 0,
|
7382 |
+
);
|
7383 |
+
|
7384 |
+
// Generate the options for the select field of the page form.
|
7385 |
+
if ($valid_day_ranges) {
|
7386 |
+
$options = array();
|
7387 |
+
foreach ($valid_day_ranges as $day) {
|
7388 |
+
$options[$day] = sprintf(
|
7389 |
+
'%d day%s ago',
|
7390 |
+
$day,
|
7391 |
+
($day === 1)?'':'s'
|
7392 |
+
);
|
7393 |
+
}
|
7394 |
+
$options_html = SucuriScanTemplate::selectOptions($options, 7);
|
7395 |
+
$template_variables['ModifiedFiles.SelectOptions'] = $options_html;
|
7396 |
+
}
|
7397 |
+
|
7398 |
+
return SucuriScanTemplate::getSection('integrity-modifiedfiles', $template_variables);
|
7399 |
+
}
|
7400 |
+
|
7401 |
+
function sucuriscan_scanner_modfiles_days($back_days = 0)
|
7402 |
+
{
|
7403 |
+
$default_number_of_days = 7;
|
7404 |
+
$back_days = intval($back_days);
|
7405 |
+
|
7406 |
+
// Keep the number of days in range.
|
7407 |
+
if ($back_days === false) {
|
7408 |
+
$back_days = $default_number_of_days;
|
7409 |
+
} else {
|
7410 |
+
if ($back_days <= 0) {
|
7411 |
+
$back_days = 1;
|
7412 |
+
} elseif ($back_days >= 60) {
|
7413 |
+
$back_days = 60;
|
7414 |
+
}
|
7415 |
+
}
|
7416 |
+
|
7417 |
+
return $back_days;
|
7418 |
+
}
|
7419 |
|
7420 |
+
function sucuriscan_scanner_modfiles_ajax()
|
7421 |
+
{
|
7422 |
+
if (SucuriScanRequest::post('form_action') == 'get_modfiles') {
|
7423 |
+
$response = '';
|
7424 |
+
$hashes = sucuriscan_get_integrity_tree(WP_CONTENT_DIR, true);
|
7425 |
+
$back_days = SucuriScanRequest::post(':last_days', '[0-9]+');
|
7426 |
+
$back_days = sucuriscan_scanner_modfiles_days($back_days);
|
7427 |
+
|
7428 |
+
if (!empty($hashes)) {
|
7429 |
+
$counter = 0;
|
7430 |
+
$back_days = current_time('timestamp') - ($back_days * 86400);
|
7431 |
+
|
7432 |
+
foreach ($hashes as $file_path => $file_info) {
|
7433 |
+
if (isset($file_info['modified_at'])
|
7434 |
+
&& $file_info['modified_at'] >= $back_days
|
7435 |
+
) {
|
7436 |
+
$css_class = ($counter % 2 === 0) ? '' : 'alternate';
|
7437 |
+
$mod_date = SucuriScan::datetime($file_info['modified_at']);
|
7438 |
+
|
7439 |
+
$response .= SucuriScanTemplate::getSnippet(
|
7440 |
+
'integrity-modifiedfiles',
|
7441 |
+
array(
|
7442 |
+
'ModifiedFiles.DateTime' => $mod_date,
|
7443 |
+
'ModifiedFiles.FilePath' => $file_path,
|
7444 |
+
'ModifiedFiles.CheckSum' => $file_info['checksum'],
|
7445 |
+
'ModifiedFiles.FileSize' => $file_info['filesize'],
|
7446 |
+
'ModifiedFiles.FileSizeHuman' => SucuriScan::human_filesize($file_info['filesize']),
|
7447 |
+
'ModifiedFiles.FileSizeNumber' => number_format($file_info['filesize']),
|
7448 |
+
'ModifiedFiles.CssClass' => $css_class,
|
7449 |
+
)
|
7450 |
+
);
|
7451 |
+
$counter++;
|
7452 |
+
}
|
7453 |
+
}
|
7454 |
+
}
|
7455 |
+
|
7456 |
+
print($response);
|
7457 |
+
exit(0);
|
7458 |
+
}
|
7459 |
}
|
7460 |
|
7461 |
/**
|
7465 |
*
|
7466 |
* @return void
|
7467 |
*/
|
7468 |
+
function sucuriscan_scanner_page()
|
7469 |
+
{
|
7470 |
SucuriScanInterface::check_permissions();
|
7471 |
|
7472 |
+
$params = array();
|
7473 |
+
$cache = new SucuriScanCache('sitecheck');
|
7474 |
+
$scan_results = $cache->get('scan_results', SUCURISCAN_SITECHECK_LIFETIME, 'array');
|
7475 |
+
$report_results = (bool) ($scan_results && !empty($scan_results));
|
7476 |
|
7477 |
+
if (SucuriScanInterface::check_nonce()
|
7478 |
+
&& SucuriScanRequest::post(':malware_scan', '1')
|
|
|
7479 |
) {
|
7480 |
$report_results = true;
|
7481 |
}
|
7482 |
|
7483 |
+
if ($report_results === true) {
|
7484 |
$template_name = 'malwarescan-results';
|
7485 |
+
$params = sucuriscan_sitecheck_info($scan_results);
|
7486 |
+
$params['PageTitle'] = 'Malware Scan';
|
7487 |
+
$params['PageStyleClass'] = 'scanner-results';
|
7488 |
} else {
|
7489 |
$template_name = 'malwarescan';
|
7490 |
+
$params['PageTitle'] = 'Malware Scan';
|
7491 |
+
$params['PageStyleClass'] = 'scanner-loading';
|
7492 |
+
}
|
7493 |
+
|
7494 |
+
echo SucuriScanTemplate::getTemplate($template_name, $params);
|
7495 |
+
}
|
7496 |
+
|
7497 |
+
/**
|
7498 |
+
* Handle an Ajax request for this specific page.
|
7499 |
+
*
|
7500 |
+
* @return mixed.
|
7501 |
+
*/
|
7502 |
+
function sucuriscan_scanner_ajax()
|
7503 |
+
{
|
7504 |
+
SucuriScanInterface::check_permissions();
|
7505 |
+
|
7506 |
+
if (SucuriScanInterface::check_nonce()) {
|
7507 |
+
sucuriscan_scanner_modfiles_ajax();
|
7508 |
}
|
7509 |
|
7510 |
+
wp_die();
|
7511 |
}
|
7512 |
|
7513 |
/**
|
7516 |
* @param array $scan_results Array with information of the scanning.
|
7517 |
* @return array Array with psuedo-variables to build the template.
|
7518 |
*/
|
7519 |
+
function sucuriscan_sitecheck_info($scan_results = array())
|
7520 |
+
{
|
7521 |
$clean_domain = SucuriScan::get_domain();
|
7522 |
+
$params = array(
|
7523 |
'ScannedDomainName' => $clean_domain,
|
7524 |
'ScannerResults.CssClass' => '',
|
7525 |
'ScannerResults.Content' => '',
|
7535 |
);
|
7536 |
|
7537 |
// If the results are not cached, then request a new scan and store in cache.
|
7538 |
+
if ($scan_results === false) {
|
7539 |
+
$scan_results = SucuriScanAPI::getSitecheckResults($clean_domain);
|
7540 |
|
7541 |
// Check for error messages in the request's response.
|
7542 |
+
if (is_string($scan_results)) {
|
7543 |
+
if (@preg_match('/^ERROR:(.*)/', $scan_results, $error_m)) {
|
7544 |
+
SucuriScanInterface::error(
|
7545 |
+
'The site <code>' . SucuriScan::escape($clean_domain) . '</code>'
|
7546 |
+
. ' was not scanned: ' . SucuriScan::escape($error_m[1])
|
7547 |
+
);
|
7548 |
} else {
|
7549 |
+
SucuriScanInterface::error('SiteCheck error: ' . $scan_results);
|
7550 |
}
|
7551 |
} else {
|
7552 |
+
$cache = new SucuriScanCache('sitecheck');
|
7553 |
+
$results_were_cached = $cache->add('scan_results', $scan_results);
|
7554 |
|
7555 |
+
if (!$results_were_cached) {
|
7556 |
+
SucuriScanInterface::error('Could not cache the malware scan results.');
|
7557 |
}
|
7558 |
}
|
7559 |
}
|
7560 |
|
7561 |
+
if (is_array($scan_results) && !empty($scan_results)) {
|
7562 |
// Increase the malware scan counter.
|
7563 |
+
$sitecheck_counter = (int) SucuriScanOption::get_option(':sitecheck_counter');
|
7564 |
+
SucuriScanOption::update_option(':sitecheck_counter', $sitecheck_counter + 1);
|
7565 |
add_thickbox();
|
7566 |
|
7567 |
+
$params = sucuriscan_sitecheck_scanner_results($scan_results, $params);
|
7568 |
+
$params = sucuriscan_sitecheck_website_details($scan_results, $params);
|
7569 |
+
$params = sucuriscan_sitecheck_website_links($scan_results, $params);
|
7570 |
+
$params = sucuriscan_sitecheck_blacklist_status($scan_results, $params);
|
7571 |
+
$params = sucuriscan_sitecheck_modified_files($scan_results, $params);
|
7572 |
|
7573 |
+
if (isset($scan_results['MALWARE']['WARN'])
|
|
|
7574 |
|| isset($scan_results['BLACKLIST']['WARN'])
|
7575 |
) {
|
7576 |
+
$params['SignupButtonVisibility'] = 'visible';
|
7577 |
}
|
7578 |
}
|
7579 |
|
7580 |
+
return $params;
|
7581 |
}
|
7582 |
|
7583 |
/**
|
7585 |
* the HTML code to display the information in the malware scan page inside the
|
7586 |
* remote scanner results tab.
|
7587 |
*
|
7588 |
+
* @param array $scan_results Array with information of the scanning.
|
7589 |
+
* @param array $params Array with psuedo-variables to build the template.
|
7590 |
+
* @return array Psuedo-variables to build the template including extra info.
|
7591 |
*/
|
7592 |
+
function sucuriscan_sitecheck_scanner_results($scan_results = false, $params = array())
|
7593 |
+
{
|
7594 |
$secvars = array(
|
7595 |
'CacheLifeTime' => SUCURISCAN_SITECHECK_LIFETIME,
|
7596 |
'WebsiteStatus' => 'Site status unknown',
|
7599 |
'MalwarePayloadList' => '',
|
7600 |
);
|
7601 |
|
7602 |
+
if (isset($scan_results['MALWARE']['WARN'])) {
|
7603 |
+
$params['ScannerResults.CssClass'] = 'sucuriscan-red-tab';
|
7604 |
$secvars['WebsiteStatus'] = 'Site compromised (malware was identified)';
|
7605 |
$secvars['NoMalwareRowVisibility'] = 'hidden';
|
7606 |
$secvars['FixButtonVisibility'] = 'visible';
|
7607 |
|
7608 |
+
foreach ($scan_results['MALWARE']['WARN'] as $key => $malres) {
|
7609 |
+
$malres = SucuriScanAPI::getSitecheckMalware($malres);
|
7610 |
+
|
7611 |
+
if ($malres !== false) {
|
7612 |
+
$secvars['MalwarePayloadList'] .= SucuriScanTemplate::getSnippet(
|
7613 |
+
'malwarescan-resmalware',
|
7614 |
+
array(
|
7615 |
+
'MalwareKey' => $key,
|
7616 |
+
'MalwareDocs' => $malres['malware_docs'],
|
7617 |
+
'MalwareType' => $malres['malware_type'],
|
7618 |
+
'MalwarePayload' => $malres['malware_payload'],
|
7619 |
+
'AlertMessage' => $malres['alert_message'],
|
7620 |
+
'InfectedUrl' => $malres['infected_url'],
|
7621 |
+
)
|
7622 |
+
);
|
7623 |
}
|
7624 |
}
|
7625 |
} else {
|
7626 |
$secvars['WebsiteStatus'] = 'Site clean (no malware was identified)';
|
7627 |
}
|
7628 |
|
7629 |
+
$params['ScannerResults.Content'] = SucuriScanTemplate::getSection('malwarescan-resmalware', $secvars);
|
7630 |
|
7631 |
+
return $params;
|
7632 |
}
|
7633 |
|
7634 |
/**
|
7636 |
* the HTML code to display the information in the malware scan page inside the
|
7637 |
* website details tab.
|
7638 |
*
|
7639 |
+
* @param array $scan_results Array with information of the scanning.
|
7640 |
+
* @param array $params Array with psuedo-variables to build the template.
|
7641 |
+
* @return array Psuedo-variables to build the template including extra info.
|
7642 |
*/
|
7643 |
+
function sucuriscan_sitecheck_website_details($scan_results = false, $params = array())
|
7644 |
+
{
|
7645 |
$secvars = array(
|
7646 |
'UpdateWebsiteButtonVisibility' => 'hidden',
|
7647 |
'VersionNumberOfTheUpdate' => '0.0',
|
7648 |
+
'AdminUrlForUpdates' => SucuriScan::admin_url('update-core.php'),
|
7649 |
'GenericInformationList' => '',
|
7650 |
'NoAppDetailsVisibility' => 'visible',
|
7651 |
'ApplicationDetailsList' => '',
|
7656 |
);
|
7657 |
|
7658 |
// Check whether this WordPress installation needs an update.
|
7659 |
+
if (function_exists('get_core_updates')) {
|
7660 |
$site_updates = get_core_updates();
|
7661 |
|
7662 |
+
if (!is_array($site_updates)
|
|
|
7663 |
|| empty($site_updates)
|
7664 |
|| $site_updates[0]->response == 'latest'
|
7665 |
) {
|
7667 |
}
|
7668 |
}
|
7669 |
|
7670 |
+
if (isset($scan_results['OUTDATEDSCAN'])
|
|
|
7671 |
|| isset($scan_results['RECOMMENDATIONS'])
|
7672 |
) {
|
7673 |
+
$params['WebsiteDetails.CssClass'] = 'sucuriscan-red-tab';
|
7674 |
}
|
7675 |
|
7676 |
+
$secvars = sucuriscan_sitecheck_general_information($scan_results, $secvars);
|
7677 |
+
$secvars = sucuriscan_sitecheck_application_details($scan_results, $secvars);
|
7678 |
+
$secvars = sucuriscan_sitecheck_system_notices($scan_results, $secvars);
|
7679 |
+
$secvars = sucuriscan_sitecheck_outdated_software($scan_results, $secvars);
|
7680 |
+
$secvars = sucuriscan_sitecheck_recommendations($scan_results, $secvars);
|
7681 |
|
7682 |
+
$params['WebsiteDetails.Content'] = SucuriScanTemplate::getSection('malwarescan-reswebdetails', $secvars);
|
7683 |
|
7684 |
+
return $params;
|
7685 |
}
|
7686 |
|
7687 |
/**
|
7689 |
* the HTML code to display the information in the malware scan page inside the
|
7690 |
* website details tab and specifically in the general information panel.
|
7691 |
*
|
7692 |
+
* @param array $scan_results Array with information of the scanning.
|
7693 |
+
* @param array $params Array with psuedo-variables to build the template.
|
7694 |
+
* @return array Psuedo-variables to build the template including extra info.
|
7695 |
*/
|
7696 |
+
function sucuriscan_sitecheck_general_information($scan_results = false, $secvars = array())
|
7697 |
+
{
|
7698 |
$possible_keys = array(
|
7699 |
'DOMAIN' => 'Domain Scanned',
|
7700 |
'IP' => 'Site IP Address',
|
7704 |
'PHP_VERSION' => 'PHP Version',
|
7705 |
);
|
7706 |
|
7707 |
+
if (isset($scan_results['SCAN'])) {
|
7708 |
+
$scan_results['SCAN']['WP_VERSION'] = array(SucuriScan::site_version());
|
7709 |
+
$scan_results['SCAN']['PHP_VERSION'] = array(phpversion());
|
7710 |
|
7711 |
+
foreach ($possible_keys as $result_key => $result_title) {
|
7712 |
+
if (isset($scan_results['SCAN'][$result_key])) {
|
7713 |
+
if (is_array($scan_results['SCAN'][$result_key])) {
|
7714 |
+
$result_value = implode(', ', $scan_results['SCAN'][$result_key]);
|
7715 |
+
} else {
|
7716 |
+
$result_value = json_encode($scan_results['SCAN'][$result_key]);
|
7717 |
+
}
|
7718 |
|
7719 |
+
$secvars['GenericInformationList'] .= SucuriScanTemplate::getSnippet(
|
7720 |
+
'malwarescan-appdetail',
|
7721 |
+
array(
|
7722 |
+
'InformationTitle' => $result_title,
|
7723 |
+
'InformationValue' => $result_value,
|
7724 |
+
)
|
7725 |
+
);
|
7726 |
}
|
7727 |
}
|
7728 |
}
|
7735 |
* the HTML code to display the information in the malware scan page inside the
|
7736 |
* website details tab and specifically in the application details panel.
|
7737 |
*
|
7738 |
+
* @param array $scan_results Array with information of the scanning.
|
7739 |
+
* @param array $params Array with psuedo-variables to build the template.
|
7740 |
+
* @return array Psuedo-variables to build the template including extra info.
|
7741 |
*/
|
7742 |
+
function sucuriscan_sitecheck_application_details($scan_results = false, $secvars = array())
|
7743 |
+
{
|
7744 |
+
if (isset($scan_results['WEBAPP'])) {
|
7745 |
+
foreach ($scan_results['WEBAPP'] as $webapp_key => $webapp_details) {
|
7746 |
+
if (is_array($webapp_details)) {
|
7747 |
+
foreach ($webapp_details as $i => $details) {
|
7748 |
$secvars['NoAppDetailsVisibility'] = 'hidden';
|
7749 |
|
7750 |
+
if (is_array($details)) {
|
7751 |
$details = isset($details[0]) ? $details[0] : '';
|
7752 |
}
|
7753 |
|
7754 |
+
$details_parts = explode(':', $details, 2);
|
7755 |
+
$result_title = isset($details_parts[0]) ? trim($details_parts[0]) : '';
|
7756 |
+
$result_value = isset($details_parts[1]) ? trim($details_parts[1]) : '';
|
7757 |
|
7758 |
+
$secvars['ApplicationDetailsList'] .= SucuriScanTemplate::getSnippet(
|
7759 |
+
'malwarescan-appdetail',
|
7760 |
+
array(
|
7761 |
+
'InformationTitle' => $result_title,
|
7762 |
+
'InformationValue' => $result_value,
|
7763 |
+
)
|
7764 |
+
);
|
7765 |
}
|
7766 |
}
|
7767 |
}
|
7775 |
* the HTML code to display the information in the malware scan page inside the
|
7776 |
* website details tab and specifically in the system notices panel.
|
7777 |
*
|
7778 |
+
* @param array $scan_results Array with information of the scanning.
|
7779 |
+
* @param array $params Array with psuedo-variables to build the template.
|
7780 |
+
* @return array Psuedo-variables to build the template including extra info.
|
7781 |
*/
|
7782 |
+
function sucuriscan_sitecheck_system_notices($scan_results = false, $secvars = array())
|
7783 |
+
{
|
7784 |
+
if (isset($scan_results['SYSTEM']['NOTICE'])) {
|
7785 |
+
foreach ($scan_results['SYSTEM']['NOTICE'] as $notice) {
|
7786 |
$secvars['NoAppDetailsVisibility'] = 'hidden';
|
7787 |
|
7788 |
+
if (is_array($notice)) {
|
7789 |
+
$notice = implode(', ', $notice);
|
7790 |
}
|
7791 |
|
7792 |
+
$secvars['SystemNoticeList'] .= SucuriScanTemplate::getSnippet(
|
7793 |
+
'malwarescan-sysnotice',
|
7794 |
+
array(
|
7795 |
+
'SystemNotice' => $notice,
|
7796 |
+
)
|
7797 |
+
);
|
7798 |
}
|
7799 |
}
|
7800 |
|
7806 |
* the HTML code to display the information in the malware scan page inside the
|
7807 |
* website details tab and specifically in the outdated software panel.
|
7808 |
*
|
7809 |
+
* @param array $scan_results Array with information of the scanning.
|
7810 |
+
* @param array $params Array with psuedo-variables to build the template.
|
7811 |
+
* @return array Psuedo-variables to build the template including extra info.
|
7812 |
*/
|
7813 |
+
function sucuriscan_sitecheck_outdated_software($scan_results = false, $secvars = array())
|
7814 |
+
{
|
7815 |
+
if (isset($scan_results['OUTDATEDSCAN'])) {
|
7816 |
+
foreach ($scan_results['OUTDATEDSCAN'] as $outdated) {
|
7817 |
+
if (count($outdated) >= 3) {
|
7818 |
$secvars['HasRecommendationsVisibility'] = 'visible';
|
7819 |
+
$secvars['OutdatedSoftwareList'] .= SucuriScanTemplate::getSnippet(
|
7820 |
+
'malwarescan-outdated',
|
7821 |
+
array(
|
7822 |
+
'OutdatedSoftwareTitle' => $outdated[0],
|
7823 |
+
'OutdatedSoftwareUrl' => $outdated[1],
|
7824 |
+
'OutdatedSoftwareValue' => $outdated[2],
|
7825 |
+
)
|
7826 |
+
);
|
7827 |
}
|
7828 |
}
|
7829 |
}
|
7836 |
* the HTML code to display the information in the malware scan page inside the
|
7837 |
* website details tab and specifically in the security recommendations panel.
|
7838 |
*
|
7839 |
+
* @param array $scan_results Array with information of the scanning.
|
7840 |
+
* @param array $params Array with psuedo-variables to build the template.
|
7841 |
+
* @return array Psuedo-variables to build the template including extra info.
|
7842 |
*/
|
7843 |
+
function sucuriscan_sitecheck_recommendations($scan_results = false, $secvars = array())
|
7844 |
+
{
|
7845 |
+
if (isset($scan_results['RECOMMENDATIONS'])) {
|
7846 |
+
foreach ($scan_results['RECOMMENDATIONS'] as $recommendation) {
|
7847 |
+
if (count($recommendation) >= 3) {
|
7848 |
$secvars['HasRecommendationsVisibility'] = 'visible';
|
7849 |
+
$secvars['SecurityRecomendationList'] .= SucuriScanTemplate::getSnippet(
|
7850 |
+
'malwarescan-recommendation',
|
7851 |
+
array(
|
7852 |
+
'RecommendationTitle' => $recommendation[0],
|
7853 |
+
'RecommendationValue' => $recommendation[1],
|
7854 |
+
'RecommendationUrl' => $recommendation[2],
|
7855 |
+
'RecommendationUrlTitle' => $recommendation[2],
|
7856 |
+
)
|
7857 |
+
);
|
7858 |
}
|
7859 |
}
|
7860 |
}
|
7867 |
* the HTML code to display the information in the malware scan page inside the
|
7868 |
* website links tab.
|
7869 |
*
|
7870 |
+
* @param array $scan_results Array with information of the scanning.
|
7871 |
+
* @param array $params Array with psuedo-variables to build the template.
|
7872 |
+
* @return array Psuedo-variables to build the template including extra information.
|
7873 |
*/
|
7874 |
+
function sucuriscan_sitecheck_website_links($scan_results = false, $params = array())
|
7875 |
+
{
|
7876 |
$possible_url_keys = array(
|
7877 |
'IFRAME' => 'List of iframes found',
|
7878 |
'JSEXTERNAL' => 'List of external scripts included',
|
7884 |
'NoLinksVisibility' => 'hidden',
|
7885 |
);
|
7886 |
|
7887 |
+
if (isset($scan_results['LINKS'])) {
|
7888 |
+
foreach ($possible_url_keys as $result_key => $result_title) {
|
7889 |
+
if (isset($scan_results['LINKS'][$result_key])) {
|
7890 |
$result_value = 0;
|
7891 |
$result_items = '';
|
7892 |
|
7893 |
+
foreach ($scan_results['LINKS'][$result_key] as $url_path) {
|
7894 |
$result_value += 1;
|
7895 |
+
$result_items .= SucuriScanTemplate::getSnippet(
|
7896 |
+
'malwarescan-weblinkitems',
|
7897 |
+
array(
|
7898 |
+
'WebsiteLinksItemTitle' => $url_path,
|
7899 |
+
)
|
7900 |
+
);
|
7901 |
}
|
7902 |
|
7903 |
+
$secvars['WebsiteLinksAllList'] .= SucuriScanTemplate::getSnippet(
|
7904 |
+
'malwarescan-weblinktitle',
|
7905 |
+
array(
|
7906 |
+
'WebsiteLinksSectionTitle' => $result_title,
|
7907 |
+
'WebsiteLinksSectionTotal' => $result_value,
|
7908 |
+
'WebsiteLinksSectionItems' => $result_items /* Do not escape. */,
|
7909 |
+
)
|
7910 |
+
);
|
7911 |
}
|
7912 |
}
|
7913 |
} else {
|
7914 |
$secvars['NoLinksVisibility'] = 'visible';
|
7915 |
}
|
7916 |
|
7917 |
+
$params['WebsiteLinks.Content'] = SucuriScanTemplate::getSection('malwarescan-resweblinks', $secvars);
|
7918 |
|
7919 |
+
return $params;
|
7920 |
}
|
7921 |
|
7922 |
/**
|
7924 |
* the HTML code to display the information in the malware scan page inside the
|
7925 |
* blacklist status tab.
|
7926 |
*
|
7927 |
+
* @param array $scan_results Array with information of the scanning.
|
7928 |
+
* @param array $params Array with psuedo-variables to build the template.
|
7929 |
+
* @return array Psuedo-variables to build the template including extra info.
|
7930 |
*/
|
7931 |
+
function sucuriscan_sitecheck_blacklist_status($scan_results = false, $params = array())
|
7932 |
+
{
|
7933 |
$blacklist_types = array(
|
7934 |
'INFO' => 'CLEAN',
|
7935 |
'WARN' => 'WARNING',
|
7939 |
'BlacklistStatusList' => '',
|
7940 |
);
|
7941 |
|
7942 |
+
if (isset($scan_results['BLACKLIST']['WARN'])) {
|
7943 |
+
$params['BlacklistStatusTitle'] = 'Site blacklisted';
|
7944 |
+
$params['BlacklistStatus.CssClass'] = 'sucuriscan-red-tab';
|
7945 |
}
|
7946 |
|
7947 |
+
foreach ($blacklist_types as $type => $group_title) {
|
7948 |
+
if (isset($scan_results['BLACKLIST'][$type])) {
|
7949 |
+
foreach ($scan_results['BLACKLIST'][$type] as $blres) {
|
7950 |
+
$css_blacklist = ($type == 'INFO') ? 'success' : 'danger';
|
7951 |
|
7952 |
+
$secvars['BlacklistStatusList'] .= SucuriScanTemplate::getSnippet(
|
7953 |
+
'malwarescan-resblacklist',
|
7954 |
+
array(
|
7955 |
+
'BlacklistStatusCssClass' => $css_blacklist,
|
7956 |
+
'BlacklistStatusGroupTitle' => $group_title,
|
7957 |
+
'BlacklistStatusReporterName' => $blres[0],
|
7958 |
+
'BlacklistStatusReporterUrl' => $blres[1],
|
7959 |
+
)
|
7960 |
+
);
|
7961 |
}
|
7962 |
}
|
7963 |
}
|
7964 |
|
7965 |
+
$params['BlacklistStatus.Content'] = SucuriScanTemplate::getSection('malwarescan-resblacklist', $secvars);
|
7966 |
|
7967 |
+
return $params;
|
7968 |
}
|
7969 |
|
7970 |
/**
|
7972 |
* the HTML code to display the information in the malware scan page inside the
|
7973 |
* modified files tab.
|
7974 |
*
|
7975 |
+
* @param array $scan_results Array with information of the scanning.
|
7976 |
+
* @param array $params Array with psuedo-variables to build the template.
|
7977 |
+
* @return array Psuedo-variables to build the template including extra info.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
7978 |
*/
|
7979 |
+
function sucuriscan_sitecheck_modified_files($scan_results = false, $params = array())
|
7980 |
+
{
|
7981 |
+
$params['ModifiedFiles.Content'] = sucuriscan_modified_files();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
7982 |
|
7983 |
+
return $params;
|
7984 |
}
|
7985 |
|
7986 |
/**
|
7987 |
+
* Generate the HTML code for the firewall settings panel.
|
7988 |
*
|
7989 |
* @param string $api_key The CloudProxy API key.
|
7990 |
+
* @return string The parsed-content of the firewall settings panel.
|
7991 |
*/
|
7992 |
+
function sucuriscan_firewall_settings($api_key = '')
|
7993 |
+
{
|
7994 |
+
$params = array(
|
7995 |
+
'Firewall.APIKey' => '',
|
7996 |
+
'Firewall.APIKeyVisibility' => 'hidden',
|
7997 |
+
'Firewall.APIKeyFormVisibility' => 'visible',
|
7998 |
+
'Firewall.SettingsVisibility' => 'hidden',
|
7999 |
+
'Firewall.SettingOptions' => '',
|
8000 |
);
|
8001 |
|
8002 |
+
if ($api_key && array_key_exists('string', $api_key)) {
|
8003 |
+
$settings = SucuriScanAPI::getCloudproxySettings($api_key);
|
8004 |
|
8005 |
+
$params['Firewall.APIKeyVisibility'] = 'visible';
|
8006 |
+
$params['Firewall.APIKeyFormVisibility'] = 'hidden';
|
8007 |
+
$params['Firewall.APIKey'] = $api_key['string'];
|
8008 |
|
8009 |
+
if ($settings) {
|
8010 |
$counter = 0;
|
8011 |
+
$params['Firewall.SettingsVisibility'] = 'visible';
|
8012 |
+
$settings = sucuriscan_explain_firewall_settings($settings);
|
|
|
|
|
|
|
|
|
|
|
|
|
8013 |
|
8014 |
+
foreach ($settings as $option_name => $option_value) {
|
8015 |
+
$css_class = ($counter % 2 === 0) ? 'alternate' : '';
|
8016 |
+
$option_title = ucwords(str_replace('_', "\x20", $option_name));
|
8017 |
|
8018 |
// Generate a HTML list when the option's value is an array.
|
8019 |
+
if (is_array($option_value)) {
|
8020 |
+
$css_scrollable = count($option_value) > 10 ? 'sucuriscan-list-as-table-scrollable' : '';
|
8021 |
$html_list = '<ul class="sucuriscan-list-as-table ' . $css_scrollable . '">';
|
8022 |
|
8023 |
+
foreach ($option_value as $single_value) {
|
8024 |
+
$html_list .= '<li>' . SucuriScan::escape($single_value) . '</li>';
|
8025 |
}
|
8026 |
|
8027 |
$html_list .= '</ul>';
|
8028 |
$option_value = $html_list;
|
8029 |
+
} else {
|
8030 |
+
$option_value = SucuriScan::escape($option_value);
|
8031 |
}
|
8032 |
|
8033 |
// Parse the snippet template and replace the pseudo-variables.
|
8034 |
+
$params['Firewall.SettingOptions'] .= SucuriScanTemplate::getSnippet(
|
8035 |
+
'firewall-settings',
|
8036 |
+
array(
|
8037 |
+
'Firewall.OptionCssClass' => $css_class,
|
8038 |
+
'Firewall.OptionName' => $option_title,
|
8039 |
+
'Firewall.OptionValue' => $option_value,
|
8040 |
+
)
|
8041 |
+
);
|
8042 |
+
$counter++;
|
8043 |
}
|
8044 |
}
|
8045 |
}
|
8046 |
|
8047 |
+
return SucuriScanTemplate::getSection('firewall-settings', $params);
|
8048 |
}
|
8049 |
|
8050 |
/**
|
8051 |
+
* Converts the value of some of the firewall settings into a human-readable
|
8052 |
* text, for example changing numbers or variable names into a more explicit
|
8053 |
* text so the administrator can understand the meaning of these settings.
|
8054 |
*
|
8055 |
* @param array $settings A hash with the settings of a CloudProxy account.
|
8056 |
* @return array The explained version of the CloudProxy settings.
|
8057 |
*/
|
8058 |
+
function sucuriscan_explain_firewall_settings($settings = array())
|
8059 |
+
{
|
8060 |
+
$cache_modes = array(
|
8061 |
+
'docache' => 'enabled (recommended)',
|
8062 |
+
'sitecache' => 'site caching (using your site headers)',
|
8063 |
+
'nocache' => 'minimal (only for a few minutes)',
|
8064 |
+
'nocacheatall' => 'caching disabled (use with caution)',
|
8065 |
+
);
|
|
|
|
|
|
|
|
|
|
|
|
|
8066 |
|
8067 |
+
// TODO: Prefer Array over stdClass, modify the API library.
|
8068 |
+
$settings = @json_decode(json_encode($settings), true);
|
8069 |
+
|
8070 |
+
foreach ($settings as $keyname => $value) {
|
8071 |
+
if ($keyname == 'proxy_active') {
|
8072 |
+
$settings[$keyname] = ($value === 1) ? 'active' : 'not active';
|
8073 |
+
} elseif ($keyname == 'cache_mode') {
|
8074 |
+
if (array_key_exists($keyname, $cache_modes)) {
|
8075 |
+
$settings[$keyname] = $cache_modes[$keyname];
|
8076 |
+
} else {
|
8077 |
+
$settings[$keyname] = 'unknown';
|
8078 |
}
|
8079 |
}
|
|
|
|
|
8080 |
}
|
8081 |
|
8082 |
+
return $settings;
|
8083 |
}
|
8084 |
|
8085 |
/**
|
8086 |
+
* Generate the HTML code for the firewall logs panel.
|
8087 |
*
|
8088 |
+
* @param string $api_key The CloudProxy API key.
|
8089 |
+
* @return string The parsed-content of the firewall logs panel.
|
8090 |
*/
|
8091 |
+
function sucuriscan_firewall_auditlogs($api_key = '')
|
8092 |
+
{
|
8093 |
+
$date = date('Y-m-d');
|
8094 |
+
$params = array();
|
8095 |
|
8096 |
+
$params['AuditLogs.DateYears'] = sucuriscan_firewall_dates('years', $date);
|
8097 |
+
$params['AuditLogs.DateMonths'] = sucuriscan_firewall_dates('months', $date);
|
8098 |
+
$params['AuditLogs.DateDays'] = sucuriscan_firewall_dates('days', $date);
|
|
|
|
|
|
|
|
|
8099 |
|
8100 |
+
return SucuriScanTemplate::getSection('firewall-auditlogs', $params);
|
8101 |
}
|
8102 |
|
8103 |
+
function sucuriscan_firewall_auditlogs_ajax()
|
8104 |
+
{
|
8105 |
+
if (SucuriScanRequest::post('form_action') == 'get_audit_logs') {
|
8106 |
+
$response = '';
|
8107 |
+
$api_key = SucuriScanAPI::getCloudproxyKey();
|
8108 |
+
|
8109 |
+
if ($api_key) {
|
8110 |
+
$query = SucuriScanRequest::post(':query');
|
8111 |
+
$month = SucuriScanRequest::post(':month');
|
8112 |
+
$year = SucuriScanRequest::post(':year');
|
8113 |
+
$day = SucuriScanRequest::post(':day');
|
8114 |
+
$limit = 50;
|
8115 |
+
$offset = 1;
|
8116 |
+
|
8117 |
+
if ($year && $month && $day) {
|
8118 |
+
$date = sprintf('%s-%s-%s', $year, $month, $day);
|
8119 |
+
} else {
|
8120 |
+
$date = date('Y-m-d');
|
8121 |
+
}
|
|
|
|
|
8122 |
|
8123 |
+
$auditlogs = SucuriScanAPI::firewallAuditLogs(
|
8124 |
+
$api_key,
|
8125 |
+
$date, /* Retrieve the data from this date. */
|
8126 |
+
$query, /* Filter the data to match this query. */
|
8127 |
+
$limit, /* Retrieve this maximum of data. */
|
8128 |
+
$offset /* Retrieve the data from this point. */
|
8129 |
+
);
|
8130 |
|
8131 |
+
if ($auditlogs && array_key_exists('total_lines', $auditlogs)) {
|
8132 |
+
$response = sucuriscan_firewall_auditlogs_entries($auditlogs['access_logs']);
|
|
|
|
|
8133 |
|
8134 |
+
if (empty($response)) {
|
8135 |
+
$response = '<tr><td>No data available for this filter.</td></tr>';
|
8136 |
+
}
|
8137 |
+
}
|
8138 |
+
} else {
|
8139 |
+
SucuriScanInterface::error('CloudProxy API Key was not found.');
|
8140 |
}
|
8141 |
|
8142 |
+
print($response);
|
8143 |
+
exit(0);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
8144 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
8145 |
}
|
8146 |
|
8147 |
+
function sucuriscan_firewall_auditlogs_entries($entries = array())
|
8148 |
+
{
|
8149 |
+
$output = '';
|
8150 |
+
$attributes = array(
|
8151 |
+
'remote_addr',
|
8152 |
+
'request_date',
|
8153 |
+
'request_time',
|
8154 |
+
'request_timezone',
|
8155 |
+
'request_method',
|
8156 |
+
'resource_path',
|
8157 |
+
'http_protocol',
|
8158 |
+
'http_status',
|
8159 |
+
'http_status_title',
|
8160 |
+
'http_referer',
|
8161 |
+
'http_user_agent',
|
8162 |
+
'sucuri_block_code',
|
8163 |
+
'sucuri_block_reason',
|
8164 |
+
'request_country_name',
|
8165 |
+
'request_country_code',
|
8166 |
+
);
|
8167 |
|
8168 |
+
if (is_array($entries) && !empty($entries)) {
|
8169 |
$counter = 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
8170 |
|
8171 |
+
foreach ($entries as $entry) {
|
8172 |
+
$data_set = array();
|
8173 |
+
$data_set['AccessLog.CssClass'] = ($counter % 2 == 0) ? '' : 'alternate';
|
|
|
8174 |
|
8175 |
+
foreach ($attributes as $attr) {
|
8176 |
+
// Generate variable name for the template pseudo-tags.
|
8177 |
+
$keyname = str_replace('_', "\x20", $attr);
|
8178 |
+
$keyname = ucwords($keyname);
|
8179 |
+
$keyname = str_replace("\x20", '', $keyname);
|
8180 |
+
$keyname = 'AccessLog.' . $keyname;
|
8181 |
|
8182 |
+
// Assign and escape variable value before rendering.
|
8183 |
+
if (array_key_exists($attr, $entry)) {
|
8184 |
+
$data_set[$keyname] = $entry[$attr];
|
8185 |
+
} else {
|
8186 |
+
$data_set[$keyname] = '';
|
|
|
|
|
|
|
8187 |
}
|
8188 |
|
8189 |
+
// Special cases to convert value to readable data.
|
8190 |
+
if ($attr == 'resource_path' && $data_set[$keyname] == '/') {
|
8191 |
+
$data_set[$keyname] = '/ (root of the website)';
|
8192 |
+
} elseif ($attr == 'http_referer' && $data_set[$keyname] == '-') {
|
8193 |
+
$data_set[$keyname] = '- (no referer)';
|
8194 |
+
} elseif ($attr == 'request_country_name' && $data_set[$keyname] == '') {
|
8195 |
+
$data_set[$keyname] = 'Anonymous';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
8196 |
}
|
|
|
|
|
8197 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
8198 |
|
8199 |
+
$output .= SucuriScanTemplate::getSnippet('firewall-auditlogs', $data_set);
|
8200 |
+
$counter++;
|
|
|
|
|
|
|
|
|
|
|
|
|
8201 |
}
|
|
|
|
|
8202 |
}
|
8203 |
|
8204 |
+
return $output;
|
8205 |
}
|
8206 |
|
8207 |
/**
|
8212 |
* @param boolean $in_html Whether the list should be converted to a HTML select options or not.
|
8213 |
* @return array Either an array with the expected values, or a HTML code.
|
8214 |
*/
|
8215 |
+
function sucuriscan_firewall_dates($type = '', $date = '', $in_html = true)
|
8216 |
+
{
|
8217 |
$options = array();
|
8218 |
$selected = '';
|
8219 |
+
$pattern = '/^([0-9]{4})\-([0-9]{2})\-([0-9]{2})$/';
|
8220 |
+
$s_year = '';
|
8221 |
+
$s_month = '';
|
8222 |
+
$s_day = '';
|
8223 |
|
8224 |
+
if (@preg_match($pattern, $date, $date_m)) {
|
8225 |
$s_year = $date_m[1];
|
8226 |
$s_month = $date_m[2];
|
8227 |
$s_day = $date_m[3];
|
|
|
|
|
|
|
|
|
8228 |
}
|
8229 |
|
8230 |
+
switch ($type) {
|
8231 |
case 'years':
|
8232 |
$selected = $s_year;
|
8233 |
+
$current_year = (int) date('Y');
|
8234 |
$max_years = 5; /* Maximum number of years to keep the logs. */
|
8235 |
+
$options = range(($current_year - $max_years), $current_year);
|
8236 |
break;
|
8237 |
case 'months':
|
8238 |
$selected = $s_month;
|
8252 |
);
|
8253 |
break;
|
8254 |
case 'days':
|
8255 |
+
$options = range(1, 31);
|
8256 |
$selected = $s_day;
|
8257 |
break;
|
8258 |
}
|
8259 |
|
8260 |
+
if ($in_html) {
|
8261 |
$html_options = '';
|
8262 |
|
8263 |
+
foreach ($options as $key => $value) {
|
8264 |
+
if (is_numeric($value)) {
|
8265 |
+
$value = str_pad($value, 2, 0, STR_PAD_LEFT);
|
8266 |
}
|
8267 |
|
8268 |
+
if ($type != 'months') {
|
8269 |
$key = $value;
|
8270 |
}
|
8271 |
|
8272 |
$selected_tag = ( $key == $selected ) ? 'selected="selected"' : '';
|
8273 |
+
$html_options .= sprintf('<option value="%s" %s>%s</option>', $key, $selected_tag, $value);
|
8274 |
}
|
8275 |
|
8276 |
return $html_options;
|
8279 |
return $options;
|
8280 |
}
|
8281 |
|
8282 |
+
/**
|
8283 |
+
* Generate the HTML code for the firewall clear cache panel.
|
8284 |
+
*
|
8285 |
+
* @param string $nonce Identifier of the HTTP request for CSRF protection
|
8286 |
+
* @return string The parsed-content of the firewall clear cache panel.
|
8287 |
+
*/
|
8288 |
+
function sucuriscan_firewall_clearcache($nonce)
|
8289 |
+
{
|
8290 |
+
$params = array();
|
8291 |
+
|
8292 |
+
if ($nonce) {
|
8293 |
+
// Flush the cache of the site(s) associated with the API key.
|
8294 |
+
if (SucuriScanRequest::post(':clear_cache') == 1) {
|
8295 |
+
$response = SucuriScanAPI::clearCloudproxyCache();
|
8296 |
+
|
8297 |
+
if ($response) {
|
8298 |
+
if (isset($response->messages[0])) {
|
8299 |
+
// Clear W3 Total Cache if it is installed.
|
8300 |
+
if (function_exists('w3tc_flush_all')) {
|
8301 |
+
w3tc_flush_all();
|
8302 |
+
}
|
8303 |
+
|
8304 |
+
SucuriScanInterface::info($response->messages[0]);
|
8305 |
+
} else {
|
8306 |
+
SucuriScanInterface::error('Could not clear the cache of your site, try later again.');
|
8307 |
+
}
|
8308 |
+
} else {
|
8309 |
+
SucuriScanInterface::error('CloudProxy is not enabled on your site, or your API key is invalid.');
|
8310 |
+
}
|
8311 |
+
}
|
8312 |
+
}
|
8313 |
+
|
8314 |
+
return SucuriScanTemplate::getSection('firewall-clearcache', $params);
|
8315 |
+
}
|
8316 |
+
|
8317 |
+
/**
|
8318 |
+
* CloudProxy firewall page.
|
8319 |
+
*
|
8320 |
+
* It checks whether the WordPress core files are the original ones, and the state
|
8321 |
+
* of the themes and plugins reporting the availability of updates. It also checks
|
8322 |
+
* the user accounts under the administrator group.
|
8323 |
+
*
|
8324 |
+
* @return void
|
8325 |
+
*/
|
8326 |
+
function sucuriscan_firewall_page()
|
8327 |
+
{
|
8328 |
+
SucuriScanInterface::check_permissions();
|
8329 |
+
|
8330 |
+
// Process all form submissions.
|
8331 |
+
$nonce = SucuriScanInterface::check_nonce();
|
8332 |
+
sucuriscan_firewall_form_submissions($nonce);
|
8333 |
+
|
8334 |
+
// Get the dynamic values for the template variables.
|
8335 |
+
$api_key = SucuriScanAPI::getCloudproxyKey();
|
8336 |
+
|
8337 |
+
// Page pseudo-variables initialization.
|
8338 |
+
$params = array(
|
8339 |
+
'PageTitle' => 'Firewall WAF',
|
8340 |
+
'Firewall.Settings' => sucuriscan_firewall_settings($api_key),
|
8341 |
+
'Firewall.AuditLogs' => sucuriscan_firewall_auditlogs($api_key),
|
8342 |
+
'Firewall.ClearCache' => sucuriscan_firewall_clearcache($nonce),
|
8343 |
+
);
|
8344 |
+
|
8345 |
+
echo SucuriScanTemplate::getTemplate('firewall', $params);
|
8346 |
+
}
|
8347 |
+
|
8348 |
+
/**
|
8349 |
+
* Handle an Ajax request for this specific page.
|
8350 |
+
*
|
8351 |
+
* @return mixed.
|
8352 |
+
*/
|
8353 |
+
function sucuriscan_firewall_ajax()
|
8354 |
+
{
|
8355 |
+
SucuriScanInterface::check_permissions();
|
8356 |
+
|
8357 |
+
if (SucuriScanInterface::check_nonce()) {
|
8358 |
+
sucuriscan_firewall_auditlogs_ajax();
|
8359 |
+
}
|
8360 |
+
|
8361 |
+
wp_die();
|
8362 |
+
}
|
8363 |
+
|
8364 |
+
/**
|
8365 |
+
* Process the requests sent by the form submissions originated in the firewall
|
8366 |
+
* page, all forms must have a nonce field that will be checked against the one
|
8367 |
+
* generated in the template render function.
|
8368 |
+
*
|
8369 |
+
* @return void
|
8370 |
+
*/
|
8371 |
+
function sucuriscan_firewall_form_submissions($nonce)
|
8372 |
+
{
|
8373 |
+
if ($nonce) {
|
8374 |
+
// Add and/or Update the Sucuri WAF API Key (do it before anything else).
|
8375 |
+
$option_name = ':cloudproxy_apikey';
|
8376 |
+
$api_key = SucuriScanRequest::post($option_name);
|
8377 |
+
|
8378 |
+
if ($api_key !== false) {
|
8379 |
+
$api_key = trim($api_key);
|
8380 |
+
|
8381 |
+
if (SucuriScanAPI::isValidCloudproxyKey($api_key)) {
|
8382 |
+
SucuriScanOption::update_option($option_name, $api_key);
|
8383 |
+
SucuriScanInterface::info('CloudProxy API key saved successfully');
|
8384 |
+
SucuriScanOption::setRevProxy('enable');
|
8385 |
+
SucuriScanOption::setAddrHeader('HTTP_X_SUCURI_CLIENTIP');
|
8386 |
+
} else {
|
8387 |
+
SucuriScanInterface::error('Invalid CloudProxy API key.');
|
8388 |
+
}
|
8389 |
+
}
|
8390 |
+
|
8391 |
+
// Delete CloudProxy API key from the plugin.
|
8392 |
+
if (SucuriScanRequest::post(':delete_wafkey') !== false) {
|
8393 |
+
SucuriScanOption::delete_option($option_name);
|
8394 |
+
SucuriScanInterface::info('CloudProxy API key removed successfully');
|
8395 |
+
SucuriScanOption::setRevProxy('disable');
|
8396 |
+
SucuriScanOption::setAddrHeader('REMOTE_ADDR');
|
8397 |
+
}
|
8398 |
+
}
|
8399 |
+
}
|
8400 |
+
|
8401 |
/**
|
8402 |
* Project hardening library.
|
8403 |
*
|
8416 |
* Apache/PHP Hardener that can, for example, deactivate unneeded features in
|
8417 |
* configuration files or perform various other protective measures.
|
8418 |
*/
|
8419 |
+
class SucuriScanHardening extends SucuriScan
|
8420 |
+
{
|
8421 |
|
8422 |
/**
|
8423 |
* Returns a list of access control rules for the Apache web server that can be
|
8631 |
*
|
8632 |
* @return void
|
8633 |
*/
|
8634 |
+
function sucuriscan_hardening_page()
|
8635 |
+
{
|
8636 |
SucuriScanInterface::check_permissions();
|
8637 |
|
8638 |
$template_variables = array(
|
8640 |
'Hardening.Whitelist' => sucuriscan_hardening_whitelist(),
|
8641 |
);
|
8642 |
|
8643 |
+
echo SucuriScanTemplate::getTemplate('hardening', $template_variables);
|
8644 |
}
|
8645 |
|
8646 |
+
function sucuriscan_hardening_panel()
|
8647 |
+
{
|
8648 |
if (SucuriScanRequest::post(':run_hardening')
|
8649 |
+
&& !SucuriScanInterface::check_nonce()
|
8650 |
) {
|
8651 |
unset($_POST['sucuriscan_run_hardening']);
|
8652 |
}
|
8679 |
$template_variables['Hardening.WpIncludes'] = sucuriscan_harden_wpincludes();
|
8680 |
}
|
8681 |
|
8682 |
+
return SucuriScanTemplate::getSection('hardening-panel', $template_variables);
|
8683 |
}
|
8684 |
|
8685 |
+
function sucuriscan_hardening_whitelist()
|
8686 |
+
{
|
8687 |
$template_variables = array(
|
8688 |
'HardeningWhitelist.List' => '',
|
8689 |
'HardeningWhitelist.NoItemsVisibility' => 'visible',
|
8732 |
foreach ($files as $file) {
|
8733 |
$css_class = ($counter % 2 === 0) ? '' : 'alternate';
|
8734 |
$fregexp = sprintf('%s/.*/%s', $folder, $file);
|
8735 |
+
$html = SucuriScanTemplate::getSnippet(
|
8736 |
+
'hardening-whitelist',
|
8737 |
+
array(
|
8738 |
+
'HardeningWhitelist.CssClass' => $css_class,
|
8739 |
+
'HardeningWhitelist.Regexp' => $fregexp,
|
8740 |
+
'HardeningWhitelist.Folder' => $folder,
|
8741 |
+
'HardeningWhitelist.File' => $file,
|
8742 |
+
)
|
8743 |
+
);
|
8744 |
$template_variables['HardeningWhitelist.List'] .= $html;
|
8745 |
$counter++;
|
8746 |
}
|
8747 |
}
|
8748 |
}
|
8749 |
|
8750 |
+
return SucuriScanTemplate::getSection('hardening-whitelist', $template_variables);
|
8751 |
}
|
8752 |
|
8753 |
/**
|
8764 |
* @param string $updatemsg Optional explanation of the hardening after the submission of the form.
|
8765 |
* @return void
|
8766 |
*/
|
8767 |
+
function sucuriscan_harden_status($title = '', $status = 0, $type = '', $messageok = '', $messagewarn = '', $desc = null, $updatemsg = null)
|
8768 |
+
{
|
8769 |
$template_variables = array(
|
8770 |
+
'Hardening.Title' => $title,
|
8771 |
'Hardening.Description' => '',
|
8772 |
'Hardening.Status' => 'unknown',
|
8773 |
'Hardening.FieldName' => '',
|
8777 |
'Hardening.UpdateMessage' => '',
|
8778 |
);
|
8779 |
|
8780 |
+
if (is_null($type)) {
|
8781 |
$type = 'unknown';
|
8782 |
$template_variables['Hardening.FieldAttributes'] = 'disabled="disabled"';
|
8783 |
}
|
8784 |
|
8785 |
$template_variables['Hardening.Status'] = (string) $status;
|
8786 |
|
8787 |
+
if ($status === 1) {
|
8788 |
$template_variables['Hardening.FieldName'] = $type . '_unharden';
|
8789 |
$template_variables['Hardening.FieldValue'] = 'Revert hardening';
|
8790 |
$template_variables['Hardening.Information'] = $messageok;
|
8791 |
+
} elseif ($status === 0) {
|
8792 |
$template_variables['Hardening.FieldName'] = $type;
|
8793 |
$template_variables['Hardening.FieldValue'] = 'Harden';
|
8794 |
$template_variables['Hardening.Information'] = $messagewarn;
|
8799 |
$template_variables['Hardening.FieldAttributes'] = 'disabled="disabled"';
|
8800 |
}
|
8801 |
|
8802 |
+
if (!is_null($desc)) {
|
8803 |
$template_variables['Hardening.Description'] = '<p>' . $desc . '</p>';
|
8804 |
}
|
8805 |
|
8806 |
+
if (!is_null($updatemsg)) {
|
8807 |
$template_variables['Hardening.UpdateMessage'] = '<p>' . $updatemsg . '</p>';
|
8808 |
}
|
8809 |
|
8810 |
+
return SucuriScanTemplate::getSnippet('hardening', $template_variables);
|
8811 |
}
|
8812 |
|
8813 |
/**
|
8816 |
*
|
8817 |
* @return void
|
8818 |
*/
|
8819 |
+
function sucuriscan_harden_version()
|
8820 |
+
{
|
8821 |
$site_version = SucuriScan::site_version();
|
8822 |
$updates = get_core_updates();
|
8823 |
+
$cp = (!is_array($updates) || empty($updates) ? 1 : 0);
|
8824 |
|
8825 |
+
if (isset($updates[0]) && $updates[0] instanceof stdClass) {
|
8826 |
+
if ($updates[0]->response == 'latest'
|
|
|
8827 |
|| $updates[0]->response == 'development'
|
8828 |
) {
|
8829 |
$cp = 1;
|
8830 |
}
|
8831 |
}
|
8832 |
|
8833 |
+
if (strcmp($site_version, '3.7') < 0) {
|
8834 |
$cp = 0;
|
8835 |
}
|
8836 |
|
8839 |
to the source code are made public, if there were security fixes then
|
8840 |
someone with malicious intent can use this information to attack any site
|
8841 |
that has not been upgraded.';
|
8842 |
+
$messageok = sprintf('Your WordPress installation (%s) is current.', $site_version);
|
8843 |
$messagewarn = sprintf(
|
8844 |
'Your current version (%s) is not current.<br>
|
8845 |
<a href="update-core.php" class="button-primary">Update now!</a>',
|
8846 |
$site_version
|
8847 |
);
|
8848 |
|
8849 |
+
return sucuriscan_harden_status('Verify WordPress version', $cp, null, $messageok, $messagewarn, $initial_msg);
|
8850 |
}
|
8851 |
|
8852 |
/**
|
8856 |
*
|
8857 |
* @return void
|
8858 |
*/
|
8859 |
+
function sucuriscan_harden_removegenerator()
|
8860 |
+
{
|
8861 |
return sucuriscan_harden_status(
|
8862 |
'Remove WordPress version',
|
8863 |
1,
|
8869 |
);
|
8870 |
}
|
8871 |
|
8872 |
+
function sucuriscan_harden_nginx_phpfpm()
|
8873 |
+
{
|
8874 |
$description = 'It seems that you are using the Nginx web server, if that is
|
8875 |
the case then you will need to add the following code into the global
|
8876 |
<code>nginx.conf</code> file or the virtualhost associated with this
|
8877 |
website. Choose the correct rules for the directories that you want to
|
8878 |
protect. If you encounter errors after restart the web server then revert
|
8879 |
the changes and contact the support team of your hosting company, or read
|
8880 |
+
the official article about <a href="https://codex.wordpress.org/Nginx">
|
8881 |
WordPress on Nginx</a>.</p>';
|
8882 |
|
8883 |
$description .= "<pre class='code'># Block PHP files in uploads directory.\nlocation ~* /(?:uploads|files)/.*\.php$ {\n\x20\x20deny all;\n}</pre>";
|
8911 |
*
|
8912 |
* @return void
|
8913 |
*/
|
8914 |
+
function sucuriscan_harden_upload()
|
8915 |
+
{
|
8916 |
$dpath = WP_CONTENT_DIR . '/uploads';
|
8917 |
|
8918 |
+
if (SucuriScanRequest::post(':run_hardening')) {
|
8919 |
+
if (SucuriScanRequest::post(':harden_upload')) {
|
8920 |
+
$result = SucuriScanHardening::harden_directory($dpath);
|
8921 |
|
8922 |
+
if ($result === true) {
|
8923 |
$message = 'Hardening applied to the uploads directory';
|
8924 |
+
SucuriScanEvent::report_notice_event($message);
|
8925 |
+
SucuriScanInterface::info($message);
|
8926 |
} else {
|
8927 |
+
SucuriScanInterface::error('Error hardening directory, check the permissions.');
|
8928 |
}
|
8929 |
+
} elseif (SucuriScanRequest::post(':harden_upload_unharden')) {
|
8930 |
+
$result = SucuriScanHardening::unharden_directory($dpath);
|
8931 |
|
8932 |
+
if ($result === true) {
|
8933 |
$message = 'Hardening reverted in the uploads directory';
|
8934 |
+
SucuriScanEvent::report_error_event($message);
|
8935 |
+
SucuriScanInterface::info($message);
|
8936 |
} else {
|
8937 |
+
SucuriScanInterface::info('Access file is not writable, check the permissions.');
|
8938 |
}
|
8939 |
}
|
8940 |
}
|
8941 |
|
8942 |
// Check whether the directory is already hardened or not.
|
8943 |
+
$is_hardened = SucuriScanHardening::is_hardened($dpath);
|
8944 |
$cp = ( $is_hardened === true ) ? 1 : 0;
|
8945 |
|
8946 |
$description = 'It checks if the uploads directory of this site allows the direct execution'
|
8972 |
*
|
8973 |
* @return void
|
8974 |
*/
|
8975 |
+
function sucuriscan_harden_wpcontent()
|
8976 |
+
{
|
8977 |
+
if (SucuriScanRequest::post(':run_hardening')) {
|
8978 |
+
if (SucuriScanRequest::post(':harden_wpcontent')) {
|
8979 |
+
$result = SucuriScanHardening::harden_directory(WP_CONTENT_DIR);
|
8980 |
|
8981 |
+
if ($result === true) {
|
8982 |
$message = 'Hardening applied to the content directory';
|
8983 |
+
SucuriScanEvent::report_notice_event($message);
|
8984 |
+
SucuriScanInterface::info($message);
|
8985 |
} else {
|
8986 |
+
SucuriScanInterface::error('Error hardening directory, check the permissions.');
|
8987 |
}
|
8988 |
+
} elseif (SucuriScanRequest::post(':harden_wpcontent_unharden')) {
|
8989 |
+
$result = SucuriScanHardening::unharden_directory(WP_CONTENT_DIR);
|
8990 |
|
8991 |
+
if ($result === true) {
|
8992 |
$message = 'Hardening reverted in the content directory';
|
8993 |
+
SucuriScanEvent::report_error_event($message);
|
8994 |
+
SucuriScanInterface::info($message);
|
8995 |
} else {
|
8996 |
+
SucuriScanInterface::info('Access file is not writable, check the permissions.');
|
8997 |
}
|
8998 |
}
|
8999 |
}
|
9000 |
|
9001 |
// Check whether the directory is already hardened or not.
|
9002 |
+
$is_hardened = SucuriScanHardening::is_hardened(WP_CONTENT_DIR);
|
9003 |
$cp = ( $is_hardened === true ) ? 1 : 0;
|
9004 |
|
9005 |
$description = 'This option blocks direct access to any PHP file located under the content'
|
9030 |
*
|
9031 |
* @return void
|
9032 |
*/
|
9033 |
+
function sucuriscan_harden_wpincludes()
|
9034 |
+
{
|
9035 |
$dpath = ABSPATH . '/wp-includes';
|
9036 |
|
9037 |
+
if (SucuriScanRequest::post(':run_hardening')) {
|
9038 |
+
if (SucuriScanRequest::post(':harden_wpincludes')) {
|
9039 |
+
$result = SucuriScanHardening::harden_directory($dpath);
|
9040 |
|
9041 |
+
if ($result === true) {
|
9042 |
$message = 'Hardening applied to the library directory';
|
9043 |
SucuriScanHardening::whitelist('wp-tinymce.php', 'wp-includes');
|
9044 |
SucuriScanHardening::whitelist('ms-files.php', 'wp-includes');
|
9045 |
+
SucuriScanEvent::report_notice_event($message);
|
9046 |
+
SucuriScanInterface::info($message);
|
9047 |
} else {
|
9048 |
+
SucuriScanInterface::error('Error hardening directory, check the permissions.');
|
9049 |
}
|
9050 |
+
} elseif (SucuriScanRequest::post(':harden_wpincludes_unharden')) {
|
9051 |
+
$result = SucuriScanHardening::unharden_directory($dpath);
|
9052 |
|
9053 |
+
if ($result === true) {
|
9054 |
$message = 'Hardening reverted in the library directory';
|
9055 |
SucuriScanHardening::dewhitelist('wp-tinymce.php', 'wp-includes');
|
9056 |
SucuriScanHardening::dewhitelist('ms-files.php', 'wp-includes');
|
9057 |
+
SucuriScanEvent::report_error_event($message);
|
9058 |
+
SucuriScanInterface::info($message);
|
9059 |
} else {
|
9060 |
+
SucuriScanInterface::info('Access file is not writable, check the permissions.');
|
9061 |
}
|
9062 |
}
|
9063 |
}
|
9064 |
|
9065 |
// Check whether the directory is already hardened or not.
|
9066 |
+
$is_hardened = SucuriScanHardening::is_hardened($dpath);
|
9067 |
$cp = ( $is_hardened === true ) ? 1 : 0;
|
9068 |
|
9069 |
return sucuriscan_harden_status(
|
9083 |
*
|
9084 |
* @return void
|
9085 |
*/
|
9086 |
+
function sucuriscan_harden_phpversion()
|
9087 |
+
{
|
9088 |
$phpv = phpversion();
|
9089 |
+
$cp = ( strncmp($phpv, '5.', 2) < 0 ) ? 0 : 1;
|
9090 |
|
9091 |
return sucuriscan_harden_status(
|
9092 |
'Verify PHP version',
|
9104 |
*
|
9105 |
* @return void
|
9106 |
*/
|
9107 |
+
function sucuriscan_cloudproxy_enabled()
|
9108 |
+
{
|
9109 |
$btn_string = '';
|
9110 |
$proxy_info = SucuriScan::is_behind_cloudproxy();
|
9111 |
$status = 1;
|
9112 |
|
9113 |
$description = 'A WAF is a protection layer for your web site, blocking all sort of attacks (brute force attempts, '
|
9114 |
. 'DDoS, SQL injections, etc) and helping it remain malware and blacklist free. This test checks if your site is '
|
9115 |
+
. 'using <a href="https://cloudproxy.sucuri.net/" target="_blank">Sucuri\'s CloudProxy WAF</a> to protect your site.';
|
9116 |
|
9117 |
+
if ($proxy_info === false) {
|
9118 |
$status = 0;
|
9119 |
+
$btn_string = '<a href="https://goo.gl/qfNkMq" target="_blank" class="button button-primary">Harden</a>';
|
9120 |
}
|
9121 |
|
9122 |
return sucuriscan_harden_status(
|
9140 |
*
|
9141 |
* @return void
|
9142 |
*/
|
9143 |
+
function sucuriscan_harden_secretkeys()
|
9144 |
+
{
|
9145 |
$wp_config_path = SucuriScan::get_wpconfig_path();
|
9146 |
$current_keys = SucuriScanOption::get_security_keys();
|
9147 |
|
9148 |
+
if ($wp_config_path) {
|
9149 |
$cp = 1;
|
9150 |
+
$wp_config_path = SucuriScan::escape($wp_config_path);
|
9151 |
+
$message = 'The main configuration file was found at: <code>' . $wp_config_path . '</code><br>';
|
9152 |
|
9153 |
+
if (!empty($current_keys['bad']) || !empty($current_keys['missing'])) {
|
|
|
|
|
|
|
9154 |
$cp = 0;
|
9155 |
}
|
9156 |
} else {
|
9159 |
}
|
9160 |
|
9161 |
$message .= '<br>It checks whether you have proper random keys/salts created for WordPress. A
|
9162 |
+
<a href="https://codex.wordpress.org/Editing_wp-config.php#Security_Keys" target="_blank">
|
9163 |
secret key</a> makes your site harder to hack and access harder to crack by adding
|
9164 |
random elements to the password. In simple terms, a secret key is a password with
|
9165 |
elements that make it harder to generate enough options to break through your
|
9166 |
security barriers.';
|
9167 |
$messageok = 'Security keys and salts not set, we recommend to create them for security reasons'
|
9168 |
+
. '<a href="' . SucuriScanTemplate::getUrl('posthack') . '" class="button button-primary">'
|
9169 |
. 'Harden</a>';
|
9170 |
|
9171 |
return sucuriscan_harden_status(
|
9186 |
*
|
9187 |
* @return void
|
9188 |
*/
|
9189 |
+
function sucuriscan_harden_readme()
|
9190 |
+
{
|
9191 |
$upmsg = null;
|
9192 |
+
$cp = is_readable(ABSPATH.'/readme.html') ? 0 : 1;
|
9193 |
|
9194 |
// TODO: After hardening create an option to automatically remove this after WP upgrade.
|
9195 |
+
if (SucuriScanRequest::post(':run_hardening')) {
|
9196 |
+
if (SucuriScanRequest::post(':harden_readme') && $cp == 0) {
|
9197 |
+
if (@unlink(ABSPATH.'/readme.html') === false) {
|
9198 |
+
$upmsg = SucuriScanInterface::error('Unable to remove <code>readme.html</code> file.');
|
9199 |
} else {
|
9200 |
$cp = 1;
|
9201 |
$message = 'Hardening applied to the <code>readme.html</code> file';
|
9202 |
+
SucuriScanEvent::report_notice_event($message);
|
9203 |
+
SucuriScanInterface::info($message);
|
9204 |
}
|
9205 |
+
} elseif (SucuriScanRequest::post(':harden_readme_unharden')) {
|
9206 |
+
SucuriScanInterface::error('We can not revert this action, you must create the <code>readme.html</code> manually.');
|
9207 |
}
|
9208 |
}
|
9209 |
|
9224 |
*
|
9225 |
* @return void
|
9226 |
*/
|
9227 |
+
function sucuriscan_harden_adminuser()
|
9228 |
+
{
|
9229 |
global $wpdb;
|
9230 |
|
9231 |
$upmsg = null;
|
9235 |
'search_columns' => array( 'user_login' ),
|
9236 |
));
|
9237 |
$results = $user_query->get_results();
|
9238 |
+
$account_removed = ( count($results) === 0 ? 1 : 0 );
|
9239 |
|
9240 |
+
if ($account_removed === 0) {
|
9241 |
$upmsg = '<i><strong>Notice.</strong> We do not offer an option to automatically change the user name.
|
9242 |
+
Go to the <a href="'.SucuriScan::admin_url('users.php').'" target="_blank">user list</a> and create
|
9243 |
+
a new administrator user. Once created, log in as that user and remove the default <code>admin</code>
|
9244 |
(make sure to assign all the admin posts to the new user too).</i>';
|
9245 |
}
|
9246 |
|
9260 |
*
|
9261 |
* @return void
|
9262 |
*/
|
9263 |
+
function sucuriscan_harden_fileeditor()
|
9264 |
+
{
|
9265 |
+
$file_editor_disabled = defined('DISALLOW_FILE_EDIT') ? DISALLOW_FILE_EDIT : false;
|
9266 |
|
9267 |
+
if (SucuriScanRequest::post(':run_hardening')) {
|
9268 |
+
$current_time = date('r');
|
9269 |
$wp_config_path = SucuriScan::get_wpconfig_path();
|
9270 |
|
9271 |
+
$wp_config_writable = ( file_exists($wp_config_path) && is_writable($wp_config_path) ) ? true : false;
|
9272 |
+
$new_wpconfig = $wp_config_writable ? @file_get_contents($wp_config_path) : '';
|
9273 |
|
9274 |
+
if (SucuriScanRequest::post(':harden_fileeditor')) {
|
9275 |
+
if ($wp_config_writable) {
|
9276 |
+
if (preg_match('/(.*define\(.DB_COLLATE..*)/', $new_wpconfig, $match)) {
|
9277 |
$disallow_fileedit_definition = "\n\ndefine('DISALLOW_FILE_EDIT', TRUE); // Sucuri Security: {$current_time}\n";
|
9278 |
+
$new_wpconfig = str_replace($match[0], $match[0].$disallow_fileedit_definition, $new_wpconfig);
|
9279 |
}
|
9280 |
|
9281 |
$file_editor_disabled = true;
|
9282 |
+
@file_put_contents($wp_config_path, $new_wpconfig, LOCK_EX);
|
9283 |
$message = 'Hardening applied to the plugin and theme editor';
|
9284 |
+
SucuriScanEvent::report_notice_event($message);
|
9285 |
+
SucuriScanInterface::info($message);
|
9286 |
} else {
|
9287 |
+
SucuriScanInterface::error('The <code>wp-config.php</code> file is not in the default location
|
9288 |
or is not writable, you will need to put the following code manually there:
|
9289 |
+
<code>define("DISALLOW_FILE_EDIT", TRUE);</code>');
|
9290 |
}
|
9291 |
+
} elseif (SucuriScanRequest::post(':harden_fileeditor_unharden')) {
|
9292 |
+
if (preg_match("/(.*define\('DISALLOW_FILE_EDIT', TRUE\);.*)/", $new_wpconfig, $match)) {
|
9293 |
+
if ($wp_config_writable) {
|
9294 |
+
$new_wpconfig = str_replace("\n{$match[1]}", '', $new_wpconfig);
|
9295 |
+
file_put_contents($wp_config_path, $new_wpconfig, LOCK_EX);
|
9296 |
$file_editor_disabled = false;
|
9297 |
$message = 'Hardening reverted in the plugin and theme editor';
|
9298 |
+
SucuriScanEvent::report_error_event($message);
|
9299 |
+
SucuriScanInterface::info($message);
|
9300 |
} else {
|
9301 |
+
SucuriScanInterface::error('The <code>wp-config.php</code> file is not in the default location
|
9302 |
or is not writable, you will need to remove the following code manually from there:
|
9303 |
+
<code>define("DISALLOW_FILE_EDIT", TRUE);</code>');
|
9304 |
}
|
9305 |
} else {
|
9306 |
+
SucuriScanInterface::error('The theme and plugin editor are not disabled from the configuration file.');
|
9307 |
}
|
9308 |
}
|
9309 |
}
|
9331 |
*
|
9332 |
* @return void
|
9333 |
*/
|
9334 |
+
function sucuriscan_harden_dbtables()
|
9335 |
+
{
|
9336 |
global $table_prefix;
|
9337 |
|
9338 |
$hardened = ( $table_prefix == 'wp_' ? 0 : 1 );
|
9353 |
*
|
9354 |
* @return void
|
9355 |
*/
|
9356 |
+
function sucuriscan_harden_errorlog()
|
9357 |
+
{
|
9358 |
$hardened = 1;
|
9359 |
+
$log_filename = SucuriScan::ini_get('error_log');
|
9360 |
+
$scan_errorlogs = SucuriScanOption::get_option(':scan_errorlogs');
|
9361 |
|
9362 |
$description = 'PHP uses files named as <code>' . $log_filename . '</code> to log errors found in '
|
9363 |
. 'the code, these files may leak sensitive information of your project allowing an attacker '
|
9365 |
. 'a development environment, and remove them in production mode.';
|
9366 |
|
9367 |
// Search error log files in the project.
|
9368 |
+
if ($scan_errorlogs != 'disabled') {
|
9369 |
$file_info = new SucuriScanFileInfo();
|
9370 |
$file_info->ignore_files = false;
|
9371 |
$file_info->ignore_directories = false;
|
9372 |
+
$error_logs = $file_info->find_file($log_filename);
|
9373 |
+
$total_log_files = count($error_logs);
|
9374 |
} else {
|
9375 |
$hardened = 2;
|
9376 |
$error_logs = array();
|
9382 |
}
|
9383 |
|
9384 |
// Remove every error log file found in the filesystem scan.
|
9385 |
+
if (SucuriScanRequest::post(':run_hardening')) {
|
9386 |
+
if (SucuriScanRequest::post(':harden_errorlog')) {
|
9387 |
$removed_logs = 0;
|
9388 |
+
SucuriScanEvent::report_notice_event(sprintf(
|
9389 |
'Error log files deleted: (multiple entries): %s',
|
9390 |
+
@implode(',', $error_logs)
|
9391 |
+
));
|
9392 |
|
9393 |
+
foreach ($error_logs as $i => $error_log_path) {
|
9394 |
+
if (unlink($error_log_path)) {
|
9395 |
unset($error_logs[ $i ]);
|
9396 |
$removed_logs += 1;
|
9397 |
}
|
9398 |
}
|
9399 |
|
9400 |
+
SucuriScanInterface::info('Error log files deleted <code>' . $removed_logs . ' out of ' . $total_log_files . '</code>');
|
9401 |
}
|
9402 |
}
|
9403 |
|
9404 |
// List the error log files in a HTML table.
|
9405 |
+
if (!empty($error_logs)) {
|
9406 |
$hardened = 0;
|
9407 |
$description .= '</p><ul class="sucuriscan-list-as-table">';
|
9408 |
|
9409 |
+
foreach ($error_logs as $error_log_path) {
|
9410 |
+
$error_log_path = str_replace(ABSPATH, '/', $error_log_path);
|
9411 |
+
$description .= '<li>' . SucuriScan::escape($error_log_path) . '</li>';
|
9412 |
}
|
9413 |
|
9414 |
$description .= '</ul><p>';
|
9441 |
// Process all form submissions.
|
9442 |
sucuriscan_integrity_form_submissions();
|
9443 |
|
9444 |
+
$params = array(
|
9445 |
'WordpressVersion' => sucuriscan_wordpress_outdated(),
|
9446 |
'CoreFiles' => sucuriscan_core_files(),
|
9447 |
'AuditReports' => sucuriscan_auditreport(),
|
9448 |
'AuditLogs' => sucuriscan_auditlogs(),
|
9449 |
);
|
9450 |
|
9451 |
+
echo SucuriScanTemplate::getTemplate('integrity', $params);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
9452 |
}
|
9453 |
|
9454 |
/**
|
9455 |
+
* Handle an Ajax request for this specific page.
|
|
|
9456 |
*
|
9457 |
+
* @return mixed.
|
|
|
|
|
9458 |
*/
|
9459 |
+
function sucuriscan_ajax()
|
9460 |
{
|
9461 |
+
SucuriScanInterface::check_permissions();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
9462 |
|
9463 |
+
if (SucuriScanInterface::check_nonce()) {
|
9464 |
+
sucuriscan_core_files_ajax();
|
9465 |
}
|
9466 |
|
9467 |
+
wp_die();
|
9468 |
}
|
9469 |
|
9470 |
/**
|
9477 |
{
|
9478 |
// Initialize the values for the pagination.
|
9479 |
$max_per_page = SUCURISCAN_AUDITLOGS_PER_PAGE;
|
9480 |
+
$page_number = SucuriScanTemplate::pageNumber();
|
9481 |
$logs_limit = $page_number * $max_per_page;
|
9482 |
+
$audit_logs = SucuriScanAPI::getLogs($logs_limit);
|
9483 |
|
9484 |
+
$params = array(
|
9485 |
'PageTitle' => 'Audit Logs',
|
9486 |
'AuditLogs.List' => '',
|
9487 |
'AuditLogs.Count' => 0,
|
9501 |
if ($audit_logs->total_entries >= $max_per_page
|
9502 |
&& SucuriScanOption::is_disabled(':audit_report')
|
9503 |
) {
|
9504 |
+
$params['AuditLogs.EnableAuditReportVisibility'] = 'visible';
|
9505 |
}
|
9506 |
|
9507 |
for ($i = $iterator_start; $i < $total_items; $i++) {
|
9515 |
$css_class = ( $counter_i % 2 == 0 ) ? '' : 'alternate';
|
9516 |
$snippet_data = array(
|
9517 |
'AuditLog.CssClass' => $css_class,
|
9518 |
+
'AuditLog.Event' => $audit_log['event'],
|
9519 |
+
'AuditLog.EventTitle' => ucfirst($audit_log['event']),
|
9520 |
+
'AuditLog.Timestamp' => $audit_log['timestamp'],
|
9521 |
'AuditLog.DateTime' => SucuriScan::datetime($audit_log['timestamp']),
|
9522 |
+
'AuditLog.Account' => $audit_log['account'],
|
9523 |
+
'AuditLog.Username' => $audit_log['username'],
|
9524 |
+
'AuditLog.RemoteAddress' => $audit_log['remote_addr'],
|
9525 |
+
'AuditLog.Message' => $audit_log['message'],
|
9526 |
'AuditLog.Extra' => '',
|
9527 |
);
|
9528 |
|
9536 |
$snippet_data['AuditLog.Extra'] .= '</ul>';
|
9537 |
}
|
9538 |
|
9539 |
+
$params['AuditLogs.List'] .= SucuriScanTemplate::getSnippet('integrity-auditlogs', $snippet_data);
|
9540 |
$counter_i += 1;
|
9541 |
}
|
9542 |
}
|
9543 |
|
9544 |
+
$params['AuditLogs.Count'] = $counter_i;
|
9545 |
+
$params['AuditLogs.NoItemsVisibility'] = 'hidden';
|
9546 |
|
9547 |
if ($total_items > 1) {
|
9548 |
$max_pages = ceil($audit_logs->total_entries / $max_per_page);
|
9552 |
}
|
9553 |
|
9554 |
if ($max_pages > 1) {
|
9555 |
+
$params['AuditLogs.PaginationVisibility'] = 'visible';
|
9556 |
+
$params['AuditLogs.PaginationLinks'] = SucuriScanTemplate::pagination(
|
9557 |
'%%SUCURI.URL.Home%%',
|
9558 |
$max_per_page * $max_pages,
|
9559 |
$max_per_page
|
9562 |
}
|
9563 |
}
|
9564 |
|
9565 |
+
return SucuriScanTemplate::getSection('integrity-auditlogs', $params);
|
9566 |
}
|
9567 |
+
|
9568 |
/**
|
9569 |
* Print a HTML code with the content of the logs audited by the remote Sucuri
|
9570 |
* API service, this page is part of the monitoring tool.
|
9577 |
$logs4report = SucuriScanOption::get_option(':logs4report');
|
9578 |
|
9579 |
if (SucuriScanOption::is_enabled(':audit_report')) {
|
9580 |
+
$audit_report = SucuriScanAPI::getAuditReport($logs4report);
|
9581 |
}
|
9582 |
|
9583 |
+
$params = array(
|
9584 |
'PageTitle' => 'Audit Reports',
|
9585 |
'AuditReport.EventColors' => '',
|
9586 |
'AuditReport.EventsPerType' => '',
|
9593 |
);
|
9594 |
|
9595 |
if ($audit_report) {
|
9596 |
+
$params['AuditReport.EventColors'] = @implode(',', $audit_report['event_colors']);
|
9597 |
|
9598 |
// Generate report chart data for the events per type.
|
9599 |
foreach ($audit_report['events_per_type'] as $event => $times) {
|
9600 |
+
$params['AuditReport.EventsPerType'] .= sprintf(
|
9601 |
"[ '%s', %d ],\n",
|
9602 |
ucwords($event . "\x20events"),
|
9603 |
$times
|
9606 |
|
9607 |
// Generate report chart data for the events per login.
|
9608 |
foreach ($audit_report['events_per_login'] as $event => $times) {
|
9609 |
+
$params['AuditReport.EventsPerLogin'] .= sprintf(
|
9610 |
"[ '%s', %d ],\n",
|
9611 |
ucwords($event . "\x20logins"),
|
9612 |
$times
|
9615 |
|
9616 |
// Generate report chart data for the events per user.
|
9617 |
foreach ($audit_report['events_per_user'] as $event => $times) {
|
9618 |
+
$params['AuditReport.EventsPerUserCategories'] .= sprintf('"%s",', $event);
|
9619 |
+
$params['AuditReport.EventsPerUserSeries'] .= sprintf('%d,', $times);
|
9620 |
}
|
9621 |
|
9622 |
// Generate report chart data for the events per remote address.
|
9623 |
foreach ($audit_report['events_per_ipaddress'] as $event => $times) {
|
9624 |
+
$params['AuditReport.EventsPerIPAddressCategories'] .= sprintf('"%s",', $event);
|
9625 |
+
$params['AuditReport.EventsPerIPAddressSeries'] .= sprintf('%d,', $times);
|
9626 |
}
|
9627 |
|
9628 |
+
return SucuriScanTemplate::getSection('integrity-auditreport', $params);
|
9629 |
}
|
9630 |
|
9631 |
return '';
|
9640 |
{
|
9641 |
$site_version = SucuriScan::site_version();
|
9642 |
$updates = get_core_updates();
|
9643 |
+
$cp = (!is_array($updates) || empty($updates) ? 1 : 0);
|
9644 |
|
9645 |
+
$params = array(
|
9646 |
'WordPress.Version' => $site_version,
|
9647 |
'WordPress.NewVersion' => '0.0.0',
|
9648 |
'WordPress.NewLocale' => 'default',
|
9649 |
+
'WordPress.UpdateURL' => SucuriScan::admin_url('update-core.php'),
|
9650 |
'WordPress.DownloadURL' => '#',
|
9651 |
'WordPress.UpdateVisibility' => 'hidden',
|
9652 |
);
|
9656 |
&& property_exists($updates[0], 'version')
|
9657 |
&& property_exists($updates[0], 'download')
|
9658 |
) {
|
9659 |
+
$params['WordPress.NewVersion'] = $updates[0]->version;
|
9660 |
+
$params['WordPress.DownloadURL'] = $updates[0]->download;
|
9661 |
|
9662 |
if (property_exists($updates[0], 'locale')) {
|
9663 |
+
$params['WordPress.NewLocale'] = $updates[0]->locale;
|
9664 |
}
|
9665 |
|
9666 |
if ($updates[0]->response == 'latest'
|
9672 |
}
|
9673 |
|
9674 |
if ($cp == 0) {
|
9675 |
+
$params['WordPress.UpdateVisibility'] = 'visible';
|
9676 |
}
|
9677 |
|
9678 |
+
return SucuriScanTemplate::getSection('integrity-wpoutdate', $params);
|
9679 |
}
|
9680 |
|
9681 |
/**
|
9685 |
* send a notification to the administrator with a list of files that were added,
|
9686 |
* modified and/or deleted so far.
|
9687 |
*
|
9688 |
+
* @return string HTML code with a list of files that were affected.
|
|
|
9689 |
*/
|
9690 |
+
function sucuriscan_core_files()
|
9691 |
+
{
|
9692 |
+
$params = array();
|
9693 |
+
|
9694 |
+
return SucuriScanTemplate::getSection('corefiles-page', $params);
|
9695 |
+
}
|
9696 |
+
|
9697 |
+
function sucuriscan_core_files_ajax()
|
9698 |
+
{
|
9699 |
+
if (SucuriScanRequest::post('form_action') == 'get_core_files') {
|
9700 |
+
$response = sucuriscan_core_files_data();
|
9701 |
+
|
9702 |
+
print($response);
|
9703 |
+
exit(0);
|
9704 |
+
}
|
9705 |
+
}
|
9706 |
+
|
9707 |
+
function sucuriscan_core_files_data($send_email = false)
|
9708 |
{
|
|
|
9709 |
$affected_files = 0;
|
9710 |
+
$site_version = SucuriScan::site_version();
|
9711 |
|
9712 |
+
$params = array(
|
9713 |
'CoreFiles.List' => '',
|
9714 |
'CoreFiles.ListCount' => 0,
|
9715 |
+
'CoreFiles.RemoteChecksumsURL' => '',
|
9716 |
'CoreFiles.BadVisibility' => 'hidden',
|
9717 |
+
'CoreFiles.GoodVisibility' => 'visible',
|
9718 |
'CoreFiles.FailureVisibility' => 'hidden',
|
9719 |
+
'CoreFiles.NotFixableVisibility' => 'hidden',
|
9720 |
);
|
9721 |
|
9722 |
if ($site_version && SucuriScanOption::is_enabled(':scan_checksums')) {
|
9723 |
// Check if there are added, removed, or modified files.
|
9724 |
$latest_hashes = sucuriscan_check_core_integrity($site_version);
|
9725 |
+
$params['CoreFiles.RemoteChecksumsURL'] =
|
9726 |
+
'https://api.wordpress.org/core/checksums/1.0/'
|
9727 |
. '?version=' . $site_version . '&locale=en_US';
|
9728 |
|
9729 |
if ($latest_hashes) {
|
9730 |
$cache = new SucuriScanCache('integrity');
|
9731 |
+
$ignored_files = $cache->getAll();
|
9732 |
$counter = 0;
|
9733 |
|
9734 |
foreach ($latest_hashes as $list_type => $file_list) {
|
9735 |
+
if ($list_type == 'stable' || empty($file_list)) {
|
|
|
|
|
9736 |
continue;
|
9737 |
}
|
9738 |
|
9753 |
// Add extra information to the file list.
|
9754 |
$css_class = ( $counter % 2 == 0 ) ? '' : 'alternate';
|
9755 |
$file_size = @filesize($full_filepath);
|
|
|
9756 |
$is_fixable_text = '';
|
9757 |
|
9758 |
// Check whether the file can be fixed automatically or not.
|
9759 |
if ($file_info['is_fixable'] !== true) {
|
9760 |
$css_class .= ' sucuriscan-opacity';
|
9761 |
+
$is_fixable_text = '(not fixable)';
|
9762 |
+
$params['CoreFiles.NotFixableVisibility'] = 'visible';
|
9763 |
}
|
9764 |
|
9765 |
// Generate the HTML code from the snippet template for this file.
|
9766 |
+
$params['CoreFiles.List'] .= SucuriScanTemplate::getSnippet(
|
9767 |
+
'corefiles',
|
9768 |
+
array(
|
9769 |
+
'CoreFiles.CssClass' => $css_class,
|
9770 |
+
'CoreFiles.StatusType' => $list_type,
|
9771 |
+
'CoreFiles.FilePath' => $file_path,
|
9772 |
+
'CoreFiles.FileSize' => $file_size,
|
9773 |
+
'CoreFiles.FileSizeHuman' => SucuriScan::human_filesize($file_size),
|
9774 |
+
'CoreFiles.FileSizeNumber' => number_format($file_size),
|
9775 |
+
'CoreFiles.ModifiedAt' => SucuriScan::datetime($file_info['modified_at']),
|
9776 |
+
'CoreFiles.IsNotFixable' => $is_fixable_text,
|
9777 |
+
)
|
9778 |
+
);
|
9779 |
$counter += 1;
|
9780 |
$affected_files += 1;
|
9781 |
}
|
9782 |
}
|
9783 |
|
9784 |
if ($counter > 0) {
|
9785 |
+
$params['CoreFiles.ListCount'] = $counter;
|
9786 |
+
$params['CoreFiles.GoodVisibility'] = 'hidden';
|
9787 |
+
$params['CoreFiles.BadVisibility'] = 'visible';
|
9788 |
}
|
9789 |
} else {
|
9790 |
+
$params['CoreFiles.GoodVisibility'] = 'hidden';
|
9791 |
+
$params['CoreFiles.BadVisibility'] = 'hidden';
|
9792 |
+
$params['CoreFiles.FailureVisibility'] = 'visible';
|
9793 |
}
|
9794 |
}
|
9795 |
|
9796 |
// Send an email notification with the affected files.
|
9797 |
if ($send_email === true) {
|
9798 |
if ($affected_files > 0) {
|
9799 |
+
$content = SucuriScanTemplate::getSection('corefiles-notification', $params);
|
9800 |
$sent = SucuriScanEvent::notify_event('scan_checksums', $content);
|
9801 |
|
9802 |
return $sent;
|
9805 |
return false;
|
9806 |
}
|
9807 |
|
9808 |
+
return SucuriScanTemplate::getSection('corefiles', $params);
|
9809 |
+
}
|
9810 |
+
|
9811 |
+
/**
|
9812 |
+
* Process the requests sent by the form submissions originated in the integrity
|
9813 |
+
* page, all forms must have a nonce field that will be checked against the one
|
9814 |
+
* generated in the template render function.
|
9815 |
+
*
|
9816 |
+
* @return void
|
9817 |
+
*/
|
9818 |
+
function sucuriscan_integrity_form_submissions()
|
9819 |
+
{
|
9820 |
+
if (SucuriScanInterface::check_nonce()) {
|
9821 |
+
// Force the execution of the filesystem scanner.
|
9822 |
+
if (SucuriScanRequest::post(':force_scan') !== false) {
|
9823 |
+
SucuriScanEvent::notify_event('plugin_change', 'Filesystem scan forced at: ' . date('r'));
|
9824 |
+
SucuriScanEvent::filesystem_scan(true);
|
9825 |
+
sucuriscan_core_files_data(true);
|
9826 |
+
}
|
9827 |
+
|
9828 |
+
// Restore, Remove, Mark as fixed the core files.
|
9829 |
+
$action = SucuriScanRequest::post(':integrity_action');
|
9830 |
+
|
9831 |
+
if ($action !== false) {
|
9832 |
+
if (SucuriScanRequest::post(':process_form') == 1) {
|
9833 |
+
if ($action == 'fixed'
|
9834 |
+
|| $action == 'delete'
|
9835 |
+
|| $action == 'restore'
|
9836 |
+
) {
|
9837 |
+
$cache = new SucuriScanCache('integrity');
|
9838 |
+
$core_files = SucuriScanRequest::post(':corefiles', '_array');
|
9839 |
+
$files_selected = count($core_files);
|
9840 |
+
$files_affected = array();
|
9841 |
+
$files_processed = 0;
|
9842 |
+
$action_titles = array(
|
9843 |
+
'restore' => 'Core file restored',
|
9844 |
+
'delete' => 'Non-core file deleted',
|
9845 |
+
'fixed' => 'Core file marked as fixed',
|
9846 |
+
);
|
9847 |
+
|
9848 |
+
if ($core_files) {
|
9849 |
+
$delimiter = '@';
|
9850 |
+
$parts_count = 2;
|
9851 |
+
|
9852 |
+
foreach ($core_files as $file_meta) {
|
9853 |
+
if (strpos($file_meta, $delimiter)) {
|
9854 |
+
$parts = explode($delimiter, $file_meta, $parts_count);
|
9855 |
+
|
9856 |
+
if (count($parts) === $parts_count) {
|
9857 |
+
$file_path = $parts[1];
|
9858 |
+
$status_type = $parts[0];
|
9859 |
+
|
9860 |
+
// Do not use realpath as the file may not exists.
|
9861 |
+
$full_path = ABSPATH . '/' . $file_path;
|
9862 |
+
|
9863 |
+
switch ($action) {
|
9864 |
+
case 'restore':
|
9865 |
+
$file_content = SucuriScanAPI::getOriginalCoreFile($file_path);
|
9866 |
+
if ($file_content) {
|
9867 |
+
$restored = @file_put_contents($full_path, $file_content);
|
9868 |
+
$files_processed += ($restored ? 1 : 0);
|
9869 |
+
$files_affected[] = $full_path;
|
9870 |
+
}
|
9871 |
+
break;
|
9872 |
+
case 'fixed':
|
9873 |
+
$cache_key = md5($file_path);
|
9874 |
+
$cache_value = array(
|
9875 |
+
'file_path' => $file_path,
|
9876 |
+
'file_status' => $status_type,
|
9877 |
+
'ignored_at' => time(),
|
9878 |
+
);
|
9879 |
+
$cached = $cache->add($cache_key, $cache_value);
|
9880 |
+
$files_processed += ($cached ? 1 : 0);
|
9881 |
+
$files_affected[] = $full_path;
|
9882 |
+
break;
|
9883 |
+
case 'delete':
|
9884 |
+
if (@unlink($full_path)) {
|
9885 |
+
$files_processed += 1;
|
9886 |
+
$files_affected[] = $full_path;
|
9887 |
+
}
|
9888 |
+
break;
|
9889 |
+
}
|
9890 |
+
}
|
9891 |
+
}
|
9892 |
+
}
|
9893 |
+
|
9894 |
+
// Report files affected as a single event.
|
9895 |
+
if (!empty($files_affected)) {
|
9896 |
+
$message_tpl = (count($files_affected) > 1)
|
9897 |
+
? '%s: (multiple entries): %s'
|
9898 |
+
: '%s: %s';
|
9899 |
+
$message = sprintf(
|
9900 |
+
$message_tpl,
|
9901 |
+
$action_titles[$action],
|
9902 |
+
@implode(',', $files_affected)
|
9903 |
+
);
|
9904 |
+
|
9905 |
+
switch ($action) {
|
9906 |
+
case 'restore':
|
9907 |
+
SucuriScanEvent::report_info_event($message);
|
9908 |
+
break;
|
9909 |
+
case 'delete':
|
9910 |
+
SucuriScanEvent::report_notice_event($message);
|
9911 |
+
break;
|
9912 |
+
case 'fixed':
|
9913 |
+
SucuriScanEvent::report_warning_event($message);
|
9914 |
+
break;
|
9915 |
+
}
|
9916 |
+
}
|
9917 |
+
|
9918 |
+
SucuriScanInterface::info(sprintf(
|
9919 |
+
'<b>%d</b> out of <b>%d</b> files were successfully processed.',
|
9920 |
+
$files_processed,
|
9921 |
+
$files_selected
|
9922 |
+
));
|
9923 |
+
} else {
|
9924 |
+
SucuriScanInterface::error('No files were selected.');
|
9925 |
+
}
|
9926 |
+
} else {
|
9927 |
+
SucuriScanInterface::error('Action requested is not supported.');
|
9928 |
+
}
|
9929 |
+
} else {
|
9930 |
+
SucuriScanInterface::error('You need to confirm that you understand the risk of this operation.');
|
9931 |
+
}
|
9932 |
+
}
|
9933 |
+
}
|
9934 |
+
}
|
9935 |
+
|
9936 |
+
/**
|
9937 |
+
* Retrieve a list of md5sum and last modification time of all the files in the
|
9938 |
+
* folder specified. This is a recursive function.
|
9939 |
+
*
|
9940 |
+
* @param string $dir The base path where the scanning will start.
|
9941 |
+
* @param boolean $recursive Either TRUE or FALSE if the scan should be performed recursively.
|
9942 |
+
* @return array List of arrays containing the md5sum and last modification time of the files found.
|
9943 |
+
*/
|
9944 |
+
function sucuriscan_get_integrity_tree($dir = './', $recursive = false)
|
9945 |
+
{
|
9946 |
+
$abs_path = rtrim(ABSPATH, '/');
|
9947 |
+
|
9948 |
+
$file_info = new SucuriScanFileInfo();
|
9949 |
+
$file_info->ignore_files = false;
|
9950 |
+
$file_info->ignore_directories = false;
|
9951 |
+
$file_info->run_recursively = $recursive;
|
9952 |
+
$file_info->scan_interface = SucuriScanOption::get_option(':scan_interface');
|
9953 |
+
$integrity_tree = $file_info->get_directory_tree_md5($dir, true);
|
9954 |
+
|
9955 |
+
if (!$integrity_tree) {
|
9956 |
+
$integrity_tree = array();
|
9957 |
+
}
|
9958 |
+
|
9959 |
+
return $integrity_tree;
|
9960 |
}
|
9961 |
|
9962 |
/**
|
9965 |
* these keys:
|
9966 |
*
|
9967 |
* <ul>
|
9968 |
+
* <li>modified: Files with a different checksum according to the official WordPress archives,</li>
|
9969 |
* <li>stable: Files with the same checksums than the official files,</li>
|
9970 |
* <li>removed: Official files which are not present in the local project,</li>
|
9971 |
* <li>added: Files present in the local project but not in the official WordPress packages.</li>
|
9976 |
*/
|
9977 |
function sucuriscan_check_core_integrity($version = 0)
|
9978 |
{
|
9979 |
+
$latest_hashes = SucuriScanAPI::getOfficialChecksums($version);
|
9980 |
$base_content_dir = defined('WP_CONTENT_DIR')
|
9981 |
? basename(rtrim(WP_CONTENT_DIR, '/'))
|
9982 |
: '';
|
9983 |
|
9984 |
+
if (!$latest_hashes) {
|
9985 |
return false;
|
9986 |
}
|
9987 |
|
10007 |
$full_filepath = sprintf('%s/%s', ABSPATH, $file_path);
|
10008 |
|
10009 |
// Patch for custom content directory path.
|
10010 |
+
if (!file_exists($full_filepath)
|
10011 |
&& strpos($file_path, 'wp-content') !== false
|
10012 |
&& defined('WP_CONTENT_DIR')
|
10013 |
) {
|
10050 |
// Search added files (files not common in a normal wordpress installation).
|
10051 |
foreach ($wp_core_hashes as $file_path => $extra_info) {
|
10052 |
$file_path = str_replace(DIRECTORY_SEPARATOR, '/', $file_path);
|
10053 |
+
$file_path = @preg_replace('/^\.\/(.*)/', '$1', $file_path);
|
10054 |
|
10055 |
if (sucuriscan_ignore_integrity_filepath($file_path)) {
|
10056 |
continue;
|
10057 |
}
|
10058 |
|
10059 |
+
if (!array_key_exists($file_path, $latest_hashes)) {
|
10060 |
$full_filepath = ABSPATH . '/' . $file_path;
|
10061 |
$modified_at = @filemtime($full_filepath);
|
10062 |
$is_fixable = (bool) is_writable($full_filepath);
|
10083 |
|
10084 |
// List of files that will be ignored from the integrity checking.
|
10085 |
$ignore_files = array(
|
10086 |
+
'^sucuri-[0-9a-z\-]+\.php$',
|
10087 |
+
'^\S+-sucuri-db-dump-gzip-[0-9]{10}-[0-9a-z]{32}\.gz$',
|
10088 |
'^favicon\.ico$',
|
10089 |
'^php\.ini$',
|
10090 |
'^\.htaccess$',
|
10119 |
|
10120 |
// Determine whether a file must be ignored from the integrity checks or not.
|
10121 |
foreach ($ignore_files as $ignore_pattern) {
|
10122 |
+
if (@preg_match('/'.$ignore_pattern.'/', $file_path)) {
|
10123 |
return true;
|
10124 |
}
|
10125 |
}
|
10127 |
return false;
|
10128 |
}
|
10129 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
10130 |
/**
|
10131 |
* Generate and print the HTML code for the Post-Hack page.
|
10132 |
*
|
10133 |
* @return void
|
10134 |
*/
|
10135 |
+
function sucuriscan_posthack_page()
|
10136 |
+
{
|
10137 |
SucuriScanInterface::check_permissions();
|
10138 |
|
10139 |
$process_form = sucuriscan_posthack_process_form();
|
10140 |
|
10141 |
// Page pseudo-variables initialization.
|
10142 |
+
$params = array(
|
10143 |
'PageTitle' => 'Post-Hack',
|
10144 |
+
'UpdateSecretKeys' => sucuriscan_update_secret_keys($process_form),
|
10145 |
+
'ResetPassword' => sucuriscan_posthack_users($process_form),
|
10146 |
+
'ResetPlugins' => sucuriscan_posthack_plugins($process_form),
|
10147 |
);
|
10148 |
|
10149 |
+
echo SucuriScanTemplate::getTemplate('posthack', $params);
|
10150 |
}
|
10151 |
|
10152 |
/**
|
10154 |
*
|
10155 |
* @return mixed.
|
10156 |
*/
|
10157 |
+
function sucuriscan_posthack_ajax()
|
10158 |
+
{
|
10159 |
SucuriScanInterface::check_permissions();
|
10160 |
|
10161 |
+
if (SucuriScanInterface::check_nonce()) {
|
10162 |
sucuriscan_posthack_plugins_ajax();
|
10163 |
}
|
10164 |
|
10170 |
*
|
10171 |
* @return boolean TRUE if a form submission should be processed, FALSE otherwise.
|
10172 |
*/
|
10173 |
+
function sucuriscan_posthack_process_form()
|
10174 |
+
{
|
10175 |
+
$process_form = SucuriScanRequest::post(':process_form', '(0|1)');
|
10176 |
|
10177 |
+
if (SucuriScanInterface::check_nonce()
|
|
|
10178 |
&& $process_form !== false
|
10179 |
) {
|
10180 |
+
if ($process_form === '1') {
|
10181 |
return true;
|
10182 |
} else {
|
10183 |
+
SucuriScanInterface::error('You need to confirm that you understand the risk of this operation.');
|
10184 |
}
|
10185 |
}
|
10186 |
|
10193 |
* @param $process_form Whether a form was submitted or not.
|
10194 |
* @return string HTML code with the information of the process.
|
10195 |
*/
|
10196 |
+
function sucuriscan_update_secret_keys($process_form = false)
|
10197 |
+
{
|
10198 |
+
$params = array(
|
10199 |
'WPConfigUpdate.Visibility' => 'hidden',
|
10200 |
'WPConfigUpdate.NewConfig' => '',
|
10201 |
'SecurityKeys.List' => '',
|
10202 |
);
|
10203 |
|
10204 |
// Update all WordPress secret keys.
|
10205 |
+
if ($process_form && SucuriScanRequest::post(':update_wpconfig', '1')) {
|
10206 |
$wpconfig_process = SucuriScanEvent::set_new_config_keys();
|
10207 |
|
10208 |
+
if ($wpconfig_process) {
|
10209 |
+
$params['WPConfigUpdate.Visibility'] = 'visible';
|
10210 |
+
SucuriScanEvent::report_notice_event('Generate new security keys');
|
10211 |
+
|
10212 |
+
if ($wpconfig_process['updated'] === true) {
|
10213 |
+
SucuriScanInterface::info('Secret keys updated successfully (summary of the operation bellow).');
|
10214 |
+
$params['WPConfigUpdate.NewConfig'] .= "// Old Keys\n";
|
10215 |
+
$params['WPConfigUpdate.NewConfig'] .= $wpconfig_process['old_keys_string'];
|
10216 |
+
$params['WPConfigUpdate.NewConfig'] .= "//\n";
|
10217 |
+
$params['WPConfigUpdate.NewConfig'] .= "// New Keys\n";
|
10218 |
+
$params['WPConfigUpdate.NewConfig'] .= $wpconfig_process['new_keys_string'];
|
10219 |
} else {
|
10220 |
SucuriScanInterface::error(
|
10221 |
'<code>wp-config.php</code> file is not writable, replace the '
|
10222 |
. 'old configuration file with the new values shown bellow.'
|
10223 |
);
|
10224 |
+
$params['WPConfigUpdate.NewConfig'] = $wpconfig_process['new_wpconfig'];
|
10225 |
}
|
10226 |
} else {
|
10227 |
+
SucuriScanInterface::error('<code>wp-config.php</code> file was not found in the default location.');
|
10228 |
}
|
10229 |
}
|
10230 |
|
10232 |
$current_keys = SucuriScanOption::get_security_keys();
|
10233 |
$counter = 0;
|
10234 |
|
10235 |
+
foreach ($current_keys as $key_status => $key_list) {
|
10236 |
+
foreach ($key_list as $key_name => $key_value) {
|
10237 |
$css_class = ( $counter % 2 == 0 ) ? '' : 'alternate';
|
10238 |
+
$key_value = SucuriScan::excerpt($key_value, 50);
|
10239 |
|
10240 |
+
switch ($key_status) {
|
10241 |
case 'good':
|
10242 |
$key_status_text = 'good';
|
10243 |
$key_status_css_class = 'success';
|
10253 |
break;
|
10254 |
}
|
10255 |
|
10256 |
+
if (isset($key_status_text)) {
|
10257 |
+
$params['SecurityKeys.List'] .= SucuriScanTemplate::getSnippet(
|
10258 |
+
'posthack-updatesecretkeys',
|
10259 |
+
array(
|
10260 |
+
'SecurityKey.CssClass' => $css_class,
|
10261 |
+
'SecurityKey.KeyName' => $key_name,
|
10262 |
+
'SecurityKey.KeyValue' => $key_value,
|
10263 |
+
'SecurityKey.KeyStatusText' => $key_status_text,
|
10264 |
+
'SecurityKey.KeyStatusCssClass' => $key_status_css_class,
|
10265 |
+
)
|
10266 |
+
);
|
10267 |
+
$counter++;
|
10268 |
}
|
10269 |
}
|
10270 |
}
|
10271 |
|
10272 |
+
return SucuriScanTemplate::getSection('posthack-updatesecretkeys', $params);
|
10273 |
}
|
10274 |
|
10275 |
/**
|
10279 |
* @param $process_form Whether a form was submitted or not.
|
10280 |
* @return string HTML code for a table where a list of user accounts will be shown.
|
10281 |
*/
|
10282 |
+
function sucuriscan_posthack_users($process_form = false)
|
10283 |
+
{
|
10284 |
+
$params = array(
|
10285 |
'ResetPassword.UserList' => '',
|
10286 |
'ResetPassword.PaginationLinks' => '',
|
10287 |
'ResetPassword.PaginationVisibility' => 'hidden',
|
10288 |
);
|
10289 |
|
10290 |
// Process the form submission (if any).
|
10291 |
+
sucuriscan_reset_user_password($process_form);
|
10292 |
|
10293 |
// Fill the user list for ResetPassword action.
|
10294 |
$user_list = false;
|
10295 |
+
$page_number = SucuriScanTemplate::pageNumber();
|
10296 |
$max_per_page = SUCURISCAN_MAX_PAGINATION_BUTTONS;
|
10297 |
+
$dbquery = new WP_User_Query(array(
|
10298 |
'number' => $max_per_page,
|
10299 |
+
'offset' => ($page_number - 1) * $max_per_page,
|
10300 |
'fields' => 'all_with_meta',
|
10301 |
'orderby' => 'ID',
|
10302 |
+
));
|
10303 |
|
10304 |
// Retrieve the results and build the pagination links.
|
10305 |
+
if ($dbquery) {
|
10306 |
$total_items = $dbquery->get_total();
|
10307 |
$user_list = $dbquery->get_results();
|
10308 |
|
10309 |
+
$params['ResetPassword.PaginationLinks'] = SucuriScanTemplate::pagination(
|
10310 |
'%%SUCURI.URL.Posthack%%#reset-users-password',
|
10311 |
$total_items,
|
10312 |
$max_per_page
|
10313 |
);
|
10314 |
|
10315 |
+
if ($total_items > $max_per_page) {
|
10316 |
+
$params['ResetPassword.PaginationVisibility'] = 'visible';
|
10317 |
}
|
10318 |
}
|
10319 |
|
10320 |
+
if ($user_list !== false) {
|
10321 |
$counter = 0;
|
10322 |
|
10323 |
+
foreach ($user_list as $user) {
|
10324 |
+
$user->user_registered_timestamp = strtotime($user->user_registered);
|
10325 |
+
$user->user_registered_formatted = SucuriScan::datetime($user->user_registered_timestamp);
|
10326 |
$css_class = ( $counter % 2 == 0 ) ? '' : 'alternate';
|
10327 |
$display_username = ( $user->user_login != $user->display_name )
|
10328 |
+
? sprintf('%s (%s)', $user->user_login, $user->display_name)
|
10329 |
: $user->user_login;
|
10330 |
|
10331 |
+
$params['ResetPassword.UserList'] .= SucuriScanTemplate::getSnippet(
|
10332 |
+
'posthack-resetpassword',
|
10333 |
+
array(
|
10334 |
+
'ResetPassword.UserId' => $user->ID,
|
10335 |
+
'ResetPassword.Username' => $user->user_login,
|
10336 |
+
'ResetPassword.Displayname' => $user->display_name,
|
10337 |
+
'ResetPassword.DisplayUsername' => $display_username,
|
10338 |
+
'ResetPassword.Email' => $user->user_email,
|
10339 |
+
'ResetPassword.Registered' => $user->user_registered_formatted,
|
10340 |
+
'ResetPassword.Roles' => @implode(', ', $user->roles),
|
10341 |
+
'ResetPassword.CssClass' => $css_class,
|
10342 |
+
)
|
10343 |
+
);
|
10344 |
+
$counter++;
|
10345 |
}
|
10346 |
}
|
10347 |
|
10348 |
+
return SucuriScanTemplate::getSection('posthack-resetpassword', $params);
|
10349 |
}
|
10350 |
|
10351 |
/**
|
10354 |
* @param $process_form Whether a form was submitted or not.
|
10355 |
* @return void
|
10356 |
*/
|
10357 |
+
function sucuriscan_reset_user_password($process_form = false)
|
10358 |
+
{
|
10359 |
+
if ($process_form && SucuriScanRequest::post(':reset_password')) {
|
10360 |
+
$user_identifiers = SucuriScanRequest::post('user_ids', '_array');
|
10361 |
$pwd_changed = array();
|
10362 |
$pwd_not_changed = array();
|
10363 |
|
10364 |
+
if (is_array($user_identifiers) && !empty($user_identifiers)) {
|
10365 |
+
arsort($user_identifiers);
|
10366 |
|
10367 |
+
foreach ($user_identifiers as $user_id) {
|
10368 |
+
$user_id = intval($user_id);
|
10369 |
|
10370 |
+
if (SucuriScanEvent::set_new_password($user_id)) {
|
10371 |
$pwd_changed[] = $user_id;
|
10372 |
} else {
|
10373 |
$pwd_not_changed[] = $user_id;
|
10374 |
}
|
10375 |
}
|
10376 |
|
10377 |
+
if (!empty($pwd_changed)) {
|
10378 |
+
$message = 'Password changed for user identifiers <code>' . @implode(', ', $pwd_changed) . '</code>';
|
10379 |
|
10380 |
+
SucuriScanEvent::report_notice_event($message);
|
10381 |
+
SucuriScanInterface::info($message);
|
10382 |
}
|
10383 |
|
10384 |
+
if (!empty($pwd_not_changed)) {
|
10385 |
+
SucuriScanInterface::error('Password change failed for users: ' . implode(', ', $pwd_not_changed));
|
10386 |
}
|
10387 |
} else {
|
10388 |
+
SucuriScanInterface::error('You did not select a user from the list.');
|
10389 |
}
|
10390 |
}
|
10391 |
}
|
10396 |
* @param boolean $process_form Whether a form was submitted or not.
|
10397 |
* @return void
|
10398 |
*/
|
10399 |
+
function sucuriscan_posthack_plugins($process_form = false)
|
10400 |
+
{
|
10401 |
+
$params = array(
|
10402 |
'ResetPlugin.PluginList' => '',
|
10403 |
'ResetPlugin.CacheLifeTime' => 'unknown',
|
10404 |
);
|
10405 |
|
10406 |
+
if (defined('SUCURISCAN_GET_PLUGINS_LIFETIME')) {
|
10407 |
+
$params['ResetPlugin.CacheLifeTime'] = SUCURISCAN_GET_PLUGINS_LIFETIME;
|
10408 |
}
|
10409 |
|
10410 |
+
sucuriscan_posthack_reinstall_plugins($process_form);
|
10411 |
|
10412 |
+
return SucuriScanTemplate::getSection('posthack-resetplugins', $params);
|
10413 |
}
|
10414 |
|
10415 |
/**
|
10417 |
*
|
10418 |
* @return string HTML code for a table with the plugins metadata.
|
10419 |
*/
|
10420 |
+
function sucuriscan_posthack_plugins_ajax()
|
10421 |
+
{
|
10422 |
+
if (SucuriScanRequest::post('form_action') == 'get_plugins_data') {
|
10423 |
+
$all_plugins = SucuriScanAPI::getPlugins();
|
10424 |
$response = '';
|
10425 |
$counter = 0;
|
10426 |
|
10427 |
+
foreach ($all_plugins as $plugin_path => $plugin_data) {
|
10428 |
$css_class = ( $counter % 2 == 0 ) ? '' : 'alternate';
|
10429 |
$plugin_type_class = ( $plugin_data['PluginType'] == 'free' ) ? 'primary' : 'warning';
|
10430 |
$input_disabled = ( $plugin_data['PluginType'] == 'free' ) ? '' : 'disabled="disabled"';
|
10431 |
$plugin_status = $plugin_data['IsPluginActive'] ? 'active' : 'not active';
|
10432 |
$plugin_status_class = $plugin_data['IsPluginActive'] ? 'success' : 'default';
|
10433 |
|
10434 |
+
$response .= SucuriScanTemplate::getSnippet(
|
10435 |
+
'posthack-resetplugins',
|
10436 |
+
array(
|
10437 |
+
'ResetPlugin.CssClass' => $css_class,
|
10438 |
+
'ResetPlugin.Disabled' => $input_disabled,
|
10439 |
+
'ResetPlugin.PluginPath' => $plugin_path,
|
10440 |
+
'ResetPlugin.Plugin' => SucuriScan::excerpt($plugin_data['Name'], 35),
|
10441 |
+
'ResetPlugin.Version' => $plugin_data['Version'],
|
10442 |
+
'ResetPlugin.Type' => $plugin_data['PluginType'],
|
10443 |
+
'ResetPlugin.TypeClass' => $plugin_type_class,
|
10444 |
+
'ResetPlugin.Status' => $plugin_status,
|
10445 |
+
'ResetPlugin.StatusClass' => $plugin_status_class,
|
10446 |
+
)
|
10447 |
+
);
|
10448 |
+
$counter++;
|
10449 |
}
|
10450 |
|
10451 |
print( $response );
|
10462 |
* @param boolean $process_form Whether a form was submitted or not.
|
10463 |
* @return void
|
10464 |
*/
|
10465 |
+
function sucuriscan_posthack_reinstall_plugins($process_form = false)
|
10466 |
+
{
|
10467 |
+
if ($process_form && isset($_POST['sucuriscan_reset_plugins'])) {
|
10468 |
+
include_once(ABSPATH . 'wp-admin/includes/class-wp-upgrader.php');
|
10469 |
+
include_once(ABSPATH . 'wp-admin/includes/plugin-install.php'); // For plugins_api.
|
10470 |
|
10471 |
+
if ($plugin_list = SucuriScanRequest::post('plugin_path', '_array')) {
|
10472 |
// Create an instance of the FileInfo interface.
|
10473 |
$file_info = new SucuriScanFileInfo();
|
10474 |
$file_info->ignore_files = false;
|
10476 |
$file_info->skip_directories = false;
|
10477 |
|
10478 |
// Get (possible) cached information from the installed plugins.
|
10479 |
+
$all_plugins = SucuriScanAPI::getPlugins();
|
10480 |
|
10481 |
// Loop through all the installed plugins.
|
10482 |
+
foreach ($_POST['plugin_path'] as $plugin_path) {
|
10483 |
+
if (array_key_exists($plugin_path, $all_plugins)) {
|
10484 |
$plugin_data = $all_plugins[ $plugin_path ];
|
10485 |
|
10486 |
// Check if the plugin can be downloaded from the free market.
|
10487 |
+
if ($plugin_data['IsFreePlugin'] === true) {
|
10488 |
+
$plugin_info = SucuriScanAPI::getRemotePluginData($plugin_data['RepositoryName']);
|
10489 |
|
10490 |
+
if ($plugin_info) {
|
10491 |
// First, remove all files/sub-folders from the plugin's directory.
|
10492 |
+
if (substr_count($plugin_path, '/') >= 1) {
|
10493 |
+
$plugin_directory = dirname(WP_PLUGIN_DIR . '/' . $plugin_path);
|
10494 |
+
$file_info->remove_directory_tree($plugin_directory);
|
10495 |
}
|
10496 |
|
10497 |
// Install a fresh copy of the plugin's files.
|
10498 |
$upgrader_skin = new Plugin_Installer_Skin();
|
10499 |
+
$upgrader = new Plugin_Upgrader($upgrader_skin);
|
10500 |
+
$upgrader->install($plugin_info->download_link);
|
10501 |
+
SucuriScanEvent::report_notice_event('Plugin re-installed: ' . $plugin_path);
|
10502 |
} else {
|
10503 |
+
SucuriScanInterface::error('Connection with the WordPress plugin market failed.');
|
10504 |
}
|
10505 |
}
|
10506 |
}
|
10507 |
}
|
10508 |
} else {
|
10509 |
+
SucuriScanInterface::error('You did not select a free plugin to reinstall.');
|
10510 |
}
|
10511 |
}
|
10512 |
}
|
10518 |
*
|
10519 |
* @return string Last-logings for the administrator accounts.
|
10520 |
*/
|
10521 |
+
function sucuriscan_lastlogins_page()
|
10522 |
+
{
|
10523 |
SucuriScanInterface::check_permissions();
|
10524 |
|
10525 |
// Reset the file with the last-logins logs.
|
10526 |
+
if (SucuriScanInterface::check_nonce()
|
10527 |
+
&& SucuriScanRequest::post(':reset_lastlogins') !== false
|
|
|
10528 |
) {
|
10529 |
$file_path = sucuriscan_lastlogins_datastore_filepath();
|
10530 |
|
10531 |
+
if (unlink($file_path)) {
|
10532 |
sucuriscan_lastlogins_datastore_exists();
|
10533 |
+
SucuriScanInterface::info('Last-Logins logs were reset successfully.');
|
10534 |
} else {
|
10535 |
+
SucuriScanInterface::error('Could not reset the last-logins logs.');
|
10536 |
}
|
10537 |
}
|
10538 |
|
10539 |
// Page pseudo-variables initialization.
|
10540 |
+
$params = array(
|
10541 |
'PageTitle' => 'Last Logins',
|
10542 |
'LastLogins.Admins' => sucuriscan_lastlogins_admins(),
|
10543 |
'LastLogins.AllUsers' => sucuriscan_lastlogins_all(),
|
10545 |
'FailedLogins' => sucuriscan_failed_logins_panel(),
|
10546 |
);
|
10547 |
|
10548 |
+
echo SucuriScanTemplate::getTemplate('lastlogins', $params);
|
10549 |
}
|
10550 |
|
10551 |
/**
|
10552 |
* List all the user administrator accounts.
|
10553 |
*
|
10554 |
+
* @see https://codex.wordpress.org/Class_Reference/WP_User_Query
|
10555 |
*
|
10556 |
* @return void
|
10557 |
*/
|
10558 |
+
function sucuriscan_lastlogins_admins()
|
10559 |
+
{
|
10560 |
// Page pseudo-variables initialization.
|
10561 |
+
$params = array(
|
10562 |
'AdminUsers.List' => '',
|
10563 |
);
|
10564 |
|
10565 |
+
$user_query = new WP_User_Query(array('role' => 'Administrator'));
|
10566 |
$admins = $user_query->get_results();
|
10567 |
|
10568 |
+
foreach ((array) $admins as $admin) {
|
10569 |
+
$last_logins = sucuriscan_get_logins(5, 0, $admin->ID);
|
10570 |
$admin->lastlogins = $last_logins['entries'];
|
10571 |
|
10572 |
$user_snippet = array(
|
10573 |
+
'AdminUsers.Username' => $admin->user_login,
|
10574 |
+
'AdminUsers.Email' => $admin->user_email,
|
10575 |
'AdminUsers.LastLogins' => '',
|
10576 |
+
'AdminUsers.RegisteredAt' => 'Unknown',
|
10577 |
+
'AdminUsers.UserURL' => SucuriScan::admin_url('user-edit.php?user_id=' . $admin->ID),
|
10578 |
'AdminUsers.NoLastLogins' => 'visible',
|
10579 |
'AdminUsers.NoLastLoginsTable' => 'hidden',
|
10580 |
);
|
10581 |
|
10582 |
+
if (!empty($admin->lastlogins)) {
|
10583 |
$user_snippet['AdminUsers.NoLastLogins'] = 'hidden';
|
10584 |
$user_snippet['AdminUsers.NoLastLoginsTable'] = 'visible';
|
10585 |
$user_snippet['AdminUsers.RegisteredAt'] = 'Unknown';
|
10586 |
$counter = 0;
|
10587 |
|
10588 |
+
foreach ($admin->lastlogins as $i => $lastlogin) {
|
10589 |
+
if ($i == 0) {
|
10590 |
+
$user_snippet['AdminUsers.RegisteredAt'] = SucuriScan::datetime(
|
10591 |
+
$lastlogin->user_registered_timestamp
|
10592 |
+
);
|
10593 |
}
|
10594 |
|
10595 |
+
$css_class = ($counter % 2 === 0) ? '' : 'alternate';
|
10596 |
+
$user_snippet['AdminUsers.LastLogins'] .= SucuriScanTemplate::getSnippet(
|
10597 |
+
'lastlogins-admins-lastlogin',
|
10598 |
+
array(
|
10599 |
+
'AdminUsers.RemoteAddr' => $lastlogin->user_remoteaddr,
|
10600 |
+
'AdminUsers.Datetime' => SucuriScan::datetime($lastlogin->user_lastlogin_timestamp),
|
10601 |
+
'AdminUsers.CssClass' => $css_class,
|
10602 |
+
)
|
10603 |
+
);
|
10604 |
+
$counter++;
|
10605 |
}
|
10606 |
}
|
10607 |
|
10608 |
+
$params['AdminUsers.List'] .= SucuriScanTemplate::getSnippet('lastlogins-admins', $user_snippet);
|
10609 |
}
|
10610 |
|
10611 |
+
return SucuriScanTemplate::getSection('lastlogins-admins', $params);
|
10612 |
}
|
10613 |
|
10614 |
/**
|
10618 |
*
|
10619 |
* @return string Last-logings for all user accounts.
|
10620 |
*/
|
10621 |
+
function sucuriscan_lastlogins_all()
|
10622 |
+
{
|
10623 |
$max_per_page = SUCURISCAN_LASTLOGINS_USERSLIMIT;
|
10624 |
+
$page_number = SucuriScanTemplate::pageNumber();
|
10625 |
$offset = ($max_per_page * $page_number) - $max_per_page;
|
10626 |
|
10627 |
+
$params = array(
|
10628 |
'UserList' => '',
|
10629 |
'UserList.Limit' => $max_per_page,
|
10630 |
'UserList.Total' => 0,
|
10633 |
'UserList.NoItemsVisibility' => 'visible',
|
10634 |
);
|
10635 |
|
10636 |
+
if (!sucuriscan_lastlogins_datastore_is_writable()) {
|
10637 |
+
$fpath = SucuriScan::escape(sucuriscan_lastlogins_datastore_filepath());
|
10638 |
+
SucuriScanInterface::error('Last-logins datastore file is not writable: <code>' . $fpath . '</code>');
|
10639 |
}
|
10640 |
|
10641 |
$counter = 0;
|
10642 |
+
$last_logins = sucuriscan_get_logins($max_per_page, $offset);
|
10643 |
+
$params['UserList.Total'] = $last_logins['total'];
|
10644 |
|
10645 |
+
if ($last_logins['total'] > $max_per_page) {
|
10646 |
+
$params['UserList.PaginationVisibility'] = 'visible';
|
10647 |
}
|
10648 |
|
10649 |
+
if ($last_logins['total'] > 0) {
|
10650 |
+
$params['UserList.NoItemsVisibility'] = 'hidden';
|
10651 |
}
|
10652 |
|
10653 |
+
foreach ($last_logins['entries'] as $user) {
|
10654 |
+
$css_class = ($counter % 2 === 0) ? '' : 'alternate';
|
|
|
10655 |
|
10656 |
$user_dataset = array(
|
10657 |
'UserList.Number' => $user->line_num,
|
10658 |
'UserList.UserId' => $user->user_id,
|
10659 |
+
'UserList.Username' => 'Unknown',
|
10660 |
'UserList.Displayname' => '',
|
10661 |
'UserList.Email' => '',
|
10662 |
'UserList.Registered' => '',
|
10663 |
+
'UserList.RemoteAddr' => $user->user_remoteaddr,
|
10664 |
+
'UserList.Hostname' => $user->user_hostname,
|
10665 |
+
'UserList.Datetime' => $user->user_lastlogin,
|
10666 |
+
'UserList.TimeAgo' => SucuriScan::time_ago($user->user_lastlogin),
|
10667 |
+
'UserList.UserURL' => SucuriScan::admin_url('user-edit.php?user_id=' . $user->user_id),
|
10668 |
'UserList.CssClass' => $css_class,
|
10669 |
);
|
10670 |
|
10671 |
+
if ($user->user_exists) {
|
10672 |
+
$user_dataset['UserList.Username'] = $user->user_login;
|
10673 |
+
$user_dataset['UserList.Displayname'] = $user->display_name;
|
10674 |
+
$user_dataset['UserList.Email'] = $user->user_email;
|
10675 |
+
$user_dataset['UserList.Registered'] = $user->user_registered;
|
10676 |
}
|
10677 |
|
10678 |
+
$params['UserList'] .= SucuriScanTemplate::getSnippet('lastlogins-all', $user_dataset);
|
10679 |
+
$counter++;
|
10680 |
}
|
10681 |
|
10682 |
// Generate the pagination for the list.
|
10683 |
+
$params['UserList.Pagination'] = SucuriScanTemplate::pagination(
|
10684 |
'%%SUCURI.URL.Lastlogins%%',
|
10685 |
$last_logins['total'],
|
10686 |
$max_per_page
|
10687 |
);
|
10688 |
|
10689 |
+
return SucuriScanTemplate::getSection('lastlogins-all', $params);
|
10690 |
}
|
10691 |
|
10692 |
/**
|
10694 |
*
|
10695 |
* @return string Absolute filepath where the user's last login information is stored.
|
10696 |
*/
|
10697 |
+
function sucuriscan_lastlogins_datastore_filepath()
|
10698 |
+
{
|
10699 |
+
return SucuriScan::datastore_folder_path('sucuri-lastlogins.php');
|
10700 |
}
|
10701 |
|
10702 |
/**
|
10705 |
*
|
10706 |
* @return string Absolute filepath where the user's last login information is stored.
|
10707 |
*/
|
10708 |
+
function sucuriscan_lastlogins_datastore_exists()
|
10709 |
+
{
|
10710 |
$fpath = sucuriscan_lastlogins_datastore_filepath();
|
10711 |
|
10712 |
if (!file_exists($fpath)) {
|
10726 |
*
|
10727 |
* @return boolean Whether the user's last login datastore file is writable or not.
|
10728 |
*/
|
10729 |
+
function sucuriscan_lastlogins_datastore_is_writable()
|
10730 |
+
{
|
10731 |
$datastore_filepath = sucuriscan_lastlogins_datastore_exists();
|
10732 |
|
10733 |
+
if ($datastore_filepath) {
|
10734 |
+
if (!is_writable($datastore_filepath)) {
|
10735 |
+
@chmod($datastore_filepath, 0644);
|
10736 |
}
|
10737 |
|
10738 |
+
if (is_writable($datastore_filepath)) {
|
10739 |
return $datastore_filepath;
|
10740 |
}
|
10741 |
}
|
10749 |
*
|
10750 |
* @return boolean Whether the user's last login datastore file is readable or not.
|
10751 |
*/
|
10752 |
+
function sucuriscan_lastlogins_datastore_is_readable()
|
10753 |
+
{
|
10754 |
$datastore_filepath = sucuriscan_lastlogins_datastore_exists();
|
10755 |
|
10756 |
+
if ($datastore_filepath && is_readable($datastore_filepath)) {
|
10757 |
return $datastore_filepath;
|
10758 |
}
|
10759 |
|
10760 |
return false;
|
10761 |
}
|
10762 |
|
10763 |
+
if (!function_exists('sucuri_set_lastlogin')) {
|
10764 |
/**
|
10765 |
* Add a new user session to the list of last user logins.
|
10766 |
*
|
10767 |
* @param string $user_login The name of the user account involved in the operation.
|
10768 |
* @return void
|
10769 |
*/
|
10770 |
+
function sucuriscan_set_lastlogin($user_login = '')
|
10771 |
+
{
|
10772 |
$datastore_filepath = sucuriscan_lastlogins_datastore_is_writable();
|
10773 |
|
10774 |
+
if ($datastore_filepath) {
|
10775 |
+
$current_user = get_user_by('login', $user_login);
|
10776 |
$remote_addr = SucuriScan::get_remote_addr();
|
10777 |
|
10778 |
$login_info = array(
|
10779 |
'user_id' => $current_user->ID,
|
10780 |
'user_login' => $current_user->user_login,
|
10781 |
'user_remoteaddr' => $remote_addr,
|
10782 |
+
'user_hostname' => @gethostbyaddr($remote_addr),
|
10783 |
+
'user_lastlogin' => current_time('mysql')
|
10784 |
);
|
10785 |
|
10786 |
+
@file_put_contents($datastore_filepath, json_encode($login_info)."\n", FILE_APPEND);
|
10787 |
}
|
10788 |
}
|
10789 |
+
add_action('wp_login', 'sucuriscan_set_lastlogin', 50);
|
10790 |
}
|
10791 |
|
10792 |
/**
|
10800 |
* @param integer $user_id Optional user identifier to filter the results.
|
10801 |
* @return array The list of all the user logins, and total of entries registered.
|
10802 |
*/
|
10803 |
+
function sucuriscan_get_logins($limit = 10, $offset = 0, $user_id = 0)
|
10804 |
+
{
|
10805 |
$datastore_filepath = sucuriscan_lastlogins_datastore_is_readable();
|
10806 |
$last_logins = array(
|
10807 |
'total' => 0,
|
10808 |
'entries' => array(),
|
10809 |
);
|
10810 |
|
10811 |
+
if ($datastore_filepath) {
|
10812 |
$parsed_lines = 0;
|
10813 |
+
$data_lines = SucuriScanFileInfo::file_lines($datastore_filepath);
|
10814 |
|
10815 |
+
if ($data_lines) {
|
10816 |
/**
|
10817 |
* This count will not be 100% accurate considering that we are checking the
|
10818 |
* syntax of each line in the loop bellow, there may be some lines without the
|
10821 |
*
|
10822 |
* @var integer
|
10823 |
*/
|
10824 |
+
$total_lines = count($data_lines);
|
10825 |
$last_logins['total'] = $total_lines;
|
10826 |
|
10827 |
// Get a list with the latest entries in the first positions.
|
10828 |
+
$reversed_lines = array_reverse($data_lines);
|
10829 |
|
10830 |
/**
|
10831 |
* Only the user accounts with administrative privileges can see the logs of all
|
10834 |
* @var object
|
10835 |
*/
|
10836 |
$current_user = wp_get_current_user();
|
10837 |
+
$is_admin_user = (bool) current_user_can('manage_options');
|
10838 |
|
10839 |
+
for ($i = $offset; $i < $total_lines; $i++) {
|
10840 |
+
$line = $reversed_lines[$i] ? trim($reversed_lines[$i]) : '';
|
10841 |
|
10842 |
// Check if the data is serialized (which we will consider as insecure).
|
10843 |
+
if (SucuriScan::is_serialized($line)) {
|
10844 |
+
$last_login = false; /* Do not unserialize; is unsafe. */
|
10845 |
} else {
|
10846 |
+
$last_login = @json_decode($line, true);
|
10847 |
}
|
10848 |
|
10849 |
+
if ($last_login) {
|
10850 |
+
$last_login['user_lastlogin_timestamp'] = strtotime($last_login['user_lastlogin']);
|
10851 |
$last_login['user_registered_timestamp'] = 0;
|
10852 |
|
10853 |
// Only administrators can see all login stats.
|
10854 |
+
if (!$is_admin_user && $current_user->user_login != $last_login['user_login']) {
|
10855 |
continue;
|
10856 |
}
|
10857 |
|
10858 |
// Filter the user identifiers using the value passed tot his function.
|
10859 |
+
if ($user_id > 0 && $last_login['user_id'] != $user_id) {
|
10860 |
continue;
|
10861 |
}
|
10862 |
|
10863 |
// Get the WP_User object and add extra information from the last-login data.
|
10864 |
$last_login['user_exists'] = false;
|
10865 |
+
$user_account = get_userdata($last_login['user_id']);
|
10866 |
|
10867 |
+
if ($user_account) {
|
10868 |
$last_login['user_exists'] = true;
|
10869 |
|
10870 |
+
foreach ($user_account->data as $var_name => $var_value) {
|
10871 |
$last_login[ $var_name ] = $var_value;
|
10872 |
|
10873 |
+
if ($var_name == 'user_registered') {
|
10874 |
+
$last_login['user_registered_timestamp'] = strtotime($var_value);
|
10875 |
}
|
10876 |
}
|
10877 |
}
|
10883 |
$last_logins['total'] -= 1;
|
10884 |
}
|
10885 |
|
10886 |
+
if (@preg_match('/^[0-9]+$/', $limit) && $limit > 0) {
|
10887 |
+
if ($parsed_lines >= $limit) {
|
10888 |
break;
|
10889 |
}
|
10890 |
}
|
10895 |
return $last_logins;
|
10896 |
}
|
10897 |
|
10898 |
+
if (!function_exists('sucuri_login_redirect')) {
|
10899 |
/**
|
10900 |
* Hook for the wp-login action to redirect the user to a specific URL after
|
10901 |
* his successfully login to the administrator interface.
|
10905 |
* @param boolean $user WordPress user object with the information of the account involved in the operation.
|
10906 |
* @return string URL where the browser must be redirected to.
|
10907 |
*/
|
10908 |
+
function sucuriscan_login_redirect($redirect_to = '', $request = null, $user = false)
|
10909 |
+
{
|
10910 |
+
$login_url = !empty($redirect_to) ? $redirect_to : SucuriScan::admin_url();
|
10911 |
|
10912 |
+
if ($user instanceof WP_User
|
10913 |
+
&& in_array('administrator', $user->roles)
|
10914 |
+
&& SucuriScanOption::is_enabled(':lastlogin_redirection')
|
|
|
10915 |
) {
|
10916 |
+
$login_url = add_query_arg('sucuriscan_lastlogin', 1, $login_url);
|
10917 |
}
|
10918 |
|
10919 |
return $login_url;
|
10920 |
}
|
10921 |
|
10922 |
+
if (SucuriScanOption::is_enabled(':lastlogin_redirection')) {
|
10923 |
+
add_filter('login_redirect', 'sucuriscan_login_redirect', 10, 3);
|
10924 |
}
|
10925 |
}
|
10926 |
|
10927 |
+
if (!function_exists('sucuri_get_user_lastlogin')) {
|
10928 |
/**
|
10929 |
* Display the last user login at the top of the admin interface.
|
10930 |
*
|
10931 |
* @return void
|
10932 |
*/
|
10933 |
+
function sucuriscan_get_user_lastlogin()
|
10934 |
+
{
|
10935 |
+
if (current_user_can('manage_options')
|
10936 |
+
&& SucuriScanRequest::get(':lastlogin', '1')
|
10937 |
) {
|
10938 |
$current_user = wp_get_current_user();
|
10939 |
|
10940 |
// Select the penultimate entry, not the last one.
|
10941 |
+
$last_logins = sucuriscan_get_logins(2, 0, $current_user->ID);
|
10942 |
|
10943 |
+
if (isset($last_logins['entries'][1])) {
|
10944 |
$row = $last_logins['entries'][1];
|
10945 |
+
$page_url = SucuriScanTemplate::getUrl('lastlogins');
|
10946 |
+
$message = sprintf(
|
10947 |
+
'Last login was at <b>%s</b> from <b>%s</b> <em>(%s)</em>',
|
10948 |
+
SucuriScan::datetime($row->user_lastlogin_timestamp),
|
10949 |
+
SucuriScan::escape($row->user_remoteaddr),
|
10950 |
+
SucuriScan::escape($row->user_hostname)
|
10951 |
);
|
10952 |
+
$message .= "\x20(<a href='" . $page_url . "'>view all logs</a>)";
|
10953 |
+
SucuriScanInterface::info($message);
|
10954 |
}
|
10955 |
}
|
10956 |
}
|
10957 |
|
10958 |
+
add_action('admin_notices', 'sucuriscan_get_user_lastlogin');
|
10959 |
}
|
10960 |
|
10961 |
/**
|
10963 |
*
|
10964 |
* @return string The HTML code displaying a list of all the users logged in at the moment.
|
10965 |
*/
|
10966 |
+
function sucuriscan_loggedin_users_panel()
|
10967 |
+
{
|
10968 |
// Get user logged in list.
|
10969 |
+
$params = array(
|
10970 |
'LoggedInUsers.List' => '',
|
10971 |
'LoggedInUsers.Total' => 0,
|
10972 |
);
|
10973 |
|
10974 |
+
$logged_in_users = sucuriscan_get_online_users(true);
|
10975 |
|
10976 |
+
if (is_array($logged_in_users) && !empty($logged_in_users)) {
|
10977 |
+
$params['LoggedInUsers.Total'] = count($logged_in_users);
|
10978 |
$counter = 0;
|
10979 |
|
10980 |
+
foreach ((array) $logged_in_users as $logged_in_user) {
|
10981 |
+
$counter++;
|
10982 |
+
$logged_in_user['last_activity_datetime'] = SucuriScan::datetime($logged_in_user['last_activity']);
|
10983 |
+
$logged_in_user['user_registered_datetime'] = SucuriScan::datetime(strtotime($logged_in_user['user_registered']));
|
10984 |
+
|
10985 |
+
$params['LoggedInUsers.List'] .= SucuriScanTemplate::getSnippet(
|
10986 |
+
'lastlogins-loggedin',
|
10987 |
+
array(
|
10988 |
+
'LoggedInUsers.Id' => $logged_in_user['user_id'],
|
10989 |
+
'LoggedInUsers.UserURL' => SucuriScan::admin_url('user-edit.php?user_id=' . $logged_in_user['user_id']),
|
10990 |
+
'LoggedInUsers.UserLogin' => $logged_in_user['user_login'],
|
10991 |
+
'LoggedInUsers.UserEmail' => $logged_in_user['user_email'],
|
10992 |
+
'LoggedInUsers.LastActivity' => $logged_in_user['last_activity_datetime'],
|
10993 |
+
'LoggedInUsers.Registered' => $logged_in_user['user_registered_datetime'],
|
10994 |
+
'LoggedInUsers.RemoveAddr' => $logged_in_user['remote_addr'],
|
10995 |
+
'LoggedInUsers.CssClass' => ($counter % 2 === 0) ? '' : 'alternate',
|
10996 |
+
)
|
10997 |
+
);
|
10998 |
}
|
10999 |
}
|
11000 |
|
11001 |
+
return SucuriScanTemplate::getSection('lastlogins-loggedin', $params);
|
11002 |
}
|
11003 |
|
11004 |
/**
|
11007 |
* @param boolean $add_current_user Whether the current user should be added to the list or not.
|
11008 |
* @return array List of registered users currently in session.
|
11009 |
*/
|
11010 |
+
function sucuriscan_get_online_users($add_current_user = false)
|
11011 |
+
{
|
11012 |
$users = array();
|
11013 |
|
11014 |
+
if (SucuriScan::is_multisite()) {
|
11015 |
+
$users = get_site_transient('online_users');
|
11016 |
} else {
|
11017 |
+
$users = get_transient('online_users');
|
11018 |
}
|
11019 |
|
11020 |
// If not online users but current user is logged in, add it to the list.
|
11021 |
+
if (empty($users) && $add_current_user) {
|
11022 |
$current_user = wp_get_current_user();
|
11023 |
|
11024 |
+
if ($current_user->ID > 0) {
|
11025 |
+
sucuriscan_set_online_user($current_user->user_login, $current_user);
|
11026 |
|
11027 |
return sucuriscan_get_online_users();
|
11028 |
}
|
11039 |
* @param array $logged_in_users List of registered users currently in session.
|
11040 |
* @return boolean Either TRUE or FALSE representing the success or fail of the operation.
|
11041 |
*/
|
11042 |
+
function sucuriscan_save_online_users($logged_in_users = array())
|
11043 |
+
{
|
11044 |
$expiration = 30 * 60;
|
11045 |
|
11046 |
+
if (SucuriScan::is_multisite()) {
|
11047 |
+
return set_site_transient('online_users', $logged_in_users, $expiration);
|
11048 |
} else {
|
11049 |
+
return set_transient('online_users', $logged_in_users, $expiration);
|
11050 |
}
|
11051 |
}
|
11052 |
|
11053 |
+
if (!function_exists('sucuriscan_unset_online_user_on_logout')) {
|
11054 |
/**
|
11055 |
* Remove a logged in user from the list of registered users in session when
|
11056 |
* the logout page is requested.
|
11057 |
*
|
11058 |
* @return void
|
11059 |
*/
|
11060 |
+
function sucuriscan_unset_online_user_on_logout()
|
11061 |
+
{
|
11062 |
$remote_addr = SucuriScan::get_remote_addr();
|
11063 |
$current_user = wp_get_current_user();
|
11064 |
$user_id = $current_user->ID;
|
11065 |
|
11066 |
+
sucuriscan_unset_online_user($user_id, $remote_addr);
|
11067 |
}
|
11068 |
|
11069 |
+
add_action('wp_logout', 'sucuriscan_unset_online_user_on_logout');
|
11070 |
}
|
11071 |
|
11072 |
/**
|
11077 |
* @param integer $remote_addr IP address of the computer where the user logged in.
|
11078 |
* @return boolean Either TRUE or FALSE representing the success or fail of the operation.
|
11079 |
*/
|
11080 |
+
function sucuriscan_unset_online_user($user_id = 0, $remote_addr = 0)
|
11081 |
+
{
|
11082 |
$logged_in_users = sucuriscan_get_online_users();
|
11083 |
|
11084 |
// Remove the specified user identifier from the list.
|
11085 |
+
if (is_array($logged_in_users) && !empty($logged_in_users)) {
|
11086 |
+
foreach ($logged_in_users as $i => $user) {
|
11087 |
+
if ($user['user_id'] == $user_id
|
11088 |
+
&& strcmp($user['remote_addr'], $remote_addr) == 0
|
|
|
11089 |
) {
|
11090 |
unset($logged_in_users[ $i ]);
|
11091 |
break;
|
11093 |
}
|
11094 |
}
|
11095 |
|
11096 |
+
return sucuriscan_save_online_users($logged_in_users);
|
11097 |
}
|
11098 |
|
11099 |
+
if (!function_exists('sucuriscan_set_online_user')) {
|
11100 |
/**
|
11101 |
* Add an user account to the list of registered users in session.
|
11102 |
*
|
11104 |
* @param boolean $user The WordPress object containing all the information associated to the user.
|
11105 |
* @return void
|
11106 |
*/
|
11107 |
+
function sucuriscan_set_online_user($user_login = '', $user = false)
|
11108 |
+
{
|
11109 |
+
if ($user) {
|
11110 |
// Get logged in user information.
|
11111 |
$current_user = ($user instanceof WP_User) ? $user : wp_get_current_user();
|
11112 |
$current_user_id = $current_user->ID;
|
11113 |
$remote_addr = SucuriScan::get_remote_addr();
|
11114 |
+
$current_time = current_time('timestamp');
|
11115 |
$logged_in_users = sucuriscan_get_online_users();
|
11116 |
|
11117 |
// Build the dataset array that will be stored in the transient variable.
|
11124 |
'remote_addr' => $remote_addr,
|
11125 |
);
|
11126 |
|
11127 |
+
if (!is_array($logged_in_users) || empty($logged_in_users)) {
|
11128 |
$logged_in_users = array( $current_user_info );
|
11129 |
+
sucuriscan_save_online_users($logged_in_users);
|
11130 |
} else {
|
11131 |
$do_nothing = false;
|
11132 |
$update_existing = false;
|
11133 |
$item_index = 0;
|
11134 |
|
11135 |
// Check if the user is already in the logged-in-user list and update it if is necessary.
|
11136 |
+
foreach ($logged_in_users as $i => $user) {
|
11137 |
+
if ($user['user_id'] == $current_user_id
|
11138 |
+
&& strcmp($user['remote_addr'], $remote_addr) == 0
|
|
|
11139 |
) {
|
11140 |
+
if ($user['last_activity'] < ($current_time - (15 * 60))) {
|
11141 |
$update_existing = true;
|
11142 |
$item_index = $i;
|
11143 |
break;
|
11148 |
}
|
11149 |
}
|
11150 |
|
11151 |
+
if ($update_existing) {
|
11152 |
$logged_in_users[ $item_index ] = $current_user_info;
|
11153 |
+
sucuriscan_save_online_users($logged_in_users);
|
11154 |
+
} elseif ($do_nothing) {
|
11155 |
// Do nothing.
|
11156 |
} else {
|
11157 |
$logged_in_users[] = $current_user_info;
|
11158 |
+
sucuriscan_save_online_users($logged_in_users);
|
11159 |
}
|
11160 |
}
|
11161 |
}
|
11162 |
}
|
11163 |
|
11164 |
+
add_action('wp_login', 'sucuriscan_set_online_user', 10, 2);
|
11165 |
}
|
11166 |
|
11167 |
/**
|
11169 |
*
|
11170 |
* @return string A list with the failed logins occurred during the last hour.
|
11171 |
*/
|
11172 |
+
function sucuriscan_failed_logins_panel()
|
11173 |
+
{
|
11174 |
$template_variables = array(
|
11175 |
'FailedLogins.List' => '',
|
11176 |
'FailedLogins.Total' => '',
|
11183 |
);
|
11184 |
|
11185 |
// Define variables for the pagination.
|
11186 |
+
$page_number = SucuriScanTemplate::pageNumber();
|
11187 |
$max_per_page = SUCURISCAN_MAX_PAGINATION_BUTTONS;
|
11188 |
+
$page_offset = ($page_number - 1) * $max_per_page;
|
11189 |
+
$page_limit = ($page_offset + $max_per_page);
|
11190 |
|
11191 |
+
$max_failed_logins = SucuriScanOption::get_option(':maximum_failed_logins');
|
11192 |
+
$notify_bruteforce_attack = SucuriScanOption::get_option(':notify_bruteforce_attack');
|
11193 |
$failed_logins = sucuriscan_get_failed_logins();
|
11194 |
+
$old_failed_logins = sucuriscan_get_failed_logins(true);
|
11195 |
|
11196 |
// Merge the new and old failed logins.
|
11197 |
+
if (is_array($old_failed_logins) && !empty($old_failed_logins)) {
|
11198 |
+
if (is_array($failed_logins) && !empty($failed_logins)) {
|
11199 |
+
$failed_logins = array_merge($failed_logins, $old_failed_logins);
|
|
|
|
|
|
|
|
|
|
|
|
|
11200 |
} else {
|
11201 |
$failed_logins = $old_failed_logins;
|
11202 |
}
|
11203 |
}
|
11204 |
|
11205 |
+
if ($failed_logins) {
|
11206 |
$counter = 0;
|
11207 |
|
11208 |
+
for ($key = $page_offset; $key < $page_limit; $key++) {
|
11209 |
+
if (array_key_exists($key, $failed_logins['entries'])) {
|
11210 |
$login_data = $failed_logins['entries'][ $key ];
|
11211 |
$css_class = ( $counter % 2 == 0 ) ? '' : 'alternate';
|
11212 |
+
$wrong_user_password = 'hidden';
|
11213 |
+
$wrong_user_password_color = 'default';
|
11214 |
|
11215 |
+
if (sucuriscan_collect_wrong_passwords() === true) {
|
11216 |
+
if (isset($login_data['user_password']) && !empty($login_data['user_password'])) {
|
11217 |
+
$wrong_user_password = $login_data['user_password'];
|
11218 |
+
$wrong_user_password_color = 'none';
|
|
|
|
|
11219 |
} else {
|
11220 |
+
$wrong_user_password = 'empty';
|
11221 |
+
$wrong_user_password_color = 'info';
|
11222 |
}
|
11223 |
}
|
11224 |
|
11225 |
+
$template_variables['FailedLogins.List'] .= SucuriScanTemplate::getSnippet(
|
11226 |
+
'lastlogins-failedlogins',
|
11227 |
+
array(
|
11228 |
+
'FailedLogins.CssClass' => $css_class,
|
11229 |
+
'FailedLogins.Num' => $login_data['attempt_count'],
|
11230 |
+
'FailedLogins.Username' => $login_data['user_login'],
|
11231 |
+
'FailedLogins.RemoteAddr' => $login_data['remote_addr'],
|
11232 |
+
'FailedLogins.UserAgent' => $login_data['user_agent'],
|
11233 |
+
'FailedLogins.Password' => $wrong_user_password,
|
11234 |
+
'FailedLogins.PasswordColor' => $wrong_user_password_color,
|
11235 |
+
'FailedLogins.Datetime' => SucuriScan::datetime($login_data['attempt_time']),
|
11236 |
+
)
|
11237 |
+
);
|
11238 |
+
$counter++;
|
11239 |
}
|
11240 |
}
|
11241 |
|
11242 |
+
if ($counter > 0) {
|
11243 |
$template_variables['FailedLogins.NoItemsVisibility'] = 'hidden';
|
11244 |
}
|
11245 |
|
11246 |
+
$template_variables['FailedLogins.PaginationLinks'] = SucuriScanTemplate::pagination(
|
11247 |
'%%SUCURI.URL.Lastlogins%%#failed-logins',
|
11248 |
$failed_logins['count'],
|
11249 |
$max_per_page
|
11250 |
);
|
11251 |
|
11252 |
+
if ($failed_logins['count'] > $max_per_page) {
|
11253 |
$template_variables['FailedLogins.PaginationVisibility'] = 'visible';
|
11254 |
}
|
11255 |
}
|
11256 |
|
11257 |
$template_variables['FailedLogins.MaxFailedLogins'] = $max_failed_logins;
|
11258 |
|
11259 |
+
if ($notify_bruteforce_attack == 'enabled') {
|
11260 |
$template_variables['FailedLogins.WarningVisibility'] = 'hidden';
|
11261 |
}
|
11262 |
|
11263 |
+
if (sucuriscan_collect_wrong_passwords() !== true) {
|
11264 |
$template_variables['FailedLogins.CollectPasswordsVisibility'] = 'hidden';
|
11265 |
}
|
11266 |
|
11267 |
+
return SucuriScanTemplate::getSection('lastlogins-failedlogins', $template_variables);
|
11268 |
}
|
11269 |
|
11270 |
/**
|
11272 |
*
|
11273 |
* @return boolean TRUE if the password must be collected, FALSE otherwise.
|
11274 |
*/
|
11275 |
+
function sucuriscan_collect_wrong_passwords()
|
11276 |
+
{
|
11277 |
+
return SucuriScanOption::is_enabled(':collect_wrong_passwords');
|
11278 |
}
|
11279 |
|
11280 |
/**
|
11289 |
* @param boolean $reset Whether the file will be resetted or not.
|
11290 |
* @return string The full (relative) path where the file is located.
|
11291 |
*/
|
11292 |
+
function sucuriscan_failed_logins_datastore_path($get_old_logs = false, $reset = false)
|
11293 |
+
{
|
11294 |
$file_name = $get_old_logs ? 'sucuri-oldfailedlogins.php' : 'sucuri-failedlogins.php';
|
11295 |
+
$datastore_path = SucuriScan::datastore_folder_path($file_name);
|
11296 |
$default_content = sucuriscan_failed_logins_default_content();
|
11297 |
|
11298 |
// Create the file if it does not exists.
|
11299 |
+
if (!file_exists($datastore_path) || $reset) {
|
11300 |
+
@file_put_contents($datastore_path, $default_content, LOCK_EX);
|
11301 |
}
|
11302 |
|
11303 |
// Return the datastore path if the file exists (or was created).
|
11304 |
+
if (file_exists($datastore_path) && is_readable($datastore_path)) {
|
|
|
|
|
|
|
11305 |
return $datastore_path;
|
11306 |
}
|
11307 |
|
11313 |
*
|
11314 |
* @return string Default content of the file.
|
11315 |
*/
|
11316 |
+
function sucuriscan_failed_logins_default_content()
|
11317 |
+
{
|
11318 |
$default_content = "<?php exit(0); ?>\n";
|
11319 |
|
11320 |
return $default_content;
|
11331 |
* @param boolean $get_old_logs Whether the old logs will be retrieved or not.
|
11332 |
* @return array Information and entries gathered from the failed logins datastore file.
|
11333 |
*/
|
11334 |
+
function sucuriscan_get_failed_logins($get_old_logs = false)
|
11335 |
+
{
|
11336 |
+
$datastore_path = sucuriscan_failed_logins_datastore_path($get_old_logs);
|
11337 |
$default_content = sucuriscan_failed_logins_default_content();
|
11338 |
+
$default_content_n = substr_count($default_content, "\n");
|
11339 |
|
11340 |
+
if ($datastore_path) {
|
11341 |
+
$lines = SucuriScanFileInfo::file_lines($datastore_path);
|
11342 |
|
11343 |
+
if ($lines) {
|
11344 |
$failed_logins = array(
|
11345 |
'count' => 0,
|
11346 |
'first_attempt' => 0,
|
11350 |
);
|
11351 |
|
11352 |
// Read and parse all the entries found in the datastore file.
|
11353 |
+
$offset = count($lines) - 1;
|
11354 |
|
11355 |
+
for ($key = $offset; $key >= 0; $key--) {
|
11356 |
+
$line = trim($lines[ $key ]);
|
11357 |
+
$login_data = @json_decode($line, true);
|
11358 |
|
11359 |
+
if (is_array($login_data)) {
|
11360 |
+
$login_data['attempt_date'] = date('r', $login_data['attempt_time']);
|
11361 |
$login_data['attempt_count'] = ( $key + 1 );
|
11362 |
|
11363 |
+
if (!$login_data['user_agent']) {
|
11364 |
$login_data['user_agent'] = 'Unknown';
|
11365 |
}
|
11366 |
|
11367 |
+
if (!isset($login_data['user_password'])) {
|
11368 |
$login_data['user_password'] = '';
|
11369 |
}
|
11370 |
|
11374 |
}
|
11375 |
|
11376 |
// Calculate the different time between the first and last attempt.
|
11377 |
+
if ($failed_logins['count'] > 0) {
|
11378 |
+
$z = abs($failed_logins['count'] - 1);
|
11379 |
$failed_logins['last_attempt'] = $failed_logins['entries'][ $z ]['attempt_time'];
|
11380 |
$failed_logins['first_attempt'] = $failed_logins['entries'][0]['attempt_time'];
|
11381 |
+
$failed_logins['diff_time'] = abs($failed_logins['last_attempt'] - $failed_logins['first_attempt']);
|
11382 |
|
11383 |
return $failed_logins;
|
11384 |
}
|
11398 |
* @param string $wrong_password Wrong password used during the supposed attack.
|
11399 |
* @return boolean Whether the information of the current failed login event was stored or not.
|
11400 |
*/
|
11401 |
+
function sucuriscan_log_failed_login($user_login = '', $wrong_password = '')
|
11402 |
+
{
|
11403 |
$datastore_path = sucuriscan_failed_logins_datastore_path();
|
11404 |
|
11405 |
// Do not collect wrong passwords if it is not necessary.
|
11406 |
+
if (sucuriscan_collect_wrong_passwords() !== true) {
|
11407 |
$wrong_password = '';
|
11408 |
}
|
11409 |
|
11410 |
+
if ($datastore_path) {
|
11411 |
$login_data = json_encode(array(
|
11412 |
'user_login' => $user_login,
|
11413 |
'user_password' => $wrong_password,
|
11416 |
'user_agent' => SucuriScan::get_user_agent(),
|
11417 |
));
|
11418 |
|
11419 |
+
$written = @file_put_contents(
|
11420 |
+
$datastore_path,
|
11421 |
+
$login_data . "\n",
|
11422 |
+
FILE_APPEND
|
11423 |
+
);
|
11424 |
|
11425 |
+
if ($written > 0) {
|
11426 |
+
return true;
|
11427 |
+
}
|
11428 |
}
|
11429 |
|
11430 |
return false;
|
11439 |
* @param array $failed_logins Information and entries gathered from the failed logins datastore file.
|
11440 |
* @return boolean Whether the report was sent via email or not.
|
11441 |
*/
|
11442 |
+
function sucuriscan_report_failed_logins($failed_logins = array())
|
11443 |
+
{
|
11444 |
+
if ($failed_logins && $failed_logins['count'] > 0) {
|
11445 |
$prettify_mails = SucuriScanMail::prettify_mails();
|
11446 |
$collect_wrong_passwords = sucuriscan_collect_wrong_passwords();
|
11447 |
$mail_content = '';
|
11448 |
|
11449 |
+
if ($prettify_mails) {
|
11450 |
$table_html = '<table border="1" cellspacing="0" cellpadding="0">';
|
11451 |
|
11452 |
// Add the table headers.
|
11454 |
$table_html .= '<tr>';
|
11455 |
$table_html .= '<th>Username</th>';
|
11456 |
|
11457 |
+
if ($collect_wrong_passwords === true) {
|
11458 |
$table_html .= '<th>Password</th>';
|
11459 |
}
|
11460 |
|
11467 |
$table_html .= '<tbody>';
|
11468 |
}
|
11469 |
|
11470 |
+
foreach ($failed_logins['entries'] as $login_data) {
|
11471 |
+
if ($prettify_mails) {
|
11472 |
$table_html .= '<tr>';
|
11473 |
+
$table_html .= '<td>' . esc_attr($login_data['user_login']) . '</td>';
|
11474 |
|
11475 |
+
if ($collect_wrong_passwords === true) {
|
11476 |
+
$table_html .= '<td>' . esc_attr($login_data['user_password']) . '</td>';
|
11477 |
}
|
11478 |
|
11479 |
+
$table_html .= '<td>' . esc_attr($login_data['remote_addr']) . '</td>';
|
11480 |
$table_html .= '<td>' . $login_data['attempt_time'] . '</td>';
|
11481 |
$table_html .= '<td>' . $login_data['attempt_date'] . '</td>';
|
11482 |
$table_html .= '</tr>';
|
11484 |
$mail_content .= "\n";
|
11485 |
$mail_content .= 'Username: ' . $login_data['user_login'] . "\n";
|
11486 |
|
11487 |
+
if ($collect_wrong_passwords === true) {
|
11488 |
$mail_content .= 'Password: ' . $login_data['user_password'] . "\n";
|
11489 |
}
|
11490 |
|
11494 |
}
|
11495 |
}
|
11496 |
|
11497 |
+
if ($prettify_mails) {
|
11498 |
$table_html .= '</tbody>';
|
11499 |
$table_html .= '</table>';
|
11500 |
$mail_content = $table_html;
|
11501 |
}
|
11502 |
|
11503 |
+
if (SucuriScanEvent::notify_event('bruteforce_attack', $mail_content)) {
|
11504 |
sucuriscan_reset_failed_logins();
|
11505 |
|
11506 |
return true;
|
11518 |
*
|
11519 |
* @return boolean Whether the datastore file was resetted or not.
|
11520 |
*/
|
11521 |
+
function sucuriscan_reset_failed_logins()
|
11522 |
+
{
|
11523 |
+
$datastore_path = SucuriScan::datastore_folder_path('sucuri-failedlogins.php');
|
11524 |
+
$datastore_backup_path = sucuriscan_failed_logins_datastore_path(true, false);
|
11525 |
$default_content = sucuriscan_failed_logins_default_content();
|
11526 |
+
$current_content = @file_get_contents($datastore_path);
|
11527 |
+
$current_content = str_replace($default_content, '', $current_content);
|
11528 |
|
11529 |
@file_put_contents(
|
11530 |
$datastore_backup_path,
|
11532 |
FILE_APPEND
|
11533 |
);
|
11534 |
|
11535 |
+
return (bool) sucuriscan_failed_logins_datastore_path(false, true);
|
11536 |
}
|
11537 |
|
11538 |
/**
|
11543 |
* @param boolean $page_nonce True if the nonce is valid, False otherwise.
|
11544 |
* @return void
|
11545 |
*/
|
11546 |
+
function sucuriscan_settings_form_submissions($page_nonce = null)
|
11547 |
+
{
|
11548 |
global $sucuriscan_schedule_allowed,
|
11549 |
$sucuriscan_interface_allowed,
|
11550 |
$sucuriscan_notify_options,
|
|
|
|
|
11551 |
$sucuriscan_email_subjects;
|
11552 |
|
11553 |
// Use this conditional to avoid double checking.
|
11554 |
+
if (is_null($page_nonce)) {
|
11555 |
$page_nonce = SucuriScanInterface::check_nonce();
|
11556 |
}
|
11557 |
|
11558 |
+
if ($page_nonce) {
|
11559 |
// Save API key after it was recovered by the administrator.
|
11560 |
+
if ($api_key = SucuriScanRequest::post(':manual_api_key')) {
|
11561 |
+
SucuriScanAPI::setPluginKey($api_key, true);
|
11562 |
SucuriScanEvent::schedule_task();
|
11563 |
+
SucuriScanEvent::report_info_event('Sucuri API key was added manually.');
|
11564 |
}
|
11565 |
|
11566 |
// Remove API key from the local storage.
|
11567 |
+
if (SucuriScanRequest::post(':remove_api_key') !== false) {
|
11568 |
+
SucuriScanAPI::setPluginKey('');
|
11569 |
+
wp_clear_scheduled_hook('sucuriscan_scheduled_scan');
|
11570 |
+
SucuriScanEvent::report_critical_event('Sucuri API key was deleted.');
|
11571 |
+
SucuriScanEvent::notify_event('plugin_change', 'Sucuri API key removed');
|
11572 |
}
|
11573 |
|
11574 |
// Enable or disable the filesystem scanner.
|
11575 |
+
if ($fs_scanner = SucuriScanRequest::post(':fs_scanner', '(en|dis)able')) {
|
11576 |
$action_d = $fs_scanner . 'd';
|
11577 |
$message = 'Main file system scanner was <code>' . $action_d . '</code>';
|
11578 |
|
11579 |
+
SucuriScanOption::update_option(':fs_scanner', $action_d);
|
11580 |
+
SucuriScanEvent::report_auto_event($message);
|
11581 |
+
SucuriScanEvent::notify_event('plugin_change', $message);
|
11582 |
+
SucuriScanInterface::info($message);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
11583 |
}
|
11584 |
|
11585 |
// Enable or disable the filesystem scanner for file integrity.
|
11586 |
+
if ($scan_checksums = SucuriScanRequest::post(':scan_checksums', '(en|dis)able')) {
|
11587 |
$action_d = $scan_checksums . 'd';
|
11588 |
$message = 'File system scanner for file integrity was <code>' . $action_d . '</code>';
|
11589 |
|
11590 |
+
SucuriScanOption::update_option(':scan_checksums', $action_d);
|
11591 |
+
SucuriScanEvent::report_auto_event($message);
|
11592 |
+
SucuriScanEvent::notify_event('plugin_change', $message);
|
11593 |
+
SucuriScanInterface::info($message);
|
11594 |
}
|
11595 |
|
11596 |
// Enable or disable the filesystem scanner for error logs.
|
11597 |
+
if ($ignore_scanning = SucuriScanRequest::post(':ignore_scanning', '(en|dis)able')) {
|
11598 |
$action_d = $ignore_scanning . 'd';
|
11599 |
$message = 'File system scanner rules to ignore directories was <code>' . $action_d . '</code>';
|
11600 |
|
11601 |
+
SucuriScanOption::update_option(':ignore_scanning', $action_d);
|
11602 |
+
SucuriScanEvent::report_auto_event($message);
|
11603 |
+
SucuriScanEvent::notify_event('plugin_change', $message);
|
11604 |
+
SucuriScanInterface::info($message);
|
11605 |
}
|
11606 |
|
11607 |
// Enable or disable the filesystem scanner for error logs.
|
11608 |
+
if ($scan_errorlogs = SucuriScanRequest::post(':scan_errorlogs', '(en|dis)able')) {
|
11609 |
$action_d = $scan_errorlogs . 'd';
|
11610 |
$message = 'File system scanner for error logs was <code>' . $action_d . '</code>';
|
11611 |
|
11612 |
+
SucuriScanOption::update_option(':scan_errorlogs', $action_d);
|
11613 |
+
SucuriScanEvent::report_auto_event($message);
|
11614 |
+
SucuriScanEvent::notify_event('plugin_change', $message);
|
11615 |
+
SucuriScanInterface::info($message);
|
11616 |
}
|
11617 |
|
11618 |
// Enable or disable the error logs parsing.
|
11619 |
+
if ($parse_errorlogs = SucuriScanRequest::post(':parse_errorlogs', '(en|dis)able')) {
|
11620 |
$action_d = $parse_errorlogs . 'd';
|
11621 |
$message = 'Analysis of main error log file was <code>' . $action_d . '</code>';
|
11622 |
|
11623 |
+
SucuriScanOption::update_option(':parse_errorlogs', $action_d);
|
11624 |
+
SucuriScanEvent::report_auto_event($message);
|
11625 |
+
SucuriScanEvent::notify_event('plugin_change', $message);
|
11626 |
+
SucuriScanInterface::info($message);
|
11627 |
}
|
11628 |
|
11629 |
// Enable or disable the SiteCheck scanner and the malware scan page.
|
11630 |
+
if ($sitecheck_scanner = SucuriScanRequest::post(':sitecheck_scanner', '(en|dis)able')) {
|
11631 |
$action_d = $sitecheck_scanner . 'd';
|
11632 |
$message = 'SiteCheck malware and blacklist scanner was <code>' . $action_d . '</code>';
|
11633 |
|
11634 |
+
SucuriScanOption::update_option(':sitecheck_scanner', $action_d);
|
11635 |
+
SucuriScanEvent::report_auto_event($message);
|
11636 |
+
SucuriScanEvent::notify_event('plugin_change', $message);
|
11637 |
+
SucuriScanInterface::info($message);
|
11638 |
}
|
11639 |
|
11640 |
// Modify the schedule of the filesystem scanner.
|
11641 |
+
if ($frequency = SucuriScanRequest::post(':scan_frequency')) {
|
11642 |
+
if (array_key_exists($frequency, $sucuriscan_schedule_allowed)) {
|
11643 |
+
SucuriScanOption::update_option(':scan_frequency', $frequency);
|
11644 |
+
wp_clear_scheduled_hook('sucuriscan_scheduled_scan');
|
11645 |
|
11646 |
+
if ($frequency != '_oneoff') {
|
11647 |
+
wp_schedule_event(time() + 10, $frequency, 'sucuriscan_scheduled_scan');
|
11648 |
}
|
11649 |
|
11650 |
+
$frequency_title = strtolower($sucuriscan_schedule_allowed[ $frequency ]);
|
11651 |
$message = 'File system scanning frequency set to <code>' . $frequency_title . '</code>';
|
11652 |
|
11653 |
+
SucuriScanEvent::report_info_event($message);
|
11654 |
+
SucuriScanEvent::notify_event('plugin_change', $message);
|
11655 |
+
SucuriScanInterface::info($message);
|
11656 |
}
|
11657 |
}
|
11658 |
|
11659 |
// Set the method (aka. interface) that will be used to scan the site.
|
11660 |
+
if ($interface = SucuriScanRequest::post(':scan_interface')) {
|
11661 |
+
$allowed_values = array_keys($sucuriscan_interface_allowed);
|
11662 |
|
11663 |
+
if (in_array($interface, $allowed_values)) {
|
11664 |
$message = 'File system scanning interface set to <code>' . $interface . '</code>';
|
11665 |
|
11666 |
+
SucuriScanOption::update_option(':scan_interface', $interface);
|
11667 |
+
SucuriScanEvent::report_info_event($message);
|
11668 |
+
SucuriScanEvent::notify_event('plugin_change', $message);
|
11669 |
+
SucuriScanInterface::info($message);
|
11670 |
}
|
11671 |
}
|
11672 |
|
11673 |
// Update the limit of error log lines to parse.
|
11674 |
+
if ($errorlogs_limit = SucuriScanRequest::post(':errorlogs_limit', '[0-9]+')) {
|
11675 |
+
if ($errorlogs_limit > 1000) {
|
11676 |
+
SucuriScanInterface::error('Analyze more than 1,000 lines will take too much time.');
|
11677 |
} else {
|
11678 |
+
SucuriScanOption::update_option(':errorlogs_limit', $errorlogs_limit);
|
11679 |
+
SucuriScanInterface::info('Analyze last <code>' . $errorlogs_limit . '</code> entries encountered in the error logs.');
|
11680 |
|
11681 |
+
if ($errorlogs_limit == 0) {
|
11682 |
+
SucuriScanOption::update_option(':parse_errorlogs', 'disabled');
|
11683 |
}
|
11684 |
}
|
11685 |
}
|
11686 |
|
11687 |
// Reset the plugin security logs.
|
11688 |
$allowed_log_files = '(integrity|lastlogins|failedlogins|sitecheck)';
|
11689 |
+
if ($reset_logfile = SucuriScanRequest::post(':reset_logfile', $allowed_log_files)) {
|
11690 |
$files_to_delete = array(
|
11691 |
'sucuri-' . $reset_logfile . '.php',
|
11692 |
'sucuri-old' . $reset_logfile . '.php',
|
11693 |
);
|
11694 |
|
11695 |
+
foreach ($files_to_delete as $log_filename) {
|
11696 |
+
$log_filepath = SucuriScan::datastore_folder_path($log_filename);
|
11697 |
|
11698 |
+
if (@unlink($log_filepath)) {
|
11699 |
+
$log_filename_simple = str_replace('.php', '', $log_filename);
|
11700 |
$message = 'Deleted security log <code>' . $log_filename_simple . '</code>';
|
11701 |
|
11702 |
+
SucuriScanEvent::report_debug_event($message);
|
11703 |
+
SucuriScanInterface::info($message);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
11704 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
11705 |
}
|
11706 |
}
|
11707 |
|
11708 |
// Ignore a new event for email notifications.
|
11709 |
+
if ($action = SucuriScanRequest::post(':ignorerule_action', '(add|remove)')) {
|
11710 |
+
$ignore_rule = SucuriScanRequest::post(':ignorerule');
|
11711 |
|
11712 |
+
if ($action == 'add') {
|
11713 |
+
if (SucuriScanOption::add_ignored_event($ignore_rule)) {
|
11714 |
+
SucuriScanInterface::info('Post-type ignored successfully.');
|
11715 |
+
SucuriScanEvent::report_warning_event('Changes in <code>' . $ignore_rule . '</code> post-type will be ignored');
|
11716 |
} else {
|
11717 |
+
SucuriScanInterface::error('The post-type is invalid or it may be already ignored.');
|
11718 |
}
|
11719 |
+
} elseif ($action == 'remove') {
|
11720 |
+
SucuriScanOption::remove_ignored_event($ignore_rule);
|
11721 |
+
SucuriScanInterface::info('Post-type removed from the list successfully.');
|
11722 |
+
SucuriScanEvent::report_notice_event('Changes in <code>' . $ignore_rule . '</code> post-type will not be ignored');
|
11723 |
}
|
11724 |
}
|
11725 |
|
11726 |
// Ignore a new directory path for the file system scans.
|
11727 |
+
if ($action = SucuriScanRequest::post(':ignorescanning_action', '(ignore|unignore)')) {
|
11728 |
+
$ignore_directories = SucuriScanRequest::post(':ignorescanning_dirs', '_array');
|
11729 |
+
$ignore_file = SucuriScanRequest::post(':ignorescanning_file');
|
11730 |
|
11731 |
+
if ($action == 'ignore') {
|
11732 |
// Target a single file path to be ignored.
|
11733 |
+
if ($ignore_file !== false) {
|
11734 |
$ignore_directories = array( $ignore_file );
|
11735 |
}
|
11736 |
|
11737 |
// Target a list of directories to be ignored.
|
11738 |
+
if (!empty($ignore_directories)) {
|
11739 |
$were_ignored = array();
|
11740 |
|
11741 |
+
foreach ($ignore_directories as $resource_path) {
|
11742 |
+
if (file_exists($resource_path)
|
11743 |
+
&& SucuriScanFSScanner::ignore_directory($resource_path)
|
|
|
11744 |
) {
|
11745 |
$were_ignored[] = $resource_path;
|
11746 |
}
|
11747 |
}
|
11748 |
|
11749 |
+
if (!empty($were_ignored)) {
|
11750 |
+
SucuriScanInterface::info('Items selected will be ignored in future scans.');
|
11751 |
+
SucuriScanEvent::report_warning_event(sprintf(
|
11752 |
'Resources will not be scanned: (multiple entries): %s',
|
11753 |
+
@implode(',', $ignore_directories)
|
11754 |
+
));
|
11755 |
}
|
11756 |
}
|
11757 |
+
} elseif ($action == 'unignore') {
|
11758 |
+
foreach ($ignore_directories as $directory_path) {
|
11759 |
+
SucuriScanFSScanner::unignore_directory($directory_path);
|
11760 |
}
|
11761 |
|
11762 |
+
SucuriScanInterface::info('Items selected will not be ignored anymore.');
|
11763 |
+
SucuriScanEvent::report_notice_event(sprintf(
|
11764 |
'Resources will be scanned: (multiple entries): %s',
|
11765 |
+
@implode(',', $ignore_directories)
|
11766 |
+
));
|
11767 |
}
|
11768 |
}
|
11769 |
|
11770 |
// Trust and IP address to ignore notifications for a subnet.
|
11771 |
+
if ($trust_ip = SucuriScanRequest::post(':trust_ip')) {
|
11772 |
+
if (SucuriScan::is_valid_ip($trust_ip)
|
11773 |
+
|| SucuriScan::is_valid_cidr($trust_ip)
|
|
|
11774 |
) {
|
11775 |
+
$cache = new SucuriScanCache('trustip');
|
11776 |
+
$ip_info = SucuriScan::get_ip_info($trust_ip);
|
11777 |
$ip_info['added_at'] = SucuriScan::local_time();
|
11778 |
+
$cache_key = md5($ip_info['remote_addr']);
|
11779 |
|
11780 |
+
if ($cache->exists($cache_key)) {
|
11781 |
+
SucuriScanInterface::error('The IP address specified was already trusted.');
|
11782 |
+
} elseif ($cache->add($cache_key, $ip_info)) {
|
11783 |
$message = 'Changes from <code>' . $trust_ip . '</code> will be ignored';
|
11784 |
|
11785 |
+
SucuriScanEvent::report_warning_event($message);
|
11786 |
+
SucuriScanInterface::info($message);
|
11787 |
} else {
|
11788 |
+
SucuriScanInterface::error('The new entry was not saved in the datastore file.');
|
11789 |
}
|
11790 |
}
|
11791 |
}
|
11792 |
|
11793 |
// Trust and IP address to ignore notifications for a subnet.
|
11794 |
+
if ($del_trust_ip = SucuriScanRequest::post(':del_trust_ip', '_array')) {
|
11795 |
+
$cache = new SucuriScanCache('trustip');
|
11796 |
|
11797 |
+
foreach ($del_trust_ip as $cache_key) {
|
11798 |
+
$cache->delete($cache_key);
|
11799 |
}
|
11800 |
|
11801 |
+
SucuriScanInterface::info('The IP addresses selected were deleted successfully.');
|
11802 |
}
|
11803 |
|
11804 |
// Update the settings for the heartbeat API.
|
11805 |
+
if ($heartbeat_status = SucuriScanRequest::post(':heartbeat_status')) {
|
11806 |
$statuses_allowed = SucuriScanHeartbeat::statuses_allowed();
|
11807 |
|
11808 |
+
if (array_key_exists($heartbeat_status, $statuses_allowed)) {
|
11809 |
$message = 'Heartbeat status set to <code>' . $heartbeat_status . '</code>';
|
11810 |
|
11811 |
+
SucuriScanOption::update_option(':heartbeat', $heartbeat_status);
|
11812 |
+
SucuriScanEvent::report_info_event($message);
|
11813 |
+
SucuriScanInterface::info($message);
|
11814 |
} else {
|
11815 |
+
SucuriScanInterface::error('Heartbeat status not allowed.');
|
11816 |
}
|
11817 |
}
|
11818 |
|
11819 |
// Update the value of the heartbeat pulse.
|
11820 |
+
if ($heartbeat_pulse = SucuriScanRequest::post(':heartbeat_pulse')) {
|
11821 |
$pulses_allowed = SucuriScanHeartbeat::pulses_allowed();
|
11822 |
|
11823 |
+
if (array_key_exists($heartbeat_pulse, $pulses_allowed)) {
|
11824 |
$message = 'Heartbeat pulse set to <code>' . $heartbeat_pulse . '</code> seconds.';
|
11825 |
|
11826 |
+
SucuriScanOption::update_option(':heartbeat_pulse', $heartbeat_pulse);
|
11827 |
+
SucuriScanEvent::report_info_event($message);
|
11828 |
+
SucuriScanInterface::info($message);
|
11829 |
} else {
|
11830 |
+
SucuriScanInterface::error('Heartbeat pulse not allowed.');
|
11831 |
}
|
11832 |
}
|
11833 |
|
11834 |
// Update the value of the heartbeat interval.
|
11835 |
+
if ($heartbeat_interval = SucuriScanRequest::post(':heartbeat_interval')) {
|
11836 |
$intervals_allowed = SucuriScanHeartbeat::intervals_allowed();
|
11837 |
|
11838 |
+
if (array_key_exists($heartbeat_interval, $intervals_allowed)) {
|
11839 |
$message = 'Heartbeat interval set to <code>' . $heartbeat_interval . '</code>';
|
11840 |
|
11841 |
+
SucuriScanOption::update_option(':heartbeat_interval', $heartbeat_interval);
|
11842 |
+
SucuriScanEvent::report_info_event($message);
|
11843 |
+
SucuriScanInterface::info($message);
|
11844 |
} else {
|
11845 |
+
SucuriScanInterface::error('Heartbeat interval not allowed.');
|
11846 |
}
|
11847 |
}
|
11848 |
|
11849 |
// Enable or disable the auto-start execution of heartbeat.
|
11850 |
+
if ($heartbeat_autostart = SucuriScanRequest::post(':heartbeat_autostart', '(en|dis)able')) {
|
11851 |
$action_d = $heartbeat_autostart . 'd';
|
11852 |
$message = 'Heartbeat auto-start was <code>' . $action_d . '</code>';
|
11853 |
|
11854 |
+
SucuriScanOption::update_option(':heartbeat_autostart', $action_d);
|
11855 |
+
SucuriScanEvent::report_info_event($message);
|
11856 |
+
SucuriScanInterface::info($message);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
11857 |
}
|
11858 |
}
|
11859 |
}
|
11860 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
11861 |
/**
|
11862 |
* Read and parse the content of the general settings template.
|
11863 |
*
|
11864 |
* @return string Parsed HTML code for the general settings panel.
|
11865 |
*/
|
11866 |
+
function sucuriscan_settings_general($nonce)
|
11867 |
+
{
|
11868 |
+
// Process all form submissions.
|
11869 |
+
sucuriscan_settings_form_submissions($nonce);
|
11870 |
|
11871 |
+
$params = array();
|
|
|
11872 |
|
11873 |
+
// Keep the reset options panel and form submission processor before anything else.
|
11874 |
+
$params['SettingsSection.ResetOptions'] = sucuriscan_settings_general_resetoptions($nonce);
|
11875 |
|
11876 |
+
// Build HTML code for the additional general settings panels.
|
11877 |
+
$params['SettingsSection.ApiKey'] = sucuriscan_settings_general_apikey($nonce);
|
11878 |
+
$params['SettingsSection.DataStorage'] = sucuriscan_settings_general_datastorage($nonce);
|
11879 |
+
$params['SettingsSection.ReverseProxy'] = sucuriscan_settings_general_reverseproxy($nonce);
|
11880 |
+
$params['SettingsSection.PasswordCollector'] = sucuriscan_settings_general_pwdcollector($nonce);
|
11881 |
+
$params['SettingsSection.IPDiscoverer'] = sucuriscan_settings_general_ipdiscoverer($nonce);
|
11882 |
+
$params['SettingsSection.CommentMonitor'] = sucuriscan_settings_general_commentmonitor($nonce);
|
11883 |
+
$params['SettingsSection.XhrMonitor'] = sucuriscan_settings_general_xhrmonitor($nonce);
|
11884 |
+
$params['SettingsSection.AuditLogStats'] = sucuriscan_settings_general_auditlogstats($nonce);
|
11885 |
+
$params['SettingsSection.Datetime'] = sucuriscan_settings_general_datetime($nonce);
|
11886 |
|
11887 |
+
sucuriscan_settings_general_adsvisibility($nonce);
|
|
|
|
|
11888 |
|
11889 |
+
return SucuriScanTemplate::getSection('settings-general', $params);
|
11890 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
11891 |
|
11892 |
+
function sucuriscan_settings_general_resetoptions($nonce)
|
11893 |
+
{
|
11894 |
+
// Reset all the plugin's options.
|
11895 |
+
if ($nonce && SucuriScanRequest::post(':reset_options') !== false) {
|
11896 |
+
$process = SucuriScanRequest::post(':process_form');
|
11897 |
|
11898 |
+
if (intval($process) === 1) {
|
11899 |
+
// Notify the event before the API key is removed.
|
11900 |
+
$message = 'Sucuri plugin options were reset';
|
11901 |
+
SucuriScanEvent::report_critical_event($message);
|
11902 |
+
SucuriScanEvent::notify_event('plugin_change', $message);
|
|
|
|
|
|
|
|
|
|
|
|
|
11903 |
|
11904 |
+
// Remove all plugin options from the database.
|
11905 |
+
SucuriScanOption::delete_plugin_options();
|
11906 |
|
11907 |
+
// Remove the scheduled tasks.
|
11908 |
+
wp_clear_scheduled_hook('sucuriscan_scheduled_scan');
|
|
|
11909 |
|
11910 |
+
// Remove all the local security logs.
|
11911 |
+
@unlink(SucuriScan::datastore_folder_path('.htaccess'));
|
11912 |
+
@unlink(SucuriScan::datastore_folder_path('index.html'));
|
11913 |
+
@unlink(SucuriScan::datastore_folder_path('sucuri-failedlogins.php'));
|
11914 |
+
@unlink(SucuriScan::datastore_folder_path('sucuri-integrity.php'));
|
11915 |
+
@unlink(SucuriScan::datastore_folder_path('sucuri-lastlogins.php'));
|
11916 |
+
@unlink(SucuriScan::datastore_folder_path('sucuri-oldfailedlogins.php'));
|
11917 |
+
@unlink(SucuriScan::datastore_folder_path('sucuri-plugindata.php'));
|
11918 |
+
@unlink(SucuriScan::datastore_folder_path('sucuri-sitecheck.php'));
|
11919 |
+
@unlink(SucuriScan::datastore_folder_path('sucuri-trustip.php'));
|
11920 |
+
@rmdir(SucuriScan::datastore_folder_path());
|
11921 |
|
11922 |
+
// Revert hardening of core directories (includes, content, uploads).
|
11923 |
+
SucuriScanHardening::dewhitelist('ms-files.php', 'wp-includes');
|
11924 |
+
SucuriScanHardening::dewhitelist('wp-tinymce.php', 'wp-includes');
|
11925 |
+
SucuriScanHardening::unharden_directory(ABSPATH . '/wp-includes');
|
11926 |
+
SucuriScanHardening::unharden_directory(WP_CONTENT_DIR . '/uploads');
|
11927 |
+
SucuriScanHardening::unharden_directory(WP_CONTENT_DIR);
|
11928 |
|
11929 |
+
SucuriScanInterface::info('Plugin options, core directory hardening, and security logs were reset');
|
11930 |
+
} else {
|
11931 |
+
SucuriScanInterface::error('You need to confirm that you understand the risk of this operation.');
|
11932 |
+
}
|
|
|
11933 |
}
|
11934 |
|
11935 |
+
return SucuriScanTemplate::getSection('settings-general-resetoptions');
|
11936 |
}
|
11937 |
|
11938 |
function sucuriscan_settings_general_apikey($nonce)
|
11952 |
|
11953 |
if ($user_obj !== false && user_can($user_obj, 'administrator')) {
|
11954 |
// Send request to generate new API key or display form to set manually.
|
11955 |
+
if (SucuriScanAPI::registerSite($user_obj->user_email)) {
|
11956 |
+
$api_registered_modal = SucuriScanTemplate::getModal(
|
11957 |
'settings-apiregistered',
|
11958 |
array(
|
11959 |
'Title' => 'Site registered successfully',
|
11968 |
|
11969 |
// Recover API key through the email registered previously.
|
11970 |
if (SucuriScanRequest::post(':recover_key') !== false) {
|
11971 |
+
SucuriScanAPI::recoverKey();
|
11972 |
SucuriScanEvent::report_info_event('Recovery of the Sucuri API key was requested.');
|
11973 |
+
$api_recovery_modal = SucuriScanTemplate::getModal(
|
11974 |
'settings-apirecovery',
|
11975 |
array(
|
11976 |
'Title' => 'Plugin API Key Recovery',
|
11980 |
}
|
11981 |
}
|
11982 |
|
11983 |
+
$api_key = SucuriScanAPI::getPluginKey();
|
11984 |
|
11985 |
// Check whether the domain name is valid or not.
|
11986 |
if (!$api_key) {
|
11989 |
$invalid_domain = (bool) ($domain_address === $clean_domain);
|
11990 |
}
|
11991 |
|
11992 |
+
$params['APIKey'] = (!$api_key ? '(not set)' : $api_key);
|
11993 |
$params['APIKey.RecoverVisibility'] = SucuriScanTemplate::visibility(!$api_key && !$display_manual_key_form);
|
11994 |
$params['APIKey.ManualKeyFormVisibility'] = SucuriScanTemplate::visibility($display_manual_key_form);
|
11995 |
$params['APIKey.RemoveVisibility'] = SucuriScanTemplate::visibility((bool) $api_key);
|
11997 |
$params['ModalWhenAPIRegistered'] = $api_registered_modal;
|
11998 |
$params['ModalForApiKeyRecovery'] = $api_recovery_modal;
|
11999 |
|
12000 |
+
return SucuriScanTemplate::getSection('settings-general-apikey', $params);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
12001 |
}
|
12002 |
|
12003 |
function sucuriscan_settings_general_datastorage($nonce)
|
12045 |
|
12046 |
$params['DatastorePath'] = SucuriScanOption::get_option(':datastore_path');
|
12047 |
|
12048 |
+
return SucuriScanTemplate::getSection('settings-general-datastorage', $params);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
12049 |
}
|
12050 |
|
12051 |
function sucuriscan_settings_general_reverseproxy($nonce)
|
12062 |
$revproxy = SucuriScanRequest::post(':revproxy', '(en|dis)able');
|
12063 |
|
12064 |
if ($revproxy) {
|
12065 |
+
if ($revproxy === 'enable') {
|
12066 |
+
SucuriScanOption::setRevProxy('enable');
|
12067 |
+
SucuriScanOption::setAddrHeader('HTTP_X_SUCURI_CLIENTIP');
|
12068 |
+
} else {
|
12069 |
+
SucuriScanOption::setRevProxy('disable');
|
12070 |
+
SucuriScanOption::setAddrHeader('REMOTE_ADDR');
|
12071 |
+
}
|
12072 |
}
|
12073 |
}
|
12074 |
|
12079 |
$params['ReverseProxySwitchCssClass'] = 'button-success';
|
12080 |
}
|
12081 |
|
12082 |
+
return SucuriScanTemplate::getSection('settings-general-reverseproxy', $params);
|
12083 |
}
|
12084 |
|
12085 |
function sucuriscan_settings_general_pwdcollector($nonce)
|
12122 |
$params['PwdCollectorSwitchCssClass'] = 'button-danger';
|
12123 |
}
|
12124 |
|
12125 |
+
return SucuriScanTemplate::getSection('settings-general-pwdcollector', $params);
|
12126 |
}
|
12127 |
|
12128 |
function sucuriscan_settings_general_ipdiscoverer($nonce)
|
12135 |
'WebsiteURL' => 'Unknown',
|
12136 |
'RemoteAddress' => '127.0.0.1',
|
12137 |
'RemoteAddressHeader' => 'INVALID',
|
12138 |
+
'AddrHeaderOptions' => '',
|
12139 |
/* Switch form information. */
|
12140 |
'DnsLookupsStatus' => 'Enabled',
|
12141 |
'DnsLookupsSwitchText' => 'Disable',
|
12143 |
'DnsLookupsSwitchCssClass' => 'button-danger',
|
12144 |
);
|
12145 |
|
12146 |
+
// Get main HTTP header for IP retrieval.
|
12147 |
+
$allowed_headers = SucuriScan::allowedHttpHeaders(true);
|
12148 |
+
|
12149 |
// Configure the DNS lookups option for reverse proxy detection.
|
12150 |
if ($nonce) {
|
12151 |
$dns_lookups = SucuriScanRequest::post(':dns_lookups', '(en|dis)able');
|
12152 |
+
$addr_header = SucuriScanRequest::post(':addr_header');
|
12153 |
|
12154 |
if ($dns_lookups) {
|
12155 |
$action_d = $dns_lookups . 'd';
|
12160 |
SucuriScanEvent::notify_event('plugin_change', $message);
|
12161 |
SucuriScanInterface::info($message);
|
12162 |
}
|
12163 |
+
|
12164 |
+
if ($addr_header) {
|
12165 |
+
if ($addr_header === 'REMOTE_ADDR') {
|
12166 |
+
SucuriScanOption::setAddrHeader('REMOTE_ADDR');
|
12167 |
+
SucuriScanOption::setRevProxy('disable');
|
12168 |
+
} else {
|
12169 |
+
SucuriScanOption::setAddrHeader($addr_header);
|
12170 |
+
SucuriScanOption::setRevProxy('enable');
|
12171 |
+
}
|
12172 |
+
}
|
12173 |
}
|
12174 |
|
12175 |
if (SucuriScanOption::is_disabled(':dns_lookups')) {
|
12189 |
$params['RemoteAddressHeader'] = SucuriScan::get_remote_addr_header();
|
12190 |
$params['RemoteAddress'] = SucuriScan::get_remote_addr();
|
12191 |
$params['WebsiteURL'] = SucuriScan::get_domain();
|
12192 |
+
$params['AddrHeaderOptions'] = SucuriScanTemplate::selectOptions(
|
12193 |
+
$allowed_headers,
|
12194 |
+
SucuriScanOption::get_option(':addr_header')
|
12195 |
+
);
|
12196 |
|
12197 |
if ($base_domain !== $proxy_info['http_host']) {
|
12198 |
$params['TopLevelDomain'] = sprintf('%s (%s)', $params['TopLevelDomain'], $base_domain);
|
12199 |
}
|
12200 |
|
12201 |
+
return SucuriScanTemplate::getSection('settings-general-ipdiscoverer', $params);
|
12202 |
}
|
12203 |
|
12204 |
function sucuriscan_settings_general_commentmonitor($nonce)
|
12232 |
$params['CommentMonitorSwitchCssClass'] = 'button-success';
|
12233 |
}
|
12234 |
|
12235 |
+
return SucuriScanTemplate::getSection('settings-general-commentmonitor', $params);
|
12236 |
}
|
12237 |
|
12238 |
function sucuriscan_settings_general_xhrmonitor($nonce)
|
12266 |
$params['XhrMonitorSwitchCssClass'] = 'button-success';
|
12267 |
}
|
12268 |
|
12269 |
+
return SucuriScanTemplate::getSection('settings-general-xhrmonitor', $params);
|
12270 |
}
|
12271 |
|
12272 |
+
function sucuriscan_settings_general_auditlogstats($nonce)
|
12273 |
{
|
12274 |
+
$params = array();
|
12275 |
+
$params['AuditLogStats.StatusNum'] = '1';
|
12276 |
+
$params['AuditLogStats.Status'] = 'Enabled';
|
12277 |
+
$params['AuditLogStats.SwitchText'] = 'Disable';
|
12278 |
+
$params['AuditLogStats.SwitchValue'] = 'disable';
|
12279 |
+
$params['AuditLogStats.SwitchCssClass'] = 'button-danger';
|
12280 |
+
$params['AuditLogStats.Limit'] = 0;
|
12281 |
|
12282 |
+
if ($nonce) {
|
12283 |
+
// Update the limit for audit logs report.
|
12284 |
+
if ($logs4report = SucuriScanRequest::post(':logs4report', '[0-9]{1,4}')) {
|
12285 |
+
$_POST['sucuriscan_audit_report'] = 'enable';
|
12286 |
+
$message = 'Audit log statistics limit set to <code>' . $logs4report . '</code>';
|
12287 |
|
12288 |
+
SucuriScanOption::update_option(':logs4report', $logs4report);
|
12289 |
SucuriScanEvent::report_info_event($message);
|
12290 |
+
SucuriScanEvent::notify_event('plugin_change', $message);
|
12291 |
SucuriScanInterface::info($message);
|
12292 |
}
|
|
|
|
|
12293 |
|
12294 |
+
// Enable or disable the audit logs report.
|
12295 |
+
if ($audit_report = SucuriScanRequest::post(':audit_report', '(en|dis)able')) {
|
12296 |
+
$action_d = $audit_report . 'd';
|
12297 |
+
$message = 'Audit log statistics were <code>' . $action_d . '</code>';
|
|
|
12298 |
|
12299 |
+
SucuriScanOption::update_option(':audit_report', $action_d);
|
12300 |
+
SucuriScanEvent::report_info_event($message);
|
|
|
|
|
12301 |
SucuriScanEvent::notify_event('plugin_change', $message);
|
12302 |
+
SucuriScanInterface::info($message);
|
12303 |
+
}
|
12304 |
+
}
|
12305 |
|
12306 |
+
$logs4report = SucuriScanOption::get_option(':logs4report');
|
12307 |
+
$audit_report = SucuriScanOption::get_option(':audit_report');
|
12308 |
+
$params['AuditLogStats.Limit'] = SucuriScan::escape($logs4report);
|
12309 |
|
12310 |
+
if ($audit_report === 'disabled') {
|
12311 |
+
$params['AuditLogStats.StatusNum'] = '0';
|
12312 |
+
$params['AuditLogStats.Status'] = 'Disabled';
|
12313 |
+
$params['AuditLogStats.SwitchText'] = 'Enable';
|
12314 |
+
$params['AuditLogStats.SwitchValue'] = 'enable';
|
12315 |
+
$params['AuditLogStats.SwitchCssClass'] = 'button-success';
|
12316 |
+
}
|
12317 |
|
12318 |
+
return SucuriScanTemplate::getSection('settings-general-auditlogstats', $params);
|
12319 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
12320 |
|
12321 |
+
function sucuriscan_settings_general_datetime($nonce)
|
12322 |
+
{
|
12323 |
+
$params = array();
|
12324 |
+
$params['Datetime.AdminURL'] = SucuriScan::admin_url('options-general.php');
|
12325 |
+
$params['Datetime.HumanReadable'] = SucuriScan::current_datetime();
|
12326 |
+
$params['Datetime.Timestamp'] = SucuriScan::local_time();
|
12327 |
+
$params['Datetime.Timezone'] = 'Unknown';
|
12328 |
|
12329 |
+
if (function_exists('wp_timezone_choice')) {
|
12330 |
+
$gmt_offset = SucuriScanOption::get_option('gmt_offset');
|
12331 |
+
$tzstring = SucuriScanOption::get_option('timezone_string');
|
12332 |
+
|
12333 |
+
$params['Datetime.Timezone'] = empty($tzstring) ? 'UTC' . $gmt_offset : $tzstring;
|
12334 |
}
|
12335 |
|
12336 |
+
return SucuriScanTemplate::getSection('settings-general-datetime', $params);
|
12337 |
+
}
|
12338 |
+
|
12339 |
+
function sucuriscan_settings_general_adsvisibility($nonce)
|
12340 |
+
{
|
12341 |
+
// Update the advertisement visibility settings.
|
12342 |
+
if ($nonce) {
|
12343 |
+
$ads_visibility = SucuriScanRequest::post(':ads_visibility');
|
12344 |
+
|
12345 |
+
if ($ads_visibility === 'disable') {
|
12346 |
+
$option_value = $ads_visibility . 'd';
|
12347 |
+
$message = sprintf('Plugin advertisement set to <code>%s</code>', $option_value);
|
12348 |
+
|
12349 |
+
SucuriScanOption::update_option(':ads_visibility', $option_value);
|
12350 |
+
SucuriScanEvent::report_info_event($message);
|
12351 |
+
SucuriScanInterface::info($message);
|
12352 |
+
}
|
12353 |
+
}
|
12354 |
}
|
12355 |
|
12356 |
/**
|
12358 |
*
|
12359 |
* @return string Parsed HTML code for the scanner settings panel.
|
12360 |
*/
|
12361 |
+
function sucuriscan_settings_scanner()
|
12362 |
+
{
|
12363 |
global $sucuriscan_schedule_allowed,
|
12364 |
$sucuriscan_interface_allowed;
|
12365 |
|
12366 |
// Get initial variables to decide some things bellow.
|
12367 |
+
$fs_scanner = SucuriScanOption::get_option(':fs_scanner');
|
12368 |
+
$scan_freq = SucuriScanOption::get_option(':scan_frequency');
|
12369 |
+
$scan_interface = SucuriScanOption::get_option(':scan_interface');
|
12370 |
+
$scan_checksums = SucuriScanOption::get_option(':scan_checksums');
|
12371 |
+
$scan_errorlogs = SucuriScanOption::get_option(':scan_errorlogs');
|
12372 |
+
$parse_errorlogs = SucuriScanOption::get_option(':parse_errorlogs');
|
12373 |
+
$errorlogs_limit = SucuriScanOption::get_option(':errorlogs_limit');
|
12374 |
+
$ignore_scanning = SucuriScanOption::get_option(':ignore_scanning');
|
12375 |
+
$sitecheck_scanner = SucuriScanOption::get_option(':sitecheck_scanner');
|
12376 |
+
$sitecheck_counter = SucuriScanOption::get_option(':sitecheck_counter');
|
12377 |
+
$runtime_scan_human = SucuriScanFSScanner::get_filesystem_runtime(true);
|
|
|
12378 |
|
12379 |
// Get the file path of the security logs.
|
12380 |
+
$integrity_log_path = SucuriScan::datastore_folder_path('sucuri-integrity.php');
|
12381 |
+
$lastlogins_log_path = SucuriScan::datastore_folder_path('sucuri-lastlogins.php');
|
12382 |
+
$failedlogins_log_path = SucuriScan::datastore_folder_path('sucuri-failedlogins.php');
|
12383 |
+
$sitecheck_log_path = SucuriScan::datastore_folder_path('sucuri-sitecheck.php');
|
12384 |
|
12385 |
// Generate the HTML code for the option list in the form select fields.
|
12386 |
+
$scan_freq_options = SucuriScanTemplate::selectOptions($sucuriscan_schedule_allowed, $scan_freq);
|
12387 |
+
$scan_interface_options = SucuriScanTemplate::selectOptions($sucuriscan_interface_allowed, $scan_interface);
|
12388 |
|
12389 |
+
$params = array(
|
12390 |
/* Filesystem scanner */
|
12391 |
'FsScannerStatus' => 'Enabled',
|
12392 |
'FsScannerSwitchText' => 'Disable',
|
12393 |
'FsScannerSwitchValue' => 'disable',
|
12394 |
'FsScannerSwitchCssClass' => 'button-danger',
|
|
|
|
|
|
|
|
|
|
|
12395 |
/* Scan files checksum. */
|
12396 |
'ScanChecksumsStatus' => 'Enabled',
|
12397 |
'ScanChecksumsSwitchText' => 'Disable',
|
12432 |
'SiteCheckLogLife' => '0B',
|
12433 |
);
|
12434 |
|
12435 |
+
if ($fs_scanner == 'disabled') {
|
12436 |
+
$params['FsScannerStatus'] = 'Disabled';
|
12437 |
+
$params['FsScannerSwitchText'] = 'Enable';
|
12438 |
+
$params['FsScannerSwitchValue'] = 'enable';
|
12439 |
+
$params['FsScannerSwitchCssClass'] = 'button-success';
|
12440 |
}
|
12441 |
|
12442 |
+
if ($scan_checksums == 'disabled') {
|
12443 |
+
$params['ScanChecksumsStatus'] = 'Disabled';
|
12444 |
+
$params['ScanChecksumsSwitchText'] = 'Enable';
|
12445 |
+
$params['ScanChecksumsSwitchValue'] = 'enable';
|
12446 |
+
$params['ScanChecksumsSwitchCssClass'] = 'button-success';
|
12447 |
}
|
12448 |
|
12449 |
+
if ($ignore_scanning == 'disabled') {
|
12450 |
+
$params['IgnoreScanningStatus'] = 'Disabled';
|
12451 |
+
$params['IgnoreScanningSwitchText'] = 'Enable';
|
12452 |
+
$params['IgnoreScanningSwitchValue'] = 'enable';
|
12453 |
+
$params['IgnoreScanningSwitchCssClass'] = 'button-success';
|
12454 |
}
|
12455 |
|
12456 |
+
if ($scan_errorlogs == 'disabled') {
|
12457 |
+
$params['ScanErrorlogsStatus'] = 'Disabled';
|
12458 |
+
$params['ScanErrorlogsSwitchText'] = 'Enable';
|
12459 |
+
$params['ScanErrorlogsSwitchValue'] = 'enable';
|
12460 |
+
$params['ScanErrorlogsSwitchCssClass'] = 'button-success';
|
12461 |
}
|
12462 |
|
12463 |
+
if ($parse_errorlogs == 'disabled') {
|
12464 |
+
$params['ParseErrorLogsStatus'] = 'Disabled';
|
12465 |
+
$params['ParseErrorLogsSwitchText'] = 'Enable';
|
12466 |
+
$params['ParseErrorLogsSwitchValue'] = 'enable';
|
12467 |
+
$params['ParseErrorLogsSwitchCssClass'] = 'button-success';
|
12468 |
}
|
12469 |
|
12470 |
+
if ($sitecheck_scanner == 'disabled') {
|
12471 |
+
$params['SiteCheckScannerStatus'] = 'Disabled';
|
12472 |
+
$params['SiteCheckScannerSwitchText'] = 'Enable';
|
12473 |
+
$params['SiteCheckScannerSwitchValue'] = 'enable';
|
12474 |
+
$params['SiteCheckScannerSwitchCssClass'] = 'button-success';
|
12475 |
+
}
|
12476 |
+
|
12477 |
+
if (array_key_exists($scan_freq, $sucuriscan_schedule_allowed)) {
|
12478 |
+
$params['ScanningFrequency'] = $sucuriscan_schedule_allowed[ $scan_freq ];
|
12479 |
+
}
|
12480 |
+
|
12481 |
+
// Determine the age of the security log files.
|
12482 |
+
$params['IntegrityLogLife'] = SucuriScan::human_filesize(@filesize($integrity_log_path));
|
12483 |
+
$params['LastLoginLogLife'] = SucuriScan::human_filesize(@filesize($lastlogins_log_path));
|
12484 |
+
$params['FailedLoginLogLife'] = SucuriScan::human_filesize(@filesize($failedlogins_log_path));
|
12485 |
+
$params['SiteCheckLogLife'] = SucuriScan::human_filesize(@filesize($sitecheck_log_path));
|
12486 |
+
|
12487 |
+
return SucuriScanTemplate::getSection('settings-scanner', $params);
|
12488 |
+
}
|
12489 |
+
|
12490 |
+
function sucuriscan_settings_ignorescanning()
|
12491 |
+
{
|
12492 |
+
$params = array(
|
12493 |
+
'IgnoreScanning.ResourceList' => '',
|
12494 |
+
'IgnoreScanning.DisabledVisibility' => 'visible',
|
12495 |
+
'IgnoreScanning.NoItemsVisibility' => 'visible',
|
12496 |
+
);
|
12497 |
+
|
12498 |
+
$ignore_scanning = SucuriScanFSScanner::will_ignore_scanning();
|
12499 |
+
|
12500 |
+
// Allow disable of this option temporarily.
|
12501 |
+
if (SucuriScanRequest::get('no_scan') == 1) {
|
12502 |
+
$ignore_scanning = false;
|
12503 |
+
}
|
12504 |
+
|
12505 |
+
// Scan the project and get the ignored paths.
|
12506 |
+
if ($ignore_scanning === true) {
|
12507 |
+
$counter = 0;
|
12508 |
+
$params['IgnoreScanning.DisabledVisibility'] = 'hidden';
|
12509 |
+
$dir_list_list = SucuriScanFSScanner::get_ignored_directories_live();
|
12510 |
+
|
12511 |
+
foreach ($dir_list_list as $group => $dir_list) {
|
12512 |
+
foreach ($dir_list as $dir_data) {
|
12513 |
+
$valid_entry = false;
|
12514 |
+
$snippet_data = array(
|
12515 |
+
'IgnoreScanning.CssClass' => '',
|
12516 |
+
'IgnoreScanning.Directory' => '',
|
12517 |
+
'IgnoreScanning.DirectoryPath' => '',
|
12518 |
+
'IgnoreScanning.IgnoredAt' => '',
|
12519 |
+
'IgnoreScanning.IgnoredAtText' => 'ok',
|
12520 |
+
'IgnoreScanning.IgnoredCssClass' => 'success',
|
12521 |
+
);
|
12522 |
+
|
12523 |
+
if ($group == 'is_ignored') {
|
12524 |
+
$valid_entry = true;
|
12525 |
+
$snippet_data['IgnoreScanning.Directory'] = urlencode($dir_data['directory_path']);
|
12526 |
+
$snippet_data['IgnoreScanning.DirectoryPath'] = $dir_data['directory_path'];
|
12527 |
+
$snippet_data['IgnoreScanning.IgnoredAt'] = SucuriScan::datetime($dir_data['ignored_at']);
|
12528 |
+
$snippet_data['IgnoreScanning.IgnoredAtText'] = 'ignored';
|
12529 |
+
$snippet_data['IgnoreScanning.IgnoredCssClass'] = 'warning';
|
12530 |
+
} elseif ($group == 'is_not_ignored') {
|
12531 |
+
$valid_entry = true;
|
12532 |
+
$snippet_data['IgnoreScanning.Directory'] = urlencode($dir_data);
|
12533 |
+
$snippet_data['IgnoreScanning.DirectoryPath'] = $dir_data;
|
12534 |
+
}
|
12535 |
+
|
12536 |
+
if ($valid_entry) {
|
12537 |
+
$css_class = ( $counter % 2 == 0 ) ? '' : 'alternate';
|
12538 |
+
$snippet_data['IgnoreScanning.CssClass'] = $css_class;
|
12539 |
+
$params['IgnoreScanning.ResourceList'] .= SucuriScanTemplate::getSnippet(
|
12540 |
+
'settings-ignorescanning',
|
12541 |
+
$snippet_data
|
12542 |
+
);
|
12543 |
+
$counter++;
|
12544 |
+
}
|
12545 |
+
}
|
12546 |
+
}
|
12547 |
+
|
12548 |
+
if ($counter > 0) {
|
12549 |
+
$params['IgnoreScanning.NoItemsVisibility'] = 'hidden';
|
12550 |
+
}
|
12551 |
+
}
|
12552 |
+
|
12553 |
+
return SucuriScanTemplate::getSection('settings-ignorescanning', $params);
|
12554 |
+
}
|
12555 |
+
|
12556 |
+
/**
|
12557 |
+
* Read and parse the content of the notification settings template.
|
12558 |
+
*
|
12559 |
+
* @return string Parsed HTML code for the notification settings panel.
|
12560 |
+
*/
|
12561 |
+
function sucuriscan_settings_alert($nonce)
|
12562 |
+
{
|
12563 |
+
$params = array();
|
12564 |
+
|
12565 |
+
$params['AlertSettings.Recipients'] = sucuriscan_settings_alert_recipients($nonce);
|
12566 |
+
$params['AlertSettings.Subject'] = sucuriscan_settings_alert_subject($nonce);
|
12567 |
+
$params['AlertSettings.PerHour'] = sucuriscan_settings_alert_perhour($nonce);
|
12568 |
+
$params['AlertSettings.BruteForce'] = sucuriscan_settings_alert_bruteforce($nonce);
|
12569 |
+
$params['AlertSettings.Events'] = sucuriscan_settings_alert_events($nonce);
|
12570 |
+
|
12571 |
+
return SucuriScanTemplate::getSection('settings-alert', $params);
|
12572 |
+
}
|
12573 |
+
|
12574 |
+
function sucuriscan_settings_alert_recipients($nonce)
|
12575 |
+
{
|
12576 |
+
$params = array();
|
12577 |
+
$params['AlertSettings.Recipients'] = '';
|
12578 |
+
$notify_to = SucuriScanOption::get_option(':notify_to');
|
12579 |
+
$emails = array();
|
12580 |
+
|
12581 |
+
// If the recipient list is not empty, explode.
|
12582 |
+
if (is_string($notify_to)) {
|
12583 |
+
$emails = explode(',', $notify_to);
|
12584 |
+
}
|
12585 |
+
|
12586 |
+
// Process form submission.
|
12587 |
+
if ($nonce) {
|
12588 |
+
// Add new email address to the alert recipient list.
|
12589 |
+
if (SucuriScanRequest::post(':save_recipient') !== false) {
|
12590 |
+
$new_email = SucuriScanRequest::post(':recipient');
|
12591 |
+
|
12592 |
+
if (SucuriScan::is_valid_email($new_email)) {
|
12593 |
+
$emails[] = $new_email;
|
12594 |
+
$message = 'Sucuri will send email alerts to: <code>' . $new_email . '</code>';
|
12595 |
+
|
12596 |
+
SucuriScanOption::update_option(':notify_to', implode(',', $emails));
|
12597 |
+
SucuriScanEvent::report_info_event($message);
|
12598 |
+
SucuriScanEvent::notify_event('plugin_change', $message);
|
12599 |
+
SucuriScanInterface::info($message);
|
12600 |
+
} else {
|
12601 |
+
SucuriScanInterface::error('Email format not supported.');
|
12602 |
+
}
|
12603 |
+
}
|
12604 |
+
|
12605 |
+
// Delete one or more recipients from the list.
|
12606 |
+
if (SucuriScanRequest::post(':delete_recipients') !== false) {
|
12607 |
+
$deleted_emails = array();
|
12608 |
+
$recipients = SucuriScanRequest::post(':recipients', '_array');
|
12609 |
+
|
12610 |
+
foreach ($recipients as $address) {
|
12611 |
+
if (in_array($address, $emails)) {
|
12612 |
+
$deleted_emails[] = $address;
|
12613 |
+
$index = array_search($address, $emails);
|
12614 |
+
unset($emails[$index]);
|
12615 |
+
}
|
12616 |
+
}
|
12617 |
+
|
12618 |
+
if (!empty($deleted_emails)) {
|
12619 |
+
$deleted_emails_str = implode(",\x20", $deleted_emails);
|
12620 |
+
$message = 'Sucuri will not send email alerts to: <code>' . $deleted_emails_str . '</code>';
|
12621 |
+
|
12622 |
+
SucuriScanOption::update_option(':notify_to', implode(',', $emails));
|
12623 |
+
SucuriScanEvent::report_info_event($message);
|
12624 |
+
SucuriScanEvent::notify_event('plugin_change', $message);
|
12625 |
+
SucuriScanInterface::info($message);
|
12626 |
+
}
|
12627 |
+
}
|
12628 |
+
|
12629 |
+
// Debug ability of the plugin to send email alerts correctly.
|
12630 |
+
if (SucuriScanRequest::post(':debug_email')) {
|
12631 |
+
$recipients = SucuriScanOption::get_option(':notify_to');
|
12632 |
+
SucuriScanMail::send_mail(
|
12633 |
+
$recipients,
|
12634 |
+
'Test Email Alert',
|
12635 |
+
sprintf('Test email alert sent at %s', date('r')),
|
12636 |
+
array('Force' => true)
|
12637 |
+
);
|
12638 |
+
SucuriScanInterface::info('Test email alert sent, check your inbox.');
|
12639 |
+
}
|
12640 |
+
}
|
12641 |
+
|
12642 |
+
$counter = 0;
|
12643 |
+
|
12644 |
+
foreach ($emails as $email) {
|
12645 |
+
if (!empty($email)) {
|
12646 |
+
$css_class = ($counter % 2 === 0) ? '' : 'alternate';
|
12647 |
+
$params['AlertSettings.Recipients'] .= SucuriScanTemplate::getSnippet(
|
12648 |
+
'settings-alert-recipients',
|
12649 |
+
array(
|
12650 |
+
'Recipient.CssClass' => $css_class,
|
12651 |
+
'Recipient.Email' => $email,
|
12652 |
+
)
|
12653 |
+
);
|
12654 |
+
$counter++;
|
12655 |
+
}
|
12656 |
+
}
|
12657 |
+
|
12658 |
+
return SucuriScanTemplate::getSection('settings-alert-recipients', $params);
|
12659 |
+
}
|
12660 |
+
|
12661 |
+
function sucuriscan_settings_alert_subject($nonce)
|
12662 |
+
{
|
12663 |
+
global $sucuriscan_email_subjects;
|
12664 |
+
|
12665 |
+
$params = array(
|
12666 |
+
'AlertSettings.Subject' => '',
|
12667 |
+
'AlertSettings.CustomChecked' => '',
|
12668 |
+
'AlertSettings.CustomValue' => '',
|
12669 |
+
);
|
12670 |
+
|
12671 |
+
// Process form submission to change the alert settings.
|
12672 |
+
if ($nonce) {
|
12673 |
+
if ($email_subject = SucuriScanRequest::post(':email_subject')) {
|
12674 |
+
$current_value = SucuriScanOption::get_option(':email_subject');
|
12675 |
+
$new_email_subject = false;
|
12676 |
+
|
12677 |
+
/**
|
12678 |
+
* Validate the format of the email subject format.
|
12679 |
+
*
|
12680 |
+
* If the user chooses the option to build the subject of the email alerts
|
12681 |
+
* manually we will need to validate the characters. Otherwise we will need to
|
12682 |
+
* check if the pseudo-tags selected by the user are allowed and supported.
|
12683 |
+
*/
|
12684 |
+
if ($email_subject === 'custom') {
|
12685 |
+
$format_pattern = '/^[0-9a-zA-Z:,\s]+$/';
|
12686 |
+
$custom_subject = SucuriScanRequest::post(':custom_email_subject');
|
12687 |
+
|
12688 |
+
if ($custom_subject !== false
|
12689 |
+
&& !empty($custom_subject)
|
12690 |
+
&& @preg_match($format_pattern, $custom_subject)
|
12691 |
+
) {
|
12692 |
+
$new_email_subject = trim($custom_subject);
|
12693 |
+
} else {
|
12694 |
+
SucuriScanInterface::error('Invalid characters in the email subject.');
|
12695 |
+
}
|
12696 |
+
} elseif (is_array($sucuriscan_email_subjects)
|
12697 |
+
&& in_array($email_subject, $sucuriscan_email_subjects)
|
12698 |
+
) {
|
12699 |
+
$new_email_subject = trim($email_subject);
|
12700 |
+
}
|
12701 |
+
|
12702 |
+
// Proceed with the operation saving the new subject.
|
12703 |
+
if ($new_email_subject !== false
|
12704 |
+
&& $current_value !== $new_email_subject
|
12705 |
+
) {
|
12706 |
+
$message = 'Email subject set to <code>' . $new_email_subject . '</code>';
|
12707 |
+
|
12708 |
+
SucuriScanOption::update_option(':email_subject', $new_email_subject);
|
12709 |
+
SucuriScanEvent::report_info_event($message);
|
12710 |
+
SucuriScanEvent::notify_event('plugin_change', $message);
|
12711 |
+
SucuriScanInterface::info($message);
|
12712 |
+
}
|
12713 |
+
}
|
12714 |
+
}
|
12715 |
+
|
12716 |
+
// Build the HTML code for the interface.
|
12717 |
+
if (is_array($sucuriscan_email_subjects)) {
|
12718 |
+
$email_subject = SucuriScanOption::get_option(':email_subject');
|
12719 |
+
$is_official_subject = false;
|
12720 |
+
|
12721 |
+
foreach ($sucuriscan_email_subjects as $subject_format) {
|
12722 |
+
if ($email_subject === $subject_format) {
|
12723 |
+
$is_official_subject = true;
|
12724 |
+
$checked = 'checked="checked"';
|
12725 |
+
} else {
|
12726 |
+
$checked = '';
|
12727 |
+
}
|
12728 |
+
|
12729 |
+
$params['AlertSettings.Subject'] .= SucuriScanTemplate::getSnippet(
|
12730 |
+
'settings-alert-subject',
|
12731 |
+
array(
|
12732 |
+
'EmailSubject.Name' => $subject_format,
|
12733 |
+
'EmailSubject.Value' => $subject_format,
|
12734 |
+
'EmailSubject.Checked' => $checked,
|
12735 |
+
)
|
12736 |
+
);
|
12737 |
+
}
|
12738 |
+
|
12739 |
+
if ($is_official_subject === false) {
|
12740 |
+
$params['AlertSettings.CustomChecked'] = 'checked="checked"';
|
12741 |
+
$params['AlertSettings.CustomValue'] = $email_subject;
|
12742 |
+
}
|
12743 |
+
}
|
12744 |
+
|
12745 |
+
return SucuriScanTemplate::getSection('settings-alert-subject', $params);
|
12746 |
+
}
|
12747 |
+
|
12748 |
+
function sucuriscan_settings_alert_perhour($nonce)
|
12749 |
+
{
|
12750 |
+
global $sucuriscan_emails_per_hour;
|
12751 |
+
|
12752 |
+
$params = array();
|
12753 |
+
$params['AlertSettings.PerHour'] = '';
|
12754 |
+
|
12755 |
+
if ($nonce) {
|
12756 |
+
// Update the value for the maximum emails per hour.
|
12757 |
+
if ($per_hour = SucuriScanRequest::post(':emails_per_hour')) {
|
12758 |
+
if (array_key_exists($per_hour, $sucuriscan_emails_per_hour)) {
|
12759 |
+
$per_hour_label = strtolower($sucuriscan_emails_per_hour[$per_hour]);
|
12760 |
+
$message = 'Maximum alerts per hour set to <code>' . $per_hour_label . '</code>';
|
12761 |
+
|
12762 |
+
SucuriScanOption::update_option(':emails_per_hour', $per_hour);
|
12763 |
+
SucuriScanEvent::report_info_event($message);
|
12764 |
+
SucuriScanEvent::notify_event('plugin_change', $message);
|
12765 |
+
SucuriScanInterface::info($message);
|
12766 |
+
} else {
|
12767 |
+
SucuriScanInterface::error('Invalid value for the maximum emails per hour.');
|
12768 |
+
}
|
12769 |
+
}
|
12770 |
+
}
|
12771 |
+
|
12772 |
+
$per_hour = SucuriScanOption::get_option(':emails_per_hour');
|
12773 |
+
$per_hour_options = SucuriScanTemplate::selectOptions($sucuriscan_emails_per_hour, $per_hour);
|
12774 |
+
$params['AlertSettings.PerHour'] = $per_hour_options;
|
12775 |
+
|
12776 |
+
return SucuriScanTemplate::getSection('settings-alert-perhour', $params);
|
12777 |
+
}
|
12778 |
+
|
12779 |
+
function sucuriscan_settings_alert_bruteforce($nonce)
|
12780 |
+
{
|
12781 |
+
global $sucuriscan_maximum_failed_logins;
|
12782 |
+
|
12783 |
+
$params = array();
|
12784 |
+
$params['AlertSettings.BruteForce'] = '';
|
12785 |
+
|
12786 |
+
if ($nonce) {
|
12787 |
+
// Update the maximum failed logins per hour before consider it a brute-force attack.
|
12788 |
+
if ($maximum = SucuriScanRequest::post(':maximum_failed_logins')) {
|
12789 |
+
if (array_key_exists($maximum, $sucuriscan_maximum_failed_logins)) {
|
12790 |
+
$message = 'Consider brute-force attack after <code>' . $maximum . '</code> failed logins per hour';
|
12791 |
+
|
12792 |
+
SucuriScanOption::update_option(':maximum_failed_logins', $maximum);
|
12793 |
+
SucuriScanEvent::report_info_event($message);
|
12794 |
+
SucuriScanEvent::notify_event('plugin_change', $message);
|
12795 |
+
SucuriScanInterface::info($message);
|
12796 |
+
} else {
|
12797 |
+
SucuriScanInterface::error('Invalid value for the brute-force alerts.');
|
12798 |
+
}
|
12799 |
+
}
|
12800 |
+
}
|
12801 |
+
|
12802 |
+
$maximum = SucuriScanOption::get_option(':maximum_failed_logins');
|
12803 |
+
$maximum_options = SucuriScanTemplate::selectOptions($sucuriscan_maximum_failed_logins, $maximum);
|
12804 |
+
$params['AlertSettings.BruteForce'] = $maximum_options;
|
12805 |
+
|
12806 |
+
return SucuriScanTemplate::getSection('settings-alert-bruteforce', $params);
|
12807 |
+
}
|
12808 |
+
|
12809 |
+
function sucuriscan_settings_alert_events($nonce)
|
12810 |
+
{
|
12811 |
+
global $sucuriscan_notify_options;
|
12812 |
+
|
12813 |
+
$params = array();
|
12814 |
+
$params['AlertSettings.Events'] = '';
|
12815 |
+
|
12816 |
+
// Process form submission to change the alert settings.
|
12817 |
+
if ($nonce) {
|
12818 |
+
// Update the notification settings.
|
12819 |
+
if (SucuriScanRequest::post(':save_alert_events') !== false) {
|
12820 |
+
$ucounter = 0;
|
12821 |
+
|
12822 |
+
if (SucuriScanRequest::post(':notify_scan_checksums') == 1) {
|
12823 |
+
$_POST['sucuriscan_prettify_mails'] = '1';
|
12824 |
+
}
|
12825 |
+
|
12826 |
+
foreach ($sucuriscan_notify_options as $alert_type => $alert_label) {
|
12827 |
+
$option_value = SucuriScanRequest::post($alert_type, '(1|0)');
|
12828 |
+
|
12829 |
+
if ($option_value !== false) {
|
12830 |
+
$current_value = SucuriScanOption::get_option($alert_type);
|
12831 |
+
$option_value = ($option_value == 1) ? 'enabled' : 'disabled';
|
12832 |
+
|
12833 |
+
// Check that the option value was actually changed.
|
12834 |
+
if ($current_value !== $option_value) {
|
12835 |
+
SucuriScanOption::update_option($alert_type, $option_value);
|
12836 |
+
$ucounter += 1;
|
12837 |
+
}
|
12838 |
+
}
|
12839 |
+
}
|
12840 |
+
|
12841 |
+
if ($ucounter > 0) {
|
12842 |
+
$message = 'A total of ' . $ucounter . ' alert events were changed';
|
12843 |
+
|
12844 |
+
SucuriScanEvent::report_info_event($message);
|
12845 |
+
SucuriScanEvent::notify_event('plugin_change', $message);
|
12846 |
+
SucuriScanInterface::info($message);
|
12847 |
+
}
|
12848 |
+
}
|
12849 |
+
}
|
12850 |
+
|
12851 |
+
// Build the HTML code for the interface.
|
12852 |
+
if (is_array($sucuriscan_notify_options)) {
|
12853 |
+
$pattern = '/^([a-z]+:)?(.+)/';
|
12854 |
+
$counter = 0;
|
12855 |
+
|
12856 |
+
foreach ($sucuriscan_notify_options as $alert_type => $alert_label) {
|
12857 |
+
$alert_value = SucuriScanOption::get_option($alert_type);
|
12858 |
+
$checked = ($alert_value == 'enabled') ? 'checked="checked"' : '';
|
12859 |
+
$css_class = ($counter % 2 === 0) ? 'alternate' : '';
|
12860 |
+
$alert_icon = '';
|
12861 |
+
|
12862 |
+
if (@preg_match($pattern, $alert_label, $match)) {
|
12863 |
+
$alert_group = str_replace(':', '', $match[1]);
|
12864 |
+
$alert_label = $match[2];
|
12865 |
+
|
12866 |
+
switch ($alert_group) {
|
12867 |
+
case 'user':
|
12868 |
+
$alert_icon = 'dashicons-before dashicons-admin-users';
|
12869 |
+
break;
|
12870 |
+
case 'plugin':
|
12871 |
+
$alert_icon = 'dashicons-before dashicons-admin-plugins';
|
12872 |
+
break;
|
12873 |
+
case 'theme':
|
12874 |
+
$alert_icon = 'dashicons-before dashicons-admin-appearance';
|
12875 |
+
break;
|
12876 |
+
}
|
12877 |
+
}
|
12878 |
+
|
12879 |
+
$params['AlertSettings.Events'] .= SucuriScanTemplate::getSnippet(
|
12880 |
+
'settings-alert-events',
|
12881 |
+
array(
|
12882 |
+
'Event.CssClass' => $css_class,
|
12883 |
+
'Event.Name' => $alert_type,
|
12884 |
+
'Event.Checked' => $checked,
|
12885 |
+
'Event.Label' => $alert_label,
|
12886 |
+
'Event.LabelIcon' => $alert_icon,
|
12887 |
+
)
|
12888 |
+
);
|
12889 |
+
$counter++;
|
12890 |
+
}
|
12891 |
+
}
|
12892 |
+
|
12893 |
+
return SucuriScanTemplate::getSection('settings-alert-events', $params);
|
12894 |
+
}
|
12895 |
+
|
12896 |
+
function sucuriscan_settings_ignore_rules()
|
12897 |
+
{
|
12898 |
+
$notify_new_site_content = SucuriScanOption::get_option(':notify_post_publication');
|
12899 |
+
|
12900 |
+
$template_variables = array(
|
12901 |
+
'IgnoreRules.MessageVisibility' => 'visible',
|
12902 |
+
'IgnoreRules.TableVisibility' => 'hidden',
|
12903 |
+
'IgnoreRules.PostTypes' => '',
|
12904 |
+
);
|
12905 |
+
|
12906 |
+
if ($notify_new_site_content == 'enabled') {
|
12907 |
+
$post_types = get_post_types();
|
12908 |
+
$ignored_events = SucuriScanOption::get_ignored_events();
|
12909 |
+
|
12910 |
+
$template_variables['IgnoreRules.MessageVisibility'] = 'hidden';
|
12911 |
+
$template_variables['IgnoreRules.TableVisibility'] = 'visible';
|
12912 |
+
$counter = 0;
|
12913 |
+
|
12914 |
+
foreach ($post_types as $post_type => $post_type_object) {
|
12915 |
+
$counter++;
|
12916 |
+
$css_class = ($counter % 2 === 0) ? 'alternate' : '';
|
12917 |
+
$post_type_title = ucwords(str_replace('_', chr(32), $post_type));
|
12918 |
+
|
12919 |
+
if (array_key_exists($post_type, $ignored_events)) {
|
12920 |
+
$is_ignored_text = 'YES';
|
12921 |
+
$was_ignored_at = SucuriScan::datetime($ignored_events[ $post_type ]);
|
12922 |
+
$is_ignored_class = 'danger';
|
12923 |
+
$button_action = 'remove';
|
12924 |
+
$button_class = 'button-primary';
|
12925 |
+
$button_text = 'Allow';
|
12926 |
+
} else {
|
12927 |
+
$is_ignored_text = 'NO';
|
12928 |
+
$was_ignored_at = 'Not ignored';
|
12929 |
+
$is_ignored_class = 'success';
|
12930 |
+
$button_action = 'add';
|
12931 |
+
$button_class = 'button-primary button-danger';
|
12932 |
+
$button_text = 'Ignore';
|
12933 |
+
}
|
12934 |
+
|
12935 |
+
$template_variables['IgnoreRules.PostTypes'] .= SucuriScanTemplate::getSnippet(
|
12936 |
+
'settings-ignorerules',
|
12937 |
+
array(
|
12938 |
+
'IgnoreRules.CssClass' => $css_class,
|
12939 |
+
'IgnoreRules.Num' => $counter,
|
12940 |
+
'IgnoreRules.PostTypeTitle' => $post_type_title,
|
12941 |
+
'IgnoreRules.IsIgnored' => $is_ignored_text,
|
12942 |
+
'IgnoreRules.WasIgnoredAt' => $was_ignored_at,
|
12943 |
+
'IgnoreRules.IsIgnoredClass' => $is_ignored_class,
|
12944 |
+
'IgnoreRules.PostType' => $post_type,
|
12945 |
+
'IgnoreRules.Action' => $button_action,
|
12946 |
+
'IgnoreRules.ButtonClass' => 'button ' . $button_class,
|
12947 |
+
'IgnoreRules.ButtonText' => $button_text,
|
12948 |
+
)
|
12949 |
+
);
|
12950 |
+
}
|
12951 |
+
}
|
12952 |
+
|
12953 |
+
return SucuriScanTemplate::getSection('settings-ignorerules', $template_variables);
|
12954 |
+
}
|
12955 |
+
|
12956 |
+
/**
|
12957 |
+
* Read and parse the content of the API service settings template.
|
12958 |
+
*
|
12959 |
+
* @return string Parsed HTML code for the API service settings panel.
|
12960 |
+
*/
|
12961 |
+
function sucuriscan_settings_apiservice($nonce)
|
12962 |
+
{
|
12963 |
+
$params = array();
|
12964 |
+
|
12965 |
+
$params['SettingsSection.ApiStatus'] = sucuriscan_settings_apiservice_status($nonce);
|
12966 |
+
$params['SettingsSection.ApiProxy'] = sucuriscan_settings_apiservice_proxy($nonce);
|
12967 |
+
$params['SettingsSection.ApiSSL'] = sucuriscan_settings_apiservice_ssl($nonce);
|
12968 |
+
$params['SettingsSection.ApiTimeout'] = sucuriscan_settings_apiservice_timeout($nonce);
|
12969 |
+
|
12970 |
+
return SucuriScanTemplate::getSection('settings-apiservice', $params);
|
12971 |
+
}
|
12972 |
+
|
12973 |
+
function sucuriscan_settings_apiservice_status($nonce)
|
12974 |
+
{
|
12975 |
+
$params = array();
|
12976 |
+
$params['ApiStatus.StatusNum'] = '1';
|
12977 |
+
$params['ApiStatus.Status'] = 'Enabled';
|
12978 |
+
$params['ApiStatus.SwitchText'] = 'Disable';
|
12979 |
+
$params['ApiStatus.SwitchValue'] = 'disable';
|
12980 |
+
$params['ApiStatus.SwitchCssClass'] = 'button-danger';
|
12981 |
+
$params['ApiStatus.WarningVisibility'] = 'visible';
|
12982 |
+
$params['ApiStatus.ErrorVisibility'] = 'hidden';
|
12983 |
+
|
12984 |
+
if ($nonce) {
|
12985 |
+
// Enable or disable the API service communication.
|
12986 |
+
if ($api_service = SucuriScanRequest::post(':api_service', '(en|dis)able')) {
|
12987 |
+
$action_d = $api_service . 'd';
|
12988 |
+
$message = 'API service communication was <code>' . $action_d . '</code>';
|
12989 |
+
|
12990 |
+
SucuriScanEvent::report_info_event($message);
|
12991 |
+
SucuriScanEvent::notify_event('plugin_change', $message);
|
12992 |
+
SucuriScanOption::update_option(':api_service', $action_d);
|
12993 |
+
SucuriScanInterface::info($message);
|
12994 |
+
}
|
12995 |
+
}
|
12996 |
+
|
12997 |
+
$api_service = SucuriScanOption::get_option(':api_service');
|
12998 |
+
|
12999 |
+
if ($api_service === 'disabled') {
|
13000 |
+
$params['ApiStatus.StatusNum'] = '0';
|
13001 |
+
$params['ApiStatus.Status'] = 'Disabled';
|
13002 |
+
$params['ApiStatus.SwitchText'] = 'Enable';
|
13003 |
+
$params['ApiStatus.SwitchValue'] = 'enable';
|
13004 |
+
$params['ApiStatus.SwitchCssClass'] = 'button-success';
|
13005 |
+
$params['ApiStatus.WarningVisibility'] = 'hidden';
|
13006 |
+
$params['ApiStatus.ErrorVisibility'] = 'visible';
|
13007 |
+
}
|
13008 |
+
|
13009 |
+
return SucuriScanTemplate::getSection('settings-apiservice-status', $params);
|
13010 |
+
}
|
13011 |
+
|
13012 |
+
function sucuriscan_settings_apiservice_proxy($nonce)
|
13013 |
+
{
|
13014 |
+
$params = array(
|
13015 |
+
'APIProxy.Host' => 'no_proxy_host',
|
13016 |
+
'APIProxy.Port' => 'no_proxy_port',
|
13017 |
+
'APIProxy.Username' => 'no_proxy_username',
|
13018 |
+
'APIProxy.Password' => 'no_proxy_password',
|
13019 |
+
'APIProxy.PasswordType' => 'default',
|
13020 |
+
'APIProxy.PasswordText' => 'empty',
|
13021 |
+
);
|
13022 |
+
|
13023 |
+
if (class_exists('WP_HTTP_Proxy')) {
|
13024 |
+
$wp_http_proxy = new WP_HTTP_Proxy();
|
13025 |
+
|
13026 |
+
if ($wp_http_proxy->is_enabled()) {
|
13027 |
+
$proxy_host = SucuriScan::escape($wp_http_proxy->host());
|
13028 |
+
$proxy_port = SucuriScan::escape($wp_http_proxy->port());
|
13029 |
+
$proxy_username = SucuriScan::escape($wp_http_proxy->username());
|
13030 |
+
$proxy_password = SucuriScan::escape($wp_http_proxy->password());
|
13031 |
|
13032 |
+
$params['APIProxy.Host'] = $proxy_host;
|
13033 |
+
$params['APIProxy.Port'] = $proxy_port;
|
13034 |
+
$params['APIProxy.Username'] = $proxy_username;
|
13035 |
+
$params['APIProxy.Password'] = $proxy_password;
|
13036 |
+
$params['APIProxy.PasswordType'] = 'info';
|
13037 |
+
$params['APIProxy.PasswordText'] = 'hidden';
|
13038 |
|
13039 |
+
}
|
|
|
13040 |
}
|
13041 |
|
13042 |
+
return SucuriScanTemplate::getSection('settings-apiservice-proxy', $params);
|
|
|
|
|
|
|
|
|
|
|
|
|
13043 |
}
|
13044 |
|
13045 |
+
function sucuriscan_settings_apiservice_ssl($nonce)
|
13046 |
+
{
|
13047 |
+
global $sucuriscan_verify_ssl_cert;
|
|
|
|
|
|
|
|
|
|
|
13048 |
|
13049 |
+
$params = array(
|
13050 |
+
'VerifySSLCert' => 'Undefined',
|
13051 |
+
'VerifySSLCertCssClass' => 0,
|
13052 |
+
'VerifySSLCertOptions' => '',
|
|
|
|
|
13053 |
);
|
13054 |
|
13055 |
+
// Update the configuration for the SSL certificate verification.
|
13056 |
+
if ($nonce) {
|
13057 |
+
$verify_ssl_cert = SucuriScanRequest::post(':verify_ssl_cert');
|
13058 |
|
13059 |
+
if ($verify_ssl_cert) {
|
13060 |
+
if (array_key_exists($verify_ssl_cert, $sucuriscan_verify_ssl_cert)) {
|
13061 |
+
$message = 'SSL certificate verification for API calls set to <code>' . $verify_ssl_cert . '</code>';
|
13062 |
+
|
13063 |
+
SucuriScanOption::update_option(':verify_ssl_cert', $verify_ssl_cert);
|
13064 |
+
SucuriScanEvent::report_warning_event($message);
|
13065 |
+
SucuriScanEvent::notify_event('plugin_change', $message);
|
13066 |
+
SucuriScanInterface::info($message);
|
13067 |
} else {
|
13068 |
+
SucuriScanInterface::error('Invalid value for the SSL certificate verification.');
|
13069 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
13070 |
}
|
13071 |
+
}
|
13072 |
+
|
13073 |
+
$verify_ssl_cert = SucuriScanOption::get_option(':verify_ssl_cert');
|
13074 |
+
$params['VerifySSLCertOptions'] = SucuriScanTemplate::selectOptions(
|
13075 |
+
$sucuriscan_verify_ssl_cert,
|
13076 |
+
$verify_ssl_cert
|
13077 |
+
);
|
13078 |
|
13079 |
+
if (array_key_exists($verify_ssl_cert, $sucuriscan_verify_ssl_cert)) {
|
13080 |
+
$params['VerifySSLCert'] = $sucuriscan_verify_ssl_cert[$verify_ssl_cert];
|
13081 |
+
|
13082 |
+
if ($verify_ssl_cert === 'true') {
|
13083 |
+
$params['VerifySSLCertCssClass'] = 1;
|
13084 |
}
|
13085 |
}
|
13086 |
|
13087 |
+
return SucuriScanTemplate::getSection('settings-apiservice-ssl', $params);
|
13088 |
+
}
|
13089 |
+
|
13090 |
+
function sucuriscan_settings_apiservice_timeout($nonce)
|
13091 |
+
{
|
13092 |
+
$params = array();
|
13093 |
|
13094 |
+
// Update the API request timeout.
|
13095 |
+
if ($nonce) {
|
13096 |
+
$timeout = (int) SucuriScanRequest::post(':request_timeout', '[0-9]+');
|
|
|
|
|
13097 |
|
13098 |
+
if ($timeout > 0) {
|
13099 |
+
if ($timeout <= SUCURISCAN_MAX_REQUEST_TIMEOUT) {
|
13100 |
+
$message = 'API request timeout set to <code>' . $timeout . '</code> seconds.';
|
13101 |
|
13102 |
+
SucuriScanOption::update_option(':request_timeout', $timeout);
|
13103 |
+
SucuriScanEvent::report_info_event($message);
|
13104 |
+
SucuriScanEvent::notify_event('plugin_change', $message);
|
13105 |
+
SucuriScanInterface::info($message);
|
13106 |
+
} else {
|
13107 |
+
SucuriScanInterface::error('API request timeout in seconds is too high.');
|
13108 |
}
|
13109 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
13110 |
}
|
13111 |
|
13112 |
+
$params['MaxRequestTimeout'] = SUCURISCAN_MAX_REQUEST_TIMEOUT;
|
13113 |
+
$params['RequestTimeout'] = SucuriScanOption::get_option(':request_timeout') . ' seconds';
|
13114 |
+
|
13115 |
+
return SucuriScanTemplate::getSection('settings-apiservice-timeout', $params);
|
13116 |
}
|
13117 |
|
13118 |
/**
|
13119 |
+
* Read and parse the content of the self-hosting settings template.
|
13120 |
*
|
13121 |
+
* @return string Parsed HTML code for the self-hosting settings panel.
|
13122 |
*/
|
13123 |
+
function sucuriscan_settings_selfhosting($nonce)
|
13124 |
+
{
|
13125 |
+
$params = array();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
13126 |
|
13127 |
+
$params['SelfHosting.Monitor'] = sucuriscan_settings_selfhosting_monitor($nonce);
|
|
|
|
|
13128 |
|
13129 |
+
return SucuriScanTemplate::getSection('settings-selfhosting', $params);
|
13130 |
+
}
|
|
|
|
|
13131 |
|
13132 |
+
function sucuriscan_selfhosting_fpath()
|
13133 |
+
{
|
13134 |
+
$monitor = SucuriScanOption::get_option(':selfhosting_monitor');
|
13135 |
+
$monitor_fpath = SucuriScanOption::get_option(':selfhosting_fpath');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
13136 |
|
13137 |
+
if ($monitor === 'enabled'
|
13138 |
+
&& !empty($monitor_fpath)
|
13139 |
+
&& file_exists($monitor_fpath)
|
13140 |
+
&& is_writable($monitor_fpath)
|
13141 |
+
) {
|
13142 |
+
return $monitor_fpath;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
13143 |
}
|
13144 |
|
13145 |
+
return false;
|
13146 |
}
|
13147 |
|
13148 |
+
function sucuriscan_settings_selfhosting_monitor($nonce)
|
13149 |
+
{
|
13150 |
+
$params = array();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
13151 |
|
13152 |
+
$params['SelfHostingMonitor.DisabledVisibility'] = 'visible';
|
13153 |
+
$params['SelfHostingMonitor.Status'] = 'Enabled';
|
13154 |
+
$params['SelfHostingMonitor.SwitchText'] = 'Disable';
|
13155 |
+
$params['SelfHostingMonitor.SwitchValue'] = 'disable';
|
13156 |
+
$params['SelfHostingMonitor.SwitchCssClass'] = 'button-danger';
|
13157 |
+
$params['SelfHostingMonitor.FpathVisibility'] = 'hidden';
|
13158 |
+
$params['SelfHostingMonitor.Fpath'] = '';
|
13159 |
|
13160 |
+
if ($nonce) {
|
13161 |
+
// Set a file path for the self-hosted event monitor.
|
13162 |
+
$monitor_fpath = SucuriScanRequest::post(':selfhosting_fpath');
|
13163 |
|
13164 |
+
if ($monitor_fpath !== false) {
|
13165 |
+
if (empty($monitor_fpath)) {
|
13166 |
+
$message = 'Log exporter was disabled.';
|
13167 |
|
13168 |
+
SucuriScanEvent::report_info_event($message);
|
13169 |
+
SucuriScanOption::delete_option(':selfhosting_fpath');
|
13170 |
+
SucuriScanOption::update_option(':selfhosting_monitor', 'disabled');
|
13171 |
+
SucuriScanEvent::notify_event('plugin_change', $message);
|
13172 |
+
SucuriScanInterface::info($message);
|
13173 |
+
} elseif (strpos($monitor_fpath, $_SERVER['DOCUMENT_ROOT']) !== false) {
|
13174 |
+
SucuriScanInterface::error('File should not be publicly accessible.');
|
13175 |
+
} elseif (!file_exists($monitor_fpath)) {
|
13176 |
+
SucuriScanInterface::error('File path does not exists.');
|
13177 |
+
} elseif (!is_writable($monitor_fpath)) {
|
13178 |
+
SucuriScanInterface::error('File path is not writable.');
|
13179 |
+
} else {
|
13180 |
+
$message = 'Log exporter file path was set correctly.';
|
13181 |
|
13182 |
+
SucuriScanEvent::report_info_event($message);
|
13183 |
+
SucuriScanOption::update_option(':selfhosting_monitor', 'enabled');
|
13184 |
+
SucuriScanOption::update_option(':selfhosting_fpath', $monitor_fpath);
|
13185 |
+
SucuriScanEvent::notify_event('plugin_change', $message);
|
13186 |
+
SucuriScanInterface::info($message);
|
13187 |
+
}
|
|
|
|
|
13188 |
}
|
13189 |
+
}
|
13190 |
|
13191 |
+
$monitor = SucuriScanOption::get_option(':selfhosting_monitor');
|
13192 |
+
$monitor_fpath = SucuriScanOption::get_option(':selfhosting_fpath');
|
13193 |
+
|
13194 |
+
if ($monitor === 'disabled') {
|
13195 |
+
$params['SelfHostingMonitor.Status'] = 'Disabled';
|
13196 |
+
$params['SelfHostingMonitor.SwitchText'] = 'Enable';
|
13197 |
+
$params['SelfHostingMonitor.SwitchValue'] = 'enable';
|
13198 |
+
$params['SelfHostingMonitor.SwitchCssClass'] = 'button-success';
|
13199 |
+
}
|
13200 |
+
|
13201 |
+
if ($monitor === 'enabled' && $monitor_fpath) {
|
13202 |
+
$params['SelfHostingMonitor.DisabledVisibility'] = 'hidden';
|
13203 |
+
$params['SelfHostingMonitor.FpathVisibility'] = 'visible';
|
13204 |
+
$params['SelfHostingMonitor.Fpath'] = SucuriScan::escape($monitor_fpath);
|
13205 |
}
|
13206 |
|
13207 |
+
return SucuriScanTemplate::getSection('settings-selfhosting-monitor', $params);
|
13208 |
}
|
13209 |
|
13210 |
/**
|
13211 |
+
* Read and parse the content of the trust-ip settings template.
|
13212 |
*
|
13213 |
+
* @return string Parsed HTML code for the trust-ip settings panel.
|
13214 |
*/
|
13215 |
+
function sucuriscan_settings_trust_ip()
|
13216 |
+
{
|
13217 |
+
$params = array();
|
13218 |
+
$params['TrustedIPs.List'] = '';
|
13219 |
+
$params['TrustedIPs.NoItems.Visibility'] = 'visible';
|
|
|
|
|
|
|
13220 |
|
13221 |
+
$cache = new SucuriScanCache('trustip');
|
13222 |
+
$trusted_ips = $cache->getAll();
|
|
|
|
|
13223 |
|
13224 |
+
if ($trusted_ips) {
|
|
|
13225 |
$counter = 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
13226 |
|
13227 |
+
foreach ($trusted_ips as $cache_key => $ip_info) {
|
13228 |
+
$css_class = ($counter % 2 === 0) ? '' : 'alternate';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
13229 |
|
13230 |
+
if ($ip_info->cidr_range == 32) {
|
13231 |
+
$ip_info->cidr_format = 'n/a';
|
|
|
|
|
|
|
|
|
13232 |
}
|
13233 |
+
|
13234 |
+
$params['TrustedIPs.List'] .= SucuriScanTemplate::getSnippet(
|
13235 |
+
'settings-trustip',
|
13236 |
+
array(
|
13237 |
+
'TrustIP.CssClass' => $css_class,
|
13238 |
+
'TrustIP.CacheKey' => $cache_key,
|
13239 |
+
'TrustIP.RemoteAddr' => SucuriScan::escape($ip_info->remote_addr),
|
13240 |
+
'TrustIP.CIDRFormat' => SucuriScan::escape($ip_info->cidr_format),
|
13241 |
+
'TrustIP.AddedAt' => SucuriScan::datetime($ip_info->added_at),
|
13242 |
+
)
|
13243 |
+
);
|
13244 |
+
|
13245 |
+
$counter++;
|
13246 |
}
|
13247 |
|
13248 |
+
if ($counter > 0) {
|
13249 |
+
$params['TrustedIPs.NoItems.Visibility'] = 'hidden';
|
13250 |
}
|
13251 |
}
|
13252 |
|
13253 |
+
return SucuriScanTemplate::getSection('settings-trustip', $params);
|
13254 |
}
|
13255 |
|
13256 |
+
|
13257 |
/**
|
13258 |
* Read and parse the content of the heartbeat settings template.
|
13259 |
*
|
13260 |
* @return string Parsed HTML code for the heartbeat settings panel.
|
13261 |
*/
|
13262 |
+
function sucuriscan_settings_heartbeat()
|
13263 |
+
{
|
13264 |
// Current values set in the options table.
|
13265 |
+
$heartbeat_status = SucuriScanOption::get_option(':heartbeat');
|
13266 |
+
$heartbeat_pulse = SucuriScanOption::get_option(':heartbeat_pulse');
|
13267 |
+
$heartbeat_interval = SucuriScanOption::get_option(':heartbeat_interval');
|
13268 |
+
$heartbeat_autostart = SucuriScanOption::get_option(':heartbeat_autostart');
|
13269 |
|
13270 |
// Allowed values for each setting.
|
13271 |
$statuses_allowed = SucuriScanHeartbeat::statuses_allowed();
|
13273 |
$intervals_allowed = SucuriScanHeartbeat::intervals_allowed();
|
13274 |
|
13275 |
// HTML select form fields.
|
13276 |
+
$heartbeat_options = SucuriScanTemplate::selectOptions($statuses_allowed, $heartbeat_status);
|
13277 |
+
$heartbeat_pulse_options = SucuriScanTemplate::selectOptions($pulses_allowed, $heartbeat_pulse);
|
13278 |
+
$heartbeat_interval_options = SucuriScanTemplate::selectOptions($intervals_allowed, $heartbeat_interval);
|
13279 |
|
13280 |
+
$params = array(
|
13281 |
'HeartbeatStatus' => 'Undefined',
|
13282 |
'HeartbeatPulse' => 'Undefined',
|
13283 |
'HeartbeatInterval' => 'Undefined',
|
13292 |
'HeartbeatAutostartSwitchCssClass' => 'button-danger',
|
13293 |
);
|
13294 |
|
13295 |
+
if (array_key_exists($heartbeat_status, $statuses_allowed)) {
|
13296 |
+
$params['HeartbeatStatus'] = $statuses_allowed[ $heartbeat_status ];
|
13297 |
}
|
13298 |
|
13299 |
+
if (array_key_exists($heartbeat_pulse, $pulses_allowed)) {
|
13300 |
+
$params['HeartbeatPulse'] = $pulses_allowed[ $heartbeat_pulse ];
|
13301 |
}
|
13302 |
|
13303 |
+
if (array_key_exists($heartbeat_interval, $intervals_allowed)) {
|
13304 |
+
$params['HeartbeatInterval'] = $intervals_allowed[ $heartbeat_interval ];
|
13305 |
}
|
13306 |
|
13307 |
+
if ($heartbeat_autostart == 'disabled') {
|
13308 |
+
$params['HeartbeatAutostart'] = 'Disabled';
|
13309 |
+
$params['HeartbeatAutostartSwitchText'] = 'Enable';
|
13310 |
+
$params['HeartbeatAutostartSwitchValue'] = 'enable';
|
13311 |
+
$params['HeartbeatAutostartSwitchCssClass'] = 'button-success';
|
13312 |
}
|
13313 |
|
13314 |
+
return SucuriScanTemplate::getSection('settings-heartbeat', $params);
|
13315 |
+
}
|
13316 |
+
|
13317 |
+
/**
|
13318 |
+
* Print a HTML code with the settings of the plugin.
|
13319 |
+
*
|
13320 |
+
* @return void
|
13321 |
+
*/
|
13322 |
+
function sucuriscan_settings_page()
|
13323 |
+
{
|
13324 |
+
SucuriScanInterface::check_permissions();
|
13325 |
+
|
13326 |
+
$params = array();
|
13327 |
+
$nonce = SucuriScanInterface::check_nonce();
|
13328 |
+
|
13329 |
+
$params['PageTitle'] = 'Settings';
|
13330 |
+
$params['Settings.General'] = sucuriscan_settings_general($nonce);
|
13331 |
+
$params['Settings.Scanner'] = sucuriscan_settings_scanner();
|
13332 |
+
$params['Settings.Alerts'] = sucuriscan_settings_alert($nonce);
|
13333 |
+
$params['Settings.ApiService'] = sucuriscan_settings_apiservice($nonce);
|
13334 |
+
$params['Settings.SelfHosting'] = sucuriscan_settings_selfhosting($nonce);
|
13335 |
+
$params['Settings.IgnoreScanning'] = sucuriscan_settings_ignorescanning();
|
13336 |
+
$params['Settings.IgnoreRules'] = sucuriscan_settings_ignore_rules();
|
13337 |
+
$params['Settings.TrustIP'] = sucuriscan_settings_trust_ip();
|
13338 |
+
$params['Settings.Heartbeat'] = sucuriscan_settings_heartbeat();
|
13339 |
+
|
13340 |
+
echo SucuriScanTemplate::getTemplate('settings', $params);
|
13341 |
}
|
13342 |
|
13343 |
/**
|
13349 |
*
|
13350 |
* @return void
|
13351 |
*/
|
13352 |
+
function sucuriscan_infosys_page()
|
13353 |
+
{
|
13354 |
SucuriScanInterface::check_permissions();
|
13355 |
|
13356 |
// Process all form submissions.
|
13357 |
sucuriscan_infosys_form_submissions();
|
13358 |
|
13359 |
// Page pseudo-variables initialization.
|
13360 |
+
$params = array(
|
13361 |
'PageTitle' => 'Site Info',
|
13362 |
'ServerInfo' => sucuriscan_server_info(),
|
13363 |
'Cronjobs' => sucuriscan_show_cronjobs(),
|
13366 |
'ErrorLogs' => sucuriscan_infosys_errorlogs(),
|
13367 |
);
|
13368 |
|
13369 |
+
echo SucuriScanTemplate::getTemplate('infosys', $params);
|
13370 |
}
|
13371 |
|
13372 |
/**
|
13375 |
*
|
13376 |
* @return string The HTML code displaying the information about the HTAccess rules.
|
13377 |
*/
|
13378 |
+
function sucuriscan_infosys_htaccess()
|
13379 |
+
{
|
13380 |
$htaccess_path = SucuriScan::get_htaccess_path();
|
13381 |
+
$params = array(
|
|
|
13382 |
'HTAccess.Content' => '',
|
|
|
|
|
|
|
13383 |
'HTAccess.TextareaVisible' => 'hidden',
|
13384 |
+
'HTAccess.StandardVisible' => 'hidden',
|
13385 |
+
'HTAccess.NotFoundVisible' => 'hidden',
|
13386 |
+
'HTAccess.FoundVisible' => 'hidden',
|
13387 |
+
'HTAccess.Fpath' => 'unknown',
|
13388 |
);
|
13389 |
|
13390 |
+
if ($htaccess_path) {
|
13391 |
+
$htaccess_rules = @file_get_contents($htaccess_path);
|
13392 |
|
13393 |
+
$params['HTAccess.TextareaVisible'] = 'visible';
|
13394 |
+
$params['HTAccess.Content'] = $htaccess_rules;
|
13395 |
+
$params['HTAccess.Fpath'] = $htaccess_path;
|
13396 |
+
$params['HTAccess.FoundVisible'] = 'visible';
|
|
|
13397 |
|
13398 |
+
if (sucuriscan_htaccess_is_standard($htaccess_rules)) {
|
13399 |
+
$params['HTAccess.StandardVisible'] = 'visible';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
13400 |
}
|
13401 |
} else {
|
13402 |
+
$params['HTAccess.NotFoundVisible'] = 'visible';
|
|
|
|
|
13403 |
}
|
13404 |
|
13405 |
+
return SucuriScanTemplate::getSection('infosys-htaccess', $params);
|
13406 |
}
|
13407 |
|
13408 |
/**
|
13409 |
+
* Check if the standard rules for a normal WordPress installation (not network
|
13410 |
+
* based) are inside the main htaccess file. This only applies to websites that
|
13411 |
+
* have permalinks enabled, or 3rd-party plugins that require custom rules
|
13412 |
+
* (generally based on mod_deflate) to compress and/or generate static files for
|
13413 |
+
* cache.
|
13414 |
*
|
13415 |
+
* @param string $rules Content of the main htaccess file.
|
13416 |
+
* @return boolean True if the htaccess has the standard rules, false otherwise.
|
13417 |
*/
|
13418 |
+
function sucuriscan_htaccess_is_standard($rules = false)
|
13419 |
+
{
|
13420 |
+
if ($rules === false) {
|
13421 |
+
$rules = '';
|
13422 |
$htaccess_path = SucuriScan::get_htaccess_path();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
13423 |
|
13424 |
+
if ($htaccess_path) {
|
13425 |
+
$rules = @file_get_contents($htaccess_path);
|
13426 |
}
|
13427 |
}
|
13428 |
|
13429 |
+
if (is_string($rules) && !empty($rules)) {
|
13430 |
+
$rewrite = new WP_Rewrite();
|
13431 |
+
$standard = $rewrite->mod_rewrite_rules();
|
13432 |
+
|
13433 |
+
return (bool) (strpos($rules, $standard) !== false);
|
13434 |
+
}
|
13435 |
+
|
13436 |
return false;
|
13437 |
}
|
13438 |
|
13443 |
*
|
13444 |
* @return string The HTML code displaying the constants and variables found in the wp-config file.
|
13445 |
*/
|
13446 |
+
function sucuriscan_infosys_wpconfig()
|
13447 |
+
{
|
13448 |
+
$params = array(
|
13449 |
'WordpressConfig.Rules' => '',
|
13450 |
'WordpressConfig.Total' => 0,
|
13451 |
);
|
13452 |
|
13453 |
+
$ignore_wp_rules = array('DB_PASSWORD');
|
13454 |
$wp_config_path = SucuriScan::get_wpconfig_path();
|
13455 |
|
13456 |
+
if ($wp_config_path) {
|
13457 |
$wp_config_rules = array();
|
13458 |
+
$wp_config_content = SucuriScanFileInfo::file_lines($wp_config_path);
|
13459 |
|
13460 |
// Parse the main configuration file and look for constants and global variables.
|
13461 |
+
foreach ((array) $wp_config_content as $line) {
|
13462 |
+
if (@preg_match('/^\s?(#|\/\/)/', $line)) {
|
13463 |
+
continue; /* Ignore commented lines. */
|
13464 |
+
} elseif (@preg_match('/define\(/', $line)) {
|
|
|
13465 |
// Detect PHP constants even if the line if indented.
|
13466 |
+
$line = preg_replace('/.*define\((.+)\);.*/', '$1', $line);
|
13467 |
+
$line_parts = explode(',', $line, 2);
|
13468 |
+
} elseif (@preg_match('/^\$[a-zA-Z_]+/', $line)) {
|
13469 |
// Detect global variables like the database table prefix.
|
13470 |
+
$line = @preg_replace('/;\s\/\/.*/', ';', $line);
|
13471 |
+
$line_parts = explode('=', $line, 2);
|
13472 |
} else {
|
13473 |
+
continue; /* Ignore other lines. */
|
|
|
13474 |
}
|
13475 |
|
13476 |
// Clean and append the rule to the wp_config_rules variable.
|
13477 |
+
if (isset($line_parts) && count($line_parts) === 2) {
|
13478 |
$key_name = '';
|
13479 |
$key_value = '';
|
13480 |
|
13481 |
// TODO: A foreach loop is not really necessary, find a better way.
|
13482 |
+
foreach ($line_parts as $i => $line_part) {
|
13483 |
+
$line_part = trim($line_part);
|
13484 |
+
$line_part = ltrim($line_part, '$');
|
13485 |
+
$line_part = rtrim($line_part, ';');
|
13486 |
|
13487 |
// Remove single/double quotes at the beginning and end of the string.
|
13488 |
+
$line_part = ltrim($line_part, "'");
|
13489 |
+
$line_part = rtrim($line_part, "'");
|
13490 |
+
$line_part = ltrim($line_part, '"');
|
13491 |
+
$line_part = rtrim($line_part, '"');
|
13492 |
|
13493 |
// Assign the clean strings to specific variables.
|
13494 |
+
if ($i == 0) {
|
13495 |
$key_name = $line_part;
|
13496 |
}
|
13497 |
|
13498 |
+
if ($i == 1) {
|
13499 |
+
if (defined($key_name)) {
|
13500 |
+
$key_value = constant($key_name);
|
13501 |
|
13502 |
+
if (is_bool($key_value)) {
|
13503 |
+
$key_value = ($key_value === true) ? 'True' : 'False';
|
13504 |
}
|
13505 |
} else {
|
13506 |
$key_value = $line_part;
|
13509 |
}
|
13510 |
|
13511 |
// Remove the value of sensitive variables like the database password.
|
13512 |
+
if (in_array($key_name, $ignore_wp_rules)) {
|
13513 |
$key_value = 'hidden';
|
13514 |
}
|
13515 |
|
13516 |
// Append the value to the configuration rules.
|
13517 |
+
$wp_config_rules[$key_name] = $key_value;
|
13518 |
}
|
13519 |
}
|
13520 |
|
13521 |
// Pass the WordPress configuration rules to the template and show them.
|
13522 |
$counter = 0;
|
13523 |
+
foreach ($wp_config_rules as $var_name => $var_value) {
|
13524 |
+
$css_class = ($counter % 2 === 0) ? '' : 'alternate';
|
13525 |
$label_css = 'sucuriscan-monospace';
|
13526 |
|
13527 |
+
if (empty($var_value)) {
|
13528 |
$var_value = 'empty';
|
13529 |
$label_css = 'sucuriscan-label-default';
|
13530 |
+
} elseif ($var_value == 'hidden') {
|
13531 |
$label_css = 'sucuriscan-label-info';
|
13532 |
}
|
13533 |
|
13534 |
+
$params['WordpressConfig.Total'] += 1;
|
13535 |
+
$params['WordpressConfig.Rules'] .= SucuriScanTemplate::getSnippet(
|
13536 |
+
'infosys-wpconfig',
|
13537 |
+
array(
|
13538 |
+
'WordpressConfig.VariableName' => $var_name,
|
13539 |
+
'WordpressConfig.VariableValue' => $var_value,
|
13540 |
+
'WordpressConfig.VariableCssClass' => $label_css,
|
13541 |
+
'WordpressConfig.CssClass' => $css_class,
|
13542 |
+
)
|
13543 |
+
);
|
13544 |
+
$counter++;
|
13545 |
}
|
13546 |
}
|
13547 |
|
13548 |
+
return SucuriScanTemplate::getSection('infosys-wpconfig', $params);
|
13549 |
}
|
13550 |
|
13551 |
/**
|
13553 |
*
|
13554 |
* @return array A list of pseudo-variables and values that will replace them in the HTML template.
|
13555 |
*/
|
13556 |
+
function sucuriscan_show_cronjobs()
|
13557 |
+
{
|
13558 |
+
$params = array(
|
13559 |
'Cronjobs.List' => '',
|
13560 |
'Cronjobs.Total' => 0,
|
13561 |
);
|
13564 |
$schedules = wp_get_schedules();
|
13565 |
$counter = 0;
|
13566 |
|
13567 |
+
foreach ($cronjobs as $timestamp => $cronhooks) {
|
13568 |
+
foreach ((array) $cronhooks as $hook => $events) {
|
13569 |
+
foreach ((array) $events as $key => $event) {
|
13570 |
+
if (empty($event['args'])) {
|
13571 |
+
$event['args'] = array('[]');
|
13572 |
}
|
13573 |
|
13574 |
+
$params['Cronjobs.Total'] += 1;
|
13575 |
+
$params['Cronjobs.List'] .= SucuriScanTemplate::getSnippet(
|
13576 |
+
'infosys-cronjobs',
|
13577 |
+
array(
|
13578 |
+
'Cronjob.Hook' => $hook,
|
13579 |
+
'Cronjob.Schedule' => $event['schedule'],
|
13580 |
+
'Cronjob.NextTime' => SucuriScan::datetime($timestamp),
|
13581 |
+
'Cronjob.Arguments' => SucuriScan::implode(', ', $event['args']),
|
13582 |
+
'Cronjob.CssClass' => ($counter % 2 === 0) ? '' : 'alternate',
|
13583 |
+
)
|
13584 |
+
);
|
13585 |
+
$counter++;
|
13586 |
}
|
13587 |
}
|
13588 |
}
|
13589 |
|
13590 |
+
return SucuriScanTemplate::getSection('infosys-cronjobs', $params);
|
13591 |
}
|
13592 |
|
13593 |
/**
|
13598 |
* @param boolean $page_nonce True if the nonce is valid, False otherwise.
|
13599 |
* @return void
|
13600 |
*/
|
13601 |
+
function sucuriscan_infosys_form_submissions()
|
13602 |
+
{
|
13603 |
+
if (SucuriScanInterface::check_nonce()) {
|
13604 |
// Modify the scheduled tasks (run now, remove, re-schedule).
|
13605 |
$allowed_actions = '(runnow|hourly|twicedaily|daily|remove)';
|
13606 |
|
13607 |
+
if ($cronjob_action = SucuriScanRequest::post(':cronjob_action', $allowed_actions)) {
|
13608 |
+
$cronjobs = SucuriScanRequest::post(':cronjobs', '_array');
|
13609 |
|
13610 |
+
if (!empty($cronjobs)) {
|
13611 |
+
$total_tasks = count($cronjobs);
|
13612 |
|
13613 |
// Force execution of the selected scheduled tasks.
|
13614 |
+
if ($cronjob_action == 'runnow') {
|
13615 |
+
SucuriScanInterface::info($total_tasks . ' tasks were scheduled to run in the next ten seconds.');
|
13616 |
+
SucuriScanEvent::report_notice_event(sprintf(
|
13617 |
'Force execution of scheduled tasks: (multiple entries): %s',
|
13618 |
+
@implode(',', $cronjobs)
|
13619 |
+
));
|
13620 |
|
13621 |
+
foreach ($cronjobs as $task_name) {
|
13622 |
+
wp_schedule_single_event(time() + 10, $task_name);
|
13623 |
}
|
13624 |
+
} // Force deletion of the selected scheduled tasks.
|
13625 |
+
elseif ($cronjob_action == 'remove') {
|
13626 |
+
SucuriScanInterface::info($total_tasks . ' scheduled tasks were removed.');
|
13627 |
+
SucuriScanEvent::report_notice_event(sprintf(
|
|
|
|
|
13628 |
'Delete scheduled tasks: (multiple entries): %s',
|
13629 |
+
@implode(',', $cronjobs)
|
13630 |
+
));
|
13631 |
|
13632 |
+
foreach ($cronjobs as $task_name) {
|
13633 |
+
wp_clear_scheduled_hook($task_name);
|
13634 |
}
|
13635 |
+
} // Re-schedule the selected scheduled tasks.
|
13636 |
+
elseif ($cronjob_action == 'hourly'
|
|
|
|
|
|
|
13637 |
|| $cronjob_action == 'twicedaily'
|
13638 |
|| $cronjob_action == 'daily'
|
13639 |
) {
|
13640 |
+
SucuriScanInterface::info($total_tasks . ' tasks were re-scheduled to run <code>' . $cronjob_action . '</code>.');
|
13641 |
+
SucuriScanEvent::report_notice_event(sprintf(
|
13642 |
'Re-configure scheduled tasks %s: (multiple entries): %s',
|
13643 |
$cronjob_action,
|
13644 |
+
@implode(',', $cronjobs)
|
13645 |
+
));
|
13646 |
|
13647 |
+
foreach ($cronjobs as $task_name) {
|
13648 |
+
wp_clear_scheduled_hook($task_name);
|
13649 |
+
$next_due = wp_next_scheduled($task_name);
|
13650 |
+
wp_schedule_event($next_due, $cronjob_action, $task_name);
|
13651 |
}
|
13652 |
}
|
13653 |
} else {
|
13654 |
+
SucuriScanInterface::error('No scheduled tasks were selected from the list.');
|
13655 |
}
|
13656 |
}
|
13657 |
}
|
13662 |
*
|
13663 |
* @return array A list of pseudo-variables and values that will replace them in the HTML template.
|
13664 |
*/
|
13665 |
+
function sucuriscan_infosys_errorlogs()
|
13666 |
+
{
|
13667 |
+
$params = array(
|
13668 |
'ErrorLog.Path' => '',
|
13669 |
'ErrorLog.Exists' => 'No',
|
13670 |
'ErrorLog.NoItemsVisibility' => 'hidden',
|
13676 |
);
|
13677 |
|
13678 |
$error_log_path = false;
|
13679 |
+
$log_filename = SucuriScan::ini_get('error_log');
|
13680 |
+
$errorlogs_limit = SucuriScanOption::get_option(':errorlogs_limit');
|
13681 |
+
$params['ErrorLog.LogsLimit'] = $errorlogs_limit;
|
13682 |
+
$counter = 0;
|
13683 |
+
|
13684 |
+
if ($log_filename) {
|
13685 |
+
$error_log_path = @realpath(ABSPATH . '/' . $log_filename);
|
13686 |
+
}
|
13687 |
+
|
13688 |
+
if (SucuriScanOption::is_disabled(':parse_errorlogs')) {
|
13689 |
+
$params['ErrorLog.DisabledVisibility'] = 'visible';
|
13690 |
+
}
|
13691 |
+
|
13692 |
+
if ($error_log_path) {
|
13693 |
+
$params['ErrorLog.Exists'] = 'Yes';
|
13694 |
+
$params['ErrorLog.Path'] = $error_log_path;
|
13695 |
+
$params['ErrorLog.FileSize'] = SucuriScan::human_filesize(filesize($error_log_path));
|
13696 |
+
|
13697 |
+
$last_lines = SucuriScanFileInfo::tail_file($error_log_path, $errorlogs_limit);
|
13698 |
+
$error_logs = SucuriScanFSScanner::parse_error_logs($last_lines);
|
13699 |
+
$error_logs = array_reverse($error_logs);
|
13700 |
+
$counter = 0;
|
13701 |
+
|
13702 |
+
foreach ($error_logs as $error_log) {
|
13703 |
+
$css_class = ( $counter % 2 === 0 ) ? '' : 'alternate';
|
13704 |
+
$params['ErrorLog.List'] .= SucuriScanTemplate::getSnippet(
|
13705 |
+
'infosys-errorlogs',
|
13706 |
+
array(
|
13707 |
+
'ErrorLog.CssClass' => $css_class,
|
13708 |
+
'ErrorLog.DateTime' => SucuriScan::datetime($error_log->timestamp),
|
13709 |
+
'ErrorLog.ErrorType' => $error_log->error_type,
|
13710 |
+
'ErrorLog.ErrorCode' => $error_log->error_code,
|
13711 |
+
'ErrorLog.ErrorAbbr' => strtoupper(substr($error_log->error_code, 0, 1)),
|
13712 |
+
'ErrorLog.ErrorMessage' => $error_log->error_message,
|
13713 |
+
'ErrorLog.FilePath' => $error_log->file_path,
|
13714 |
+
'ErrorLog.LineNumber' => $error_log->line_number,
|
13715 |
+
)
|
13716 |
+
);
|
13717 |
+
$counter += 1;
|
13718 |
}
|
13719 |
|
13720 |
+
if ($counter <= 0) {
|
13721 |
+
$params['ErrorLog.InvalidFormatVisibility'] = 'visible';
|
13722 |
}
|
13723 |
} else {
|
13724 |
+
$params['ErrorLog.NoItemsVisibility'] = 'visible';
|
13725 |
}
|
13726 |
|
13727 |
+
return SucuriScanTemplate::getSection('infosys-errorlogs', $params);
|
13728 |
}
|
13729 |
|
13730 |
/**
|
13732 |
*
|
13733 |
* @return array A list of pseudo-variables and values that will replace them in the HTML template.
|
13734 |
*/
|
13735 |
+
function sucuriscan_server_info()
|
13736 |
+
{
|
13737 |
global $wpdb;
|
13738 |
|
13739 |
+
$params = array(
|
13740 |
'ServerInfo.Variables' => '',
|
13741 |
);
|
13742 |
|
13743 |
$info_vars = array(
|
13744 |
'Plugin_version' => SUCURISCAN_VERSION,
|
13745 |
'Plugin_checksum' => SUCURISCAN_PLUGIN_CHECKSUM,
|
13746 |
+
'Last_filesystem_scan' => SucuriScanFSScanner::get_filesystem_runtime(true),
|
13747 |
'Datetime_and_Timezone' => '',
|
13748 |
+
'Operating_system' => sprintf('%s (%d Bit)', PHP_OS, PHP_INT_SIZE * 8),
|
13749 |
'Server' => 'Unknown',
|
13750 |
'Developer_mode' => 'OFF',
|
13751 |
'Memory_usage' => 'N/A',
|
13757 |
$info_vars['Datetime_and_Timezone'] = sprintf(
|
13758 |
'%s (GMT %s)',
|
13759 |
SucuriScan::current_datetime(),
|
13760 |
+
get_option('gmt_offset')
|
13761 |
);
|
13762 |
|
13763 |
+
if (defined('WP_DEBUG') && WP_DEBUG) {
|
13764 |
$info_vars['Developer_mode'] = 'ON';
|
13765 |
}
|
13766 |
|
13767 |
+
if (function_exists('memory_get_usage')) {
|
13768 |
+
$info_vars['Memory_usage'] = round(memory_get_usage() / 1024 / 1024, 2).' MB';
|
13769 |
}
|
13770 |
|
13771 |
+
if (isset($_SERVER['SERVER_SOFTWARE'])) {
|
13772 |
+
$info_vars['Server'] = $_SERVER['SERVER_SOFTWARE'];
|
13773 |
}
|
13774 |
|
13775 |
+
if ($wpdb) {
|
13776 |
+
$info_vars['MySQL_version'] = $wpdb->get_var('SELECT VERSION() AS version');
|
13777 |
|
13778 |
+
$mysql_info = $wpdb->get_results('SHOW VARIABLES LIKE "sql_mode"');
|
13779 |
+
if (is_array($mysql_info) && !empty($mysql_info[0]->Value)) {
|
13780 |
$info_vars['SQL_mode'] = $mysql_info[0]->Value;
|
13781 |
}
|
13782 |
}
|
13792 |
'max_input_time',
|
13793 |
);
|
13794 |
|
13795 |
+
foreach ($field_names as $php_flag) {
|
13796 |
+
$php_flag_value = SucuriScan::ini_get($php_flag);
|
13797 |
$php_flag_name = 'PHP_' . $php_flag;
|
13798 |
+
$info_vars[$php_flag_name] = $php_flag_value ? $php_flag_value : 'N/A';
|
13799 |
}
|
13800 |
|
13801 |
$counter = 0;
|
13802 |
|
13803 |
+
foreach ($info_vars as $var_name => $var_value) {
|
13804 |
+
$css_class = ($counter % 2 === 0) ? '' : 'alternate';
|
13805 |
+
$var_name = str_replace('_', "\x20", $var_name);
|
13806 |
|
13807 |
+
$params['ServerInfo.Variables'] .= SucuriScanTemplate::getSnippet(
|
13808 |
+
'infosys-serverinfo',
|
13809 |
+
array(
|
13810 |
+
'ServerInfo.CssClass' => $css_class,
|
13811 |
+
'ServerInfo.Title' => $var_name,
|
13812 |
+
'ServerInfo.Value' => $var_value,
|
13813 |
+
)
|
13814 |
+
);
|
13815 |
$counter += 1;
|
13816 |
}
|
13817 |
|
13818 |
+
return SucuriScanTemplate::getSection('infosys-serverinfo', $params);
|
13819 |
}
|
13820 |
|
uninstall.php
CHANGED
@@ -11,8 +11,7 @@
|
|
11 |
* @since File available since Release 0.1
|
12 |
*/
|
13 |
|
14 |
-
if (
|
15 |
-
! defined( 'WP_UNINSTALL_PLUGIN' )
|
16 |
|| WP_UNINSTALL_PLUGIN != 'sucuri-scanner/sucuri.php'
|
17 |
) {
|
18 |
exit(0);
|
@@ -20,8 +19,10 @@ if (
|
|
20 |
|
21 |
$sucuriscan_option_names = array(
|
22 |
'account',
|
|
|
23 |
'ads_visibility',
|
24 |
'api_key',
|
|
|
25 |
'audit_report',
|
26 |
'cloudproxy_apikey',
|
27 |
'collect_wrong_passwords',
|
@@ -76,6 +77,8 @@ $sucuriscan_option_names = array(
|
|
76 |
'scan_frequency',
|
77 |
'scan_interface',
|
78 |
'scan_modfiles',
|
|
|
|
|
79 |
'site_version',
|
80 |
'sitecheck_counter',
|
81 |
'sitecheck_scanner',
|
@@ -84,31 +87,30 @@ $sucuriscan_option_names = array(
|
|
84 |
'xhr_monitor',
|
85 |
);
|
86 |
|
87 |
-
$sucuriscan_storage_path = get_option(
|
88 |
|
89 |
-
if (
|
90 |
-
$sucuriscan_storage_path
|
91 |
-
&&
|
92 |
-
&&
|
93 |
-
&& is_dir( $sucuriscan_storage_path )
|
94 |
) {
|
95 |
-
@unlink(
|
96 |
-
@unlink(
|
97 |
-
@unlink(
|
98 |
-
@unlink(
|
99 |
-
@unlink(
|
100 |
-
@unlink(
|
101 |
-
@unlink(
|
102 |
-
@unlink(
|
103 |
-
@unlink(
|
104 |
-
@unlink(
|
105 |
|
106 |
-
@rmdir(
|
107 |
}
|
108 |
|
109 |
-
foreach (
|
110 |
-
delete_option(
|
111 |
-
delete_site_option(
|
112 |
}
|
113 |
|
114 |
// EOF
|
11 |
* @since File available since Release 0.1
|
12 |
*/
|
13 |
|
14 |
+
if (!defined('WP_UNINSTALL_PLUGIN')
|
|
|
15 |
|| WP_UNINSTALL_PLUGIN != 'sucuri-scanner/sucuri.php'
|
16 |
) {
|
17 |
exit(0);
|
19 |
|
20 |
$sucuriscan_option_names = array(
|
21 |
'account',
|
22 |
+
'addr_header',
|
23 |
'ads_visibility',
|
24 |
'api_key',
|
25 |
+
'api_service',
|
26 |
'audit_report',
|
27 |
'cloudproxy_apikey',
|
28 |
'collect_wrong_passwords',
|
77 |
'scan_frequency',
|
78 |
'scan_interface',
|
79 |
'scan_modfiles',
|
80 |
+
'selfhosting_fpath',
|
81 |
+
'selfhosting_monitor',
|
82 |
'site_version',
|
83 |
'sitecheck_counter',
|
84 |
'sitecheck_scanner',
|
87 |
'xhr_monitor',
|
88 |
);
|
89 |
|
90 |
+
$sucuriscan_storage_path = get_option('sucuriscan_datastore_path');
|
91 |
|
92 |
+
if ($sucuriscan_storage_path !== false
|
93 |
+
&& file_exists($sucuriscan_storage_path)
|
94 |
+
&& is_writable($sucuriscan_storage_path)
|
95 |
+
&& is_dir($sucuriscan_storage_path)
|
|
|
96 |
) {
|
97 |
+
@unlink($sucuriscan_storage_path . '/.htaccess');
|
98 |
+
@unlink($sucuriscan_storage_path . '/index.html');
|
99 |
+
@unlink($sucuriscan_storage_path . '/sucuri-failedlogins.php');
|
100 |
+
@unlink($sucuriscan_storage_path . '/sucuri-ignorescanning.php');
|
101 |
+
@unlink($sucuriscan_storage_path . '/sucuri-integrity.php');
|
102 |
+
@unlink($sucuriscan_storage_path . '/sucuri-lastlogins.php');
|
103 |
+
@unlink($sucuriscan_storage_path . '/sucuri-oldfailedlogins.php');
|
104 |
+
@unlink($sucuriscan_storage_path . '/sucuri-plugindata.php');
|
105 |
+
@unlink($sucuriscan_storage_path . '/sucuri-sitecheck.php');
|
106 |
+
@unlink($sucuriscan_storage_path . '/sucuri-trustip.php');
|
107 |
|
108 |
+
@rmdir($sucuriscan_storage_path);
|
109 |
}
|
110 |
|
111 |
+
foreach ($sucuriscan_option_names as $option_name) {
|
112 |
+
delete_option('sucuriscan_' . $option_name);
|
113 |
+
delete_site_option('sucuriscan_' . $option_name);
|
114 |
}
|
115 |
|
116 |
// EOF
|