0x01 背景

现在的WEB程序基本都有对SQL注入的全局过滤,像PHP开启了GPC或者在全局文件common.php上使用addslashes()函数对接收的参数进行过滤,尤其是单引号。二次注入也是一种比较常见的注入,它涉及到入库和出库。因为有全局转义所以入库的时候:

Insert into table (username) values (‘hack\’’);

这样入库后转义符就会消失变成了hack’,这样如果hack’出库被带入查询的话就会成功的引入了单引号导致注入。
漏洞来源于乌云:http://www.wooyun.org/bugs/wooyun-2014-068362

0x02 环境搭建

看背景我们使用了低版本的74cms程序,版本为3.4(20140310)
①源码网上可以搜到,我打包了一份:http://pan.baidu.com/s/1c1mLCru
②解压到www的74cms(20140310)目录下,浏览器访问http://localhost/74cms(20140310)),然后按照提示一步步安装即可,安装遇到问题请自行百度或谷歌,成功后访问如下图:

0x03 漏洞分析

Part1:源码结构

源码的结构比较清晰,应该是审计过最清晰的结构了,主要有下面三块内容:

index.php引入了common.inc.php文件,我们跟进common.inc.php,发现了处理gpc的函数:

<?phpif (!empty($_GET)){ $_GET = addslashes_deep($_GET);}if (!empty($_POST)){ $_POST = addslashes_deep($_POST);}$_COOKIE = addslashes_deep($_COOKIE);$_REQUEST = addslashes_deep($_REQUEST);

可以看到,服务端处理GET和POST请求的变量时都会做addslashes处理。

Part2:审计过程

1.首先在个人发布简历处:

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); //看到这里有个插入表“qs_resume_education”的操作,将教育背景相关的字段入库 if (inserttable(table('resume_education'), $setsqlarr)) { check_resume($_SESSION['uid'], intval($_REQUEST['pid']));

2.这里看到insert入库了,可以尝试加个单引号,入库后就会消除转义字符。我们先继续跟进inserttables后的check_resume函数

//检查简历的完成程度function check_resume($uid, $pid){ global $db, $timestamp, $_CFG; $uid = intval($uid); $pid = intval($pid); $percent = 0; $resume_basic = get_resume_basic($uid, $pid); $resume_intention = $resume_basic['intention_jobs']; $resume_specialty = $resume_basic['specialty']; //获取教育经历,出数据库了 $resume_education = get_resume_education($uid, $pid); if (!empty($resume_basic)) $percent = $percent + 15; if (!empty($resume_intention)) $percent = $percent + 15; if (!empty($resume_specialty)) $percent = $percent + 15; if (!empty($resume_education)) $percent = $percent + 15; if ($resume_basic['photo_img'] && $resume_basic['photo_audit'] == "1" && $resume_basic['photo_display'] == "1") { $setsqlarr['photo'] = 1; } else { $setsqlarr['photo'] = 0; } if ($percent < 60) { $setsqlarr['complete_percent'] = $percent; $setsqlarr['complete'] = 2; } else { $resume_work = get_resume_work($uid, $pid); $resume_training = get_resume_training($uid, $pid); $resume_photo = $resume_basic['photo_img']; if (!empty($resume_work)) $percent = $percent + 13; if (!empty($resume_training)) $percent = $percent + 13; if (!empty($resume_photo)) $percent = $percent + 14; $setsqlarr['complete'] = 1; $setsqlarr['complete_percent'] = $percent; require_once(QISHI_ROOT_PATH . 'include/splitword.class.php'); $sp = new SPWord(); $setsqlarr['key'] = $resume_basic['intention_jobs'] . $resume_basic['recentjobs'] . $resume_basic['specialty']; $setsqlarr['key'] = "{$resume_basic['fullname']} " . $sp->extracttag($setsqlarr['key']); $setsqlarr['key'] = str_replace(",", " ", $resume_basic['intention_jobs']) . " {$setsqlarr['key']} {$resume_basic['education_cn']}"; $setsqlarr['key'] = $sp->pad($setsqlarr['key']); if (!empty($resume_education)) { //遍历教育经历所有字段,加入到数组里 foreach ($resume_education as $li) { $setsqlarr['key'] = "{$li['school']} {$setsqlarr['key']} {$li['speciality']}"; } } $setsqlarr['refreshtime'] = $timestamp; } //这里对教育经历做了次更新操作,二次注入由此产生! updatetable(table('resume'), $setsqlarr, "uid='{$uid}' AND id='{$pid}'"); updatetable(table('resume_tmp'), $setsqlarr, "uid='{$uid}' AND id='{$pid}'");

3.我们填写一份简历简单试验下,在教育经历处学校名称字段填写aa’

保存后发现报错语句:

0x04 漏洞证明

构造获取数据库用户相关信息的POC:

查看简历发现简历姓名变成了root@localhost:

查看sql语句发现更新语句是成功执行的:

最后,有兴趣的同学可以继续获取其它的管理员账户等相关字段的信息。

原文链接:http://www.cnbraid.com/2016/02/19/sql3/,如需转载请联系作者。

【PHP代码审计】 那些年我们一起挖掘SQL注入 - 4.全局防护Bypass之二次注入相关推荐

  1. 【PHP代码审计】 那些年我们一起挖掘SQL注入 - 6.全局防护盲点的总结上篇

    [PHP代码审计] 那些年我们一起挖掘SQL注入 - 6.全局防护盲点的总结上篇 0x01 背景 现在的WEB应用对SQL注入的防护基本都是判断GPC是否开启,然后使用addlashes函数对单引号等 ...

  2. SQL注入-二次注入和多语句注入

    二次注入 一.二次注入的定义 简单的说二次注入就是已经存储到数据库中的用户输入,在进行再一次读取的时候进去SQL查询语句中的注入. 二.二次注入的原理 第一步:插入恶意数据 第一次进行数据库插入数据的 ...

  3. 编解码注入、二次注入、DNSlog盲注

    1.编解码注入 靶场 sqlilabs-Less21 登录后,使用bp抓包 分析源码: 发现,如果正确登录,就会设置一个cookie,并且使用base64编码 分析cookie: 发现此处可以进行co ...

  4. (17)网络安全:cookie注入、二次注入、DNSlog注入、中转注入、堆叠注入的原理及注入过程

    目录 cookie注入 sqli-lasb-master less-21 方法一:用burpsuite进行抓包后修改 方法二:安装火狐的cookie manager等插件进行修改cookie 第一步: ...

  5. JAVA代码审计之WebGoat靶场SQL注入

    文章目录 前言 WebGoat IDEA部署靶场 No.1 回显注入 No.2 布尔盲注 No.3 Order by 代审技巧 SQL注入挖掘 SQL注入防御 Fortify体验 总结 前言 为了从自 ...

  6. jdbctemplate 执行多条sql_白帽推荐:可以自动检索、挖掘sql注入的神器,sqlmap入门实战

    学习web渗透的小白,必须有一份sqlmap的入门档案,收藏好,以备不时之需哈! Sqlmap介绍 sqlmap是一个自动化的SQL注入工具,其主要功能就是扫描.发现并利用给定的URL的SQL注入漏洞 ...

  7. SQL注入之二次注入(sql-lab第24关)

    什么是二次注入 二次注入可以理解为,攻击者构造的恶意数据存储在数据库后,恶意数据被读取并进入到SQL查询语句所导致的注入.防御者可能在用户 输入恶意数据时对其中的特殊字符进行了转义处理,但在恶意数据插 ...

  8. php sql 二次注入,espcms 二次注入一枚

    Author:Yaseng 1:通过 $alias 二次注入来控制sql 用户昵称 $alias 从数据库查询出来 未过滤 interface/member.php [php] $db_sql = & ...

  9. SQL注入-SQLMAP基础使用(十二)

    实验目的 了解SQLMAP的工作原理,熟悉SQLMAP的常用命令,掌握SQLMAP的-u参数的基本使用方法. 实验环境 攻击机:吹毁目标 (2)安装的应用软件:sqlmap .Burpsuite .F ...

  10. SQL注入——基于联合查询的字符型GET注入(三)

    本章目的 普及字符型GET注入的原理和特点,掌握利用联合查询(unionselect)的方法实现SQL注入的基本流程. 实验环境 攻击机:Pentest-Atk (1)操作系统:Windows10 ( ...

最新文章

  1. c#正则表达式使用详解
  2. 求行指针所指的字符串数组中长度最长的字符串所在的行下标
  3. 办公室琐事--沟通、交流
  4. R语言forestmodel包使用教程
  5. u-boot移植重要问题说明
  6. php 通过array_merge()和array+array合并数组的区别和效率比较
  7. Go语言并发爬虫,爬取空姐网所有相册图片
  8. 无任何网络提供程序接受指定的网络路径解决方法
  9. 虚拟 ​router 原理分析- 每天5分钟玩转 OpenStack(101)
  10. 提高数据库的查询速率及其sql语句的优化问题
  11. 谷歌浏览器无法登录账号
  12. 织梦cms里面文章里面的HTML,dede源码在其它页面调用单页文章内容并过滤HTML代码的方法...
  13. iOS之深入解析App Thinning的应用瘦身优化
  14. 国内外PaaS案例解析、赛道、趋势
  15. LaTeX使用excel2latex插入表格
  16. 下载后端传来的excel文件
  17. 用java实现对字符串文本的哈夫曼编码与解码
  18. k8s集群详细安装步骤
  19. Spring cloud使用ELK配置与使用详解之elasticsearch
  20. 如何在Word中设置其中一页为横向(Office 2013)

热门文章

  1. matlab矩阵的表示和简单操作
  2. macOS Big Sur无法完成安装 Big Sur为什么安装不了?
  3. vue2.0 实现导航守卫(路由守卫)
  4. NTFS for Mac 15如何检查与修复连接的移动磁盘
  5. EasyRecovery恢复数据的具体步骤是什么
  6. 【MongoDb入门】15分钟让你敢说自己会用MongoDB了
  7. Java 集合系列4、家喻户晓之HashMap(上)
  8. SFB 项目经验-44-别以为Hyper-V比VMware差太多(仅个人观点,不喜误喷,谢谢)
  9. 算法笔记 --- 布隆过滤器
  10. 【转】使用AIDL实现进程间的通信之复杂类型传递