Kryn CMS 0.6 Cross Site Request Forgery / Cross Site Scripting

Type packetstorm
Reporter TurboBorland
Modified 2010-06-30T00:00:00


                                            `Found By: TurboBorland  
Email Address:  
Software: Kryn <=0.6  
Date Found: 06/21/2010  
Date Submitted: 06/29/2010  
Ethical Disclosure: Vendor submitted - Replied with fix: "We've fix  
this issues and already uploaded the new versions for kryn-core and  
usermanagement." - Submission to bugtraq.  
Vulnerabilities: Persistent XSS & Administrative information change for CSRF  
Kryn CMS has multiple vulnerabilities. This includes the ability to  
immediately own the site based off of a failed login in the  
administrative login.  
The vulnerable code, included in:  
line 96  
klog('authentication', str_replace("%s", $_REQUEST['username'],  
"SECURITY Login failed for '%s' to administration"));  
This is the overview section of the administrative login, which is the  
entry to several administrative tasks. This will permanently store the  
injection in both the failed logins and the "logs", which will execute  
automatically upon viewing.  
The next vulnerability is a CSRF. No action in the administrative  
panel has a random token, nonce, to verify an action. Through this,  
the PoC shown has the ability to change admin information:[%221%22]&module=users&code=users%2FeditMe%2F  
Vulnerable Code:  
class usersAdminEdit extends windowEdit {  
public $table = 'system_user';  
public $checkUsage = true; //default on  
public $primary = array('rsn');  
function __construct(){  
$rsn = getArgv('rsn')+0;  
public $fields = array(  
'username' => array(  
'label' => 'Username',  
'desc' => 'Also the administration login',  
'type' => 'text',  
'empty' => false  
'email' => array(  
'label' => 'Email',  
'type' => 'text',  
'empty' => false  
'passwd' => array(  
'label' => 'Password',  
'desc' => 'Let it empty to change nothing',  
'type' => 'password',  
'startempty' => true,  
'onlyIfFilled' => true,  
'modifier' => 'toPasswd'  
'adminLanguage' => array(  
'label' => 'Admin Language',  
'type' => 'select',  
'sql' => 'SELECT * FROM %pfx%system_langs',  
'table_key' => 'code',  
'table_label' => 'title',  
'customSave' => 'saveLanguage',  
'customValue' => 'getLanguage',  
'userBg' => array(  
'label' => 'Desktop background image',  
'type' => 'fileChooser',  
'customSave' => 'saveUserBg',  
'customValue' => 'userBgValue',  
'groups' => array(  
'label' => 'Groups',  
'type' => 'select',  
'table' => 'system_groupaccess',  
//TODO geht so nicht,aber so vllt:  
'relation' => 'n-n',  
'n-n' => array(  
'right' => 'system_groups',  
'right_key' => 'rsn',  
'right_label' => 'name',  
'middle' => 'system_groupaccess',  
'middle_keyright' => 'group_rsn',  
'middle_keyleft' => 'user_rsn',  
'left_key' => 'rsn'  
'size' => 6,  
'multiple' => 1,  
'fake' => true //'group' will not be used in update  
public function userBgValue($pPrimary, $pItem){  
$rsn = $pPrimary['rsn'];  
$user = dbTableFetch('system_user', 1, "rsn = $rsn");  
$settings = unserialize($user['settings']);  
return $settings['userBg'];  
public function saveUserBg(){  
global $user;  
$cacheCode = "user_".(getArgv('rsn')+0);  
$user = dbTableFetch('system_user', 1, "rsn = ".(getArgv('rsn')+0));  
$settings = unserialize( $user['settings'] );  
$settings['userBg'] = getArgv('userBg', 1);  
$settings = serialize( $settings );  
dbUpdate( 'system_user', array('rsn' => getArgv('rsn')+0),  
array('settings' => $settings) );  
public function saveLanguage(){  
$user = dbTableFetch('system_user', 1, "rsn = ".(getArgv('rsn')+0));  
$settings = unserialize( $user['settings'] );  
$settings['adminLanguage'] = getArgv('adminLanguage');  
$settings = serialize( $settings );  
dbUpdate( 'system_user', array('rsn' => getArgv('rsn')+0),  
array('settings' => $settings) );  
public function getLanguage( $pPrimary, $pItem ){  
$rsn = $pPrimary['rsn'];  
$user = dbTableFetch('system_user', 1, "rsn = $rsn");  
$settings = unserialize($user['settings']);  
return $settings['adminLanguage'];  
public function toPasswd( $pPw ){  
return md5($pPw);  
No nonce checking for any field in submission. POST used, but not required.  
+++Vulnerability Impact: Through this, our injection will modify  
whatever we feel like for whatever user:  
<img src="[%221%22]&module=users&code=users%2FeditMe%2F"/>  
No bounds checking (even if added, we can point a script src= to a  
script and still inject), will inject this CSRF into the page as  
persistant XSS, and once admin logs in and looks at overview,  
immediate (can be made quieter) control can be had.  
Virtual file manager already included, so no need for shell. ;)