2021天津攻防决赛的一道mysql

题目

<?php
//mysql_query('set names utf8')
function check_username($str){
    if(preg_match("/^admin$/i",$str)){
        return 1;
    }

    for($i=195;$i<240;$i++){
        if(preg_match("/".chr($i)."/i",$str)){ 
            return 1;
        }
    }
    return 0;
}
function check_password($str){
    if(preg_match("/admins/i",$str)){ 
        return 1;
    }
    return 0;
}

$link=connect();
$u=$_GET['username'];
$p=$_GET['password'];
if(check_username($u)==1||check_password($p)==1){
    die("admin can not Login");
}

$query="select * from user where username=' $u'and password='$p'";
$res = mysqLi_query($link,$query);
echo $res;

题目大致代码如上,要求当我们使用admin用户成功登录之后就会得到flag

分析

从代码上可以看见用户名为admin,密码为admins

首先对于用户名admin,check_username()要求我们不能以admin开头并且以admin结尾,即只输入admin不行的。我们需要在admin前后加一个或多个字符让其绕过preg_match(),但是加的字符转换成数字不能在【195-239】之间。

其次对于密码admins,check_password()要求我们输入的密码中不能包含admins字符串。所以我们需要找一个字符串他不会被preg_match()匹配到admins,但是要能在mysql里面被当作admins处理。

知识点

Mysql字符编码利用技巧 | 离别歌

从一道题深入mysql字符集与比对方法collation · sky's blog

当Mysql字段的字符集和php mysqli客户端设置的字符集不相同时会有转换漏洞:

在默认情况下,mysql字符集为latin1,而如果在客户端使用set names utf8 将客户端的字符集设置为utf8。如果在客户端输入不完整的汉字的utf-8编码,latin1又不支持汉字就会将其忽略,从而达到绕过。

\xC2~\xEF 会被忽略从而返回admin的结果

我们可以在admin前后加上%c2~%ef之间的一个字符就能绕过,for循环的意思是避免我们用latin1字符绕过。

对于密码只做了preg_match()处理,所以可以用latin1字符绕过。latin1全部字符

为什么能绕过呢?mysql字符集默认为latin1,而latin1里的å并不等于阿拉伯数字a

最终传入?username=admin%c2&password=ådmins即可得到flag。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值