Package: jenkins-winstone / 0.9.10-jenkins-37+dfsg-2

CVE-2012-6072.patch Patch series | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
From 62e890b9589a844553d837d91b5f68eb3dba334e Mon Sep 17 00:00:00 2001
From: Kohsuke Kawaguchi <kk@kohsuke.org>
Date: Mon, 12 Nov 2012 16:25:06 -0800
Subject: [PATCH] [FIXED SECURITY-44]

Do not allow the webapp to split HTTP header values into multiple lines. Since there's no obvious escaping semantics here, we just drop those characters, which is what Jetty does.
---
 src/java/winstone/URIUtil.java                 |   14 +++++++++++---
 src/java/winstone/WinstoneOutputStream.java    |    3 +--
 src/java/winstone/ajp13/Ajp13OutputStream.java |    6 +++---
 3 files changed, 15 insertions(+), 8 deletions(-)

--- a/src/java/winstone/URIUtil.java
+++ b/src/java/winstone/URIUtil.java
@@ -2,8 +2,8 @@ package winstone;
 
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.Iterator;
 import java.util.List;
+import java.util.regex.Pattern;
 
 /**
  * @author Kohsuke Kawaguchi
@@ -15,9 +15,9 @@ public class URIUtil {
      * this method preserves the leading and trailing '/'.
      */
     static String canonicalPath(String path) {
-        List r = new ArrayList(Arrays.asList(path.split("[/\\\\]+")));
+        List<String> r = new ArrayList<String>(Arrays.asList(path.split("[/\\\\]+")));
         for (int i=0; i<r.size(); ) {
-            String cur = (String)r.get(i);
+            String cur = r.get(i);
             if (cur.length()==0 || cur.equals(".")) {
                 // empty token occurs for example, "".split("/+") is [""]
                 r.remove(i);
@@ -67,4 +67,12 @@ public class URIUtil {
         }
         return buf.toString();
     }
+
+    /**
+     * Removes any occurrence of CR and LF in the text.
+     */
+    public static String noCRLF(String text) {
+        // so long as the value doesn't contain CR nor LF, don't really care how they get replaced
+        return text.replace('\r',' ').replace('\n',' ');
+    }
 }
--- a/src/java/winstone/WinstoneOutputStream.java
+++ b/src/java/winstone/WinstoneOutputStream.java
@@ -10,7 +10,6 @@ import java.io.BufferedOutputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.OutputStream;
-import java.util.Iterator;
 import java.util.Stack;
 
 import javax.servlet.http.Cookie;
@@ -147,7 +146,7 @@ public class WinstoneOutputStream extend
             // Write headers and cookies
             for (Object o2 : this.owner.getHeaders()) {
                 String header = (String) o2;
-                o.write(header.getBytes("8859_1"));
+                o.write(URIUtil.noCRLF(header).getBytes("8859_1"));
                 o.write(CR_LF);
                 Logger.log(Logger.FULL_DEBUG, Launcher.RESOURCES,
                         "WinstoneOutputStream.Header", header);
--- a/src/java/winstone/ajp13/Ajp13OutputStream.java
+++ b/src/java/winstone/ajp13/Ajp13OutputStream.java
@@ -11,12 +11,12 @@ import java.io.IOException;
 import java.io.OutputStream;
 import java.io.UnsupportedEncodingException;
 import java.util.Hashtable;
-import java.util.Iterator;
 import java.util.Map;
 
 import javax.servlet.http.Cookie;
 
 import winstone.Logger;
+import winstone.URIUtil;
 import winstone.WinstoneException;
 import winstone.WinstoneOutputStream;
 
@@ -78,8 +78,8 @@ public class Ajp13OutputStream extends W
                 if (colonPos == -1)
                     throw new WinstoneException(Ajp13Listener.AJP_RESOURCES.getString(
                             "Ajp13OutputStream.NoColonHeader", header));
-                String headerName = header.substring(0, colonPos).trim();
-                String headerValue = header.substring(colonPos + 1).trim();
+                String headerName = URIUtil.noCRLF(header.substring(0, colonPos).trim());
+                String headerValue = URIUtil.noCRLF(header.substring(colonPos + 1).trim());
                 byte headerCode[] = (byte[]) headerCodes.get(headerName
                         .toLowerCase());
                 if (headerCode == null) {