@@ -48,6 +48,11 @@ class MainWP_Child_Vulnerability_Checker {
4848 */
4949 private $ wpvulndb_nvd_api = 'https://services.nvd.nist.gov/rest/json/cves/2.0 ' ;
5050
51+ /**
52+ * Wordfence API URL
53+ */
54+ private $ wordfence_api_url = 'www.wordfence.com/api/intelligence/v2/vulnerabilities/ ' ;
55+
5156
5257 /**
5358 * Method instance()
@@ -100,7 +105,7 @@ public function vulner_recheck() {
100105 $ result = array ();
101106 // phpcs:disable WordPress.Security.NonceVerification
102107 $ force = ( isset ( $ _POST ['force ' ] ) && ! empty ( $ _POST ['force ' ] ) ) ? true : false ;
103- $ service = ( isset ( $ _POST ['service ' ] ) && 'nvd_nist ' === $ _POST ['service ' ] ) ? 'nvd_nist ' : ' wpvulndb ' ;
108+ $ service = ( isset ( $ _POST ['service ' ] ) && 'nvd_nist ' === $ _POST ['service ' ] ) ? 'nvd_nist ' : ( ( isset ( $ _POST [ ' service ' ] ) && ' wordfence ' == $ _POST [ ' service ' ] ) ? ' wordfence ' : ' wpvulndb ' ) ;
104109
105110 if ( 'wpvulndb ' === $ service ) {
106111 if ( empty ( $ _POST ['wpvulndb_tk ' ] ) ) {
@@ -120,6 +125,87 @@ public function vulner_recheck() {
120125 );
121126 }
122127
128+ /**
129+ * @param $version
130+ * @param $data
131+ * @return bool
132+ */
133+ function isFixedVersion ( $ version , $ data ) {
134+ if ( $ data ['from_version ' ] === '* ' && $ data ['to_version ' ] === '* ' ) {
135+ return false ;
136+ }
137+
138+ if ( $ data ['from_version ' ] === '* ' ) {
139+ $ data ['from_version ' ] = '0 ' ;
140+ }
141+
142+ $ fromOperator = $ data ['from_inclusive ' ] ? '>= ' : '> ' ;
143+ $ toOperator = $ data ['to_inclusive ' ] ? '<= ' : '< ' ;
144+
145+ if ( version_compare ($ version , $ data ['from_version ' ], $ fromOperator ) && version_compare ($ version , $ data ['to_version ' ], $ toOperator ) ) {
146+ return false ;
147+ } else {
148+ return true ;
149+ }
150+ }
151+
152+ /**
153+ * @param $data
154+ * @param $slug
155+ * @param $version
156+ * @return array
157+ */
158+ public function get_vuln_wordfence_info ( $ data , $ slug , $ version ) {
159+
160+ $ data = json_decode ( $ data , true );
161+ $ filtered_data = array ();
162+
163+ if ( is_array ( $ data ) && isset ( $ data ['result ' ] ) && isset ( $ data ['result ' ]['CVE_Items ' ] ) ) {
164+ $ vulns = array ();
165+ $ version_missed = true ;
166+ $ fixed = false ;
167+
168+ foreach ( $ data ['result ' ]['CVE_Items ' ] as $ item ) {
169+ $ info = array ();
170+ $ remediation = '' ;
171+ foreach ( $ item ['software ' ] as $ software ) {
172+ foreach ( $ software ['affected_versions ' ] as $ affected_version ) {
173+ $ fixed = $ this ->isFixedVersion ($ version , $ affected_version );
174+ $ version_missed = false ;
175+ if ( $ fixed ) {
176+ break ;
177+ }
178+ }
179+
180+ $ remediation .= ' [ ' . ucfirst ($ software ['type ' ]) . '-> ' . $ software ['name ' ] . '] ' . $ software ['remediation ' ];
181+ }
182+
183+ if ( ! $ fixed ) {
184+ if ( isset ( $ item ['published ' ] ) ) {
185+ $ info ['date ' ] = $ item ['published ' ];
186+ }
187+
188+ if ( isset ( $ item ['description ' ] ) ) {
189+ $ info ['detail ' ] = $ item ['description ' ] . $ remediation ;
190+ }
191+
192+ $ customCveId = explode ( '- ' , $ item ['id ' ]);
193+ $ info ['cve_id ' ] = $ item ['cve ' ] ?? end ($ customCveId );
194+ $ info ['slug ' ] = $ slug ;
195+ }
196+ if ( $ version_missed ) {
197+ $ info ['missed_version ' ] = 1 ;
198+ }
199+ if ( ! empty ( $ info ) ) {
200+ $ vulns [] = $ info ;
201+ }
202+ }
203+ $ filtered_data [ $ slug ]['vulnerabilities ' ] = $ vulns ;
204+ }
205+
206+ return $ filtered_data ;
207+ }
208+
123209 /**
124210 * Check for plugin vulnerabilities.
125211 *
@@ -151,6 +237,8 @@ public function check_plugins( $force = false, $service = '' ) { //phpcs:ignore
151237 }
152238 // URL Syntax example: https://services.nvd.nist.gov/rest/json/cves/2.0?virtualMatchString=cpe:2.3:a:automattic:akismet:* .
153239 $ url = $ this ->wpvulndb_nvd_api . '?virtualMatchString=cpe:2.3:a: ' . $ author_name . ': ' . $ slug . ':* ' ;
240+ } elseif ( 'wordfence ' === $ service ) {
241+ $ url = $ this ->wordfence_api_url . 'production?keyword= ' . $ string [0 ];
154242 } else {
155243 $ url = $ this ->wpvulndb_api . 'plugins/ ' . $ string [0 ];
156244 }
@@ -161,6 +249,8 @@ public function check_plugins( $force = false, $service = '' ) { //phpcs:ignore
161249 $ plug_vuln_filter = array ();
162250 if ( 'nvd_nist ' === $ service ) {
163251 $ plug_vuln_filter = $ this ->get_vuln_nvd_nist_info ( $ plug_vuln , $ string [0 ], $ plugin_version );
252+ } elseif ( 'wordfence ' == $ service ) {
253+ $ plug_vuln_filter = $ this ->get_vuln_wordfence_info ( $ plug_vuln , $ string [0 ], $ plugin_version );
164254 } else {
165255 $ plug_vuln = json_decode ( $ plug_vuln , true );
166256 $ plug_vuln_filter = $ plug_vuln ;
@@ -214,6 +304,8 @@ public function check_wp( $force = false, $service = '' ) {
214304 if ( false === $ wp_vuln || $ force ) {
215305 if ( 'nvd_nist ' === $ service ) {
216306 $ url = $ this ->wpvulndb_nvd_api . '?virtualMatchString=cpe:2.3:a:WordPress:WordPress ' ;
307+ } elseif ( 'wordfence ' == $ service ) {
308+ $ url = $ this ->wordfence_api_url . 'production?keyword=WordPress ' ;
217309 } else {
218310 $ url = $ this ->wpvulndb_api . 'wordpresses/ ' . $ number_version ;
219311 }
@@ -223,6 +315,12 @@ public function check_wp( $force = false, $service = '' ) {
223315 $ wp_vuln = $ this ->get_vuln_nvd_nist_info ( $ wp_vuln , 'wordpress ' , $ wp_version ); //phpcs:ignore -- wordpress.
224316 $ wp_vuln = wp_json_encode ( $ wp_vuln );
225317 }
318+
319+ if ( 'wordfence ' == $ service ) {
320+ $ wp_vuln = $ this ->get_vuln_wordfence_info ( $ wp_vuln , 'WordPress ' , $ wp_version );
321+ $ wp_vuln = wp_json_encode ( $ wp_vuln );
322+ }
323+
226324 set_transient ( 'mainwp_vulnche_trans_wp_json ' , $ wp_vuln , 1 * DAY_IN_SECONDS );
227325 }
228326 return $ wp_vuln ;
@@ -257,6 +355,8 @@ public function check_themes( $force = false, $service = '' ) { // phpcs:ignore
257355
258356 if ( 'nvd_nist ' === $ service ) {
259357 $ url = $ this ->wpvulndb_nvd_api . '?keywordSearch= ' . $ th ['id ' ] . '&keywordExactMatch ' ;
358+ } elseif ( 'wordfence ' === $ service ) {
359+ $ url = $ this ->wordfence_api_url . 'production?keyword= ' . $ th ['id ' ];
260360 } else {
261361 $ url = $ this ->wpvulndb_api . 'themes/ ' . $ th ['id ' ];
262362 }
@@ -268,6 +368,8 @@ public function check_themes( $force = false, $service = '' ) { // phpcs:ignore
268368 if ( $ th_vuln ) {
269369 if ( 'nvd_nist ' === $ service ) {
270370 $ th_vuln_filter = $ this ->get_vuln_nvd_nist_info ( $ th_vuln , $ th ['id ' ], $ th ['version ' ] );
371+ } elseif ( 'wordfence ' === $ service ) {
372+ $ th_vuln_filter = $ this ->get_vuln_wordfence_info ( $ th_vuln , $ th ['id ' ], $ th ['version ' ] );
271373 } else {
272374 $ th_vuln = json_decode ( $ th_vuln , true );
273375 $ th_vuln_filter = $ th_vuln ;
@@ -535,37 +637,79 @@ public function get_vuln_nvd_nist_info( $data, $slug, $version ) { // phpcs:ign
535637 */
536638 public function vulnche_get_content ( $ url , $ service = '' ) {
537639
538- $ encrypted = get_transient ( 'mainwp_child_trans_wpvulndb_tk ' );
539- $ wpvulndb_token = MainWP_Child_Keys_Manager::instance ()->decrypt_string ( $ encrypted );
540-
541- // phpcs:disable WordPress.WP.AlternativeFunctions -- Required to achieve desired results, pull request solutions appreciated.
542- $ ch = curl_init ();
543- curl_setopt ( $ ch , CURLOPT_URL , $ url );
544- curl_setopt ( $ ch , CURLOPT_HEADER , 0 );
545- if ( 'nvd_nist ' !== $ service ) {
546- if ( empty ( $ wpvulndb_token ) ) {
547- if ( 'resource ' === gettype ( $ ch ) ) {
548- curl_close ( $ ch );
640+ if ( 'wordfence ' === $ service ) {
641+
642+ $ typeName = explode ( '= ' , $ url );
643+ if ( $ this ->wordfenceJson == '' ) {
644+ $ ch = curl_init ();
645+ curl_setopt ( $ ch , CURLOPT_URL , $ url );
646+ curl_setopt ( $ ch , CURLOPT_HEADER , 0 );
647+ curl_setopt ( $ ch , CURLOPT_USERAGENT , $ this ->get_random_user_agent () );
648+ curl_setopt ( $ ch , CURLOPT_RETURNTRANSFER , true );
649+ curl_setopt ($ ch , CURLOPT_FOLLOWLOCATION , true );
650+ $ response = curl_exec ( $ ch );
651+ $ this ->wordfenceJson = json_decode ($ response , true );
652+ }
653+ $ output = array ();
654+ $ resultData = array ();
655+ foreach ( $ this ->wordfenceJson as $ feed ) {
656+ if ( $ typeName [1 ] == $ feed ['software ' ][0 ]['slug ' ] ) {
657+ $ output [] = $ feed ;
658+
659+ $ resultData [] = array (
660+ 'CVE_data_type ' => isset ($ feed ['cve ' ]) ? 'CVE ' : '' ,
661+ 'references ' => array ( 'reference_data ' => $ feed ['references ' ] ),
662+ 'description ' => array ( 'description_data ' => $ feed ['description ' ] ),
663+ 'publishedDate ' => $ feed ['published ' ],
664+ 'lastModifiedDate ' => $ feed ['updated ' ],
665+ );
549666 }
550- return false ;
551667 }
552- curl_setopt ( $ ch , CURLOPT_HTTPHEADER , array ( 'Authorization: Token token= ' . $ wpvulndb_token ) );
553- }
554- curl_setopt ( $ ch , CURLOPT_USERAGENT , $ this ->get_random_user_agent () );
555- curl_setopt ( $ ch , CURLOPT_RETURNTRANSFER , true );
556668
557- $ output = curl_exec ( $ ch );
558- $ info = curl_getinfo ( $ ch , CURLINFO_HTTP_CODE );
669+ $ data = array (
670+ 'resultsPerPage ' => count ($ output ),
671+ 'startIndex ' => 0 ,
672+ 'totalResults ' => count ($ output ),
673+ 'result ' => array (
674+ 'CVE_Items ' => $ output ,
675+ ),
676+ );
559677
560- if ( 'resource ' === gettype ( $ ch ) ) {
561- curl_close ( $ ch );
562- }
563- // phpcs:enable
678+ return json_encode ($ data );
679+ } else {
680+
681+ $ encrypted = get_transient ( 'mainwp_child_trans_wpvulndb_tk ' );
682+ $ wpvulndb_token = MainWP_Child_Keys_Manager::instance ()->decrypt_string ( $ encrypted );
683+
684+ // phpcs:disable WordPress.WP.AlternativeFunctions -- Required to achieve desired results, pull request solutions appreciated.
685+ $ ch = curl_init ();
686+ curl_setopt ( $ ch , CURLOPT_URL , $ url );
687+ curl_setopt ( $ ch , CURLOPT_HEADER , 0 );
688+ if ( 'nvd_nist ' !== $ service ) {
689+ if ( empty ( $ wpvulndb_token ) ) {
690+ if ( 'resource ' === gettype ( $ ch ) ) {
691+ curl_close ( $ ch );
692+ }
693+ return false ;
694+ }
695+ curl_setopt ( $ ch , CURLOPT_HTTPHEADER , array ( 'Authorization: Token token= ' . $ wpvulndb_token ) );
696+ }
697+ curl_setopt ( $ ch , CURLOPT_USERAGENT , $ this ->get_random_user_agent () );
698+ curl_setopt ( $ ch , CURLOPT_RETURNTRANSFER , true );
699+
700+ $ output = curl_exec ( $ ch );
701+ $ info = curl_getinfo ( $ ch , CURLINFO_HTTP_CODE );
564702
565- if ( false === $ output || 200 !== (int ) $ info ) {
566- $ output = null ;
703+ if ( 'resource ' === gettype ( $ ch ) ) {
704+ curl_close ( $ ch );
705+ }
706+ // phpcs:enable
707+
708+ if ( false === $ output || 200 !== (int ) $ info ) {
709+ $ output = null ;
710+ }
711+ return $ output ;
567712 }
568- return $ output ;
569713 }
570714
571715 /**
0 commit comments