| @@ -710,8 +710,17 @@ | ||
| 710 | 710 | |
| 711 | 711 | //Define $user |
| 712 | 712 | $user = $data[ $form ]; |
| 713 | 713 | |
| 714 | + // SECURITY: Strip admin-only profile fields from form input unless | |
| 715 | + // user has edit members permission. Prevents mass assignment attacks | |
| 716 | + // where users manipulate status, reputation, or email confirmation. | |
| 717 | + if( ! WPF()->usergroup->can( 'em' ) ) { | |
| 718 | + unset( $user['custom_points'] ); | |
| 719 | + unset( $user['status'] ); | |
| 720 | + unset( $user['is_email_confirmed'] ); | |
| 721 | + } | |
| 722 | + | |
| 714 | 723 | //Define $userid |
| 715 | 724 | $userid = intval( $data[ $form ]['userid'] ); |
| 716 | 725 | |
| 717 | 726 | //Check profile editor permissions |
| @@ -892,8 +901,10 @@ | ||
| 892 | 901 | $this->upload_avatar( $userid ); |
| 893 | 902 | } |
| 894 | 903 | |
| 895 | 904 | //Update Custom Fields |
| 905 | + // $custom_fields is still the raw $_POST['data']. The same values were merged into $user, where validate() has since dropped every field the current user may not edit and sanitize() has cleaned the rest, so read them back from $user: a key that is still there is one this user was allowed to submit, and its value is the sanitized one. | |
| 906 | + $custom_fields = array_intersect_key( $user, $custom_fields ); | |
| 896 | 907 | if( ! empty( $custom_fields ) && ( in_array( 'full', $type ) || in_array( 'custom_fields', $type ) ) ) { |
| 897 | 908 | $result_fields = $this->update_custom_fields( $userid, $custom_fields, false ); |
| 898 | 909 | } |
| 899 | 910 | |
| @@ -1657,16 +1668,17 @@ | ||
| 1657 | 1668 | } else { |
| 1658 | 1669 | $wheres[] = "`" . esc_sql( $field ) . "` LIKE '%" . esc_sql( $needle ) . "%'"; |
| 1659 | 1670 | } |
| 1660 | 1671 | } else { |
| 1661 | - $needle = preg_quote( preg_quote( $needle ) ); | |
| 1672 | + // Local var: $needle must stay raw for the remaining fields of this loop | |
| 1673 | + $n = wpforo_json_regexp_needle( $needle ); | |
| 1662 | 1674 | if( in_array( $f['type'], [ 'text', 'search', 'textarea' ], true ) ) { |
| 1663 | 1675 | $wheres[] = "`fields` REGEXP '[{,]\"" . $field . "\":(\\\[[^\\\[]*)?\"[^\"]*" . esc_sql( |
| 1664 | - $needle | |
| 1676 | + $n | |
| 1665 | 1677 | ) . "[^\"]*\"'"; |
| 1666 | 1678 | } else { |
| 1667 | 1679 | $wheres[] = "`fields` REGEXP '[{,]\"" . $field . "\":(\\\[[^\\\[]*)?\"" . esc_sql( |
| 1668 | - $needle | |
| 1680 | + $n | |
| 1669 | 1681 | ) . "\"'"; |
| 1670 | 1682 | } |
| 1671 | 1683 | } |
| 1672 | 1684 | } |
| @@ -1709,31 +1721,27 @@ | ||
| 1709 | 1721 | } |
| 1710 | 1722 | } else { |
| 1711 | 1723 | if( in_array( $f['type'], [ 'text', 'search', 'textarea' ], true ) ) { |
| 1712 | 1724 | if( is_scalar( $needle ) ) { |
| 1713 | - $needle = preg_quote( preg_quote( wpforo_encode( $needle ) ) ); | |
| 1714 | 1725 | $wheres[] = "`fields` REGEXP '[{,]\"" . $field . "\":(\\\[[^\\\[]*)?\"[^\"]*" . esc_sql( |
| 1715 | - $needle | |
| 1726 | + wpforo_json_regexp_needle( wpforo_encode( $needle ) ) | |
| 1716 | 1727 | ) . "[^\"]*\"'"; |
| 1717 | 1728 | } elseif( is_array( $needle ) ) { |
| 1718 | 1729 | foreach( $needle as $n ) { |
| 1719 | - $n = preg_quote( preg_quote( wpforo_encode( $n ) ) ); | |
| 1720 | 1730 | $wheres[] = "`fields` REGEXP '[{,]\"" . $field . "\":(\\\[[^\\\[]*)?\"[^\"]*" . esc_sql( |
| 1721 | - $n | |
| 1731 | + wpforo_json_regexp_needle( wpforo_encode( $n ) ) | |
| 1722 | 1732 | ) . "[^\"]*\"'"; |
| 1723 | 1733 | } |
| 1724 | 1734 | } |
| 1725 | 1735 | } else { |
| 1726 | 1736 | if( is_scalar( $needle ) ) { |
| 1727 | - $needle = preg_quote( preg_quote( wpforo_encode( $needle ) ) ); | |
| 1728 | 1737 | $wheres[] = "`fields` REGEXP '[{,]\"" . $field . "\":(\\\[[^\\\[]*)?\"" . esc_sql( |
| 1729 | - $needle | |
| 1738 | + wpforo_json_regexp_needle( wpforo_encode( $needle ) ) | |
| 1730 | 1739 | ) . "\"'"; |
| 1731 | 1740 | } elseif( is_array( $needle ) ) { |
| 1732 | 1741 | foreach( $needle as $n ) { |
| 1733 | - $n = preg_quote( preg_quote( wpforo_encode( $n ) ) ); | |
| 1734 | 1742 | $wheres[] = "`fields` REGEXP '[{,]\"" . $field . "\":(\\\[[^\\\[]*)?\"" . esc_sql( |
| 1735 | - $n | |
| 1743 | + wpforo_json_regexp_needle( wpforo_encode( $n ) ) | |
| 1736 | 1744 | ) . "\"'"; |
| 1737 | 1745 | } |
| 1738 | 1746 | } |
| 1739 | 1747 | } |