Skip to content

Patch to fix IDOR vulnerability in userinfo.php#1541

Draft
emilylwan wants to merge 9 commits into
ImpressCMS:mainfrom
emilylwan:1.5.x-idor-vulnerability
Draft

Patch to fix IDOR vulnerability in userinfo.php#1541
emilylwan wants to merge 9 commits into
ImpressCMS:mainfrom
emilylwan:1.5.x-idor-vulnerability

Conversation

@emilylwan
Copy link
Copy Markdown

This PR prevents the existing IDOR vulnerability at the endpoint userinfo.php/?uid=. Currently hackers are able to gain access to profiles by manipulating the uid field in the url to retrieve any profile in the database. We prevent that by changing what is received in the url.

Changes were made to the database structure, the user object, and the redirect urls to userinfo.php to support implementing a new hash_uid variable. The hash_uid variable is a randomly generated 64 character long hex string. It is saved into the databases and replaces the uid that is shown in the url of the userinfo.php page to prevent users from gaining access to another user’s profile through guessing the uid and crafting the url. This hash_uid is also used to verify if a current user is the same as the profile user to enable editing access. It also retrieves the user’s profile. These changes help remove the IDOR vulnerability at the endpoint userinfo.php/?uid= by crafting the uid in the url.

Copy link
Copy Markdown
Member

@MekDrop MekDrop left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the fix! Is very rare for us to get such big PR from first time contributors!

Still I have found few problems that I think should be solved before this can be merged.


CREATE TABLE users (
`uid` mediumint(8) unsigned NOT NULL auto_increment,
`hash_uid` varchar(64) NOT NULL default '',
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we use DB field, it should be unique; just add similar line like 'login_name'

*/
public function &getHash($hash_uid) {
$user = FALSE;
$sql = "SELECT * FROM " . $this->db->prefix('users') . " WHERE hash_uid = '" . $hash_uid . "'";
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hash_uid should be escaped in case of SQL Injection. $this->db->quote($hash_uid) or $this->db->quoteString($hash_uid) should be used here

*/
public function &getHash($hash_uid) {
$user = FALSE;
$sql = "SELECT * FROM " . $this->db->prefix('users') . " WHERE hash_uid = '" . $hash_uid . "'";
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Àdding LIMIT 1 to then end of this SQL can improve execution speed

Comment on lines +211 to +217
$hash_uid = bin2hex(random_bytes(32));
$user->assignVar('hash_uid', $hash_uid);
$sql = sprintf(
"UPDATE %s SET hash_uid = '%s' WHERE uid = '%u'",
$this->db->prefix('users'), $hash_uid, (int) $uid
);
$result = $this->db->query($sql);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure fully how to solve this but I see possible collision for users with same hash_uid problem.

Maybe here everything should be wrapped into transaction that first tries verify if user with such hash_uid exists and then if not try to update. If fails because of unique index violation, retry again.

Comment thread htdocs/userinfo.php
include 'mainfile.php';
$hash_uid = (int) $_GET['uid'];
$hash_uid = $_GET['uid'];

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The input should be filtered and tested before using. In the original code, we force it to be an integer before proceeding

Copy link
Copy Markdown
Contributor

@skenow skenow Dec 9, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a little better. I recommend reviewing the icms_core_DataFilter::checkVar() method. Strings can still be malicious and validating input and access are the best defense against breaches. You can view how we've utilized it in a lot of places - includes/finduser.php is a good example.

@emilylwan emilylwan requested review from MekDrop and skenow December 2, 2023 21:43
@skenow
Copy link
Copy Markdown
Contributor

skenow commented Dec 10, 2023

I should have said this earlier - thank you!

You have done what we encourage everyone to do -

  1. See something that could be improved
  2. Do something about it - not just for yourself, but for everyone

Another thing that makes this important is that you focused on improving security and protecting user data. That is something we are very committed to.

This is not a small thing, and we'd like more time to review on how best to assimilate this into our code base. We are in a release cycle and this is the branch we use for packaging and releasing.

ImpressCMS is a very user-driven platform and just about everything is linked to a user through their ID. To maintain data integrity, we have to exercise due diligence when changing a key field (a primary, in most cases). Some of the questions we have are about handling changes to existing installations, especially the database changes necessary. Once the release of 2.0 is out, we'll have more time to focus on this.

Again - thank you!

@fiammybe fiammybe marked this pull request as draft July 17, 2024 09:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants