Browsing the archives for the software development tag.

Vulnerable Code: MoinMoin User

Programming

I’ve just started posting code samples from the wonderful SpotTheVuln.com on the walls in our building on 11×17 cardstock behind thin plexiglass panes so they can be annotated with dry erase marker when people solve them or have comments:

I love the site but wanted to branch out a little bit into some samples outside of the PHP and Wordpress world. In my first attempt, I didn’t branch very far, and it’s a bit longer than I would have preferred, but here it is — from MoinMoin. Hopefully I included enough information to find the issue.

def getUserId(request, searchName):
    """
    Get the user ID for a specific user NAME.
 
    @param searchName: the user name to look up
    @rtype: string
    @return: the corresponding user ID or None
    """
    if not searchName:
        return None
    cfg = request.cfg
    try:
        _name2id = cfg._name2id
    except AttributeError:
        arena = 'user'
        key = 'name2id'
        cache = caching.CacheEntry(request, arena, key)
        try:
            _name2id = pickle.loads(cache.content())
        except (pickle.UnpicklingError, IOError, EOFError, ValueError):
            _name2id = {}
        cfg._name2id = _name2id
    id = _name2id.get(searchName, None)
    if id is None:
        for userid in getUserList(request):
            name = User(request, id=userid).name
            _name2id[name] = userid
        cfg._name2id = _name2id
        arena = 'user'
        key = 'name2id'
        cache = caching.CacheEntry(request, arena, key)
        cache.update(pickle.dumps(_name2id, PICKLE_PROTOCOL))
        id = _name2id.get(searchName, None)
    return id
 
class User:
    """A MoinMoin User"""
 
    def __init__(self, request, id=None, name="", password=None,
                 auth_username="", **kw):
        """ Initialize User object
 
        @param request: the request object
        @param id: (optional) user ID
        @param name: (optional) user name
        @param password: (optional) user password (unicode)
        @param auth_username: (optional) already authenticated user name
                              (e.g. when using http basic auth) (unicode)"""
        self._cfg = request.cfg
        self.valid = 0
        self.trusted = 0
        self.id = id
        self.auth_username = auth_username
        self.auth_method = kw.get('auth_method', 'internal')
        self.auth_attribs = kw.get('auth_attribs', ())
 
        # we got an already authenticated username:
        check_pass = 0
        if not self.id and self.auth_username:
            self.id = getUserId(request, self.auth_username)
            if not password is None:
                check_pass = 1
        if self.id:
            self.load_from_id(check_pass)
            if self.name == self.auth_username:
                self.trusted = 1
        elif self.name:
            self.id = getUserId(self._request, self.name)
            if self.id:
                self.load_from_id(1)
            else:
                self.id = self.make_id()
        else:
            self.id = self.make_id()
 
    def __filename(self):
        """ Get filename of the user's file on disk
        @rtype: string
        @return: full path and filename of user account file
        """
        return os.path.join(self._cfg.user_dir, self.id or "...NONE...")
 
    def save(self):
        """ Save user account data to user account file on disk.
 
        This saves all member variables, except "id" and "valid" and
        those starting with an underscore.
        """
        if not self.id:
            return
 
        user_dir = self._cfg.user_dir
        filesys.makeDirs(user_dir)
 
        self.last_saved = str(time.time())
 
        data = codecs.open(self.__filename(), "w", config.charset)
        data.write("# Data saved '%s' for id '%s'\n" % (
            time.strftime(self._cfg.datetime_fmt, time.localtime(time.time())),
            self.id))
        attrs = vars(self).items()
        attrs.sort()
        for key, value in attrs:
            if key not in self._cfg.user_transient_fields and key[0] != '_':
                # Encode list values
                if key in ['quicklinks', 'subscribed_pages']:
                    value = encodeList(value)
                line = u"%s=%s\n" % (key, unicode(value))
                data.write(line)
        data.close()
 
        if not self.disabled:
            self.valid = 1
No Comments