Fix crash while unloading modules

The bug allowed unprivileged users to trigger use-after-free while
unloading modules

Note that the fix requires a slight API change for OnEmbeddedWebRequest:
now the callers (webadmin is the only known caller of it) call it via
DoEmbeddedWebRequest() instead. The modules which implement this hook
need no changes.

CVE-2026-82373

Found by Claude from Anthropic, reported by Ada Logics.
This commit is contained in:
Alexey Sokolov committed 2026-09-12 19:08:21 +01:00
1 parent d9b392afd9
commit 4b88c64c6e
7 files changed
+143 -111

No files matched your search

+6 -6
View File
@@ -742,7 +742,7 @@ class CWebAdminMod : public CModule {
CTemplate& mod = Tmpl.AddRow("EmbeddedModuleLoop");
mod.insert(Tmpl.begin(), Tmpl.end());
mod["WebadminAction"] = "display";
if ((*i)->OnEmbeddedWebRequest(WebSock, "webadmin/channel",
if ((*i)->DoEmbeddedWebRequest(WebSock, "webadmin/channel",
mod)) {
mod["Embed"] = WebSock.FindTmpl(*i, "WebadminChan.tmpl");
mod["ModName"] = (*i)->GetModName();
@@ -816,7 +816,7 @@ class CWebAdminMod : public CModule {
TmplMod["ChanName"] = pChan->GetName();
TmplMod["WebadminAction"] = "change";
FOR_EACH_MODULE(it, pNetwork) {
(*it)->OnEmbeddedWebRequest(WebSock, "webadmin/channel", TmplMod);
(*it)->DoEmbeddedWebRequest(WebSock, "webadmin/channel", TmplMod);
}
if (!CZNC::Get().WriteConfig()) {
@@ -1027,7 +1027,7 @@ class CWebAdminMod : public CModule {
CTemplate& mod = Tmpl.AddRow("EmbeddedModuleLoop");
mod.insert(Tmpl.begin(), Tmpl.end());
mod["WebadminAction"] = "display";
if ((*i)->OnEmbeddedWebRequest(WebSock, "webadmin/network",
if ((*i)->DoEmbeddedWebRequest(WebSock, "webadmin/network",
mod)) {
mod["Embed"] = WebSock.FindTmpl(*i, "WebadminNetwork.tmpl");
mod["ModName"] = (*i)->GetModName();
@@ -1246,7 +1246,7 @@ class CWebAdminMod : public CModule {
TmplMod["Name"] = pNetwork->GetName();
TmplMod["WebadminAction"] = "change";
FOR_EACH_MODULE(it, make_pair(pUser, pNetwork)) {
(*it)->OnEmbeddedWebRequest(WebSock, "webadmin/network", TmplMod);
(*it)->DoEmbeddedWebRequest(WebSock, "webadmin/network", TmplMod);
}
if (!CZNC::Get().WriteConfig()) {
@@ -1670,7 +1670,7 @@ class CWebAdminMod : public CModule {
CTemplate& mod = Tmpl.AddRow("EmbeddedModuleLoop");
mod.insert(Tmpl.begin(), Tmpl.end());
mod["WebadminAction"] = "display";
if ((*i)->OnEmbeddedWebRequest(WebSock, "webadmin/user", mod)) {
if ((*i)->DoEmbeddedWebRequest(WebSock, "webadmin/user", mod)) {
mod["Embed"] = WebSock.FindTmpl(*i, "WebadminUser.tmpl");
mod["ModName"] = (*i)->GetModName();
}
@@ -1731,7 +1731,7 @@ class CWebAdminMod : public CModule {
TmplMod["Username"] = sUsername;
TmplMod["WebadminAction"] = "change";
FOR_EACH_MODULE(it, pUser) {
(*it)->OnEmbeddedWebRequest(WebSock, "webadmin/user", TmplMod);
(*it)->DoEmbeddedWebRequest(WebSock, "webadmin/user", TmplMod);
}
if (!CZNC::Get().WriteConfig()) {