From 21120e214654234d7b484f63d05f89f42f442ade Mon Sep 17 00:00:00 2001 From: psychon Date: Tue, 24 Feb 2009 16:00:11 +0000 Subject: [PATCH] Handle newlines in CHTTPSock::GetParam() and strip them out. There was a bug in webadmin which allowed any users to write arbitrary strings to znc.conf by setting e.g. their quit message to: Some quit message Admin = true LoadModule = shell ISpoofFile = /home//.ssh/authorited_keys ISpoofFormat = (The newlines must be sent as newlines to webadmin) This commit fixes this by stripping all newlines from all the data fields by default. Since some fields (e.g. CTCPReplies and Servers) do need newlines, there is a new function CHTTPSock::GetRawParam() which doesn't do the stripping. Thanks to cnu for finding and reporting this bug. Thanks to kroimon for patch review. git-svn-id: https://znc.svn.sourceforge.net/svnroot/znc/trunk@1395 726aef4b-f618-498e-8847-2d620e286838 --- HTTPSock.cpp | 39 +++++++++++++++++++++++++++++++-------- HTTPSock.h | 7 ++++--- modules/webadmin.cpp | 10 +++++----- 3 files changed, 40 insertions(+), 16 deletions(-) diff --git a/HTTPSock.cpp b/HTTPSock.cpp index e2b3d0ad..ed0b1cfd 100644 --- a/HTTPSock.cpp +++ b/HTTPSock.cpp @@ -259,38 +259,61 @@ bool CHTTPSock::HasParam(const CString& sName) const { return (m_msvsParams.find(sName) != m_msvsParams.end()); } -CString CHTTPSock::GetParam(const CString& sName) const { +CString CHTTPSock::GetRawParam(const CString& sName) const { CString sRet; - VCString vsParams; - if (GetParamValues(sName, vsParams)) { - sRet = vsParams[0]; + map::const_iterator it = m_msvsParams.find(sName); + + if (it != m_msvsParams.end() && it->second.size() > 0) { + sRet = it->second[0]; } return sRet; } -unsigned int CHTTPSock::GetParamValues(const CString& sName, set& ssRet) const { +CString CHTTPSock::GetParam(const CString& sName, const CString& sFilter) const { + CString sRet = GetRawParam(sName); + + for (size_t i = 0; i < sFilter.length(); i++) { + sRet.Replace(CString(sFilter.at(i)), ""); + } + + return sRet; +} + +unsigned int CHTTPSock::GetParamValues(const CString& sName, set& ssRet, const CString& sFilter) const { ssRet.clear(); map::const_iterator it = m_msvsParams.find(sName); if (it != m_msvsParams.end()) { for (unsigned int a = 0; a < it->second.size(); a++) { - ssRet.insert(it->second[a]); + CString sParam = it->second[a]; + + for (size_t i = 0; i < sFilter.length(); i++) { + sParam.Replace(CString(sFilter.at(i)), ""); + } + ssRet.insert(sParam); } } return ssRet.size(); } -unsigned int CHTTPSock::GetParamValues(const CString& sName, VCString& vsRet) const { +unsigned int CHTTPSock::GetParamValues(const CString& sName, VCString& vsRet, const CString& sFilter) const { vsRet.clear(); map::const_iterator it = m_msvsParams.find(sName); if (it != m_msvsParams.end()) { - vsRet = it->second; + for (unsigned int a = 0; a < it->second.size(); a++) { + CString sParam = it->second[a]; + + for (size_t i = 0; i < sFilter.length(); i++) { + sParam.Replace(CString(sFilter.at(i)), ""); + } + vsRet.push_back(sParam); + } } return vsRet.size(); diff --git a/HTTPSock.h b/HTTPSock.h index e8b25250..b3554142 100644 --- a/HTTPSock.h +++ b/HTTPSock.h @@ -58,15 +58,16 @@ public: // Getters bool HasParam(const CString& sName) const; - CString GetParam(const CString& sName) const; + CString GetRawParam(const CString& sName) const; + CString GetParam(const CString& sName, const CString& sFilter = "\r\n") const; bool IsLoggedIn() const { return m_bLoggedIn; } const CString& GetDocRoot() const; const CString& GetUser() const; const CString& GetPass() const; const CString& GetParamString() const; const CString& GetContentType() const; - unsigned int GetParamValues(const CString& sName, VCString& vsRet) const; - unsigned int GetParamValues(const CString& sName, set& ssRet) const; + unsigned int GetParamValues(const CString& sName, VCString& vsRet, const CString& sFilter = "\r\n") const; + unsigned int GetParamValues(const CString& sName, set& ssRet, const CString& sFilter = "\r\n") const; const map& GetParams() const; // !Getters private: diff --git a/modules/webadmin.cpp b/modules/webadmin.cpp index dd52b558..b67c2570 100644 --- a/modules/webadmin.cpp +++ b/modules/webadmin.cpp @@ -614,7 +614,7 @@ bool CWebAdminSock::SettingsPage(CString& sPageRet) { //sArg = GetParam(""); if (!sArg.empty()) { CZNC::Get().Set(sArg); } VCString vsArgs; - GetParam("motd").Split("\n", vsArgs); + GetRawParam("motd").Split("\n", vsArgs); CZNC::Get().ClearMotd(); unsigned int a = 0; @@ -622,7 +622,7 @@ bool CWebAdminSock::SettingsPage(CString& sPageRet) { CZNC::Get().AddMotd(vsArgs[a].TrimRight_n()); } - GetParam("vhosts").Split("\n", vsArgs); + GetRawParam("vhosts").Split("\n", vsArgs); CZNC::Get().ClearVHosts(); for (a = 0; a < vsArgs.size(); a++) { @@ -1044,14 +1044,14 @@ CUser* CWebAdminSock::GetNewUser(CString& sPageRet, CUser* pUser) { } VCString vsArgs; - GetParam("servers").Split("\n", vsArgs); + GetRawParam("servers").Split("\n", vsArgs); unsigned int a = 0; for (a = 0; a < vsArgs.size(); a++) { pNewUser->AddServer(vsArgs[a].Trim_n()); } - GetParam("allowedips").Split("\n", vsArgs); + GetRawParam("allowedips").Split("\n", vsArgs); if (vsArgs.size()) { for (a = 0; a < vsArgs.size(); a++) { pNewUser->AddAllowedHost(vsArgs[a].Trim_n()); @@ -1064,7 +1064,7 @@ CUser* CWebAdminSock::GetNewUser(CString& sPageRet, CUser* pUser) { pNewUser->AddAllowedHost(GetParam("ownip")); } - GetParam("ctcpreplies").Split("\n", vsArgs); + GetRawParam("ctcpreplies").Split("\n", vsArgs); for (a = 0; a < vsArgs.size(); a++) { CString sReply = vsArgs[a].TrimRight_n("\r"); pNewUser->AddCTCPReply(sReply.Token(0).Trim_n(), sReply.Token(1, true).Trim_n());