CVE-2013-3300: Improper Restriction of Operations within the Bounds of a Memory Buffer (CWE-119)
value: The JsonParser class in json/JsonParser.scala in Lift before 2.5 interprets a certain end-index value as a length value, which allows remote authenticated users to obtain sensitive information from other users' sessions via invalid input data containing a < (less than) character.
CWE description: The product performs operations on a memory buffer, but it reads from or writes to a memory location outside the buffer's intended boundary. This may result in read or write operations on unexpected memory locations that could be linked to other variables, data structures, or internal program data.
Published: 2013-07-29T13:59Z
Repository: https://github.com/lift/framework
Language: Scala
Files changed: core/json/src/main/scala/net/liftweb/json/JsonParser.scala, core/json/src/test/scala/net/liftweb/json/JsonParserSpec.scala
Commit date: 2013-04-05 13:32:18 -0700
Commit message: Addresses a data bleeding issue with lift-json

Diff: diff --git a/core/json/src/main/scala/net/liftweb/json/JsonParser.scala b/core/json/src/main/scala/net/liftweb/json/JsonParser.scala
index 8bb2853e..5917b337 100644
--- a/core/json/src/main/scala/net/liftweb/json/JsonParser.scala
+++ b/core/json/src/main/scala/net/liftweb/json/JsonParser.scala
@@ -382,11 +382,15 @@ object JsonParser {
         }
         new String(chars)
       }
     }
 
-    def near = new String(segment, (cur-20) max 0, (cur + 1) min Segments.segmentSize)
+    def near = {
+      val start = (cur - 20) max 0
+      val len = ((cur + 1) min Segments.segmentSize) - start
+      new String(segment, start, len)
+    }
 
     def release = segments.foreach(Segments.release)
 
     private[JsonParser] def automaticClose = if (closeAutomatically) in.close
 
diff --git a/core/json/src/test/scala/net/liftweb/json/JsonParserSpec.scala b/core/json/src/test/scala/net/liftweb/json/JsonParserSpec.scala
index de1a6d34..5cd41e3d 100644
--- a/core/json/src/test/scala/net/liftweb/json/JsonParserSpec.scala
+++ b/core/json/src/test/scala/net/liftweb/json/JsonParserSpec.scala
@@ -25,10 +25,19 @@ import org.scalacheck.Prop._
 
 /**
  * System under specification for JSON Parser.
  */
 object JsonParserSpec extends Specification with JValueGen with ScalaCheck {
+
+  private def parseBadThing(): String =     try {
+    parse("""{"user":"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"<}""")
+    "x" * 1000
+  } catch {
+    case e: Throwable => e.getMessage
+  }
+
+
   "JSON Parser Specification".title
 
   "Any valid json can be parsed" in {
     val parsing = (json: JValue) => { parse(Printer.pretty(render(json))); true }
     check(forAll(genJValue)(parsing))
@@ -52,10 +61,19 @@ object JsonParserSpec extends Specification with JValueGen with ScalaCheck {
 
   "All valid string escape characters can be parsed" in {
     parse("[\"abc\\\"\\\\\\/\\b\\f\\n\\r\\t\\u00a0\"]") must_== JArray(JString("abc\"\\/\b\f\n\r\t\u00a0")::Nil)
   }
 
+
+  "Parser does not bleed prior results" in {
+    parse("""{"a": "now is the time for all good men to come to the aid of their dog and eat dog food with other dogs and bark and woof and do dog things. now is the time for all good men to come to the aid of their dog and eat dog food with other dogs and bark and woof and do dog things. now is the time for all good men to come to the aid of their dog and eat dog food with other dogs and bark and woof and do dog things. now is the time for all good men to come to the aid of their dog and eat dog food with other dogs and bark and woof and do dog things. now is the time for all good men to come to the aid of their dog and eat dog food with other dogs and bark and woof and do dog things. now is the time for all good men to come to the aid of their dog and eat dog food with other dogs and bark and woof and do dog things. now is the time for all good men to come to the aid of their dog and eat dog food with other dogs and bark and woof and do dog things.now is the time for all good men to come to the aid of their dog and eat dog food with other dogs and bark and woof and do dog things"}""")
+
+    val msg = parseBadThing()
+
+    msg.length must be_<=(50)
+  }
+
   "Unclosed string literal fails parsing" in {
     parseOpt("{\"foo\":\"sd") mustEqual None
     parseOpt("{\"foo\":\"sd}") mustEqual None
   }
 

Vulnerable code:     def near = new String(segment, (cur-20) max 0, (cur + 1) min Segments.segmentSize)
Fixed code:     def near = {
      val start = (cur - 20) max 0
      val len = ((cur + 1) min Segments.segmentSize) - start
      new String(segment, start, len)
    }

  private def parseBadThing(): String =     try {
    parse("""{"user":"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"<}""")
    "x" * 1000
  } catch {
    case e: Throwable => e.getMessage
  }



  "Parser does not bleed prior results" in {
    parse("""{"a": "now is the time for all good men to come to the aid of their dog and eat dog food with other dogs and bark and woof and do dog things. now is the time for all good men to come to the aid of their dog and eat dog food with other dogs and bark and woof and do dog things. now is the time for all good men to come to the aid of their dog and eat dog food with other dogs and bark and woof and do dog things. now is the time for all good men to come to the aid of their dog and eat dog food with other dogs and bark and woof and do dog things. now is the time for all good men to come to the aid of their dog and eat dog food with other dogs and bark and woof and do dog things. now is the time for all good men to come to the aid of their dog and eat dog food with other dogs and bark and woof and do dog things. now is the time for all good men to come to the aid of their dog and eat dog food with other dogs and bark and woof and do dog things.now is the time for all good men to come to the aid of their dog and eat dog food with other dogs and bark and woof and do dog things"}""")

    val msg = parseBadThing()

    msg.length must be_<=(50)
  }