论Web狗如何在CTF中苟到最后

访客 330 0
本文来源:蚁景科技

一、 前记

最近打了一些比赛,收获了不少知识,简单在这里罗列一下要分享的东西:

1. 一道SSRF结合spl_autoload_register()特性,反序列化命令执行的题目。

2. 一道最新的wordpress格式化字符串漏洞导致的二次注入的题目。

3. 一道有关Mysql指令妙用的题目。

4. 关于数组弱比较导致绕过危险过滤,成功写入shell的一则记录。

5. parse_url()有关特性的小trick。

二、 题目一:重定向与反序列化

题目来自2017湖湘杯复赛web400,感觉质量比较高:

(注:研究出来的时候题目已经关了,自己本地尝试的,所有没有css和js很丑,这个其实不重要)

最开始拿到题目:http://118.190.113.111:10080/index.php?act=user的时候挺没有头绪的

一开始以为是ssrf摸内网,又发现好像有上传,各种尝试302打进去探测端口,发现都挺奇怪的,一直没get到考点

后来发现有一个redirect.php,会重定向

于是在photo url处尝试了一下

http://118.190.113.111:10080/redirect.php?redirect=file:///etc/passwd

但是这里会被waf拦下,只允许通过.jpg和.png的结尾,于是尝试00截断

如下:

论Web狗如何在CTF中苟到最后-第1张图片-网盾网络安全培训

发现可以成功读取到内容

于是拿下源码进行分析(以下为本地测试,vps就打码了,毕竟是队友的)

在login.php里

论Web狗如何在CTF中苟到最后-第2张图片-网盾网络安全培训

如果是本地访问的话,token才会为1

在common.php中

论Web狗如何在CTF中苟到最后-第3张图片-网盾网络安全培训

可以发现debug的值为1会返回http头数据

于是猜想利用redirect.php请问,伪造本地登录

'body','content_type'=>'application/x-www-form-urlencoded','payload'=>urlencode($payload)); $post_data = json_encode($postd); $ch = curl_init($url); curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST"); curl_setopt($ch, CURLOPT_POSTFIELDS,$post_data); curl_setopt($ch, CURLOPT_RETURNTRANSFER,true); curl_setopt($ch, CURLOPT_HTTPHEADER, array( 'Content-Type: application/json', 'Content-Length: ' . strlen($post_data)) ); $result = curl_exec($ch); $arr = json_decode($result,true); if(!array_key_exists('attack',$arr)||$arr['attack']>0) die('error!'); if(preg_match('/from|@|information_schema|\./is',$payload)) die('hacker?'); $sql = "mysql -u****** -p****** -e ".escapeshellarg($sqlque.$payload); exec($sql,$aa); var_dump($aa); ?>

(2)源码分析

题目大体原理如下:

1.我们传入点在$a变量

2.传入值后,会被过滤;

3.然后被json编码传入https://sqlchop.chaitin.cn/demo/detect/进行检测

4.将检测结果传回来,再进行json解码

5.如果解码后发现attack不存在(因为不可能不存在,无危险是0,不存在是伪造了),或者检测到attack>0,就直接die

6.如果没有检测到attack,则进一步过滤from,@,information_achema,.这些字符

7.如果检测到上述危险字符则die

8.如果没有检测到,则将payload与select 1 from dual where 1=进行拼接,然后执行命令

9.然后打印出命令执行的结果

(3)攻击方式

(3.1)前引知识

这里用到的知识点是Mysql的相关命令

如下

论Web狗如何在CTF中苟到最后-第4张图片-网盾网络安全培训


这里我们这次比赛用到的几个点:

clear (\c) Clear the current input statement.

delimiter (\d) Set statement delimiter.

use (\u) Use another database. Takes database name as argument.

nopager (\n) Disable pager, print to stdout.

system (\!) Execute a system shell command.


这里简单说一下:

\c:清除之前的sql语句 (用来清除之前没用的sql语句影响)

\d:指定sql分割符号(用来绕过;过滤)

\n:关闭页面设置,可以在任何位置,例如sel\nect(用来绕过关键词过滤)

\u:可以指定一个数据库 (用来查表)

\!:可以执行linux bash命令 (用来执行命令)

(3.2) 用法之一:执行命令

所以这里的第一步攻击就很明显了:

a = \! ls -l

即拼接后得到:

mysql -u****** -p****** -e "\! ls -l"

我们在linux下试试:

论Web狗如何在CTF中苟到最后-第5张图片-网盾网络安全培训


没错,可以成功执行命令,于是乎利用这一点可以成功的进行反弹shell

但是反弹shell里被过滤了.,应该怎么处理呢?

这里我们选择用base64编码的方式绕过:

论Web狗如何在CTF中苟到最后-第6张图片-网盾网络安全培训

如果我们将这里的ls -al换成其他反弹shell的命令,就可以成功绕过.的过滤,反弹shell

(3.3)用法之二:查询数据库

首先利用\c清除之前的sql语句,去除之前没用的干扰

于是构造:

\c show databases

可以得到回显:

论Web狗如何在CTF中苟到最后-第7张图片-网盾网络安全培训

故可以得到数据库的所有库名

然后继续查询:

利用指令:

\c show tables \u web1

从而指定库名为web1(因为是自己复现,所以随便挑了个库)

论Web狗如何在CTF中苟到最后-第8张图片-网盾网络安全培训

最后查询表内信息:

论Web狗如何在CTF中苟到最后-第9张图片-网盾网络安全培训

即可获取表内信息

注意:题目里的from被过滤了,我们可以用fr\nom来绕过

(\n可以用来绕过一些过滤)

五、 题目四:数组弱比较

这个知识点的学习来自于ph牛的博客

有这样一道源码审计:

?php
function is_valid($title, $data)
{
  $data = $title . $data;
  return preg_match('|\A[ _a-zA-Z0-9]+\z|is', $data);
}

function write_cache($title, $content)
{
  if (!is_valid($title, $content)) {
      exit("title or content error");
  }

  $filename = "1.php";
  file_put_contents($filename, $content);
}
$title = $_GET['title'];
$content = $_GET['content'];
write_cache($title,$content);

乍一看,过滤的比较严格,想要写入shell像这样这样的符号肯定是通不过的,那么如何破解呢?

主要问题还是在于

function is_valid($title, $data)
{
  $data = $title . $data;
  return preg_match('|\A[ _a-zA-Z0-9]+\z|is', $data);
}

验证函数的弱类型问题

这里为了显示清楚,我加了两个var_dump()

论Web狗如何在CTF中苟到最后-第10张图片-网盾网络安全培训

如果正常传入参数,显然是没有问题的

scheme) efree(ret->scheme); if (ret->user) efree(ret->user); if (ret->pass) efree(ret->pass); efree(ret); return NULL; }

可以看到,在函数 parse_url 内部,如果 url 是以 // 开始,就认为它是相对 url,而后认为 url 的部件从 url+2 开始。line 281,若 p-s 1 也就是如果 url 为 ///x.php,则 p = e = s = s + 2,函数将返回 NULL。

再看 PHP_FUNCTION,line 351:

/* {{{ proto mixed parse_url(string url, [int url_component])
 Parse a URL and return its components */
PHP_FUNCTION(parse_url)
{
  char *str;
  size_t str_len;
  php_url *resource;
  zend_long key = -1;

  if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|l", 
  }

  resource = php_url_parse_ex(str, str_len);
  if (resource == NULL) {
      /* @todo Find a method to determine why php_url_parse_ex() failed */
      RETURN_FALSE;
}

若 php_url_parse_ex 结果为 NULL,函数 parse_url 将返回 FALSE

技巧点二

题目来自2016asisctf

源码如下:

?php
$data = parse_url($_SERVER['REQUEST_URI']);
var_dump($data);
$filter=["cache", "binarycloud"];
foreach($filter as $f)
{
if(preg_match("/".$f."/i", $data['query']))
{
die("Attack Detected");
}
}
?>

这里如果我们输入

http://localhost/web/trick1/parse2.php?/home/binarycloud/

论Web狗如何在CTF中苟到最后-第11张图片-网盾网络安全培训

就会被waf拦截

但是如果输入

http://localhost/web/trick1//parse2.php?/home/binarycloud/

则会被当做相对url,

此时的parse2.php?/home/binarycloud/都会被当做是data[‘path’]

而不再是query

但是需要注意的是:

论Web狗如何在CTF中苟到最后-第12张图片-网盾网络安全培训

刚漏洞问题只存在于php5.4.7以前

六、 后记

Web的知识博大精深,希望能做到更多有关真实漏洞的题目,在实战中不断成长!如果文章中出现错误,也请各位大佬斧正!

标签: web安全 CTF

发表评论 (已有0条评论)

还木有评论哦,快来抢沙发吧~