| 1 | package com.jsql.model.injection.strategy.blind; | |
| 2 | ||
| 3 | import com.jsql.model.InjectionModel; | |
| 4 | import com.jsql.model.exception.StoppedByUserSlidingException; | |
| 5 | import com.jsql.model.injection.strategy.blind.callable.AbstractCallableBit; | |
| 6 | import com.jsql.model.injection.strategy.blind.callable.CallableVendor; | |
| 7 | import com.jsql.model.injection.strategy.blind.patch.Diff; | |
| 8 | import com.jsql.model.injection.vendor.model.Vendor; | |
| 9 | import com.jsql.model.injection.vendor.model.VendorYaml; | |
| 10 | import com.jsql.util.LogLevelUtil; | |
| 11 | import org.apache.commons.lang3.StringUtils; | |
| 12 | import org.apache.logging.log4j.LogManager; | |
| 13 | import org.apache.logging.log4j.Logger; | |
| 14 | ||
| 15 | import java.util.ArrayList; | |
| 16 | import java.util.Collection; | |
| 17 | import java.util.List; | |
| 18 | import java.util.concurrent.ExecutionException; | |
| 19 | import java.util.concurrent.ExecutorService; | |
| 20 | import java.util.concurrent.Future; | |
| 21 | ||
| 22 | public class InjectionVendor { | |
| 23 | ||
| 24 | private static final Logger LOGGER = LogManager.getRootLogger(); | |
| 25 | ||
| 26 | private String blankFalseMark; // Source code of the FALSE web page (e.g. ?id=-123456789) | |
| 27 | ||
| 28 | private List<Diff> constantTrueMark = new ArrayList<>(); | |
| 29 | ||
| 30 | protected final InjectionModel injectionModel; | |
| 31 | ||
| 32 | private final List<String> falsy; | |
| 33 | ||
| 34 | public InjectionVendor(InjectionModel injectionModel, String vendorSpecificWithOperator, Vendor vendor) { | |
| 35 | this.injectionModel = injectionModel; | |
| 36 | ||
| 37 | List<String> truthy = this.injectionModel.getMediatorVendor().getVendor().instance().getTruthyBit(); | |
| 38 | this.falsy = this.injectionModel.getMediatorVendor().getVendor().instance().getFalsyBit(); | |
| 39 | | |
| 40 | // No blind | |
| 41 |
2
1. <init> : negated conditional → NO_COVERAGE 2. <init> : negated conditional → NO_COVERAGE |
if (truthy.isEmpty() || this.injectionModel.isStoppedByUser()) { |
| 42 | return; | |
| 43 | } | |
| 44 | | |
| 45 | // Call the SQL request which must be FALSE (usually ?id=-123456879) | |
| 46 | this.blankFalseMark = this.callUrl( | |
| 47 | StringUtils.EMPTY, | |
| 48 | "vendor:" + vendor | |
| 49 | ); | |
| 50 | ||
| 51 | // Concurrent calls to the FALSE statements, | |
| 52 | // it will use inject() from the model | |
| 53 | ExecutorService taskExecutor = this.injectionModel.getMediatorUtils().getThreadUtil().getExecutor("CallableVendorTagTrue"); | |
| 54 | Collection<CallableVendor> listCallableTagTrue = new ArrayList<>(); | |
| 55 | for (String urlTest: truthy) { | |
| 56 | listCallableTagTrue.add( | |
| 57 | new CallableVendor( | |
| 58 | vendorSpecificWithOperator.replace(VendorYaml.TEST, urlTest), | |
| 59 | this, | |
| 60 | "vendor#true" | |
| 61 | ) | |
| 62 | ); | |
| 63 | } | |
| 64 | | |
| 65 | // Delete junk from the results of FALSE statements, | |
| 66 | // keep only opcodes found in each and every FALSE pages. | |
| 67 | // Allow the user to stop the loop | |
| 68 | try { | |
| 69 | List<Future<CallableVendor>> listTagTrue = taskExecutor.invokeAll(listCallableTagTrue); | |
| 70 |
1
1. <init> : removed call to com/jsql/util/ThreadUtil::shutdown → NO_COVERAGE |
this.injectionModel.getMediatorUtils().getThreadUtil().shutdown(taskExecutor); |
| 71 | | |
| 72 |
2
1. <init> : negated conditional → NO_COVERAGE 2. <init> : changed conditional boundary → NO_COVERAGE |
for (var i = 1 ; i < listTagTrue.size() ; i++) { |
| 73 |
1
1. <init> : negated conditional → NO_COVERAGE |
if (this.injectionModel.isStoppedByUser()) { |
| 74 | return; | |
| 75 | } | |
| 76 |
1
1. <init> : negated conditional → NO_COVERAGE |
if (this.constantTrueMark.isEmpty()) { |
| 77 | this.constantTrueMark = listTagTrue.get(i).get().getOpcodes(); | |
| 78 | } else { | |
| 79 | this.constantTrueMark.retainAll(listTagTrue.get(i).get().getOpcodes()); | |
| 80 | } | |
| 81 | } | |
| 82 | } catch (ExecutionException e) { | |
| 83 | LOGGER.log(LogLevelUtil.CONSOLE_JAVA, e, e); | |
| 84 | } catch (InterruptedException e) { | |
| 85 | LOGGER.log(LogLevelUtil.IGNORE, e, e); | |
| 86 |
1
1. <init> : removed call to java/lang/Thread::interrupt → NO_COVERAGE |
Thread.currentThread().interrupt(); |
| 87 | } | |
| 88 | | |
| 89 |
1
1. <init> : removed call to com/jsql/model/injection/strategy/blind/InjectionVendor::initFalseMarks → NO_COVERAGE |
this.initFalseMarks(vendorSpecificWithOperator); |
| 90 | } | |
| 91 | | |
| 92 | private void initFalseMarks(String vendorSpecificWithMode) { | |
| 93 | // Concurrent calls to the TRUE statements, | |
| 94 | // it will use inject() from the model. | |
| 95 | ExecutorService taskExecutor = this.injectionModel.getMediatorUtils().getThreadUtil().getExecutor("CallableVendorTagFalse"); | |
| 96 | Collection<CallableVendor> listCallableTagFalse = new ArrayList<>(); | |
| 97 | for (String urlTest: this.falsy) { | |
| 98 | listCallableTagFalse.add( | |
| 99 | new CallableVendor( | |
| 100 | vendorSpecificWithMode.replace(VendorYaml.TEST, urlTest), | |
| 101 | this, | |
| 102 | "vendor#false" | |
| 103 | ) | |
| 104 | ); | |
| 105 | } | |
| 106 | | |
| 107 | // Remove TRUE opcodes in the FALSE opcodes, because | |
| 108 | // a significant FALSE statement shouldn't contain any TRUE opcode. | |
| 109 | // Allow the user to stop the loop. | |
| 110 | try { | |
| 111 | List<Future<CallableVendor>> listTagFalse = taskExecutor.invokeAll(listCallableTagFalse); | |
| 112 |
1
1. initFalseMarks : removed call to com/jsql/util/ThreadUtil::shutdown → NO_COVERAGE |
this.injectionModel.getMediatorUtils().getThreadUtil().shutdown(taskExecutor); |
| 113 | for (Future<CallableVendor> falseTag: listTagFalse) { | |
| 114 |
1
1. initFalseMarks : negated conditional → NO_COVERAGE |
if (this.injectionModel.isStoppedByUser()) { |
| 115 | return; | |
| 116 | } | |
| 117 | this.constantTrueMark.removeAll(falseTag.get().getOpcodes()); | |
| 118 | } | |
| 119 | } catch (ExecutionException e) { | |
| 120 | LOGGER.log(LogLevelUtil.CONSOLE_JAVA, e, e); | |
| 121 | } catch (InterruptedException e) { | |
| 122 | LOGGER.log(LogLevelUtil.IGNORE, e, e); | |
| 123 |
1
1. initFalseMarks : removed call to java/lang/Thread::interrupt → NO_COVERAGE |
Thread.currentThread().interrupt(); |
| 124 | } | |
| 125 | } | |
| 126 | ||
| 127 | public boolean isInjectable(String vendorSpecificWithMode) throws StoppedByUserSlidingException { | |
| 128 |
1
1. isInjectable : negated conditional → NO_COVERAGE |
if (this.injectionModel.isStoppedByUser()) { |
| 129 | throw new StoppedByUserSlidingException(); | |
| 130 | } | |
| 131 | ||
| 132 | var blindTest = new CallableVendor( | |
| 133 | vendorSpecificWithMode.replace(VendorYaml.TEST, this.injectionModel.getMediatorVendor().getVendor().instance().sqlBlindConfirm()), | |
| 134 | this, | |
| 135 | "vendor#confirm" | |
| 136 | ); | |
| 137 | try { | |
| 138 | blindTest.call(); | |
| 139 | } catch (Exception e) { | |
| 140 | LOGGER.log(LogLevelUtil.CONSOLE_JAVA, e, e); | |
| 141 | } | |
| 142 | ||
| 143 |
3
1. isInjectable : negated conditional → NO_COVERAGE 2. isInjectable : replaced boolean return with true for com/jsql/model/injection/strategy/blind/InjectionVendor::isInjectable → NO_COVERAGE 3. isInjectable : negated conditional → NO_COVERAGE |
return blindTest.isTrue() && !this.constantTrueMark.isEmpty(); |
| 144 | } | |
| 145 | | |
| 146 | public String callUrl(String urlString, String metadataInjectionProcess) { | |
| 147 |
1
1. callUrl : replaced return value with "" for com/jsql/model/injection/strategy/blind/InjectionVendor::callUrl → NO_COVERAGE |
return this.injectionModel.injectWithoutIndex(urlString, metadataInjectionProcess); |
| 148 | } | |
| 149 | ||
| 150 | public String callUrl(String urlString, String metadataInjectionProcess, AbstractCallableBit<?> callableBoolean) { | |
| 151 |
1
1. callUrl : replaced return value with "" for com/jsql/model/injection/strategy/blind/InjectionVendor::callUrl → NO_COVERAGE |
return this.injectionModel.injectWithoutIndex(urlString, metadataInjectionProcess, callableBoolean); |
| 152 | } | |
| 153 | ||
| 154 | ||
| 155 | // Getter | |
| 156 | ||
| 157 | public String getBlankFalseMark() { | |
| 158 |
1
1. getBlankFalseMark : replaced return value with "" for com/jsql/model/injection/strategy/blind/InjectionVendor::getBlankFalseMark → NO_COVERAGE |
return this.blankFalseMark; |
| 159 | } | |
| 160 | | |
| 161 | public List<Diff> getConstantTrueMark() { | |
| 162 |
1
1. getConstantTrueMark : replaced return value with Collections.emptyList for com/jsql/model/injection/strategy/blind/InjectionVendor::getConstantTrueMark → NO_COVERAGE |
return this.constantTrueMark; |
| 163 | } | |
| 164 | } | |
Mutations | ||
| 41 |
1.1 2.2 |
|
| 70 |
1.1 |
|
| 72 |
1.1 2.2 |
|
| 73 |
1.1 |
|
| 76 |
1.1 |
|
| 86 |
1.1 |
|
| 89 |
1.1 |
|
| 112 |
1.1 |
|
| 114 |
1.1 |
|
| 123 |
1.1 |
|
| 128 |
1.1 |
|
| 143 |
1.1 2.2 3.3 |
|
| 147 |
1.1 |
|
| 151 |
1.1 |
|
| 158 |
1.1 |
|
| 162 |
1.1 |