whT=QddlZddlZddlZddlmZddlmZddlmZm Z m Z m Z ddl m Z ddlmZddlmZmZmZddlmZdd lmZmZmZdd lmZmZdd lmZdd lm Z dd l!m"Z"ddlm#Z#ddl$m%Z%ddl&m'Z'm(Z(m)Z)ddl*m+Z+m,Z,ddl!m-Z-m.Z.m/Z/ddl0m1Z1ddl2m3Z3ej4e5Z6edej7Z8edej7Z9edZ:edZ;e:dz Zde?fdZ@GddeeZAdS) N)Path) Coroutine)ANTIVIRUS_MODEConfigValidationError SystemConfig UserConfig) HookEvent) MessageType) MessageSink MessageSourceexpect) hosting_panel) load_stateregister_lock_file save_state)Scoperecurring_check) check_lock)DAY)plugin) WordpressWPSite)get_sites_by_pathget_sites_for_userget_installed_sites)is_secret_expired rotate_secret)ChangelogProcessorIncidentCollectorIncidentSender)update_disabled_rules_on_sites)delete_old_wordpress_incidentsz wp-gen-authzwp-site-processz-/etc/sysconfig/imunify360/imunify360.config.dzF/opt/imunify360/venv/share/imunify360/11_on_first_install_wp_av.configz 11_on_first_install_wp_av.configz.11_on_first_install_wp_av.flagstarted_timestampreturnc ddlm}||S#t$rtdgcYSwxYw)z Get malware hits cleaned since the given timestamp with lazy import fallback. Returns empty list if imav.malwarelib is not available. r) MalwareHitz;imav.malwarelib not available, returning empty cleaned hits)imav.malwarelib.modelr' cleaned_since ImportErrorloggerdebug)r$r's V/opt/imunify360/venv/lib/python3.11/site-packages/defence360agent/plugins/wordpress.py_get_cleaned_malware_hitsr.Fsm 444444''(9:::  I    s&AAc eZdZejZdZdZdZdZ dZ dZ dZ dZ d ejfd Zd d efd ZdZeedeedZeeddedZdZdZdZdZdZe e!j"dZ#e e!j$dZ%e e!j$dZ&e e!j$dZ'e e(j)dZ*e e(j+dZ,dS)!ImunifySecurityPlugincZd|_d|_td}|d|_|d}||n t j|_ t j|_ n#t$r d|_ YnwxYwi|_ tj |_tj|_d|_d|_d|_t)|_t-|_t1|_t5|_d|_dS)Nr0 installedenabledT)_loop_sinkrgetinstallation_completedrSECURITY_PLUGIN_ENABLEDlast_config_value WAF_ENABLED_last_waf_enabledKeyError_last_user_waf_enabledr_get_global_ai_bot_protection_last_ai_bot_protection$_get_global_ai_bot_protection_preset_last_ai_bot_protection_presetinstallation_task deleting_taskinstall_and_update_tasksetfreshly_installed_sitesr incident_collectorr!incident_senderrchangelog_processor_site_processing_task)selfstatepersisted_enableds r-__init__zImunifySecurityPlugin.__init__Zs/  233&+ii &<&<#"IIi00!,  2   *%.%:D " " * * *%)D " " " *>@#(.'K'M'M$  7 9 9 +7;26<@$47EE$#4"5"5-//#5#7#7 :>"""s#A55B B c KdSN)rKloops r- create_sinkz!ImunifySecurityPlugin.create_sink}s  cK||_||_|j||_|j||_tr|d{Vnt d| d{VdS)NT) missing_ok) r4r5 create_taskrefresh_auth_files_update_auth_taskprocess_wordpress_sitesrJr_apply_first_install_configFIRST_INSTALL_FLAGunlink _recover_installation_on_startup)rKrRsinks r- create_sourcez#ImunifySecurityPlugin.create_sources  !%!7!7  # # % %" " &*Z%;%;  ( ( * *& & "  72244 4 4 4 4 4 4 4 4  % % % 6 6 63355555555555rTc,K|js tjsdStdd|_|tj|j d{V|j !|j |j dSdS)a Self-heal when the installation state was lost. If the feature is enabled but installation_completed is falsy (state file missing, earlier install interrupted, etc.), manage_plugin_installation can never recover: its True == True guard always returns early. Trigger install_everywhere once per restart to repopulate the wordpress_site table and flip the flag. NzXInstallation state is missing while feature is enabled; triggering startup self-recoveryTr_) r7rr8r+infor9process_installationrinstall_everywherer5rBadd_done_callback_mark_installation_donerKs r-r^z6ImunifySecurityPlugin._recover_installation_on_startups  ' 4  F  /   "&''  %4: 6 6 6           ! -  " 4 4,      . -rTcfKtsdStjd{VdkrKt t}t dt dS)Ni) r\existsr HostingPanel users_countFIRST_INSTALL_CONFIG_PATH write_textFIRST_INSTALL_CONFIG_FILE read_textchmodr])rK_s r-r[z1ImunifySecurityPlugin._apply_first_install_configs!((**  F+--99;; ; ; ; ; ; ;q @ @)44)3355A & + +E 2 2 2!!#####rTcK|j|jd{V|jr(|j|jd{VdSdSrP)rYcancelrJrhs r-shutdownzImunifySecurityPlugin.shutdowns %%'''$$$$$$$$  % -  & - - / / /, , , , , , , , , , - -rTct||std|dSt||}|duo)| o| S)NzUnknown task '%s'F)hasattrr+errorgetattrdone cancelled)rKtask_attr_nametasks r-_task_in_progressz'ImunifySecurityPlugin._task_in_progresssit^,,  LL,n = = =5t^,,4L OLDNNFeature was disabled during installation, skipping flag updateT)r|r+rc exceptionryr9r7r)rKr~excs r-rgz-ImunifySecurityPlugin._mark_installation_dones >>    KK9 : : : Fnn ? LL7 = = = F%  KK'    F&*# %%'''''rTFcorocK|dr\|r|dS|jr=|j |jd{Vn#tj$rYnwxYw|dr0t d|dSt j||_ dS)NrCrBzInstallation is already running) rcloserCruasyncioCancelledErrorr+warningrWrB)rKr for_new_sitess r-rdz*ImunifySecurityPlugin.process_installations  ! !/ 2 2   ! "))+++,,,,,,,,,-D  ! !"5 6 6  NN< = = = JJLLL F!(!4T!:!:s AA10A1cPK|drD|jr=|j |jd{Vn#tj$rYnwxYw|drt ddStj||_dS)NrBrCzDeleting is already running) rrBrurrr+rrWrC)rKrs r-process_deletingz&ImunifySecurityPlugin.process_deletings  ! !"5 6 6 % &--///000000000-D  ! !/ 2 2  NN8 9 9 9 F$066s AAAT)check_period_firstcheck_lock_period lock_filecKtrtd{Vtj|jd{VdSNrb)rrrupdate_auth_everywherer5rhs r-rXz(ImunifySecurityPlugin.refresh_auth_filess`    "// ! ! ! ! ! ! !+<<<<<<<<<<<zAImunifySecurityPlugin.process_wordpress_sites..;s>>>!QX>>>rT)domainsr_T)delete_after_processing)daysz*Error in WordPress periodic processing: %s)r+r,rrIprocess_changelogs_for_sitesr5r"rGcollect_incidents_for_sitesrHsend_incidentsr# Exceptionry)rKsitesaffected_sites incidentses r-rZz-ImunifySecurityPlugin.process_wordpress_sitess   A   ! J'))E  F.KK4:   4>>~>>>-II,0J &55dj)LL L L L L L L L * 3 3 3 3 3 3 J J J LLEq I I I I I I I I I Js*C2 B&C22 D"<DD"cKjfd}|dd{VdS)z&Install plugin on new WordPress sites.cKtjjd{V}|rj||Sr)rrer5rFupdate)installed_sitesrKs r-install_and_trackzFImunifySecurityPlugin._install_on_new_sites..install_and_trackSsT$*$=4:$N$N$NNNNNNNO E,33ODDD" "rTT)rN)rFclearrd)rKrs` r-_install_on_new_sitesz+ImunifySecurityPlugin._install_on_new_sitesNs $**,,, # # # # # ''    (           rTc\Ktj|j|jd{Vtj|jd{Vt jsW|tj|jd{Vd|_ d|_ | dSdS)zCTidy up sites from which the WordPress plugin was deleted manually.)r_rFNrbF) rtidy_up_manually_deletedr5rF$fix_data_file_permissions_everywhererr8rremove_all_installedr7r9rrhs r-_tidy_upzImunifySecurityPlugin._tidy_up^s-$($@          9tzJJJJJJJJJJ0 ,''+<<<       +0D '%*D "  ) ) + + + + +  , ,rTcKtj|jd{V}|r|j|dSdS)zFAdopt sites where plugin is installed but not tracked in our database.rbN)radopt_found_sitesr5rFr)rK adopted_sitess r-_adopt_found_sitesz(ImunifySecurityPlugin._adopt_found_sitesns^$6DJGGGGGGGGG   ?  ( / / > > > > > ? ?rTcJKtj|jd{VdS)z1Update plugin on all sites where it is installed.rbN)rupdate_everywherer5rhs r-_update_existingz&ImunifySecurityPlugin._update_existingvs4&DJ777777777777rTcK|d{V|jr |jd{V|d{V|d{V|d{VdS)z Combined operation: install on new sites, adopt found sites, tidy up, and update existing plugins. This runs all operations sequentially to avoid race conditions. N)rrBrrrrhs r-_run_install_and_updatez-ImunifySecurityPlugin._run_install_and_updatezs((*********  ! )( ( ( ( ( ( ( (%%'''''''''mmoo##%%%%%%%%%%%rTcRKtd|j|j|dr"td|jdS|jdkr%|jsdS|d{VdS|dr"td|jdS|dr"td|jdS|jd kr|d{VdS|jd kr| d{VdS|jd krP|jstd dStj | |_ dSdS) NzInstallation is not completed yet, skipping install_and_update)r+rcactionmethodrrr7rrrrrWrrD)rKmessages r-manage_plugin_actionz*ImunifySecurityPlugin.manage_plugin_actions J N N     ! !"; < <  NNI    F >3 3 3. ,,.. . . . . . . . F  ! !"5 6 6  NNC    F  ! !/ 2 2  NNG    F >. . .'')) ) ) ) ) ) ) ) F >Y & &--// ! ! ! ! ! ! ! F >1 1 1. * ,3+>,,..,,D ( ( ( 2 1rTcKt|dtsdStj}||jkrdS||_|r-|js% tdddiid|_n*#t$rt dYnwxYw tdddiid|_ tj |_n*#t$rt dYnwxYw|tj|j d{V|j!|j|jdSdS|sl|js|d rR|tj|j d{Vd|_|dSdSdS) Nconf WORDPRESS waf_enabledTz9waf_enabled config reset skipped, field not in schema yetai_bot_protectionFz?ai_bot_protection config reset skipped, field not in schema yetrbrB) isinstancerrr8r9r7dict_to_configr;rr+r,r?rr@rArdrer5rBrfrgrrrr)rKrcurrent_config_values r-manage_plugin_installationz0ImunifySecurityPlugin.manage_plugin_installations'&/<88  F(@ 4#9 9 9 F"6 , ,(C, , -- =$"78*.&&(    O  -- #6">?05,?AA33)    /  ++)tz:::       %1&88021 & ,  ' ,%%&9:: ,''+<<<       +0D '  ) ) + + + + + , , , ,s% ,A99$B B $AC))$DDcKt|dtsdStjsdS|jsdSt j}t j}||jkr ||j krdS|j dtd{V}|s||_||_ dSt j |d{V}|t|kr||_||_ dSdS)a Propagate admin toggles of WORDPRESS.ai_bot_protection and WORDPRESS.ai_bot_protection_preset to every managed WP install's plugin_config.php immediately, so the WP plugin picks up the change at the next request rather than waiting for a scan cycle. Phase 2 per-account support extends *this* handler with a UserConfig branch (mirroring manage_waf_config); do not add a sibling handler. rN)rrrr8r7rr>r@r?rAr4run_in_executorrupdate_plugin_config_on_siteslen)rKrcurrent_enabledcurrent_presetrwrittens r-manage_ai_bot_protection_configz5ImunifySecurityPlugin.manage_ai_bot_protection_configs'&/<88  F0  F*  F >@@DFF t; ; ;$"EEE Fj007JKKKKKKKK +:D (2@D / F no sites found for cleaned hitsz1Cleanup finished => %s site(s) need to be updatedc8g|]\}}t|d|S))docrootruidr)r site_pathrs r-rzIImunifySecurityPlugin.handle_malware_cleanup_finished..s;    3 9RS 9 9 9   rTz"%s site(s) updated after a cleanup)r9r6r.rE resource_typepwdgetpwnamuserrpw_uid orig_file startswithaddr<r+r,rcrrupdate_data_on_sitesr5) rKrhits site_pathshit user_info user_sitesrrwordpress_sitess r-handle_malware_cleanup_finishedz5ImunifySecurityPlugin.handle_malware_cleanup_finishedVs %  F ;;x D ( ( I0F0F ( F));<<UU   C F**  # SX 6 6I!3I!>!>J,5? ((4&0"" =33I>>"&NNIs+;<<<!E" D+  LLN O O O F ?  OO     ",    )$*oFFFFFFFFF 8#o:N:NOOOOOs/A+C C('C(cK|jsdS|ddks*|dr|dsdS|d}t|}|std|dStdt |tj|j |d{Vtdt |dS) a INFO [2025-02-24 11:57:17,968] imav.plugins.wordpress: Malware scan finished: HookEvent.MalwareScanningFinished( { 'scan_id': 'b9bd136aff0a4d87a248c859cfe41c47', 'scan_type': 'user', 'path': '/home/user1' } ) INFO [2025-02-24 12:00:10,740] imav.plugins.wordpress: Malware scan finished: HookEvent.MalwareScanningFinished( { 'scan_id': 'a74271d2cdd04e0c9bd49ef6de23e0d8', 'scan_type': 'user', 'path': '/home/user4', 'started': 1740398383, 'total_files': 39229, 'total_malicious': 3, 'error': None, 'status': 'ok', 'scan_params': {'intensity_cpu': 2, 'intensity_io': 2, 'intensity_ram': 2048, 'initiator': None, 'file_patterns': None, 'exclude_patterns': None, 'follow_symlinks': False, 'detect_elf': True}, 'stats': {'scan_time': 27, 'mem_peak': 28217344, 'smart_time_hs': 0.004, 'scan_time_hs': 1.1751, 'smart_time_preg': 0, 'scan_time_preg': 2.7391, 'finder_time': 13.5896, 'cas_time': 0.7562, 'deobfuscate_time': 0.8998, 'total_files': 39229} } ) Nrrpathstatsz+Scan finished => no sites found for path=%sz.Scan finished => %s site(s) need to be updatedz%s site(s) updated after a scan) r9r6rr+r,rcrrrr5)rKrrrs r-handle_malware_scan_finishedz2ImunifySecurityPlugin.handle_malware_scan_finisheds8%  F KK ! !T ) );;v&& *;;w'' * Fv!$''  LLF M M M F  P>P.->P@ VI -..4C4C/.4C4C4CrTr0)Brloggingrpathlibrtypingr defence360agent.contracts.configrrrr%defence360agent.contracts.hook_eventsr "defence360agent.contracts.messagesr !defence360agent.contracts.pluginsr r r defence360agent.subsys.panelsr'defence360agent.subsys.persistent_staterrrdefence360agent.utilsrr defence360agent.utils.check_lockrdefence360agent.utils.commonrdefence360agent.wordpressrrdefence360agent.model.wordpressr)defence360agent.wordpress.site_repositoryrrr$defence360agent.wordpress.proxy_authrrrr r! defence360agent.wordpress.pluginr"(defence360agent.model.wordpress_incidentr# getLoggerrr+rrr  CONFIG_DIRrprnr\floatlistr.r0rQrTr-r$s@  <;;;;;:::::: 877777 98888888777777,,,,,,,,,,,,666666222222  LKKKKK  8 $ $  }en = = ..u~TA B B  DL')KK"CC4"u Cu Cu Cu Cu CKu Cu Cu Cu Cu CrT