anchorcms/anchor-cms

There is a storage xss vulnerability after you login in

Closed this issue · 7 comments

First, let me explain the harm of the vulnerability.
Storage type XSS is also called persistent type.In general, it is the most harmful of the three XSS.This type of XSS vulnerability is caused by malicious attack code that is persisted to the server and then displayed on the HTML page. I found a storage XSS in anchorcms. The trigger condition is to log in. The details are as follows:

The first step:In this case, I'm going to audit the trace of the hazard function, and look for the print function, I found this in /anchor/libraries/languages.php file ,The following code:

public static function line($key, $default = '', $args = array()) {
$parts = explode('.', $key);

	if(count($parts) > 1) {
		$file = array_shift($parts);
		$line = array_shift($parts);
	}

	if(count($parts) == 1) {
		$file = 'global';
		$line = array_shift($parts);
	}

	if( ! isset(static::$lines[$file])) {
		static::load($file);
	}

	if(isset(static::$lines[$file][$line])) {
		$text = static::$lines[$file][$line];
	}
	else if($default) {
		$text = $default;
	}
	else {
		$text = $key;
	}

	if(count($args)) {
		return call_user_func_array('sprintf', array_merge(array($text), $args));
	}

	return $text;
}

The second step:
By see, This defines a line function that calls call_user_func_array (), which takes the second argument Pass the first argument as a variable.Pass it to sprintf() here, and see if the second parameter in call_user_func_array () is controllable. Global search where to call the line function, found a return in /anchor/helpers.php, and trace the file as follows:

function __($line) {
$args = array_slice(func_get_args(), 1);

return Language::line($line, null, $args);

The third step:By see,Here we found a function __(), which intercepts the incoming $line and returns the output parameters $line and $args
Parameters can be controlled, so again global search, to see whether call function __(), I found a lot, Here to enter /anchor/views/pages/add.php file

The fourth step:Choose to enter, enter here /anchor/views/pages/add.php found processing ,The following code:

<input name="token" type="hidden" value="<?php echo $token; ?>">

<fieldset class="header">
	<div class="wrap">
		<?php echo $messages; ?>

		<?php echo Form::text('title', Input::previous('title'), array(
			'placeholder' => __('pages.title'),
			'autocomplete'=> 'off',
			'autofocus' => 'true'
		)); ?>

		<aside class="buttons">
			<?php echo Form::button(__('global.save'), array(
				'type' => 'submit',
				'class' => 'btn'
			)); ?>

			<?php echo Form::button(__('pages.redirect'), array(
				'class' => 'btn secondary'
			)); ?>
		</aside>
	</div>
</fieldset>

<fieldset class="redirect">
	<div class="wrap">
		<?php echo Form::text('redirect', Input::previous('redirect'), array(
			'placeholder' => __('pages.redirect_url')
		)); ?>
	</div>
</fieldset>

<fieldset class="main">
	<div class="wrap">
		<?php echo Form::textarea('content', Input::previous('content'), array(
			'placeholder' => __('pages.content_explain')
		)); ?>

		<?php echo $editor; ?>
	</div>
</fieldset>

<fieldset class="meta split">
	<div class="wrap">
		<p>
			<label for="label-show_in_menu"><?php echo __('pages.show_in_menu'); ?>:</label>
			<?php echo Form::checkbox('show_in_menu', 1, Input::previous('show_in_menu', 0) == 1, array('id' => 'label-show_in_menu')); ?>
			<em><?php echo __('pages.show_in_menu_explain'); ?></em>
		</p>
		<p>
			<label for="label-name"><?php echo __('pages.name'); ?>:</label>
			<?php echo Form::text('name', Input::previous('name'), array('id' => 'label-name')); ?>
			<em><?php echo __('pages.name_explain'); ?></em>
		</p>
		<p>
			<label for="label-slug"><?php echo __('pages.slug'); ?>:</label>
			<?php echo Form::text('slug', Input::previous('slug'), array('id' => 'label-slug')); ?>
			<em><?php echo __('pages.slug_explain'); ?></em>
		</p>
		<p>
			<label for="label-status"><?php echo __('pages.status'); ?>:</label>
			<?php echo Form::select('status', $statuses, Input::previous('status'), array('id' => 'label-status')); ?>
			<em><?php echo __('pages.status_explain'); ?></em>
		</p>
		<p>
			<label for="label-parent"><?php echo __('pages.parent'); ?>:</label>
			<?php echo Form::select('parent', $pages, Input::previous('parent'), array('id' => 'label-parent')); ?>
			<em><?php echo __('pages.parent_explain'); ?></em>
		</p>
		<?php foreach($fields as $field): ?>
		<p>
			<label for="extend_<?php echo $field->key; ?>"><?php echo $field->label; ?>:</label>
			<?php echo Extend::html($field); ?>
		</p>
		<?php endforeach; ?>
	</div>
</fieldset>
<script src=""></script> <script src=""></script> <script src=""></script> <script src=""></script> <script src=""></script> <script src=""></script> <script> $('textarea[name=content]').editor(); </script>

The step 5: Then build the environment into the following:
I'm sorry, I don't know how to paste the picture here, I just described verbally. The following:

Built environment into the root directory /index.php/admin/pages/add, need to log in here. Insert <script>alert(1)</script> in the form name and ni-hao in the form slug, And then visit root directory /index.php/admin/pages/ and bounced

  • Anchor version:0.9.2

"after you login", how can this be a vulnerability when you need to be logged in? Surely if you're logged in you're already vulnerable? 🤔

"after you login", how can this be a vulnerability when you need to be logged in? Surely if you're logged in you're already vulnerable?

This is a vulnerability in itself. I can insert a link of rebound cookie. which will be triggerd when the administrator or others . so that I can log in directly with the cookie.without the account password.

Well if you think it's an issue you're welcome to contribute with a fix ✨

This is a vulnerability in itself. I can insert a link of rebound cookie. which will be triggerd when the administrator or others [do what?]. so that I can log in directly with the cookie.without the account password.

So wouldn't the vulnerability be with the cookies? I'm no expert though. 🤷‍♂️ Nevermind, I was silly on this one. But still,

Duplicate of #1298?

Anchor explicitly allows admins to use raw HTML in their pages. If a user was able to make a comment with XXS, then yes this would be a problem.

Feel like this should be closed since, as @Gerrit0 has pointed out, it’s already been addressed in #1298. Anchor intentionally allows markup when entering content, it’s down to the user to take care when entering content

Further, it was confirmed that no user could insert unescaped chars in #1102. Closing this unless there's a genuine vulnerability. If comments are sanitized, then it's not possible for someone to steal cookies?