<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Software and Opinions &#187; flickr</title>
	<atom:link href="http://ianloic.com/tag/flickr/feed/" rel="self" type="application/rss+xml" />
	<link>http://ianloic.com</link>
	<description>from Ian McKellar</description>
	<lastBuildDate>Wed, 07 Sep 2011 21:48:48 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
	<atom:link rel='hub' href='http://ianloic.com/?pushpress=hub'/>
		<item>
		<title>Flipy, a new Python library for Flickr</title>
		<link>http://ianloic.com/2010/01/26/flipy/</link>
		<comments>http://ianloic.com/2010/01/26/flipy/#comments</comments>
		<pubDate>Tue, 26 Jan 2010 19:31:25 +0000</pubDate>
		<dc:creator>Ian McKellar</dc:creator>
				<category><![CDATA[Default]]></category>
		<category><![CDATA[flickr]]></category>
		<category><![CDATA[flipy]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://ianloic.com/?p=185</guid>
		<description><![CDATA[In the past day or so I&#8217;ve written a new Python library for Flickr. It came from some frustration using other Python libraries. They&#8217;re all great, but none of them work quite how I want. My goal was to have &#8230; <a href="http://ianloic.com/2010/01/26/flipy/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>In the past day or so I&#8217;ve written a new Python library for Flickr. It came from some frustration using other Python libraries. They&#8217;re all great, but none of them work quite how I want.</p>
<p>My goal was to have a library that feels like <a href="http://en.wikipedia.org/wiki/Python_(programming_language)#Neologisms">Python</a> and the Flickr API at the same time. I think it&#8217;s worked out pretty well so far. You can make calls using the standard Flickr API calls as <a href="http://www.flickr.com/services/api/">documented</a> on the Flickr site, but the response objects feel like normal Python objects. For example you can do something like this:</p>
<pre class="prettyprint">from flipy import Flipy
flickr = Flipy(MY_API_KEY)
me = flickr.people.findByUsername(username='ianloic')
me_info = flickr.people.getInfo(user_id=me.nsid)
print 'My name is %s. I have %s photos at %s.' % (me_info.realname, me_info.photos.count, me_info.photosurl)</pre>
<p>I&#8217;ve put more details about the mapping in the <a href="http://github.com/ianloic/flipy#readme">README</a>.</p>
<p>Beyond simple mapping of methods to responses I&#8217;m working on decorating certain important response objects such as users and photos with more object oriented methods. For example right now if you have a user object you can call <code class="prettyprint">user.photos()</code> and get a iterator for of a user&#8217;s photos. My code takes care of all of the paging behind the scenes.</p>
<p>Since I haven&#8217;t implemented authentication or uploading yet so right now it&#8217;s mostly useful for simple mashup-style applications, but I&#8217;ll get uploads and authentication complete when I get back from <a href="http://en.wikipedia.org/wiki/Jordan">Jordan</a> next week.</p>
<p>Check out the code on <a href="http://github.com/ianloic/flipy">github</a> and let me know what you think.</p>
]]></content:encoded>
			<wfw:commentRss>http://ianloic.com/2010/01/26/flipy/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>A Different Model For Web Services Authorization</title>
		<link>http://ianloic.com/2009/01/05/a-different-model-for-web-services-authorization/</link>
		<comments>http://ianloic.com/2009/01/05/a-different-model-for-web-services-authorization/#comments</comments>
		<pubDate>Tue, 06 Jan 2009 07:59:46 +0000</pubDate>
		<dc:creator>Ian McKellar</dc:creator>
				<category><![CDATA[Default]]></category>
		<category><![CDATA[flickr]]></category>
		<category><![CDATA[google]]></category>
		<category><![CDATA[oauth]]></category>
		<category><![CDATA[security]]></category>

		<guid isPermaLink="false">http://ianloic.com/?p=102</guid>
		<description><![CDATA[In my last post I set out to describe how easy it is to extract private keys from desktop software. As I was concluding I stumbled on an alternative approach that might be more secure in some circumstances. I didn&#8217;t &#8230; <a href="http://ianloic.com/2009/01/05/a-different-model-for-web-services-authorization/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>In <a href="http://ianloic.com/2009/01/05/no-more-secrets/">my last post</a> I set out to describe how easy it is to extract private keys from desktop software. As I was concluding I stumbled on an alternative approach that might be more secure in some circumstances. I didn&#8217;t really go into details, so here&#8217;s an expansion of the idea.</p>
<p>Current API authentication mechanisms including Flickr Auth, OAuth, Yahoo BBAuth and Google AuthSub work by allowing users to grant an application the right to act for the user on the site. Some implementations allow the user to grant access to only a subset of the functionality — Flickr lets users grant just read access, Google lets users grant access to just one class of data (for example Google Docs but not Google Calendar). But still, the user doesn&#8217;t know which specific operations they&#8217;re allowing to be carried out. This wouldn&#8217;t matter so much if the user can trust the application that they&#8217;re granting access to, but there&#8217;s no way to provide for that completely.</p>
<p>Another approach might be to give third-party applications the ability to submit sets of changes to be applied to a user&#8217;s account, but require the user to approve them through the service provider&#8217;s web site before they&#8217;re applied to the the user&#8217;s real data. For example, a Flickr upload might look like this:</p>
<ul>
<li>Client makes API request flickr.transaction.create(total_files=20, total_data=20M)</li>
<li>Flickr responds with transaction id X and a maximum lifetime for the transaction</li>
<li>Flickr responds with an URL to direct the user&#8217;s browser to to:
<ul>
<li>associate the transaction with an account, and</li>
<li>preview, permit and commit the changes</li>
</ul>
</li>
</ul>
<p>To a user this isn&#8217;t going to look or feel to different from the current Flickr upload scenario where on completion they&#8217;re presented with a set of uploaded photos and offered the opportunity to make metadata changes.</p>
<p>The key advantage here from a security standpoint is that users approve actions not applications. The challenge of expressing a set of changes to a user clearly is not small but unlike the challenge of identifying and trusting applications it&#8217;s solvable.</p>
<p>This model probably only makes sense for write-oriented sessions, and for infrequent, large write sessions (such as Flickr uploads) rather than frequent, small writes (like Twitter posting).</p>
<p>These ideas aren&#8217;t well thought out in my head, they&#8217;re fresh from me trying to come up with a workable model for API authentication and authorization that doesn&#8217;t depend on trusting the identity of clients. I&#8217;d really welcome feedback and ideas on how to take this forward and feedback implementers on the feasibility of adopting a model like this.</p>
]]></content:encoded>
			<wfw:commentRss>http://ianloic.com/2009/01/05/a-different-model-for-web-services-authorization/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>No More Secrets</title>
		<link>http://ianloic.com/2009/01/05/no-more-secrets/</link>
		<comments>http://ianloic.com/2009/01/05/no-more-secrets/#comments</comments>
		<pubDate>Mon, 05 Jan 2009 23:40:31 +0000</pubDate>
		<dc:creator>Ian McKellar</dc:creator>
				<category><![CDATA[Default]]></category>
		<category><![CDATA[flickr]]></category>
		<category><![CDATA[oauth]]></category>
		<category><![CDATA[security]]></category>

		<guid isPermaLink="false">http://ianloic.com/?p=93</guid>
		<description><![CDATA[Using secret keys to identify applications communicating across the internet has become popular as people have copied the very successful Flickr authentication API. Unfortunately people trust that they can keep these keys secret from attackers, even as they distribute applications &#8230; <a href="http://ianloic.com/2009/01/05/no-more-secrets/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Using secret keys to identify applications communicating across the internet has become popular as people have copied the very successful <a href="http://www.flickr.com/services/api/auth.spec.html">Flickr authentication API</a>. Unfortunately people trust that they can keep these keys secret from attackers, even as they distribute applications that contain the secret keys to other people. I decided to see how hard it would be to extract the secret key and API key from Flickr&#8217;s new XULRunner based <a href="http://www.flickr.com/tools/uploadr/">Uploadr</a>.</p>
<p>While the Uploadr is nominally open source, they don&#8217;t include the key in the source code. In the README they instruct anyone building it to acquire their own key and modify the source code to include that key:</p>
<pre>You'll need your own API key and secret from Flickr to build Uploadr.
These can be obtained at http://flickr.com/services/api/.  The key
and secret must be placed in flKey.cpp as indicated.  This file is at:
  UPLOADR/MacUploadr.app/Contents/Resources/components/flKey.cpp

The API key is stored as a string.  The secret is stored as individual
characters so it is not easily readable from the binary.</pre>
<p>Such noble goals.</p>
<p>Getting the API key was as simple as running tcpdump:</p>
<pre>sudo tcpdump -i en1 -vvv -n -s 0 -w /tmp/DumpFile.dmp</pre>
<p>running the Uploadr, and then looking through the dump file to find where the API key is passed. Look:</p>
<pre>api_key=a5c4c07991a15c6b56b88005a76e7774</pre>
<p>In theory getting the secret key is harder, but it turned out to be even easier. It&#8217;s stored in the source code for the <code>flKey::Sign</code> method:</p>
<pre>	// The shared secret
#ifdef XP_MACOSX
	bytes[0] = '-';
	bytes[1] = '-';
	bytes[2] = '-';
	bytes[3] = '-';
	bytes[4] = '-';
	bytes[5] = '-';
	bytes[6] = '-';
	bytes[7] = '-';
	bytes[8] = '-';
	bytes[9] = '-';
	bytes[10] = '-';
	bytes[11] = '-';
	bytes[12] = '-';
	bytes[13] = '-';
	bytes[14] = '-';
	bytes[15] = '-';
#endif</pre>
<p>All I need to do is find that code, disassemble it and reassemble the string. I ran the Uploadr under gdb:</p>
<pre>gdb '/Applications/Flickr Uploadr.app/Contents/MacOS/xulrunner'</pre>
<p>and once it was up and running tried to find something to break on that would expose the secret key. There weren&#8217;t symbols for the <code>flKey::Sign</code> method that&#8217;s defined in the source file but I found I could break on <code>MD5Init</code> that&#8217;s called from that function. So:</p>
<pre>break MD5Init
kill
run</pre>
<p>And now I stop in the middle of the signature function &#8211; and from the stack trace I can see where flKey::Sign begins:</p>
<pre>Breakpoint 1, 0x149a086b in MD5Init ()
(gdb) where
#0  0x149a086b in MD5Init ()
#1  0x149a1588 in flKey::Sign ()
#2  0x017bb45d in NS_InvokeByIndex_P ()
...</pre>
<p>All I have to do is disassemble <code>flKey::Sign</code>:</p>
<pre>(gdb) disassemble 0x149a1588
Dump of assembler code for function _ZN5flKey4SignERK9nsAStringRS0_:
0x149a1498 &lt;_ZN5flKey4SignERK9nsAStringRS0_+0&gt;:	push   %ebp
0x149a1499 &lt;_ZN5flKey4SignERK9nsAStringRS0_+1&gt;:	mov    %esp,%ebp
0x149a149b &lt;_ZN5flKey4SignERK9nsAStringRS0_+3&gt;:	push   %edi
0x149a149c &lt;_ZN5flKey4SignERK9nsAStringRS0_+4&gt;:	push   %esi
...
0x149a153e &lt;_ZN5flKey4SignERK9nsAStringRS0_+166&gt;:	movb   <strong>$0xXX</strong>,(%eax)
0x149a1541 &lt;_ZN5flKey4SignERK9nsAStringRS0_+169&gt;:	movb   <strong>$0xXX</strong>,0x1(%eax)
0x149a1545 &lt;_ZN5flKey4SignERK9nsAStringRS0_+173&gt;:	movb   <strong>$0xXX</strong>,0x2(%eax)
0x149a1549 &lt;_ZN5flKey4SignERK9nsAStringRS0_+177&gt;:	movb   <strong>$0xXX</strong>,0x3(%eax)
0x149a154d &lt;_ZN5flKey4SignERK9nsAStringRS0_+181&gt;:	movb   <strong>$0xXX</strong>,0x4(%eax)
0x149a1551 &lt;_ZN5flKey4SignERK9nsAStringRS0_+185&gt;:	movb   <strong>$0xXX</strong>,0x5(%eax)
0x149a1555 &lt;_ZN5flKey4SignERK9nsAStringRS0_+189&gt;:	movb   <strong>$0xXX</strong>,0x6(%eax)
0x149a1559 &lt;_ZN5flKey4SignERK9nsAStringRS0_+193&gt;:	movb   <strong>$0xXX</strong>,0x7(%eax)
0x149a155d &lt;_ZN5flKey4SignERK9nsAStringRS0_+197&gt;:	movb   <strong>$0xXX</strong>,0x8(%eax)
0x149a1561 &lt;_ZN5flKey4SignERK9nsAStringRS0_+201&gt;:	movb   <strong>$0xXX</strong>,0x9(%eax)
0x149a1565 &lt;_ZN5flKey4SignERK9nsAStringRS0_+205&gt;:	movb   <strong>$0xXX</strong>,0xa(%eax)
0x149a1569 &lt;_ZN5flKey4SignERK9nsAStringRS0_+209&gt;:	movb   <strong>$0xXX</strong>,0xb(%eax)
0x149a156d &lt;_ZN5flKey4SignERK9nsAStringRS0_+213&gt;:	movb   <strong>$0xXX</strong>,0xc(%eax)
0x149a1571 &lt;_ZN5flKey4SignERK9nsAStringRS0_+217&gt;:	movb   <strong>$0xXX</strong>,0xd(%eax)
0x149a1575 &lt;_ZN5flKey4SignERK9nsAStringRS0_+221&gt;:	movb   <strong>$0xXX</strong>,0xe(%eax)
0x149a1579 &lt;_ZN5flKey4SignERK9nsAStringRS0_+225&gt;:	movb   <strong>$0xXX</strong>,0xf(%eax)
...
0x149a168e &lt;_ZN5flKey4SignERK9nsAStringRS0_+502&gt;:	pop    %esi
0x149a168f &lt;_ZN5flKey4SignERK9nsAStringRS0_+503&gt;:	pop    %edi
0x149a1690 &lt;_ZN5flKey4SignERK9nsAStringRS0_+504&gt;:	pop    %ebp
0x149a1691 &lt;_ZN5flKey4SignERK9nsAStringRS0_+505&gt;:	ret
End of assembler dump.</pre>
<p>And sure enough if I reconstruct those bytes, the secret key is: <strong style="color:white;background-color:black;"><code>REDACTED</code><code>REDACTED</code></strong></p>
<p>That wasn&#8217;t too hard was it? The fact that the code around the key was open source made it easier to find but even if it was closed source if I knew what kind of algorithm I was looking for it wouldn&#8217;t be hard to find and examine. It&#8217;s pretty easy to trace forward from user input or backward from network IO to find the signature algorithm, and the secret&#8217;s always the input to that.</p>
<p>Unfortunately <a href="http://oauth.net/">OAuth</a> follows the same model as Flickr, placing some value in a consumer&#8217;s &#8220;private&#8221; key. They do mention in <a href="http://oauth.net/core/1.0/#anchor40">Appendix B.7</a> that it&#8217;s often possible for attackers to access a secret it&#8217;s still a vital part of the protocol.</p>
<p>Since it&#8217;s not possible to securely identify clients we should move to a model where users approve actions against their accounts rather than granting carte-blanche actions to clients. For example Flickr could put photos that are uploaded into a staging area and require approval on the web site before including them in a user&#8217;s photo stream. This would allow users to make a informed decisions about third-party access to their accounts.</p>
<p><b>Updated:</b> at Flickr&#8217;s request I&#8217;ve removed the &#8220;secret&#8221; key.</p>
<p><b>Updated again:</b> I made <a href="http://ianloic.com/2009/01/05/a-different-model-for-web-services-authorization/">another post</a> about this topic, expanding on the final paragraph of this post.</p>
]]></content:encoded>
			<wfw:commentRss>http://ianloic.com/2009/01/05/no-more-secrets/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Flickr for Dojo</title>
		<link>http://ianloic.com/2007/02/10/flickr_for_dojo/</link>
		<comments>http://ianloic.com/2007/02/10/flickr_for_dojo/#comments</comments>
		<pubDate>Wed, 30 Nov -0001 00:00:00 +0000</pubDate>
		<dc:creator>Ian McKellar</dc:creator>
				<category><![CDATA[Default]]></category>
		<category><![CDATA[dojo]]></category>
		<category><![CDATA[flickr]]></category>
		<category><![CDATA[json]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[I&#8217;ve been working on a little Dojo based application which talks to Flickr, so I put together a little library which uses Dojo to talk to Flickr using it&#8217;s rest JSON interface. Use It&#8217;s pretty simple to use, just include &#8230; <a href="http://ianloic.com/2007/02/10/flickr_for_dojo/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been working on a little <a href="http://www.dojotoolkit.org/">Dojo</a> based application which talks to <a href="http://www.flickr.com/">Flickr</a>, so I put together a little library which uses Dojo to talk to Flickr using it&#8217;s rest <a href="http://www.json.org/">JSON</a> interface.</p>
<p><strong>Use</strong><br />
It&#8217;s pretty simple to use, just include the JavaScript file:</p>
<pre class="prettyprint">
&lt;script src="flickr.js"&gt;&lt;/script&gt;</pre>
<p>Tell the library what your <a href="http://www.flickr.com/services/api/keys/">keys</a> are:</p>
<pre class="prettyprint">
flickr.keys(API_KEY, SECRET_KEY);</pre>
<p>And you&#8217;re set to go.</p>
<p>The main entry-point is <code language="js">flickr.call</code>. As the first argument, you pass in a hash of arguments, as described in the <a href="http://www.flickr.com/services/api/">Flickr API documentation</a>. The method you&#8217;re calling is included in this hash. The second argument is optional and is a callback to be called with the response from the Flickr servers. The response will come back in JSON format so it is easy to handle it in JavaScript. The Flickr JSON response format is discussed in detail <a href="http://www.flickr.com/services/api/response.json.html">on the Flickr site</a>.</p>
<p>So what would all this look like? Something like this will load interesting photos from Flickr and add them to the current document:</p>
<pre class="prettyprint">
flickr.keys(API_KEY, SECRET_KEY);
var pagenum = 1;
function interesting () {
    flickr.call({method:'flickr.interestingness.getList',
            page: pagenum, per_page: 10}, interesting_cb);
    pagenum++;
}
function interesting_cb (response) {
    if (response.stat != 'ok') {
        var error = document.createElement('div');
        error.appendChild(document.createTextNode(response.message));
        document.body.appendChild(error);
        return;
    }
    for (var i in response.photos.photo) {
        var photo = response.photos.photo[i];
        var img = document.createElement('img');
        img.classname = 'interesting';
        img.setAttribute('src', 'http://farm'+photo.farm+
                '.static.flickr.com/'+photo.server+'/'+photo.id+
                '_'+photo.secret+'_s.jpg');
        img.setAttribute('width', '75');
        img.setAttribute('height', '75');

        var a = document.createElement('a');
        a.setAttribute('href', 'http://www.flickr.com/photos/'+
                photo.owner+'/'+photo.id);
        a.appendChild(img);

        document.body.appendChild(a)
    }
}</pre>
<p><strong>Implementation</strong><br />
I&#8217;m not actually using all that much from Dojo. The main thing I&#8217;m taking is the crypto library, specifically <a href="http://dojotoolkit.org/api/#dojo.crypto.MD5">dojo.crypto.MD5</a>. The way I&#8217;m making the actual JSON calls is by appending <code language="html"><script src="http://api.flickr.com/services/..."></script></code> elements to the page. Perhaps at some point I&#8217;ll move to using Dojo&#8217;s ScriptSrcIO but right now I&#8217;m not.</p>
<p>The current version of the code is attached: <a href="http://scratch.ianloic.com/wordpress/wp-content/uploads/2008/01/flickrjs.txt" title="flickr.js">flickr.js</a></p>
]]></content:encoded>
			<wfw:commentRss>http://ianloic.com/2007/02/10/flickr_for_dojo/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Flickr Authentication Security</title>
		<link>http://ianloic.com/2006/12/23/flickr_authentication_security/</link>
		<comments>http://ianloic.com/2006/12/23/flickr_authentication_security/#comments</comments>
		<pubDate>Wed, 30 Nov -0001 00:00:00 +0000</pubDate>
		<dc:creator>Ian McKellar</dc:creator>
				<category><![CDATA[Default]]></category>
		<category><![CDATA[flickr]]></category>
		<category><![CDATA[json]]></category>
		<category><![CDATA[security]]></category>
		<category><![CDATA[xss]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[[flickr-photo:id=1187679,size=m] Recently <a href="http://www.flickr.com/">Flickr</a> closed a little security hole I found in their API authentication. I was able to convince their servers to hand out a token to me based on a user's cookies and the <a href="http://www.flickr.com/services/api/keys/">API key and secret key</a> of an application the user had used. Then with the <a href="http://www.flickr.com/services/api/response.json.html">JSON</a> form of the Flickr API I had full access to the user's account. 

The there two flaws in Flickr's security that exposed this problem. The first was that the security is based on the assumption that applications can keep a key secret. This is easy for web applications that make server to server API calls, but for anything that a user downloads and especially open source software it's impossible to keep the key secret. My experiment used the secret key from <a href="http://www.flock.com/">Flock</a> which is open source - the secret key can be found in <a href="http://svn-mirror.flock.com/">subversion</a>, and the secret key from Flickr's own MacOS X uploader application which can be easilly extracted from the download from their site. Secondly the Flickr server was giving out new authentication tokens without requiring user approval.

The exploit itself is a little state-machine making a series of Flickr API calls and using one IFRAME. It goes like this:
<ul>
<li>Request a frob (via JSON)</li>
<li>Request authentication (via an IFRAME)</li>
<li>Request the auth token (via JSON)</li>
<li>Do evil (via JSON)</li>
</ul>
In my case the evil consisted of posting a comment on the user's most recent photo.

The security hole is now closed, but if you're interested in seeing how to access the Flickr API entirely from JavaScript in a web page take a look at the attached exploit. You'll also need the MD5 library. <a href="http://ianloic.com/2006/12/23/flickr_authentication_security/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Recently <a href="http://www.flickr.com/">Flickr</a> closed a little security hole I found in their API authentication. I was able to convince their servers to hand out a token to me based on a user&#8217;s cookies and the <a href="http://www.flickr.com/services/api/keys/">API key and secret key</a> of an application the user had used. Then with the <a href="http://www.flickr.com/services/api/response.json.html">JSON</a> form of the Flickr API I had full access to the user&#8217;s account.</p>
<p>The there two flaws in Flickr&#8217;s security that exposed this problem. The first was that the security is based on the assumption that applications can keep a key secret. This is easy for web applications that make server to server API calls, but for anything that a user downloads and especially open source software it&#8217;s impossible to keep the key secret. My experiment used the secret key from <a href="http://www.flock.com/">Flock</a> which is open source &#8211; the secret key can be found in <a href="http://svn-mirror.flock.com/">subversion</a>, and the secret key from Flickr&#8217;s own MacOS X uploader application which can be easilly extracted from the download from their site. Secondly the Flickr server was giving out new authentication tokens without requiring user approval.</p>
<p>The exploit itself is a little state-machine making a series of Flickr API calls and using one IFRAME. It goes like this:</p>
<ul>
<li>Request a frob (via JSON)</li>
<li>Request authentication (via an IFRAME)</li>
<li>Request the auth token (via JSON)</li>
<li>Do evil (via JSON)</li>
</ul>
<p>In my case the evil consisted of posting a comment on the user&#8217;s most recent photo.</p>
<p>The security hole is now closed, but if you&#8217;re interested in seeing how to access the Flickr API entirely from JavaScript in a web page take a look at the attached exploit: <a href="http://scratch.ianloic.com/wordpress/wp-content/uploads/2008/01/sploitr.html" title="sploitr.html">sploitr.html</a> and the md5 library: <a href="http://scratch.ianloic.com/wordpress/wp-content/uploads/2008/01/md5js.txt" title="md5.js">md5.js</a></p>
]]></content:encoded>
			<wfw:commentRss>http://ianloic.com/2006/12/23/flickr_authentication_security/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>

