From JBRJ to JUCEC: Exposed Infrastructure Reveals a Broad Brazilian Government Intrusion Campaign
A forensic look at exposed attack directories containing a confirmed JBRJ compromise, a JUCEC intrusion toolkit, credential-harvesting infrastructure, webshells, persistence mechanisms, and a staged Linux kernel privilege-escalation exploit.
- Published
- Reading time
- 34 min
- Analyst
- @volrant136
- Region
- Brazil
- Cybersecurity
- Open Directory
- SQL Injection
- Active Directory
- Webshell
- Kernel Exploit

Contents
Hunt.io Attack Capture (opens in a new tab) flagged three open directories on a single Malaysian VPS between August 27 and August 29, 2026, on ports 9998, 18080, and 18082.
The evidence confirms active compromise of the Brazilian Federal Biodiversity Research Institute, a reusable Zimbra and Active Directory hunting kit already inside a Brazilian state government network, and a portable Linux kernel privilege-escalation toolkit staged alongside the other attack infrastructure.
Let's walk through what was recovered.
Key Findings
-
Hunt.io tracked
threeopen directories at111.90.145[.]92(Kuala Lumpur, Malaysia, Shinjiru Technology Sdn Bhd,AS45839) on ports 9998, 18080, and 18082. -
Port 9998 documents a confirmed, multi-stage compromise of the
Instituto de Pesquisas Jardim Botânico do Rio de Janeiro (JBRJ), Brazil's federal botanical research institute. -
Port 18082 is a self-contained
"z-kit"already deployed inside JUCEC, theJunta Comercial do Estado do Ceará (Ceará's state Board of Trade), a Brazilian state government agency. -
Port 18080 is a clean, multi-language mirror of a public POC for
CVE-2026-31431("Copy Fail"), a real Linux kernel local privilege escalation bug.
Host Infrastructure
Hunt.io lists 111.90.145[.]92 (opens in a new tab) under Shinjiru Technology Sdn Bhd (AS45839), based in Kuala Lumpur, Malaysia, with three open-directory warnings on record: two dated 2026-08-27 and one dated 2026-08-29.

At 111.90.145[.]92:9998 (opens in a new tab), an exposed open directory contained 289 files with no subdirectories, totaling approximately 615 KB. Hunt.io recorded the directory on 2026-08-29.

111.90.145[.]92:9998, containing 289 files totaling approximately 615 KB.At 111.90.145[.]92:18082 (opens in a new tab), the exposed opendir contains 434 files across four subdirectories, totaling approximately 553 KB. The directory was observed on 2026-08-27, indicating a second exposed service on the same infrastructure.

111.90.145[.]92:18082, containing 434 files across four subdirectoriesA third instance was accessible at 111.90.145[.]92:18080 (opens in a new tab), exposing 87 files across two subdirectories with a total size of approximately 1.83 MB. Hunt.io recorded this directory on 2026-08-27, providing another exposed directory on the same host.

111.90.145[.]92:18080, containing 87 files across two subdirectories.The table below shows the full scope.
| Port | Captured | Files | Size | Theme |
|---|---|---|---|---|
| 9998 | 2026-08-27 to 08-29 | 289 files | 615 KB | Confirmed compromise of a Brazilian federal biodiversity institute (JBRJ) |
| 18082 | 2026-08-27 | 434 files | 553 KB | Zimbra, Active Directory, and helpdesk hunting kit inside JUCEC (Ceará state government) |
| 18080 | 2026-08-27 | 87 files | 1.83 MB | Portable dropper for CVE-2026-31431, a Linux kernel privilege escalation bug |
Compromise of the Rio de Janeiro Botanical Garden Research Institute (JBRJ)
The scripts in 111.90.145[.]92:9998 share the local path prefix /root/pentest/florariojaneiro/loot/, matching the target subdomain florariojaneiro.jbrj.gov.br (opens in a new tab).
A copy of the target's page source, saved as extra_painel_php, confirms the domain with the tag <meta property="og:url" content="//florariojaneiro.jbrj.gov.br/">.
The evidence carries enough timestamps to reconstruct roughly two days of the intrusion.

Stolen Internal Documentation
The files appear in two naming formats: the original filename and a second version with the internal repository path flattened into the filename (extra_docs_PAINEL_CONSULTAS_SQL_md, corresponding to docs/PAINEL_CONSULTAS_SQL.md referenced in AGENTS.md). The copies are identical and contain JBRJ internal data, including the staging host, .env path, and SQL audit panel source. This indicates the files came from the compromised host.
| File(s) | What it is |
|---|---|
AGENTS.md, extra_AGENTS_md, extra__agents_README_md | JBRJ's own onboarding file for AI coding agents, explicitly naming "Cursor, Codex, Claude Code, local automation, etc." and describing the FloraRJ dev server and .env credential layout |
DECISIONS.md | JBRJ's internal architectural decision log |
PAINEL_SQL.md, extra_docs_PAINEL_CONSULTAS_SQL_md, extra_docs_PAINEL_DIAGNOSTICO_md, extra_painel_php | Internal documentation and source for JBRJ's own SQL audit panel |
RELATORIO_E8.md, SPEC001.md, TEST_PLAN.md, extra_docs_specs_001-security_* | JBRJ's own security spec and the results of its automated test suite: 9 passed, 15 failed, 2 skipped |
extra_docs_specs_003-infra-security_scripts_run_infra_tests_php | JBRJ's own infrastructure/CSP test runner output |
_js_custom.js, _js_pages_cadlote.js, _js_pages_cadusuario.js, _js_pages_consusuario.js, login.js | Front-end JavaScript pulled from the live application |
flora_swagger.json, jabot_swagger.json | Stolen API definitions for two of JBRJ's applications |
florario_README.md, jabotimage_README.md, florarj_relatorio.xlsx | JBRJ's own project descriptions and a report export |

The Exploitation Chain: Two Bugs, One Portal
The open directory contains 77 ipt_*.py scripts driving an attack chain against ipt.jbrj.gov.br, JBRJ's GBIF Integrated Publishing Toolkit (IPT) instance. The scripts target two separate vulnerabilities, which the operator's tooling labels as CVE-2026-71880 and CVE-2026-71878.
| Label | Bug class | Entry point | Scripts |
|---|---|---|---|
| CVE-2026-71880 (opens in a new tab) | FreeMarker SSTI | manage/metadata-basic.do resource metadata fields | ipt_check_ssti.py, ipt_preview_ssti.py, ipt_ssti.py, ipt_ssti_500.py, ipt_ssti_ctrl.py, ipt_ssti_inc.py, ipt_ssti_ls.py, ipt_ssti_sq.py, ipt_ssti_rce.py |
| CVE-2026-71878 (opens in a new tab) | Missing auth on first-run setup flow | setupDefaultAdministrator.do | ipt_cve71878.py, ipt_cve_interno.py, ipt_race.py |
The scripts can be summarized as follows:
-
ipt_check_ssti.pyandipt_preview_ssti.pylocate the injection point. -
ipt_ssti.py, labeled internally as CVE-2026-71880, exploits a FreeMarker?interpretserver-side template injection through IPT resource metadata.
Figure 7: ipt_ssti.pyshows automated FreeMarker SSTI testing against the JBRJ IPT application. -
ipt_ssti_500.py,ipt_ssti_ctrl.py,ipt_ssti_inc.py,ipt_ssti_ls.py,ipt_ssti_sq.py, andipt_ssti_rce.pyiterate on that SSTI, capturing error bodies, testing file reads, and eventually publishing a private IPT resource whose description field carries the payload. -
ipt_cve71878.pyandipt_cve_interno.pytarget a second, separately labeled bug,CVE-2026-71878, by posting to IPT'ssetupDefaultAdministrator.doendpoint to create an extra administrator account under the emailipt.ops.2026@jbrj.organd a password redacted here asJb_REDACTED_.
Figure 8: ipt_cve71878.pyshows an automated exploitation of the IPT administrator creation flaw. -
ipt_race.pyruns theCVE-2026-71878exploit as a race condition, flooding IPT's origin-validation threads soisBaseURLValid()times out and the check can be bypassed. -
ipt_sql_source.py,ipt_fileurl.py,ipt_fileurl_mp.py,ipt_next.py,ipt_analyze.py,ipt_commit.py,ipt_cte_write.py, andipt_dblink.pybuild out IPT's own JDBC "SQL source" and DuckDB integration features into a file-read and command-execution primitive, including forcing committed writes viadblink_execso they survive IPT's normal transaction rollback. -
ipt_duck_files.py,ipt_duck_sqli.py,ipt_duckdb.py, andipt_duckdb2.pypush that further, using DuckDB'sread_blob,read_csv, andCOPYfunctions to read arbitrary host files and write new ones through IPT's own database layer.
From SSTI to a JSP Web Shell and Confirmed Code Execution
After gaining file-write access, the attacker used 14 scripts (ipt_jsp_fauna.py through ipt_jsp_fauna13.py) to develop and update a JSP web shell. The shell was written through IPT’s DuckDB file-write function rather than a separate upload flaw, while other scripts handled the remaining post-exploitation steps:
| Script | Purpose |
|---|---|
ipt_jsp_cont.py | Continued shell interaction, first io_uring capability probe |
ipt_jsp_decrypt.py, ipt_jsp_secrets.py | Decrypting and reading application secrets through the shell |
ipt_jsp_fstab.py, ipt_jsp_recon.py, ipt_jsp_recon2.py, ipt_jsp_svcs.py | Host and mount reconnaissance |
ipt_jsp_iouring.py, ipt_jsp_lpe_cves.py | Local privilege escalation preconditions, described by the operator's own docstring as testing "recent Linux LPE CVE preconditions inside IPT tomcat container" |
ipt_jsp_iptuser.py, ipt_jsp_pg.py, ipt_jsp_sqlxml.py | IPT and PostgreSQL configuration extraction |
ipt_jsp_privesc.py, ipt_jsp_privesc2.py, ipt_jsp_su.py | Container privilege-escalation enumeration |
ipt_jsp_sshhost.py | Drops a JSch SSH client into the container to spray port 22 on nearby hosts |
ipt_tomcat_rce.py, ipt_tomcat_shell.py, and ipt_tomcat_pivot.py drive the same shell to enumerate the Tomcat service, write a cleaner command-execution JSP, and pivot toward other internal hosts. ipt_persist.py plants a backup copy on the container's EFS mount, with an inline comment telling the tool not to touch /srv/ipt/config, and ipt_restore.py re-drops the JSP if a container rebuild wipes it.

The directory contains 29 raw output files, all prefixed with rce_, capturing the output returned by the executed commands.
| Finding | File | Value |
|---|---|---|
| Shell identity | rce_id.txt | uid=999(tomcat) gid=999(tomcat) groups=999(tomcat) |
| Kernel/OS | rce_uname.txt | Linux 66f0afa1a05f 6.8.0-1047-aws, Ubuntu 24.04 |
| Cloud region | rce_hosts.txt | DNS search domain sa-east-1.compute.internal, AWS São Paulo |
| File write confirmed | rce_write_jsp.txt, rce_write_txt.txt | JSP and marker files written under the Tomcat webroot at 10:44 UTC |
| IPT config | rce_ipt_props.txt | Base URL and administrator contact address from IPT's own properties file |
| Config file inventory | rce_aws_files.txt | Every .properties/config file discovered under the Tomcat webapps directory |


rce_id.txt and rce_uname.txt, confirming interactive command execution as the Tomcat service account.Two Stolen Sets of AWS Temporary Credentials
extract_imds.py, ipt_imds_role.py, ipt_imds_ssti.py, and ipt_imds_url.py abuse the IPT/Tomcat foothold to reach the EC2 Instance Metadata Service. The operator recovered two sets of temporary AWS credentials from the instance metadata service, associated with two IAM roles.:
| Source file | IAM role | Retrieved (UTC) | Expired (UTC) | AccessKeyId | SecretAccessKey |
|---|---|---|---|---|---|
aws_ec2_idcred.json | (unnamed instance role) | 07:56:08 | 14:15:55 | AS_REDACTED_ | zC_REDACTED_ |
aws_ssm_role.json, rce_imds_role.txt | _redacted_ | 09:54:14 | 15:54:53 | AS_REDACTED_ | xV_REDACTED_ |
ipt_aws_enum.py and ipt_aws_enum2.py use the boto3 SDK with the stolen role keys to enumerate AWS services region by region.

aws_ssm_role.json, one of two stolen AWS IMDS temporary credential sets recovered from the compromised Tomcat container.ipt_aws_logs.py uses the same credentials to query CloudWatch log groups, streams, and events, likely seeking additional secrets or evidence of the intrusion in JBRJ's logging infrastructure.

ipt_aws_logs.py querying CloudWatch logs using the stolen SSM role credentials.rce_imds_list.txt and rce_imds_net.txt capture the IAM role name and the container's internal network details that enabled the IMDS pivot.
Credential Harvesting Across JBRJ's Application Stack
With access to IPT, the operator started targeting other systems. access.txt, a notes file kept by the operator, records the accounts they tried, the passwords that worked, and brief notes about what each account could access. The full scope is easier to understand in one table before looking at how each application was accessed:
| Application | Source | Role/Note |
|---|---|---|
| GBIF IPT | ipt_cve71878.py, access.txt | Rogue admin account created by the operator |
| JABOT | access.txt | Staff/administrator, account ID X |
| JABOT | spray_edalcin.py | Named administrator account the insert scripts were told not to touch directly |
| jabotimage | access.txt, jabotimage_admin.py | ADMINISTRADOR, named in comments as the system's original developer |
| jabotimage | access.txt | OPERADOR |
| CITSmart | ipt_img_citsmart.py | IT service management console |
| CKAN | ckan_verify.py | Open-data portal |
| Fauna do Brasil (Jardim DB) | access.txt | Decrypted from a JDBC connection pool secured with a PBE passphrase |
| Fauna do Brasil (Jardim DB) | access.txt | Same decryption pass |
| Fauna do Brasil (application login) | access.txt | Unlocks a self-built PostgreSQL instance separate from Jardim |
| Fauna do Brasil (self-created operator) | access.txt | Inserted directly into fauna_ca.op_c_a with profile level 8 (GerenteDeUsuarios) |
| Fauna do Brasil (existing librarian) | access.txt | Live, pre-existing account, not created by the operator |
| Fauna do Brasil (five staff/partner accounts) | fauna_auth_hashes.txt | icmbio and sibbr are Brazil's federal conservation agency and national biodiversity information system; wcmc is an international conservation-monitoring partner |
| GBIF.BR organization token | access.txt | Identical string to the CKAN secret above; the operator reused one secret across two unrelated systems |
| DataCite API key | access.txt | Controls DOI minting for JBRJ's published datasets |
| IPT web-service password | access.txt | Found alongside the Jardim database secrets |
| PostgreSQL (Jardim schema) | ipt_insert_ops.py, ipt_write_user.py | Operator's own account inserted directly into the Jardim and jabot_image databases |
JABOT and jabotimage: A Ten-Script Account-Takeover Pipeline
The ten scripts form a step-by-step workflow for JABOT and its image system. The docstrings in each script describe the changes made at each stage, making it possible to follow the process from one script to the next:

The sequence of unlocking accounts, cracking a reset token, setting a new password for a real staff account, and then moving into file inclusion and upload-based RCE testing shows a deliberate, staged compromise.

jabot_takeover.py script connected with a staff account gives the operator a working login.Fauna do Brasil: A Second, Self-Built Database Foothold
The credentials in access.txt provided access beyond the five bcrypt-hashed application accounts. The notes also exposed database credentials, privileged accounts, API credentials, and reused secrets across multiple systems:
-
A Java PBE-protected JDBC connection pool was listed under the internal label "Carla Maria Luise". The operator manually decrypted it and recovered plaintext credentials for
florarjandipt, both associated with the Jardim database. -
The credential
fauna/!f_REDACTED_provided access to a separate PostgreSQL environment. The environment was PostgreSQL 15.1 on Ubuntu and included thefaunaandfauna_cadatabases. -
The PostgreSQL environment exposed
supabase_adminandpostgressuperuser accounts. -
The operator wrote directly to
fauna_ca.op_c_aand created an account namediptops26with passwordOp_REDACTED_and profile level8(GerenteDeUsuarios, or user manager). -
The same
iptops26credentials were also added to PostgREST's authentication table, providing an API-level identity in addition to the database record. -
The notes contained credentials for an existing librarian account,
rforzza/fl_REDACTED_, along with other staff accounts protected by weak passwords. -
Other exposed secrets included a GBIF.BR organization token and a
DataCite API keyused for DOI minting for JBRJ datasets. -
The GBIF.BR organization token was also reused as the password for the
CKANcentralitaccount, linking credentials across two otherwise separate systems.

access.txt shows the operator's own running notes.Note:
fauna_crack.pyruns the hashes againstrockyou.txtand a separatefauna_wl.txtwordlist. The custom list includes the target's name as well as plaintext passwords that had already been recovered from IPT and Jardim. This shows that credentials found in one part of the environment were being reused to test access to another.
CKAN, CITSmart, and the Downstream RDS Instance
ipt_pg_dump.py, ipt_pg_grants.py, ipt_pg_plain.py, ipt_pg_plain2.py, and ipt_pg_users.py query JBRJ's PostgreSQL instance, identified in the code comments as JBRJ RDS instance, through IPT's SQL source feature. The scripts specifically look for short, plaintext-recoverable passwords in the Jardim application schema.
ckan_rds.txt documents a separate PostgreSQL finding involving an internally labeled CVE-2026-42031 (opens in a new tab) ts_rewrite issue. The issue was confirmed against the ckan_default role, which was not a superuser, on RDS host running PostgreSQL 16.13.
-
The flaw provided a
CONNECTpath to multiple databases. -
The affected databases covered several parts of the institute's infrastructure, including the
data catalog, GIS, and IT service management systems. -
The operator could also enumerate admin database roles on the instance and named staff accounts.
-
ckan_users.jsoncontains a dump of the CKAN user table, including account IDs, creation dates, sysadmin flags, and named staff and partner-organization accounts. -
The dump also includes accounts belonging to
JBRJ IT staffthat were marked with the sysadmin flag.

ckan_users.json, a harvested dump of the CKAN portal's user table, showing sysadmin flags, creation timestamps, and named staff and partner-organization accounts.Note:
reuse_flora.pyandreuse_gbif_pw.pytry passwords recovered elsewhere in the campaign against CITSmart, CKAN, and Matomo.spray_edalcin.pyandspray_plain.pytest a small set of weak, organization-related passwords against the same applications. The end ofaccess.txtalso contains persistence notes, including a hidden loot directory at/srv/ipt/logs/.dw/and a note that daily access is handled throughipt_sh.py "id".
Kernel Exploit Staging on the Compromised Container
iouring_probe.c is a small, self-contained io_uring_setup() syscall probe used to check whether the target kernel exposes the io_uring interface before attempting an io_uring-based local privilege escalation. ipt_jsp_iouring.py runs the same check remotely through the JSP shell, while ipt_jsp_lpe_cves.py tests preconditions for recent Linux LPE CVEs, as described in its own docstring.
Note: The scripts show that the operator was testing ways to move beyond the low-privileged
tomcataccount.

iouring_probe.c, a minimal io_uring capability check staged alongside the confirmed Tomcat RCE and matched by ipt_jsp_lpe_cves.py's remote CVE-precondition probe.A Zimbra, Active Directory, and Helpdesk Hunting Kit Live Inside Junta Comercial do Estado do Ceará
The open directory at 111.90.145[.]92:18082 contains 321 files, most of which are small PHP, PowerShell, Python, C#, or compiled JAR utilities.
The files appear to have been deployed for activity against JUCEC, the Junta Comercial do Estado do Ceará (Ceará's state Board of Trade), and its e-Simples business registration portal.
The servers below were identified from IP addresses that recur across dozens of scripts:
| Role | How it was reached |
|---|---|
| Active Directory domain controller | LDAP bind, then SMB as _redacted_\Administrator |
| File server, JUCEC document and backup shares, "Núcleo de Tecnologia" | SMB as _redacted_.sync and _redacted_ |
| Openfire XMPP/chat server, port 9090 | Directory-traversal to an admin JSP endpoint |
| Microsoft SQL Server | Live connection string with an application account |
| Zimbra mail server | SOAP admin probing, SMTP spraying |
| Operator's own WampServer relay inside the network | Already fully controlled, used to stage further attacks |
| Unidentified internal host | Probed, not confirmed compromised |
A Shared Webshell Key Ties the Kit Together
I found the same hardcoded key, Hx_Redacted_, in 34 different webshells across the directory, spanning PHP, ASP.NET, JSP, Python, and PowerShell. The analysis shows that the webshells support directory listing, file reading, and command execution, as shown in the table below.
| File(s) | Platform | What it does |
|---|---|---|
mini.php, gate.php | PHP | Base shell with three core functions: directory listing (ls), file reading (cat), and command execution (c) |
g.aspx | ASP.NET / IIS | Same base commands, ported to execute cmd.exe on IIS hosts |
hxok.jsp | Java / Tomcat | Same base commands, ported to execute /bin/sh on Tomcat hosts |
p.php | PHP | Adds cu to fetch an arbitrary URL with curl.exe, and smtp to speak SMTP over a raw socket to a Zimbra server while spoofing noreply@jucec.local |
setup.php | PHP | Uses GLPI's GLPIKey and Toolbox::sodiumDecrypt classes to decrypt and return stored SMTP, proxy, and database passwords as JSON |
lang-english.php | PHP | Disguised as a language file; its drop2 parameter fetches p.php from the operator's port 18082 directory and writes it to two IIS webroots |
da.php | PHP | Obfuscated 50 KB loader that builds function names with chr(), decodes a hex-encoded blob, and executes it at runtime |
drop.ps1 | PowerShell | Copies the shell to the operator's internal WampServer relay over SMB and confirms access with whoami |
drop.py | Python | Uses the planted shell to deploy a ScriptCase NetMake config-decoder probe and zadm.php, the Zimbra password-spray script discussed earlier |
gsc_run.py | Python | General-purpose command runner for the key-gated shell |
sc.py | Python | Core ScriptCase task runner over HTTP |
scclean.py | Python | Deletes dropped files after a task is completed |
scfin.py | Python | Verifies that a task completed successfully |
scinv.py | Python | Inventories installed applications on the reached host |
scpersist.py | Python | Re-deploys the shell if it is removed |
scsvc.py | Python | Checks service status on the reached host |
scof.py | Python | Openfire-specific variant of the command runner |
sc-* and persist-* scripts | PowerShell / PHP | Copies the shell onto newly reached hosts |
z*-run.ps1 scripts | PowerShell | Zimbra-specific launchers for the same shell |
zcb.txt, marker.txt | Text | Marker files containing HIT or pwn, used to confirm that a new location is writable before staging additional files |
Zimbra Mail Server: SOAP Reconnaissance, Authentication Bypass Testing, and SMTP Spraying
The port 18082 directory contains more than 50 scripts and support files related to Zimbra. The main findings are:
-
Access paths: The scripts cover unauthenticated admin SOAP reconnaissance on port 7071, account-level SOAP authentication, SMTP on ports 25 and 587, and direct SSH access.
-
Credential spraying:
nspray.ps1tests ten credential pairs against four named JUCEC staff members acrossjucec.ce.gov.brandesimples.ce.gov.br. -
SMTP testing:
smtptryp.ps1tests another ten passwords against a single mailbox. -
Mailbox access:
zmail.pysuccessfully logs intoglpi@esimples.ce.gov.br, obtains a live Zimbra session token, and uses it to search the account's inbox. This is the only confirmed mailbox compromise found in the directory. -
Credential reuse: The same credentials are later tested against Gmail IMAP.
-
Internal relay: The already-compromised host
10.25.x.xis used to relay SOAP traffic, making the requests appear to originate from an internal system. -
File deletion:
zrm.ps1deletes eighteen named files after the activity is complete.

Active Directory: Working Domain Credentials and NTDS Extraction
Thirteen scripts handled the initial directory enumeration using the reused _redacted_.sync credential. They connected to the domain controller and enumerated the environment before elevated access was available. Two scripts, next.ps1 and smb2.ps1, later used the recovered _redacted_\Administrator credential to access the domain's administrative shares.
-
Initial enumeration: Thirteen scripts used
_redacted_.syncto query the domain controller and enumerate the directory. -
Administrator access:
next.ps1andsmb2.ps1used the recovered_redacted_\Administratorcredential with full domain administrator privileges. -
Administrative shares: Both scripts accessed the
C$andADMIN$shares directly. -
Lateral movement: The activity then included SSH-based lateral movement.
-
Shadow copy access: A Volume Shadow Copy was triggered remotely through WMI.
-
Credential database extraction: The scripts accessed
ntds.dit,SYSTEM, andSECURITYfrom the shadow-copy device path, allowing the domain's password hashes to be extracted without accessing the live database files.

File Share Hunting and Data Exfiltration
A large group of PowerShell scripts systematically walks JUCEC's internal file shares looking for backups and sensitive documents.
The activity ranges from broad share enumeration to targeted collection of specific files and directories.
-
Backup and file-share discovery:
huntbkp.ps1,huntc.ps1,huntex.ps1,huntftp.ps1,huntip.ps1,huntip2.ps1,huntn.ps1,huntdir.ps1,huntz.ps1,huntti.ps1,bkp.ps1,bkp2.ps1,bkp3.ps1,bkp4.ps1, andbkp5.ps1enumerate JUCEC's internal shares and backup infrastructure, including "Centro de Eventos" folder, and theD:\JUCECshare. -
Targeted file collection:
huntcs.ps1,ticopy.ps1,ticopy2.ps1,tifind.ps1, andtifind2.ps1search for and copyPGFN_Acessos.csvfrom the Núcleo de Tecnologia directory. -
Directory archiving:
sczip.ps1andscbox.ps1locate and archive the Núcleo de Tecnologia directory through_redacted_.local. -
Zimbra file collection:
getxlsx.ps1copies spreadsheet files containing "Zimbra" in their filenames from a mailing-list share. -
Local backup discovery:
readbkp.ps1inventories theC:\Backup Sistemasdirectory on the drop host. -
Administrator profile discovery:
scuser.ps1enumerates the local Administrator's Desktop, Documents, and Downloads folders. -
File and software discovery:
arqfind.ps1searches for cached share listings, whilefindbr.ps1checks for Chrome installation paths. -
Host reconnaissance:
nutec.ps1checks host liveness, andsvcs.ps1enumerates listening TCP ports and running services on the drop host.
GLPI Helpdesk: Database Dump and Persistence Through a Scheduled Task
gsql.py, gsenha.py, gtkt.py, gldump.py, and gldump.sh all authenticate to a local MySQL instance against database glpidb, using the password redacted as ju_REDACTED_, dumping mail collector configuration (including any stored SMTP credentials), ticket follow-up content, and searching ticket bodies for keyword matches.
cron.txt is a crontab entry that copies a cached plugin metadata file over the top of GLPI's own setup script every 25 minutes, a lightweight file-based persistence mechanism, and gfin.py/gfix.py install and verify that crontab entry.

Additionally, gclean.py is the corresponding cleanup script, removing leftover Python files from /tmp and running a final gfix.py pass. gpersist.py separately drops a mini.php-style webshell for GLPI-adjacent persistence, and gsc_run.py is a thin command-runner wrapper against that shell.
osTicket: Configuration Hunting and CAPTCHA Harvesting
huntost.ps1 searches JUCEC's web roots for osTicket configuration strings, effectively bridging the GLPI and osTicket hunting efforts described below.

ostfind.php, ostfind2.php, and ostgrep.php scan internal IP ranges and JUCEC web roots for osTicket's ost-config.php file and its secret salt.
ostbak.ps1 retrieves backup copies of the same configuration file over HTTP. ostm.php and ostmysql.php then test a short list of MySQL root and osTicket credentials against port 3306 on the identified host, including several root password combinations.
ostopen.php, along with ostbody.txt and scpbody.txt, submits or replays pre-built osTicket support-ticket requests, including one populated with the real name and email address of a JUCEC staff member (_redacted_@jucec.ce.gov.br). This appears to test whether the ticketing form could be abused.
ost_captcha.png and ost_captcha_live.png contain CAPTCHA images collected from the login form. osthi.php is a one-line PHP version fingerprinting probe, while ostlink.ps1 and ostscan.ps1 perform additional connectivity and link-discovery checks against the same host.
Openfire Chat Server Compromise
A large family targets Openfire and the path from unauthenticated access to persistent tooling runs through five stages:
| Stage | Scripts | Result |
|---|---|---|
| 1. Directory traversal | ofjsp.ps1, ofjsp2.ps1 | Reaches /setup/setup-s/%u002e%u002e/%u002e%u002e/plugins/..., an admin-only JSP execution path, without authentication |
| 2. Log exposure | oflog.php, oflog3.php, oflog4.php, oflog.html | Pulls Openfire's web-accessible log viewer |
| 3. Admin login | ofadm.ps1, ofadmjsp.ps1, oflogin.ps1, oflogin.php | Credential pair openfire / 0P_REDACTED_ |
| 4. Shell deployment | ofcmd.php, ofsh.php, ofire.php, ofchk.ps1 | Command-execution shells dropped post-login |
| 5. Disguised plugin upload | ofadd.php, ofup.php through ofup10.ps1, of5.ps1 through of13.ps1 | Three compiled jars (healthcheck.jar, syshealth.jar, sysprobe.jar) uploaded as fake monitoring plugins, each beaconing to ofbeacon.php |
jrun.ps1 uses a captured Openfire session cookie (JSESSIONID plus CSRF token) to run authenticated commands directly, including reading the server's XMPP and Kerberos keytabs.

Microsoft SQL Server: JUCEC's Internal EasyCapture Application
sql2.ps1, sqldump.ps1, and sqlq.ps1 connect directly to a Microsoft SQL Server instance using the connection string _REDACTED_, querying both the named application database and the server's own master database.
sqmore.php/sqmorego.ps1 and sqscan.php/sqrun.ps1 do broader port scanning of nearby internal hosts for the same class of service.
sqpwn.php/sqpwngo.ps1, sqweb.php/sqgo.ps1, sqwm.php, sqwm2.php/sqwmgo.ps1, sqint.php/sqintgo.ps1, sqauth.php/sqau.ps1, sq10000.php/sq10kgo.ps1, and sqsmb.php/sqsmb.ps1 form a related family of SOAP and web-service probes and SMB session tests, reusing the same _redacted_\google.sync credential over SMB.
mc.py and mcget.py test an exposed Memcached instance, capable of leaking whatever keys the operator could guess or brute-force from that cache.
Internal Drop Server Management and Cleanup
Another internal host appears to function as an operator-controlled internal staging and relay server within JUCEC's network. The tooling stored on the host can be grouped into the following activities:
-
Application discovery and ScriptCase enumeration
scapps.ps1andscfast.ps1enumerate five application directories:alan,auxiliar,dados,jaux, andmac.sclook.ps1checks whether a NetMake ScriptCase development environment is installed.findcfg.php,cfg2.php,cfg3.php,cfg4.php, andcfg5.phplocate and extract JUCEC's internal ScriptCase configuration files, including a production database configuration and an SQLite database containing ScriptCase developer credentials.dec.phpanddecsc.phpdecrypt ScriptCase's proprietary configuration format to recover plaintext configuration values.
-
Command execution and tool staging
scmysql.ps1,scof.py,scget.py,scget2.py,scinv.py,scw.py,scw2.py,scfin.py,scsvc.py, andsc.pyact as lightweight command-execution wrappers.soap.zip,usoap.zip,usoap2.zip, andusoap3.zip, together with their corresponding PowerShell launchers, provide additional compressed toolsets for deployment.
-
Webshells and additional payload delivery
d.zis a raw binary blob containing an embedded.phpfile signature.da.phpis a heavily obfuscated, multilayer-encoded PHP loader that uses base64 encoding and custom string transformations before dynamically constructing anevalcall.- Its behavior is consistent with a generic obfuscated backdoor rather than a payload specific to Zimbra or JUCEC.
scclean.py,scdec.ps1, andscdrop.ps1support staged-file cleanup and decryption activities on the host.
-
Browser and session-data collection
chacc.phpsearches Chrome's saved-preferences data for stored JUCEC-related session information.chmail.ps1andchmail2.ps1interact directly with the Chrome process using native Windows API calls through inline C# code.chtask.ps1andrunchrome.batterminate and relaunch Chrome under a specified user profile, apparently to obtain a fresh and unlocked browser session.
-
Google Cloud Directory Sync credential decryption
dec.batanddec2.batinvoke Google Cloud Directory Sync'sencrypt-util.exeto decrypt stored configuration secrets, including an operator-held encrypted value represented here ass5_REDACTED_.decgcds.ps1anddecoauth.ps1independently implement the same AES decryption process in PowerShell and operate on captured encrypted values labeledldapanddef.jar.batandjarls.ps1inspect GCDS'sDirSync.jar, searching for cryptographic routines using strings such asEncrypt,Crypto,Cipher,PBE, andGenerate. This appears to support the subsequent decryption attempts.
-
Captured Google authentication material
ga_ac2dm.txt,ga_ah.txt,ga_gm.txt, andga_oauthmail.txtcontain captured Google ClientLogin requests associated with_redacted_@jucec.ce.gov.br.- The requests contain a password in URL-encoded form, represented here as
ju_REDACTED_, and request device-sync, mail, and OAuth-related tokens. gauth.txtis another variant of the same authentication request and identifies its source asJucec-gcds-1.0.
-
Direct Gmail session access through Chrome DevTools
gdump.cs,gdump3.cs, andgdump4.csare successive versions of a C# utility that connects to Chrome's local DevTools Protocol endpoint at127.0.0.1:9222.- The utilities locate an already authenticated Gmail tab and interact with the session through the browser debugging interface, allowing mail to be accessed without directly supplying the account password.
glogin.csperforms a related function by automating Gmail login through the same debugging interface.- These tools require Chrome to be running with remote debugging enabled and therefore appear intended for use on a previously accessed workstation.
-
Scheduled-task persistence
mk.bat,sc-mk.bat,persist.ps1,persist-sc.ps1, andpersist-sc2.ps1create or maintain a Scheduled Task namedWaaSHealthCheck.- The task is designed to resemble a legitimate Windows Update health-check task.
- It periodically copies a disguised PHP payload,
display.dll.php, fromC:\ProgramData\Microsoft\Windows\Cachesinto the web root under names such ashx.phporcache.php. - This provides a persistence mechanism independent of the webshells already deployed.
-
Persistence monitoring and secondary payload deployment
sc-q.php/sc-q.ps1andsc-task.phpquery the status of theWaaSHealthChecktask and identify the currently logged-in user.task1.ps1extends the same copy operation to a second destination disguised as anoficios/imagensdocument or image directory.runc2.ps1throughrunc5.ps1,runcfg.ps1,rungrep.ps1,runls.ps1, andrunsoap.batprovide simple copy-and-execute functionality for staging PHP and SOAP payloads on the internal server.
-
Network probing and auxiliary utilities
probe.pyprovides generic connectivity testing.sites.pychecks URL responses.listen.pyimplements a raw TCP listener on port18099.untar.pyretrieves and extracts a remote archive fromhttp://x.x.x.x/mbox.tgz.
-
Cleanup and removal
rmd.ps1andrmfin.ps1provide final cleanup functionality.- These scripts remove the operator's staging directory and specified residual files from the compromised web root.
Target Scope Beyond JUCEC: Eighteen Rio Grande do Norte Municipal Councils
vfy.sh runs the same Hx_redacted_ webshell key against eighteen municipal government domains in the state of Rio Grande do Norte.
- cmielmomarinho.rn.gov.br
- camaramunicipaldeextremoz.rn.gov.br
- japi.rn.gov.br
- messiastargino.rn.gov.br
- piparosepasseios.com.br
- saaeextremoz.com.br
- camarabomjesus.rn.gov.br
- camaramunicipaldearez.rn.gov.br
- camarasjc.rn.gov.br
- cmcaicaradonorte.rn.gov.br
- cmmessiastargino.rn.gov.br
- cmparazinho.rn.gov.br
- cmsaobentodonorte.rn.gov.br
- cmserracaiada.rn.gov.br
- cmserranegradonorte.rn.gov.br
- caraubas.rn.leg.br
- serradesaobento.rn.leg.br
- taipu.rn.leg.br

Port 18080: A Kernel Privilege Escalation Dropper Ready to Deploy
The smallest directory contains a faithful mirror of the public CVE-2026-31431 (“Copy Fail”) Linux kernel exploit.
The vulnerability affects the kernel’s algif_aead interface and can allow an unprivileged user to modify file contents in the page cache by exploiting a crafted failed decryption request. This can be abused to alter files such as setuid-root binaries or /etc/passwd, enabling local privilege escalation.
The key files in the exposed directory are listed below:
| Category | Files |
|---|---|
| Documentation | README.md plus four translations (README.ja.md, README.ko.md, README.ru.md, README.zh-cn.md), CITATION.cff, LICENSE-MIT, LICENSE-LGPL, SECURITY.md, Makefile |
| Exploit source | exploit.c, exploit-passwd.c, payload.c, vulnerable.c, utils.c, utils.h, compat.h |
| Pre-built binaries | payload, payload.o, utils.o, exploit.__rev2, vulnerable.__rev2 |
| Vendored nolibc runtime | 66 header files across thirteen CPU architectures, letting the exploit compile to a single static binary with no glibc/musl dependency |
exploit.c is the primary dropper. It walks the embedded payload four bytes at a time, patches each window into the target's page cache, then executes it:
1for (off_t off = 0; (size_t)off < len; off += 4) {
2 unsigned char window[4] = { 0, 0, 0, 0 };
3 size_t take = (len - (size_t)off >= 4) ? 4 : len - (size_t)off;
4 memcpy(window, PAYLOAD + off, take);
5 if (patch_chunk(file_fd, off, window) < 0) { ... }
6}
7execl("/bin/sh", "sh", "-c", cmd, (char *)NULL);exploit-passwd.c takes a different approach from variants that target setuid binaries. Instead, it manipulates the cached contents of /etc/passwd so that the current user’s account is temporarily associated with a privileged UID, then invokes su. Authentication still relies on /etc/shadow, but the altered account information can cause the subsequent privilege transition to behave incorrectly. The approach does not require an embedded payload and relies on the fact that /etc/passwd is normally readable by unprivileged users.
payload.c is the payload produced by exploit.c. It is a minimal static program that uses the vendored nolibc implementation, so it does not depend on the system’s C library at runtime. vulnerable.c is a non-destructive checker that determines whether the target is potentially exploitable without actually performing the page-cache corruption.

Operator Assessment
Portuguese-language documentation, variable names, and comments run through both the port 9998 and port 18082 directories, and every named target across both, JUCEC, e-Simples, JBRJ, and the eighteen Rio Grande do Norte municipalities, is Brazilian. The recovered tooling uses Brazilian Portuguese terminology and references multiple Brazilian public-sector and federal research targets.
Mitigations
- Patch internet-facing applications and prioritize critical vulnerabilities.
- Remove hardcoded secrets from source code, scripts, and configuration files.
- Prevent credential reuse and rotate compromised credentials immediately.
- Apply least privilege to privileged and service accounts.
- Secure Active Directory and monitor unusual SMB, LDAP, WMI, and credential-dumping activity.
- Harden cloud metadata access and enforce least-privilege IAM permissions.
- Monitor for webshells and unexpected changes to web-facing files.
- Protect browser sessions and restrict remote debugging interfaces.
- Secure internal staging servers with proper network access controls.
- Harden email platforms with MFA and protection against password spraying.
- Monitor persistence mechanisms such as scheduled tasks, cron jobs, SSH keys, and unauthorized services.
- Segment critical systems to limit lateral movement.
- Rotate credentials after compromise, including application, database, domain, cloud, SSH, and session credentials.
- Hunt for IOCs and attacker behavior across endpoint, network, identity, cloud, and application telemetry.
Conclusion
The exposed directories examined in this investigation provide a detailed view into a multi-stage intrusion operation targeting Brazilian public-sector and research environments.
The evidence includes a confirmed compromise of JBRJ's IPT environment, subsequent access to application and database infrastructure, harvesting of AWS temporary credentials, credential reuse across multiple services, webshell deployment, and preparation for privilege escalation.
A separate directory contained an extensive toolkit targeting JUCEC, including Zimbra, Active Directory, Openfire, GLPI, osTicket, SQL Server, internal file shares, and browser sessions.
The same infrastructure also contained a staged Linux kernel privilege-escalation toolkit and tooling referencing additional Brazilian government targets.
Several recurring weaknesses stand out: exposed services, insufficiently protected credentials, credential reuse, excessive privileges, weak segmentation, and inadequate monitoring of persistence and lateral-movement activity. The investigation also demonstrates how an initial application compromise can become significantly more serious when cloud credentials, database access, administrative accounts, and internal network connectivity are subsequently exposed.
Organizations operating internet-facing applications should therefore treat application security, identity protection, cloud credential isolation, network segmentation, and continuous threat hunting as interconnected controls rather than separate security functions.
MITRE ATT&CK Mapping
| Technique ID | Name | Evidence |
|---|---|---|
| T1190 | Exploit Public-Facing Application | SSTI and admin-creation flaws against GBIF IPT; directory traversal against Openfire's plugin-admin path |
| T1068 | Exploitation for Privilege Escalation | CVE-2026-31431 kernel LPE dropper staged on the same infrastructure; io_uring capability probes run against the compromised Tomcat container |
| T1505.003 | Server Software Component: Web Shell | JSP shells deployed through IPT's DuckDB file functions; mini.php, gate.php, g.aspx, hxok.jsp, and da.php, all gated behind a shared key |
| T1078 | Valid Accounts | Domain administrator SMB access as redacted\Administrator; Openfire admin login; reused google.sync AD service account across a dozen scripts |
| T1110.001 / T1110.002 | Brute Force: Password Guessing / Cracking | fauna_crack.py bcrypt cracking; spray_plain.py and spray_edalcin.py default-password spraying; smtptryp.ps1 SMTP password spraying against Zimbra |
| T1552.001 | Unsecured Credentials: Credentials In Files | Hardcoded domain and application passwords across dozens of PowerShell and PHP scripts; access.txt operator notes recording working credentials |
| T1552.005 | Unsecured Credentials: Cloud Instance Metadata API | ipt_imds_role.py and ipt_imds_url.py abusing SSTI/SSRF to reach two separate AWS IMDS credential sets |
| T1555.003 | Credentials from Web Browsers | glogin.cs and gdump*.cs hijacking an authenticated Gmail session through the Chrome remote-debugging protocol |
| T1003.003 | OS Credential Dumping: NTDS | ntds.ps1 and cpntds.bat triggering remote Volume Shadow Copy creation and reading ntds.dit directly from the shadow device path |
| T1021.002 | Remote Services: SMB/Windows Admin Shares | next.ps1 and smb2.ps1 mounting C$ and ADMIN$ as redacted\Administrator |
| T1053.005 | Scheduled Task/Job: Scheduled Task | mk.bat and persist.ps1 creating a WaaSHealthCheck scheduled task for recurring webshell redeployment |
| T1213 | Data from Information Repositories | ckan_users.json full user-table dump; AGENTS.md, PAINEL_SQL.md, and related internal JBRJ documentation harvested from the target's own repository |
| T1074 | Data Staged | huntbkp.ps1 and ticopy.ps1 family locating and copying PGFN_Acessos.csv and other files out of JUCEC's internal backup and technology-team file shares |
Indicators of Compromise
Network infrastructure
| Indicator | ASN | Provider | Country | Context |
|---|---|---|---|---|
| 111.90.145[.]92:9998 | AS45839 | Shinjiru Technology Sdn Bhd | Malaysia | Open directory holding the confirmed JBRJ/IPT/Tomcat compromise |
| 111.90.145[.]92:18080 | AS45839 | Shinjiru Technology Sdn Bhd | Malaysia | Open directory holding the CVE-2026-31431 kernel exploit dropper |
| 111.90.145[.]92:18082 | AS45839 | Shinjiru Technology Sdn Bhd | Malaysia | Open directory holding the Zimbra/AD/helpdesk hunting kit |
Files, tools, and identifiers
| Indicator | Type | Context |
|---|---|---|
| CVE-2026-31431 | CVE reference | "Copy Fail" Linux kernel LPE, packaged as exploit.c/exploit-passwd.c in the port 18080 directory |
| CVE-2026-71878 (operator label) | Internal CVE reference | GBIF IPT setupDefaultAdministrator.do rogue-admin creation flaw, cited by ipt_cve71878.py and ipt_cve_interno.py |
| CVE-2026-71880 (operator label) | Internal CVE reference | GBIF IPT FreeMarker ?interpret SSTI, cited by ipt_ssti.py |
| CVE-2026-42031 (operator label) | Internal CVE reference | PostgreSQL ts_rewrite issue used against a JBRJ downstream RDS instance, documented in ckan_rds.txt |
| WaaSHealthCheck | Windows Scheduled Task name | Disguised persistence task created by mk.bat and persist.ps1 on JUCEC hosts |
| jucec.ce.gov.br, esimples.ce.gov.br | Target domains | Ceará state Board of Trade (JUCEC) and its e-Simples business registration portal |
| Eighteen *.rn.gov.br / *.rn.leg.br domains | Target domains | Rio Grande do Norte municipal câmara (city council) sites, checked in vfy.sh with the same webshell key used inside JUCEC |
| ipt.jbrj.gov.br, jabotimage.jbrj.gov.br, ckan.jbrj.gov.br | Target domains | JBRJ's GBIF IPT portal, JABOT image system, and CKAN open-data portal |
Published by @volrant136
Related research
- Threat Research

One Host, Six Operations: How Two Open Directories Exposed a Multi-Target Campaign
Two open directories on a single Singapore host exposed the working files behind six separate operations. The recovered data shows a mix of LLM gateway fraud, government and military reconnaissance, credential spraying, SQL injection attempts, proxy infrastructure, and a confirmed compromise of a Mexican web application.
20 minutes to read - Threat Research

Nigerian and Kenyan Government Portals Targeted by Suspected Chinese-Speaking Operator in Multi-Stage Credential Harvesting Campaign
An exposed server uncovered a collection of scripts, credentials, session artifacts, and exploitation tooling targeting government portals across several countries. This investigation traces the infrastructure from DeHashed searches and WordPress testing to Java deserialization payloads and a Telegram-controlled automation framework.
17 minutes to read - Threat Research

Operation BlueDash: Infrastructure Expansion, VBS Analysis & Multi-Lure Kill Chain
Starting from a single known IOC, Hunt.io pivots exposed additional BlueDash infrastructure and previously undocumented lure variants. The campaign uses multiple delivery paths to deploy Level RMM and ScreenConnect across separate infrastructure and RMM tenants.
23 minutes to read