├── .build ├── MSBuild.Community.Tasks.dll └── MSBuild.Community.Tasks.targets ├── .github ├── CONTRIBUTING.md ├── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── feature_request.md │ └── help-and-other-questions.md └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── App_LocalResources └── View.ascx.resx ├── Build.proj ├── BuildScripts ├── MSBuild.Community.Tasks.Targets └── ModulePackage.targets ├── Components ├── AuditChecks.cs ├── CheckResult.cs ├── Checks │ ├── CheckAllowableFileExtensions.cs │ ├── CheckBiography.cs │ ├── CheckDebug.cs │ ├── CheckDefaultPage.cs │ ├── CheckDiskAcccessPermissions.cs │ ├── CheckDnnVersion.cs │ ├── CheckHiddenSystemFiles.cs │ ├── CheckHttpModules.cs │ ├── CheckModuleHeaderAndFooter.cs │ ├── CheckPasswordFormat.cs │ ├── CheckRarelyUsedSuperuser.cs │ ├── CheckSiteRegistration.cs │ ├── CheckSqlRisk.cs │ ├── CheckSuperuserOldPassword.cs │ ├── CheckTelerikVulnerability.cs │ ├── CheckTracing.cs │ ├── CheckUnexpectedExtensions.cs │ └── CheckViewstatemac.cs ├── EscapedString.cs ├── FeatureController.cs ├── FileExtensionWhitelist.cs ├── IAuditCheck.cs ├── SeverityEnum.cs └── Utility.cs ├── DNN.Modules.SecurityAnalyzer.csproj ├── DNN.Modules.SecurityAnalyzer.sln ├── HttpModules └── SecurityAnalyzerModule.cs ├── Images ├── Extensions_16x16_Standard.png └── Extensions_32x32_Standard.png ├── LICENSE ├── License.txt ├── Properties └── AssemblyInfo.cs ├── Providers └── DataProviders │ └── SqlDataProvider │ ├── 01.00.00.SqlDataProvider │ ├── 08.00.02.SqlDataProvider │ └── Uninstall.SqlDataProvider ├── README.md ├── References └── DotNetNuke.dll ├── ReleaseNotes.txt ├── Resources ├── CheckFileExists.resources ├── ExecuteCommand.resources ├── GetFolderTree.resources ├── RegRead.resources ├── SysAdmin.resources └── sums.resources ├── Scripts ├── dnnscripts.js └── jquery-ui.min.js ├── SecurityAnalyzer.dnn ├── SecurityAnalyzerModuleBase.cs ├── Styles └── dnnstyles.css ├── View.ascx ├── View.ascx.cs ├── View.ascx.designer.cs ├── module.css ├── packages.config ├── web.Debug.config ├── web.Release.config └── web.config /.build/MSBuild.Community.Tasks.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DNNCommunity/DNN.SecurityAnalyzer/c4fd5bc4cccface170f959ad9d19fa885c5baba6/.build/MSBuild.Community.Tasks.dll -------------------------------------------------------------------------------- /.build/MSBuild.Community.Tasks.targets: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | $(MSBuildExtensionsPath)\MSBuildCommunityTasks 7 | $(MSBuildCommunityTasksPath)\MSBuild.Community.Tasks.dll 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | -------------------------------------------------------------------------------- /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # How to contribute 2 | 3 | Community contributions are essential part of any open source project. The 4 | community has access to a large number of unique configurations which would 5 | be extremely difficult for the core maintainers to reproduce. We want to keep 6 | it as easy as possible to contribute changes that get things working in your 7 | environment. There are a few guidelines that we need contributors to follow 8 | so that we can have a chance of keeping on top of things. 9 | 10 | ## Getting Started 11 | 12 | 13 | * Make sure you have a [GitHub account](https://github.com/signup/free) 14 | * **Submit an issue** for your issue, assuming one does not already exist. If you have the rights, you should assign yourself to the issue. If you do not have that ability please add a comment noting that a pull request will be submitted for the issue. After review, if the pull request is accepted, we will mark the issue as resolved and assign it to a release so it can be QA'ed. 15 | * Clearly describe the issue including steps to reproduce when it is a bug. 16 | * Make sure you fill in the earliest version that you know has the issue. 17 | * Fork the repository on GitHub 18 | 19 | ## Making Changes 20 | 21 | * Create a topic branch from where you want to base your work. 22 | * This is usually the 'development' branch. 23 | * Release branches should only be targeted by official committers. 24 | * To quickly create a topic branch based on development; `git checkout -b my_contribution development` 25 | * Make commits of logical units. 26 | * Check for unnecessary whitespace with `git diff --check` before committing. 27 | * Make sure your commit messages are in the proper format 28 | * For bonus points run and add unit tests 29 | * Make sure you have added the necessary tests for your changes. 30 | * Run _all_ the tests to assure nothing else was accidentally broken. 31 | 32 | 33 | ## Making Trivial Changes 34 | 35 | ### Documentation 36 | 37 | For changes of a trivial nature to comments and documentation, it is not 38 | always necessary to create a new ticket in the issue tracker. In this case, it is appropriate to start the first line of a commit with '(doc)' instead of 39 | a ticket number. 40 | 41 | ```` 42 | (doc) Add documentation commit example to CONTRIBUTING 43 | 44 | There is no example for contributing a documentation commit 45 | to the DNN repository. This is a problem because the contributor 46 | is left to assume how a commit of this nature may appear. 47 | 48 | The first line is a real life imperative statement with '(doc)' in 49 | place of what would have been the ticket number in a 50 | non-documentation related commit. The body describes the nature of 51 | the new documentation or comments added. 52 | ```` 53 | 54 | ## Submitting Changes 55 | 56 | * Sign the [Contributor License Agreement](http://www.dnnsoftware.com). 57 | * Push your changes to a topic branch in your fork of the repository. 58 | * Submit a pull request to the DNN.Platform repository in the DNNSoftware organization. 59 | * The committers will handle updating the associated issue in the DNN Tracker to ensure it gets the necessary code review and QA. 60 | 61 | ## Acceptance of your Changes 62 | * We have a group of fellow developers that review pull requests submitted by developers like yourself. 63 | * If your changes look good, then changes are merged to an appropriate release. 64 | * We may ask you to make further changes or reject the change (with proper reasonsing - we hope that's not the case though). 65 | * You should get an email notification as we complete processing of your pull request. 66 | 67 | ## Downloading latest package with your changes 68 | * As soon as changes are accepted, our team city build server gets into action. 69 | * New builds are usually available within 10 minutes of acceptance. 70 | 71 | # Additional Resources 72 | 73 | * [Contributor License Agreement](http://www.dnnsoftware.com) 74 | * [General GitHub documentation](http://help.github.com/) 75 | * [GitHub pull request documentation](http://help.github.com/send-pull-requests/) 76 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | 5 | --- 6 | 7 | ## Describe the bug 8 | A clear and concise description of what the bug is. 9 | 10 | 11 | ## Software Versions 12 | - DNN: 00.00.00 13 | - Module: 00.00.00 14 | 15 | 16 | ## To Reproduce 17 | Steps to reproduce the behavior: 18 | 1. Go to '...' 19 | 2. Click on '....' 20 | 3. Scroll down to '....' 21 | 4. See error 22 | 23 | 24 | ## Expected behavior 25 | A clear and concise description of what you expected to happen. 26 | 27 | 28 | ## Screenshots 29 | If applicable, add screenshots to help explain your problem. 30 | 31 | 32 | ## Error log 33 | **Note: Debug DLL's** 34 | Please replace the current extension DLL's with the debug DLL's (if these are available with the release) and reproduce the error with the debug DLL's before pasting the error log. 35 | 36 | Paste the error log that is related to this issue. 37 | 38 | 39 | ## Additional context 40 | Add any other context about the problem here. 41 | 42 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | 5 | --- 6 | 7 | ## Is your feature request related to a problem? 8 | **Please describe.** 9 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 10 | 11 | ## Describe the solution you'd like 12 | A clear and concise description of what you want to happen. 13 | 14 | ## Describe alternatives you've considered 15 | A clear and concise description of any alternative solutions or features you've considered. 16 | 17 | ## Additional context 18 | Add any other context or screenshots about the feature request here. 19 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/help-and-other-questions.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Help and other questions 3 | about: Ask for help or others questions re. using the module 4 | 5 | --- 6 | 7 | ## Please summarize your question in one sentence 8 | 9 | 10 | ## Give a more extended description 11 | 12 | 13 | ## Steps to reproduce (if needed) 14 | 15 | 16 | ## Other comments or remarks 17 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 5 | 6 | ### Description of PR... 7 | 8 | ## Changes made 9 | - Item 1 10 | - Item 2 11 | 12 | 13 | ## PR Template Checklist 14 | 15 | - [ ] Fixes Bug 16 | - [ ] Feature solution 17 | - [ ] Other 18 | 19 | 20 | ## Please mark which issue is solved 21 | 22 | 23 | Close # -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ################# 2 | ## Visual Studio 3 | ################# 4 | 5 | ## Ignore Visual Studio temporary files, build results, and 6 | ## files generated by popular Visual Studio add-ons. 7 | 8 | # User-specific files 9 | *.suo 10 | *.user 11 | *.sln.docstates 12 | *.local.sln 13 | *.local.sln.GhostDoc.xml 14 | 15 | ## Ignore VS2015/Roslyn artifacts 16 | *.sln.ide/ 17 | .vs/ 18 | 19 | # Build results 20 | [Rr]elease 21 | *_i.c 22 | *_p.c 23 | *.ilk 24 | *.meta 25 | *.obj 26 | *.pch 27 | *.pgc 28 | *.pgd 29 | *.rsp 30 | *.sbr 31 | *.tlb 32 | *.tli 33 | *.tlh 34 | *.tmp 35 | *.eml 36 | *.vspscc 37 | .builds 38 | *.dotCover 39 | *.ldf 40 | 41 | # git merge artifacts 42 | *.orig 43 | *.gitmodules 44 | 45 | ## TODO: If you have NuGet Package Restore enabled, uncomment this 46 | [Pp]ackages/ 47 | 48 | # Visual Studio profiler 49 | *.psess 50 | *.vsp 51 | 52 | # ReSharper is a .NET coding add-in 53 | _ReSharper* 54 | 55 | # Others 56 | 57 | [Oo]bj 58 | TestResults 59 | *.Cache 60 | ClientBin 61 | stylecop.* 62 | ~$* 63 | *.dbmdl 64 | Generated_Code #added for RIA/Silverlight projects 65 | 66 | # Backup & report files from converting an old project file to a newer 67 | # Visual Studio version. Backup files are not needed, because we have git ;-) 68 | _UpgradeReport_Files/ 69 | Backup*/ 70 | UpgradeLog*.XML 71 | 72 | ############ 73 | ## DNN 74 | ############ 75 | 76 | # Ignore artifacts from deployed/installed site 77 | 78 | DNN_*.zip 79 | 80 | !DNN [Pp]latform/[Cc]omponents 81 | !DNN [Pp]latform/[Cc]ontrols 82 | DNN [Pp]latform/[Cc]omponents/[Cc]lient[Dd]ependency/[Ss]ource/[Bb]in 83 | DNN [Pp]latform/[Cc]ontrols/[Cc]ountry[Ll]ist[Bb]ox/[Bb]in/* 84 | 85 | DNN [Pp]latform/*/[Bb]in 86 | DNN [Pp]latform/Tests/*/[Bb]in/* 87 | DNN [Pp]latform/Modules/*/[Bb]in/* 88 | DNN [Pp]latform/Admin Modules/*/[Bb]in/* 89 | DNN [Pp]latform/MVC Modules/*/[Bb]in/* 90 | DNN [Pp]latform/[Pp]roviders/*/*/[Bb]in/* 91 | DNN [Pp]latform/[Pp]roviders/*/*/*/[Bb]in/* 92 | DNN [Pp]latform/Syndication/[Bb]in/* 93 | 94 | 95 | [Ww]ebsite/*/[Dd]efault.aspx 96 | 97 | [Ww]ebsite/[Aa]dmin/[Pp]ersonabar 98 | 99 | [Ww]ebsite/[Aa]pp_[Cc]ode 100 | 101 | [Ww]ebsite/[Aa]pp_[Dd]ata 102 | 103 | [Ww]ebsite/[Bb]in 104 | 105 | [Ww]ebsite/[Cc]onfig 106 | 107 | [Ww]ebsite/[Dd]esktop[Mm]odules/[Aa]dmin/[Ff]ifty[Oo]ne[Cc]lient[Cc]apability[Pp]rovider 108 | [Ww]ebsite/[Dd]esktop[Mm]odules/[Aa]dmin/[Rr]ad[Ee]ditor[Pp]rovider 109 | [Ww]ebsite/[Dd]esktop[Mm]odules/[Aa]dmin/[Tt]axonomy 110 | [Ww]ebsite/[Dd]esktop[Mm]odules/[Aa]dmin/[Uu]rl[Mm]anagement 111 | [Ww]ebsite/[Dd]esktop[Mm]odules/[Aa]dmin/[Hh]tml[Ee]ditor[Mm]anager 112 | [Ww]ebsite/[Dd]esktop[Mm]odules/[Aa]dmin/[Rr]ecycle[Bb]in 113 | [Ww]ebsite/[Dd]esktop[Mm]odules/[Aa]dmin/[Nn]ewsletters 114 | 115 | [Ww]ebsite/[Dd]esktop[Mm]odules/[Aa]uthentication[Ss]ervices/[Ff]acebook 116 | [Ww]ebsite/[Dd]esktop[Mm]odules/[Aa]uthentication[Ss]ervices/[Gg]oogle 117 | [Ww]ebsite/[Dd]esktop[Mm]odules/[Aa]uthentication[Ss]ervices/[Ll]ive 118 | [Ww]ebsite/[Dd]esktop[Mm]odules/[Aa]uthentication[Ss]ervices/[Tt]witter 119 | [Ww]ebsite/[Dd]esktop[Mm]odules/[Aa]uthentication[Ss]ervices/DNN[Pp]ro_[Aa]ctive[Dd]irectory 120 | 121 | [Ww]ebsite/[Dd]esktop[Mm]odules/[Cc]ore[Mm]essaging 122 | [Ww]ebsite/[Dd]esktop[Mm]odules/DDRMenu 123 | [Ww]ebsite/[Dd]esktop[Mm]odules/[Dd]evice[Pp]review[Mm]anagement 124 | [Ww]ebsite/[Dd]esktop[Mm]odules/[Dd]igital[Aa]ssets 125 | [Ww]ebsite/[Dd]esktop[Mm]odules/DNNCorp 126 | [Ww]ebsite/[Dd]esktop[Mm]odules/[Dd][Nn][Nn] 127 | [Ww]ebsite/[Dd]esktop[Mm]odules/HTML 128 | [Ww]ebsite/[Dd]esktop[Mm]odules/MVC 129 | [Ww]ebsite/[Dd]esktop[Mm]odules/[Jj]ournal 130 | [Ww]ebsite/[Dd]esktop[Mm]odules/[Mm]ember[Dd]irectory 131 | [Ww]ebsite/[Dd]esktop[Mm]odules/[Mm]obile[Mm]anagement 132 | [Ww]ebsite/[Dd]esktop[Mm]odules/[Rr]azor[Mm]odules 133 | [Ww]ebsite/[Dd]esktop[Mm]odules/[Ss]ocial[Gg]roups 134 | [Ww]ebsite/[Dd]esktop[Mm]odules/[Ss]ubscriptions[Mm]gmt 135 | [Ww]ebsite/[Dd]esktop[Mm]odules/[Ii]dentity[Ss]witcher 136 | [Ww]ebsite/[Dd]esktop[Mm]odules/[Bb]log 137 | [Ww]ebsite/[Dd]esktop[Mm]odules/[Ii][Ff]rame 138 | [Ww]ebsite/[Dd]esktop[Mm]odules/[Aa]nnouncements 139 | [Ww]ebsite/[Dd]esktop[Mm]odules/[Ee]vents 140 | [Ww]ebsite/[Dd]esktop[Mm]odules/[Ff]eedback 141 | [Ww]ebsite/[Dd]esktop[Mm]odules/[Ff][Aa][Qq]s 142 | [Ww]ebsite/[Dd]esktop[Mm]odules/[Mm]edia 143 | [Ww]ebsite/[Dd]esktop[Mm]odules/[Uu]ser[Dd]efined[Tt]able 144 | [Ww]ebsite/[Dd]esktop[Mm]odules/dnnGlimpse 145 | [Ww]ebsite/[Dd]esktop[Mm]odules/[Tt]est* 146 | 147 | [Ww]ebsite/[Ii]nstall/*/*.zip 148 | [Ww]ebsite/[Ii]nstall/*/*.resources 149 | [Ww]ebsite/[Ii]nstall/[Cc]leanup 150 | [Ww]ebsite/[Ii]nstall/[Cc]onfig 151 | [Ww]ebsite/[Ii]nstall/[Dd]ot[Nn]et[Nn]uke.install.config 152 | [Ww]ebsite/[Ii]nstall/installstat.log.resources.txt 153 | [Ww]ebsite/[Ii]nstall/upgradestat.log.resources.txt 154 | 155 | [Ww]ebsite/[Ll]icenses/*.txt 156 | 157 | [Ww]ebsite/[Mm]odules 158 | 159 | [Ww]ebsite/[Pp]ortals/_default/[Ll]ogs 160 | [Ww]ebsite/[Pp]ortals/_default/[Mm]erged[Tt]emplate 161 | [Ww]ebsite/[Pp]ortals/_default/[Bb]lank [Ww]ebsite*.* 162 | [Ww]ebsite/[Pp]ortals/_default/[Dd]efault [Ww]ebsite*.* 163 | [Ww]ebsite/[Pp]ortals/_default/[Mm]obile [Ww]ebsite*.* 164 | [Ww]ebsite/[Pp]ortals/_default/[Cc]ontainers/*/thumbnail*.jpg 165 | [Ww]ebsite/[Pp]ortals/_default/[Cc]ontainers/[Cc]avalier/*.* 166 | [Ww]ebsite/[Pp]ortals/_default/[Ss]kins/*/thumbnail*.jpg 167 | [Ww]ebsite/[Pp]ortals/_default/[Ss]kins/[Cc]avalier 168 | [Ww]ebsite/[Pp]ortals/_default/[Ss]kins/[Cc]avalier/*/*.* 169 | 170 | [Ww]ebsite/[Pp]ortals/_default/[Uu]ser* 171 | [Ww]ebsite/[Pp]ortals/[0-9]*/ 172 | 173 | [Ww]ebsite/[Pp]roviders/[Dd]ata[Pp]roviders/*/*.resources 174 | [Ww]ebsite/[Pp]roviders/*/*/license.txt 175 | [Ww]ebsite/[Pp]roviders/*/*/release[Nn]otes.txt 176 | [Ww]ebsite/[Pp]roviders/[Ff]older[Pp]roviders 177 | 178 | [Ww]ebsite/[Rr]esources/[Ll]ibraries 179 | 180 | [Ww]ebsite/[Ss]ignatures 181 | 182 | [Ww]ebsite/51[Dd]egrees.mobi.config 183 | [Ww]ebsite/[Dd]ot[Nn]et[Nn]uke.log4net.config 184 | [Ww]ebsite/[Dd]ot[Nn]et[Nn]uke.config 185 | [Ww]ebsite/[Ss]ite[Aa]nalytics.config 186 | [Ww]ebsite/[Ss]ite[Uu]rls.config 187 | [Ww]ebsite/web.config 188 | [Ww]ebsite/app_offline.htm 189 | 190 | # ignore all other language resx files 191 | *.de-DE.resx 192 | *.es-ES.resx 193 | *.fr-FR.resx 194 | *.it-IT.resx 195 | *.nl-NL.resx 196 | 197 | # but do track translations in the Install folder 198 | ![Ww]ebsite/[Ii]nstall/[Aa]pp_[Ll]ocal[Rr]esources/*.de-DE.resx 199 | ![Ww]ebsite/[Ii]nstall/[Aa]pp_[Ll]ocal[Rr]esources/*.es-ES.resx 200 | ![Ww]ebsite/[Ii]nstall/[Aa]pp_[Ll]ocal[Rr]esources/*.fr-FR.resx 201 | ![Ww]ebsite/[Ii]nstall/[Aa]pp_[Ll]ocal[Rr]esources/*.it-IT.resx 202 | ![Ww]ebsite/[Ii]nstall/[Aa]pp_[Ll]ocal[Rr]esources/*.nl-NL.resx 203 | 204 | *.zip.manifest 205 | 206 | ############ 207 | ## Windows 208 | ############ 209 | 210 | # Windows image file caches 211 | Thumbs.db 212 | 213 | # Folder config file 214 | Desktop.ini 215 | 216 | Website/Install/Temp/ 217 | install/ 218 | -------------------------------------------------------------------------------- /Build.proj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | $(MSBuildProjectDirectory)\.build 5 | 6 | 7 | 8 | 9 | 10 | 11 | 1.0.0.0 12 | 1.0.0.0 13 | 1.0.0.0 14 | 15 | 16 | 17 | 18 | 1.0.0.0 19 | $(BUILD_NUMBER) 20 | $(BUILD_NUMBER) 21 | 22 | 23 | 24 | Release 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 35 | 36 | 37 | 38 | 39 | 40 | 48 | 49 | 50 | 51 | 52 | 53 | Configuration=$(BuildConfiguration) 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /BuildScripts/MSBuild.Community.Tasks.Targets: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $(MSBuildProjectDirectory)\BuildScripts 5 | $(MSBuildProjectDirectory)\..\..\..\bin 6 | $(SolutionDir)\packages\MSBuildTasks.1.4.0.61\tools\MSBuild.Community.Tasks.dll 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | -------------------------------------------------------------------------------- /BuildScripts/ModulePackage.targets: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 13 | 14 | 15 | 16 | $(Version).00 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | -------------------------------------------------------------------------------- /Components/AuditChecks.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | using DNN.Modules.SecurityAnalyzer.Components.Checks; 6 | using DotNetNuke.Common; 7 | 8 | namespace DNN.Modules.SecurityAnalyzer.Components 9 | { 10 | public class AuditChecks 11 | { 12 | private readonly IEnumerable _auditChecks; 13 | 14 | public AuditChecks() 15 | { 16 | var checks = new List 17 | { 18 | new CheckDnnVersion(), 19 | new CheckDebug(), 20 | new CheckTracing(), 21 | new CheckBiography(), 22 | new CheckSiteRegistration(), 23 | new CheckRarelyUsedSuperuser(), 24 | new CheckSuperuserOldPassword(), 25 | new CheckUnexpectedExtensions(), 26 | new CheckDefaultPage(), 27 | new CheckModuleHeaderAndFooter(), 28 | new CheckPasswordFormat(), 29 | new CheckDiskAcccessPermissions(), 30 | new CheckSqlRisk(), 31 | new CheckAllowableFileExtensions(), 32 | new CheckHiddenSystemFiles(), 33 | new CheckTelerikVulnerability(), 34 | new CheckHttpModules() 35 | }; 36 | 37 | if (Globals.NETFrameworkVersion <= new Version(4, 5, 1)) 38 | { 39 | checks.Insert(2, new CheckViewstatemac()); 40 | } 41 | 42 | _auditChecks= checks.AsReadOnly(); 43 | } 44 | 45 | public IList DoChecks(bool checkAll = false) 46 | { 47 | var results = new List(); 48 | foreach (var check in _auditChecks) 49 | { 50 | try 51 | { 52 | var result = checkAll || !check.LazyLoad ? check.Execute() : new CheckResult(SeverityEnum.Unverified, check.Id); 53 | results.Add(result); 54 | } 55 | catch (Exception ex) 56 | { 57 | var result = new CheckResult(SeverityEnum.Unverified, check.Id); 58 | result.Notes.Add("An error occured, Message: " + HttpUtility.HtmlEncode(ex.Message)); 59 | results.Add(result); 60 | } 61 | 62 | } 63 | return results; 64 | } 65 | 66 | public CheckResult DoCheck(string id) 67 | { 68 | try 69 | { 70 | var check = _auditChecks.FirstOrDefault(c => c.Id.Equals(id, StringComparison.InvariantCultureIgnoreCase)); 71 | return check?.Execute(); 72 | } 73 | catch (Exception) 74 | { 75 | return new CheckResult(SeverityEnum.Unverified, id); 76 | } 77 | } 78 | } 79 | } -------------------------------------------------------------------------------- /Components/CheckResult.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using DotNetNuke.Services.Localization; 4 | 5 | namespace DNN.Modules.SecurityAnalyzer.Components 6 | { 7 | [Serializable] 8 | public class CheckResult 9 | { 10 | public CheckResult(SeverityEnum severity, string checkname) 11 | { 12 | Severity = severity; 13 | CheckName = checkname; 14 | Notes = new List(); 15 | } 16 | 17 | public SeverityEnum Severity { get; set; } 18 | public string CheckName { get; set; } 19 | 20 | public string Reason 21 | { 22 | get 23 | { 24 | return Localization.GetString(CheckName + "Reason", LocalResourceFile); 25 | } 26 | } 27 | 28 | public string FailureText 29 | { 30 | get { return Localization.GetString(CheckName + "Failure", LocalResourceFile); } 31 | } 32 | 33 | public string SuccessText 34 | { 35 | get { return Localization.GetString(CheckName + "Success", LocalResourceFile); } 36 | } 37 | 38 | public string CheckNameText 39 | { 40 | get 41 | { 42 | 43 | return CheckName + " : " + Localization.GetString(CheckName + "Name", LocalResourceFile); 44 | } 45 | } 46 | 47 | public IList Notes { get; set; } 48 | 49 | private string LocalResourceFile 50 | { 51 | get { return "~/DesktopModules/DNNCorp/SecurityAnalyzer/App_LocalResources/view.ascx"; } 52 | } 53 | } 54 | } -------------------------------------------------------------------------------- /Components/Checks/CheckAllowableFileExtensions.cs: -------------------------------------------------------------------------------- 1 | using DotNetNuke.Entities.Controllers; 2 | 3 | namespace DNN.Modules.SecurityAnalyzer.Components.Checks 4 | { 5 | public class CheckAllowableFileExtensions : IAuditCheck 6 | { 7 | public string Id => "CheckAllowableFileExtensions"; 8 | 9 | public bool LazyLoad => false; 10 | 11 | public CheckResult Execute() 12 | { 13 | var result = new CheckResult(SeverityEnum.Unverified, Id); 14 | var allowedExtensions = new FileExtensionWhitelist(HostController.Instance.GetString("FileExtensions")); 15 | if (allowedExtensions.IsAllowedExtension("asp") 16 | || allowedExtensions.IsAllowedExtension("aspx") 17 | || allowedExtensions.IsAllowedExtension("php")) 18 | { 19 | result.Severity = SeverityEnum.Failure; 20 | result.Notes.Add("Extensions: " + allowedExtensions.ToDisplayString()); 21 | } 22 | else 23 | { 24 | result.Severity = SeverityEnum.Pass; 25 | } 26 | return result; 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /Components/Checks/CheckBiography.cs: -------------------------------------------------------------------------------- 1 | using DotNetNuke.Common.Lists; 2 | using DotNetNuke.Entities.Portals; 3 | using DotNetNuke.Entities.Profile; 4 | 5 | namespace DNN.Modules.SecurityAnalyzer.Components.Checks 6 | { 7 | public class CheckBiography : IAuditCheck 8 | { 9 | public string Id => "CheckBiography"; 10 | 11 | public bool LazyLoad => false; 12 | 13 | public CheckResult Execute() 14 | { 15 | var result = new CheckResult(SeverityEnum.Unverified, Id); 16 | var portalController = new PortalController(); 17 | var controller = new ListController(); 18 | 19 | var richTextDataType = controller.GetListEntryInfo("DataType", "RichText"); 20 | result.Severity = SeverityEnum.Pass; 21 | foreach (PortalInfo portal in portalController.GetPortals()) 22 | { 23 | var pd = ProfileController.GetPropertyDefinitionByName(portal.PortalID, "Biography"); 24 | if (pd != null && pd.DataType == richTextDataType.EntryID) 25 | { 26 | result.Severity = SeverityEnum.Failure; 27 | result.Notes.Add("Portal:" + portal.PortalName); 28 | } 29 | } 30 | return result; 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /Components/Checks/CheckDebug.cs: -------------------------------------------------------------------------------- 1 | using System.Web; 2 | 3 | namespace DNN.Modules.SecurityAnalyzer.Components.Checks 4 | { 5 | public class CheckDebug : IAuditCheck 6 | { 7 | public string Id => "CheckDebug"; 8 | 9 | public bool LazyLoad => false; 10 | 11 | public CheckResult Execute() 12 | { 13 | var result = new CheckResult(SeverityEnum.Unverified, Id) 14 | { 15 | Severity = HttpContext.Current.IsDebuggingEnabled 16 | ? SeverityEnum.Warning 17 | : SeverityEnum.Pass 18 | }; 19 | return result; 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /Components/Checks/CheckDefaultPage.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.IO; 3 | using System.Xml; 4 | using DotNetNuke.Application; 5 | using DotNetNuke.Common; 6 | 7 | namespace DNN.Modules.SecurityAnalyzer.Components.Checks 8 | { 9 | public class CheckDefaultPage : IAuditCheck 10 | { 11 | public string Id => "CheckDefaultPage"; 12 | 13 | public bool LazyLoad => false; 14 | 15 | public CheckResult Execute() 16 | { 17 | var result = new CheckResult(SeverityEnum.Unverified, Id); 18 | IList modifiedFiles; 19 | var fileModified = CheckDefaultPageModified(out modifiedFiles); 20 | if (fileModified) 21 | { 22 | if (modifiedFiles.Count == 0) 23 | { 24 | if (DotNetNukeContext.Current.Application.Version.Major > 6) 25 | { 26 | result.Notes.Add("There is no data available about your current installation, please upgrade this module to it's latest version."); 27 | } 28 | else 29 | { 30 | fileModified = false; 31 | } 32 | } 33 | 34 | result.Severity = SeverityEnum.Failure; 35 | foreach (var filename in modifiedFiles) 36 | { 37 | result.Notes.Add("file:" + filename); 38 | } 39 | } 40 | else 41 | { 42 | result.Severity = SeverityEnum.Pass; 43 | } 44 | return result; 45 | } 46 | 47 | private bool CheckDefaultPageModified(out IList modifiedFiles) 48 | { 49 | modifiedFiles = new List(); 50 | 51 | var sumData = Utility.LoadFileSumData(); 52 | 53 | var appVersion = Utility.GetApplicationVersion(); 54 | var appType = Utility.GetApplicationType(); 55 | 56 | var dataNodes = sumData.SelectNodes("/checksums/sum[@version=\"" + appVersion + "\"][@type=\"" + appType + "\"]"); 57 | if (dataNodes == null || dataNodes.Count == 0) 58 | { 59 | return true; //when no record matched, need notify user to update the module. 60 | } 61 | 62 | var fileModified = false; 63 | foreach (XmlNode node in dataNodes) 64 | { 65 | var fileName = node.Attributes["name"].Value; 66 | var sum = node.Attributes["sum"].Value; 67 | var file = Path.Combine(Globals.ApplicationMapPath, fileName); 68 | if (!File.Exists(file) || Utility.GetFileCheckSum(file) != sum) 69 | { 70 | fileModified = true; 71 | modifiedFiles.Add(fileName); 72 | } 73 | } 74 | 75 | return fileModified; 76 | } 77 | } 78 | } -------------------------------------------------------------------------------- /Components/Checks/CheckDiskAcccessPermissions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Security.AccessControl; 6 | using System.Security.Principal; 7 | using DotNetNuke.Common; 8 | 9 | namespace DNN.Modules.SecurityAnalyzer.Components.Checks 10 | { 11 | public class CheckDiskAcccessPermissions : IAuditCheck 12 | { 13 | public string Id => "CheckDiskAccess"; 14 | 15 | public bool LazyLoad => false; 16 | 17 | public CheckResult Execute() 18 | { 19 | var result = new CheckResult(SeverityEnum.Unverified, Id); 20 | IList accessErrors = new List(); 21 | try 22 | { 23 | accessErrors = CheckAccessToDrives(); 24 | } 25 | catch (IOException) 26 | { 27 | // e.g., a disk error or a drive was not ready 28 | } 29 | catch (UnauthorizedAccessException) 30 | { 31 | // The caller does not have the required permission. 32 | 33 | } 34 | catch (System.Security.SecurityException) 35 | { 36 | //Some security exception 37 | } 38 | 39 | 40 | if (accessErrors.Count == 0) 41 | { 42 | result.Severity = SeverityEnum.Pass; 43 | } 44 | else 45 | { 46 | result.Severity = SeverityEnum.Warning; 47 | result.Notes = accessErrors; 48 | } 49 | return result; 50 | } 51 | 52 | #region private methods 53 | 54 | private static IList CheckAccessToDrives() 55 | { 56 | var errors = new List(); 57 | var dir = new DirectoryInfo(Globals.ApplicationMapPath); 58 | 59 | 60 | while (dir.Parent != null) 61 | { 62 | 63 | try 64 | { 65 | dir = dir.Parent; 66 | var permissions = CheckPermissionOnDir(dir); 67 | var isRoot = dir.Name == dir.Root.Name; 68 | if (permissions.Create == Yes || permissions.Write == Yes || permissions.Delete == Yes || (!isRoot && permissions.Read == Yes)) 69 | { 70 | errors.Add(GetPermissionText(dir, permissions, isRoot)); 71 | } 72 | } 73 | catch (IOException) 74 | { 75 | // e.g., a disk error or a drive was not ready 76 | } 77 | catch (UnauthorizedAccessException) 78 | { 79 | // The caller does not have the required permission. 80 | 81 | } 82 | 83 | } 84 | 85 | var drives = DriveInfo.GetDrives(); 86 | var checkedDrives = new List(); 87 | foreach (var drive in drives.Where(d => d.IsReady && d.RootDirectory.Name != dir.Root.Name)) 88 | { 89 | try 90 | { 91 | var driveType = drive.DriveType; 92 | if (driveType == DriveType.Fixed || driveType == DriveType.Network) 93 | { 94 | var dir2 = drive.RootDirectory; 95 | var key = dir2.FullName.ToLowerInvariant(); 96 | if (checkedDrives.Contains(key)) 97 | { 98 | continue; 99 | } 100 | 101 | checkedDrives.Add(key); 102 | 103 | var permissions = CheckPermissionOnDir(dir2); 104 | if (permissions.AnyYes) 105 | { 106 | errors.Add(GetPermissionText(dir2, permissions)); 107 | } 108 | } 109 | } 110 | catch (IOException) 111 | { 112 | // e.g., a disk error or a drive was not ready 113 | } 114 | catch (UnauthorizedAccessException) 115 | { 116 | // The caller does not have the required permission. 117 | } 118 | } 119 | 120 | return errors; 121 | } 122 | 123 | private static string GetPermissionText(DirectoryInfo dir, Permissions permissions, bool ignoreRead = false) 124 | { 125 | var message = ignoreRead 126 | ? @"{0} - Write:{2}, Create:{3}, Delete:{4}" 127 | : @"{0} - Read:{1}, Write:{2}, Create:{3}, Delete:{4}"; 128 | return string.Format(@"{0} - Read:{1}, Write:{2}, Create:{3}, Delete:{4}", 129 | dir.FullName, permissions.Read, permissions.Write, permissions.Create, permissions.Delete); 130 | } 131 | 132 | private static Permissions CheckPermissionOnDir(DirectoryInfo dir) 133 | { 134 | var permissions = new Permissions(No); 135 | var disSecurity = dir.GetAccessControl(AccessControlSections.Access); 136 | var accessRules = disSecurity.GetAccessRules(true, true, typeof(SecurityIdentifier)); 137 | var poolIdentity = WindowsIdentity.GetCurrent(); 138 | if (poolIdentity.User != null && poolIdentity.Groups != null) 139 | { 140 | foreach (FileSystemAccessRule rule in accessRules) 141 | { 142 | if (poolIdentity.User.Value == rule.IdentityReference.Value || poolIdentity.Groups.Contains(rule.IdentityReference)) 143 | { 144 | if ((rule.FileSystemRights & (FileSystemRights.CreateDirectories | FileSystemRights.CreateFiles)) != 0) 145 | if (rule.AccessControlType == AccessControlType.Allow) 146 | permissions.Create = Yes; 147 | else 148 | permissions.SetThenLockCreate(No); 149 | 150 | if ((rule.FileSystemRights & FileSystemRights.Write) != 0) 151 | if (rule.AccessControlType == AccessControlType.Allow) 152 | permissions.Write = Yes; 153 | else 154 | permissions.SetThenLockWrite(No); 155 | 156 | if ((rule.FileSystemRights & (FileSystemRights.Read | FileSystemRights.ReadData)) != 0) 157 | if (rule.AccessControlType == AccessControlType.Allow) 158 | permissions.Read = Yes; 159 | else 160 | permissions.SetThenLockRead(No); 161 | 162 | if ((rule.FileSystemRights & (FileSystemRights.Delete | FileSystemRights.DeleteSubdirectoriesAndFiles)) != 0) 163 | if (rule.AccessControlType == AccessControlType.Allow) 164 | permissions.Delete = Yes; 165 | else 166 | permissions.SetThenLockDelete(No); 167 | } 168 | } 169 | } 170 | 171 | return permissions; 172 | } 173 | 174 | #endregion 175 | 176 | #region helpers 177 | 178 | private const char Yes = 'Y'; 179 | private const char No = 'N'; 180 | 181 | private class Permissions 182 | { 183 | public Permissions(char initial) 184 | { 185 | _create = _write = _read = _delete = initial; 186 | } 187 | 188 | public bool AnyYes 189 | { 190 | get { return Create == Yes || Write == Yes || Read == Yes || Delete == Yes; } 191 | } 192 | 193 | private char _create; 194 | private char _write; 195 | private char _read; 196 | private char _delete; 197 | 198 | private bool _createLocked; 199 | private bool _writeLocked; 200 | private bool _readLocked; 201 | private bool _deleteLocked; 202 | 203 | public char Create 204 | { 205 | get { return _create; } 206 | set { if (!_createLocked) _create = value; } 207 | } 208 | 209 | public char Write 210 | { 211 | get { return _write; } 212 | set { if (!_writeLocked) _write = value; } 213 | } 214 | 215 | public char Read 216 | { 217 | get { return _read; } 218 | set { if (!_readLocked) _read = value; } 219 | } 220 | 221 | public char Delete 222 | { 223 | get { return _delete; } 224 | set { if (!_deleteLocked) _delete = value; } 225 | } 226 | 227 | public void SetThenLockCreate(char value) 228 | { 229 | if (!_createLocked) 230 | { 231 | _createLocked = true; 232 | _create = value; 233 | } 234 | } 235 | 236 | public void SetThenLockWrite(char value) 237 | { 238 | if (!_writeLocked) 239 | { 240 | _writeLocked = true; 241 | _write = value; 242 | } 243 | } 244 | 245 | public void SetThenLockRead(char value) 246 | { 247 | if (!_readLocked) 248 | { 249 | _readLocked = true; 250 | _read = value; 251 | } 252 | } 253 | 254 | public void SetThenLockDelete(char value) 255 | { 256 | if (!_deleteLocked) 257 | { 258 | _deleteLocked = true; 259 | _delete = value; 260 | } 261 | } 262 | } 263 | 264 | #endregion 265 | } 266 | } 267 | -------------------------------------------------------------------------------- /Components/Checks/CheckDnnVersion.cs: -------------------------------------------------------------------------------- 1 | namespace DNN.Modules.SecurityAnalyzer.Components.Checks 2 | { 3 | using DotNetNuke.Application; 4 | using DotNetNuke.Services.Localization; 5 | 6 | public class CheckDnnVersion : IAuditCheck 7 | { 8 | private const string ResourceFileRoot = "~/DesktopModules/DNNCorp/SecurityAnalyzer/App_LocalResources/View.ascx"; 9 | 10 | public string Id => "CheckDnnVersion"; 11 | 12 | public bool LazyLoad => false; 13 | 14 | public CheckResult Execute() 15 | { 16 | const int KnownCompromisedVersion = 8; 17 | var severity = DotNetNukeContext.Current.Application.Version.Major <= KnownCompromisedVersion 18 | ? SeverityEnum.Failure 19 | : SeverityEnum.Warning; 20 | 21 | return new CheckResult(severity, Id) 22 | { 23 | Notes = 24 | { 25 | Localization.GetString("CheckDnnVersion" + severity + "Note", ResourceFileRoot), 26 | } 27 | }; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Components/Checks/CheckHiddenSystemFiles.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | 3 | namespace DNN.Modules.SecurityAnalyzer.Components.Checks 4 | { 5 | public class CheckHiddenSystemFiles : IAuditCheck 6 | { 7 | public string Id => "CheckHiddenSystemFiles"; 8 | 9 | public bool LazyLoad => true; 10 | 11 | public CheckResult Execute() 12 | { 13 | var result = new CheckResult(SeverityEnum.Unverified, Id); 14 | var investigatefiles = Utility.FineHiddenSystemFiles(); 15 | if (investigatefiles.Any()) 16 | { 17 | result.Severity = SeverityEnum.Failure; 18 | foreach (var filename in investigatefiles) 19 | { 20 | result.Notes.Add("file:" + filename); 21 | } 22 | } 23 | else 24 | { 25 | result.Severity = SeverityEnum.Pass; 26 | } 27 | return result; 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /Components/Checks/CheckHttpModules.cs: -------------------------------------------------------------------------------- 1 | using DNN.Modules.SecurityAnalyzer.HttpModules; 2 | 3 | namespace DNN.Modules.SecurityAnalyzer.Components.Checks 4 | { 5 | public class CheckHttpModules : IAuditCheck 6 | { 7 | public string Id => "CheckHttpModules"; 8 | 9 | public bool LazyLoad => false; 10 | 11 | public CheckResult Execute() 12 | { 13 | var result = new CheckResult(SeverityEnum.Unverified, Id) 14 | { 15 | Severity = !SecurityAnalyzerModule.SAHttpModuleExists 16 | ? SeverityEnum.Failure 17 | : SeverityEnum.Pass 18 | }; 19 | return result; 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /Components/Checks/CheckModuleHeaderAndFooter.cs: -------------------------------------------------------------------------------- 1 | using System.Web; 2 | using DotNetNuke.Data; 3 | 4 | namespace DNN.Modules.SecurityAnalyzer.Components.Checks 5 | { 6 | public class CheckModuleHeaderAndFooter : IAuditCheck 7 | { 8 | public string Id => "CheckModuleHeaderAndFooter"; 9 | 10 | public bool LazyLoad => false; 11 | 12 | public CheckResult Execute() 13 | { 14 | var result = new CheckResult(SeverityEnum.Unverified, Id); 15 | var dr = DataProvider.Instance().ExecuteReader("SecurityAnalyzer_GetModulesHasHeaderFooter"); 16 | result.Severity = SeverityEnum.Pass; 17 | while (dr.Read()) 18 | { 19 | result.Severity = SeverityEnum.Warning; 20 | var note = string.Format("TabId: {0}, Module Id: {1}", dr["TabId"], dr["ModuleId"]); 21 | var headerValue = dr["Header"].ToString(); 22 | var footerValue = dr["Footer"].ToString(); 23 | if (!string.IsNullOrEmpty(headerValue)) 24 | { 25 | note += string.Format("
Header: {0}", HttpUtility.HtmlEncode(headerValue)); 26 | } 27 | if (!string.IsNullOrEmpty(footerValue)) 28 | { 29 | note += string.Format("
Footer: {0}", HttpUtility.HtmlEncode(footerValue)); 30 | } 31 | note += "< br />"; 32 | 33 | result.Notes.Add(note); 34 | } 35 | return result; 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /Components/Checks/CheckPasswordFormat.cs: -------------------------------------------------------------------------------- 1 | using DotNetNuke.Security.Membership; 2 | 3 | namespace DNN.Modules.SecurityAnalyzer.Components.Checks 4 | { 5 | public class CheckPasswordFormat : IAuditCheck 6 | { 7 | public string Id => "CheckPasswordFormat"; 8 | 9 | public bool LazyLoad => false; 10 | 11 | public CheckResult Execute() 12 | { 13 | var result = new CheckResult(SeverityEnum.Unverified, Id); 14 | var format = MembershipProvider.Instance().PasswordFormat; 15 | if (format == PasswordFormat.Hashed) 16 | { 17 | result.Severity = SeverityEnum.Pass; 18 | } 19 | else 20 | { 21 | result.Notes.Add("Setting:" + format.ToString()); 22 | result.Severity = SeverityEnum.Failure; 23 | } 24 | return result; 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /Components/Checks/CheckRarelyUsedSuperuser.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using DotNetNuke.Entities.Users; 3 | 4 | namespace DNN.Modules.SecurityAnalyzer.Components.Checks 5 | { 6 | public class CheckRarelyUsedSuperuser : IAuditCheck 7 | { 8 | public string Id => "CheckRarelyUsedSuperuser"; 9 | 10 | public bool LazyLoad => false; 11 | 12 | public CheckResult Execute() 13 | { 14 | var result = new CheckResult(SeverityEnum.Unverified, Id); 15 | var totalRecords = 0; 16 | 17 | var superUsers = UserController.GetUsers(-1, 1, int.MaxValue, ref totalRecords, false, true); 18 | result.Severity = SeverityEnum.Pass; 19 | foreach (UserInfo user in superUsers) 20 | { 21 | if (DateTime.Now.AddMonths(-6) > user.Membership.LastLoginDate || 22 | DateTime.Now.AddMonths(-6) > user.Membership.LastActivityDate) 23 | { 24 | result.Severity = SeverityEnum.Warning; 25 | result.Notes.Add("Superuser:" + user.Username); 26 | } 27 | } 28 | return result; 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /Components/Checks/CheckSiteRegistration.cs: -------------------------------------------------------------------------------- 1 | using DotNetNuke.Entities.Portals; 2 | 3 | namespace DNN.Modules.SecurityAnalyzer.Components.Checks 4 | { 5 | public class CheckSiteRegistration : IAuditCheck 6 | { 7 | public string Id => "CheckSiteRegistration"; 8 | 9 | public bool LazyLoad => false; 10 | 11 | public CheckResult Execute() 12 | { 13 | var result = new CheckResult(SeverityEnum.Unverified, Id); 14 | var portalController = new PortalController(); 15 | result.Severity = SeverityEnum.Pass; 16 | foreach (PortalInfo portal in portalController.GetPortals()) 17 | { 18 | //check for public registration 19 | if (portal.UserRegistration == 2) 20 | { 21 | result.Severity = SeverityEnum.Warning; 22 | result.Notes.Add("Portal:" + portal.PortalName); 23 | } 24 | } 25 | return result; 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /Components/Checks/CheckSqlRisk.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Data.SqlClient; 3 | using System.IO; 4 | using DotNetNuke.Common; 5 | using DotNetNuke.Data; 6 | using DotNetNuke.Services.Localization; 7 | using Assembly = System.Reflection.Assembly; 8 | 9 | namespace DNN.Modules.SecurityAnalyzer.Components.Checks 10 | { 11 | public class CheckSqlRisk : IAuditCheck 12 | { 13 | public string Id => "CheckSqlRisk"; 14 | 15 | public bool LazyLoad => false; 16 | 17 | private string LocalResourceFile 18 | { 19 | get { return "~/DesktopModules/DNNCorp/SecurityAnalyzer/App_LocalResources/view.ascx"; } 20 | } 21 | 22 | public CheckResult Execute() 23 | { 24 | var result = new CheckResult(SeverityEnum.Unverified, Id); 25 | IList checkList = new List() 26 | { 27 | "SysAdmin", 28 | "ExecuteCommand", 29 | "GetFolderTree", 30 | "CheckFileExists", 31 | "RegRead" 32 | }; 33 | 34 | result.Severity = SeverityEnum.Pass; 35 | foreach (var name in checkList) 36 | { 37 | if (!VerifyScript(name)) 38 | { 39 | result.Severity = SeverityEnum.Warning; 40 | result.Notes.Add(Localization.GetString(name + ".Error", LocalResourceFile)); 41 | } 42 | } 43 | return result; 44 | } 45 | 46 | private static bool VerifyScript(string name) 47 | { 48 | try 49 | { 50 | var script = LoadScript(name); 51 | if (!string.IsNullOrEmpty(script)) 52 | { 53 | using (var reader = DataProvider.Instance().ExecuteSQL(script)) 54 | { 55 | if (reader != null && reader.Read()) 56 | { 57 | int affectCount; 58 | int.TryParse(reader[0].ToString(), out affectCount); 59 | return affectCount == 0; 60 | } 61 | } 62 | } 63 | } 64 | catch (SqlException) 65 | { 66 | //ignore; return no failure 67 | } 68 | return true; 69 | } 70 | 71 | public static string LoadScript(string name) 72 | { 73 | var resourceName = string.Format("DNN.Modules.SecurityAnalyzer.Resources.{0}.resources", name); 74 | using (var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName)) 75 | { 76 | if (stream != null) 77 | { 78 | var script = new StreamReader(stream).ReadToEnd(); 79 | return script.Replace("%SiteRoot%", Globals.ApplicationMapPath); 80 | } 81 | 82 | return null; 83 | } 84 | } 85 | } 86 | } -------------------------------------------------------------------------------- /Components/Checks/CheckSuperuserOldPassword.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using DotNetNuke.Entities.Users; 3 | 4 | namespace DNN.Modules.SecurityAnalyzer.Components.Checks 5 | { 6 | public class CheckSuperuserOldPassword : IAuditCheck 7 | { 8 | public string Id => "CheckSuperuserOldPassword"; 9 | 10 | public bool LazyLoad => false; 11 | 12 | public CheckResult Execute() 13 | { 14 | var result = new CheckResult(SeverityEnum.Unverified, Id); 15 | var totalRecords = 0; 16 | var superUsers = UserController.GetUsers(-1, 1, int.MaxValue, ref totalRecords, false, true); 17 | result.Severity = SeverityEnum.Pass; 18 | foreach (UserInfo user in superUsers) 19 | { 20 | if (DateTime.Now.AddMonths(-6) > user.Membership.LastPasswordChangeDate) 21 | { 22 | result.Severity = SeverityEnum.Warning; 23 | result.Notes.Add("Superuser:" + user.Username); 24 | } 25 | } 26 | return result; 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /Components/Checks/CheckTelerikVulnerability.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Web; 7 | using DotNetNuke.Common; 8 | using DotNetNuke.Common.Utilities; 9 | using DotNetNuke.Security; 10 | using Assembly = System.Reflection.Assembly; 11 | 12 | namespace DNN.Modules.SecurityAnalyzer.Components.Checks 13 | { 14 | public class CheckTelerikVulnerability : IAuditCheck 15 | { 16 | public string Id => "CheckTelerikVulnerability"; 17 | 18 | public bool LazyLoad => false; 19 | 20 | private string[] _configKeys = { 21 | "Telerik.AsyncUpload.ConfigurationEncryptionKey", 22 | "Telerik.Upload.ConfigurationHashKey", 23 | "Telerik.Web.UI.DialogParametersEncryptionKey", 24 | }; 25 | 26 | private const string DefaultValue = "MDEyMzQ1Njc4OUFCQ0RFRjAxMjM0NTY3ODlBQkNERUYwMTIzNDU2Nzg5QUJDREVG"; 27 | private Func _funx = s => string.IsNullOrEmpty(s) || DefaultValue.Equals(s) || s.Length < 40; 28 | 29 | public CheckResult Execute() 30 | { 31 | var result = new CheckResult(SeverityEnum.Unverified, Id); 32 | 33 | var fileSums = new List 34 | { 35 | // SHA-256 hashes 36 | "63de0ee563f34c21b0688fb5f81be02bb2aee94c8e5c855fbece72e4de455945", //Telerik 2013.2.717.40 37 | "f6dc6dd32f4f5698217c72a512ce9872c002be98cfced9a0344b46c50c1a6f02" //Telerik 2013.2.717.35 38 | }; 39 | 40 | var compareVersion = new Version(2017, 2, 711); 41 | var filePath = Path.Combine(Globals.ApplicationMapPath, "bin\\Telerik.Web.UI.dll"); 42 | result.Severity = SeverityEnum.Pass; 43 | 44 | if (File.Exists(filePath)) 45 | { 46 | var assemblyVersion = Assembly.LoadFile(filePath).GetName().Version; 47 | if (assemblyVersion < compareVersion && !fileSums.Contains(Utility.GetFileCheckSum(filePath))) 48 | { 49 | result.Severity = SeverityEnum.Failure; 50 | result.Notes.Add("Telerik.Web.UI.dll assembly has't been patched."); 51 | } 52 | 53 | if (_configKeys.Select(Config.GetSetting).Any(val => _funx(val))) 54 | { 55 | var err = UpdateWebConfigFile(); 56 | if (string.IsNullOrEmpty(err)) 57 | { 58 | if (HttpContext.Current != null) 59 | { 60 | HttpContext.Current.Response.Redirect(HttpContext.Current.Request.RawUrl, true); 61 | } 62 | } 63 | else 64 | { 65 | result.Notes.Add("Couldn't update web.config file!"); 66 | } 67 | } 68 | 69 | // check after trying to add the missing key(s) 70 | foreach (var configKey in _configKeys) 71 | { 72 | if (string.IsNullOrEmpty(Config.GetSetting(configKey))) 73 | { 74 | result.Severity = SeverityEnum.Failure; 75 | result.Notes.Add("App Setting \"" + configKey + "\" doesn't exist in web.config."); 76 | } 77 | } 78 | } 79 | else 80 | { 81 | result.Notes.Add("Telerik component is not installed in this site."); 82 | } 83 | 84 | return result; 85 | } 86 | 87 | private string UpdateWebConfigFile() 88 | { 89 | var strError = ""; 90 | try 91 | { 92 | var appSettings = new Dictionary(); 93 | foreach (var configKey in _configKeys) 94 | { 95 | var currentKey = Config.GetSetting(configKey); 96 | if (_funx(currentKey)) 97 | { 98 | //create a random Telerik encryption key and add it under 99 | var newKey = new PortalSecurity().CreateKey(32); 100 | newKey = Convert.ToBase64String(Encoding.ASCII.GetBytes(newKey)); 101 | 102 | appSettings.Add(configKey, newKey); 103 | } 104 | } 105 | 106 | if (appSettings.Count > 0) 107 | { 108 | //save the current config file 109 | Config.BackupConfig(); 110 | 111 | //decrypt the web.config if needed. 112 | string providerName; 113 | var decrypted = Utility.DecryptConfigFile(out providerName); 114 | 115 | //open the web.config 116 | var xmlConfig = Config.Load(); 117 | 118 | //Update the app settings. 119 | foreach (var settingKey in appSettings.Keys) 120 | { 121 | Config.AddAppSetting(xmlConfig, settingKey, appSettings[settingKey]); 122 | } 123 | 124 | //save the web.config 125 | strError += Config.Save(xmlConfig); 126 | 127 | if (decrypted) 128 | { 129 | Utility.EncryptConfigFile(providerName); 130 | } 131 | } 132 | } 133 | catch (Exception ex) 134 | { 135 | strError += ex.Message; 136 | } 137 | return strError; 138 | } 139 | } 140 | } -------------------------------------------------------------------------------- /Components/Checks/CheckTracing.cs: -------------------------------------------------------------------------------- 1 | using System.Web; 2 | using System.Web.UI; 3 | 4 | namespace DNN.Modules.SecurityAnalyzer.Components.Checks 5 | { 6 | public class CheckTracing : IAuditCheck 7 | { 8 | public string Id => "CheckTracing"; 9 | 10 | public bool LazyLoad => false; 11 | 12 | public CheckResult Execute() 13 | { 14 | var result = new CheckResult(SeverityEnum.Unverified, Id); 15 | var page = HttpContext.Current.Handler as Page; 16 | 17 | if (page != null) 18 | { 19 | result.Severity = page.TraceEnabled ? SeverityEnum.Failure : SeverityEnum.Pass; 20 | } 21 | return result; 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /Components/Checks/CheckUnexpectedExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | 4 | namespace DNN.Modules.SecurityAnalyzer.Components.Checks 5 | { 6 | public class CheckUnexpectedExtensions : IAuditCheck 7 | { 8 | public string Id => "CheckUnexpectedExtensions"; 9 | 10 | public bool LazyLoad => true; 11 | 12 | public CheckResult Execute() 13 | { 14 | var result = new CheckResult(SeverityEnum.Unverified, Id); 15 | var invalidFolders = new List(); 16 | var investigatefiles = Utility.FindUnexpectedExtensions(invalidFolders).ToList(); 17 | if (investigatefiles.Count > 0) 18 | { 19 | result.Severity = SeverityEnum.Failure; 20 | foreach (var filename in investigatefiles) 21 | { 22 | result.Notes.Add("file:" + filename); 23 | } 24 | } 25 | else 26 | { 27 | result.Severity = SeverityEnum.Pass; 28 | } 29 | 30 | if (invalidFolders.Count > 0) 31 | { 32 | var folders = string.Join("", invalidFolders.Select(f => $"

{f}

").ToArray()); 33 | result.Notes.Add($"

The following folders are inaccessible due to permission restrictions:

{folders}"); 34 | } 35 | return result; 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /Components/Checks/CheckViewstatemac.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Web; 3 | using System.Web.UI; 4 | 5 | namespace DNN.Modules.SecurityAnalyzer.Components.Checks 6 | { 7 | public class CheckViewstatemac : IAuditCheck 8 | { 9 | public string Id => "CheckViewstatemac"; 10 | 11 | public bool LazyLoad => false; 12 | 13 | public CheckResult Execute() 14 | { 15 | var result = new CheckResult(SeverityEnum.Unverified, Id); 16 | try 17 | { 18 | var page = HttpContext.Current.Handler as Page; 19 | 20 | if (page != null) 21 | { 22 | if (page.EnableViewStateMac == false) 23 | { 24 | result.Severity = SeverityEnum.Failure; 25 | } 26 | else 27 | { 28 | result.Severity = SeverityEnum.Pass; 29 | } 30 | } 31 | } 32 | catch (Exception ex) 33 | { 34 | throw (ex); 35 | } 36 | return result; 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /Components/EscapedString.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DNNCommunity/DNN.SecurityAnalyzer/c4fd5bc4cccface170f959ad9d19fa885c5baba6/Components/EscapedString.cs -------------------------------------------------------------------------------- /Components/FeatureController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Text; 4 | using DotNetNuke.Common; 5 | using DotNetNuke.Common.Utilities; 6 | using DotNetNuke.Entities.Modules; 7 | using DotNetNuke.Entities.Modules.Definitions; 8 | using DotNetNuke.Entities.Tabs; 9 | using DotNetNuke.Security; 10 | using DotNetNuke.Security.Permissions; 11 | 12 | namespace DNN.Modules.SecurityAnalyzer.Components 13 | { 14 | public class FeatureController : IUpgradeable 15 | { 16 | public string UpgradeModule(string version) 17 | { 18 | switch (version) 19 | { 20 | case "01.00.00": 21 | //Add Extensions Host Page 22 | var moduleDefId = GetModuleDefinition("SecurityAnalyzer", "SecurityAnalyzer"); 23 | var auditPage = AddHostPage("Security Analyzer", "Audit site security for best practices.", 24 | "~/DesktopModules/DNNCorp/SecurityAnalyzer/Images/Extensions_16x16_Standard.png", "~/DesktopModules/DNNCorp/SecurityAnalyzer/Images/Extensions_32x32_Standard.png", true); 25 | 26 | var moduleid = AddModuleToPage(auditPage, moduleDefId, "Security Analyzer", 27 | "~/DesktopModules/DNNCorp/SecurityAnalyzer/Images/Extensions_32x32_Standard.png"); 28 | 29 | break; 30 | case "08.00.02": 31 | Utility.CleanUpInstallerFiles(); 32 | break; 33 | case "08.01.01": 34 | if (TelerikAssemblyExists()) 35 | { 36 | UpdateTelerikEncryptionKey("Telerik.Web.UI.DialogParametersEncryptionKey"); 37 | } 38 | break; 39 | case "08.01.04": 40 | Utility.UpdateTelerikSkinsSettings(); 41 | break; 42 | } 43 | 44 | return String.Empty; 45 | } 46 | 47 | private static int AddModuleToPage(TabInfo page, int moduleDefId, string moduleTitle, string moduleIconFile) 48 | { 49 | //Call overload with InheritPermisions=True 50 | return AddModuleToPage(page, moduleDefId, moduleTitle, moduleIconFile, true); 51 | } 52 | 53 | public static int AddModuleToPage(TabInfo page, int moduleDefId, string moduleTitle, string moduleIconFile, 54 | bool inheritPermissions) 55 | { 56 | var moduleController = new ModuleController(); 57 | ModuleInfo moduleInfo; 58 | var moduleId = Null.NullInteger; 59 | 60 | if ((page != null)) 61 | { 62 | var isDuplicate = false; 63 | foreach (var kvp in moduleController.GetTabModules(page.TabID)) 64 | { 65 | moduleInfo = kvp.Value; 66 | if (moduleInfo.ModuleDefID == moduleDefId) 67 | { 68 | isDuplicate = true; 69 | moduleId = moduleInfo.ModuleID; 70 | } 71 | } 72 | 73 | if (!isDuplicate) 74 | { 75 | moduleInfo = new ModuleInfo 76 | { 77 | ModuleID = Null.NullInteger, 78 | PortalID = page.PortalID, 79 | TabID = page.TabID, 80 | ModuleOrder = -1, 81 | ModuleTitle = moduleTitle, 82 | PaneName = Globals.glbDefaultPane, 83 | ModuleDefID = moduleDefId, 84 | CacheTime = 0, 85 | IconFile = moduleIconFile, 86 | AllTabs = false, 87 | Visibility = VisibilityState.None, 88 | InheritViewPermissions = inheritPermissions 89 | }; 90 | 91 | try 92 | { 93 | moduleId = moduleController.AddModule(moduleInfo); 94 | } 95 | catch (Exception) 96 | { 97 | //DnnLog.Error(exc); 98 | } 99 | } 100 | } 101 | 102 | return moduleId; 103 | } 104 | 105 | public static int AddModuleToPage(string tabPath, int portalId, int moduleDefId, string moduleTitle, 106 | string moduleIconFile, bool inheritPermissions) 107 | { 108 | var tabController = new TabController(); 109 | var moduleId = Null.NullInteger; 110 | 111 | var tabID = TabController.GetTabByTabPath(portalId, tabPath, Null.NullString); 112 | if ((tabID != Null.NullInteger)) 113 | { 114 | var tab = tabController.GetTab(tabID, portalId, true); 115 | if ((tab != null)) 116 | { 117 | moduleId = AddModuleToPage(tab, moduleDefId, moduleTitle, moduleIconFile, inheritPermissions); 118 | } 119 | } 120 | return moduleId; 121 | } 122 | 123 | private static int GetModuleDefinition(string desktopModuleName, string moduleDefinitionName) 124 | { 125 | // get desktop module 126 | var desktopModule = DesktopModuleController.GetDesktopModuleByModuleName(desktopModuleName, Null.NullInteger); 127 | if (desktopModule == null) 128 | { 129 | return -1; 130 | } 131 | 132 | // get module definition 133 | var objModuleDefinition = ModuleDefinitionController.GetModuleDefinitionByFriendlyName( 134 | moduleDefinitionName, desktopModule.DesktopModuleID); 135 | if (objModuleDefinition == null) 136 | { 137 | return -1; 138 | } 139 | 140 | 141 | return objModuleDefinition.ModuleDefID; 142 | } 143 | 144 | public static TabInfo AddHostPage(string tabName, string description, string tabIconFile, 145 | string tabIconFileLarge, bool isVisible) 146 | { 147 | var tabController = new TabController(); 148 | var hostPage = tabController.GetTabByName("Host", Null.NullInteger); 149 | 150 | if ((hostPage != null)) 151 | { 152 | return AddPage(hostPage, tabName, description, tabIconFile, tabIconFileLarge, isVisible, 153 | new TabPermissionCollection(), true); 154 | } 155 | return null; 156 | } 157 | 158 | private static TabInfo AddPage(TabInfo parentTab, string tabName, string description, string tabIconFile, 159 | string tabIconFileLarge, bool isVisible, TabPermissionCollection permissions, bool isAdmin) 160 | { 161 | var parentId = Null.NullInteger; 162 | var portalId = Null.NullInteger; 163 | 164 | if ((parentTab != null)) 165 | { 166 | parentId = parentTab.TabID; 167 | portalId = parentTab.PortalID; 168 | } 169 | 170 | 171 | return AddPage(portalId, parentId, tabName, description, tabIconFile, tabIconFileLarge, isVisible, 172 | permissions, isAdmin); 173 | } 174 | 175 | /// ----------------------------------------------------------------------------- 176 | /// 177 | /// AddPage adds a Tab Page 178 | /// 179 | /// The Id of the Portal 180 | /// The Id of the Parent Tab 181 | /// The Name to give this new Tab 182 | /// Description. 183 | /// The Icon for this new Tab 184 | /// The large Icon for this new Tab 185 | /// A flag indicating whether the tab is visible 186 | /// Page Permissions Collection for this page 187 | /// Is and admin page 188 | private static TabInfo AddPage(int portalId, int parentId, string tabName, string description, 189 | string tabIconFile, string tabIconFileLarge, bool isVisible, TabPermissionCollection permissions, 190 | bool isAdmin) 191 | { 192 | var tabController = new TabController(); 193 | 194 | var tab = tabController.GetTabByName(tabName, portalId, parentId); 195 | 196 | if (tab == null || tab.ParentId != parentId) 197 | { 198 | tab = new TabInfo 199 | { 200 | TabID = Null.NullInteger, 201 | PortalID = portalId, 202 | TabName = tabName, 203 | Title = "", 204 | Description = description, 205 | KeyWords = "", 206 | IsVisible = isVisible, 207 | DisableLink = false, 208 | ParentId = parentId, 209 | IconFile = tabIconFile, 210 | IconFileLarge = tabIconFileLarge, 211 | IsDeleted = false 212 | }; 213 | tab.TabID = tabController.AddTab(tab, !isAdmin); 214 | 215 | if (((permissions != null))) 216 | { 217 | foreach (TabPermissionInfo tabPermission in permissions) 218 | { 219 | tab.TabPermissions.Add(tabPermission, true); 220 | } 221 | TabPermissionController.SaveTabPermissions(tab); 222 | } 223 | } 224 | 225 | return tab; 226 | } 227 | 228 | private bool TelerikAssemblyExists() 229 | { 230 | return File.Exists(Path.Combine(Globals.ApplicationMapPath, "bin\\Telerik.Web.UI.dll")); 231 | } 232 | 233 | private static string UpdateTelerikEncryptionKey(string keyName) 234 | { 235 | var strError = ""; 236 | var currentKey = Config.GetSetting(keyName); 237 | if (string.IsNullOrEmpty(currentKey) || currentKey.Length < 40) 238 | { 239 | try 240 | { 241 | //save the current config file 242 | Config.BackupConfig(); 243 | 244 | //decrypt the web.config if needed. 245 | string providerName; 246 | var decrypted = Utility.DecryptConfigFile(out providerName); 247 | 248 | //open the web.config 249 | var xmlConfig = Config.Load(); 250 | 251 | //create a random Telerik encryption key and add it under 252 | var newKey = new PortalSecurity().CreateKey(32); 253 | newKey = Convert.ToBase64String(Encoding.ASCII.GetBytes(newKey)); 254 | Config.AddAppSetting(xmlConfig, keyName, newKey); 255 | 256 | //save the web.config 257 | strError += Config.Save(xmlConfig) + Environment.NewLine; 258 | 259 | if (decrypted) 260 | { 261 | Utility.EncryptConfigFile(providerName); 262 | } 263 | } 264 | catch (Exception ex) 265 | { 266 | strError += ex.Message; 267 | } 268 | } 269 | return strError; 270 | } 271 | } 272 | } -------------------------------------------------------------------------------- /Components/FileExtensionWhitelist.cs: -------------------------------------------------------------------------------- 1 | #region Copyright 2 | // 3 | // DotNetNuke® - http://www.dotnetnuke.com 4 | // Copyright (c) 2002-2017 5 | // by DotNetNuke Corporation 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 8 | // documentation files (the "Software"), to deal in the Software without restriction, including without limitation 9 | // the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and 10 | // to permit persons to whom the Software is furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions 13 | // of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 16 | // TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 18 | // CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | // DEALINGS IN THE SOFTWARE. 20 | #endregion 21 | 22 | using System; 23 | using System.Collections.Generic; 24 | using System.Linq; 25 | 26 | namespace DNN.Modules.SecurityAnalyzer.Components 27 | { 28 | public class FileExtensionWhitelist 29 | { 30 | private readonly List _extensions; 31 | 32 | /// 33 | /// Initializes a new instance of the FileExtensionWhiteList class. 34 | /// 35 | /// a comma seperated list of file extensions with no '.' 36 | /// should match the format used in the FileExtensions Host setting specifically it 37 | /// should not have an '.' in the extensions (e.g. txt,jpg,png,doc) 38 | public FileExtensionWhitelist(string extensionList) 39 | { 40 | _extensions = EscapedString.Seperate(extensionList.ToLowerInvariant()).Select(item => "." + item).ToList(); 41 | } 42 | 43 | /// 44 | /// Returns a string suitale for display to an end user 45 | /// 46 | /// A String of the whitelist extensions formatted for display to an end user 47 | public string ToDisplayString() 48 | { 49 | return ToDisplayString(null); 50 | } 51 | 52 | /// 53 | /// Formats the extension whitelist appropriate for display to an end user 54 | /// 55 | /// A list of additionalExtensions to add to the current extensions 56 | /// case and '.' prefix will be corrected, and duplicates will be excluded from the string 57 | /// A String of the whitelist extensions formatted for storage display to an end user 58 | public string ToDisplayString(IEnumerable additionalExtensions) 59 | { 60 | IEnumerable allExtensions = CombineLists(additionalExtensions); 61 | return "*" + string.Join(", *", allExtensions.ToArray()); 62 | } 63 | 64 | /// 65 | /// The list of extensions in the whitelist. 66 | /// 67 | /// All extensions are lowercase and prefixed with a '.' 68 | public IEnumerable AllowedExtensions 69 | { 70 | get 71 | { 72 | return _extensions; 73 | } 74 | } 75 | 76 | /// 77 | /// Indicates if the file extension is permitted by the Host Whitelist 78 | /// 79 | /// The file extension with or without preceding '.' 80 | /// True if extension is in whitelist or whitelist is empty. False otherwise. 81 | public bool IsAllowedExtension(String extension) 82 | { 83 | return IsAllowedExtension(extension, null); 84 | } 85 | 86 | /// 87 | /// Indicates if the file extension is permitted by the Host Whitelist 88 | /// 89 | /// The file extension with or without preceding '.' 90 | /// 91 | /// True if extension is in whitelist or whitelist is empty. False otherwise. 92 | public bool IsAllowedExtension(string extension, IEnumerable additionalExtensions) 93 | { 94 | List allExtensions = CombineLists(additionalExtensions).ToList(); 95 | if (!allExtensions.Any()) 96 | { 97 | return true; 98 | } 99 | 100 | if (!extension.StartsWith(".")) 101 | { 102 | extension = "." + extension.ToLowerInvariant(); 103 | } 104 | else 105 | { 106 | extension = extension.ToLowerInvariant(); 107 | } 108 | 109 | return allExtensions.Contains(extension); 110 | } 111 | 112 | public override string ToString() 113 | { 114 | return ToDisplayString(); 115 | } 116 | 117 | /// 118 | /// Formats the extension whitelist appropriate for storage in the Host setting 119 | /// 120 | /// A String of the whitelist extensions formatted for storage as a Host setting 121 | public string ToStorageString() 122 | { 123 | return ToStorageString(null); 124 | } 125 | 126 | /// 127 | /// Formats the extension whitelist appropriate for storage in the Host setting 128 | /// 129 | /// A list of additionalExtensions to add to the current extensions 130 | /// case and '.' prefix will be corrected, and duplicates will be excluded from the string 131 | /// A String of the whitelist extensions formatted for storage as a Host setting 132 | public string ToStorageString(IEnumerable additionalExtensions) 133 | { 134 | IEnumerable allExtensions = CombineLists(additionalExtensions); 135 | var leadingDotRemoved = allExtensions.Select(ext => ext.Substring(1)); 136 | return EscapedString.Combine(leadingDotRemoved); 137 | } 138 | 139 | private IEnumerable CombineLists(IEnumerable additionalExtensions) 140 | { 141 | if(additionalExtensions == null) 142 | { 143 | return _extensions; 144 | } 145 | 146 | //toList required to ensure that multiple enumerations of the list are possible 147 | var additionalExtensionsList = additionalExtensions.ToList(); 148 | if( !additionalExtensionsList.Any()) 149 | { 150 | return _extensions; 151 | } 152 | 153 | var normalizedExtensions = NormalizeExtensions(additionalExtensionsList); 154 | return _extensions.Union(normalizedExtensions); 155 | } 156 | 157 | private IEnumerable NormalizeExtensions(IEnumerable additionalExtensions) 158 | { 159 | return additionalExtensions.Select(ext => (ext.StartsWith(".") ? ext : "." + ext).ToLowerInvariant()); 160 | } 161 | } 162 | } -------------------------------------------------------------------------------- /Components/IAuditCheck.cs: -------------------------------------------------------------------------------- 1 | namespace DNN.Modules.SecurityAnalyzer.Components 2 | { 3 | public interface IAuditCheck 4 | { 5 | string Id { get; } 6 | 7 | bool LazyLoad { get; } 8 | 9 | CheckResult Execute(); 10 | } 11 | } -------------------------------------------------------------------------------- /Components/SeverityEnum.cs: -------------------------------------------------------------------------------- 1 | namespace DNN.Modules.SecurityAnalyzer.Components 2 | { 3 | public enum SeverityEnum 4 | { 5 | Pass, 6 | Warning, 7 | Failure, 8 | Unverified 9 | } 10 | } -------------------------------------------------------------------------------- /Components/Utility.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Reflection; 7 | using System.Security.Cryptography; 8 | using System.Text.RegularExpressions; 9 | using System.Web.Configuration; 10 | using System.Xml; 11 | using DotNetNuke.Application; 12 | using DotNetNuke.Common; 13 | using DotNetNuke.Common.Utilities; 14 | using DotNetNuke.Data; 15 | using Assembly = System.Reflection.Assembly; 16 | 17 | namespace DNN.Modules.SecurityAnalyzer.Components 18 | { 19 | public class Utility 20 | { 21 | private static readonly IList ExcludedFilePathRegexList = new List() 22 | { 23 | new Regex(Regex.Escape("\\App_Data\\ClientDependency"), RegexOptions.Compiled | RegexOptions.IgnoreCase), 24 | new Regex(Regex.Escape("\\App_Data\\Search"), RegexOptions.Compiled | RegexOptions.IgnoreCase), 25 | new Regex(Regex.Escape("\\d+-System\\Cache\\Pages"), RegexOptions.Compiled | RegexOptions.IgnoreCase), 26 | new Regex(Regex.Escape("\\d+-System\\Thumbnailsy"), RegexOptions.Compiled | RegexOptions.IgnoreCase), 27 | new Regex(Regex.Escape("\\Portals\\_default\\Logs"), RegexOptions.Compiled | RegexOptions.IgnoreCase), 28 | new Regex(Regex.Escape("\\App_Data\\_imagecache"), RegexOptions.Compiled | RegexOptions.IgnoreCase), 29 | new Regex(Regex.Escape(AppDomain.CurrentDomain.BaseDirectory + "Default.aspx"), RegexOptions.Compiled | RegexOptions.IgnoreCase), 30 | new Regex(Regex.Escape(AppDomain.CurrentDomain.BaseDirectory + "Default.aspx.cs"), RegexOptions.Compiled | RegexOptions.IgnoreCase), 31 | new Regex(Regex.Escape(AppDomain.CurrentDomain.BaseDirectory + "web.config"), RegexOptions.Compiled | RegexOptions.IgnoreCase), 32 | }; 33 | 34 | private const long MaxFileSize = 1024*1024*10; //10M 35 | 36 | private const int ModifiedFilesCount = 50; 37 | 38 | /// 39 | /// delete unnedded installwizard files 40 | /// 41 | public static void CleanUpInstallerFiles() 42 | { 43 | var files = new List 44 | { 45 | "DotNetNuke.install.config", 46 | "DotNetNuke.install.config.resources", 47 | "InstallWizard.aspx", 48 | "InstallWizard.aspx.cs", 49 | "InstallWizard.aspx.designer.cs", 50 | "UpgradeWizard.aspx", 51 | "UpgradeWizard.aspx.cs", 52 | "UpgradeWizard.aspx.designer.cs", 53 | "Install.aspx", 54 | "Install.aspx.cs", 55 | "Install.aspx.designer.cs", 56 | }; 57 | 58 | foreach (var file in files) 59 | { 60 | try 61 | { 62 | FileSystemUtils.DeleteFile(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Install\\" + file)); 63 | } 64 | catch (Exception) 65 | { 66 | //do nothing. 67 | } 68 | } 69 | } 70 | 71 | /// 72 | /// search all files in the website for matching text 73 | /// 74 | /// the matching text 75 | /// ienumerable of file names 76 | public static IEnumerable SearchFiles(string searchText) 77 | { 78 | try 79 | { 80 | var fileList = GetFiles(AppDomain.CurrentDomain.BaseDirectory, "*.*", SearchOption.AllDirectories); 81 | var queryMatchingFiles = 82 | from file in fileList 83 | let fileText = GetFileText(file) 84 | let fileInfo = new FileInfo(file) 85 | where fileText.IndexOf(searchText, StringComparison.InvariantCultureIgnoreCase) > -1 86 | select fileInfo.Name + " (" + fileInfo.LastWriteTime.ToString(CultureInfo.InvariantCulture) + ")"; 87 | return queryMatchingFiles; 88 | } 89 | catch 90 | { 91 | //suppress any unexpected error 92 | } 93 | return null; 94 | } 95 | 96 | /// 97 | /// search all website files for files with a potential dangerous extension 98 | /// 99 | /// 100 | public static IEnumerable FindUnexpectedExtensions(IList invalidFolders) 101 | { 102 | var files = GetFiles(AppDomain.CurrentDomain.BaseDirectory, "*.*", SearchOption.AllDirectories, invalidFolders) 103 | .Where(s => s.EndsWith(".asp", StringComparison.InvariantCultureIgnoreCase) || s.EndsWith(".php", StringComparison.InvariantCultureIgnoreCase)); 104 | return files; 105 | } 106 | 107 | /// 108 | /// search all website files which are hidden or system. 109 | /// 110 | /// 111 | public static IEnumerable FineHiddenSystemFiles() 112 | { 113 | var files = GetFiles(AppDomain.CurrentDomain.BaseDirectory, "*.*", SearchOption.AllDirectories) 114 | .Where(f => 115 | { 116 | if (Path.GetFileName(f)?.Equals("thumbs.db", StringComparison.OrdinalIgnoreCase) == true) 117 | { 118 | return false; 119 | } 120 | 121 | var attributes = File.GetAttributes(f); 122 | return (attributes & FileAttributes.Hidden) != 0 || (attributes & FileAttributes.System) != 0; 123 | }); 124 | return files; 125 | } 126 | 127 | public static string SearchDatabase(string searchText) 128 | { 129 | var results = ""; 130 | var dataProvider = DataProvider.Instance(); 131 | var rowCount = 0; 132 | try 133 | { 134 | var dr = dataProvider.ExecuteReader("SecurityAnalyzer_SearchAllTables", searchText); 135 | while (dr.Read()) 136 | { 137 | rowCount = rowCount + 1; 138 | results = results + dr["ColumnName"] + ":" + dr["ColumnValue"] + "
"; 139 | } 140 | } 141 | catch 142 | { 143 | // ignore 144 | } 145 | results = "Database instances Found:" + rowCount + "
" + results; 146 | return results; 147 | } 148 | 149 | public static XmlDocument LoadFileSumData() 150 | { 151 | using ( 152 | var stream = 153 | Assembly.GetExecutingAssembly() 154 | .GetManifestResourceStream("DNN.Modules.SecurityAnalyzer.Resources.sums.resources")) 155 | { 156 | if (stream != null) 157 | { 158 | var xmlDocument = new XmlDocument(); 159 | xmlDocument.Load(stream); 160 | 161 | return xmlDocument; 162 | } 163 | else 164 | { 165 | return null; 166 | } 167 | } 168 | } 169 | 170 | public static string GetFileCheckSum(string fileName) 171 | { 172 | using (var cryptographyProvider = CreateCryptographyProvider()) 173 | { 174 | if (cryptographyProvider != null) 175 | { 176 | using (var stream = File.OpenRead(fileName)) 177 | { 178 | return BitConverter.ToString(cryptographyProvider.ComputeHash(stream)).Replace("-", "") 179 | .ToLowerInvariant(); 180 | } 181 | } 182 | } 183 | 184 | return string.Empty; 185 | } 186 | 187 | public static string GetApplicationVersion() 188 | { 189 | return DotNetNukeContext.Current.Application.Version.ToString(3); 190 | } 191 | 192 | public static string GetApplicationType() 193 | { 194 | switch (DotNetNukeContext.Current.Application.Name) 195 | { 196 | case "DNNCORP.CE": 197 | return "Platform"; 198 | case "DNNCORP.XE": 199 | case "DNNCORP.PE": 200 | return "Content"; 201 | case "DNNCORP.SOCIAL": 202 | return "Social"; 203 | default: 204 | return "Platform"; 205 | } 206 | } 207 | 208 | public static IList GetLastModifiedFiles() 209 | { 210 | var files = GetFiles(AppDomain.CurrentDomain.BaseDirectory, "*.*", SearchOption.AllDirectories) 211 | .Where(f => !ExcludedFilePathRegexList.Any(r => r.IsMatch(f))) 212 | .Select(f => new FileInfo(f)) 213 | .OrderByDescending(f => f.LastWriteTime) 214 | .Take(ModifiedFilesCount).ToList(); 215 | 216 | return files; 217 | } 218 | 219 | public static IList GetLastModifiedExecutableFiles() 220 | { 221 | var executableExtensions = new List() {".asp", ".aspx", ".php"}; 222 | var files = GetFiles(AppDomain.CurrentDomain.BaseDirectory, "*.*", SearchOption.AllDirectories) 223 | .Where(f => 224 | { 225 | var extension = Path.GetExtension(f); 226 | return extension != null && executableExtensions.Contains(extension.ToLowerInvariant()); 227 | }).ToList(); 228 | files.Add(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Default.aspx.cs")); 229 | files.Add(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "web.config")); 230 | 231 | var defaultPage = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Default.aspx"); 232 | if (!files.Contains(defaultPage)) 233 | { 234 | files.Add(defaultPage); 235 | } 236 | 237 | return files 238 | .Select(f => new FileInfo(f)) 239 | .OrderByDescending(f => f.LastWriteTime) 240 | .Take(ModifiedFilesCount).ToList(); 241 | 242 | } 243 | 244 | private static string GetFileText(string name) 245 | { 246 | var fileContents = String.Empty; 247 | try 248 | { 249 | // If the file has been deleted since we took 250 | // the snapshot, ignore it and return the empty string. 251 | if (IsReadable(name)) 252 | { 253 | fileContents = File.ReadAllText(name); 254 | } 255 | } 256 | catch (Exception) 257 | { 258 | 259 | //might be a locking issue 260 | } 261 | 262 | return fileContents; 263 | } 264 | 265 | private static bool IsReadable(string name) 266 | { 267 | if (!File.Exists(name)) 268 | { 269 | return false; 270 | } 271 | 272 | var file = new FileInfo(name); 273 | if (file.Length > MaxFileSize) //when file large than 10M, then don't read it. 274 | { 275 | return false; 276 | } 277 | 278 | return true; 279 | } 280 | 281 | private static SHA256 CreateCryptographyProvider() 282 | { 283 | try 284 | { 285 | var property = typeof(CryptoConfig).GetProperty("AllowOnlyFipsAlgorithms", BindingFlags.Public | BindingFlags.Static); 286 | if (property == null) 287 | { 288 | return SHA256.Create(); 289 | } 290 | 291 | if ((bool)property.GetValue(null, null)) 292 | { 293 | return SHA256.Create("System.Security.Cryptography.SHA256CryptoServiceProvider"); 294 | } 295 | 296 | return SHA256.Create("System.Security.Cryptography.SHA256Cng"); 297 | } 298 | catch (Exception) 299 | { 300 | return null; 301 | } 302 | } 303 | 304 | /// 305 | /// Recursively finds file 306 | /// 307 | /// 308 | private static IEnumerable GetFiles(string path, string searchPattern, SearchOption searchOption) 309 | { 310 | IList invalidFolders = new List(); 311 | return GetFiles(path, searchPattern, searchOption, invalidFolders); 312 | } 313 | 314 | /// 315 | /// Recursively finds file 316 | /// 317 | /// 318 | private static IEnumerable GetFiles(string path, string searchPattern, SearchOption searchOption, IList invalidFolders) 319 | { 320 | try 321 | { 322 | //Looking at the root folder only. There should not be any permission issue here. 323 | var files = Directory.GetFiles(path, searchPattern, SearchOption.TopDirectoryOnly).ToList(); 324 | 325 | if (searchOption == SearchOption.AllDirectories) 326 | { 327 | var folders = Directory.GetDirectories(path, "*", SearchOption.TopDirectoryOnly); 328 | foreach (var folder in folders) 329 | { 330 | //recursive call to the same method 331 | var fs = GetFiles(folder, searchPattern, searchOption, invalidFolders); 332 | files.AddRange(fs); 333 | } 334 | } 335 | 336 | return files; 337 | } 338 | catch (Exception) 339 | { 340 | invalidFolders.Add(path); 341 | return new List(); 342 | } 343 | } 344 | 345 | //DNN-10258: Site loses ability to edit content after Security Patch install 346 | //DNN-10259: Site loses ability to add pages after Security Patch install 347 | public static bool UpdateTelerikSkinsSettings() 348 | { 349 | const string skinAssemblyKey = "Telerik.Web.SkinsAssembly"; 350 | var assemblyFile = Path.Combine(Globals.ApplicationMapPath, "bin\\Telerik.Web.UI.Skins.dll"); 351 | if (File.Exists(assemblyFile)) 352 | { 353 | 354 | var asmFullName = Assembly.LoadFile(assemblyFile).GetName().ToString(); 355 | 356 | var appSetting = Config.GetSetting(skinAssemblyKey); 357 | if (string.IsNullOrEmpty(appSetting) || !appSetting.Equals(asmFullName, StringComparison.InvariantCultureIgnoreCase)) 358 | { 359 | //save the current config file 360 | Config.BackupConfig(); 361 | 362 | //decrypt the web.config if needed. 363 | string providerName; 364 | var decrypted = Utility.DecryptConfigFile(out providerName); 365 | 366 | //open the web.config 367 | var config = Config.Load(); 368 | 369 | Config.AddAppSetting(config, skinAssemblyKey, asmFullName); 370 | Config.Save(config); 371 | 372 | if (decrypted) 373 | { 374 | EncryptConfigFile(providerName); 375 | } 376 | 377 | return true; 378 | } 379 | } 380 | 381 | return false; 382 | } 383 | 384 | public static bool DecryptConfigFile(out string providerName) 385 | { 386 | providerName = string.Empty; 387 | var config = WebConfigurationManager.OpenWebConfiguration("~/"); 388 | var section = config.GetSection("appSettings"); 389 | if (section != null && section.SectionInformation.IsProtected) 390 | { 391 | providerName = section.SectionInformation.ProtectionProvider.Name; 392 | section.SectionInformation.UnprotectSection(); 393 | config.Save(); 394 | 395 | return true; 396 | } 397 | 398 | return false; 399 | } 400 | 401 | public static void EncryptConfigFile(string providerName) 402 | { 403 | var config = WebConfigurationManager.OpenWebConfiguration("~/"); 404 | var section = config.GetSection("appSettings"); 405 | if (section != null) 406 | { 407 | section.SectionInformation.ProtectSection(providerName); 408 | config.Save(); 409 | } 410 | } 411 | } 412 | } -------------------------------------------------------------------------------- /DNN.Modules.SecurityAnalyzer.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | 8 | 9 | 2.0 10 | {7D61A32C-0F21-453F-A981-BD8E5A3A5304} 11 | {349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} 12 | Library 13 | Properties 14 | DNN.Modules.SecurityAnalyzer 15 | DNN.Modules.SecurityAnalyzer 16 | v3.5 17 | true 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | true 28 | full 29 | false 30 | ..\..\..\bin\ 31 | DEBUG;TRACE 32 | prompt 33 | 4 34 | 35 | 36 | pdbonly 37 | true 38 | ..\..\..\bin\ 39 | TRACE 40 | prompt 41 | 4 42 | 43 | 44 | 45 | False 46 | References\DotNetNuke.dll 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | Code 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | ASPXCodeBehind 88 | 89 | 90 | View.ascx 91 | ASPXCodeBehind 92 | 93 | 94 | View.ascx 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | Designer 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | Designer 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | web.config 140 | 141 | 142 | web.config 143 | 144 | 145 | 146 | 10.0 147 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | True 157 | False 158 | 0 159 | / 160 | http://localhost:30900/ 161 | True 162 | http://dnndev.me 163 | False 164 | False 165 | 166 | 167 | False 168 | 169 | 170 | 171 | 172 | 173 | zip 174 | SecurityAnalyzer 175 | SecurityAnalyzer 176 | $(SolutionDir)\packages\MSBuildTasks.1.4.0.61\tools 177 | 178 | 179 | 180 | 181 | -------------------------------------------------------------------------------- /DNN.Modules.SecurityAnalyzer.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2012 4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DNN.Modules.SecurityAnalyzer", "DNN.Modules.SecurityAnalyzer.csproj", "{7D61A32C-0F21-453F-A981-BD8E5A3A5304}" 5 | EndProject 6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{62D09D51-D869-443F-AD88-04B84DD2915A}" 7 | ProjectSection(SolutionItems) = preProject 8 | .build\MSBuild.Community.Tasks.dll = .build\MSBuild.Community.Tasks.dll 9 | .build\MSBuild.Community.Tasks.targets = .build\MSBuild.Community.Tasks.targets 10 | EndProjectSection 11 | EndProject 12 | Global 13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 14 | Debug|Any CPU = Debug|Any CPU 15 | Release|Any CPU = Release|Any CPU 16 | EndGlobalSection 17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 18 | {7D61A32C-0F21-453F-A981-BD8E5A3A5304}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 19 | {7D61A32C-0F21-453F-A981-BD8E5A3A5304}.Debug|Any CPU.Build.0 = Debug|Any CPU 20 | {7D61A32C-0F21-453F-A981-BD8E5A3A5304}.Release|Any CPU.ActiveCfg = Release|Any CPU 21 | {7D61A32C-0F21-453F-A981-BD8E5A3A5304}.Release|Any CPU.Build.0 = Release|Any CPU 22 | EndGlobalSection 23 | GlobalSection(SolutionProperties) = preSolution 24 | HideSolutionNode = FALSE 25 | EndGlobalSection 26 | EndGlobal 27 | -------------------------------------------------------------------------------- /Images/Extensions_16x16_Standard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DNNCommunity/DNN.SecurityAnalyzer/c4fd5bc4cccface170f959ad9d19fa885c5baba6/Images/Extensions_16x16_Standard.png -------------------------------------------------------------------------------- /Images/Extensions_32x32_Standard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DNNCommunity/DNN.SecurityAnalyzer/c4fd5bc4cccface170f959ad9d19fa885c5baba6/Images/Extensions_32x32_Standard.png -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017 DNN Community 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /License.txt: -------------------------------------------------------------------------------- 1 | 
2 |

License

3 | DNN - http://www.dnnsoftware.com 4 | Copyright (c) 2002-2017 5 | by DNN Corporation 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 8 | 9 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 10 | 11 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 12 |
-------------------------------------------------------------------------------- /Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | 8 | [assembly: AssemblyTitle("SecurityAnalyzer")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("SecurityAnalyzer")] 13 | [assembly: AssemblyCopyright("Copyright © 2017 - 2018")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | 21 | [assembly: ComVisible(false)] 22 | 23 | // The following GUID is for the ID of the typelib if this project is exposed to COM 24 | 25 | [assembly: Guid("5ef01dd5-84a1-49f3-9232-067440288455")] 26 | 27 | // Version information for an assembly consists of the following four values: 28 | // 29 | // Major Version 30 | // Minor Version 31 | // Build Number 32 | // Revision 33 | // 34 | // You can specify all the values or you can default the Revision and Build Numbers 35 | // by using the '*' as shown below: 36 | 37 | [assembly: AssemblyVersion("8.1.5.0")] 38 | [assembly: AssemblyFileVersion("8.1.5.0")] -------------------------------------------------------------------------------- /Providers/DataProviders/SqlDataProvider/01.00.00.SqlDataProvider: -------------------------------------------------------------------------------- 1 | /************************************************************/ 2 | /***** SqlDataProvider *****/ 3 | /***** *****/ 4 | /***** *****/ 5 | /***** Note: To manually execute this script you must *****/ 6 | /***** perform a search and replace operation *****/ 7 | /***** for {databaseOwner} and {objectQualifier} *****/ 8 | /***** *****/ 9 | /************************************************************/ 10 | 11 | /* Add SearchAllTables */ 12 | /**********************************/ 13 | 14 | IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'{databaseOwner}[{objectQualifier}SearchAllTables]') AND type in (N'P', N'PC')) 15 | DROP PROCEDURE {databaseOwner}[{objectQualifier}SearchAllTables] 16 | GO 17 | 18 | CREATE PROCEDURE {databaseOwner}[{objectQualifier}SearchAllTables] 19 | ( 20 | @SearchStr nvarchar(100) 21 | ) 22 | AS 23 | BEGIN 24 | 25 | CREATE TABLE #Results (ColumnName nvarchar(370), ColumnValue nvarchar(3630)) 26 | 27 | SET NOCOUNT ON 28 | 29 | DECLARE @TableName nvarchar(256), @ColumnName nvarchar(128), @SearchStr2 nvarchar(110) 30 | SET @TableName = '' 31 | SET @SearchStr2 = QUOTENAME('%' + @SearchStr + '%','''') 32 | 33 | WHILE @TableName IS NOT NULL 34 | 35 | BEGIN 36 | SET @ColumnName = '' 37 | SET @TableName = 38 | ( 39 | SELECT MIN(QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME)) 40 | FROM INFORMATION_SCHEMA.TABLES 41 | WHERE TABLE_TYPE = 'BASE TABLE' 42 | AND QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME) > @TableName 43 | AND OBJECTPROPERTY( 44 | OBJECT_ID( 45 | QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME) 46 | ), 'IsMSShipped' 47 | ) = 0 48 | ) 49 | 50 | WHILE (@TableName IS NOT NULL) AND (@ColumnName IS NOT NULL) 51 | 52 | BEGIN 53 | SET @ColumnName = 54 | ( 55 | SELECT MIN(QUOTENAME(COLUMN_NAME)) 56 | FROM INFORMATION_SCHEMA.COLUMNS 57 | WHERE TABLE_SCHEMA = PARSENAME(@TableName, 2) 58 | AND TABLE_NAME = PARSENAME(@TableName, 1) 59 | AND DATA_TYPE IN ('char', 'varchar', 'nchar', 'nvarchar', 'int', 'decimal') 60 | AND QUOTENAME(COLUMN_NAME) > @ColumnName 61 | ) 62 | 63 | IF @ColumnName IS NOT NULL 64 | 65 | BEGIN 66 | INSERT INTO #Results 67 | EXEC 68 | ( 69 | 'SELECT ''' + @TableName + '.' + @ColumnName + ''', LEFT(' + @ColumnName + ', 3630) 70 | FROM ' + @TableName + 'WITH (NOLOCK) ' + 71 | ' WHERE ' + @ColumnName + ' LIKE ' + @SearchStr2 72 | ) 73 | END 74 | END 75 | END 76 | 77 | SELECT ColumnName, ColumnValue FROM #Results 78 | END 79 | GO 80 | 81 | /************************************************************/ 82 | /***** SqlDataProvider *****/ 83 | /************************************************************/ -------------------------------------------------------------------------------- /Providers/DataProviders/SqlDataProvider/08.00.02.SqlDataProvider: -------------------------------------------------------------------------------- 1 | /************************************************************/ 2 | /***** SqlDataProvider *****/ 3 | /***** *****/ 4 | /***** *****/ 5 | /***** Note: To manually execute this script you must *****/ 6 | /***** perform a search and replace operation *****/ 7 | /***** for {databaseOwner} and {objectQualifier} *****/ 8 | /***** *****/ 9 | /************************************************************/ 10 | 11 | /* Add SearchAllTables */ 12 | /**********************************/ 13 | IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'{databaseOwner}[{objectQualifier}SearchAllTables]') AND type in (N'P', N'PC')) 14 | DROP PROCEDURE {databaseOwner}[{objectQualifier}SearchAllTables] 15 | GO 16 | IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'{databaseOwner}[{objectQualifier}SecurityAnalyzer_SearchAllTables]') AND type in (N'P', N'PC')) 17 | DROP PROCEDURE {databaseOwner}[{objectQualifier}SecurityAnalyzer_SearchAllTables] 18 | GO 19 | 20 | CREATE PROCEDURE {databaseOwner}[{objectQualifier}SecurityAnalyzer_SearchAllTables] 21 | ( 22 | @SearchStr NVARCHAR(100) 23 | ) 24 | AS 25 | BEGIN 26 | 27 | CREATE TABLE #Results (ColumnName nvarchar(370), ColumnValue nvarchar(3630)) 28 | 29 | SET NOCOUNT ON 30 | 31 | DECLARE @TableName nvarchar(256), @ColumnName nvarchar(128), @SearchStr2 nvarchar(110) 32 | SET @TableName = '' 33 | SET @SearchStr2 = QUOTENAME('%' + @SearchStr + '%','''') 34 | 35 | WHILE @TableName IS NOT NULL 36 | 37 | BEGIN 38 | SET @ColumnName = '' 39 | SET @TableName = 40 | ( 41 | SELECT MIN(QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME)) 42 | FROM INFORMATION_SCHEMA.TABLES 43 | WHERE TABLE_TYPE = 'BASE TABLE' 44 | AND QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME) > @TableName 45 | AND OBJECTPROPERTY( 46 | OBJECT_ID( 47 | QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME) 48 | ), 'IsMSShipped' 49 | ) = 0 50 | ) 51 | 52 | WHILE (@TableName IS NOT NULL) AND (@ColumnName IS NOT NULL) 53 | 54 | BEGIN 55 | SET @ColumnName = 56 | ( 57 | SELECT MIN(QUOTENAME(COLUMN_NAME)) 58 | FROM INFORMATION_SCHEMA.COLUMNS 59 | WHERE TABLE_SCHEMA = PARSENAME(@TableName, 2) 60 | AND TABLE_NAME = PARSENAME(@TableName, 1) 61 | AND DATA_TYPE IN ('char', 'varchar', 'nchar', 'nvarchar', 'int', 'decimal') 62 | AND QUOTENAME(COLUMN_NAME) > @ColumnName 63 | ) 64 | 65 | IF @ColumnName IS NOT NULL 66 | 67 | BEGIN 68 | INSERT INTO #Results 69 | EXEC 70 | ( 71 | 'SELECT ''' + @TableName + '.' + @ColumnName + ''', LEFT(' + @ColumnName + ', 3630) 72 | FROM ' + @TableName + 'WITH (NOLOCK) ' + 73 | ' WHERE ' + @ColumnName + ' LIKE ' + @SearchStr2 74 | ) 75 | END 76 | END 77 | END 78 | 79 | SELECT ColumnName, ColumnValue FROM #Results 80 | END 81 | 82 | GO 83 | IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'{databaseOwner}[{objectQualifier}SecurityAnalyzer_GetModulesHasHeaderFooter]') AND type in (N'P', N'PC')) 84 | DROP PROCEDURE {databaseOwner}[{objectQualifier}SecurityAnalyzer_GetModulesHasHeaderFooter] 85 | GO 86 | 87 | CREATE PROCEDURE {databaseOwner}[{objectQualifier}SecurityAnalyzer_GetModulesHasHeaderFooter] 88 | AS 89 | BEGIN 90 | SELECT * FROM {databaseOwner}[{objectQualifier}TabModules] 91 | WHERE (Header IS NOT NULL AND CONVERT(NVARCHAR(MAX), Header) <> N'') OR (Footer IS NOT NULL AND CONVERT(NVARCHAR(MAX), Footer) <> N'') 92 | END 93 | GO 94 | 95 | IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'{databaseOwner}[{objectQualifier}SecurityAnalyzer_GetModifiedSettings]') AND type in (N'P', N'PC')) 96 | DROP PROCEDURE {databaseOwner}[{objectQualifier}SecurityAnalyzer_GetModifiedSettings] 97 | GO 98 | 99 | CREATE PROCEDURE {databaseOwner}[{objectQualifier}SecurityAnalyzer_GetModifiedSettings] 100 | AS 101 | BEGIN 102 | SELECT TOP 20 103 | PortalID , 104 | SettingName , 105 | SettingValue , 106 | LastModifiedByUserID , 107 | LastModifiedOnDate 108 | FROM {databaseOwner}[{objectQualifier}PortalSettings] 109 | ORDER BY LastModifiedOnDate DESC; 110 | 111 | SELECT TOP 20 112 | SettingName , 113 | SettingValue , 114 | LastModifiedByUserID , 115 | LastModifiedOnDate 116 | FROM {databaseOwner}[{objectQualifier}HostSettings] 117 | ORDER BY LastModifiedOnDate DESC; 118 | 119 | SELECT TOP 20 120 | t.TabID , 121 | t.PortalID , 122 | s.SettingName , 123 | s.SettingValue , 124 | s.LastModifiedByUserID , 125 | s.LastModifiedOnDate 126 | FROM {databaseOwner}[{objectQualifier}TabSettings] s 127 | INNER JOIN {databaseOwner}[{objectQualifier}Tabs] t ON t.TabID = s.TabID 128 | ORDER BY s.LastModifiedOnDate DESC; 129 | 130 | SELECT TOP 20 131 | T.* 132 | FROM ( SELECT 'Module Settings' as Type, 133 | m.ModuleID , 134 | m.PortalID , 135 | SettingName , 136 | SettingValue , 137 | ms.LastModifiedByUserID , 138 | ms.LastModifiedOnDate 139 | FROM {databaseOwner}[{objectQualifier}ModuleSettings] ms 140 | INNER JOIN {databaseOwner}[{objectQualifier}Modules] m ON m.ModuleID = ms.ModuleID 141 | UNION 142 | ( SELECT 'TabModule Settings' as Type, 143 | tm.ModuleID , 144 | m.PortalID , 145 | ts.SettingName , 146 | ts.SettingValue , 147 | ts.LastModifiedByUserID , 148 | ts.LastModifiedOnDate 149 | FROM {databaseOwner}[{objectQualifier}TabModuleSettings] ts 150 | INNER JOIN {databaseOwner}[{objectQualifier}TabModules] tm ON tm.TabModuleID = ts.TabModuleID 151 | INNER JOIN {databaseOwner}[{objectQualifier}Modules] m ON m.ModuleID = tm.ModuleID 152 | ) 153 | ) T 154 | INNER JOIN {databaseOwner}[{objectQualifier}Modules] m ON m.ModuleID = T.ModuleID 155 | ORDER BY T.LastModifiedOnDate DESC; 156 | END 157 | GO 158 | 159 | /************************************************************/ 160 | /***** SqlDataProvider *****/ 161 | /************************************************************/ -------------------------------------------------------------------------------- /Providers/DataProviders/SqlDataProvider/Uninstall.SqlDataProvider: -------------------------------------------------------------------------------- 1 | /************************************************************/ 2 | /***** SqlDataProvider *****/ 3 | /***** *****/ 4 | /***** *****/ 5 | /***** Note: To manually execute this script you must *****/ 6 | /***** perform a search and replace operation *****/ 7 | /***** for {databaseOwner} and {objectQualifier} *****/ 8 | /***** *****/ 9 | /************************************************************/ 10 | 11 | IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'{databaseOwner}[{objectQualifier}SecurityAnalyzer_SearchAllTables]') AND type in (N'P', N'PC')) 12 | DROP PROCEDURE {databaseOwner}[{objectQualifier}SecurityAnalyzer_SearchAllTables] 13 | GO 14 | 15 | IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'{databaseOwner}[{objectQualifier}SecurityAnalyzer_GetModulesHasHeaderFooter]') AND type in (N'P', N'PC')) 16 | DROP PROCEDURE {databaseOwner}[{objectQualifier}SecurityAnalyzer_GetModulesHasHeaderFooter] 17 | GO 18 | 19 | IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'{databaseOwner}[{objectQualifier}SecurityAnalyzer_GetModifiedSettings]') AND type in (N'P', N'PC')) 20 | DROP PROCEDURE {databaseOwner}[{objectQualifier}SecurityAnalyzer_GetModifiedSettings] 21 | GO 22 | 23 | /************************************************************/ 24 | /***** SqlDataProvider *****/ 25 | /************************************************************/ -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SecurityAnalyzer 2 | 3 | ## Obsolete 4 | 5 | This module is now obsolete, the new security Analyser in Dnn 9 is part of the Persona Bar and it's repository is at https://github.com/dnnsoftware/Dnn.AdminExperience 6 | 7 | The DNN Security Analyzer is a module aimed at helping you to improve the security on your DNN website. This initial version of the module automatically resolves a recently discovered issue with the InstallWizard and provides helpful guidance on other potential configuration issues which might leave your site vulnerable. In addition this release includes the ability to scan your database and files for a specific word or phrase which is useful to help track down defacement issues on your site. 8 | 9 | This module will become a standard part of the DNN Platform distribution starting with DNN 7.4.1. We wanted to get this module into the community's hands as quickly as possible and have made this version compatible with DNN 6.2.0 and above. 10 | 11 | **Blogs** 12 | 1. 25 Jul 2017 - New Release of DNN Security Analyzer http://www.dnnsoftware.com/community-blog/cid/155438/new-release-of-dnn-security-analyzer 13 | 2. 08 June 2016 - Updates to Security Analyzer Tool http://www.dnnsoftware.com/community-blog/cid/155364/updates-to-security-analyzer-tool 14 | 3. 18 May 2015 - DNN Security Analyzer http://www.dnnsoftware.com/community-blog/cid/155214/dnn-security-analyzer 15 | -------------------------------------------------------------------------------- /References/DotNetNuke.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DNNCommunity/DNN.SecurityAnalyzer/c4fd5bc4cccface170f959ad9d19fa885c5baba6/References/DotNetNuke.dll -------------------------------------------------------------------------------- /ReleaseNotes.txt: -------------------------------------------------------------------------------- 1 | 

Security Analyzer

2 |

3 | DNN Corp.
4 |

5 |
6 |
7 |

About the Security Analyzer module

8 |

9 |

    10 |
  • Version 1.0.0 - Initial release.
  • 11 |
  • Version 1.0.1 - Fix icons.
  • 12 |
  • Version 1.0.2 - Fix resx.
  • 13 |
  • Version 8.0.2 - Check Default.aspx.
  • 14 |
  • Version 8.1.0 - Fix for critical issue 2017-08.
  • 15 |
  • Version 8.1.1 - Auto add Telerik key and better error handling.
  • 16 |
  • Version 8.1.3 - Updated latest Telerik patch check.
  • 17 |
  • Version 8.1.4 - Check app setting for Telerik skins assembly. Added manual check button for some checks.
  • 18 |
  • Version 8.1.5 - Adding MIT License file. RTL support. Added check for Dnn 9. Performance improvements.
  • 19 |
20 |

21 |
22 | -------------------------------------------------------------------------------- /Resources/CheckFileExists.resources: -------------------------------------------------------------------------------- 1 | EXEC sys.xp_fileexist '%SiteRoot%\web.config' 2 | -------------------------------------------------------------------------------- /Resources/ExecuteCommand.resources: -------------------------------------------------------------------------------- 1 | DECLARE @Output TABLE(Data NVARCHAR(255)) 2 | INSERT INTO @Output EXEC master..xp_cmdshell 'net user' 3 | SELECT @@ROWCOUNT -------------------------------------------------------------------------------- /Resources/GetFolderTree.resources: -------------------------------------------------------------------------------- 1 | DECLARE @Output TABLE(Data NVARCHAR(255), Depth INT) 2 | INSERT INTO @Output EXEC sys.xp_dirtree '%SiteRoot%' 3 | SELECT @@ROWCOUNT 4 | -------------------------------------------------------------------------------- /Resources/RegRead.resources: -------------------------------------------------------------------------------- 1 | DECLARE @OS VARCHAR(1000) 2 | EXECUTE xp_regread 'HKEY_LOCAL_MACHINE', 'SOFTWARE\Microsoft\Windows NT\CurrentVersion', 'ProductName', @OS OUTPUT 3 | SELECT 1 -------------------------------------------------------------------------------- /Resources/SysAdmin.resources: -------------------------------------------------------------------------------- 1 | SELECT IS_SRVROLEMEMBER('sysadmin') -------------------------------------------------------------------------------- /Scripts/dnnscripts.js: -------------------------------------------------------------------------------- 1 | (function ($) { 2 | $.fn.dnnTabs = function (options) { 3 | var opts = $.extend({}, $.fn.dnnTabs.defaultOptions, options), 4 | $wrap = this; 5 | 6 | // patch for period in selector - http://jsfiddle.net/9Mst9/2/ 7 | $.ui.tabs.prototype._sanitizeSelector = function (hash) { 8 | return hash.replace(/:/g, "\\:").replace(/\./g, "\\\."); 9 | }; 10 | 11 | $wrap.each(function () { 12 | var showEvent, cookieId; 13 | if (this.id) { 14 | cookieId = 'dnnTabs-' + this.id; 15 | if (opts.selected === -1) { 16 | var cookieValue = dnn.dom.getCookie(cookieId); 17 | if (cookieValue) { 18 | opts.selected = cookieValue; 19 | } 20 | if (opts.selected === -1) { 21 | opts.selected = 0; 22 | } 23 | } 24 | showEvent = (function (cid) { 25 | return function (event, ui) { 26 | dnn.dom.setCookie(cid, ui.newTab.index(), opts.cookieDays, '/', '', false, opts.cookieMilleseconds); 27 | }; 28 | })(cookieId); 29 | } else { 30 | showEvent = function () { 31 | }; 32 | } 33 | 34 | $wrap.tabs({ 35 | activate: showEvent, 36 | active: opts.selected, 37 | disabled: opts.disabled, 38 | fx: { 39 | opacity: opts.opacity, 40 | duration: opts.duration 41 | } 42 | }); 43 | 44 | if (window.location.hash && window.location.hash != '#') { 45 | var substr = window.location.hash.substr(0, 50); 46 | $('a[href="' + encodeURI(substr) + '"]', $wrap).trigger('click'); 47 | } 48 | 49 | // page validation integration - select tab that contain tripped validators 50 | if (typeof window.Page_ClientValidate != "undefined" && $.isFunction(window.Page_ClientValidate)) { 51 | $wrap.find(opts.validationTriggerSelector).click(function () { 52 | if (!window.Page_ClientValidate(opts.validationGroup)) { 53 | var invalidControl = $wrap.find(opts.invalidItemSelector).eq(0); 54 | var $parent = invalidControl.closest(".ui-tabs-panel"); 55 | if ($parent.length > 0) { 56 | var tabId = $parent.attr("id"); 57 | $parent.parent().find("a[href='#" + tabId + "']").click(); 58 | } 59 | } 60 | }); 61 | }; 62 | }); 63 | 64 | return $wrap; 65 | }; 66 | 67 | $.fn.dnnTabs.defaultOptions = { 68 | opacity: 'toggle', 69 | duration: 'fast', 70 | validationTriggerSelector: '.dnnPrimaryAction', 71 | validationGroup: '', 72 | invalidItemSelector: '.dnnFormError[style*="inline"]', 73 | regionToToggleSelector: 'fieldset', 74 | selected: -1, 75 | cookieDays: 0, 76 | cookieMilleseconds: 1200000 // twenty minutes 77 | }; 78 | 79 | })(jQuery); -------------------------------------------------------------------------------- /SecurityAnalyzer.dnn: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Security Analyzer 5 | SecurityAnalyzer module 6 | ~/DesktopModules/DNNCorp/SecurityAnalyzer/Images/Extensions_32x32_standard.png 7 | 8 | DNN Software 9 | DNN Software 10 | http://www.dnnsoftware.com 11 | sales@dnnsoftware.com 12 | 13 | 14 | 15 | true 16 | 17 | 05.06.02 18 | 19 | 20 | 21 | 22 | DesktopModules\DNNCorp\SecurityAnalyzer 23 | 28 | 33 | 38 | 39 | 40 | 41 | 42 | SecurityAnalyzer 43 | DNNCorp/SecurityAnalyzer 44 | 45 | DNN.Modules.SecurityAnalyzer.Components.FeatureController 46 | 47 | 48 | 49 | 50 | 51 | SecurityAnalyzer 52 | 0 53 | 54 | 55 | 56 | DesktopModules/DNNCorp/SecurityAnalyzer/View.ascx 57 | False 58 | 59 | Host 60 | 61 | 62 | 0 63 | 64 | 65 | 66 | 67 | 68 | 69 | DotNetNuke.Entities.Modules.EventMessageProcessor, DotNetNuke 70 | UpgradeModule 71 | 72 | DNN.Modules.SecurityAnalyzer.Components.FeatureController 73 | [DESKTOPMODULEID] 74 | 01.00.00,08.00.02,08.01.01,08.01.04 75 | 76 | 77 | 78 | 79 | 80 | DesktopModules\DNNCorp\SecurityAnalyzer 81 | 82 | License.txt 83 | 84 | 85 | ReleaseNotes.txt 86 | 87 | 88 | SecurityAnalyzer.dnn 89 | 90 | 91 | 92 | 93 | 94 | 95 | DNN.Modules.SecurityAnalyzer.dll 96 | bin 97 | 98 | 99 | 100 | 101 | 102 | DesktopModules/DNNCorp/SecurityAnalyzer 103 | 104 | Resources.zip 105 | 106 | 107 | 108 | 109 | 110 | web.config 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | -------------------------------------------------------------------------------- /SecurityAnalyzerModuleBase.cs: -------------------------------------------------------------------------------- 1 | using DotNetNuke.Entities.Modules; 2 | 3 | namespace DNN.Modules.SecurityAnalyzer 4 | { 5 | public class SecurityAnalyzerModuleBase : PortalModuleBase 6 | { 7 | } 8 | } -------------------------------------------------------------------------------- /Styles/dnnstyles.css: -------------------------------------------------------------------------------- 1 | /*-------------------------------------*/ 2 | /* TABS : JQUERY UI TABS 1.8.14 */ 3 | /*-------------------------------------*/ 4 | /* Tabs */ 5 | ul.dnnAdminTabNav li a, .dnnPrimaryAction, 6 | .dnnSecondaryAction{ 7 | display: inline-block; 8 | padding: 9px 9px; 9 | margin-bottom: 9px; 10 | cursor: pointer; 11 | min-width: 75px; 12 | *overflow: visible; 13 | border: 1px solid #c2c2c2; 14 | background: #eaeaea; 15 | -webkit-border-radius: 3px; 16 | border-radius: 3px; 17 | color: #333; 18 | font-weight: bold; 19 | text-decoration: none; 20 | text-align: center; 21 | background: #f5f5f5; /* Old browsers */ 22 | background: -moz-linear-gradient(top, #f5f5f5 0%, #dfdfdf 100%); /* FF3.6+ */ 23 | background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#f5f5f5), color-stop(100%,#dfdfdf)); /* Chrome,Safari4+ */ 24 | background: -webkit-linear-gradient(top, #f5f5f5 0%,#dfdfdf 100%); /* Chrome10+,Safari5.1+ */ 25 | background: -o-linear-gradient(top, #f5f5f5 0%,#dfdfdf 100%); /* Opera 11.10+ */ 26 | background: -ms-linear-gradient(top, #f5f5f5 0%,#dfdfdf 100%); /* IE10+ */ 27 | background: linear-gradient(top, #f5f5f5 0%,#dfdfdf 100%); /* W3C */ 28 | -webkit-box-shadow: 0px 1px 0px 0px rgba(0, 0, 0, 0.4), inset 0px 1px 0px 0px rgba(255, 255, 255, 1); 29 | box-shadow: 0px 1px 0px 0px rgba(0, 0, 0, 0.4), inset 0px 1px 0px 0px rgba(255, 255, 255, 1); 30 | text-shadow: 0px 1px 0px #ffffff; 31 | color: #333; 32 | } 33 | 34 | ul.dnnAdminTabNav { 35 | display: inline-block; 36 | margin-top: 5px; 37 | margin-left: 0; 38 | width: 100%; 39 | height: 37px; 40 | border-bottom: 1px solid #c2c2c2; 41 | padding-left: 0; 42 | } 43 | 44 | ul.dnnAdminTabNav li { 45 | float: left; 46 | margin-right: 4px; 47 | list-style: none; 48 | } 49 | 50 | ul.dnnAdminTabNav li a { 51 | /* most styles are inherited from typography.css */ 52 | margin-bottom: 0; 53 | border-bottom: 0; 54 | box-shadow: none; 55 | webkit-box-shadow: none; 56 | -webkit-border-radius: 3px 3px 0px 0px; 57 | border-radius: 3px 3px 0px 0px; 58 | } 59 | 60 | ul.dnnAdminTabNav li.ui-tabs-active a { 61 | margin-top: -3px; 62 | padding: 12px 9px 10px 9px; 63 | background: #fff; 64 | } 65 | 66 | /* Panels */ 67 | .ui-tabs .ui-tabs-panel { 68 | position: relative; 69 | display: block; 70 | } 71 | 72 | .ui-tabs .ui-tabs-hide { 73 | display: none; 74 | } 75 | /* UI Helpers */ 76 | .dnnForm .ui-helper-hidden { 77 | display: none; 78 | } 79 | 80 | .dnnForm .ui-helper-hidden-accessible { 81 | position: absolute !important; 82 | clip: rect(1px 1px 1px 1px); 83 | } 84 | 85 | /* Interaction Cues */ 86 | .dnnForm .ui-state-highlight, 87 | .dnnForm .ui-widget-content .ui-state-highlight, 88 | .dnnForm .ui-widget-header .ui-state-highlight { 89 | border: 1px solid #fed22f; 90 | background: #ffe45c; 91 | color: #363636; 92 | } 93 | 94 | .dnnForm .ui-state-highlight a, 95 | .dnnForm .ui-widget-content .ui-state-highlight a, 96 | .ui-widget-header .ui-state-highlight a { 97 | color: #363636; 98 | } 99 | 100 | .dnnForm .ui-state-error, 101 | .dnnForm .ui-widget-content .ui-state-error, 102 | .dnnForm .ui-widget-header .ui-state-error { 103 | border: 1px solid #cd0a0a; 104 | background: #b81900; 105 | color: #ffffff; 106 | } 107 | 108 | .dnnForm .ui-state-error a, 109 | .dnnForm .ui-widget-content .ui-state-error a, 110 | .dnnForm .ui-widget-header .ui-state-error a { 111 | color: #ffffff; 112 | } 113 | 114 | .dnnForm .ui-state-error-text, 115 | .dnnForm .ui-widget-content .ui-state-error-text, 116 | .dnnForm .ui-widget-header .ui-state-error-text { 117 | color: #ffffff; 118 | } 119 | 120 | .dnnForm .ui-priority-primary, 121 | .dnnForm .ui-widget-content .ui-priority-primary, 122 | .dnnForm .ui-widget-header .ui-priority-primary { 123 | font-weight: bold; 124 | } 125 | 126 | .dnnForm .ui-priority-secondary, 127 | .dnnForm .ui-widget-content .ui-priority-secondary, 128 | .ui-widget-header .ui-priority-secondary { 129 | opacity: .7; 130 | filter: Alpha(Opacity=70); 131 | font-weight: normal; 132 | } 133 | 134 | .dnnForm .ui-state-disabled, 135 | .dnnForm .ui-widget-content .ui-state-disabled, 136 | .dnnForm .ui-widget-header .ui-state-disabled { 137 | opacity: .35; 138 | filter: Alpha(Opacity=35); 139 | background-image: none; 140 | } 141 | 142 | .dnnForm .ui-draggable { 143 | cursor: move; 144 | } 145 | 146 | /* Corner radius */ 147 | .dnnForm .ui-corner-all, 148 | .dnnForm .ui-corner-top, 149 | .dnnForm .ui-corner-left, 150 | .dnnForm .ui-corner-tl { 151 | border-radius: 4px; 152 | } 153 | 154 | .dnnForm .ui-corner-all, 155 | .dnnForm .ui-corner-top, 156 | .dnnForm .ui-corner-right, 157 | .dnnForm .ui-corner-tr { 158 | border-radius: 4px; 159 | } 160 | /*-------------------------------------*/ -------------------------------------------------------------------------------- /View.ascx: -------------------------------------------------------------------------------- 1 | <%@ Control Language="C#" AutoEventWireup="true" CodeBehind="View.ascx.cs" Inherits="DNN.Modules.SecurityAnalyzer.View" EnableViewState="true" %> 2 | <%@ Import Namespace="DNN.Modules.SecurityAnalyzer.Components" %> 3 | <%@ Import Namespace="DotNetNuke.Entities.Users" %> 4 | <%@ Import Namespace="DotNetNuke.Services.Localization" %> 5 | <%@ Register TagPrefix="dnn" TagName="Label" Src="~/controls/LabelControl.ascx" %> 6 | 7 |
8 | 25 |
26 | 27 |
28 | 29 | 30 | 31 |
32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 50 | 57 | 58 | 59 | 60 | 61 |
<%# DisplayResult((CheckResult) Container.DataItem) %>
62 |
63 |
64 | 65 | 66 |
<%# DisplayNotes(((CheckResult) Container.DataItem).Notes) %>
67 |
68 |
69 | 70 |
71 | 72 |
73 |
74 | 75 |
76 |
77 |
78 | 79 |
80 | 81 |
82 | 83 | 84 | 87 | 88 |
89 |
90 |
91 |
92 |
93 | 94 | File Results
95 | 96 |

97 | 98 | Database Results 99 | 100 | 101 |
102 | 103 |
104 | 105 | 106 | 107 |
108 |
109 |
110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 |
149 |
150 |
151 | 152 |
153 |
154 | 155 |
156 | 157 |
158 |
159 |
160 | 161 | 162 | 163 |
164 |
165 |
166 |

<%=GetString("HighRiskFiles") %>

167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | <%# GetFilePath(Eval("FullName").ToString()) %> 178 | 179 | 180 | 181 | 182 | <%# DisplayDate(Convert.ToDateTime(Eval("LastWriteTime"))) %> 183 | 184 | 185 | 186 | 187 |

<%=GetString("LowRiskFiles") %>

188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | <%# GetFilePath(Eval("FullName").ToString()) %> 199 | 200 | 201 | 202 | 203 | <%# DisplayDate(Convert.ToDateTime(Eval("LastWriteTime"))) %> 204 | 205 | 206 | 207 | 208 |
209 |
210 |
211 | 212 | 213 | 214 |
215 |
216 |
217 |

<%=GetString("PortalSettings") %>

218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 |
227 |
228 |

<%=GetString("HostSettings") %>

229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 |
238 |
239 |

<%=GetString("TabSettings") %>

240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 |
249 |
250 |

<%=GetString("ModuleSettings") %>

251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 |
260 |
261 |
262 | 263 | 264 | 265 | 266 | 267 | 272 | -------------------------------------------------------------------------------- /View.ascx.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using System.Data; 5 | using System.Globalization; 6 | using System.IO; 7 | using System.Linq; 8 | using System.Text.RegularExpressions; 9 | using System.Web.UI.WebControls; 10 | using DNN.Modules.SecurityAnalyzer.Components; 11 | using DotNetNuke.Common; 12 | using DotNetNuke.Common.Utilities; 13 | using DotNetNuke.Data; 14 | using DotNetNuke.Entities.Users; 15 | using DotNetNuke.Services.Exceptions; 16 | using DotNetNuke.Services.Localization; 17 | using DotNetNuke.UI.Skins; 18 | using DotNetNuke.UI.Skins.Controls; 19 | 20 | namespace DNN.Modules.SecurityAnalyzer 21 | { 22 | public partial class View : SecurityAnalyzerModuleBase 23 | { 24 | protected ArrayList Users { get; set; } 25 | 26 | private IList CheckResults 27 | { 28 | get 29 | { 30 | if (ViewState["CheckResults"] == null) 31 | { 32 | var audit = new AuditChecks(); 33 | ViewState["CheckResults"] = audit.DoChecks(); 34 | } 35 | 36 | return ViewState["CheckResults"] as IList; 37 | } 38 | } 39 | 40 | protected void Page_Load(object sender, EventArgs e) 41 | { 42 | if (!UserInfo.IsSuperUser) 43 | { 44 | Response.Redirect(Globals.NavigateURL("Access Denied"), true); 45 | } 46 | 47 | try 48 | { 49 | cmdSearch.Click += cmdSearch_Click; 50 | cmdModifiedFiles.Click += cmdModifiedFiles_Click; 51 | } 52 | catch (Exception exc) //Module failed to load 53 | { 54 | Exceptions.ProcessModuleLoadException(this, exc); 55 | } 56 | 57 | if (!Page.IsPostBack) 58 | { 59 | Utility.CleanUpInstallerFiles(); 60 | 61 | if (Utility.UpdateTelerikSkinsSettings()) 62 | { 63 | Response.Redirect(Request.RawUrl, true); 64 | } 65 | 66 | GetAuditResults(); 67 | GetSuperUsers(); 68 | GetModifiedSettings(); 69 | 70 | 71 | if (DotNetNuke.Application.DotNetNukeContext.Current.Application.Version < new Version(6, 0, 0)) 72 | { 73 | panelResources.Visible = true; 74 | } 75 | } 76 | } 77 | 78 | protected void OnAuditCheck(object sender, EventArgs e) 79 | { 80 | var linkButton = sender as LinkButton; 81 | var checkName = linkButton?.CommandArgument; 82 | if (!string.IsNullOrEmpty(checkName)) 83 | { 84 | 85 | var existResult = CheckResults.FirstOrDefault(r => r.CheckName == checkName); 86 | if (existResult != null) 87 | { 88 | var scriptTimeout = Server.ScriptTimeout; 89 | Server.ScriptTimeout = int.MaxValue; 90 | 91 | try 92 | { 93 | var result = new AuditChecks().DoCheck(checkName); 94 | var index = CheckResults.IndexOf(existResult); 95 | CheckResults.RemoveAt(index); 96 | CheckResults.Insert(index, result); 97 | 98 | dgResults.DataSource = CheckResults; 99 | dgResults.DataBind(); 100 | } 101 | finally 102 | { 103 | Server.ScriptTimeout = scriptTimeout; 104 | } 105 | } 106 | } 107 | } 108 | 109 | private void GetAuditResults() 110 | { 111 | var audit = new AuditChecks(); 112 | Localization.LocalizeDataGrid(ref dgResults, LocalResourceFile); 113 | dgResults.DataSource = audit.DoChecks(); 114 | dgResults.DataBind(); 115 | } 116 | 117 | private void cmdSearch_Click(object sender, EventArgs e) 118 | { 119 | var scriptTimeout = Server.ScriptTimeout; 120 | try 121 | { 122 | Server.ScriptTimeout = int.MaxValue; 123 | 124 | pnlDatabaseresults.Visible = true; 125 | pnlFileresults.Visible = true; 126 | var foundinfiles = Utility.SearchFiles(txtSearchTerm.Text); 127 | IEnumerable files = foundinfiles as IList ?? foundinfiles.ToList(); 128 | if (files.Any() == false) 129 | { 130 | lblfileresults.Text = Localization.GetString("NoFileResults", LocalResourceFile); 131 | } 132 | else 133 | { 134 | var results = files.Aggregate("", (current, filename) => current + filename + "
"); 135 | lblfileresults.Text = results; 136 | } 137 | 138 | lbldatabaseresults.Text = Utility.SearchDatabase(txtSearchTerm.Text); 139 | } 140 | finally 141 | { 142 | Server.ScriptTimeout = scriptTimeout; 143 | } 144 | } 145 | 146 | private void SetMinimalModifiedFilesGrid() 147 | { 148 | dgModifiedFiles.DataSource = new List 149 | { 150 | new FileInfo(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "web.config")), 151 | new FileInfo(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "default.aspx")) 152 | }; 153 | dgModifiedFiles.DataBind(); 154 | } 155 | 156 | private void cmdModifiedFiles_Click(object sender, EventArgs e) 157 | { 158 | var scriptTimeout = Server.ScriptTimeout; 159 | try 160 | { 161 | Server.ScriptTimeout = 600; // 10 minutes 162 | 163 | Localization.LocalizeDataGrid(ref dgModifiedExecutableFiles, LocalResourceFile); 164 | dgModifiedExecutableFiles.DataSource = Utility.GetLastModifiedExecutableFiles(); 165 | dgModifiedExecutableFiles.DataBind(); 166 | 167 | Localization.LocalizeDataGrid(ref dgModifiedFiles, LocalResourceFile); 168 | dgModifiedFiles.DataSource = Utility.GetLastModifiedFiles(); 169 | dgModifiedFiles.DataBind(); 170 | } 171 | catch (Exception) 172 | { 173 | SetMinimalModifiedFilesGrid(); 174 | } 175 | finally 176 | { 177 | Server.ScriptTimeout = scriptTimeout; 178 | } 179 | } 180 | 181 | public string GetSeverityImageUrl(int severity) 182 | { 183 | switch (severity) 184 | { 185 | case (int) SeverityEnum.Pass: 186 | return ResolveUrl("~/images/green-ok.gif"); 187 | case (int) SeverityEnum.Warning: 188 | return ResolveUrl("~/images/yellow-warning.gif"); 189 | case (int) SeverityEnum.Failure: 190 | return ResolveUrl("~/images/red-error.gif"); 191 | } 192 | return ResolveUrl("~/images/icon_help_32px.gif"); 193 | } 194 | 195 | public string DisplayResult(CheckResult checkResult) 196 | { 197 | switch (checkResult.Severity) 198 | { 199 | case SeverityEnum.Unverified: 200 | return checkResult.Reason; 201 | case SeverityEnum.Pass: 202 | return checkResult.SuccessText; 203 | default: 204 | return checkResult.FailureText; 205 | } 206 | } 207 | 208 | public string DisplayFriendlyName(string reason) 209 | { 210 | return reason; 211 | } 212 | 213 | public string DisplayNotes(IList notes) 214 | { 215 | if (notes != null) 216 | { 217 | if (notes.Count == 0) 218 | { 219 | return "N/A"; 220 | } 221 | return notes.Aggregate(string.Empty, (current, note) => current + note + "
"); 222 | } 223 | return "N/A"; 224 | } 225 | 226 | public string DisplayEmail(string email) 227 | { 228 | var displayEmail = Null.NullString; 229 | try 230 | { 231 | if (email != null) 232 | { 233 | displayEmail = HtmlUtils.FormatEmail(email, false); 234 | } 235 | } 236 | catch (Exception exc) //Module failed to load 237 | { 238 | Exceptions.ProcessModuleLoadException(this, exc); 239 | } 240 | return displayEmail; 241 | } 242 | 243 | public string GetFilePath(string filePath) 244 | { 245 | var path = Regex.Replace(filePath, Regex.Escape(Globals.ApplicationMapPath), string.Empty, RegexOptions.IgnoreCase); 246 | 247 | return path.TrimStart('\\'); 248 | } 249 | 250 | public string DisplayDate(DateTime userDate) 251 | { 252 | var date = Null.NullString; 253 | try 254 | { 255 | date = !Null.IsNull(userDate) ? userDate.ToString() : ""; 256 | } 257 | catch (Exception exc) //Module failed to load 258 | { 259 | Exceptions.ProcessModuleLoadException(this, exc); 260 | } 261 | return date; 262 | } 263 | 264 | private void GetSuperUsers() 265 | { 266 | var totalRecords = 0; 267 | 268 | Users = UserController.GetUsers(-1, dgUsers.CurrentPageIndex, dgUsers.PageSize, 269 | ref totalRecords, true, true); 270 | 271 | Localization.LocalizeDataGrid(ref dgUsers, LocalResourceFile); 272 | dgUsers.DataSource = Users; 273 | dgUsers.DataBind(); 274 | } 275 | 276 | private void GetModifiedSettings() 277 | { 278 | try 279 | { 280 | var reader = DataProvider.Instance().ExecuteReader("SecurityAnalyzer_GetModifiedSettings"); 281 | if (reader != null) 282 | { 283 | var tables = new List(); 284 | do 285 | { 286 | var table = new DataTable { Locale = CultureInfo.CurrentCulture }; 287 | table.Load(reader); 288 | tables.Add(table); 289 | } 290 | while (!reader.IsClosed); // table.Load automatically moves to the next result and closes the reader once there are no more 291 | 292 | dgPortalSettings.DataSource = tables[0]; 293 | dgPortalSettings.DataBind(); 294 | 295 | dgHostSettings.DataSource = tables[1]; 296 | dgHostSettings.DataBind(); 297 | 298 | dgTabSettings.DataSource = tables[2]; 299 | dgTabSettings.DataBind(); 300 | 301 | dgModuleSettings.DataSource = tables[3]; 302 | dgModuleSettings.DataBind(); 303 | } 304 | } 305 | catch (Exception ex) 306 | { 307 | Skin.AddModuleMessage(this, ex.Message, ModuleMessage.ModuleMessageType.RedError); 308 | throw; 309 | } 310 | } 311 | 312 | } 313 | } -------------------------------------------------------------------------------- /View.ascx.designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // 5 | // Changes to this file may cause incorrect behavior and will be lost if 6 | // the code is regenerated. 7 | // 8 | //------------------------------------------------------------------------------ 9 | 10 | namespace DNN.Modules.SecurityAnalyzer { 11 | 12 | 13 | public partial class View { 14 | 15 | /// 16 | /// lblAuditExplanation control. 17 | /// 18 | /// 19 | /// Auto-generated field. 20 | /// To modify move field declaration from designer file to code-behind file. 21 | /// 22 | protected global::System.Web.UI.WebControls.Label lblAuditExplanation; 23 | 24 | /// 25 | /// dgResults control. 26 | /// 27 | /// 28 | /// Auto-generated field. 29 | /// To modify move field declaration from designer file to code-behind file. 30 | /// 31 | protected global::System.Web.UI.WebControls.DataGrid dgResults; 32 | 33 | /// 34 | /// panelSearch control. 35 | /// 36 | /// 37 | /// Auto-generated field. 38 | /// To modify move field declaration from designer file to code-behind file. 39 | /// 40 | protected global::System.Web.UI.WebControls.Panel panelSearch; 41 | 42 | /// 43 | /// lblScannerExplanation control. 44 | /// 45 | /// 46 | /// Auto-generated field. 47 | /// To modify move field declaration from designer file to code-behind file. 48 | /// 49 | protected global::System.Web.UI.WebControls.Label lblScannerExplanation; 50 | 51 | /// 52 | /// plSearchTerm control. 53 | /// 54 | /// 55 | /// Auto-generated field. 56 | /// To modify move field declaration from designer file to code-behind file. 57 | /// 58 | protected global::System.Web.UI.UserControl plSearchTerm; 59 | 60 | /// 61 | /// txtSearchTerm control. 62 | /// 63 | /// 64 | /// Auto-generated field. 65 | /// To modify move field declaration from designer file to code-behind file. 66 | /// 67 | protected global::System.Web.UI.WebControls.TextBox txtSearchTerm; 68 | 69 | /// 70 | /// RequiredFieldValidator1 control. 71 | /// 72 | /// 73 | /// Auto-generated field. 74 | /// To modify move field declaration from designer file to code-behind file. 75 | /// 76 | protected global::System.Web.UI.WebControls.RequiredFieldValidator RequiredFieldValidator1; 77 | 78 | /// 79 | /// cmdSearch control. 80 | /// 81 | /// 82 | /// Auto-generated field. 83 | /// To modify move field declaration from designer file to code-behind file. 84 | /// 85 | protected global::System.Web.UI.WebControls.LinkButton cmdSearch; 86 | 87 | /// 88 | /// pnlFileresults control. 89 | /// 90 | /// 91 | /// Auto-generated field. 92 | /// To modify move field declaration from designer file to code-behind file. 93 | /// 94 | protected global::System.Web.UI.WebControls.Panel pnlFileresults; 95 | 96 | /// 97 | /// lblfileresults control. 98 | /// 99 | /// 100 | /// Auto-generated field. 101 | /// To modify move field declaration from designer file to code-behind file. 102 | /// 103 | protected global::System.Web.UI.WebControls.Label lblfileresults; 104 | 105 | /// 106 | /// pnlDatabaseresults control. 107 | /// 108 | /// 109 | /// Auto-generated field. 110 | /// To modify move field declaration from designer file to code-behind file. 111 | /// 112 | protected global::System.Web.UI.WebControls.Panel pnlDatabaseresults; 113 | 114 | /// 115 | /// lbldatabaseresults control. 116 | /// 117 | /// 118 | /// Auto-generated field. 119 | /// To modify move field declaration from designer file to code-behind file. 120 | /// 121 | protected global::System.Web.UI.WebControls.Label lbldatabaseresults; 122 | 123 | /// 124 | /// lblSuperUserActivityExplaination control. 125 | /// 126 | /// 127 | /// Auto-generated field. 128 | /// To modify move field declaration from designer file to code-behind file. 129 | /// 130 | protected global::System.Web.UI.WebControls.Label lblSuperUserActivityExplaination; 131 | 132 | /// 133 | /// dgUsers control. 134 | /// 135 | /// 136 | /// Auto-generated field. 137 | /// To modify move field declaration from designer file to code-behind file. 138 | /// 139 | protected global::System.Web.UI.WebControls.DataGrid dgUsers; 140 | 141 | /// 142 | /// panelModifiedFiles control. 143 | /// 144 | /// 145 | /// Auto-generated field. 146 | /// To modify move field declaration from designer file to code-behind file. 147 | /// 148 | protected global::System.Web.UI.WebControls.Panel panelModifiedFiles; 149 | 150 | /// 151 | /// cmdModifiedFiles control. 152 | /// 153 | /// 154 | /// Auto-generated field. 155 | /// To modify move field declaration from designer file to code-behind file. 156 | /// 157 | protected global::System.Web.UI.WebControls.LinkButton cmdModifiedFiles; 158 | 159 | /// 160 | /// LabelCheckModifiedFiles control. 161 | /// 162 | /// 163 | /// Auto-generated field. 164 | /// To modify move field declaration from designer file to code-behind file. 165 | /// 166 | protected global::System.Web.UI.WebControls.Label LabelCheckModifiedFiles; 167 | 168 | /// 169 | /// lblModifiedFilesExplaination control. 170 | /// 171 | /// 172 | /// Auto-generated field. 173 | /// To modify move field declaration from designer file to code-behind file. 174 | /// 175 | protected global::System.Web.UI.WebControls.Label lblModifiedFilesExplaination; 176 | 177 | /// 178 | /// dgModifiedExecutableFiles control. 179 | /// 180 | /// 181 | /// Auto-generated field. 182 | /// To modify move field declaration from designer file to code-behind file. 183 | /// 184 | protected global::System.Web.UI.WebControls.DataGrid dgModifiedExecutableFiles; 185 | 186 | /// 187 | /// dgModifiedFiles control. 188 | /// 189 | /// 190 | /// Auto-generated field. 191 | /// To modify move field declaration from designer file to code-behind file. 192 | /// 193 | protected global::System.Web.UI.WebControls.DataGrid dgModifiedFiles; 194 | 195 | /// 196 | /// lblModifiedSettingsExplaination control. 197 | /// 198 | /// 199 | /// Auto-generated field. 200 | /// To modify move field declaration from designer file to code-behind file. 201 | /// 202 | protected global::System.Web.UI.WebControls.Label lblModifiedSettingsExplaination; 203 | 204 | /// 205 | /// dgPortalSettings control. 206 | /// 207 | /// 208 | /// Auto-generated field. 209 | /// To modify move field declaration from designer file to code-behind file. 210 | /// 211 | protected global::System.Web.UI.WebControls.DataGrid dgPortalSettings; 212 | 213 | /// 214 | /// dgHostSettings control. 215 | /// 216 | /// 217 | /// Auto-generated field. 218 | /// To modify move field declaration from designer file to code-behind file. 219 | /// 220 | protected global::System.Web.UI.WebControls.DataGrid dgHostSettings; 221 | 222 | /// 223 | /// dgTabSettings control. 224 | /// 225 | /// 226 | /// Auto-generated field. 227 | /// To modify move field declaration from designer file to code-behind file. 228 | /// 229 | protected global::System.Web.UI.WebControls.DataGrid dgTabSettings; 230 | 231 | /// 232 | /// dgModuleSettings control. 233 | /// 234 | /// 235 | /// Auto-generated field. 236 | /// To modify move field declaration from designer file to code-behind file. 237 | /// 238 | protected global::System.Web.UI.WebControls.DataGrid dgModuleSettings; 239 | 240 | /// 241 | /// panelResources control. 242 | /// 243 | /// 244 | /// Auto-generated field. 245 | /// To modify move field declaration from designer file to code-behind file. 246 | /// 247 | protected global::System.Web.UI.WebControls.Panel panelResources; 248 | } 249 | } 250 | -------------------------------------------------------------------------------- /module.css: -------------------------------------------------------------------------------- 1 | .severityblock { 2 | border-color: rgba(0, 0, 0, .2); 3 | border-style: solid; 4 | border-width: 1px; 5 | float: left; 6 | height: 20px; 7 | margin: 5px 5px 5px 5px; 8 | width: 20px; 9 | } 10 | 11 | .redblock { background-color: #FF0000; } 12 | 13 | .yellowblock { background-color: #FFFF00; } 14 | 15 | .greenblock { background-color: #00FF00; } 16 | 17 | @font-face { src: url("//maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css"); } 18 | 19 | .dnnForm #modifiedSettings .dnnGridItem td, 20 | .dnnForm #modifiedSettings .dnnGridAltItem td { 21 | word-break: break-all; 22 | } -------------------------------------------------------------------------------- /packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /web.Debug.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 17 | 18 | 29 | 30 | -------------------------------------------------------------------------------- /web.Release.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 17 | 18 | 19 | 30 | 31 | -------------------------------------------------------------------------------- /web.config: -------------------------------------------------------------------------------- 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 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | --------------------------------------------------------------------------------