[SCM] Debian packaging for the Shibboleth Apache SP branch, etch, updated. debian/1.3f.dfsg1-2+etch1-1-ga7122a3
Russ Allbery
rra at debian.org
Sun Dec 6 21:26:01 UTC 2009
The following commit has been merged in the etch branch:
commit a7122a3e40c8d3cb5577e2abfe664c157c10ea5f
Author: Russ Allbery <rra at debian.org>
Date: Wed Dec 2 22:15:59 2009 -0800
Backport upstream security fix for URL handling
* SECURITY: Fix improper handling of URLs that could be abused for
script injection and other cross-site scripting attacks.
(CVE-2009-3300)
diff --git a/debian/changelog b/debian/changelog
index d943fe9..63eef42 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,11 @@
+shibboleth-sp (1.3f.dfsg1-2+etch2) oldstable-security; urgency=high
+
+ * SECURITY: Fix improper handling of URLs that could be abused for
+ script injection and other cross-site scripting attacks.
+ (CVE-2009-3300)
+
+ -- Russ Allbery <rra at debian.org> Wed, 02 Dec 2009 22:15:50 -0800
+
shibboleth-sp (1.3f.dfsg1-2+etch1) oldstable-security; urgency=high
* SECURITY: Correctly handle decoding of malformed URLs, closing a
diff --git a/debian/patches/CVE-2009-3300 b/debian/patches/CVE-2009-3300
new file mode 100644
index 0000000..e4c9ce8
--- /dev/null
+++ b/debian/patches/CVE-2009-3300
@@ -0,0 +1,216 @@
+SECURITY: Fix improper handling of URLs that could be abused for
+script injection and other cross-site scripting attacks.
+(CVE-2009-3300)
+
+--- shibboleth-sp.orig/adfs/handlers.cpp
++++ shibboleth-sp/adfs/handlers.cpp
+@@ -429,8 +429,19 @@
+ ret=handler->getString("ResponseLocation").second;
+ if (!ret)
+ ret=st->getApplication()->getString("homeURL").second;
+- if (!ret)
+- ret="/";
++ if (!ret) {
++ // No homeURL, so compute a URL to the root of the site.
++ int port = st->getPort();
++ const char* scheme = st->getProtocol();
++ string dest = string(scheme) + "://" + st->getHostname();
++ if ((!strcmp(scheme,"http") && port!=80) || (!strcmp(scheme,"https") && port!=443)) {
++ ostringstream portstr;
++ portstr << port;
++ dest += ':' + portstr.str();
++ }
++ dest += '/';
++ return make_pair(true, st->sendRedirect(dest));
++ }
+ return make_pair(true, st->sendRedirect(ret));
+ }
+
+@@ -469,7 +480,7 @@
+
+ if (target=="default") {
+ pair<bool,const char*> homeURL=app->getString("homeURL");
+- target=homeURL.first ? homeURL.second : "/";
++ target=homeURL.first ? homeURL.second : "";
+ }
+ else if (target=="cookie" || target.empty()) {
+ // Pull the target value from the "relay state" cookie.
+@@ -478,7 +489,7 @@
+ if (!relay_state || !*relay_state) {
+ // No apparent relay state value to use, so fall back on the default.
+ pair<bool,const char*> homeURL=app->getString("homeURL");
+- target=homeURL.first ? homeURL.second : "/";
++ target=homeURL.first ? homeURL.second : "";
+ }
+ else {
+ char* rscopy=strdup(relay_state);
+@@ -519,6 +530,19 @@
+ }
+ }
+
++ if (target == "") {
++ // No homeURL, so compute a URL to the root of the site.
++ int port = st->getPort();
++ const char* scheme = st->getProtocol();
++ target = string(scheme) + "://" + st->getHostname();
++ if ((!strcmp(scheme,"http") && port!=80) || (!strcmp(scheme,"https") && port!=443)) {
++ ostringstream portstr;
++ portstr << port;
++ target += ':' + portstr.str();
++ }
++ target += '/';
++ }
++
+ // Now redirect to the target.
+ return make_pair(true, st->sendRedirect(target));
+ }
+--- shibboleth-sp.orig/apache/mod_apache.cpp
++++ shibboleth-sp/apache/mod_apache.cpp
+@@ -68,6 +68,7 @@
+ char* g_szSHIBConfig = NULL;
+ char* g_szSchemaDir = NULL;
+ ShibTargetConfig* g_Config = NULL;
++ set<string> g_allowedSchemes;
+ string g_unsetHeaderValue;
+ static const char* g_UserDataKey = "_shib_check_user_";
+ }
+@@ -299,9 +300,12 @@
+ const string& content_type="text/html",
+ const Iterator<header_t>& headers=EMPTY(header_t)
+ ) {
++ checkString(content_type, "Detected control character in a response header.");
+ m_req->content_type = ap_psprintf(m_req->pool, content_type.c_str());
+ while (headers.hasNext()) {
+ const header_t& h=headers.next();
++ checkString(h.first, "Detected control character in a response header.");
++ checkString(h.second, "Detected control character in a response header.");
+ ap_table_set(m_req->headers_out, h.first.c_str(), h.second.c_str());
+ }
+ ap_send_http_header(m_req);
+@@ -309,6 +313,9 @@
+ return (void*)((code==200) ? DONE : code);
+ }
+ virtual void* sendRedirect(const string& url) {
++ checkString(url, "Detected control character in an attempted redirect.");
++ if (g_allowedSchemes.find(url.substr(0, url.find(':'))) == g_allowedSchemes.end())
++ throw FatalProfileException("Invalid scheme in attempted redirect.");
+ ap_table_set(m_req->headers_out, "Location", url.c_str());
+ return (void*)REDIRECT;
+ }
+@@ -318,6 +325,15 @@
+ request_rec* m_req;
+ shib_dir_config* m_dc;
+ shib_server_config* m_sc;
++
++private:
++ void checkString(const string& s, const char* msg) {
++ string::const_iterator e = s.end();
++ for (string::const_iterator i=s.begin(); i!=e; ++i) {
++ if (iscntrl(*i))
++ throw FatalProfileException(msg);
++ }
++ }
+ };
+
+ /********************************************************************************/
+@@ -943,9 +959,25 @@
+ Locker locker(conf);
+ const IPropertySet* props=conf->getPropertySet("Local");
+ if (props) {
+- pair<bool,const char*> unsetValue=props->getString("unsetHeaderValue");
+- if (unsetValue.first)
+- g_unsetHeaderValue = unsetValue.second;
++ pair<bool,const char*> str=props->getString("unsetHeaderValue");
++ if (str.first)
++ g_unsetHeaderValue = str.second;
++ str=props->getString("allowedSchemes");
++ if (str.first) {
++ string schemes=str.second;
++ unsigned int j=0;
++ for (unsigned int i=0; i < schemes.length(); i++) {
++ if (schemes.at(i)==' ') {
++ g_allowedSchemes.insert(schemes.substr(j, i-j));
++ j = i+1;
++ }
++ }
++ g_allowedSchemes.insert(schemes.substr(j, schemes.length()-j));
++ }
++ }
++ if (g_allowedSchemes.empty()) {
++ g_allowedSchemes.insert("https");
++ g_allowedSchemes.insert("http");
+ }
+ }
+ catch (...) {
+--- shibboleth-sp.orig/schemas/shibboleth-targetconfig-1.0.xsd
++++ shibboleth-sp/schemas/shibboleth-targetconfig-1.0.xsd
+@@ -179,6 +179,7 @@
+ <attribute name="logger" type="anyURI" use="optional"/>
+ <attribute name="localRelayState" type="boolean" use="optional" default="false"/>
+ <attribute name="unsetHeaderValue" type="string" use="optional"/>
++ <attribute name="allowedSchemes" type="conf:listOfStrings"/>
+ <anyAttribute namespace="##other" processContents="lax"/>
+ </complexType>
+
+--- shibboleth-sp.orig/shib-target/shib-handlers.cpp
++++ shibboleth-sp/shib-target/shib-handlers.cpp
+@@ -316,7 +316,7 @@
+
+ if (target=="default") {
+ pair<bool,const char*> homeURL=app->getString("homeURL");
+- target=homeURL.first ? homeURL.second : "/";
++ target=homeURL.first ? homeURL.second : "";
+ }
+ else if (target=="cookie" || target.empty()) {
+ // Pull the target value from the "relay state" cookie.
+@@ -325,7 +325,7 @@
+ if (!relay_state || !*relay_state) {
+ // No apparent relay state value to use, so fall back on the default.
+ pair<bool,const char*> homeURL=app->getString("homeURL");
+- target=homeURL.first ? homeURL.second : "/";
++ target=homeURL.first ? homeURL.second : "";
+ }
+ else {
+ char* rscopy=strdup(relay_state);
+@@ -366,6 +366,19 @@
+ }
+ }
+
++ if (target == "") {
++ // No homeURL, so compute a URL to the root of the site.
++ int port = st->getPort();
++ const char* scheme = st->getProtocol();
++ target = string(scheme) + "://" + st->getHostname();
++ if ((!strcmp(scheme,"http") && port!=80) || (!strcmp(scheme,"https") && port!=443)) {
++ ostringstream portstr;
++ portstr << port;
++ target += ':' + portstr.str();
++ }
++ target += '/';
++ }
++
+ // Now redirect to the target.
+ return make_pair(true, st->sendRedirect(target));
+ }
+@@ -401,8 +414,19 @@
+ ret=handler->getString("ResponseLocation").second;
+ if (!ret)
+ ret=st->getApplication()->getString("homeURL").second;
+- if (!ret)
+- ret="/";
++ if (!ret) {
++ // No homeURL, so compute a URL to the root of the site.
++ int port = st->getPort();
++ const char* scheme = st->getProtocol();
++ string dest = string(scheme) + "://" + st->getHostname();
++ if ((!strcmp(scheme,"http") && port!=80) || (!strcmp(scheme,"https") && port!=443)) {
++ ostringstream portstr;
++ portstr << port;
++ dest += ':' + portstr.str();
++ }
++ dest += '/';
++ return make_pair(true, st->sendRedirect(dest));
++ }
+ return make_pair(true, st->sendRedirect(ret));
+ }
+
diff --git a/debian/patches/series b/debian/patches/series
index 67f99f4..a083830 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -3,3 +3,4 @@ remote-mysql
64-bit
security-cert-name
security-url-decode
+CVE-2009-3300
--
Debian packaging for the Shibboleth Apache SP
More information about the Pkg-shibboleth-devel
mailing list