CTF中Web题目的常见题型及解题姿势

想写这个想了很久了,但一直觉得自己的知识不足,于是一直没有写。

后来觉得至少还是要边学边写才好,于是就有了这篇总结。

长期更新中,欢迎各位大佬挑错或者提出意见、建议。

由于本人淡出CTF圈,本文已停更,感谢大家的支持。

基础知识类题目

考察基本的查看网页源代码、HTTP请求、修改页面元素等。

这些题很简单,比较难的比赛应该不会单独出,就算有应该也是Web的签到题。

实际做题的时候基本都是和其他更复杂的知识结合起来出现。

姿势:恶补基础知识就行

查看网页源代码

按F12就都看到了,flag一般都在注释里,有时候注释里也会有一条hint或者是对解题有用的信息。

发送HTTP请求

可以用hackbar,有的也可以写脚本。

举个写脚本的例子(题目是Bugku web基础$_POST):

import requests
r = requests.post('http://123.206.87.240:8002/post/', data={'what' : 'flag'})
print(r.text)

不常见类型的请求发送

以前做过一道题考OPTIONS请求,可惜题目找不到了,而且那题也不算很基础。

不过如果要发送这类请求,写一个脚本应该就能解决了。

HTTP头相关的题目

主要是查看和修改HTTP头。

目前做过的Web题目有很大一部分都是与HTTP头相关的,而且这种题目也相当常见,不和其他知识结合的情况下也算是属于基础题的范畴吧。

姿势:不同的类型有不同的利用方法,基本都离不开抓包改包,有些简单的也可以利用浏览器F12的网络标签解决。但是最根本的应对策略,是熟悉一些常见请求头的格式、作用等,这样题目考到的时候就很容易知道要怎样做了。

查看响应头

有时候响应头里会有hint或者题目的关键信息,也有的时候会直接把flag放在响应头里给你,但是直接查看响应头拿flag的题目并不多,因为太简单了。

只是查看的话,可以不用抓包,用F12的“网络”标签就可以解决了。

修改请求头、伪造Cookie

常见的有set-cookie、XFF和Referer,总之考法很灵活,做法比较固定,知道一些常见的请求头再根据题目随机应变就没问题了。

有些题目还需要伪造Cookie,根据题目要求做就行了。

可以用BurpSuite抓包,也可以直接在浏览器的F12“网络”标签里改。

Git源码泄露

flag一般在源码的某个文件里,但也有和其他知识结合、需要进一步利用的情况,比如XCTF社区的mfw这道题。

姿势:GitHack一把梭

Python爬虫信息处理

这类题目一般都是给一个页面,页面中有算式或者是一些数字,要求在很短的时间内求出结果并提交,如果结果正确就可以返回flag。

因为所给时间一般都很短而且计算比较复杂,所以只能写脚本。这种题目的脚本一般都需要用到requests库和BeautifulSoup库(或者re库(正则表达式)),个人感觉使用BeautifulSoup简单一些。

姿势:requests库和BeautifulSoup库熟练掌握后,再多做几道题或者写几个爬虫的项目,一般这类题目就没有什么问题了。主要还是对BeautifulSoup的熟练掌握,另外还需要一点点web前端(HTML)的知识。

#这道题的脚本如下,还可以继续优化
#经常出现执行了但是不弹flag的情况,多试几次就行了
from bs4 import BeautifulSoup
import requests

r = requests.Session()
s = r.get("http://123.206.87.240:8002/qiumingshan/")
s.encoding = 'utf-8'
text = s.text
soup = BeautifulSoup(text)
tag = soup.div
express = str(tag.string)
express = express[0 : -3]
answer = eval(express)
ans = {"value" : answer}
flag = r.post('http://123.206.87.240:8002/qiumingshan/', data = ans)
print(flag.text)

HGAME2019的部分题目似乎还出现了反爬虫措施,但当时我还不会写爬虫,那一道题目也没有做,所以也不大清楚,以后如果再遇到那类题目再慢慢补上吧。

PHP代码审计

代码审计覆盖面特别广,分类也很多,而且几乎什么样的比赛都会有,算是比较重要的题目类型之一吧。

姿势:具体问题具体分析,归根结底还是要熟练掌握PHP这门语言,了解一些常见的会造成漏洞的函数及利用方法等。

hash加密相关

PHP弱类型hash比较缺陷

这是代码审计最基础的题目了,也比较常见。

典型代码:

if(md5($a) == md5($b)) {    //注意两个等号“==”
    echo $flag;
}

加密函数也有可能是sha1或者其他的,但是原理都是不变的。

这个漏洞的原理如下:

== 在进行比较的时候,会先将两边的变量类型转化成相同的,再进行比较。
0e在比较的时候会将其视作为科学计数法,所以无论0e后面是什么,0的多少次方还是0。

所以只要让a和b在经过相应的函数加密之后都是以0e开头就可以。

以下是一些md5加密后开头为0e的字符串:

QNKCDZO
0e830400451993494058024219903391

s878926199a
0e545993274517709034328855841020
  
s155964671a
0e342768416822451524974117254469
  
s214587387a
0e848240448830537924465865611904
  
s214587387a
0e848240448830537924465865611904
  
s878926199a
0e545993274517709034328855841020
  
s1091221200a
0e940624217856561557816327384675
  
s1885207154a
0e509367213418206700842008763514

aabg7XSs

另外,这个也可以用数组绕过,这个方法在下面会详细说。

数组返回NULL绕过

PHP绝大多数函数无法处理数组,向md5函数传入数组类型的参数会使md5()函数返回NULL(转换后为False),进而绕过某些限制。

如果上面的代码变成:

if(md5($a) === md5($b)) {       //两个等号变成三个
    echo $flag;
}

那么利用弱类型hash比较缺陷将无法绕过,这时可以使用数组绕过。

传入?a[]=1&b[]=2就可以成功绕过判断。

这样的方法也可以用来绕过sha1()等hash加密函数相关的判断,也可以绕过正则判断,可以根据具体情况来灵活运用。

正则表达式相关

ereg正则%00截断

ereg函数存在NULL截断漏洞,使用NULL可以截断过滤,所以可以使用%00截断正则匹配。

数组绕过

正则表达式相关的函数也可以使用数组绕过过滤,绕过方法详见数组返回NULL绕过。

上面那道题也可以用数组绕过。

单引号绕过preg_match()正则匹配

在每一个字符前加上单引号可以绕过preg_match的匹配,原理暂时不明。

例如有如下代码:

<?php
    $p = $_GET['p'];
    if (preg_match('/[0-9a-zA-Z]{2}/',$p) === 1) {
        echo 'False';
    } else {
        $pp = trim(base64_decode($p));
        if ($pp === 'flag.php') {
            echo 'success';
        }
    }
?>

payload:p='Z'm'x'h'Z'y'5'w'a'H'A'=

不含数字与字母的WebShell

如果题目使用preg_match()过滤掉了所有的数字和字母,但是没有过滤PHP的变量符号$,可以考虑使用这种方法。

典型代码:

<?php 

include'flag.php'; 

if(isset($_GET['code'])){ 
   $code=$_GET['code']; 
   if(strlen($code)>50){ 
       die("Too Long."); 
  } 
   if(preg_match("/[A-Za-z0-9_]+/",$code)){ 
       die("Not Allowed."); 
  } 
   @eval($code); 
}else{ 
   highlight_file(__FILE__); 
} 
//$hint = "php function getFlag() to get flag"; 
?>

这种方法的核心是字符串的异或操作

爆破脚本:

chr1 = ['@', '!', '"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/', ':', ';', '<', '=', '>', '?', '[', '\\', ']', '^', '_', '`', '{', '|', '}', '~']
chr2 = ['@', '!', '"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/', ':', ';', '<', '=', '>', '?', '[', '\\', ']', '^', '_', '`', '{', '|', '}', '~']

for i in chr1 :
    for j in chr2 :
        print(i + 'xor' + j + '=' + (chr(ord(i) ^ ord(j))))

根据题目的要求,用异或出来的字符串拼出合适的Payload,并放在PHP变量中执行。变量名可以用中文。

比如这道题的Payload:?code=$啊="@@^|@@@"^"'%*:,!'";$啊();

Linux通配符绕过正则匹配

典型代码如下,与前一种题目非常相似,但也不大一样:

<?php 

if(isset($_GET['code'])){ 
   $code=$_GET['code']; 
   if(strlen($code)>50){ 
       die("Too Long."); 
  } 
   if(preg_match("/[A-Za-z0-9_$]+/",$code)){ 
       die("Not Allowed."); 
  } 
   @eval($code); 
}else{ 
   highlight_file(__FILE__); 
} 
//flag in / 
?> 

最主要的区别就是过滤了$_,也就是说无法使用变量符号$了。

这时候可以考虑采用通配符绕过。

通配符有点像正则表达式,有自己的匹配规则,看这张图:

所以构造一下通配符就是/???/??? /*

因为过滤了变量符号,没法通过上面那种方法来执行了。但是,可以通过闭合PHP标记来执行,也就是:?><?=/???/??? /*?>(/bin/cat /*)。

所以本题的payload为:?code=?><?=/???/??? /*?>

具体解法可以参照此篇文章的前两道题目://www.greatytc.com/p/ecc2414ec110

命令执行漏洞

assert()函数引起的命令执行

assert函数的参数为字符串时,会将字符串当做PHP命令来执行。

例如:assert('phpinfo()')相当于执行<?php phpinfo() ?>

以一道题目为例:

本题目中题目文件夹下放置了一个隐藏的flag文件。

<?php
error_reporting(0);
if (isset($_GET['file'])) {
    if($_GET['file'] === "flag"){
        highlight_file("flag.php");
    }else{
        $page = $_GET['file'];
    }
} else {
    $page = "./flag.php";
}

assert("file_exists('$page')");
?>

解法:

构造闭合 file_exists()函数,并使assert()执行恶意代码。

Linux命令ls -a可用于查看该目录下所有文件,包括隐藏文件。

payload:

  1. ?file=123') or system('ls -a');#
  2. ?file=123') or system('cat .ffll44gg');#

XSS题目

这类题目会涉及到三种XSS类型,具体类型要根据题目来判断。一般都是向后台发送一个带有XSS Payload的文本,在返回的Cookie中含有flag,解法是在XSS Payload。

这类题目一般都会带有过滤和各种限制,需要了解一些常用的绕过方法。

姿势:XSS归根结底还是JavaScript,JavaScript的威力有多大,XSS的威力就有多大。要知道一些常用的XSS Payload,还要把三类XSS的原理弄明白。做题时需要用到XSS平台,网上有公用的,也可以自己在VPS上搭一个。

绕过waf

其实绝大多数比较难的题目多多少都会对输入有过滤,毕竟在现实的网络中肯定是会对输入进行限制的,但是这里还是把过滤单独列出来了。

姿势:多掌握一些不同的绕过方法。

长度限制

有些题目会要求输入较长的文本,但对文本的长度进行了限制。

对于这种题目,既可以用BurpSuite抓包改包绕过,也可以直接在F12里改页面源代码。

双写

双写可以绕过对输入内容过滤的单次判断,在XSS、SQL注入和PHP代码审计的题目中比较常见。

双写顾名思义就是将被过滤的关键字符写两遍,比如,如果要添加XSS Payload,又需要插入<script>标签,就可以构造如下的Payload:<scr<script>ipt>来绕过对<script>标签的单次过滤限制。

这样的方法不仅对XSS有用,也可以用于代码审计和SQL注入。

HGAME2019有一道XSS题目就是过滤了<script>,可以用双写绕过。

等价替代

就是不用被过滤的字符,而使用没有被过滤却会产生相同效果的字符。

比如,如果SQL注入题目中过滤了空格,可以用/**/绕过对空格的限制;XSS题目如果过滤了<script>标签,可以使用其他类型的payload;如果需要使用cat命令却被过滤,可以使用tac、more、less命令来替代等。

URL编码绕过

如果过滤了某个必须要用的字符串,输入的内容是以GET方式获取的(也就是直接在地址栏中输入),可以采用url编码绕过的方式。比如,过滤了 cat,可以使用 c%61t来绕过。

Linux命令使用反斜杠绕过

在Linux下,命令中加入反斜杠与原命令完全等价。例如,catca\t两条命令等价,效果完全相同。

可以利用这个特性来进行一些绕过操作(当然,这个仅限于命令执行漏洞)。

URL二次解码绕过

这个类型本来应该放在代码审计里面,但是既然是一种绕过过滤的姿势,就写在这里了。

如果源码中出现了urldecode()函数,可以利用url二次解码来绕过。

以下是一些常用的HTML URL编码:

ASCII Value URL-encode ASCII Value URL-encode ASCII Value URL-encode
æ %00 0 %30 ` %60
%01 1 %31 a %61
%02 2 %32 b %62
%03 3 %33 c %63
%04 4 %34 d %64
%05 5 %35 e %65
%06 6 %36 f %66
%07 7 %37 g %67
backspace %08 8 %38 h %68
tab %09 9 %39 i %69
linefeed %0a : %3a j %6a
%0b ; %3b k %6b
%0c < %3c l %6c
c return %0d = %3d m %6d
%0e > %3e n %6e
%0f ? %3f o %6f
%10 @ %40 p %70
%11 A %41 q %71
%12 B %42 r %72
%13 C %43 s %73
%14 D %44 t %74
%15 E %45 u %75
%16 F %46 v %76
%17 G %47 w %77
%18 H %48 x %78
%19 I %49 y %79
%1a J %4a z %7a
%1b K %4b { %7b
%1c L %4c | %7c
%1d M %4d } %7d
%1e N %4e ~ %7e
%1f O %4f %7f
space %20 P %50 %80
! %21 Q %51 %81
" %22 R %52 %82
# %23 S %53 ƒ %83
$ %24 T %54 %84
% %25 U %55 %85
& %26 V %56 %86
' %27 W %57 %87
( %28 X %58 ˆ %88
) %29 Y %59 %89
* %2a Z %5a Š %8a
+ %2b [ %5b %8b
, %2c \ %5c Œ %8c
- %2d ] %5d %8d
. %2e ^ %5e Ž %8e
/ %2f _ %5f %8f

数组绕过

详见PHP代码审计的“数组返回NULL”绕过。

数组绕过的应用很广,很多题目都可以用数组绕过。

SQL注入

SQL注入是一种灵活而复杂的攻击方式,归根结底还是考察对SQL语言的了解和根据输入不同数据网页的反应对后台语句的判断,当然也有sqlmap这样的自动化工具可以使用。

姿势:如果不用sqlmap或者是用不了,就一定要把SQL语言弄明白,sqlmap这样的自动化工具也可以使用。

使用sqlmap

sqlmap的应用范围还不大明确,我都是如果sqlmap没法注入就手工注入。

我写的一篇简单的sqlmap教程://www.greatytc.com/p/4509bdf5e3d0

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,723评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,485评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,998评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,323评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,355评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,079评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,389评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,019评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,519评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,971评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,100评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,738评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,293评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,289评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,517评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,547评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,834评论 2 345

推荐阅读更多精彩内容

  • 去训练一下基础! Bugku地址:https://ctf.bugku.com/challenges 0x01 we...
    DYBOY阅读 4,746评论 0 2
  • 前几个题目都分开写了,后面的会继续全部这个帖子之中!有问题的机油可以互相交流。 web2 草鸡简单的题目 文件上传...
    syxvip阅读 9,746评论 0 0
  • web2 听说聪明的人都能找到答案http://123.206.87.240:8002/web2/ 点开后发现很多...
    Emily0917阅读 998评论 0 1
  • 前两天无意间翻到一个CTF平台--BugKu,记下wp WEB 1.Web2 查看源代码即可得到flag 2.计算...
    BerL1n阅读 3,688评论 0 1
  • 1.web2 F12直接找到 2.计算器 准备输入答案时发现只能输入一位,检查源码 将maxlength的值修改一...
    保持O童心阅读 1,982评论 0 0