CVE-2021-25980: Improper Neutralization of Special Elements in Output Used by a Downstream Component ('Injection') (CWE-74)
value: In Talkyard, versions v0.04.01 through v0.6.74-WIP-63220cb, v0.2020.22-WIP-b2e97fe0e through v0.2021.02-WIP-879ef3fe1 and tyse-v0.2021.02-879ef3fe1-regular through tyse-v0.2021.28-af66b6905-regular, are vulnerable to Host Header Injection. By luring a victim application-user to click on a link, an unauthenticated attacker can use the “forgot password” functionality to reset the victim’s password and successfully take over their account.
CWE description: The product constructs all or part of a command, data structure, or record using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify how it is parsed or interpreted when it is sent to a downstream component.
CVSS v3 base score: 8.8
Published: 2021-11-11T07:15Z
Repository: https://github.com/debiki/talkyard
Language: Scala
Files changed: appsv/server/debiki/Globals.scala, appsv/server/talkyard/server/api/GetController.scala
Commit date: 2021-10-11 12:12:59 +0200
Commit message: Bump get query limit from 29 to 50. Disallow access via IP.

Diff: diff --git a/appsv/server/debiki/Globals.scala b/appsv/server/debiki/Globals.scala
index e6c43498..84434649 100644
--- a/appsv/server/debiki/Globals.scala
+++ b/appsv/server/debiki/Globals.scala
@@ -799,15 +799,16 @@ class Globals(  // RENAME to TyApp? or AppContext? TyAppContext? variable name =
             die("TyEMAT752", s"Shouldn't have loaded deleted hostname: $result")
           case _ =>
             die("DwE20SE4")
         }
       case None =>
+        /* Not really needed. Better to use a real domain name.
         if (Site.Ipv4AnyPortRegex.matches(hostname)) {
           // Make it possible to access the server before any domain has been pointed
           // to it, just after installation, by lazy-creating an empty default site.
           return defaultSiteIdAndHostname
-        }
+        } */
         throwSiteNotFound(
           hostname, debugCode = "LKPCANHOST")
     }
     val site = systemDao.getSiteById(lookupResult.siteId) getOrDie "EsE2KU503"
     site.brief
diff --git a/appsv/server/talkyard/server/api/GetController.scala b/appsv/server/talkyard/server/api/GetController.scala
index c902a45e..b34dcdf7 100644
--- a/appsv/server/talkyard/server/api/GetController.scala
+++ b/appsv/server/talkyard/server/api/GetController.scala
@@ -62,12 +62,12 @@ class GetController @Inject()(cc: ControllerComponents, edContext: EdContext)
           : Result = {
     import request.{dao, requester}
 
     val authzCtx = dao.getForumAuthzContext(requester)
 
-    throwUnimplementedIf(pageRefs.size >= 30,
-          "TyE603MRT4", "Currently at most 30 at a time")
+    throwUnimplementedIf(pageRefs.size > 50,
+          "TyE603MRT4", "Currently at most 50 at a time")
 
     def notFoundMsg(embUrl: St, pageId: PageId = NoPageId): St = {
       s"No page with that embedding url or discussion id: $embUrl"
     }
 

Vulnerable code:         }
    throwUnimplementedIf(pageRefs.size >= 30,
          "TyE603MRT4", "Currently at most 30 at a time")
Fixed code:         /* Not really needed. Better to use a real domain name.
        } */
    throwUnimplementedIf(pageRefs.size > 50,
          "TyE603MRT4", "Currently at most 50 at a time")