CVE-2020-13775: NULL Pointer Dereference (CWE-476)
value: ZNC 1.8.0 up to 1.8.1-rc1 allows authenticated users to trigger an application crash (with a NULL pointer dereference) if echo-message is not enabled and there is no network.
CWE description: The product dereferences a pointer that it expects to be valid but is NULL.
CVSS v3 base score: 6.5
Published: 2020-06-02T23:15Z
Repository: https://github.com/znc/znc
Language: C++
Files changed: src/Client.cpp, test/integration/tests/core.cpp
Commit date: 2020-03-29 08:45:10 +0100
Commit message: Fix echo-message for *status

Close #1705

Diff: diff --git a/src/Client.cpp b/src/Client.cpp
index c7a35dbe8..6d8f4518b 100644
--- a/src/Client.cpp
+++ b/src/Client.cpp
@@ -1232,10 +1232,12 @@ bool CClient::OnTextMessage(CTextMessage& Message) {
             // May be nullptr.
             Message.SetChan(m_pNetwork->FindChan(sTarget));
         }
 
         if (sTarget.TrimPrefix(m_pUser->GetStatusPrefix())) {
+            EchoMessage(Message);
+
             if (sTarget.Equals("status")) {
                 CString sMsg = Message.GetText();
                 UserCommand(sMsg);
             } else {
                 CALLMOD(sTarget, this, m_pUser, m_pNetwork,
diff --git a/test/integration/tests/core.cpp b/test/integration/tests/core.cpp
index 8d8e32c31..a3f0d4dab 100644
--- a/test/integration/tests/core.cpp
+++ b/test/integration/tests/core.cpp
@@ -12,13 +12,14 @@
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 
-#include "znctest.h"
 #include <gmock/gmock.h>
 
+#include "znctest.h"
+
 using testing::HasSubstr;
 
 namespace znc_inttest {
 namespace {
 
@@ -242,11 +243,12 @@ TEST_F(ZNCTest, AwayNotify) {
     client.Write("PASS :hunter2");
     client.Write("NICK nick");
     client.Write("USER user/test x x :x");
     QByteArray cap_ls;
     client.ReadUntilAndGet(" LS :", cap_ls);
-    ASSERT_THAT(cap_ls.toStdString(), AllOf(HasSubstr("cap-notify"), Not(HasSubstr("away-notify"))));
+    ASSERT_THAT(cap_ls.toStdString(),
+                AllOf(HasSubstr("cap-notify"), Not(HasSubstr("away-notify"))));
     client.Write("CAP REQ :cap-notify");
     client.ReadUntil("ACK :cap-notify");
     client.Write("CAP END");
     client.ReadUntil(" 001 ");
     ircd.ReadUntil("USER");
@@ -282,7 +284,17 @@ TEST_F(ZNCTest, JoinKey) {
     ircd = ConnectIRCd();
     ircd.Write(":server 001 nick :Hello");
     ircd.ReadUntil("JOIN #znc secret");
 }
 
+TEST_F(ZNCTest, StatusEchoMessage) {
+    auto znc = Run();
+    auto ircd = ConnectIRCd();
+    auto client = LoginClient();
+    client.Write("CAP REQ :echo-message");
+    client.Write("PRIVMSG *status :blah");
+    client.ReadUntil(":nick!user@irc.znc.in PRIVMSG *status :blah");
+    client.ReadUntil(":*status!znc@znc.in PRIVMSG nick :Unknown command");
+}
+
 }  // namespace
 }  // namespace znc_inttest

Vulnerable code: #include "znctest.h"
    ASSERT_THAT(cap_ls.toStdString(), AllOf(HasSubstr("cap-notify"), Not(HasSubstr("away-notify"))));
Fixed code:             EchoMessage(Message);

#include "znctest.h"

    ASSERT_THAT(cap_ls.toStdString(),
                AllOf(HasSubstr("cap-notify"), Not(HasSubstr("away-notify"))));
TEST_F(ZNCTest, StatusEchoMessage) {
    auto znc = Run();
    auto ircd = ConnectIRCd();
    auto client = LoginClient();
    client.Write("CAP REQ :echo-message");
    client.Write("PRIVMSG *status :blah");
    client.ReadUntil(":nick!user@irc.znc.in PRIVMSG *status :blah");
    client.ReadUntil(":*status!znc@znc.in PRIVMSG nick :Unknown command");
}